internal static Coordinates[] Locate <TItem, TKey>( this UniqueKeyQuery <TItem, TKey> self, ref ReferenceNode <TItem, TKey> node, Coordinates[] coordinateSet, int lvlIndex = 1, int lastOverallIndex = 0) { if (node == null) { node = self.Root; } if (object.Equals(node.Key, default(TKey))) { node.Key = self.Key; } var keyComparison = self.KeyComparer(node.Key, self.Key); //the key in the node is lower than the new key if (keyComparison < 0 && node.References != null) { /* set the rest of the coordinates to the right * if the node has the maximum length, go to the parent and move one to the right * all in the first position * return coordinates set */ return(GetCoordinates <TItem, TKey>( self, ref node, coordinateSet, lvlIndex, lastOverallIndex, node[node.Length - 1], node.Length - 1)); } //the key in the node is higher than the new key else //if (rootComparison > 0) { /* * if it is a reference one, search inside the child node, * else search inside the values and return the coordinates set */ var selectKey = self.SelectKey; var comparer = self.KeyComparer; int rawIndex = ListMixins.BinarySearch(node.Values, v => v != null ? comparer(self.Key, selectKey(v.Value)):0); var found = node[rawIndex < 0 ? ~rawIndex : rawIndex]; return(GetCoordinates <TItem, TKey>( self, ref node, coordinateSet, lvlIndex, lastOverallIndex, found, rawIndex)); } }
public void Setup() { RightIndex = 0; Query = new UniqueKeyQuery <MockItem, int>() { SelectKey = item => item.Index }; Collection = new OptimizedCollection <MockItem>(Query); }
/// <summary> /// Adds to the value count /// </summary> /// <typeparam name="TItem">Type of the item</typeparam> /// <typeparam name="TKey">Type of the key</typeparam> /// <param name="self"></param> /// <param name="sumQtd"></param> public static void AugmentValueCount <TItem, TKey>(this UniqueKeyQuery <TItem, TKey> self, int sumQtd) { var lastRefNode = self.LastRefNode(self.Root); //if needs to change to the next ref node if (lastRefNode.Length >= self.State.MaxLengthPerNode) { self.TryResizeReferencesByOne(lastRefNode); } else { TryResizeValues(self, lastRefNode, sumQtd); } }
/// <summary> /// Diminishes the value count from a unique key query /// </summary> /// <typeparam name="TItem">Type of the item</typeparam> /// <typeparam name="TKey">Type of the key</typeparam> /// <param name="self">The query</param> /// <param name="qtdToSubtract">Quantity to substract</param> public static void AbridgeValueCount <TItem, TKey>(this UniqueKeyQuery <TItem, TKey> self, int qtdToSubtract) { var lastRefNode = self.LastRefNode(self.Root); if (lastRefNode.Length < 2) { TryEraseNode(lastRefNode.Parent); } else { lastRefNode.Values = lastRefNode .Values.Resize(lastRefNode.Length - 1); } }
/// <summary> /// Augments the level count. /// </summary> /// <param name='root'> /// The Root of the selector. /// </param> /// <param name='state'> /// the state of the selector tree. /// </param> /// <param name='itemAmmountToSum'> /// Item ammount to sum to the tree. /// </param> public static void AugmentLevelCount <TItem, TKey>(this UniqueKeyQuery <TItem, TKey> self, int itemAmmountToSum) { var root = self.Root; //increases one level //if there is only one level bellow the root, if (root.Values != null) { //Increase one level, and send them to the first node of this new level root.References = new [] { new ReferenceNode <TItem, TKey> { Values = root.Values, Parent = root, Key = root.Key, Comparer = self.KeyComparer } }; root.Values = null; } else { //Increase one level, and send them to the first node of this new level var refs = root.References; root.References = new[] { new ReferenceNode <TItem, TKey> { References = refs, Key = root.Key, Parent = root, Comparer = self.KeyComparer } }; for (int i = 0; i < refs.Length; i++) { refs[i].Parent = root.References[0]; } refs = null; } }
/// <summary> /// Augments the level count. /// </summary> /// <param name='root'> /// The Root of the selector. /// </param> /// <param name='state'> /// the state of the selector tree. /// </param> /// <param name='itemAmmountToSum'> /// Item ammount to sum to the tree. /// </param> public static void AbridgeLevelCount <TItem, TKey>(this UniqueKeyQuery <TItem, TKey> self, int itemAmmountToSum) { var root = self.Root; if (root.Values != null) { throw new NotImplementedException(); } var refs = new List <ReferenceNode <TItem, TKey> >(); foreach (var subRef in root.GetGrandChildren()) { subRef.Parent = root; refs.Add(subRef); } root.References = refs.ToArray(); }
/// <summary> /// Tries to resize the references by one /// </summary> /// <typeparam name="TItem">Type of the item</typeparam> /// <typeparam name="TKey">Type of the key</typeparam> /// <param name="self"></param> /// <param name="node">the node that will be increased</param> private static void TryResizeReferencesByOne <TItem, TKey>(this UniqueKeyQuery <TItem, TKey> self, ReferenceNode <TItem, TKey> node) { var lvlIndex = self.State.LevelCount - 2; while (node != null) { if (node.Length < self.State.MaxLengthPerNode) { for (int i = lvlIndex; i < self.State.LevelCount; i++) { if (i != (self.State.LevelCount - 2)) { node.References = node.References != null? node.References.Resize(node.Length + 1) : new ReferenceNode <TItem, TKey> [1]; node.References[node.Length - 1] = new ReferenceNode <TItem, TKey> { Parent = node, Comparer = self.KeyComparer }; node = node.References[node.Length - 1]; } else { node.Values = node.Values != null? node.Values.Resize(node.Length + 1) : new ValueNode <TItem> [1]; return; } } } lvlIndex--; node = node.Parent; } }
internal static Coordinates[] GetCoordinates <TItem, TKey>(UniqueKeyQuery <TItem, TKey> self, ref ReferenceNode <TItem, TKey> node, Coordinates[] coordinateSet, int lvlIndex, int lastOverallIndex, INode found, int rawIndex) { var index = rawIndex < 0 ? ~rawIndex : rawIndex; var coord = coordinateSet[lvlIndex]; coord.Length = node.Length; coord.Index = index; coord.OverallLength = self.State.Levels[lvlIndex].TotalUsed; coord.OverallIndex = (lastOverallIndex * self.State.MaxLengthPerNode) + index; lastOverallIndex = coord.OverallIndex; if (found is ReferenceNode <TItem, TKey> ) { node = (ReferenceNode <TItem, TKey>)found; return(self.Locate( ref node, coordinateSet, lvlIndex + 1, lastOverallIndex)); } return(coordinateSet); }
/// <summary> /// Loops throughtout all the value nodes, starting from a set of coordinates /// </summary> /// <typeparam name="TItem"></typeparam> /// <typeparam name="TKey"></typeparam> /// <param name="self"></param> /// <param name="coordinateSet"></param> /// <param name="inEach"></param> /// <returns></returns> public static Stack <ReferenceNode <TItem, TKey> > ForEachValuedNode <TItem, TKey>(this UniqueKeyQuery <TItem, TKey> self, Coordinates[] coordinateSet, Action <ReferenceNode <TItem, TKey>, int> inEach) { var queue = new Stack <ReferenceNode <TItem, TKey> >(); var coordinates = coordinateSet[coordinateSet.Length - 1]; ReferenceNode <TItem, TKey> @ref = null; var iterator = IntoLowestRefs(self, coordinateSet).GetEnumerator(); int overallIndex = coordinates.OverallIndex; while (iterator.MoveNext()) { queue.Push(@ref = iterator.Current); for (int i = coordinates.Index; i < @ref.Length && overallIndex < coordinates.OverallLength; i++) { overallIndex++; inEach(@ref, i); } } return(queue); }
/// <summary> /// Loops throughtout all the value nodes, starting from a set of coordinates, in reverse /// </summary> /// <typeparam name="TItem"></typeparam> /// <typeparam name="TKey"></typeparam> /// <param name="self"></param> /// <param name="coordinates"></param> /// <param name="inEach"></param> /// <returns></returns> public static Stack <ReferenceNode <TItem, TKey> > ForEachValuedNodeReverse <TItem, TKey>(this UniqueKeyQuery <TItem, TKey> self, Coordinates[] coordinates, Action <ReferenceNode <TItem, TKey>, int> inEach) { var queue = new Stack <ReferenceNode <TItem, TKey> >(); var offset = coordinates[coordinates.Length - 1]; ReferenceNode <TItem, TKey> @ref = null; var iterator = IntoLowestRefsReverse(self, self.Root, coordinates).GetEnumerator(); int reverseIndex = offset.OverallLength; while (iterator.MoveNext()) { queue.Push(@ref = iterator.Current); for (int i = @ref.Values.Length - 1; i > -1 && offset.OverallIndex < reverseIndex; i--) { reverseIndex--; inEach(@ref, i); } } return(queue); }
/// <summary> /// Moves all the references to values one position to the left, starting from a set of coordinates /// </summary> /// <typeparam name="TItem"></typeparam> /// <typeparam name="TKey"></typeparam> /// <param name="self"></param> /// <param name="coordinateSet"></param> /// <returns></returns> public static Stack <ReferenceNode <TItem, TKey> > MoveAll2TheLeft <TItem, TKey>(this UniqueKeyQuery <TItem, TKey> self, Coordinates[] coordinateSet) { ReferenceNode <TItem, TKey> previousRef = null; return(self.ForEachValuedNode(coordinateSet, (@ref, i) => { //if (@ref.Key.Equals(1089) || (@ref.Key.Equals(1088) && i == 32)) //{ // System.Diagnostics.Debugger.Break(); //} if (i == (@ref.Length - 1) && i > 1) { previousRef = @ref; } else { if (previousRef != null) { previousRef.Values[previousRef.Length - 1] = @ref.Values[0]; previousRef = null; } if (i != (@ref.Length - 1)) { @ref.Values[i] = @ref.Values[i + 1]; } } })); }
/// <summary> /// Moves all the references to values one position to the right, starting from a set of coordinates /// </summary> /// <typeparam name="TItem"></typeparam> /// <typeparam name="TKey"></typeparam> /// <param name="self"></param> /// <param name="coordinateSet"></param> /// <returns></returns> public static Stack <ReferenceNode <TItem, TKey> > MoveAll2TheRight <TItem, TKey>(this UniqueKeyQuery <TItem, TKey> self, Coordinates[] coordinateSet) { ReferenceNode <TItem, TKey> previousRef = null; return(self.ForEachValuedNodeReverse(coordinateSet, (@ref, i) => { if (i < 1) { previousRef = @ref; } else { if (previousRef != null) { previousRef.Values[0] = @ref.Values[@ref.Values.Length - 1]; previousRef = null; } @ref.Values[i] = @ref.Values[i - 1]; } })); }