public Put ( PredictionContext a, PredictionContext b, PredictionContext value ) : void | ||
a | PredictionContext | |
b | PredictionContext | |
value | PredictionContext | |
Résultat | void |
public static PredictionContext MergeArrays( ArrayPredictionContext a, ArrayPredictionContext b, bool rootIsWildcard, MergeCache mergeCache) { if (mergeCache != null) { PredictionContext previous = mergeCache.Get(a, b); if (previous != null) { return(previous); } previous = mergeCache.Get(b, a); if (previous != null) { return(previous); } } // merge sorted payloads a + b => M int i = 0; // walks a int j = 0; // walks b int k = 0; // walks target M array int[] mergedReturnStates = new int[a.returnStates.Length + b.returnStates.Length]; PredictionContext[] mergedParents = new PredictionContext[a.returnStates.Length + b.returnStates.Length]; // walk and merge to yield mergedParents, mergedReturnStates while (i < a.returnStates.Length && j < b.returnStates.Length) { PredictionContext a_parent = a.parents[i]; PredictionContext b_parent = b.parents[j]; if (a.returnStates[i] == b.returnStates[j]) { // same payload (stack tops are equal), must yield merged singleton int payload = a.returnStates[i]; // $+$ = $ bool both_dollar = payload == EMPTY_RETURN_STATE && a_parent == null && b_parent == null; bool ax_ax = (a_parent != null && b_parent != null) && a_parent.Equals(b_parent); // ax+ax -> ax if (both_dollar || ax_ax) { mergedParents[k] = a_parent; // choose left mergedReturnStates[k] = payload; } else // ax+ay -> a'[x,y] { PredictionContext mergedParent = Merge(a_parent, b_parent, rootIsWildcard, mergeCache); mergedParents[k] = mergedParent; mergedReturnStates[k] = payload; } i++; // hop over left one as usual j++; // but also skip one in right side since we merge } else if (a.returnStates[i] < b.returnStates[j]) { // copy a[i] to M mergedParents[k] = a_parent; mergedReturnStates[k] = a.returnStates[i]; i++; } else // b > a, copy b[j] to M { mergedParents[k] = b_parent; mergedReturnStates[k] = b.returnStates[j]; j++; } k++; } // copy over any payloads remaining in either array if (i < a.returnStates.Length) { for (int p = i; p < a.returnStates.Length; p++) { mergedParents[k] = a.parents[p]; mergedReturnStates[k] = a.returnStates[p]; k++; } } else { for (int p = j; p < b.returnStates.Length; p++) { mergedParents[k] = b.parents[p]; mergedReturnStates[k] = b.returnStates[p]; k++; } } // trim merged if we combined a few that had same stack tops if (k < mergedParents.Length) { // write index < last position; trim if (k == 1) { // for just one merged element, return singleton top PredictionContext a_ = SingletonPredictionContext.Create(mergedParents[0], mergedReturnStates[0]); if (mergeCache != null) { mergeCache.Put(a, b, a_); } return(a_); } mergedParents = Arrays.CopyOf(mergedParents, k); mergedReturnStates = Arrays.CopyOf(mergedReturnStates, k); } PredictionContext M = new ArrayPredictionContext(mergedParents, mergedReturnStates); // if we created same array as a or b, return that instead // TODO: track whether this is possible above during merge sort for speed if (M.Equals(a)) { if (mergeCache != null) { mergeCache.Put(a, b, a); } return(a); } if (M.Equals(b)) { if (mergeCache != null) { mergeCache.Put(a, b, b); } return(b); } CombineCommonParents(mergedParents); if (mergeCache != null) { mergeCache.Put(a, b, M); } return(M); }
public static PredictionContext MergeSingletons( SingletonPredictionContext a, SingletonPredictionContext b, bool rootIsWildcard, MergeCache mergeCache) { if (mergeCache != null) { PredictionContext previous = mergeCache.Get(a, b); if (previous != null) { return(previous); } previous = mergeCache.Get(b, a); if (previous != null) { return(previous); } } PredictionContext rootMerge = MergeRoot(a, b, rootIsWildcard); if (rootMerge != null) { if (mergeCache != null) { mergeCache.Put(a, b, rootMerge); } return(rootMerge); } if (a.returnState == b.returnState) { // a == b PredictionContext parent = Merge(a.parent, b.parent, rootIsWildcard, mergeCache); // if parent is same as existing a or b parent or reduced to a parent, return it if (parent == a.parent) { return(a); // ax + bx = ax, if a=b } if (parent == b.parent) { return(b); // ax + bx = bx, if a=b } // else: ax + ay = a'[x,y] // merge parents x and y, giving array node with x,y then remainders // of those graphs. dup a, a' points at merged array // new joined parent so create new singleton pointing to it, a' PredictionContext a_ = SingletonPredictionContext.Create(parent, a.returnState); if (mergeCache != null) { mergeCache.Put(a, b, a_); } return(a_); } else // a != b payloads differ // see if we can collapse parents due to $+x parents if local ctx { int[] payloads = new int[2]; PredictionContext[] parents = new PredictionContext[2]; PredictionContext pc; PredictionContext singleParent = null; if (a == b || (a.parent != null && a.parent.Equals(b.parent))) { // ax + bx = [a,b]x singleParent = a.parent; } if (singleParent != null) { // parents are same // sort payloads and use same parent if (a.returnState > b.returnState) { payloads[0] = b.returnState; payloads[1] = a.returnState; } else { payloads[0] = a.returnState; payloads[1] = b.returnState; } parents[0] = singleParent; parents[1] = singleParent; pc = new ArrayPredictionContext(parents, payloads); if (mergeCache != null) { mergeCache.Put(a, b, pc); } return(pc); } // parents differ and can't merge them. Just pack together // into array; can't merge. // ax + by = [ax,by] // sort by payload if (a.returnState > b.returnState) { payloads[0] = b.returnState; payloads[1] = a.returnState; parents[0] = b.parent; parents[1] = a.parent; } else { payloads[0] = a.returnState; payloads[1] = b.returnState; parents[0] = a.parent; parents[1] = b.parent; } pc = new ArrayPredictionContext(parents, payloads); if (mergeCache != null) { mergeCache.Put(a, b, pc); } return(pc); } }