public override void IterBack(Action <Leaf <TValue> > action) { #if ASSERTS action.AssertNotNull(); #endif switch (Size) { case 1: First.IterBack(action); return; case 2: Second.IterBack(action); First.IterBack(action); return; case 3: Third.IterBack(action); Second.IterBack(action); First.IterBack(action); return; case 4: Fourth.IterBack(action); Third.IterBack(action); Second.IterBack(action); First.IterBack(action); return; default: throw ImplErrors.Invalid_execution_path("Checked all sizes already"); } }
/// <summary> /// Adds the specified key-value pair to the tree. O(logn) /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="lineage"></param> /// <param name="overwrite"></param> /// <returns></returns> private Node AvlAdd(TKey key, TValue value, Lineage lineage, bool overwrite) { if (IsEmpty) { throw ImplErrors.Invalid_invocation("EmptyNode"); } var r = Comparer.Compare(key, Key); if (r < 0) { var newLeft = Left.IsEmpty ? NewForKvp(key, value, lineage) : Left.AvlAdd(key, value, lineage, overwrite); if (newLeft == null) { return(null); } return(AvlBalance(newLeft, Right, lineage)); } if (r > 0) { var newRight = Right.IsEmpty ? NewForKvp(key, value, lineage) : Right.AvlAdd(key, value, lineage, overwrite); if (newRight == null) { return(null); } return(AvlBalance(Left, newRight, lineage)); } return(overwrite ? WithValue(value, lineage) : null); }
public override string Print() { string[] rest; switch (Size) { case 1: rest = new[] { First.Print() }; break; case 2: rest = new[] { First.Print(), Second.Print() }; break; case 3: rest = new[] { First.Print(), Second.Print(), Third.Print() }; break; case 4: rest = new[] { First.Print(), Second.Print(), Third.Print(), Fourth.Print() }; break; default: throw ImplErrors.Bad_digit_size(Size); } var joined = String.Join(", ", rest); return(Measure == Size?Measure.ToString() : string.Format("{2} {0}: ({1})", Size, Measure, joined)); }
Digit Update_MUTATES(int index, Leaf <TValue> leaf) { var whereIsThisIndex = WhereIsThisIndex(index); switch (whereIsThisIndex) { case IN_START: case IN_MIDDLE_OF_1: First = First.Update(index, leaf, Lineage); return(this); case IN_START_OF_2: case IN_MIDDLE_OF_2: Second = Second.Update(index - First.Measure, leaf, Lineage); return(this); case IN_START_OF_3: case IN_MIDDLE_OF_3: Third = Third.Update(index - First.Measure - Second.Measure, leaf, Lineage); return(this); case IN_START_OF_4: case IN_MIDDLE_OF_4: Fourth = Fourth.Update(index - First.Measure - Second.Measure - Third.Measure, leaf, Lineage); return(this); case IN_END: case OUTSIDE: throw ImplErrors.Arg_out_of_range("index", index); default: throw ImplErrors.Invalid_execution_path("Checked all index locations already."); } }
public override FingerTreeElement GetChild(int index) { if (index != 0) { throw ImplErrors.Arg_out_of_range("index", index); } return(CenterDigit); }
public override void Split(int index, out FTree <TChild> left, out TChild child, out FTree <TChild> right, Lineage lineage) { #if ASSERTS var oldMeasure = Measure; var oldValue = this[index]; #endif switch (WhereIsThisIndex(index)) { case IN_START: case IN_MIDDLE_OF_LEFT: Digit lLeft, lRight; LeftDigit.Split(index, out lLeft, out child, out lRight, lineage); index -= lLeft == null ? 0 : lLeft.Measure; left = CreateCheckNull(Lineage.Immutable, lLeft); right = CreateCheckNull(lineage, lRight, DeepTree, RightDigit); break; case IN_START_OF_DEEP: case IN_MIDDLE_OF_DEEP: index -= LeftDigit.Measure; FTree <Digit> mLeft, mRight; Digit mCenter; DeepTree.Split(index, out mLeft, out mCenter, out mRight, lineage); Digit mcLeft, mcRight; index -= mLeft.Measure; mCenter.Split(index, out mcLeft, out child, out mcRight, lineage); index -= mcLeft == null ? 0 : mcLeft.Measure; left = CreateCheckNull(Lineage.Immutable, LeftDigit, mLeft, mcLeft); right = CreateCheckNull(lineage, mcRight, mRight, RightDigit); break; case IN_MIDDLE_OF_RIGHT: case IN_START_OF_RIGHT: Digit rLeft, rRight; index -= LeftDigit.Measure + DeepTree.Measure; RightDigit.Split(index, out rLeft, out child, out rRight, lineage); index -= rLeft == null ? 0 : rLeft.Measure; right = CreateCheckNull(Lineage.Immutable, rRight); left = CreateCheckNull(lineage, LeftDigit, DeepTree, rLeft); break; case IN_END: case OUTSIDE: throw ImplErrors.Arg_out_of_range("index", index); default: throw ImplErrors.Invalid_execution_path("Index didn't match any of the cases."); } #if ASSERTS oldMeasure.AssertEqual(left.Measure + child.Measure + right.Measure); oldValue.AssertEqual(child[index]); #endif }
/// <summary> /// Removes the minimum element and returns it. O(logn) /// </summary> /// <param name="min"></param> /// <param name="lineage"></param> /// <returns></returns> public Node ExtractMin(out Node min, Lineage lineage) { if (IsEmpty) { throw ImplErrors.Invalid_invocation("EmptyNode"); } if (!Left.IsEmpty) { return(AvlBalance(Left.ExtractMin(out min, lineage), Right, lineage)); } min = this; return(Right); }
public Node ExtractMax(out Node max, Lineage lineage) { if (IsEmpty) { throw ImplErrors.Invalid_invocation("EmptyNode"); } if (!Right.IsEmpty) { return(AvlBalance(Left, Right.ExtractMax(out max, lineage), lineage)); } max = this; return(Left); }
/// <summary> /// Returns a code telling where is the index located /// </summary> /// <param name="index"> </param> /// <returns> </returns> int WhereIsThisIndex(int index) { #if ASSERTS index.AssertEqual(i => i < Measure); #endif var measure1 = First.Measure; if (index == 0) { return(IN_START); } if (index < measure1) { return(IN_MIDDLE_OF_1); } if (index == measure1) { return(IN_START_OF_2); } var measure2 = measure1 + Second.Measure; if (index < measure2) { return(IN_MIDDLE_OF_2); } if (index == measure2) { return(IN_START_OF_3); } var measure3 = measure2 + Third.Measure; if (index < measure3) { return(IN_MIDDLE_OF_3); } if (index == measure3) { return(IN_START_OF_4); } var measure4 = measure3 + Fourth.Measure; if (index < measure4) { return(IN_MIDDLE_OF_4); } if (index == measure4) { return(IN_END); } if (index > measure4) { return(OUTSIDE); } throw ImplErrors.Invalid_execution_path("Checked all possible index locations"); }
private Node AvlAdd(int hash, TKey key, TValue value, Lineage lineage, bool overwrite) { #if ASSERTS var initialCount = Count; #endif if (IsEmpty) { throw ImplErrors.Invalid_invocation("Empty Node"); } Node ret; if (hash < Hash) { var newLeft = Left.IsEmpty ? NewForKvp(hash, key, value, lineage) : Left.AvlAdd(hash, key, value, lineage, overwrite); if (newLeft == null) { return(null); } ret = AvlBalance(newLeft, Right, lineage); } else if (hash > Hash) { var newRight = Right.IsEmpty ? NewForKvp(hash, key, value, lineage) : Right.AvlAdd(hash, key, value, lineage, overwrite); if (newRight == null) { return(null); } ret = AvlBalance(Left, newRight, lineage); } else { var newBucket = Bucket.Add(key, value, lineage, overwrite); if (newBucket == null) { return(null); } ret = WithBucket(newBucket, lineage); } #if ASSERTS ret.Count.AssertEqual(x => x <= initialCount + 1 && x >= initialCount); ret.IsBalanced.AssertTrue(); ret.Root_Contains(key).AssertTrue(); //ret.AllBuckets.Count(b => b.Find(key).IsSome).Is(1); #endif return(ret); }
FTree <TChild> CreateCheckNull(Lineage lineage, Digit left = null, FTree <Digit> deep = null, Digit right = null) { var memberPermutation = left != null ? 1 << 0 : 0; memberPermutation |= (deep != null && deep.Measure != 0) ? 1 << 1 : 0; memberPermutation |= right != null ? 1 << 2 : 0; switch (memberPermutation) { case 0 << 0 | 0 << 1 | 0 << 2: return(Empty); case 1 << 0 | 0 << 1 | 0 << 2: return(new Single(left, lineage)); case 1 << 0 | 1 << 1 | 0 << 2: var r2 = deep.Right; var deep1 = deep.RemoveLast(lineage); return(MutateOrCreate(left, deep1, r2, lineage)); case 1 << 0 | 1 << 1 | 1 << 2: return(MutateOrCreate(left, deep, right, lineage)); case 0 << 0 | 1 << 1 | 1 << 2: return(MutateOrCreate(deep.Left, deep.RemoveFirst(lineage), right, lineage)); case 1 << 0 | 0 << 1 | 1 << 2: return(MutateOrCreate(left, deep, right, lineage)); case 0 << 0 | 1 << 1 | 0 << 2: left = deep.Left; deep = deep.RemoveFirst(lineage); if (deep.Measure != 0) { right = deep.Right; deep = deep.RemoveLast(lineage); return(MutateOrCreate(left, deep, right, lineage)); } return(new Single(left, lineage)); case 0 << 0 | 0 << 1 | 1 << 2: return(new Single(right, lineage)); default: throw ImplErrors.Invalid_execution_path("Explicitly checked all possible tree permutations."); } }
public Bucket ByArbitraryOrder(int index) { if (IsEmpty) { throw ImplErrors.Arg_out_of_range("index", index); } if (index < Left.Count) { return(Left.ByArbitraryOrder(index)); } if (index < Left.Count + Bucket.Count) { return(Bucket.ByIndex(index - Left.Count)); } return(Right.ByArbitraryOrder(index - Left.Count - Bucket.Count)); }
public override FingerTreeElement GetChild(int index) { switch (index) { case 0: return(LeftDigit); case 1: return(DeepTree); case 2: return(RightDigit); default: throw ImplErrors.Arg_out_of_range("index", index); } }
public Bucket Add(TKey key, TValue v, Lineage lin, bool overwrite) { if (IsEmpty) { throw ImplErrors.Invalid_invocation("Empty Bucket"); } if (Eq.Equals(key, Key)) { return(overwrite ? WithKeyValue(key, v, lin) : null); } var newNext = Next.IsEmpty ? new Bucket(key, v, Empty, Eq, lin) : Next.Add(key, v, lin, overwrite); if (newNext == null) { return(null); } return(WithNext(newNext, lin)); }
public Digit AddLast(TChild item, Lineage lineage) { switch (Size) { case 1: return(MutateOrCreate(First, item, lineage)); case 2: return(MutateOrCreate(First, Second, item, lineage)); case 3: return(MutateOrCreate(First, Second, Third, item, lineage)); case 4: throw ImplErrors.Bad_digit_size(Size); } throw ImplErrors.Bad_digit_size(Size); }
public Digit RemoveFirst(Lineage lineage) { switch (Size) { case 1: throw ImplErrors.Digit_too_small(Size); case 2: return(MutateOrCreate(Second, lineage)); case 3: return(MutateOrCreate(Second, Third, lineage)); case 4: return(MutateOrCreate(Second, Third, Fourth, lineage)); } throw ImplErrors.Bad_digit_size(Size); }
public Digit RemoveLast(Lineage lineage) { switch (Size) { case 1: throw ImplErrors.Bad_digit_size(Size); case 2: return(MutateOrCreate(First, lineage)); case 3: return(MutateOrCreate(First, Second, lineage)); case 4: return(MutateOrCreate(First, Second, Third, lineage)); } throw ImplErrors.Bad_digit_size(Size); }
public override FingerTreeElement GetChild(int index) { switch (index) { case 0: return(First); case 1: return(Second); case 2: return(Third); case 3: return(Fourth); default: throw ImplErrors.Arg_out_of_range("index", index); } }
public override FTree <TChild> Update(int index, Leaf <TValue> leaf, Lineage lineage) { var whereIsThisIndex = WhereIsThisIndex(index); FTree <TChild> ret; #if ASSERTS var oldSize = Measure; #endif switch (whereIsThisIndex) { case IN_START: case IN_MIDDLE_OF_LEFT: var newLeft = LeftDigit.Update(index, leaf, lineage); ret = MutateOrCreate(newLeft, DeepTree, RightDigit, lineage); break; case IN_START_OF_DEEP: case IN_MIDDLE_OF_DEEP: if (DeepTree.Measure == 0) { goto case IN_START_OF_RIGHT; } var newDeep = DeepTree.Update(index - LeftDigit.Measure, leaf, lineage); ret = MutateOrCreate(LeftDigit, newDeep, RightDigit, lineage); break; case IN_START_OF_RIGHT: case IN_MIDDLE_OF_RIGHT: var newRight = RightDigit.Update(index - LeftDigit.Measure - DeepTree.Measure, leaf, lineage); ret = MutateOrCreate(LeftDigit, DeepTree, newRight, lineage); break; default: throw ImplErrors.Arg_out_of_range("index", index); } #if ASSERTS ret.Measure.AssertEqual(oldSize); ret[index].AssertEqual(leaf); #endif return(ret); }
public override Digit Update(int index, Leaf <TValue> leaf, Lineage lineage) { if (Lineage.AllowMutation(lineage)) { return(Update_MUTATES(index, leaf)); } #if ASSERTS leaf.AssertNotNull(); #endif var whereIsThisIndex = WhereIsThisIndex(index); TChild res; switch (whereIsThisIndex) { case IN_START: case IN_MIDDLE_OF_1: res = First.Update(index, leaf, lineage); return(CreateCheckNull(lineage, res, Second, Third, Fourth)); case IN_START_OF_2: case IN_MIDDLE_OF_2: res = Second.Update(index - First.Measure, leaf, lineage); return(CreateCheckNull(lineage, First, res, Third, Fourth)); case IN_START_OF_3: case IN_MIDDLE_OF_3: res = Third.Update(index - First.Measure - Second.Measure, leaf, lineage); return(CreateCheckNull(lineage, First, Second, res, Fourth)); case IN_START_OF_4: case IN_MIDDLE_OF_4: res = Fourth.Update(index - First.Measure - Second.Measure - Third.Measure, leaf, lineage); return(CreateCheckNull(lineage, First, Second, Third, res)); case IN_END: case OUTSIDE: throw ImplErrors.Arg_out_of_range("index", index); default: throw ImplErrors.Invalid_execution_path("Checked all index locations."); } }
public override Digit Reverse(Lineage lineage) { switch (Size) { case 1: return(MutateOrCreate(First.Reverse(lineage), lineage)); case 2: return(MutateOrCreate(Second.Reverse(lineage), First.Reverse(lineage), lineage)); case 3: return(MutateOrCreate(Third.Reverse(lineage), Second.Reverse(lineage), First.Reverse(lineage), lineage)); case 4: return(MutateOrCreate(Fourth.Reverse(lineage), Third.Reverse(lineage), Second.Reverse(lineage), First.Reverse(lineage), lineage)); default: throw ImplErrors.Invalid_execution_path("Checked all sizes"); } }
public Node ByOrder(int index) { for (Node cur = this; !cur.IsEmpty;) { var left = cur.Left.Count; if (index < left) { cur = cur.Left; } else if (index == left) { return(cur); } else { cur = cur.Right; index -= left + 1; } } throw ImplErrors.Arg_out_of_range("index", index); }
public void Split(int index, out Digit left, out TChild center, out Digit right, Lineage lineage) { switch (WhereIsThisIndex(index)) { case IN_START: case IN_MIDDLE_OF_1: left = null; center = First; right = CreateCheckNull(lineage, Second, Third, Fourth); break; case IN_START_OF_2: case IN_MIDDLE_OF_2: left = new Digit(First, lineage); center = Second; right = CreateCheckNull(lineage, Third, Fourth); break; case IN_START_OF_3: case IN_MIDDLE_OF_3: left = new Digit(First, Second, lineage); center = Third; right = CreateCheckNull(lineage, Fourth); break; case IN_MIDDLE_OF_4: case IN_START_OF_4: left = new Digit(First, Second, Third, lineage); center = Fourth; right = null; break; case IN_END: case OUTSIDE: throw ImplErrors.Arg_out_of_range("index", index); default: throw ImplErrors.Invalid_execution_path("Checked all index locations."); } }
private Node ExtractMin(out Node min, Lineage lineage) { if (IsEmpty) { throw ImplErrors.Invalid_invocation("EmptyNode"); } Node ret; if (!Left.IsEmpty) { ret = AvlBalance(Left.ExtractMin(out min, lineage), Right, lineage); } else { min = this; ret = Right; } #if ASSERTS ret.IsBalanced.AssertTrue(); #endif return(ret); }
public override Leaf <TValue> this[int index] { get { index.AssertEqual(i => i < Measure); var m1 = LeftDigit.Measure; var m2 = DeepTree.Measure + m1; if (index < m1) { return(LeftDigit[index]); } if (index < m2) { return(DeepTree[index - m1]); } if (index < Measure) { return(RightDigit[index - m2]); } throw ImplErrors.Arg_out_of_range("index", index); } }
public Digit ConstructMult(TValue[] arr, ref int index, int mult, Lineage lin) { var c = ExampleChild; switch (mult) { case 1: return(new Digit(c.Construct3(arr, ref index, lin), lin)); case 2: return(new Digit(c.Construct3(arr, ref index, lin), c.Construct3(arr, ref index, lin), lin)); case 3: return(new Digit(c.Construct3(arr, ref index, lin), c.Construct3(arr, ref index, lin), c.Construct3(arr, ref index, lin), lin)); case 4: return(new Digit(c.Construct3(arr, ref index, lin), c.Construct3(arr, ref index, lin), c.Construct3(arr, ref index, lin), c.Construct3(arr, ref index, lin), lin)); default: throw ImplErrors.Bad_digit_size(mult); } }
public override FTree <TChild> RemoveAt(int index, Lineage lineage) { throw ImplErrors.Invalid_invocation("Empty FingerTree"); }
public override FTree <TChild> Update(int index, Leaf <TValue> leaf, Lineage lineage) { throw ImplErrors.Invalid_invocation("Empty FingerTree"); }
public override FingerTreeElement GetChild(int index) { throw ImplErrors.Invalid_invocation("Empty FingerTree"); }
public override FTree <TChild> RemoveAt(int index, Lineage lineage) { var whereIsThisIndex = WhereIsThisIndex(index); Digit newLeft; FTree <TChild> ret = this; #if ASSERTS var newMeasure = Measure - 1; var expectedAtIndex = index != Measure - 1 ? this[index + 1] : null; var expectedBeforeIndex = index != 0 ? this[index - 1] : null; #endif switch (whereIsThisIndex) { case IN_START: case IN_MIDDLE_OF_LEFT: if (LeftDigit.IsFragment) { var fixedTree = FixLeftDigit(lineage); ret = fixedTree.RemoveAt(index, lineage); } else { newLeft = LeftDigit.Remove(index, lineage); ret = CreateCheckNull(lineage, newLeft, DeepTree, RightDigit); } break; case IN_START_OF_DEEP: case IN_MIDDLE_OF_DEEP: if (DeepTree.Measure == 0) { goto case IN_START_OF_RIGHT; } var deep = DeepTree; FTree <Digit> newDeep; if (deep.IsFragment) { newDeep = deep.AddFirst(LeftDigit, lineage); newDeep = newDeep.RemoveAt(index, lineage); newLeft = newDeep.Left; newDeep = newDeep.RemoveFirst(lineage); ret = MutateOrCreate(newLeft, newDeep, RightDigit, lineage); } else { newDeep = DeepTree.RemoveAt(index - LeftDigit.Measure, lineage); ret = CreateCheckNull(lineage, LeftDigit, newDeep, RightDigit); } break; case IN_START_OF_RIGHT: case IN_MIDDLE_OF_RIGHT: if (RightDigit.IsFragment) { var fixedTree = FixRightDigit(lineage); ret = fixedTree.RemoveAt(index, lineage); } else { var newRight = RightDigit.Remove(index - LeftDigit.Measure - DeepTree.Measure, lineage); ret = CreateCheckNull(lineage, LeftDigit, DeepTree, newRight); } break; case IN_END: case OUTSIDE: throw ImplErrors.Arg_out_of_range("index", index); default: throw ImplErrors.Invalid_execution_path("Checked all possible index locations already."); } #if ASSERTS ret.Measure.AssertEqual(newMeasure); if (expectedAtIndex != null) { ret[index].Value.AssertEqual(expectedAtIndex.Value); } if (expectedBeforeIndex != null) { ret[index - 1].Value.AssertEqual(expectedBeforeIndex.Value); } #endif return(ret); }