From 3335eedf3b91ec45c708a4a5a4c7d5c6b99c878e Mon Sep 17 00:00:00 2001 From: Zachary Patten Date: Sat, 24 Oct 2020 15:06:38 -0400 Subject: [PATCH 01/30] TagAttribute example comments fix --- Examples/ValueAttributes/Program.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Examples/ValueAttributes/Program.cs b/Examples/ValueAttributes/Program.cs index 2d8e4d5b..79d037fb 100644 --- a/Examples/ValueAttributes/Program.cs +++ b/Examples/ValueAttributes/Program.cs @@ -44,7 +44,7 @@ static void Main() Console.WriteLine($@" type of code member:"); Console.WriteLine(); - // Looking Up MyAttributeA + // Looking Up MyTagA Console.WriteLine($" - type: {type.GetTag(MyTagA).Value}"); Console.WriteLine($" - method: {methodInfo.GetTag(MyTagA).Value}"); Console.WriteLine($" - event: {eventInfo.GetTag(MyTagA).Value}"); @@ -59,7 +59,7 @@ static void Main() Console.WriteLine($@" on the same code members:"); Console.WriteLine(); - // Looking Up MyAttributeB + // Looking Up MyTagB Console.WriteLine($" - type: {type.GetTag(MyTagB).Value}"); Console.WriteLine($" - method: {methodInfo.GetTag(MyTagB).Value}"); Console.WriteLine($" - event: {eventInfo.GetTag(MyTagB).Value}"); From 7cd809b37633adbba05c4740b8e5d7542a1fe938 Mon Sep 17 00:00:00 2001 From: Zachary Patten Date: Sun, 25 Oct 2020 02:02:46 -0400 Subject: [PATCH 02/30] dotnet 5 sugguestions and clean up --- .../BasicsAndExtensions.csproj | 2 +- Examples/CommandLine/CommandLine.csproj | 2 +- Examples/ConsoleHelpers/ConsoleHelpers.csproj | 2 +- Examples/DataStructures/DataStructures.csproj | 2 +- Examples/GraphSearch/GraphSearch.csproj | 2 +- Examples/Mathematics/Mathematics.csproj | 2 +- Examples/Measurements/Measurements.csproj | 2 +- .../OmnitreeGraphicsDemo.csproj | 2 +- Examples/ValueAttributes/Program.cs | 4 +- Examples/ValueAttributes/TagAttributes.csproj | 2 +- Sources/Towel/DataStructures/Array.cs | 6 +- Sources/Towel/DataStructures/AvlTree.cs | 306 ++- Sources/Towel/DataStructures/DataStructure.cs | 19 + .../Towel/DataStructures/DoubleEndedQueue.cs | 36 +- Sources/Towel/DataStructures/Graph.cs | 41 +- Sources/Towel/DataStructures/Heap.cs | 86 +- Sources/Towel/DataStructures/Link.cs | 210 +- Sources/Towel/DataStructures/Link.tt | 24 +- Sources/Towel/DataStructures/List.cs | 221 +- Sources/Towel/DataStructures/Map.cs | 145 +- Sources/Towel/DataStructures/Omnitree_ND.cs | 60 +- Sources/Towel/DataStructures/Queue.cs | 247 +-- Sources/Towel/DataStructures/RedBlackTree.cs | 212 +- Sources/Towel/DataStructures/Set.cs | 214 +- .../Towel/DataStructures/SortedBinaryTree.cs | 41 + Sources/Towel/DataStructures/Stack.cs | 212 +- Sources/Towel/DataStructures/Trie.cs | 56 +- Sources/Towel/Extensions.cs | 16 +- Sources/Towel/Mathematics/Matrix.cs | 36 +- Sources/Towel/Mathematics/Symbolics.cs | 4 +- Sources/Towel/Meta.cs | 2 +- Sources/Towel/Statics.cs | 149 +- Sources/Towel/Towel.csproj | 11 +- Sources/Towel/Towel.xml | 1867 ++++++++--------- .../Towel_Benchmarking.csproj | 2 +- .../Towel_Documenting.csproj | 2 +- .../Towel_Generating/Towel_Generating.csproj | 2 +- Tools/Towel_Testing/Towel_Testing.csproj | 2 +- 38 files changed, 2033 insertions(+), 2218 deletions(-) diff --git a/Examples/BasicsAndExtensions/BasicsAndExtensions.csproj b/Examples/BasicsAndExtensions/BasicsAndExtensions.csproj index 52bceba0..6d2394b6 100644 --- a/Examples/BasicsAndExtensions/BasicsAndExtensions.csproj +++ b/Examples/BasicsAndExtensions/BasicsAndExtensions.csproj @@ -1,7 +1,7 @@  Exe - netcoreapp3.1 + net5.0 false diff --git a/Examples/CommandLine/CommandLine.csproj b/Examples/CommandLine/CommandLine.csproj index b713993c..30db8a6a 100644 --- a/Examples/CommandLine/CommandLine.csproj +++ b/Examples/CommandLine/CommandLine.csproj @@ -1,7 +1,7 @@ Exe - netcoreapp3.1 + net5.0 false CommandLine.xml diff --git a/Examples/ConsoleHelpers/ConsoleHelpers.csproj b/Examples/ConsoleHelpers/ConsoleHelpers.csproj index 89e61afa..7c69b515 100644 --- a/Examples/ConsoleHelpers/ConsoleHelpers.csproj +++ b/Examples/ConsoleHelpers/ConsoleHelpers.csproj @@ -1,7 +1,7 @@ Exe - netcoreapp3.1 + net5.0 false diff --git a/Examples/DataStructures/DataStructures.csproj b/Examples/DataStructures/DataStructures.csproj index 52bceba0..6d2394b6 100644 --- a/Examples/DataStructures/DataStructures.csproj +++ b/Examples/DataStructures/DataStructures.csproj @@ -1,7 +1,7 @@  Exe - netcoreapp3.1 + net5.0 false diff --git a/Examples/GraphSearch/GraphSearch.csproj b/Examples/GraphSearch/GraphSearch.csproj index 89e61afa..7c69b515 100644 --- a/Examples/GraphSearch/GraphSearch.csproj +++ b/Examples/GraphSearch/GraphSearch.csproj @@ -1,7 +1,7 @@ Exe - netcoreapp3.1 + net5.0 false diff --git a/Examples/Mathematics/Mathematics.csproj b/Examples/Mathematics/Mathematics.csproj index 89e61afa..7c69b515 100644 --- a/Examples/Mathematics/Mathematics.csproj +++ b/Examples/Mathematics/Mathematics.csproj @@ -1,7 +1,7 @@ Exe - netcoreapp3.1 + net5.0 false diff --git a/Examples/Measurements/Measurements.csproj b/Examples/Measurements/Measurements.csproj index 89e61afa..7c69b515 100644 --- a/Examples/Measurements/Measurements.csproj +++ b/Examples/Measurements/Measurements.csproj @@ -1,7 +1,7 @@ Exe - netcoreapp3.1 + net5.0 false diff --git a/Examples/OmnitreeGraphicsDemo/OmnitreeGraphicsDemo.csproj b/Examples/OmnitreeGraphicsDemo/OmnitreeGraphicsDemo.csproj index 9723b7e9..5f5700e7 100644 --- a/Examples/OmnitreeGraphicsDemo/OmnitreeGraphicsDemo.csproj +++ b/Examples/OmnitreeGraphicsDemo/OmnitreeGraphicsDemo.csproj @@ -1,7 +1,7 @@ Exe - netcoreapp3.1 + net5.0 false true diff --git a/Examples/ValueAttributes/Program.cs b/Examples/ValueAttributes/Program.cs index 79d037fb..52de5d06 100644 --- a/Examples/ValueAttributes/Program.cs +++ b/Examples/ValueAttributes/Program.cs @@ -27,7 +27,7 @@ static void Main() BindingFlags.Static | BindingFlags.Instance); EventInfo eventInfo = typeof(Program).GetEvent(nameof(Event)); - ConstructorInfo constructorInfo = type.GetConstructor(new Type[] { }); + ConstructorInfo constructorInfo = type.GetConstructor(Array.Empty()); FieldInfo fieldInfo = typeof(A).GetField(nameof(A.Field), BindingFlags.Public | BindingFlags.NonPublic | @@ -97,7 +97,7 @@ public A() { } public static void Method( [Tag(MyTagA, "works ;)")] [Tag(MyTagB, "G")] - object a) { } + object a) => a.ToString(); [Tag(MyTagA, "works :D")] [Tag(MyTagB, "C")] diff --git a/Examples/ValueAttributes/TagAttributes.csproj b/Examples/ValueAttributes/TagAttributes.csproj index 89e61afa..7c69b515 100644 --- a/Examples/ValueAttributes/TagAttributes.csproj +++ b/Examples/ValueAttributes/TagAttributes.csproj @@ -1,7 +1,7 @@ Exe - netcoreapp3.1 + net5.0 false diff --git a/Sources/Towel/DataStructures/Array.cs b/Sources/Towel/DataStructures/Array.cs index a935817b..f6611659 100644 --- a/Sources/Towel/DataStructures/Array.cs +++ b/Sources/Towel/DataStructures/Array.cs @@ -43,7 +43,7 @@ public Array(int size) { if (size < 1) { - throw new ArgumentOutOfRangeException("size of the array must be at least 1."); + throw new ArgumentOutOfRangeException(nameof(size), "size of the array must be at least 1."); } _array = new T[size]; } @@ -65,7 +65,7 @@ public T this[int index] { if (!(0 <= index || index < _array.Length)) { - throw new ArgumentOutOfRangeException("!(0 <= " + nameof(index) + " < this." + nameof(_array.Length) + ")"); + throw new ArgumentOutOfRangeException(nameof(index), $"!(0 <= {nameof(index)} < this.{nameof(_array.Length)})"); } return _array[index]; } @@ -73,7 +73,7 @@ public T this[int index] { if (!(0 <= index || index < _array.Length)) { - throw new ArgumentOutOfRangeException("!(0 <= " + nameof(index) + " < this." + nameof(_array.Length) + ")"); + throw new ArgumentOutOfRangeException(nameof(index), $"!(0 <= {nameof(index)} < this.{nameof(_array.Length)})"); } _array[index] = value; } diff --git a/Sources/Towel/DataStructures/AvlTree.cs b/Sources/Towel/DataStructures/AvlTree.cs index 06d2d298..8480ef8b 100644 --- a/Sources/Towel/DataStructures/AvlTree.cs +++ b/Sources/Towel/DataStructures/AvlTree.cs @@ -35,9 +35,11 @@ internal class Node #region Constructors - /// Constructs an AVL Tree. + /// + /// Constructs an AVL Tree. + /// Runtime: O(1) + /// /// The comparison function for sorting the items. - /// θ(1) public AvlTreeLinked(Compare compare = default) { _root = null; @@ -67,8 +69,10 @@ static Node Clone(Node node) => #region Properties - /// Gets the current least item in the avl tree. - /// θ(ln(Count)) + /// + /// Gets the current least item in the avl tree. + /// Runtime: θ(ln(Count)) + /// public T CurrentLeast { get @@ -83,8 +87,10 @@ public T CurrentLeast } } - /// Gets the current greated item in the avl tree. - /// θ(ln(Count)) + /// + /// Gets the current greated item in the avl tree. + /// Runtime: θ(ln(Count)) + /// public T CurrentGreatest { get @@ -99,15 +105,19 @@ public T CurrentGreatest } } - /// The comparison function being utilized by this structure. - /// θ(1) + /// + /// The comparison function being utilized by this structure. + /// Runtime: O(1) + /// Func DataStructure.IComparing.Compare => _compare is FuncRuntime func - ? func._delegate - : _compare.Do; + ? func._delegate + : _compare.Do; - /// Gets the number of elements in the collection. - /// θ(1) + /// + /// Gets the number of elements in the collection. + /// Runtime: O(1) + /// public int Count => _count; #endregion @@ -116,11 +126,13 @@ _compare is FuncRuntime func #region Add - /// Tries to add a value to the AVL tree. + /// + /// Tries to add a value to the AVL tree. + /// Runtime: O(ln(n)) + /// /// The value to add. /// The exception that occurred if the add failed. /// True if the add succeeded or false if not. - /// O(ln(n)) public bool TryAdd(T value, out Exception exception) { Exception capturedException = null; @@ -140,9 +152,11 @@ Node Add(Node node) capturedException = new ArgumentException($"Adding to add a duplicate value to an {nameof(AvlTreeLinked)}: {value}.", nameof(value)); return node; default: +#pragma warning disable CA2208 // Instantiate argument exceptions correctly capturedException = compareResult.IsDefined() - ? (Exception)new TowelBugException($"Unhandled {nameof(CompareResult)} value: {compareResult}.") - : new ArgumentException($"Invalid {nameof(Compare)} function; an undefined {nameof(CompareResult)} was returned.", nameof(Compare)); + ? (Exception)new TowelBugException($"Unhandled {nameof(CompareResult)} value: {compareResult}.") + : new ArgumentException($"Invalid {nameof(Compare)} function; an undefined {nameof(CompareResult)} was returned.", nameof(Compare)); +#pragma warning restore CA2208 // Instantiate argument exceptions correctly break; } return capturedException is null ? Balance(node) : node; @@ -155,8 +169,10 @@ Node Add(Node node) #region Clear - /// Returns the tree to an iterative state. - /// θ(1) + /// + /// Returns the tree to an iterative state. + /// Runtime: O(1) + /// public void Clear() { _root = null; @@ -167,26 +183,32 @@ public void Clear() #region Clone - /// Clones the AVL tree. + /// + /// Clones the AVL tree. + /// Runtime: θ(n) + /// /// A clone of the AVL tree. - /// θ(n) public AvlTreeLinked Clone() => new AvlTreeLinked(this); #endregion #region Contains - /// Determines if the AVL tree contains a value. + /// + /// Determines if the AVL tree contains a value. + /// Runtime: O(ln(Count)), Ω(1) + /// /// The value to look for. /// Whether or not the AVL tree contains the value. - /// O(ln(Count)) Ω(1) public bool Contains(T value) => Contains(x => _compare.Do(x, value)); - /// Determines if this structure contains an item by a given key. + /// + /// Determines if this structure contains an item by a given key. + /// Runtime: O(ln(Count)), Ω(1) + /// /// The sorting technique (must synchronize with this structure's sorting). /// True of contained, False if not. - /// O(ln(Count)) Ω(1) public bool Contains(Func sift) { Node node = _root; @@ -213,12 +235,14 @@ public bool Contains(Func sift) #region Get - /// Tries to get a value. + /// + /// Tries to get a value. + /// Runtime: O(ln(Count)), Ω(1) + /// /// The compare delegate. /// The value if found or default. /// The exception that occurred if the get failed. /// True if the get succeeded or false if not. - /// O(ln(Count)) Ω(1) public bool TryGet(Func sift, out T value, out Exception exception) { Node node = _root; @@ -316,54 +340,36 @@ Node Remove(Node node) #region Stepper - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void Stepper(Step step = default) where Step : struct, IAction => StepperRef>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void Stepper(Action step) => Stepper>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void StepperRef(Step step = default) where Step : struct, IStepRef => StepperRefBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void Stepper(StepRef step) => StepperRef>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// public StepStatus StepperBreak(Step step = default) where Step : struct, IFunc => StepperRefBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// public StepStatus Stepper(Func step) => StepperBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// + public StepStatus Stepper(StepRefBreak step) => StepperRefBreak>(step); + + /// public StepStatus StepperRefBreak(Step step = default) where Step : struct, IStepRefBreak { @@ -382,72 +388,42 @@ StepStatus Stepper(Node node) return Stepper(_root); } - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) - public StepStatus Stepper(StepRefBreak step) => StepperRefBreak>(step); - #endregion #region Stepper (ranged) - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) + /// public virtual void Stepper(T minimum, T maximum, Step step = default) where Step : struct, IAction => StepperBreak>(minimum, maximum, step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) + /// public virtual void Stepper(T minimum, T maximum, Action step) => Stepper>(minimum, maximum, step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) + /// public virtual void StepperRef(T minimum, T maximum, Step step = default) where Step : struct, IStepRef => StepperRefBreak>(minimum, maximum, step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) + /// public virtual void Stepper(T minimum, T maximum, StepRef step) => StepperRef>(minimum, maximum, step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) + /// public virtual StepStatus StepperBreak(T minimum, T maximum, Step step = default) where Step : struct, IFunc => StepperRefBreak>(minimum, maximum, step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) + /// public virtual StepStatus Stepper(T minimum, T maximum, Func step) => StepperBreak>(minimum, maximum, step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) + /// + public virtual StepStatus Stepper(T minimum, T maximum, StepRefBreak step) => + StepperRefBreak>(minimum, maximum); + + /// public virtual StepStatus StepperRefBreak(T minimum, T maximum, Step step = default) where Step : struct, IStepRefBreak { @@ -481,63 +457,42 @@ StepStatus Stepper(Node node) return Stepper(_root); } - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) - public virtual StepStatus Stepper(T minimum, T maximum, StepRefBreak step) => - StepperRefBreak>(minimum, maximum); - #endregion #region StepperReverse - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void StepperReverse(Step step = default) where Step : struct, IAction => StepperReverseBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void StepperReverse(Action step) => StepperReverse>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void StepperReverseRef(Step step = default) where Step : struct, IStepRef => StepperReverseRefBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void StepperReverse(StepRef step) => StepperReverseRef>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// public StepStatus StepperReverseBreak(Step step = default) where Step : struct, IFunc => StepperReverseRefBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// public StepStatus StepperReverse(Func step) => StepperReverseBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// + public StepStatus StepperReverse(StepRefBreak step) => + StepperReverseRefBreak>(step); + + /// public StepStatus StepperReverseRefBreak(Step step = default) where Step : struct, IStepRefBreak { @@ -556,73 +511,42 @@ StepStatus StepperReverse(Node node) return StepperReverse(_root); } - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) - public StepStatus StepperReverse(StepRefBreak step) => - StepperReverseRefBreak>(step); - #endregion #region StepperReverse (ranged) - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) + /// public virtual void StepperReverse(T minimum, T maximum, Step step = default) where Step : struct, IAction => StepperReverseBreak>(minimum, maximum, step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) + /// public virtual void StepperReverse(T minimum, T maximum, Action step) => StepperReverse>(minimum, maximum, step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) + /// public virtual void StepperReverseRef(T minimum, T maximum, Step step = default) where Step : struct, IStepRef => StepperReverseRefBreak>(minimum, maximum, step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) + /// public virtual void StepperReverse(T minimum, T maximum, StepRef step) => StepperReverseRef>(minimum, maximum, step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) + /// public virtual StepStatus StepperReverseBreak(T minimum, T maximum, Step step = default) where Step : struct, IFunc => StepperReverseRefBreak>(minimum, maximum, step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) + /// public virtual StepStatus StepperReverse(T minimum, T maximum, Func step) => StepperReverseBreak>(minimum, maximum, step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) + /// + public virtual StepStatus StepperReverse(T minimum, T maximum, StepRefBreak step) => + StepperReverseRefBreak>(minimum, maximum, step); + + /// public virtual StepStatus StepperReverseRefBreak(T minimum, T maximum, Step step = default) where Step : struct, IStepRefBreak { @@ -656,14 +580,6 @@ StepStatus StepperReverse(Node node) return StepperReverse(_root); } - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) - public virtual StepStatus StepperReverse(T minimum, T maximum, StepRefBreak step) => - StepperReverseRefBreak>(minimum, maximum, step); - #endregion #region IEnumerable @@ -685,10 +601,12 @@ public IEnumerator GetEnumerator() #region Helpers - /// Standard balancing algorithm for an AVL Tree. + /// + /// Standard balancing algorithm for an AVL Tree. + /// Runtime: O(1) + /// /// The tree to check the balancing of. /// The result of the possible balancing. - /// θ(1) internal static Node Balance(Node node) { static Node RotateSingleLeft(Node node) @@ -753,10 +671,12 @@ static Node RotateDoubleRight(Node node) return node; } - /// This is just a protection against the null valued leaf nodes, which have a height of "-1". + /// + /// This is just a protection against the null valued leaf nodes, which have a height of "-1". + /// Runtime: O(1) + /// /// The node to find the hight of. /// Returns "-1" if null (leaf) or the height property of the node. - /// θ(1) internal static int Height(Node node) => node is null ? -1 @@ -796,9 +716,11 @@ internal static Node RemoveRightMost(Node node, out Node rightMost) return Balance(node); } - /// Sets the height of a tree based on its children's heights. + /// + /// Sets the height of a tree based on its children's heights. + /// Runtime: O(1) + /// /// The tree to have its height adjusted. - /// O(1) internal static void SetHeight(Node node) => node.Height = Math.Max(Height(node.LeftChild), Height(node.RightChild)) + 1; @@ -813,9 +735,11 @@ public class AvlTreeLinked : AvlTreeLinkedConstructs an AVL Tree. + /// + /// Constructs an AVL Tree. + /// Runtime: O(1) + /// /// The comparison function for sorting the items. - /// θ(1) public AvlTreeLinked(Func compare = null) : base(compare ?? Statics.Compare) { } /// This constructor if for cloning purposes. @@ -840,17 +764,21 @@ static Node Clone(Node node) => #region Properties - /// The comparison function being utilized by this structure. - /// θ(1) + /// + /// The comparison function being utilized by this structure. + /// Runtime: O(1) + /// public Func Compare => _compare._delegate; #endregion #region Clone - /// Clones the AVL tree. + /// + /// Clones the AVL tree. + /// Runtime: O(1) + /// /// A clone of the AVL tree. - /// θ(n) public new AvlTreeLinked Clone() => new AvlTreeLinked(this); #endregion diff --git a/Sources/Towel/DataStructures/DataStructure.cs b/Sources/Towel/DataStructures/DataStructure.cs index 96dcd4a7..47311add 100644 --- a/Sources/Towel/DataStructures/DataStructure.cs +++ b/Sources/Towel/DataStructures/DataStructure.cs @@ -20,6 +20,25 @@ public interface IDataStructure : IEnumerable /// Contains extension methods for the Structure interface. public static class DataStructure { + #region XML + +#pragma warning disable CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name +#pragma warning disable CS1572 // XML comment has a param tag, but there is no parameter by that name + + /// + /// Invokes a method for each entry in the data structure. + /// Runtime: O(n * step) + /// + /// The method to invoke on each item in the structure. + /// The method to invoke on each item in the structure. + /// The resulting status of the iteration. + internal static void Stepper_O_n_step_XML() => throw new DocumentationMethodException(); + +#pragma warning restore CS1572 // XML comment has a param tag, but there is no parameter by that name +#pragma warning restore CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name + + #endregion + #region Interfaces /// Property of a data structure (does it have a contains method). diff --git a/Sources/Towel/DataStructures/DoubleEndedQueue.cs b/Sources/Towel/DataStructures/DoubleEndedQueue.cs index 066e000b..60a534d4 100644 --- a/Sources/Towel/DataStructures/DoubleEndedQueue.cs +++ b/Sources/Towel/DataStructures/DoubleEndedQueue.cs @@ -46,8 +46,10 @@ internal Node(T data) #region Constructors - /// Creates an instance of a queue. - /// O(1) + /// + /// Creates an instance of a queue. + /// Runtime: O(1) + /// public DoubleEndedQueueLinked() { _head = _tail = null; @@ -58,17 +60,21 @@ public DoubleEndedQueueLinked() #region Properties - /// Returns the number of items in the queue. - /// O(1) + /// + /// Returns the number of items in the queue. + /// Runtime: O(1) + /// public int Count => _count; #endregion #region Methods - /// Adds an item to the back of the queue. + /// + /// Adds an item to the back of the queue. + /// Runtime: O(1) + /// /// The item to add to the queue. - /// O(1) public void EnqueueBack(T enqueue) { if (_tail is null) @@ -82,8 +88,10 @@ public void EnqueueBack(T enqueue) _count++; } - /// Removes the oldest item in the queue. - /// O(1) + /// + /// Removes the oldest item in the queue. + /// Runtime: O(1) + /// public T DequeueFront() { if (_head is null) @@ -112,17 +120,21 @@ public T PeekFront() return returnValue; } - /// Resets the queue to an empty state. - /// O(1) + /// + /// Resets the queue to an empty state. + /// Runtime: O(1) + /// public void Clear() { _head = _tail = null; _count = 0; } - /// Converts the list into a standard array. + /// + /// Converts the list into a standard array. + /// Runtime: O(n) + /// /// A standard array of all the items. - /// O(n) public T[] ToArray() { if (_count == 0) diff --git a/Sources/Towel/DataStructures/Graph.cs b/Sources/Towel/DataStructures/Graph.cs index 980558c0..4390d6b3 100644 --- a/Sources/Towel/DataStructures/Graph.cs +++ b/Sources/Towel/DataStructures/Graph.cs @@ -63,18 +63,9 @@ public class GraphSetOmnitree : IGraph public class Edge { /// The starting node of the edge. - public readonly T Start; - /// The ending node of hte edge. - public readonly T End; - - /// Constructs a new Edge. - /// The starting point of the Edge. - /// The ending point of the Edge. - public Edge(T start, T end) - { - Start = start; - End = end; - } + public T Start { get; internal set; } + /// The ending node of the edge. + public T End { get; internal set; } } #endregion @@ -151,7 +142,7 @@ public void Add(T start, T end) (Edge e) => throw new InvalidOperationException("Adding an edge to a graph that already exists"), start, start, end, end); - _edges.Add(new Edge(start, end)); + _edges.Add(new Edge() { Start = start, End = end }); } /// Removes a node from the graph and all attached edges. @@ -263,32 +254,10 @@ public class GraphMap : IGraph internal MapHashLinked, T> _map; internal int _edges; - #region Edge - - /// Represents an edge in a graph. - public class Edge - { - /// The starting point of the edge. - public readonly T Start; - /// The ending point of the edge. - public readonly T End; - - /// Constructs a new Edge. - /// The starting point of the edge. - /// The ending point of the edge. - public Edge(T start, T end) - { - Start = start; - End = end; - } - } - - #endregion - #region Constructors /// Constructs a new GraphMap. - public GraphMap() : this(Statics.Equate, DefaultHash) { } + public GraphMap() : this(Equate, DefaultHash) { } /// Constructs a new GraphMap. /// The equate delegate for the data structure to use. diff --git a/Sources/Towel/DataStructures/Heap.cs b/Sources/Towel/DataStructures/Heap.cs index 38b37a9b..110979a0 100644 --- a/Sources/Towel/DataStructures/Heap.cs +++ b/Sources/Towel/DataStructures/Heap.cs @@ -39,13 +39,15 @@ public class HeapArray : IHeap internal T[] _heap; internal int _minimumCapacity; internal int _count; - + #region Constructors - /// Generates a priority queue with a capacity of the parameter. Runtime O(1). + /// + /// Generates a priority queue with a capacity of the parameter. + /// Runtime: O(1) + /// /// Delegate determining the comparison technique used for sorting. /// The capacity you want this priority queue to have. - /// θ(1) public HeapArray(Compare compare = default, int ? minimumCapacity = null) { int capacity = minimumCapacity ?? 1; @@ -67,23 +69,31 @@ internal HeapArray(HeapArray heap) #region Properties - /// The comparison function being utilized by this structure. - /// θ(1) + /// + /// The comparison function being utilized by this structure. + /// Runtime: O(1) + /// Func DataStructure.IComparing.Compare => _compare is FuncRuntime func ? func._delegate : _compare.Do; - /// The maximum items the queue can hold. - /// θ(1) + /// + /// The maximum items the queue can hold. + /// Runtime: O(1) + /// public int CurrentCapacity => _heap.Length - 1; - /// The minumum capacity of this queue to limit low-level resizing. - /// θ(1) + /// + /// The minumum capacity of this queue to limit low-level resizing. + /// Runtime: O(1) + /// public int MinimumCapacity => _minimumCapacity; - /// The number of items in the queue. - /// O(1) + /// + /// The number of items in the queue. + /// Runtime: O(1) + /// public int Count => _count; #endregion @@ -105,9 +115,11 @@ _compare is FuncRuntime func /// The index of the parent of the provided item. internal static int Parent(int child) => child / 2; - /// Enqueue an item into the priority queue and let it works its magic. + /// + /// Enqueue an item into the priority queue and let it works its magic. + /// Runtime: O(ln(n)), Ω(1), ε(ln(n)) + /// /// The item to be added. - /// O(ln(n)), Ω(1), ε(ln(n)) public void Enqueue(T addition) { if (!(_count + 1 < _heap.Length)) @@ -128,9 +140,11 @@ public void Enqueue(T addition) ShiftUp(_count); } - /// Dequeues the item with the highest priority. + /// + /// Dequeues the item with the highest priority. + /// Runtime: O(ln(n)) + /// /// The item of the highest priority. - /// O(ln(n)) public T Dequeue() { if (_count > 0) @@ -144,9 +158,11 @@ public T Dequeue() throw new InvalidOperationException("Attempting to remove from an empty priority queue."); } - /// Requeues an item after a change has occured. + /// + /// Requeues an item after a change has occured. + /// Runtime: O(n) + /// /// The item to requeue. - /// O(n) public void Requeue(T item) { int i; @@ -165,8 +181,10 @@ public void Requeue(T item) ShiftDown(i); } - /// This lets you peek at the top priority WITHOUT REMOVING it. - /// O(1) + /// + /// Get the highest priority element without removing it. + /// Runtime: O(1) + /// public T Peek() { if (_count > 0) @@ -176,9 +194,11 @@ public T Peek() throw new InvalidOperationException("Attempting to peek at an empty priority queue."); } - /// Standard priority queue algorithm for up sifting. + /// + /// Standard priority queue algorithm for up sifting. + /// Runtime: O(ln(n)), Ω(1) + /// /// The index to be up sifted. - /// O(ln(n)), Ω(1) internal void ShiftUp(int index) { int parent; @@ -189,9 +209,11 @@ internal void ShiftUp(int index) } } - /// Standard priority queue algorithm for sifting down. + /// + /// Standard priority queue algorithm for sifting down. + /// Runtime: O(ln(n)), Ω(1) + /// /// The index to be down sifted. - /// O(ln(n)), Ω(1) internal void ShiftDown(int index) { int leftChild, rightChild; @@ -211,10 +233,12 @@ internal void ShiftDown(int index) } } - /// Standard array swap method. + /// + /// Standard array swap method. + /// Runtime: O(1) + /// /// The first index of the swap. /// The second index of the swap. - /// O(1) internal void ArraySwap(int indexOne, int indexTwo) { T temp = _heap[indexTwo]; @@ -222,8 +246,10 @@ internal void ArraySwap(int indexOne, int indexTwo) _heap[indexOne] = temp; } - /// Returns this queue to an empty state. - /// O(1) + /// + /// Returns this queue to an empty state. + /// Runtime: O(1) + /// public void Clear() { _count = 0; @@ -284,10 +310,12 @@ public class HeapArray : HeapArray> { #region Constructors - /// Generates a priority queue with a capacity of the parameter. Runtime O(1). + /// + /// Generates a priority queue with a capacity of the parameter. + /// Runtime: O(1) + /// /// Delegate determining the comparison technique used for sorting. /// The capacity you want this priority queue to have. - /// θ(1) public HeapArray(Func compare = null, int? minimumCapacity = null) : base(compare ?? Statics.Compare, minimumCapacity) { } internal HeapArray(HeapArray heap) diff --git a/Sources/Towel/DataStructures/Link.cs b/Sources/Towel/DataStructures/Link.cs index 697f7e82..989c2529 100644 --- a/Sources/Towel/DataStructures/Link.cs +++ b/Sources/Towel/DataStructures/Link.cs @@ -29,9 +29,11 @@ public class LinkCreates a link between objects. + /// + /// Creates a link between objects. + /// Runtime: O(1) + /// /// The #1 item to be linked. - /// O(1) public Link(T1 _1 ) { @@ -42,10 +44,12 @@ public Link(T1 _1 #region Properties - /// The number of objects in the tuple. + /// + /// The number of objects in the tuple. + /// Runtime: O(1) + /// public int Size => 1; /// The #1 item in the link. - /// O(1) public T1 _1 { get => __1; set => __1 = value; } #endregion @@ -207,9 +211,11 @@ public struct LinkStructCreates a link between objects. + /// + /// Creates a link between objects. + /// Runtime: O(1) + /// /// The #1 item to be linked. - /// O(1) public LinkStruct(T1 _1 ) { @@ -220,10 +226,12 @@ public LinkStruct(T1 _1 #region Properties - /// The number of objects in the tuple. + /// + /// The number of objects in the tuple. + /// Runtime: O(1) + /// public int Size => 1; /// The #1 item in the link. - /// O(1) public T1 _1 { get => __1; set => __1 = value; } #endregion @@ -394,10 +402,12 @@ public class LinkCreates a link between objects. + /// + /// Creates a link between objects. + /// Runtime: O(1) + /// /// The #1 item to be linked. /// The #2 item to be linked. - /// O(1) public Link(T1 _1 , T2 _2 ) @@ -410,13 +420,14 @@ public Link(T1 _1 #region Properties - /// The number of objects in the tuple. + /// + /// The number of objects in the tuple. + /// Runtime: O(1) + /// public int Size => 2; /// The #1 item in the link. - /// O(1) public T1 _1 { get => __1; set => __1 = value; } /// The #2 item in the link. - /// O(1) public T2 _2 { get => __2; set => __2 = value; } #endregion @@ -618,10 +629,12 @@ public struct LinkStructCreates a link between objects. + /// + /// Creates a link between objects. + /// Runtime: O(1) + /// /// The #1 item to be linked. /// The #2 item to be linked. - /// O(1) public LinkStruct(T1 _1 , T2 _2 ) @@ -634,13 +647,14 @@ public LinkStruct(T1 _1 #region Properties - /// The number of objects in the tuple. + /// + /// The number of objects in the tuple. + /// Runtime: O(1) + /// public int Size => 2; /// The #1 item in the link. - /// O(1) public T1 _1 { get => __1; set => __1 = value; } /// The #2 item in the link. - /// O(1) public T2 _2 { get => __2; set => __2 = value; } #endregion @@ -848,11 +862,13 @@ public class LinkCreates a link between objects. + /// + /// Creates a link between objects. + /// Runtime: O(1) + /// /// The #1 item to be linked. /// The #2 item to be linked. /// The #3 item to be linked. - /// O(1) public Link(T1 _1 , T2 _2 , T3 _3 @@ -867,16 +883,16 @@ public Link(T1 _1 #region Properties - /// The number of objects in the tuple. + /// + /// The number of objects in the tuple. + /// Runtime: O(1) + /// public int Size => 3; /// The #1 item in the link. - /// O(1) public T1 _1 { get => __1; set => __1 = value; } /// The #2 item in the link. - /// O(1) public T2 _2 { get => __2; set => __2 = value; } /// The #3 item in the link. - /// O(1) public T3 _3 { get => __3; set => __3 = value; } #endregion @@ -1120,11 +1136,13 @@ public struct LinkStructCreates a link between objects. + /// + /// Creates a link between objects. + /// Runtime: O(1) + /// /// The #1 item to be linked. /// The #2 item to be linked. /// The #3 item to be linked. - /// O(1) public LinkStruct(T1 _1 , T2 _2 , T3 _3 @@ -1139,16 +1157,16 @@ public LinkStruct(T1 _1 #region Properties - /// The number of objects in the tuple. + /// + /// The number of objects in the tuple. + /// Runtime: O(1) + /// public int Size => 3; /// The #1 item in the link. - /// O(1) public T1 _1 { get => __1; set => __1 = value; } /// The #2 item in the link. - /// O(1) public T2 _2 { get => __2; set => __2 = value; } /// The #3 item in the link. - /// O(1) public T3 _3 { get => __3; set => __3 = value; } #endregion @@ -1393,12 +1411,14 @@ public class LinkCreates a link between objects. + /// + /// Creates a link between objects. + /// Runtime: O(1) + /// /// The #1 item to be linked. /// The #2 item to be linked. /// The #3 item to be linked. /// The #4 item to be linked. - /// O(1) public Link(T1 _1 , T2 _2 , T3 _3 @@ -1415,19 +1435,18 @@ public Link(T1 _1 #region Properties - /// The number of objects in the tuple. + /// + /// The number of objects in the tuple. + /// Runtime: O(1) + /// public int Size => 4; /// The #1 item in the link. - /// O(1) public T1 _1 { get => __1; set => __1 = value; } /// The #2 item in the link. - /// O(1) public T2 _2 { get => __2; set => __2 = value; } /// The #3 item in the link. - /// O(1) public T3 _3 { get => __3; set => __3 = value; } /// The #4 item in the link. - /// O(1) public T4 _4 { get => __4; set => __4 = value; } #endregion @@ -1715,12 +1734,14 @@ public struct LinkStructCreates a link between objects. + /// + /// Creates a link between objects. + /// Runtime: O(1) + /// /// The #1 item to be linked. /// The #2 item to be linked. /// The #3 item to be linked. /// The #4 item to be linked. - /// O(1) public LinkStruct(T1 _1 , T2 _2 , T3 _3 @@ -1737,19 +1758,18 @@ public LinkStruct(T1 _1 #region Properties - /// The number of objects in the tuple. + /// + /// The number of objects in the tuple. + /// Runtime: O(1) + /// public int Size => 4; /// The #1 item in the link. - /// O(1) public T1 _1 { get => __1; set => __1 = value; } /// The #2 item in the link. - /// O(1) public T2 _2 { get => __2; set => __2 = value; } /// The #3 item in the link. - /// O(1) public T3 _3 { get => __3; set => __3 = value; } /// The #4 item in the link. - /// O(1) public T4 _4 { get => __4; set => __4 = value; } #endregion @@ -2031,13 +2051,15 @@ public class LinkCreates a link between objects. + /// + /// Creates a link between objects. + /// Runtime: O(1) + /// /// The #1 item to be linked. /// The #2 item to be linked. /// The #3 item to be linked. /// The #4 item to be linked. /// The #5 item to be linked. - /// O(1) public Link(T1 _1 , T2 _2 , T3 _3 @@ -2056,22 +2078,20 @@ public Link(T1 _1 #region Properties - /// The number of objects in the tuple. + /// + /// The number of objects in the tuple. + /// Runtime: O(1) + /// public int Size => 5; /// The #1 item in the link. - /// O(1) public T1 _1 { get => __1; set => __1 = value; } /// The #2 item in the link. - /// O(1) public T2 _2 { get => __2; set => __2 = value; } /// The #3 item in the link. - /// O(1) public T3 _3 { get => __3; set => __3 = value; } /// The #4 item in the link. - /// O(1) public T4 _4 { get => __4; set => __4 = value; } /// The #5 item in the link. - /// O(1) public T5 _5 { get => __5; set => __5 = value; } #endregion @@ -2405,13 +2425,15 @@ public struct LinkStructCreates a link between objects. + /// + /// Creates a link between objects. + /// Runtime: O(1) + /// /// The #1 item to be linked. /// The #2 item to be linked. /// The #3 item to be linked. /// The #4 item to be linked. /// The #5 item to be linked. - /// O(1) public LinkStruct(T1 _1 , T2 _2 , T3 _3 @@ -2430,22 +2452,20 @@ public LinkStruct(T1 _1 #region Properties - /// The number of objects in the tuple. + /// + /// The number of objects in the tuple. + /// Runtime: O(1) + /// public int Size => 5; /// The #1 item in the link. - /// O(1) public T1 _1 { get => __1; set => __1 = value; } /// The #2 item in the link. - /// O(1) public T2 _2 { get => __2; set => __2 = value; } /// The #3 item in the link. - /// O(1) public T3 _3 { get => __3; set => __3 = value; } /// The #4 item in the link. - /// O(1) public T4 _4 { get => __4; set => __4 = value; } /// The #5 item in the link. - /// O(1) public T5 _5 { get => __5; set => __5 = value; } #endregion @@ -2764,14 +2784,16 @@ public class LinkCreates a link between objects. + /// + /// Creates a link between objects. + /// Runtime: O(1) + /// /// The #1 item to be linked. /// The #2 item to be linked. /// The #3 item to be linked. /// The #4 item to be linked. /// The #5 item to be linked. /// The #6 item to be linked. - /// O(1) public Link(T1 _1 , T2 _2 , T3 _3 @@ -2792,25 +2814,22 @@ public Link(T1 _1 #region Properties - /// The number of objects in the tuple. + /// + /// The number of objects in the tuple. + /// Runtime: O(1) + /// public int Size => 6; /// The #1 item in the link. - /// O(1) public T1 _1 { get => __1; set => __1 = value; } /// The #2 item in the link. - /// O(1) public T2 _2 { get => __2; set => __2 = value; } /// The #3 item in the link. - /// O(1) public T3 _3 { get => __3; set => __3 = value; } /// The #4 item in the link. - /// O(1) public T4 _4 { get => __4; set => __4 = value; } /// The #5 item in the link. - /// O(1) public T5 _5 { get => __5; set => __5 = value; } /// The #6 item in the link. - /// O(1) public T6 _6 { get => __6; set => __6 = value; } #endregion @@ -3192,14 +3211,16 @@ public struct LinkStructCreates a link between objects. + /// + /// Creates a link between objects. + /// Runtime: O(1) + /// /// The #1 item to be linked. /// The #2 item to be linked. /// The #3 item to be linked. /// The #4 item to be linked. /// The #5 item to be linked. /// The #6 item to be linked. - /// O(1) public LinkStruct(T1 _1 , T2 _2 , T3 _3 @@ -3220,25 +3241,22 @@ public LinkStruct(T1 _1 #region Properties - /// The number of objects in the tuple. + /// + /// The number of objects in the tuple. + /// Runtime: O(1) + /// public int Size => 6; /// The #1 item in the link. - /// O(1) public T1 _1 { get => __1; set => __1 = value; } /// The #2 item in the link. - /// O(1) public T2 _2 { get => __2; set => __2 = value; } /// The #3 item in the link. - /// O(1) public T3 _3 { get => __3; set => __3 = value; } /// The #4 item in the link. - /// O(1) public T4 _4 { get => __4; set => __4 = value; } /// The #5 item in the link. - /// O(1) public T5 _5 { get => __5; set => __5 = value; } /// The #6 item in the link. - /// O(1) public T6 _6 { get => __6; set => __6 = value; } #endregion @@ -3594,7 +3612,10 @@ public class LinkCreates a link between objects. + /// + /// Creates a link between objects. + /// Runtime: O(1) + /// /// The #1 item to be linked. /// The #2 item to be linked. /// The #3 item to be linked. @@ -3602,7 +3623,6 @@ public class LinkThe #5 item to be linked. /// The #6 item to be linked. /// The #7 item to be linked. - /// O(1) public Link(T1 _1 , T2 _2 , T3 _3 @@ -3625,28 +3645,24 @@ public Link(T1 _1 #region Properties - /// The number of objects in the tuple. + /// + /// The number of objects in the tuple. + /// Runtime: O(1) + /// public int Size => 7; /// The #1 item in the link. - /// O(1) public T1 _1 { get => __1; set => __1 = value; } /// The #2 item in the link. - /// O(1) public T2 _2 { get => __2; set => __2 = value; } /// The #3 item in the link. - /// O(1) public T3 _3 { get => __3; set => __3 = value; } /// The #4 item in the link. - /// O(1) public T4 _4 { get => __4; set => __4 = value; } /// The #5 item in the link. - /// O(1) public T5 _5 { get => __5; set => __5 = value; } /// The #6 item in the link. - /// O(1) public T6 _6 { get => __6; set => __6 = value; } /// The #7 item in the link. - /// O(1) public T7 _7 { get => __7; set => __7 = value; } #endregion @@ -4078,7 +4094,10 @@ public struct LinkStructCreates a link between objects. + /// + /// Creates a link between objects. + /// Runtime: O(1) + /// /// The #1 item to be linked. /// The #2 item to be linked. /// The #3 item to be linked. @@ -4086,7 +4105,6 @@ public struct LinkStructThe #5 item to be linked. /// The #6 item to be linked. /// The #7 item to be linked. - /// O(1) public LinkStruct(T1 _1 , T2 _2 , T3 _3 @@ -4109,28 +4127,24 @@ public LinkStruct(T1 _1 #region Properties - /// The number of objects in the tuple. + /// + /// The number of objects in the tuple. + /// Runtime: O(1) + /// public int Size => 7; /// The #1 item in the link. - /// O(1) public T1 _1 { get => __1; set => __1 = value; } /// The #2 item in the link. - /// O(1) public T2 _2 { get => __2; set => __2 = value; } /// The #3 item in the link. - /// O(1) public T3 _3 { get => __3; set => __3 = value; } /// The #4 item in the link. - /// O(1) public T4 _4 { get => __4; set => __4 = value; } /// The #5 item in the link. - /// O(1) public T5 _5 { get => __5; set => __5 = value; } /// The #6 item in the link. - /// O(1) public T6 _6 { get => __6; set => __6 = value; } /// The #7 item in the link. - /// O(1) public T7 _7 { get => __7; set => __7 = value; } #endregion diff --git a/Sources/Towel/DataStructures/Link.tt b/Sources/Towel/DataStructures/Link.tt index 001bf0e0..53351c45 100644 --- a/Sources/Towel/DataStructures/Link.tt +++ b/Sources/Towel/DataStructures/Link.tt @@ -40,11 +40,13 @@ namespace Towel.DataStructures #region Constructors - /// Creates a link between objects. + /// + /// Creates a link between objects. + /// Runtime: O(1) + /// <# for (int j = 1; j <= i; j++) { #> /// The #<#= j #> item to be linked. <# } #> - /// O(1) public Link(T1 _1 <# for (int j = 2; j <= i; j++) { #> , T<#= j #> _<#= j #> @@ -60,11 +62,13 @@ namespace Towel.DataStructures #region Properties - /// The number of objects in the tuple. + /// + /// The number of objects in the tuple. + /// Runtime: O(1) + /// public int Size => <#= i #>; <# for (int j = 1; j <= i; j++) { #> /// The #<#= j #> item in the link. - /// O(1) public T<#= j #> _<#= j #> { get => __<#= j #>; set => __<#= j #> = value; } <# } #> @@ -314,11 +318,13 @@ namespace Towel.DataStructures #region Constructors - /// Creates a link between objects. + /// + /// Creates a link between objects. + /// Runtime: O(1) + /// <# for (int j = 1; j <= i; j++) { #> /// The #<#= j #> item to be linked. <# } #> - /// O(1) public LinkStruct(T1 _1 <# for (int j = 2; j <= i; j++) { #> , T<#= j #> _<#= j #> @@ -333,11 +339,13 @@ namespace Towel.DataStructures #region Properties - /// The number of objects in the tuple. + /// + /// The number of objects in the tuple. + /// Runtime: O(1) + /// public int Size => <#= i #>; <# for (int j = 1; j <= i; j++) { #> /// The #<#= j #> item in the link. - /// O(1) public T<#= j #> _<#= j #> { get => __<#= j #>; set => __<#= j #> = value; } <# } #> diff --git a/Sources/Towel/DataStructures/List.cs b/Sources/Towel/DataStructures/List.cs index 1d4ce5dc..306c7a9b 100644 --- a/Sources/Towel/DataStructures/List.cs +++ b/Sources/Towel/DataStructures/List.cs @@ -141,11 +141,6 @@ internal class Node { internal Node Next; internal T Value; - - internal Node(T data) - { - Value = data; - } } #endregion @@ -154,12 +149,12 @@ internal Node(T data) internal ListLinked(ListLinked listLinked) { - Node head = new Node(listLinked._head.Value); + Node head = new Node { Value = listLinked._head.Value }; Node current = listLinked._head.Next; Node current_clone = head; while (!(current is null)) { - current_clone.Next = new Node(current.Value); + current_clone.Next = new Node { Value = current.Value }; current_clone = current_clone.Next; current = current.Next; } @@ -168,8 +163,10 @@ internal ListLinked(ListLinked listLinked) _count = listLinked._count; } - /// Creates an instance of a AddableLinked. - /// θ(1) + /// + /// Creates an instance of a AddableLinked. + /// Runtime: O(1) + /// public ListLinked() { _head = _tail = null; @@ -180,8 +177,10 @@ public ListLinked() #region Properties - /// Returns the number of items in the list. - /// θ(1) + /// + /// Returns the number of items in the list. + /// Runitme: O(1) + /// public int Count => _count; #endregion @@ -190,11 +189,13 @@ public ListLinked() #region Add - /// Adds an item to the list. + /// + /// Adds an item to the list. + /// Runtime: O(1) + /// /// The item to add to the list. /// The exception that occurred if the add failed. /// True if the add succeeded or false if not. - /// O(1) public bool TryAdd(T value, out Exception exception) { Add(value); @@ -202,18 +203,20 @@ public bool TryAdd(T value, out Exception exception) return true; } - /// Adds an item to the list. + /// + /// Adds an item to the list. + /// Runtime: O(1) + /// /// The item to add to the list. - /// O(1) public void Add(T addition) { if (_tail is null) { - _head = _tail = new Node(addition); + _head = _tail = new Node { Value = addition }; } else { - _tail = _tail.Next = new Node(addition); + _tail = _tail.Next = new Node { Value = addition }; } _count++; } @@ -222,8 +225,10 @@ public void Add(T addition) #region Clear - /// Resets the list to an empty state. - /// θ(1) + /// + /// Resets the list to an empty state. + /// Runtime: O(1) + /// public void Clear() { _head = _tail = null; @@ -234,9 +239,11 @@ public void Clear() #region Clone - /// Creates a shallow clone of this data structure. + /// + /// Creates a shallow clone of this data structure. + /// Runtime: O(n) + /// /// A shallow clone of this data structure. - /// θ(n) public ListLinked Clone() => new ListLinked(this); #endregion @@ -351,60 +358,36 @@ public bool TryRemoveFirst(out Exception exception, Predicate predica #region Stepper - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void Stepper(Step step = default) where Step : struct, IAction => StepperRef>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void Stepper(Action step) => Stepper>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void StepperRef(Step step = default) where Step : struct, IStepRef => StepperRefBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void Stepper(StepRef step) => StepperRef>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// public StepStatus StepperBreak(Step step = default) where Step : struct, IFunc => StepperRefBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// public StepStatus Stepper(Func step) => StepperBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// public StepStatus Stepper(StepRefBreak step) => StepperRefBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// public StepStatus StepperRefBreak(Step step = default) where Step : struct, IStepRefBreak { @@ -441,14 +424,16 @@ public System.Collections.Generic.IEnumerator GetEnumerator() #region ToArray - /// Converts the list into a standard array. + /// + /// Converts the list into a standard array. + /// Runtime: O(n) + /// /// A standard array of all the items. - /// Θ(n) public T[] ToArray() { if (_count == 0) { - return new T[0]; + return Array.Empty(); } T[] array = new T[_count]; Node node = _head; @@ -474,13 +459,17 @@ public class ListArray : IList #region Constructor - /// Creates an instance of a ListArray, and sets it's minimum capacity. - /// O(1) + /// + /// Creates an instance of a ListArray, and sets it's minimum capacity. + /// Runtime: O(1) + /// public ListArray() : this(1) { } - /// Creates an instance of a ListArray, and sets it's minimum capacity. + /// + /// Creates an instance of a ListArray, and sets it's minimum capacity. + /// Runtime: O(1) + /// /// The initial and smallest array size allowed by this list. - /// O(1) public ListArray(int expectedCount) { if (expectedCount < 1) @@ -535,12 +524,16 @@ public T this[int index] } } - /// Gets the number of items in the list. - /// O(1) + /// + /// Gets the number of items in the list. + /// Runtime: O(1) + /// public int Count { get { return this._count; } } - /// Gets the current capacity of the list. - /// O(1) + /// + /// Gets the current capacity of the list. + /// Runtime: O(1) + /// public int CurrentCapacity => _list.Length; #endregion @@ -549,11 +542,13 @@ public T this[int index] #region Add - /// Tries to add a value. + /// + /// Tries to add a value. + /// Runtime: O(n), Ω(1), ε(1) + /// /// The value to be added. /// The exception that occurrs if the add fails. /// True if the add succeds or false if not. - /// O(n), Ω(1), ε(1) public bool TryAdd(T value, out Exception exception) { if (_count == _list.Length) @@ -599,8 +594,10 @@ public void Add(T addition, int index) #region Clear - /// Empties the list back and reduces it back to its original capacity. - /// O(1) + /// + /// Empties the list back and reduces it back to its original capacity. + /// Runtime: O(1) + /// public void Clear() { _list = new T[1]; @@ -622,9 +619,11 @@ public ListArray Clone() #region Remove - /// Removes the item at a specific index. + /// + /// Removes the item at a specific index. + /// Runtime: O(n), Ω(n - index), ε(n - index) + /// /// The index of the item to be removed. - /// O(n), Ω(n - index), ε(n - index) public void Remove(int index) { RemoveWithoutShrink(index); @@ -639,9 +638,11 @@ public void Remove(int index) } } - /// Removes the item at a specific index. + /// + /// Removes the item at a specific index. + /// Runtime: Θ(n - index) + /// /// The index of the item to be removed. - /// Θ(n - index) public void RemoveWithoutShrink(int index) { if (index < 0 || index >= _count) @@ -655,9 +656,11 @@ public void RemoveWithoutShrink(int index) _count--; } - /// Removes all predicated items from the list. + /// + /// Removes all predicated items from the list. + /// Runtime: Θ(n) + /// /// The predicate to determine removals. - /// Θ(n) public void RemoveAll(Predicate predicate = default) where Predicate : struct, IFunc { @@ -673,9 +676,11 @@ public void RemoveAll(Predicate predicate = default) } } - /// Removes all predicated items from the list. + /// + /// Removes all predicated items from the list. + /// Runtime: Θ(n) + /// /// The predicate to determine removals. - /// Θ(n) public void RemoveAllWithoutShrink(Predicate predicate = default) where Predicate : struct, IFunc { @@ -698,9 +703,11 @@ public void RemoveAllWithoutShrink(Predicate predicate = default) _count -= removed; } - /// Removes the first predicated value from the list. + /// + /// Removes the first predicated value from the list. + /// Runtime: O(n), Ω(1) + /// /// The predicate to determine removals. - /// O(n), Ω(1) public void RemoveFirst(Func predicate) { if (!TryRemoveFirst(predicate, out Exception exception)) @@ -709,27 +716,33 @@ public void RemoveFirst(Func predicate) } } - /// Removes the first occurence of a value from the list without causing the list to shrink. + /// + /// Removes the first occurence of a value from the list without causing the list to shrink. + /// Runtime: O(n), Ω(1) + /// /// The value to remove. - /// O(n), Ω(1) public void RemoveFirstWithoutShrink(T value) { RemoveFirstWithoutShrink(value, Equate); } - /// Removes the first occurence of a value from the list without causing the list to shrink. + /// + /// Removes the first occurence of a value from the list without causing the list to shrink. + /// Runtime: O(n), Ω(1) + /// /// The value to remove. /// The delegate providing the equality check. - /// O(n), Ω(1) public void RemoveFirstWithoutShrink(T value, Func equate) { RemoveFirstWithoutShrink(x => equate(x, value), out _); } - /// Removes the first predicated value from the list wihtout shrinking the list. + /// + /// Removes the first predicated value from the list wihtout shrinking the list. + /// Runtime: O(n), Ω(1) + /// /// The predicate to determine removals. /// The exception that occured if the removal failed. - /// O(n), Ω(1) public void RemoveFirstWithoutShrink(Func predicate, out Exception exception) { if (!TryRemoveFirst(predicate, out exception)) @@ -775,60 +788,36 @@ public bool TryRemoveFirst(out Exception exception, Predicate predica #region Stepper - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void Stepper(Step step = default) where Step : struct, IAction => StepperRef>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void Stepper(Action step) => Stepper>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void StepperRef(Step step = default) where Step : struct, IStepRef => StepperRefBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void Stepper(StepRef step) => StepperRef>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// public StepStatus StepperBreak(Step step = default) where Step : struct, IFunc => StepperRefBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// public StepStatus Stepper(Func step) => StepperBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// public StepStatus Stepper(StepRefBreak step) => StepperRefBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// public StepStatus StepperRefBreak(Step step = default) where Step : struct, IStepRefBreak => _list.StepperRefBreak(0, _count, step); diff --git a/Sources/Towel/DataStructures/Map.cs b/Sources/Towel/DataStructures/Map.cs index d7476695..85ee3718 100644 --- a/Sources/Towel/DataStructures/Map.cs +++ b/Sources/Towel/DataStructures/Map.cs @@ -193,11 +193,13 @@ internal class Node #region Constructors - /// Constructs a hashed map. + /// + /// Constructs a hashed map. + /// Runtime: O(1) + /// /// The equate delegate. /// The hashing function. /// The expected count of the map. - /// O(1) public MapHashLinked( Equate equate = default, Hash hash = default, @@ -221,9 +223,11 @@ public MapHashLinked( _count = 0; } - /// This constructor is for cloning purposes. + /// + /// This constructor is for cloning purposes. + /// Runtime: O(n) + /// /// The map to clone. - /// O(n) internal MapHashLinked(MapHashLinked map) { _equate = map._equate; @@ -236,23 +240,31 @@ internal MapHashLinked(MapHashLinked map) #region Properties - /// The current size of the hashed table. - /// O(1) + /// + /// The current size of the hashed table. + /// Runtime: O(1) + /// public int TableSize => _table.Length; - /// The current number of values in the map. - /// O(1) + /// + /// The current number of values in the map. + /// Runtime: O(1) + /// public int Count => _count; - /// The delegate for computing hash codes. - /// O(1) + /// + /// The delegate for computing hash codes. + /// Runtime: O(1) + /// Func DataStructure.IHashing.Hash => _hash is FuncRuntime hash ? hash._delegate : _hash.Do; - /// The delegate for equality checking. - /// O(1) + /// + /// The delegate for equality checking. + /// Runtime: O(1) + /// Func DataStructure.IEquating.Equate => _equate is FuncRuntime equate ? equate._delegate @@ -269,12 +281,14 @@ _equate is FuncRuntime equate #region Add - /// Tries to add a value to the map. + /// + /// Tries to add a value to the map. + /// Runtime: O(n), Ω(1), ε(1) + /// /// The key of the value. /// The value to be added. /// The exception that occured if the add failed. /// True if the value was added or false if not. - /// O(n), Ω(1), ε(1) public bool TryAdd(K key, T value, out Exception exception) { _ = key ?? throw new ArgumentNullException(nameof(key)); @@ -350,10 +364,12 @@ public bool TryGet(K key, out T value, out Exception exception) #region Set - /// Sets value in the map. + /// + /// Sets value in the map. + /// Runtime: O(n), Ω(1), ε(1) + /// /// The key of the value. /// The value to be set. - /// O(n), Ω(1), ε(1) public void Set(K key, T value) { _ = key ?? throw new ArgumentNullException(nameof(key)); @@ -481,8 +497,10 @@ internal void Resize(int tableSize) #region Trim - /// Trims the table to an appropriate size based on the current count. - /// O(n), Ω(1) + /// + /// Trims the table to an appropriate size based on the current count. + /// Runtime: O(n), Ω(1) + /// public void Trim() { int tableSize = _count; @@ -497,19 +515,23 @@ public void Trim() #region Clone - /// Creates a shallow clone of this map. + /// + /// Creates a shallow clone of this map. + /// Runtime: Θ(n) + /// /// A shallow clone of this map. - /// Θ(n) public MapHashLinked Clone() => new MapHashLinked(this); #endregion #region Contains - /// Determines if a value has been added to a map. + /// + /// Determines if a value has been added to a map. + /// Runtime: O(n), Ω(1), ε(1) + /// /// The key of the value to look for in the map. /// True if the value has been added to the map or false if not. - /// O(n), Ω(1), ε(1) public bool Contains(K key) { int hashCode = _hash.Do(key); @@ -528,8 +550,10 @@ public bool Contains(K key) #region Clear - /// Removes all the values in the map. - /// O(1) + /// + /// Removes all the values in the map. + /// Runtime: O(1) + /// public void Clear() { _table = new Node[2]; @@ -540,9 +564,7 @@ public void Clear() #region Stepper And IEnumerable - /// Steps through all the values of the map. - /// The action to perform on every value in the map. - /// Θ(n * step) + /// public void Stepper(Action step) { for (int i = 0; i < _table.Length; i++) @@ -554,9 +576,7 @@ public void Stepper(Action step) } } - /// Steps through all the values of the map. - /// The action to perform on every value in the map. - /// Θ(n * step) + /// public void Stepper(StepRef step) { for (int i = 0; i < _table.Length; i++) @@ -568,10 +588,7 @@ public void Stepper(StepRef step) } } - /// Steps through all the values of the map. - /// The action to perform on every value in the map. - /// The status of the stepper. - /// Θ(n * step) + /// public StepStatus Stepper(Func step) { for (int i = 0; i < _table.Length; i++) @@ -587,10 +604,7 @@ public StepStatus Stepper(Func step) return Continue; } - /// Steps through all the values of the map. - /// The action to perform on every value in the map. - /// The status of the stepper. - /// Θ(n * step) + /// public StepStatus Stepper(StepRefBreak step) { for (int i = 0; i < _table.Length; i++) @@ -606,9 +620,7 @@ public StepStatus Stepper(StepRefBreak step) return Continue; } - /// Steps through all the keys of the map. - /// The action to perform on every value in the map. - /// Θ(n * step) + /// public void Keys(Action step) { for (int i = 0; i < _table.Length; i++) @@ -620,10 +632,7 @@ public void Keys(Action step) } } - /// Steps through all the keys of the map. - /// The action to perform on every value in the map. - /// The status of the stepper. - /// Θ(n * step) + /// public StepStatus Keys(Func step) { for (int i = 0; i < _table.Length; i++) @@ -639,9 +648,7 @@ public StepStatus Keys(Func step) return Continue; } - /// Steps through all the keys and values of the map. - /// The action to perform on every key and value in the map. - /// Θ(n * step) + /// public void Stepper(Action step) { for (int i = 0; i < _table.Length; i++) @@ -653,10 +660,7 @@ public void Stepper(Action step) } } - /// Steps through all the keys and values of the map. - /// The action to perform on every key and value in the map. - /// The status of the stepper. - /// Θ(n * step) + /// public StepStatus Stepper(Func step) { for (int i = 0; i < _table.Length; i++) @@ -676,7 +680,6 @@ public StepStatus Stepper(Func step) /// Gets the enumerator for the map. /// The enumerator for the map. - /// O(n) public System.Collections.Generic.IEnumerator GetEnumerator() { for (int i = 0; i < _table.Length; i++) @@ -692,9 +695,11 @@ public System.Collections.Generic.IEnumerator GetEnumerator() #region ToArray - /// Puts all the values in this map into an array. + /// + /// Puts all the values in this map into an array. + /// Runtime: Θ(n) + /// /// An array with all the values in the map. - /// Θ(n) public T[] ToArray() { T[] array = new T[_count]; @@ -721,19 +726,23 @@ public class MapHashLinked : MapHashLinked, { #region Constructors - /// Constructs a hashed map. + /// + /// Constructs a hashed map. + /// Runtime: O(1) + /// /// The equate delegate. /// The hashing function. /// The expected count of the map. - /// O(1) public MapHashLinked( Func equate = null, Func hash = null, int? expectedCount = null) : base(equate ?? Statics.Equate, hash ?? DefaultHash, expectedCount) { } - /// This constructor is for cloning purposes. + /// + /// This constructor is for cloning purposes. + /// Runtime: O(n) + /// /// The map to clone. - /// O(n) internal MapHashLinked(MapHashLinked map) { _equate = map._equate; @@ -746,21 +755,27 @@ internal MapHashLinked(MapHashLinked map) #region Properties - /// The delegate for computing hash codes. - /// O(1) + /// + /// The delegate for computing hash codes. + /// Runtime: O(1) + /// public Func Hash => _hash._delegate; - /// The delegate for equality checking. - /// O(1) + /// + /// The delegate for equality checking. + /// Runtime: O(1) + /// public Func Equate => _equate._delegate; #endregion #region Clone - /// Creates a shallow clone of this map. + /// + /// Creates a shallow clone of this map. + /// Runtime: Θ(n) + /// /// A shallow clone of this map. - /// Θ(n) public new MapHashLinked Clone() => new MapHashLinked(this); #endregion diff --git a/Sources/Towel/DataStructures/Omnitree_ND.cs b/Sources/Towel/DataStructures/Omnitree_ND.cs index 943eff12..0d800c89 100644 --- a/Sources/Towel/DataStructures/Omnitree_ND.cs +++ b/Sources/Towel/DataStructures/Omnitree_ND.cs @@ -97,58 +97,31 @@ public enum Keyword /// The generic type of the bound. public struct Bound { - internal readonly bool Exists; - internal readonly T Value; - - /// Constructs a bound from a value. - /// The value of the bound. - public Bound(T value) - { - Exists = true; - Value = value; - } - - internal Bound(bool exists, T value) - { - Exists = exists; - Value = value; - } + internal bool Exists; + internal T Value; /// Represents a null bound meaning it does not exist. - public readonly static Bound None = new Bound(false, default); + public readonly static Bound None = new Bound { Value = default, Exists = false }; /// Converts a value to a bound. /// The value to convert into a bound. - public static implicit operator Bound(T value) => new Bound(value); + public static implicit operator Bound(T value) => new Bound { Value = value, Exists = true }; /// Implicitly converts the "None" keyword into a non-existant bound. /// The keyword to convert into a non-existant bound. public static implicit operator Bound(Keyword keyword) => keyword == Keyword.None - ? None - : throw new InvalidCastException("Implicit cast from invalid Omnitree.Keyword."); + ? None + : throw new InvalidCastException("Implicit cast from invalid Omnitree.Keyword."); /// Gets the bound compare delegate from a value compare delegate. /// The value compare to wrap into a bounds compare. /// The bounds compare. - public static Func, Bound, CompareResult> Compare(Func compare) - { - return (Bound a, Bound b) => - { - if (a.Exists && b.Exists) - { - return compare(a.Value, b.Value); - } - else if (!b.Exists) - { - return Equal; - } - else - { - return Greater; - } - }; - } + public static Func, Bound, CompareResult> Compare(Func compare) => + (a, b) => + a.Exists && b.Exists ? compare(a.Value, b.Value) : + !b.Exists ? Equal : + Greater; } /// A delegate for determining the point of subdivision in a set of values and current bounds. @@ -243,16 +216,11 @@ public struct Vector { internal object[] _location; - /// The locations along each axis. public object[] Location => _location; - /// Returns a vector with defaulted values. - public static Vector Default - { - get { return new Vector(null); } - } + public static Vector Default => new Vector(null); /// Constructs an N-D vector. /// @@ -287,8 +255,8 @@ public static Bounds None(int dimensions) /// A set of values denoting a range (or lack of range) along each axis. public Bounds(Bound[] min, Bound[] max) { - this._min = min.Clone() as Bound[]; - this._max = max.Clone() as Bound[]; + _min = min.Clone() as Bound[]; + _max = max.Clone() as Bound[]; } } diff --git a/Sources/Towel/DataStructures/Queue.cs b/Sources/Towel/DataStructures/Queue.cs index 2ffdfbd2..1553123d 100644 --- a/Sources/Towel/DataStructures/Queue.cs +++ b/Sources/Towel/DataStructures/Queue.cs @@ -48,19 +48,16 @@ internal class Node { internal T Value; internal Node Next; - - internal Node(T data) - { - Value = data; - } } #endregion #region Constructors - /// Creates an instance of a queue. - /// O(1) + /// + /// Creates an instance of a queue. + /// Runtime: O(1) + /// public QueueLinked() { _head = _tail = null; @@ -71,22 +68,28 @@ public QueueLinked() #region Properties - /// The newest item currently in the queue. - /// O(1) + /// + /// The newest item currently in the queue. + /// Runtime: O(1) + /// public T Newest => _count > 0 ? _tail.Value : throw new InvalidOperationException("attempting to get the newest item in an empty queue"); - /// The oldest item currently in the queue. - /// O(1) + /// + /// The oldest item currently in the queue. + /// Runtime: O(1) + /// public T Oldest => _count > 0 ? _head.Value : throw new InvalidOperationException("attempting to get the oldet item in an empty queue"); - /// Returns the number of items in the queue. - /// O(1) + /// + /// Returns the number of items in the queue. + /// Runtime: O(1) + /// public int Count => _count; #endregion @@ -95,9 +98,11 @@ public QueueLinked() #region ToArray - /// Converts the list into a standard array. + /// + /// Converts the list into a standard array. + /// Runtime: O(n) + /// /// A standard array of all the items. - /// O(n) public T[] ToArray() { T[] array = new T[_count]; @@ -117,12 +122,12 @@ public T[] ToArray() /// A shallow clone of this data structure. public QueueLinked Clone() { - Node head = new Node(_head.Value); + Node head = new Node { Value = _head.Value }; Node current = _head.Next; Node current_clone = head; while (!(current is null)) { - current_clone.Next = new Node(current.Value); + current_clone.Next = new Node { Value = current.Value }; current_clone = current_clone.Next; current = current.Next; } @@ -139,18 +144,20 @@ public QueueLinked Clone() #region Enqueue - /// Adds an item to the back of the queue. + /// + /// Adds an item to the back of the queue. + /// Runtime: O(1) + /// /// The item to add to the queue. - /// O(1) public void Enqueue(T enqueue) { if (_tail is null) { - _head = _tail = new Node(enqueue); + _head = _tail = new Node { Value = enqueue }; } else { - _tail = _tail.Next = new Node(enqueue); + _tail = _tail.Next = new Node { Value = enqueue }; } _count++; } @@ -159,9 +166,11 @@ public void Enqueue(T enqueue) #region Dequeue - /// Removes the oldest item in the queue. + /// + /// Removes the oldest item in the queue. + /// Runtime: O(1) + /// /// The next item in the queue. - /// O(1) public T Dequeue() { if (_head is null) @@ -198,8 +207,10 @@ public T Peek() #region Clear - /// Resets the queue to an empty state. - /// O(1) + /// + /// Resets the queue to an empty state. + /// Runtime: O(1) + /// public void Clear() { _head = _tail = null; @@ -210,54 +221,37 @@ public void Clear() #region Stepper - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void Stepper(Step step = default) where Step : struct, IAction => StepperRef>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void Stepper(Action step) => Stepper>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void StepperRef(Step step = default) where Step : struct, IStepRef => StepperRefBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void Stepper(StepRef step) => StepperRef>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// public StepStatus StepperBreak(Step step = default) where Step : struct, IFunc => StepperRefBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) - public StepStatus Stepper(Func step) => StepperBreak>(step); - - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// + public StepStatus Stepper(Func step) => + StepperBreak>(step); + + /// + public StepStatus Stepper(StepRefBreak step) => StepperRefBreak>(step); + + /// public StepStatus StepperRefBreak(Step step = default) where Step : struct, IStepRefBreak { @@ -271,12 +265,6 @@ public StepStatus StepperRefBreak(Step step = default) return Continue; } - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) - public StepStatus Stepper(StepRefBreak step) => StepperRefBreak>(step); - #endregion #region IEnumerable @@ -309,8 +297,10 @@ public class QueueArray : IQueue #region Constructors - /// Creates an instance of a ListArray, and sets it's minimum capacity. - /// θ(1) + /// + /// Creates an instance of a ListArray, and sets it's minimum capacity. + /// Runtime: O(1) + /// public QueueArray() { _queue = new T[1]; @@ -318,9 +308,11 @@ public QueueArray() _minimumCapacity = 1; } - /// Creates an instance of a ListArray, and sets it's minimum capacity. + /// + /// Creates an instance of a ListArray, and sets it's minimum capacity. + /// Runtime: O(1) + /// /// The initial and smallest array size allowed by this list. - /// θ(1) public QueueArray(int minimumCapacity) { _queue = new T[minimumCapacity]; @@ -332,28 +324,23 @@ public QueueArray(int minimumCapacity) #region Properties - /// Gets the number of items in the list. - /// O(1) - public int Count - { - get - { - return _count; - } - } - - /// Gets the current capacity of the list. - /// O(1) - public int CurrentCapacity - { - get - { - return _queue.Length; - } - } + /// + /// Gets the number of items in the list. + /// Runtime: O(1) + /// + public int Count => _count; - /// Allows you to adjust the minimum capacity of this list. - /// O(n), Ω(1) + /// + /// Gets the current capacity of the list. + /// Runtime: O(1) + /// + public int CurrentCapacity => _queue.Length; + + /// + /// Allows you to adjust the minimum capacity of this list. + /// Runtime (Get): O(1) + /// Runtime (Set): O(n), Ω(1) + /// public int MinimumCapacity { get @@ -381,29 +368,17 @@ public int MinimumCapacity /// The newest item currently in the queue. public T Newest { - get - { - if (this._count > 0) - return this._queue[(this._start + this._count) % this._queue.Length]; - else - throw new System.InvalidOperationException("attempting to get the newest item in an empty queue"); - } + get => _count > 0 + ? _queue[(_start + _count) % _queue.Length] + : throw new InvalidOperationException("attempting to get the newest item in an empty queue"); } /// The oldest item currently in the queue. public T Oldest { - get - { - if (_count > 0) - { - return _queue[_start]; - } - else - { - throw new InvalidOperationException("attempting to get the oldet item in an empty queue"); - } - } + get => _count > 0 + ? _queue[_start] + : throw new InvalidOperationException("attempting to get the oldet item in an empty queue"); } #endregion @@ -451,9 +426,11 @@ public IDataStructure Clone() #region Enqueue - /// Adds an item to the end of the list. + /// + /// Adds an item to the end of the list. + /// Runtime: O(n), ε(1) + /// /// The item to be added. - /// O(n), ε(1) public void Enqueue(T addition) { if (_count == _queue.Length) @@ -477,8 +454,10 @@ public void Enqueue(T addition) #region Dequeue - /// Removes the item at a specific index. - /// O(n - index) + /// + /// Removes the item at a specific index. + /// Runtime: O(n - index) + /// public T Dequeue() { if (_count == 0) @@ -520,8 +499,10 @@ public T Peek() #region Clear - /// Empties the list back and reduces it back to its original capacity. - /// O(1) + /// + /// Empties the list back and reduces it back to its original capacity. + /// Runtime: O(1) + /// public void Clear() { _queue = new T[_minimumCapacity]; @@ -532,60 +513,38 @@ public void Clear() #region Stepper - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void Stepper(Step step = default) where Step : struct, IAction => StepperRef>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void Stepper(Action step) => Stepper>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void StepperRef(Step step = default) where Step : struct, IStepRef => StepperRefBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void Stepper(StepRef step) => StepperRef>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// public StepStatus StepperBreak(Step step = default) where Step : struct, IFunc => StepperRefBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) - public StepStatus Stepper(Func step) => StepperBreak>(step); + /// + public StepStatus Stepper(Func step) => + StepperBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) - public StepStatus Stepper(StepRefBreak step) => StepperRefBreak>(step); + /// + public StepStatus Stepper(StepRefBreak step) => + StepperRefBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// public StepStatus StepperRefBreak(Step step = default) where Step : struct, IStepRefBreak { diff --git a/Sources/Towel/DataStructures/RedBlackTree.cs b/Sources/Towel/DataStructures/RedBlackTree.cs index 133ec3dc..3d240d01 100644 --- a/Sources/Towel/DataStructures/RedBlackTree.cs +++ b/Sources/Towel/DataStructures/RedBlackTree.cs @@ -116,8 +116,10 @@ public T CurrentGreatest /// The number of items in this data structure. public int Count => _count; - /// The comparison function being utilized by this structure. - /// θ(1) + /// + /// The comparison function being utilized by this structure. + /// Runtime: O(1) + /// Func DataStructure.IComparing.Compare => _compare is FuncRuntime func ? func._delegate @@ -150,9 +152,11 @@ public bool TryAdd(T value, out Exception exception) capturedException = new ArgumentException($"Adding to add a duplicate value to a {nameof(RedBlackTreeLinked)}: {value}.", nameof(value)); goto Break; default: +#pragma warning disable CA2208 // Instantiate argument exceptions correctly capturedException = compareResult.IsDefined() - ? (Exception)new TowelBugException($"Unhandled {nameof(CompareResult)} value: {compareResult}.") - : new ArgumentException($"Invalid {nameof(Compare)} function; an undefined {nameof(CompareResult)} was returned.", nameof(Compare)); + ? (Exception)new TowelBugException($"Unhandled {nameof(CompareResult)} value: {compareResult}.") + : new ArgumentException($"Invalid {nameof(Compare)} function; an undefined {nameof(CompareResult)} was returned.", nameof(Compare)); +#pragma warning restore CA2208 // Instantiate argument exceptions correctly goto Break; } } @@ -224,10 +228,12 @@ public void Clear() /// True if the tree contains the value. False if not. public bool Contains(T value) => Contains(x => _compare.Do(x, value)); - /// Determines if this structure contains an item by a given key. + /// + /// Determines if this structure contains an item by a given key. + /// Runtime: O(ln(Count)), Ω(1) + /// /// The sorting technique (must synchronize with this structure's sorting). /// True of contained, False if not. - /// O(ln(Count)) Ω(1) public bool Contains(Func sift) { Node node = _root; @@ -391,54 +397,36 @@ internal void Remove(Node removal) #region Stepper - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void Stepper(Step step = default) where Step : struct, IAction => StepperRef>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void Stepper(Action step) => Stepper>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void StepperRef(Step step = default) where Step : struct, IStepRef => StepperRefBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void Stepper(StepRef step) => StepperRef>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// public StepStatus StepperBreak(Step step = default) where Step : struct, IFunc => StepperRefBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// public StepStatus Stepper(Func step) => StepperBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// + public StepStatus Stepper(StepRefBreak step) => StepperRefBreak>(step); + + /// public StepStatus StepperRefBreak(Step step = default) where Step : struct, IStepRefBreak { @@ -457,72 +445,42 @@ StepStatus Stepper(Node node) return Stepper(_root); } - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) - public StepStatus Stepper(StepRefBreak step) => StepperRefBreak>(step); - #endregion #region Stepper (ranged) - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) + /// public virtual void Stepper(T minimum, T maximum, Step step = default) where Step : struct, IAction => StepperBreak>(minimum, maximum, step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) + /// public virtual void Stepper(T minimum, T maximum, Action step) => Stepper>(minimum, maximum, step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) + /// public virtual void StepperRef(T minimum, T maximum, Step step = default) where Step : struct, IStepRef => StepperRefBreak>(minimum, maximum, step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) + /// public virtual void Stepper(T minimum, T maximum, StepRef step) => StepperRef>(minimum, maximum, step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) + /// public virtual StepStatus StepperBreak(T minimum, T maximum, Step step = default) where Step : struct, IFunc => StepperRefBreak>(minimum, maximum, step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) + /// public virtual StepStatus Stepper(T minimum, T maximum, Func step) => StepperBreak>(minimum, maximum, step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) + /// + public virtual StepStatus Stepper(T minimum, T maximum, StepRefBreak step) => + StepperRefBreak>(minimum, maximum); + + /// public virtual StepStatus StepperRefBreak(T minimum, T maximum, Step step = default) where Step : struct, IStepRefBreak { @@ -556,63 +514,42 @@ StepStatus Stepper(Node node) return Stepper(_root); } - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) - public virtual StepStatus Stepper(T minimum, T maximum, StepRefBreak step) => - StepperRefBreak>(minimum, maximum); - #endregion #region StepperReverse - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void StepperReverse(Step step = default) where Step : struct, IAction => StepperReverseBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void StepperReverse(Action step) => StepperReverse>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void StepperReverseRef(Step step = default) where Step : struct, IStepRef => StepperReverseRefBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void StepperReverse(StepRef step) => StepperReverseRef>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// public StepStatus StepperReverseBreak(Step step = default) where Step : struct, IFunc => StepperReverseRefBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// public StepStatus StepperReverse(Func step) => StepperReverseBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// + public StepStatus StepperReverse(StepRefBreak step) => + StepperReverseRefBreak>(step); + + /// public StepStatus StepperReverseRefBreak(Step step = default) where Step : struct, IStepRefBreak { @@ -631,73 +568,42 @@ StepStatus StepperReverse(Node node) return StepperReverse(_root); } - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) - public StepStatus StepperReverse(StepRefBreak step) => - StepperReverseRefBreak>(step); - #endregion #region StepperReverse (ranged) - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) + /// public virtual void StepperReverse(T minimum, T maximum, Step step = default) where Step : struct, IAction => StepperReverseBreak>(minimum, maximum, step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) + /// public virtual void StepperReverse(T minimum, T maximum, Action step) => StepperReverse>(minimum, maximum, step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) + /// public virtual void StepperReverseRef(T minimum, T maximum, Step step = default) where Step : struct, IStepRef => StepperReverseRefBreak>(minimum, maximum, step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) + /// public virtual void StepperReverse(T minimum, T maximum, StepRef step) => StepperReverseRef>(minimum, maximum, step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) + /// public virtual StepStatus StepperReverseBreak(T minimum, T maximum, Step step = default) where Step : struct, IFunc => StepperReverseRefBreak>(minimum, maximum, step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) + /// public virtual StepStatus StepperReverse(T minimum, T maximum, Func step) => StepperReverseBreak>(minimum, maximum, step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) + /// + public virtual StepStatus StepperReverse(T minimum, T maximum, StepRefBreak step) => + StepperReverseRefBreak>(minimum, maximum, step); + + /// public virtual StepStatus StepperReverseRefBreak(T minimum, T maximum, Step step = default) where Step : struct, IStepRefBreak { @@ -731,14 +637,6 @@ StepStatus StepperReverse(Node node) return StepperReverse(_root); } - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The minimum value of the optimized stepper function. - /// The maximum value of the optimized stepper function. - /// O(n * step), Ω(1) - public virtual StepStatus StepperReverse(T minimum, T maximum, StepRefBreak step) => - StepperReverseRefBreak>(minimum, maximum, step); - #endregion #region IEnumerable diff --git a/Sources/Towel/DataStructures/Set.cs b/Sources/Towel/DataStructures/Set.cs index 3c29c008..6962fa07 100644 --- a/Sources/Towel/DataStructures/Set.cs +++ b/Sources/Towel/DataStructures/Set.cs @@ -40,23 +40,19 @@ internal class Node { internal T Value; internal Node Next; - - internal Node(T value, Node next) - { - Value = value; - Next = next; - } } #endregion #region Constructors - /// Constructs a hashed set. + /// + /// Constructs a hashed set. + /// Runtime: O(1) + /// /// The equate delegate. /// The hashing function. /// The expected count of the set. - /// O(1) public SetHashLinked( Equate equate = default, Hash hash = default, @@ -80,9 +76,11 @@ public SetHashLinked( _count = 0; } - /// This constructor is for cloning purposes. + /// + /// This constructor is for cloning purposes. + /// Runtime: O(n) + /// /// The set to clone. - /// O(n) internal SetHashLinked(SetHashLinked set) { _equate = set._equate; @@ -95,23 +93,31 @@ internal SetHashLinked(SetHashLinked set) #region Properties - /// The current size of the hashed table. - /// O(1) + /// + /// The current size of the hashed table. + /// Runtime: O(1) + /// public int TableSize => _table.Length; - /// The current number of values in the set. - /// O(1) + /// + /// The current number of values in the set. + /// Runtime: O(1) + /// public int Count => _count; - /// The delegate for computing hash codes. - /// O(1) + /// + /// The delegate for computing hash codes. + /// Runtime: O(1) + /// Func DataStructure.IHashing.Hash => _hash is FuncRuntime hash ? hash._delegate : _hash.Do; - /// The delegate for equality checking. - /// O(1) + /// + /// The delegate for equality checking. + /// Runtime: O(1) + /// Func DataStructure.IEquating.Equate => _equate is FuncRuntime func ? func._delegate @@ -123,10 +129,12 @@ _equate is FuncRuntime func #region Add - /// Adds a value to the set. + /// + /// Adds a value to the set. + /// Runtime: O(n), Ω(1), ε(1) + /// /// The value to add to the set. /// The exception that occurred if the add failed. - /// O(n), Ω(1), ε(1) public bool TryAdd(T value, out Exception exception) { _ = value ?? throw new ArgumentNullException(nameof(value)); @@ -147,7 +155,7 @@ public bool TryAdd(T value, out Exception exception) { // add the value - Node node = new Node(value, _table[location]); + Node node = new Node { Value = value, Next = _table[location] }; _table[location] = node; } @@ -282,8 +290,10 @@ internal void Resize(int tableSize) #region Trim - /// Trims the table to an appropriate size based on the current count. - /// O(n), Ω(1) + /// + /// Trims the table to an appropriate size based on the current count. + /// Runtime: O(n), Ω(1) + /// public void Trim() { int tableSize = _count; @@ -298,19 +308,23 @@ public void Trim() #region Clone - /// Creates a shallow clone of this set. + /// + /// Creates a shallow clone of this set. + /// Runtime: Θ(n) + /// /// A shallow clone of this set. - /// Θ(n) public SetHashLinked Clone() => new SetHashLinked(this); #endregion #region Contains - /// Determines if a value has been added to a set. + /// + /// Determines if a value has been added to a set. + /// Runtime: O(n), Ω(1), ε(1) + /// /// The value to look for in the set. /// True if the value has been added to the set or false if not. - /// O(n), Ω(1), ε(1) public bool Contains(T value) { // compute the hash code and relate it to the current table @@ -332,8 +346,10 @@ public bool Contains(T value) #region Clear - /// Removes all the values in the set. - /// O(1) + /// + /// Removes all the values in the set. + /// Runtime: O(1) + /// public void Clear() { _table = new Node[2]; @@ -344,9 +360,7 @@ public void Clear() #region Stepper And IEnumerable - /// Steps through all the values of the set. - /// The action to perform on every value in the set. - /// Θ(n * step) + /// public void Stepper(Action step) { for (int i = 0; i < _table.Length; i++) @@ -358,10 +372,7 @@ public void Stepper(Action step) } } - /// Steps through all the values of the set. - /// The action to perform on every value in the set. - /// The status of the stepper. - /// Θ(n * step) + /// public StepStatus Stepper(Func step) { for (int i = 0; i < _table.Length; i++) @@ -381,7 +392,6 @@ public StepStatus Stepper(Func step) /// Gets the enumerator for the set. /// The enumerator for the set. - /// O(n) public System.Collections.Generic.IEnumerator GetEnumerator() { for (int i = 0; i < _table.Length; i++) @@ -397,9 +407,11 @@ public System.Collections.Generic.IEnumerator GetEnumerator() #region ToArray - /// Puts all the values in this set into an array. + /// + /// Puts all the values in this set into an array. + /// Runtime: Θ(n) + /// /// An array with all the values in the set. - /// Θ(n) public T[] ToArray() { T[] array = new T[_count]; @@ -425,19 +437,23 @@ public class SetHashLinked : SetHashLinked, FuncRu { #region Constructors - /// Constructs a hashed set. + /// + /// Constructs a hashed set. + /// Runtime: O(1) + /// /// The equate delegate. /// The hashing function. /// The expected count of the set. - /// O(1) public SetHashLinked( Func equate = null, Func hash = null, int? expectedCount = null) : base(equate ?? Statics.Equate, hash ?? DefaultHash, expectedCount) { } - /// This constructor is for cloning purposes. + /// + /// This constructor is for cloning purposes. + /// Runtime: O(n) + /// /// The set to clone. - /// O(n) internal SetHashLinked(SetHashLinked set) { _equate = set._equate; @@ -450,21 +466,27 @@ internal SetHashLinked(SetHashLinked set) #region Properties - /// The delegate for computing hash codes. - /// O(1) + /// + /// The delegate for computing hash codes. + /// Runtime: O(1) + /// public Func Hash => _hash._delegate; - /// The delegate for equality checking. - /// O(1) + /// + /// The delegate for equality checking. + /// Runtime: O(1) + /// public Func Equate => _equate._delegate; #endregion #region Clone - /// Creates a shallow clone of this set. + /// + /// Creates a shallow clone of this set. + /// Runtime: Θ(n) + /// /// A shallow clone of this set. - /// Θ(n) public new SetHashLinked Clone() => new SetHashLinked(this); #endregion @@ -509,12 +531,14 @@ public class Set : ISet, #region Constructors - /// Constructs a hashed set. + /// + /// Constructs a hashed set. + /// Runtime: O(1) + /// /// The factory delegate. /// The equate delegate. /// The hashing function. /// The expected count of the set. - /// O(1) public Set( StructureFactory factory, Func equate = null, @@ -540,10 +564,12 @@ public Set( _count = 0; } - /// This constructor is for cloning purposes. + /// + /// This constructor is for cloning purposes. + /// Runtime: O(n) + /// /// The set to clone. /// A delegate for cloning the structures. - /// O(n) internal Set(Set set, StructureClone clone) { _factory = set._factory; @@ -564,20 +590,28 @@ internal Set(Set set, StructureClone clone) #region Properties - /// The current size of the hashed table. - /// O(1) + /// + /// The current size of the hashed table. + /// Runtime: O(1) + /// public int TableSize => _table.Length; - /// The current number of values in the set. - /// O(1) + /// + /// The current number of values in the set. + /// Runtime: O(1) + /// public int Count => _count; - /// The delegate for computing hash codes. - /// O(1) + /// + /// The delegate for computing hash codes. + /// Runtime: O(1) + /// public Func Hash => _hash; - /// The delegate for equality checking. - /// O(1) + /// + /// The delegate for equality checking. + /// Runtime: O(1) + /// public Func Equate => _equate; #endregion @@ -586,10 +620,12 @@ internal Set(Set set, StructureClone clone) #region Add - /// Adds a value to the hash table. + /// + /// Adds a value to the hash table. + /// Runtime: O(n), Ω(1), ε(1) + /// /// The key value to use as the look-up reference in the hash table. /// The exception that occurred if the add failed. - /// O(n), Ω(1), ε(1) public bool TryAdd(T value, out Exception exception) { _ = value ?? throw new ArgumentNullException(nameof(value)); @@ -639,10 +675,12 @@ public bool TryAdd(T value, out Exception exception) #region Remove - /// Removes a value from the set. + /// + /// Removes a value from the set. + /// Runtime: O(n), Ω(1), ε(1) + /// /// The value to remove. /// The exception that occurred if the remove failed. - /// O(n), Ω(1), ε(1) public bool TryRemove(T value, out Exception exception) { if (TryRemoveWithoutTrim(value, out exception)) @@ -664,10 +702,12 @@ public bool TryRemove(T value, out Exception exception) return false; } - /// Removes a value from the set. + /// + /// Removes a value from the set. + /// Runtime: O(n), Ω(1), ε(1) + /// /// The value to remove. /// The exception that occurred if the remove failed. - /// O(n), Ω(1), ε(1) public bool TryRemoveWithoutTrim(T value, out Exception exception) { _ = value ?? throw new ArgumentNullException(nameof(value)); @@ -723,19 +763,23 @@ internal void Resize(int tableSize) #region Clone - /// Creates a shallow clone of this set. + /// + /// Creates a shallow clone of this set. + /// Runtime: Θ(n) + /// /// A shallow clone of this set. - /// Θ(n) public Set Clone(StructureClone clone) => new Set(this, clone); #endregion #region Contains - /// Determines if a value has been added to a set. + /// + /// Determines if a value has been added to a set. + /// Runtime: O(n), Ω(1), ε(1) + /// /// The value to look for in the set. /// True if the value has been added to the set or false if not. - /// O(n), Ω(1), ε(1) public bool Contains(T value) { _ = value ?? throw new ArgumentNullException(nameof(value)); @@ -751,8 +795,10 @@ public bool Contains(T value) #region Clear - /// Removes all the values in the set. - /// O(1) + /// + /// Removes all the values in the set. + /// Runtime: O(1) + /// public void Clear() { _table = new Structure[2]; @@ -763,8 +809,10 @@ public void Clear() #region Trim - /// Trims the table to an appropriate size based on the current count. - /// O(n), Ω(1) + /// + /// Trims the table to an appropriate size based on the current count. + /// Runtime: O(n), Ω(1) + /// public void Trim() { int tableSize = _count; @@ -779,9 +827,7 @@ public void Trim() #region Stepper And IEnumerable - /// Steps through all the values of the set. - /// The action to perform on every value in the set. - /// Θ(n * step) + /// public void Stepper(Action step) { for (int i = 0; i < _table.Length; i++) @@ -793,10 +839,7 @@ public void Stepper(Action step) } } - /// Steps through all the values of the set. - /// The action to perform on every value in the set. - /// The status of the stepper. - /// Θ(n * step) + /// public StepStatus Stepper(Func step) { for (int i = 0; i < _table.Length; i++) @@ -816,7 +859,6 @@ public StepStatus Stepper(Func step) /// Gets the enumerator for the set. /// The enumerator for the set. - /// O(n) public System.Collections.Generic.IEnumerator GetEnumerator() { for (int i = 0; i < _table.Length; i++) @@ -835,9 +877,11 @@ public System.Collections.Generic.IEnumerator GetEnumerator() #region ToArray - /// Puts all the values in this set into an array. + /// + /// Puts all the values in this set into an array. + /// Runtime: Θ(n) + /// /// An array with all the values in the set. - /// Θ(n) public T[] ToArray() { T[] array = new T[_count]; diff --git a/Sources/Towel/DataStructures/SortedBinaryTree.cs b/Sources/Towel/DataStructures/SortedBinaryTree.cs index 3c6b4718..c120982b 100644 --- a/Sources/Towel/DataStructures/SortedBinaryTree.cs +++ b/Sources/Towel/DataStructures/SortedBinaryTree.cs @@ -109,6 +109,47 @@ public interface ISortedBinaryTree : IDataStructure, /// Contains extensions methods for the SortedBinaryTree interface. public static class SortedBinaryTree { + #region XML + +#pragma warning disable CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name +#pragma warning disable CS1572 // XML comment has a param tag, but there is no parameter by that name + + /// + /// Invokes a method for each entry in the data structure. + /// Runtime: O(n * step), Ω(1) + /// + /// The method to invoke on each item in the structure. + /// The minimum value of iteration. + /// The maximum value of iteration. + /// The method to invoke on each item in the structure. + /// The resulting status of the iteration. + internal static void Stepper_MinMax_O_n_step_Ω_1_XML() => throw new DocumentationMethodException(); + + /// + /// Invokes a method for each entry in the data structure. + /// Runtime: O(n * step) + /// + /// The method to invoke on each item in the structure. + /// The method to invoke on each item in the structure. + /// The resulting status of the iteration. + internal static void Stepper_Reverse_O_n_step_XML() => throw new DocumentationMethodException(); + + /// + /// Invokes a method for each entry in the data structure. + /// Runtime: O(n * step), Ω(1) + /// + /// The method to invoke on each item in the structure. + /// The minimum value of iteration. + /// The maximum value of iteration. + /// The method to invoke on each item in the structure. + /// The resulting status of the iteration. + internal static void Stepper_Reverse_MinMax_O_n_step_Ω_1_XML() => throw new DocumentationMethodException(); + +#pragma warning restore CS1572 // XML comment has a param tag, but there is no parameter by that name +#pragma warning restore CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name + + #endregion + #region Extensions /// Gets a traversal stepper for the tree. diff --git a/Sources/Towel/DataStructures/Stack.cs b/Sources/Towel/DataStructures/Stack.cs index 1f3fea21..9ab588b7 100644 --- a/Sources/Towel/DataStructures/Stack.cs +++ b/Sources/Towel/DataStructures/Stack.cs @@ -39,20 +39,16 @@ internal class Node { internal T Value; internal Node Down; - - internal Node(T data, Node down) - { - Value = data; - Down = down; - } } #endregion #region Constructors - /// Creates an instance of a stack. - /// θ(1) + /// + /// Creates an instance of a stack. + /// Runtime: O(1) + /// public StackLinked() { _top = null; @@ -63,15 +59,11 @@ public StackLinked() #region Properties - /// Returns the number of items in the stack. - /// θ(1) - public int Count - { - get - { - return _count; - } - } + /// + /// Returns the number of items in the stack. + /// Runtime: O(1) + /// + public int Count => _count; #endregion @@ -89,12 +81,12 @@ public StackLinked Clone() return clone; } Node copying = _top; - Node cloneTop = new Node(_top.Value, null); + Node cloneTop = new Node { Value = _top.Value }; Node cloning = cloneTop; while (!(copying is null)) { copying = copying.Down; - cloning.Down = new Node(copying.Value, null); + cloning.Down = new Node { Value = _top.Value }; cloning = cloning.Down; } clone._top = cloneTop; @@ -105,9 +97,11 @@ public StackLinked Clone() #region ToArray - /// Converts the structure into an array. + /// + /// Converts the structure into an array. + /// Runtime: Θ(n) + /// /// An array containing all the item in the structure. - /// Θ(n) public T[] ToArray() { if (_count == 0) @@ -128,12 +122,14 @@ public T[] ToArray() #region Push - /// Adds an item to the top of the stack. + /// + /// Adds an item to the top of the stack. + /// Runtime: O(1) + /// /// The item to add to the stack. - /// O(1) public void Push(T addition) { - _top = new Node(addition, _top); + _top = new Node { Value = addition, Down = _top }; _count++; } @@ -141,13 +137,17 @@ public void Push(T addition) #region Peek - /// Returns the most recent addition to the stack. + /// + /// Returns the most recent addition to the stack. + /// Runtime: O(1) + /// /// The most recent addition to the stack. - /// O(1) public T Peek() { if (_top is null) + { throw new System.InvalidOperationException("Attempting to remove from an empty queue."); + } T peek = _top.Value; return peek; } @@ -156,9 +156,11 @@ public T Peek() #region Pop - /// Removes and returns the most recent addition to the stack. + /// + /// Removes and returns the most recent addition to the stack. + /// Runtime: O(1) + /// /// The most recent addition to the stack. - /// O(1) public T Pop() { if (_count == 0) @@ -175,8 +177,10 @@ public T Pop() #region Clear - /// Clears the stack to an empty state. - /// O(1). Note: causes considerable garbage collection + /// + /// Clears the stack to an empty state. + /// Runtime: O(1) + /// public void Clear() { _top = null; @@ -187,60 +191,36 @@ public void Clear() #region Stepper - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void Stepper(Step step = default) where Step : struct, IAction => StepperRef>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void Stepper(Action step) => Stepper>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void StepperRef(Step step = default) where Step : struct, IStepRef => StepperRefBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void Stepper(StepRef step) => StepperRef>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// public StepStatus StepperBreak(Step step = default) where Step : struct, IFunc => StepperRefBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// public StepStatus Stepper(Func step) => StepperBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// public StepStatus Stepper(StepRefBreak step) => StepperRefBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// public StepStatus StepperRefBreak(Step step = default) where Step : struct, IStepRefBreak { @@ -287,8 +267,10 @@ public class StackArray : IStack #region Constructors - /// Creates an instance of a ListArray, and sets it's minimum capacity. - /// O(1) + /// + /// Creates an instance of a ListArray, and sets it's minimum capacity. + /// Runtime: O(1) + /// public StackArray() { _array = new T[1]; @@ -296,9 +278,11 @@ public StackArray() _minimumCapacity = DefaultMinimumCapacity; } - /// Creates an instance of a ListArray, and sets it's minimum capacity. + /// + /// Creates an instance of a ListArray, and sets it's minimum capacity. + /// Runtime: O(1) + /// /// The initial and smallest array size allowed by this list. - /// O(1) public StackArray(int minimumCapacity) { _array = new T[minimumCapacity]; @@ -308,21 +292,25 @@ public StackArray(int minimumCapacity) internal StackArray(T[] array, int count, int minimumCapacity = DefaultMinimumCapacity) { - this._array = array; - this._count = count; - this._minimumCapacity = minimumCapacity; + _array = array; + _count = count; + _minimumCapacity = minimumCapacity; } #endregion #region Properties - /// Gets the current capacity of the list. - /// O(1) + /// + /// Gets the current capacity of the list. + /// Runtime: O(1) + /// public int CurrentCapacity => _array.Length; - /// Allows you to adjust the minimum capacity of this list. - /// O(n), Ω(1) + /// + /// Allows you to adjust the minimum capacity of this list. + /// Runtime: O(n), Ω(1) + /// public int MinimumCapacity { get @@ -349,15 +337,11 @@ public int MinimumCapacity } } - /// Gets the number of items in the list. - /// O(1) - public int Count - { - get - { - return _count; - } - } + /// + /// Gets the number of items in the list. + /// Runtime: O(1) + /// + public int Count => _count; #endregion @@ -389,9 +373,11 @@ public T[] ToArray() #region Push - /// Adds an item to the end of the list. + /// + /// Adds an item to the end of the list. + /// Runtime: O(n), Ω(1), ε(1) + /// /// The item to be added. - /// O(n), ε(1) public void Push(T addition) { if (_count == _array.Length) @@ -414,8 +400,10 @@ public void Push(T addition) #region Pop - /// Removes the item at a specific index. - /// O(Count), Ω(1), ε(1) + /// + /// Removes the item at a specific index. + /// Runtime: O(Count), Ω(1), ε(1) + /// public T Pop() { if (_count == 0) @@ -439,17 +427,21 @@ public T Pop() #region Peek - /// Returns the most recent addition to the stack. + /// + /// Returns the most recent addition to the stack. + /// Runtime: O(1) + /// /// The most recent addition to the stack. - /// O(1) public T Peek() => _array[_count - 1]; #endregion #region Clear - /// Empties the list back and reduces it back to its original capacity. - /// O(1) + /// + /// Empties the list back and reduces it back to its original capacity. + /// Runtime: O(1) + /// public void Clear() { _array = new T[_minimumCapacity]; @@ -460,60 +452,36 @@ public void Clear() #region Stepper - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void Stepper(Step step = default) where Step : struct, IAction => StepperRef>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void Stepper(Action step) => Stepper>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void StepperRef(Step step = default) where Step : struct, IStepRef => StepperRefBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// O(n * step) + /// public void Stepper(StepRef step) => StepperRef>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// public StepStatus StepperBreak(Step step = default) where Step : struct, IFunc => StepperRefBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// public StepStatus Stepper(Func step) => StepperBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// public StepStatus Stepper(StepRefBreak step) => StepperRefBreak>(step); - /// Invokes a delegate for each entry in the data structure. - /// The delegate to invoke on each item in the structure. - /// The delegate to invoke on each item in the structure. - /// The resulting status of the iteration. - /// O(n * step) + /// public StepStatus StepperRefBreak(Step step = default) where Step : struct, IStepRefBreak => _array.StepperRefBreak(0, _count, step); diff --git a/Sources/Towel/DataStructures/Trie.cs b/Sources/Towel/DataStructures/Trie.cs index 337d0496..60288629 100644 --- a/Sources/Towel/DataStructures/Trie.cs +++ b/Sources/Towel/DataStructures/Trie.cs @@ -112,14 +112,8 @@ public class TrieLinkedHashLinked : ITrie, internal class Node { internal MapHashLinked Map; - internal bool IsLeaf = false; + internal bool IsLeaf; internal int Count; - - internal Node(Func equate, Func hash) - { - Count = 0; - Map = new MapHashLinked(equate, hash); - } } #endregion @@ -178,7 +172,7 @@ public bool TryAdd(Action> stepper, out Exception exception) } else { - Node temp = new Node(Equate, Hash); + Node temp = new Node { Map = new MapHashLinked(Equate, Hash) }; map[key] = temp; node = temp; } @@ -186,12 +180,12 @@ public bool TryAdd(Action> stepper, out Exception exception) }); if (node is null) { - exception = new ArgumentException(nameof(stepper), "Stepper was empty."); + exception = new ArgumentException("Stepper was empty.", nameof(stepper)); return false; } else if (node.IsLeaf) { - exception = new ArgumentException(nameof(stepper), "Attempted to add an already existing item."); + exception = new ArgumentException("Attempted to add an already existing item.", nameof(stepper)); return false; } else @@ -236,7 +230,7 @@ public bool TryRemove(Action> stepper, out Exception exception) } else { - capturedException ??= new ArgumentException(nameof(stepper), "Attempted to remove a non-existing item."); + capturedException ??= new ArgumentException("Attempted to remove a non-existing item.", nameof(stepper)); } pathStack.Push((finalKey, finalMap, node)); }); @@ -247,12 +241,12 @@ public bool TryRemove(Action> stepper, out Exception exception) } else if (node is null) { - exception = new ArgumentException(nameof(stepper), "Stepper was empty."); + exception = new ArgumentException("Stepper was empty.", nameof(stepper)); return false; } else if (!node.IsLeaf) { - exception = new ArgumentException(nameof(stepper), "Attempted to remove a non-existing item."); + exception = new ArgumentException("Attempted to remove a non-existing item.", nameof(stepper)); return false; } else @@ -312,7 +306,7 @@ public bool Contains(Action> stepper) }); if (node is null) { - throw new ArgumentException(nameof(stepper), "Stepper was empty."); + throw new ArgumentException("Stepper was empty.", nameof(stepper)); } return node.IsLeaf; } @@ -455,15 +449,9 @@ public class TrieLinkedHashLinked : ITrie, internal class Node { internal MapHashLinked Map; - internal D Value = default; - internal bool HasValue = false; + internal D Value; + internal bool HasValue; internal int Count; - - internal Node(Func equate, Func hash) - { - Count = 0; - Map = new MapHashLinked(equate, hash); - } } #endregion @@ -523,7 +511,7 @@ public bool TryAdd(D value, Action> stepper, out Exception exception) } else { - Node temp = new Node(Equate, Hash); + Node temp = new Node { Map = new MapHashLinked(Equate, Hash) }; map[key] = temp; node = temp; } @@ -531,12 +519,12 @@ public bool TryAdd(D value, Action> stepper, out Exception exception) }); if (node is null) { - exception = new ArgumentException(nameof(stepper), "Stepper was empty."); + exception = new ArgumentException("Stepper was empty.", nameof(stepper)); return false; } else if (node.HasValue) { - exception = new ArgumentException(nameof(stepper), "Attempted to add an already existing item."); + exception = new ArgumentException("Attempted to add an already existing item.", nameof(stepper)); return false; } else @@ -579,7 +567,7 @@ public bool TryGet(Action> stepper, out D value, out Exception excepti } else { - Node temp = new Node(Equate, Hash); + Node temp = new Node { Map = new MapHashLinked(Equate, Hash) }; map[key] = temp; node = temp; } @@ -587,13 +575,13 @@ public bool TryGet(Action> stepper, out D value, out Exception excepti if (node is null) { value = default; - exception = new ArgumentException(nameof(stepper), "Stepper was empty."); + exception = new ArgumentException("Stepper was empty.", nameof(stepper)); return false; } else if (!node.HasValue) { value = default; - exception = new ArgumentException(nameof(stepper), "Attempted to get a non-existing item."); + exception = new ArgumentException("Attempted to get a non-existing item.", nameof(stepper)); return false; } else @@ -620,8 +608,8 @@ public bool TryRemove(Action> stepper, out Exception exception) return false; } IStack<(T, MapHashLinked, Node)> pathStack = new StackLinked<(T, MapHashLinked, Node)>(); - T finalKey = default; - MapHashLinked finalMap = null; + T finalKey; + MapHashLinked finalMap; Node node = null; Exception capturedException = null; stepper(key => @@ -636,7 +624,7 @@ public bool TryRemove(Action> stepper, out Exception exception) } else { - capturedException ??= new ArgumentException(nameof(stepper), "Attempted to remove a non-existing item."); + capturedException ??= new ArgumentException("Attempted to remove a non-existing item.", nameof(stepper)); } pathStack.Push((finalKey, finalMap, node)); }); @@ -647,12 +635,12 @@ public bool TryRemove(Action> stepper, out Exception exception) } else if (node is null) { - exception = new ArgumentException(nameof(stepper), "Stepper was empty."); + exception = new ArgumentException("Stepper was empty.", nameof(stepper)); return false; } else if (!node.HasValue) { - exception = new ArgumentException(nameof(stepper), "Attempted to remove a non-existing item."); + exception = new ArgumentException("Attempted to remove a non-existing item.", nameof(stepper)); return false; } else @@ -712,7 +700,7 @@ public bool Contains(Action> stepper) }); if (node is null) { - throw new ArgumentException(nameof(stepper), "Stepper was empty."); + throw new ArgumentException("Stepper was empty.", nameof(stepper)); } return node.HasValue; } diff --git a/Sources/Towel/Extensions.cs b/Sources/Towel/Extensions.cs index eb398705..210bdf9f 100644 --- a/Sources/Towel/Extensions.cs +++ b/Sources/Towel/Extensions.cs @@ -49,7 +49,7 @@ private static string ReplaceBase(string @this, (string Pattern, string Replacem { if (Pattern is null) throw new ArgumentNullException(nameof(rules), $"{nameof(rules)} contains null {nameof(Pattern)}s"); if (Replacement is null) throw new ArgumentNullException(nameof(rules), $"{nameof(rules)} contains null {nameof(Replacement)}s"); - if (Pattern == string.Empty) throw new ArgumentException(nameof(rules), $"{nameof(rules)} contains empty {nameof(Pattern)}s"); + if (Pattern == string.Empty) throw new ArgumentException($"{nameof(rules)} contains empty {nameof(Pattern)}s", nameof(rules)); // TODO: TryAdd when available if (regexAndRuleSet.RuleSet.ContainsKey(Pattern)) { @@ -296,11 +296,11 @@ public static string PadLinesLeft(this string @string, string padding, int start string[] lines = @string.SplitLines(); if (startingLineNumber < 0 || startingLineNumber >= lines.Length) { - throw new ArgumentOutOfRangeException("startingLineNumber"); + throw new ArgumentOutOfRangeException(nameof(startingLineNumber)); } if (endingLineNumber >= lines.Length || endingLineNumber < startingLineNumber) { - throw new ArgumentOutOfRangeException("endingLineNumber"); + throw new ArgumentOutOfRangeException(nameof(endingLineNumber)); } for (int i = startingLineNumber; i <= endingLineNumber; i++) { @@ -781,26 +781,26 @@ public static T Next(this Random random, System.Collections.Generic.IEnumerab foreach (var (Value, Weight) in pool) { if (Weight < 0) - throw new ArgumentOutOfRangeException("A value in the pool had a weight less than zero."); + throw new ArgumentOutOfRangeException(nameof(pool), $"A value in {nameof(pool)} had a weight less than zero."); totalWeight += Weight; } } else { if (totalWeight < 0) - throw new ArgumentOutOfRangeException("The provided total weight of the pool was less than zero."); + throw new ArgumentOutOfRangeException(nameof(totalWeight), $"The provided {nameof(totalWeight)} of the {nameof(pool)} was less than zero."); } if (totalWeight == 0) - throw new ArgumentOutOfRangeException("The total weight of all values in the pool was zero."); + throw new ArgumentOutOfRangeException(nameof(pool), $"The total weight of all values in the {nameof(pool)} was zero."); if (double.IsInfinity(totalWeight.Value)) - throw new ArgumentOutOfRangeException("The total weight of all values in the pool was an infinite double."); + throw new ArgumentOutOfRangeException(nameof(pool), $"The total weight of all values in the {nameof(pool)} was an infinite double."); double randomDouble = random.NextDouble(); double range = 0; foreach (var (Value, Weight) in pool) { range += Weight; if (range > totalWeight) - throw new ArgumentOutOfRangeException("The provided total weight of the pool was less than the actual total weight."); + throw new ArgumentOutOfRangeException(nameof(totalWeight), $"The provided {nameof(totalWeight)} of the {nameof(pool)} was less than the actual total weight."); if (randomDouble < range / totalWeight) return Value; } diff --git a/Sources/Towel/Mathematics/Matrix.cs b/Sources/Towel/Mathematics/Matrix.cs index b70b38c5..705f5073 100644 --- a/Sources/Towel/Mathematics/Matrix.cs +++ b/Sources/Towel/Mathematics/Matrix.cs @@ -102,26 +102,24 @@ internal string DebuggerString { get { - int ROWS = this.Rows; - int COLUMNS = this.Columns; - if (ROWS < 5 && COLUMNS < 5) + if (Rows < 5 && Columns < 5) { StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.Append("["); - for (int i = 0; i < ROWS; i++) + stringBuilder.Append('['); + for (int i = 0; i < Rows; i++) { - stringBuilder.Append("["); - for (int j = 0; j < COLUMNS; j++) + stringBuilder.Append('['); + for (int j = 0; j < Columns; j++) { stringBuilder.Append(Get(i, j)); - if (j < COLUMNS - 1) + if (j < Columns - 1) { - stringBuilder.Append(","); + stringBuilder.Append(','); } } - stringBuilder.Append("]"); + stringBuilder.Append(']'); } - stringBuilder.Append("]"); + stringBuilder.Append(']'); return stringBuilder.ToString(); } return ToString(); @@ -146,11 +144,11 @@ public Matrix(int rows, int columns) { if (rows < 1) { - throw new ArgumentOutOfRangeException("rows", rows, "!(rows > 0)"); + throw new ArgumentOutOfRangeException(nameof(rows), rows, "!(rows > 0)"); } if (columns < 1) { - throw new ArgumentOutOfRangeException("columns", columns, "!(columns > 0)"); + throw new ArgumentOutOfRangeException(nameof(columns), columns, "!(columns > 0)"); } _matrix = new T[rows * columns]; _rows = rows; @@ -1283,10 +1281,12 @@ public static T Determinant(Matrix a) } - /// Computes the determinant of a square matrix via Gaussian elimination. + /// + /// Computes the determinant of a square matrix via Gaussian elimination. + /// Runtime: O((n^3 + 2n^−3) / 3) + /// /// The matrix to compute the determinant of. /// The computed determinant. - /// O((n^3 + 2n^−3) / 3) public static T DeterminantGaussian(Matrix a) { _ = a ?? throw new ArgumentNullException(nameof(a)); @@ -1297,10 +1297,12 @@ public static T DeterminantGaussian(Matrix a) return GetDeterminantGaussian(a, a.Rows); } - /// Computes the determinant of a square matrix via Laplace's method. + /// + /// Computes the determinant of a square matrix via Laplace's method. + /// Runtime: O(n(2^(n − 1) − 1)) + /// /// The matrix to compute the determinant of. /// The computed determinant. - /// O(n(2^(n − 1) − 1)) public static T DeterminantLaplace(Matrix a) { _ = a ?? throw new ArgumentNullException(nameof(a)); diff --git a/Sources/Towel/Mathematics/Symbolics.cs b/Sources/Towel/Mathematics/Symbolics.cs index f5d90a8a..eaebe00a 100644 --- a/Sources/Towel/Mathematics/Symbolics.cs +++ b/Sources/Towel/Mathematics/Symbolics.cs @@ -15,6 +15,7 @@ public static class Symbolics internal enum OperatorPriority { +#pragma warning disable CA1069 // Enums values should not be duplicated Addition = 1, Subtraction = 1, Multiplication = 2, @@ -24,6 +25,7 @@ internal enum OperatorPriority Logical = 4, Negation = 5, Factorial = 6, +#pragma warning restore CA1069 // Enums values should not be duplicated } #endregion @@ -2983,7 +2985,7 @@ public Multinary(Expression[] operands) #region Runtime Built Parsing Libary // Library Building Fields - internal static bool ParseableLibraryBuilt = false; + internal static bool ParseableLibraryBuilt; internal static readonly object ParseableLibraryLock = new object(); // Regex Expressions internal const string ParenthesisPattern = @"\(.*\)"; diff --git a/Sources/Towel/Meta.cs b/Sources/Towel/Meta.cs index 0fa73e39..6a832c92 100644 --- a/Sources/Towel/Meta.cs +++ b/Sources/Towel/Meta.cs @@ -762,7 +762,7 @@ public static System.Collections.Generic.IEnumerable GetDerivedTypes /// The file path of the assembly. public static string GetDirectoryPath(this Assembly assembly) { - string codeBase = assembly.CodeBase; + string codeBase = assembly.Location; UriBuilder uri = new UriBuilder(codeBase); string path = Uri.UnescapeDataString(uri.Path); return Path.GetDirectoryName(path); diff --git a/Sources/Towel/Statics.cs b/Sources/Towel/Statics.cs index 6ff0d119..8489315e 100644 --- a/Sources/Towel/Statics.cs +++ b/Sources/Towel/Statics.cs @@ -65,7 +65,7 @@ internal static T OperationOnStepper(Action> stepper, Func }); return assigned ? result - : throw new ArgumentException(nameof(stepper), nameof(stepper) + " is empty."); + : throw new ArgumentException($"{nameof(stepper)} is empty.", nameof(stepper)); } #endregion @@ -337,9 +337,9 @@ public abstract class Condition { public abstract bool Resolve(); public static implicit operator Condition(bool result) => new Bool { Result = result, }; -#pragma warning disable IDE0060 // Remove unused parameter +//#pragma warning disable IDE0060 // Remove unused parameter public static implicit operator Condition(Keyword keyword) => new Default(); -#pragma warning restore IDE0060 // Remove unused parameter +//#pragma warning restore IDE0060 // Remove unused parameter public static implicit operator bool(Condition condition) => condition.Resolve(); } @@ -367,9 +367,11 @@ internal class Default : Condition public struct ChanceSyntax { /// The random algorithm currently being used by chance syntax. +#pragma warning disable CA2211 // Non-constant fields should not be visible public static Random Algorithm = new Random(); +#pragma warning restore CA2211 // Non-constant fields should not be visible -#pragma warning disable IDE0060 // Remove unused parameter +//#pragma warning disable IDE0060 // Remove unused parameter #pragma warning disable IDE0075 // Simplify conditional expression /// Creates a chance from a percentage that will be evaluated at runtime. @@ -379,13 +381,12 @@ public struct ChanceSyntax public static bool operator %(double percentage, ChanceSyntax chance) => percentage < 0d ? throw new ArgumentOutOfRangeException(nameof(chance)) : percentage > 100d ? throw new ArgumentOutOfRangeException(nameof(chance)) : - percentage is 100d ? true : percentage is 0d ? false : Algorithm.NextDouble() < percentage / 100d; #pragma warning restore IDE0075 // Simplify conditional expression -#pragma warning restore IDE0060 // Remove unused parameter +//#pragma warning restore IDE0060 // Remove unused parameter } #endregion @@ -600,7 +601,7 @@ public void Add(T item) Value = newValue; } [Obsolete(TowelConstants.NotIntended, true)] - public void Clear() => Value = new T[0]; + public void Clear() => Value = Array.Empty(); [Obsolete(TowelConstants.NotIntended, true)] public bool Contains(T item) => Value.Contains(item); [Obsolete(TowelConstants.NotIntended, true)] @@ -4445,10 +4446,12 @@ public static Action> SearchGraph(Node start, SearchNeighbors #region SortBubble - /// Sorts values using the bubble sort algorithm. - /// Ω(n), ε(n^2), O(n^2) - /// True - /// O(1) + /// + /// Sorts values using the bubble sort algorithm. + /// Runtime: Ω(n), ε(n^2), O(n^2) + /// Memory: O(1) + /// Stable: True + /// /// [Obsolete(TowelConstants.NotIntended, true)] internal static void SortBubble_XML() => throw new DocumentationMethodException(); @@ -4502,10 +4505,12 @@ public static void SortBubble(Span span, Compare compare = defaul #region SortSelection - /// Sorts values using the selection sort algoritm. - /// Ω(n^2), ε(n^2), O(n^2) - /// False - /// O(1) + /// + /// Sorts values using the selection sort algoritm. + /// Runtime: Ω(n^2), ε(n^2), O(n^2) + /// Memory: O(1) + /// Stable: False + /// /// [Obsolete(TowelConstants.NotIntended, true)] internal static void SortSelection_XML() => throw new DocumentationMethodException(); @@ -4563,10 +4568,12 @@ public static void SortSelection(Span span, Compare compare = def #region SortInsertion - /// Sorts values using the insertion sort algorithm. - /// Ω(n), ε(n^2), O(n^2) - /// True - /// O(1) + /// + /// Sorts values using the insertion sort algorithm. + /// Runtime: Ω(n), ε(n^2), O(n^2) + /// Memory: O(1) + /// Stable: True + /// /// [Obsolete(TowelConstants.NotIntended, true)] internal static void SortInsertion_XML() => throw new DocumentationMethodException(); @@ -4617,10 +4624,12 @@ public static void SortInsertion(Span span, Compare compare = def #region SortQuick - /// Sorts values using the quick sort algorithm. - /// Ω(n*ln(n)), ε(n*ln(n)), O(n^2) - /// False - /// ln(n) + /// + /// Sorts values using the quick sort algorithm. + /// Runtime: Ω(n*ln(n)), ε(n*ln(n)), O(n^2) + /// Memory: ln(n) + /// Stable: False + /// /// [Obsolete(TowelConstants.NotIntended, true)] internal static void SortQuick_XML() => throw new DocumentationMethodException(); @@ -4715,10 +4724,12 @@ void SortQuick_Recursive(Span span, int startIndex, int len) #region SortMerge - /// Sorts values using the merge sort algorithm. - /// Ω(n*ln(n)), ε(n*ln(n)), O(n*ln(n)) - /// True - /// Θ(n) + /// + /// Sorts values using the merge sort algorithm. + /// Runtime: Ω(n*ln(n)), ε(n*ln(n)), O(n*ln(n)) + /// Memory: Θ(n) + /// Stable: True + /// /// [Obsolete(TowelConstants.NotIntended, true)] internal static void SortMerge_XML() => throw new DocumentationMethodException(); @@ -4825,10 +4836,12 @@ void SortMerge_Recursive(Span span) #region SortHeap - /// Sorts values using the heap sort algorithm. - /// Ω(n*ln(n)), ε(n*ln(n)), O(n^2) - /// False - /// O(1) + /// + /// Sorts values using the heap sort algorithm. + /// Runtime: Ω(n*ln(n)), ε(n*ln(n)), O(n^2) + /// Memory: O(1) + /// Stable: False + /// /// [Obsolete(TowelConstants.NotIntended, true)] internal static void SortHeap_XML() => throw new DocumentationMethodException(); @@ -4929,10 +4942,12 @@ void MaxSortHeapify(Span span, int heapSize, int index, int offset) #region SortOddEven - /// Sorts values using the odd even sort algorithm. - /// Ω(n), ε(n^2), O(n^2) - /// True - /// O(1) + /// + /// Sorts values using the odd even sort algorithm. + /// Runtime: Ω(n), ε(n^2), O(n^2) + /// Memory: O(1) + /// Stable: True + /// /// [Obsolete(TowelConstants.NotIntended, true)] internal static void SortOddEven_XML() => throw new DocumentationMethodException(); @@ -5019,11 +5034,15 @@ public static void SortOddEven(Span span, Compare compare = defau ///// The counting key computed from the provided instance. //public delegate int ComputeSortCountingKey(T instance); - ///// Sorts an entire array in non-decreasing order using the heap sort algorithm. + ///// + ///// Sorts an entire array in non-decreasing order using the heap sort algorithm. + ///// Runtime: Θ(Max(key)) + ///// Memory: Max(Key) + ///// Stable: True + ///// ///// The type of objects stored within the array. ///// Method specifically for computing object keys in the SortCounting Sort algorithm. ///// The array to be sorted - ///// Θ(Max(key)). Memory: Max(key). Stablity: yes //public static void SortCounting(ComputeSortCountingKey computeSortCountingKey, T[] array) //{ // throw new System.NotImplementedException(); @@ -5056,21 +5075,11 @@ public static void SortOddEven(Span span, Compare compare = defau // } //} - ///// Sorts an entire array in non-decreasing order using the heap sort algorithm. - ///// The type of objects stored within the array. - ///// Method specifically for computing object keys in the SortCounting Sort algorithm. - ///// The array to be sorted - ///// Θ(Max(key)). Memory: Max(key). Stablity: yes //public static void SortCounting(ComputeSortCountingKey computeSortCountingKey, T[] array, int start, int end) //{ // throw new System.NotImplementedException(); //} - ///// Sorts an entire array in non-decreasing order using the heap sort algorithm. - ///// The type of objects stored within the array. - ///// Method specifically for computing object keys in the SortCounting Sort algorithm. - ///// The array to be sorted - ///// Θ(Max(key)). Memory: Max(key). Stablity: yes //public static void SortCounting(ComputeSortCountingKey computeSortCountingKey, Get get, Assign set, int start, int end) //{ // throw new System.NotImplementedException(); @@ -5084,7 +5093,11 @@ public static void SortOddEven(Span span, Compare compare = defau #pragma warning disable CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name #pragma warning disable CS1572 // XML comment has a param tag, but there is no parameter by that name - /// Sorts values into a randomized order. + /// + /// Sorts values into a randomized order. + /// Runtime: O(n) + /// Memory: O(1) + /// /// The type of values to sort. /// The get function. /// The set function. @@ -5094,8 +5107,6 @@ public static void SortOddEven(Span span, Compare compare = defau /// The set function. /// The random to shuffle with. /// The array to shuffle. - /// O(n) - /// O(1) [Obsolete(TowelConstants.NotIntended, true)] internal static void Shuffle_XML() => throw new DocumentationMethodException(); #pragma warning restore CS1572 // XML comment has a param tag, but there is no parameter by that name @@ -5146,10 +5157,12 @@ public static void Shuffle(Span span, Random random = default) #region SortBogo - /// Sorts values using the bogo sort algorithm. - /// Ω(n), ε(n*n!), O(∞) - /// False - /// O(1) + /// + /// Sorts values using the bogo sort algorithm. + /// Runtime: Ω(n), ε(n*n!), O(∞) + /// Memory: O(1) + /// Stable: False + /// /// [Obsolete(TowelConstants.NotIntended, true)] internal static void SortBogo_XML() => throw new DocumentationMethodException(); @@ -5623,11 +5636,17 @@ public static void NextUniqueRollTracking(int count, int minValue, where Random : struct, IFunc { if (maxValue < minValue) - throw new ArgumentOutOfRangeException(nameof(minValue) + " > " + nameof(minValue)); + { + throw new ArgumentOutOfRangeException(nameof(maxValue), $"{nameof(minValue)} > {nameof(maxValue)}"); + } if (count < 0) - throw new ArgumentOutOfRangeException(nameof(count) + " < 0"); + { + throw new ArgumentOutOfRangeException(nameof(count), $"{nameof(count)} < 0"); + } if (maxValue - minValue < count) - throw new ArgumentOutOfRangeException(nameof(count) + " is larger than " + nameof(maxValue) + " - " + nameof(minValue) + "."); + { + throw new ArgumentOutOfRangeException(nameof(count), $"{nameof(count)} is larger than {nameof(maxValue)} - {nameof(minValue)}."); + } // Algorithm B: O(.5*count^2), Ω(count), ε(.5*count^2) Node head = null; for (int i = 0; i < count; i++) // Θ(count) @@ -5647,9 +5666,13 @@ public static void NextUniqueRollTracking(int count, int minValue, } step.Do(roll); if (previous is null) + { head = new Node() { Value = roll, Next = head, }; + } else + { previous.Next = new Node() { Value = roll, Next = previous.Next }; + } } } internal class Node @@ -5676,11 +5699,17 @@ public static void NextUniquePoolTracking(int count, int minValue, where Random : struct, IFunc { if (maxValue < minValue) - throw new ArgumentOutOfRangeException(nameof(minValue) + " > " + nameof(minValue)); + { + throw new ArgumentOutOfRangeException(nameof(maxValue), $"{nameof(minValue)} > {nameof(maxValue)}"); + } if (count < 0) - throw new ArgumentOutOfRangeException(nameof(count) + " < 0"); + { + throw new ArgumentOutOfRangeException(nameof(count), $"{nameof(count)} < 0"); + } if (maxValue - minValue < count) - throw new ArgumentOutOfRangeException(nameof(count) + " is larger than " + nameof(maxValue) + " - " + nameof(minValue) + "."); + { + throw new ArgumentOutOfRangeException(nameof(count), $"{nameof(count)} is larger than {nameof(maxValue)} - {nameof(minValue)}."); + } // Algorithm B: Θ(range + count) int pool = maxValue - minValue; int[] array = new int[pool]; diff --git a/Sources/Towel/Towel.csproj b/Sources/Towel/Towel.csproj index 22d18ea2..b1a2f792 100644 --- a/Sources/Towel/Towel.csproj +++ b/Sources/Towel/Towel.csproj @@ -1,6 +1,6 @@  - netcoreapp3.1 + net5.0 Towel.xml Towel icon.png @@ -19,9 +19,9 @@ Functional.cs - True - True - Functional.tt + True + True + Functional.tt @@ -64,4 +64,7 @@ <_Parameter1>Towel_Testing + + + diff --git a/Sources/Towel/Towel.xml b/Sources/Towel/Towel.xml index b7e4f3ab..5d28dd9e 100644 --- a/Sources/Towel/Towel.xml +++ b/Sources/Towel/Towel.xml @@ -295,65 +295,87 @@ The Compare delegate. - Constructs an AVL Tree. + + Constructs an AVL Tree. + Runtime: O(1) + The comparison function for sorting the items. - θ(1) This constructor if for cloning purposes. The tree to clone. - Gets the current least item in the avl tree. - θ(ln(Count)) + + Gets the current least item in the avl tree. + Runtime: θ(ln(Count)) + - Gets the current greated item in the avl tree. - θ(ln(Count)) + + Gets the current greated item in the avl tree. + Runtime: θ(ln(Count)) + - The comparison function being utilized by this structure. - θ(1) + + The comparison function being utilized by this structure. + Runtime: O(1) + - Gets the number of elements in the collection. - θ(1) + + Gets the number of elements in the collection. + Runtime: O(1) + - Tries to add a value to the AVL tree. + + Tries to add a value to the AVL tree. + Runtime: O(ln(n)) + The value to add. The exception that occurred if the add failed. True if the add succeeded or false if not. - O(ln(n)) - Returns the tree to an iterative state. - θ(1) + + Returns the tree to an iterative state. + Runtime: O(1) + - Clones the AVL tree. + + Clones the AVL tree. + Runtime: θ(n) + A clone of the AVL tree. - θ(n) - Determines if the AVL tree contains a value. + + Determines if the AVL tree contains a value. + Runtime: O(ln(Count)), Ω(1) + The value to look for. Whether or not the AVL tree contains the value. - O(ln(Count)) Ω(1) - Determines if this structure contains an item by a given key. + + Determines if this structure contains an item by a given key. + Runtime: O(ln(Count)), Ω(1) + The sorting technique (must synchronize with this structure's sorting). True of contained, False if not. - O(ln(Count)) Ω(1) - Tries to get a value. + + Tries to get a value. + Runtime: O(ln(Count)), Ω(1) + The compare delegate. The value if found or default. The exception that occurred if the get failed. True if the get succeeded or false if not. - O(ln(Count)) Ω(1) Tries to remove a value. @@ -368,224 +390,120 @@ True if the remove was successful or false if not. - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) - - - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + + + + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) - - - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) + + + + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) - - - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + + + + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) - - - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) + + + + Gets the enumerator for this instance. An enumerator to iterate through the data structure. - Standard balancing algorithm for an AVL Tree. + + Standard balancing algorithm for an AVL Tree. + Runtime: O(1) + The tree to check the balancing of. The result of the possible balancing. - θ(1) - This is just a protection against the null valued leaf nodes, which have a height of "-1". + + This is just a protection against the null valued leaf nodes, which have a height of "-1". + Runtime: O(1) + The node to find the hight of. Returns "-1" if null (leaf) or the height property of the node. - θ(1) Removes the left-most child of an AVL Tree node and returns it @@ -602,31 +520,39 @@ The updated tree with the removal. - Sets the height of a tree based on its children's heights. + + Sets the height of a tree based on its children's heights. + Runtime: O(1) + The tree to have its height adjusted. - O(1) A self-sorting binary tree based on the heights of each node. The generic type of values to store in the AVL tree. - Constructs an AVL Tree. + + Constructs an AVL Tree. + Runtime: O(1) + The comparison function for sorting the items. - θ(1) This constructor if for cloning purposes. The tree to clone. - The comparison function being utilized by this structure. - θ(1) + + The comparison function being utilized by this structure. + Runtime: O(1) + - Clones the AVL tree. + + Clones the AVL tree. + Runtime: O(1) + A clone of the AVL tree. - θ(n) Polymorphism base for all data structures in the Towel framework. @@ -644,6 +570,15 @@ Contains extension methods for the Structure interface. + + + Invokes a method for each entry in the data structure. + Runtime: O(n * step) + + The method to invoke on each item in the structure. + The method to invoke on each item in the structure. + The resulting status of the iteration. + Property of a data structure (does it have a contains method). The type of value. @@ -800,16 +735,11 @@ Represents an edge in a graph. - + The starting node of the edge. - - The ending node of hte edge. - - - Constructs a new Edge. - The starting point of the Edge. - The ending point of the Edge. + + The ending node of the edge. This constructor is for cloning purposes. @@ -892,20 +822,6 @@ Stores a graph as a map and nested map (adjacency matrix). The generic node type of this graph. - - Represents an edge in a graph. - - - The starting point of the edge. - - - The ending point of the edge. - - - Constructs a new Edge. - The starting point of the edge. - The ending point of the edge. - Constructs a new GraphMap. @@ -1007,26 +923,36 @@ The Compare delegate. - Generates a priority queue with a capacity of the parameter. Runtime O(1). + + Generates a priority queue with a capacity of the parameter. + Runtime: O(1) + Delegate determining the comparison technique used for sorting. The capacity you want this priority queue to have. - θ(1) - The comparison function being utilized by this structure. - θ(1) + + The comparison function being utilized by this structure. + Runtime: O(1) + - The maximum items the queue can hold. - θ(1) + + The maximum items the queue can hold. + Runtime: O(1) + - The minumum capacity of this queue to limit low-level resizing. - θ(1) + + The minumum capacity of this queue to limit low-level resizing. + Runtime: O(1) + - The number of items in the queue. - O(1) + + The number of items in the queue. + Runtime: O(1) + Gets the index of the left child of the provided item. @@ -1044,43 +970,59 @@ The index of the parent of the provided item. - Enqueue an item into the priority queue and let it works its magic. + + Enqueue an item into the priority queue and let it works its magic. + Runtime: O(ln(n)), Ω(1), ε(ln(n)) + The item to be added. - O(ln(n)), Ω(1), ε(ln(n)) - Dequeues the item with the highest priority. + + Dequeues the item with the highest priority. + Runtime: O(ln(n)) + The item of the highest priority. - O(ln(n)) - Requeues an item after a change has occured. + + Requeues an item after a change has occured. + Runtime: O(n) + The item to requeue. - O(n) - This lets you peek at the top priority WITHOUT REMOVING it. - O(1) + + Get the highest priority element without removing it. + Runtime: O(1) + - Standard priority queue algorithm for up sifting. + + Standard priority queue algorithm for up sifting. + Runtime: O(ln(n)), Ω(1) + The index to be up sifted. - O(ln(n)), Ω(1) - Standard priority queue algorithm for sifting down. + + Standard priority queue algorithm for sifting down. + Runtime: O(ln(n)), Ω(1) + The index to be down sifted. - O(ln(n)), Ω(1) - Standard array swap method. + + Standard array swap method. + Runtime: O(1) + The first index of the swap. The second index of the swap. - O(1) - Returns this queue to an empty state. - O(1) + + Returns this queue to an empty state. + Runtime: O(1) + Converts the heap into an array using pre-order traversal (WARNING: items are not ordered). @@ -1117,10 +1059,12 @@ The type of item to be stored in this priority heap. - Generates a priority queue with a capacity of the parameter. Runtime O(1). + + Generates a priority queue with a capacity of the parameter. + Runtime: O(1) + Delegate determining the comparison technique used for sorting. The capacity you want this priority queue to have. - θ(1) Delegate determining the comparison technique used for sorting. @@ -1140,16 +1084,20 @@ The type of #1 element in the link. - Creates a link between objects. + + Creates a link between objects. + Runtime: O(1) + The #1 item to be linked. - O(1) - The number of objects in the tuple. + + The number of objects in the tuple. + Runtime: O(1) + The #1 item in the link. - O(1) Converts a System.ValueTuple to a Towel.DataStructures.Link of the same generic types. @@ -1211,16 +1159,20 @@ The type of #1 element in the link. - Creates a link between objects. + + Creates a link between objects. + Runtime: O(1) + The #1 item to be linked. - O(1) - The number of objects in the tuple. + + The number of objects in the tuple. + Runtime: O(1) + The #1 item in the link. - O(1) Converts a System.ValueTuple to a Towel.DataStructures.LinkStruct of the same generic types. @@ -1289,21 +1241,24 @@ The type of #2 element in the link. - Creates a link between objects. + + Creates a link between objects. + Runtime: O(1) + The #1 item to be linked. The #2 item to be linked. - O(1) - The number of objects in the tuple. + + The number of objects in the tuple. + Runtime: O(1) + The #1 item in the link. - O(1) The #2 item in the link. - O(1) Converts a System.ValueTuple to a Towel.DataStructures.Link of the same generic types. @@ -1366,21 +1321,24 @@ The type of #2 element in the link. - Creates a link between objects. + + Creates a link between objects. + Runtime: O(1) + The #1 item to be linked. The #2 item to be linked. - O(1) - The number of objects in the tuple. + + The number of objects in the tuple. + Runtime: O(1) + The #1 item in the link. - O(1) The #2 item in the link. - O(1) Converts a System.ValueTuple to a Towel.DataStructures.LinkStruct of the same generic types. @@ -1450,26 +1408,28 @@ The type of #3 element in the link. - Creates a link between objects. + + Creates a link between objects. + Runtime: O(1) + The #1 item to be linked. The #2 item to be linked. The #3 item to be linked. - O(1) - The number of objects in the tuple. + + The number of objects in the tuple. + Runtime: O(1) + The #1 item in the link. - O(1) The #2 item in the link. - O(1) The #3 item in the link. - O(1) Converts a System.ValueTuple to a Towel.DataStructures.Link of the same generic types. @@ -1533,26 +1493,28 @@ The type of #3 element in the link. - Creates a link between objects. + + Creates a link between objects. + Runtime: O(1) + The #1 item to be linked. The #2 item to be linked. The #3 item to be linked. - O(1) - The number of objects in the tuple. + + The number of objects in the tuple. + Runtime: O(1) + The #1 item in the link. - O(1) The #2 item in the link. - O(1) The #3 item in the link. - O(1) Converts a System.ValueTuple to a Towel.DataStructures.LinkStruct of the same generic types. @@ -1623,31 +1585,32 @@ The type of #4 element in the link. - Creates a link between objects. + + Creates a link between objects. + Runtime: O(1) + The #1 item to be linked. The #2 item to be linked. The #3 item to be linked. The #4 item to be linked. - O(1) - The number of objects in the tuple. + + The number of objects in the tuple. + Runtime: O(1) + The #1 item in the link. - O(1) The #2 item in the link. - O(1) The #3 item in the link. - O(1) The #4 item in the link. - O(1) Converts a System.ValueTuple to a Towel.DataStructures.Link of the same generic types. @@ -1712,31 +1675,32 @@ The type of #4 element in the link. - Creates a link between objects. + + Creates a link between objects. + Runtime: O(1) + The #1 item to be linked. The #2 item to be linked. The #3 item to be linked. The #4 item to be linked. - O(1) - The number of objects in the tuple. + + The number of objects in the tuple. + Runtime: O(1) + The #1 item in the link. - O(1) The #2 item in the link. - O(1) The #3 item in the link. - O(1) The #4 item in the link. - O(1) Converts a System.ValueTuple to a Towel.DataStructures.LinkStruct of the same generic types. @@ -1808,36 +1772,36 @@ The type of #5 element in the link. - Creates a link between objects. + + Creates a link between objects. + Runtime: O(1) + The #1 item to be linked. The #2 item to be linked. The #3 item to be linked. The #4 item to be linked. The #5 item to be linked. - O(1) - The number of objects in the tuple. + + The number of objects in the tuple. + Runtime: O(1) + The #1 item in the link. - O(1) The #2 item in the link. - O(1) The #3 item in the link. - O(1) The #4 item in the link. - O(1) The #5 item in the link. - O(1) Converts a System.ValueTuple to a Towel.DataStructures.Link of the same generic types. @@ -1903,36 +1867,36 @@ The type of #5 element in the link. - Creates a link between objects. + + Creates a link between objects. + Runtime: O(1) + The #1 item to be linked. The #2 item to be linked. The #3 item to be linked. The #4 item to be linked. The #5 item to be linked. - O(1) - The number of objects in the tuple. + + The number of objects in the tuple. + Runtime: O(1) + The #1 item in the link. - O(1) The #2 item in the link. - O(1) The #3 item in the link. - O(1) The #4 item in the link. - O(1) The #5 item in the link. - O(1) Converts a System.ValueTuple to a Towel.DataStructures.LinkStruct of the same generic types. @@ -2005,41 +1969,40 @@ The type of #6 element in the link. - Creates a link between objects. + + Creates a link between objects. + Runtime: O(1) + The #1 item to be linked. The #2 item to be linked. The #3 item to be linked. The #4 item to be linked. The #5 item to be linked. The #6 item to be linked. - O(1) - The number of objects in the tuple. + + The number of objects in the tuple. + Runtime: O(1) + The #1 item in the link. - O(1) The #2 item in the link. - O(1) The #3 item in the link. - O(1) The #4 item in the link. - O(1) The #5 item in the link. - O(1) The #6 item in the link. - O(1) Converts a System.ValueTuple to a Towel.DataStructures.Link of the same generic types. @@ -2106,41 +2069,40 @@ The type of #6 element in the link. - Creates a link between objects. + + Creates a link between objects. + Runtime: O(1) + The #1 item to be linked. The #2 item to be linked. The #3 item to be linked. The #4 item to be linked. The #5 item to be linked. The #6 item to be linked. - O(1) - The number of objects in the tuple. + + The number of objects in the tuple. + Runtime: O(1) + The #1 item in the link. - O(1) The #2 item in the link. - O(1) The #3 item in the link. - O(1) The #4 item in the link. - O(1) The #5 item in the link. - O(1) The #6 item in the link. - O(1) Converts a System.ValueTuple to a Towel.DataStructures.LinkStruct of the same generic types. @@ -2214,7 +2176,10 @@ The type of #7 element in the link. - Creates a link between objects. + + Creates a link between objects. + Runtime: O(1) + The #1 item to be linked. The #2 item to be linked. The #3 item to be linked. @@ -2222,38 +2187,33 @@ The #5 item to be linked. The #6 item to be linked. The #7 item to be linked. - O(1) - The number of objects in the tuple. + + The number of objects in the tuple. + Runtime: O(1) + The #1 item in the link. - O(1) The #2 item in the link. - O(1) The #3 item in the link. - O(1) The #4 item in the link. - O(1) The #5 item in the link. - O(1) The #6 item in the link. - O(1) The #7 item in the link. - O(1) Converts a System.ValueTuple to a Towel.DataStructures.Link of the same generic types. @@ -2321,7 +2281,10 @@ The type of #7 element in the link. - Creates a link between objects. + + Creates a link between objects. + Runtime: O(1) + The #1 item to be linked. The #2 item to be linked. The #3 item to be linked. @@ -2329,38 +2292,33 @@ The #5 item to be linked. The #6 item to be linked. The #7 item to be linked. - O(1) - The number of objects in the tuple. + + The number of objects in the tuple. + Runtime: O(1) + The #1 item in the link. - O(1) The #2 item in the link. - O(1) The #3 item in the link. - O(1) The #4 item in the link. - O(1) The #5 item in the link. - O(1) The #6 item in the link. - O(1) The #7 item in the link. - O(1) Converts a System.ValueTuple to a Towel.DataStructures.LinkStruct of the same generic types. @@ -2511,33 +2469,45 @@ This class just holds the data for each individual node of the list. - Creates an instance of a AddableLinked. - θ(1) + + Creates an instance of a AddableLinked. + Runtime: O(1) + - Returns the number of items in the list. - θ(1) + + Returns the number of items in the list. + Runitme: O(1) + - Adds an item to the list. + + Adds an item to the list. + Runtime: O(1) + The item to add to the list. The exception that occurred if the add failed. True if the add succeeded or false if not. - O(1) - Adds an item to the list. + + Adds an item to the list. + Runtime: O(1) + The item to add to the list. - O(1) - Resets the list to an empty state. - θ(1) + + Resets the list to an empty state. + Runtime: O(1) + - Creates a shallow clone of this data structure. + + Creates a shallow clone of this data structure. + Runtime: O(n) + A shallow clone of this data structure. - θ(n) Removes the first equality by object reference. @@ -2566,74 +2536,56 @@ True if the value was removed. False if the value did not exist. - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + Gets the enumerator for this list. The enumerator for this list. - Converts the list into a standard array. + + Converts the list into a standard array. + Runtime: O(n) + A standard array of all the items. - Θ(n) A list implemented as a growing array. The type of objects to be placed in the list. - Creates an instance of a ListArray, and sets it's minimum capacity. - O(1) + + Creates an instance of a ListArray, and sets it's minimum capacity. + Runtime: O(1) + - Creates an instance of a ListArray, and sets it's minimum capacity. + + Creates an instance of a ListArray, and sets it's minimum capacity. + Runtime: O(1) + The initial and smallest array size allowed by this list. - O(1) Look-up and set an indexed item in the list. @@ -2641,19 +2593,25 @@ The value at the given index. - Gets the number of items in the list. - O(1) + + Gets the number of items in the list. + Runtime: O(1) + - Gets the current capacity of the list. - O(1) + + Gets the current capacity of the list. + Runtime: O(1) + - Tries to add a value. + + Tries to add a value. + Runtime: O(n), Ω(1), ε(1) + The value to be added. The exception that occurrs if the add fails. True if the add succeds or false if not. - O(n), Ω(1), ε(1) Adds an item at a given index. @@ -2661,54 +2619,72 @@ The index to add the item at. - Empties the list back and reduces it back to its original capacity. - O(1) + + Empties the list back and reduces it back to its original capacity. + Runtime: O(1) + Creates a shallow clone of this data structure. A shallow clone of this data structure. - Removes the item at a specific index. + + Removes the item at a specific index. + Runtime: O(n), Ω(n - index), ε(n - index) + The index of the item to be removed. - O(n), Ω(n - index), ε(n - index) - Removes the item at a specific index. + + Removes the item at a specific index. + Runtime: Θ(n - index) + The index of the item to be removed. - Θ(n - index) - Removes all predicated items from the list. + + Removes all predicated items from the list. + Runtime: Θ(n) + The predicate to determine removals. - Θ(n) - Removes all predicated items from the list. + + Removes all predicated items from the list. + Runtime: Θ(n) + The predicate to determine removals. - Θ(n) - Removes the first predicated value from the list. + + Removes the first predicated value from the list. + Runtime: O(n), Ω(1) + The predicate to determine removals. - O(n), Ω(1) - Removes the first occurence of a value from the list without causing the list to shrink. + + Removes the first occurence of a value from the list without causing the list to shrink. + Runtime: O(n), Ω(1) + The value to remove. - O(n), Ω(1) - Removes the first occurence of a value from the list without causing the list to shrink. + + Removes the first occurence of a value from the list without causing the list to shrink. + Runtime: O(n), Ω(1) + The value to remove. The delegate providing the equality check. - O(n), Ω(1) - Removes the first predicated value from the list wihtout shrinking the list. + + Removes the first predicated value from the list wihtout shrinking the list. + Runtime: O(n), Ω(1) + The predicate to determine removals. The exception that occured if the removal failed. - O(n), Ω(1) Tries to remove the first predicated value if the value exists. @@ -2724,52 +2700,28 @@ True if the value was removed. False if the value did not exist. - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + Gets the enumerator for the data structure. @@ -2901,32 +2853,44 @@ The hash function. - Constructs a hashed map. + + Constructs a hashed map. + Runtime: O(1) + The equate delegate. The hashing function. The expected count of the map. - O(1) - This constructor is for cloning purposes. + + This constructor is for cloning purposes. + Runtime: O(n) + The map to clone. - O(n) - The current size of the hashed table. - O(1) + + The current size of the hashed table. + Runtime: O(1) + - The current number of values in the map. - O(1) + + The current number of values in the map. + Runtime: O(1) + - The delegate for computing hash codes. - O(1) + + The delegate for computing hash codes. + Runtime: O(1) + - The delegate for equality checking. - O(1) + + The delegate for equality checking. + Runtime: O(1) + Gets the value of a specified key. @@ -2934,12 +2898,14 @@ The value of the key. - Tries to add a value to the map. + + Tries to add a value to the map. + Runtime: O(n), Ω(1), ε(1) + The key of the value. The value to be added. The exception that occured if the add failed. True if the value was added or false if not. - O(n), Ω(1), ε(1) Tries to get a value by key. @@ -2949,10 +2915,12 @@ True if the key was found or false if not. - Sets value in the map. + + Sets value in the map. + Runtime: O(n), Ω(1), ε(1) + The key of the value. The value to be set. - O(n), Ω(1), ε(1) Tries to remove a keyed value. @@ -2971,77 +2939,66 @@ The desired size of the table. - Trims the table to an appropriate size based on the current count. - O(n), Ω(1) + + Trims the table to an appropriate size based on the current count. + Runtime: O(n), Ω(1) + - Creates a shallow clone of this map. + + Creates a shallow clone of this map. + Runtime: Θ(n) + A shallow clone of this map. - Θ(n) - Determines if a value has been added to a map. + + Determines if a value has been added to a map. + Runtime: O(n), Ω(1), ε(1) + The key of the value to look for in the map. True if the value has been added to the map or false if not. - O(n), Ω(1), ε(1) - Removes all the values in the map. - O(1) + + Removes all the values in the map. + Runtime: O(1) + - Steps through all the values of the map. - The action to perform on every value in the map. - Θ(n * step) + - Steps through all the values of the map. - The action to perform on every value in the map. - Θ(n * step) + - Steps through all the values of the map. - The action to perform on every value in the map. - The status of the stepper. - Θ(n * step) + - Steps through all the values of the map. - The action to perform on every value in the map. - The status of the stepper. - Θ(n * step) + - Steps through all the keys of the map. - The action to perform on every value in the map. - Θ(n * step) + - Steps through all the keys of the map. - The action to perform on every value in the map. - The status of the stepper. - Θ(n * step) + - Steps through all the keys and values of the map. - The action to perform on every key and value in the map. - Θ(n * step) + - Steps through all the keys and values of the map. - The action to perform on every key and value in the map. - The status of the stepper. - Θ(n * step) + Gets the enumerator for the map. The enumerator for the map. - O(n) - Puts all the values in this map into an array. + + Puts all the values in this map into an array. + Runtime: Θ(n) + An array with all the values in the map. - Θ(n) An unsorted structure of unique items. @@ -3049,29 +3006,39 @@ The generic key type of this map. - Constructs a hashed map. + + Constructs a hashed map. + Runtime: O(1) + The equate delegate. The hashing function. The expected count of the map. - O(1) - This constructor is for cloning purposes. + + This constructor is for cloning purposes. + Runtime: O(n) + The map to clone. - O(n) - The delegate for computing hash codes. - O(1) + + The delegate for computing hash codes. + Runtime: O(1) + - The delegate for equality checking. - O(1) + + The delegate for equality checking. + Runtime: O(1) + - Creates a shallow clone of this map. + + Creates a shallow clone of this map. + Runtime: Θ(n) + A shallow clone of this map. - Θ(n) Contains the necessary type definitions for the various omnitree types. @@ -4452,10 +4419,6 @@ Represents a bound in ND space. The generic type of the bound. - - Constructs a bound from a value. - The value of the bound. - Represents a null bound meaning it does not exist. @@ -13561,95 +13524,87 @@ The generic type within the structure. - Creates an instance of a queue. - O(1) + + Creates an instance of a queue. + Runtime: O(1) + - The newest item currently in the queue. - O(1) + + The newest item currently in the queue. + Runtime: O(1) + - The oldest item currently in the queue. - O(1) + + The oldest item currently in the queue. + Runtime: O(1) + - Returns the number of items in the queue. - O(1) + + Returns the number of items in the queue. + Runtime: O(1) + - Converts the list into a standard array. + + Converts the list into a standard array. + Runtime: O(n) + A standard array of all the items. - O(n) Creates a shallow clone of this data structure. A shallow clone of this data structure. - Adds an item to the back of the queue. + + Adds an item to the back of the queue. + Runtime: O(1) + The item to add to the queue. - O(1) - Removes the oldest item in the queue. + + Removes the oldest item in the queue. + Runtime: O(1) + The next item in the queue. - O(1) Gets the next item in the queue without removing it. The next item in the queue. - Resets the queue to an empty state. - O(1) + + Resets the queue to an empty state. + Runtime: O(1) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) - - - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + + + + Gets the enumerator for this queue. @@ -13660,25 +13615,36 @@ The generic type within the structure. - Creates an instance of a ListArray, and sets it's minimum capacity. - θ(1) + + Creates an instance of a ListArray, and sets it's minimum capacity. + Runtime: O(1) + - Creates an instance of a ListArray, and sets it's minimum capacity. + + Creates an instance of a ListArray, and sets it's minimum capacity. + Runtime: O(1) + The initial and smallest array size allowed by this list. - θ(1) - Gets the number of items in the list. - O(1) + + Gets the number of items in the list. + Runtime: O(1) + - Gets the current capacity of the list. - O(1) + + Gets the current capacity of the list. + Runtime: O(1) + - Allows you to adjust the minimum capacity of this list. - O(n), Ω(1) + + Allows you to adjust the minimum capacity of this list. + Runtime (Get): O(1) + Runtime (Set): O(n), Ω(1) + The newest item currently in the queue. @@ -13695,69 +13661,51 @@ A shallow clone of this data structure. - Adds an item to the end of the list. + + Adds an item to the end of the list. + Runtime: O(n), ε(1) + The item to be added. - O(n), ε(1) - Removes the item at a specific index. - O(n - index) + + Removes the item at a specific index. + Runtime: O(n - index) + Gets the next item in the queue without removing it. The next item in the queue. - Empties the list back and reduces it back to its original capacity. - O(1) + + Empties the list back and reduces it back to its original capacity. + Runtime: O(1) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + Gets the enumerator for this queue. @@ -13793,8 +13741,10 @@ The number of items in this data structure. - The comparison function being utilized by this structure. - θ(1) + + The comparison function being utilized by this structure. + Runtime: O(1) + Tries to add a value to the Red-Black tree. @@ -13815,10 +13765,12 @@ True if the tree contains the value. False if not. - Determines if this structure contains an item by a given key. + + Determines if this structure contains an item by a given key. + Runtime: O(ln(Count)), Ω(1) + The sorting technique (must synchronize with this structure's sorting). True of contained, False if not. - O(ln(Count)) Ω(1) Tries to get a value. @@ -13840,208 +13792,100 @@ True if the remove was successful or false if not. - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) - - - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + + + + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) - - - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) + + + + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) - - - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + + + + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) - - - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The minimum value of the optimized stepper function. - The maximum value of the optimized stepper function. - O(n * step), Ω(1) + + + + Returns the IEnumerator for this data structure. @@ -14084,38 +13928,52 @@ The function for computing hash codes. - Constructs a hashed set. + + Constructs a hashed set. + Runtime: O(1) + The equate delegate. The hashing function. The expected count of the set. - O(1) - This constructor is for cloning purposes. + + This constructor is for cloning purposes. + Runtime: O(n) + The set to clone. - O(n) - The current size of the hashed table. - O(1) + + The current size of the hashed table. + Runtime: O(1) + - The current number of values in the set. - O(1) + + The current number of values in the set. + Runtime: O(1) + - The delegate for computing hash codes. - O(1) + + The delegate for computing hash codes. + Runtime: O(1) + - The delegate for equality checking. - O(1) + + The delegate for equality checking. + Runtime: O(1) + - Adds a value to the set. + + Adds a value to the set. + Runtime: O(n), Ω(1), ε(1) + The value to add to the set. The exception that occurred if the add failed. - O(n), Ω(1), ε(1) Tries to remove a value from the set. @@ -14134,73 +13992,87 @@ The desired size of the table. - Trims the table to an appropriate size based on the current count. - O(n), Ω(1) + + Trims the table to an appropriate size based on the current count. + Runtime: O(n), Ω(1) + - Creates a shallow clone of this set. + + Creates a shallow clone of this set. + Runtime: Θ(n) + A shallow clone of this set. - Θ(n) - Determines if a value has been added to a set. + + Determines if a value has been added to a set. + Runtime: O(n), Ω(1), ε(1) + The value to look for in the set. True if the value has been added to the set or false if not. - O(n), Ω(1), ε(1) - Removes all the values in the set. - O(1) + + Removes all the values in the set. + Runtime: O(1) + - Steps through all the values of the set. - The action to perform on every value in the set. - Θ(n * step) + - Steps through all the values of the set. - The action to perform on every value in the set. - The status of the stepper. - Θ(n * step) + Gets the enumerator for the set. The enumerator for the set. - O(n) - Puts all the values in this set into an array. + + Puts all the values in this set into an array. + Runtime: Θ(n) + An array with all the values in the set. - Θ(n) An unsorted structure of unique items implemented as a hashed table of linked lists. The type of values to store in the set. - Constructs a hashed set. + + Constructs a hashed set. + Runtime: O(1) + The equate delegate. The hashing function. The expected count of the set. - O(1) - This constructor is for cloning purposes. + + This constructor is for cloning purposes. + Runtime: O(n) + The set to clone. - O(n) - The delegate for computing hash codes. - O(1) + + The delegate for computing hash codes. + Runtime: O(1) + - The delegate for equality checking. - O(1) + + The delegate for equality checking. + Runtime: O(1) + - Creates a shallow clone of this set. + + Creates a shallow clone of this set. + Runtime: Θ(n) + A shallow clone of this set. - Θ(n) An unsorted structure of unique items. @@ -14219,96 +14091,118 @@ A clone of the structure. - Constructs a hashed set. + + Constructs a hashed set. + Runtime: O(1) + The factory delegate. The equate delegate. The hashing function. The expected count of the set. - O(1) - This constructor is for cloning purposes. + + This constructor is for cloning purposes. + Runtime: O(n) + The set to clone. A delegate for cloning the structures. - O(n) - The current size of the hashed table. - O(1) + + The current size of the hashed table. + Runtime: O(1) + - The current number of values in the set. - O(1) + + The current number of values in the set. + Runtime: O(1) + - The delegate for computing hash codes. - O(1) + + The delegate for computing hash codes. + Runtime: O(1) + - The delegate for equality checking. - O(1) + + The delegate for equality checking. + Runtime: O(1) + - Adds a value to the hash table. + + Adds a value to the hash table. + Runtime: O(n), Ω(1), ε(1) + The key value to use as the look-up reference in the hash table. The exception that occurred if the add failed. - O(n), Ω(1), ε(1) - Removes a value from the set. + + Removes a value from the set. + Runtime: O(n), Ω(1), ε(1) + The value to remove. The exception that occurred if the remove failed. - O(n), Ω(1), ε(1) - Removes a value from the set. + + Removes a value from the set. + Runtime: O(n), Ω(1), ε(1) + The value to remove. The exception that occurred if the remove failed. - O(n), Ω(1), ε(1) Resizes the table. The desired size of the table. - Creates a shallow clone of this set. + + Creates a shallow clone of this set. + Runtime: Θ(n) + A shallow clone of this set. - Θ(n) - Determines if a value has been added to a set. + + Determines if a value has been added to a set. + Runtime: O(n), Ω(1), ε(1) + The value to look for in the set. True if the value has been added to the set or false if not. - O(n), Ω(1), ε(1) - Removes all the values in the set. - O(1) + + Removes all the values in the set. + Runtime: O(1) + - Trims the table to an appropriate size based on the current count. - O(n), Ω(1) + + Trims the table to an appropriate size based on the current count. + Runtime: O(n), Ω(1) + - Steps through all the values of the set. - The action to perform on every value in the set. - Θ(n * step) + - Steps through all the values of the set. - The action to perform on every value in the set. - The status of the stepper. - Θ(n * step) + Gets the enumerator for the set. The enumerator for the set. - O(n) - Puts all the values in this set into an array. + + Puts all the values in this set into an array. + Runtime: Θ(n) + An array with all the values in the set. - Θ(n) A self-sorting binary tree based on the heights of each node. @@ -14420,6 +14314,37 @@ Contains extensions methods for the SortedBinaryTree interface. + + + Invokes a method for each entry in the data structure. + Runtime: O(n * step), Ω(1) + + The method to invoke on each item in the structure. + The minimum value of iteration. + The maximum value of iteration. + The method to invoke on each item in the structure. + The resulting status of the iteration. + + + + Invokes a method for each entry in the data structure. + Runtime: O(n * step) + + The method to invoke on each item in the structure. + The method to invoke on each item in the structure. + The resulting status of the iteration. + + + + Invokes a method for each entry in the data structure. + Runtime: O(n * step), Ω(1) + + The method to invoke on each item in the structure. + The minimum value of iteration. + The maximum value of iteration. + The method to invoke on each item in the structure. + The resulting status of the iteration. + Gets a traversal stepper for the tree. The generic type of this data structure. @@ -14581,88 +14506,78 @@ The generic type within the structure. - Creates an instance of a stack. - θ(1) + + Creates an instance of a stack. + Runtime: O(1) + - Returns the number of items in the stack. - θ(1) + + Returns the number of items in the stack. + Runtime: O(1) + Creates a shallow clone of this data structure. A shallow clone of this data structure. - Converts the structure into an array. + + Converts the structure into an array. + Runtime: Θ(n) + An array containing all the item in the structure. - Θ(n) - Adds an item to the top of the stack. + + Adds an item to the top of the stack. + Runtime: O(1) + The item to add to the stack. - O(1) - Returns the most recent addition to the stack. + + Returns the most recent addition to the stack. + Runtime: O(1) + The most recent addition to the stack. - O(1) - Removes and returns the most recent addition to the stack. + + Removes and returns the most recent addition to the stack. + Runtime: O(1) + The most recent addition to the stack. - O(1) - Clears the stack to an empty state. - O(1). Note: causes considerable garbage collection + + Clears the stack to an empty state. + Runtime: O(1) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + Gets the enumerator for this stack. @@ -14673,25 +14588,35 @@ The generic type within the structure. - Creates an instance of a ListArray, and sets it's minimum capacity. - O(1) + + Creates an instance of a ListArray, and sets it's minimum capacity. + Runtime: O(1) + - Creates an instance of a ListArray, and sets it's minimum capacity. + + Creates an instance of a ListArray, and sets it's minimum capacity. + Runtime: O(1) + The initial and smallest array size allowed by this list. - O(1) - Gets the current capacity of the list. - O(1) + + Gets the current capacity of the list. + Runtime: O(1) + - Allows you to adjust the minimum capacity of this list. - O(n), Ω(1) + + Allows you to adjust the minimum capacity of this list. + Runtime: O(n), Ω(1) + - Gets the number of items in the list. - O(1) + + Gets the number of items in the list. + Runtime: O(1) + Creates a shallow clone of this data structure. @@ -14702,70 +14627,54 @@ A standard array of all the elements. - Adds an item to the end of the list. + + Adds an item to the end of the list. + Runtime: O(n), Ω(1), ε(1) + The item to be added. - O(n), ε(1) - Removes the item at a specific index. - O(Count), Ω(1), ε(1) + + Removes the item at a specific index. + Runtime: O(Count), Ω(1), ε(1) + - Returns the most recent addition to the stack. + + Returns the most recent addition to the stack. + Runtime: O(1) + The most recent addition to the stack. - O(1) - Empties the list back and reduces it back to its original capacity. - O(1) + + Empties the list back and reduces it back to its original capacity. + Runtime: O(1) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + - Invokes a delegate for each entry in the data structure. - The delegate to invoke on each item in the structure. - The delegate to invoke on each item in the structure. - The resulting status of the iteration. - O(n * step) + Gets the enumerator for this stack. @@ -16629,16 +16538,20 @@ The computed determinant. - Computes the determinant of a square matrix via Gaussian elimination. + + Computes the determinant of a square matrix via Gaussian elimination. + Runtime: O((n^3 + 2n^−3) / 3) + The matrix to compute the determinant of. The computed determinant. - O((n^3 + 2n^−3) / 3) - Computes the determinant of a square matrix via Laplace's method. + + Computes the determinant of a square matrix via Laplace's method. + Runtime: O(n(2^(n − 1) − 1)) + The matrix to compute the determinant of. The computed determinant. - O(n(2^(n − 1) − 1)) Computes the determinant of a square matrix. @@ -31342,10 +31255,12 @@ The span to be sorted. - Sorts values using the bubble sort algorithm. - Ω(n), ε(n^2), O(n^2) - True - O(1) + + Sorts values using the bubble sort algorithm. + Runtime: Ω(n), ε(n^2), O(n^2) + Memory: O(1) + Stable: True + @@ -31361,10 +31276,12 @@ - Sorts values using the selection sort algoritm. - Ω(n^2), ε(n^2), O(n^2) - False - O(1) + + Sorts values using the selection sort algoritm. + Runtime: Ω(n^2), ε(n^2), O(n^2) + Memory: O(1) + Stable: False + @@ -31380,10 +31297,12 @@ - Sorts values using the insertion sort algorithm. - Ω(n), ε(n^2), O(n^2) - True - O(1) + + Sorts values using the insertion sort algorithm. + Runtime: Ω(n), ε(n^2), O(n^2) + Memory: O(1) + Stable: True + @@ -31399,10 +31318,12 @@ - Sorts values using the quick sort algorithm. - Ω(n*ln(n)), ε(n*ln(n)), O(n^2) - False - ln(n) + + Sorts values using the quick sort algorithm. + Runtime: Ω(n*ln(n)), ε(n*ln(n)), O(n^2) + Memory: ln(n) + Stable: False + @@ -31418,10 +31339,12 @@ - Sorts values using the merge sort algorithm. - Ω(n*ln(n)), ε(n*ln(n)), O(n*ln(n)) - True - Θ(n) + + Sorts values using the merge sort algorithm. + Runtime: Ω(n*ln(n)), ε(n*ln(n)), O(n*ln(n)) + Memory: Θ(n) + Stable: True + @@ -31437,10 +31360,12 @@ - Sorts values using the heap sort algorithm. - Ω(n*ln(n)), ε(n*ln(n)), O(n^2) - False - O(1) + + Sorts values using the heap sort algorithm. + Runtime: Ω(n*ln(n)), ε(n*ln(n)), O(n^2) + Memory: O(1) + Stable: False + @@ -31456,10 +31381,12 @@ - Sorts values using the odd even sort algorithm. - Ω(n), ε(n^2), O(n^2) - True - O(1) + + Sorts values using the odd even sort algorithm. + Runtime: Ω(n), ε(n^2), O(n^2) + Memory: O(1) + Stable: True + @@ -31475,7 +31402,11 @@ - Sorts values into a randomized order. + + Sorts values into a randomized order. + Runtime: O(n) + Memory: O(1) + The type of values to sort. The get function. The set function. @@ -31485,8 +31416,6 @@ The set function. The random to shuffle with. The array to shuffle. - O(n) - O(1) @@ -31504,10 +31433,12 @@ - Sorts values using the bogo sort algorithm. - Ω(n), ε(n*n!), O(∞) - False - O(1) + + Sorts values using the bogo sort algorithm. + Runtime: Ω(n), ε(n*n!), O(∞) + Memory: O(1) + Stable: False + diff --git a/Tools/Towel_Benchmarking/Towel_Benchmarking.csproj b/Tools/Towel_Benchmarking/Towel_Benchmarking.csproj index 7673bc9d..ec92ad73 100644 --- a/Tools/Towel_Benchmarking/Towel_Benchmarking.csproj +++ b/Tools/Towel_Benchmarking/Towel_Benchmarking.csproj @@ -2,7 +2,7 @@ Exe false - netcoreapp3.1 + net5.0 diff --git a/Tools/Towel_Documenting/Towel_Documenting.csproj b/Tools/Towel_Documenting/Towel_Documenting.csproj index 9d61e85c..6201e2a8 100644 --- a/Tools/Towel_Documenting/Towel_Documenting.csproj +++ b/Tools/Towel_Documenting/Towel_Documenting.csproj @@ -2,7 +2,7 @@ Exe false - netcoreapp3.1 + net5.0 diff --git a/Tools/Towel_Generating/Towel_Generating.csproj b/Tools/Towel_Generating/Towel_Generating.csproj index 9d61e85c..6201e2a8 100644 --- a/Tools/Towel_Generating/Towel_Generating.csproj +++ b/Tools/Towel_Generating/Towel_Generating.csproj @@ -2,7 +2,7 @@ Exe false - netcoreapp3.1 + net5.0 diff --git a/Tools/Towel_Testing/Towel_Testing.csproj b/Tools/Towel_Testing/Towel_Testing.csproj index 4db22ff9..e5cb22de 100644 --- a/Tools/Towel_Testing/Towel_Testing.csproj +++ b/Tools/Towel_Testing/Towel_Testing.csproj @@ -1,6 +1,6 @@  - netcoreapp3.1 + net5.0 false Towel_Testing.xml true From 859286226a1ce78d9bb2c16d2ab45591b77642df Mon Sep 17 00:00:00 2001 From: Zachary Patten Date: Tue, 27 Oct 2020 00:57:33 -0400 Subject: [PATCH 03/30] nullable ref + clean up --- Sources/Towel/CommandLine.cs | 22 +- Sources/Towel/ConsoleHelper.cs | 20 +- Sources/Towel/DataStructures/AvlTree.cs | 77 ++-- Sources/Towel/DataStructures/DataStructure.cs | 8 +- Sources/Towel/DataStructures/Graph.cs | 42 +- Sources/Towel/DataStructures/Heap.cs | 2 +- Sources/Towel/DataStructures/List.cs | 387 +++++++----------- Sources/Towel/DataStructures/Map.cs | 105 ++--- Sources/Towel/DataStructures/Omnitree_ND.cs | 23 +- Sources/Towel/DataStructures/Queue.cs | 364 ++++++++-------- Sources/Towel/DataStructures/Set.cs | 128 +++--- .../Towel/DataStructures/SortedBinaryTree.cs | 10 +- Sources/Towel/DataStructures/Stack.cs | 181 +++----- Sources/Towel/DataStructures/Trie.cs | 48 +-- Sources/Towel/Extensions.cs | 16 +- Sources/Towel/Meta.cs | 144 ++++--- Sources/Towel/Towel.csproj | 1 + Sources/Towel/Towel.xml | 83 ++-- 18 files changed, 723 insertions(+), 938 deletions(-) diff --git a/Sources/Towel/CommandLine.cs b/Sources/Towel/CommandLine.cs index 7354c45d..4e35cfc5 100644 --- a/Sources/Towel/CommandLine.cs +++ b/Sources/Towel/CommandLine.cs @@ -11,7 +11,7 @@ public static class CommandLine /// Handles the command line arguments by invoking the relative method in the calling . /// The command line arguments. - public static void HandleArguments(string[] args = null) + public static void HandleArguments(string[]? args = null) { Assembly assembly = Assembly.GetCallingAssembly(); args ??= Environment.GetCommandLineArgs(); @@ -74,9 +74,10 @@ public static void HandleArguments(string[] args = null) ParameterInfo[] parameterInfos = methodInfo.GetParameters(); foreach (ParameterInfo parameterInfo in parameterInfos) { + _ = parameterInfo.Name ?? throw new Exception("encountered a null parameter name"); parameterMap.Add(parameterInfo.Name, parameterCount++); } - object[] parameters = new object[parameterCount]; + object?[] parameters = new object[parameterCount]; for (int i = 1; i < args.Length; i += 2) { string arg = args[i]; @@ -91,7 +92,7 @@ public static void HandleArguments(string[] args = null) Console.Error.WriteLine($"Invalid parameter --{arg} in index {i}."); return; } - if (!(parameters[index] is null)) + if (parameters[index] is not null) { Console.Error.WriteLine($"Duplicate parameters provided --{arg}."); return; @@ -104,20 +105,20 @@ public static void HandleArguments(string[] args = null) else { MethodInfo tryParse; - ConstructorInfo constuctor; - if (!((tryParse = Meta.GetTryParseMethod(parameterType)) is null)) + ConstructorInfo? constuctor; + if ((tryParse = Meta.GetTryParseMethod(parameterType)) is not null) { object[] tryParseParameters = new object[2]; tryParseParameters[0] = args[i + 1]; - object result = tryParse.Invoke(null, tryParseParameters); - if (!(result is bool resultBool) || !resultBool) + object? result = tryParse.Invoke(null, tryParseParameters); + if (result is not bool resultBool || !resultBool) { Console.Error.WriteLine($"Could not parse parameter value --{arg} {args[i + 1]}."); return; } parameters[index] = tryParseParameters[1]; } - else if (!((constuctor = parameterType.GetConstructor(Ɐ(typeof(string)))) is null)) + else if ((constuctor = parameterType.GetConstructor(Ɐ(typeof(string)))) is not null) { parameters[index] = constuctor.Invoke(Ɐ(args[i + 1])); } @@ -146,7 +147,7 @@ public static void HandleArguments(string[] args = null) /// This method is going to be changed... [Obsolete("warning, this method is going to be changed... it is new and the design isn't finalized", false)] - public static void DefaultVersion(Assembly assembly = null) + public static void DefaultVersion(Assembly? assembly = null) { assembly ??= Assembly.GetCallingAssembly(); AssemblyName assemblyName = assembly.GetName(); @@ -156,8 +157,9 @@ public static void DefaultVersion(Assembly assembly = null) /// This method is going to be changed... [Obsolete("warning, this method is going to be changed... it is new and the design isn't finalized", false)] - public static void DefaultHelp(Assembly assembly = null, string command = null) + public static void DefaultHelp(Assembly? assembly = null, string? command = null) { + assembly ??= Assembly.GetCallingAssembly(); if (command is null) { DefaultVersion(assembly); diff --git a/Sources/Towel/ConsoleHelper.cs b/Sources/Towel/ConsoleHelper.cs index 9557076b..e84a2e9a 100644 --- a/Sources/Towel/ConsoleHelper.cs +++ b/Sources/Towel/ConsoleHelper.cs @@ -32,7 +32,7 @@ public static void PressToContinue(ConsoleKey key = ConsoleKey.Enter) /// Prompts the user to press [enter] in the console before continuing. /// The key to wait for the user to press before continuing. /// The prompt to display to the user. Default: "Press [enter] to continue...". - public static void PromptPressToContinue(string prompt = null, ConsoleKey key = ConsoleKey.Enter) + public static void PromptPressToContinue(string? prompt = null, ConsoleKey key = ConsoleKey.Enter) { if (!key.IsDefined()) { @@ -54,9 +54,9 @@ public static void IntMenu(params (string DisplayName, Action Action)[] options) /// The message to display if invalid input is detected. /// The options of the menu. public static void IntMenu( - string title = null, - string prompt = null, - string invalidMessage = null, + string? title = null, + string? prompt = null, + string? invalidMessage = null, params (string DisplayName, Action Action)[] options) { _ = options ?? throw new ArgumentNullException(nameof(options)); @@ -92,10 +92,10 @@ public static void IntMenu( /// The predicate for validating the value of the input. /// The validated value of the console input provided by the user. public static T GetInput( - string prompt = null, - string invalidMessage = null, - Func tryParse = null, - Predicate validation = null) + string? prompt = null, + string? invalidMessage = null, + Func? tryParse = null, + Predicate? validation = null) { if (tryParse is null && (typeof(T) != typeof(string) && !typeof(T).IsEnum && Meta.GetTryParseMethod() is null)) { @@ -139,8 +139,8 @@ internal static void HiddenReadLineBase( Action Append, Action InsertAt, Action RemoveAt, - Action RemoveRange = null, - Action Clear = null) + Action? RemoveRange = null, + Action? Clear = null) { int position = 0; diff --git a/Sources/Towel/DataStructures/AvlTree.cs b/Sources/Towel/DataStructures/AvlTree.cs index 8480ef8b..c2646749 100644 --- a/Sources/Towel/DataStructures/AvlTree.cs +++ b/Sources/Towel/DataStructures/AvlTree.cs @@ -17,7 +17,7 @@ public static class AvlTree { } public class AvlTreeLinked : IAvlTree where Compare : struct, IFunc { - internal Node _root; + internal Node? _root; internal int _count; internal Compare _compare; @@ -26,8 +26,8 @@ public class AvlTreeLinked : IAvlTree internal class Node { internal T Value; - internal Node LeftChild; - internal Node RightChild; + internal Node? LeftChild; + internal Node? RightChild; internal int Height; } @@ -79,7 +79,7 @@ public T CurrentLeast { _ = _root ?? throw new InvalidOperationException("Attempting to get the current least value from an empty AVL tree."); Node node = _root; - while (!(node.LeftChild is null)) + while (node.LeftChild is not null) { node = node.LeftChild; } @@ -97,7 +97,7 @@ public T CurrentGreatest { _ = _root ?? throw new InvalidOperationException("Attempting to get the current greatest value from an empty AVL tree."); Node node = _root; - while (!(node.RightChild is null)) + while (node.RightChild is not null) { node = node.RightChild; } @@ -133,10 +133,10 @@ _compare is FuncRuntime func /// The value to add. /// The exception that occurred if the add failed. /// True if the add succeeded or false if not. - public bool TryAdd(T value, out Exception exception) + public bool TryAdd(T value, out Exception? exception) { - Exception capturedException = null; - Node Add(Node node) + Exception? capturedException = null; + Node? Add(Node? node) { if (node is null) { @@ -211,8 +211,8 @@ public bool Contains(T value) => /// True of contained, False if not. public bool Contains(Func sift) { - Node node = _root; - while (!(node is null)) + Node? node = _root; + while (node is not null) { CompareResult compareResult = sift(node.Value); if (compareResult is Less) @@ -243,10 +243,10 @@ public bool Contains(Func sift) /// The value if found or default. /// The exception that occurred if the get failed. /// True if the get succeeded or false if not. - public bool TryGet(Func sift, out T value, out Exception exception) + public bool TryGet(Func sift, out T value, out Exception? exception) { - Node node = _root; - while (!(node is null)) + Node? node = _root; + while (node is not null) { CompareResult comparison = sift(node.Value); if (comparison is Less) @@ -277,19 +277,19 @@ public bool TryGet(Func sift, out T value, out Exception excep /// The value to remove. /// The exception that occurred if the remove failed. /// True if the remove was successful or false if not. - public bool TryRemove(T value, out Exception exception) => + public bool TryRemove(T value, out Exception? exception) => TryRemove(x => _compare.Do(x, value), out exception); /// Tries to remove a value. /// The compare delegate. /// The exception that occurred if the remove failed. /// True if the remove was successful or false if not. - public bool TryRemove(Func sift, out Exception exception) + public bool TryRemove(Func sift, out Exception? exception) { - Exception capturedException = null; - Node Remove(Node node) + Exception? capturedException = null; + Node? Remove(Node? node) { - if (!(node is null)) + if (node is not null) { CompareResult compareResult = sift(node.Value); if (compareResult is Less) @@ -364,18 +364,20 @@ public StepStatus StepperBreak(Step step = default) StepperRefBreak>(step); /// - public StepStatus Stepper(Func step) => StepperBreak>(step); + public StepStatus Stepper(Func step) => + StepperBreak>(step); /// - public StepStatus Stepper(StepRefBreak step) => StepperRefBreak>(step); + public StepStatus Stepper(StepRefBreak step) => + StepperRefBreak>(step); /// public StepStatus StepperRefBreak(Step step = default) where Step : struct, IStepRefBreak { - StepStatus Stepper(Node node) + StepStatus Stepper(Node? node) { - if (!(node is null)) + if (node is not null) { return Stepper(node.LeftChild) is Break ? Break : @@ -427,9 +429,9 @@ public virtual StepStatus Stepper(T minimum, T maximum, StepRefBreak step) => public virtual StepStatus StepperRefBreak(T minimum, T maximum, Step step = default) where Step : struct, IStepRefBreak { - StepStatus Stepper(Node node) + StepStatus Stepper(Node? node) { - if (!(node is null)) + if (node is not null) { if (_compare.Do(node.Value, minimum) is Less) { @@ -496,9 +498,9 @@ public StepStatus StepperReverse(StepRefBreak step) => public StepStatus StepperReverseRefBreak(Step step = default) where Step : struct, IStepRefBreak { - StepStatus StepperReverse(Node node) + StepStatus StepperReverse(Node? node) { - if (!(node is null)) + if (node is not null) { return StepperReverse(node.RightChild) is Break ? Break : @@ -550,9 +552,9 @@ public virtual StepStatus StepperReverse(T minimum, T maximum, StepRefBreak s public virtual StepStatus StepperReverseRefBreak(T minimum, T maximum, Step step = default) where Step : struct, IStepRefBreak { - StepStatus StepperReverse(Node node) + StepStatus StepperReverse(Node? node) { - if (!(node is null)) + if (node is not null) { if (_compare.Do(node.Value, minimum) is Less) { @@ -607,11 +609,11 @@ public IEnumerator GetEnumerator() /// /// The tree to check the balancing of. /// The result of the possible balancing. - internal static Node Balance(Node node) + internal static Node? Balance(Node node) { static Node RotateSingleLeft(Node node) { - Node temp = node.RightChild; + Node? temp = node.RightChild; node.RightChild = temp.LeftChild; temp.LeftChild = node; SetHeight(node); @@ -621,7 +623,7 @@ static Node RotateSingleLeft(Node node) static Node RotateDoubleLeft(Node node) { - Node temp = node.RightChild.LeftChild; + Node? temp = node.RightChild.LeftChild; node.RightChild.LeftChild = temp.RightChild; temp.RightChild = node.RightChild; node.RightChild = temp.LeftChild; @@ -634,7 +636,7 @@ static Node RotateDoubleLeft(Node node) static Node RotateSingleRight(Node node) { - Node temp = node.LeftChild; + Node? temp = node.LeftChild; node.LeftChild = temp.RightChild; temp.RightChild = node; SetHeight(node); @@ -642,9 +644,9 @@ static Node RotateSingleRight(Node node) return temp; } - static Node RotateDoubleRight(Node node) + static Node? RotateDoubleRight(Node node) { - Node temp = node.LeftChild.RightChild; + Node? temp = node.LeftChild.RightChild; node.LeftChild.RightChild = temp.LeftChild; temp.LeftChild = node.LeftChild; node.LeftChild = temp.RightChild; @@ -677,10 +679,7 @@ static Node RotateDoubleRight(Node node) /// /// The node to find the hight of. /// Returns "-1" if null (leaf) or the height property of the node. - internal static int Height(Node node) => - node is null - ? -1 - : node.Height; + internal static int Height(Node? node) => node is null ? -1 : node.Height; /// Removes the left-most child of an AVL Tree node and returns it /// through the out parameter. @@ -740,7 +739,7 @@ public class AvlTreeLinked : AvlTreeLinkedRuntime: O(1) /// /// The comparison function for sorting the items. - public AvlTreeLinked(Func compare = null) : base(compare ?? Statics.Compare) { } + public AvlTreeLinked(Func? compare = null) : base(compare ?? Statics.Compare) { } /// This constructor if for cloning purposes. /// The tree to clone. diff --git a/Sources/Towel/DataStructures/DataStructure.cs b/Sources/Towel/DataStructures/DataStructure.cs index 47311add..df4c8e31 100644 --- a/Sources/Towel/DataStructures/DataStructure.cs +++ b/Sources/Towel/DataStructures/DataStructure.cs @@ -75,7 +75,7 @@ public interface IAddable /// The value to add to the data structure. /// The exception that occurred if the add failed. /// True if the value was added or false if not. - bool TryAdd(T value, out Exception exception); + bool TryAdd(T value, out Exception? exception); } /// Property of a data structure (does it have a Romove method). @@ -86,7 +86,7 @@ public interface IRemovable /// The value to remove. /// The exception that occurred if the remove failed. /// True if the value was removed or false if not. - bool TryRemove(T value, out Exception exception); + bool TryRemove(T value, out Exception? exception); } /// Property of a data structure (does it have a Count method). @@ -152,7 +152,7 @@ public static bool TryAdd(this IAddable structure, T value) => /// The value to be added. public static void Add(this IAddable structure, T value) { - if (!structure.TryAdd(value, out Exception exception)) + if (!structure.TryAdd(value, out Exception? exception)) { throw exception; } @@ -172,7 +172,7 @@ public static bool TryRemove(this IRemovable structure, T value) => /// The value to be removed. public static void Remove(this IRemovable structure, T value) { - if (!structure.TryRemove(value, out Exception exception)) + if (!structure.TryRemove(value, out Exception? exception)) { throw exception; } diff --git a/Sources/Towel/DataStructures/Graph.cs b/Sources/Towel/DataStructures/Graph.cs index 4390d6b3..c2c910af 100644 --- a/Sources/Towel/DataStructures/Graph.cs +++ b/Sources/Towel/DataStructures/Graph.cs @@ -30,7 +30,7 @@ public interface IGraph : IDataStructure, /// Gets all the nodes adjacent to a and performs the provided delegate on each. /// The node to find all the adjacent node to. /// The delegate to perform on each adjacent node to a. - void Neighbors(T a, Action function); + void Neighbors(T a, Action function); /// Adds an edge to the graph starting at a and ending at b. /// The stating point of the edge to add. /// The ending point of the edge to add. @@ -41,11 +41,11 @@ public interface IGraph : IDataStructure, void Remove(T start, T end); /// Invokes a delegate for each entry in the data structure. /// The delegate to invoke on each item in the structure. - void Stepper(Action step); + void Stepper(Action step); /// Invokes a delegate for each entry in the data structure. /// The delegate to invoke on each item in the structure. /// The resulting status of the iteration. - StepStatus Stepper(Func step); + StepStatus Stepper(Func step); #endregion } @@ -63,9 +63,9 @@ public class GraphSetOmnitree : IGraph public class Edge { /// The starting node of the edge. - public T Start { get; internal set; } + public T? Start { get; internal set; } /// The ending node of the edge. - public T End { get; internal set; } + public T? End { get; internal set; } } #endregion @@ -85,9 +85,9 @@ internal GraphSetOmnitree(GraphSetOmnitree graph) /// The compare delegate for the data structure to use. /// The hash delegate for the datastructure to use. public GraphSetOmnitree( - Func equate = null, - Func compare = null, - Func hash = null) + Func? equate = null, + Func? compare = null, + Func? hash = null) { equate ??= Statics.Equate; compare ??= Compare; @@ -120,7 +120,7 @@ public GraphSetOmnitree( /// Tries to add a node to the graph. /// The node to add to the graph. /// The exception that occurred if the add failed. - public bool TryAdd(T node, out Exception exception) + public bool TryAdd(T node, out Exception? exception) { return _nodes.TryAdd(node, out exception); } @@ -149,7 +149,7 @@ public void Add(T start, T end) /// The edge to remove from the graph. /// The exception that occurred if the remove failed. /// True if the remove succeeded or false if not. - public bool TryRemove(T node, out Exception exception) + public bool TryRemove(T node, out Exception? exception) { if (!_nodes.TryRemove(node, out exception)) { @@ -198,7 +198,7 @@ public bool Adjacent(T a, T b) /// Gets the neighbors of a node. /// The node to get the neighbors of. /// The step to perform on all the neighbors. - public void Neighbors(T node, Action step) + public void Neighbors(T node, Action step) { if (!_nodes.Contains(node)) { @@ -222,27 +222,27 @@ public void Clear() /// Steps through all the nodes in the graph. /// The action to perform on all the nodes in the graph. - public void Stepper(Action step) => _nodes.Stepper(step); + public void Stepper(Action step) => _nodes.Stepper(step); /// Steps through all the nodes in the graph. /// The action to perform on all the nodes in the graph. /// The status of the stepper operation. - public StepStatus Stepper(Func step) => _nodes.Stepper(step); + public StepStatus Stepper(Func step) => _nodes.Stepper(step); /// Steps through all the edges in the graph. /// The action to perform on all the edges in the graph. - public void Stepper(Action step) => _edges.Stepper(edge => step(edge.Start, edge.End)); + public void Stepper(Action step) => _edges.Stepper(edge => step(edge.Start, edge.End)); /// Steps through all the edges in the graph. /// The action to perform on all the edges in the graph. /// The status of the stepper operation. - public StepStatus Stepper(Func step) => _edges.Stepper(edge => step(edge.Start, edge.End)); + public StepStatus Stepper(Func step) => _edges.Stepper(edge => step(edge.Start, edge.End)); System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); /// Gets the enumerator for the nodes in the graph. /// The enumerator for the nodes in the graph. - public System.Collections.Generic.IEnumerator GetEnumerator() => _nodes.GetEnumerator(); + public System.Collections.Generic.IEnumerator GetEnumerator() => _nodes.GetEnumerator(); #endregion } @@ -355,7 +355,7 @@ public bool Adjacent(T a, T b) /// Steps through all the neighbors of a node. /// The node to step through the children of. /// The action to perform on all the neighbors of the provided node. - public void Neighbors(T a, Action step) + public void Neighbors(T a, Action step) { if (_map.TryGet(a, out SetHashLinked map)) { @@ -376,14 +376,14 @@ public StepStatus Stepper(Func step) => /// Steps through all the edges in the /// The action to perform on every edge in the graph. - public void Stepper(Action step) => + public void Stepper(Action step) => _map.Stepper((edges, a) => edges.Stepper(b => step(a, b))); /// Steps through all the edges in the /// The action to perform on every edge in the graph. /// The status of the iteration. - public StepStatus Stepper(Func step) => + public StepStatus Stepper(Func step) => _map.Stepper((edges, a) => edges.Stepper(b => step(a, b))); @@ -408,8 +408,8 @@ public T[] ToArray() throw new NotImplementedException(); } - System.Collections.Generic.IEnumerator - System.Collections.Generic.IEnumerable.GetEnumerator() + System.Collections.Generic.IEnumerator + System.Collections.Generic.IEnumerable.GetEnumerator() { throw new NotImplementedException(); } diff --git a/Sources/Towel/DataStructures/Heap.cs b/Sources/Towel/DataStructures/Heap.cs index 110979a0..fb922e4d 100644 --- a/Sources/Towel/DataStructures/Heap.cs +++ b/Sources/Towel/DataStructures/Heap.cs @@ -316,7 +316,7 @@ public class HeapArray : HeapArray> /// /// Delegate determining the comparison technique used for sorting. /// The capacity you want this priority queue to have. - public HeapArray(Func compare = null, int? minimumCapacity = null) : base(compare ?? Statics.Compare, minimumCapacity) { } + public HeapArray(Func? compare = null, int? minimumCapacity = null) : base(compare ?? Statics.Compare, minimumCapacity) { } internal HeapArray(HeapArray heap) { diff --git a/Sources/Towel/DataStructures/List.cs b/Sources/Towel/DataStructures/List.cs index 306c7a9b..25427f77 100644 --- a/Sources/Towel/DataStructures/List.cs +++ b/Sources/Towel/DataStructures/List.cs @@ -18,7 +18,7 @@ public interface IList : IDataStructure, /// The exception that occurred if the remove failed. /// The predicate to determine removal. /// True if the value was removed. False if the value did not exist. - bool TryRemoveFirst(out Exception exception, Predicate predicate = default) + bool TryRemoveFirst(out Exception? exception, Predicate predicate = default) where Predicate : struct, IFunc; /// Removes all occurences of predicated values from the list. @@ -56,7 +56,7 @@ public static bool TryRemoveFirst(this IList iList, Func predicat /// The predicate for selecting the removal from the . /// The exception that occured if the removal failed. /// True if the predicated element was found and removed. False if not. - public static bool TryRemoveFirst(this IList iList, Func predicate, out Exception exception) => + public static bool TryRemoveFirst(this IList iList, Func predicate, out Exception? exception) => iList.TryRemoveFirst>(out exception, predicate); /// Removes the first equality by object reference. @@ -64,9 +64,9 @@ public static bool TryRemoveFirst(this IList iList, Func predicat /// The predicate to determine removal. public static void RemoveFirst(this IList iList, Func predicate) { - if (!iList.TryRemoveFirst>(out Exception exception, predicate)) + if (!iList.TryRemoveFirst>(out Exception? exception, predicate)) { - throw exception; + throw exception ?? new ArgumentNullException(nameof(exception), $"{nameof(TryRemoveFirst)} failed but the {nameof(exception)} is null"); } } @@ -118,7 +118,7 @@ public static void RemoveAll(this IList iList, T value) /// The list to remove the values from. /// The value to remove all occurences of. /// The delegate for performing equality checks. - public static void RemoveAll(this IList iList, T value, Func equate) + public static void RemoveAll(this IList iList, T value, Func equate) { iList.RemoveAll(x => equate(x, value)); } @@ -131,36 +131,43 @@ public static void RemoveAll(this IList iList, T value, Func e public class ListLinked : IList { internal int _count; - internal Node _head; - internal Node _tail; + internal Node? _head; + internal Node? _tail; #region Node - /// This class just holds the data for each individual node of the list. internal class Node { - internal Node Next; internal T Value; + internal Node? Next; + + internal Node(T value, Node? next = null) + { + Value = value; + Next = next; + } } #endregion #region Constructors - internal ListLinked(ListLinked listLinked) + internal ListLinked(ListLinked list) { - Node head = new Node { Value = listLinked._head.Value }; - Node current = listLinked._head.Next; - Node current_clone = head; - while (!(current is null)) + if (list._head is not null) { - current_clone.Next = new Node { Value = current.Value }; - current_clone = current_clone.Next; - current = current.Next; + _head = new Node(value: list._head.Value); + Node? a = list._head.Next; + Node? b = _head; + while (a is not null) + { + b.Next = new Node(value: a.Value); + b = b.Next; + a = a.Next; + } + _tail = b; + _count = list._count; } - _head = head; - _tail = current_clone; - _count = listLinked._count; } /// @@ -187,8 +194,6 @@ public ListLinked() #region Methods - #region Add - /// /// Adds an item to the list. /// Runtime: O(1) @@ -196,7 +201,7 @@ public ListLinked() /// The item to add to the list. /// The exception that occurred if the add failed. /// True if the add succeeded or false if not. - public bool TryAdd(T value, out Exception exception) + public bool TryAdd(T value, out Exception? exception) { Add(value); exception = null; @@ -212,33 +217,26 @@ public void Add(T addition) { if (_tail is null) { - _head = _tail = new Node { Value = addition }; + _head = _tail = new Node(value: addition); } else { - _tail = _tail.Next = new Node { Value = addition }; + _tail = _tail.Next = new Node(value: addition); } _count++; } - #endregion - - #region Clear - /// /// Resets the list to an empty state. /// Runtime: O(1) /// public void Clear() { - _head = _tail = null; + _head = null; + _tail = null; _count = 0; } - #endregion - - #region Clone - /// /// Creates a shallow clone of this data structure. /// Runtime: O(n) @@ -246,17 +244,13 @@ public void Clear() /// A shallow clone of this data structure. public ListLinked Clone() => new ListLinked(this); - #endregion - - #region Remove - /// Removes the first equality by object reference. /// The predicate to determine removal. public void RemoveFirst(Func predicate) { - if (!TryRemoveFirst(predicate, out Exception exception)) + if (!TryRemoveFirst(predicate, out Exception? exception)) { - throw exception; + throw exception ?? new TowelBugException($"{nameof(TryRemoveFirst)} failed but the {nameof(exception)} is null"); } } @@ -265,33 +259,32 @@ public void RemoveFirst(Func predicate) public void RemoveAll(Predicate predicate = default) where Predicate : struct, IFunc { - if (_head is null) - { - return; - } - while (predicate.Do(_head.Value)) - { - _head = _head.Next; - _count--; - } - Node tail = null; - for (Node node = _head; !(node.Next is null); node = node.Next) + if (_head is not null) { - if (predicate.Do(node.Next.Value)) + while (predicate.Do(_head!.Value)) { - if (node.Next.Equals(_tail)) - { - _tail = node; - } - node.Next = node.Next.Next; + _head = _head.Next; _count--; } - else + Node? tail = null; + for (Node? node = _head; node!.Next is not null; node = node.Next) { - tail = node; + if (predicate.Do(node.Next.Value)) + { + if (node.Next.Equals(_tail)) + { + _tail = node; + } + node.Next = node.Next.Next; + _count--; + } + else + { + tail = node; + } } + _tail = tail; } - _tail = tail; } /// Tries to remove the first predicated value if the value exists. @@ -304,7 +297,7 @@ public bool TryRemoveFirst(Func predicate) => /// The predicate to determine removal. /// The exception that occurred if the remove failed. /// True if the value was removed. False if the value did not exist. - public bool TryRemoveFirst(Func predicate, out Exception exception) => + public bool TryRemoveFirst(Func predicate, out Exception? exception) => TryRemoveFirst>(out exception, predicate); /// Tries to remove the first predicated value if the value exists. @@ -312,52 +305,30 @@ public bool TryRemoveFirst(Func predicate, out Exception exception) => /// The exception that occurred if the remove failed. /// The predicate to determine removal. /// True if the value was removed. False if the value did not exist. - public bool TryRemoveFirst(out Exception exception, Predicate predicate = default) + public bool TryRemoveFirst(out Exception? exception, Predicate predicate = default) where Predicate : struct, IFunc { - if (_head is null) + for (Node? node = _head, previous = null; node is not null; previous = node, node = node.Next) { - goto NonExistingValue; - } - if (predicate.Do(_head.Value)) - { - _head = _head.Next; - _count--; - exception = null; - return true; - } - Node listNode = _head; - while (!(listNode is null)) - { - if (listNode.Next is null) + if (predicate.Do(node.Value)) { - goto NonExistingValue; - } - else if (predicate.Do(listNode.Next.Value)) - { - if (listNode.Next.Equals(_tail)) + if (previous is null) + { + _head = node.Next; + } + else { - _tail = listNode; + previous.Next = node.Next; } - listNode.Next = listNode.Next.Next; _count--; exception = null; return true; } - else - { - listNode = listNode.Next; - } } - NonExistingValue: exception = new ArgumentException("Attempting to remove a non-existing value from a list."); return false; } - #endregion - - #region Stepper - /// public void Stepper(Step step = default) where Step : struct, IAction => @@ -382,7 +353,8 @@ public StepStatus StepperBreak(Step step = default) StepperRefBreak>(step); /// - public StepStatus Stepper(Func step) => StepperBreak>(step); + public StepStatus Stepper(Func step) => + StepperBreak>(step); /// public StepStatus Stepper(StepRefBreak step) => StepperRefBreak>(step); @@ -391,7 +363,7 @@ public StepStatus StepperBreak(Step step = default) public StepStatus StepperRefBreak(Step step = default) where Step : struct, IStepRefBreak { - for (Node node = _head; !(node is null); node = node.Next) + for (Node? node = _head; node is not null; node = node.Next) { T temp = node.Value; if (step.Do(ref temp) is Break) @@ -404,26 +376,18 @@ public StepStatus StepperRefBreak(Step step = default) return Continue; } - #endregion - - #region IEnumerable - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); /// Gets the enumerator for this list. /// The enumerator for this list. public System.Collections.Generic.IEnumerator GetEnumerator() { - for (Node node = _head; !(node is null); node = node.Next) + for (Node? node = _head; node is not null; node = node.Next) { yield return node.Value; } } - #endregion - - #region ToArray - /// /// Converts the list into a standard array. /// Runtime: O(n) @@ -436,25 +400,21 @@ public T[] ToArray() return Array.Empty(); } T[] array = new T[_count]; - Node node = _head; - for (int i = 0; i < _count; i++) + for (var (i, node) = (0, _head); node is not null; node = node.Next, i++) { array[i] = node.Value; - node = node.Next; } return array; } #endregion - - #endregion } /// A list implemented as a growing array. /// The type of objects to be placed in the list. public class ListArray : IList { - internal T[] _list; + internal T[] _array; internal int _count; #region Constructor @@ -474,25 +434,21 @@ public ListArray(int expectedCount) { if (expectedCount < 1) { - throw new ArgumentOutOfRangeException(nameof(expectedCount), expectedCount, "!(0 < " + nameof(expectedCount) + ")"); + throw new ArgumentOutOfRangeException(nameof(expectedCount), expectedCount, $"{nameof(expectedCount)} < 1"); } - _list = new T[expectedCount]; + _array = new T[expectedCount]; _count = 0; } - internal ListArray(ListArray listArray) + internal ListArray(ListArray list) { - _list = new T[listArray._list.Length]; - for (int i = 0; i < _list.Length; i++) - { - _list[i] = listArray._list[i]; - } - _count = listArray._count; + _array = (T[])list._array.Clone(); + _count = list._count; } - internal ListArray(T[] list, int count) + internal ListArray(T[] array, int count) { - _list = list; + _array = array; _count = count; } @@ -509,18 +465,17 @@ public T this[int index] { if (index < 0 || index > _count) { - throw new ArgumentOutOfRangeException(nameof(index), index, "!(0 <= " + nameof(index) + " <= " + nameof(Count) + "[" + _count + "])"); + throw new ArgumentOutOfRangeException(nameof(index), index, $"{nameof(index)}[{index}] < 0 || {nameof(index)}[{index}] > {nameof(Count)}[{_count}]"); } - T returnValue = _list[index]; - return returnValue; + return _array[index]; } set { if (index < 0 || index > _count) { - throw new ArgumentOutOfRangeException(nameof(index), index, "!(0 <= " + nameof(index) + " <= " + nameof(Count) + "[" + _count + "])"); + throw new ArgumentOutOfRangeException(nameof(index), index, $"{nameof(index)}[{index}] < 0 || {nameof(index)}[{index}] > {nameof(Count)}[{_count}]"); } - _list[index] = value; + _array[index] = value; } } @@ -528,20 +483,18 @@ public T this[int index] /// Gets the number of items in the list. /// Runtime: O(1) /// - public int Count { get { return this._count; } } + public int Count => _count; /// /// Gets the current capacity of the list. /// Runtime: O(1) /// - public int CurrentCapacity => _list.Length; + public int CurrentCapacity => _array.Length; #endregion #region Methods - #region Add - /// /// Tries to add a value. /// Runtime: O(n), Ω(1), ε(1) @@ -549,20 +502,21 @@ public T this[int index] /// The value to be added. /// The exception that occurrs if the add fails. /// True if the add succeds or false if not. - public bool TryAdd(T value, out Exception exception) + /// == && > / 2 + public bool TryAdd(T value, out Exception? exception) { - if (_count == _list.Length) + if (_count == _array.Length) { - if (_list.Length > int.MaxValue / 2) + if (_array.Length > int.MaxValue / 2) { - exception = new InvalidOperationException("Your list is so large that it can no longer double itself (int.MaxValue barrier reached)."); + exception = new InvalidOperationException($"{nameof(Count)} == {nameof(CurrentCapacity)} && {nameof(CurrentCapacity)} > {nameof(Int32)}.{nameof(int.MaxValue)} / 2"); return false; } - T[] newList = new T[_list.Length * 2]; - _list.CopyTo(newList, 0); - _list = newList; + T[] newList = new T[_array.Length * 2]; + _array.CopyTo(newList, 0); + _array = newList; } - _list[_count++] = value; + _array[_count++] = value; exception = null; return true; } @@ -570,54 +524,45 @@ public bool TryAdd(T value, out Exception exception) /// Adds an item at a given index. /// The item to be added. /// The index to add the item at. + /// index < 0 || index > + /// == && > / 2 public void Add(T addition, int index) { - if (_count == _list.Length) + if (index < 0 || index > _array.Length) + { + throw new ArgumentOutOfRangeException(nameof(index), index, $"{nameof(index)} < 0 || {nameof(index)} > {nameof(Count)}"); + } + if (_count == _array.Length) { - if (_list.Length > int.MaxValue / 2) + if (_array.Length > int.MaxValue / 2) { - throw new InvalidOperationException("Your list is so large that it can no longer double itself (int.MaxValue barrier reached)."); + throw new InvalidOperationException($"{nameof(Count)} == {nameof(CurrentCapacity)} && {nameof(CurrentCapacity)} > {nameof(Int32)}.{nameof(int.MaxValue)} / 2"); } - T[] newList = new T[_list.Length * 2]; - _list.CopyTo(newList, 0); - _list = newList; + T[] array = new T[_array.Length * 2]; + _array.CopyTo(array, 0); + _array = array; } for (int i = _count; i > index; i--) { - _list[i] = _list[i - 1]; + _array[i] = _array[i - 1]; } - _list[index] = addition; + _array[index] = addition; _count++; } - #endregion - - #region Clear - /// /// Empties the list back and reduces it back to its original capacity. /// Runtime: O(1) /// public void Clear() { - _list = new T[1]; + _array = new T[1]; _count = 0; } - #endregion - - #region Clone - /// Creates a shallow clone of this data structure. /// A shallow clone of this data structure. - public ListArray Clone() - { - return new ListArray(this); - } - - #endregion - - #region Remove + public ListArray Clone() => new ListArray(this); /// /// Removes the item at a specific index. @@ -627,14 +572,14 @@ public ListArray Clone() public void Remove(int index) { RemoveWithoutShrink(index); - if (_count < _list.Length / 2) + if (_count < _array.Length / 2) { - T[] newList = new T[_list.Length / 2]; + T[] newList = new T[_array.Length / 2]; for (int i = 0; i < _count; i++) { - newList[i] = _list[i]; + newList[i] = _array[i]; } - _list = newList; + _array = newList; } } @@ -643,15 +588,16 @@ public void Remove(int index) /// Runtime: Θ(n - index) /// /// The index of the item to be removed. + /// Thrown when: index < 0 || index >= _count public void RemoveWithoutShrink(int index) { if (index < 0 || index >= _count) { - throw new ArgumentOutOfRangeException(nameof(index), index, "!(0 <= " + nameof(index) + " <= " + nameof(ListArray) + "." + nameof(Count) + ")"); + throw new ArgumentOutOfRangeException(nameof(index), index, $"{nameof(index)} < 0 || {nameof(index)} >= {nameof(Count)}"); } for (int i = index; i < _count - 1; i++) { - _list[i] = _list[i + 1]; + _array[i] = _array[i + 1]; } _count--; } @@ -665,14 +611,14 @@ public void RemoveAll(Predicate predicate = default) where Predicate : struct, IFunc { RemoveAllWithoutShrink(predicate); - if (_count < _list.Length / 2) + if (_count < _array.Length / 2) { - T[] newList = new T[_list.Length / 2]; + T[] newList = new T[_array.Length / 2]; for (int i = 0; i < _count; i++) { - newList[i] = _list[i]; + newList[i] = _array[i]; } - _list = newList; + _array = newList; } } @@ -691,13 +637,13 @@ public void RemoveAllWithoutShrink(Predicate predicate = default) int removed = 0; for (int i = 0; i < _count; i++) { - if (predicate.Do(_list[i])) + if (predicate.Do(_array[i])) { removed++; } else { - _list[i - removed] = _list[i]; + _array[i - removed] = _array[i]; } } _count -= removed; @@ -708,33 +654,26 @@ public void RemoveAllWithoutShrink(Predicate predicate = default) /// Runtime: O(n), Ω(1) /// /// The predicate to determine removals. + /// Thrown when does not find a in the list. public void RemoveFirst(Func predicate) { - if (!TryRemoveFirst(predicate, out Exception exception)) + if (!TryRemoveFirst(predicate, out Exception? exception)) { - throw exception; + throw exception ?? new TowelBugException($"{nameof(TryRemoveFirst)} failed but the {nameof(exception)} is null"); } } - /// - /// Removes the first occurence of a value from the list without causing the list to shrink. - /// Runtime: O(n), Ω(1) - /// - /// The value to remove. - public void RemoveFirstWithoutShrink(T value) - { - RemoveFirstWithoutShrink(value, Equate); - } - /// /// Removes the first occurence of a value from the list without causing the list to shrink. /// Runtime: O(n), Ω(1) /// /// The value to remove. /// The delegate providing the equality check. - public void RemoveFirstWithoutShrink(T value, Func equate) + /// Thrown when is not found in the list. + public void RemoveFirstWithoutShrink(T value, Func? equate = null) { - RemoveFirstWithoutShrink(x => equate(x, value), out _); + equate ??= Equate; + RemoveFirstWithoutShrink(x => equate(x, value)); } /// @@ -742,12 +681,12 @@ public void RemoveFirstWithoutShrink(T value, Func equate) /// Runtime: O(n), Ω(1) /// /// The predicate to determine removals. - /// The exception that occured if the removal failed. - public void RemoveFirstWithoutShrink(Func predicate, out Exception exception) + /// Thrown when does not find a in the list. + public void RemoveFirstWithoutShrink(Func predicate) { - if (!TryRemoveFirst(predicate, out exception)) + if (!TryRemoveFirst(predicate, out Exception? exception)) { - throw new ArgumentException("Attempting to remove a non-existing item from this list."); + throw exception ?? new TowelBugException($"{nameof(TryRemoveFirst)} failed but the {nameof(exception)} is null"); } } @@ -755,7 +694,7 @@ public void RemoveFirstWithoutShrink(Func predicate, out Exception exce /// The predicate to determine removals. /// The exception that occured if the removal failed. /// True if the item was found and removed. False if not. - public bool TryRemoveFirst(Func predicate, out Exception exception) => + public bool TryRemoveFirst(Func predicate, out Exception? exception) => TryRemoveFirst>(out exception, predicate); /// Tries to remove the first predicated value if the value exists. @@ -763,31 +702,23 @@ public bool TryRemoveFirst(Func predicate, out Exception exception) => /// The exception that occurred if the remove failed. /// The predicate to determine removal. /// True if the value was removed. False if the value did not exist. - public bool TryRemoveFirst(out Exception exception, Predicate predicate = default) + public bool TryRemoveFirst(out Exception? exception, Predicate predicate = default) where Predicate : struct, IFunc { int i; for (i = 0; i < _count; i++) { - if (predicate.Do(_list[i])) + if (predicate.Do(_array[i])) { - break; + Remove(i); + exception = null; + return true; } } - if (i == _count) - { - exception = new ArgumentException("Attempting to remove a non-existing item from this list."); - return false; - } - Remove(i); - exception = null; - return true; + exception = new ArgumentException("Attempting to remove a non-existing item from this list."); + return false; } - #endregion - - #region Stepper - /// public void Stepper(Step step = default) where Step : struct, IAction => @@ -820,11 +751,7 @@ public StepStatus StepperBreak(Step step = default) /// public StepStatus StepperRefBreak(Step step = default) where Step : struct, IStepRefBreak => - _list.StepperRefBreak(0, _count, step); - - #endregion - - #region IEnumerable + _array.StepperRefBreak(0, _count, step); System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); @@ -834,39 +761,21 @@ public System.Collections.Generic.IEnumerator GetEnumerator() { for (int i = 0; i < _count; i++) { - yield return _list[i]; + yield return _array[i]; } } - #endregion - - #region ToArray - /// Converts the list array into a standard array. /// A standard array of all the elements. - public T[] ToArray() - { - T[] array = new T[_count]; - Array.Copy(_list, array, _count); - return array; - } - - #endregion - - #region Trim + public T[] ToArray() => + _count is 0 ? Array.Empty() : + _array.AsSpan(0, _count).ToArray(); /// Resizes this allocation to the current count. - public void Trim() - { - T[] newList = new T[_count]; - for (int i = 0; i < _count; i++) - { - newList[i] = _list[i]; - } - _list = newList; - } - - #endregion + public void Trim() => + _array = + _count is 0 ? new T[1] : + _array.AsSpan(0, _count).ToArray(); #endregion } diff --git a/Sources/Towel/DataStructures/Map.cs b/Sources/Towel/DataStructures/Map.cs index 85ee3718..7dc109e4 100644 --- a/Sources/Towel/DataStructures/Map.cs +++ b/Sources/Towel/DataStructures/Map.cs @@ -30,7 +30,7 @@ public interface IMap : IDataStructure, /// The value if found or default. /// The exception that occured if not found. /// True if the key was found or false if not. - bool TryGet(K key, out T value, out Exception exception); + bool TryGet(K key, out T value, out Exception? exception); /// Sets value in the map. /// The key of the value. /// The value to be set. @@ -40,7 +40,7 @@ public interface IMap : IDataStructure, /// The value to be added. /// The exception that occured if the add failed. /// True if the value was added or false if not. - bool TryAdd(K key, T value, out Exception exception); + bool TryAdd(K key, T value, out Exception? exception); ///// Tries to remove a key-value pair from the map. ///// The key of the key-value pair to remove. ///// The exception that occurred if the removal failed. @@ -97,7 +97,7 @@ public static bool TryAdd(this IMap map, K key, T value) => /// The value of the provided key in the map. public static void Add(this IMap map, K key, T value) { - if (!map.TryAdd(key, value, out Exception exception)) + if (!map.TryAdd(key, value, out Exception? exception)) { throw exception; } @@ -112,12 +112,10 @@ public static void Add(this IMap map, K key, T value) /// The type of keys in the map. /// The map to get the value from. /// The key of the value to get. - /// The default value to return if the value is not found. + /// The default value to return if the value is not found. /// The value if found or the defautl value. - public static T TryGet(this IMap map, K key, T Default = default) => - map.TryGet(key, out T value, out _) - ? value - : Default; + public static T TryGet(this IMap map, K key, T @default) => + map.TryGet(key, out T value, out _) ? value : @default; /// Tries to get a value in a map by key. /// The type of values in the map. @@ -137,7 +135,7 @@ public static bool TryGet(this IMap map, K key, out T value) => /// The value of the provided key in the map. public static T Get(this IMap map, K key) { - if (!map.TryGet(key, out T value, out Exception exception)) + if (!map.TryGet(key, out T value, out Exception? exception)) { throw exception; } @@ -177,7 +175,7 @@ public class MapHashLinked : IMap, internal Equate _equate; internal Hash _hash; - internal Node[] _table; + internal Node?[] _table; internal int _count; #region Node @@ -186,7 +184,14 @@ internal class Node { internal K Key; internal T Value; - internal Node Next; + internal Node? Next; + + internal Node(T value, K key, Node? next = null) + { + Value = value; + Key = key; + Next = next; + } } #endregion @@ -289,13 +294,13 @@ _equate is FuncRuntime equate /// The value to be added. /// The exception that occured if the add failed. /// True if the value was added or false if not. - public bool TryAdd(K key, T value, out Exception exception) + public bool TryAdd(K key, T value, out Exception? exception) { _ = key ?? throw new ArgumentNullException(nameof(key)); _ = value ?? throw new ArgumentNullException(nameof(value)); int hashCode = _hash.Do(key); int location = (hashCode & int.MaxValue) % _table.Length; - for (Node node = _table[location]; !(node is null); node = node.Next) + for (Node? node = _table[location]; node is not null; node = node.Next) { if (_equate.Do(node.Key, key)) { @@ -303,12 +308,10 @@ public bool TryAdd(K key, T value, out Exception exception) return false; } } - _table[location] = new Node() - { - Key = key, - Value = value, - Next = _table[location], - }; + _table[location] = new Node( + value: value, + key: key, + next: _table[location]); _count++; if (_count > _table.Length * _maxLoadFactor) { @@ -336,16 +339,14 @@ public bool TryAdd(K key, T value, out Exception exception) /// The value if found or default. /// The exception that occured if not found. /// True if the key was found or false if not. - public bool TryGet(K key, out T value, out Exception exception) + public bool TryGet(K key, out T value, out Exception? exception) { _ = key ?? throw new ArgumentNullException(nameof(key)); - // compute the hash code and relate it to the current table int hashCode = _hash.Do(key); int location = (hashCode & int.MaxValue) % _table.Length; - // look for the value - for (Node node = _table[location]; !(node is null); node = node.Next) + for (Node? node = _table[location]; node is not null; node = node.Next) { if (_equate.Do(node.Key, key)) { @@ -376,7 +377,7 @@ public void Set(K key, T value) _ = value ?? throw new ArgumentNullException(nameof(value)); int hashCode = _hash.Do(key); int location = (hashCode & int.MaxValue) % _table.Length; - for (Node node = _table[location]; !(node is null); node = node.Next) + for (Node? node = _table[location]; node is not null; node = node.Next) { if (_equate.Do(node.Key, key)) { @@ -384,12 +385,10 @@ public void Set(K key, T value) return; } } - _table[location] = new Node() - { - Key = key, - Value = value, - Next = _table[location], - }; + _table[location] = new Node( + value: value, + key: key, + next: _table[location]); _count++; if (_count > _table.Length * _maxLoadFactor) { @@ -414,7 +413,7 @@ public void Set(K key, T value) /// The key of the value to remove. /// The exception that occurred if the removal failed. /// True if the removal was successful for false if not. - public bool TryRemove(K key, out Exception exception) + public bool TryRemove(K key, out Exception? exception) { if (TryRemoveWithoutTrim(key, out exception)) { @@ -436,7 +435,7 @@ public bool TryRemove(K key, out Exception exception) /// The key of the value to remove. /// The exception that occurred if the removal failed. /// True if the removal was successful for false if not. - public bool TryRemoveWithoutTrim(K key, out Exception exception) + public bool TryRemoveWithoutTrim(K key, out Exception? exception) { _ = key ?? throw new ArgumentNullException(nameof(key)); int hashCode = _hash.Do(key); @@ -450,7 +449,7 @@ public bool TryRemoveWithoutTrim(K key, out Exception exception) } else { - for (Node node = _table[location]; !(node.Next is null); node = node.Next) + for (Node? node = _table[location]; node.Next is not null; node = node.Next) { if (_equate.Do(node.Next.Key, key)) { @@ -477,16 +476,19 @@ internal void Resize(int tableSize) { return; } - Node[] temp = _table; + + Node?[] temp = _table; _table = new Node[tableSize]; + for (int i = 0; i < temp.Length; i++) { - while (!(temp[i] is null)) + for (Node? node = temp[i]; node is not null; node = temp[i]) { - Node node = temp[i]; temp[i] = node.Next; + int hashCode = _hash.Do(node.Key); int location = (hashCode & int.MaxValue) % _table.Length; + node.Next = _table[location]; _table[location] = node; } @@ -536,7 +538,7 @@ public bool Contains(K key) { int hashCode = _hash.Do(key); int location = (hashCode & int.MaxValue) % _table.Length; - for (Node node = _table[location]; !(node is null); node = node.Next) + for (Node? node = _table[location]; node is not null; node = node.Next) { if (_equate.Do(node.Key, key)) { @@ -569,7 +571,7 @@ public void Stepper(Action step) { for (int i = 0; i < _table.Length; i++) { - for (Node node = _table[i]; !(node is null); node = node.Next) + for (Node? node = _table[i]; node is not null; node = node.Next) { step(node.Value); } @@ -581,7 +583,7 @@ public void Stepper(StepRef step) { for (int i = 0; i < _table.Length; i++) { - for (Node node = _table[i]; !(node is null); node = node.Next) + for (Node? node = _table[i]; node is not null; node = node.Next) { step(ref node.Value); } @@ -593,7 +595,7 @@ public StepStatus Stepper(Func step) { for (int i = 0; i < _table.Length; i++) { - for (Node node = _table[i]; !(node is null); node = node.Next) + for (Node? node = _table[i]; node is not null; node = node.Next) { if (step(node.Value) is Break) { @@ -609,7 +611,7 @@ public StepStatus Stepper(StepRefBreak step) { for (int i = 0; i < _table.Length; i++) { - for (Node node = _table[i]; !(node is null); node = node.Next) + for (Node? node = _table[i]; node is not null; node = node.Next) { if (step(ref node.Value) is Break) { @@ -625,7 +627,7 @@ public void Keys(Action step) { for (int i = 0; i < _table.Length; i++) { - for (Node node = _table[i]; !(node is null); node = node.Next) + for (Node? node = _table[i]; node is not null; node = node.Next) { step(node.Key); } @@ -637,7 +639,7 @@ public StepStatus Keys(Func step) { for (int i = 0; i < _table.Length; i++) { - for (Node node = _table[i]; !(node is null); node = node.Next) + for (Node? node = _table[i]; node is not null; node = node.Next) { if (step(node.Key) is Break) { @@ -653,7 +655,7 @@ public void Stepper(Action step) { for (int i = 0; i < _table.Length; i++) { - for (Node node = _table[i]; !(node is null); node = node.Next) + for (Node? node = _table[i]; node is not null; node = node.Next) { step(node.Value, node.Key); } @@ -665,7 +667,7 @@ public StepStatus Stepper(Func step) { for (int i = 0; i < _table.Length; i++) { - for (Node node = _table[i]; !(node is null); node = node.Next) + for (Node? node = _table[i]; node is not null; node = node.Next) { if (step(node.Value, node.Key) is Break) { @@ -684,7 +686,7 @@ public System.Collections.Generic.IEnumerator GetEnumerator() { for (int i = 0; i < _table.Length; i++) { - for (Node node = _table[i]; !(node is null); node = node.Next) + for (Node? node = _table[i]; node is not null; node = node.Next) { yield return node.Value; } @@ -703,12 +705,11 @@ public System.Collections.Generic.IEnumerator GetEnumerator() public T[] ToArray() { T[] array = new T[_count]; - int index = 0; - for (int i = 0; i < _table.Length; i++) + for (int i = 0, index = 0; i < _table.Length; i++) { - for (Node node = _table[i]; !(node is null); node = node.Next) + for (Node? node = _table[i]; node is not null; node = node.Next, index++) { - array[index++] = node.Value; + array[index] = node.Value; } } return array; @@ -734,8 +735,8 @@ public class MapHashLinked : MapHashLinked, /// The hashing function. /// The expected count of the map. public MapHashLinked( - Func equate = null, - Func hash = null, + Func? equate = null, + Func? hash = null, int? expectedCount = null) : base(equate ?? Statics.Equate, hash ?? DefaultHash, expectedCount) { } /// diff --git a/Sources/Towel/DataStructures/Omnitree_ND.cs b/Sources/Towel/DataStructures/Omnitree_ND.cs index 0d800c89..5d43c087 100644 --- a/Sources/Towel/DataStructures/Omnitree_ND.cs +++ b/Sources/Towel/DataStructures/Omnitree_ND.cs @@ -98,7 +98,7 @@ public enum Keyword public struct Bound { internal bool Exists; - internal T Value; + internal T? Value; /// Represents a null bound meaning it does not exist. public readonly static Bound None = new Bound { Value = default, Exists = false }; @@ -117,7 +117,7 @@ public static implicit operator Bound(Keyword keyword) => /// Gets the bound compare delegate from a value compare delegate. /// The value compare to wrap into a bounds compare. /// The bounds compare. - public static Func, Bound, CompareResult> Compare(Func compare) => + public static Func, Bound, CompareResult> Compare(Func compare) => (a, b) => a.Exists && b.Exists ? compare(a.Value, b.Value) : !b.Exists ? Equal : @@ -133,7 +133,7 @@ public static Func, Bound, CompareResult> Compare(Func public delegate A SubdivisionOverride(BoundsType bounds, Action> values); - internal static T SubDivide(Bound[] bounds, Func compare) + internal static T? SubDivide(Bound[] bounds, Func? compare) { // make sure a bound exists (not all objects are infinitely bound) bool exists = false; @@ -151,7 +151,7 @@ internal static T SubDivide(Bound[] bounds, Func comp if (!exists) return default; - SortQuick(bounds, Bound.Compare(compare)); + SortQuick(bounds, Bound.Compare(compare ?? Compare)); // after sorting, we need to find the middle-most value that exists int medianIndex = bounds.Length / 2; @@ -169,7 +169,7 @@ internal static T SubDivide(Bound[] bounds, Func comp throw new Exception("There is a bug in the Towel Framwork [SubDivide]"); } - internal static T SubDivide(ArrayJagged> bounds, Func compare) + internal static T? SubDivide(ArrayJagged> bounds, Func compare) { // make sure a bound exists (not all objects are infinitely bound) bool exists = false; @@ -217,17 +217,10 @@ public struct Vector internal object[] _location; /// The locations along each axis. - public object[] Location => _location; + public ReadOnlySpan Location => _location; /// Returns a vector with defaulted values. - public static Vector Default => new Vector(null); - - /// Constructs an N-D vector. - /// - public Vector(params object[] location) - { - _location = location.Clone() as object[]; - } + public static Vector Default => new Vector(); } /// An N-D bounding box. @@ -253,7 +246,7 @@ public static Bounds None(int dimensions) } /// A set of values denoting a range (or lack of range) along each axis. - public Bounds(Bound[] min, Bound[] max) + public Bounds(Bound[]? min, Bound[]? max) { _min = min.Clone() as Bound[]; _max = max.Clone() as Bound[]; diff --git a/Sources/Towel/DataStructures/Queue.cs b/Sources/Towel/DataStructures/Queue.cs index 1553123d..33076c8c 100644 --- a/Sources/Towel/DataStructures/Queue.cs +++ b/Sources/Towel/DataStructures/Queue.cs @@ -12,9 +12,9 @@ public interface IQueue : IDataStructure, { #region Properties - /// The newest item currently in the queue. + /// The current newest element in the queue. T Newest { get; } - /// The oldest item currently in the queue. + /// The current oldest element in the queue. T Oldest { get; } #endregion @@ -38,8 +38,8 @@ public interface IQueue : IDataStructure, /// The generic type within the structure. public class QueueLinked : IQueue { - internal Node _head; - internal Node _tail; + internal Node? _head; + internal Node? _tail; internal int _count; #region Node @@ -47,7 +47,13 @@ public class QueueLinked : IQueue internal class Node { internal T Value; - internal Node Next; + internal Node? Next; + + internal Node(T value, Node? next = null) + { + Value = value; + Next = next; + } } #endregion @@ -64,27 +70,45 @@ public QueueLinked() _count = 0; } + internal QueueLinked(QueueLinked queue) + { + if (queue._head is not null) + { + _head = new Node(value: queue._head.Value); + Node? a = queue._head.Next; + Node? b = _head; + while (a is not null) + { + b.Next = new Node(value: a.Value); + b = b.Next; + a = a.Next; + } + _tail = b; + _count = queue._count; + } + } + #endregion #region Properties /// - /// The newest item currently in the queue. + /// The current newest element in the queue. /// Runtime: O(1) /// public T Newest => - _count > 0 - ? _tail.Value - : throw new InvalidOperationException("attempting to get the newest item in an empty queue"); + _count <= 0 ? throw new InvalidOperationException("attempting to get the newest item in an empty queue") : + _tail is null ? throw new TowelBugException($"{nameof(Count)} is greater than 0 but {nameof(_tail)} is null") : + _tail.Value; /// - /// The oldest item currently in the queue. + /// The current oldest element in the queue. /// Runtime: O(1) /// public T Oldest => - _count > 0 - ? _head.Value - : throw new InvalidOperationException("attempting to get the oldet item in an empty queue"); + _count <= 0 ? throw new InvalidOperationException("attempting to get the oldet item in an empty queue") : + _head is null ? throw new TowelBugException($"{nameof(Count)} is greater than 0 but {nameof(_head)} is null") : + _head.Value; /// /// Returns the number of items in the queue. @@ -96,8 +120,6 @@ public QueueLinked() #region Methods - #region ToArray - /// /// Converts the list into a standard array. /// Runtime: O(n) @@ -105,44 +127,21 @@ public QueueLinked() /// A standard array of all the items. public T[] ToArray() { + if (_count == 0) + { + return Array.Empty(); + } T[] array = new T[_count]; - int index = 0; - for (Node current = _head; !(current is null); current = current.Next) + for (var (i, node) = (0, _head); node is not null; node = node.Next, i++) { - array[index++] = current.Value; + array[i] = node.Value; } return array; } - #endregion - - #region Clone - /// Creates a shallow clone of this data structure. /// A shallow clone of this data structure. - public QueueLinked Clone() - { - Node head = new Node { Value = _head.Value }; - Node current = _head.Next; - Node current_clone = head; - while (!(current is null)) - { - current_clone.Next = new Node { Value = current.Value }; - current_clone = current_clone.Next; - current = current.Next; - } - QueueLinked clone = new QueueLinked - { - _head = head, - _tail = current_clone, - _count = _count - }; - return clone; - } - - #endregion - - #region Enqueue + public QueueLinked Clone() => new QueueLinked(this); /// /// Adds an item to the back of the queue. @@ -153,19 +152,15 @@ public void Enqueue(T enqueue) { if (_tail is null) { - _head = _tail = new Node { Value = enqueue }; + _head = _tail = new Node(value: enqueue); } else { - _tail = _tail.Next = new Node { Value = enqueue }; + _tail = _tail.Next = new Node(value: enqueue); } _count++; } - #endregion - - #region Dequeue - /// /// Removes the oldest item in the queue. /// Runtime: O(1) @@ -187,25 +182,15 @@ public T Dequeue() return value; } - #endregion - - #region Peek - - /// Gets the next item in the queue without removing it. + /// + /// Gets the next item in the queue without removing it. + /// Runtime: O(1) + /// /// The next item in the queue. - public T Peek() - { - if (_head is null) - { - throw new InvalidOperationException("peek from an empty queue"); - } - T returnValue = _head.Value; - return returnValue; - } - - #endregion - - #region Clear + public T Peek() => + _count <= 0 ? throw new InvalidOperationException("attempting to peek an empty queue") : + _head is null ? throw new TowelBugException($"{nameof(Count)} is greater than 0 but {nameof(_head)} is null") : + _head.Value; /// /// Resets the queue to an empty state. @@ -213,14 +198,11 @@ public T Peek() /// public void Clear() { - _head = _tail = null; + _head = null; + _tail = null; _count = 0; } - #endregion - - #region Stepper - /// public void Stepper(Step step = default) where Step : struct, IAction => @@ -249,13 +231,14 @@ public StepStatus Stepper(Func step) => StepperBreak>(step); /// - public StepStatus Stepper(StepRefBreak step) => StepperRefBreak>(step); + public StepStatus Stepper(StepRefBreak step) => + StepperRefBreak>(step); /// public StepStatus StepperRefBreak(Step step = default) where Step : struct, IStepRefBreak { - for (Node current = _head; !(current is null); current = current.Next) + for (Node? current = _head; current is not null; current = current.Next) { if (step.Do(ref current.Value) is Break) { @@ -265,32 +248,29 @@ public StepStatus StepperRefBreak(Step step = default) return Continue; } - #endregion - - #region IEnumerable - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); - /// Gets the enumerator for this queue. + /// + /// Gets the enumerator for this queue. + /// Runtime: O(1) + /// /// The enumerator for the queue. public System.Collections.Generic.IEnumerator GetEnumerator() { - for (Node current = _head; !(current is null); current = current.Next) + for (Node? current = _head; current is not null; current = current.Next) { yield return current.Value; } } #endregion - - #endregion } /// Implements First-In-First-Out queue data structure using an array. /// The generic type within the structure. public class QueueArray : IQueue { - internal T[] _queue; + internal T[] _array; internal int _start; internal int _count; internal int _minimumCapacity; @@ -298,28 +278,31 @@ public class QueueArray : IQueue #region Constructors /// - /// Creates an instance of a ListArray, and sets it's minimum capacity. + /// Constructs a new queue. /// Runtime: O(1) /// - public QueueArray() - { - _queue = new T[1]; - _count = 0; - _minimumCapacity = 1; - } + public QueueArray() : this(1) { } /// - /// Creates an instance of a ListArray, and sets it's minimum capacity. + /// Constructs a new queue. /// Runtime: O(1) /// /// The initial and smallest array size allowed by this list. public QueueArray(int minimumCapacity) { - _queue = new T[minimumCapacity]; + _array = new T[minimumCapacity]; _count = 0; _minimumCapacity = minimumCapacity; } + internal QueueArray(QueueArray queue) + { + _minimumCapacity = queue._minimumCapacity; + _start = queue._start; + _count = queue._count; + _array = (T[])queue._array.Clone(); + } + #endregion #region Properties @@ -334,7 +317,7 @@ public QueueArray(int minimumCapacity) /// Gets the current capacity of the list. /// Runtime: O(1) /// - public int CurrentCapacity => _queue.Length; + public int CurrentCapacity => _array.Length; /// /// Allows you to adjust the minimum capacity of this list. @@ -343,88 +326,86 @@ public QueueArray(int minimumCapacity) /// public int MinimumCapacity { - get - { - int returnValue = _minimumCapacity; - return returnValue; - } + get => _minimumCapacity; set { if (value < 1) { - throw new InvalidOperationException("Attempting to set a minimum capacity to a negative or zero value."); + throw new ArgumentOutOfRangeException(nameof(value), value, $"{nameof(value)} < 1"); } - else if (value > _queue.Length) + if (value > _array.Length) { - T[] newList = new T[value]; - _queue.CopyTo(newList, 0); - _queue = newList; + T[] array = new T[value]; + _array.CopyTo(array, 0); + _array = array; } - else - _minimumCapacity = value; + _minimumCapacity = value; } } - /// The newest item currently in the queue. - public T Newest - { - get => _count > 0 - ? _queue[(_start + _count) % _queue.Length] - : throw new InvalidOperationException("attempting to get the newest item in an empty queue"); - } + /// + /// The current newest in the queue. + /// Runtime: O(1) + /// + /// Thrown when: _count <= 0 + public T Newest => + _count <= 0 ? throw new InvalidOperationException("attempting to get the newest item in an empty queue") : + _array[(_start + _count) % _array.Length]; + + /// + /// The current newest in the queue. + /// Runtime: O(1) + /// + /// Thrown when: _count <= 0 + public T Oldest => + _count <= 0 ? throw new InvalidOperationException("attempting to get the oldet item in an empty queue") : + _array[_start]; - /// The oldest item currently in the queue. - public T Oldest + /// + /// Gets or sets the at an index in the queue. + /// Runtime: O(1) + /// + /// The index of the to get or set. + /// The element at the provided index. + /// Thrown when: index <= 0 || index > _count + public T this[int index] { - get => _count > 0 - ? _queue[_start] - : throw new InvalidOperationException("attempting to get the oldet item in an empty queue"); + get => + index <= 0 || index > _count ? throw new ArgumentOutOfRangeException(nameof(index), index, $"!(0 <= {nameof(index)} < {nameof(Count)})") : + _array[(_start + index) % _array.Length]; + set + { + if (index <= 0 || index > _count) throw new ArgumentOutOfRangeException(nameof(index), index, $"!(0 <= {nameof(index)} < {nameof(Count)})"); + _array[(_start + index) % _array.Length] = value; + } } #endregion #region Methods - #region ToArray - - /// Converts the list array into a standard array. + /// + /// Converts the list array into a standard array. + /// Runtime: O() + /// /// A standard array of all the elements. public T[] ToArray() { + if (_count <= 0) + { + return Array.Empty(); + } T[] array = new T[_count]; - for (int i = 0; i < _count; i++) + for (int i = 0, index = _start; i < _count; i++, index = ++index >= _array.Length ? 0 : index) { - array[i] = _queue[i]; + array[i] = _array[index]; } return array; } - #endregion - - #region Clone - /// Creates a shallow clone of this data structure. /// A shallow clone of this data structure. - public IDataStructure Clone() - { - QueueArray clone = new QueueArray - { - _queue = new T[_queue.Length], - _count = this._count, - _start = this._start, - _minimumCapacity = this._minimumCapacity, - }; - T[] array = clone._queue; - for (int i = 0; i < _count; i++) - { - array[i] = _queue[i]; - } - return clone; - } - - #endregion - - #region Enqueue + public QueueArray Clone() => new QueueArray(this); /// /// Adds an item to the end of the list. @@ -433,30 +414,31 @@ public IDataStructure Clone() /// The item to be added. public void Enqueue(T addition) { - if (_count == _queue.Length) + if (_count + 1 >= _array.Length) { - if (_queue.Length > int.MaxValue / 2) + if (_array.Length > int.MaxValue / 2) { throw new InvalidOperationException("your queue is so large that it can no longer double itself (Int32.MaxValue barrier reached)."); } - T[] newQueue = new T[_queue.Length * 2]; - for (int i = 0; i < _count; i++) + T[] array = new T[_array.Length * 2]; + for (int i = 0, index = _start; i < _count; i++, index = ++index >= _array.Length ? 0 : index) { - newQueue[i] = _queue[(i + _start) % _queue.Length]; + array[i] = _array[index]; } _start = 0; - _queue = newQueue; + _array = array; + } + int end = _start + _count++; + if (end >= _array.Length) + { + end -= _array.Length - _start; } - _queue[(_start + _count++) % _queue.Length] = addition; + _array[end] = addition; } - #endregion - - #region Dequeue - /// /// Removes the item at a specific index. - /// Runtime: O(n - index) + /// Runtime: O(n), ε(1) /// public T Dequeue() { @@ -464,55 +446,39 @@ public T Dequeue() { throw new InvalidOperationException("attempting to queue from an empty queue."); } - if (_count < _queue.Length / 4 && _queue.Length / 2 > _minimumCapacity) + if (_count < _array.Length / 4 && _array.Length > _minimumCapacity) { - T[] newQueue = new T[_queue.Length / 2]; - for (int i = 0; i < _count; i++) + int length = Math.Max(_minimumCapacity, _array.Length / 2); + T[] array = new T[length]; + for (int i = 0, index = _start; i < _count; i++, index = ++index >= _array.Length ? 0 : index) { - newQueue[i] = _queue[(i + _start) % _queue.Length]; + array[i] = _array[index]; } _start = 0; - _queue = newQueue; + _array = array; } - T returnValue = _queue[_start++]; + T element = _array[_start]; + _start = ++_start >= _array.Length ? _start : 0; _count--; - if (_count == 0) - { - _start = 0; - } - return returnValue; + return element; } - #endregion - - #region Peek - /// Gets the next item in the queue without removing it. /// The next item in the queue. - public T Peek() - { - T returnValue = _queue[_start]; - return returnValue; - } - - #endregion - - #region Clear + public T Peek() => + _count <= 0 ? throw new InvalidOperationException("attempting to peek an empty queue") : + _array[_start]; /// - /// Empties the list back and reduces it back to its original capacity. + /// Returns the queue to an empty state. /// Runtime: O(1) /// public void Clear() { - _queue = new T[_minimumCapacity]; _count = 0; + _start = 0; } - #endregion - - #region Stepper - /// public void Stepper(Step step = default) where Step : struct, IAction => @@ -548,13 +514,9 @@ public StepStatus Stepper(StepRefBreak step) => public StepStatus StepperRefBreak(Step step = default) where Step : struct, IStepRefBreak { - for (int i = 0, index = _start; i < _count; i++, index++) + for (int i = 0, index = _start; i < _count; i++, index = ++index >= _array.Length ? 0 : index) { - if (index == _queue.Length) - { - index = 0; - } - if (step.Do(ref _queue[index]) is Break) + if (step.Do(ref _array[index]) is Break) { return Break; } @@ -562,10 +524,6 @@ public StepStatus StepperRefBreak(Step step = default) return Continue; } - #endregion - - #region IEnumerable - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); /// Gets the enumerator for this queue. @@ -574,16 +532,14 @@ public System.Collections.Generic.IEnumerator GetEnumerator() { for (int i = 0, index = _start; i < _count; i++, index++) { - if (index == _queue.Length) + if (index == _array.Length) { index = 0; } - yield return _queue[index]; + yield return _array[index]; } } #endregion - - #endregion } } diff --git a/Sources/Towel/DataStructures/Set.cs b/Sources/Towel/DataStructures/Set.cs index 6962fa07..03df6775 100644 --- a/Sources/Towel/DataStructures/Set.cs +++ b/Sources/Towel/DataStructures/Set.cs @@ -31,7 +31,7 @@ public class SetHashLinked : ISet, internal Equate _equate; internal Hash _hash; - internal Node[] _table; + internal Node?[] _table; internal int _count; #region Node @@ -39,7 +39,13 @@ public class SetHashLinked : ISet, internal class Node { internal T Value; - internal Node Next; + internal Node? Next; + + internal Node(T value, Node? next = null) + { + Value = value; + Next = next; + } } #endregion @@ -135,16 +141,14 @@ _equate is FuncRuntime func /// /// The value to add to the set. /// The exception that occurred if the add failed. - public bool TryAdd(T value, out Exception exception) + public bool TryAdd(T value, out Exception? exception) { _ = value ?? throw new ArgumentNullException(nameof(value)); - // compute the hash code and relate it to the current table int hashCode = _hash.Do(value); int location = (hashCode & int.MaxValue) % _table.Length; - // duplicate value check - for (Node node = _table[location]; !(node is null); node = node.Next) + for (Node? node = _table[location]; node is not null; node = node.Next) { if (_equate.Do(node.Value, value)) { @@ -153,16 +157,10 @@ public bool TryAdd(T value, out Exception exception) } } - { - // add the value - Node node = new Node { Value = value, Next = _table[location] }; - _table[location] = node; - } + _table[location] = new Node(value: value, next: _table[location]); - // check if the table needs to grow if (++_count > _table.Length * _maxLoadFactor) { - // calculate new table size float tableSizeFloat = (_count * 2) * (1 / _maxLoadFactor); if (tableSizeFloat <= int.MaxValue) { @@ -171,8 +169,6 @@ public bool TryAdd(T value, out Exception exception) { tableSize++; } - - // resize the table Resize(tableSize); } } @@ -189,7 +185,7 @@ public bool TryAdd(T value, out Exception exception) /// The value to remove. /// The exception that occurred if the remove failed. /// True if the remove was successful or false if not. - public bool TryRemove(T value, out Exception exception) + public bool TryRemove(T value, out Exception? exception) { if (TryRemoveWithoutTrim(value, out exception)) { @@ -214,39 +210,30 @@ public bool TryRemove(T value, out Exception exception) /// The value to remove. /// The exception that occurred if the remove failed. /// True if the remove was successful or false if not. - public bool TryRemoveWithoutTrim(T value, out Exception exception) + public bool TryRemoveWithoutTrim(T value, out Exception? exception) { _ = value ?? throw new ArgumentNullException(nameof(value)); - - // compute the hash code and relate it to the current table int hashCode = _hash.Do(value); int location = (hashCode & int.MaxValue) % _table.Length; - - // find and remove the node - if (_equate.Do(_table[location].Value, value)) - { - // the value was the head node of the table index - _table[location] = _table[location].Next; - _count--; - exception = null; - return true; - } - else + for (Node? node = _table[location], previous = null; node is not null; previous = node, node = node.Next) { - // that value is a child node of the table index - for (Node node = _table[location]; !(node.Next is null); node = node.Next) + if (_equate.Do(node.Value, value)) { - if (_equate.Do(node.Next.Value, value)) + if (previous is null) { - node.Next = node.Next.Next; - _count--; - exception = null; - return true; + _table[location] = node.Next; } + else + { + previous.Next = node.Next; + } + _count--; + exception = null; + return true; } - exception = new ArgumentException("Attempting to remove a value that is no in a set.", nameof(value)); - return false; } + exception = new ArgumentException("Attempting to remove a value that is no in a set.", nameof(value)); + return false; } #endregion @@ -257,29 +244,23 @@ public bool TryRemoveWithoutTrim(T value, out Exception exception) /// The desired size of the table. internal void Resize(int tableSize) { - // ensure the desired size is different than the current if (tableSize == _table.Length) { return; } - Node[] temp = _table; + Node?[] temp = _table; _table = new Node[tableSize]; - // iterate through all the values for (int i = 0; i < temp.Length; i++) { - while (!(temp[i] is null)) + for (Node? node = temp[i]; node is not null; node = temp[i]) { - // grab the value from the old table - Node node = temp[i]; temp[i] = node.Next; - // compute the hash code and relate it to the current table int hashCode = _hash.Do(node.Value); int location = (hashCode & int.MaxValue) % _table.Length; - // add the value to the new table node.Next = _table[location]; _table[location] = node; } @@ -327,12 +308,10 @@ public void Trim() /// True if the value has been added to the set or false if not. public bool Contains(T value) { - // compute the hash code and relate it to the current table int hashCode = _hash.Do(value); int location = (hashCode & int.MaxValue) % _table.Length; - // look for the value - for (Node node = _table[location]; !(node is null); node = node.Next) + for (Node? node = _table[location]; node is not null; node = node.Next) { if (_equate.Do(node.Value, value)) { @@ -365,7 +344,7 @@ public void Stepper(Action step) { for (int i = 0; i < _table.Length; i++) { - for (Node node = _table[i]; !(node is null); node = node.Next) + for (Node? node = _table[i]; node is not null; node = node.Next) { step(node.Value); } @@ -377,7 +356,7 @@ public StepStatus Stepper(Func step) { for (int i = 0; i < _table.Length; i++) { - for (Node node = _table[i]; !(node is null); node = node.Next) + for (Node? node = _table[i]; node is not null; node = node.Next) { if (step(node.Value) is Break) { @@ -396,7 +375,7 @@ public System.Collections.Generic.IEnumerator GetEnumerator() { for (int i = 0; i < _table.Length; i++) { - for (Node node = _table[i]; !(node is null); node = node.Next) + for (Node? node = _table[i]; node is not null; node = node.Next) { yield return node.Value; } @@ -409,18 +388,17 @@ public System.Collections.Generic.IEnumerator GetEnumerator() /// /// Puts all the values in this set into an array. - /// Runtime: Θ(n) + /// Runtime: Θ( + ) /// /// An array with all the values in the set. - public T[] ToArray() + public T?[] ToArray() { T[] array = new T[_count]; - int index = 0; - for (int i = 0; i < _table.Length; i++) + for (int i = 0, index = 0; i < _table.Length; i++) { - for (Node node = _table[i]; !(node is null); node = node.Next) + for (Node? node = _table[i]; node is not null; node = node.Next, index++) { - array[index++] = node.Value; + array[index] = node.Value; } } return array; @@ -445,8 +423,8 @@ public class SetHashLinked : SetHashLinked, FuncRu /// The hashing function. /// The expected count of the set. public SetHashLinked( - Func equate = null, - Func hash = null, + Func? equate = null, + Func? hash = null, int? expectedCount = null) : base(equate ?? Statics.Equate, hash ?? DefaultHash, expectedCount) { } /// @@ -541,8 +519,8 @@ public class Set : ISet, /// The expected count of the set. public Set( StructureFactory factory, - Func equate = null, - Func hash = null, + Func? equate = null, + Func? hash = null, int? expectedCount = null) { if (expectedCount.HasValue && expectedCount.Value > 0) @@ -626,7 +604,7 @@ internal Set(Set set, StructureClone clone) /// /// The key value to use as the look-up reference in the hash table. /// The exception that occurred if the add failed. - public bool TryAdd(T value, out Exception exception) + public bool TryAdd(T value, out Exception? exception) { _ = value ?? throw new ArgumentNullException(nameof(value)); @@ -681,7 +659,7 @@ public bool TryAdd(T value, out Exception exception) /// /// The value to remove. /// The exception that occurred if the remove failed. - public bool TryRemove(T value, out Exception exception) + public bool TryRemove(T value, out Exception? exception) { if (TryRemoveWithoutTrim(value, out exception)) { @@ -708,7 +686,7 @@ public bool TryRemove(T value, out Exception exception) /// /// The value to remove. /// The exception that occurred if the remove failed. - public bool TryRemoveWithoutTrim(T value, out Exception exception) + public bool TryRemoveWithoutTrim(T value, out Exception? exception) { _ = value ?? throw new ArgumentNullException(nameof(value)); @@ -828,11 +806,11 @@ public void Trim() #region Stepper And IEnumerable /// - public void Stepper(Action step) + public void Stepper(Action step) { for (int i = 0; i < _table.Length; i++) { - if (!(_table[i] is null)) + if (_table[i] is not null) { _table[i].Stepper(step); } @@ -840,11 +818,11 @@ public void Stepper(Action step) } /// - public StepStatus Stepper(Func step) + public StepStatus Stepper(Func step) { for (int i = 0; i < _table.Length; i++) { - if (!(_table[i] is null)) + if (_table[i] is not null) { if (_table[i].Stepper(step) is Break) { @@ -859,11 +837,11 @@ public StepStatus Stepper(Func step) /// Gets the enumerator for the set. /// The enumerator for the set. - public System.Collections.Generic.IEnumerator GetEnumerator() + public System.Collections.Generic.IEnumerator GetEnumerator() { for (int i = 0; i < _table.Length; i++) { - if (!(_table[i] is null)) + if (_table[i] is not null) { foreach (T value in _table[i]) { @@ -882,13 +860,13 @@ public System.Collections.Generic.IEnumerator GetEnumerator() /// Runtime: Θ(n) /// /// An array with all the values in the set. - public T[] ToArray() + public T?[] ToArray() { - T[] array = new T[_count]; + T?[] array = new T[_count]; int index = 0; for (int i = 0; i < _table.Length; i++) { - if (!(_table[i] is null)) + if (_table[i] is not null) { _table[i].Stepper(x => array[index++] = x); } diff --git a/Sources/Towel/DataStructures/SortedBinaryTree.cs b/Sources/Towel/DataStructures/SortedBinaryTree.cs index c120982b..f3e31581 100644 --- a/Sources/Towel/DataStructures/SortedBinaryTree.cs +++ b/Sources/Towel/DataStructures/SortedBinaryTree.cs @@ -31,12 +31,12 @@ public interface ISortedBinaryTree : IDataStructure, /// The value if found or default. /// The exception that occurred if the get failed. /// True if the value was found or false if not. - bool TryGet(Func sift, out T value, out Exception exception); + bool TryGet(Func sift, out T value, out Exception? exception); /// Tries to remove a value. /// The compare delegate. This must match the compare delegate of the tree. /// The exception that occurred if the remove failed. /// True if the remove succeeded or false if not. - bool TryRemove(Func sift, out Exception exception); + bool TryRemove(Func sift, out Exception? exception); /// Invokes a delegate for each entry in the data structure (left to right). /// The delegate to invoke on each item in the structure. void Stepper(StepRef step); @@ -294,8 +294,8 @@ public static bool TryGet(this ISortedBinaryTree tree, FuncThe tree to get the value from. /// The compare delegate. This must match the compare that the Red-Black tree is sorted with. /// The value. - public static T Get(this ISortedBinaryTree tree, Func sift) => - tree.TryGet(sift, out T value, out Exception exception) + public static T? Get(this ISortedBinaryTree tree, Func sift) => + tree.TryGet(sift, out T value, out Exception? exception) ? value : throw exception; @@ -313,7 +313,7 @@ public static bool TryRemove(this ISortedBinaryTree tree, FuncThe compare delegate. public static void Remove(this ISortedBinaryTree tree, Func sift) { - if (!tree.TryRemove(sift, out Exception exception)) + if (!tree.TryRemove(sift, out Exception? exception)) { throw exception; } diff --git a/Sources/Towel/DataStructures/Stack.cs b/Sources/Towel/DataStructures/Stack.cs index 9ab588b7..fe7548cc 100644 --- a/Sources/Towel/DataStructures/Stack.cs +++ b/Sources/Towel/DataStructures/Stack.cs @@ -30,7 +30,7 @@ public interface IStack : IDataStructure, /// The generic type within the structure. public class StackLinked : IStack { - internal Node _top; + internal Node? _top; internal int _count; #region Node @@ -38,7 +38,13 @@ public class StackLinked : IStack internal class Node { internal T Value; - internal Node Down; + internal Node? Down; + + internal Node(T value, Node? down = null) + { + Value = value; + Down = down; + } } #endregion @@ -55,6 +61,23 @@ public StackLinked() _count = 0; } + internal StackLinked(StackLinked stack) + { + if (stack._top is not null) + { + _top = new Node(value: stack._top.Value); + Node? a = stack._top.Down; + Node? b = _top; + while (a is not null) + { + b.Down = new Node(value: a.Value); + b = b.Down; + a = a.Down; + } + _count = stack._count; + } + } + #endregion #region Properties @@ -69,59 +92,29 @@ public StackLinked() #region Methods - #region Clone - /// Creates a shallow clone of this data structure. /// A shallow clone of this data structure. - public StackLinked Clone() - { - StackLinked clone = new StackLinked(); - if (_count == 0) - { - return clone; - } - Node copying = _top; - Node cloneTop = new Node { Value = _top.Value }; - Node cloning = cloneTop; - while (!(copying is null)) - { - copying = copying.Down; - cloning.Down = new Node { Value = _top.Value }; - cloning = cloning.Down; - } - clone._top = cloneTop; - return clone; - } - - #endregion - - #region ToArray + public StackLinked Clone() => new StackLinked(this); /// /// Converts the structure into an array. /// Runtime: Θ(n) /// /// An array containing all the item in the structure. - public T[] ToArray() + public T?[] ToArray() { if (_count == 0) { - return null; + return Array.Empty(); } T[] array = new T[_count]; - Node node = _top; - for (int i = 0; i < _count; i++) + for (var (i, node) = (0, _top); node is not null; node = node.Down, i++) { array[i] = node.Value; - node = node.Down; } return array; } - #endregion - - #region Push - /// /// Adds an item to the top of the stack. /// Runtime: O(1) @@ -129,14 +122,10 @@ public T[] ToArray() /// The item to add to the stack. public void Push(T addition) { - _top = new Node { Value = addition, Down = _top }; + _top = new Node(value: addition, down: _top); _count++; } - #endregion - - #region Peek - /// /// Returns the most recent addition to the stack. /// Runtime: O(1) @@ -146,16 +135,12 @@ public T Peek() { if (_top is null) { - throw new System.InvalidOperationException("Attempting to remove from an empty queue."); + throw new InvalidOperationException("Attempting to remove from an empty queue."); } T peek = _top.Value; return peek; } - #endregion - - #region Pop - /// /// Removes and returns the most recent addition to the stack. /// Runtime: O(1) @@ -167,16 +152,16 @@ public T Pop() { throw new InvalidOperationException("attempting to pop from an empty stack."); } - T x = _top.Value; + if (_top is null) + { + throw new TowelBugException($"{nameof(Count)} is greater than 0 but {nameof(_top)} is null"); + } + T pop = _top.Value; _top = _top.Down; _count--; - return x; + return pop; } - #endregion - - #region Clear - /// /// Clears the stack to an empty state. /// Runtime: O(1) @@ -187,10 +172,6 @@ public void Clear() _count = 0; } - #endregion - - #region Stepper - /// public void Stepper(Step step = default) where Step : struct, IAction => @@ -215,16 +196,18 @@ public StepStatus StepperBreak(Step step = default) StepperRefBreak>(step); /// - public StepStatus Stepper(Func step) => StepperBreak>(step); + public StepStatus Stepper(Func step) => + StepperBreak>(step); /// - public StepStatus Stepper(StepRefBreak step) => StepperRefBreak>(step); + public StepStatus Stepper(StepRefBreak step) => + StepperRefBreak>(step); /// public StepStatus StepperRefBreak(Step step = default) where Step : struct, IStepRefBreak { - for (Node node = _top; !(node is null); node = node.Down) + for (Node? node = _top; node is not null; node = node.Down) { if (step.Do(ref node.Value) is Break) { @@ -234,25 +217,19 @@ public StepStatus StepperRefBreak(Step step = default) return Continue; } - #endregion - - #region IEnumerable - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); /// Gets the enumerator for this stack. /// The enumerator for this stack. public System.Collections.Generic.IEnumerator GetEnumerator() { - for (Node node = _top; !(node is null); node = node.Down) + for (Node? node = _top; node is not null; node = node.Down) { yield return node.Value; } } #endregion - - #endregion } /// Implements a First-In-Last-Out stack data structure using an array. @@ -271,12 +248,7 @@ public class StackArray : IStack /// Creates an instance of a ListArray, and sets it's minimum capacity. /// Runtime: O(1) /// - public StackArray() - { - _array = new T[1]; - _count = 0; - _minimumCapacity = DefaultMinimumCapacity; - } + public StackArray() : this(DefaultMinimumCapacity) { } /// /// Creates an instance of a ListArray, and sets it's minimum capacity. @@ -297,6 +269,13 @@ internal StackArray(T[] array, int count, int minimumCapacity = DefaultMinimumCa _minimumCapacity = minimumCapacity; } + internal StackArray(StackArray stack) + { + _array = (T[])stack._array.Clone(); + _count = stack._count; + _minimumCapacity = stack._minimumCapacity; + } + #endregion #region Properties @@ -309,15 +288,12 @@ internal StackArray(T[] array, int count, int minimumCapacity = DefaultMinimumCa /// /// Allows you to adjust the minimum capacity of this list. - /// Runtime: O(n), Ω(1) + /// Runtime (get): O(1) + /// Runtime (set): O(n), Ω(1) /// public int MinimumCapacity { - get - { - int returnValue = _minimumCapacity; - return returnValue; - } + get => _minimumCapacity; set { if (value < 1) @@ -330,10 +306,7 @@ public int MinimumCapacity _array.CopyTo(newList, 0); _array = newList; } - else - { - _minimumCapacity = value; - } + _minimumCapacity = value; } } @@ -347,31 +320,13 @@ public int MinimumCapacity #region Methods - #region Clone - /// Creates a shallow clone of this data structure. /// A shallow clone of this data structure. - public StackArray Clone() => new StackArray((T[])_array.Clone(), _count, _minimumCapacity); - - #endregion - - #region ToArray + public StackArray Clone() => new StackArray(this); /// Converts the list array into a standard array. /// A standard array of all the elements. - public T[] ToArray() - { - T[] array = new T[_count]; - for (int i = 0; i < _count; i++) - { - array[i] = _array[i]; - } - return array; - } - - #endregion - - #region Push + public T[] ToArray() => _array.AsSpan(0, _count).ToArray(); /// /// Adds an item to the end of the list. @@ -396,10 +351,6 @@ public void Push(T addition) _array[_count++] = addition; } - #endregion - - #region Pop - /// /// Removes the item at a specific index. /// Runtime: O(Count), Ω(1), ε(1) @@ -423,10 +374,6 @@ public T Pop() return returnValue; } - #endregion - - #region Peek - /// /// Returns the most recent addition to the stack. /// Runtime: O(1) @@ -434,10 +381,6 @@ public T Pop() /// The most recent addition to the stack. public T Peek() => _array[_count - 1]; - #endregion - - #region Clear - /// /// Empties the list back and reduces it back to its original capacity. /// Runtime: O(1) @@ -448,10 +391,6 @@ public void Clear() _count = 0; } - #endregion - - #region Stepper - /// public void Stepper(Step step = default) where Step : struct, IAction => @@ -486,10 +425,6 @@ public StepStatus StepperRefBreak(Step step = default) where Step : struct, IStepRefBreak => _array.StepperRefBreak(0, _count, step); - #endregion - - #region IEnumerable - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); /// Gets the enumerator for this stack. @@ -503,7 +438,5 @@ public System.Collections.Generic.IEnumerator GetEnumerator() } #endregion - - #endregion } } diff --git a/Sources/Towel/DataStructures/Trie.cs b/Sources/Towel/DataStructures/Trie.cs index 60288629..6220a3c1 100644 --- a/Sources/Towel/DataStructures/Trie.cs +++ b/Sources/Towel/DataStructures/Trie.cs @@ -111,7 +111,7 @@ public class TrieLinkedHashLinked : ITrie, internal class Node { - internal MapHashLinked Map; + internal MapHashLinked? Map; internal bool IsLeaf; internal int Count; } @@ -123,7 +123,7 @@ internal class Node /// Constructs a new trie that uses linked hash tables of linked lists. /// The equality delegate for the keys. /// The hashing function for the keys. - public TrieLinkedHashLinked(Func equate = null, Func hash = null) + public TrieLinkedHashLinked(Func? equate = null, Func? hash = null) { _count = 0; _map = new MapHashLinked( @@ -152,7 +152,7 @@ public TrieLinkedHashLinked(Func equate = null, Func hash = /// The relative keys of the value. /// The exception that occurred if the add failed. /// True if the value was added or false if not. - public bool TryAdd(Action> stepper, out Exception exception) + public bool TryAdd(Action> stepper, out Exception? exception) { if (stepper is null) { @@ -160,10 +160,10 @@ public bool TryAdd(Action> stepper, out Exception exception) return false; } IStack stack = new StackLinked(); - Node node = null; + Node? node = null; stepper(key => { - MapHashLinked map = node is null + MapHashLinked? map = node is null ? _map : node.Map; if (map.Contains(key)) @@ -206,7 +206,7 @@ public bool TryAdd(Action> stepper, out Exception exception) /// The relative keys of the value. /// The exception that occurred if the remove failed. /// True if the remove was successful or false if not. - public bool TryRemove(Action> stepper, out Exception exception) + public bool TryRemove(Action> stepper, out Exception? exception) { if (stepper is null) { @@ -215,9 +215,9 @@ public bool TryRemove(Action> stepper, out Exception exception) } IStack<(T, MapHashLinked, Node)> pathStack = new StackLinked<(T, MapHashLinked, Node)>(); T finalKey = default; - MapHashLinked finalMap = null; - Node node = null; - Exception capturedException = null; + MapHashLinked? finalMap = null; + Node? node = null; + Exception? capturedException = null; stepper(key => { finalKey = key; @@ -281,7 +281,7 @@ public bool TryRemove(Action> stepper, out Exception exception) public bool Contains(Action> stepper) { _ = stepper ?? throw new ArgumentNullException(nameof(stepper)); - Node node = null; + Node? node = null; bool contains = true; stepper(key => { @@ -291,7 +291,7 @@ public bool Contains(Action> stepper) } else { - MapHashLinked map = node is null + MapHashLinked? map = node is null ? _map : node.Map; if (map.Contains(key)) @@ -448,7 +448,7 @@ public class TrieLinkedHashLinked : ITrie, internal class Node { - internal MapHashLinked Map; + internal MapHashLinked? Map; internal D Value; internal bool HasValue; internal int Count; @@ -461,7 +461,7 @@ internal class Node /// Constructs a new trie that uses linked hash tables of linked lists. /// The equality delegate for the keys. /// The hashing function for the keys. - public TrieLinkedHashLinked(Func equate = null, Func hash = null) + public TrieLinkedHashLinked(Func? equate = null, Func? hash = null) { _count = 0; _map = new MapHashLinked( @@ -499,10 +499,10 @@ public bool TryAdd(D value, Action> stepper, out Exception exception) return false; } IStack stack = new StackLinked(); - Node node = null; + Node? node = null; stepper(key => { - MapHashLinked map = node is null + MapHashLinked? map = node is null ? _map : node.Map; if (map.Contains(key)) @@ -547,7 +547,7 @@ public bool TryAdd(D value, Action> stepper, out Exception exception) /// The value if found. /// The exception that occurred if the get failed. /// True if the remove was successful or false if not. - public bool TryGet(Action> stepper, out D value, out Exception exception) + public bool TryGet(Action> stepper, out D value, out Exception? exception) { if (stepper is null) { @@ -555,10 +555,10 @@ public bool TryGet(Action> stepper, out D value, out Exception excepti exception = new ArgumentNullException(nameof(stepper)); return false; } - Node node = null; + Node? node = null; stepper(key => { - MapHashLinked map = node is null + MapHashLinked? map = node is null ? _map : node.Map; if (map.Contains(key)) @@ -600,7 +600,7 @@ public bool TryGet(Action> stepper, out D value, out Exception excepti /// The relative keys of the value. /// The exception that occurred if the remove failed. /// True if the remove was successful or false if not. - public bool TryRemove(Action> stepper, out Exception exception) + public bool TryRemove(Action> stepper, out Exception? exception) { if (stepper is null) { @@ -609,9 +609,9 @@ public bool TryRemove(Action> stepper, out Exception exception) } IStack<(T, MapHashLinked, Node)> pathStack = new StackLinked<(T, MapHashLinked, Node)>(); T finalKey; - MapHashLinked finalMap; - Node node = null; - Exception capturedException = null; + MapHashLinked? finalMap; + Node? node = null; + Exception? capturedException = null; stepper(key => { finalKey = key; @@ -675,7 +675,7 @@ public bool TryRemove(Action> stepper, out Exception exception) public bool Contains(Action> stepper) { _ = stepper ?? throw new ArgumentNullException(nameof(stepper)); - Node node = null; + Node? node = null; bool contains = true; stepper(key => { @@ -685,7 +685,7 @@ public bool Contains(Action> stepper) } else { - MapHashLinked map = node is null + MapHashLinked? map = node is null ? _map : node.Map; if (map.Contains(key)) diff --git a/Sources/Towel/Extensions.cs b/Sources/Towel/Extensions.cs index 210bdf9f..9444ad7f 100644 --- a/Sources/Towel/Extensions.cs +++ b/Sources/Towel/Extensions.cs @@ -1101,7 +1101,7 @@ internal static class ToEnglishWordsDefinitions { internal static string[] Digit = { - /* 0 */ null, + /* 0 */ null!, /* 1 */ "One", /* 2 */ "Two", /* 3 */ "Three", @@ -1115,7 +1115,7 @@ internal static class ToEnglishWordsDefinitions internal static string[] FractionalSufix = { - /* 0 */ null, + /* 0 */ null!, /* 1 */ "Tenths", /* 2 */ "Hundredths", /* 3 */ "Thousandths", @@ -1149,7 +1149,7 @@ internal static class ToEnglishWordsDefinitions internal static string[] Ten = { - /* 0 */ null, + /* 0 */ null!, /* 1 */ "Ten", /* 2 */ "Twenty", /* 3 */ "Thirty", @@ -1163,7 +1163,7 @@ internal static class ToEnglishWordsDefinitions internal static string[] Teen = { - /* 0 */ null, + /* 0 */ null!, /* 1 */ "Eleven", /* 2 */ "Twelve", /* 3 */ "Thirteen", @@ -1177,8 +1177,8 @@ internal static class ToEnglishWordsDefinitions internal static string[] Group = { - /* 0 */ null, - /* 1 */ null, + /* 0 */ null!, + /* 1 */ null!, /* 2 */ "Thousand", /* 3 */ "Million", /* 4 */ "Billion", @@ -1659,7 +1659,7 @@ public static Action> EveryNth(this Action> stepper, int /// An equality function for the data /// A hashing function for the data. /// True if the data contains duplicates. False if not. - public static bool ContainsDuplicates(this Func, StepStatus> stepper, Func equate, Func hash) + public static bool ContainsDuplicates(this Func, StepStatus> stepper, Func? equate = null, Func? hash = null) { bool duplicateFound = false; SetHashLinked set = new SetHashLinked(equate, hash); @@ -1686,7 +1686,7 @@ public static bool ContainsDuplicates(this Func, StepStat /// A hashing function for the data. /// True if the data contains duplicates. False if not. /// Use the StepperBreak overload if possible. It is more effiecient. - public static bool ContainsDuplicates(this Action> stepper, Func equate, Func hash) + public static bool ContainsDuplicates(this Action> stepper, Func? equate = null, Func? hash = null) { bool duplicateFound = false; SetHashLinked set = new SetHashLinked(equate, hash); diff --git a/Sources/Towel/Meta.cs b/Sources/Towel/Meta.cs index 6a832c92..d45ff423 100644 --- a/Sources/Towel/Meta.cs +++ b/Sources/Towel/Meta.cs @@ -84,30 +84,29 @@ public static MethodInfo GetMethod(this Type declaringType) /// Gets the TryParse on a type if it exists [ TryParse(, out )]. /// The type of the out parameter. /// The TryParse if found or null if not. - public static MethodInfo GetTryParseMethod() => GetTryParseMethodCache.Value; + public static MethodInfo? GetTryParseMethod() => GetTryParseMethodCache.Value; /// Gets the TryParse on a type if it exists [ TryParse(, out )]. /// The type of the out parameter. /// The TryParse if found or null if not. - public static MethodInfo GetTryParseMethod(Type a) + public static MethodInfo? GetTryParseMethod(Type a) { _ = a ?? throw new ArgumentNullException(nameof(a)); - MethodInfo methodInfo = a.GetMethod("TryParse", + MethodInfo? methodInfo = a.GetMethod("TryParse", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Ɐ(typeof(string), a.MakeByRefType()), null); - return !(methodInfo is null) - && methodInfo.ReturnType == typeof(bool) - ? methodInfo - : null; + return methodInfo is not null && methodInfo.ReturnType == typeof(bool) + ? methodInfo + : null; } internal static class GetTryParseMethodCache { - internal static readonly MethodInfo Value = GetTryParseMethod(typeof(A)); + internal static readonly MethodInfo? Value = GetTryParseMethod(typeof(A)); } #endregion @@ -117,30 +116,29 @@ internal static class GetTryParseMethodCache /// Gets the Factorial on a type if it exists [ Factorial()]. /// The type of the out parameter. /// The IsPrime if found or null if not. - public static MethodInfo GetFactorialMethod() => GetFactorialMethodCache.Value; + public static MethodInfo? GetFactorialMethod() => GetFactorialMethodCache.Value; /// Gets the Factorial on a type if it exists [ Factorial()]. /// The type of the out parameter. /// The IsNonNegative if found or null if not. - public static MethodInfo GetFactorialMethod(Type a) + public static MethodInfo? GetFactorialMethod(Type a) { _ = a ?? throw new ArgumentNullException(nameof(a)); - MethodInfo methodInfo = a.GetMethod("Factorial", + MethodInfo? methodInfo = a.GetMethod("Factorial", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Ɐ(a), null); - return !(methodInfo is null) - && methodInfo.ReturnType == typeof(bool) + return methodInfo is not null && methodInfo.ReturnType == typeof(bool) ? methodInfo : null; } internal static class GetFactorialMethodCache { - internal static readonly MethodInfo Value = GetFactorialMethod(typeof(A)); + internal static readonly MethodInfo? Value = GetFactorialMethod(typeof(A)); } #endregion @@ -150,30 +148,29 @@ internal static class GetFactorialMethodCache /// Gets the IsPrime on a type if it exists [ IsPrime()]. /// The type of the out parameter. /// The IsPrime if found or null if not. - public static MethodInfo GetIsPrimeMethod() => GetIsPrimeMethodCache.Value; + public static MethodInfo? GetIsPrimeMethod() => GetIsPrimeMethodCache.Value; /// Gets the IsPrime on a type if it exists [ IsPrime()]. /// The type of the out parameter. /// The IsNonNegative if found or null if not. - public static MethodInfo GetIsPrimeMethod(Type a) + public static MethodInfo? GetIsPrimeMethod(Type a) { _ = a ?? throw new ArgumentNullException(nameof(a)); - MethodInfo methodInfo = a.GetMethod("IsPrime", + MethodInfo? methodInfo = a.GetMethod("IsPrime", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Ɐ(a), null); - return !(methodInfo is null) - && methodInfo.ReturnType == typeof(bool) - ? methodInfo - : null; + return methodInfo is not null && methodInfo.ReturnType == typeof(bool) + ? methodInfo + : null; } internal static class GetIsPrimeMethodCache { - internal static readonly MethodInfo Value = GetIsPrimeMethod(typeof(A)); + internal static readonly MethodInfo? Value = GetIsPrimeMethod(typeof(A)); } #endregion @@ -183,30 +180,29 @@ internal static class GetIsPrimeMethodCache /// Gets the IsNonNegative on a type if it exists [ IsNonNegative()]. /// The type of the out parameter. /// The IsNonNegative if found or null if not. - public static MethodInfo GetIsNonNegativeMethod() => GetIsNonNegativeMethodCache.Value; + public static MethodInfo? GetIsNonNegativeMethod() => GetIsNonNegativeMethodCache.Value; /// Gets the IsNonNegative on a type if it exists [ IsNonNegative()]. /// The type of the out parameter. /// The IsNonNegative if found or null if not. - public static MethodInfo GetIsNonNegativeMethod(Type a) + public static MethodInfo? GetIsNonNegativeMethod(Type a) { _ = a ?? throw new ArgumentNullException(nameof(a)); - MethodInfo methodInfo = a.GetMethod("IsNonNegative", + MethodInfo? methodInfo = a.GetMethod("IsNonNegative", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Ɐ(a), null); - return !(methodInfo is null) - && methodInfo.ReturnType == typeof(bool) - ? methodInfo - : null; + return methodInfo is not null && methodInfo.ReturnType == typeof(bool) + ? methodInfo + : null; } internal static class GetIsNonNegativeMethodCache { - internal static readonly MethodInfo Value = GetIsNonNegativeMethod(typeof(A)); + internal static readonly MethodInfo? Value = GetIsNonNegativeMethod(typeof(A)); } #endregion @@ -216,30 +212,29 @@ internal static class GetIsNonNegativeMethodCache /// Gets the IsNegative on a type if it exists [ IsNegative()]. /// The type of the out parameter. /// The IsNegative if found or null if not. - public static MethodInfo GetIsNegativeMethod() => GetIsNegativeMethodCache.Value; + public static MethodInfo? GetIsNegativeMethod() => GetIsNegativeMethodCache.Value; /// Gets the IsNegative on a type if it exists [ IsNegative()]. /// The type of the out parameter. /// The IsNegative if found or null if not. - public static MethodInfo GetIsNegativeMethod(Type a) + public static MethodInfo? GetIsNegativeMethod(Type a) { _ = a ?? throw new ArgumentNullException(nameof(a)); - MethodInfo methodInfo = a.GetMethod("IsNegative", + MethodInfo? methodInfo = a.GetMethod("IsNegative", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Ɐ(a), null); - return !(methodInfo is null) - && methodInfo.ReturnType == typeof(bool) + return methodInfo is not null && methodInfo.ReturnType == typeof(bool) ? methodInfo : null; } internal static class GetIsNegativeMethodCache { - internal static readonly MethodInfo Value = GetIsNegativeMethod(typeof(A)); + internal static readonly MethodInfo? Value = GetIsNegativeMethod(typeof(A)); } #endregion @@ -249,30 +244,29 @@ internal static class GetIsNegativeMethodCache /// Gets the IsPositive on a type if it exists [ IsPositive()]. /// The type of the out parameter. /// The IsPositive if found or null if not. - public static MethodInfo GetIsPositiveMethod() => GetIsPositiveMethodCache.Value; + public static MethodInfo? GetIsPositiveMethod() => GetIsPositiveMethodCache.Value; /// Gets the IsPositive on a type if it exists [ IsPositive()]. /// The type of the out parameter. /// The IsPositive if found or null if not. - public static MethodInfo GetIsPositiveMethod(Type a) + public static MethodInfo? GetIsPositiveMethod(Type a) { _ = a ?? throw new ArgumentNullException(nameof(a)); - MethodInfo methodInfo = a.GetMethod("IsPositive", + MethodInfo? methodInfo = a.GetMethod("IsPositive", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Ɐ(a), null); - return !(methodInfo is null) - && methodInfo.ReturnType == typeof(bool) + return methodInfo is not null && methodInfo.ReturnType == typeof(bool) ? methodInfo : null; } internal static class GetIsPositiveMethodCache { - internal static readonly MethodInfo Value = GetIsPositiveMethod(typeof(A)); + internal static readonly MethodInfo? Value = GetIsPositiveMethod(typeof(A)); } #endregion @@ -282,15 +276,15 @@ internal static class GetIsPositiveMethodCache /// Gets the IsEven on a type if it exists [ IsEven()]. /// The type of the out parameter. /// The IsEven if found or null if not. - public static MethodInfo GetIsEvenMethod() => GetIsEvenMethodCache.Value; + public static MethodInfo? GetIsEvenMethod() => GetIsEvenMethodCache.Value; /// Gets the IsEven on a type if it exists [ IsEven()]. /// The type of the out parameter. /// The IsEven if found or null if not. - public static MethodInfo GetIsEvenMethod(Type a) + public static MethodInfo? GetIsEvenMethod(Type a) { _ = a ?? throw new ArgumentNullException(nameof(a)); - MethodInfo methodInfo = a.GetMethod( + MethodInfo? methodInfo = a.GetMethod( "IsOdd", BindingFlags.Static | BindingFlags.Public | @@ -298,15 +292,14 @@ public static MethodInfo GetIsEvenMethod(Type a) null, Ɐ(a), null); - return !(methodInfo is null) - && methodInfo.ReturnType == typeof(bool) + return methodInfo is not null && methodInfo.ReturnType == typeof(bool) ? methodInfo : null; } internal static class GetIsEvenMethodCache { - internal static readonly MethodInfo Value = GetIsEvenMethod(typeof(A)); + internal static readonly MethodInfo? Value = GetIsEvenMethod(typeof(A)); } #endregion @@ -316,15 +309,15 @@ internal static class GetIsEvenMethodCache /// Gets the IsOdd on a type if it exists [ IsOdd()]. /// The type of the out parameter. /// The IsOdd if found or null if not. - public static MethodInfo GetIsOddMethod() => GetIsOddMethodCache.Value; + public static MethodInfo? GetIsOddMethod() => GetIsOddMethodCache.Value; /// Gets the IsOdd on a type if it exists [ IsOdd()]. /// The type of the out parameter. /// The IsOdd if found or null if not. - public static MethodInfo GetIsOddMethod(Type a) + public static MethodInfo? GetIsOddMethod(Type a) { _ = a ?? throw new ArgumentNullException(nameof(a)); - MethodInfo methodInfo = a.GetMethod( + MethodInfo? methodInfo = a.GetMethod( "IsOdd", BindingFlags.Static | BindingFlags.Public | @@ -332,15 +325,14 @@ public static MethodInfo GetIsOddMethod(Type a) null, Ɐ(a), null); - return !(methodInfo is null) - && methodInfo.ReturnType == typeof(bool) + return methodInfo is not null && methodInfo.ReturnType == typeof(bool) ? methodInfo : null; } internal static class GetIsOddMethodCache { - internal static readonly MethodInfo Value = GetIsOddMethod(typeof(A)); + internal static readonly MethodInfo? Value = GetIsOddMethod(typeof(A)); } #endregion @@ -350,15 +342,15 @@ internal static class GetIsOddMethodCache /// Gets the IsInteger on a type if it exists [ IsInteger()]. /// The type of the out parameter. /// The TryParse if found or null if not. - public static MethodInfo GetIsIntegerMethod() => GetIsIntegerMethodCache.Value; + public static MethodInfo? GetIsIntegerMethod() => GetIsIntegerMethodCache.Value; /// Gets the IsInteger on a type if it exists [ IsInteger()]. /// The type of the out parameter. /// The TryParse if found or null if not. - public static MethodInfo GetIsIntegerMethod(Type a) + public static MethodInfo? GetIsIntegerMethod(Type a) { _ = a ?? throw new ArgumentNullException(nameof(a)); - MethodInfo methodInfo = a.GetMethod( + MethodInfo? methodInfo = a.GetMethod( "IsInteger", BindingFlags.Static | BindingFlags.Public | @@ -366,15 +358,14 @@ public static MethodInfo GetIsIntegerMethod(Type a) null, Ɐ(a), null); - return !(methodInfo is null) - && methodInfo.ReturnType == typeof(bool) + return methodInfo is not null && methodInfo.ReturnType == typeof(bool) ? methodInfo : null; } internal static class GetIsIntegerMethodCache { - internal static readonly MethodInfo Value = GetIsIntegerMethod(typeof(A)); + internal static readonly MethodInfo? Value = GetIsIntegerMethod(typeof(A)); } #endregion @@ -386,20 +377,20 @@ internal static class GetIsIntegerMethodCache /// The type of the right operand. /// The type of the return. /// True if the op_LessThan member exists or false if not. - public static MethodInfo GetLessThanMethod() => GetLessThanMethodCache.Value; + public static MethodInfo? GetLessThanMethod() => GetLessThanMethodCache.Value; /// Determines if an op_LessThan member exists. /// The type of the left operand. /// The type of the right operand. /// The type of the return. /// True if the op_LessThan member exists or false if not. - internal static MethodInfo GetLessThanMethod(Type a, Type b, Type c) + internal static MethodInfo? GetLessThanMethod(Type a, Type b, Type c) { _ = a ?? throw new ArgumentNullException(nameof(a)); _ = b ?? throw new ArgumentNullException(nameof(b)); - MethodInfo CheckType(Type type) + MethodInfo? CheckType(Type type) { - MethodInfo methodInfo = type.GetMethod( + MethodInfo? methodInfo = type.GetMethod( "op_LessThan", BindingFlags.Static | BindingFlags.Public | @@ -407,7 +398,7 @@ MethodInfo CheckType(Type type) null, Ɐ(a, b), null); - return !(methodInfo is null) + return methodInfo is not null && methodInfo.ReturnType == c && methodInfo.IsSpecialName ? methodInfo @@ -418,7 +409,7 @@ MethodInfo CheckType(Type type) internal static class GetLessThanMethodCache { - internal static readonly MethodInfo Value = GetLessThanMethod(typeof(A), typeof(B), typeof(C)); + internal static readonly MethodInfo? Value = GetLessThanMethod(typeof(A), typeof(B), typeof(C)); } #endregion @@ -430,20 +421,20 @@ internal static class GetLessThanMethodCache /// The type of the right operand. /// The type of the return. /// True if the op_GreaterThan member exists or false if not. - public static MethodInfo GetGreaterThanMethod() => GetGreaterThanMethodCache.Value; + public static MethodInfo? GetGreaterThanMethod() => GetGreaterThanMethodCache.Value; /// Determines if an op_GreaterThan member exists. /// The type of the left operand. /// The type of the right operand. /// The type of the return. /// True if the op_GreaterThan member exists or false if not. - internal static MethodInfo GetGreaterThanMethod(Type a, Type b, Type c) + internal static MethodInfo? GetGreaterThanMethod(Type a, Type b, Type c) { _ = a ?? throw new ArgumentNullException(nameof(a)); _ = b ?? throw new ArgumentNullException(nameof(b)); - MethodInfo CheckType(Type type) + MethodInfo? CheckType(Type type) { - MethodInfo methodInfo = type.GetMethod( + MethodInfo? methodInfo = type.GetMethod( "op_GreaterThan", BindingFlags.Static | BindingFlags.Public | @@ -462,7 +453,7 @@ MethodInfo CheckType(Type type) internal static class GetGreaterThanMethodCache { - internal static readonly MethodInfo Value = GetGreaterThanMethod(typeof(A), typeof(B), typeof(C)); + internal static readonly MethodInfo? Value = GetGreaterThanMethod(typeof(A), typeof(B), typeof(C)); } #endregion @@ -501,7 +492,7 @@ internal static bool HasCast(Type fromType, Type toType, bool @implicit) : "op_Explicit"; bool CheckType(Type type) { - MethodInfo methodInfo = type.GetMethod( + MethodInfo? methodInfo = type.GetMethod( methodName, BindingFlags.Static | BindingFlags.Public | @@ -760,7 +751,7 @@ public static System.Collections.Generic.IEnumerable GetDerivedTypes /// Gets the file path of an assembly. /// The assembly to get the file path of. /// The file path of the assembly. - public static string GetDirectoryPath(this Assembly assembly) + public static string? GetDirectoryPath(this Assembly assembly) { string codeBase = assembly.Location; UriBuilder uri = new UriBuilder(codeBase); @@ -810,8 +801,11 @@ public static void LoadXmlDocumentation(TextReader textReader) { if (xmlReader.NodeType == XmlNodeType.Element && xmlReader.Name == "member") { - string raw_name = xmlReader["name"]; - loadedXmlDocumentation[raw_name] = xmlReader.ReadInnerXml(); + string? raw_name = xmlReader["name"]; + if (!string.IsNullOrWhiteSpace(raw_name)) + { + loadedXmlDocumentation[raw_name] = xmlReader.ReadInnerXml(); + } } } } diff --git a/Sources/Towel/Towel.csproj b/Sources/Towel/Towel.csproj index b1a2f792..a01eaf88 100644 --- a/Sources/Towel/Towel.csproj +++ b/Sources/Towel/Towel.csproj @@ -1,6 +1,7 @@  net5.0 + enable Towel.xml Towel icon.png diff --git a/Sources/Towel/Towel.xml b/Sources/Towel/Towel.xml index 5d28dd9e..4568a6dc 100644 --- a/Sources/Towel/Towel.xml +++ b/Sources/Towel/Towel.xml @@ -2465,9 +2465,6 @@ Implements a growing, singularly-linked list data structure that inherits InterfaceTraversable. The type of objects to be placed in the list. - - This class just holds the data for each individual node of the list. - Creates an instance of a AddableLinked. @@ -2612,11 +2609,14 @@ The value to be added. The exception that occurrs if the add fails. True if the add succeds or false if not. + == && > / 2 Adds an item at a given index. The item to be added. The index to add the item at. + index < 0 || index > + == && > / 2 @@ -2641,6 +2641,7 @@ Runtime: Θ(n - index) The index of the item to be removed. + Thrown when: index < 0 || index >= _count @@ -2662,13 +2663,7 @@ Runtime: O(n), Ω(1) The predicate to determine removals. - - - - Removes the first occurence of a value from the list without causing the list to shrink. - Runtime: O(n), Ω(1) - - The value to remove. + Thrown when does not find a in the list. @@ -2677,14 +2672,15 @@ The value to remove. The delegate providing the equality check. + Thrown when is not found in the list. - + Removes the first predicated value from the list wihtout shrinking the list. Runtime: O(n), Ω(1) The predicate to determine removals. - The exception that occured if the removal failed. + Thrown when does not find a in the list. Tries to remove the first predicated value if the value exists. @@ -2817,7 +2813,7 @@ The type of keys in the map. The map to get the value from. The key of the value to get. - The default value to return if the value is not found. + The default value to return if the value is not found. The value if found or the defautl value. @@ -4453,10 +4449,6 @@ Returns a vector with defaulted values. - - Constructs an N-D vector. - - An N-D bounding box. @@ -13502,10 +13494,10 @@ The generic type within the structure. - The newest item currently in the queue. + The current newest element in the queue. - The oldest item currently in the queue. + The current oldest element in the queue. Adds an item to the back of the queue. @@ -13531,13 +13523,13 @@ - The newest item currently in the queue. + The current newest element in the queue. Runtime: O(1) - The oldest item currently in the queue. + The current oldest element in the queue. Runtime: O(1) @@ -13573,7 +13565,10 @@ The next item in the queue. - Gets the next item in the queue without removing it. + + Gets the next item in the queue without removing it. + Runtime: O(1) + The next item in the queue. @@ -13607,7 +13602,10 @@ - Gets the enumerator for this queue. + + Gets the enumerator for this queue. + Runtime: O(1) + The enumerator for the queue. @@ -13616,13 +13614,13 @@ - Creates an instance of a ListArray, and sets it's minimum capacity. + Constructs a new queue. Runtime: O(1) - Creates an instance of a ListArray, and sets it's minimum capacity. + Constructs a new queue. Runtime: O(1) The initial and smallest array size allowed by this list. @@ -13647,13 +13645,33 @@ - The newest item currently in the queue. + + The current newest in the queue. + Runtime: O(1) + + Thrown when: _count <= 0 - The oldest item currently in the queue. + + The current newest in the queue. + Runtime: O(1) + + Thrown when: _count <= 0 + + + + Gets or sets the at an index in the queue. + Runtime: O(1) + + The index of the to get or set. + The element at the provided index. + Thrown when: index <= 0 || index > _count - Converts the list array into a standard array. + + Converts the list array into a standard array. + Runtime: O() + A standard array of all the elements. @@ -13670,7 +13688,7 @@ Removes the item at a specific index. - Runtime: O(n - index) + Runtime: O(n), ε(1) @@ -13679,7 +13697,7 @@ - Empties the list back and reduces it back to its original capacity. + Returns the queue to an empty state. Runtime: O(1) @@ -14031,7 +14049,7 @@ Puts all the values in this set into an array. - Runtime: Θ(n) + Runtime: Θ( + ) An array with all the values in the set. @@ -14609,7 +14627,8 @@ Allows you to adjust the minimum capacity of this list. - Runtime: O(n), Ω(1) + Runtime (get): O(1) + Runtime (set): O(n), Ω(1) From d89e17d894353fd56ffdb461ab3952f6d1895f19 Mon Sep 17 00:00:00 2001 From: Zachary Patten Date: Tue, 27 Oct 2020 21:51:47 -0400 Subject: [PATCH 04/30] nullable ref + code clean up --- Sources/Towel/DataStructures/AvlTree.cs | 199 +++++++------ Sources/Towel/DataStructures/DataStructure.cs | 4 +- Sources/Towel/DataStructures/Queue.cs | 13 +- Sources/Towel/DataStructures/RedBlackTree.cs | 275 +++++++++--------- .../Towel/DataStructures/SortedBinaryTree.cs | 20 +- Sources/Towel/Meta.cs | 4 +- Sources/Towel/Towel.xml | 63 +++- Tools/Towel_Testing/Meta.cs | 58 ++-- 8 files changed, 356 insertions(+), 280 deletions(-) diff --git a/Sources/Towel/DataStructures/AvlTree.cs b/Sources/Towel/DataStructures/AvlTree.cs index c2646749..dddc8c01 100644 --- a/Sources/Towel/DataStructures/AvlTree.cs +++ b/Sources/Towel/DataStructures/AvlTree.cs @@ -29,6 +29,18 @@ internal class Node internal Node? LeftChild; internal Node? RightChild; internal int Height; + + internal Node( + T value, + int height = default, + Node? leftChild = null, + Node? rightChild = null) + { + Value = value; + Height = height; + LeftChild = leftChild; + RightChild = rightChild; + } } #endregion @@ -52,14 +64,11 @@ public AvlTreeLinked(Compare compare = default) internal AvlTreeLinked(AvlTreeLinked tree) { static Node Clone(Node node) => - new Node() - { - Value = node.Value, - LeftChild = node.LeftChild is null ? null : Clone(node.LeftChild), - RightChild = node.RightChild is null ? null : Clone(node.RightChild), - Height = node.Height, - }; - + new Node( + value: node.Value, + height: node.Height, + leftChild: node.LeftChild is null ? null : Clone(node.LeftChild), + rightChild: node.RightChild is null ? null : Clone(node.RightChild)); _root = tree._root is null ? null : Clone(tree._root); _count = tree._count; _compare = tree._compare; @@ -141,7 +150,7 @@ public bool TryAdd(T value, out Exception? exception) if (node is null) { _count++; - return new Node() { Value = value, }; + return new Node(value: value); } CompareResult compareResult = _compare.Do(node.Value, value); switch (compareResult) @@ -152,11 +161,9 @@ public bool TryAdd(T value, out Exception? exception) capturedException = new ArgumentException($"Adding to add a duplicate value to an {nameof(AvlTreeLinked)}: {value}.", nameof(value)); return node; default: -#pragma warning disable CA2208 // Instantiate argument exceptions correctly capturedException = compareResult.IsDefined() - ? (Exception)new TowelBugException($"Unhandled {nameof(CompareResult)} value: {compareResult}.") - : new ArgumentException($"Invalid {nameof(Compare)} function; an undefined {nameof(CompareResult)} was returned.", nameof(Compare)); -#pragma warning restore CA2208 // Instantiate argument exceptions correctly + ? new TowelBugException($"Unhandled {nameof(CompareResult)} value: {compareResult}.") + : new ArgumentException($"Invalid {nameof(Compare)} function; an undefined {nameof(CompareResult)} was returned."); break; } return capturedException is null ? Balance(node) : node; @@ -165,10 +172,6 @@ public bool TryAdd(T value, out Exception? exception) return (exception = capturedException) is null; } - #endregion - - #region Clear - /// /// Returns the tree to an iterative state. /// Runtime: O(1) @@ -179,10 +182,6 @@ public void Clear() _count = 0; } - #endregion - - #region Clone - /// /// Clones the AVL tree. /// Runtime: θ(n) @@ -190,10 +189,6 @@ public void Clear() /// A clone of the AVL tree. public AvlTreeLinked Clone() => new AvlTreeLinked(this); - #endregion - - #region Contains - /// /// Determines if the AVL tree contains a value. /// Runtime: O(ln(Count)), Ω(1) @@ -209,23 +204,32 @@ public bool Contains(T value) => /// /// The sorting technique (must synchronize with this structure's sorting). /// True of contained, False if not. - public bool Contains(Func sift) + public bool Contains(Func sift) => + sift is null ? throw new ArgumentNullException(nameof(sift)) : + Contains>(sift); + + /// + /// Determines if this structure contains an item by a given key. + /// Runtime: O(ln(Count)), Ω(1) + /// + /// The sorting technique (must synchronize with this structure's sorting). + /// True of contained, False if not. + public bool Contains(Sift sift = default) + where Sift : struct, IFunc { Node? node = _root; while (node is not null) { - CompareResult compareResult = sift(node.Value); - if (compareResult is Less) - { - node = node.RightChild; - } - else if (compareResult is Greater) - { - node = node.LeftChild; - } - else // (compareResult == Copmarison.Equal) + CompareResult compareResult = sift.Do(node.Value); + switch (compareResult) { - return true; + case Less: node = node.RightChild; break; + case Greater: node = node.LeftChild; break; + case Equal: return true; + default: + throw compareResult.IsDefined() + ? new TowelBugException($"Unhandled {nameof(CompareResult)} value: {compareResult}.") + : new ArgumentException($"Invalid {nameof(Compare)} function; an undefined {nameof(CompareResult)} was returned."); } } return false; @@ -243,25 +247,37 @@ public bool Contains(Func sift) /// The value if found or default. /// The exception that occurred if the get failed. /// True if the get succeeded or false if not. - public bool TryGet(Func sift, out T value, out Exception? exception) + public bool TryGet(out T? value, out Exception? exception, Func sift) => + TryGet>(out value, out exception, sift); + + /// + /// Tries to get a value. + /// Runtime: O(ln(Count)), Ω(1) + /// + /// The compare delegate. + /// The compare delegate. + /// The value if found or default. + /// The exception that occurred if the get failed. + /// True if the get succeeded or false if not. + public bool TryGet(out T? value, out Exception? exception, Sift sift = default) + where Sift : struct, IFunc { Node? node = _root; while (node is not null) { - CompareResult comparison = sift(node.Value); - if (comparison is Less) - { - node = node.LeftChild; - } - else if (comparison is Greater) - { - node = node.RightChild; - } - else // (compareResult == Copmarison.Equal) + CompareResult compareResult = sift.Do(node.Value); + switch (compareResult) { - value = node.Value; - exception = null; - return true; + case Less: node = node.LeftChild; break; + case Greater: node = node.RightChild; break; + case Equal: + value = node.Value; + exception = null; + return true; + default: + throw compareResult.IsDefined() + ? new TowelBugException($"Unhandled {nameof(CompareResult)} value: {compareResult}.") + : new ArgumentException($"Invalid {nameof(Compare)} function; an undefined {nameof(CompareResult)} was returned."); } } value = default; @@ -278,48 +294,56 @@ public bool TryGet(Func sift, out T value, out Exception? exce /// The exception that occurred if the remove failed. /// True if the remove was successful or false if not. public bool TryRemove(T value, out Exception? exception) => - TryRemove(x => _compare.Do(x, value), out exception); + TryRemove(out exception, new SiftFromCompareAndValue(value, _compare)); + + /// Tries to remove a value. + /// The compare delegate. + /// The exception that occurred if the remove failed. + /// True if the remove was successful or false if not. + public bool TryRemove(out Exception? exception, Func sift) => + TryRemove>(out exception, sift); /// Tries to remove a value. /// The compare delegate. /// The exception that occurred if the remove failed. /// True if the remove was successful or false if not. - public bool TryRemove(Func sift, out Exception? exception) + public bool TryRemove(out Exception? exception, Sift sift = default) + where Sift : struct, IFunc { Exception? capturedException = null; Node? Remove(Node? node) { if (node is not null) { - CompareResult compareResult = sift(node.Value); - if (compareResult is Less) - { - node.RightChild = Remove(node.RightChild); - } - else if (compareResult is Greater) + CompareResult compareResult = sift.Do(node.Value); + switch (compareResult) { - node.LeftChild = Remove(node.LeftChild); - } - else // (compareResult == Comparison.Equal) - { - if (!(node.RightChild is null)) - { - node.RightChild = RemoveLeftMost(node.RightChild, out Node leftMostOfRight); - leftMostOfRight.RightChild = node.RightChild; - leftMostOfRight.LeftChild = node.LeftChild; - node = leftMostOfRight; - } - else if (!(node.LeftChild is null)) - { - node.LeftChild = RemoveRightMost(node.LeftChild, out Node rightMostOfLeft); - rightMostOfLeft.RightChild = node.RightChild; - rightMostOfLeft.LeftChild = node.LeftChild; - node = rightMostOfLeft; - } - else - { - return null; - } + case Less: node.RightChild = Remove(node.RightChild); break; + case Greater: node.LeftChild = Remove(node.LeftChild); break; + case Equal: + if (!(node.RightChild is null)) + { + node.RightChild = RemoveLeftMost(node.RightChild, out Node leftMostOfRight); + leftMostOfRight.RightChild = node.RightChild; + leftMostOfRight.LeftChild = node.LeftChild; + node = leftMostOfRight; + } + else if (!(node.LeftChild is null)) + { + node.LeftChild = RemoveRightMost(node.LeftChild, out Node rightMostOfLeft); + rightMostOfLeft.RightChild = node.RightChild; + rightMostOfLeft.LeftChild = node.LeftChild; + node = rightMostOfLeft; + } + else + { + return null; + } + break; + default: + throw compareResult.IsDefined() + ? new TowelBugException($"Unhandled {nameof(CompareResult)} value: {compareResult}.") + : new ArgumentException($"Invalid {nameof(Compare)} function; an undefined {nameof(CompareResult)} was returned."); } SetHeight(node); return Balance(node); @@ -746,14 +770,11 @@ public AvlTreeLinked(Func? compare = null) : base(compare ? internal AvlTreeLinked(AvlTreeLinked tree) { static Node Clone(Node node) => - new Node() - { - Value = node.Value, - LeftChild = node.LeftChild is null ? null : Clone(node.LeftChild), - RightChild = node.RightChild is null ? null : Clone(node.RightChild), - Height = node.Height, - }; - + new Node( + value: node.Value, + height: node.Height, + leftChild: node.LeftChild is null ? null : Clone(node.LeftChild), + rightChild: node.RightChild is null ? null : Clone(node.RightChild)); _root = tree._root is null ? null : Clone(tree._root); _count = tree._count; _compare = tree._compare; diff --git a/Sources/Towel/DataStructures/DataStructure.cs b/Sources/Towel/DataStructures/DataStructure.cs index df4c8e31..6b7f4cc4 100644 --- a/Sources/Towel/DataStructures/DataStructure.cs +++ b/Sources/Towel/DataStructures/DataStructure.cs @@ -154,7 +154,7 @@ public static void Add(this IAddable structure, T value) { if (!structure.TryAdd(value, out Exception? exception)) { - throw exception; + throw exception ?? new ArgumentException(nameof(exception), $"{nameof(Add)} failed but the {nameof(exception)} is null"); ; } } @@ -174,7 +174,7 @@ public static void Remove(this IRemovable structure, T value) { if (!structure.TryRemove(value, out Exception? exception)) { - throw exception; + throw exception ?? new ArgumentException(nameof(exception), $"{nameof(Remove)} failed but the {nameof(exception)} is null"); ; } } diff --git a/Sources/Towel/DataStructures/Queue.cs b/Sources/Towel/DataStructures/Queue.cs index 33076c8c..7d7af1bd 100644 --- a/Sources/Towel/DataStructures/Queue.cs +++ b/Sources/Towel/DataStructures/Queue.cs @@ -1,4 +1,5 @@ using System; +using System.Security; using static Towel.Statics; namespace Towel.DataStructures @@ -428,12 +429,13 @@ public void Enqueue(T addition) _start = 0; _array = array; } - int end = _start + _count++; + int end = _start + _count; if (end >= _array.Length) { - end -= _array.Length - _start; + end %= _array.Length; } _array[end] = addition; + _count++; } /// @@ -457,8 +459,11 @@ public T Dequeue() _start = 0; _array = array; } - T element = _array[_start]; - _start = ++_start >= _array.Length ? _start : 0; + T element = _array[_start++]; + if (_start >= _array.Length) + { + _start = 0; + } _count--; return element; } diff --git a/Sources/Towel/DataStructures/RedBlackTree.cs b/Sources/Towel/DataStructures/RedBlackTree.cs index 3d240d01..bfa50e91 100644 --- a/Sources/Towel/DataStructures/RedBlackTree.cs +++ b/Sources/Towel/DataStructures/RedBlackTree.cs @@ -19,7 +19,7 @@ public class RedBlackTreeLinked : IRedBlackTree { internal const bool Red = true; internal const bool Black = false; - internal readonly Node _sentinelNode = new Node() { Color = Black }; + internal readonly Node _sentinelNode = new Node(value: default, color: Black); internal Compare _compare; internal int _count; @@ -29,11 +29,25 @@ public class RedBlackTreeLinked : IRedBlackTree internal class Node { - internal bool Color = Red; internal T Value; - internal Node LeftChild; - internal Node RightChild; - internal Node Parent; + internal bool Color; + internal Node? Parent; + internal Node? LeftChild; + internal Node? RightChild; + + public Node( + T value, + bool color = Red, + Node? parent = null, + Node? leftChild = null, + Node? rightChild = null) + { + Value = value; + Color = color; + Parent = parent; + LeftChild = leftChild; + RightChild = rightChild; + } } #endregion @@ -58,12 +72,10 @@ Node Clone(Node node, Node parent) { return _sentinelNode; } - Node clone = new Node - { - Value = node.Value, - Color = node.Color, - Parent = parent - }; + Node clone = new Node( + value: node.Value, + color: node.Color, + parent: parent); clone.LeftChild = node.LeftChild is null ? null : Clone(node.LeftChild, clone); clone.RightChild = node.RightChild is null ? null : Clone(node.RightChild, clone); return clone; @@ -129,65 +141,55 @@ _compare is FuncRuntime func #region Methods - #region Add - /// Tries to add a value to the Red-Black tree. /// The value to be added to the Red-Black tree. /// The exception that occurred if the add failed. /// True if the add was successful or false if not. - public bool TryAdd(T value, out Exception exception) + public bool TryAdd(T value, out Exception? exception) { - Exception capturedException = null; - Node addition = new Node(); - Node temp = _root; - while (temp != _sentinelNode) + Exception? capturedException = null; + Node addition = new Node( + value: value, + leftChild: _sentinelNode, + rightChild: _sentinelNode); + Node node = _root; + while (node != _sentinelNode) { - addition.Parent = temp; - CompareResult compareResult = _compare.Do(value, temp.Value); + addition.Parent = node; + CompareResult compareResult = _compare.Do(value, node.Value); switch (compareResult) { - case Less: temp = temp.LeftChild; break; - case Greater: temp = temp.RightChild; break; + case Less: node = node.LeftChild; break; + case Greater: node = node.RightChild; break; case Equal: capturedException = new ArgumentException($"Adding to add a duplicate value to a {nameof(RedBlackTreeLinked)}: {value}.", nameof(value)); goto Break; default: -#pragma warning disable CA2208 // Instantiate argument exceptions correctly capturedException = compareResult.IsDefined() - ? (Exception)new TowelBugException($"Unhandled {nameof(CompareResult)} value: {compareResult}.") + ? new TowelBugException($"Unhandled {nameof(CompareResult)} value: {compareResult}.") : new ArgumentException($"Invalid {nameof(Compare)} function; an undefined {nameof(CompareResult)} was returned.", nameof(Compare)); -#pragma warning restore CA2208 // Instantiate argument exceptions correctly goto Break; } } Break: - - if (!(capturedException is null)) + if (capturedException is not null) { exception = capturedException; return false; } - addition.Value = value; - addition.LeftChild = _sentinelNode; - addition.RightChild = _sentinelNode; - if (!(addition.Parent is null)) + if (addition.Parent is not null) { CompareResult compareResult = _compare.Do(addition.Value, addition.Parent.Value); - if (compareResult is Less) - { - addition.Parent.LeftChild = addition; - } - else if (compareResult is Greater) - { - addition.Parent.RightChild = addition; - } - else if (compareResult is Equal) - { - throw new CorruptedDataStructureException(); - } - else + switch (compareResult) { - throw new TowelBugException("Encountered Unhandled CompareResult."); + case Less: addition.Parent.LeftChild = addition; break; + case Greater: addition.Parent.RightChild = addition; break; + case Equal: capturedException = new CorruptedDataStructureException(); break; + default: + capturedException = compareResult.IsDefined() + ? new TowelBugException($"Unhandled {nameof(CompareResult)} value: {compareResult}.") + : new ArgumentException($"Invalid {nameof(Compare)} function; an undefined {nameof(CompareResult)} was returned.", nameof(Compare)); + break; } } else @@ -200,10 +202,6 @@ public bool TryAdd(T value, out Exception exception) return true; } - #endregion - - #region Clear - /// Returns the tree to an empty state. public void Clear() { @@ -211,22 +209,14 @@ public void Clear() _count = 0; } - #endregion - - #region Clone - /// Creates a shallow clone of this data structure. /// A shallow clone of this data structure. public RedBlackTreeLinked Clone() => new RedBlackTreeLinked(this); - #endregion - - #region Contains - /// Determines if the tree contains a given value; /// The value to see if the tree contains. /// True if the tree contains the value. False if not. - public bool Contains(T value) => Contains(x => _compare.Do(x, value)); + public bool Contains(T value) => Contains(new SiftFromCompareAndValue(value, _compare)); /// /// Determines if this structure contains an item by a given key. @@ -234,60 +224,70 @@ public void Clear() /// /// The sorting technique (must synchronize with this structure's sorting). /// True of contained, False if not. - public bool Contains(Func sift) + public bool Contains(Func sift) => + Contains>(sift); + + /// + /// Determines if this structure contains an item by a given key. + /// Runtime: O(ln(Count)), Ω(1) + /// + /// The sifting method. + /// The sifting method. + /// True of contained, False if not. + public bool Contains(Sift sift = default) + where Sift : struct, IFunc { Node node = _root; - while (node != _sentinelNode && !(node is null)) + while (node != _sentinelNode && node is not null) { - CompareResult compareResult = sift(node.Value); - if (compareResult is Less) - { - node = node.RightChild; - } - else if (compareResult is Greater) - { - node = node.LeftChild; - } - else if (compareResult is Equal) - { - return true; - } - else + CompareResult compareResult = sift.Do(node.Value); + switch (compareResult) { - throw new TowelBugException("Unhandled CompareResult."); + case Less: node = node.RightChild; break; + case Greater: node = node.LeftChild; break; + case Equal: return true; + default: + throw compareResult.IsDefined() + ? new TowelBugException($"Unhandled {nameof(CompareResult)} value: {compareResult}.") + : new ArgumentException($"Invalid {nameof(Compare)} function; an undefined {nameof(CompareResult)} was returned.", nameof(Compare)); } } return false; } - #endregion - - #region Get + /// Tries to get a value. + /// The compare delegate. + /// The value if it was found or default. + /// The exception that occurred if the get failed. + /// True if the value was found or false if not. + public bool TryGet(out T? value, out Exception? exception, Func sift) => + TryGet>(out value, out exception, sift); /// Tries to get a value. + /// The compare delegate. /// The compare delegate. /// The value if it was found or default. /// The exception that occurred if the get failed. /// True if the value was found or false if not. - public bool TryGet(Func sift, out T value, out Exception exception) + public bool TryGet(out T? value, out Exception? exception, Sift sift = default) + where Sift : struct, IFunc { Node node = _root; while (node != _sentinelNode) { - CompareResult compareResult = sift(node.Value); - if (compareResult is Greater) - { - node = node.RightChild; - } - else if (compareResult is Less) - { - node = node.LeftChild; - } - else + CompareResult compareResult = sift.Do(node.Value); + switch (compareResult) { - value = node.Value; - exception = null; - return true; + case Less: node = node.LeftChild; break; + case Greater: node = node.RightChild; break; + case Equal: + value = node.Value; + exception = null; + return true; + default: + throw compareResult.IsDefined() + ? new TowelBugException($"Unhandled {nameof(CompareResult)} value: {compareResult}.") + : new ArgumentException($"Invalid {nameof(Compare)} function; an undefined {nameof(CompareResult)} was returned.", nameof(Compare)); } } value = default; @@ -295,46 +295,51 @@ public bool TryGet(Func sift, out T value, out Exception excep return false; } - #endregion - - #region Remove - /// Tries to remove a value. /// The value to remove. /// The exception that occurred if the remove failed. /// True if the remove was successful or false if not. - public bool TryRemove(T value, out Exception exception) => TryRemove(x => _compare.Do(value, x), out exception); + public bool TryRemove(T value, out Exception? exception) => + TryRemove(out exception, new SiftFromCompareAndValue(value, _compare)); + + /// Tries to remove a value. + /// The compare delegate. + /// The exception that occurred if the remove failed. + /// True if the remove was successful or false if not. + public bool TryRemove(out Exception? exception, Func sift) => + TryRemove>(out exception, sift); /// Tries to remove a value. + /// The compare delegate. /// The compare delegate. /// The exception that occurred if the remove failed. /// True if the remove was successful or false if not. - public bool TryRemove(Func sift, out Exception exception) + public bool TryRemove(out Exception? exception, Sift sift = default) + where Sift : struct, IFunc { Node node; node = _root; while (node != _sentinelNode) { - CompareResult compareResult = sift(node.Value); - if (compareResult is Less) - { - node = node.LeftChild; - } - else if (compareResult is Greater) - { - node = node.RightChild; - } - else // (compareResult is Equal) + CompareResult compareResult = sift.Do(node.Value); + switch (compareResult) { - if (node == _sentinelNode) - { - exception = new ArgumentException("Attempting to remove a non-existing entry."); - return false; - } - Remove(node); - _count -= 1; - exception = null; - return true; + case Less: node = node.RightChild; break; + case Greater: node = node.LeftChild; break; + case Equal: + if (node == _sentinelNode) + { + exception = new ArgumentException("Attempting to remove a non-existing entry."); + return false; + } + Remove(node); + _count -= 1; + exception = null; + return true; + default: + throw compareResult.IsDefined() + ? new TowelBugException($"Unhandled {nameof(CompareResult)} value: {compareResult}.") + : new ArgumentException($"Invalid {nameof(Compare)} function; an undefined {nameof(CompareResult)} was returned.", nameof(Compare)); } } exception = new ArgumentException("Attempting to remove a non-existing entry."); @@ -391,8 +396,6 @@ internal void Remove(Node removal) } } - #endregion - #region Stepper And IEnumerable #region Stepper @@ -484,6 +487,11 @@ public virtual StepStatus Stepper(T minimum, T maximum, StepRefBreak step) => public virtual StepStatus StepperRefBreak(T minimum, T maximum, Step step = default) where Step : struct, IStepRefBreak { + if (_compare.Do(minimum, maximum) is Greater) + { + throw new InvalidOperationException($"{nameof(minimum)}[{minimum}] > {nameof(maximum)}[{maximum}]"); + } + StepStatus Stepper(Node node) { if (node != _sentinelNode) @@ -507,10 +515,7 @@ StepStatus Stepper(Node node) } return Continue; } - if (_compare.Do(minimum, maximum) is Greater) - { - throw new InvalidOperationException("!(" + nameof(minimum) + " <= " + nameof(maximum) + ")"); - } + return Stepper(_root); } @@ -555,7 +560,7 @@ public StepStatus StepperReverseRefBreak(Step step = default) { StepStatus StepperReverse(Node node) { - if (!(node is null)) + if (node is not null) { return StepperReverse(node.RightChild) is Break ? Break : @@ -609,7 +614,7 @@ public virtual StepStatus StepperReverseRefBreak(T minimum, T maximum, Ste { StepStatus StepperReverse(Node node) { - if (!(node is null)) + if (node is not null) { if (_compare.Do(node.Value, minimum) is Less) { @@ -652,14 +657,14 @@ StepStatus StepperReverse(Node node) /// public IEnumerator GetEnumerator() { - Node GetNextNode(Node current) + Node? GetNextNode(Node current) { if (!(current.RightChild is null) && current.RightChild != _sentinelNode) { return GetLeftMostNode(current.RightChild); } var parent = current.Parent; - while (!(parent is null) && current == parent.RightChild) + while (parent is not null && current == parent.RightChild) { current = parent; parent = parent.Parent; @@ -667,7 +672,7 @@ Node GetNextNode(Node current) return parent; } - for (var current = GetLeftMostNode(_root); !(current is null); current = GetNextNode(current)) + for (var current = GetLeftMostNode(_root); current is not null; current = GetNextNode(current)) { yield return current.Value; } @@ -687,7 +692,7 @@ internal void BalanceAddition(Node balancing) if (balancing.Parent == balancing.Parent.Parent.LeftChild) { temp = balancing.Parent.Parent.RightChild; - if (!(temp is null) && temp.Color == Red) + if (temp is not null && temp.Color == Red) { balancing.Parent.Color = Black; temp.Color = Black; @@ -709,7 +714,7 @@ internal void BalanceAddition(Node balancing) else { temp = balancing.Parent.Parent.LeftChild; - if (!(temp is null) && temp.Color == Red) + if (temp is not null && temp.Color == Red) { balancing.Parent.Color = Black; temp.Color = Black; @@ -881,12 +886,10 @@ Node Clone(Node node, Node parent) { return _sentinelNode; } - Node clone = new Node - { - Value = node.Value, - Color = node.Color, - Parent = parent - }; + Node clone = new Node( + value: node.Value, + color: node.Color, + parent: parent); clone.LeftChild = node.LeftChild is null ? null : Clone(node.LeftChild, clone); clone.RightChild = node.RightChild is null ? null : Clone(node.RightChild, clone); return clone; diff --git a/Sources/Towel/DataStructures/SortedBinaryTree.cs b/Sources/Towel/DataStructures/SortedBinaryTree.cs index f3e31581..b7206328 100644 --- a/Sources/Towel/DataStructures/SortedBinaryTree.cs +++ b/Sources/Towel/DataStructures/SortedBinaryTree.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace Towel.DataStructures { @@ -31,12 +29,12 @@ public interface ISortedBinaryTree : IDataStructure, /// The value if found or default. /// The exception that occurred if the get failed. /// True if the value was found or false if not. - bool TryGet(Func sift, out T value, out Exception? exception); + bool TryGet(out T? value, out Exception? exception, Func sift); /// Tries to remove a value. /// The compare delegate. This must match the compare delegate of the tree. /// The exception that occurred if the remove failed. /// True if the remove succeeded or false if not. - bool TryRemove(Func sift, out Exception? exception); + bool TryRemove(out Exception? exception, Func sift); /// Invokes a delegate for each entry in the data structure (left to right). /// The delegate to invoke on each item in the structure. void Stepper(StepRef step); @@ -286,8 +284,8 @@ public static StepperRefBreak StepperRefBreakReverse(this ISortedBinaryTre /// The compare delegate. This must match the compare that the Red-Black tree is sorted with. /// The value if it is found. /// True if the value was found or false if not. - public static bool TryGet(this ISortedBinaryTree tree, Func sift, out T value) => - tree.TryGet(sift, out value, out _); + public static bool TryGet(this ISortedBinaryTree tree, out T? value, Func sift) => + tree.TryGet(out value, out _, sift); /// Gets a value. /// The type of value. @@ -295,9 +293,9 @@ public static bool TryGet(this ISortedBinaryTree tree, FuncThe compare delegate. This must match the compare that the Red-Black tree is sorted with. /// The value. public static T? Get(this ISortedBinaryTree tree, Func sift) => - tree.TryGet(sift, out T value, out Exception? exception) + tree.TryGet(out T value, out Exception? exception, sift) ? value - : throw exception; + : throw exception ?? new ArgumentException(nameof(exception), $"{nameof(Get)} failed but the {nameof(exception)} is null"); /// Tries to remove a value. /// The type of value. @@ -305,7 +303,7 @@ public static bool TryGet(this ISortedBinaryTree tree, FuncThe compare delegate. /// True if the remove was successful or false if not. public static bool TryRemove(this ISortedBinaryTree tree, Func sift) => - tree.TryRemove(sift, out _); + tree.TryRemove(out _, sift); /// Removes a value. /// The type of value. @@ -313,9 +311,9 @@ public static bool TryRemove(this ISortedBinaryTree tree, FuncThe compare delegate. public static void Remove(this ISortedBinaryTree tree, Func sift) { - if (!tree.TryRemove(sift, out Exception? exception)) + if (!tree.TryRemove(out Exception? exception, sift)) { - throw exception; + throw exception ?? new ArgumentException(nameof(exception), $"{nameof(Remove)} failed but the {nameof(exception)} is null"); } } diff --git a/Sources/Towel/Meta.cs b/Sources/Towel/Meta.cs index d45ff423..e21b1535 100644 --- a/Sources/Towel/Meta.cs +++ b/Sources/Towel/Meta.cs @@ -551,8 +551,8 @@ string ConvertToCsharpSource(Type type) Type correctGeneric = genericParameters.Dequeue(); result += (firstIteration ? string.Empty : ",") + (correctGeneric.IsGenericParameter - ? (showGenericParameters ? (firstIteration ? string.Empty : " ") + correctGeneric.Name : string.Empty) - : (firstIteration ? string.Empty : " ") + ConvertToCSharpSource(correctGeneric)); + ? (showGenericParameters ? (firstIteration ? string.Empty : " ") + correctGeneric.Name : string.Empty) + : (firstIteration ? string.Empty : " ") + ConvertToCSharpSource(correctGeneric)); firstIteration = false; } result += ">"; diff --git a/Sources/Towel/Towel.xml b/Sources/Towel/Towel.xml index 4568a6dc..bda64d37 100644 --- a/Sources/Towel/Towel.xml +++ b/Sources/Towel/Towel.xml @@ -367,7 +367,15 @@ The sorting technique (must synchronize with this structure's sorting). True of contained, False if not. - + + + Determines if this structure contains an item by a given key. + Runtime: O(ln(Count)), Ω(1) + + The sorting technique (must synchronize with this structure's sorting). + True of contained, False if not. + + Tries to get a value. Runtime: O(ln(Count)), Ω(1) @@ -377,13 +385,30 @@ The exception that occurred if the get failed. True if the get succeeded or false if not. + + + Tries to get a value. + Runtime: O(ln(Count)), Ω(1) + + The compare delegate. + The compare delegate. + The value if found or default. + The exception that occurred if the get failed. + True if the get succeeded or false if not. + Tries to remove a value. The value to remove. The exception that occurred if the remove failed. True if the remove was successful or false if not. - + + Tries to remove a value. + The compare delegate. + The exception that occurred if the remove failed. + True if the remove was successful or false if not. + + Tries to remove a value. The compare delegate. The exception that occurred if the remove failed. @@ -13790,21 +13815,45 @@ The sorting technique (must synchronize with this structure's sorting). True of contained, False if not. - + + + Determines if this structure contains an item by a given key. + Runtime: O(ln(Count)), Ω(1) + + The sifting method. + The sifting method. + True of contained, False if not. + + Tries to get a value. The compare delegate. The value if it was found or default. The exception that occurred if the get failed. True if the value was found or false if not. + + Tries to get a value. + The compare delegate. + The compare delegate. + The value if it was found or default. + The exception that occurred if the get failed. + True if the value was found or false if not. + Tries to remove a value. The value to remove. The exception that occurred if the remove failed. True if the remove was successful or false if not. - + + Tries to remove a value. + The compare delegate. + The exception that occurred if the remove failed. + True if the remove was successful or false if not. + + Tries to remove a value. + The compare delegate. The compare delegate. The exception that occurred if the remove failed. True if the remove was successful or false if not. @@ -14237,14 +14286,14 @@ The compare delegate. This must match the compare delegate of the tree. True if the value is in the tree or false if not. - + Tries to get a value. The compare delegate. This must match the compare delegate of the tree. The value if found or default. The exception that occurred if the get failed. True if the value was found or false if not. - + Tries to remove a value. The compare delegate. This must match the compare delegate of the tree. The exception that occurred if the remove failed. @@ -14475,7 +14524,7 @@ The maximum step value. The stepper of the traversal. - + Tries to get a value. The type of value. The tree to get the value from. diff --git a/Tools/Towel_Testing/Meta.cs b/Tools/Towel_Testing/Meta.cs index dbe1512f..8ae6c6b5 100644 --- a/Tools/Towel_Testing/Meta.cs +++ b/Tools/Towel_Testing/Meta.cs @@ -15,30 +15,30 @@ [TestMethod] public void Type_ConvertToCsharpSource() { // showGenericParameters = false (Type, string)[] testCases = new (Type, string)[] { - (typeof(System.Int32), "System.Int32"), - (typeof(Towel.Mathematics.Symbolics.Expression), "Towel.Mathematics.Symbolics.Expression"), - (typeof(Towel.Mathematics.Symbolics.Constant), "Towel.Mathematics.Symbolics.Constant"), - (typeof(Towel_Testing.A.B.C), "Towel_Testing.A.B.C"), - (typeof(Towel_Testing.A.D.E), "Towel_Testing.A.D.E"), - (typeof(Towel_Testing.A.D<>.E<>), "Towel_Testing.A.D<>.E<>"), - (typeof(System.Collections.Generic.List<(System.String @event, System.Object @class)>), "System.Collections.Generic.List>"), - (typeof(System.Int32?), "System.Nullable"), - (typeof(Towel_Testing.A.D.E), "Towel_Testing.A.D.E"), - (typeof(Towel.DataStructures.IOmnitreePoints<,,,>), "Towel.DataStructures.IOmnitreePoints<,,,>"), - (typeof(Towel.DataStructures.IOmnitreePoints), "Towel.DataStructures.IOmnitreePoints"), - (typeof((int, int, int, int, int, int, int, int, int)), "System.ValueTuple>"), - (typeof(StepStatus), "Towel.StepStatus"), - (typeof(int*), "System.Int32*"), - (typeof(int**), "System.Int32**"), - (typeof(Span), "System.Span"), - (typeof(int[]), "System.Int32[]"), - (typeof(int[][]), "System.Int32[][]"), - (typeof(int[][][]), "System.Int32[][][]"), - (typeof(int[,]), "System.Int32[,]"), - (typeof(int[,,]), "System.Int32[,,]"), - (typeof(int[,,,]), "System.Int32[,,,]"), - (typeof(int[][,,,][]), "System.Int32[][,,,][]"), - (typeof(int[,,,][][,,,]), "System.Int32[,,,][][,,,]"), + (typeof(System.Int32), "System.Int32"), + (typeof(Towel.Mathematics.Symbolics.Expression), "Towel.Mathematics.Symbolics.Expression"), + (typeof(Towel.Mathematics.Symbolics.Constant), "Towel.Mathematics.Symbolics.Constant"), + (typeof(Towel_Testing.A.B.C), "Towel_Testing.A.B.C"), + (typeof(Towel_Testing.A.D.E), "Towel_Testing.A.D.E"), + (typeof(Towel_Testing.A.D<>.E<>), "Towel_Testing.A.D<>.E<>"), + (typeof(System.Collections.Generic.List<(System.String @event, System.Object @class)>), "System.Collections.Generic.List>"), + (typeof(System.Int32?), "System.Nullable"), + (typeof(Towel_Testing.A.D.E), "Towel_Testing.A.D.E"), + (typeof(Towel.DataStructures.IOmnitreePoints<,,,>), "Towel.DataStructures.IOmnitreePoints<,,,>"), + (typeof(Towel.DataStructures.IOmnitreePoints), "Towel.DataStructures.IOmnitreePoints"), + (typeof((int, int, int, int, int, int, int, int, int)), "System.ValueTuple>"), + (typeof(StepStatus), "Towel.StepStatus"), + (typeof(int*), "System.Int32*"), + (typeof(int**), "System.Int32**"), + (typeof(Span), "System.Span"), + (typeof(int[]), "System.Int32[]"), + (typeof(int[][]), "System.Int32[][]"), + (typeof(int[][][]), "System.Int32[][][]"), + (typeof(int[,]), "System.Int32[,]"), + (typeof(int[,,]), "System.Int32[,,]"), + (typeof(int[,,,]), "System.Int32[,,,]"), + (typeof(int[][,,,][]), "System.Int32[][,,,][]"), + (typeof(int[,,,][][,,,]), "System.Int32[,,,][][,,,]"), }; foreach ((Type, string) testCase in testCases) { @@ -60,11 +60,11 @@ [TestMethod] public void Type_ConvertToCsharpSource() { // showGenericParameters = true (Type, string)[] testCases = new (Type, string)[] { - (typeof(System.Collections.Generic.List<>), "System.Collections.Generic.List"), - (typeof(Towel.Mathematics.Symbolics.Constant<>), "Towel.Mathematics.Symbolics.Constant"), - (typeof(Towel_Testing.A.D<>.E<>), "Towel_Testing.A.D.E"), - (typeof(Towel.DataStructures.IOmnitreePoints<,,,>), "Towel.DataStructures.IOmnitreePoints"), - (typeof(Span<>), "System.Span"), + (typeof(System.Collections.Generic.List<>), "System.Collections.Generic.List"), + (typeof(Towel.Mathematics.Symbolics.Constant<>), "Towel.Mathematics.Symbolics.Constant"), + (typeof(Towel_Testing.A.D<>.E<>), "Towel_Testing.A.D.E"), + (typeof(Towel.DataStructures.IOmnitreePoints<,,,>), "Towel.DataStructures.IOmnitreePoints"), + (typeof(Span<>), "System.Span"), }; foreach ((Type, string) testCase in testCases) { From f7401fb0a28d845a1e581851979dc8aaed688390 Mon Sep 17 00:00:00 2001 From: Zachary Patten Date: Wed, 28 Oct 2020 23:01:52 -0400 Subject: [PATCH 05/30] nullable ref and other updates --- Sources/Towel/DataStructures/Graph.cs | 28 +- Sources/Towel/DataStructures/Map.cs | 123 ++--- Sources/Towel/DataStructures/RedBlackTree.cs | 2 +- Sources/Towel/DataStructures/Set.cs | 474 +------------------ Sources/Towel/Statics.cs | 235 ++++----- Sources/Towel/Towel.xml | 147 +----- 6 files changed, 183 insertions(+), 826 deletions(-) diff --git a/Sources/Towel/DataStructures/Graph.cs b/Sources/Towel/DataStructures/Graph.cs index c2c910af..7bac4af3 100644 --- a/Sources/Towel/DataStructures/Graph.cs +++ b/Sources/Towel/DataStructures/Graph.cs @@ -30,7 +30,7 @@ public interface IGraph : IDataStructure, /// Gets all the nodes adjacent to a and performs the provided delegate on each. /// The node to find all the adjacent node to. /// The delegate to perform on each adjacent node to a. - void Neighbors(T a, Action function); + void Neighbors(T a, Action function); /// Adds an edge to the graph starting at a and ending at b. /// The stating point of the edge to add. /// The ending point of the edge to add. @@ -45,7 +45,7 @@ public interface IGraph : IDataStructure, /// Invokes a delegate for each entry in the data structure. /// The delegate to invoke on each item in the structure. /// The resulting status of the iteration. - StepStatus Stepper(Func step); + StepStatus Stepper(Func step); #endregion } @@ -63,9 +63,9 @@ public class GraphSetOmnitree : IGraph public class Edge { /// The starting node of the edge. - public T? Start { get; internal set; } + public T Start { get; internal set; } /// The ending node of the edge. - public T? End { get; internal set; } + public T End { get; internal set; } } #endregion @@ -85,11 +85,11 @@ internal GraphSetOmnitree(GraphSetOmnitree graph) /// The compare delegate for the data structure to use. /// The hash delegate for the datastructure to use. public GraphSetOmnitree( - Func? equate = null, - Func? compare = null, - Func? hash = null) + Func? equate = null, + Func? compare = null, + Func? hash = null) { - equate ??= Statics.Equate; + equate ??= Equate; compare ??= Compare; hash ??= DefaultHash; @@ -198,7 +198,7 @@ public bool Adjacent(T a, T b) /// Gets the neighbors of a node. /// The node to get the neighbors of. /// The step to perform on all the neighbors. - public void Neighbors(T node, Action step) + public void Neighbors(T node, Action step) { if (!_nodes.Contains(node)) { @@ -222,27 +222,27 @@ public void Clear() /// Steps through all the nodes in the graph. /// The action to perform on all the nodes in the graph. - public void Stepper(Action step) => _nodes.Stepper(step); + public void Stepper(Action step) => _nodes.Stepper(step); /// Steps through all the nodes in the graph. /// The action to perform on all the nodes in the graph. /// The status of the stepper operation. - public StepStatus Stepper(Func step) => _nodes.Stepper(step); + public StepStatus Stepper(Func step) => _nodes.Stepper(step); /// Steps through all the edges in the graph. /// The action to perform on all the edges in the graph. - public void Stepper(Action step) => _edges.Stepper(edge => step(edge.Start, edge.End)); + public void Stepper(Action step) => _edges.Stepper(edge => step(edge.Start, edge.End)); /// Steps through all the edges in the graph. /// The action to perform on all the edges in the graph. /// The status of the stepper operation. - public StepStatus Stepper(Func step) => _edges.Stepper(edge => step(edge.Start, edge.End)); + public StepStatus Stepper(Func step) => _edges.Stepper(edge => step(edge.Start, edge.End)); System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); /// Gets the enumerator for the nodes in the graph. /// The enumerator for the nodes in the graph. - public System.Collections.Generic.IEnumerator GetEnumerator() => _nodes.GetEnumerator(); + public System.Collections.Generic.IEnumerator GetEnumerator() => _nodes.GetEnumerator(); #endregion } diff --git a/Sources/Towel/DataStructures/Map.cs b/Sources/Towel/DataStructures/Map.cs index 7dc109e4..ef69fff0 100644 --- a/Sources/Towel/DataStructures/Map.cs +++ b/Sources/Towel/DataStructures/Map.cs @@ -30,7 +30,7 @@ public interface IMap : IDataStructure, /// The value if found or default. /// The exception that occured if not found. /// True if the key was found or false if not. - bool TryGet(K key, out T value, out Exception? exception); + bool TryGet(K key, out T? value, out Exception? exception); /// Sets value in the map. /// The key of the value. /// The value to be set. @@ -41,11 +41,6 @@ public interface IMap : IDataStructure, /// The exception that occured if the add failed. /// True if the value was added or false if not. bool TryAdd(K key, T value, out Exception? exception); - ///// Tries to remove a key-value pair from the map. - ///// The key of the key-value pair to remove. - ///// The exception that occurred if the removal failed. - ///// True if the key-value pair was removed. False if the key-value pair was not found. - //bool TryRemove(K key, out Exception exception); /// Steps through all the values in the map. /// The action to perform on all the values. void Stepper(StepRef step); @@ -99,7 +94,7 @@ public static void Add(this IMap map, K key, T value) { if (!map.TryAdd(key, value, out Exception? exception)) { - throw exception; + throw exception ?? new ArgumentException(nameof(exception), $"{nameof(Add)} failed but the {nameof(exception)} is null"); ; } } @@ -115,7 +110,7 @@ public static void Add(this IMap map, K key, T value) /// The default value to return if the value is not found. /// The value if found or the defautl value. public static T TryGet(this IMap map, K key, T @default) => - map.TryGet(key, out T value, out _) ? value : @default; + map.TryGet(key, out T? value, out _) ? value! : @default; /// Tries to get a value in a map by key. /// The type of values in the map. @@ -124,7 +119,7 @@ public static T TryGet(this IMap map, K key, T @default) => /// The key of the value to get. /// The value of the provided key in the map or default. /// True if the key was found or false if not found. - public static bool TryGet(this IMap map, K key, out T value) => + public static bool TryGet(this IMap map, K key, out T? value) => map.TryGet(key, out value, out _); /// Gets a value in a map by key. @@ -135,11 +130,11 @@ public static bool TryGet(this IMap map, K key, out T value) => /// The value of the provided key in the map. public static T Get(this IMap map, K key) { - if (!map.TryGet(key, out T value, out Exception? exception)) + if (!map.TryGet(key, out T? value, out Exception? exception)) { - throw exception; + throw exception ?? new ArgumentException(nameof(exception), $"{nameof(Get)} failed but the {nameof(exception)} is null"); ; ; } - return value; + return value!; } #endregion @@ -284,7 +279,8 @@ _equate is FuncRuntime equate #region Methods - #region Add + internal int GetLocation(K key) => + (_hash.Do(key) & int.MaxValue) % _table.Length; /// /// Tries to add a value to the map. @@ -296,15 +292,12 @@ _equate is FuncRuntime equate /// True if the value was added or false if not. public bool TryAdd(K key, T value, out Exception? exception) { - _ = key ?? throw new ArgumentNullException(nameof(key)); - _ = value ?? throw new ArgumentNullException(nameof(value)); - int hashCode = _hash.Do(key); - int location = (hashCode & int.MaxValue) % _table.Length; + int location = GetLocation(key); for (Node? node = _table[location]; node is not null; node = node.Next) { if (_equate.Do(node.Key, key)) { - exception = new ArgumentException("Attempting to add a duplicate keyed value to a map.", nameof(value)); + exception = new ArgumentException("Attempting to add a duplicate key to a map.", nameof(key)); return false; } } @@ -330,22 +323,14 @@ public bool TryAdd(K key, T value, out Exception? exception) return true; } - #endregion - - #region Get - /// Tries to get a value by key. /// The key of the value to get. /// The value if found or default. /// The exception that occured if not found. /// True if the key was found or false if not. - public bool TryGet(K key, out T value, out Exception? exception) + public bool TryGet(K key, out T? value, out Exception? exception) { - _ = key ?? throw new ArgumentNullException(nameof(key)); - - int hashCode = _hash.Do(key); - int location = (hashCode & int.MaxValue) % _table.Length; - + int location = GetLocation(key); for (Node? node = _table[location]; node is not null; node = node.Next) { if (_equate.Do(node.Key, key)) @@ -355,16 +340,11 @@ public bool TryGet(K key, out T value, out Exception? exception) return true; } } - value = default; exception = new ArgumentException("Attempting to get a value from the map that has not been added.", nameof(key)); return false; } - #endregion - - #region Set - /// /// Sets value in the map. /// Runtime: O(n), Ω(1), ε(1) @@ -373,10 +353,7 @@ public bool TryGet(K key, out T value, out Exception? exception) /// The value to be set. public void Set(K key, T value) { - _ = key ?? throw new ArgumentNullException(nameof(key)); - _ = value ?? throw new ArgumentNullException(nameof(value)); - int hashCode = _hash.Do(key); - int location = (hashCode & int.MaxValue) % _table.Length; + int location = GetLocation(key); for (Node? node = _table[location]; node is not null; node = node.Next) { if (_equate.Do(node.Key, key)) @@ -405,10 +382,6 @@ public void Set(K key, T value) } } - #endregion - - #region Remove - /// Tries to remove a keyed value. /// The key of the value to remove. /// The exception that occurred if the removal failed. @@ -437,39 +410,28 @@ public bool TryRemove(K key, out Exception? exception) /// True if the removal was successful for false if not. public bool TryRemoveWithoutTrim(K key, out Exception? exception) { - _ = key ?? throw new ArgumentNullException(nameof(key)); - int hashCode = _hash.Do(key); - int location = (hashCode & int.MaxValue) % _table.Length; - if (_equate.Do(_table[location].Key, key)) - { - _table[location] = _table[location].Next; - _count--; - exception = null; - return true; - } - else + int location = GetLocation(key); + for (Node? node = _table[location], previous = null; node is not null; previous = node, node = node.Next) { - for (Node? node = _table[location]; node.Next is not null; node = node.Next) + if (_equate.Do(node.Key, key)) { - if (_equate.Do(node.Next.Key, key)) + if (previous is null) + { + _table[location] = node.Next; + } + else { - node.Next = node.Next.Next; - _count--; - exception = null; - return true; + previous.Next = node.Next; } + _count--; + exception = null; + return true; } - exception = new ArgumentException("Attempting to remove a keyed value that is no in a value.", nameof(key)); - return false; } + exception = new ArgumentException("Attempting to remove a key that is no in a map.", nameof(key)); + return false; } - #endregion - - #region Resize - - /// Resizes the table. - /// The desired size of the table. internal void Resize(int tableSize) { if (tableSize == _table.Length) @@ -495,10 +457,6 @@ internal void Resize(int tableSize) } } - #endregion - - #region Trim - /// /// Trims the table to an appropriate size based on the current count. /// Runtime: O(n), Ω(1) @@ -513,10 +471,6 @@ public void Trim() Resize(tableSize); } - #endregion - - #region Clone - /// /// Creates a shallow clone of this map. /// Runtime: Θ(n) @@ -524,10 +478,6 @@ public void Trim() /// A shallow clone of this map. public MapHashLinked Clone() => new MapHashLinked(this); - #endregion - - #region Contains - /// /// Determines if a value has been added to a map. /// Runtime: O(n), Ω(1), ε(1) @@ -536,8 +486,7 @@ public void Trim() /// True if the value has been added to the map or false if not. public bool Contains(K key) { - int hashCode = _hash.Do(key); - int location = (hashCode & int.MaxValue) % _table.Length; + int location = GetLocation(key); for (Node? node = _table[location]; node is not null; node = node.Next) { if (_equate.Do(node.Key, key)) @@ -548,10 +497,6 @@ public bool Contains(K key) return false; } - #endregion - - #region Clear - /// /// Removes all the values in the map. /// Runtime: O(1) @@ -562,10 +507,6 @@ public void Clear() _count = 0; } - #endregion - - #region Stepper And IEnumerable - /// public void Stepper(Action step) { @@ -693,10 +634,6 @@ public System.Collections.Generic.IEnumerator GetEnumerator() } } - #endregion - - #region ToArray - /// /// Puts all the values in this map into an array. /// Runtime: Θ(n) @@ -716,8 +653,6 @@ public T[] ToArray() } #endregion - - #endregion } /// An unsorted structure of unique items. diff --git a/Sources/Towel/DataStructures/RedBlackTree.cs b/Sources/Towel/DataStructures/RedBlackTree.cs index bfa50e91..803fc10d 100644 --- a/Sources/Towel/DataStructures/RedBlackTree.cs +++ b/Sources/Towel/DataStructures/RedBlackTree.cs @@ -82,7 +82,7 @@ Node Clone(Node node, Node parent) } _compare = tree._compare; _count = tree._count; - _root = tree._root is null ? null : Clone(tree._root, null); + _root = Clone(tree._root, null); } #endregion diff --git a/Sources/Towel/DataStructures/Set.cs b/Sources/Towel/DataStructures/Set.cs index 03df6775..5af5ef82 100644 --- a/Sources/Towel/DataStructures/Set.cs +++ b/Sources/Towel/DataStructures/Set.cs @@ -133,7 +133,8 @@ _equate is FuncRuntime func #region Methods - #region Add + internal int GetLocation(T value) => + (_hash.Do(value) & int.MaxValue) % _table.Length; /// /// Adds a value to the set. @@ -143,11 +144,7 @@ _equate is FuncRuntime func /// The exception that occurred if the add failed. public bool TryAdd(T value, out Exception? exception) { - _ = value ?? throw new ArgumentNullException(nameof(value)); - - int hashCode = _hash.Do(value); - int location = (hashCode & int.MaxValue) % _table.Length; - + int location = GetLocation(value); for (Node? node = _table[location]; node is not null; node = node.Next) { if (_equate.Do(node.Value, value)) @@ -156,9 +153,7 @@ public bool TryAdd(T value, out Exception? exception) return false; } } - _table[location] = new Node(value: value, next: _table[location]); - if (++_count > _table.Length * _maxLoadFactor) { float tableSizeFloat = (_count * 2) * (1 / _maxLoadFactor); @@ -177,10 +172,6 @@ public bool TryAdd(T value, out Exception? exception) return true; } - #endregion - - #region Remove - /// Tries to remove a value from the set. /// The value to remove. /// The exception that occurred if the remove failed. @@ -191,14 +182,11 @@ public bool TryRemove(T value, out Exception? exception) { if (_table.Length > 2 && _count < _table.Length * _minLoadFactor) { - // calculate new table size int tableSize = (int)(_count * (1 / _maxLoadFactor)); while (!IsPrime(tableSize)) { tableSize++; } - - // resize the table Resize(tableSize); } return true; @@ -212,9 +200,7 @@ public bool TryRemove(T value, out Exception? exception) /// True if the remove was successful or false if not. public bool TryRemoveWithoutTrim(T value, out Exception? exception) { - _ = value ?? throw new ArgumentNullException(nameof(value)); - int hashCode = _hash.Do(value); - int location = (hashCode & int.MaxValue) % _table.Length; + int location = GetLocation(value); for (Node? node = _table[location], previous = null; node is not null; previous = node, node = node.Next) { if (_equate.Do(node.Value, value)) @@ -236,10 +222,6 @@ public bool TryRemoveWithoutTrim(T value, out Exception? exception) return false; } - #endregion - - #region Resize - /// Resizes the table. /// The desired size of the table. internal void Resize(int tableSize) @@ -248,29 +230,20 @@ internal void Resize(int tableSize) { return; } - Node?[] temp = _table; _table = new Node[tableSize]; - for (int i = 0; i < temp.Length; i++) { for (Node? node = temp[i]; node is not null; node = temp[i]) { temp[i] = node.Next; - - int hashCode = _hash.Do(node.Value); - int location = (hashCode & int.MaxValue) % _table.Length; - + int location = GetLocation(node.Value); node.Next = _table[location]; _table[location] = node; } } } - #endregion - - #region Trim - /// /// Trims the table to an appropriate size based on the current count. /// Runtime: O(n), Ω(1) @@ -285,10 +258,6 @@ public void Trim() Resize(tableSize); } - #endregion - - #region Clone - /// /// Creates a shallow clone of this set. /// Runtime: Θ(n) @@ -296,10 +265,6 @@ public void Trim() /// A shallow clone of this set. public SetHashLinked Clone() => new SetHashLinked(this); - #endregion - - #region Contains - /// /// Determines if a value has been added to a set. /// Runtime: O(n), Ω(1), ε(1) @@ -308,9 +273,7 @@ public void Trim() /// True if the value has been added to the set or false if not. public bool Contains(T value) { - int hashCode = _hash.Do(value); - int location = (hashCode & int.MaxValue) % _table.Length; - + int location = GetLocation(value); for (Node? node = _table[location]; node is not null; node = node.Next) { if (_equate.Do(node.Value, value)) @@ -321,10 +284,6 @@ public bool Contains(T value) return false; } - #endregion - - #region Clear - /// /// Removes all the values in the set. /// Runtime: O(1) @@ -335,10 +294,6 @@ public void Clear() _count = 0; } - #endregion - - #region Stepper And IEnumerable - /// public void Stepper(Action step) { @@ -382,16 +337,12 @@ public System.Collections.Generic.IEnumerator GetEnumerator() } } - #endregion - - #region ToArray - /// /// Puts all the values in this set into an array. /// Runtime: Θ( + ) /// /// An array with all the values in the set. - public T?[] ToArray() + public T[] ToArray() { T[] array = new T[_count]; for (int i = 0, index = 0; i < _table.Length; i++) @@ -405,8 +356,6 @@ public System.Collections.Generic.IEnumerator GetEnumerator() } #endregion - - #endregion } /// An unsorted structure of unique items implemented as a hashed table of linked lists. @@ -469,413 +418,4 @@ internal SetHashLinked(SetHashLinked set) #endregion } - - /// An unsorted structure of unique items. - /// The type of structure to use for each index of the hash table. - /// The type of values to store in the set. - public class Set : ISet, - // Structure Properties - DataStructure.IHashing - where Structure : - class, - IDataStructure, - DataStructure.IAddable, - DataStructure.IRemovable, - DataStructure.IAuditable - { - internal const float _maxLoadFactor = .7f; - internal const float _minLoadFactor = .3f; - - internal StructureFactory _factory; - internal Func _equate; - internal Func _hash; - internal Structure[] _table; - internal int _count; - - #region Delegates - - /// Factory for constructing new structures. - /// A delegate for equality checks. - /// A delegate for computing hash codes. - /// The constructed structure. - public delegate Structure StructureFactory(Func equate, Func hash); - - /// Clones a structure. - /// The structure to clone. - /// A clone of the structure. - public delegate Structure StructureClone(Structure structure); - - #endregion - - #region Constructors - - /// - /// Constructs a hashed set. - /// Runtime: O(1) - /// - /// The factory delegate. - /// The equate delegate. - /// The hashing function. - /// The expected count of the set. - public Set( - StructureFactory factory, - Func? equate = null, - Func? hash = null, - int? expectedCount = null) - { - if (expectedCount.HasValue && expectedCount.Value > 0) - { - int tableSize = (int)(expectedCount.Value * (1 / _maxLoadFactor)); - while (!IsPrime(tableSize)) - { - tableSize++; - } - _table = new Structure[tableSize]; - } - else - { - _table = new Structure[2]; - } - _factory = factory; - _equate = equate ?? Statics.Equate; - _hash = hash ?? DefaultHash; - _count = 0; - } - - /// - /// This constructor is for cloning purposes. - /// Runtime: O(n) - /// - /// The set to clone. - /// A delegate for cloning the structures. - internal Set(Set set, StructureClone clone) - { - _factory = set._factory; - _equate = set._equate; - _hash = set._hash; - _table = new Structure[set._table.Length]; - for (int i = 0; i < _table.Length; i++) - { - if (!(set._table[i] is null)) - { - _table[i] = clone(set._table[i]); - } - } - _count = set._count; - } - - #endregion - - #region Properties - - /// - /// The current size of the hashed table. - /// Runtime: O(1) - /// - public int TableSize => _table.Length; - - /// - /// The current number of values in the set. - /// Runtime: O(1) - /// - public int Count => _count; - - /// - /// The delegate for computing hash codes. - /// Runtime: O(1) - /// - public Func Hash => _hash; - - /// - /// The delegate for equality checking. - /// Runtime: O(1) - /// - public Func Equate => _equate; - - #endregion - - #region Methods - - #region Add - - /// - /// Adds a value to the hash table. - /// Runtime: O(n), Ω(1), ε(1) - /// - /// The key value to use as the look-up reference in the hash table. - /// The exception that occurred if the add failed. - public bool TryAdd(T value, out Exception? exception) - { - _ = value ?? throw new ArgumentNullException(nameof(value)); - - // compute the hash code and relate it to the current table - int hashCode = _hash(value); - int location = (hashCode & int.MaxValue) % _table.Length; - - // duplicate value check - if (_table[location].Contains(value)) - { - exception = new ArgumentException("Attempting to add a duplicate value to a set.", nameof(value)); - return false; - } - - // add the value - if (_table[location] is null) - { - _table[location] = _factory(_equate, _hash); - } - _table[location].Add(value); - - // check if the table needs to grow - if (++_count > _table.Length * _maxLoadFactor) - { - if (_count == int.MaxValue) - { - throw new InvalidOperationException("maximum size of hash table reached."); - } - - // calculate new table size - int tableSize = (int)((_count * 2) * (1 / _maxLoadFactor)); - while (!IsPrime(tableSize)) - { - tableSize++; - } - - // resize the table - Resize(tableSize); - } - - exception = null; - return true; - } - - #endregion - - #region Remove - - /// - /// Removes a value from the set. - /// Runtime: O(n), Ω(1), ε(1) - /// - /// The value to remove. - /// The exception that occurred if the remove failed. - public bool TryRemove(T value, out Exception? exception) - { - if (TryRemoveWithoutTrim(value, out exception)) - { - if (_table.Length > 2 && _count < _table.Length * _minLoadFactor) - { - // calculate new table size - int tableSize = (int)(_count * (1 / _maxLoadFactor)); - while (!IsPrime(tableSize)) - { - tableSize++; - } - - // resize the table - Resize(tableSize); - } - return true; - } - return false; - } - - /// - /// Removes a value from the set. - /// Runtime: O(n), Ω(1), ε(1) - /// - /// The value to remove. - /// The exception that occurred if the remove failed. - public bool TryRemoveWithoutTrim(T value, out Exception? exception) - { - _ = value ?? throw new ArgumentNullException(nameof(value)); - - // compute the hash code and relate it to the current table - int hashCode = _hash(value); - int location = (hashCode & int.MaxValue) % _table.Length; - - // remove the value - if (_table[location].TryRemove(value, out exception)) - { - _count--; - return true; - } - else - { - return false; - } - } - - #endregion - - #region Resize - - /// Resizes the table. - /// The desired size of the table. - internal void Resize(int tableSize) - { - // ensure the desired size is different than the current - if (tableSize == _table.Length) - { - return; - } - - Structure[] temp = _table; - _table = new Structure[tableSize]; - - // iterate through all the values - for (int i = 0; i < temp.Length; i++) - { - temp[i].Stepper(x => - { - // compute the hash code and relate it to the current table - int hashCode = _hash(x); - int location = (hashCode & int.MaxValue) % _table.Length; - - _table[location].Add(x); - }); - } - } - - #endregion - - #region Clone - - /// - /// Creates a shallow clone of this set. - /// Runtime: Θ(n) - /// - /// A shallow clone of this set. - public Set Clone(StructureClone clone) => new Set(this, clone); - - #endregion - - #region Contains - - /// - /// Determines if a value has been added to a set. - /// Runtime: O(n), Ω(1), ε(1) - /// - /// The value to look for in the set. - /// True if the value has been added to the set or false if not. - public bool Contains(T value) - { - _ = value ?? throw new ArgumentNullException(nameof(value)); - - // compute the hash code and relate it to the current table - int hashCode = _hash(value); - int location = (hashCode & int.MaxValue) % _table.Length; - - return _table[location].Contains(value); - } - - #endregion - - #region Clear - - /// - /// Removes all the values in the set. - /// Runtime: O(1) - /// - public void Clear() - { - _table = new Structure[2]; - _count = 0; - } - - #endregion - - #region Trim - - /// - /// Trims the table to an appropriate size based on the current count. - /// Runtime: O(n), Ω(1) - /// - public void Trim() - { - int tableSize = _count; - while (!IsPrime(tableSize)) - { - tableSize++; - } - Resize(tableSize); - } - - #endregion - - #region Stepper And IEnumerable - - /// - public void Stepper(Action step) - { - for (int i = 0; i < _table.Length; i++) - { - if (_table[i] is not null) - { - _table[i].Stepper(step); - } - } - } - - /// - public StepStatus Stepper(Func step) - { - for (int i = 0; i < _table.Length; i++) - { - if (_table[i] is not null) - { - if (_table[i].Stepper(step) is Break) - { - return Break; - } - } - } - return Continue; - } - - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); - - /// Gets the enumerator for the set. - /// The enumerator for the set. - public System.Collections.Generic.IEnumerator GetEnumerator() - { - for (int i = 0; i < _table.Length; i++) - { - if (_table[i] is not null) - { - foreach (T value in _table[i]) - { - yield return value; - } - } - } - } - - #endregion - - #region ToArray - - /// - /// Puts all the values in this set into an array. - /// Runtime: Θ(n) - /// - /// An array with all the values in the set. - public T?[] ToArray() - { - T?[] array = new T[_count]; - int index = 0; - for (int i = 0; i < _table.Length; i++) - { - if (_table[i] is not null) - { - _table[i].Stepper(x => array[index++] = x); - } - } - return array; - } - - #endregion - - #endregion - } } diff --git a/Sources/Towel/Statics.cs b/Sources/Towel/Statics.cs index 8489315e..baf27337 100644 --- a/Sources/Towel/Statics.cs +++ b/Sources/Towel/Statics.cs @@ -139,16 +139,16 @@ public static T sourceof(T expression, out string source, [CallerArgumentExpr /// - Success: True if the parse was successful; False if not. /// - Value: The value if the parse was successful or default if not. /// - public static (bool Success, A Value) TryParse(string @string) => + public static (bool Success, A? Value) TryParse(string @string) => (TryParseImplementation.Function(@string, out A value), value); internal static class TryParseImplementation { - internal delegate TResult TryParse(T1 arg1, out T2 arg2); + internal delegate TResult TryParse(T1 arg1, out T2? arg2); - internal static TryParse Function = (string @string, out A value) => + internal static TryParse Function = (string @string, out A? value) => { - static bool Fail(string @string, out A value) + static bool Fail(string @string, out A? value) { value = default; return false; @@ -180,7 +180,7 @@ static bool Fail(string @string, out A value) } else { - MethodInfo methodInfo = Meta.GetTryParseMethod(); + MethodInfo? methodInfo = Meta.GetTryParseMethod(); Function = methodInfo is null ? Fail : methodInfo.CreateDelegate>(); @@ -197,7 +197,11 @@ static bool Fail(string @string, out A value) /// The generic type of the hash operation. /// The item to get the hash code of. /// The computed hash code using the base GetHashCode instance method. - public static int DefaultHash(T value) => value.GetHashCode(); + public static int DefaultHash(T value) + { + _ = value ?? throw new ArgumentNullException(nameof(value)); + return value.GetHashCode(); + } #endregion @@ -274,6 +278,7 @@ public static void Switch(params (SwitchSyntax.Condition, Action)[] possibleActi /// Definitions for Switch syntax. public static class SwitchSyntax { + /// Delegate with params intended to be used with the Switch syntax. public delegate void ParamsAction(params (A, B)[] values); internal static ParamsAction, Action> Do(T value) => @@ -301,8 +306,10 @@ internal static void Do(params (Condition Condition, Action Action)[] possibleAc } } + /// Intended to be used with Switch syntax. public enum Keyword { + /// The default keyword for the the Switch syntax. Default, } @@ -371,8 +378,8 @@ public struct ChanceSyntax public static Random Algorithm = new Random(); #pragma warning restore CA2211 // Non-constant fields should not be visible -//#pragma warning disable IDE0060 // Remove unused parameter #pragma warning disable IDE0075 // Simplify conditional expression +#pragma warning disable IDE0060 // Remove unused parameter /// Creates a chance from a percentage that will be evaluated at runtime. /// The value of the percentage. @@ -385,8 +392,8 @@ public struct ChanceSyntax percentage is 0d ? false : Algorithm.NextDouble() < percentage / 100d; +#pragma warning restore IDE0060 // Remove unused parameter #pragma warning restore IDE0075 // Simplify conditional expression -//#pragma warning restore IDE0060 // Remove unused parameter } #endregion @@ -460,7 +467,7 @@ public static OperatorValidated.Inequality operator >(Inequality a, T b) = /// This member is not intended to be invoked. /// This member is not intended to be invoked. [Obsolete(TowelConstants.NotIntended, true)] - public override bool Equals(object obj) => throw new InequalitySyntaxException(); + public override bool Equals(object? obj) => throw new InequalitySyntaxException(); /// This member is not intended to be invoked. /// This member is not intended to be invoked. [Obsolete(TowelConstants.NotIntended, true)] @@ -531,7 +538,7 @@ public static Inequality operator >(Inequality a, T b) => /// This member is not intended to be invoked. /// This member is not intended to be invoked. [Obsolete(TowelConstants.NotIntended, true)] - public override bool Equals(object obj) => throw new InequalitySyntaxException(); + public override bool Equals(object? obj) => throw new InequalitySyntaxException(); /// This member is not intended to be invoked. /// This member is not intended to be invoked. [Obsolete(TowelConstants.NotIntended, true)] @@ -703,13 +710,13 @@ public void RemoveAt(int index) /// Converts a universal quantification to a sorted . /// The universal quantification to be converted. public static implicit operator System.Collections.Generic.SortedSet(UniversalQuantification universalQuantification) => new System.Collections.Generic.SortedSet(universalQuantification.Value); - /// Converts a universal quantification to an . + /// Converts a universal quantification to an Action<Action<T>>. /// The universal quantification to be converted. public static implicit operator Action>(UniversalQuantification universalQuantification) => universalQuantification.Value.ToStepper(); /// Converts a universal quantification to an . /// The universal quantification to be converted. public static implicit operator StepperRef(UniversalQuantification universalQuantification) => universalQuantification.Value.ToStepperRef(); - /// Converts a universal quantification to an . + /// Converts a universal quantification to an Func<Func<T, StepStatus>, StepStatus>. /// The universal quantification to be converted. public static implicit operator Func, StepStatus>(UniversalQuantification universalQuantification) => universalQuantification.Value.ToStepperBreak(); /// Converts a universal quantification to an . @@ -836,7 +843,7 @@ public static bool Equate(int start, int end, A a = default, B /// The second span of the equate. /// The element equate function. /// True if the spans are equal; False if not. - public static bool Equate(Span a, Span b, Func equate = default) => + public static bool Equate(Span a, Span b, Func? equate = default) => Equate(0, a.Length - 1, a, b, equate); /// Determines if two spans are equal. @@ -858,7 +865,7 @@ public static bool Equate(Span a, Span b, Equate equate = defau /// The second span of the equate. /// The element equate function. /// True if the spans are equal; False if not. - public static bool Equate(int start, int end, Span a, Span b, Func equate = default) => + public static bool Equate(int start, int end, Span a, Span b, Func? equate = default) => Equate>(start, end, a, b, equate ?? Equate); /// Determines if two spans are equal. @@ -1113,7 +1120,7 @@ internal static class CompareImplementation ParameterExpression A = Expression.Parameter(typeof(A)); ParameterExpression B = Expression.Parameter(typeof(B)); - Expression lessThanPredicate = + Expression? lessThanPredicate = typeof(A).IsPrimitive && typeof(B).IsPrimitive ? Expression.LessThan(A, B) : !(Meta.GetLessThanMethod() is null) @@ -1122,7 +1129,7 @@ internal static class CompareImplementation ? Expression.GreaterThan(B, A) : null; - Expression greaterThanPredicate = + Expression? greaterThanPredicate = typeof(A).IsPrimitive && typeof(B).IsPrimitive ? Expression.GreaterThan(A, B) : !(Meta.GetGreaterThanMethod() is null) @@ -1625,8 +1632,8 @@ internal static class IsIntegerImplementation { internal static Func Function = a => { - MethodInfo methodInfo = Meta.GetIsIntegerMethod(); - if (!(methodInfo is null)) + MethodInfo? methodInfo = Meta.GetIsIntegerMethod(); + if (methodInfo is not null) { Function = methodInfo.CreateDelegate>(); return Function(a); @@ -1656,8 +1663,8 @@ internal static class IsNonNegativeImplementation { internal static Func Function = a => { - MethodInfo methodInfo = Meta.GetIsNonNegativeMethod(); - if (!(methodInfo is null)) + MethodInfo? methodInfo = Meta.GetIsNonNegativeMethod(); + if (methodInfo is not null) { Function = methodInfo.CreateDelegate>(); return Function(a); @@ -1685,8 +1692,8 @@ internal static class IsNegativeImplementation { internal static Func Function = a => { - MethodInfo methodInfo = Meta.GetIsNegativeMethod(); - if (!(methodInfo is null)) + MethodInfo? methodInfo = Meta.GetIsNegativeMethod(); + if (methodInfo is not null) { Function = methodInfo.CreateDelegate>(); return Function(a); @@ -1715,8 +1722,8 @@ internal static class IsPositiveImplementation { internal static Func Function = a => { - MethodInfo methodInfo = Meta.GetIsPositiveMethod(); - if (!(methodInfo is null)) + MethodInfo? methodInfo = Meta.GetIsPositiveMethod(); + if (methodInfo is not null) { Function = methodInfo.CreateDelegate>(); return Function(a); @@ -1744,8 +1751,8 @@ internal static class IsEvenImplementation { internal static Func Function = a => { - MethodInfo methodInfo = Meta.GetIsEvenMethod(); - if (!(methodInfo is null)) + MethodInfo? methodInfo = Meta.GetIsEvenMethod(); + if (methodInfo is not null) { Function = methodInfo.CreateDelegate>(); return Function(a); @@ -1773,8 +1780,8 @@ internal static class IsOddImplementation { internal static Func Function = a => { - MethodInfo methodInfo = Meta.GetIsOddMethod(); - if (!(methodInfo is null)) + MethodInfo? methodInfo = Meta.GetIsOddMethod(); + if (methodInfo is not null) { Function = methodInfo.CreateDelegate>(); return Function(a); @@ -1807,8 +1814,8 @@ internal static class IsPrimeImplementation { internal static Func Function = a => { - MethodInfo methodInfo = Meta.GetIsPrimeMethod(); - if (!(methodInfo is null)) + MethodInfo? methodInfo = Meta.GetIsPrimeMethod(); + if (methodInfo is not null) { Function = methodInfo.CreateDelegate>(); return Function(a); @@ -2154,8 +2161,8 @@ internal static class FactorialImplementation { internal static Func Function = a => { - MethodInfo methodInfo = Meta.GetFactorialMethod(); - if (!(methodInfo is null)) + MethodInfo? methodInfo = Meta.GetFactorialMethod(); + if (methodInfo is not null) { Function = methodInfo.CreateDelegate>(); return Function(a); @@ -2289,7 +2296,7 @@ public static IMap Occurences(Func equate, Func h /// The equality delegate. /// The hash code delegate. /// The occurence map of the data. - public static IMap Occurences(Action> stepper, Func equate = null, Func hash = null) + public static IMap Occurences(Action> stepper, Func? equate = null, Func? hash = null) { IMap map = new MapHashLinked(equate, hash); stepper(a => @@ -2353,7 +2360,7 @@ public static void Mode(Action step, Func equate, Func /// The equality delegate. /// The hash code delegate /// The modes of the data set. - public static void Mode(Action> stepper, Action step, Func equate = null, Func hash = null) + public static void Mode(Action> stepper, Action step, Func? equate = null, Func? hash = null) { int maxOccurences = -1; IMap map = new MapHashLinked(equate, hash); @@ -3402,9 +3409,9 @@ public static int HammingDistance( GetA a = default, GetB b = default, Equals equals = default) - where GetA : IFunc - where GetB : IFunc - where Equals : IFunc + where GetA : struct, IFunc + where GetB : struct, IFunc + where Equals : struct, IFunc { if (length < 0) { @@ -3439,7 +3446,7 @@ public static int HammingDistance( ReadOnlySpan a, ReadOnlySpan b, Equals equals = default) - where Equals : IFunc + where Equals : struct, IFunc { if (a.Length != b.Length) { @@ -3477,9 +3484,9 @@ public static int LevenshteinDistanceRecursive( GetA a = default, GetB b = default, Equals equals = default) - where GetA : IFunc - where GetB : IFunc - where Equals : IFunc + where GetA : struct, IFunc + where GetB : struct, IFunc + where Equals : struct, IFunc { if (a_length < 0) { @@ -3522,7 +3529,7 @@ public static int LevenshteinDistanceRecursive( ReadOnlySpan a, ReadOnlySpan b, Equals equals = default) - where Equals : IFunc + where Equals : struct, IFunc { int LDR( ReadOnlySpan a, @@ -3559,9 +3566,9 @@ public static int LevenshteinDistanceIterative( GetA a = default, GetB b = default, Equals equals = default) - where GetA : IFunc - where GetB : IFunc - where Equals : IFunc + where GetA : struct, IFunc + where GetB : struct, IFunc + where Equals : struct, IFunc { if (a_length < 0) { @@ -3615,7 +3622,7 @@ public static int LevenshteinDistanceIterative( ReadOnlySpan a, ReadOnlySpan b, Equals equals = default) - where Equals : IFunc + where Equals : struct, IFunc { int a_length = a.Length + 1; int b_length = b.Length + 1; @@ -3730,7 +3737,7 @@ void Swap(int a, int b) } /// - public static void PermuteRecursive(Span span, Action action = default) => + public static void PermuteRecursive(Span span, Action action) => PermuteRecursive(span, action); /// @@ -3739,7 +3746,7 @@ public static void PermuteRecursive(Span span, Action action = def PermuteRecursive(span, action); /// - public static void PermuteRecursive(Span span, Action action = default, Status status = default) + public static void PermuteRecursive(Span span, Action action, Status status = default) where Status : struct, IFunc => PermuteRecursive(span, action); @@ -3821,7 +3828,7 @@ void Swap(int a, int b) } /// - public static void PermuteIterative(Span span, Action action = default) => + public static void PermuteIterative(Span span, Action action) => PermuteIterative(span, action); /// @@ -3830,7 +3837,7 @@ public static void PermuteIterative(Span span, Action action = def PermuteIterative(span, action); /// - public static void PermuteIterative(Span span, Action action = default, Status status = default) + public static void PermuteIterative(Span span, Action action, Status status = default) where Status : struct, IFunc => PermuteIterative(span, action, status); @@ -3931,7 +3938,7 @@ public static (bool Found, int Index, T Value) SearchBinary(T[] array, #endif /// - public static (bool Found, int Index, T Value) SearchBinary(int length, Func get, Func sift) + public static (bool Found, int Index, T? Value) SearchBinary(int length, Func get, Func sift) { _ = get ?? throw new ArgumentNullException(nameof(get)); _ = sift ?? throw new ArgumentNullException(nameof(sift)); @@ -3939,7 +3946,7 @@ public static (bool Found, int Index, T Value) SearchBinary(int length, Func< } /// - public static (bool Found, int Index, T Value) SearchBinary(int index, int length, Get get = default, Sift sift = default) + public static (bool Found, int Index, T? Value) SearchBinary(int index, int length, Get get = default, Sift sift = default) where Get : IFunc where Sift : IFunc { @@ -3977,23 +3984,23 @@ public static (bool Found, int Index, T Value) SearchBinary(int in } /// - public static (bool Found, int Index, T Value) SearchBinary(ReadOnlySpan span, T element, Func compare = default) => + public static (bool Found, int Index, T? Value) SearchBinary(ReadOnlySpan span, T element, Func compare = default) => SearchBinary>>(span, new SiftFromCompareAndValue>(element, compare ?? Compare)); /// - public static (bool Found, int Index, T Value) SearchBinary(ReadOnlySpan span, Func sift) + public static (bool Found, int Index, T? Value) SearchBinary(ReadOnlySpan span, Func sift) { _ = sift ?? throw new ArgumentNullException(nameof(sift)); return SearchBinary>(span, sift); } /// - public static (bool Found, int Index, T Value) SearchBinary(ReadOnlySpan span, T element, Compare compare = default) + public static (bool Found, int Index, T? Value) SearchBinary(ReadOnlySpan span, T element, Compare compare = default) where Compare : IFunc => SearchBinary>(span, new SiftFromCompareAndValue(element, compare)); /// - public static (bool Found, int Index, T Value) SearchBinary(ReadOnlySpan span, Sift sift = default) + public static (bool Found, int Index, T? Value) SearchBinary(ReadOnlySpan span, Sift sift = default) where Sift : IFunc { if (span.IsEmpty) @@ -4096,7 +4103,7 @@ public struct GraphSearchStatusStruct internal abstract class BaseAlgorithmNode where AlgorithmNode : BaseAlgorithmNode { - internal AlgorithmNode Previous; + internal AlgorithmNode? Previous; internal Node Value; } @@ -4116,16 +4123,16 @@ internal class AstarNode : BaseAlgorithmNode { internal Node Value; - internal PathNode Next; + internal PathNode? Next; } internal static Action> BuildPath(BaseAlgorithmNode node) where AlgorithmNode : BaseAlgorithmNode { - PathNode start = null; - for (BaseAlgorithmNode current = node; !(current is null); current = current.Previous) + PathNode? start = null; + for (BaseAlgorithmNode? current = node; current is not null; current = current.Previous) { - PathNode temp = start; + PathNode? temp = start; start = new PathNode() { Value = current.Value, @@ -4134,7 +4141,7 @@ internal static Action> BuildPath(BaseAlgorith } return step => { - PathNode current = start; + PathNode? current = start; while (!(current is null)) { step(current.Value); @@ -4189,31 +4196,31 @@ public CompareResult Do(DijkstraNode a, DijkstraNode throw new DocumentationMethodException(); /// - public static Action> SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchCost cost, SearchGoal goal, out Numeric totalCost) => + public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchCost cost, SearchGoal goal, out Numeric totalCost) => SearchGraph(start, neighbors, heuristic, cost, node => goal(node) ? GraphSearchStatus.Goal : GraphSearchStatus.Continue, out totalCost); /// - public static Action> SearchGraph(Node start, IGraph graph, SearchHeuristic heuristic, SearchCost cost, SearchGoal goal, out Numeric totalCost) => + public static Action>? SearchGraph(Node start, IGraph graph, SearchHeuristic heuristic, SearchCost cost, SearchGoal goal, out Numeric totalCost) => SearchGraph(start, graph.Neighbors, heuristic, cost, goal, out totalCost); /// - public static Action> SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchCost cost, Node goal, out Numeric totalCost) => + public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchCost cost, Node goal, out Numeric totalCost) => SearchGraph(start, neighbors, heuristic, cost, goal, Equate, out totalCost); /// - public static Action> SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchCost cost, Node goal, Func equate, out Numeric totalCost) => + public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchCost cost, Node goal, Func equate, out Numeric totalCost) => SearchGraph(start, neighbors, heuristic, cost, node => equate(node, goal), out totalCost); /// - public static Action> SearchGraph(Node start, IGraph graph, SearchHeuristic heuristic, SearchCost cost, Node goal, out Numeric totalCost) => + public static Action>? SearchGraph(Node start, IGraph graph, SearchHeuristic heuristic, SearchCost cost, Node goal, out Numeric totalCost) => SearchGraph(start, graph, heuristic, cost, goal, Equate, out totalCost); /// - public static Action> SearchGraph(Node start, IGraph graph, SearchHeuristic heuristic, SearchCost cost, Node goal, Func equate, out Numeric totalCost) => + public static Action>? SearchGraph(Node start, IGraph graph, SearchHeuristic heuristic, SearchCost cost, Node goal, Func equate, out Numeric totalCost) => SearchGraph(start, graph.Neighbors, heuristic, cost, node => equate(node, goal), out totalCost); /// - public static Action> SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchCost cost, SearchCheck check, out Numeric totalCost) + public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchCost cost, SearchCheck check, out Numeric totalCost) { // using a heap (aka priority queue) to store nodes based on their computed A* f(n) value IHeap> fringe = new HeapArray, AStarPriorityCompare>(); @@ -4273,31 +4280,31 @@ public static Action> SearchGraph(Node start, Search internal static void Graph_Dijkstra_XML() => throw new DocumentationMethodException(); /// - public static Action> SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchGoal goal) => + public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchGoal goal) => SearchGraph(start, neighbors, heuristic, node => goal(node) ? GraphSearchStatus.Goal : GraphSearchStatus.Continue); /// - public static Action> SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, Node goal) => + public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, Node goal) => SearchGraph(start, neighbors, heuristic, goal, Equate); /// - public static Action> SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, Node goal, Func equate) => + public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, Node goal, Func equate) => SearchGraph(start, neighbors, heuristic, node => equate(node, goal)); /// - public static Action> SearchGraph(Node start, IGraph graph, SearchHeuristic heuristic, Node goal) => + public static Action>? SearchGraph(Node start, IGraph graph, SearchHeuristic heuristic, Node goal) => SearchGraph(start, graph, heuristic, goal, Equate); /// - public static Action> SearchGraph(Node start, IGraph graph, SearchHeuristic heuristic, Node goal, Func equate) => + public static Action>? SearchGraph(Node start, IGraph graph, SearchHeuristic heuristic, Node goal, Func equate) => SearchGraph(start, graph.Neighbors, heuristic, node => equate(node, goal)); /// - public static Action> SearchGraph(Node start, IGraph graph, SearchHeuristic heuristic, SearchGoal goal) => + public static Action>? SearchGraph(Node start, IGraph graph, SearchHeuristic heuristic, SearchGoal goal) => SearchGraph(start, graph.Neighbors, heuristic, goal); /// - public static Action> SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchCheck check) + public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchCheck check) { // using a heap (aka priority queue) to store nodes based on their computed heuristic value IHeap> fringe = new HeapArray, DijkstraPriorityCompare>(); @@ -4352,31 +4359,31 @@ public static Action> SearchGraph(Node start, Search internal static void Graph_BreadthFirstSearch_XML() => throw new DocumentationMethodException(); /// - public static Action> SearchGraph(Node start, SearchNeighbors neighbors, SearchGoal goal) => + public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchGoal goal) => SearchGraph(start, neighbors, node => goal(node) ? GraphSearchStatus.Goal : GraphSearchStatus.Continue); /// - public static Action> SearchGraph(Node start, SearchNeighbors neighbors, Node goal) => + public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, Node goal) => SearchGraph(start, neighbors, goal, Equate); /// - public static Action> SearchGraph(Node start, SearchNeighbors neighbors, Node goal, Func equate) => + public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, Node goal, Func equate) => SearchGraph(start, neighbors, node => equate(node, goal)); /// - public static Action> SearchGraph(Node start, IGraph graph, Node goal) => + public static Action>? SearchGraph(Node start, IGraph graph, Node goal) => SearchGraph(start, graph, goal, Equate); /// - public static Action> SearchGraph(Node start, IGraph graph, Node goal, Func equate) => + public static Action>? SearchGraph(Node start, IGraph graph, Node goal, Func equate) => SearchGraph(start, graph.Neighbors, node => equate(node, goal)); /// - public static Action> SearchGraph(Node start, IGraph graph, SearchGoal goal) => + public static Action>? SearchGraph(Node start, IGraph graph, SearchGoal goal) => SearchGraph(start, graph.Neighbors, goal); /// - public static Action> SearchGraph(Node start, SearchNeighbors neighbors, SearchCheck check) + public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchCheck check) { IQueue> fringe = new QueueLinked>(); @@ -4457,7 +4464,7 @@ public static Action> SearchGraph(Node start, SearchNeighbors internal static void SortBubble_XML() => throw new DocumentationMethodException(); /// - public static void SortBubble(int start, int end, Func get, Action set, Func compare = null) => + public static void SortBubble(int start, int end, Func get, Action set, Func? compare = null) => SortBubble, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); /// @@ -4482,7 +4489,7 @@ public static void SortBubble(int start, int end, Compare } /// - public static void SortBubble(Span span, Func compare = null) => + public static void SortBubble(Span span, Func? compare = null) => SortBubble>(span, compare ?? Compare); /// @@ -4516,7 +4523,7 @@ public static void SortBubble(Span span, Compare compare = defaul internal static void SortSelection_XML() => throw new DocumentationMethodException(); /// - public static void SortSelection(int start, int end, Func get, Action set, Func compare = null) => + public static void SortSelection(int start, int end, Func get, Action set, Func? compare = null) => SortSelection, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); /// @@ -4543,7 +4550,7 @@ public static void SortSelection(int start, int end, Compa } /// - public static void SortSelection(Span span, Func compare = null) => + public static void SortSelection(Span span, Func? compare = null) => SortSelection>(span, compare ?? Compare); /// @@ -4579,7 +4586,7 @@ public static void SortSelection(Span span, Compare compare = def internal static void SortInsertion_XML() => throw new DocumentationMethodException(); /// - public static void SortInsertion(int start, int end, Func get, Action set, Func compare = null) => + public static void SortInsertion(int start, int end, Func get, Action set, Func? compare = null) => SortInsertion, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); /// @@ -4601,7 +4608,7 @@ public static void SortInsertion(int start, int end, Compa } /// - public static void SortInsertion(Span span, Func compare = null) => + public static void SortInsertion(Span span, Func? compare = null) => SortInsertion>(span, compare ?? Compare); /// @@ -4635,7 +4642,7 @@ public static void SortInsertion(Span span, Compare compare = def internal static void SortQuick_XML() => throw new DocumentationMethodException(); /// - public static void SortQuick(int start, int end, Func get, Action set, Func compare = null) => + public static void SortQuick(int start, int end, Func get, Action set, Func? compare = null) => SortQuick, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); /// @@ -4682,7 +4689,7 @@ void Swap(int a, int b) } /// - public static void SortQuick(Span span, Func compare = null) => + public static void SortQuick(Span span, Func? compare = null) => SortQuick>(span, compare ?? Compare); /// @@ -4735,7 +4742,7 @@ void SortQuick_Recursive(Span span, int startIndex, int len) internal static void SortMerge_XML() => throw new DocumentationMethodException(); /// - public static void SortMerge(int start, int end, Func get, Action set, Func compare = null) => + public static void SortMerge(int start, int end, Func get, Action set, Func? compare = null) => SortMerge, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); /// @@ -4785,7 +4792,7 @@ void SortMerge_Recursive(int start, int length) } /// - public static void SortMerge(Span span, Func compare = null) => + public static void SortMerge(Span span, Func? compare = null) => SortMerge>(span, compare ?? Compare); /// @@ -4847,7 +4854,7 @@ void SortMerge_Recursive(Span span) internal static void SortHeap_XML() => throw new DocumentationMethodException(); /// - public static void SortHeap(int start, int end, Func get, Action set, Func compare = null) => + public static void SortHeap(int start, int end, Func get, Action set, Func? compare = null) => SortHeap, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); /// @@ -4896,7 +4903,7 @@ void Swap(int a, int b) } /// - public static void SortHeap(Span span, Func compare = null) => + public static void SortHeap(Span span, Func? compare = null) => SortHeap>(span, compare ?? Compare); /// @@ -4953,7 +4960,7 @@ void MaxSortHeapify(Span span, int heapSize, int index, int offset) internal static void SortOddEven_XML() => throw new DocumentationMethodException(); /// - public static void SortOddEven(int start, int end, Func get, Action set, Func compare = null) => + public static void SortOddEven(int start, int end, Func get, Action set, Func? compare = null) => SortOddEven, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); /// @@ -4992,7 +4999,7 @@ void Swap(int a, int b) } /// - public static void SortOddEven(Span span, Func compare = null) => + public static void SortOddEven(Span span, Func? compare = null) => SortOddEven>(span, compare ?? Compare); /// @@ -5113,11 +5120,11 @@ public static void SortOddEven(Span span, Compare compare = defau #pragma warning restore CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name /// - public static void Shuffle(int start, int end, Func get, Action set, Random random = null) => + public static void Shuffle(int start, int end, Func get, Action set, Random? random = null) => Shuffle, ActionRuntime>(start, end, get, set, random); /// - public static void Shuffle(int start, int end, Get get = default, Set set = default, Random random = null) + public static void Shuffle(int start, int end, Get get = default, Set set = default, Random? random = null) where Get : struct, IFunc where Set : struct, IAction => Shuffle(start, end, get, set, random ?? new Random()); @@ -5139,7 +5146,7 @@ public static void Shuffle(int start, int end, Get get = de } /// - public static void Shuffle(Span span, Random random = null) => + public static void Shuffle(Span span, Random? random = null) => Shuffle(span, random ?? new Random()); /// @@ -5168,11 +5175,11 @@ public static void Shuffle(Span span, Random random = default) internal static void SortBogo_XML() => throw new DocumentationMethodException(); /// - public static void SortBogo(int start, int end, Func get, Action set, Func compare = null, Random random = null) => + public static void SortBogo(int start, int end, Func get, Action set, Func? compare = null, Random? random = null) => SortBogo, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set, random); /// - public static void SortBogo(int start, int end, Compare compare = default, Get get = default, Set set = default, Random random = null) + public static void SortBogo(int start, int end, Compare compare = default, Get get = default, Set set = default, Random? random = null) where Compare : struct, IFunc where Get : struct, IFunc where Set : struct, IAction => @@ -5203,11 +5210,11 @@ bool SortBogoCheck(int start, int end) } /// - public static void SortBogo(Span span, Func compare = null, Random random = null) => + public static void SortBogo(Span span, Func? compare = null, Random? random = null) => SortBogo>(span, compare ?? Compare, random ?? new Random()); /// - public static void SortBogo(Span span, Compare compare = default, Random random = null) + public static void SortBogo(Span span, Compare compare = default, Random? random = null) where Compare : struct, IFunc => SortBogo(span, compare, random ?? new Random()); @@ -5243,7 +5250,7 @@ bool SortBogoCheck(Span span) internal static void SortSlow_XML() => throw new DocumentationMethodException(); /// - public static void SortSlow(int start, int end, Func get, Action set, Func compare = null) => + public static void SortSlow(int start, int end, Func get, Action set, Func? compare = null) => SortSlow, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); /// @@ -5274,7 +5281,7 @@ void SortSlowRecursive(int i, int j) } /// - public static void SortSlow(Span span, Func compare = null) => + public static void SortSlow(Span span, Func? compare = null) => SortSlow>(span, compare ?? Compare); /// @@ -5309,7 +5316,7 @@ void SortSlowRecursive(Span span, int i, int j) internal static void SortGnome_XML() => throw new DocumentationMethodException(); /// - public static void SortGnome(int start, int end, Func get, Action set, Func compare = null) => + public static void SortGnome(int start, int end, Func get, Action set, Func? compare = null) => SortGnome, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); /// @@ -5337,7 +5344,7 @@ public static void SortGnome(int start, int end, Compare c } /// - public static void SortGnome(Span span, Func compare = null) => + public static void SortGnome(Span span, Func? compare = null) => SortGnome>(span, compare ?? Compare); /// @@ -5369,7 +5376,7 @@ public static void SortGnome(Span span, Compare compare = default internal static void SortComb_XML() => throw new DocumentationMethodException(); /// - public static void SortComb(int start, int end, Func get, Action set, Func compare = null) => + public static void SortComb(int start, int end, Func get, Action set, Func? compare = null) => SortComb, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); /// @@ -5403,7 +5410,7 @@ public static void SortComb(int start, int end, Compare co } /// - public static void SortComb(Span span, Func compare = null) => + public static void SortComb(Span span, Func? compare = null) => SortComb>(span, compare ?? Compare); /// @@ -5442,7 +5449,7 @@ public static void SortComb(Span span, Compare compare = default) internal static void SortShell_XML() => throw new DocumentationMethodException(); /// - public static void SortShell(int start, int end, Func get, Action set, Func compare = null) => + public static void SortShell(int start, int end, Func get, Action set, Func? compare = null) => SortShell, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); /// @@ -5468,7 +5475,7 @@ public static void SortShell(int start, int end, Compare c } /// - public static void SortShell(Span span, Func compare = null) => + public static void SortShell(Span span, Func? compare = null) => SortShell>(span, compare ?? Compare); /// @@ -5501,7 +5508,7 @@ public static void SortShell(Span span, Compare compare = default internal static void SortCocktail_XML() => throw new DocumentationMethodException(); /// - public static void SortCocktail(int start, int end, Func get, Action set, Func compare = null) => + public static void SortCocktail(int start, int end, Func get, Action set, Func? compare = null) => SortCocktail, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); /// @@ -5546,7 +5553,7 @@ public static void SortCocktail(int start, int end, Compar } /// - public static void SortCocktail(Span span, Func compare = null) => + public static void SortCocktail(Span span, Func? compare = null) => SortCocktail>(span, compare ?? Compare); /// diff --git a/Sources/Towel/Towel.xml b/Sources/Towel/Towel.xml index bda64d37..d8f1883d 100644 --- a/Sources/Towel/Towel.xml +++ b/Sources/Towel/Towel.xml @@ -2955,10 +2955,6 @@ The exception that occurred if the removal failed. True if the removal was successful for false if not. - - Resizes the table. - The desired size of the table. - Trims the table to an appropriate size based on the current count. @@ -14141,136 +14137,6 @@ A shallow clone of this set. - - An unsorted structure of unique items. - The type of structure to use for each index of the hash table. - The type of values to store in the set. - - - Factory for constructing new structures. - A delegate for equality checks. - A delegate for computing hash codes. - The constructed structure. - - - Clones a structure. - The structure to clone. - A clone of the structure. - - - - Constructs a hashed set. - Runtime: O(1) - - The factory delegate. - The equate delegate. - The hashing function. - The expected count of the set. - - - - This constructor is for cloning purposes. - Runtime: O(n) - - The set to clone. - A delegate for cloning the structures. - - - - The current size of the hashed table. - Runtime: O(1) - - - - - The current number of values in the set. - Runtime: O(1) - - - - - The delegate for computing hash codes. - Runtime: O(1) - - - - - The delegate for equality checking. - Runtime: O(1) - - - - - Adds a value to the hash table. - Runtime: O(n), Ω(1), ε(1) - - The key value to use as the look-up reference in the hash table. - The exception that occurred if the add failed. - - - - Removes a value from the set. - Runtime: O(n), Ω(1), ε(1) - - The value to remove. - The exception that occurred if the remove failed. - - - - Removes a value from the set. - Runtime: O(n), Ω(1), ε(1) - - The value to remove. - The exception that occurred if the remove failed. - - - Resizes the table. - The desired size of the table. - - - - Creates a shallow clone of this set. - Runtime: Θ(n) - - A shallow clone of this set. - - - - Determines if a value has been added to a set. - Runtime: O(n), Ω(1), ε(1) - - The value to look for in the set. - True if the value has been added to the set or false if not. - - - - Removes all the values in the set. - Runtime: O(1) - - - - - Trims the table to an appropriate size based on the current count. - Runtime: O(n), Ω(1) - - - - - - - - - - Gets the enumerator for the set. - The enumerator for the set. - - - - Puts all the values in this set into an array. - Runtime: Θ(n) - - An array with all the values in the set. - A self-sorting binary tree based on the heights of each node. The generic type of this data structure. @@ -29888,6 +29754,15 @@ Definitions for Switch syntax. + + Delegate with params intended to be used with the Switch syntax. + + + Intended to be used with Switch syntax. + + + The default keyword for the the Switch syntax. + Represents the result of a conditional expression inside Switch syntax. The generic type of the Switch condition for equality checks. @@ -30097,7 +29972,7 @@ The universal quantification to be converted. - Converts a universal quantification to an . + Converts a universal quantification to an Action<Action<T>>. The universal quantification to be converted. @@ -30105,7 +29980,7 @@ The universal quantification to be converted. - Converts a universal quantification to an . + Converts a universal quantification to an Func<Func<T, StepStatus>, StepStatus>. The universal quantification to be converted. From 20b4807edfe8363bd4b7e3e5934135d9a4207378 Mon Sep 17 00:00:00 2001 From: Zachary Patten Date: Thu, 29 Oct 2020 18:55:10 -0400 Subject: [PATCH 06/30] nullable refs + is not --- Sources/Towel/CommandLine.cs | 2 +- Sources/Towel/ConsoleHelper.cs | 15 +- Sources/Towel/Constant.cs | 2 +- Sources/Towel/DataStructures/AvlTree.cs | 4 +- Sources/Towel/DataStructures/BTree.cs | 6 +- .../Towel/DataStructures/DoubleEndedQueue.cs | 10 +- Sources/Towel/DataStructures/KdTree.cs | 26 +- Sources/Towel/DataStructures/Omnitree.cs | 714 +++++++++--------- Sources/Towel/DataStructures/Omnitree.tt | 96 +-- Sources/Towel/DataStructures/Omnitree_ND.cs | 40 +- Sources/Towel/DataStructures/RedBlackTree.cs | 10 +- Sources/Towel/DataStructures/Trie.cs | 4 +- Sources/Towel/Functional.cs | 128 +++- Sources/Towel/Functional.tt | 16 +- Sources/Towel/Mathematics/Matrix.cs | 32 +- Sources/Towel/Mathematics/Symbolics.cs | 18 +- Sources/Towel/Measurements/Measurement.cs | 6 +- .../Towel/Measurements/MeasurementTypes.tt | 16 +- Sources/Towel/Meta.cs | 8 +- Sources/Towel/Statics.cs | 277 ++++--- Sources/Towel/TagAttribute.cs | 8 +- Sources/Towel/Towel.csproj | 5 + Sources/Towel/Towel.xml | 348 +++++++++ 23 files changed, 1136 insertions(+), 655 deletions(-) diff --git a/Sources/Towel/CommandLine.cs b/Sources/Towel/CommandLine.cs index 4e35cfc5..99548a3f 100644 --- a/Sources/Towel/CommandLine.cs +++ b/Sources/Towel/CommandLine.cs @@ -104,7 +104,7 @@ public static void HandleArguments(string[]? args = null) } else { - MethodInfo tryParse; + MethodInfo? tryParse; ConstructorInfo? constuctor; if ((tryParse = Meta.GetTryParseMethod(parameterType)) is not null) { diff --git a/Sources/Towel/ConsoleHelper.cs b/Sources/Towel/ConsoleHelper.cs index e84a2e9a..5f0ac6d5 100644 --- a/Sources/Towel/ConsoleHelper.cs +++ b/Sources/Towel/ConsoleHelper.cs @@ -66,7 +66,7 @@ public static void IntMenu( } prompt ??= $"Choose an option (1-{options.Length}): "; invalidMessage ??= "Invalid Input. Try Again..."; - if (!(title is null)) + if (title is not null) { Console.WriteLine(title); } @@ -94,8 +94,8 @@ public static void IntMenu( public static T GetInput( string? prompt = null, string? invalidMessage = null, - Func? tryParse = null, - Predicate? validation = null) + Func? tryParse = null, + Predicate? validation = null) { if (tryParse is null && (typeof(T) != typeof(string) && !typeof(T).IsEnum && Meta.GetTryParseMethod() is null)) { @@ -103,11 +103,16 @@ public static T GetInput( } tryParse ??= typeof(T) == typeof(string) ? s => (true, (T)(object)s) - : (Func)TryParse; + : (Func)TryParse; validation ??= v => true; GetInput: Console.Write(prompt ?? $"Input a {typeof(T).Name} value: "); - var (success, value) = tryParse(Console.ReadLine()); + string? readLine = Console.ReadLine(); + if (readLine is null) + { + throw new ArgumentException($"{nameof(System)}.{nameof(Console)}.{nameof(Console.ReadLine)} returned null"); + } + var (success, value) = tryParse(readLine); if (!success || !validation(value)) { Console.WriteLine(invalidMessage ?? $"Invalid input. Try again..."); diff --git a/Sources/Towel/Constant.cs b/Sources/Towel/Constant.cs index 924acef9..53ed9f6f 100644 --- a/Sources/Towel/Constant.cs +++ b/Sources/Towel/Constant.cs @@ -408,7 +408,7 @@ public static T Negative4OverπSquared /// Computes the value of pi for the provided generic type. /// The cancellation token for cutting off computation. /// The computed value of pi. - public static T ComputePi(Predicate predicate = null) + public static T ComputePi(Predicate? predicate = null) { // Series: PI = 2 * (1 + 1/3 * (1 + 2/5 * (1 + 3/7 * (...)))) // more terms in computation inproves accuracy diff --git a/Sources/Towel/DataStructures/AvlTree.cs b/Sources/Towel/DataStructures/AvlTree.cs index dddc8c01..a3b5e036 100644 --- a/Sources/Towel/DataStructures/AvlTree.cs +++ b/Sources/Towel/DataStructures/AvlTree.cs @@ -321,14 +321,14 @@ public bool TryRemove(out Exception? exception, Sift sift = default) case Less: node.RightChild = Remove(node.RightChild); break; case Greater: node.LeftChild = Remove(node.LeftChild); break; case Equal: - if (!(node.RightChild is null)) + if (node.RightChild is not null) { node.RightChild = RemoveLeftMost(node.RightChild, out Node leftMostOfRight); leftMostOfRight.RightChild = node.RightChild; leftMostOfRight.LeftChild = node.LeftChild; node = leftMostOfRight; } - else if (!(node.LeftChild is null)) + else if (node.LeftChild is not null) { node.LeftChild = RemoveRightMost(node.LeftChild, out Node rightMostOfLeft); rightMostOfLeft.RightChild = node.RightChild; diff --git a/Sources/Towel/DataStructures/BTree.cs b/Sources/Towel/DataStructures/BTree.cs index de392bcf..eeb44011 100644 --- a/Sources/Towel/DataStructures/BTree.cs +++ b/Sources/Towel/DataStructures/BTree.cs @@ -538,7 +538,7 @@ internal void RemoveKeyFromSubtree(Node parentNode, CompareToKnownValue compa int rightIndex = subtreeIndexInNode + 1; Node rightSibling = subtreeIndexInNode < parentNode.ChildCount - 1 ? parentNode.Children[rightIndex] : null; - if (!(leftSibling is null) && leftSibling.ItemCount > _node_size - 1) + if (leftSibling is not null && leftSibling.ItemCount > _node_size - 1) { for (int i = childNode.ChildCount; i > -1; i--) childNode.Items[i] = childNode.Items[i - 1]; @@ -555,7 +555,7 @@ internal void RemoveKeyFromSubtree(Node parentNode, CompareToKnownValue compa leftSibling.ChildCount--; } } - else if (!(rightSibling is null) && rightSibling.ItemCount > _node_size - 1) + else if (rightSibling is not null && rightSibling.ItemCount > _node_size - 1) { childNode.Items[childNode.ItemCount] = parentNode.Items[subtreeIndexInNode]; childNode.ItemCount++; @@ -575,7 +575,7 @@ internal void RemoveKeyFromSubtree(Node parentNode, CompareToKnownValue compa } else { - if (!(leftSibling is null)) + if (leftSibling is not null) { for (int i = childNode.ItemCount; i > 0; i--) childNode.Items[i] = childNode.Items[i - 1]; diff --git a/Sources/Towel/DataStructures/DoubleEndedQueue.cs b/Sources/Towel/DataStructures/DoubleEndedQueue.cs index 60a534d4..ae6438df 100644 --- a/Sources/Towel/DataStructures/DoubleEndedQueue.cs +++ b/Sources/Towel/DataStructures/DoubleEndedQueue.cs @@ -157,7 +157,7 @@ public T[] ToArray() /// The delegate to invoke on each item in the structure. public void Stepper(Action step) { - for (Node current = _head; !(current is null); current = current.Next) + for (Node current = _head; current is not null; current = current.Next) { step(current.Value); } @@ -167,7 +167,7 @@ public void Stepper(Action step) /// The delegate to invoke on each item in the structure. public void Stepper(StepRef step) { - for (Node current = _head; !(current is null); current = current.Next) + for (Node current = _head; current is not null; current = current.Next) { step(ref current.Value); } @@ -178,7 +178,7 @@ public void Stepper(StepRef step) /// The resulting status of the iteration. public StepStatus Stepper(Func step) { - for (Node current = _head; !(current is null); current = current.Next) + for (Node current = _head; current is not null; current = current.Next) { if (step(current.Value) is Break) { @@ -193,7 +193,7 @@ public StepStatus Stepper(Func step) /// The resulting status of the iteration. public StepStatus Stepper(StepRefBreak step) { - for (Node current = _head; !(current is null); current = current.Next) + for (Node current = _head; current is not null; current = current.Next) { if (step(ref current.Value) is Break) { @@ -209,7 +209,7 @@ public StepStatus Stepper(StepRefBreak step) /// The enumerator for this dequeue. public System.Collections.Generic.IEnumerator GetEnumerator() { - for (Node current = _head; !(current is null); current = current.Next) + for (Node current = _head; current is not null; current = current.Next) { yield return current.Value; } diff --git a/Sources/Towel/DataStructures/KdTree.cs b/Sources/Towel/DataStructures/KdTree.cs index 6946223f..da3a0048 100644 --- a/Sources/Towel/DataStructures/KdTree.cs +++ b/Sources/Towel/DataStructures/KdTree.cs @@ -205,10 +205,10 @@ internal void ReaddChildNodes(Node removedNode) var nodesToReaddQueue = new System.Collections.Generic.Queue(); - if (!(removedNode.LeftChild is null)) + if (removedNode.LeftChild is not null) nodesToReaddQueue.Enqueue(removedNode.LeftChild); - if (!(removedNode.RightChild is null)) + if (removedNode.RightChild is not null) nodesToReaddQueue.Enqueue(removedNode.RightChild); while (nodesToReaddQueue.Count > 0) @@ -217,13 +217,13 @@ internal void ReaddChildNodes(Node removedNode) nodesToReadd.Enqueue(nodeToReadd); - if (!(nodeToReadd.LeftChild is null)) + if (nodeToReadd.LeftChild is not null) { nodesToReaddQueue.Enqueue(nodeToReadd.LeftChild); nodeToReadd.LeftChild = null; } - if (!(nodeToReadd.RightChild is null)) + if (nodeToReadd.RightChild is not null) { nodesToReaddQueue.Enqueue(nodeToReadd.RightChild); nodeToReadd.RightChild = null; @@ -312,7 +312,7 @@ public void RemoveAt(GetIndex point) throw new System.NotImplementedException(); } } - while (!(node is null)); + while (node is not null); } #endregion #region public Node[] GetNearestNeighbours(Get point, int count) @@ -395,7 +395,7 @@ internal void AddNearestNeighbours( var furtherNode = compareTargetPoint_as_int <= 0 ? node.RightChild : node.LeftChild; // Let's walk down into the nearer branch - if (!(nearerNode is null)) + if (nearerNode is not null) { AddNearestNeighbours( nearerNode, @@ -549,9 +549,9 @@ public bool TryFindValue(T value, out GetIndex point) } else { - if (!(nodeToSearch.LeftChild is null)) + if (nodeToSearch.LeftChild is not null) nodesToSearch.Enqueue(nodeToSearch.LeftChild); - if (!(nodeToSearch.RightChild is null)) + if (nodeToSearch.RightChild is not null) nodesToSearch.Enqueue(nodeToSearch.RightChild); } } @@ -577,12 +577,12 @@ internal void AddNodesToList(Node node, System.Collections.Generic.List no nodes.Add(node); - if (!(node.LeftChild is null)) + if (node.LeftChild is not null) { AddNodesToList(node.LeftChild, nodes); node.LeftChild = null; } - if (!(node.RightChild is null)) + if (node.RightChild is not null) { AddNodesToList(node.RightChild, nodes); node.RightChild = null; @@ -655,12 +655,12 @@ public void Balance() #region internal void RemoveChildNodes(Node node) internal void RemoveChildNodes(Node node) { - if (!(node.LeftChild is null)) + if (node.LeftChild is not null) { RemoveChildNodes(node.LeftChild); node.LeftChild = null; } - if (!(node.RightChild is null)) + if (node.RightChild is not null) { RemoveChildNodes(node.RightChild); node.RightChild = null; @@ -791,7 +791,7 @@ public PriorityQueue(int capacity, Compare comparePriority, TPriority this.capacity = capacity; queue = new ItemPriority[capacity]; - //if (!(priorityMath is null)) + //if (priorityMath is not null) // this.priorityMath = priorityMath; //else // this.priorityMath = TypeMath.GetMath(); diff --git a/Sources/Towel/DataStructures/Omnitree.cs b/Sources/Towel/DataStructures/Omnitree.cs index 46500305..97641923 100644 --- a/Sources/Towel/DataStructures/Omnitree.cs +++ b/Sources/Towel/DataStructures/Omnitree.cs @@ -3030,7 +3030,7 @@ internal int Depth get { int depth = -1; - for (Node node = this; !(node is null); node = node.Parent) + for (Node node = this; node is not null; node = node.Parent) depth++; return depth; } @@ -3168,7 +3168,7 @@ internal Leaf(Leaf leaf) : base(leaf) Head = new Node(leaf.Head.Value, null); Node a = Head; Node b = leaf.Head; - while (!(b is null)) + while (b is not null) { a.Next = new Node(b.Next.Value, null); a = a.Next; @@ -3397,7 +3397,7 @@ public void Add(T addition) this._top = new Branch(DetermineMedians(top), Omnitree.Bounds.None, null, -1); // iterate through the elements and add them to the appropriate children - for (Leaf.Node list = top.Head; !(list is null); list = list.Next) + for (Leaf.Node list = top.Head; list is not null; list = list.Next) Add(list.Value, this._top, LocateVector(list.Value), 0); } @@ -3425,7 +3425,7 @@ internal void Add(T addition, Node node, Omnitree.Vector location, int de int child_index = this.DetermineChildIndex(parent.PointOfDivision, location); Branch growth = new Branch(DetermineMedians(leaf), leaf.Bounds, parent, child_index); parent[child_index] = growth; - for (Leaf.Node list = leaf.Head; !(list is null); list = list.Next) + for (Leaf.Node list = leaf.Head; list is not null; list = list.Next) { Omnitree.Vector temp_location = LocateVector(list.Value); if (EncapsulationCheck(growth.Bounds, temp_location)) @@ -3471,7 +3471,7 @@ internal Omnitree.Vector DetermineMedians(Leaf leaf) { division1 = _subdivisionOverride1(leaf.Bounds, x => { - for (Leaf.Node node = leaf.Head; !(node is null); node = node.Next) + for (Leaf.Node node = leaf.Head; node is not null; node = node.Next) { x(node.Value); } @@ -3590,7 +3590,7 @@ internal int CountSubSpace(Node node, Omnitree.Bounds bounds) count += node.Count; else if (node is Leaf) { - for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next) + for (Leaf.Node list = (node as Leaf).Head; list is null; list = list.Next) if (EncapsulationCheck(bounds, LocateVector(list.Value))) count++; } @@ -3602,7 +3602,7 @@ internal int CountSubSpace(Node node, Omnitree.Bounds bounds) int child_index = DetermineChildIndex(branch.PointOfDivision, new Omnitree.Vector(bounds.Min1.Value )); Node child = branch[child_index]; - if (!(child is null)) + if (child is not null) { count += this.CountSubSpace(child, bounds); } @@ -3638,7 +3638,7 @@ internal int Update(Node node, int depth) Leaf leaf = node as Leaf; Leaf.Node current = leaf.Head; Leaf.Node previous = null; - while (!(current is null)) + while (current is not null) { Omnitree.Vector location = LocateVector(current.Value); if (!this.EncapsulationCheck(node.Bounds, location)) @@ -3730,7 +3730,7 @@ internal int Update(Omnitree.Bounds bounds, Node node, int depth) Leaf leaf = node as Leaf; Leaf.Node current = leaf.Head; Leaf.Node previous = null; - while (!(current is null)) + while (current is not null) { Omnitree.Vector location = LocateVector(current.Value); if (!this.EncapsulationCheck(node.Bounds, location)) @@ -3802,15 +3802,15 @@ internal int Remove(Node node, Predicate where) if (node is Leaf) { Leaf leaf = node as Leaf; - while (!(leaf.Head is null) && where(leaf.Head.Value)) + while (leaf.Head is not null && where(leaf.Head.Value)) { leaf.Head = leaf.Head.Next; removals++; } - if (!(leaf.Head is null)) + if (leaf.Head is not null) { Leaf.Node list = leaf.Head; - while (!(list.Next is null)) + while (list.Next is not null) { if (where(list.Next.Value)) { @@ -3950,7 +3950,7 @@ internal int Remove(Node node, Omnitree.Bounds bounds, Predicate where Leaf leaf = node as Leaf; Leaf.Node current = leaf.Head; Leaf.Node previous = null; - while (!(current is null)) + while (current is not null) { if (this.EncapsulationCheck(bounds, LocateVector(current.Value)) && where(current.Value)) { @@ -4128,7 +4128,7 @@ internal void Stepper(Action step, Node node) if (node is Leaf) { Leaf.Node list = (node as Leaf).Head; - while (!(list is null)) + while (list is not null) { step(list.Value); list = list.Next; @@ -4151,7 +4151,7 @@ internal StepStatus Stepper(Func step, Node node) StepStatus status = StepStatus.Continue; if (node is Leaf) { - for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next) + for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next) if ((status = step(list.Value)) != StepStatus.Continue) break; } @@ -4182,7 +4182,7 @@ internal void Stepper(Action step, Node node, Omnitree.Bounds bounds) { if (node is Leaf) { - for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next) + for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next) if (EncapsulationCheck(bounds, LocateVector(list.Value))) step(list.Value); } @@ -4216,7 +4216,7 @@ internal StepStatus Stepper(Func step, Node node, Omnitree.Bounds StepStatus status = StepStatus.Continue; if (node is Leaf) { - for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next) + for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next) if (EncapsulationCheck(bounds, LocateVector(list.Value)) && (status = step(list.Value)) != StepStatus.Continue) break; @@ -4244,11 +4244,11 @@ public void Stepper(Action step, Axis1 axis1) => internal void Stepper(Action step, Node node, Omnitree.Vector vector) { Node current = node; - while (!(current is null)) + while (current is not null) { if (current is Leaf) { - for (Leaf.Node leaf_node = (current as Leaf).Head; !(leaf_node is null); leaf_node = leaf_node.Next) + for (Leaf.Node leaf_node = (current as Leaf).Head; leaf_node is not null; leaf_node = leaf_node.Next) if (EqualsCheck(vector, LocateVector(leaf_node.Value))) step(leaf_node.Value); break; @@ -4271,11 +4271,11 @@ public StepStatus Stepper(Func step, Axis1 axis1) => internal StepStatus Stepper(Func step, Node node, Omnitree.Vector vector) { Node current = node; - while (!(current is null)) + while (current is not null) { if (current is Leaf) { - for (Leaf.Node list = (current as Leaf).Head; !(list is null); list = list.Next) + for (Leaf.Node list = (current as Leaf).Head; list is not null; list = list.Next) { StepStatus status = StepStatus.Continue; if (EqualsCheck(vector, LocateVector(list.Value)) && @@ -4361,7 +4361,7 @@ internal void ReduceParentCounts(Node parent, int reduction) internal void IncreaseParentCounts(Node parent, int increase) { Node node = parent; - while (!(node is null)) + while (node is not null) { node.Count += increase; node = node.Parent; @@ -4402,7 +4402,7 @@ internal bool EqualsCheck(Omnitree.Vector a, Omnitree.Vector b) => /// The nearest node that encapsulates the given location. internal Node GetEncapsulationParent(Node node, Omnitree.Vector vector) { - while (!(node is null) && !EncapsulationCheck(node.Bounds, vector)) + while (node is not null && !EncapsulationCheck(node.Bounds, vector)) { node = node.Parent; } @@ -4560,7 +4560,7 @@ internal int Depth get { int depth = -1; - for (Node node = this; !(node is null); node = node.Parent) + for (Node node = this; node is not null; node = node.Parent) depth++; return depth; } @@ -4698,7 +4698,7 @@ internal Leaf(Leaf leaf) : base(leaf) Head = new Node(leaf.Head.Value, null); Node a = Head; Node b = leaf.Head; - while (!(b is null)) + while (b is not null) { a.Next = new Node(b.Next.Value, null); a = a.Next; @@ -4956,7 +4956,7 @@ public void Add(T addition) this._top = new Branch(DetermineMedians(top), Omnitree.Bounds.None, null, -1); // iterate through the elements and add them to the appropriate children - for (Leaf.Node list = top.Head; !(list is null); list = list.Next) + for (Leaf.Node list = top.Head; list is not null; list = list.Next) Add(list.Value, this._top, LocateVector(list.Value), 0); } @@ -4984,7 +4984,7 @@ internal void Add(T addition, Node node, Omnitree.Vector location, int child_index = this.DetermineChildIndex(parent.PointOfDivision, location); Branch growth = new Branch(DetermineMedians(leaf), leaf.Bounds, parent, child_index); parent[child_index] = growth; - for (Leaf.Node list = leaf.Head; !(list is null); list = list.Next) + for (Leaf.Node list = leaf.Head; list is not null; list = list.Next) { Omnitree.Vector temp_location = LocateVector(list.Value); if (EncapsulationCheck(growth.Bounds, temp_location)) @@ -5030,7 +5030,7 @@ internal Omnitree.Vector DetermineMedians(Leaf leaf) { division1 = _subdivisionOverride1(leaf.Bounds, x => { - for (Leaf.Node node = leaf.Head; !(node is null); node = node.Next) + for (Leaf.Node node = leaf.Head; node is not null; node = node.Next) { x(node.Value); } @@ -5056,7 +5056,7 @@ internal Omnitree.Vector DetermineMedians(Leaf leaf) { division2 = _subdivisionOverride2(leaf.Bounds, x => { - for (Leaf.Node node = leaf.Head; !(node is null); node = node.Next) + for (Leaf.Node node = leaf.Head; node is not null; node = node.Next) { x(node.Value); } @@ -5197,7 +5197,7 @@ internal int CountSubSpace(Node node, Omnitree.Bounds bounds) count += node.Count; else if (node is Leaf) { - for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next) + for (Leaf.Node list = (node as Leaf).Head; list is null; list = list.Next) if (EncapsulationCheck(bounds, LocateVector(list.Value))) count++; } @@ -5210,7 +5210,7 @@ internal int CountSubSpace(Node node, Omnitree.Bounds bounds) , bounds.Min2.Value )); Node child = branch[child_index]; - if (!(child is null)) + if (child is not null) { count += this.CountSubSpace(child, bounds); } @@ -5246,7 +5246,7 @@ internal int Update(Node node, int depth) Leaf leaf = node as Leaf; Leaf.Node current = leaf.Head; Leaf.Node previous = null; - while (!(current is null)) + while (current is not null) { Omnitree.Vector location = LocateVector(current.Value); if (!this.EncapsulationCheck(node.Bounds, location)) @@ -5344,7 +5344,7 @@ internal int Update(Omnitree.Bounds bounds, Node node, int depth) Leaf leaf = node as Leaf; Leaf.Node current = leaf.Head; Leaf.Node previous = null; - while (!(current is null)) + while (current is not null) { Omnitree.Vector location = LocateVector(current.Value); if (!this.EncapsulationCheck(node.Bounds, location)) @@ -5416,15 +5416,15 @@ internal int Remove(Node node, Predicate where) if (node is Leaf) { Leaf leaf = node as Leaf; - while (!(leaf.Head is null) && where(leaf.Head.Value)) + while (leaf.Head is not null && where(leaf.Head.Value)) { leaf.Head = leaf.Head.Next; removals++; } - if (!(leaf.Head is null)) + if (leaf.Head is not null) { Leaf.Node list = leaf.Head; - while (!(list.Next is null)) + while (list.Next is not null) { if (where(list.Next.Value)) { @@ -5572,7 +5572,7 @@ internal int Remove(Node node, Omnitree.Bounds bounds, Predicate step, Node node) if (node is Leaf) { Leaf.Node list = (node as Leaf).Head; - while (!(list is null)) + while (list is not null) { step(list.Value); list = list.Next; @@ -5777,7 +5777,7 @@ internal StepStatus Stepper(Func step, Node node) StepStatus status = StepStatus.Continue; if (node is Leaf) { - for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next) + for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next) if ((status = step(list.Value)) != StepStatus.Continue) break; } @@ -5812,7 +5812,7 @@ internal void Stepper(Action step, Node node, Omnitree.Bounds b { if (node is Leaf) { - for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next) + for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next) if (EncapsulationCheck(bounds, LocateVector(list.Value))) step(list.Value); } @@ -5850,7 +5850,7 @@ internal StepStatus Stepper(Func step, Node node, Omnitree.Bounds StepStatus status = StepStatus.Continue; if (node is Leaf) { - for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next) + for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next) if (EncapsulationCheck(bounds, LocateVector(list.Value)) && (status = step(list.Value)) != StepStatus.Continue) break; @@ -5879,11 +5879,11 @@ public void Stepper(Action step, Axis1 axis1, Axis2 axis2) => internal void Stepper(Action step, Node node, Omnitree.Vector vector) { Node current = node; - while (!(current is null)) + while (current is not null) { if (current is Leaf) { - for (Leaf.Node leaf_node = (current as Leaf).Head; !(leaf_node is null); leaf_node = leaf_node.Next) + for (Leaf.Node leaf_node = (current as Leaf).Head; leaf_node is not null; leaf_node = leaf_node.Next) if (EqualsCheck(vector, LocateVector(leaf_node.Value))) step(leaf_node.Value); break; @@ -5907,11 +5907,11 @@ public StepStatus Stepper(Func step, Axis1 axis1, Axis2 axis2) => internal StepStatus Stepper(Func step, Node node, Omnitree.Vector vector) { Node current = node; - while (!(current is null)) + while (current is not null) { if (current is Leaf) { - for (Leaf.Node list = (current as Leaf).Head; !(list is null); list = list.Next) + for (Leaf.Node list = (current as Leaf).Head; list is not null; list = list.Next) { StepStatus status = StepStatus.Continue; if (EqualsCheck(vector, LocateVector(list.Value)) && @@ -6000,7 +6000,7 @@ internal void ReduceParentCounts(Node parent, int reduction) internal void IncreaseParentCounts(Node parent, int increase) { Node node = parent; - while (!(node is null)) + while (node is not null) { node.Count += increase; node = node.Parent; @@ -6045,7 +6045,7 @@ internal bool EqualsCheck(Omnitree.Vector a, Omnitree.VectorThe nearest node that encapsulates the given location. internal Node GetEncapsulationParent(Node node, Omnitree.Vector vector) { - while (!(node is null) && !EncapsulationCheck(node.Bounds, vector)) + while (node is not null && !EncapsulationCheck(node.Bounds, vector)) { node = node.Parent; } @@ -6229,7 +6229,7 @@ internal int Depth get { int depth = -1; - for (Node node = this; !(node is null); node = node.Parent) + for (Node node = this; node is not null; node = node.Parent) depth++; return depth; } @@ -6367,7 +6367,7 @@ internal Leaf(Leaf leaf) : base(leaf) Head = new Node(leaf.Head.Value, null); Node a = Head; Node b = leaf.Head; - while (!(b is null)) + while (b is not null) { a.Next = new Node(b.Next.Value, null); a = a.Next; @@ -6654,7 +6654,7 @@ public void Add(T addition) this._top = new Branch(DetermineMedians(top), Omnitree.Bounds.None, null, -1); // iterate through the elements and add them to the appropriate children - for (Leaf.Node list = top.Head; !(list is null); list = list.Next) + for (Leaf.Node list = top.Head; list is not null; list = list.Next) Add(list.Value, this._top, LocateVector(list.Value), 0); } @@ -6682,7 +6682,7 @@ internal void Add(T addition, Node node, Omnitree.Vector lo int child_index = this.DetermineChildIndex(parent.PointOfDivision, location); Branch growth = new Branch(DetermineMedians(leaf), leaf.Bounds, parent, child_index); parent[child_index] = growth; - for (Leaf.Node list = leaf.Head; !(list is null); list = list.Next) + for (Leaf.Node list = leaf.Head; list is not null; list = list.Next) { Omnitree.Vector temp_location = LocateVector(list.Value); if (EncapsulationCheck(growth.Bounds, temp_location)) @@ -6728,7 +6728,7 @@ internal Omnitree.Vector DetermineMedians(Leaf leaf) { division1 = _subdivisionOverride1(leaf.Bounds, x => { - for (Leaf.Node node = leaf.Head; !(node is null); node = node.Next) + for (Leaf.Node node = leaf.Head; node is not null; node = node.Next) { x(node.Value); } @@ -6755,7 +6755,7 @@ internal Omnitree.Vector DetermineMedians(Leaf leaf) { division2 = _subdivisionOverride2(leaf.Bounds, x => { - for (Leaf.Node node = leaf.Head; !(node is null); node = node.Next) + for (Leaf.Node node = leaf.Head; node is not null; node = node.Next) { x(node.Value); } @@ -6782,7 +6782,7 @@ internal Omnitree.Vector DetermineMedians(Leaf leaf) { division3 = _subdivisionOverride3(leaf.Bounds, x => { - for (Leaf.Node node = leaf.Head; !(node is null); node = node.Next) + for (Leaf.Node node = leaf.Head; node is not null; node = node.Next) { x(node.Value); } @@ -6945,7 +6945,7 @@ internal int CountSubSpace(Node node, Omnitree.Bounds bound count += node.Count; else if (node is Leaf) { - for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next) + for (Leaf.Node list = (node as Leaf).Head; list is null; list = list.Next) if (EncapsulationCheck(bounds, LocateVector(list.Value))) count++; } @@ -6959,7 +6959,7 @@ internal int CountSubSpace(Node node, Omnitree.Bounds bound , bounds.Min3.Value )); Node child = branch[child_index]; - if (!(child is null)) + if (child is not null) { count += this.CountSubSpace(child, bounds); } @@ -6995,7 +6995,7 @@ internal int Update(Node node, int depth) Leaf leaf = node as Leaf; Leaf.Node current = leaf.Head; Leaf.Node previous = null; - while (!(current is null)) + while (current is not null) { Omnitree.Vector location = LocateVector(current.Value); if (!this.EncapsulationCheck(node.Bounds, location)) @@ -7099,7 +7099,7 @@ internal int Update(Omnitree.Bounds bounds, Node node, int Leaf leaf = node as Leaf; Leaf.Node current = leaf.Head; Leaf.Node previous = null; - while (!(current is null)) + while (current is not null) { Omnitree.Vector location = LocateVector(current.Value); if (!this.EncapsulationCheck(node.Bounds, location)) @@ -7171,15 +7171,15 @@ internal int Remove(Node node, Predicate where) if (node is Leaf) { Leaf leaf = node as Leaf; - while (!(leaf.Head is null) && where(leaf.Head.Value)) + while (leaf.Head is not null && where(leaf.Head.Value)) { leaf.Head = leaf.Head.Next; removals++; } - if (!(leaf.Head is null)) + if (leaf.Head is not null) { Leaf.Node list = leaf.Head; - while (!(list.Next is null)) + while (list.Next is not null) { if (where(list.Next.Value)) { @@ -7335,7 +7335,7 @@ internal int Remove(Node node, Omnitree.Bounds bounds, Pred Leaf leaf = node as Leaf; Leaf.Node current = leaf.Head; Leaf.Node previous = null; - while (!(current is null)) + while (current is not null) { if (this.EncapsulationCheck(bounds, LocateVector(current.Value)) && where(current.Value)) { @@ -7521,7 +7521,7 @@ internal void Stepper(Action step, Node node) if (node is Leaf) { Leaf.Node list = (node as Leaf).Head; - while (!(list is null)) + while (list is not null) { step(list.Value); list = list.Next; @@ -7544,7 +7544,7 @@ internal StepStatus Stepper(Func step, Node node) StepStatus status = StepStatus.Continue; if (node is Leaf) { - for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next) + for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next) if ((status = step(list.Value)) != StepStatus.Continue) break; } @@ -7583,7 +7583,7 @@ internal void Stepper(Action step, Node node, Omnitree.Bounds step, Node node, Omnitree.Bounds StepStatus status = StepStatus.Continue; if (node is Leaf) { - for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next) + for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next) if (EncapsulationCheck(bounds, LocateVector(list.Value)) && (status = step(list.Value)) != StepStatus.Continue) break; @@ -7655,11 +7655,11 @@ public void Stepper(Action step, Axis1 axis1, Axis2 axis2, Axis3 axis3) => internal void Stepper(Action step, Node node, Omnitree.Vector vector) { Node current = node; - while (!(current is null)) + while (current is not null) { if (current is Leaf) { - for (Leaf.Node leaf_node = (current as Leaf).Head; !(leaf_node is null); leaf_node = leaf_node.Next) + for (Leaf.Node leaf_node = (current as Leaf).Head; leaf_node is not null; leaf_node = leaf_node.Next) if (EqualsCheck(vector, LocateVector(leaf_node.Value))) step(leaf_node.Value); break; @@ -7684,11 +7684,11 @@ public StepStatus Stepper(Func step, Axis1 axis1, Axis2 axis2, Ax internal StepStatus Stepper(Func step, Node node, Omnitree.Vector vector) { Node current = node; - while (!(current is null)) + while (current is not null) { if (current is Leaf) { - for (Leaf.Node list = (current as Leaf).Head; !(list is null); list = list.Next) + for (Leaf.Node list = (current as Leaf).Head; list is not null; list = list.Next) { StepStatus status = StepStatus.Continue; if (EqualsCheck(vector, LocateVector(list.Value)) && @@ -7780,7 +7780,7 @@ internal void ReduceParentCounts(Node parent, int reduction) internal void IncreaseParentCounts(Node parent, int increase) { Node node = parent; - while (!(node is null)) + while (node is not null) { node.Count += increase; node = node.Parent; @@ -7829,7 +7829,7 @@ internal bool EqualsCheck(Omnitree.Vector a, Omnitree.Vecto /// The nearest node that encapsulates the given location. internal Node GetEncapsulationParent(Node node, Omnitree.Vector vector) { - while (!(node is null) && !EncapsulationCheck(node.Bounds, vector)) + while (node is not null && !EncapsulationCheck(node.Bounds, vector)) { node = node.Parent; } @@ -8039,7 +8039,7 @@ internal int Depth get { int depth = -1; - for (Node node = this; !(node is null); node = node.Parent) + for (Node node = this; node is not null; node = node.Parent) depth++; return depth; } @@ -8177,7 +8177,7 @@ internal Leaf(Leaf leaf) : base(leaf) Head = new Node(leaf.Head.Value, null); Node a = Head; Node b = leaf.Head; - while (!(b is null)) + while (b is not null) { a.Next = new Node(b.Next.Value, null); a = a.Next; @@ -8493,7 +8493,7 @@ public void Add(T addition) this._top = new Branch(DetermineMedians(top), Omnitree.Bounds.None, null, -1); // iterate through the elements and add them to the appropriate children - for (Leaf.Node list = top.Head; !(list is null); list = list.Next) + for (Leaf.Node list = top.Head; list is not null; list = list.Next) Add(list.Value, this._top, LocateVector(list.Value), 0); } @@ -8521,7 +8521,7 @@ internal void Add(T addition, Node node, Omnitree.Vector temp_location = LocateVector(list.Value); if (EncapsulationCheck(growth.Bounds, temp_location)) @@ -8567,7 +8567,7 @@ internal Omnitree.Vector DetermineMedians(Leaf leaf) { division1 = _subdivisionOverride1(leaf.Bounds, x => { - for (Leaf.Node node = leaf.Head; !(node is null); node = node.Next) + for (Leaf.Node node = leaf.Head; node is not null; node = node.Next) { x(node.Value); } @@ -8595,7 +8595,7 @@ internal Omnitree.Vector DetermineMedians(Leaf leaf) { division2 = _subdivisionOverride2(leaf.Bounds, x => { - for (Leaf.Node node = leaf.Head; !(node is null); node = node.Next) + for (Leaf.Node node = leaf.Head; node is not null; node = node.Next) { x(node.Value); } @@ -8623,7 +8623,7 @@ internal Omnitree.Vector DetermineMedians(Leaf leaf) { division3 = _subdivisionOverride3(leaf.Bounds, x => { - for (Leaf.Node node = leaf.Head; !(node is null); node = node.Next) + for (Leaf.Node node = leaf.Head; node is not null; node = node.Next) { x(node.Value); } @@ -8651,7 +8651,7 @@ internal Omnitree.Vector DetermineMedians(Leaf leaf) { division4 = _subdivisionOverride4(leaf.Bounds, x => { - for (Leaf.Node node = leaf.Head; !(node is null); node = node.Next) + for (Leaf.Node node = leaf.Head; node is not null; node = node.Next) { x(node.Value); } @@ -8836,7 +8836,7 @@ internal int CountSubSpace(Node node, Omnitree.Bounds location = LocateVector(current.Value); if (!this.EncapsulationCheck(node.Bounds, location)) @@ -8997,7 +8997,7 @@ internal int Update(Omnitree.Bounds bounds, Node nod Leaf leaf = node as Leaf; Leaf.Node current = leaf.Head; Leaf.Node previous = null; - while (!(current is null)) + while (current is not null) { Omnitree.Vector location = LocateVector(current.Value); if (!this.EncapsulationCheck(node.Bounds, location)) @@ -9069,15 +9069,15 @@ internal int Remove(Node node, Predicate where) if (node is Leaf) { Leaf leaf = node as Leaf; - while (!(leaf.Head is null) && where(leaf.Head.Value)) + while (leaf.Head is not null && where(leaf.Head.Value)) { leaf.Head = leaf.Head.Next; removals++; } - if (!(leaf.Head is null)) + if (leaf.Head is not null) { Leaf.Node list = leaf.Head; - while (!(list.Next is null)) + while (list.Next is not null) { if (where(list.Next.Value)) { @@ -9241,7 +9241,7 @@ internal int Remove(Node node, Omnitree.Bounds bound Leaf leaf = node as Leaf; Leaf.Node current = leaf.Head; Leaf.Node previous = null; - while (!(current is null)) + while (current is not null) { if (this.EncapsulationCheck(bounds, LocateVector(current.Value)) && where(current.Value)) { @@ -9431,7 +9431,7 @@ internal void Stepper(Action step, Node node) if (node is Leaf) { Leaf.Node list = (node as Leaf).Head; - while (!(list is null)) + while (list is not null) { step(list.Value); list = list.Next; @@ -9454,7 +9454,7 @@ internal StepStatus Stepper(Func step, Node node) StepStatus status = StepStatus.Continue; if (node is Leaf) { - for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next) + for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next) if ((status = step(list.Value)) != StepStatus.Continue) break; } @@ -9497,7 +9497,7 @@ internal void Stepper(Action step, Node node, Omnitree.Bounds step, Node node, Omnitree.Bounds StepStatus status = StepStatus.Continue; if (node is Leaf) { - for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next) + for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next) if (EncapsulationCheck(bounds, LocateVector(list.Value)) && (status = step(list.Value)) != StepStatus.Continue) break; @@ -9574,11 +9574,11 @@ public void Stepper(Action step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 internal void Stepper(Action step, Node node, Omnitree.Vector vector) { Node current = node; - while (!(current is null)) + while (current is not null) { if (current is Leaf) { - for (Leaf.Node leaf_node = (current as Leaf).Head; !(leaf_node is null); leaf_node = leaf_node.Next) + for (Leaf.Node leaf_node = (current as Leaf).Head; leaf_node is not null; leaf_node = leaf_node.Next) if (EqualsCheck(vector, LocateVector(leaf_node.Value))) step(leaf_node.Value); break; @@ -9604,11 +9604,11 @@ public StepStatus Stepper(Func step, Axis1 axis1, Axis2 axis2, Ax internal StepStatus Stepper(Func step, Node node, Omnitree.Vector vector) { Node current = node; - while (!(current is null)) + while (current is not null) { if (current is Leaf) { - for (Leaf.Node list = (current as Leaf).Head; !(list is null); list = list.Next) + for (Leaf.Node list = (current as Leaf).Head; list is not null; list = list.Next) { StepStatus status = StepStatus.Continue; if (EqualsCheck(vector, LocateVector(list.Value)) && @@ -9703,7 +9703,7 @@ internal void ReduceParentCounts(Node parent, int reduction) internal void IncreaseParentCounts(Node parent, int increase) { Node node = parent; - while (!(node is null)) + while (node is not null) { node.Count += increase; node = node.Parent; @@ -9756,7 +9756,7 @@ internal bool EqualsCheck(Omnitree.Vector a, Omnitre /// The nearest node that encapsulates the given location. internal Node GetEncapsulationParent(Node node, Omnitree.Vector vector) { - while (!(node is null) && !EncapsulationCheck(node.Bounds, vector)) + while (node is not null && !EncapsulationCheck(node.Bounds, vector)) { node = node.Parent; } @@ -9992,7 +9992,7 @@ internal int Depth get { int depth = -1; - for (Node node = this; !(node is null); node = node.Parent) + for (Node node = this; node is not null; node = node.Parent) depth++; return depth; } @@ -10130,7 +10130,7 @@ internal Leaf(Leaf leaf) : base(leaf) Head = new Node(leaf.Head.Value, null); Node a = Head; Node b = leaf.Head; - while (!(b is null)) + while (b is not null) { a.Next = new Node(b.Next.Value, null); a = a.Next; @@ -10475,7 +10475,7 @@ public void Add(T addition) this._top = new Branch(DetermineMedians(top), Omnitree.Bounds.None, null, -1); // iterate through the elements and add them to the appropriate children - for (Leaf.Node list = top.Head; !(list is null); list = list.Next) + for (Leaf.Node list = top.Head; list is not null; list = list.Next) Add(list.Value, this._top, LocateVector(list.Value), 0); } @@ -10503,7 +10503,7 @@ internal void Add(T addition, Node node, Omnitree.Vector temp_location = LocateVector(list.Value); if (EncapsulationCheck(growth.Bounds, temp_location)) @@ -10549,7 +10549,7 @@ internal Omnitree.Vector DetermineMedians(Lea { division1 = _subdivisionOverride1(leaf.Bounds, x => { - for (Leaf.Node node = leaf.Head; !(node is null); node = node.Next) + for (Leaf.Node node = leaf.Head; node is not null; node = node.Next) { x(node.Value); } @@ -10578,7 +10578,7 @@ internal Omnitree.Vector DetermineMedians(Lea { division2 = _subdivisionOverride2(leaf.Bounds, x => { - for (Leaf.Node node = leaf.Head; !(node is null); node = node.Next) + for (Leaf.Node node = leaf.Head; node is not null; node = node.Next) { x(node.Value); } @@ -10607,7 +10607,7 @@ internal Omnitree.Vector DetermineMedians(Lea { division3 = _subdivisionOverride3(leaf.Bounds, x => { - for (Leaf.Node node = leaf.Head; !(node is null); node = node.Next) + for (Leaf.Node node = leaf.Head; node is not null; node = node.Next) { x(node.Value); } @@ -10636,7 +10636,7 @@ internal Omnitree.Vector DetermineMedians(Lea { division4 = _subdivisionOverride4(leaf.Bounds, x => { - for (Leaf.Node node = leaf.Head; !(node is null); node = node.Next) + for (Leaf.Node node = leaf.Head; node is not null; node = node.Next) { x(node.Value); } @@ -10665,7 +10665,7 @@ internal Omnitree.Vector DetermineMedians(Lea { division5 = _subdivisionOverride5(leaf.Bounds, x => { - for (Leaf.Node node = leaf.Head; !(node is null); node = node.Next) + for (Leaf.Node node = leaf.Head; node is not null; node = node.Next) { x(node.Value); } @@ -10872,7 +10872,7 @@ internal int CountSubSpace(Node node, Omnitree.Bounds location = LocateVector(current.Value); if (!this.EncapsulationCheck(node.Bounds, location)) @@ -11040,7 +11040,7 @@ internal int Update(Omnitree.Bounds bounds, N Leaf leaf = node as Leaf; Leaf.Node current = leaf.Head; Leaf.Node previous = null; - while (!(current is null)) + while (current is not null) { Omnitree.Vector location = LocateVector(current.Value); if (!this.EncapsulationCheck(node.Bounds, location)) @@ -11112,15 +11112,15 @@ internal int Remove(Node node, Predicate where) if (node is Leaf) { Leaf leaf = node as Leaf; - while (!(leaf.Head is null) && where(leaf.Head.Value)) + while (leaf.Head is not null && where(leaf.Head.Value)) { leaf.Head = leaf.Head.Next; removals++; } - if (!(leaf.Head is null)) + if (leaf.Head is not null) { Leaf.Node list = leaf.Head; - while (!(list.Next is null)) + while (list.Next is not null) { if (where(list.Next.Value)) { @@ -11292,7 +11292,7 @@ internal int Remove(Node node, Omnitree.Bounds step, Node node) if (node is Leaf) { Leaf.Node list = (node as Leaf).Head; - while (!(list is null)) + while (list is not null) { step(list.Value); list = list.Next; @@ -11509,7 +11509,7 @@ internal StepStatus Stepper(Func step, Node node) StepStatus status = StepStatus.Continue; if (node is Leaf) { - for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next) + for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next) if ((status = step(list.Value)) != StepStatus.Continue) break; } @@ -11556,7 +11556,7 @@ internal void Stepper(Action step, Node node, Omnitree.Bounds step, Node node, Omnitree.Bounds StepStatus status = StepStatus.Continue; if (node is Leaf) { - for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next) + for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next) if (EncapsulationCheck(bounds, LocateVector(list.Value)) && (status = step(list.Value)) != StepStatus.Continue) break; @@ -11638,11 +11638,11 @@ public void Stepper(Action step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 internal void Stepper(Action step, Node node, Omnitree.Vector vector) { Node current = node; - while (!(current is null)) + while (current is not null) { if (current is Leaf) { - for (Leaf.Node leaf_node = (current as Leaf).Head; !(leaf_node is null); leaf_node = leaf_node.Next) + for (Leaf.Node leaf_node = (current as Leaf).Head; leaf_node is not null; leaf_node = leaf_node.Next) if (EqualsCheck(vector, LocateVector(leaf_node.Value))) step(leaf_node.Value); break; @@ -11669,11 +11669,11 @@ public StepStatus Stepper(Func step, Axis1 axis1, Axis2 axis2, Ax internal StepStatus Stepper(Func step, Node node, Omnitree.Vector vector) { Node current = node; - while (!(current is null)) + while (current is not null) { if (current is Leaf) { - for (Leaf.Node list = (current as Leaf).Head; !(list is null); list = list.Next) + for (Leaf.Node list = (current as Leaf).Head; list is not null; list = list.Next) { StepStatus status = StepStatus.Continue; if (EqualsCheck(vector, LocateVector(list.Value)) && @@ -11771,7 +11771,7 @@ internal void ReduceParentCounts(Node parent, int reduction) internal void IncreaseParentCounts(Node parent, int increase) { Node node = parent; - while (!(node is null)) + while (node is not null) { node.Count += increase; node = node.Parent; @@ -11828,7 +11828,7 @@ internal bool EqualsCheck(Omnitree.Vector a, /// The nearest node that encapsulates the given location. internal Node GetEncapsulationParent(Node node, Omnitree.Vector vector) { - while (!(node is null) && !EncapsulationCheck(node.Bounds, vector)) + while (node is not null && !EncapsulationCheck(node.Bounds, vector)) { node = node.Parent; } @@ -12090,7 +12090,7 @@ internal int Depth get { int depth = -1; - for (Node node = this; !(node is null); node = node.Parent) + for (Node node = this; node is not null; node = node.Parent) depth++; return depth; } @@ -12228,7 +12228,7 @@ internal Leaf(Leaf leaf) : base(leaf) Head = new Node(leaf.Head.Value, null); Node a = Head; Node b = leaf.Head; - while (!(b is null)) + while (b is not null) { a.Next = new Node(b.Next.Value, null); a = a.Next; @@ -12602,7 +12602,7 @@ public void Add(T addition) this._top = new Branch(DetermineMedians(top), Omnitree.Bounds.None, null, -1); // iterate through the elements and add them to the appropriate children - for (Leaf.Node list = top.Head; !(list is null); list = list.Next) + for (Leaf.Node list = top.Head; list is not null; list = list.Next) Add(list.Value, this._top, LocateVector(list.Value), 0); } @@ -12630,7 +12630,7 @@ internal void Add(T addition, Node node, Omnitree.Vector temp_location = LocateVector(list.Value); if (EncapsulationCheck(growth.Bounds, temp_location)) @@ -12676,7 +12676,7 @@ internal Omnitree.Vector DetermineMedi { division1 = _subdivisionOverride1(leaf.Bounds, x => { - for (Leaf.Node node = leaf.Head; !(node is null); node = node.Next) + for (Leaf.Node node = leaf.Head; node is not null; node = node.Next) { x(node.Value); } @@ -12706,7 +12706,7 @@ internal Omnitree.Vector DetermineMedi { division2 = _subdivisionOverride2(leaf.Bounds, x => { - for (Leaf.Node node = leaf.Head; !(node is null); node = node.Next) + for (Leaf.Node node = leaf.Head; node is not null; node = node.Next) { x(node.Value); } @@ -12736,7 +12736,7 @@ internal Omnitree.Vector DetermineMedi { division3 = _subdivisionOverride3(leaf.Bounds, x => { - for (Leaf.Node node = leaf.Head; !(node is null); node = node.Next) + for (Leaf.Node node = leaf.Head; node is not null; node = node.Next) { x(node.Value); } @@ -12766,7 +12766,7 @@ internal Omnitree.Vector DetermineMedi { division4 = _subdivisionOverride4(leaf.Bounds, x => { - for (Leaf.Node node = leaf.Head; !(node is null); node = node.Next) + for (Leaf.Node node = leaf.Head; node is not null; node = node.Next) { x(node.Value); } @@ -12796,7 +12796,7 @@ internal Omnitree.Vector DetermineMedi { division5 = _subdivisionOverride5(leaf.Bounds, x => { - for (Leaf.Node node = leaf.Head; !(node is null); node = node.Next) + for (Leaf.Node node = leaf.Head; node is not null; node = node.Next) { x(node.Value); } @@ -12826,7 +12826,7 @@ internal Omnitree.Vector DetermineMedi { division6 = _subdivisionOverride6(leaf.Bounds, x => { - for (Leaf.Node node = leaf.Head; !(node is null); node = node.Next) + for (Leaf.Node node = leaf.Head; node is not null; node = node.Next) { x(node.Value); } @@ -13055,7 +13055,7 @@ internal int CountSubSpace(Node node, Omnitree.Bounds location = LocateVector(current.Value); if (!this.EncapsulationCheck(node.Bounds, location)) @@ -13230,7 +13230,7 @@ internal int Update(Omnitree.Bounds bo Leaf leaf = node as Leaf; Leaf.Node current = leaf.Head; Leaf.Node previous = null; - while (!(current is null)) + while (current is not null) { Omnitree.Vector location = LocateVector(current.Value); if (!this.EncapsulationCheck(node.Bounds, location)) @@ -13302,15 +13302,15 @@ internal int Remove(Node node, Predicate where) if (node is Leaf) { Leaf leaf = node as Leaf; - while (!(leaf.Head is null) && where(leaf.Head.Value)) + while (leaf.Head is not null && where(leaf.Head.Value)) { leaf.Head = leaf.Head.Next; removals++; } - if (!(leaf.Head is null)) + if (leaf.Head is not null) { Leaf.Node list = leaf.Head; - while (!(list.Next is null)) + while (list.Next is not null) { if (where(list.Next.Value)) { @@ -13490,7 +13490,7 @@ internal int Remove(Node node, Omnitree.Bounds step, Node node) if (node is Leaf) { Leaf.Node list = (node as Leaf).Head; - while (!(list is null)) + while (list is not null) { step(list.Value); list = list.Next; @@ -13711,7 +13711,7 @@ internal StepStatus Stepper(Func step, Node node) StepStatus status = StepStatus.Continue; if (node is Leaf) { - for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next) + for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next) if ((status = step(list.Value)) != StepStatus.Continue) break; } @@ -13762,7 +13762,7 @@ internal void Stepper(Action step, Node node, Omnitree.Bounds step, Node node, Omnitree.Bounds StepStatus status = StepStatus.Continue; if (node is Leaf) { - for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next) + for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next) if (EncapsulationCheck(bounds, LocateVector(list.Value)) && (status = step(list.Value)) != StepStatus.Continue) break; @@ -13849,11 +13849,11 @@ public void Stepper(Action step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 internal void Stepper(Action step, Node node, Omnitree.Vector vector) { Node current = node; - while (!(current is null)) + while (current is not null) { if (current is Leaf) { - for (Leaf.Node leaf_node = (current as Leaf).Head; !(leaf_node is null); leaf_node = leaf_node.Next) + for (Leaf.Node leaf_node = (current as Leaf).Head; leaf_node is not null; leaf_node = leaf_node.Next) if (EqualsCheck(vector, LocateVector(leaf_node.Value))) step(leaf_node.Value); break; @@ -13881,11 +13881,11 @@ public StepStatus Stepper(Func step, Axis1 axis1, Axis2 axis2, Ax internal StepStatus Stepper(Func step, Node node, Omnitree.Vector vector) { Node current = node; - while (!(current is null)) + while (current is not null) { if (current is Leaf) { - for (Leaf.Node list = (current as Leaf).Head; !(list is null); list = list.Next) + for (Leaf.Node list = (current as Leaf).Head; list is not null; list = list.Next) { StepStatus status = StepStatus.Continue; if (EqualsCheck(vector, LocateVector(list.Value)) && @@ -13986,7 +13986,7 @@ internal void ReduceParentCounts(Node parent, int reduction) internal void IncreaseParentCounts(Node parent, int increase) { Node node = parent; - while (!(node is null)) + while (node is not null) { node.Count += increase; node = node.Parent; @@ -14047,7 +14047,7 @@ internal bool EqualsCheck(Omnitree.VectorThe nearest node that encapsulates the given location. internal Node GetEncapsulationParent(Node node, Omnitree.Vector vector) { - while (!(node is null) && !EncapsulationCheck(node.Bounds, vector)) + while (node is not null && !EncapsulationCheck(node.Bounds, vector)) { node = node.Parent; } @@ -14335,7 +14335,7 @@ internal int Depth get { int depth = -1; - for (Node node = this; !(node is null); node = node.Parent) + for (Node node = this; node is not null; node = node.Parent) depth++; return depth; } @@ -14473,7 +14473,7 @@ internal Leaf(Leaf leaf) : base(leaf) Head = new Node(leaf.Head.Value, null); Node a = Head; Node b = leaf.Head; - while (!(b is null)) + while (b is not null) { a.Next = new Node(b.Next.Value, null); a = a.Next; @@ -14876,7 +14876,7 @@ public void Add(T addition) this._top = new Branch(DetermineMedians(top), Omnitree.Bounds.None, null, -1); // iterate through the elements and add them to the appropriate children - for (Leaf.Node list = top.Head; !(list is null); list = list.Next) + for (Leaf.Node list = top.Head; list is not null; list = list.Next) Add(list.Value, this._top, LocateVector(list.Value), 0); } @@ -14904,7 +14904,7 @@ internal void Add(T addition, Node node, Omnitree.Vector temp_location = LocateVector(list.Value); if (EncapsulationCheck(growth.Bounds, temp_location)) @@ -14950,7 +14950,7 @@ internal Omnitree.Vector Determ { division1 = _subdivisionOverride1(leaf.Bounds, x => { - for (Leaf.Node node = leaf.Head; !(node is null); node = node.Next) + for (Leaf.Node node = leaf.Head; node is not null; node = node.Next) { x(node.Value); } @@ -14981,7 +14981,7 @@ internal Omnitree.Vector Determ { division2 = _subdivisionOverride2(leaf.Bounds, x => { - for (Leaf.Node node = leaf.Head; !(node is null); node = node.Next) + for (Leaf.Node node = leaf.Head; node is not null; node = node.Next) { x(node.Value); } @@ -15012,7 +15012,7 @@ internal Omnitree.Vector Determ { division3 = _subdivisionOverride3(leaf.Bounds, x => { - for (Leaf.Node node = leaf.Head; !(node is null); node = node.Next) + for (Leaf.Node node = leaf.Head; node is not null; node = node.Next) { x(node.Value); } @@ -15043,7 +15043,7 @@ internal Omnitree.Vector Determ { division4 = _subdivisionOverride4(leaf.Bounds, x => { - for (Leaf.Node node = leaf.Head; !(node is null); node = node.Next) + for (Leaf.Node node = leaf.Head; node is not null; node = node.Next) { x(node.Value); } @@ -15074,7 +15074,7 @@ internal Omnitree.Vector Determ { division5 = _subdivisionOverride5(leaf.Bounds, x => { - for (Leaf.Node node = leaf.Head; !(node is null); node = node.Next) + for (Leaf.Node node = leaf.Head; node is not null; node = node.Next) { x(node.Value); } @@ -15105,7 +15105,7 @@ internal Omnitree.Vector Determ { division6 = _subdivisionOverride6(leaf.Bounds, x => { - for (Leaf.Node node = leaf.Head; !(node is null); node = node.Next) + for (Leaf.Node node = leaf.Head; node is not null; node = node.Next) { x(node.Value); } @@ -15136,7 +15136,7 @@ internal Omnitree.Vector Determ { division7 = _subdivisionOverride7(leaf.Bounds, x => { - for (Leaf.Node node = leaf.Head; !(node is null); node = node.Next) + for (Leaf.Node node = leaf.Head; node is not null; node = node.Next) { x(node.Value); } @@ -15387,7 +15387,7 @@ internal int CountSubSpace(Node node, Omnitree.Bounds location = LocateVector(current.Value); if (!this.EncapsulationCheck(node.Bounds, location)) @@ -15569,7 +15569,7 @@ internal int Update(Omnitree.Bounds location = LocateVector(current.Value); if (!this.EncapsulationCheck(node.Bounds, location)) @@ -15641,15 +15641,15 @@ internal int Remove(Node node, Predicate where) if (node is Leaf) { Leaf leaf = node as Leaf; - while (!(leaf.Head is null) && where(leaf.Head.Value)) + while (leaf.Head is not null && where(leaf.Head.Value)) { leaf.Head = leaf.Head.Next; removals++; } - if (!(leaf.Head is null)) + if (leaf.Head is not null) { Leaf.Node list = leaf.Head; - while (!(list.Next is null)) + while (list.Next is not null) { if (where(list.Next.Value)) { @@ -15837,7 +15837,7 @@ internal int Remove(Node node, Omnitree.Bounds step, Node node) if (node is Leaf) { Leaf.Node list = (node as Leaf).Head; - while (!(list is null)) + while (list is not null) { step(list.Value); list = list.Next; @@ -16062,7 +16062,7 @@ internal StepStatus Stepper(Func step, Node node) StepStatus status = StepStatus.Continue; if (node is Leaf) { - for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next) + for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next) if ((status = step(list.Value)) != StepStatus.Continue) break; } @@ -16117,7 +16117,7 @@ internal void Stepper(Action step, Node node, Omnitree.Bounds step, Node node, Omnitree.Bounds StepStatus status = StepStatus.Continue; if (node is Leaf) { - for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next) + for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next) if (EncapsulationCheck(bounds, LocateVector(list.Value)) && (status = step(list.Value)) != StepStatus.Continue) break; @@ -16209,11 +16209,11 @@ public void Stepper(Action step, Axis1 axis1, Axis2 axis2, Axis3 axis3, Axis4 internal void Stepper(Action step, Node node, Omnitree.Vector vector) { Node current = node; - while (!(current is null)) + while (current is not null) { if (current is Leaf) { - for (Leaf.Node leaf_node = (current as Leaf).Head; !(leaf_node is null); leaf_node = leaf_node.Next) + for (Leaf.Node leaf_node = (current as Leaf).Head; leaf_node is not null; leaf_node = leaf_node.Next) if (EqualsCheck(vector, LocateVector(leaf_node.Value))) step(leaf_node.Value); break; @@ -16242,11 +16242,11 @@ public StepStatus Stepper(Func step, Axis1 axis1, Axis2 axis2, Ax internal StepStatus Stepper(Func step, Node node, Omnitree.Vector vector) { Node current = node; - while (!(current is null)) + while (current is not null) { if (current is Leaf) { - for (Leaf.Node list = (current as Leaf).Head; !(list is null); list = list.Next) + for (Leaf.Node list = (current as Leaf).Head; list is not null; list = list.Next) { StepStatus status = StepStatus.Continue; if (EqualsCheck(vector, LocateVector(list.Value)) && @@ -16350,7 +16350,7 @@ internal void ReduceParentCounts(Node parent, int reduction) internal void IncreaseParentCounts(Node parent, int increase) { Node node = parent; - while (!(node is null)) + while (node is not null) { node.Count += increase; node = node.Parent; @@ -16415,7 +16415,7 @@ internal bool EqualsCheck(Omnitree.VectorThe nearest node that encapsulates the given location. internal Node GetEncapsulationParent(Node node, Omnitree.Vector vector) { - while (!(node is null) && !EncapsulationCheck(node.Bounds, vector)) + while (node is not null && !EncapsulationCheck(node.Bounds, vector)) { node = node.Parent; } @@ -16682,7 +16682,7 @@ internal int Depth get { int depth = -1; - for (Node node = this; !(node is null); node = node.Parent) + for (Node node = this; node is not null; node = node.Parent) depth++; return depth; } @@ -16718,7 +16718,7 @@ internal Node(Node nodeToClone) ValueNode a = this.Head; ValueNode b = nodeToClone.Head; - while (!(b is null)) + while (b is not null) { a.Next = new ValueNode(b.Next.Value, null); a = a.Next; @@ -16910,7 +16910,7 @@ public void Add(T addition) this._top = new Node(DetermineMedians(top), Omnitree.Bounds.None, null, -1); // iterate through the elements and add them to the appropriate children - for (Node.ValueNode list = top.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = top.Head; list is not null; list = list.Next) Add(list.Value, this._top, GetBoundings(list.Value), 0); } @@ -16942,7 +16942,7 @@ internal void Add(T addition, Node node, Omnitree.Bounds bounds, int dept Node growth = new Node(DetermineMedians(node), node.Bounds, node.Parent, node.Index); node.Parent[node.Index] = growth; - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) { Omnitree.Bounds temp_bounds = GetBoundings(list.Value); if (EncapsulationCheck(growth.Bounds, temp_bounds)) @@ -17158,7 +17158,7 @@ internal int CountSubSpaceBase( count += node.Count; else if (!node.PointOfDivision.HasValue) { - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if (spatialCheck(bounds, GetBoundings(list.Value))) count++; } @@ -17169,7 +17169,7 @@ internal int CountSubSpaceBase( { int child_index = DetermineChildIndex(branch.PointOfDivision.Value, bounds); Node child = branch[child_index]; - if (!(child is null)) + if (child is not null) count += this.CountSubSpaceBase(child, bounds, spatialCheck); } else @@ -17220,7 +17220,7 @@ internal int Update(Node node, int depth) { Node.ValueNode current = node.Head; Node.ValueNode previous = null; - while (!(current is null)) + while (current is not null) { Omnitree.Bounds bounds = GetBoundings(current.Value); if (!this.EncapsulationCheck(node.Bounds, bounds)) @@ -17307,7 +17307,7 @@ internal int Update(Omnitree.Bounds bounds, Node node, int depth) { Node.ValueNode current = node.Head; Node.ValueNode previous = null; - while (!(current is null)) + while (current is not null) { Omnitree.Bounds item_bounds = GetBoundings(current.Value); if (!this.EncapsulationCheck(node.Bounds, item_bounds)) @@ -17356,7 +17356,7 @@ internal int Remove(Node node, Predicate where) int removals = 0; // children - if (!(node.Children is null)) + if (node.Children is not null) { int skipped = 0; for (int i = 0; i + skipped < node.Children.Length; ) @@ -17376,15 +17376,15 @@ internal int Remove(Node node, Predicate where) } // items - while (!(node.Head is null) && where(node.Head.Value)) + while (node.Head is not null && where(node.Head.Value)) { node.Head = node.Head.Next; removals++; } - if (!(node.Head is null)) + if (node.Head is not null) { Node.ValueNode list = node.Head; - while (!(list.Next is null)) + while (list.Next is not null) { if (where(list.Next.Value)) { @@ -17480,7 +17480,7 @@ internal int RemoveBase( } // children - if (!(node.Children is null)) + if (node.Children is not null) { int skipped = 0; for (int i = 0; i + skipped < node.Children.Length; ) @@ -17565,7 +17565,7 @@ internal int RemoveBase( // items Node.ValueNode current = node.Head; Node.ValueNode previous = null; - while (!(current is null)) + while (current is not null) { if (spatialCheck(bounds, GetBoundings(current.Value)) && where(current.Value)) { @@ -17584,7 +17584,7 @@ internal int RemoveBase( } // children - if (!(node.Children is null)) + if (node.Children is not null) { int skipped = 0; for (int i = 0; i + skipped < node.Children.Length; ) @@ -17657,12 +17657,12 @@ public void Stepper(Action step) => internal void Stepper(Action step, Node node) { Node.ValueNode list = node.Head; - while (!(list is null)) + while (list is not null) { step(list.Value); list = list.Next; } - if (!(node.Children is null)) + if (node.Children is not null) foreach (Node child in node.Children) this.Stepper(step, child); } @@ -17676,11 +17676,11 @@ internal StepStatus Stepper(Func step, Node node) { StepStatus status = StepStatus.Continue; - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if ((status = step(list.Value)) != StepStatus.Continue) break; - if (!(node.Children is null)) + if (node.Children is not null) foreach (Node child in node.Children) if ((status = Stepper(step, child)) != StepStatus.Continue) break; @@ -17728,11 +17728,11 @@ internal void StepperBase( Omnitree.Bounds bounds, Omnitree.SpatialCheck, Omnitree.Bounds> spatialCheck) { - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if (spatialCheck(bounds, GetBoundings(list.Value))) step(list.Value); - if (!(node.Children is null)) + if (node.Children is not null) { foreach (Node child in node.Children) // optimization: stop bounds checking if space encapsulates node @@ -17785,12 +17785,12 @@ internal StepStatus StepperBase( { StepStatus status = StepStatus.Continue; - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if (spatialCheck(bounds, GetBoundings(list.Value)) && (status = step(list.Value)) != StepStatus.Continue) break; - if (!(node.Children is null)) + if (node.Children is not null) { foreach (Node child in node.Children) // optimization: stop bounds checking if space encapsulates node @@ -17891,7 +17891,7 @@ internal void ReduceParentCounts(Node parent, int reduction) internal void IncreaseParentCounts(Node parent, int increase) { Node node = parent; - while (!(node is null)) + while (node is not null) { node.Count += increase; node = node.Parent; @@ -17932,7 +17932,7 @@ internal bool EqualsCheck(Omnitree.Vector a, Omnitree.Vector b) => /// The nearest node that encapsulates the given location. internal Node GetEncapsulationParent(Node node, Omnitree.Bounds bounds) { - while (!(node is null) && !EncapsulationCheck(node.Bounds, bounds)) + while (node is not null && !EncapsulationCheck(node.Bounds, bounds)) { node = node.Parent; } @@ -18227,7 +18227,7 @@ internal int Depth get { int depth = -1; - for (Node node = this; !(node is null); node = node.Parent) + for (Node node = this; node is not null; node = node.Parent) depth++; return depth; } @@ -18263,7 +18263,7 @@ internal Node(Node nodeToClone) ValueNode a = this.Head; ValueNode b = nodeToClone.Head; - while (!(b is null)) + while (b is not null) { a.Next = new ValueNode(b.Next.Value, null); a = a.Next; @@ -18492,7 +18492,7 @@ public void Add(T addition) this._top = new Node(DetermineMedians(top), Omnitree.Bounds.None, null, -1); // iterate through the elements and add them to the appropriate children - for (Node.ValueNode list = top.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = top.Head; list is not null; list = list.Next) Add(list.Value, this._top, GetBoundings(list.Value), 0); } @@ -18524,7 +18524,7 @@ internal void Add(T addition, Node node, Omnitree.Bounds bounds, i Node growth = new Node(DetermineMedians(node), node.Bounds, node.Parent, node.Index); node.Parent[node.Index] = growth; - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) { Omnitree.Bounds temp_bounds = GetBoundings(list.Value); if (EncapsulationCheck(growth.Bounds, temp_bounds)) @@ -18776,7 +18776,7 @@ internal int CountSubSpaceBase( count += node.Count; else if (!node.PointOfDivision.HasValue) { - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if (spatialCheck(bounds, GetBoundings(list.Value))) count++; } @@ -18787,7 +18787,7 @@ internal int CountSubSpaceBase( { int child_index = DetermineChildIndex(branch.PointOfDivision.Value, bounds); Node child = branch[child_index]; - if (!(child is null)) + if (child is not null) count += this.CountSubSpaceBase(child, bounds, spatialCheck); } else @@ -18838,7 +18838,7 @@ internal int Update(Node node, int depth) { Node.ValueNode current = node.Head; Node.ValueNode previous = null; - while (!(current is null)) + while (current is not null) { Omnitree.Bounds bounds = GetBoundings(current.Value); if (!this.EncapsulationCheck(node.Bounds, bounds)) @@ -18931,7 +18931,7 @@ internal int Update(Omnitree.Bounds bounds, Node node, int depth) { Node.ValueNode current = node.Head; Node.ValueNode previous = null; - while (!(current is null)) + while (current is not null) { Omnitree.Bounds item_bounds = GetBoundings(current.Value); if (!this.EncapsulationCheck(node.Bounds, item_bounds)) @@ -18980,7 +18980,7 @@ internal int Remove(Node node, Predicate where) int removals = 0; // children - if (!(node.Children is null)) + if (node.Children is not null) { int skipped = 0; for (int i = 0; i + skipped < node.Children.Length; ) @@ -19000,15 +19000,15 @@ internal int Remove(Node node, Predicate where) } // items - while (!(node.Head is null) && where(node.Head.Value)) + while (node.Head is not null && where(node.Head.Value)) { node.Head = node.Head.Next; removals++; } - if (!(node.Head is null)) + if (node.Head is not null) { Node.ValueNode list = node.Head; - while (!(list.Next is null)) + while (list.Next is not null) { if (where(list.Next.Value)) { @@ -19113,7 +19113,7 @@ internal int RemoveBase( } // children - if (!(node.Children is null)) + if (node.Children is not null) { int skipped = 0; for (int i = 0; i + skipped < node.Children.Length; ) @@ -19206,7 +19206,7 @@ internal int RemoveBase( // items Node.ValueNode current = node.Head; Node.ValueNode previous = null; - while (!(current is null)) + while (current is not null) { if (spatialCheck(bounds, GetBoundings(current.Value)) && where(current.Value)) { @@ -19225,7 +19225,7 @@ internal int RemoveBase( } // children - if (!(node.Children is null)) + if (node.Children is not null) { int skipped = 0; for (int i = 0; i + skipped < node.Children.Length; ) @@ -19303,12 +19303,12 @@ public void Stepper(Action step) => internal void Stepper(Action step, Node node) { Node.ValueNode list = node.Head; - while (!(list is null)) + while (list is not null) { step(list.Value); list = list.Next; } - if (!(node.Children is null)) + if (node.Children is not null) foreach (Node child in node.Children) this.Stepper(step, child); } @@ -19322,11 +19322,11 @@ internal StepStatus Stepper(Func step, Node node) { StepStatus status = StepStatus.Continue; - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if ((status = step(list.Value)) != StepStatus.Continue) break; - if (!(node.Children is null)) + if (node.Children is not null) foreach (Node child in node.Children) if ((status = Stepper(step, child)) != StepStatus.Continue) break; @@ -19382,11 +19382,11 @@ internal void StepperBase( Omnitree.Bounds bounds, Omnitree.SpatialCheck, Omnitree.Bounds> spatialCheck) { - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if (spatialCheck(bounds, GetBoundings(list.Value))) step(list.Value); - if (!(node.Children is null)) + if (node.Children is not null) { foreach (Node child in node.Children) // optimization: stop bounds checking if space encapsulates node @@ -19447,12 +19447,12 @@ internal StepStatus StepperBase( { StepStatus status = StepStatus.Continue; - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if (spatialCheck(bounds, GetBoundings(list.Value)) && (status = step(list.Value)) != StepStatus.Continue) break; - if (!(node.Children is null)) + if (node.Children is not null) { foreach (Node child in node.Children) // optimization: stop bounds checking if space encapsulates node @@ -19560,7 +19560,7 @@ internal void ReduceParentCounts(Node parent, int reduction) internal void IncreaseParentCounts(Node parent, int increase) { Node node = parent; - while (!(node is null)) + while (node is not null) { node.Count += increase; node = node.Parent; @@ -19605,7 +19605,7 @@ internal bool EqualsCheck(Omnitree.Vector a, Omnitree.VectorThe nearest node that encapsulates the given location. internal Node GetEncapsulationParent(Node node, Omnitree.Bounds bounds) { - while (!(node is null) && !EncapsulationCheck(node.Bounds, bounds)) + while (node is not null && !EncapsulationCheck(node.Bounds, bounds)) { node = node.Parent; } @@ -19946,7 +19946,7 @@ internal int Depth get { int depth = -1; - for (Node node = this; !(node is null); node = node.Parent) + for (Node node = this; node is not null; node = node.Parent) depth++; return depth; } @@ -19982,7 +19982,7 @@ internal Node(Node nodeToClone) ValueNode a = this.Head; ValueNode b = nodeToClone.Head; - while (!(b is null)) + while (b is not null) { a.Next = new ValueNode(b.Next.Value, null); a = a.Next; @@ -20248,7 +20248,7 @@ public void Add(T addition) this._top = new Node(DetermineMedians(top), Omnitree.Bounds.None, null, -1); // iterate through the elements and add them to the appropriate children - for (Node.ValueNode list = top.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = top.Head; list is not null; list = list.Next) Add(list.Value, this._top, GetBoundings(list.Value), 0); } @@ -20280,7 +20280,7 @@ internal void Add(T addition, Node node, Omnitree.Bounds bo Node growth = new Node(DetermineMedians(node), node.Bounds, node.Parent, node.Index); node.Parent[node.Index] = growth; - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) { Omnitree.Bounds temp_bounds = GetBoundings(list.Value); if (EncapsulationCheck(growth.Bounds, temp_bounds)) @@ -20568,7 +20568,7 @@ internal int CountSubSpaceBase( count += node.Count; else if (!node.PointOfDivision.HasValue) { - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if (spatialCheck(bounds, GetBoundings(list.Value))) count++; } @@ -20579,7 +20579,7 @@ internal int CountSubSpaceBase( { int child_index = DetermineChildIndex(branch.PointOfDivision.Value, bounds); Node child = branch[child_index]; - if (!(child is null)) + if (child is not null) count += this.CountSubSpaceBase(child, bounds, spatialCheck); } else @@ -20630,7 +20630,7 @@ internal int Update(Node node, int depth) { Node.ValueNode current = node.Head; Node.ValueNode previous = null; - while (!(current is null)) + while (current is not null) { Omnitree.Bounds bounds = GetBoundings(current.Value); if (!this.EncapsulationCheck(node.Bounds, bounds)) @@ -20729,7 +20729,7 @@ internal int Update(Omnitree.Bounds bounds, Node node, int { Node.ValueNode current = node.Head; Node.ValueNode previous = null; - while (!(current is null)) + while (current is not null) { Omnitree.Bounds item_bounds = GetBoundings(current.Value); if (!this.EncapsulationCheck(node.Bounds, item_bounds)) @@ -20778,7 +20778,7 @@ internal int Remove(Node node, Predicate where) int removals = 0; // children - if (!(node.Children is null)) + if (node.Children is not null) { int skipped = 0; for (int i = 0; i + skipped < node.Children.Length; ) @@ -20798,15 +20798,15 @@ internal int Remove(Node node, Predicate where) } // items - while (!(node.Head is null) && where(node.Head.Value)) + while (node.Head is not null && where(node.Head.Value)) { node.Head = node.Head.Next; removals++; } - if (!(node.Head is null)) + if (node.Head is not null) { Node.ValueNode list = node.Head; - while (!(list.Next is null)) + while (list.Next is not null) { if (where(list.Next.Value)) { @@ -20920,7 +20920,7 @@ internal int RemoveBase( } // children - if (!(node.Children is null)) + if (node.Children is not null) { int skipped = 0; for (int i = 0; i + skipped < node.Children.Length; ) @@ -21021,7 +21021,7 @@ internal int RemoveBase( // items Node.ValueNode current = node.Head; Node.ValueNode previous = null; - while (!(current is null)) + while (current is not null) { if (spatialCheck(bounds, GetBoundings(current.Value)) && where(current.Value)) { @@ -21040,7 +21040,7 @@ internal int RemoveBase( } // children - if (!(node.Children is null)) + if (node.Children is not null) { int skipped = 0; for (int i = 0; i + skipped < node.Children.Length; ) @@ -21123,12 +21123,12 @@ public void Stepper(Action step) => internal void Stepper(Action step, Node node) { Node.ValueNode list = node.Head; - while (!(list is null)) + while (list is not null) { step(list.Value); list = list.Next; } - if (!(node.Children is null)) + if (node.Children is not null) foreach (Node child in node.Children) this.Stepper(step, child); } @@ -21142,11 +21142,11 @@ internal StepStatus Stepper(Func step, Node node) { StepStatus status = StepStatus.Continue; - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if ((status = step(list.Value)) != StepStatus.Continue) break; - if (!(node.Children is null)) + if (node.Children is not null) foreach (Node child in node.Children) if ((status = Stepper(step, child)) != StepStatus.Continue) break; @@ -21210,11 +21210,11 @@ internal void StepperBase( Omnitree.Bounds bounds, Omnitree.SpatialCheck, Omnitree.Bounds> spatialCheck) { - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if (spatialCheck(bounds, GetBoundings(list.Value))) step(list.Value); - if (!(node.Children is null)) + if (node.Children is not null) { foreach (Node child in node.Children) // optimization: stop bounds checking if space encapsulates node @@ -21283,12 +21283,12 @@ internal StepStatus StepperBase( { StepStatus status = StepStatus.Continue; - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if (spatialCheck(bounds, GetBoundings(list.Value)) && (status = step(list.Value)) != StepStatus.Continue) break; - if (!(node.Children is null)) + if (node.Children is not null) { foreach (Node child in node.Children) // optimization: stop bounds checking if space encapsulates node @@ -21403,7 +21403,7 @@ internal void ReduceParentCounts(Node parent, int reduction) internal void IncreaseParentCounts(Node parent, int increase) { Node node = parent; - while (!(node is null)) + while (node is not null) { node.Count += increase; node = node.Parent; @@ -21452,7 +21452,7 @@ internal bool EqualsCheck(Omnitree.Vector a, Omnitree.Vecto /// The nearest node that encapsulates the given location. internal Node GetEncapsulationParent(Node node, Omnitree.Bounds bounds) { - while (!(node is null) && !EncapsulationCheck(node.Bounds, bounds)) + while (node is not null && !EncapsulationCheck(node.Bounds, bounds)) { node = node.Parent; } @@ -21839,7 +21839,7 @@ internal int Depth get { int depth = -1; - for (Node node = this; !(node is null); node = node.Parent) + for (Node node = this; node is not null; node = node.Parent) depth++; return depth; } @@ -21875,7 +21875,7 @@ internal Node(Node nodeToClone) ValueNode a = this.Head; ValueNode b = nodeToClone.Head; - while (!(b is null)) + while (b is not null) { a.Next = new ValueNode(b.Next.Value, null); a = a.Next; @@ -22178,7 +22178,7 @@ public void Add(T addition) this._top = new Node(DetermineMedians(top), Omnitree.Bounds.None, null, -1); // iterate through the elements and add them to the appropriate children - for (Node.ValueNode list = top.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = top.Head; list is not null; list = list.Next) Add(list.Value, this._top, GetBoundings(list.Value), 0); } @@ -22210,7 +22210,7 @@ internal void Add(T addition, Node node, Omnitree.Bounds temp_bounds = GetBoundings(list.Value); if (EncapsulationCheck(growth.Bounds, temp_bounds)) @@ -22534,7 +22534,7 @@ internal int CountSubSpaceBase( count += node.Count; else if (!node.PointOfDivision.HasValue) { - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if (spatialCheck(bounds, GetBoundings(list.Value))) count++; } @@ -22545,7 +22545,7 @@ internal int CountSubSpaceBase( { int child_index = DetermineChildIndex(branch.PointOfDivision.Value, bounds); Node child = branch[child_index]; - if (!(child is null)) + if (child is not null) count += this.CountSubSpaceBase(child, bounds, spatialCheck); } else @@ -22596,7 +22596,7 @@ internal int Update(Node node, int depth) { Node.ValueNode current = node.Head; Node.ValueNode previous = null; - while (!(current is null)) + while (current is not null) { Omnitree.Bounds bounds = GetBoundings(current.Value); if (!this.EncapsulationCheck(node.Bounds, bounds)) @@ -22701,7 +22701,7 @@ internal int Update(Omnitree.Bounds bounds, Node nod { Node.ValueNode current = node.Head; Node.ValueNode previous = null; - while (!(current is null)) + while (current is not null) { Omnitree.Bounds item_bounds = GetBoundings(current.Value); if (!this.EncapsulationCheck(node.Bounds, item_bounds)) @@ -22750,7 +22750,7 @@ internal int Remove(Node node, Predicate where) int removals = 0; // children - if (!(node.Children is null)) + if (node.Children is not null) { int skipped = 0; for (int i = 0; i + skipped < node.Children.Length; ) @@ -22770,15 +22770,15 @@ internal int Remove(Node node, Predicate where) } // items - while (!(node.Head is null) && where(node.Head.Value)) + while (node.Head is not null && where(node.Head.Value)) { node.Head = node.Head.Next; removals++; } - if (!(node.Head is null)) + if (node.Head is not null) { Node.ValueNode list = node.Head; - while (!(list.Next is null)) + while (list.Next is not null) { if (where(list.Next.Value)) { @@ -22901,7 +22901,7 @@ internal int RemoveBase( } // children - if (!(node.Children is null)) + if (node.Children is not null) { int skipped = 0; for (int i = 0; i + skipped < node.Children.Length; ) @@ -23010,7 +23010,7 @@ internal int RemoveBase( // items Node.ValueNode current = node.Head; Node.ValueNode previous = null; - while (!(current is null)) + while (current is not null) { if (spatialCheck(bounds, GetBoundings(current.Value)) && where(current.Value)) { @@ -23029,7 +23029,7 @@ internal int RemoveBase( } // children - if (!(node.Children is null)) + if (node.Children is not null) { int skipped = 0; for (int i = 0; i + skipped < node.Children.Length; ) @@ -23117,12 +23117,12 @@ public void Stepper(Action step) => internal void Stepper(Action step, Node node) { Node.ValueNode list = node.Head; - while (!(list is null)) + while (list is not null) { step(list.Value); list = list.Next; } - if (!(node.Children is null)) + if (node.Children is not null) foreach (Node child in node.Children) this.Stepper(step, child); } @@ -23136,11 +23136,11 @@ internal StepStatus Stepper(Func step, Node node) { StepStatus status = StepStatus.Continue; - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if ((status = step(list.Value)) != StepStatus.Continue) break; - if (!(node.Children is null)) + if (node.Children is not null) foreach (Node child in node.Children) if ((status = Stepper(step, child)) != StepStatus.Continue) break; @@ -23212,11 +23212,11 @@ internal void StepperBase( Omnitree.Bounds bounds, Omnitree.SpatialCheck, Omnitree.Bounds> spatialCheck) { - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if (spatialCheck(bounds, GetBoundings(list.Value))) step(list.Value); - if (!(node.Children is null)) + if (node.Children is not null) { foreach (Node child in node.Children) // optimization: stop bounds checking if space encapsulates node @@ -23293,12 +23293,12 @@ internal StepStatus StepperBase( { StepStatus status = StepStatus.Continue; - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if (spatialCheck(bounds, GetBoundings(list.Value)) && (status = step(list.Value)) != StepStatus.Continue) break; - if (!(node.Children is null)) + if (node.Children is not null) { foreach (Node child in node.Children) // optimization: stop bounds checking if space encapsulates node @@ -23420,7 +23420,7 @@ internal void ReduceParentCounts(Node parent, int reduction) internal void IncreaseParentCounts(Node parent, int increase) { Node node = parent; - while (!(node is null)) + while (node is not null) { node.Count += increase; node = node.Parent; @@ -23473,7 +23473,7 @@ internal bool EqualsCheck(Omnitree.Vector a, Omnitre /// The nearest node that encapsulates the given location. internal Node GetEncapsulationParent(Node node, Omnitree.Bounds bounds) { - while (!(node is null) && !EncapsulationCheck(node.Bounds, bounds)) + while (node is not null && !EncapsulationCheck(node.Bounds, bounds)) { node = node.Parent; } @@ -23906,7 +23906,7 @@ internal int Depth get { int depth = -1; - for (Node node = this; !(node is null); node = node.Parent) + for (Node node = this; node is not null; node = node.Parent) depth++; return depth; } @@ -23942,7 +23942,7 @@ internal Node(Node nodeToClone) ValueNode a = this.Head; ValueNode b = nodeToClone.Head; - while (!(b is null)) + while (b is not null) { a.Next = new ValueNode(b.Next.Value, null); a = a.Next; @@ -24282,7 +24282,7 @@ public void Add(T addition) this._top = new Node(DetermineMedians(top), Omnitree.Bounds.None, null, -1); // iterate through the elements and add them to the appropriate children - for (Node.ValueNode list = top.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = top.Head; list is not null; list = list.Next) Add(list.Value, this._top, GetBoundings(list.Value), 0); } @@ -24314,7 +24314,7 @@ internal void Add(T addition, Node node, Omnitree.Bounds temp_bounds = GetBoundings(list.Value); if (EncapsulationCheck(growth.Bounds, temp_bounds)) @@ -24674,7 +24674,7 @@ internal int CountSubSpaceBase( count += node.Count; else if (!node.PointOfDivision.HasValue) { - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if (spatialCheck(bounds, GetBoundings(list.Value))) count++; } @@ -24685,7 +24685,7 @@ internal int CountSubSpaceBase( { int child_index = DetermineChildIndex(branch.PointOfDivision.Value, bounds); Node child = branch[child_index]; - if (!(child is null)) + if (child is not null) count += this.CountSubSpaceBase(child, bounds, spatialCheck); } else @@ -24736,7 +24736,7 @@ internal int Update(Node node, int depth) { Node.ValueNode current = node.Head; Node.ValueNode previous = null; - while (!(current is null)) + while (current is not null) { Omnitree.Bounds bounds = GetBoundings(current.Value); if (!this.EncapsulationCheck(node.Bounds, bounds)) @@ -24847,7 +24847,7 @@ internal int Update(Omnitree.Bounds bounds, N { Node.ValueNode current = node.Head; Node.ValueNode previous = null; - while (!(current is null)) + while (current is not null) { Omnitree.Bounds item_bounds = GetBoundings(current.Value); if (!this.EncapsulationCheck(node.Bounds, item_bounds)) @@ -24896,7 +24896,7 @@ internal int Remove(Node node, Predicate where) int removals = 0; // children - if (!(node.Children is null)) + if (node.Children is not null) { int skipped = 0; for (int i = 0; i + skipped < node.Children.Length; ) @@ -24916,15 +24916,15 @@ internal int Remove(Node node, Predicate where) } // items - while (!(node.Head is null) && where(node.Head.Value)) + while (node.Head is not null && where(node.Head.Value)) { node.Head = node.Head.Next; removals++; } - if (!(node.Head is null)) + if (node.Head is not null) { Node.ValueNode list = node.Head; - while (!(list.Next is null)) + while (list.Next is not null) { if (where(list.Next.Value)) { @@ -25056,7 +25056,7 @@ internal int RemoveBase( } // children - if (!(node.Children is null)) + if (node.Children is not null) { int skipped = 0; for (int i = 0; i + skipped < node.Children.Length; ) @@ -25173,7 +25173,7 @@ internal int RemoveBase( // items Node.ValueNode current = node.Head; Node.ValueNode previous = null; - while (!(current is null)) + while (current is not null) { if (spatialCheck(bounds, GetBoundings(current.Value)) && where(current.Value)) { @@ -25192,7 +25192,7 @@ internal int RemoveBase( } // children - if (!(node.Children is null)) + if (node.Children is not null) { int skipped = 0; for (int i = 0; i + skipped < node.Children.Length; ) @@ -25285,12 +25285,12 @@ public void Stepper(Action step) => internal void Stepper(Action step, Node node) { Node.ValueNode list = node.Head; - while (!(list is null)) + while (list is not null) { step(list.Value); list = list.Next; } - if (!(node.Children is null)) + if (node.Children is not null) foreach (Node child in node.Children) this.Stepper(step, child); } @@ -25304,11 +25304,11 @@ internal StepStatus Stepper(Func step, Node node) { StepStatus status = StepStatus.Continue; - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if ((status = step(list.Value)) != StepStatus.Continue) break; - if (!(node.Children is null)) + if (node.Children is not null) foreach (Node child in node.Children) if ((status = Stepper(step, child)) != StepStatus.Continue) break; @@ -25388,11 +25388,11 @@ internal void StepperBase( Omnitree.Bounds bounds, Omnitree.SpatialCheck, Omnitree.Bounds> spatialCheck) { - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if (spatialCheck(bounds, GetBoundings(list.Value))) step(list.Value); - if (!(node.Children is null)) + if (node.Children is not null) { foreach (Node child in node.Children) // optimization: stop bounds checking if space encapsulates node @@ -25477,12 +25477,12 @@ internal StepStatus StepperBase( { StepStatus status = StepStatus.Continue; - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if (spatialCheck(bounds, GetBoundings(list.Value)) && (status = step(list.Value)) != StepStatus.Continue) break; - if (!(node.Children is null)) + if (node.Children is not null) { foreach (Node child in node.Children) // optimization: stop bounds checking if space encapsulates node @@ -25611,7 +25611,7 @@ internal void ReduceParentCounts(Node parent, int reduction) internal void IncreaseParentCounts(Node parent, int increase) { Node node = parent; - while (!(node is null)) + while (node is not null) { node.Count += increase; node = node.Parent; @@ -25668,7 +25668,7 @@ internal bool EqualsCheck(Omnitree.Vector a, /// The nearest node that encapsulates the given location. internal Node GetEncapsulationParent(Node node, Omnitree.Bounds bounds) { - while (!(node is null) && !EncapsulationCheck(node.Bounds, bounds)) + while (node is not null && !EncapsulationCheck(node.Bounds, bounds)) { node = node.Parent; } @@ -26147,7 +26147,7 @@ internal int Depth get { int depth = -1; - for (Node node = this; !(node is null); node = node.Parent) + for (Node node = this; node is not null; node = node.Parent) depth++; return depth; } @@ -26183,7 +26183,7 @@ internal Node(Node nodeToClone) ValueNode a = this.Head; ValueNode b = nodeToClone.Head; - while (!(b is null)) + while (b is not null) { a.Next = new ValueNode(b.Next.Value, null); a = a.Next; @@ -26560,7 +26560,7 @@ public void Add(T addition) this._top = new Node(DetermineMedians(top), Omnitree.Bounds.None, null, -1); // iterate through the elements and add them to the appropriate children - for (Node.ValueNode list = top.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = top.Head; list is not null; list = list.Next) Add(list.Value, this._top, GetBoundings(list.Value), 0); } @@ -26592,7 +26592,7 @@ internal void Add(T addition, Node node, Omnitree.Bounds temp_bounds = GetBoundings(list.Value); if (EncapsulationCheck(growth.Bounds, temp_bounds)) @@ -26988,7 +26988,7 @@ internal int CountSubSpaceBase( count += node.Count; else if (!node.PointOfDivision.HasValue) { - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if (spatialCheck(bounds, GetBoundings(list.Value))) count++; } @@ -26999,7 +26999,7 @@ internal int CountSubSpaceBase( { int child_index = DetermineChildIndex(branch.PointOfDivision.Value, bounds); Node child = branch[child_index]; - if (!(child is null)) + if (child is not null) count += this.CountSubSpaceBase(child, bounds, spatialCheck); } else @@ -27050,7 +27050,7 @@ internal int Update(Node node, int depth) { Node.ValueNode current = node.Head; Node.ValueNode previous = null; - while (!(current is null)) + while (current is not null) { Omnitree.Bounds bounds = GetBoundings(current.Value); if (!this.EncapsulationCheck(node.Bounds, bounds)) @@ -27167,7 +27167,7 @@ internal int Update(Omnitree.Bounds bo { Node.ValueNode current = node.Head; Node.ValueNode previous = null; - while (!(current is null)) + while (current is not null) { Omnitree.Bounds item_bounds = GetBoundings(current.Value); if (!this.EncapsulationCheck(node.Bounds, item_bounds)) @@ -27216,7 +27216,7 @@ internal int Remove(Node node, Predicate where) int removals = 0; // children - if (!(node.Children is null)) + if (node.Children is not null) { int skipped = 0; for (int i = 0; i + skipped < node.Children.Length; ) @@ -27236,15 +27236,15 @@ internal int Remove(Node node, Predicate where) } // items - while (!(node.Head is null) && where(node.Head.Value)) + while (node.Head is not null && where(node.Head.Value)) { node.Head = node.Head.Next; removals++; } - if (!(node.Head is null)) + if (node.Head is not null) { Node.ValueNode list = node.Head; - while (!(list.Next is null)) + while (list.Next is not null) { if (where(list.Next.Value)) { @@ -27385,7 +27385,7 @@ internal int RemoveBase( } // children - if (!(node.Children is null)) + if (node.Children is not null) { int skipped = 0; for (int i = 0; i + skipped < node.Children.Length; ) @@ -27510,7 +27510,7 @@ internal int RemoveBase( // items Node.ValueNode current = node.Head; Node.ValueNode previous = null; - while (!(current is null)) + while (current is not null) { if (spatialCheck(bounds, GetBoundings(current.Value)) && where(current.Value)) { @@ -27529,7 +27529,7 @@ internal int RemoveBase( } // children - if (!(node.Children is null)) + if (node.Children is not null) { int skipped = 0; for (int i = 0; i + skipped < node.Children.Length; ) @@ -27627,12 +27627,12 @@ public void Stepper(Action step) => internal void Stepper(Action step, Node node) { Node.ValueNode list = node.Head; - while (!(list is null)) + while (list is not null) { step(list.Value); list = list.Next; } - if (!(node.Children is null)) + if (node.Children is not null) foreach (Node child in node.Children) this.Stepper(step, child); } @@ -27646,11 +27646,11 @@ internal StepStatus Stepper(Func step, Node node) { StepStatus status = StepStatus.Continue; - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if ((status = step(list.Value)) != StepStatus.Continue) break; - if (!(node.Children is null)) + if (node.Children is not null) foreach (Node child in node.Children) if ((status = Stepper(step, child)) != StepStatus.Continue) break; @@ -27738,11 +27738,11 @@ internal void StepperBase( Omnitree.Bounds bounds, Omnitree.SpatialCheck, Omnitree.Bounds> spatialCheck) { - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if (spatialCheck(bounds, GetBoundings(list.Value))) step(list.Value); - if (!(node.Children is null)) + if (node.Children is not null) { foreach (Node child in node.Children) // optimization: stop bounds checking if space encapsulates node @@ -27835,12 +27835,12 @@ internal StepStatus StepperBase( { StepStatus status = StepStatus.Continue; - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if (spatialCheck(bounds, GetBoundings(list.Value)) && (status = step(list.Value)) != StepStatus.Continue) break; - if (!(node.Children is null)) + if (node.Children is not null) { foreach (Node child in node.Children) // optimization: stop bounds checking if space encapsulates node @@ -27976,7 +27976,7 @@ internal void ReduceParentCounts(Node parent, int reduction) internal void IncreaseParentCounts(Node parent, int increase) { Node node = parent; - while (!(node is null)) + while (node is not null) { node.Count += increase; node = node.Parent; @@ -28037,7 +28037,7 @@ internal bool EqualsCheck(Omnitree.VectorThe nearest node that encapsulates the given location. internal Node GetEncapsulationParent(Node node, Omnitree.Bounds bounds) { - while (!(node is null) && !EncapsulationCheck(node.Bounds, bounds)) + while (node is not null && !EncapsulationCheck(node.Bounds, bounds)) { node = node.Parent; } @@ -28562,7 +28562,7 @@ internal int Depth get { int depth = -1; - for (Node node = this; !(node is null); node = node.Parent) + for (Node node = this; node is not null; node = node.Parent) depth++; return depth; } @@ -28598,7 +28598,7 @@ internal Node(Node nodeToClone) ValueNode a = this.Head; ValueNode b = nodeToClone.Head; - while (!(b is null)) + while (b is not null) { a.Next = new ValueNode(b.Next.Value, null); a = a.Next; @@ -29012,7 +29012,7 @@ public void Add(T addition) this._top = new Node(DetermineMedians(top), Omnitree.Bounds.None, null, -1); // iterate through the elements and add them to the appropriate children - for (Node.ValueNode list = top.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = top.Head; list is not null; list = list.Next) Add(list.Value, this._top, GetBoundings(list.Value), 0); } @@ -29044,7 +29044,7 @@ internal void Add(T addition, Node node, Omnitree.Bounds temp_bounds = GetBoundings(list.Value); if (EncapsulationCheck(growth.Bounds, temp_bounds)) @@ -29476,7 +29476,7 @@ internal int CountSubSpaceBase( count += node.Count; else if (!node.PointOfDivision.HasValue) { - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if (spatialCheck(bounds, GetBoundings(list.Value))) count++; } @@ -29487,7 +29487,7 @@ internal int CountSubSpaceBase( { int child_index = DetermineChildIndex(branch.PointOfDivision.Value, bounds); Node child = branch[child_index]; - if (!(child is null)) + if (child is not null) count += this.CountSubSpaceBase(child, bounds, spatialCheck); } else @@ -29538,7 +29538,7 @@ internal int Update(Node node, int depth) { Node.ValueNode current = node.Head; Node.ValueNode previous = null; - while (!(current is null)) + while (current is not null) { Omnitree.Bounds bounds = GetBoundings(current.Value); if (!this.EncapsulationCheck(node.Bounds, bounds)) @@ -29661,7 +29661,7 @@ internal int Update(Omnitree.Bounds item_bounds = GetBoundings(current.Value); if (!this.EncapsulationCheck(node.Bounds, item_bounds)) @@ -29710,7 +29710,7 @@ internal int Remove(Node node, Predicate where) int removals = 0; // children - if (!(node.Children is null)) + if (node.Children is not null) { int skipped = 0; for (int i = 0; i + skipped < node.Children.Length; ) @@ -29730,15 +29730,15 @@ internal int Remove(Node node, Predicate where) } // items - while (!(node.Head is null) && where(node.Head.Value)) + while (node.Head is not null && where(node.Head.Value)) { node.Head = node.Head.Next; removals++; } - if (!(node.Head is null)) + if (node.Head is not null) { Node.ValueNode list = node.Head; - while (!(list.Next is null)) + while (list.Next is not null) { if (where(list.Next.Value)) { @@ -29888,7 +29888,7 @@ internal int RemoveBase( } // children - if (!(node.Children is null)) + if (node.Children is not null) { int skipped = 0; for (int i = 0; i + skipped < node.Children.Length; ) @@ -30021,7 +30021,7 @@ internal int RemoveBase( // items Node.ValueNode current = node.Head; Node.ValueNode previous = null; - while (!(current is null)) + while (current is not null) { if (spatialCheck(bounds, GetBoundings(current.Value)) && where(current.Value)) { @@ -30040,7 +30040,7 @@ internal int RemoveBase( } // children - if (!(node.Children is null)) + if (node.Children is not null) { int skipped = 0; for (int i = 0; i + skipped < node.Children.Length; ) @@ -30143,12 +30143,12 @@ public void Stepper(Action step) => internal void Stepper(Action step, Node node) { Node.ValueNode list = node.Head; - while (!(list is null)) + while (list is not null) { step(list.Value); list = list.Next; } - if (!(node.Children is null)) + if (node.Children is not null) foreach (Node child in node.Children) this.Stepper(step, child); } @@ -30162,11 +30162,11 @@ internal StepStatus Stepper(Func step, Node node) { StepStatus status = StepStatus.Continue; - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if ((status = step(list.Value)) != StepStatus.Continue) break; - if (!(node.Children is null)) + if (node.Children is not null) foreach (Node child in node.Children) if ((status = Stepper(step, child)) != StepStatus.Continue) break; @@ -30262,11 +30262,11 @@ internal void StepperBase( Omnitree.Bounds bounds, Omnitree.SpatialCheck, Omnitree.Bounds> spatialCheck) { - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if (spatialCheck(bounds, GetBoundings(list.Value))) step(list.Value); - if (!(node.Children is null)) + if (node.Children is not null) { foreach (Node child in node.Children) // optimization: stop bounds checking if space encapsulates node @@ -30367,12 +30367,12 @@ internal StepStatus StepperBase( { StepStatus status = StepStatus.Continue; - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if (spatialCheck(bounds, GetBoundings(list.Value)) && (status = step(list.Value)) != StepStatus.Continue) break; - if (!(node.Children is null)) + if (node.Children is not null) { foreach (Node child in node.Children) // optimization: stop bounds checking if space encapsulates node @@ -30515,7 +30515,7 @@ internal void ReduceParentCounts(Node parent, int reduction) internal void IncreaseParentCounts(Node parent, int increase) { Node node = parent; - while (!(node is null)) + while (node is not null) { node.Count += increase; node = node.Parent; @@ -30580,7 +30580,7 @@ internal bool EqualsCheck(Omnitree.VectorThe nearest node that encapsulates the given location. internal Node GetEncapsulationParent(Node node, Omnitree.Bounds bounds) { - while (!(node is null) && !EncapsulationCheck(node.Bounds, bounds)) + while (node is not null && !EncapsulationCheck(node.Bounds, bounds)) { node = node.Parent; } diff --git a/Sources/Towel/DataStructures/Omnitree.tt b/Sources/Towel/DataStructures/Omnitree.tt index 617feba4..22111d01 100644 --- a/Sources/Towel/DataStructures/Omnitree.tt +++ b/Sources/Towel/DataStructures/Omnitree.tt @@ -593,7 +593,7 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume get { int depth = -1; - for (Node node = this; !(node is null); node = node.Parent) + for (Node node = this; node is not null; node = node.Parent) depth++; return depth; } @@ -731,7 +731,7 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume Head = new Node(leaf.Head.Value, null); Node a = Head; Node b = leaf.Head; - while (!(b is null)) + while (b is not null) { a.Next = new Node(b.Next.Value, null); a = a.Next; @@ -1292,7 +1292,7 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume this._top = new Branch(DetermineMedians(top), Omnitree.Bounds<<#= chain_AxisX #>>.None, null, -1); // iterate through the elements and add them to the appropriate children - for (Leaf.Node list = top.Head; !(list is null); list = list.Next) + for (Leaf.Node list = top.Head; list is not null; list = list.Next) Add(list.Value, this._top, LocateVector(list.Value), 0); } @@ -1320,7 +1320,7 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume <#= child_index_type #> child_index = this.DetermineChildIndex(parent.PointOfDivision, location); Branch growth = new Branch(DetermineMedians(leaf), leaf.Bounds, parent, child_index); parent[child_index] = growth; - for (Leaf.Node list = leaf.Head; !(list is null); list = list.Next) + for (Leaf.Node list = leaf.Head; list is not null; list = list.Next) { Omnitree.Vector<<#= chain_AxisX #>> temp_location = LocateVector(list.Value); if (EncapsulationCheck(growth.Bounds, temp_location)) @@ -1367,7 +1367,7 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume { division<#= j #> = _subdivisionOverride<#= j #>(leaf.Bounds, x => { - for (Leaf.Node node = leaf.Head; !(node is null); node = node.Next) + for (Leaf.Node node = leaf.Head; node is not null; node = node.Next) { x(node.Value); } @@ -1493,7 +1493,7 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume count += node.Count; else if (node is Leaf) { - for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next) + for (Leaf.Node list = (node as Leaf).Head; list is null; list = list.Next) if (EncapsulationCheck(bounds, LocateVector(list.Value))) count++; } @@ -1508,7 +1508,7 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume <# } #> )); Node child = branch[child_index]; - if (!(child is null)) + if (child is not null) { count += this.CountSubSpace(child, bounds); } @@ -1544,7 +1544,7 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume Leaf leaf = node as Leaf; Leaf.Node current = leaf.Head; Leaf.Node previous = null; - while (!(current is null)) + while (current is not null) { Omnitree.Vector<<#= chain_AxisX #>> location = LocateVector(current.Value); if (!this.EncapsulationCheck(node.Bounds, location)) @@ -1634,7 +1634,7 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume Leaf leaf = node as Leaf; Leaf.Node current = leaf.Head; Leaf.Node previous = null; - while (!(current is null)) + while (current is not null) { Omnitree.Vector<<#= chain_AxisX #>> location = LocateVector(current.Value); if (!this.EncapsulationCheck(node.Bounds, location)) @@ -1706,15 +1706,15 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume if (node is Leaf) { Leaf leaf = node as Leaf; - while (!(leaf.Head is null) && where(leaf.Head.Value)) + while (leaf.Head is not null && where(leaf.Head.Value)) { leaf.Head = leaf.Head.Next; removals++; } - if (!(leaf.Head is null)) + if (leaf.Head is not null) { Leaf.Node list = leaf.Head; - while (!(list.Next is null)) + while (list.Next is not null) { if (where(list.Next.Value)) { @@ -1850,7 +1850,7 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume Leaf leaf = node as Leaf; Leaf.Node current = leaf.Head; Leaf.Node previous = null; - while (!(current is null)) + while (current is not null) { if (this.EncapsulationCheck(bounds, LocateVector(current.Value)) && where(current.Value)) { @@ -2034,7 +2034,7 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume if (node is Leaf) { Leaf.Node list = (node as Leaf).Head; - while (!(list is null)) + while (list is not null) { step(list.Value); list = list.Next; @@ -2057,7 +2057,7 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume StepStatus status = StepStatus.Continue; if (node is Leaf) { - for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next) + for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next) if ((status = step(list.Value)) != StepStatus.Continue) break; } @@ -2086,7 +2086,7 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume { if (node is Leaf) { - for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next) + for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next) if (EncapsulationCheck(bounds, LocateVector(list.Value))) step(list.Value); } @@ -2118,7 +2118,7 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume StepStatus status = StepStatus.Continue; if (node is Leaf) { - for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next) + for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next) if (EncapsulationCheck(bounds, LocateVector(list.Value)) && (status = step(list.Value)) != StepStatus.Continue) break; @@ -2146,11 +2146,11 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume internal void Stepper(Action step, Node node, Omnitree.Vector<<#= chain_AxisX #>> vector) { Node current = node; - while (!(current is null)) + while (current is not null) { if (current is Leaf) { - for (Leaf.Node leaf_node = (current as Leaf).Head; !(leaf_node is null); leaf_node = leaf_node.Next) + for (Leaf.Node leaf_node = (current as Leaf).Head; leaf_node is not null; leaf_node = leaf_node.Next) if (EqualsCheck(vector, LocateVector(leaf_node.Value))) step(leaf_node.Value); break; @@ -2173,11 +2173,11 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume internal StepStatus Stepper(Func step, Node node, Omnitree.Vector<<#= chain_AxisX #>> vector) { Node current = node; - while (!(current is null)) + while (current is not null) { if (current is Leaf) { - for (Leaf.Node list = (current as Leaf).Head; !(list is null); list = list.Next) + for (Leaf.Node list = (current as Leaf).Head; list is not null; list = list.Next) { StepStatus status = StepStatus.Continue; if (EqualsCheck(vector, LocateVector(list.Value)) && @@ -2267,7 +2267,7 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume internal void IncreaseParentCounts(Node parent, int increase) { Node node = parent; - while (!(node is null)) + while (node is not null) { node.Count += increase; node = node.Parent; @@ -2316,7 +2316,7 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume /// The nearest node that encapsulates the given location. internal Node GetEncapsulationParent(Node node, Omnitree.Vector<<#= chain_AxisX #>> vector) { - while (!(node is null) && !EncapsulationCheck(node.Bounds, vector)) + while (node is not null && !EncapsulationCheck(node.Bounds, vector)) { node = node.Parent; } @@ -2589,7 +2589,7 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume get { int depth = -1; - for (Node node = this; !(node is null); node = node.Parent) + for (Node node = this; node is not null; node = node.Parent) depth++; return depth; } @@ -2625,7 +2625,7 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume ValueNode a = this.Head; ValueNode b = nodeToClone.Head; - while (!(b is null)) + while (b is not null) { a.Next = new ValueNode(b.Next.Value, null); a = a.Next; @@ -3160,7 +3160,7 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume this._top = new Node(DetermineMedians(top), Omnitree.Bounds<<#= chain_AxisX #>>.None, null, -1); // iterate through the elements and add them to the appropriate children - for (Node.ValueNode list = top.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = top.Head; list is not null; list = list.Next) Add(list.Value, this._top, GetBoundings(list.Value), 0); } @@ -3192,7 +3192,7 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume Node growth = new Node(DetermineMedians(node), node.Bounds, node.Parent, node.Index); node.Parent[node.Index] = growth; - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) { Omnitree.Bounds<<#= chain_AxisX #>> temp_bounds = GetBoundings(list.Value); if (EncapsulationCheck(growth.Bounds, temp_bounds)) @@ -3426,7 +3426,7 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume count += node.Count; else if (!node.PointOfDivision.HasValue) { - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if (spatialCheck(bounds, GetBoundings(list.Value))) count++; } @@ -3437,7 +3437,7 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume { <#= child_index_type #> child_index = DetermineChildIndex(branch.PointOfDivision.Value, bounds); Node child = branch[child_index]; - if (!(child is null)) + if (child is not null) count += this.CountSubSpaceBase(child, bounds, spatialCheck); } else @@ -3488,7 +3488,7 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume { Node.ValueNode current = node.Head; Node.ValueNode previous = null; - while (!(current is null)) + while (current is not null) { Omnitree.Bounds<<#= chain_AxisX #>> bounds = GetBoundings(current.Value); if (!this.EncapsulationCheck(node.Bounds, bounds)) @@ -3573,7 +3573,7 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume { Node.ValueNode current = node.Head; Node.ValueNode previous = null; - while (!(current is null)) + while (current is not null) { Omnitree.Bounds<<#= chain_AxisX #>> item_bounds = GetBoundings(current.Value); if (!this.EncapsulationCheck(node.Bounds, item_bounds)) @@ -3622,7 +3622,7 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume int removals = 0; // children - if (!(node.Children is null)) + if (node.Children is not null) { int skipped = 0; for (int i = 0; i + skipped < node.Children.Length; ) @@ -3642,15 +3642,15 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume } // items - while (!(node.Head is null) && where(node.Head.Value)) + while (node.Head is not null && where(node.Head.Value)) { node.Head = node.Head.Next; removals++; } - if (!(node.Head is null)) + if (node.Head is not null) { Node.ValueNode list = node.Head; - while (!(list.Next is null)) + while (list.Next is not null) { if (where(list.Next.Value)) { @@ -3742,7 +3742,7 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume } // children - if (!(node.Children is null)) + if (node.Children is not null) { int skipped = 0; for (int i = 0; i + skipped < node.Children.Length; ) @@ -3823,7 +3823,7 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume // items Node.ValueNode current = node.Head; Node.ValueNode previous = null; - while (!(current is null)) + while (current is not null) { if (spatialCheck(bounds, GetBoundings(current.Value)) && where(current.Value)) { @@ -3842,7 +3842,7 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume } // children - if (!(node.Children is null)) + if (node.Children is not null) { int skipped = 0; for (int i = 0; i + skipped < node.Children.Length; ) @@ -3924,12 +3924,12 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume internal void Stepper(Action step, Node node) { Node.ValueNode list = node.Head; - while (!(list is null)) + while (list is not null) { step(list.Value); list = list.Next; } - if (!(node.Children is null)) + if (node.Children is not null) foreach (Node child in node.Children) this.Stepper(step, child); } @@ -3943,11 +3943,11 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume { StepStatus status = StepStatus.Continue; - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if ((status = step(list.Value)) != StepStatus.Continue) break; - if (!(node.Children is null)) + if (node.Children is not null) foreach (Node child in node.Children) if ((status = Stepper(step, child)) != StepStatus.Continue) break; @@ -3991,11 +3991,11 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume Omnitree.Bounds<<#= chain_AxisX #>> bounds, Omnitree.SpatialCheck>, Omnitree.Bounds<<#= chain_AxisX #>>> spatialCheck) { - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if (spatialCheck(bounds, GetBoundings(list.Value))) step(list.Value); - if (!(node.Children is null)) + if (node.Children is not null) { foreach (Node child in node.Children) // optimization: stop bounds checking if space encapsulates node @@ -4044,12 +4044,12 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume { StepStatus status = StepStatus.Continue; - for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) + for (Node.ValueNode list = node.Head; list is not null; list = list.Next) if (spatialCheck(bounds, GetBoundings(list.Value)) && (status = step(list.Value)) != StepStatus.Continue) break; - if (!(node.Children is null)) + if (node.Children is not null) { foreach (Node child in node.Children) // optimization: stop bounds checking if space encapsulates node @@ -4160,7 +4160,7 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume internal void IncreaseParentCounts(Node parent, int increase) { Node node = parent; - while (!(node is null)) + while (node is not null) { node.Count += increase; node = node.Parent; @@ -4209,7 +4209,7 @@ string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { docume /// The nearest node that encapsulates the given location. internal Node GetEncapsulationParent(Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds) { - while (!(node is null) && !EncapsulationCheck(node.Bounds, bounds)) + while (node is not null && !EncapsulationCheck(node.Bounds, bounds)) { node = node.Parent; } diff --git a/Sources/Towel/DataStructures/Omnitree_ND.cs b/Sources/Towel/DataStructures/Omnitree_ND.cs index 5d43c087..02a13214 100644 --- a/Sources/Towel/DataStructures/Omnitree_ND.cs +++ b/Sources/Towel/DataStructures/Omnitree_ND.cs @@ -409,7 +409,7 @@ public interface IOmnitree : IDataStructure, // get // { // int depth = -1; - // for (Node node = this; !(node is null); node = node.Parent) + // for (Node node = this; node is not null; node = node.Parent) // depth++; // return depth; // } @@ -564,7 +564,7 @@ public interface IOmnitree : IDataStructure, // Node a = this._head; // Node b = leaf._head; - // while (!(b is null)) + // while (b is not null) // { // a.Next = new Node(b.Next.Value, null); // a = a.Next; @@ -1418,7 +1418,7 @@ public interface IOmnitree : IDataStructure, // this._top = new Branch(DetermineMedians(top), Omnitree.Bounds.None, null, -1); // // iterate through the elements and add them to the appropriate children - // for (Leaf.Node list = top.Head; !(list is null); list = list.Next) + // for (Leaf.Node list = top.Head; list is not null; list = list.Next) // Add(list.Value, this._top, LocateVector(list.Value), 0); // } @@ -1446,7 +1446,7 @@ public interface IOmnitree : IDataStructure, // int child_index = this.DetermineChildIndex(parent.PointOfDivision, location); // Branch growth = new Branch(DetermineMedians(leaf), leaf.Bounds, parent, child_index); // parent[child_index] = growth; - // for (Leaf.Node list = leaf.Head; !(list is null); list = list.Next) + // for (Leaf.Node list = leaf.Head; list is not null; list = list.Next) // { // Omnitree.Vector temp_location = LocateVector(list.Value); // if (EncapsulationCheck(growth.Bounds, temp_location)) @@ -1668,7 +1668,7 @@ public interface IOmnitree : IDataStructure, // count += node.Count; // else if (node is Leaf) // { - // for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next) + // for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next) // if (EncapsulationCheck(bounds, LocateVector(list.Value))) // count++; // } @@ -1702,7 +1702,7 @@ public interface IOmnitree : IDataStructure, // Leaf leaf = node as Leaf; // Leaf.Node current = leaf.Head; // Leaf.Node previous = null; - // while (!(current is null)) + // while (current is not null) // { // Omnitree.Vector location = LocateVector(current.Value); // if (!this.EncapsulationCheck(node.Bounds, location)) @@ -1806,7 +1806,7 @@ public interface IOmnitree : IDataStructure, // Leaf leaf = node as Leaf; // Leaf.Node current = leaf.Head; // Leaf.Node previous = null; - // while (!(current is null)) + // while (current is not null) // { // Omnitree.Vector location = LocateVector(current.Value); // if (!this.EncapsulationCheck(node.Bounds, location)) @@ -1878,15 +1878,15 @@ public interface IOmnitree : IDataStructure, // if (node is Leaf) // { // Leaf leaf = node as Leaf; - // while (!(leaf.Head is null) && where(leaf.Head.Value)) + // while (leaf.Head is not null && where(leaf.Head.Value)) // { // leaf.Head = leaf.Head.Next; // removals++; // } - // if (!(leaf.Head is null)) + // if (leaf.Head is not null) // { // Leaf.Node list = leaf.Head; - // while (!(list.Next is null)) + // while (list.Next is not null) // { // if (where(list.Next.Value)) // { @@ -2059,7 +2059,7 @@ public interface IOmnitree : IDataStructure, // Leaf leaf = node as Leaf; // Leaf.Node current = leaf.Head; // Leaf.Node previous = null; - // while (!(current is null)) + // while (current is not null) // { // if (this.EncapsulationCheck(bounds, LocateVector(current.Value)) && where(current.Value)) // { @@ -2232,7 +2232,7 @@ public interface IOmnitree : IDataStructure, // if (node is Leaf) // { // Leaf.Node list = (node as Leaf).Head; - // while (!(list is null)) + // while (list is not null) // { // function(list.Value); // list = list.Next; @@ -2261,7 +2261,7 @@ public interface IOmnitree : IDataStructure, // StepStatus status = StepStatus.Continue; // if (node is Leaf) // { - // for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next) + // for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next) // if (Code.ReturnAssign(ref status, function(list._value)) != StepStatus.Continue) // break; // } @@ -2302,7 +2302,7 @@ public interface IOmnitree : IDataStructure, // { // if (node is Leaf) // { - // for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next) + // for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next) // if (EncapsulationCheck(bounds, LocateVector(list.Value))) // function(list.Value); // } @@ -2354,7 +2354,7 @@ public interface IOmnitree : IDataStructure, // StepStatus status = StepStatus.Continue; // if (node is Leaf) // { - // for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next) + // for (Leaf.Node list = (node as Leaf).Head; list is not null; list = list.Next) // if (EncapsulationCheck(bounds, LocateVector(list.Value)) && // Code.ReturnAssign(ref status, function(list.Value)) != StepStatus.Continue) // break; @@ -2384,7 +2384,7 @@ public interface IOmnitree : IDataStructure, // internal void Stepper(Action function, Node node, Omnitree.Vector vector) // { // Node current = node; - // while (!(current is null)) + // while (current is not null) // { // if (current is Leaf) // { @@ -2419,11 +2419,11 @@ public interface IOmnitree : IDataStructure, // internal StepStatus Stepper(Func function, Node node, Omnitree.Vector vector) // { // Node current = node; - // while (!(current is null)) + // while (current is not null) // { // if (current is Leaf) // { - // for (Leaf.Node list = (current as Leaf).Head; !(list is null); list = list.Next) + // for (Leaf.Node list = (current as Leaf).Head; list is not null; list = list.Next) // { // StepStatus status = StepStatus.Continue; // if (EqualsCheck(vector, LocateVector(list.Value)) && @@ -2512,7 +2512,7 @@ public interface IOmnitree : IDataStructure, // internal void IncreaseParentCounts(Node parent, int increase) // { // Node node = parent; - // while (!(node is null)) + // while (node is not null) // { // node.Count += increase; // node = node.Parent; @@ -2600,7 +2600,7 @@ public interface IOmnitree : IDataStructure, // /// The nearest node that encapsulates the given location. // internal Node GetEncapsulationParent(Node node, Omnitree.Vector vector) // { - // while (!(node is null) && !EncapsulationCheck(node.Bounds, vector)) + // while (node is not null && !EncapsulationCheck(node.Bounds, vector)) // node = node.Parent; // return node; // } diff --git a/Sources/Towel/DataStructures/RedBlackTree.cs b/Sources/Towel/DataStructures/RedBlackTree.cs index 803fc10d..08b8c28d 100644 --- a/Sources/Towel/DataStructures/RedBlackTree.cs +++ b/Sources/Towel/DataStructures/RedBlackTree.cs @@ -371,7 +371,7 @@ internal void Remove(Node removal) x = temp.RightChild; } x.Parent = temp.Parent; - if (!(temp.Parent is null)) + if (temp.Parent is not null) { if (temp == temp.Parent.LeftChild) { @@ -659,7 +659,7 @@ public IEnumerator GetEnumerator() { Node? GetNextNode(Node current) { - if (!(current.RightChild is null) && current.RightChild != _sentinelNode) + if (current.RightChild is not null && current.RightChild != _sentinelNode) { return GetLeftMostNode(current.RightChild); } @@ -745,7 +745,7 @@ internal void RotateLeft(Node redBlackTree) temp.LeftChild.Parent = redBlackTree; if (temp != _sentinelNode) temp.Parent = redBlackTree.Parent; - if (!(redBlackTree.Parent is null)) + if (redBlackTree.Parent is not null) { if (redBlackTree == redBlackTree.Parent.LeftChild) redBlackTree.Parent.LeftChild = temp; @@ -767,7 +767,7 @@ internal void RotateRight(Node redBlacktree) temp.RightChild.Parent = redBlacktree; if (temp != _sentinelNode) temp.Parent = redBlacktree.Parent; - if (!(redBlacktree.Parent is null)) + if (redBlacktree.Parent is not null) { if (redBlacktree == redBlacktree.Parent.RightChild) redBlacktree.Parent.RightChild = temp; @@ -854,7 +854,7 @@ internal void BalanceRemoval(Node balancing) internal Node GetLeftMostNode(Node node) { - while (!(node.LeftChild is null) && node.LeftChild != _sentinelNode) + while (node.LeftChild is not null && node.LeftChild != _sentinelNode) { node = node.LeftChild; } diff --git a/Sources/Towel/DataStructures/Trie.cs b/Sources/Towel/DataStructures/Trie.cs index 6220a3c1..6dfe8bf3 100644 --- a/Sources/Towel/DataStructures/Trie.cs +++ b/Sources/Towel/DataStructures/Trie.cs @@ -234,7 +234,7 @@ public bool TryRemove(Action> stepper, out Exception? exception) } pathStack.Push((finalKey, finalMap, node)); }); - if (!(capturedException is null)) + if (capturedException is not null) { exception = capturedException; return false; @@ -628,7 +628,7 @@ public bool TryRemove(Action> stepper, out Exception? exception) } pathStack.Push((finalKey, finalMap, node)); }); - if (!(capturedException is null)) + if (capturedException is not null) { exception = capturedException; return false; diff --git a/Sources/Towel/Functional.cs b/Sources/Towel/Functional.cs index 22806e4b..35345a57 100644 --- a/Sources/Towel/Functional.cs +++ b/Sources/Towel/Functional.cs @@ -3,227 +3,291 @@ namespace Towel { + /// Encapsulates a method. public interface IAction { + /// Inocation of the method. void Do(); } + /// Encapsulates a method. public interface IAction { + /// Inocation of the method. void Do(T1 arg1); } + /// Encapsulates a method. public interface IAction { + /// Inocation of the method. void Do(T1 arg1, T2 arg2); } + /// Encapsulates a method. public interface IAction { + /// Inocation of the method. void Do(T1 arg1, T2 arg2, T3 arg3); } + /// Encapsulates a method. public interface IAction { + /// Inocation of the method. void Do(T1 arg1, T2 arg2, T3 arg3, T4 arg4); } + /// Encapsulates a method. public interface IAction { + /// Inocation of the method. void Do(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5); } + /// Encapsulates a method. public interface IAction { + /// Inocation of the method. void Do(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6); } + /// Encapsulates a method. public interface IAction { + /// Inocation of the method. void Do(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7); } + /// Encapsulates a method. public interface IFunc { + /// Inocation of the method. TResult Do(); } + /// Encapsulates a method. public interface IFunc { + /// Inocation of the method. TResult Do(T1 arg1); } + /// Encapsulates a method. public interface IFunc { + /// Inocation of the method. TResult Do(T1 arg1, T2 arg2); } + /// Encapsulates a method. public interface IFunc { + /// Inocation of the method. TResult Do(T1 arg1, T2 arg2, T3 arg3); } + /// Encapsulates a method. public interface IFunc { + /// Inocation of the method. TResult Do(T1 arg1, T2 arg2, T3 arg3, T4 arg4); } + /// Encapsulates a method. public interface IFunc { + /// Inocation of the method. TResult Do(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5); } + /// Encapsulates a method. public interface IFunc { + /// Inocation of the method. TResult Do(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6); } + /// Encapsulates a method. public interface IFunc { + /// Inocation of the method. TResult Do(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7); } + /// Encapsulates a delegate. public struct ActionRuntime : IAction { + /// The delegate instance. internal Action _delegate; - + /// Inocation of the delegate. public void Do() => _delegate(); - + /// Implicit caster from a delegate. public static implicit operator ActionRuntime(Action @delegate) => new ActionRuntime() { _delegate = @delegate, }; } + /// Encapsulates a delegate. public struct ActionRuntime : IAction { + /// The delegate instance. internal Action _delegate; - + /// Inocation of the delegate. public void Do(T1 arg1) => _delegate(arg1); - + /// Implicit caster from a delegate. public static implicit operator ActionRuntime(Action @delegate) => new ActionRuntime() { _delegate = @delegate, }; } + /// Encapsulates a delegate. public struct ActionRuntime : IAction { + /// The delegate instance. internal Action _delegate; - + /// Inocation of the delegate. public void Do(T1 arg1, T2 arg2) => _delegate(arg1, arg2); - + /// Implicit caster from a delegate. public static implicit operator ActionRuntime(Action @delegate) => new ActionRuntime() { _delegate = @delegate, }; } + /// Encapsulates a delegate. public struct ActionRuntime : IAction { + /// The delegate instance. internal Action _delegate; - + /// Inocation of the delegate. public void Do(T1 arg1, T2 arg2, T3 arg3) => _delegate(arg1, arg2, arg3); - + /// Implicit caster from a delegate. public static implicit operator ActionRuntime(Action @delegate) => new ActionRuntime() { _delegate = @delegate, }; } + /// Encapsulates a delegate. public struct ActionRuntime : IAction { + /// The delegate instance. internal Action _delegate; - + /// Inocation of the delegate. public void Do(T1 arg1, T2 arg2, T3 arg3, T4 arg4) => _delegate(arg1, arg2, arg3, arg4); - + /// Implicit caster from a delegate. public static implicit operator ActionRuntime(Action @delegate) => new ActionRuntime() { _delegate = @delegate, }; } + /// Encapsulates a delegate. public struct ActionRuntime : IAction { + /// The delegate instance. internal Action _delegate; - + /// Inocation of the delegate. public void Do(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) => _delegate(arg1, arg2, arg3, arg4, arg5); - + /// Implicit caster from a delegate. public static implicit operator ActionRuntime(Action @delegate) => new ActionRuntime() { _delegate = @delegate, }; } + /// Encapsulates a delegate. public struct ActionRuntime : IAction { + /// The delegate instance. internal Action _delegate; - + /// Inocation of the delegate. public void Do(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) => _delegate(arg1, arg2, arg3, arg4, arg5, arg6); - + /// Implicit caster from a delegate. public static implicit operator ActionRuntime(Action @delegate) => new ActionRuntime() { _delegate = @delegate, }; } + /// Encapsulates a delegate. public struct ActionRuntime : IAction { + /// The delegate instance. internal Action _delegate; - + /// Inocation of the delegate. public void Do(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) => _delegate(arg1, arg2, arg3, arg4, arg5, arg6, arg7); - + /// Implicit caster from a delegate. public static implicit operator ActionRuntime(Action @delegate) => new ActionRuntime() { _delegate = @delegate, }; } + /// Encapsulates a delegate. public struct FuncRuntime : IFunc { + /// The delegate instance. internal Func _delegate; - + /// Inocation of the delegate. public TResult Do() => _delegate(); - + /// Implicit caster from a delegate. public static implicit operator FuncRuntime(Func @delegate) => new FuncRuntime() { _delegate = @delegate, }; } + /// Encapsulates a delegate. public struct FuncRuntime : IFunc { + /// The delegate instance. internal Func _delegate; - + /// Inocation of the delegate. public TResult Do(T1 arg1) => _delegate(arg1); - + /// Implicit caster from a delegate. public static implicit operator FuncRuntime(Func @delegate) => new FuncRuntime() { _delegate = @delegate, }; } + /// Encapsulates a delegate. public struct FuncRuntime : IFunc { + /// The delegate instance. internal Func _delegate; - + /// Inocation of the delegate. public TResult Do(T1 arg1, T2 arg2) => _delegate(arg1, arg2); - + /// Implicit caster from a delegate. public static implicit operator FuncRuntime(Func @delegate) => new FuncRuntime() { _delegate = @delegate, }; } + /// Encapsulates a delegate. public struct FuncRuntime : IFunc { + /// The delegate instance. internal Func _delegate; - + /// Inocation of the delegate. public TResult Do(T1 arg1, T2 arg2, T3 arg3) => _delegate(arg1, arg2, arg3); - + /// Implicit caster from a delegate. public static implicit operator FuncRuntime(Func @delegate) => new FuncRuntime() { _delegate = @delegate, }; } + /// Encapsulates a delegate. public struct FuncRuntime : IFunc { + /// The delegate instance. internal Func _delegate; - + /// Inocation of the delegate. public TResult Do(T1 arg1, T2 arg2, T3 arg3, T4 arg4) => _delegate(arg1, arg2, arg3, arg4); - + /// Implicit caster from a delegate. public static implicit operator FuncRuntime(Func @delegate) => new FuncRuntime() { _delegate = @delegate, }; } + /// Encapsulates a delegate. public struct FuncRuntime : IFunc { + /// The delegate instance. internal Func _delegate; - + /// Inocation of the delegate. public TResult Do(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) => _delegate(arg1, arg2, arg3, arg4, arg5); - + /// Implicit caster from a delegate. public static implicit operator FuncRuntime(Func @delegate) => new FuncRuntime() { _delegate = @delegate, }; } + /// Encapsulates a delegate. public struct FuncRuntime : IFunc { + /// The delegate instance. internal Func _delegate; - + /// Inocation of the delegate. public TResult Do(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) => _delegate(arg1, arg2, arg3, arg4, arg5, arg6); - + /// Implicit caster from a delegate. public static implicit operator FuncRuntime(Func @delegate) => new FuncRuntime() { _delegate = @delegate, }; } + /// Encapsulates a delegate. public struct FuncRuntime : IFunc { + /// The delegate instance. internal Func _delegate; - + /// Inocation of the delegate. public TResult Do(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) => _delegate(arg1, arg2, arg3, arg4, arg5, arg6, arg7); - + /// Implicit caster from a delegate. public static implicit operator FuncRuntime(Func @delegate) => new FuncRuntime() { _delegate = @delegate, }; } } diff --git a/Sources/Towel/Functional.tt b/Sources/Towel/Functional.tt index 48ebb17a..e837504f 100644 --- a/Sources/Towel/Functional.tt +++ b/Sources/Towel/Functional.tt @@ -11,37 +11,45 @@ namespace Towel { <# for (int i = 0; i <= parameterCount; i++) { #> + /// Encapsulates a method. public interface IAction<#= i == 0 ? "" : $"<{string.Join(", ", Enumerable.Range(1, i).Select(j => $"T{j}"))}>" #> { + /// Inocation of the method. void Do(<#= i == 0 ? "" : string.Join(", ", Enumerable.Range(1, i).Select(j => $"T{j} arg{j}")) #>); } <# } #> <# for (int i = 0; i <= parameterCount; i++) { #> + /// Encapsulates a method. public interface IFunc<<#= i == 0 ? "" : string.Join(", ", Enumerable.Range(1, i).Select(j => $"T{j}")) +", " #>TResult> { + /// Inocation of the method. TResult Do(<#= i == 0 ? "" : string.Join(", ", Enumerable.Range(1, i).Select(j => $"T{j} arg{j}")) #>); } <# } #> <# for (int i = 0; i <= parameterCount; i++) { #> + /// Encapsulates a delegate. public struct ActionRuntime<#= i == 0 ? "" : $"<{string.Join(", ", Enumerable.Range(1, i).Select(j => $"T{j}"))}>" #> : IAction<#= i == 0 ? "" : $"<{string.Join(", ", Enumerable.Range(1, i).Select(j => $"T{j}"))}>" #> { + /// The delegate instance. internal Action<#= i == 0 ? "" : $"<{string.Join(", ", Enumerable.Range(1, i).Select(j => $"T{j}"))}>" #> _delegate; - + /// Inocation of the delegate. public void Do(<#= i == 0 ? "" : string.Join(", ", Enumerable.Range(1, i).Select(j => $"T{j} arg{j}")) #>) => _delegate(<#= i == 0 ? "" : string.Join(", ", Enumerable.Range(1, i).Select(j => $"arg{j}")) #>); - + /// Implicit caster from a delegate. public static implicit operator ActionRuntime<#= i == 0 ? "" : $"<{string.Join(", ", Enumerable.Range(1, i).Select(j => $"T{j}"))}>" #>(Action<#= i == 0 ? "" : $"<{string.Join(", ", Enumerable.Range(1, i).Select(j => $"T{j}"))}>" #> @delegate) => new ActionRuntime<#= i == 0 ? "" : $"<{string.Join(", ", Enumerable.Range(1, i).Select(j => $"T{j}"))}>" #>() { _delegate = @delegate, }; } <# } #> <# for (int i = 0; i <= parameterCount; i++) { #> + /// Encapsulates a delegate. public struct FuncRuntime<<#= i == 0 ? "" : string.Join(", ", Enumerable.Range(1, i).Select(j => $"T{j}")) +", " #>TResult> : IFunc<<#= i == 0 ? "" : string.Join(", ", Enumerable.Range(1, i).Select(j => $"T{j}")) +", " #>TResult> { + /// The delegate instance. internal Func<<#= i == 0 ? "" : string.Join(", ", Enumerable.Range(1, i).Select(j => $"T{j}")) +", " #>TResult> _delegate; - + /// Inocation of the delegate. public TResult Do(<#= i == 0 ? "" : string.Join(", ", Enumerable.Range(1, i).Select(j => $"T{j} arg{j}")) #>) => _delegate(<#= i == 0 ? "" : string.Join(", ", Enumerable.Range(1, i).Select(j => $"arg{j}")) #>); - + /// Implicit caster from a delegate. public static implicit operator FuncRuntime<<#= i == 0 ? "" : string.Join(", ", Enumerable.Range(1, i).Select(j => $"T{j}")) +", " #>TResult>(Func<<#= i == 0 ? "" : string.Join(", ", Enumerable.Range(1, i).Select(j => $"T{j}")) +", " #>TResult> @delegate) => new FuncRuntime<<#= i == 0 ? "" : string.Join(", ", Enumerable.Range(1, i).Select(j => $"T{j}")) +", " #>TResult>() { _delegate = @delegate, }; } <# } #> diff --git a/Sources/Towel/Mathematics/Matrix.cs b/Sources/Towel/Mathematics/Matrix.cs index 705f5073..1a9711b4 100644 --- a/Sources/Towel/Mathematics/Matrix.cs +++ b/Sources/Towel/Mathematics/Matrix.cs @@ -596,7 +596,7 @@ public static void Negate(Matrix a, ref Matrix b) int Length = a._matrix.Length; T[] A = a._matrix; T[] B; - if (!(b is null) && b._matrix.Length == Length) + if (b is not null && b._matrix.Length == Length) { B = b._matrix; b._rows = a._rows; @@ -667,7 +667,7 @@ public static void Add(Matrix a, Matrix b, ref Matrix c) T[] A = a._matrix; T[] B = b._matrix; T[] C; - if (!(c is null) && c._matrix.Length == Length) + if (c is not null && c._matrix.Length == Length) { C = c._matrix; c._rows = a._rows; @@ -742,7 +742,7 @@ public static void Subtract(Matrix a, Matrix b, ref Matrix c) T[] B = b._matrix; int Length = A.Length; T[] C; - if (!(c is null) && c._matrix.Length == Length) + if (c is not null && c._matrix.Length == Length) { C = c._matrix; c._rows = a._rows; @@ -832,7 +832,7 @@ public static void Multiply(Matrix a, Matrix b, ref Matrix c) T[] A = a._matrix; T[] B = b._matrix; T[] C; - if (!(c is null) && c._matrix.Length == c_Rows * c_Columns) + if (c is not null && c._matrix.Length == c_Rows * c_Columns) { C = c._matrix; c._rows = c_Rows; @@ -917,7 +917,7 @@ public static void Multiply(Matrix a, Vector b, ref Vector c) T[] A = a._matrix; T[] B = b._vector; T[] C; - if (!(c is null) && c.Dimensions == columns) + if (c is not null && c.Dimensions == columns) { C = c._vector; } @@ -988,7 +988,7 @@ public static void Multiply(Matrix a, T b, ref Matrix c) T[] A = a._matrix; int Length = A.Length; T[] C; - if (!(c is null) && c._matrix.Length == Length) + if (c is not null && c._matrix.Length == Length) { C = c._matrix; c._rows = a._rows; @@ -1073,7 +1073,7 @@ public static void Divide(Matrix a, T b, ref Matrix c) T[] A = a._matrix; int Length = A.Length; T[] C; - if (!(c is null) && c._matrix.Length == Length) + if (c is not null && c._matrix.Length == Length) { C = c._matrix; c._rows = a._rows; @@ -1148,7 +1148,7 @@ public static void Power(Matrix a, int b, ref Matrix c) } if (b == 0) { - if (!(c is null) && c._matrix.Length == a._matrix.Length) + if (c is not null && c._matrix.Length == a._matrix.Length) { c._rows = a._rows; c._columns = a._columns; @@ -1160,7 +1160,7 @@ public static void Power(Matrix a, int b, ref Matrix c) } return; } - if (!(c is null) && c._matrix.Length == a._matrix.Length) + if (c is not null && c._matrix.Length == a._matrix.Length) { c._rows = a._rows; c._columns = a._columns; @@ -1560,7 +1560,7 @@ public static void Echelon(Matrix a, ref Matrix b) a = a.Clone(); } int Rows = a.Rows; - if (!(b is null) && b._matrix.Length == a._matrix.Length) + if (b is not null && b._matrix.Length == a._matrix.Length) { b._rows = Rows; b._columns = a._columns; @@ -1648,7 +1648,7 @@ public static void ReducedEchelon(Matrix a, ref Matrix b) { b = a.Clone(); } - else if (!(b is null) && b._matrix.Length == a._matrix.Length) + else if (b is not null && b._matrix.Length == a._matrix.Length) { b._rows = Rows; b._columns = a._columns; @@ -1716,7 +1716,7 @@ public static void ReducedEchelon(Matrix a, ref Matrix b) // a = a.Clone(); //} //int Rows = a.Rows; - //if (!(b is null) && b._matrix.Length == a._matrix.Length) + //if (b is not null && b._matrix.Length == a._matrix.Length) //{ // b._rows = Rows; // b._columns = a._columns; @@ -1819,7 +1819,7 @@ public static void Inverse(Matrix a, ref Matrix b) { b = a.Clone(); } - else if (!(b is null) && b.Length == Length) + else if (b is not null && b.Length == Length) { b._rows = dimension; b._columns = dimension; @@ -1949,7 +1949,7 @@ public static void Adjoint(Matrix a, ref Matrix b) { b = a.Clone(); } - else if (!(b is null) && b.Length == Length) + else if (b is not null && b.Length == Length) { b._rows = dimension; b._columns = dimension; @@ -1991,7 +1991,7 @@ public static void Adjoint(Matrix a, ref Matrix b) //int Length = a.Length; //int Rows = a.Rows; //int Columns = a.Columns; - //if (!(b is null) && b.Length == Length) + //if (b is not null && b.Length == Length) //{ // b._rows = Rows; // b._columns = Columns; @@ -2063,7 +2063,7 @@ public static void Transpose(Matrix a, ref Matrix b) int Length = a.Length; int Rows = a.Columns; int Columns = a.Rows; - if (!(b is null) && b.Length == a.Length && !ReferenceEquals(a, b)) + if (b is not null && b.Length == a.Length && !ReferenceEquals(a, b)) { b._rows = Rows; b._columns = Columns; diff --git a/Sources/Towel/Mathematics/Symbolics.cs b/Sources/Towel/Mathematics/Symbolics.cs index eaebe00a..e70ed8ab 100644 --- a/Sources/Towel/Mathematics/Symbolics.cs +++ b/Sources/Towel/Mathematics/Symbolics.cs @@ -3034,7 +3034,7 @@ internal static void BuildParsableOperationLibrary() } ParsableUnaryOperations.Add(operationName.ToLower(), newFunction); OperationAttribute operationAttribute = type.GetCustomAttribute(); - if (!(operationAttribute is null)) + if (operationAttribute is not null) { foreach (string representation in operationAttribute.Representations) { @@ -3073,7 +3073,7 @@ internal static void BuildParsableOperationLibrary() } ParsableBinaryOperations.Add(operationName.ToLower(), newFunction); OperationAttribute operationAttribute = type.GetCustomAttribute(); - if (!(operationAttribute is null)) + if (operationAttribute is not null) { foreach (string representation in operationAttribute.Representations) { @@ -3106,7 +3106,7 @@ internal static void BuildParsableOperationLibrary() } ParsableTernaryOperations.Add(operationName.ToLower(), newFunction); OperationAttribute operationAttribute = type.GetCustomAttribute(); - if (!(operationAttribute is null)) + if (operationAttribute is not null) { foreach (string representation in operationAttribute.Representations) { @@ -3131,7 +3131,7 @@ internal static void BuildParsableOperationLibrary() } ParsableMultinaryOperations.Add(operationName.ToLower(), newFunction); OperationAttribute operationAttribute = type.GetCustomAttribute(); - if (!(operationAttribute is null)) + if (operationAttribute is not null) { foreach (string representation in operationAttribute.Representations) { @@ -3155,7 +3155,7 @@ internal static void BuildParsableOperationLibrary() //} //ParsableKnownConstants.Add(knownConstant.ToLower(), newFunction); KnownConstantAttribute knownConstantAttribute = type.GetCustomAttribute(); - if (!(knownConstantAttribute is null)) + if (knownConstantAttribute is not null) { foreach (string representation in knownConstantAttribute.Representations) { @@ -3237,7 +3237,7 @@ public static Expression Parse(System.Linq.Expressions.Expression e) } Expression[] arguments = null; - if (!(methodCallExpression.Arguments is null)) + if (methodCallExpression.Arguments is not null) { arguments = new Expression[methodCallExpression.Arguments.Count]; for (int i = 0; i < arguments.Length; i++) @@ -3472,7 +3472,7 @@ bool IsUnaryRightOperator() if (IsUnaryLeftOperator())// first character in the expression //currentMatch.Index == 0 || //// nothing but white space to the left - //(!(previousMatch is null) && + //(previousMatch is not null && //string.IsNullOrWhiteSpace( // @string.Substring( @@ -3498,7 +3498,7 @@ bool IsUnaryRightOperator() //// last character(s) in the expression //(currentMatch.Index + currentMatch.Length - 1) == @string.Length - 1 || //// nothing but white space until the next operator - //(!(nextMatch is null) && + //(nextMatch is not null && //string.IsNullOrWhiteSpace( // @string.Substring( // currentMatch.Index + currentMatch.Length, @@ -3668,7 +3668,7 @@ internal static bool TryParseOperationExpression(string @string, Func(string @string, out object measurement, Func(string @string, out object measurement, Func(string @string, out object measurement, Func null, Ɐ(a, b), null); - return !(methodInfo is null) + return methodInfo is not null && methodInfo.ReturnType == c && methodInfo.IsSpecialName ? methodInfo @@ -500,7 +500,7 @@ bool CheckType(Type type) null, Ɐ(fromType), null); - return !(methodInfo is null) + return methodInfo is not null && methodInfo.ReturnType == toType && methodInfo.IsSpecialName; } @@ -1028,7 +1028,7 @@ public static string GetDocumentation(this EventInfo eventInfo) internal static string XmlDocumentationKeyHelper(string typeFullNameString, string memberNameString) { string key = Regex.Replace(typeFullNameString, @"\[.*\]", string.Empty).Replace('+', '.'); - if (!(memberNameString is null)) + if (memberNameString is not null) { key += "." + memberNameString; } @@ -1091,7 +1091,7 @@ public static string GetDocumentation(this MemberInfo memberInfo) public static string GetDocumentation(this ParameterInfo parameterInfo) { string memberDocumentation = parameterInfo.Member.GetDocumentation(); - if (!(memberDocumentation is null)) + if (memberDocumentation is not null) { string regexPattern = Regex.Escape(@"") + diff --git a/Sources/Towel/Statics.cs b/Sources/Towel/Statics.cs index baf27337..13c79ad7 100644 --- a/Sources/Towel/Statics.cs +++ b/Sources/Towel/Statics.cs @@ -317,16 +317,27 @@ public enum Keyword /// The generic type of the Switch condition for equality checks. public abstract class Condition { + /// Resolves the condition to a bool. public abstract bool Resolve(T b); - public static implicit operator Condition(T value) => new Value { A = value, }; + /// Casts a to a bool using an equality check. + public static implicit operator Condition(T value) => new Value(a: value); + /// Uses the bool as the condition result. public static implicit operator Condition(bool result) => new Bool { Result = result, }; + /// Converts a keyword to a condition result (for "Default" case). +#pragma warning disable IDE0060 // Remove unused parameter public static implicit operator Condition(Keyword keyword) => new Default(); +#pragma warning restore IDE0060 // Remove unused parameter } internal class Value : Condition { + /// The value of this condition for an equality check. internal T A; - public override bool Resolve(T b) => A.Equals(b); + public override bool Resolve(T b) => Equate(A, b); + public Value(T a) + { + A = a; + } } internal class Bool : Condition @@ -340,13 +351,18 @@ internal class Default : Condition public override bool Resolve(T b) => true; } + /// Represents the result of a conditional expression inside Switch syntax. public abstract class Condition { + /// Resolves the condition to a bool. public abstract bool Resolve(); + /// Uses the bool as the condition result. public static implicit operator Condition(bool result) => new Bool { Result = result, }; //#pragma warning disable IDE0060 // Remove unused parameter + /// Converts a keyword to a condition result (for "Default" case). public static implicit operator Condition(Keyword keyword) => new Default(); //#pragma warning restore IDE0060 // Remove unused parameter + /// Converts a condition to a bool using the Resolve method. public static implicit operator bool(Condition condition) => condition.Resolve(); } @@ -366,6 +382,11 @@ internal class Default : Condition #region Chance +#pragma warning disable CA2211 // Non-constant fields should not be visible +#pragma warning disable IDE0079 // Remove unnecessary suppression +#pragma warning disable IDE0075 // Simplify conditional expression +#pragma warning disable IDE0060 // Remove unused parameter + /// Allows chance syntax with "using static Towel.Syntax;". /// 25% Chance public static ChanceSyntax Chance => default; @@ -374,12 +395,7 @@ internal class Default : Condition public struct ChanceSyntax { /// The random algorithm currently being used by chance syntax. -#pragma warning disable CA2211 // Non-constant fields should not be visible public static Random Algorithm = new Random(); -#pragma warning restore CA2211 // Non-constant fields should not be visible - -#pragma warning disable IDE0075 // Simplify conditional expression -#pragma warning disable IDE0060 // Remove unused parameter /// Creates a chance from a percentage that will be evaluated at runtime. /// The value of the percentage. @@ -391,10 +407,12 @@ public struct ChanceSyntax percentage is 100d ? true : percentage is 0d ? false : Algorithm.NextDouble() < percentage / 100d; + } #pragma warning restore IDE0060 // Remove unused parameter #pragma warning restore IDE0075 // Simplify conditional expression - } +#pragma warning restore IDE0079 // Remove unnecessary suppression +#pragma warning restore CA2211 // Non-constant fields should not be visible #endregion @@ -607,15 +625,20 @@ public void Add(T item) newValue[Value.Length] = item; Value = newValue; } + /// Not intended to be invoked directly. [Obsolete(TowelConstants.NotIntended, true)] public void Clear() => Value = Array.Empty(); + /// Not intended to be invoked directly. [Obsolete(TowelConstants.NotIntended, true)] public bool Contains(T item) => Value.Contains(item); + /// Not intended to be invoked directly. [Obsolete(TowelConstants.NotIntended, true)] public void CopyTo(T[] array, int arrayIndex) => Array.Copy(Value, 0, array, arrayIndex, Value.Length); + /// Not intended to be invoked directly. [Obsolete(TowelConstants.NotIntended, true)] public int IndexOf(T item) => Array.IndexOf(Value, item); + /// Not intended to be invoked directly. [Obsolete(TowelConstants.NotIntended, true)] public void Insert(int index, T item) { @@ -630,6 +653,7 @@ public void Insert(int index, T item) } Value = newValue; } + /// Not intended to be invoked directly. [Obsolete(TowelConstants.NotIntended, true)] public bool Remove(T item) { @@ -637,7 +661,7 @@ public bool Remove(T item) bool found = false; for (int i = 0; i < Value.Length; i++) { - if (Value[i].Equals(item)) + if (Equate(Value[i], item)) { found = true; } @@ -657,6 +681,7 @@ public bool Remove(T item) Value = newValue; return true; } + /// Not intended to be invoked directly. [Obsolete(TowelConstants.NotIntended, true)] public void RemoveAt(int index) { @@ -1123,18 +1148,18 @@ internal static class CompareImplementation Expression? lessThanPredicate = typeof(A).IsPrimitive && typeof(B).IsPrimitive ? Expression.LessThan(A, B) - : !(Meta.GetLessThanMethod() is null) + : Meta.GetLessThanMethod() is not null ? Expression.LessThan(A, B) - : !(Meta.GetGreaterThanMethod() is null) + : Meta.GetGreaterThanMethod() is not null ? Expression.GreaterThan(B, A) : null; Expression? greaterThanPredicate = typeof(A).IsPrimitive && typeof(B).IsPrimitive ? Expression.GreaterThan(A, B) - : !(Meta.GetGreaterThanMethod() is null) + : Meta.GetGreaterThanMethod() is not null ? Expression.GreaterThan(A, B) - : !(Meta.GetLessThanMethod() is null) + : Meta.GetLessThanMethod() is not null ? Expression.LessThan(B, A) : null; @@ -1497,29 +1522,33 @@ internal static class PowerImplementation { ParameterExpression A = Expression.Parameter(typeof(T)); ParameterExpression B = Expression.Parameter(typeof(T)); - Expression BODY = Expression.Convert(Expression.Call(typeof(Math).GetMethod(nameof(Math.Pow)), Expression.Convert(A, typeof(double)), Expression.Convert(B, typeof(double))), typeof(T)); - Function = Expression.Lambda>(BODY, A, B).Compile(); + MethodInfo? Math_Pow = typeof(Math).GetMethod(nameof(Math.Pow)); + if (Math_Pow is not null) + { + Expression BODY = Expression.Convert(Expression.Call(Math_Pow, Expression.Convert(A, typeof(double)), Expression.Convert(B, typeof(double))), typeof(T)); + Function = Expression.Lambda>(BODY, A, B).Compile(); + return Function(a, b); + } } - else + + Function = (A, B) => { - Function = (A, B) => + if (IsInteger(B) && IsPositive(B) && LessThan(B, Convert(int.MaxValue))) { - if (IsInteger(B) && IsPositive(B)) + T result = A; + int power = Convert(B); + for (int i = 0; i < power; i++) { - T result = A; - int power = Convert(B); - for (int i = 0; i < power; i++) - { - result = Multiplication(result, A); - } - return result; + result = Multiplication(result, A); } - else - { - throw new NotImplementedException("This feature is still in development."); - } - }; - } + return result; + } + else + { + throw new NotImplementedException("This feature is still in development."); + } + }; + return Function(a, b); }; } @@ -2128,13 +2157,13 @@ public static T LinearInterpolation(T x, T x0, T x1, T y0, T y1) GreaterThan(x, x1) || LessThan(x, x0)) { - throw new MathematicsException("Arguments out of range !(" + nameof(x0) + " <= " + nameof(x) + " <= " + nameof(x1) + ") [" + x0 + " <= " + x + " <= " + x1 + "]."); + throw new MathematicsException($"!({nameof(x0)}[{x0}] <= {nameof(x)}[{x}] <= {nameof(x1)}[{x1}])"); } if (Equate(x0, x1)) { if (Inequate(y0, y1)) { - throw new MathematicsException("Arguments out of range (" + nameof(x0) + " == " + nameof(x1) + ") but !(" + nameof(y0) + " != " + nameof(y1) + ") [" + y0 + " != " + y1 + "]."); + throw new MathematicsException($"{nameof(x0)}[{x0}] == {nameof(x1)}[{x1}] && {nameof(y0)}[{y0}] != {nameof(y1)}[{y1}]"); } else { @@ -2172,11 +2201,11 @@ internal static class FactorialImplementation { if (!IsInteger(A)) { - throw new ArgumentOutOfRangeException(nameof(A), A, "!" + nameof(A) + "." + nameof(IsInteger)); + throw new ArgumentOutOfRangeException(nameof(A), A, $"!{nameof(A)}[{A}].{nameof(IsInteger)}()"); } if (LessThan(A, Constant.Zero)) { - throw new ArgumentOutOfRangeException(nameof(A), A, "!(" + nameof(A) + " >= 0)"); + throw new ArgumentOutOfRangeException(nameof(A), A, $"!({nameof(A)}[{A}] >= 0)"); } T result = Constant.One; for (; GreaterThan(A, Constant.One); A = Subtraction(A, Constant.One)) @@ -2200,7 +2229,7 @@ public static T Combinations(T N, T[] n) { if (!IsInteger(N)) { - throw new ArgumentOutOfRangeException(nameof(N), N, "!(" + nameof(N) + "." + nameof(IsInteger) + ")"); + throw new ArgumentOutOfRangeException(nameof(N), N, $"!({nameof(N)}.{nameof(IsInteger)})"); } T result = Factorial(N); T sum = Constant.Zero; @@ -2481,7 +2510,7 @@ public static T Median(Action> stepper) //public static T Median(Func compare, Hash hash, Func equate, params T[] values) //{ // // this is an optimized median algorithm, but it only works on odd sets without duplicates - // if (!(hash is null) && !(equate is null) && values.Length % 2 == 1 && !values.ToStepper().ContainsDuplicates(equate, hash)) + // if (hash is not null && equate is not null && values.Length % 2 == 1 && !values.ToStepper().ContainsDuplicates(equate, hash)) // { // int medianIndex = 0; // OddNoDupesMedianImplementation(values, values.Length, ref medianIndex, compare); @@ -2774,9 +2803,13 @@ internal static class NaturalLogarithmImplementation if (TypeDescriptor.GetConverter(typeof(T)).CanConvertTo(typeof(double))) { ParameterExpression A = Expression.Parameter(typeof(T)); - Expression BODY = Expression.Call(typeof(Math).GetMethod("Log"), A); - Function = Expression.Lambda>(BODY, A).Compile(); - return Function(a); + MethodInfo? Math_Log = typeof(Math).GetMethod("Log"); + if (Math_Log is not null) + { + Expression BODY = Expression.Call(Math_Log, A); + Function = Expression.Lambda>(BODY, A).Compile(); + return Function(a); + } } throw new NotImplementedException(); }; @@ -2793,7 +2826,7 @@ internal static class NaturalLogarithmImplementation /// The angle to compute the sine ratio of. /// Determines if coputation should continue or is accurate enough. /// The taylor series computed sine ratio of the provided angle. - public static T SineTaylorSeries(Angle a, Predicate predicate = null) + public static T SineTaylorSeries(Angle a, Predicate? predicate = null) { // Series: sine(x) = x - (x^3 / 3!) + (x^5 / 5!) - (x^7 / 7!) + (x^9 / 9!) + ... // more terms in computation inproves accuracy @@ -3947,8 +3980,8 @@ public static (bool Found, int Index, T? Value) SearchBinary(int length, Func /// public static (bool Found, int Index, T? Value) SearchBinary(int index, int length, Get get = default, Sift sift = default) - where Get : IFunc - where Sift : IFunc + where Get : struct, IFunc + where Sift : struct, IFunc { if (length <= 0) { @@ -3984,7 +4017,7 @@ public static (bool Found, int Index, T? Value) SearchBinary(int i } /// - public static (bool Found, int Index, T? Value) SearchBinary(ReadOnlySpan span, T element, Func compare = default) => + public static (bool Found, int Index, T? Value) SearchBinary(ReadOnlySpan span, T element, Func? compare = default) => SearchBinary>>(span, new SiftFromCompareAndValue>(element, compare ?? Compare)); /// @@ -3996,12 +4029,12 @@ public static (bool Found, int Index, T? Value) SearchBinary(ReadOnlySpan /// public static (bool Found, int Index, T? Value) SearchBinary(ReadOnlySpan span, T element, Compare compare = default) - where Compare : IFunc => + where Compare : struct, IFunc => SearchBinary>(span, new SiftFromCompareAndValue(element, compare)); /// public static (bool Found, int Index, T? Value) SearchBinary(ReadOnlySpan span, Sift sift = default) - where Sift : IFunc + where Sift : struct, IFunc { if (span.IsEmpty) { @@ -4105,25 +4138,54 @@ internal abstract class BaseAlgorithmNode { internal AlgorithmNode? Previous; internal Node Value; + + internal BaseAlgorithmNode(Node value, AlgorithmNode? previous = null) + { + Value = value; + Previous = previous; + } } - internal class BreadthFirstSearch : BaseAlgorithmNode, Node> { } + internal class BreadthFirstSearch : BaseAlgorithmNode, Node> + { + internal BreadthFirstSearch(Node value, BreadthFirstSearch? previous = null) + : base(value: value, previous: previous) { } + } internal class DijkstraNode : BaseAlgorithmNode, Node> { internal Numeric Priority; + + internal DijkstraNode(Node value, Numeric priority, DijkstraNode? previous = null) + : base(value: value, previous: previous) + { + Priority = priority; + } } internal class AstarNode : BaseAlgorithmNode, Node> { internal Numeric Priority; internal Numeric Cost; + + internal AstarNode(Node value, Numeric priority, Numeric cost, AstarNode? previous = null) + : base(value: value, previous: previous) + { + Priority = priority; + Cost = cost; + } } internal class PathNode { internal Node Value; internal PathNode? Next; + + internal PathNode(Node value, PathNode? next = null) + { + Value = value; + Next = next; + } } internal static Action> BuildPath(BaseAlgorithmNode node) @@ -4133,16 +4195,14 @@ internal static Action> BuildPath(BaseAlgorith for (BaseAlgorithmNode? current = node; current is not null; current = current.Previous) { PathNode? temp = start; - start = new PathNode() - { - Value = current.Value, - Next = temp, - }; + start = new PathNode( + value: current.Value, + next: temp); } return step => { PathNode? current = start; - while (!(current is null)) + while (current is not null) { step(current.Value); current = current.Next; @@ -4196,44 +4256,42 @@ public CompareResult Do(DijkstraNode a, DijkstraNode throw new DocumentationMethodException(); /// - public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchCost cost, SearchGoal goal, out Numeric totalCost) => + public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchCost cost, SearchGoal goal, out Numeric? totalCost) => SearchGraph(start, neighbors, heuristic, cost, node => goal(node) ? GraphSearchStatus.Goal : GraphSearchStatus.Continue, out totalCost); /// - public static Action>? SearchGraph(Node start, IGraph graph, SearchHeuristic heuristic, SearchCost cost, SearchGoal goal, out Numeric totalCost) => + public static Action>? SearchGraph(Node start, IGraph graph, SearchHeuristic heuristic, SearchCost cost, SearchGoal goal, out Numeric? totalCost) => SearchGraph(start, graph.Neighbors, heuristic, cost, goal, out totalCost); /// - public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchCost cost, Node goal, out Numeric totalCost) => + public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchCost cost, Node goal, out Numeric? totalCost) => SearchGraph(start, neighbors, heuristic, cost, goal, Equate, out totalCost); /// - public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchCost cost, Node goal, Func equate, out Numeric totalCost) => + public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchCost cost, Node goal, Func equate, out Numeric? totalCost) => SearchGraph(start, neighbors, heuristic, cost, node => equate(node, goal), out totalCost); /// - public static Action>? SearchGraph(Node start, IGraph graph, SearchHeuristic heuristic, SearchCost cost, Node goal, out Numeric totalCost) => + public static Action>? SearchGraph(Node start, IGraph graph, SearchHeuristic heuristic, SearchCost cost, Node goal, out Numeric? totalCost) => SearchGraph(start, graph, heuristic, cost, goal, Equate, out totalCost); /// - public static Action>? SearchGraph(Node start, IGraph graph, SearchHeuristic heuristic, SearchCost cost, Node goal, Func equate, out Numeric totalCost) => + public static Action>? SearchGraph(Node start, IGraph graph, SearchHeuristic heuristic, SearchCost cost, Node goal, Func equate, out Numeric? totalCost) => SearchGraph(start, graph.Neighbors, heuristic, cost, node => equate(node, goal), out totalCost); /// - public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchCost cost, SearchCheck check, out Numeric totalCost) + public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchCost cost, SearchCheck check, out Numeric? totalCost) { // using a heap (aka priority queue) to store nodes based on their computed A* f(n) value IHeap> fringe = new HeapArray, AStarPriorityCompare>(); // push starting node fringe.Enqueue( - new AstarNode() - { - Previous = null, - Value = start, - Priority = default, - Cost = Constant.Zero, - }); + new AstarNode( + value: start, + priority: Constant.Zero, + cost: Constant.Zero, + previous: null)); // run the algorithm while (fringe.Count != 0) @@ -4256,13 +4314,11 @@ public CompareResult Do(DijkstraNode a, DijkstraNode() - { - Previous = current, - Value = neighbor, - Priority = Addition(heuristic(neighbor), costValue), - Cost = costValue, - }); + new AstarNode( + value: neighbor, + priority: Addition(heuristic(neighbor), costValue), + cost: costValue, + previous: current)); }); } } @@ -4311,12 +4367,10 @@ public CompareResult Do(DijkstraNode a, DijkstraNode() - { - Previous = null, - Value = start, - Priority = default, - }); + new DijkstraNode( + value: start, + priority: Constant.Zero, + previous: null)); // run the algorithm while (fringe.Count != 0) @@ -4337,12 +4391,10 @@ public CompareResult Do(DijkstraNode a, DijkstraNode { fringe.Enqueue( - new DijkstraNode() - { - Previous = current, - Value = neighbor, - Priority = heuristic(neighbor), - }); + new DijkstraNode( + value: neighbor, + priority: heuristic(neighbor), + previous: current)); }); } } @@ -4389,11 +4441,9 @@ public CompareResult Do(DijkstraNode a, DijkstraNode() - { - Previous = null, - Value = start, - }); + new BreadthFirstSearch( + value: start, + previous: null)); // run the algorithm while (fringe.Count != 0) @@ -4414,11 +4464,9 @@ public CompareResult Do(DijkstraNode a, DijkstraNode { fringe.Enqueue( - new BreadthFirstSearch() - { - Previous = current, - Value = neighbor, - }); + new BreadthFirstSearch( + value: neighbor, + previous: current)); }); } } @@ -5655,7 +5703,7 @@ public static void NextUniqueRollTracking(int count, int minValue, throw new ArgumentOutOfRangeException(nameof(count), $"{nameof(count)} is larger than {nameof(maxValue)} - {nameof(minValue)}."); } // Algorithm B: O(.5*count^2), Ω(count), ε(.5*count^2) - Node head = null; + Node? head = null; for (int i = 0; i < count; i++) // Θ(count) { int roll = random.Do(minValue, maxValue - i); @@ -5663,9 +5711,9 @@ public static void NextUniqueRollTracking(int count, int minValue, { throw new ArgumentException("The Random provided returned a value outside the requested range."); } - Node node = head; - Node previous = null; - while (!(node is null) && !(node.Value > roll)) // O(count / 2), Ω(0), ε(count / 2) + Node? node = head; + Node? previous = null; + while (node is not null && node.Value <= roll) // O(count / 2), Ω(0), ε(count / 2) { roll++; previous = node; @@ -5685,7 +5733,7 @@ public static void NextUniqueRollTracking(int count, int minValue, internal class Node { internal int Value; - internal Node Next; + internal Node? Next; } /// @@ -5783,7 +5831,7 @@ public static int[] NextUnique(int count, int minValue, int maxValue, Ra /// The element equate function. /// The get index function of the sequence. /// True if the sequence is a palindrome; False if not. - public static bool IsPalindrome(int start, int end, Func get, Func equate = default) => + public static bool IsPalindrome(int start, int end, Func get, Func? equate = default) => IsPalindrome , FuncRuntime>(start, end, get, equate ?? Equate); /// Determines if a sequence is a palindrome. @@ -5794,7 +5842,7 @@ public static bool IsPalindrome(int start, int end, Func get, FuncThe element equate function. /// The get index function of the sequence. /// True if the sequence is a palindrome; False if not. - public static bool IsPalindrome(int start, int end, Get get = default, Func equate = default) + public static bool IsPalindrome(int start, int end, Get get = default, Func? equate = default) where Get : struct, IFunc => IsPalindrome>(start, end, get, equate ?? Equate); @@ -5833,7 +5881,7 @@ public static bool IsPalindrome(ReadOnlySpan span) => /// The span to check. /// The element equate function. /// True if the sequence is a palindrome; False if not. - public static bool IsPalindrome(ReadOnlySpan span, Func equate = default) => + public static bool IsPalindrome(ReadOnlySpan span, Func? equate = default) => IsPalindrome>(span, equate ?? Equate); /// Determines if a sequence is a palindrome. @@ -5865,6 +5913,7 @@ public static bool IsPalindrome(ReadOnlySpan span, Equate equate = #pragma warning disable CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name #pragma warning disable CS1572 // XML comment has a param tag, but there is no parameter by that name #pragma warning disable CS1734 // XML comment has a paramref tag, but there is no parameter by that name +#pragma warning disable CS1735 // XML comment has a typeparamref tag, but there is no type parameter by that name /// The element type of the sequences. /// The first sequence to determine if is interleaved of. @@ -5903,6 +5952,7 @@ public static bool IsPalindrome(ReadOnlySpan span, Equate equate = /// internal static void IsInterleavedIterative_XML() => throw new DocumentationMethodException(); +#pragma warning restore CS1735 // XML comment has a typeparamref tag, but there is no type parameter by that name #pragma warning restore CS1734 // XML comment has a paramref tag, but there is no parameter by that name #pragma warning restore CS1572 // XML comment has a param tag, but there is no parameter by that name #pragma warning restore CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name @@ -5910,7 +5960,7 @@ public static bool IsPalindrome(ReadOnlySpan span, Equate equate = #endregion /// - public static bool IsInterleavedRecursive(ReadOnlySpan a, ReadOnlySpan b, ReadOnlySpan c, Func equate = default) => + public static bool IsInterleavedRecursive(ReadOnlySpan a, ReadOnlySpan b, ReadOnlySpan c, Func? equate = default) => IsInterleavedRecursive>(a, b, c, equate ?? Equate); /// @@ -5919,7 +5969,7 @@ public static bool IsInterleavedRecursive(ReadOnlySpan a, ReadOnlySpan public static bool IsInterleavedRecursive(ReadOnlySpan a, ReadOnlySpan b, ReadOnlySpan c, Equate equate = default) - where Equate : IFunc + where Equate : struct, IFunc { if (a.Length + b.Length != c.Length) { @@ -5940,7 +5990,7 @@ bool Implementation(ReadOnlySpan a, ReadOnlySpan b, ReadOnlySpan c) => } /// - public static bool IsInterleavedIterative(ReadOnlySpan a, ReadOnlySpan b, ReadOnlySpan c, Func equate = default) => + public static bool IsInterleavedIterative(ReadOnlySpan a, ReadOnlySpan b, ReadOnlySpan c, Func? equate = default) => IsInterleavedIterative>(a, b, c, equate ?? Equate); /// @@ -5949,7 +5999,7 @@ public static bool IsInterleavedIterative(ReadOnlySpan a, ReadOnlySpan public static bool IsInterleavedIterative(ReadOnlySpan a, ReadOnlySpan b, ReadOnlySpan c, Equate equate = default) - where Equate : IFunc + where Equate : struct, IFunc { if (a.Length + b.Length != c.Length) { @@ -6037,7 +6087,7 @@ public struct CharEquate : IFunc /// The generic type of the values to compare. /// The compare function. public struct SiftFromCompareAndValue : IFunc - where Compare : IFunc + where Compare : struct, IFunc { internal Compare CompareFunction; internal T Value; @@ -6063,13 +6113,14 @@ public struct StepStatusContinue : IFunc public StepStatus Do() => Continue; } + /// Struct wrapper for the method as an . public struct RandomNextIntMinValueIntMaxValue : IFunc { internal Random _random; - public int Do(int a, int b) => _random.Next(a, b); - - public static implicit operator RandomNextIntMinValueIntMaxValue(Random random) => - new RandomNextIntMinValueIntMaxValue() { _random = random, }; + /// + public int Do(int minValue, int maxValue) => _random.Next(minValue, maxValue); + /// Casts a to a struct wrapper. + public static implicit operator RandomNextIntMinValueIntMaxValue(Random random) => new RandomNextIntMinValueIntMaxValue() { _random = random, }; } #endregion diff --git a/Sources/Towel/TagAttribute.cs b/Sources/Towel/TagAttribute.cs index bff35e30..98cb6708 100644 --- a/Sources/Towel/TagAttribute.cs +++ b/Sources/Towel/TagAttribute.cs @@ -31,11 +31,11 @@ public static class TagAttributeExtensions /// - Found: True if the tag was found; False if not or if multiple tags were found (ambiguous). /// - Value: The value if found or default if not. /// - public static (bool Found, object Value) GetTag(this MemberInfo memberInfo, object tag) + public static (bool Found, object? Value) GetTag(this MemberInfo memberInfo, object tag) { _ = memberInfo ?? throw new ArgumentNullException(nameof(memberInfo)); bool found = false; - object value = default; + object? value = default; foreach (TagAttribute valueAttribute in memberInfo.GetCustomAttributes()) { if (ReferenceEquals(tag, valueAttribute.Tag) || tag.Equals(valueAttribute.Tag)) @@ -59,11 +59,11 @@ public static (bool Found, object Value) GetTag(this MemberInfo memberInfo, obje /// - Found: True if the tag was found; False if not or if multiple tags were found (ambiguous). /// - Value: The value if found or default if not. /// - public static (bool Found, object Value) GetTag(this ParameterInfo parameterInfo, object tag) + public static (bool Found, object? Value) GetTag(this ParameterInfo parameterInfo, object tag) { _ = parameterInfo ?? throw new ArgumentNullException(nameof(parameterInfo)); bool found = false; - object value = default; + object? value = default; foreach (TagAttribute valueAttribute in parameterInfo.GetCustomAttributes()) { if (ReferenceEquals(tag, valueAttribute.Tag) || tag.Equals(valueAttribute.Tag)) diff --git a/Sources/Towel/Towel.csproj b/Sources/Towel/Towel.csproj index a01eaf88..91b90268 100644 --- a/Sources/Towel/Towel.csproj +++ b/Sources/Towel/Towel.csproj @@ -43,6 +43,11 @@ True Link.tt + + True + True + Functional.tt + TextTemplatingFileGenerator Omnitree.cs diff --git a/Sources/Towel/Towel.xml b/Sources/Towel/Towel.xml index d8f1883d..c698708a 100644 --- a/Sources/Towel/Towel.xml +++ b/Sources/Towel/Towel.xml @@ -15758,6 +15758,294 @@ The stepper to concatenate the values into a string. The string of the concatenated chars. + + Encapsulates a method. + + + Inocation of the method. + + + Encapsulates a method. + + + Inocation of the method. + + + Encapsulates a method. + + + Inocation of the method. + + + Encapsulates a method. + + + Inocation of the method. + + + Encapsulates a method. + + + Inocation of the method. + + + Encapsulates a method. + + + Inocation of the method. + + + Encapsulates a method. + + + Inocation of the method. + + + Encapsulates a method. + + + Inocation of the method. + + + Encapsulates a method. + + + Inocation of the method. + + + Encapsulates a method. + + + Inocation of the method. + + + Encapsulates a method. + + + Inocation of the method. + + + Encapsulates a method. + + + Inocation of the method. + + + Encapsulates a method. + + + Inocation of the method. + + + Encapsulates a method. + + + Inocation of the method. + + + Encapsulates a method. + + + Inocation of the method. + + + Encapsulates a method. + + + Inocation of the method. + + + Encapsulates a delegate. + + + The delegate instance. + + + Inocation of the delegate. + + + Implicit caster from a delegate. + + + Encapsulates a delegate. + + + The delegate instance. + + + Inocation of the delegate. + + + Implicit caster from a delegate. + + + Encapsulates a delegate. + + + The delegate instance. + + + Inocation of the delegate. + + + Implicit caster from a delegate. + + + Encapsulates a delegate. + + + The delegate instance. + + + Inocation of the delegate. + + + Implicit caster from a delegate. + + + Encapsulates a delegate. + + + The delegate instance. + + + Inocation of the delegate. + + + Implicit caster from a delegate. + + + Encapsulates a delegate. + + + The delegate instance. + + + Inocation of the delegate. + + + Implicit caster from a delegate. + + + Encapsulates a delegate. + + + The delegate instance. + + + Inocation of the delegate. + + + Implicit caster from a delegate. + + + Encapsulates a delegate. + + + The delegate instance. + + + Inocation of the delegate. + + + Implicit caster from a delegate. + + + Encapsulates a delegate. + + + The delegate instance. + + + Inocation of the delegate. + + + Implicit caster from a delegate. + + + Encapsulates a delegate. + + + The delegate instance. + + + Inocation of the delegate. + + + Implicit caster from a delegate. + + + Encapsulates a delegate. + + + The delegate instance. + + + Inocation of the delegate. + + + Implicit caster from a delegate. + + + Encapsulates a delegate. + + + The delegate instance. + + + Inocation of the delegate. + + + Implicit caster from a delegate. + + + Encapsulates a delegate. + + + The delegate instance. + + + Inocation of the delegate. + + + Implicit caster from a delegate. + + + Encapsulates a delegate. + + + The delegate instance. + + + Inocation of the delegate. + + + Implicit caster from a delegate. + + + Encapsulates a delegate. + + + The delegate instance. + + + Inocation of the delegate. + + + Implicit caster from a delegate. + + + Encapsulates a delegate. + + + The delegate instance. + + + Inocation of the delegate. + + + Implicit caster from a delegate. + Represents a rational value with a numerator and a denominator. The type of the numerator and denominator. @@ -29767,6 +30055,36 @@ Represents the result of a conditional expression inside Switch syntax. The generic type of the Switch condition for equality checks. + + Resolves the condition to a bool. + + + Casts a to a bool using an equality check. + + + Uses the bool as the condition result. + + + Converts a keyword to a condition result (for "Default" case). + + + The value of this condition for an equality check. + + + Represents the result of a conditional expression inside Switch syntax. + + + Resolves the condition to a bool. + + + Uses the bool as the condition result. + + + Converts a keyword to a condition result (for "Default" case). + + + Converts a condition to a bool using the Resolve method. + Allows chance syntax with "using static Towel.Syntax;". 25% Chance @@ -29939,6 +30257,27 @@ Adds an item to this universal quantifier. The item to add to this universal quantifier. + + Not intended to be invoked directly. + + + Not intended to be invoked directly. + + + Not intended to be invoked directly. + + + Not intended to be invoked directly. + + + Not intended to be invoked directly. + + + Not intended to be invoked directly. + + + Not intended to be invoked directly. + Gets the for this universal quantification. The for this universal quantification. @@ -31692,6 +32031,15 @@ Returns . + + Struct wrapper for the method as an . + + + + + + Casts a to a struct wrapper. + Status of iteration. From f0a906af9eaadaa4ce941b09fba26847c975643f Mon Sep 17 00:00:00 2001 From: Zachary Patten Date: Fri, 30 Oct 2020 12:12:50 -0400 Subject: [PATCH 07/30] git mv Examples/ValueAttributes Examples/TagAttributes --- Examples/{ValueAttributes => TagAttributes}/Program.cs | 0 .../{ValueAttributes => TagAttributes}/TagAttributes.csproj | 0 Towel.sln | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) rename Examples/{ValueAttributes => TagAttributes}/Program.cs (100%) rename Examples/{ValueAttributes => TagAttributes}/TagAttributes.csproj (100%) diff --git a/Examples/ValueAttributes/Program.cs b/Examples/TagAttributes/Program.cs similarity index 100% rename from Examples/ValueAttributes/Program.cs rename to Examples/TagAttributes/Program.cs diff --git a/Examples/ValueAttributes/TagAttributes.csproj b/Examples/TagAttributes/TagAttributes.csproj similarity index 100% rename from Examples/ValueAttributes/TagAttributes.csproj rename to Examples/TagAttributes/TagAttributes.csproj diff --git a/Towel.sln b/Towel.sln index 5d5768fe..5c328d2b 100644 --- a/Towel.sln +++ b/Towel.sln @@ -35,7 +35,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Towel_Generating", "Tools\T EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleHelpers", "Examples\ConsoleHelpers\ConsoleHelpers.csproj", "{84268336-B88E-4DBA-8CE0-7BA24BFCCA58}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TagAttributes", "Examples\ValueAttributes\TagAttributes.csproj", "{EFC33B0A-7AB9-4D5B-AB8F-FE0C600C5CA6}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TagAttributes", "Examples\TagAttributes\TagAttributes.csproj", "{EFC33B0A-7AB9-4D5B-AB8F-FE0C600C5CA6}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution From 72c9caa4c759875a893a3f9ddcb990ee4016154b Mon Sep 17 00:00:00 2001 From: Zachary Patten Date: Fri, 30 Oct 2020 12:19:52 -0400 Subject: [PATCH 08/30] Towel.csproj clean up --- Sources/Towel/Towel.csproj | 42 +++++++++++++------------------------- 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/Sources/Towel/Towel.csproj b/Sources/Towel/Towel.csproj index 91b90268..ddc12923 100644 --- a/Sources/Towel/Towel.csproj +++ b/Sources/Towel/Towel.csproj @@ -15,25 +15,19 @@ https://github.com/ZacharyPatten/Towel + + True + + TextTemplatingFileGenerator Functional.cs - + True True Functional.tt - - - - True - - - - True - True - MeasurementTypes.tt - + TextTemplatingFileGenerator Link.cs @@ -43,34 +37,26 @@ True Link.tt - - True - True - Functional.tt - - + TextTemplatingFileGenerator - Omnitree.cs + MeasurementTypes.cs - + True True - Omnitree.tt + MeasurementTypes.tt - + TextTemplatingFileGenerator - MeasurementTypes.cs + Omnitree.cs - + True True - MeasurementTypes.tt + Omnitree.tt <_Parameter1>Towel_Testing - - - From 0a0d0c5d80b793f3abee1223e7b52885fb72d366 Mon Sep 17 00:00:00 2001 From: Zachary Patten Date: Fri, 30 Oct 2020 12:29:53 -0400 Subject: [PATCH 09/30] .vscode (.NET 5 pathing) --- .vscode/launch.json | 40 ++++++++++++++++++++-------------------- .vscode/tasks.json | 8 ++++---- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 00d59bdc..15b26a0a 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,9 +10,9 @@ "type": "coreclr", "request": "launch", "preLaunchTask": "Build BasicsAndExtensions Example [Debug]", - "program": "${workspaceFolder}/Examples/BasicsAndExtensions/bin/Debug/netcoreapp3.1/BasicsAndExtensions.dll", + "program": "${workspaceFolder}/Examples/BasicsAndExtensions/bin/Debug/net5.0/BasicsAndExtensions.dll", "args": [], - "cwd": "${workspaceFolder}/Examples/BasicsAndExtensions/bin/Debug/netcoreapp3.1", + "cwd": "${workspaceFolder}/Examples/BasicsAndExtensions/bin/Debug/net5.0", "console": "externalTerminal", "stopAtEntry": false }, @@ -21,9 +21,9 @@ "type": "coreclr", "request": "launch", "preLaunchTask": "Build CommandLine Example [Debug]", - "program": "${workspaceFolder}/Examples/CommandLine/bin/Debug/netcoreapp3.1/CommandLine.dll", + "program": "${workspaceFolder}/Examples/CommandLine/bin/Debug/net5.0/CommandLine.dll", "args": [], - "cwd": "${workspaceFolder}/Examples/CommandLine/bin/Debug/netcoreapp3.1", + "cwd": "${workspaceFolder}/Examples/CommandLine/bin/Debug/net5.0", "console": "externalTerminal", "stopAtEntry": false }, @@ -32,9 +32,9 @@ "type": "coreclr", "request": "launch", "preLaunchTask": "Build ConsoleHelpers Example [Debug]", - "program": "${workspaceFolder}/Examples/ConsoleHelpers/bin/Debug/netcoreapp3.1/ConsoleHelpers.dll", + "program": "${workspaceFolder}/Examples/ConsoleHelpers/bin/Debug/net5.0/ConsoleHelpers.dll", "args": [], - "cwd": "${workspaceFolder}/Examples/ConsoleHelpers/bin/Debug/netcoreapp3.1", + "cwd": "${workspaceFolder}/Examples/ConsoleHelpers/bin/Debug/net5.0", "console": "externalTerminal", "stopAtEntry": false }, @@ -43,9 +43,9 @@ "type": "coreclr", "request": "launch", "preLaunchTask": "Build Data Structures Example [Debug]", - "program": "${workspaceFolder}/Examples/DataStructures/bin/Debug/netcoreapp3.1/DataStructures.dll", + "program": "${workspaceFolder}/Examples/DataStructures/bin/Debug/net5.0/DataStructures.dll", "args": [], - "cwd": "${workspaceFolder}/Examples/DataStructures/bin/Debug/netcoreapp3.1", + "cwd": "${workspaceFolder}/Examples/DataStructures/bin/Debug/net5.0", "console": "externalTerminal", "stopAtEntry": false }, @@ -54,9 +54,9 @@ "type": "coreclr", "request": "launch", "preLaunchTask": "Build GraphSearch Example [Debug]", - "program": "${workspaceFolder}/Examples/GraphSearch/bin/Debug/netcoreapp3.1/GraphSearch.dll", + "program": "${workspaceFolder}/Examples/GraphSearch/bin/Debug/net5.0/GraphSearch.dll", "args": [], - "cwd": "${workspaceFolder}/Examples/GraphSearch/bin/Debug/netcoreapp3.1", + "cwd": "${workspaceFolder}/Examples/GraphSearch/bin/Debug/net5.0", "console": "externalTerminal", "stopAtEntry": false }, @@ -65,9 +65,9 @@ "type": "coreclr", "request": "launch", "preLaunchTask": "Build Mathematics Example [Debug]", - "program": "${workspaceFolder}/Examples/Mathematics/bin/Debug/netcoreapp3.1/Mathematics.dll", + "program": "${workspaceFolder}/Examples/Mathematics/bin/Debug/net5.0/Mathematics.dll", "args": [], - "cwd": "${workspaceFolder}/Examples/Mathematics/bin/Debug/netcoreapp3.1", + "cwd": "${workspaceFolder}/Examples/Mathematics/bin/Debug/net5.0", "console": "externalTerminal", "stopAtEntry": false }, @@ -76,9 +76,9 @@ "type": "coreclr", "request": "launch", "preLaunchTask": "Build Measurements Example [Debug]", - "program": "${workspaceFolder}/Examples/Measurements/bin/Debug/netcoreapp3.1/Measurements.dll", + "program": "${workspaceFolder}/Examples/Measurements/bin/Debug/net5.0/Measurements.dll", "args": [], - "cwd": "${workspaceFolder}/Examples/Measurements/bin/Debug/netcoreapp3.1", + "cwd": "${workspaceFolder}/Examples/Measurements/bin/Debug/net5.0", "console": "externalTerminal", "stopAtEntry": false }, @@ -87,20 +87,20 @@ "type": "coreclr", "request": "launch", "preLaunchTask": "Build OmnitreeGraphicsDemo Example [Debug]", - "program": "${workspaceFolder}/Examples/OmnitreeGraphicsDemo/bin/Debug/netcoreapp3.1/OmnitreeGraphicsDemo.dll", + "program": "${workspaceFolder}/Examples/OmnitreeGraphicsDemo/bin/Debug/net5.0/OmnitreeGraphicsDemo.dll", "args": [], - "cwd": "${workspaceFolder}/Examples/OmnitreeGraphicsDemo/bin/Debug/netcoreapp3.1", + "cwd": "${workspaceFolder}/Examples/OmnitreeGraphicsDemo/bin/Debug/net5.0", "console": "externalTerminal", "stopAtEntry": false }, { - "name": "ValueAttributes Example [Debug]", + "name": "TagAttributes Example [Debug]", "type": "coreclr", "request": "launch", - "preLaunchTask": "Build ValueAttributes Example [Debug]", - "program": "${workspaceFolder}/Examples/ValueAttributes/bin/Debug/netcoreapp3.1/ValueAttributes.dll", + "preLaunchTask": "Build TagAttributes Example [Debug]", + "program": "${workspaceFolder}/Examples/TagAttributes/bin/Debug/net5.0/TagAttributes.dll", "args": [], - "cwd": "${workspaceFolder}/Examples/ValueAttributes/bin/Debug/netcoreapp3.1", + "cwd": "${workspaceFolder}/Examples/TagAttributes/bin/Debug/net5.0", "console": "externalTerminal", "stopAtEntry": false }, diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 1aa628c8..29997c66 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -339,28 +339,28 @@ "problemMatcher": "$msCompile" }, { - "label": "Build ValueAttributes Example [Debug]", + "label": "Build TagAttributes Example [Debug]", "command": "dotnet", "type": "process", "args": [ "build", "--configuration", "Debug", - "${workspaceFolder}/Examples/ValueAttributes/ValueAttributes.csproj", + "${workspaceFolder}/Examples/TagAttributes/TagAttributes.csproj", "/property:GenerateFullPaths=true", "/consoleloggerparameters:NoSummary", ], "problemMatcher": "$msCompile" }, { - "label": "Build ValueAttributes Example [Release]", + "label": "Build TagAttributes Example [Release]", "command": "dotnet", "type": "process", "args": [ "build", "--configuration", "Release", - "${workspaceFolder}/Examples/ValueAttributes/ValueAttributes.csproj", + "${workspaceFolder}/Examples/TagAttributes/TagAttributes.csproj", "/property:GenerateFullPaths=true", "/consoleloggerparameters:NoSummary", ], From e8eed3c639e180c8b05801458f6d5aa989e7b2e3 Mon Sep 17 00:00:00 2001 From: Zachary Patten Date: Sun, 1 Nov 2020 09:46:59 -0500 Subject: [PATCH 10/30] XML Documentation clean up and nullabe refs --- Sources/Towel/Exceptions.cs | 11 +- Sources/Towel/Meta.cs | 409 +++++++++++++++++------------------- 2 files changed, 205 insertions(+), 215 deletions(-) diff --git a/Sources/Towel/Exceptions.cs b/Sources/Towel/Exceptions.cs index 3dd35d29..380918d0 100644 --- a/Sources/Towel/Exceptions.cs +++ b/Sources/Towel/Exceptions.cs @@ -18,14 +18,21 @@ public MathematicsException(string message, Exception innerException) : base(mes /// Represents a bug in the Towel project. Please report it. public class TowelBugException : Exception { + static string reportMessage = + Environment.NewLine + + Environment.NewLine + + "Please submit this issue to the Towel GitHub repository. " + + Environment.NewLine + + "https://github.com/ZacharyPatten/Towel/issues/new/choose"; + /// Represents a bug in the Towel project. Please report it. /// The message of the exception. - public TowelBugException(string message) : base(message) { } + public TowelBugException(string message) : base(message + reportMessage) { } /// Represents a bug in the Towel project. Please report it. /// The message of the exception. /// The inner exception. - public TowelBugException(string message, Exception innerException) : base(message, innerException) { } + public TowelBugException(string message, Exception innerException) : base(message + reportMessage, innerException) { } } /// Thrown when a data structure operation fails due to external corruption. diff --git a/Sources/Towel/Meta.cs b/Sources/Towel/Meta.cs index edca27da..71419b4f 100644 --- a/Sources/Towel/Meta.cs +++ b/Sources/Towel/Meta.cs @@ -535,7 +535,7 @@ string ConvertToCsharpSource(Type type) { _ = type ?? throw new ArgumentNullException(nameof(type)); string result = type.IsNested - ? ConvertToCsharpSource(type.DeclaringType) + "." + ? ConvertToCsharpSource(type.DeclaringType ?? throw new ArgumentException($"{nameof(type)}.{nameof(Type.DeclaringType)} is null", nameof(type))) + "." : type.Namespace + "."; result += Regex.Replace(type.Name, "`.*", string.Empty); if (type.IsGenericType) @@ -569,7 +569,7 @@ string ConvertToCsharpSource(Type type) /// The type of attribute to get. /// The enum value to get the attribute of. /// The attribute on the enum value of the provided type. - public static AttributeType GetEnumAttribute(this Enum @enum) + public static AttributeType? GetEnumAttribute(this Enum @enum) where AttributeType : Attribute { Type type = @enum.GetType(); @@ -755,16 +755,17 @@ public static System.Collections.Generic.IEnumerable GetDerivedTypes { string codeBase = assembly.Location; UriBuilder uri = new UriBuilder(codeBase); - string path = Uri.UnescapeDataString(uri.Path); - return Path.GetDirectoryName(path); + string assemblyPath = Uri.UnescapeDataString(uri.Path); + string? directoryPath = Path.GetDirectoryName(assemblyPath); + return directoryPath == string.Empty ? null : directoryPath; } #endregion #region XML Code Documentation - internal static System.Collections.Generic.HashSet loadedAssemblies = new System.Collections.Generic.HashSet(); - internal static System.Collections.Generic.Dictionary loadedXmlDocumentation = new System.Collections.Generic.Dictionary(); + internal static SetHashLinked loadedAssemblies = new(); + internal static MapHashLinked loadedXmlDocumentation = new(); internal static void LoadXmlDocumentation(Assembly assembly) { @@ -772,15 +773,16 @@ internal static void LoadXmlDocumentation(Assembly assembly) { return; } - string directoryPath = assembly.GetDirectoryPath(); - string xmlFilePath = Path.Combine(directoryPath, assembly.GetName().Name + ".xml"); - if (File.Exists(xmlFilePath)) + string? directoryPath = assembly.GetDirectoryPath(); + if (directoryPath is not null) { - using StreamReader streamReader = new StreamReader(xmlFilePath); - LoadXmlDocumentation(streamReader); + string xmlFilePath = Path.Combine(directoryPath, assembly.GetName().Name + ".xml"); + if (File.Exists(xmlFilePath)) + { + using StreamReader streamReader = new StreamReader(xmlFilePath); + LoadXmlDocumentation(streamReader); + } } - // currently marking assembly as loaded even if the XML file was not found - // may want to adjust in future, but I think this is good for now loadedAssemblies.Add(assembly); } @@ -801,10 +803,10 @@ public static void LoadXmlDocumentation(TextReader textReader) { if (xmlReader.NodeType == XmlNodeType.Element && xmlReader.Name == "member") { - string? raw_name = xmlReader["name"]; - if (!string.IsNullOrWhiteSpace(raw_name)) + string? rawName = xmlReader["name"]; + if (!string.IsNullOrWhiteSpace(rawName)) { - loadedXmlDocumentation[raw_name] = xmlReader.ReadInnerXml(); + loadedXmlDocumentation[rawName] = xmlReader.ReadInnerXml(); } } } @@ -821,11 +823,13 @@ public static void ClearXmlDocumentation() /// The type to get the XML documentation of. /// The XML documentation on the type. /// The XML documentation must be loaded into memory for this function to work. - public static string GetDocumentation(this Type type) + public static string? GetDocumentation(this Type type) { + _ = type ?? throw new ArgumentNullException(nameof(type)); + _ = type.FullName ?? throw new ArgumentException($"{nameof(type)}.{nameof(Type.FullName)} is null", nameof(type)); LoadXmlDocumentation(type.Assembly); - string key = "T:" + XmlDocumentationKeyHelper(type.FullName, null); - loadedXmlDocumentation.TryGetValue(key, out string documentation); + string key = "T:" + GetXmlNameTypeSegment(type.FullName); + loadedXmlDocumentation.TryGet(key, out string? documentation); return documentation; } @@ -833,73 +837,167 @@ public static string GetDocumentation(this Type type) /// The method to get the XML documentation of. /// The XML documentation on the method. /// The XML documentation must be loaded into memory for this function to work. - public static string GetDocumentation(this MethodInfo methodInfo) + public static string? GetDocumentation(this MethodInfo methodInfo) { - LoadXmlDocumentation(methodInfo.DeclaringType.Assembly); + _ = methodInfo ?? throw new ArgumentNullException(nameof(methodInfo)); + _ = methodInfo.DeclaringType ?? throw new ArgumentException($"{nameof(methodInfo)}.{nameof(Type.DeclaringType)} is null", nameof(methodInfo)); + return GetDocumentationMethodBase(methodInfo: methodInfo); + } - System.Collections.Generic.Dictionary typeGenericMap = new System.Collections.Generic.Dictionary(); - int tempTypeGeneric = 0; - Array.ForEach(methodInfo.DeclaringType.GetGenericArguments(), x => typeGenericMap[x.Name] = tempTypeGeneric++); + /// Gets the XML documentation on a constructor. + /// The constructor to get the XML documentation of. + /// The XML documentation on the constructor. + /// The XML documentation must be loaded into memory for this function to work. + public static string? GetDocumentation(this ConstructorInfo constructorInfo) + { + _ = constructorInfo ?? throw new ArgumentNullException(nameof(constructorInfo)); + _ = constructorInfo.DeclaringType ?? throw new ArgumentException($"{nameof(constructorInfo)}.{nameof(Type.DeclaringType)} is null", nameof(constructorInfo)); + return GetDocumentationMethodBase(constructorInfo: constructorInfo); + } - System.Collections.Generic.Dictionary methodGenericMap = new System.Collections.Generic.Dictionary(); - int tempMethodGeneric = 0; - Array.ForEach(methodInfo.GetGenericArguments(), x => methodGenericMap.Add(x.Name, tempMethodGeneric++)); + /// Gets the XML documentation on a property. + /// The property to get the XML documentation of. + /// The XML documentation on the property. + /// The XML documentation must be loaded into memory for this function to work. + public static string? GetDocumentation(this PropertyInfo propertyInfo) + { + _ = propertyInfo ?? throw new ArgumentNullException(nameof(propertyInfo)); + _ = propertyInfo.DeclaringType ?? throw new ArgumentException($"{nameof(propertyInfo)}.{nameof(Type.DeclaringType)} is null", nameof(propertyInfo)); + _ = propertyInfo.DeclaringType.FullName ?? throw new ArgumentException($"{nameof(propertyInfo)}.{nameof(EventInfo.DeclaringType)}.{nameof(Type.FullName)} is null", nameof(propertyInfo)); + LoadXmlDocumentation(propertyInfo.DeclaringType.Assembly); + string key = "P:" + GetXmlNameTypeSegment(propertyInfo.DeclaringType.FullName) + "." + propertyInfo.Name; + loadedXmlDocumentation.TryGet(key, out string? documentation); + return documentation; + } - ParameterInfo[] parameterInfos = methodInfo.GetParameters(); + /// Gets the XML documentation on a field. + /// The field to get the XML documentation of. + /// The XML documentation on the field. + /// The XML documentation must be loaded into memory for this function to work. + public static string? GetDocumentation(this FieldInfo fieldInfo) + { + _ = fieldInfo ?? throw new ArgumentNullException(nameof(fieldInfo)); + _ = fieldInfo.DeclaringType ?? throw new ArgumentException($"{nameof(fieldInfo)}.{nameof(Type.DeclaringType)} is null", nameof(fieldInfo)); + _ = fieldInfo.DeclaringType.FullName ?? throw new ArgumentException($"{nameof(fieldInfo)}.{nameof(EventInfo.DeclaringType)}.{nameof(Type.FullName)} is null", nameof(fieldInfo)); + LoadXmlDocumentation(fieldInfo.DeclaringType.Assembly); + string key = "F:" + GetXmlNameTypeSegment(fieldInfo.DeclaringType.FullName) + "." + fieldInfo.Name; + loadedXmlDocumentation.TryGet(key, out string? documentation); + return documentation; + } - string memberTypePrefix = "M:"; - string declarationTypeString = GetXmlDocumenationFormattedString(methodInfo.DeclaringType, false, typeGenericMap, methodGenericMap); - string memberNameString = methodInfo.Name; - string methodGenericArgumentsString = - methodGenericMap.Count > 0 ? - "``" + methodGenericMap.Count : - string.Empty; - string parametersString = - parameterInfos.Length > 0 ? - "(" + string.Join(",", methodInfo.GetParameters().Select(x => GetXmlDocumenationFormattedString(x.ParameterType, true, typeGenericMap, methodGenericMap))) + ")" : - string.Empty; + /// Gets the XML documentation on an event. + /// The event to get the XML documentation of. + /// The XML documentation on the event. + /// The XML documentation must be loaded into memory for this function to work. + public static string? GetDocumentation(this EventInfo eventInfo) + { + _ = eventInfo ?? throw new ArgumentNullException(nameof(eventInfo)); + _ = eventInfo.DeclaringType ?? throw new ArgumentException($"{nameof(eventInfo)}.{nameof(Type.DeclaringType)} is null", nameof(eventInfo)); + _ = eventInfo.DeclaringType.FullName ?? throw new ArgumentException($"{nameof(eventInfo)}.{nameof(EventInfo.DeclaringType)}.{nameof(Type.FullName)} is null", nameof(eventInfo)); + LoadXmlDocumentation(eventInfo.DeclaringType.Assembly); + string key = "E:" + GetXmlNameTypeSegment(eventInfo.DeclaringType.FullName) + "." + eventInfo.Name; + loadedXmlDocumentation.TryGet(key, out string? documentation); + return documentation; + } - string key = - memberTypePrefix + - declarationTypeString + - "." + - memberNameString + - methodGenericArgumentsString + - parametersString; + /// Gets the XML documentation on a member. + /// The member to get the XML documentation of. + /// The XML documentation on the member. + /// The XML documentation must be loaded into memory for this function to work. + public static string? GetDocumentation(this MemberInfo memberInfo) + { + switch (memberInfo) + { + case FieldInfo fieldInfo: + _ = fieldInfo.DeclaringType ?? throw new ArgumentException($"{nameof(memberInfo)}.{nameof(Type.DeclaringType)} is null", nameof(memberInfo)); + _ = fieldInfo.DeclaringType.FullName ?? throw new ArgumentException($"{nameof(memberInfo)}.{nameof(EventInfo.DeclaringType)}.{nameof(Type.FullName)} is null", nameof(memberInfo)); + return fieldInfo.GetDocumentation(); + case PropertyInfo propertyInfo: + _ = propertyInfo.DeclaringType ?? throw new ArgumentException($"{nameof(memberInfo)}.{nameof(Type.DeclaringType)} is null", nameof(memberInfo)); + _ = propertyInfo.DeclaringType.FullName ?? throw new ArgumentException($"{nameof(memberInfo)}.{nameof(EventInfo.DeclaringType)}.{nameof(Type.FullName)} is null", nameof(memberInfo)); + return propertyInfo.GetDocumentation(); + case EventInfo eventInfo: + _ = eventInfo.DeclaringType ?? throw new ArgumentException($"{nameof(memberInfo)}.{nameof(Type.DeclaringType)} is null", nameof(memberInfo)); + _ = eventInfo.DeclaringType.FullName ?? throw new ArgumentException($"{nameof(memberInfo)}.{nameof(EventInfo.DeclaringType)}.{nameof(Type.FullName)} is null", nameof(memberInfo)); + return eventInfo.GetDocumentation(); + case ConstructorInfo constructorInfo: + _ = constructorInfo.DeclaringType ?? throw new ArgumentException($"{nameof(memberInfo)}.{nameof(Type.DeclaringType)} is null", nameof(memberInfo)); + return constructorInfo.GetDocumentation(); + case MethodInfo methodInfo: + _ = methodInfo.DeclaringType ?? throw new ArgumentException($"{nameof(memberInfo)}.{nameof(Type.DeclaringType)} is null", nameof(memberInfo)); + return methodInfo.GetDocumentation(); + case Type type: + _ = type.FullName ?? throw new ArgumentException($"{nameof(memberInfo)}.{nameof(Type.FullName)} is null", nameof(memberInfo)); + return type.GetDocumentation(); + case null: + throw new ArgumentNullException(nameof(memberInfo)); + default: + throw new TowelBugException($"{nameof(GetDocumentation)} encountered an unhandled {nameof(MemberInfo)} type: {memberInfo}"); + }; + } - if (methodInfo.Name == "op_Implicit" || - methodInfo.Name == "op_Explicit") + /// Gets the XML documentation for a parameter. + /// The parameter to get the XML documentation for. + /// The XML documenation of the parameter. + public static string? GetDocumentation(this ParameterInfo parameterInfo) + { + _ = parameterInfo ?? throw new ArgumentNullException(nameof(parameterInfo)); + string? memberDocumentation = parameterInfo.Member.GetDocumentation(); + if (memberDocumentation is not null) { - key += "~" + GetXmlDocumenationFormattedString(methodInfo.ReturnType, true, typeGenericMap, methodGenericMap); - } + string regexPattern = + Regex.Escape(@"") + + ".*?" + + Regex.Escape(@""); - loadedXmlDocumentation.TryGetValue(key, out string documentation); - return documentation; + Match match = Regex.Match(memberDocumentation, regexPattern); + if (match.Success) + { + return match.Value; + } + } + return null; } - /// Gets the XML documentation on a constructor. - /// The constructor to get the XML documentation of. - /// The XML documentation on the constructor. - /// The XML documentation must be loaded into memory for this function to work. - public static string GetDocumentation(this ConstructorInfo constructorInfo) + internal static string? GetDocumentationMethodBase(MethodInfo? methodInfo = null, ConstructorInfo? constructorInfo = null) { - LoadXmlDocumentation(constructorInfo.DeclaringType.Assembly); + if (methodInfo is not null && constructorInfo is not null) + { + throw new TowelBugException($"{nameof(GetDocumentation)} {nameof(methodInfo)} is not null && {nameof(constructorInfo)} is not null"); + } - System.Collections.Generic.Dictionary typeGenericMap = new System.Collections.Generic.Dictionary(); + MethodBase? methodBase = methodInfo ?? (MethodBase?)constructorInfo; + _ = methodBase ?? throw new TowelBugException($"{nameof(GetDocumentation)} {nameof(methodInfo)} is null && {nameof(constructorInfo)} is null"); + _ = methodBase.DeclaringType ?? throw new ArgumentException($"{nameof(methodBase)}.{nameof(Type.DeclaringType)} is null"); + + LoadXmlDocumentation(methodBase.DeclaringType.Assembly); + + MapHashLinked typeGenericMap = new(); int tempTypeGeneric = 0; - Array.ForEach(constructorInfo.DeclaringType.GetGenericArguments(), x => typeGenericMap[x.Name] = tempTypeGeneric++); + Array.ForEach(methodBase.DeclaringType.GetGenericArguments(), x => typeGenericMap[x.Name] = tempTypeGeneric++); - // constructors don't support generic types so this will always be empty - System.Collections.Generic.Dictionary methodGenericMap = new System.Collections.Generic.Dictionary(); + MapHashLinked methodGenericMap = new(); + + if (constructorInfo is null) + { + int tempMethodGeneric = 0; + Array.ForEach(methodBase.GetGenericArguments(), x => methodGenericMap.Add(x.Name, tempMethodGeneric++)); + } - ParameterInfo[] parameterInfos = constructorInfo.GetParameters(); + ParameterInfo[] parameterInfos = methodBase.GetParameters(); string memberTypePrefix = "M:"; - string declarationTypeString = GetXmlDocumenationFormattedString(constructorInfo.DeclaringType, false, typeGenericMap, methodGenericMap); - string memberNameString = "#ctor"; + string declarationTypeString = GetXmlDocumenationFormattedString(methodBase.DeclaringType, false, typeGenericMap, methodGenericMap); + string memberNameString = + constructorInfo is not null ? "#ctor" : + methodBase.Name; + string methodGenericArgumentsString = + methodGenericMap.Count > 0 ? + "``" + methodGenericMap.Count : + string.Empty; string parametersString = parameterInfos.Length > 0 ? - "(" + string.Join(",", constructorInfo.GetParameters().Select(x => GetXmlDocumenationFormattedString(x.ParameterType, true, typeGenericMap, methodGenericMap))) + ")" : + "(" + string.Join(",", methodBase.GetParameters().Select(x => GetXmlDocumenationFormattedString(x.ParameterType, true, typeGenericMap, methodGenericMap))) + ")" : string.Empty; string key = @@ -907,64 +1005,64 @@ public static string GetDocumentation(this ConstructorInfo constructorInfo) declarationTypeString + "." + memberNameString + + methodGenericArgumentsString + parametersString; - loadedXmlDocumentation.TryGetValue(key, out string documentation); + if (methodInfo is not null && + (methodBase.Name == "op_Implicit" || + methodBase.Name == "op_Explicit")) + { + key += "~" + GetXmlDocumenationFormattedString(methodInfo.ReturnType, true, typeGenericMap, methodGenericMap); + } + + loadedXmlDocumentation.TryGet(key, out string? documentation); return documentation; } internal static string GetXmlDocumenationFormattedString( Type type, bool isMethodParameter, - System.Collections.Generic.Dictionary typeGenericMap, - System.Collections.Generic.Dictionary methodGenericMap) + MapHashLinked typeGenericMap, + MapHashLinked methodGenericMap) { if (type.IsGenericParameter) { - return methodGenericMap.TryGetValue(type.Name, out int methodIndex) + return methodGenericMap.TryGet(type.Name, out int methodIndex) ? "``" + methodIndex : "`" + typeGenericMap[type.Name]; } else if (type.HasElementType) { string elementTypeString = GetXmlDocumenationFormattedString( - type.GetElementType(), + type.GetElementType() ?? throw new ArgumentException($"{nameof(type)}.{nameof(Type.HasElementType)} && {nameof(type)}.{nameof(Type.GetElementType)}() is null", nameof(type)), isMethodParameter, typeGenericMap, methodGenericMap); - if (type.IsPointer) - { - return elementTypeString + "*"; - } - else if (type.IsArray) - { - int rank = type.GetArrayRank(); - string arrayDimensionsString = rank > 1 - ? "[" + string.Join(",", Enumerable.Repeat("0:", rank)) + "]" - : "[]"; - return elementTypeString + arrayDimensionsString; - } - else if (type.IsByRef) + switch (type) { - return elementTypeString + "@"; - } - else - { - // Hopefully this will never hit. At the time of writing - // this code, type.HasElementType is only true if the type - // is a pointer, array, or by reference. - throw new TowelBugException(nameof(GetXmlDocumenationFormattedString) + - " encountered an unhandled element type. " + - "Please submit this issue to the Towel GitHub repository. " + - "https://github.com/ZacharyPatten/Towel/issues/new/choose"); + case Type when type.IsPointer: + return elementTypeString + "*"; + + case Type when type.IsByRef: + return elementTypeString + "@"; + + case Type when type.IsArray: + int rank = type.GetArrayRank(); + string arrayDimensionsString = rank > 1 + ? "[" + string.Join(",", Enumerable.Repeat("0:", rank)) + "]" + : "[]"; + return elementTypeString + arrayDimensionsString; + + default: + throw new TowelBugException($"{nameof(GetXmlDocumenationFormattedString)} encountered an unhandled element type: {type}"); } } else { string prefaceString = type.IsNested ? GetXmlDocumenationFormattedString( - type.DeclaringType, + type.DeclaringType ?? throw new ArgumentException($"{nameof(type)}.{nameof(Type.IsNested)} && {nameof(type)}.{nameof(Type.DeclaringType)} is null", nameof(type)), isMethodParameter, typeGenericMap, methodGenericMap) + "." @@ -989,123 +1087,8 @@ internal static string GetXmlDocumenationFormattedString( } } - /// Gets the XML documentation on a property. - /// The property to get the XML documentation of. - /// The XML documentation on the property. - /// The XML documentation must be loaded into memory for this function to work. - public static string GetDocumentation(this PropertyInfo propertyInfo) - { - LoadXmlDocumentation(propertyInfo.DeclaringType.Assembly); - string key = "P:" + XmlDocumentationKeyHelper(propertyInfo.DeclaringType.FullName, propertyInfo.Name); - loadedXmlDocumentation.TryGetValue(key, out string documentation); - return documentation; - } - - /// Gets the XML documentation on a field. - /// The field to get the XML documentation of. - /// The XML documentation on the field. - /// The XML documentation must be loaded into memory for this function to work. - public static string GetDocumentation(this FieldInfo fieldInfo) - { - LoadXmlDocumentation(fieldInfo.DeclaringType.Assembly); - string key = "F:" + XmlDocumentationKeyHelper(fieldInfo.DeclaringType.FullName, fieldInfo.Name); - loadedXmlDocumentation.TryGetValue(key, out string documentation); - return documentation; - } - - /// Gets the XML documentation on an event. - /// The event to get the XML documentation of. - /// The XML documentation on the event. - /// The XML documentation must be loaded into memory for this function to work. - public static string GetDocumentation(this EventInfo eventInfo) - { - LoadXmlDocumentation(eventInfo.DeclaringType.Assembly); - string key = "E:" + XmlDocumentationKeyHelper(eventInfo.DeclaringType.FullName, eventInfo.Name); - loadedXmlDocumentation.TryGetValue(key, out string documentation); - return documentation; - } - - internal static string XmlDocumentationKeyHelper(string typeFullNameString, string memberNameString) - { - string key = Regex.Replace(typeFullNameString, @"\[.*\]", string.Empty).Replace('+', '.'); - if (memberNameString is not null) - { - key += "." + memberNameString; - } - return key; - } - - /// Gets the XML documentation on a member. - /// The member to get the XML documentation of. - /// The XML documentation on the member. - /// The XML documentation must be loaded into memory for this function to work. - public static string GetDocumentation(this MemberInfo memberInfo) - { - if (memberInfo is FieldInfo fieldInfo) - { - return fieldInfo.GetDocumentation(); - } - else if (memberInfo is PropertyInfo propertyInfo) - { - return propertyInfo.GetDocumentation(); - } - else if (memberInfo is EventInfo eventInfo) - { - return eventInfo.GetDocumentation(); - } - else if (memberInfo is ConstructorInfo constructorInfo) - { - return constructorInfo.GetDocumentation(); - } - else if (memberInfo is MethodInfo methodInfo) - { - return methodInfo.GetDocumentation(); - } - else if (memberInfo is Type type) // + TypeInfo - { - return type.GetDocumentation(); - } - else if (memberInfo.MemberType.HasFlag(MemberTypes.Custom)) - { - // This represents a cutom type that is not part of - // the standard .NET languages as far as I'm aware. - // This will never be supported so return null. - return null; - } - else - { - // Hopefully this will never hit. At the time of writing - // this code, I am only aware of the following Member types: - // FieldInfo, PropertyInfo, EventInfo, ConstructorInfo, - // MethodInfo, and Type. - throw new TowelBugException(nameof(GetDocumentation) + - " encountered an unhandled type [" + memberInfo.GetType().FullName + "]. " + - "Please submit this issue to the Towel GitHub repository. " + - "https://github.com/ZacharyPatten/Towel/issues/new/choose"); - } - } - - /// Gets the XML documentation for a parameter. - /// The parameter to get the XML documentation for. - /// The XML documenation of the parameter. - public static string GetDocumentation(this ParameterInfo parameterInfo) - { - string memberDocumentation = parameterInfo.Member.GetDocumentation(); - if (memberDocumentation is not null) - { - string regexPattern = - Regex.Escape(@"") + - ".*?" + - Regex.Escape(@""); - - Match match = Regex.Match(memberDocumentation, regexPattern); - if (match.Success) - { - return match.Value; - } - } - return null; - } + internal static string GetXmlNameTypeSegment(string typeFullNameString) => + Regex.Replace(typeFullNameString, @"\[.*\]", string.Empty).Replace('+', '.'); #endregion From 83ea2d3c20940a2b2d65978217ee3dcffd3bc8bd Mon Sep 17 00:00:00 2001 From: Zachary Patten Date: Sun, 1 Nov 2020 14:17:12 -0500 Subject: [PATCH 11/30] nullable ref + suppressions + permute status fix + try/catch -> IsWindows --- Examples/ConsoleHelpers/Program.cs | 4 ++-- Sources/Towel/CommandLine.cs | 2 +- Sources/Towel/ConsoleHelper.cs | 4 ++-- Sources/Towel/Exceptions.cs | 2 +- Sources/Towel/Statics.cs | 11 +++++++---- Tools/Towel_Testing/Meta.cs | 16 ++++++++++++---- Tools/Towel_Testing/Statics.cs | 13 ++++++++----- Tools/Towel_Testing/Towel_Testing.csproj | 6 ++++++ 8 files changed, 39 insertions(+), 19 deletions(-) diff --git a/Examples/ConsoleHelpers/Program.cs b/Examples/ConsoleHelpers/Program.cs index 6c226c3b..54ec7da0 100644 --- a/Examples/ConsoleHelpers/Program.cs +++ b/Examples/ConsoleHelpers/Program.cs @@ -172,11 +172,11 @@ public static void DoWith( } if (cursorVisible.HasValue) { - try + if (OperatingSystem.IsWindows()) { cursorVisibleRevert = Console.CursorVisible; } - catch (PlatformNotSupportedException) + else { cursorVisibleRevert = true; } diff --git a/Sources/Towel/CommandLine.cs b/Sources/Towel/CommandLine.cs index 99548a3f..ab10984b 100644 --- a/Sources/Towel/CommandLine.cs +++ b/Sources/Towel/CommandLine.cs @@ -193,7 +193,7 @@ public static void DefaultHelp(Assembly? assembly = null, string? command = null else { MethodInfo methodInfo = commandMatches[0]; - string documentation = Meta.GetDocumentation(methodInfo); + string? documentation = Meta.GetDocumentation(methodInfo); if (documentation is null) { Console.WriteLine("Parameters:"); diff --git a/Sources/Towel/ConsoleHelper.cs b/Sources/Towel/ConsoleHelper.cs index 5f0ac6d5..06a6131f 100644 --- a/Sources/Towel/ConsoleHelper.cs +++ b/Sources/Towel/ConsoleHelper.cs @@ -91,7 +91,7 @@ public static void IntMenu( /// The method for converting into a value. /// The predicate for validating the value of the input. /// The validated value of the console input provided by the user. - public static T GetInput( + public static T? GetInput( string? prompt = null, string? invalidMessage = null, Func? tryParse = null, @@ -103,7 +103,7 @@ public static T GetInput( } tryParse ??= typeof(T) == typeof(string) ? s => (true, (T)(object)s) - : (Func)TryParse; + : TryParse; validation ??= v => true; GetInput: Console.Write(prompt ?? $"Input a {typeof(T).Name} value: "); diff --git a/Sources/Towel/Exceptions.cs b/Sources/Towel/Exceptions.cs index 380918d0..2d8d3410 100644 --- a/Sources/Towel/Exceptions.cs +++ b/Sources/Towel/Exceptions.cs @@ -18,7 +18,7 @@ public MathematicsException(string message, Exception innerException) : base(mes /// Represents a bug in the Towel project. Please report it. public class TowelBugException : Exception { - static string reportMessage = + static readonly string reportMessage = Environment.NewLine + Environment.NewLine + "Please submit this issue to the Towel GitHub repository. " + diff --git a/Sources/Towel/Statics.cs b/Sources/Towel/Statics.cs index 13c79ad7..a0fe0669 100644 --- a/Sources/Towel/Statics.cs +++ b/Sources/Towel/Statics.cs @@ -324,9 +324,11 @@ public abstract class Condition /// Uses the bool as the condition result. public static implicit operator Condition(bool result) => new Bool { Result = result, }; /// Converts a keyword to a condition result (for "Default" case). +#pragma warning disable IDE0079 // Remove unnecessary suppression #pragma warning disable IDE0060 // Remove unused parameter public static implicit operator Condition(Keyword keyword) => new Default(); #pragma warning restore IDE0060 // Remove unused parameter +#pragma warning restore IDE0079 // Remove unnecessary suppression } internal class Value : Condition @@ -358,10 +360,10 @@ public abstract class Condition public abstract bool Resolve(); /// Uses the bool as the condition result. public static implicit operator Condition(bool result) => new Bool { Result = result, }; -//#pragma warning disable IDE0060 // Remove unused parameter +#pragma warning disable IDE0060 // Remove unused parameter /// Converts a keyword to a condition result (for "Default" case). public static implicit operator Condition(Keyword keyword) => new Default(); -//#pragma warning restore IDE0060 // Remove unused parameter +#pragma warning restore IDE0060 // Remove unused parameter /// Converts a condition to a bool using the Resolve method. public static implicit operator bool(Condition condition) => condition.Resolve(); } @@ -812,6 +814,7 @@ internal static class EquateImplementation { internal static Func Function = (a, b) => { + // todo: add null equality checks // todo: I need to kill this try-catch... try { @@ -2912,7 +2915,7 @@ public static T SineQuadratic(Angle a) /// The angle to compute the cosine ratio of. /// Determines if coputation should continue or is accurate enough. /// The taylor series computed cosine ratio of the provided angle. - public static T CosineTaylorSeries(Angle a, Predicate predicate = null) + public static T CosineTaylorSeries(Angle a, Predicate? predicate = null) { // Series: cosine(x) = 1 - (x^2 / 2!) + (x^4 / 4!) - (x^6 / 6!) + (x^8 / 8!) - ... // more terms in computation inproves accuracy @@ -3781,7 +3784,7 @@ public static void PermuteRecursive(Span span, Action action = def /// public static void PermuteRecursive(Span span, Action action, Status status = default) where Status : struct, IFunc => - PermuteRecursive(span, action); + PermuteRecursive(span, action, status); /// public static void PermuteRecursive(Span span, Action action = default, Status status = default) diff --git a/Tools/Towel_Testing/Meta.cs b/Tools/Towel_Testing/Meta.cs index 8ae6c6b5..9f486d18 100644 --- a/Tools/Towel_Testing/Meta.cs +++ b/Tools/Towel_Testing/Meta.cs @@ -254,8 +254,6 @@ [TestMethod] public void ParameterInfo_GetDocumentation() #region MethodInfo Testing -#pragma warning disable IDE0062 // Make local function 'static' - [TestMethod] public void MethodInfo_IsLocalFunction() { void a() { } @@ -295,8 +293,6 @@ void j() { } Assert.IsFalse(new Action(MethodInfo_IsLocalFunction).Method.IsLocalFunction()); } -#pragma warning restore IDE0062 // Make local function 'static' - #endregion #region HasImplicitCast @@ -358,11 +354,15 @@ public class E #region XML Documentation Types + +#pragma warning disable CA1822 // Mark members as static #pragma warning disable CS0067 // The event is never used #pragma warning disable IDE0060 // Remove unused parameter +#pragma warning disable CA2211 // Non-constant fields should not be visible #region XML Documentation From MethodInfo + [AttributeUsage(AttributeTargets.Method)] public class XmlDocumentationFromMethodAttribute : Attribute { } public class XmlDocumentationFromMethod @@ -639,6 +639,7 @@ public void DocumentedMethod_OptionalParameters(int a = 2) { } #region XML Documentation From Type Types + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Delegate | AttributeTargets.Enum)] public class XmlDocumentationFromTypeAttribute : Attribute { } /// Test A @@ -749,6 +750,7 @@ public static class XmlDocumentationFromTypeT { } #region XML Documentation From FieldInfo + [AttributeUsage(AttributeTargets.Field)] public class XmlDocumentationFromFieldAttribute : Attribute { } public class XmlDocumentationFromField @@ -836,6 +838,7 @@ public class NestedTypeGeneric #region XML Documentation From PropertyInfo + [AttributeUsage(AttributeTargets.Property)] public class XmlDocumentationFromPropertyAttribute : Attribute { } public class XmlDocumentationFromProperty @@ -923,6 +926,7 @@ public class NestedTypeGeneric #region XML Documentation From ConstructorInfo + [AttributeUsage(AttributeTargets.Constructor)] public class XmlDocumentationFromConstructorAttribute : Attribute { } public class XmlDocumentationFromConstructor @@ -1015,6 +1019,7 @@ public NestedGenericType2(A[] a, B[,] b, C[,,] c) { } #region XML Documentation From EventInfo + [AttributeUsage(AttributeTargets.Event)] public class XmlDocumentationFromEventAttribute : Attribute { } public class XmlDocumentationFromEvent @@ -1066,6 +1071,7 @@ public class NestedTypeGeneric #region XML Documentation From ParameterInfo + [AttributeUsage(AttributeTargets.Parameter)] public class XmlDocumentationFromParameterAttribute : Attribute { } public class XmlDocumentationFromParameter @@ -1077,6 +1083,8 @@ public void Test1(object a) { } #endregion +#pragma warning restore CA2211 // Non-constant fields should not be visible +#pragma warning restore CA1822 // Mark members as static #pragma warning restore CS0067 // The event is never used #pragma warning restore IDE0060 // Remove unused parameter diff --git a/Tools/Towel_Testing/Statics.cs b/Tools/Towel_Testing/Statics.cs index ccb09788..7007ad38 100644 --- a/Tools/Towel_Testing/Statics.cs +++ b/Tools/Towel_Testing/Statics.cs @@ -517,9 +517,9 @@ [TestMethod] public void Power_Testing() #endregion - #region EqualTo_Testing + #region Equate_Testing - [TestMethod] public void EqualTo_Testing() + [TestMethod] public void Equate_Testing() { Assert.IsTrue(Equate(0, 0)); Assert.IsTrue(Equate(1, 1)); @@ -558,6 +558,12 @@ [TestMethod] public void EqualTo_Testing() Assert.IsFalse(Equate(1, 0, 0)); Assert.IsFalse(Equate(2, 1, 1)); Assert.IsFalse(Equate(3, 2, 2)); + + // nulls + Assert.IsFalse(Equate(null, null)); + Assert.IsFalse(Equate(null, "")); + Assert.IsFalse(Equate("", null)); + Assert.IsFalse(Equate("", "")); } #endregion @@ -1596,8 +1602,6 @@ public static bool IsLeastToGreatest(T[] array) return true; } - public static int[] watchArray; - public static void TestAlgorithm( Action> algorithm, Action> algorithmPartial, @@ -1620,7 +1624,6 @@ void Test(int sizeAdjusted) { // Partial Array Sort int[] array = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; - watchArray = array; algorithmPartial(array, 3, 7, Compare); int[] expected = { 9, 8, 7, /*|*/ 2, 3, 4, 5, 6, /*|*/ 1, 0 }; for (int i = 0; i < SortSize; i++) diff --git a/Tools/Towel_Testing/Towel_Testing.csproj b/Tools/Towel_Testing/Towel_Testing.csproj index e5cb22de..12cce47a 100644 --- a/Tools/Towel_Testing/Towel_Testing.csproj +++ b/Tools/Towel_Testing/Towel_Testing.csproj @@ -5,6 +5,12 @@ Towel_Testing.xml true + + 1701;1702;1591 + + + 1701;1702;1591 + From 3c01ac7a914539ecb8f82b36525c8a9b5fe6721b Mon Sep 17 00:00:00 2001 From: Zachary Patten Date: Sun, 1 Nov 2020 15:29:51 -0500 Subject: [PATCH 12/30] nullable refs + measurement syntax readonly --- .../MeasurementUnitDefinitions.cs | 189 +++++++++--------- Sources/Towel/Statics.cs | 18 +- 2 files changed, 106 insertions(+), 101 deletions(-) diff --git a/Sources/Towel/Measurements/MeasurementUnitDefinitions.cs b/Sources/Towel/Measurements/MeasurementUnitDefinitions.cs index df29f730..48e0a292 100644 --- a/Sources/Towel/Measurements/MeasurementUnitDefinitions.cs +++ b/Sources/Towel/Measurements/MeasurementUnitDefinitions.cs @@ -439,10 +439,10 @@ public enum Units internal static Func[][] BuildConversionTable() { - T A = (Symbolics.Parse("273.15").Simplify() as Symbolics.Constant).Value; - T B = (Symbolics.Parse("9 / 5").Simplify() as Symbolics.Constant).Value; - T C = (Symbolics.Parse("459.67").Simplify() as Symbolics.Constant).Value; - T D = (Symbolics.Parse("32").Simplify() as Symbolics.Constant).Value; + T A = Symbolics.ParseAndSimplifyToConstant("273.15"); + T B = Symbolics.ParseAndSimplifyToConstant("9 / 5"); + T C = Symbolics.ParseAndSimplifyToConstant("459.67"); + T D = Symbolics.ParseAndSimplifyToConstant("32"); Func[][] table = Extensions.ConstructSquareJaggedArray>(3); @@ -524,9 +524,9 @@ internal class ConversionFactorAttribute : Attribute internal ConversionFactorAttribute(object to, string expression) { - if (!(to is Enum)) + if (to is not Enum) { - throw new ArgumentException("There is a BUG in " + nameof(Towel) + ". A " + nameof(ConversionFactorAttribute) + " contains a non-enum value.", nameof(to)); + throw new TowelBugException($"a {nameof(ConversionFactorAttribute)} contains a non-enum value: {to}"); } To = (Enum)to; Expression = expression; @@ -535,7 +535,10 @@ internal ConversionFactorAttribute(object to, string expression) internal T Value() { Symbolics.Expression expression = Symbolics.Parse(Expression); - Symbolics.Constant constant = expression.Simplify() as Symbolics.Constant; + if (expression.Simplify() is not Symbolics.Constant constant) + { + throw new TowelBugException($"encountered a measurement conversion expression that could not be simplified to a constant: {expression}"); + } return constant.Value; } } @@ -570,14 +573,14 @@ internal static Func[][] Build() { int B = System.Convert.ToInt32(B_unit); - MetricUnitAttribute A_metric = A_unit.GetEnumAttribute(); - MetricUnitAttribute B_metric = B_unit.GetEnumAttribute(); + MetricUnitAttribute? A_metric = A_unit.GetEnumAttribute(); + MetricUnitAttribute? B_metric = B_unit.GetEnumAttribute(); if (A == B) { conversionFactorTable[A][B] = x => x; } - else if (!(A_metric is null) && !(B_metric is null)) + else if (A_metric is not null && B_metric is not null) { int metricDifference = (int)A_metric.MetricUnits - (int)B_metric.MetricUnits; if (metricDifference < 0) @@ -701,67 +704,67 @@ public static class MeasurementsSyntax #region Angle Units /// Units of an angle measurement. - public static MeasurementUnitsSyntaxTypes.AngleUnits Gradians = new MeasurementUnitsSyntaxTypes.AngleUnits() { _AngleUnits1 = Angle.Units.Gradians }; + public readonly static MeasurementUnitsSyntaxTypes.AngleUnits Gradians = new MeasurementUnitsSyntaxTypes.AngleUnits() { _AngleUnits1 = Angle.Units.Gradians }; /// Units of an angle measurement. - public static MeasurementUnitsSyntaxTypes.AngleUnits Degrees = new MeasurementUnitsSyntaxTypes.AngleUnits() { _AngleUnits1 = Angle.Units.Degrees }; + public readonly static MeasurementUnitsSyntaxTypes.AngleUnits Degrees = new MeasurementUnitsSyntaxTypes.AngleUnits() { _AngleUnits1 = Angle.Units.Degrees }; /// Units of an angle measurement. - public static MeasurementUnitsSyntaxTypes.AngleUnits Radians = new MeasurementUnitsSyntaxTypes.AngleUnits() { _AngleUnits1 = Angle.Units.Radians }; + public readonly static MeasurementUnitsSyntaxTypes.AngleUnits Radians = new MeasurementUnitsSyntaxTypes.AngleUnits() { _AngleUnits1 = Angle.Units.Radians }; /// Units of an angle measurement. - public static MeasurementUnitsSyntaxTypes.AngleUnits Revolutions = new MeasurementUnitsSyntaxTypes.AngleUnits() { _AngleUnits1 = Angle.Units.Revolutions }; + public readonly static MeasurementUnitsSyntaxTypes.AngleUnits Revolutions = new MeasurementUnitsSyntaxTypes.AngleUnits() { _AngleUnits1 = Angle.Units.Revolutions }; #endregion #region Electric Charge Units /// Units of an electric charge measurement. - public static MeasurementUnitsSyntaxTypes.ElectricChargeUnits Coulombs = new MeasurementUnitsSyntaxTypes.ElectricChargeUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Coulombs }; + public readonly static MeasurementUnitsSyntaxTypes.ElectricChargeUnits Coulombs = new MeasurementUnitsSyntaxTypes.ElectricChargeUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Coulombs }; #endregion #region Electric Current Units /// Units of an electric charge measurement. - public static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Yoctoampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Yoctocoulombs, _TimeUnits2 = Time.Units.Seconds }; + public readonly static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Yoctoampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Yoctocoulombs, _TimeUnits2 = Time.Units.Seconds }; /// Units of an electric charge measurement. - public static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Zeptoampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Zeptocoulombs, _TimeUnits2 = Time.Units.Seconds }; + public readonly static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Zeptoampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Zeptocoulombs, _TimeUnits2 = Time.Units.Seconds }; /// Units of an electric charge measurement. - public static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Attoampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Attocoulombs, _TimeUnits2 = Time.Units.Seconds }; + public readonly static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Attoampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Attocoulombs, _TimeUnits2 = Time.Units.Seconds }; /// Units of an electric charge measurement. - public static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Femtoampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Femtocoulombs, _TimeUnits2 = Time.Units.Seconds }; + public readonly static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Femtoampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Femtocoulombs, _TimeUnits2 = Time.Units.Seconds }; /// Units of an electric charge measurement. - public static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Picoampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Picocoulombs, _TimeUnits2 = Time.Units.Seconds }; + public readonly static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Picoampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Picocoulombs, _TimeUnits2 = Time.Units.Seconds }; /// Units of an electric charge measurement. - public static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Nanoampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Nanocoulombs, _TimeUnits2 = Time.Units.Seconds }; + public readonly static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Nanoampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Nanocoulombs, _TimeUnits2 = Time.Units.Seconds }; /// Units of an electric charge measurement. - public static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Microampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Microcoulombs, _TimeUnits2 = Time.Units.Seconds }; + public readonly static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Microampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Microcoulombs, _TimeUnits2 = Time.Units.Seconds }; /// Units of an electric charge measurement. - public static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Milliampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Millicoulombs, _TimeUnits2 = Time.Units.Seconds }; + public readonly static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Milliampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Millicoulombs, _TimeUnits2 = Time.Units.Seconds }; /// Units of an electric charge measurement. - public static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Centiampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Centicoulombs, _TimeUnits2 = Time.Units.Seconds }; + public readonly static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Centiampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Centicoulombs, _TimeUnits2 = Time.Units.Seconds }; /// Units of an electric charge measurement. - public static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Deciampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Decicoulombs, _TimeUnits2 = Time.Units.Seconds }; + public readonly static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Deciampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Decicoulombs, _TimeUnits2 = Time.Units.Seconds }; /// Units of an electric charge measurement. - public static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Amperes = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Coulombs, _TimeUnits2 = Time.Units.Seconds }; + public readonly static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Amperes = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Coulombs, _TimeUnits2 = Time.Units.Seconds }; /// Units of an electric charge measurement. - public static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Dekaampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Dekacoulombs, _TimeUnits2 = Time.Units.Seconds }; + public readonly static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Dekaampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Dekacoulombs, _TimeUnits2 = Time.Units.Seconds }; /// Units of an electric charge measurement. - public static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Hectoampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Hectocoulombs, _TimeUnits2 = Time.Units.Seconds }; + public readonly static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Hectoampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Hectocoulombs, _TimeUnits2 = Time.Units.Seconds }; /// Units of an electric charge measurement. - public static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Kiloampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Kilocoulombs, _TimeUnits2 = Time.Units.Seconds }; + public readonly static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Kiloampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Kilocoulombs, _TimeUnits2 = Time.Units.Seconds }; /// Units of an electric charge measurement. - public static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Megaampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Megacoulombs, _TimeUnits2 = Time.Units.Seconds }; + public readonly static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Megaampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Megacoulombs, _TimeUnits2 = Time.Units.Seconds }; /// Units of an electric charge measurement. - public static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Gigaampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Gigacoulombs, _TimeUnits2 = Time.Units.Seconds }; + public readonly static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Gigaampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Gigacoulombs, _TimeUnits2 = Time.Units.Seconds }; /// Units of an electric charge measurement. - public static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Teraampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Teracoulombs, _TimeUnits2 = Time.Units.Seconds }; + public readonly static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Teraampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Teracoulombs, _TimeUnits2 = Time.Units.Seconds }; /// Units of an electric charge measurement. - public static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Petaampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Petacoulombs, _TimeUnits2 = Time.Units.Seconds }; + public readonly static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Petaampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Petacoulombs, _TimeUnits2 = Time.Units.Seconds }; /// Units of an electric charge measurement. - public static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Exaampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Exacoulombs, _TimeUnits2 = Time.Units.Seconds }; + public readonly static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Exaampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Exacoulombs, _TimeUnits2 = Time.Units.Seconds }; /// Units of an electric charge measurement. - public static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Zettaampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Zettacoulombs, _TimeUnits2 = Time.Units.Seconds }; + public readonly static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Zettaampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Zettacoulombs, _TimeUnits2 = Time.Units.Seconds }; /// Units of an electric charge measurement. - public static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Yottaampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Yottacoulombs, _TimeUnits2 = Time.Units.Seconds }; + public readonly static MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits Yottaampheres = new MeasurementUnitsSyntaxTypes.ElectricCurrentBaseUnits() { _ElectricChargeUnits1 = ElectricCharge.Units.Yottacoulombs, _TimeUnits2 = Time.Units.Seconds }; #endregion @@ -769,154 +772,154 @@ public static class MeasurementsSyntax #region Energy Units /// Units of an Energy measurement. - public static MeasurementUnitsSyntaxTypes.EnergyBaseUnits Joules = new MeasurementUnitsSyntaxTypes.EnergyBaseUnits() { _MassUnits1 = Mass.Units.Kilograms, _LengthUnits2 = Length.Units.Meters, _LengthUnits3 = Length.Units.Meters, _TimeUnits4 = Time.Units.Seconds, _TimeUnits5 = Time.Units.Seconds }; + public readonly static MeasurementUnitsSyntaxTypes.EnergyBaseUnits Joules = new MeasurementUnitsSyntaxTypes.EnergyBaseUnits() { _MassUnits1 = Mass.Units.Kilograms, _LengthUnits2 = Length.Units.Meters, _LengthUnits3 = Length.Units.Meters, _TimeUnits4 = Time.Units.Seconds, _TimeUnits5 = Time.Units.Seconds }; #endregion #region Force Units /// Units of an force measurement. - public static MeasurementUnitsSyntaxTypes.ForceBaseUnits Newtons = new MeasurementUnitsSyntaxTypes.ForceBaseUnits() { _MassUnits1 = Mass.Units.Kilograms, _LengthUnits2 = Length.Units.Meters, _TimeUnits3 = Time.Units.Seconds, _TimeUnits4 = Time.Units.Seconds }; + public readonly static MeasurementUnitsSyntaxTypes.ForceBaseUnits Newtons = new MeasurementUnitsSyntaxTypes.ForceBaseUnits() { _MassUnits1 = Mass.Units.Kilograms, _LengthUnits2 = Length.Units.Meters, _TimeUnits3 = Time.Units.Seconds, _TimeUnits4 = Time.Units.Seconds }; #endregion #region Length Units /// Units of an length measurement. - public static MeasurementUnitsSyntaxTypes.LengthUnits Yoctometers = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Yoctometers }; + public readonly static MeasurementUnitsSyntaxTypes.LengthUnits Yoctometers = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Yoctometers }; /// Units of an length measurement. - public static MeasurementUnitsSyntaxTypes.LengthUnits Zeptometers = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Zeptometers }; + public readonly static MeasurementUnitsSyntaxTypes.LengthUnits Zeptometers = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Zeptometers }; /// Units of an length measurement. - public static MeasurementUnitsSyntaxTypes.LengthUnits Attometers = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Attometers }; + public readonly static MeasurementUnitsSyntaxTypes.LengthUnits Attometers = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Attometers }; /// Units of an length measurement. - public static MeasurementUnitsSyntaxTypes.LengthUnits Femtometers = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Femtometers }; + public readonly static MeasurementUnitsSyntaxTypes.LengthUnits Femtometers = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Femtometers }; /// Units of an length measurement. - public static MeasurementUnitsSyntaxTypes.LengthUnits Picometers = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Picometers }; + public readonly static MeasurementUnitsSyntaxTypes.LengthUnits Picometers = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Picometers }; /// Units of an length measurement. - public static MeasurementUnitsSyntaxTypes.LengthUnits Nanometers = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Nanometers }; + public readonly static MeasurementUnitsSyntaxTypes.LengthUnits Nanometers = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Nanometers }; /// Units of an length measurement. - public static MeasurementUnitsSyntaxTypes.LengthUnits Micrometers = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Micrometers }; + public readonly static MeasurementUnitsSyntaxTypes.LengthUnits Micrometers = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Micrometers }; /// Units of an length measurement. - public static MeasurementUnitsSyntaxTypes.LengthUnits Millimeters = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Millimeters }; + public readonly static MeasurementUnitsSyntaxTypes.LengthUnits Millimeters = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Millimeters }; /// Units of an length measurement. - public static MeasurementUnitsSyntaxTypes.LengthUnits Centimeters = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Centimeters }; + public readonly static MeasurementUnitsSyntaxTypes.LengthUnits Centimeters = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Centimeters }; /// Units of an length measurement. - public static MeasurementUnitsSyntaxTypes.LengthUnits Inches = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Inches }; + public readonly static MeasurementUnitsSyntaxTypes.LengthUnits Inches = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Inches }; /// Units of an length measurement. - public static MeasurementUnitsSyntaxTypes.LengthUnits Decimeters = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Decimeters }; + public readonly static MeasurementUnitsSyntaxTypes.LengthUnits Decimeters = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Decimeters }; /// Units of an length measurement. - public static MeasurementUnitsSyntaxTypes.LengthUnits Feet = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Feet }; + public readonly static MeasurementUnitsSyntaxTypes.LengthUnits Feet = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Feet }; /// Units of an length measurement. - public static MeasurementUnitsSyntaxTypes.LengthUnits Yards = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Yards }; + public readonly static MeasurementUnitsSyntaxTypes.LengthUnits Yards = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Yards }; /// Units of an length measurement. - public static MeasurementUnitsSyntaxTypes.LengthUnits Meters = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Meters }; + public readonly static MeasurementUnitsSyntaxTypes.LengthUnits Meters = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Meters }; /// Units of an length measurement. - public static MeasurementUnitsSyntaxTypes.LengthUnits Dekameters = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Dekameters }; + public readonly static MeasurementUnitsSyntaxTypes.LengthUnits Dekameters = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Dekameters }; /// Units of an length measurement. - public static MeasurementUnitsSyntaxTypes.LengthUnits Hectometers = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Hectometers }; + public readonly static MeasurementUnitsSyntaxTypes.LengthUnits Hectometers = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Hectometers }; /// Units of an length measurement. - public static MeasurementUnitsSyntaxTypes.LengthUnits Kilometers = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Kilometers }; + public readonly static MeasurementUnitsSyntaxTypes.LengthUnits Kilometers = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Kilometers }; /// Units of an length measurement. - public static MeasurementUnitsSyntaxTypes.LengthUnits Miles = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Miles }; + public readonly static MeasurementUnitsSyntaxTypes.LengthUnits Miles = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Miles }; /// Units of an length measurement. - public static MeasurementUnitsSyntaxTypes.LengthUnits NauticalMiles = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.NauticalMiles }; + public readonly static MeasurementUnitsSyntaxTypes.LengthUnits NauticalMiles = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.NauticalMiles }; /// Units of an length measurement. - public static MeasurementUnitsSyntaxTypes.LengthUnits Megameters = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Megameters }; + public readonly static MeasurementUnitsSyntaxTypes.LengthUnits Megameters = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Megameters }; /// Units of an length measurement. - public static MeasurementUnitsSyntaxTypes.LengthUnits Gigameters = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Gigameters }; + public readonly static MeasurementUnitsSyntaxTypes.LengthUnits Gigameters = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Gigameters }; /// Units of an length measurement. - public static MeasurementUnitsSyntaxTypes.LengthUnits Terameters = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Terameters }; + public readonly static MeasurementUnitsSyntaxTypes.LengthUnits Terameters = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Terameters }; /// Units of an length measurement. - public static MeasurementUnitsSyntaxTypes.LengthUnits Petameters = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Petameters }; + public readonly static MeasurementUnitsSyntaxTypes.LengthUnits Petameters = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Petameters }; /// Units of an length measurement. - public static MeasurementUnitsSyntaxTypes.LengthUnits Exameters = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Exameters }; + public readonly static MeasurementUnitsSyntaxTypes.LengthUnits Exameters = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Exameters }; /// Units of an length measurement. - public static MeasurementUnitsSyntaxTypes.LengthUnits Zettameters = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Zettameters }; + public readonly static MeasurementUnitsSyntaxTypes.LengthUnits Zettameters = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Zettameters }; /// Units of an length measurement. - public static MeasurementUnitsSyntaxTypes.LengthUnits Yottameters = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Yottameters }; + public readonly static MeasurementUnitsSyntaxTypes.LengthUnits Yottameters = new MeasurementUnitsSyntaxTypes.LengthUnits() { _LengthUnits1 = Length.Units.Yottameters }; #endregion #region Mass Units /// Units of an mass measurement. - public static MeasurementUnitsSyntaxTypes.MassUnits Yoctograms = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Yoctograms }; + public readonly static MeasurementUnitsSyntaxTypes.MassUnits Yoctograms = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Yoctograms }; /// Units of an mass measurement. - public static MeasurementUnitsSyntaxTypes.MassUnits Zeptograms = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Zeptograms }; + public readonly static MeasurementUnitsSyntaxTypes.MassUnits Zeptograms = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Zeptograms }; /// Units of an mass measurement. - public static MeasurementUnitsSyntaxTypes.MassUnits Attograms = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Attograms }; + public readonly static MeasurementUnitsSyntaxTypes.MassUnits Attograms = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Attograms }; /// Units of an mass measurement. - public static MeasurementUnitsSyntaxTypes.MassUnits Femtograms = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Femtograms }; + public readonly static MeasurementUnitsSyntaxTypes.MassUnits Femtograms = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Femtograms }; /// Units of an mass measurement. - public static MeasurementUnitsSyntaxTypes.MassUnits Picograms = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Picograms }; + public readonly static MeasurementUnitsSyntaxTypes.MassUnits Picograms = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Picograms }; /// Units of an mass measurement. - public static MeasurementUnitsSyntaxTypes.MassUnits Nanograms = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Nanograms }; + public readonly static MeasurementUnitsSyntaxTypes.MassUnits Nanograms = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Nanograms }; /// Units of an mass measurement. - public static MeasurementUnitsSyntaxTypes.MassUnits Micrograms = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Micrograms }; + public readonly static MeasurementUnitsSyntaxTypes.MassUnits Micrograms = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Micrograms }; /// Units of an mass measurement. - public static MeasurementUnitsSyntaxTypes.MassUnits Milligrams = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Milligrams }; + public readonly static MeasurementUnitsSyntaxTypes.MassUnits Milligrams = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Milligrams }; /// Units of an mass measurement. - public static MeasurementUnitsSyntaxTypes.MassUnits Centigrams = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Centigrams }; + public readonly static MeasurementUnitsSyntaxTypes.MassUnits Centigrams = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Centigrams }; /// Units of an mass measurement. - public static MeasurementUnitsSyntaxTypes.MassUnits Decigrams = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Decigrams }; + public readonly static MeasurementUnitsSyntaxTypes.MassUnits Decigrams = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Decigrams }; /// Units of an mass measurement. - public static MeasurementUnitsSyntaxTypes.MassUnits Grams = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Grams }; + public readonly static MeasurementUnitsSyntaxTypes.MassUnits Grams = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Grams }; /// Units of an mass measurement. - public static MeasurementUnitsSyntaxTypes.MassUnits Dekagrams = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Dekagrams }; + public readonly static MeasurementUnitsSyntaxTypes.MassUnits Dekagrams = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Dekagrams }; /// Units of an mass measurement. - public static MeasurementUnitsSyntaxTypes.MassUnits Hectograms = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Hectograms }; + public readonly static MeasurementUnitsSyntaxTypes.MassUnits Hectograms = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Hectograms }; /// Units of an mass measurement. - public static MeasurementUnitsSyntaxTypes.MassUnits Kilograms = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Kilograms }; + public readonly static MeasurementUnitsSyntaxTypes.MassUnits Kilograms = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Kilograms }; /// Units of an mass measurement. - public static MeasurementUnitsSyntaxTypes.MassUnits Megagrams = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Megagrams }; + public readonly static MeasurementUnitsSyntaxTypes.MassUnits Megagrams = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Megagrams }; /// Units of an mass measurement. - public static MeasurementUnitsSyntaxTypes.MassUnits Gigagrams = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Gigagrams }; + public readonly static MeasurementUnitsSyntaxTypes.MassUnits Gigagrams = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Gigagrams }; /// Units of an mass measurement. - public static MeasurementUnitsSyntaxTypes.MassUnits Teragrams = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Teragrams }; + public readonly static MeasurementUnitsSyntaxTypes.MassUnits Teragrams = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Teragrams }; /// Units of an mass measurement. - public static MeasurementUnitsSyntaxTypes.MassUnits Petagrams = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Petagrams }; + public readonly static MeasurementUnitsSyntaxTypes.MassUnits Petagrams = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Petagrams }; /// Units of an mass measurement. - public static MeasurementUnitsSyntaxTypes.MassUnits Exagrams = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Exagrams }; + public readonly static MeasurementUnitsSyntaxTypes.MassUnits Exagrams = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Exagrams }; /// Units of an mass measurement. - public static MeasurementUnitsSyntaxTypes.MassUnits Zettagrams = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Zettagrams }; + public readonly static MeasurementUnitsSyntaxTypes.MassUnits Zettagrams = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Zettagrams }; /// Units of an mass measurement. - public static MeasurementUnitsSyntaxTypes.MassUnits Yottagrams = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Yottagrams }; + public readonly static MeasurementUnitsSyntaxTypes.MassUnits Yottagrams = new MeasurementUnitsSyntaxTypes.MassUnits() { _MassUnits1 = Mass.Units.Yottagrams }; #endregion #region Power Units /// Units of an Power measurement. - public static MeasurementUnitsSyntaxTypes.PowerBaseUnits Watts = new MeasurementUnitsSyntaxTypes.PowerBaseUnits() { _MassUnits1 = Mass.Units.Kilograms, _LengthUnits2 = Length.Units.Meters, _LengthUnits3 = Length.Units.Meters, _TimeUnits4 = Time.Units.Seconds, _TimeUnits5 = Time.Units.Seconds, _TimeUnits6 = Time.Units.Seconds }; + public readonly static MeasurementUnitsSyntaxTypes.PowerBaseUnits Watts = new MeasurementUnitsSyntaxTypes.PowerBaseUnits() { _MassUnits1 = Mass.Units.Kilograms, _LengthUnits2 = Length.Units.Meters, _LengthUnits3 = Length.Units.Meters, _TimeUnits4 = Time.Units.Seconds, _TimeUnits5 = Time.Units.Seconds, _TimeUnits6 = Time.Units.Seconds }; #endregion #region Pressure Units /// Units of an Pressure measurement. - public static MeasurementUnitsSyntaxTypes.PressureBaseUnits Pascals = new MeasurementUnitsSyntaxTypes.PressureBaseUnits() { _MassUnits1 = Mass.Units.Kilograms, _LengthUnits2 = Length.Units.Meters, _TimeUnits3 = Time.Units.Seconds, _TimeUnits4 = Time.Units.Seconds }; + public readonly static MeasurementUnitsSyntaxTypes.PressureBaseUnits Pascals = new MeasurementUnitsSyntaxTypes.PressureBaseUnits() { _MassUnits1 = Mass.Units.Kilograms, _LengthUnits2 = Length.Units.Meters, _TimeUnits3 = Time.Units.Seconds, _TimeUnits4 = Time.Units.Seconds }; #endregion #region Speed Units /// Units of an speed measurement. - public static MeasurementUnitsSyntaxTypes.SpeedBaseUnits Knots = new MeasurementUnitsSyntaxTypes.SpeedBaseUnits() { _LengthUnits1 = Length.Units.NauticalMiles, _TimeUnits2 = Time.Units.Hours }; + public readonly static MeasurementUnitsSyntaxTypes.SpeedBaseUnits Knots = new MeasurementUnitsSyntaxTypes.SpeedBaseUnits() { _LengthUnits1 = Length.Units.NauticalMiles, _TimeUnits2 = Time.Units.Hours }; #endregion #region Time Units /// Units of an time measurement. - public static MeasurementUnitsSyntaxTypes.TimeUnits Milliseconds = new MeasurementUnitsSyntaxTypes.TimeUnits() { _TimeUnits1 = Time.Units.Milliseconds }; + public readonly static MeasurementUnitsSyntaxTypes.TimeUnits Milliseconds = new MeasurementUnitsSyntaxTypes.TimeUnits() { _TimeUnits1 = Time.Units.Milliseconds }; /// Units of an time measurement. - public static MeasurementUnitsSyntaxTypes.TimeUnits Seconds = new MeasurementUnitsSyntaxTypes.TimeUnits() { _TimeUnits1 = Time.Units.Seconds }; + public readonly static MeasurementUnitsSyntaxTypes.TimeUnits Seconds = new MeasurementUnitsSyntaxTypes.TimeUnits() { _TimeUnits1 = Time.Units.Seconds }; /// Units of an time measurement. - public static MeasurementUnitsSyntaxTypes.TimeUnits Minutes = new MeasurementUnitsSyntaxTypes.TimeUnits() { _TimeUnits1 = Time.Units.Minutes }; + public readonly static MeasurementUnitsSyntaxTypes.TimeUnits Minutes = new MeasurementUnitsSyntaxTypes.TimeUnits() { _TimeUnits1 = Time.Units.Minutes }; /// Units of an time measurement. - public static MeasurementUnitsSyntaxTypes.TimeUnits Hours = new MeasurementUnitsSyntaxTypes.TimeUnits() { _TimeUnits1 = Time.Units.Hours }; + public readonly static MeasurementUnitsSyntaxTypes.TimeUnits Hours = new MeasurementUnitsSyntaxTypes.TimeUnits() { _TimeUnits1 = Time.Units.Hours }; /// Units of an time measurement. - public static MeasurementUnitsSyntaxTypes.TimeUnits Days = new MeasurementUnitsSyntaxTypes.TimeUnits() { _TimeUnits1 = Time.Units.Days }; + public readonly static MeasurementUnitsSyntaxTypes.TimeUnits Days = new MeasurementUnitsSyntaxTypes.TimeUnits() { _TimeUnits1 = Time.Units.Days }; #endregion } diff --git a/Sources/Towel/Statics.cs b/Sources/Towel/Statics.cs index a0fe0669..9f507999 100644 --- a/Sources/Towel/Statics.cs +++ b/Sources/Towel/Statics.cs @@ -55,7 +55,7 @@ internal static T OperationOnStepper(Action> stepper, Func { if (assigned) { - result = operation(result, a); + result = operation(result!, a); } else { @@ -64,7 +64,7 @@ internal static T OperationOnStepper(Action> stepper, Func } }); return assigned - ? result + ? result! : throw new ArgumentException($"{nameof(stepper)} is empty.", nameof(stepper)); } @@ -360,10 +360,12 @@ public abstract class Condition public abstract bool Resolve(); /// Uses the bool as the condition result. public static implicit operator Condition(bool result) => new Bool { Result = result, }; +#pragma warning disable IDE0079 // Remove unnecessary suppression #pragma warning disable IDE0060 // Remove unused parameter /// Converts a keyword to a condition result (for "Default" case). public static implicit operator Condition(Keyword keyword) => new Default(); #pragma warning restore IDE0060 // Remove unused parameter +#pragma warning restore IDE0079 // Remove unnecessary suppression /// Converts a condition to a bool using the Resolve method. public static implicit operator bool(Condition condition) => condition.Resolve(); } @@ -832,7 +834,7 @@ internal static class EquateImplementation if (typeof(C) == typeof(bool)) { EquateImplementation.Function = (_A, _B) => _A.Equals(_B); - return Function(a, b); + return Function!(a, b); } throw new NotImplementedException(); @@ -1183,7 +1185,7 @@ internal static class CompareImplementation Expression.Label(RETURN, Expression.Constant(default(CompareResult), typeof(CompareResult)))); CompareImplementation.Function = Expression.Lambda>(BODY, A, B).Compile(); } - return Function(a, b); + return Function!(a, b); } throw new NotImplementedException(); }; @@ -1602,7 +1604,7 @@ static int SquareRoot(int x) return ans; } SquareRootImplementation.Function = SquareRoot; - return Function(a); + return Function!(a); } #endregion @@ -2139,7 +2141,7 @@ public static T LeastCommonMultiple(Action> stepper) { throw new ArgumentException(nameof(stepper) + " is empty.", nameof(stepper)); } - return answer; + return answer!; } #endregion @@ -2681,8 +2683,8 @@ public static void Range(Action> stepper, out T minimum, out T maxi { throw new ArgumentException("The argument is empty.", nameof(stepper)); } - minimum = min; - maximum = max; + minimum = min!; + maximum = max!; } #endregion From 17a696f06d033815b6e080a58a4de59e12e5bfcd Mon Sep 17 00:00:00 2001 From: Zachary Patten Date: Sun, 1 Nov 2020 17:35:08 -0500 Subject: [PATCH 13/30] fixing Equate test --- Sources/Towel/Statics.cs | 19 +++++++++++++++++-- Tools/Towel_Testing/Statics.cs | 5 +++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/Sources/Towel/Statics.cs b/Sources/Towel/Statics.cs index 9f507999..4f0f3557 100644 --- a/Sources/Towel/Statics.cs +++ b/Sources/Towel/Statics.cs @@ -816,7 +816,7 @@ internal static class EquateImplementation { internal static Func Function = (a, b) => { - // todo: add null equality checks + // todo: add a type safe meethodinfo look up // todo: I need to kill this try-catch... try { @@ -833,7 +833,22 @@ internal static class EquateImplementation if (typeof(C) == typeof(bool)) { - EquateImplementation.Function = (_A, _B) => _A.Equals(_B); + EquateImplementation.Function = + (typeof(A).IsValueType, typeof(B).IsValueType) switch + { + (true, true) => (A, B) => A.Equals(B), + (true, false) => (A, B) => A.Equals(B), + (false, true) => (A, B) => B.Equals(A), + (false, false) => + (A, B) => + (A, B) switch + { + (null, null) => true, + (_, null) => false, + (null, _) => false, + _ => A.Equals(B), + }, + }; return Function!(a, b); } diff --git a/Tools/Towel_Testing/Statics.cs b/Tools/Towel_Testing/Statics.cs index 7007ad38..4e277e7b 100644 --- a/Tools/Towel_Testing/Statics.cs +++ b/Tools/Towel_Testing/Statics.cs @@ -560,10 +560,11 @@ [TestMethod] public void Equate_Testing() Assert.IsFalse(Equate(3, 2, 2)); // nulls - Assert.IsFalse(Equate(null, null)); + + Assert.IsTrue(Equate(null, null)); Assert.IsFalse(Equate(null, "")); Assert.IsFalse(Equate("", null)); - Assert.IsFalse(Equate("", "")); + Assert.IsTrue(Equate("", "")); } #endregion From 54e3bc0660fc0548518ef30ce305e107a008e23c Mon Sep 17 00:00:00 2001 From: Zachary Patten Date: Mon, 2 Nov 2020 09:03:19 -0500 Subject: [PATCH 14/30] + Extra Path Finding (Graph Search) Example + Vector HashCode and Equals + nullable refs + exceptions --- Examples/GraphSearch/Program.cs | 119 +++++++++++++++++++++++ Examples/TagAttributes/Program.cs | 2 +- Sources/Towel/Extensions.cs | 11 +-- Sources/Towel/Mathematics/Matrix.cs | 145 +++++++++++++++------------- Sources/Towel/Mathematics/Vector.cs | 20 +--- Sources/Towel/Serialization.cs | 34 +++++-- Sources/Towel/Towel.xml | 4 - 7 files changed, 234 insertions(+), 101 deletions(-) diff --git a/Examples/GraphSearch/Program.cs b/Examples/GraphSearch/Program.cs index 93dd47ae..86fdee5e 100644 --- a/Examples/GraphSearch/Program.cs +++ b/Examples/GraphSearch/Program.cs @@ -4,6 +4,7 @@ using Towel.DataStructures; using Towel.Mathematics; using static Towel.Statics; +using Vector2 = System.Numerics.Vector2; namespace GraphSearch { @@ -315,6 +316,124 @@ bool goalFunction(Vector currentLocation) } #endregion + #region char[][] 2D Example + { + Console.WriteLine(" Graph Searching (char[][] 2D Example)---------------------"); + Console.WriteLine(); + Console.WriteLine(" Board: "); + + // Set Up Map (not necessarily required, but we need something to path find) + + char[][] board = + { + "███████████".ToCharArray(), + "█ █".ToCharArray(), + "█ █ █ █".ToCharArray(), + "█ █ █ █".ToCharArray(), + "█E █ P █".ToCharArray(), + "███████████".ToCharArray(), + }; + + int columns = 11; + int rows = 6; + + Vector2 enemyLocation = default; + Vector2 playerLocation = default; + + for (int i = 0; i < rows; i++) + { + for (int j = 0; j < columns; j++) + { + if (board[i][j] is 'E') + { + enemyLocation = new Vector2(i, j); + } + if (board[i][j] is 'P') + { + playerLocation = new Vector2(i, j); + } + } + } + + // Write Board To Console + + for (int i = 0; i < rows; i++) + { + Console.Write(" "); + for (int j = 0; j < columns; j++) + { + Console.Write(board[i][j]); + } + Console.WriteLine(); + } + Console.WriteLine(); + + // Make Path Finding Functions + + SetHashLinked alreadyUsed = new SetHashLinked(); + + void Neighbors(Vector2 currentLocation, Action neighbors) + { + float x = currentLocation.X; + float y = currentLocation.Y; + + void HandleNeighbor(Vector2 neighbor) + { + if (!alreadyUsed.Contains(neighbor) && board[(int)neighbor.X][(int)neighbor.Y] is not '█') + { + alreadyUsed.Add(neighbor); + neighbors(neighbor); + } + } + + HandleNeighbor(new Vector2(x - 1, y)); // north + HandleNeighbor(new Vector2(x, y + 1)); // east + HandleNeighbor(new Vector2(x + 1, y)); // south + HandleNeighbor(new Vector2(x, y - 1)); // west + } + + float Heuristic(Vector2 node) => Vector2.Distance(node, playerLocation); + + bool Goal(Vector2 node) => Vector2.Distance(node, playerLocation) < 1; + + // Run The Path Finding Algorithm + + Action> path = + SearchGraph( + enemyLocation, + Neighbors, + Heuristic, + Goal); + + // Print Path To Console + + Vector2[] pathAsArray = path.ToArray(); + Console.WriteLine(" Path:"); + foreach (Vector2 node in pathAsArray) + { + Console.WriteLine(" " + node); + } + Console.WriteLine(); + Console.WriteLine(" Board (with path):"); + + // Print Map With Path To Console + + foreach (Vector2 node in pathAsArray) + { + board[(int)node.X][(int)node.Y] = ':'; + } + for (int i = 0; i < rows; i++) + { + Console.Write(" "); + for (int j = 0; j < columns; j++) + { + Console.Write(board[i][j]); + } + Console.WriteLine(); + } + } + #endregion + Console.WriteLine(); Console.WriteLine("============================================"); Console.WriteLine("Example Complete..."); diff --git a/Examples/TagAttributes/Program.cs b/Examples/TagAttributes/Program.cs index 52de5d06..d5b4ff40 100644 --- a/Examples/TagAttributes/Program.cs +++ b/Examples/TagAttributes/Program.cs @@ -81,7 +81,7 @@ public class A { [Tag(MyTagA, "works :3")] [Tag(MyTagB, "E")] - public object Field; + public object Field = new object(); [Tag(MyTagA, "works :b")] [Tag(MyTagB, "F")] diff --git a/Sources/Towel/Extensions.cs b/Sources/Towel/Extensions.cs index 9444ad7f..d23d6447 100644 --- a/Sources/Towel/Extensions.cs +++ b/Sources/Towel/Extensions.cs @@ -1191,9 +1191,6 @@ internal static class ToEnglishWordsDefinitions }; } - internal static string ToEnglishWords(string number) => - ToEnglishWords(number.AsSpan()); - internal static string ToEnglishWords(ReadOnlySpan number) { if (number.Length == 1 && number[0] == '0') @@ -1282,9 +1279,9 @@ void WholeNumber(ReadOnlySpan wholeNumber) void DigitGroup(char hundredsDigit, char tensDigit, char onesDigit) { - int hundred = hundredsDigit - '0', - ten = tensDigit - '0', - one = onesDigit - '0'; + int hundred = hundredsDigit - '0'; + int ten = tensDigit - '0'; + int one = onesDigit - '0'; if (hundred > 0) { AppendLeadingSpace(); @@ -1398,7 +1395,7 @@ public static TimeSpan Time_StopWatch(this Action action) /// The IEnumerable to try to get the first value of. /// The first value of the or default if empty. /// True if the has a first value or false if it is empty. - public static bool TryFirst(this System.Collections.Generic.IEnumerable iEnumerable, out T first) + public static bool TryFirst(this System.Collections.Generic.IEnumerable iEnumerable, out T? first) { foreach (T value in iEnumerable) { diff --git a/Sources/Towel/Mathematics/Matrix.cs b/Sources/Towel/Mathematics/Matrix.cs index 1a9711b4..e8aac376 100644 --- a/Sources/Towel/Mathematics/Matrix.cs +++ b/Sources/Towel/Mathematics/Matrix.cs @@ -98,7 +98,7 @@ public T this[int flatIndex] #region Debugger Properties - internal string DebuggerString + internal string? DebuggerString { get { @@ -196,14 +196,14 @@ internal Matrix(Matrix matrix) { _rows = matrix._rows; _columns = matrix.Columns; - _matrix = (matrix._matrix).Clone() as T[]; + _matrix = (T[])matrix._matrix.Clone(); } internal Matrix(Vector vector) { _rows = vector.Dimensions; _columns = 1; - _matrix = vector._vector.Clone() as T[]; + _matrix = (T[])vector._vector.Clone(); } #endregion @@ -590,7 +590,7 @@ public bool IsSymetric /// Negates all the values in a matrix. /// The matrix to have its values negated. /// The resulting matrix after the negation. - public static void Negate(Matrix a, ref Matrix b) + public static void Negate(Matrix a, ref Matrix? b) { _ = a ?? throw new ArgumentNullException(nameof(a)); int Length = a._matrix.Length; @@ -618,9 +618,9 @@ public static void Negate(Matrix a, ref Matrix b) /// The resulting matrix after the negation. public static Matrix Negate(Matrix a) { - Matrix b = null; + Matrix? b = null; Negate(a, ref b); - return b; + return b!; } /// Negates all the values in a matrix. @@ -633,7 +633,7 @@ public static Matrix Negate(Matrix a) /// Negates all the values in a matrix. /// The resulting matrix after the negation. - public void Negate(ref Matrix b) + public void Negate(ref Matrix? b) { Negate(this, ref b); } @@ -653,7 +653,7 @@ public Matrix Negate() /// The left matrix of the addition. /// The right matrix of the addition. /// The resulting matrix after the addition. - public static void Add(Matrix a, Matrix b, ref Matrix c) + public static void Add(Matrix a, Matrix b, ref Matrix? c) { _ = a ?? throw new ArgumentNullException(nameof(a)); _ = b ?? throw new ArgumentNullException(nameof(b)); @@ -690,9 +690,9 @@ public static void Add(Matrix a, Matrix b, ref Matrix c) /// The resulting matrix after the addition. public static Matrix Add(Matrix a, Matrix b) { - Matrix c = null; + Matrix? c = null; Add(a, b, ref c); - return c; + return c!; } /// Does a standard matrix addition. @@ -707,7 +707,7 @@ public static Matrix Add(Matrix a, Matrix b) /// Does standard addition of two matrices. /// The right matrix of the addition. /// The resulting matrix after the addition. - public void Add(Matrix b, ref Matrix c) + public void Add(Matrix b, ref Matrix? c) { Add(this, b, ref c); } @@ -728,7 +728,7 @@ public Matrix Add(Matrix b) /// The left matrix of the subtraction. /// The right matrix of the subtraction. /// The resulting matrix after the subtraction. - public static void Subtract(Matrix a, Matrix b, ref Matrix c) + public static void Subtract(Matrix a, Matrix b, ref Matrix? c) { _ = a ?? throw new ArgumentNullException(nameof(a)); _ = b ?? throw new ArgumentNullException(nameof(b)); @@ -765,9 +765,9 @@ public static void Subtract(Matrix a, Matrix b, ref Matrix c) /// The resulting matrix after the subtraction. public static Matrix Subtract(Matrix a, Matrix b) { - Matrix c = null; + Matrix? c = null; Subtract(a, b, ref c); - return c; + return c!; } /// Does a standard matrix subtraction. @@ -782,7 +782,7 @@ public static Matrix Subtract(Matrix a, Matrix b) /// Does a standard matrix subtraction. /// The right matrix of the subtraction. /// The resulting matrix after the subtraction. - public void Subtract(Matrix b, ref Matrix c) + public void Subtract(Matrix b, ref Matrix? c) { Subtract(this, b, ref c); } @@ -803,7 +803,7 @@ public Matrix Subtract(Matrix b) /// The left matrix of the multiplication. /// The right matrix of the multiplication. /// The resulting matrix of the multiplication. - public static void Multiply(Matrix a, Matrix b, ref Matrix c) + public static void Multiply(Matrix a, Matrix b, ref Matrix? c) { _ = a ?? throw new ArgumentNullException(nameof(a)); _ = b ?? throw new ArgumentNullException(nameof(b)); @@ -812,17 +812,17 @@ public static void Multiply(Matrix a, Matrix b, ref Matrix c) throw new MathematicsException("Arguments invalid !(" + nameof(a) + "." + nameof(a.Columns) + " == " + nameof(b) + "." + nameof(b.Rows) + ")"); } - if (object.ReferenceEquals(a, b) && object.ReferenceEquals(a, c)) + if (ReferenceEquals(a, b) && ReferenceEquals(a, c)) { Matrix clone = a.Clone(); a = clone; b = clone; } - else if (object.ReferenceEquals(a, c)) + else if (ReferenceEquals(a, c)) { a = a.Clone(); } - else if (object.ReferenceEquals(b, c)) + else if (ReferenceEquals(b, c)) { b = b.Clone(); } @@ -865,9 +865,9 @@ public static void Multiply(Matrix a, Matrix b, ref Matrix c) /// The resulting matrix of the multiplication. public static Matrix Multiply(Matrix a, Matrix b) { - Matrix c = null; + Matrix? c = null; Multiply(a, b, ref c); - return c; + return c!; } /// Does a standard (triple for looped) multiplication between matrices. @@ -882,7 +882,7 @@ public static Matrix Multiply(Matrix a, Matrix b) /// Does a standard (triple for looped) multiplication between matrices. /// The right matrix of the multiplication. /// The resulting matrix of the multiplication. - public void Multiply(Matrix b, ref Matrix c) + public void Multiply(Matrix b, ref Matrix? c) { Multiply(this, b, ref c); } @@ -903,7 +903,7 @@ public Matrix Multiply(Matrix b) /// The left matrix of the multiplication. /// The right vector of the multiplication. /// The resulting vector of the multiplication. - public static void Multiply(Matrix a, Vector b, ref Vector c) + public static void Multiply(Matrix a, Vector b, ref Vector? c) { _ = a ?? throw new ArgumentNullException(nameof(a)); _ = b ?? throw new ArgumentNullException(nameof(b)); @@ -944,9 +944,9 @@ public static void Multiply(Matrix a, Vector b, ref Vector c) /// The resulting vector of the multiplication. public static Vector Multiply(Matrix a, Vector b) { - Vector c = null; + Vector? c = null; Multiply(a, b, ref c); - return c; + return c!; } /// Does a matrix-vector multiplication. @@ -961,7 +961,7 @@ public static Vector Multiply(Matrix a, Vector b) /// Does a matrix-vector multiplication. /// The right vector of the multiplication. /// The resulting vector of the multiplication. - public void Multiply(Vector b, ref Vector c) + public void Multiply(Vector b, ref Vector? c) { Multiply(this, b, ref c); } @@ -982,7 +982,7 @@ public Vector Multiply(Vector b) /// The matrix to have the values multiplied. /// The scalar to multiply the values by. /// The resulting matrix after the multiplications. - public static void Multiply(Matrix a, T b, ref Matrix c) + public static void Multiply(Matrix a, T b, ref Matrix? c) { _ = a ?? throw new ArgumentNullException(nameof(a)); T[] A = a._matrix; @@ -1011,9 +1011,9 @@ public static void Multiply(Matrix a, T b, ref Matrix c) /// The resulting matrix after the multiplications. public static Matrix Multiply(Matrix a, T b) { - Matrix c = null; + Matrix? c = null; Multiply(a, b, ref c); - return c; + return c!; } /// Multiplies all the values in a matrix by a scalar. @@ -1046,7 +1046,7 @@ public static Matrix Multiply(T b, Matrix a) /// Multiplies all the values in a matrix by a scalar. /// The scalar to multiply the values by. /// The resulting matrix after the multiplications. - public void Multiply(T b, ref Matrix c) + public void Multiply(T b, ref Matrix? c) { Multiply(this, b, ref c); } @@ -1067,7 +1067,7 @@ public Matrix Multiply(T b) /// The matrix to divide the values of. /// The scalar to divide all the matrix values by. /// The resulting matrix after the division. - public static void Divide(Matrix a, T b, ref Matrix c) + public static void Divide(Matrix a, T b, ref Matrix? c) { _ = a ?? throw new ArgumentNullException(nameof(a)); T[] A = a._matrix; @@ -1097,9 +1097,9 @@ public static void Divide(Matrix a, T b, ref Matrix c) /// The resulting matrix after the division. public static Matrix Divide(Matrix a, T b) { - Matrix c = null; + Matrix? c = null; Divide(a, b, ref c); - return c; + return c!; } /// Divides all the values in the matrix by a scalar. @@ -1114,7 +1114,7 @@ public static Matrix Divide(Matrix a, T b) /// Divides all the values in the matrix by a scalar. /// The scalar to divide all the matrix values by. /// The resulting matrix after the division. - public void Divide(T b, ref Matrix c) + public void Divide(T b, ref Matrix? c) { Divide(this, b, ref c); } @@ -1135,7 +1135,7 @@ public Matrix Divide(T b) /// The matrix to be powered by. /// The power to apply to the matrix. /// The resulting matrix of the power operation. - public static void Power(Matrix a, int b, ref Matrix c) + public static void Power(Matrix a, int b, ref Matrix? c) { _ = a ?? throw new ArgumentNullException(nameof(a)); if (!a.IsSquare) @@ -1175,11 +1175,11 @@ public static void Power(Matrix a, int b, ref Matrix c) { c = a.Clone(); } - Matrix d = new Matrix(a._rows, a._columns, a._matrix.Length); + Matrix? d = new Matrix(a._rows, a._columns, a._matrix.Length); for (int i = 0; i < b; i++) { Multiply(c, a, ref d); - Matrix temp = d; + Matrix? temp = d; d = c; c = d; } @@ -1191,9 +1191,9 @@ public static void Power(Matrix a, int b, ref Matrix c) /// The resulting matrix of the power operation. public static Matrix Power(Matrix a, int b) { - Matrix c = null; + Matrix? c = null; Power(a, b, ref c); - return c; + return c!; } /// Applies a power to a square matrix. @@ -1209,7 +1209,7 @@ public static Matrix Power(Matrix a, int b) /// Applies a power to a square matrix. /// The power to apply to the matrix. /// The resulting matrix of the power operation. - public void Power(int b, ref Matrix c) + public void Power(int b, ref Matrix? c) { Power(this, b, ref c); } @@ -1389,17 +1389,17 @@ public Matrix Minor(int row, int column) => /// public static Matrix Minor(Matrix a, int row, int column) { - Matrix b = null; + Matrix? b = null; Minor(a, row, column, ref b); - return b; + return b!; } /// - public void Minor(int row, int column, ref Matrix b) => + public void Minor(int row, int column, ref Matrix? b) => Minor(this, row, column, ref b); /// - public static void Minor(Matrix a, int row, int column, ref Matrix b) + public static void Minor(Matrix a, int row, int column, ref Matrix? b) { _ = a ?? throw new ArgumentNullException(nameof(a)); if (a._rows < 2 || a._columns < 2) @@ -1465,7 +1465,7 @@ public static void Minor(Matrix a, int row, int column, ref Matrix b) /// The left matrix of the concatenation. /// The right matrix of the concatenation. /// The resulting matrix of the concatenation. - public static void ConcatenateRowWise(Matrix a, Matrix b, ref Matrix c) + public static void ConcatenateRowWise(Matrix a, Matrix b, ref Matrix? c) { _ = a ?? throw new ArgumentNullException(nameof(a)); _ = b ?? throw new ArgumentNullException(nameof(b)); @@ -1519,16 +1519,16 @@ public static void ConcatenateRowWise(Matrix a, Matrix b, ref Matrix c) /// The resulting matrix of the concatenation. public static Matrix ConcatenateRowWise(Matrix a, Matrix b) { - Matrix c = null; + Matrix? c = null; ConcatenateRowWise(a, b, ref c); - return c; + return c!; } /// Combines two matrices from left to right /// (result.Rows = left.Rows AND result.Columns = left.Columns + right.Columns). /// The right matrix of the concatenation. /// The resulting matrix of the concatenation. - public void ConcatenateRowWise(Matrix b, ref Matrix c) + public void ConcatenateRowWise(Matrix b, ref Matrix? c) { ConcatenateRowWise(this, b, ref c); } @@ -1639,7 +1639,7 @@ public Matrix Echelon() /// Calculates the echelon of a matrix and reduces it (aka RREF). /// The matrix matrix to calculate the reduced echelon of (aka RREF). /// The reduced echelon of the matrix (aka RREF). - public static void ReducedEchelon(Matrix a, ref Matrix b) + public static void ReducedEchelon(Matrix a, ref Matrix? b) { _ = a ?? throw new ArgumentNullException(nameof(a)); int Rows = a.Rows; @@ -1774,14 +1774,14 @@ public static void ReducedEchelon(Matrix a, ref Matrix b) /// The reduced echelon of the matrix (aka RREF). public static Matrix ReducedEchelon(Matrix a) { - Matrix b = null; + Matrix? b = null; ReducedEchelon(a, ref b); - return b; + return b!; } /// Calculates the echelon of a matrix and reduces it (aka RREF). /// The reduced echelon of the matrix (aka RREF). - public void ReducedEchelon(ref Matrix b) + public void ReducedEchelon(ref Matrix? b) { ReducedEchelon(this, ref b); } @@ -1800,7 +1800,7 @@ public Matrix ReducedEchelon() /// Calculates the inverse of a matrix. /// The matrix to calculate the inverse of. /// The inverse of the matrix. - public static void Inverse(Matrix a, ref Matrix b) + public static void Inverse(Matrix a, ref Matrix? b) { _ = a ?? throw new ArgumentNullException(nameof(a)); if (!a.IsSquare) @@ -1917,9 +1917,9 @@ public static void Inverse(Matrix a, ref Matrix b) /// The inverse of the matrix. public static Matrix Inverse(Matrix a) { - Matrix b = null; + Matrix? b = null; Inverse(a, ref b); - return b; + return b!; } /// Matrixs the inverse of this matrix. @@ -1936,7 +1936,7 @@ public Matrix Inverse() /// Calculates the adjoint of a matrix. /// The matrix to calculate the adjoint of. /// The adjoint of the matrix. - public static void Adjoint(Matrix a, ref Matrix b) + public static void Adjoint(Matrix a, ref Matrix? b) { _ = a ?? throw new ArgumentNullException(nameof(a)); if (!a.IsSquare) @@ -2023,14 +2023,14 @@ public static void Adjoint(Matrix a, ref Matrix b) /// The adjoint of the matrix. public static Matrix Adjoint(Matrix a) { - Matrix b = null; + Matrix? b = null; Adjoint(a, ref b); - return b; + return b!; } /// Calculates the adjoint of a matrix. /// The adjoint of the matrix. - public void Adjoint(ref Matrix b) + public void Adjoint(ref Matrix? b) { Adjoint(this, ref b); } @@ -2049,7 +2049,7 @@ public Matrix Adjoint() /// Returns the transpose of a matrix. /// The matrix to transpose. /// The transpose of the matrix. - public static void Transpose(Matrix a, ref Matrix b) + public static void Transpose(Matrix a, ref Matrix? b) { _ = a ?? throw new ArgumentNullException(nameof(a)); if (ReferenceEquals(a, b)) @@ -2086,14 +2086,14 @@ public static void Transpose(Matrix a, ref Matrix b) /// The transpose of the matrix. public static Matrix Transpose(Matrix a) { - Matrix b = null; + Matrix? b = null; Transpose(a, ref b); - return b; + return b!; } /// Returns the transpose of a matrix. /// The transpose of the matrix. - public void Transpose(ref Matrix b) + public void Transpose(ref Matrix? b) { Transpose(this, ref b); } @@ -2607,18 +2607,27 @@ public static implicit operator Matrix(T[,] array) => #region Overrides - /// Prints out a string representation of this matrix. - /// A string representing this matrix. - public override string ToString() => base.ToString(); + ///// Prints out a string representation of this matrix. + ///// A string representing this matrix. + //public override string? ToString() => base.ToString(); /// Matrixs a hash code from the values of this matrix. /// A hash code for the matrix. - public override int GetHashCode() => _matrix.GetHashCode() ^ _rows ^ _columns; + public override int GetHashCode() + { + //return _matrix.GetHashCode() ^ _rows ^ _columns; + int hashCode = HashCode.Combine(_rows, _columns); + foreach (T value in _matrix) + { + hashCode = HashCode.Combine(hashCode, DefaultHash(value)); + } + return hashCode; + } /// Does an equality check by value. /// The object to compare to. /// True if the references are equal, false if not. - public override bool Equals(object b) => b is Matrix B && Equal(this, B); + public override bool Equals(object? b) => b is Matrix B && Equal(this, B); #endregion } diff --git a/Sources/Towel/Mathematics/Vector.cs b/Sources/Towel/Mathematics/Vector.cs index 225bf47a..864f604a 100644 --- a/Sources/Towel/Mathematics/Vector.cs +++ b/Sources/Towel/Mathematics/Vector.cs @@ -1347,28 +1347,18 @@ public StepStatus Stepper(StepRefBreak step) /// A hash code for the matrix. public override int GetHashCode() { - int hash = this._vector[0].GetHashCode(); - for (int i = 1; i < this._vector.Length; i++) + int hashCode = default; + for (int i = 1; i < _vector.Length; i++) { - hash ^= this._vector[i].GetHashCode(); + hashCode = HashCode.Combine(hashCode, _vector[i]); } - return hash; + return hashCode; } /// Does an equality check by reference. /// The object to compare to. /// True if the references are equal, false if not. - public override bool Equals(object right) - { - if (!(right is Vector vector)) - { - return false; - } - else - { - return Equal(this, vector); - } - } + public override bool Equals(object? right) => right is Vector vector && Equal(this, vector); #endregion } diff --git a/Sources/Towel/Serialization.cs b/Sources/Towel/Serialization.cs index 3027cf46..106e7736 100644 --- a/Sources/Towel/Serialization.cs +++ b/Sources/Towel/Serialization.cs @@ -172,6 +172,10 @@ public static void StaticDelegateToXml(T @delegate, TextWriter textWriter, Xm { throw new NotSupportedException("delegates assigned to non-static methods are not supported"); } + if (methodInfo.DeclaringType is null) + { + throw new ArgumentException($"{nameof(@delegate)}.{nameof(Delegate.Method)}.{nameof(MethodInfo.DeclaringType)} is null", nameof(@delegate)); + } ParameterInfo[] parameterInfos = methodInfo.GetParameters(); xmlWriter.WriteStartElement(StaticDelegateConstants.Name); { @@ -245,10 +249,10 @@ public static Delegate StaticDelegateFromXml(TextReader textReader) wh { try { - string declaringTypeString = null; - string methodNameString = null; + string? declaringTypeString = null; + string? methodNameString = null; IList parameterTypeStrings = new ListArray(); - string returnTypeString = null; + string? returnTypeString = null; using (XmlReader xmlReader = XmlReader.Create(textReader)) { while (xmlReader.Read()) @@ -274,9 +278,17 @@ public static Delegate StaticDelegateFromXml(TextReader textReader) wh } } } - Type declaringType = Type.GetType(declaringTypeString); - Type returnType = Type.GetType(returnTypeString); - MethodInfo methodInfo = null; + if (declaringTypeString is null) + { + goto ThrowMissingType; + } + if (returnTypeString is null) + { + goto ThrowMissingReturnType; + } + Type? declaringType = Type.GetType(declaringTypeString); + Type? returnType = Type.GetType(returnTypeString); + MethodInfo? methodInfo = null; if (parameterTypeStrings.Count > 0) { Type[] parameterTypes = parameterTypeStrings.Select(x => Type.GetType(x)).ToArray(); @@ -286,6 +298,10 @@ public static Delegate StaticDelegateFromXml(TextReader textReader) wh { methodInfo = declaringType.GetMethod(methodNameString); } + if (methodInfo is null) + { + goto ThrowMethodNotFound; + } if (methodInfo.IsLocalFunction()) { goto ThrowLocalFunctionException; @@ -304,6 +320,12 @@ public static Delegate StaticDelegateFromXml(TextReader textReader) wh { throw new Exception("Deserialization failed.", exception); } + ThrowMethodNotFound: + throw new Exception("The method of the deserialization was not found."); + ThrowMissingReturnType: + throw new ArgumentException("Deserialization failed due to missing return type."); + ThrowMissingType: + throw new ArgumentException("Deserialization failed due to missing type."); ThrowNonStaticException: throw new NotSupportedException("Delegates assigned to non-static methods are not supported."); ThrowLocalFunctionException: diff --git a/Sources/Towel/Towel.xml b/Sources/Towel/Towel.xml index c698708a..99a26a1b 100644 --- a/Sources/Towel/Towel.xml +++ b/Sources/Towel/Towel.xml @@ -17017,10 +17017,6 @@ The delegate to invoke on each item in the structure. The resulting status of the iteration. - - Prints out a string representation of this matrix. - A string representing this matrix. - Matrixs a hash code from the values of this matrix. A hash code for the matrix. From 7a9fd5f073349b320e9a756828c3cf4917b83e0f Mon Sep 17 00:00:00 2001 From: Zachary Patten Date: Mon, 2 Nov 2020 20:54:59 -0500 Subject: [PATCH 15/30] github actions workflow .NET 5 rc2 --- .github/workflows/Towel Continuous Integration.yml | 2 +- .github/workflows/Towel Deployment.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/Towel Continuous Integration.yml b/.github/workflows/Towel Continuous Integration.yml index c017c62e..1859c97f 100644 --- a/.github/workflows/Towel Continuous Integration.yml +++ b/.github/workflows/Towel Continuous Integration.yml @@ -22,7 +22,7 @@ jobs: - name: setup dotnet uses: actions/setup-dotnet@v1 with: - dotnet-version: 3.1.101 + dotnet-version: 5.0.100-rc.2.20479.15 - name: dotnet build run: dotnet build --configuration 'Release' - name: dotnet test diff --git a/.github/workflows/Towel Deployment.yml b/.github/workflows/Towel Deployment.yml index 764a94f7..23632290 100644 --- a/.github/workflows/Towel Deployment.yml +++ b/.github/workflows/Towel Deployment.yml @@ -10,7 +10,7 @@ jobs: - name: setup dotnet uses: actions/setup-dotnet@v1 with: - dotnet-version: 3.1.101 + dotnet-version: 5.0.100-rc.2.20479.15 - name: dotnet pack run: dotnet pack Sources/Towel/Towel.csproj --configuration Release /p:Version=${{ github.event.release.tag_name }} /p:PackageReleaseNotes="See https://github.com/ZacharyPatten/Towel/releases/tag/${{ github.event.release.tag_name }}" - name: archive nuget From 17688c227aa4aac9cf2fc2d7debe309266cd0be9 Mon Sep 17 00:00:00 2001 From: Zachary Patten Date: Mon, 2 Nov 2020 21:03:32 -0500 Subject: [PATCH 16/30] GetDirectoryPath (removed URI code) --- Sources/Towel/Meta.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Sources/Towel/Meta.cs b/Sources/Towel/Meta.cs index 71419b4f..12527df5 100644 --- a/Sources/Towel/Meta.cs +++ b/Sources/Towel/Meta.cs @@ -753,10 +753,7 @@ public static System.Collections.Generic.IEnumerable GetDerivedTypes /// The file path of the assembly. public static string? GetDirectoryPath(this Assembly assembly) { - string codeBase = assembly.Location; - UriBuilder uri = new UriBuilder(codeBase); - string assemblyPath = Uri.UnescapeDataString(uri.Path); - string? directoryPath = Path.GetDirectoryName(assemblyPath); + string? directoryPath = Path.GetDirectoryName(assembly.Location); return directoryPath == string.Empty ? null : directoryPath; } From 8dc63f3d937d0c604e2b4b758fe4e119ff4fdc4c Mon Sep 17 00:00:00 2001 From: Zachary Patten Date: Tue, 3 Nov 2020 00:17:12 -0500 Subject: [PATCH 17/30] Array.ForEach -> for loop (idk... i think for loop is more readable atm) --- Sources/Towel/Meta.cs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/Sources/Towel/Meta.cs b/Sources/Towel/Meta.cs index 12527df5..b1ec93fa 100644 --- a/Sources/Towel/Meta.cs +++ b/Sources/Towel/Meta.cs @@ -970,15 +970,22 @@ public static void ClearXmlDocumentation() LoadXmlDocumentation(methodBase.DeclaringType.Assembly); MapHashLinked typeGenericMap = new(); - int tempTypeGeneric = 0; - Array.ForEach(methodBase.DeclaringType.GetGenericArguments(), x => typeGenericMap[x.Name] = tempTypeGeneric++); + Type[] typeGenericArguments = methodBase.DeclaringType.GetGenericArguments(); + for (int i = 0; i < typeGenericArguments.Length; i++) + { + Type typeGeneric = typeGenericArguments[i]; + typeGenericMap[typeGeneric.Name] = i; + } MapHashLinked methodGenericMap = new(); - if (constructorInfo is null) { - int tempMethodGeneric = 0; - Array.ForEach(methodBase.GetGenericArguments(), x => methodGenericMap.Add(x.Name, tempMethodGeneric++)); + Type[] methodGenericArguments = methodBase.GetGenericArguments(); + for (int i = 0; i < methodGenericArguments.Length; i++) + { + Type methodGeneric = methodGenericArguments[i]; + methodGenericMap[methodGeneric.Name] = i; + } } ParameterInfo[] parameterInfos = methodBase.GetParameters(); From c40b6dd34e6b5440cda99f201ce020b6bb9880fa Mon Sep 17 00:00:00 2001 From: Zachary Patten Date: Tue, 3 Nov 2020 10:06:01 -0500 Subject: [PATCH 18/30] blah --- Sources/Towel/Extensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Towel/Extensions.cs b/Sources/Towel/Extensions.cs index d23d6447..88b6a073 100644 --- a/Sources/Towel/Extensions.cs +++ b/Sources/Towel/Extensions.cs @@ -106,7 +106,7 @@ public static bool ContainsAny(this string @string, params char[] chars) throw new InvalidOperationException("Attempting a contains check with an empty set."); } - ISet set = new SetHashLinked(); + SetHashLinked set = new SetHashLinked(); foreach (char c in chars) { set.Add(c); From 9b0bff1ad56ba845a672a782d80459588ff5cf24 Mon Sep 17 00:00:00 2001 From: Zachary Patten Date: Fri, 6 Nov 2020 10:37:42 -0500 Subject: [PATCH 19/30] omnitree --- .vscode/tasks.json | 14 + Tools/Towel_Generating/Omnitree.cs | 4669 +---------------- .../Towel_Generating/Towel_Generating.csproj | 2 +- 3 files changed, 195 insertions(+), 4490 deletions(-) diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 29997c66..784c3146 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -366,5 +366,19 @@ ], "problemMatcher": "$msCompile" }, + { + "label": "dotnet run Towel_Generating", + "command": "dotnet", + "type": "process", + "args": + [ + "run", + "--configuration", "Release", + "${workspaceFolder}/Tools/Towel_Generating/Towel_Generating.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary", + ], + "problemMatcher": "$msCompile" + }, ] } diff --git a/Tools/Towel_Generating/Omnitree.cs b/Tools/Towel_Generating/Omnitree.cs index 7a0ff00a..55d2e8f4 100644 --- a/Tools/Towel_Generating/Omnitree.cs +++ b/Tools/Towel_Generating/Omnitree.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Runtime.CompilerServices; using System.Text; using Towel; using static Towel.Statics; @@ -12,7 +11,7 @@ namespace Towel_Generating internal static class Omnitree { internal static void Generate( - int dimensions = 10) + int dimensions = 7) { StringBuilder file = new StringBuilder(); file.AppendLine($@"//------------------------------------------------------------------------------"); @@ -23,9 +22,10 @@ internal static void Generate( file.AppendLine($@""); file.AppendLine($@"using System;"); file.AppendLine($@"using System.Numerics;"); - file.AppendLine($@"using static Towel.Syntax;"); + file.AppendLine($@"using static Towel.Statics;"); file.AppendLine($@"using static Towel.DataStructures.Omnitree;"); - file.AppendLine($@"namespace Towel_Generating.DataStructures"); + file.AppendLine($@""); + file.AppendLine($@"namespace Towel.DataStructures.TEMP"); file.AppendLine($@"{{"); file.AppendLine($@" #region Notes"); file.AppendLine($@""); @@ -79,4502 +79,193 @@ internal static void Generate( file.AppendLine($@""); file.AppendLine($@" #endregion Notes"); file.AppendLine($@""); - + file.AppendLine($@" /// Contains the necessary type definitions for the various omnitree types."); + file.AppendLine($@" public static partial class Omnitree"); + file.AppendLine($@" {{"); for (int i = 1; i <= dimensions; i++) { - void AppendLines(Func func) - { - for (int j = 1; j <= i; j++) - { - file.AppendLine(); - } - } - - #region Partials - - Dictionary ___ = new Dictionary(); - - IEnumerable ie = Enumerable.Range(1, i); - - #region A1... - - ___["A1..."] = string.Join(", ", ie.Select(n => $"A{n}")); - - #endregion - - #region Hidden - - #region A1 axis1... - - ___["A1 axis1..."] = string.Join(", ", ie.Select(n => $"A{n} axis{n}")); - - #endregion - - #region default(A1)... - - ___["default(A1)..."] = string.Join(", ", ie.Select(n => $"default(A{n})")); - - #endregion - - #region this.Axis1 = axis1;... - - ___["this.Axis1 = axis1;..."] = string.Join(@" - ", ie.Select(n => $"this.Axis{n} = axis{n};")); - - #endregion - - #region /// The generic type of the 1 dimension.... - - ___[@"/// The generic type of the 1 dimension...."] = - string.Join(@" - ", ie.Select(n => $@"/// The generic type of the {n} dimension....")); - - #endregion - - #region /// The location along axis 1.... - - ___[@"/// The location along axis 1...."] = - string.Join(@" - ", ie.Select(n => $@"/// The location along axis {n}.")); - - #endregion - - // /// The value along axis 1. - // public A1 Axis1;... - #region - - ___[$@"/// The value along axis 1. - public A1 Axis1;..."] = - string.Join(@" - ", ie.Select(n => $@"/// The value along axis {n}. - public A{n} Axis{n};")); - - #endregion - - #region this.Axis1 = axis1;... - - ___[$@"this.Axis1 = axis1;..."] = - string.Join(@" - ", ie.Select(n => $@"this.Axis{n} = axis{n};")); - - #endregion - - // /// The minimum value along the 1 dimension. - // public Bound Min1; - // /// The maximum value along the 1 dimension. - // public Bound Max1;... - #region - - ___[ -$@"/// The minimum value along the 1 dimension. - public Bound Min1; - /// The maximum value along the 1 dimension. - public Bound Max1;..."] = - string.Join($@" - - ", ie.Select(n => - $@"/// The minimum value along the {n} dimension. - public Bound Min{n}; - /// The maximum value along the {n} dimension. - public Bound Max{n};")); - - #endregion - - #region Bound.None, Bound.None... - - ___["Bound.None, Bound.None..."] = string.Join(@", - ", ie.Select(n => $"Bound.None, Bound.None")); - - #endregion - - #region Bound min1, Bound max1... - - ___["Bound min1, Bound max1..."] = string.Join(@", - ", ie.Select(n => $"Bound min{n}, Bound max{n}")); - - #endregion - - #region out A1 min1, out A1 max1... - - ___["out A1 min1, out A1 max1..."] = string.Join(@", - ", ie.Select(n => $"out A{n} min{n}, out A{n} max{n}")); - - #endregion - - // this.Min{j} = min{j}; - // this.Max{ j} = max{ j}; - #region - - ___[ - @"this.Min1 = min1; - this.Max1 = max1;..."] = - string.Join($@" - - ", ie.Select(n => - $@"this.Min{n} = min{n}; - this.Max{n} = max{n};")); - - #endregion - - #region /// The generic type of the 1 dimension.... - - ___[@"/// The generic type of the 1 dimension...."] = - string.Join(@" - ", ie.Select(n => $@"/// The generic type of the {n} dimension.")); - - #endregion - - #region /// The location of the item along the 1 dimension.... - - ___[@"/// The location of the item along the 1 dimension...."] = - string.Join(@" - ", ie.Select(n => $@"/// The location of the item along the {n} dimension.")); - - #endregion - - #region out A1 axis1... - - ___["out A1 axis1..."] = string.Join(@", ", ie.Select(n => $@"out A{n} axis{n}")); - - #endregion - - #region /// The minimum bound of the item along the 1 dimension. - - ___[@"/// The minimum bound of the item along the 1 dimension...."] = - string.Join(@" - ", ie.Select(n => $@"/// The minimum bound of the item along the {n} dimension.")); - - #endregion - - #region /// "">The maximum bound of the item along the <#= j #> dimension. - - ___[@"/// The maximum bound of the item along the 1 dimension...."] = - string.Join(@" - ", ie.Select(n => $@"/// The maximum bound of the item along the {n} dimension.")); - - #endregion - - #region out Bound min1, out Bound max1... - - ___["out Bound min1, out Bound max1..."] = string.Join(@", ", ie.Select(n => $@"out Bound min{n}, out Bound max{n}")); - - #endregion - - #region out A1 min1a, out A1 max1a... - - ___["out A1 min1a, out A1 max1a..."] = string.Join(@", - ", ie.Select(n => $"out A{n} min{n}a, out A{n} max{n}a")); - - #endregion - - #region A1 min1; A1 max1;... - - ___["A1 min1; A1 max1;..."] = string.Join(@" - ", ie.Select(n => $@"A{n} min{n}; A{n} max{n};")); - - #endregion - - #region minBound1 = min1; maxBound1 = max1;... - - ___["min1 = min1a; max1 = max1a;..."] = string.Join(@" - ", ie.Select(n => $@"min{n} = min{n}a; max{n} = max{n}a;")); - - #endregion - - //string __(string key) => partials[key]; - - #endregion - - #endregion - file.AppendLine($@" #region {i} Dimensional"); file.AppendLine($@""); file.AppendLine($@" /// Represents a {i}D vector."); - AppendLines(n => $@" /// The generic type of the {n} dimension...."); + for (int j = 1; j <= i; j++) + { + file.AppendLine($@" /// The generic type of the {j} dimension."); + } file.AppendLine($@" public struct Vector<{Join(1..(i + 1), n => $"A{n}", ", ")}>"); file.AppendLine($@" {{"); - - + for (int j = 1; j <= i; j++) + { + file.AppendLine($@" /// The value along axis {j}."); + file.AppendLine($@" public A{j} Axis{j};"); + } + file.AppendLine($@""); + file.AppendLine($@" /// Returns a vector with defaulted values."); + file.AppendLine($@" public static Vector<{Join(1..(i + 1), n => $"A{n}", ", ")}> Default =>"); + file.AppendLine($@" new Vector<{Join(1..(i + 1), n => $"A{n}", ", ")}>("); + file.AppendLine($@" {Join(1..(i + 1), n => $"default", ", ")});"); + file.AppendLine($@""); + file.AppendLine($@" /// A location along each axis."); + for (int j = 1; j <= i; j++) + { + file.AppendLine($@" /// The location along axis {j}."); + } + file.AppendLine($@" public Vector({Join(1..(i + 1), n => $"A{n} axis{n}", ", ")})"); + file.AppendLine($@" {{"); + for (int j = 1; j <= i; j++) + { + file.AppendLine($@" this.Axis{j} = axis{j};"); + } + file.AppendLine($@" }}"); + file.AppendLine($@" }}"); + file.AppendLine($@""); + file.AppendLine($@" /// Represents a {i}D bounding box."); + for (int j = 1; j <= i; j++) + { + file.AppendLine($@" /// The generic type of the {j} dimension."); + } + file.AppendLine($@" public struct Bounds<{Join(1..(i + 1), n => $"A{n}", ", ")}>"); + file.AppendLine($@" {{"); + for (int j = 1; j <= i; j++) + { + file.AppendLine($@" /// The minimum value along the {j} dimension."); + file.AppendLine($@" public Bound Min{j};"); + file.AppendLine($@" /// The maximum value along the {j} dimension."); + file.AppendLine($@" public Bound Max{j};"); + } + file.AppendLine($@""); + file.AppendLine($@" /// Extends infinitely along each axis."); + file.AppendLine($@" public static Bounds<{Join(1..(i + 1), n => $"A{n}", ", ")}> None =>"); + file.AppendLine($@" new Bounds<{Join(1..(i + 1), n => $"A{n}", ", ")}>("); + file.AppendLine($@" {Join(1..(i + 1), n => $"Bound.None, Bound.None", ", ")});"); + file.AppendLine($@""); + file.AppendLine($@" /// A set of values denoting a range (or lack of range) along each axis."); + file.AppendLine($@" public Bounds({Join(1..(i + 1), n => $"Bound min{n}, Bound max{n}", ", ")})"); + file.AppendLine($@" {{"); + for (int j = 1; j <= i; j++) + { + file.AppendLine($@" this.Min{j} = min{j};"); + file.AppendLine($@" this.Max{j} = max{j};"); + } + file.AppendLine($@" }}"); file.AppendLine($@" }}"); + file.AppendLine($@""); + file.AppendLine($@" /// Checks a node for inclusion (overlap) between two bounds."); + file.AppendLine($@" /// True if the spaces overlap; False if not."); + file.AppendLine($@" public static bool InclusionCheck<{Join(1..(i + 1), n => $"A{n}", ", ")}, {Join(1..(i + 1), n => $"Compare{n}", ", ")}>("); + file.AppendLine($@" Omnitree.Bounds<{Join(1..(i + 1), n => $"A{n}", ", ")}> a, Omnitree.Bounds<{Join(1..(i + 1), n => $"A{n}", ", ")}> b, {Join(1..(i + 1), n => $"Compare{n} compare{n} = default", ", ")})"); + for (int j = 1; j <= i; j++) + { + file.AppendLine($@" where Compare{j} : struct, IFunc"); + } + file.AppendLine($@" =>"); + for (int j = 1; j <= i; j++) + { + file.AppendLine($@" a.Max{j}.Exists && b.Min{j}.Exists && compare{j}.Do(a.Max{j}.Value, b.Min{j}.Value) == CompareResult.Less ? false :"); + file.AppendLine($@" a.Min{j}.Exists && b.Max{j}.Exists && compare{j}.Do(a.Min{j}.Value, b.Max{j}.Value) == CompareResult.Greater ? false :"); + } + file.AppendLine($@" true;"); + file.AppendLine($@""); + file.AppendLine($@" public static bool EncapsulationCheck<{Join(1..(i + 1), n => $"A{n}", ", ")}, {Join(1..(i + 1), n => $"Compare{n}", ", ")}>("); + file.AppendLine($@" Omnitree.Bounds<{Join(1..(i + 1), n => $"A{n}", ", ")}> a, Omnitree.Bounds<{Join(1..(i + 1), n => $"A{n}", ", ")}> b, {Join(1..(i + 1), n => $"Compare{n} compare{n} = default", ", ")})"); + for (int j = 1; j <= i; j++) + { + file.AppendLine($@" where Compare{j} : struct, IFunc"); + } + file.AppendLine($@" =>"); + file.AppendLine($@" ("); + for (int j = 1; j <= i; j++) + { + file.AppendLine($@" (a.Min{j}.Exists && !b.Min{j}.Exists) {(j == i ? "" : "||")}"); + } + file.AppendLine($@" )"); + file.AppendLine($@" ? false :"); + file.AppendLine($@" ("); + for (int j = 1; j <= i; j++) + { + file.AppendLine($@" (a.Max{j}.Exists && !b.Max{j}.Exists) {(j == i ? "" : "||")}"); + } + file.AppendLine($@" )"); + file.AppendLine($@" ? false :"); + for (int j = 1; j <= i; j++) + { + file.AppendLine($@" b.Min{i}.Exists && a.Min{i}.Exists && compare{i}.Do(a.Min{i}.Value, b.Min{i}.Value) != CompareResult.Less ? false :"); + file.AppendLine($@" b.Max{i}.Exists && a.Max{i}.Exists && compare{i}.Do(a.Max{i}.Value, b.Max{i}.Value) != CompareResult.Greater ? false :"); + } + file.AppendLine($@" true;"); + file.AppendLine($@""); + file.AppendLine($@" public static bool EqualsCheck<{Join(1..(i + 1), n => $"A{n}", ", ")}, {Join(1..(i + 1), n => $"Compare{n}", ", ")}>("); + file.AppendLine($@" Omnitree.Vector<{Join(1..(i + 1), n => $"A{n}", ", ")}> a, Omnitree.Vector<{Join(1..(i + 1), n => $"A{n}", ", ")}> b, {Join(1..(i + 1), n => $"Compare{n} compare{n} = default", ", ")})"); + for (int j = 1; j <= i; j++) + { + file.AppendLine($@" where Compare{j} : struct, IFunc"); + } + file.AppendLine($@" =>"); + for (int j = 1; j <= i; j++) + { + file.AppendLine($@" compare{j}.Do(a.Axis{j}, b.Axis{j}) is Equal{(j == i ? "; " : " &&")}"); + } + file.AppendLine($@""); + file.AppendLine($@" /// Checks if a bounds straddles a point if the point extended as a plane along each dimension."); + file.AppendLine($@" /// The bounds to determine if it straddles the extended point."); + file.AppendLine($@" /// The point representing an extended plan along each axis."); + file.AppendLine($@" /// True if the extended point was straddled or false if not."); + for (int j = 1; j <= i; j++) + { + file.AppendLine($@" /// The generic type of the {j} dimension."); + file.AppendLine($@" /// The method for comparing elements along the {j} dimension."); + file.AppendLine($@" /// The method for comparing elements along the {j} dimension."); + } + file.AppendLine($@" public static bool StraddlesLines<{Join(1..(i + 1), n => $"A{n}", ", ")}, {Join(1..(i + 1), n => $"Compare{n}", ", ")}>("); + file.AppendLine($@" Omnitree.Bounds<{Join(1..(i + 1), n => $"A{n}", ", ")}> a, Omnitree.Vector<{Join(1..(i + 1), n => $"A{n}", ", ")}> b, {Join(1..(i + 1), n => $"Compare{n} compare{n} = default", ", ")})"); + for (int j = 1; j <= i; j++) + { + file.AppendLine($@" where Compare{j} : struct, IFunc"); + } + file.AppendLine($@" =>"); + for (int j = 1; j <= i; j++) + { + file.AppendLine($@" (!a.Min{j}.Exists || (a.Min{j}.Exists && compare{j}.Do(a.Min{j}.Value, b.Axis{j}) != Greater)) &&"); + file.AppendLine($@" (!a.Max{j}.Exists || (a.Max{j}.Exists && compare{j}.Do(a.Max{j}.Value, b.Axis{j}) != Less)) ? true :"); + } + file.AppendLine($@" false;"); + file.AppendLine($@""); + file.AppendLine($@" #endregion {i} Dimensional"); + file.AppendLine($@""); } + file.AppendLine($@" }}"); + file.AppendLine($@""); + for (int i = 1; i <= dimensions; i++) + { + file.AppendLine($@" #region {i} Dimensional"); + file.AppendLine($@""); + file.AppendLine($@" /// Inheritance base for {i}D omnitrees."); + file.AppendLine($@" /// The element type of the omnitree."); + for (int j = 1; j <= i; j++) + { + file.AppendLine($@" /// The type of the {j}D axis."); + } + file.AppendLine($@" public interface IOmnitree $"A{n}", ", ")}, {Join(1..(i + 1), n => $"Compare{n}", ", ")}> : IOmnitree {{ }}"); + file.AppendLine($@""); + file.AppendLine($@" #region OmnitreePoints"); + file.AppendLine($@""); + file.AppendLine($@" public interface IOmnitreePoints $"A{n}", ", ")}, {Join(1..(i + 1), n => $"Compare{n}", ", ")}> : IOmnitree $"A{n}", ", ")}, {Join(1..(i + 1), n => $"Compare{n}", ", ")}>"); + file.AppendLine($@" {{"); + file.AppendLine($@" // todo"); + file.AppendLine($@" }}"); + file.AppendLine($@""); + file.AppendLine($@" public interface OmnitreePoints $"A{n}", ", ")}, {Join(1..(i + 1), n => $"Compare{n}", ", ")}> : IOmnitree $"A{n}", ", ")}, {Join(1..(i + 1), n => $"Compare{n}", ", ")}>"); + file.AppendLine($@" {{"); + file.AppendLine($@" }}"); + file.AppendLine($@""); + file.AppendLine($@" #endregion OmnitreePoints"); + file.AppendLine($@""); + file.AppendLine($@" #endregion {i} Dimensional"); + file.AppendLine($@""); + } + file.AppendLine($@"}}"); -// for (int i = 1; i <= dimensions; i++) -// { -// #region partials - -// IEnumerable ie = Enumerable.Range(1, i); - -// #region A1... - -// partials["A1..."] = string.Join(", ", ie.Select(n => $"A{n}")); - -// #endregion - -// #region A1 axis1... - -// partials["A1 axis1..."] = string.Join(", ", ie.Select(n => $"A{n} axis{n}")); - -// #endregion - -// #region default(A1)... - -// partials["default(A1)..."] = string.Join(", ", ie.Select(n => $"default(A{n})")); - -// #endregion - -// #region this.Axis1 = axis1;... - -// partials["this.Axis1 = axis1;..."] = string.Join(@" -// ", ie.Select(n => $"this.Axis{n} = axis{n};")); - -// #endregion - -// #region /// The generic type of the 1 dimension.... - -// partials[@"/// The generic type of the 1 dimension...."] = -// string.Join(@" -// ", ie.Select(n => $@"/// The generic type of the {n} dimension....")); - -// #endregion - -// #region /// The location along axis 1.... - -// partials[@"/// The location along axis 1...."] = -// string.Join(@" -// ", ie.Select(n => $@"/// The location along axis {n}.")); - -// #endregion - -// // /// The value along axis 1. -// // public A1 Axis1;... -// #region - -// partials[$@"/// The value along axis 1. -// public A1 Axis1;..."] = -// string.Join(@" -// ", ie.Select(n => $@"/// The value along axis {n}. -// public A{n} Axis{n};")); - -// #endregion - -// #region this.Axis1 = axis1;... - -// partials[$@"this.Axis1 = axis1;..."] = -// string.Join(@" -// ", ie.Select(n => $@"this.Axis{n} = axis{n};")); - -// #endregion - -// // /// The minimum value along the 1 dimension. -// // public Bound Min1; -// // /// The maximum value along the 1 dimension. -// // public Bound Max1;... -// #region - -// partials[ -//$@"/// The minimum value along the 1 dimension. -// public Bound Min1; -// /// The maximum value along the 1 dimension. -// public Bound Max1;..."] = -// string.Join($@" - -// ", ie.Select(n => -// $@"/// The minimum value along the {n} dimension. -// public Bound Min{n}; -// /// The maximum value along the {n} dimension. -// public Bound Max{n};")); - -// #endregion - -// #region Bound.None, Bound.None... - -// partials["Bound.None, Bound.None..."] = string.Join(@", -// ", ie.Select(n => $"Bound.None, Bound.None")); - -// #endregion - -// #region Bound min1, Bound max1... - -// partials["Bound min1, Bound max1..."] = string.Join(@", -// ", ie.Select(n => $"Bound min{n}, Bound max{n}")); - -// #endregion - -// #region out A1 min1, out A1 max1... - -// partials["out A1 min1, out A1 max1..."] = string.Join(@", -// ", ie.Select(n => $"out A{n} min{n}, out A{n} max{n}")); - -// #endregion - -// // this.Min{j} = min{j}; -// // this.Max{ j} = max{ j}; -// #region - -// partials[ -// @"this.Min1 = min1; -// this.Max1 = max1;..."] = -// string.Join($@" - -// ", ie.Select(n => -// $@"this.Min{n} = min{n}; -// this.Max{n} = max{n};")); - -// #endregion - -// #region /// The generic type of the 1 dimension.... - -// partials[@"/// The generic type of the 1 dimension...."] = -// string.Join(@" -// ", ie.Select(n => $@"/// The generic type of the {n} dimension.")); - -// #endregion - -// #region /// The location of the item along the 1 dimension.... - -// partials[@"/// The location of the item along the 1 dimension...."] = -// string.Join(@" -// ", ie.Select(n => $@"/// The location of the item along the {n} dimension.")); - -// #endregion - -// #region out A1 axis1... - -// partials["out A1 axis1..."] = string.Join(@", ", ie.Select(n => $@"out A{n} axis{n}")); - -// #endregion - -// #region /// The minimum bound of the item along the 1 dimension. - -// partials[@"/// The minimum bound of the item along the 1 dimension...."] = -// string.Join(@" -// ", ie.Select(n => $@"/// The minimum bound of the item along the {n} dimension.")); - -// #endregion - -// #region /// "">The maximum bound of the item along the <#= j #> dimension. - -// partials[@"/// The maximum bound of the item along the 1 dimension...."] = -// string.Join(@" -// ", ie.Select(n => $@"/// The maximum bound of the item along the {n} dimension.")); - -// #endregion - -// #region out Bound min1, out Bound max1... - -// partials["out Bound min1, out Bound max1..."] = string.Join(@", ", ie.Select(n => $@"out Bound min{n}, out Bound max{n}")); - -// #endregion - -// #region out A1 min1a, out A1 max1a... - -// partials["out A1 min1a, out A1 max1a..."] = string.Join(@", -// ", ie.Select(n => $"out A{n} min{n}a, out A{n} max{n}a")); - -// #endregion - -// #region A1 min1; A1 max1;... - -// partials["A1 min1; A1 max1;..."] = string.Join(@" -// ", ie.Select(n => $@"A{n} min{n}; A{n} max{n};")); - -// #endregion - -// #region minBound1 = min1; maxBound1 = max1;... - -// partials["min1 = min1a; max1 = max1a;..."] = string.Join(@" -// ", ie.Select(n => $@"min{n} = min{n}a; max{n} = max{n}a;")); - -// #endregion - -// string __(string key) => partials[key]; - -// #endregion - - -// file.AppendLine( -//$@" #region {i} Dimensional - -// /// Represents a {i}D vector. -// {__(@"/// The generic type of the 1 dimension....")} -// public struct Vector<{__("A1...")}> -// {{ -// {__(@"/// The value along axis 1. -// public A1 Axis1;...")} - -// /// Returns a vector with defaulted values. -// public static Vector<{__("A1...")}> Default => -// new Vector<{__("A1...")}>({__("default(A1)...")}); - -// /// A location along each axis. -// {__(@"/// The location along axis 1....")} -// public Vector({__("A1 axis1...")}) -// {{ -// {__("this.Axis1 = axis1;...")} -// }} -// }} - -// /// Represents a {i}D bounding box. -// {__(@"/// The generic type of the 1 dimension....")} -// public struct Bounds<{__("A1...")}> -// {{ -// {__($@"/// The minimum value along the 1 dimension. -// public Bound Min1; -// /// The maximum value along the 1 dimension. -// public Bound Max1;...")} - -// /// Extends infinitely along each axis. -// public static Bounds<{__("A1...")}> None => -// new Bounds<{__("A1...")}>( -// {__("Bound.None, Bound.None...")}); - -// /// A set of values denoting a range (or lack of range) along each axis. -// public Bounds( -// {__("Bound min1, Bound max1...")}) -// {{ -// {__(@"this.Min1 = min1; -// this.Max1 = max1;...")} -// }} -// }} - -// /// Delegate for locating an item in {i}D space. -// /// The generic type of the item to locate. -// {__(@"/// The generic type of the 1 dimension....")} -// /// The item to locate. -// {__(@"/// The location of the item along the 1 dimension....")} -// public delegate void Location(T item, {__("out A1 axis1...")}); - -// /// Delegate for getting the {i}D bounding box of an item. -// /// The generic type of the item to get the bounding box of. -// {__(@"/// The generic type of the 1 dimension....")} -// /// The item to get the bounding box of. -// {__(@"/// The minimum bound of the item along the 1 dimension....")} -// {__(@"/// The maximum bound of the item along the 1 dimension....")} -// public delegate void GetBounds (T item, {__("out Bound min1, out Bound max1...")}); - -// /// Delegate for getting the {i}D bounding box of an item. -// /// The generic type of the item to get the bounding box of. -// {__(@"/// The generic type of the 1 dimension....")} -// /// The item to get the bounding box of. -// {__(@"/// The minimum bound of the item along the 1 dimension....")} -// {__(@"/// The maximum bound of the item along the 1 dimension....")} -// public delegate void GetBoundings( -// T item, -// {__("out A1 min1, out A1 max1...")}); - -// /// Converts an Omnitree.GetBoundings delegate into an Omnitree.GetBounds delegate. -// /// The generic type to get the bounds of. -// {__(@"/// The generic type of the 1 dimension....")} -// /// The Omnitree.GetBoundings to convert into a Omnitree.GetBounds. -// /// The converted Omnitree.GetBounds delegate. -// public static GetBounds ConvertToGetBounds(GetBoundings getBoundings) => -// (T item, {__("out Bound min1, out Bound max1...")}) => -// {{ -// getBoundings(item, -// {__("out A1 min1a, out A1 max1a...")}); -// {__("min1 = min1a; max1 = max1a;...")} -// }}; - - -//"); - - - -// #region HIDE - -// // End Dimension -// file.AppendLine( -//$@" #endregion {i} Dimensional -//"); -// } -// file.AppendLine($@" -// #endregion Spacial Types (Bound, Vector, Bounds), Location/Bounding Delegates, And Dimensional Helper Methods - -// }} -//}}"); - -// #endregion - - - ///// Checks a node for inclusion (overlap) between two bounds. - ///// True if the spaces overlap; False if not. - //public static bool InclusionCheck<<#= chain_AxisX #>>(Omnitree.Bounds<<#= chain_AxisX #>> a, Omnitree.Bounds<<#= chain_AxisX #>> b, - // <#= chain_Compare_AxisX_compareX #>) => - //<# for (int j = 1; j <= i; j++) { #> - // a.Max <#= j #>.Exists && b.Min<#= j #>.Exists && compare<#= j #>(a.Max<#= j #>.Value, b.Min<#= j #>.Value) == CompareResult.Less ? false : - // a.Min <#= j #>.Exists && b.Max<#= j #>.Exists && compare<#= j #>(a.Min<#= j #>.Value, b.Max<#= j #>.Value) == CompareResult.Greater ? false : - //<# } #> - // true; - - ///// Checks if a space encapsulates a point. - ///// True if the space encapsulates the point; False if not. - //public static bool EncapsulationCheck<<#= chain_AxisX #>>(Omnitree.Bounds<<#= chain_AxisX #>> bounds, Omnitree.Vector<<#= chain_AxisX #>> vector, - // <#= chain_Compare_AxisX_compareX #>) => - // // if the location is not outside the bounds, it must be inside - //<# for (int j = 1; j <= i; j++) { #> - // bounds.Min <#= j #>.Exists && compare<#= j #>(vector.Axis<#= j #>, bounds.Min<#= j #>.Value) == CompareResult.Less ? false : - // bounds.Max <#= j #>.Exists && compare<#= j #>(vector.Axis<#= j #>, bounds.Max<#= j #>.Value) == CompareResult.Greater ? false : - //<# } #> - // true; - - ///// Checks if a space (left) encapsulates another space (right). - ///// True if the left space encapsulates the right; False if not. - //public static bool EncapsulationCheck<<#= chain_AxisX #>>(Omnitree.Bounds<<#= chain_AxisX #>> a, Omnitree.Bounds<<#= chain_AxisX #>> b, - // <#= chain_Compare_AxisX_compareX #>) => - // (a.Min1.Exists && !b.Min1.Exists) - //<# for (int j = 2; j <= i; j++) { #> - // || (a.Min <#= j #>.Exists && !b.Min<#= j #>.Exists) - //<# } #> - // ? false : - // (a.Max1.Exists && !b.Max1.Exists) - //<# for (int j = 2; j <= i; j++) { #> - // || (a.Max <#= j #>.Exists && !b.Max<#= j #>.Exists) - //<# } #> - // ? false : - //<# for (int j = 1; j <= i; j++) { #> - // b.Min <#= j #>.Exists && a.Min<#= j #>.Exists && compare<#= j #>(a.Min<#= j #>.Value, b.Min<#= j #>.Value) != CompareResult.Less ? false : - // b.Max <#= j #>.Exists && a.Max<#= j #>.Exists && compare<#= j #>(a.Max<#= j #>.Value, b.Max<#= j #>.Value) != CompareResult.Greater ? false : - //<# } #> - // true; - - ///// Checks for equality between two locations. - ///// True if equal; False if not; - //public static bool EqualsCheck<<#= chain_AxisX #>>(Omnitree.Vector<<#= chain_AxisX #>> a, Omnitree.Vector<<#= chain_AxisX #>> b, - // <#= chain_Equate_AxisX_equateX #>) => - //<# for (int j = 1; j <= i; j++) { #> - // !equate <#= j #>(a.Axis<#= j #>, b.Axis<#= j #>) ? false : - //<# } #> - // true; - - // /// Checks if a bounds straddles a point if the point extended as a plane along each dimension. - //<# for (int j = 1; j <= i; j++) { #> - // /// The generic type of the <#= j #> dimension. - //<# } #> - // /// The bounds to determine if it straddles the extended point. - // /// The point representing an extended plan along each axis. - //<# for (int j = 1; j <= i; j++) { #> - // /// The delegate for comparing values along the the <#= j #> dimension. - //<# } #> - // /// True if the extended point was straddled or false if not. - //public static bool StraddlesLines<<#= chain_AxisX #>>(Omnitree.Bounds<<#= chain_AxisX #>> bounds, Omnitree.Vector<<#= chain_AxisX #>> vector, - // <#= chain_Compare_AxisX_compareX #>) => - //<# for (int j = 1; j <= i; j++) { #> - // (!bounds.Min <#= j #>.Exists || (bounds.Min<#= j #>.Exists && compare<#= j #>(bounds.Min<#= j #>.Value, vector.Axis<#= j #>) != CompareResult.Greater)) && - // (!bounds.Max <#= j #>.Exists || (bounds.Max<#= j #>.Exists && compare<#= j #>(bounds.Max<#= j #>.Value, vector.Axis<#= j #>) != CompareResult.Less)) ? true : - //<# } #> - // false; - - // /// Removes all occurences of a value from the omnitree. - // /// The generic value type being stored in the omnitree. - //<# for (int j = 1; j <= i; j++) { #> - // /// The geneic type of the <#= j #>D axis. - //<# } #> - // /// The omnitree to remove from. - // /// The value to have all occurences removed. - //public static void Remove>(this IOmnitreePoints> omnitree, T removal) => Remove(omnitree, removal, Equate.Default); - - // /// Removes all occurences of a value from the omnitree. - // /// The generic value type being stored in the omnitree. - //<# for (int j = 1; j <= i; j++) { #> - // /// The geneic type of the <#= j #>D axis. - //<# } #> - // /// The omnitree to remove from. - // /// The value to have all occurences removed. - // /// The delegate for checking for equality. - //public static void Remove>(this IOmnitreePoints> omnitree, T removal, Func equate) - // { - //<# for (int j = 1; j <= i; j++) { #> - // Axis<#= j #> axis<#= j #>; - //<# } #> - // omnitree.Locate(removal, out axis1 - //<# for (int j = 2; j <= i; j++) { #> - // , out axis<#= j #> - //<# } #> - // ); - // omnitree.Remove( - //<# for (int j = 1; j <= i; j++) { #> - // axis<#= j #>, - //<# } #> - // x => equate(x, removal)); - //} - - // /// Removes all occurences of a value from the omnitree. - // /// The generic value type being stored in the omnitree. - //<# for (int j = 1; j <= i; j++) { #> - // /// The geneic type of the <#= j #>D axis. - //<# } #> - // /// The omnitree to remove from. - // /// The value to have all occurences removed. - //public static void Remove>(this IOmnitreeBounds> omnitree, T removal) => Remove(omnitree, removal, Equate.Default); - - // /// Removes all occurences of a value from the omnitree. - // /// The generic value type being stored in the omnitree. - //<# for (int j = 1; j <= i; j++) { #> - // /// The geneic type of the <#= j #>D axis. - //<# } #> - // /// The omnitree to remove from. - // /// The value to have all occurences removed. - // /// The delegate for checking for equality. - //public static void Remove>(this IOmnitreeBounds> omnitree,T removal, Func equate) - // { - //<# for (int j = 1; j <= i; j++) { #> - // Omnitree.Bound> min<#= j #>; Omnitree.Bound> max<#= j #>; - //<# } #> - // omnitree.GetBounds(removal, out min1, out max1 - //<# for (int j = 2; j <= i; j++) { #> - // , out min<#= j #>, out max<#= j #> - //<# } #> - // ); - // omnitree.RemoveOverlapped(min1, max1 - //<# for (int j = 2; j <= i; j++) { #> - // , min<#= j #>, max<#= j #> - //<# } #> - // , x => equate(x, removal)); - //} - - // #endregion - //<# } #> - - // #endregion - // } - - // #region Omnitree - //<# foreach (int i in dimensionsToGenerate) { - //// ------------------------------------------------------------------------------------------------------------------------------ - //// PARAMETER/ARGUMENT CHAINS - //string chain_AxisX = "Axis1"; for (int j = 2; j <= i; j++) { chain_AxisX += ", Axis" + j; } - //string chain_axisX = "axis1"; for (int j = 2; j <= i; j++) { chain_axisX += ", axis" + j; } - //string chain_AxisX_axisX = "Axis1 axis1"; for (int j = 2; j <= i; j++) { chain_AxisX_axisX += ", Axis" + j + " axis" + j; } - //string chain_AxisX_minX_AxisX_maxX = "Axis1 min1, Axis1 max1"; for (int j = 2; j <= i; j++) { chain_AxisX_minX_AxisX_maxX += ", Axis" + j + " min" + j + ", Axis" + j + " max" + j; } - //string chain_BoundAxisX_minX_BoundAxisX_maxX = "Omnitree.Bound min1, Omnitree.Bound max1"; for (int j = 2; j <= i; j++) { chain_BoundAxisX_minX_BoundAxisX_maxX += ", Omnitree.Bound min" + j + ", Omnitree.Bound max" + j; } - //string chain_BoundAxisX_axisX = "Omnitree.Bound axis1"; for (int j = 2; j <= i; j++) { chain_BoundAxisX_axisX += ", Omnitree.Bound axis" + j; } - //string chain_minX_maxX = "min1, max1"; for (int j = 2; j <= i; j++) { chain_minX_maxX += ", min" + j + ", max" + j; } - //string chain_axisX_axisX = "axis1, axis1"; for (int j = 2; j <= i; j++) { chain_axisX_axisX += ", axis" + j + ", axis" + j; } - ////string child_index_type; if (i <= 30) { child_index_type = "int"; } else if (i <= 60) { child_index_type = "long"; } else { child_index_type = "BigInteger"; } - //// DOCUMENTATION - //string documentation_AxisX_axisX = string.Empty; for (int j = 1; j <= i; j++) { documentation_AxisX_axisX += "\n\t\t/// The coordinate along the " + j + "D axis."; } - //documentation_AxisX_axisX = documentation_AxisX_axisX.Trim(); - //string documentation_AxisX_minX_AxisX_maxX = string.Empty; for (int j = 1; j <= i; j++) { documentation_AxisX_minX_AxisX_maxX += "\n\t\t/// The minimum coordinate of the space along the " + j + " axis.\n\t\t/// The maximum coordinate of the space along the " + j + " axis."; } - //documentation_AxisX_minX_AxisX_maxX = documentation_AxisX_minX_AxisX_maxX.Trim(); - //string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { documentation_axisX += "\n\t\t/// The axis of the removal along the " + j + "D axis."; } - //documentation_axisX = documentation_axisX.Trim(); - //// ------------------------------------------------------------------------------------------------------------------------------ #> - - //#region <#= i #> Dimensional - - ///// Inheritance base for <#= i #>D omnitrees. - ///// The type of items to store in the omnitree. - //<# for (int j = 1; j <= i; j++) { #> - // /// The type <#= j #>D axis. - //<# } #> - // public interface IOmnitree> : IOmnitree { } - - // #endregion - //<# } #> - - // #endregion - - // #region OmnitreePoints - //<# foreach (int i in dimensionsToGenerate) - //{ - // // ------------------------------------------------------------------------------------------------------------------------------ - // // PARAMETER/ARGUMENT CHAINS - // string chain_AxisX = "Axis1"; for (int j = 2; j <= i; j++) { chain_AxisX += ", Axis" + j; } - //string chain_axisX = "axis1"; for (int j = 2; j <= i; j++) { chain_axisX += ", axis" + j; } - //string chain_AxisX_axisX = "Axis1 axis1"; for (int j = 2; j <= i; j++) { chain_AxisX_axisX += ", Axis" + j + " axis" + j; } - //string chain_AxisX_minX_AxisX_maxX = "Axis1 min1, Axis1 max1"; for (int j = 2; j <= i; j++) { chain_AxisX_minX_AxisX_maxX += ", Axis" + j + " min" + j + ", Axis" + j + " max" + j; } - //string chain_BoundAxisX_minX_BoundAxisX_maxX = "Omnitree.Bound min1, Omnitree.Bound max1"; for (int j = 2; j <= i; j++) { chain_BoundAxisX_minX_BoundAxisX_maxX += ", Omnitree.Bound min" + j + ", Omnitree.Bound max" + j; } - //string chain_BoundAxisX_axisX = "Omnitree.Bound axis1"; for (int j = 2; j <= i; j++) { chain_BoundAxisX_axisX += ", Omnitree.Bound axis" + j; } - //string chain_minX_maxX = "min1, max1"; for (int j = 2; j <= i; j++) { chain_minX_maxX += ", min" + j + ", max" + j; } - //string chain_axisX_axisX = "axis1, axis1"; for (int j = 2; j <= i; j++) { chain_axisX_axisX += ", axis" + j + ", axis" + j; } - //string child_index_type; if (i <= 30) { child_index_type = "int"; } else if (i <= 60) { child_index_type = "long"; } else { child_index_type = "BigInteger"; } - //// DOCUMENTATION - //string documentation_AxisX_axisX = string.Empty; for (int j = 1; j <= i; j++) { documentation_AxisX_axisX += "\n\t\t/// The coordinate along the " + j + "D axis."; } - //documentation_AxisX_axisX = documentation_AxisX_axisX.Trim(); - //string documentation_AxisX_minX_AxisX_maxX = string.Empty; for (int j = 1; j <= i; j++) { documentation_AxisX_minX_AxisX_maxX += "\n\t\t/// The minimum coordinate of the space along the " + j + " axis.\n\t\t/// The maximum coordinate of the space along the " + j + " axis."; } - //documentation_AxisX_minX_AxisX_maxX = documentation_AxisX_minX_AxisX_maxX.Trim(); - //string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { documentation_axisX += "\n\t\t/// The axis of the removal along the " + j + "D axis."; } - //documentation_axisX = documentation_axisX.Trim(); - //// ------------------------------------------------------------------------------------------------------------------------------ #> - - //#region <#= i #> Dimensional - - ///// Inheritance base for <#= i #>D omnitrees that store points. - ///// The type of items to store in the omnitree. - //<# for (int j = 1; j <= i; j++) { #> - // /// The type <#= j #>D axis. - //<# } #> - // public interface IOmnitreePoints> : IOmnitree> - // { - // #region Properties - - // /// Steps through the values at a given location. - // <#= documentation_AxisX_axisX #> - - // /// A Stepper of the items at the given coordinates. - // Action> this[<#= chain_AxisX_axisX #>] { get; } - - // /// The number of dimensions in this tree. - // int Dimensions { get; } - - // /// The delegate being used by the omnitree to locate items in <#= i #>D space. - // Omnitree.Location - // , Axis<#= j #> - //<# } #> - // > Locate { get; } - - // #endregion - - //#region Methods - - // /// Counts the number of items in a sub space. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // /// The number of items in the provided sub space. - // int CountSubSpace(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>); - - // /// Iterates through the entire tree and ensures each item is in the proper leaf. - // void Update(); - // /// Iterates through the provided dimensions and ensures each item is in the proper leaf. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // void Update(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>); - - // /// Removes all the items in a given space. - // <#= documentation_AxisX_axisX #> - // void Remove(<#= chain_AxisX_axisX #>); - // /// Removes all the items in a given space. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // void Remove(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>); - // /// Removes all the items in a given space where equality is met. - // <#= documentation_AxisX_axisX #> - // /// The equality constraint of the removal. - // void Remove(<#= chain_AxisX_axisX #>, Predicate where); - // /// Removes all the items in a given space where predicate is met. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // /// The predicate constraint of the removal. - // void Remove(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>, Predicate where); - - // /// Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions. - // /// The step function to perform on all items in the tree within the given bounds. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // void Stepper(Step < T > step, <#= chain_BoundAxisX_minX_BoundAxisX_maxX #>); - // /// Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions. - // /// The step function to perform on all items in the tree within the given bounds. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // StepStatus Stepper(StepBreak < T > step, <#= chain_BoundAxisX_minX_BoundAxisX_maxX #>); - // /// Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions. - // /// The step function to perform on all items in the tree within the given bounds. - // <#= documentation_AxisX_axisX #> - // void Stepper(Step < T > step, <#= chain_AxisX_axisX #>); - // /// Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions. - // /// The step function to perform on all items in the tree within the given bounds. - // <#= documentation_AxisX_axisX #> - // StepStatus Stepper(StepBreak < T > step, <#= chain_AxisX_axisX #>); - - // #endregion - // } - - // /// Omnitree that stores points along <#= i #> dimensions implemented as a linked tree. - // /// The type of items to store in the omnitree. - //<# for (int j = 1; j <= i; j++) { #> - // /// The type <#= j #>D axis. - //<# } #> - // public class OmnitreePointsLinked> : IOmnitreePoints> - // { - // internal const int _dimensions = <#= i #>; - // internal static <#= child_index_type #> _children_per_node = (<#= child_index_type #>)BigInteger.Pow(2, <#= i #>); - - // internal Node _top; - // internal int _naturalLogLower = 1; // caching the next time to calculate loads (lower count) - // internal int _naturalLogUpper = -1; // caching the next time to calculate loads (upper count) - // internal int _load; // ln(count); min = _defaultLoad - // internal Omnitree.Location - // , Axis<#= j #> - //<# } #> - // > _locate; - //<# for (int j = 1; j <= i; j++) { #> - // internal bool _defaultCompare<#= j #>; - // internal Compare> _compare<#= j #>; - //<# } #> - //<# for (int j = 1; j <= i; j++) { #> - // internal Omnitree.SubdivisionOverride, Omnitree.Bounds<<#= chain_AxisX #>>> _subdivisionOverride<#= j #>; - //<# } #> - - // #region Nested Types - - // /// Can be a leaf or a branch. - // internal abstract class Node - // { - // internal Omnitree.Bounds<<#= chain_AxisX #>> Bounds; - // internal Branch Parent; - // internal <#= child_index_type #> Index; - // internal int Count; - - // /// The depth this node is located in the Omnitree. - // internal int Depth - // { - // get - // { - // int depth = -1; - // for (Node node = this; !(node is null); node = node.Parent) - // depth++; - // return depth; - // } - // } - - // /// Constructs a node. - // /// The bounds of this node. - // /// The parent of this node. - // /// The number of elements stored in this node and its children. - // internal Node(Omnitree.Bounds<<#= chain_AxisX #>> bounds, Branch parent, <#= child_index_type #> index) - // { - // Bounds = bounds; - // Parent = parent; - // Index = index; - // } - - // internal Node(Node nodeToClone) - // { - // this.Bounds = nodeToClone.Bounds; - // this.Parent = nodeToClone.Parent; - // this.Index = nodeToClone.Index; - // this.Count = nodeToClone.Count; - // } - - // internal abstract Node Clone(); - // } - - // /// A branch in the tree. Only contains nodes. - // internal class Branch : Node - // { - // internal Node[] Children; - // internal Omnitree.Vector<<#= chain_AxisX #>> PointOfDivision; - - // /// Gets child by index. - // /// The index of the child to get. - // /// The child of the given index or null if non-existent. - // internal Node this[<#= child_index_type #> child_index] - // { - // get - // { - // if (Children is null) - // return null; - // if (Children.Length == OmnitreePointsLinked>._children_per_node) - // return Children[(int)child_index]; - // foreach (Node node in Children) - // if (node.Index == child_index) - // return node; - // return null; - // } - // set - // { - // // This error check should be unnecessary... but fuck it... might as well - // if (value.Index != child_index) - // throw new System.Exception("Bug in Omnitree (index/property mis-match when setting a child on a branch)"); - - // // no children yet - // if (Children is null) - // { - // Children = Ɐ(value); - // return; - // } - // // max children overwrite - //else if (this.Children.Length == OmnitreePointsLinked < T, <#= chain_AxisX #>>._children_per_node) - // { - // Children[(int)child_index] = value; - // return; - //} - //// non-max child overwrite - //for (int i = 0; i < Children.Length; i++) - // if (Children[i].Index == child_index) - // { - // Children[i] = value; - // return; - // } - //// new child - //Node[] newArray = new Node[Children.Length + 1]; - //if (newArray.Length == OmnitreePointsLinked < T, <#= chain_AxisX #>>._children_per_node) - // { - // // new child resulting in a max children branch (sorting required) - // for (int i = 0; i < Children.Length; i++) - // { - // newArray[(int)Children[i].Index] = Children[i]; - // } - // newArray[(int)value.Index] = value; - //} - // else - //{ - // // new child resulting in a non-max children branch - // Array.Copy(Children, newArray, Children.Length); - // newArray[newArray.Length - 1] = value; - //} - //this.Children = newArray; - // } - // } - - // internal Branch(Omnitree.Vector<<#= chain_AxisX #>> pointOfDivision, Omnitree.Bounds<<#= chain_AxisX #>> bounds, Branch parent, <#= child_index_type #> index) - // : base(bounds, parent, index) - // { - // this.PointOfDivision = pointOfDivision; - //} - - //internal Branch(Branch branchToClone) : base(branchToClone) - // { - // Children = branchToClone.Children.Clone() as Node[]; - // PointOfDivision = branchToClone.PointOfDivision; - //} - - //internal override Node Clone() => - // new Branch(this); - // } - - // /// A branch in the tree. Only contains items. - // internal class Leaf : Node - //{ - // internal class Node - // { - // internal T Value; - // internal Leaf.Node Next; - - // internal Node(T value, Leaf.Node next) - // { - // Value = value; - // Next = next; - // } - // } - - // internal Leaf.Node Head; - - // internal Leaf(Omnitree.Bounds<<#= chain_AxisX #>> bounds, Branch parent, <#= child_index_type #> index) - // : base(bounds, parent, index) - // { } - - // internal Leaf(Leaf leaf) : base(leaf) - // { - // Head = new Node(leaf.Head.Value, null); - // Node a = Head; - // Node b = leaf.Head; - // while (!(b is null)) - // { - // a.Next = new Node(b.Next.Value, null); - // a = a.Next; - // b = b.Next; - // } - // } - - // internal void Add(T addition) - // { - // Head = new Leaf.Node(addition, Head); - // this.Count++; - // } - - // internal override OmnitreePointsLinked>.Node Clone() => - // new Leaf(this); - //} - - //#endregion - - //#region Constructors - - ///// This constructor is for cloning purposes - //internal OmnitreePointsLinked(OmnitreePointsLinked> omnitree) - // { - // this._top = omnitree._top.Clone(); - //this._load = omnitree._load; - //this._locate = omnitree._locate; - //<# for (int j = 1; j <= i; j++) { #> - // this._defaultCompare <#= j #> = omnitree._defaultCompare<#= j #>; - // this._compare <#= j #> = omnitree._compare<#= j #>; - //<# } #> - //<# for (int j = 1; j <= i; j++) { #> - // this._subdivisionOverride <#= j #> = omnitree._subdivisionOverride<#= j #>; - //<# } #> - // } - - // internal OmnitreePointsLinked( - // Omnitree.Location> locate, - //<# for (int j = 1; j <= i; j++) { #> - // bool defaultCompare<#= j #>, - // Compare> compare<#= j #>, - //<# } #> - // Omnitree.SubdivisionOverride>> subdivisionOverride1 - //<# for (int j = 2; j <= i; j++) { #>, - // Omnitree.SubdivisionOverride, Omnitree.Bounds<<#= chain_AxisX #>>> subdivisionOverride<#= j #> - //<# } #> - // ) - //{ - // if (locate is null) - // { - // throw new ArgumentNullException(nameof(locate)); - // } - //<# for (int j = 1; j <= i; j++) { #> - // if (compare <#= j #> is null) - // { - // throw new ArgumentNullException(nameof(compare <#= j #>)); - // } - - //<# } #> - // this._locate = locate; - //<# for (int j = 1; j <= i; j++) { #> - // this._defaultCompare <#= j #> = defaultCompare<#= j #>; - // this._compare <#= j #> = compare<#= j #>; - //<# } #> - //<# for (int j = 1; j <= i; j++) { #> - // this._subdivisionOverride <#= j #> = subdivisionOverride<#= j #>; - //<# } #> - // this._top = new Leaf(Omnitree.Bounds <<#= chain_AxisX #>>.None, null, -1); - // Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load); - //} - - // /// Constructs a new <#= i #>D omnitree that stores points. - // /// The delegate for locating items in <#= i #>D space. - //<# for (int j = 1; j <= i; j++) { #> - - // /// The delegate for comparing values along the <#= j #>D axis. - //<# } #> - //<# for (int j = 1; j <= i; j++) { #> - - // /// The subdivision overide to be used when splitting the <#= j #> dimension. - //<# } #> - // public OmnitreePointsLinked( - // Omnitree.Location> locate, - //<# for (int j = 1; j <= i; j++) { #> - // Compare> compare<#= j #> = null, - //<# } #> - // Omnitree.SubdivisionOverride>> subdivisionOverride1 = null - //<# for (int j = 2; j <= i; j++) { #>, - // Omnitree.SubdivisionOverride, Omnitree.Bounds<<#= chain_AxisX #>>> subdivisionOverride<#= j #> = null - //<# } #> - // ) - // : this( - // locate, - //<# for (int j = 1; j <= i; j++) { #> - // compare <#= j #> is null ? true : false, - // compare <#= j #> ?? Compare.Default, - //<# } #> - // subdivisionOverride1 - //<# for (int j = 2; j <= i; j++) { #>, - // subdivisionOverride <#= j #> - //<# } #> - // ) { } - - // #endregion - - //#region Properties - - ///// Steps through all the items at a given coordinate. - //<# for (int j = 1; j <= i; j++) { #> - // /// The coordinate along axis <#= j #>. - //<# } #> - // /// The stepper for the items at the given coordinate. - //public Action> this[<#= chain_AxisX_axisX #>] => - // step => Stepper(step, <#= chain_axisX #>); - - // /// The number of dimensions in this tree. - //public int Dimensions { get { return _dimensions; } } - - ///// The location function the Omnitree is using. - //public Omnitree.Location> Locate { get { return this._locate; } } - - //<# for (int j = 1; j <= i; j++) { #> - // /// The comparison function the Omnitree is using along the <#= j #>D axis. - // public Compare> Compare<#= j #> { get { return this._compare<#= j #>; } } - //<# } #> - - // /// The current number of items in the tree. - // public int Count { get { return this._top.Count; } } - - //internal delegate void MaxDepthFinder(Node node, int current_depth, ref int max_depth); - ///// Finds the current maximum depth of the tree. NOT AN O(1) OPERATION. Intended for educational purposes only. - //public int MaxDepth - //{ - // get - // { - // MaxDepthFinder maxDepthFinder = null; - // maxDepthFinder = - // (Node node, int current_depth, ref int max_depth) => - // { - // if (current_depth > max_depth) - // max_depth = current_depth; - // if (node is Branch) - // foreach (Node child in (node as Branch).Children) - // maxDepthFinder(child, current_depth + 1, ref max_depth); - // }; - // int _max_depth = -1; - // maxDepthFinder(this._top, 0, ref _max_depth); - // return _max_depth; - // } - //} - - //internal delegate void NodeCountFinder(Node node, ref int current_count); - ///// Counts the current number of nodes in the tree. NOT AN O(1) OPERATION. Intended for educational purposes only. - //public int NodeCount - //{ - // get - // { - // NodeCountFinder nodeCountFinder = null; - // nodeCountFinder = - // (Node node, ref int current_count) => - // { - // current_count++; - // if (node is Branch) - // foreach (Node child in (node as Branch).Children) - // nodeCountFinder(child, ref current_count); - // }; - - // int _current_count = 0; - // nodeCountFinder(this._top, ref _current_count); - // return _current_count; - // } - //} - - //internal delegate void BranchCountFinder(Node node, ref int current_count); - ///// Counts the current number of branches in the tree. NOT AN O(1) OPERATION. Intended for educational purposes only. - //public int BranchCount - //{ - // get - // { - // BranchCountFinder branchCountFinder = null; - // branchCountFinder = - // (Node node, ref int current_count) => - // { - // if (node is Branch) - // { - // current_count++; - // foreach (Node child in (node as Branch).Children) - // branchCountFinder(child, ref current_count); - // } - // }; - - // int _current_count = 0; - // branchCountFinder(this._top, ref _current_count); - // return _current_count; - // } - //} - - //internal delegate void LeafCountFinder(Node node, ref int current_count); - ///// Counts the current number of leaves in the tree. NOT AN O(1) OPERATION. Intended for educational purposes only. - //public int LeafCount - //{ - // get - // { - // LeafCountFinder leafCountFinder = null; - // leafCountFinder = - // (Node node, ref int current_count) => - // { - // if (node is Leaf) - // current_count++; - // else - // foreach (Node child in (node as Branch).Children) - // leafCountFinder(child, ref current_count); - // }; - - // int _current_count = 0; - // leafCountFinder(this._top, ref _current_count); - // return _current_count; - // } - //} - - // #endregion - - //#region Methods - - //#region Add - - //< - //#if (false) { #> - //#region Bulk - - //// public void Add(ArrayJagged additions, bool allowMultithreading) - //// { - //// if (additions.Length > int.MaxValue) - //// throw new System.Exception("The maximum size of the Omnitree was exceeded during bulk addition."); - //// - //// if (this._top.Count != 0 || (int)additions.Length <= _load) - //// { - //// for (ulong i = 0; i < additions.Length; i++) - //// this.Add(additions[i]); - //// } - //// else - //// { - //// // adjust the loads prior to additions - //// Omnitree.ComputeLoads((int)additions.Length, ref _naturalLogLower, ref _naturalLogUpper, ref _load); - //// - //// Branch new_top = new Branch(Omnitree.Vector<<#= chain_AxisX #>>.Default, Omnitree.Bounds<<#= chain_AxisX #>>.None, null, -1); - //// new_top.Count = (int)additions.Length; - //// - //// - //<# for (int j = 1; j <= i; j++) { #> - //// // prepare data for median computations - //// ArrayJagged> values<#= j #>; - //// //IAsyncResult result<#= j #> = null; - //// if (!(this._subdivisionOverride<#= j #> is null)) - //// values<#= j #> = null; - //// else - //// { - //// values<#= j #> = null; - //// Action action = () => - //// { - //// values<#= j #> = new ArrayJagged>(additions.Length); - //// for (ulong i = 0; i < additions.Length; i++) - //// values<#= j #>[i] = LocateVector(additions[i]).Axis<#= j #>; - //// Towel.Algorithms.Sort.Merge(this._compare<#= j #>, (int i) => { return values<#= j #>[(ulong)i]; }, (int i, Axis<#= j #> value) => { values<#= j #>[(ulong)i] = value; }, 0, (int)(additions.Length - 1)); - //// }; - //// - //// if (allowMultithreading) - //// { - //// //result<#= j #> = ParallelThread.Run(operation); - //// throw new NotImplementedException(); - //// } - //// else - //// { - //// action(); - //// } - //// } - //// - //<# } #> - //// - //// - //<# for (int j = 1; j <= i; j++) { #> - //// //if (this._subdivisionOverride<#= j #> is null && allowMultithreading) - //// // result<#= j #>.AsyncWaitHandle.WaitOne(); - //// - //<# } #> - //// - //// // build the tree - //// Add(new_top, 1, -1, additions.ToStepper(), (int)additions.Length, - //<# for (int j = 1; j <= i; j++) { #>int.MinValue, - //<# } #>(int)additions.Length, - //<# for (int j = 1; j <= i; j++) { #>(int index) => { return values<#= j #>[index]; }, - //<# } #>allowMultithreading); - //// - //// this._top = new_top; - //// } - //// } - //// - //// public void Add(bool allowMultithreading, params T[] additions) - //// { - //// if (additions.Length > int.MaxValue) - //// throw new System.Exception("The maximum size of the Omnitree was exceeded during bulk addition."); - //// - //// if (this._top.Count != 0 || (int)additions.Length <= _load) - //// { - //// for (int i = 0; i < additions.Length; i++) - //// this.Add(additions[i]); - //// } - //// else - //// { - //// // adjust the loads prior to additions - //// Omnitree.ComputeLoads((int)additions.Length, ref _naturalLogLower, ref _naturalLogUpper, ref _load); - //// - //// Branch new_top = new Branch(Omnitree.Vector<<#= chain_AxisX #>>.Default, Omnitree.Bounds<<#= chain_AxisX #>>.None, null, -1); - //// new_top.Count = (int)additions.Length; - //// - //// - //<# for (int j = 1; j <= i; j++) { #> - //// // prepare data for median computations - //// ArrayJagged> values<#= j #>; - //// //IAsyncResult result<#= j #> = null; - //// if (!(this._subdivisionOverride<#= j #> is null)) - //// values<#= j #> = null; - //// else - //// { - //// values<#= j #> = null; - //// Action action = () => - //// { - //// values<#= j #> = new ArrayJagged>(additions.Length); - //// for (int i = 0; i < additions.Length; i++) - //// values<#= j #>[i] = LocateVector(additions[i]).Axis<#= j #>; - //// Towel.Algorithms.Sort.Merge(this._compare<#= j #>, (int i) => { return values<#= j #>[(ulong)i]; }, (int i, Axis<#= j #> value) => { values<#= j #>[(ulong)i] = value; }, 0, (int)(additions.Length - 1)); - //// }; - //// - //// if (allowMultithreading) - //// { - //// //result<#= j #> = ParallelThread.Run(operation); - //// throw new NotImplementedException(); - //// } - //// else - //// { - //// action(); - //// } - //// } - //// - //<# } #> - //// - //// - //<# for (int j = 1; j <= i; j++) { #> - //// //if (this._subdivisionOverride<#= j #> is null && allowMultithreading) - //// // result<#= j #>.AsyncWaitHandle.WaitOne(); - //// - //<# } #> - //// - //// // build the tree - //// Add(new_top, 1, -1, additions.ToStepper(), additions.Length, - //<# for (int j = 1; j <= i; j++) { #>int.MinValue, - //<# } #>(int)additions.Length, - //<# for (int j = 1; j <= i; j++) { #>(int index) => { return values<#= j #>[index]; }, - //<# } #>allowMultithreading); - //// - //// this._top = new_top; - //// } - //// } - //// - //// - //// internal int Add(Branch parent, int depth, <#= child_index_type #> child, Action> additions, int parent_count, - //<# for (int j = 1; j <= i; j++) { #>int prevmed<#= j #>, - //<# } #>int initial_count, - //<# for (int j = 1; j <= i; j++) { #>GetIndex> values<#= j #>, - //<# } #>bool allowMultithreading) - //// { - //<# for (int j = 1; j <= i; j++) { #> - //// Axis<#= j #> pointOfDivision<#= j #>; - //<# } #> - //// - //<# for (int j = 1; j <= i; j++) { #> - //// int median_axis<#= j #> = -1; - //<# } #> - //// if (this._subdivisionOverride1 is null - //<# for (int j = 2; j <= i; j++) { #> || this._subdivisionOverride<#= j #> is null - //<# } #>) - //// GetMedianIndexes(initial_count, child, depth, - //<# for (int j = 1; j <= i; j++) { #>prevmed<#= j #>, - //<# } #>out median_axis1 - //<# for (int j = 2; j <= i; j++) { #>, out median_axis<#= j #> - //<# } #>); - //// - //<# for (int j = 1; j <= i; j++) { #> - //// if (!(this._subdivisionOverride<#= j #> is null)) - //// pointOfDivision<#= j #> = this._subdivisionOverride<#= j #>(parent.Bounds, additions); - //// else - //// pointOfDivision<#= j #> = values<#= j #>(median_axis<#= j #>); - //// - //<# } #> - //// parent.PointOfDivision = new Omnitree.Vector<<#= chain_AxisX #>>(pointOfDivision1 - //<# for (int j = 2; j <= i; j++) { #>, pointOfDivision<#= j #> - //<# } #>); - //// - //// // divide the values along the medians - //// IMap, <#= child_index_type #>> collection_map = new MapHashLinked, <#= child_index_type #>>(); - //// additions((T value) => - //// { - //// <#= child_index_type #> index = DetermineChildIndex(parent.PointOfDivision, LocateVector(value)); - //// IList list = null; - //// if (collection_map.TryGet(index, out list)) - //// { - //// list.Add(value); - //// } - //// else - //// { - //// if (parent_count < 100000) - //// list = new ListArray(); - //// else - //// list = new ListLinked(); - //// collection_map.Add(index, list); - //// list.Add(value); - //// } - //// }); - //// - //// //if (depth == 1 && allowMultithreading) - //// //{ - //// // // NOTE: Must assign placeholders before multithreading so that the threads do not overwrite each other - //// // collection_map.Keys((<#= child_index_type #> key) => { parent[key] = new Leaf(Omnitree.Bounds<<#= chain_AxisX #>>.None, parent, key); }); - //// // IAsyncResult[] handles = new IAsyncResult[Environment.ProcessorCount]; - //// // for (int i = 0; i < handles.Length; i++) - //// // { - //// // int multiTheadSafe_i = i; // used as catpure variable below making it multithread-safe - //// // handles[i] = ParallelThread.Run(() => - //// // { - //// // Step.EveryNth, <#= child_index_type #>>>(collection_map.Pairs, multiTheadSafe_i + 1)( - //// // (Link, <#= child_index_type #>> link) => - //// // { - //// // ReversedChildBuilding(parent, link._2, depth, link._1.Stepper, link._1.Count, - //<# for (int j = 1; j <= i; j++) { #>median_axis<#= j #>, - //<# } #>initial_count, - //<# for (int j = 1; j <= i; j++) { #>values<#= j #>, - //<# } #>allowMultithreading); - //// // }); - //// // }); - //// // } - //// // - //// // foreach (IAsyncResult handle in handles) - //// // { - //// // handle.AsyncWaitHandle.WaitOne(); - //// // } - //// //} - //// //else - //// //{ - //// collection_map.Pairs((v, k) => - //// { - //// ReversedChildBuilding(parent, k, depth, v.Stepper, v.Count, - //<# for (int j = 1; j <= i; j++) { #>median_axis<#= j #>, - //<# } #>initial_count, - //<# for (int j = 1; j <= i; j++) { #>values<#= j #>, - //<# } #>allowMultithreading); - //// }); - //// //} - //// - //// int count = 0; - //// foreach (Node node in parent.Children) - //// count += node.Count; - //// return count; - //// } - //// - //// int ReversedChildBuilding(Branch parent, <#= child_index_type #> child_index, int depth, Action> additions, int count, - //<# for (int j = 1; j <= i; j++) { #>int prevmed<#= j #>, - //<# } #>int initial_count, - //<# for (int j = 1; j <= i; j++) { #>GetIndex> values<#= j #>, - //<# } #>bool allowMultithreading) - //// { - //// Omnitree.Bounds<<#= chain_AxisX #>> child_bounds = DetermineChildBounds(parent, child_index); - //// if (depth >= _load || count <= _load) - //// { - //// Leaf new_leaf = new Leaf(child_bounds, parent, child_index); - //// additions((T value) => { new_leaf.Add(value); }); - //// parent[new_leaf.Index] = new_leaf; - //// return new_leaf.Count; - //// } - //// else - //// { - //// Branch new_branch = new Branch(Omnitree.Vector<<#= chain_AxisX #>>.Default, child_bounds, parent, child_index); - //// parent[new_branch.Index] = new_branch; - //// new_branch.Count = Add(new_branch, depth + 1, child_index, additions, count, - //<# for (int j = 1; j <= i; j++) { #>prevmed<#= j #>, - //<# } #>count, - //<# for (int j = 1; j <= i; j++) { #>values<#= j #>, - //<# } #>allowMultithreading); - //// return new_branch.Count; - //// } - //// } - //// - //// /// Gets the indeces of the median values at the given position during bulk additions. - //// internal void GetMedianIndexes(int count, <#= child_index_type #> child_index, int depth, - //<# for (int j = 1; j <= i; j++) { #>int previous<#= j #>, - //<# } #>out int index1 - //<# for (int j = 2; j <= i; j++) { #>, out int index<#= j #> - //<# } #>) - //// { - //// if (depth == 1) - //// { - //<# for (int j = 1; j <= i; j++) { #> - //// index<#= j #> = (count - 1) / 2; - //<# } #> - //// return; - //// } - //// - //// int splits = Compute.Power(2, depth); - //// int mid_child_range = count / splits; - //// - //<# for (int j = i; j >= 1; j--) { #> - //// if (child_index >= <#= (2 << (j - 1)) / 2 #>) - //// { - //// index<#= j #> = previous<#= j #> + mid_child_range; - //// child_index -= <#= (2 << (j - 1)) / 2 #>; - //// } - //// else - //// { - //// index<#= j #> = previous<#= j #> - mid_child_range; - //// } - //// - //<# } #> - //// } - - //#endregion - - //<# } #> - - //#region single - - // /// Tries to add a value. - // /// The value to be added. - // /// The exception that occurred if the add failed. - // /// True if successful or false if not. - // public bool TryAdd(T value, out Exception exception) - // { - // Add(value); - // exception = null; - // return true; - // } - - // /// Adds an item to the tree. - // /// The item to be added. - // public void Add(T addition) - // { - // if (this._top.Count == int.MaxValue) - // throw new System.InvalidOperationException("(Count == int.MaxValue) max Omnitree size reached (change ints to longs if you need to)."); - - // // dynamic tree sizes - // Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load); - - // Omnitree.Vector<<#= chain_AxisX #>> location = LocateVector(addition); - - // // grow the first branch of the tree - // if (this._top is Leaf && (this._top as Leaf).Count >= _load) - // { - // Leaf top = this._top as Leaf; - - // // create the new branch from the median values - // this._top = new Branch(DetermineMedians(top), Omnitree.Bounds<<#= chain_AxisX #>>.None, null, -1); - - // // iterate through the elements and add them to the appropriate children - // for (Leaf.Node list = top.Head; !(list is null); list = list.Next) - // Add(list.Value, this._top, LocateVector(list.Value), 0); - // } - - // this.Add(addition, this._top, location, 0); - // } - - // /// Recursive version of the add function. - // /// The item to be added. - // /// The current node for tree trversal. - // /// The location of the addition. - // /// The current depth of iteration. - // internal void Add(T addition, Node node, Omnitree.Vector<<#= chain_AxisX #>> location, int depth) - // { - // if (node is Leaf) - // { - // Leaf leaf = node as Leaf; - // if (depth >= _load || !(leaf.Count >= _load)) - // { - // leaf.Add(addition); - // return; - // } - // else - // { - // Branch parent = node.Parent; - // <#= child_index_type #> child_index = this.DetermineChildIndex(parent.PointOfDivision, location); - // Branch growth = new Branch(DetermineMedians(leaf), leaf.Bounds, parent, child_index); - // parent[child_index] = growth; - // for (Leaf.Node list = leaf.Head; !(list is null); list = list.Next) - // { - // Omnitree.Vector<<#= chain_AxisX #>> temp_location = LocateVector(list.Value); - // if (EncapsulationCheck(growth.Bounds, temp_location)) - // Add(list.Value, growth, temp_location, depth); - // else - // { - // ReduceParentCounts(parent, 1); - // Add(list.Value, this._top, temp_location, depth); - // } - // } - - // Add(addition, growth, location, depth); - // return; - // } - // } - // else - // { - // Branch branch = node as Branch; - // <#= child_index_type #> child_index = this.DetermineChildIndex(branch.PointOfDivision, location); // determine the child "index" (0 through 2^Dimensions) the addition belongs in - // Node child_node = branch[child_index]; - - // // null children in branches are just empty leaves - // if (child_node is null) - // { - // Leaf new_leaf = new Leaf(DetermineChildBounds(branch, child_index), branch, child_index); - // branch[child_index] = new_leaf; - // new_leaf.Add(addition); - // } - // else - // // child exists already, continue adding - // Add(addition, child_node, location, depth + 1); - - // branch.Count++; - // return; - // } - // } - - // internal Omnitree.Vector<<#= chain_AxisX #>> DetermineMedians(Leaf leaf) - // { - - //<# for (int j = 1; j <= i; j++) { #> - // Axis<#= j #> division<#= j #>; - // if (!(_subdivisionOverride<#= j #> is null)) - // { - // division<#= j #> = _subdivisionOverride<#= j #>(leaf.Bounds, x => - // { - // for (Leaf.Node node = leaf.Head; !(node is null); node = node.Next) - // { - // x(node.Value); - // } - // }); - // } - // else - // { - // Axis<#= j #>[] values = new Axis<#= j #>[leaf.Count]; - // Leaf.Node for_current = leaf.Head; - // for (int i = 0; i < leaf.Count; i++, for_current = for_current.Next) - // this._locate(for_current.Value - //<# for (int k = 1; k <= i; k++) { #> - // <#= j == k ? ", out values[i]" : ", out _" #> - //<# } #> - // ); - // if (_defaultCompare<#= j #>) Array.Sort(values); - // else Array.Sort(values, Compare.ToSystemComparison(this._compare<#= j #>)); - // int index = (leaf.Count - 1) / 2; - // division<#= j #> = values[index]; - // } - - //<# } #> - // return new Omnitree.Vector<<#= chain_AxisX #>>( - // division1 - - //<# for (int j = 2; j <= i; j++) { #> - // , division<#= j #> - - //<# } #> - // ); - // } - - //#endregion - - //#region Add Helpers - - // internal Omnitree.Bounds<<#= chain_AxisX #>> DetermineChildBounds(Branch branch, <#= child_index_type #> child_index) - // { - - //<# for (int j = i; j >= 1; j--) { #> - // Omnitree.Bound> min<#= j #>, max<#= j #>; - // if (child_index >= <#= (2 << (j - 1)) / 2 #>) - // { - // min<#= j #> = branch.PointOfDivision.Axis<#= j #>; - // max<#= j #> = branch.Bounds.Max<#= j #>; - // child_index -= <#= (2 << (j - 1)) / 2 #>; - // } - // else - // { - // min<#= j #> = branch.Bounds.Min<#= j #>; - // max<#= j #> = branch.PointOfDivision.Axis<#= j #>; - // } - - //<# } #> - // return new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>); - // } - - //#endregion - - //#endregion - - //#region Clear - - // /// Returns the tree to an empty state. - // public void Clear() - // { - // this._top = new Leaf(Omnitree.Bounds<<#= chain_AxisX #>>.None, null, -1); - // Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load); - // } - - //#endregion - - //#region Clone - - // /// Creates a shallow clone of this data structure. - // /// A shallow clone of this data structure. - // public OmnitreePointsLinked> Clone() - // { - // return new OmnitreePointsLinked>(this); - // } - - //#endregion - - //#region Count - - // /// Counts the number of items in a sub space. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // /// The number of items in the provided sub space. - // public int CountSubSpace(<#= chain_AxisX_minX_AxisX_maxX #>) - // { - // return CountSubSpace(_top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>)); - // } - // /// Counts the number of items in a sub space. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // /// The number of items in the provided sub space. - // public int CountSubSpace(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>) - // { - // return CountSubSpace(_top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>)); - // } - // /// Counts the number of items in a sub space. - // <#= documentation_AxisX_axisX #> - // /// The number of items in the provided sub space. - // public int CountSubSpace(<#= chain_AxisX_axisX #>) - // { - // return CountSubSpace(_top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_axisX_axisX #>)); - // } - // /// Counts the number of items in a sub space. - // <#= documentation_AxisX_axisX #> - // /// The number of items in the provided sub space. - // public int CountSubSpace(<#= chain_BoundAxisX_axisX #>) - // { - // return CountSubSpace(_top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_axisX_axisX #>)); - // } - // /// Counts the number of items in a sub space. - // /// The current traversal node. - // /// The bounds of the sub space being counted. - // /// The number of items in the provided sub space. - // internal int CountSubSpace(Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds) - // { - // // adjust min/max values - // int count = 0; - // if (EncapsulationCheck(bounds, node.Bounds)) - // count += node.Count; - // else if (node is Leaf) - // { - // for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next) - // if (EncapsulationCheck(bounds, LocateVector(list.Value))) - // count++; - // } - // else - // { - // Branch branch = node as Branch; - // if (!StraddlesLines(branch.Bounds, branch.PointOfDivision)) - // { - // <#= child_index_type #> child_index = DetermineChildIndex(branch.PointOfDivision, new Omnitree.Vector<<#= chain_AxisX #>>(bounds.Min1.Value - //<# for (int j = 2; j <= i; j++) { #> - // , bounds.Min<#= j #>.Value - //<# } #> - // )); - // Node child = branch[child_index]; - // if (!(child is null)) - // { - // count += this.CountSubSpace(child, bounds); - // } - // } - // else - // { - // foreach (Node child in (node as Branch).Children) - // count += this.CountSubSpace(child, bounds); - // } - // } - // return count; - // } - - //#endregion - - //#region Update - - // /// Iterates through the entire tree and ensures each item is in the proper leaf. - // public void Update() - // { - // this.Update(this._top, 0); - // } - - // /// Recursive version of the Update method. - // /// The current node of iteration. - // /// The current depth of iteration. - // internal int Update(Node node, int depth) - // { - // int removals = 0; - - // if (node is Leaf) - // { - // Leaf leaf = node as Leaf; - // Leaf.Node current = leaf.Head; - // Leaf.Node previous = null; - // while (!(current is null)) - // { - // Omnitree.Vector<<#= chain_AxisX #>> location = LocateVector(current.Value); - // if (!this.EncapsulationCheck(node.Bounds, location)) - // { - // removals++; - // T updated = current.Value; - // if (previous is null) - // { - // leaf.Head = current.Next; - // goto HeadRemoved; - // } - // else - // previous.Next = current.Next; - - // Node whereToAdd = GetEncapsulationParent(node.Parent, location); - - // if (whereToAdd is null) - // throw new System.Exception("an item was updated outside the range of the omnitree"); - - // this.Add(updated, whereToAdd, location, whereToAdd.Depth); - // } - // previous = current; - // HeadRemoved: - // current = current.Next; - // } - // leaf.Count -= removals; - // return removals; - // } - // else - // { - // Branch branch = node as Branch; - // int skipped = 0; - // for (int i = 0; i + skipped < branch.Children.Length; ) - // { - // removals += this.Update(branch.Children[i], depth + 1); - // if (branch.Children[i].Count == 0) - // branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1]; - // else - // i++; - // } - // Node[] newArray = new Node[branch.Children.Length - skipped]; - // Array.Copy(branch.Children, newArray, newArray.Length); - // branch.Children = newArray; - - // branch.Count -= removals; - - // if (branch.Count < _load && branch.Count != 0) - // ShrinkChild(branch.Parent, branch.Index); - // } - - // return removals; - // } - - // /// Iterates through the provided dimensions and ensures each item is in the proper leaf. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // public void Update(<#= chain_AxisX_minX_AxisX_maxX #>) - // { - // this.Update(new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>), this._top, 0); - // } - // /// Iterates through the provided dimensions and ensures each item is in the proper leaf. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // public void Update(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>) - // { - // this.Update(new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>), this._top, 0); - // } - // /// Iterates through the provided dimensions and ensures each item is in the proper leaf. - // <#= documentation_AxisX_axisX #> - // public void Update(<#= chain_AxisX_axisX #>) - // { - // this.Update(new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_axisX_axisX #>), this._top, 0); - // } - // /// Iterates through the provided dimensions and ensures each item is in the proper leaf. - // <#= documentation_AxisX_axisX #> - // public void Update(<#= chain_BoundAxisX_axisX #>) - // { - // this.Update(new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_axisX_axisX #>), this._top, 0); - // } - // internal int Update(Omnitree.Bounds<<#= chain_AxisX #>> bounds, Node node, int depth) - // { - // if (!InclusionCheck(bounds, node.Bounds)) - // return 0; - - // int removals = 0; - - // if (node is Leaf) - // { - // Leaf leaf = node as Leaf; - // Leaf.Node current = leaf.Head; - // Leaf.Node previous = null; - // while (!(current is null)) - // { - // Omnitree.Vector<<#= chain_AxisX #>> location = LocateVector(current.Value); - // if (!this.EncapsulationCheck(node.Bounds, location)) - // { - // removals++; - // T updated = current.Value; - // if (previous is null) - // { - // leaf.Head = current.Next; - // goto HeadRemoved; - // } - // else - // previous.Next = current.Next; - // Node whereToAdd = GetEncapsulationParent(node.Parent, location); - // if (whereToAdd is null) - // throw new System.Exception("an item was updates outside the range of the omnitree"); - // this.Add(updated, whereToAdd, location, whereToAdd.Depth); - // } - // previous = current; - // HeadRemoved: - // current = current.Next; - // } - // leaf.Count -= removals; - // return removals; - // } - // else - // { - // Branch branch = node as Branch; - // int skipped = 0; - // for (int i = 0; i + skipped < branch.Children.Length; ) - // { - // removals += this.Update(branch.Children[i], depth + 1); - // if (branch.Children[i].Count == 0) - // branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1]; - // else - // i++; - // } - // Node[] newArray = new Node[branch.Children.Length - skipped]; - // Array.Copy(branch.Children, newArray, newArray.Length); - // branch.Children = newArray; - - // branch.Count -= removals; - - // if (branch.Count < _load && branch.Count != 0) - // ShrinkChild(branch.Parent, branch.Index); - // } - - // return removals; - // } - - //#endregion - - //#region Remove - - // /// Removes all the items qualified by the delegate. - // /// The predicate to qualify removals. - // public void Remove(Predicate where) - // { - // this.Remove(this._top, where); - // Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load); - // } - - // /// Recursive version of the remove method. - // /// The current node of traversal. - // /// The predicate to qualify removals. - // internal int Remove(Node node, Predicate where) - // { - // int removals = 0; - // if (node is Leaf) - // { - // Leaf leaf = node as Leaf; - // while (!(leaf.Head is null) && where(leaf.Head.Value)) - // { - // leaf.Head = leaf.Head.Next; - // removals++; - // } - // if (!(leaf.Head is null)) - // { - // Leaf.Node list = leaf.Head; - // while (!(list.Next is null)) - // { - // if (where(list.Next.Value)) - // { - // list.Next = list.Next.Next; - // removals++; - // } - // } - // } - - // leaf.Count -= removals; - // return removals; - // } - // else - // { - // Branch branch = node as Branch; - // int skipped = 0; - // for (int i = 0; i + skipped < branch.Children.Length; ) - // { - // removals += this.Remove(branch.Children[i], where); - // if (branch.Children[i].Count == 0) - // branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1]; - // else - // i++; - // } - // Node[] newArray = new Node[branch.Children.Length - skipped]; - // Array.Copy(branch.Children, newArray, newArray.Length); - // branch.Children = newArray; - - // branch.Count -= removals; - - // if (branch.Count < _load && branch.Count != 0) - // ShrinkChild(branch.Parent, branch.Index); - - // return removals; - // } - // } - - // /// Removes all the items in a given space. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // /// The number of items that were removed. - // public void Remove(<#= chain_AxisX_minX_AxisX_maxX #>) - // { - // this.Remove(this._top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>)); - // Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load); - // } - // /// Removes all the items in a given space. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // /// The number of items that were removed. - // public void Remove(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>) - // { - // this.Remove(this._top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>)); - // Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load); - // } - // internal int Remove(Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds) - // { - // int removals = 0; - // if (InclusionCheck(bounds, node.Bounds)) - // { - // if (node is Leaf) - // { - // Leaf leaf = node as Leaf; - // Leaf.Node current_node = leaf.Head; - // Leaf.Node previous_node = null; - // while (!(current_node is null)) - // { - // Leaf.Node temp_previous = current_node; - // if (EncapsulationCheck(bounds, LocateVector(current_node.Value))) - // { - // removals++; - // if (current_node == leaf.Head) - // leaf.Head = leaf.Head.Next; - // else - // { - // previous_node.Next = current_node.Next; - // temp_previous = previous_node; - // } - // } - // previous_node = temp_previous; - // current_node = current_node.Next; - // } - // leaf.Count -= removals; - // } - // else - // { - // Branch branch = node as Branch; - // int skipped = 0; - // for (int i = 0; i + skipped < branch.Children.Length; ) - // { - // removals += this.Remove(branch.Children[i], bounds); - // if (branch.Children[i].Count == 0) - // branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1]; - // else - // i++; - // } - // Node[] newArray = new Node[branch.Children.Length - skipped]; - // Array.Copy(branch.Children, newArray, newArray.Length); - // branch.Children = newArray; - - // branch.Count -= removals; - // // convert this branch back into a leaf - // // Note: if count is zero, it will be chopped off - // if (branch.Count < _load && branch.Count > 0) - // ShrinkChild(branch.Parent, branch.Index); - // } - // } - - // return removals; - // } - - // /// Removes all the items in a given space validated by a predicate. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // /// The equality constraint of the removal. - // public void Remove(<#= chain_AxisX_minX_AxisX_maxX #>, Predicate where) - // { - // this.Remove(this._top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>), where); - // Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load); - // } - // /// Removes all the items in a given space validated by a predicate. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // /// The equality constraint of the removal. - // public void Remove(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>, Predicate where) - // { - // this.Remove(this._top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>), where); - // Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load); - // } - // internal int Remove(Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds, Predicate where) - // { - // if (!InclusionCheck(node.Bounds, bounds)) - // return 0; - // int removals = 0; - // if (node is Leaf) - // { - // Leaf leaf = node as Leaf; - // Leaf.Node current = leaf.Head; - // Leaf.Node previous = null; - // while (!(current is null)) - // { - // if (this.EncapsulationCheck(bounds, LocateVector(current.Value)) && where(current.Value)) - // { - // removals++; - // if (previous is null) - // { - // leaf.Head = current.Next; - // goto HeadRemoved; - // } - // else - // previous.Next = current.Next; - // } - // previous = current; - // HeadRemoved: - // current = current.Next; - // } - - // leaf.Count -= removals; - // return removals; - // } - // else - // { - // Branch branch = node as Branch; - // int skipped = 0; - // for (int i = 0; i + skipped < branch.Children.Length; ) - // { - // removals += this.Remove(branch.Children[i], bounds, where); - // if (branch.Children[i].Count == 0) - // branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1]; - // else - // i++; - // } - // Node[] newArray = new Node[branch.Children.Length - skipped]; - // Array.Copy(branch.Children, newArray, newArray.Length); - // branch.Children = newArray; - - // node.Count -= removals; - - // if (node.Count < _load && node.Count != 0) - // ShrinkChild(node.Parent, node.Index); - - // return removals; - // } - // } - - // /// Tries to remove a value. - // /// The value to remove. - // /// The exception that occurred if the remove failed. - // /// True if successful or false if not. - // public bool TryRemove(T value, out Exception exception) - // { - // Remove(value); - // exception = null; - // return true; - // } - - // /// Removes all instances of a given value. - // public void Remove(T removal) => Omnitree.Remove(this, removal); - - // /// Removes all instances of a given value. - // public void Remove(T removal, Func equate) => Omnitree.Remove(this, removal, equate); - - // /// Removes all the items in a given space. - // <#= documentation_axisX #> - // /// The number of items that were removed. - // public void Remove(Axis1 axis1 - //<# for (int j = 2; j <= i; j++) { #> - // , Axis<#= j #> axis<#= j #> - //<# } #> - // ) - // { - // this.Remove(this._top, new Omnitree.Vector<<#= chain_AxisX #>>(axis1 - //<# for (int j = 2; j <= i; j++) { #> - // , axis<#= j #> - //<# } #> - // )); - // Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load); - // } - // internal int Remove(Node node, Omnitree.Vector<<#= chain_AxisX #>> vector) - // { - // int removals = 0; - // if (node is Leaf) - // { - // Leaf leaf = node as Leaf; - // Leaf.Node current_node = leaf.Head; - // Leaf.Node previous_node = null; - // while (!(current_node is null)) - // { - // Leaf.Node temp_previous = current_node; - // if (EqualsCheck(vector, LocateVector(current_node.Value))) - // { - // removals++; - // if (current_node == leaf.Head) - // leaf.Head = leaf.Head.Next; - // else - // { - // previous_node.Next = current_node.Next; - // temp_previous = previous_node; - // } - // } - // previous_node = temp_previous; - // current_node = current_node.Next; - // } - // leaf.Count -= removals; - // } - // else - // { - // Branch branch = node as Branch; - // <#= child_index_type #> child_index = DetermineChildIndex(branch.PointOfDivision, vector); - // removals += Remove(branch[child_index], vector); - // branch.Count -= removals; - // // convert this branch back into a leaf - // // Note: if count is zero, it will be chopped off - // if (branch.Count < _load && branch.Count > 0) - // ShrinkChild(branch.Parent, branch.Index); - // } - - // return removals; - // } - - // /// Removes all the items in a given space validated by a predicate. - // <#= documentation_axisX #> - // /// The equality constraint of the removal. - // public void Remove(<#= chain_AxisX_axisX #>, Predicate where) - // { - // this.Remove(this._top, new Omnitree.Vector<<#= chain_AxisX #>>(<#= chain_axisX #>), where); - // Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load); - // } - // internal int Remove(Node node, Omnitree.Vector<<#= chain_AxisX #>> vector, Predicate where) - // { - // int removals = 0; - // if (node is Leaf) - // { - // Leaf leaf = node as Leaf; - // Leaf.Node current_node = leaf.Head; - // Leaf.Node previous_node = null; - // while (!(current_node is null)) - // { - // Leaf.Node temp_previous = current_node; - // if (EqualsCheck(vector, LocateVector(current_node.Value)) && where(current_node.Value)) - // { - // removals++; - // if (current_node == leaf.Head) - // leaf.Head = leaf.Head.Next; - // else - // { - // previous_node.Next = current_node.Next; - // temp_previous = previous_node; - // } - // } - // previous_node = temp_previous; - // current_node = current_node.Next; - // } - // leaf.Count -= removals; - // } - // else - // { - // Branch branch = node as Branch; - // <#= child_index_type #> child_index = DetermineChildIndex(branch.PointOfDivision, vector); - // removals += Remove(branch[child_index], vector, where); - // branch.Count -= removals; - // // convert this branch back into a leaf - // // Note: if count is zero, it will be chopped off - // if (branch.Count < _load && branch.Count > 0) - // ShrinkChild(branch.Parent, branch.Index); - // } - // return removals; - // } - - //#endregion - - //#region Stepper And IEnumerable - - // /// Traverses every item in the tree and performs the delegate in them. - // /// The delegate to perform on every item in the tree. - // public void Stepper(Action step) => - // this.Stepper(step, this._top); - - // internal void Stepper(Action step, Node node) - // { - // if (node is Leaf) - // { - // Leaf.Node list = (node as Leaf).Head; - // while (!(list is null)) - // { - // step(list.Value); - // list = list.Next; - // } - // } - // else - // { - // foreach (Node child in (node as Branch).Children) - // this.Stepper(step, child); - // } - // } - - // /// Traverses every item in the tree and performs the delegate in them. - // /// The delegate to perform on every item in the tree. - // public StepStatus Stepper(Func step) => - // Stepper(step, _top); - - // internal StepStatus Stepper(Func step, Node node) - // { - // StepStatus status = StepStatus.Continue; - // if (node is Leaf) - // { - // for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next) - // if ((status = step(list.Value)) != StepStatus.Continue) - // break; - // } - // else - // { - // foreach (Node child in (node as Branch).Children) - // if ((status = Stepper(step, child)) != StepStatus.Continue) - // break; - // } - // return status; - // } - - // /// Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions. - // /// The delegate to perform on all items in the tree within the given bounds. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // public void Stepper(Action step, <#= chain_AxisX_minX_AxisX_maxX #>) => - // Stepper(step, _top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>)); - - // /// Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions. - // /// The delegate to perform on all items in the tree within the given bounds. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // public void Stepper(Action step, <#= chain_BoundAxisX_minX_BoundAxisX_maxX #>) => - // Stepper(step, _top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>)); - - // internal void Stepper(Action step, Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds) - // { - // if (node is Leaf) - // { - // for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next) - // if (EncapsulationCheck(bounds, LocateVector(list.Value))) - // step(list.Value); - // } - // else - // { - // foreach (Node child in (node as Branch).Children) - // // optimization: stop bounds checking if space encapsulates node - // if (EncapsulationCheck(bounds, child.Bounds)) - // this.Stepper(step, child); - // else if (InclusionCheck(child.Bounds, bounds)) - // this.Stepper(step, child, bounds); - // } - // } - - // /// Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions. - // /// The delegate to perform on all items in the tree within the given bounds. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // public StepStatus Stepper(Func step, <#= chain_AxisX_minX_AxisX_maxX #>) => - // Stepper(step, _top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>)); - - // /// Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions. - // /// The delegate to perform on all items in the tree within the given bounds. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // public StepStatus Stepper(Func step, <#= chain_BoundAxisX_minX_BoundAxisX_maxX #>) => - // Stepper(step, _top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>)); - - // internal StepStatus Stepper(Func step, Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds) - // { - // StepStatus status = StepStatus.Continue; - // if (node is Leaf) - // { - // for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next) - // if (EncapsulationCheck(bounds, LocateVector(list.Value)) && - // (status = step(list.Value)) != StepStatus.Continue) - // break; - // } - // else - // { - // foreach (Node child in (node as Branch).Children) - // // optimization: stop bounds checking if space encapsulates node - // if (EncapsulationCheck(bounds, child.Bounds) && - // (status = this.Stepper(step, child)) != StepStatus.Continue) - // break; - // else if (!InclusionCheck(child.Bounds, bounds) && - // (status = this.Stepper(step, child, bounds)) != StepStatus.Continue) - // break; - // } - // return status; - // } - - // /// Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions. - // /// The delegate to perform on all items in the tree within the given bounds. - // <#= documentation_axisX #> - // public void Stepper(Action step, <#= chain_AxisX_axisX #>) => - // Stepper(step, _top, new Omnitree.Vector<<#= chain_AxisX #>>(<#= chain_axisX #>)); - - // internal void Stepper(Action step, Node node, Omnitree.Vector<<#= chain_AxisX #>> vector) - // { - // Node current = node; - // while (!(current is null)) - // { - // if (current is Leaf) - // { - // for (Leaf.Node leaf_node = (current as Leaf).Head; !(leaf_node is null); leaf_node = leaf_node.Next) - // if (EqualsCheck(vector, LocateVector(leaf_node.Value))) - // step(leaf_node.Value); - // break; - // } - // else - // { - // Branch branch = current as Branch; - // <#= child_index_type #> child_index = DetermineChildIndex(branch.PointOfDivision, vector); - // current = branch[child_index]; - // } - // } - // } - - // /// Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions. - // /// The delegate to perform on all items in the tree within the given bounds. - // <#= documentation_axisX #> - // public StepStatus Stepper(Func step, <#= chain_AxisX_axisX #>) => - // Stepper(step, _top, new Omnitree.Vector<<#= chain_AxisX #>>(<#= chain_axisX #>)); - - // internal StepStatus Stepper(Func step, Node node, Omnitree.Vector<<#= chain_AxisX #>> vector) - // { - // Node current = node; - // while (!(current is null)) - // { - // if (current is Leaf) - // { - // for (Leaf.Node list = (current as Leaf).Head; !(list is null); list = list.Next) - // { - // StepStatus status = StepStatus.Continue; - // if (EqualsCheck(vector, LocateVector(list.Value)) && - // (status = step(list.Value)) != StepStatus.Continue) - // return status; - // } - // } - // else - // { - // Branch branch = current as Branch; - // <#= child_index_type #> child_index = DetermineChildIndex(branch.PointOfDivision, vector); - // current = branch[child_index]; - // } - // } - // return StepStatus.Continue; - // } - - // System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); - - // public System.Collections.Generic.IEnumerator GetEnumerator() - // { - // // Note: this can be optimized. - // IList list = new ListLinked(); - // Stepper(x => list.Add(x)); - // return list.GetEnumerator(); - // } - - //#endregion - - //#region Helpers - - // internal bool StraddlesLines(Omnitree.Bounds<<#= chain_AxisX #>> bounds, Omnitree.Vector<<#= chain_AxisX #>> vector) => - // Omnitree.StraddlesLines(bounds, vector - //<# for (int j = 1; j <= i; j++) { #> - // , _compare<#= j #> - //<# } #> - // ); - - // /// Computes the child index that contains the desired dimensions. - // /// The point of division to compare against. - // /// The dimensions to determine the child index. - // /// The computed child index based on the coordinates relative to the center of the node. - // internal <#= child_index_type #> DetermineChildIndex(Omnitree.Vector<<#= chain_AxisX #>> pointOfDivision, Omnitree.Vector<<#= chain_AxisX #>> vector) - // { - // <#= child_index_type #> child = 0; - //<# for (int j = 1; j <= i; j++) { #> - // if (!(this._compare<#= j #>(vector.Axis<#= j #>, pointOfDivision.Axis<#= j #>) == CompareResult.Less)) - // child += 1 << <#= j - 1 #>; - //<# } #> - // return child; - // } - - // /// Converts a branch back into a leaf when the count is reduced. - // /// The parent to shrink a child of. - // /// The index of the child to shrink. - // internal void ShrinkChild(Branch parent, <#= child_index_type #> child_index) - // { - // Leaf leaf; - // Node removal = null; - // if (parent is null) // top of tree - // { - // removal = this._top; - // leaf = new Leaf(Omnitree.Bounds<<#= chain_AxisX #>>.None, null, -1); - // this._top = leaf; - // } - // else // non-top branch - // { - // removal = parent[child_index]; - // leaf = new Leaf(removal.Bounds, removal.Parent, removal.Index); - // parent[child_index] = leaf; - // } - - // this.Stepper((T step) => { leaf.Add(step); }, removal); - // } - - // /// Reduces the counts of all the parents of a given node by a given amount. - // /// The starting parent of the reduction. - // /// The amount to reduce the parent counts by. - // internal void ReduceParentCounts(Node parent, int reduction) - // { - // IncreaseParentCounts(parent, -reduction); - // } - - // /// Increases the counts of all the parents of a given node by a given amount. - // /// The starting parent of the increase. - // /// The amount to increase the parent counts by. - // internal void IncreaseParentCounts(Node parent, int increase) - // { - // Node node = parent; - // while (!(node is null)) - // { - // node.Count += increase; - // node = node.Parent; - // } - // } - - // /// Checks a node for inclusion (overlap) between two bounds. - // /// True if the spaces overlap; False if not. - // internal bool InclusionCheck(Omnitree.Bounds<<#= chain_AxisX #>> a, Omnitree.Bounds<<#= chain_AxisX #>> b) => - // Omnitree.InclusionCheck(a, b - //<# for (int j = 1; j <= i; j++) { #> - // , _compare<#= j #> - //<# } #> - // ); - - // /// Checks if a space encapsulates a point. - // /// True if the space encapsulates the point; False if not. - // internal bool EncapsulationCheck(Omnitree.Bounds<<#= chain_AxisX #>> bounds, Omnitree.Vector<<#= chain_AxisX #>> vector) => - // Omnitree.EncapsulationCheck(bounds, vector - //<# for (int j = 1; j <= i; j++) { #> - // , _compare<#= j #> - //<# } #> - // ); - - // /// Checks if a space (left) encapsulates another space (right). - // /// True if the left space encapsulates the right; False if not. - // internal bool EncapsulationCheck(Omnitree.Bounds<<#= chain_AxisX #>> a, Omnitree.Bounds<<#= chain_AxisX #>> b) => - // Omnitree.EncapsulationCheck(a, b - //<# for (int j = 1; j <= i; j++) { #> - // , _compare<#= j #> - //<# } #> - // ); - - // /// Checks for equality between two locations. - // /// True if equal; False if not; - // internal bool EqualsCheck(Omnitree.Vector<<#= chain_AxisX #>> a, Omnitree.Vector<<#= chain_AxisX #>> b) => - // Omnitree.EqualsCheck(a, b - //<# for (int j = 1; j <= i; j++) { #> - // , Equate.FromCompare(_compare<#= j #>) - //<# } #> - // ); - - // /// Gets the nearest parent that encapsulates a location. - // /// The starting node to find the encapsulating parent of the location. - // /// The coordinates of the value. - // /// The nearest node that encapsulates the given location. - // internal Node GetEncapsulationParent(Node node, Omnitree.Vector<<#= chain_AxisX #>> vector) - // { - // while (!(node is null) && !EncapsulationCheck(node.Bounds, vector)) - // { - // node = node.Parent; - // } - // return node; - // } - - // internal Omnitree.Vector<<#= chain_AxisX #>> LocateVector(T value) - // { - //<# for (int j = 1; j <= i; j++) { #> - // Axis<#= j #> axis<#= j #>; - //<# } #> - // this._locate(value, out axis1 - //<# for (int j = 2; j <= i; j++) { #>, out axis<#= j #> - //<# } #>); - // return new Omnitree.Vector<<#= chain_AxisX #>>(<#= chain_axisX #>); - // } - - //#endregion - - //#endregion - // } - - //#endregion - //<# } #> - - //#endregion - - //#region OmnitreeBounds - //<# foreach (int i in dimensionsToGenerate) { - //// ------------------------------------------------------------------------------------------------------------------------------ - // // PARAMETER/ARGUMENT CHAINS - // string chain_AxisX = "Axis1"; for (int j = 2; j <= i; j++) { chain_AxisX += ", Axis" + j; } - // string chain_axisX = "axis1"; for (int j = 2; j <= i; j++) { chain_axisX += ", axis" + j; } - // string chain_AxisX_axisX = "Axis1 axis1"; for (int j = 2; j <= i; j++) { chain_AxisX_axisX += ", Axis" + j + " axis" + j; } - // string chain_AxisX_minX_AxisX_maxX = "Axis1 min1, Axis1 max1"; for (int j = 2; j <= i; j++) { chain_AxisX_minX_AxisX_maxX += ", Axis" + j + " min" + j + ", Axis" + j + " max" + j; } - // string chain_BoundAxisX_minX_BoundAxisX_maxX = "Omnitree.Bound min1, Omnitree.Bound max1"; for (int j = 2; j <= i; j++) { chain_BoundAxisX_minX_BoundAxisX_maxX += ", Omnitree.Bound min" + j + ", Omnitree.Bound max" + j; } - // string chain_BoundAxisX_axisX = "Omnitree.Bound axis1"; for (int j = 2; j <= i; j++) { chain_BoundAxisX_axisX += ", Omnitree.Bound axis" + j; } - // string chain_minX_maxX = "min1, max1"; for (int j = 2; j <= i; j++) { chain_minX_maxX += ", min" + j + ", max" + j; } - // string chain_axisX_axisX = "axis1, axis1"; for (int j = 2; j <= i; j++) { chain_axisX_axisX += ", axis" + j + ", axis" + j; } - // string child_index_type; if (i <= 30) { child_index_type = "int"; } else if (i <= 60) { child_index_type = "long"; } else { child_index_type = "BigInteger"; } - // // DOCUMENTATION - // string documentation_AxisX_axisX = string.Empty; for (int j = 1; j <= i; j++) { documentation_AxisX_axisX += "\n\t\t/// The coordinate along the " + j + "D axis."; } documentation_AxisX_axisX = documentation_AxisX_axisX.Trim(); - // string documentation_AxisX_minX_AxisX_maxX = string.Empty; for (int j = 1; j <= i; j++) { documentation_AxisX_minX_AxisX_maxX += "\n\t\t/// The minimum coordinate of the space along the " + j + " axis.\n\t\t/// The maximum coordinate of the space along the " + j + " axis."; } documentation_AxisX_minX_AxisX_maxX = documentation_AxisX_minX_AxisX_maxX.Trim(); - // string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { documentation_axisX += "\n\t\t/// The axis of the removal along the " + j + "D axis."; } documentation_axisX = documentation_axisX.Trim(); - // // ------------------------------------------------------------------------------------------------------------------------------ #> - - //#region <#= i #> Dimensional - - // /// Inheritance base for <#= i #>D omnitrees that store bounds. - // /// The type of items to store in the omnitree. - //<# for (int j = 1; j <= i; j++) { #> - // /// The type <#= j #>D axis. - //<# } #> - // public interface IOmnitreeBounds> : IOmnitree> - // { - //#region Properties - - // /// The number of dimensions in this tree. - // int Dimensions { get; } - - // /// The delegate being used by the omnitree to get the bounds of values in <#= i #>D space. - // Omnitree.GetBounds, Axis<#= j #> - //<# } #> - // > GetBounds { get; } - - //#endregion - - //#region Methods - - // /// Counts the number of items encapsulated by a sub space. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // /// The number of items in the provided sub space. - // int CountSubSpaceEncapsulated(<#= chain_AxisX_minX_AxisX_maxX #>); - - // /// Counts the number of items overlapped by a sub space. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // /// The number of items in the provided sub space. - // int CountSubSpaceOverlapped(<#= chain_AxisX_minX_AxisX_maxX #>); - - // /// Iterates through the entire tree and ensures each item is in the proper leaf. - // void Update(); - // /// Iterates through the provided dimensions and ensures each item is in the proper leaf. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // void Update(<#= chain_AxisX_minX_AxisX_maxX #>); - - // /// Removes all the items in a given space. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // void RemoveEncapsulated(<#= chain_AxisX_minX_AxisX_maxX #>); - // /// Removes all the items in a given space. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // void RemoveEncapsulated(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>); - // /// Removes all the items in a given space where predicate is met. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // /// The predicate constraint of the removal. - // void RemoveEncapsulated(<#= chain_AxisX_minX_AxisX_maxX #>, Predicate where); - // /// Removes all the items in a given space where predicate is met. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // /// The predicate constraint of the removal. - // void RemoveEncapsulated(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>, Predicate where); - - // /// Removes all the items in a given space. - // <#= documentation_AxisX_axisX #> - // void RemoveOverlapped(<#= chain_AxisX_axisX #>); - // /// Removes all the items in a given space. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // void RemoveOverlapped(<#= chain_AxisX_minX_AxisX_maxX #>); - // /// Removes all the items in a given space. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // void RemoveOverlapped(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>); - // /// Removes all the items in a given space where equality is met. - // <#= documentation_AxisX_axisX #> - // /// The equality constraint of the removal. - // void RemoveOverlapped(<#= chain_AxisX_axisX #>, Predicate where); - // /// Removes all the items in a given space where predicate is met. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // /// The predicate constraint of the removal. - // void RemoveOverlapped(<#= chain_AxisX_minX_AxisX_maxX #>, Predicate where); - // /// Removes all the items in a given space where predicate is met. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // /// The predicate constraint of the removal. - // void RemoveOverlapped(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>, Predicate where); - - // /// Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions. - // /// The step function to perform on all items in the tree within the given bounds. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // void StepperEncapsulated(Action step, <#= chain_BoundAxisX_minX_BoundAxisX_maxX #>); - // /// Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions. - // /// The step function to perform on all items in the tree within the given bounds. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // StepStatus StepperEncapsulated(Func step, <#= chain_BoundAxisX_minX_BoundAxisX_maxX #>); - - // /// Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions. - // /// The step function to perform on all items in the tree within the given bounds. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // void StepperOverlapped(Action step, <#= chain_BoundAxisX_minX_BoundAxisX_maxX #>); - // /// Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions. - // /// The step function to perform on all items in the tree within the given bounds. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // StepStatus StepperOverlapped(Func step, <#= chain_BoundAxisX_minX_BoundAxisX_maxX #>); - - // /// Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions. - // /// The step function to perform on all items in the tree within the given bounds. - // <#= documentation_AxisX_axisX #> - // void StepperOverlapped(Action step, <#= chain_AxisX_axisX #>); - // /// Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions. - // /// The step function to perform on all items in the tree within the given bounds. - // <#= documentation_AxisX_axisX #> - // StepStatus StepperOverlapped(Func step, <#= chain_AxisX_axisX #>); - - //#endregion - // } - - // /// Omnitree that stores bounds along <#= i #> dimensions implemented as a linked tree. - // /// The type of items to store in the omnitree. - //<# for (int j = 1; j <= i; j++) { #> - // /// The type <#= j #>D axis. - //<# } #> - // public class OmnitreeBoundsLinked> : IOmnitreeBounds> - // { - // internal const int _dimensions = <#= i #>; - // internal static <#= child_index_type #> _children_per_node = (<#= child_index_type #>)BigInteger.Pow(2, <#= i #>); - - // internal Node _top; - // internal int _naturalLogLower = 1; // caching the next time to calculate loads (lower count) - // internal int _naturalLogUpper = -1; // caching the next time to calculate loads (upper count) - // internal int _load; // ln(count); min = _defaultLoad - // internal Omnitree.GetBounds, Axis<#= j #> - //<# } #> - // > _getBounds; - //<# for (int j = 1; j <= i; j++) { #> - // internal bool _defaultCompare<#= j #>; - // internal Compare> _compare<#= j #>; - //<# } #> - //<# for (int j = 1; j <= i; j++) { #> - // internal Omnitree.SubdivisionOverride, Omnitree.Bounds<<#= chain_AxisX #>>> _subdivisionOverride<#= j #>; - //<# } #> - - //#region Nested Types - - // /// Can be a leaf or a branch. - // internal class Node - // { - // internal class ValueNode - // { - // internal T Value; - // internal ValueNode Next; - - // internal ValueNode(T value, ValueNode next) - // { - // Value = value; - // Next = next; - // } - // } - - // internal Omnitree.Bounds<<#= chain_AxisX #>> Bounds; - // internal Node Parent; - // internal <#= child_index_type #> Index; - // internal int Count; - // internal ValueNode Head; - // internal Node[] Children; - // internal Omnitree.Vector<<#= chain_AxisX #>>? PointOfDivision; - - // /// Gets child by index. - // /// The index of the child to get. - // /// The child of the given index or null if non-existent. - // internal Node this[<#= child_index_type #> child_index] - // { - // get - // { - // if (Children is null) - // return null; - // if (Children.Length == OmnitreePointsLinked>._children_per_node) - // return Children[(int)child_index]; - // foreach (Node node in Children) - // if (node.Index == child_index) - // return node; - // return null; - // } - // set - // { - // // This error check should be unnecessary... but fuck it... might as well - // if (value.Index != child_index) - // throw new System.Exception("Bug in Omnitree (index/property mis-match when setting a child on a branch)"); - - // // no children yet - // if (Children is null) - // { - // Children = Ɐ(value); - // return; - // } - // // max children overwrite - // else if (Children.Length == OmnitreePointsLinked>._children_per_node) - // { - // Children[(int)child_index] = value; - // return; - // } - // // non-max child overwrite - // for (int i = 0; i < Children.Length; i++) - // if (Children[i].Index == child_index) - // { - // Children[i] = value; - // return; - // } - // // new child - // Node[] newArray = new Node[Children.Length + 1]; - // if (newArray.Length == OmnitreePointsLinked>._children_per_node) - // { - // // new child resulting in a max children branch (sorting required) - // for (int i = 0; i < Children.Length; i++) - // { - // newArray[(int)Children[i].Index] = Children[i]; - // } - // newArray[(int)value.Index] = value; - // } - // else - // { - // // new child resulting in a non-max children branch - // Array.Copy(Children, newArray, Children.Length); - // newArray[newArray.Length - 1] = value; - // } - // Children = newArray; - // } - // } - - // /// The depth this node is located in the Omnitree. - // internal int Depth - // { - // get - // { - // int depth = -1; - // for (Node node = this; !(node is null); node = node.Parent) - // depth++; - // return depth; - // } - // } - - // /// Constructs a node. - // /// The bounds of this node. - // /// The parent of this node. - // /// The number of elements stored in this node and its children. - // internal Node(Omnitree.Bounds<<#= chain_AxisX #>> bounds, Node parent, <#= child_index_type #> index) - // { - // Bounds = bounds; - // Parent = parent; - // Index = index; - // } - - // internal Node(Omnitree.Vector<<#= chain_AxisX #>> pointOfDivision, Omnitree.Bounds<<#= chain_AxisX #>> bounds, Node parent, <#= child_index_type #> index) - // : this(bounds, parent, index) - // { - // PointOfDivision = pointOfDivision; - // } - - // internal Node(Node nodeToClone) - // { - // this.Bounds = nodeToClone.Bounds; - // this.Parent = nodeToClone.Parent; - // this.Index = nodeToClone.Index; - // this.Count = nodeToClone.Count; - - // Children = nodeToClone.Children.Clone() as Node[]; - // PointOfDivision = nodeToClone.PointOfDivision; - - // ValueNode a = this.Head; - // ValueNode b = nodeToClone.Head; - - // while (!(b is null)) - // { - // a.Next = new ValueNode(b.Next.Value, null); - // a = a.Next; - // b = b.Next; - // } - // } - - // internal void Add(T addition) - // { - // Head = new ValueNode(addition, Head); - // Count++; - // } - - // internal Node Clone() => - // new Node(this); - // } - - //#endregion - - //#region Constructors - - // /// This constructor is for cloning purposes - // internal OmnitreeBoundsLinked(OmnitreeBoundsLinked> omnitree) - // { - // this._top = omnitree._top.Clone(); - // this._load = omnitree._load; - // this._getBounds = omnitree._getBounds; - //<# for (int j = 1; j <= i; j++) { #> - // this._defaultCompare<#= j #> = omnitree._defaultCompare<#= j #>; - // this._compare<#= j #> = omnitree._compare<#= j #>; - //<# } #> - //<# for (int j = 1; j <= i; j++) { #> - // this._subdivisionOverride<#= j #> = omnitree._subdivisionOverride<#= j #>; - //<# } #> - // } - - // internal OmnitreeBoundsLinked( - // Omnitree.GetBounds> getBounds, - //<# for (int j = 1; j <= i; j++) { #> - // bool defaultCompare<#= j #>, - // Compare> compare<#= j #>, - //<# } #> - // Omnitree.SubdivisionOverride>> subdivisionOverride1 - //<# for (int j = 2; j <= i; j++) { #>, - // Omnitree.SubdivisionOverride, Omnitree.Bounds<<#= chain_AxisX #>>> subdivisionOverride<#= j #> - //<# } #> - // ) - // { - // if (getBounds is null) - // { - // throw new ArgumentNullException(nameof(getBounds)); - // } - //<# for (int j = 1; j <= i; j++) { #> - // if (compare<#= j #> is null) - // { - // throw new ArgumentNullException(nameof(compare<#= j #>)); - // } - //<# } #> - // this._getBounds = getBounds; - //<# for (int j = 1; j <= i; j++) { #> - // this._defaultCompare<#= j #> = defaultCompare<#= j #>; - // this._compare<#= j #> = compare<#= j #>; - //<# } #> - //<# for (int j = 1; j <= i; j++) { #> - // this._subdivisionOverride<#= j #> = subdivisionOverride<#= j #>; - //<# } #> - // this._top = new Node(Omnitree.Bounds<<#= chain_AxisX #>>.None, null, -1); - // Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load); - // } - - // /// Constructs a new <#= i #>D omnitree that stores bounds. - // /// The delegate for getting object bounds in <#= i #>D space. - //<# for (int j = 1; j <= i; j++) { #> - - // /// The delegate for comparing values along the <#= j #>D axis. - //<# } #> - //<# for (int j = 1; j <= i; j++) { #> - - // /// The subdivision overide to be used when splitting the <#= j #> dimension. - //<# } #> - // public OmnitreeBoundsLinked( - // Omnitree.GetBounds> getBounds, - //<# for (int j = 1; j <= i; j++) { #> - // Compare> compare<#= j #> = null, - //<# } #> - // Omnitree.SubdivisionOverride>> subdivisionOverride1 = null - //<# for (int j = 2; j <= i; j++) { #>, - // Omnitree.SubdivisionOverride, Omnitree.Bounds<<#= chain_AxisX #>>> subdivisionOverride<#= j #> = null - //<# } #> - // ) - // : this( - // getBounds, - //<# for (int j = 1; j <= i; j++) { #> - // compare<#= j #> is null ? true : false, - // compare<#= j #> ?? Compare.Default, - //<# } #> - // subdivisionOverride1 - //<# for (int j = 2; j <= i; j++) { #>, - // subdivisionOverride<#= j #> - //<# } #> - // ) { } - - // /// Constructs a new <#= i #>D omnitree that stores bounds. - // /// The delegate for getting object bounds in <#= i #>D space. - //<# for (int j = 1; j <= i; j++) { #> - // /// The delegate for comparing values along the <#= j #>D axis. - //<# } #> - //<# for (int j = 1; j <= i; j++) { #> - - // /// The subdivision overide to be used when splitting the <#= j #> dimension. - //<# } #> - // public OmnitreeBoundsLinked( - // Omnitree.GetBoundings> getBoundings, - //<# for (int j = 1; j <= i; j++) { #> - // Compare> compare<#= j #> = null, - //<# } #> - // Omnitree.SubdivisionOverride>> subdivisionOverride1 = null - //<# for (int j = 2; j <= i; j++) { #> - // , Omnitree.SubdivisionOverride, Omnitree.Bounds<<#= chain_AxisX #>>> subdivisionOverride<#= j #> = null - //<# } #> - // ) - // : this( - // Omnitree.ConvertToGetBounds(getBoundings), - //<# for (int j = 1; j <= i; j++) { #> - // compare<#= j #> is null ? true : false, - // compare<#= j #> ?? Compare.Default, - //<# } #> - // subdivisionOverride1 - //<# for (int j = 2; j <= i; j++) { #>, - // subdivisionOverride<#= j #> - //<# } #> - // ) { } - - //#endregion - - //#region Properties - - // /// The number of dimensions in this tree. - // public int Dimensions => _dimensions; - - // /// The delegate being used by the omnitree to locate items in <#= i #>D space. - // public Omnitree.GetBounds - // , Axis<#= j #> - //<# } #> - // > GetBounds => _getBounds; - - - //<# for (int j = 1; j <= i; j++) { #> - // /// The comparison function the Omnitree is using along the <#= j #>D axis. - // public Compare> Compare<#= j #> => _compare<#= j #>; - //<# } #> - - // /// The current number of items in the tree. - // public int Count => _top.Count; - - // internal delegate void MaxDepthFinder(Node node, int current_depth, ref int max_depth); - // /// Finds the current maximum depth of the tree. NOT AN O(1) OPERATION. Intended for educational purposes only. - // public int MaxDepth - // { - // get - // { - // MaxDepthFinder maxDepthFinder = null; - // maxDepthFinder = - // (Node node, int current_depth, ref int max_depth) => - // { - // if (current_depth > max_depth) - // max_depth = current_depth; - // foreach (Node child in node.Children) - // maxDepthFinder(child, current_depth + 1, ref max_depth); - // }; - // int _max_depth = -1; - // maxDepthFinder(this._top, 0, ref _max_depth); - // return _max_depth; - // } - // } - - // internal delegate void NodeCountFinder(Node node, ref int current_count); - // /// Counts the current number of nodes in the tree. NOT AN O(1) OPERATION. Intended for educational purposes only. - // public int NodeCount - // { - // get - // { - // NodeCountFinder nodeCountFinder = null; - // nodeCountFinder = - // (Node node, ref int current_count) => - // { - // current_count++; - // foreach (Node child in node.Children) - // nodeCountFinder(child, ref current_count); - // }; - - // int _current_count = 0; - // nodeCountFinder(this._top, ref _current_count); - // return _current_count; - // } - // } - - //#endregion - - //#region Methods - - //#region Add - - //<# if (false) { #> - //#region Bulk - - // // not yet implemented - - //// public void Add(ArrayJagged additions, bool allowMultithreading) - //// { - //// if (additions.Length > int.MaxValue) - //// throw new System.Exception("The maximum size of the Omnitree was exceeded during bulk addition."); - //// - //// if (this._top.Count != 0 || (int)additions.Length <= _load) - //// { - //// for (ulong i = 0; i < additions.Length; i++) - //// this.Add(additions[i]); - //// } - //// else - //// { - //// // adjust the loads prior to additions - //// ComputeLoads((int)additions.Length); - //// - //// Node new_top = new Node(Omnitree.Bounds<<#= chain_AxisX #>>.None, null, -1); - //// new_top.Count = (int)additions.Length; - //// - //// - //<# for (int j = 1; j <= i; j++) { #> - //// // prepare data for median computations - //// ArrayJagged> values<#= j #>; - //// IAsyncResult result<#= j #> = null; - //// if (!(this._subdivisionOverride<#= j #> is null)) - //// values<#= j #> = null; - //// else - //// { - //// values<#= j #> = null; - //// ParallelThread.Operation operation = () => - //// { - //// values<#= j #> = new ArrayJagged>(additions.Length * 2); - //// for (ulong i = 0; i < additions.Length; i++) - //// { - //// Omnitree.Bounds<<#= chain_AxisX #>> bounds = GetBoundings(additions[i]); - //// values<#= j #>[i * 2] = bounds.Min1; - //// values<#= j #>[i * 2 + 1] = bounds.Max1; - //// } - //// - //// Towel.Algorithms.Sort.Merge(this._compare<#= j #>, (int i) => { return values<#= j #>[(ulong)i]; }, (int i, Axis<#= j #> value) => { values<#= j #>[(ulong)i] = value; }, 0, (int)(additions.Length - 1)); - //// }; - //// - //// if (allowMultithreading) - //// result<#= j #> = ParallelThread.Run(operation); - //// else - //// operation(); - //// } - //// - //<# } #> - //// - //// - //<# for (int j = 1; j <= i; j++) { #> - //// if (this._subdivisionOverride<#= j #> is null && allowMultithreading) - //// result<#= j #>.AsyncWaitHandle.WaitOne(); - //<# } #> - //// - //// // build the tree - //// Add(new_top, 1, -1, additions.ToStepper(), (int)additions.Length, - //<# for (int j = 1; j <= i; j++) { #>int.MinValue, - //<# } #>(int)additions.Length, - //<# for (int j = 1; j <= i; j++) { #>(int index) => { return values<#= j #>[index]; }, - //<# } #>allowMultithreading); - //// - //// this._top = new_top; - //// } - //// } - //// - //// public void Add(bool allowMultithreading, params T[] additions) - //// { - //// if (additions.Length > int.MaxValue) - //// throw new System.Exception("The maximum size of the Omnitree was exceeded during bulk addition."); - //// - //// if (this._top.Count != 0 || (int)additions.Length <= _load) - //// { - //// for (int i = 0; i < additions.Length; i++) - //// this.Add(additions[i]); - //// } - //// else - //// { - //// // adjust the loads prior to additions - //// ComputeLoads((int)additions.Length); - //// - //// Node new_top = new Node(Omnitree.Bounds<<#= chain_AxisX #>>.None, null, -1); - //// new_top.Count = (int)additions.Length; - //// - //// - //<# for (int j = 1; j <= i; j++) { #> - //// // prepare data for median computations - //// ArrayJagged> values<#= j #>; - //// IAsyncResult result<#= j #> = null; - //// if (!(this._subdivisionOverride<#= j #> is null)) - //// values<#= j #> = null; - //// else - //// { - //// values<#= j #> = null; - //// ParallelThread.Operation operation = () => - //// { - //// values<#= j #> = new ArrayJagged>(additions.Length); - //// for (int i = 0; i < additions.Length; i++) - //// values<#= j #>[i] = LocateVector(additions[i]).Axis<#= j #>; - //// Towel.Algorithms.Sort.Merge(this._compare<#= j #>, (int i) => { return values<#= j #>[(ulong)i]; }, (int i, Axis<#= j #> value) => { values<#= j #>[(ulong)i] = value; }, 0, (int)(additions.Length - 1)); - //// }; - //// - //// if (allowMultithreading) - //// result<#= j #> = ParallelThread.Run(operation); - //// else - //// operation(); - //// } - //// - //<# } #> - //// - //// - //<# for (int j = 1; j <= i; j++) { #> - //// if (this._subdivisionOverride<#= j #> is null && allowMultithreading) - //// result<#= j #>.AsyncWaitHandle.WaitOne(); - //// - //<# } #> - //// - //// // build the tree - //// Add(new_top, 1, -1, additions.ToStepper(), additions.Length, - //<# for (int j = 1; j <= i; j++) { #>int.MinValue, - //<# } #>(int)additions.Length, - //<# for (int j = 1; j <= i; j++) { #>(int index) => { return values<#= j #>[index]; }, - //<# } #>allowMultithreading); - //// - //// this._top = new_top; - //// } - //// } - //// - //// - //// internal int Add(Node parent, int depth, <#= child_index_type #> child, Action> additions, int parent_count, - //<# for (int j = 1; j <= i; j++) { #>int prevmed<#= j #>, - //<# } #>int initial_count, - //<# for (int j = 1; j <= i; j++) { #>GetIndex> values<#= j #>, - //<# } #>bool allowMultithreading) - //// { - //<# for (int j = 1; j <= i; j++) { #> - //// Axis<#= j #> pointOfDivision<#= j #>; - //<# } #> - //// - //<# for (int j = 1; j <= i; j++) { #> - //// int median_axis<#= j #> = -1; - //<# } #> - //// if (this._subdivisionOverride1 is null - //<# for (int j = 2; j <= i; j++) { #> || this._subdivisionOverride<#= j #> is null - //<# } #>) - //// GetMedianIndexes(initial_count, child, depth, - //<# for (int j = 1; j <= i; j++) { #>prevmed<#= j #>, - //<# } #>out median_axis1 - //<# for (int j = 2; j <= i; j++) { #>, out median_axis<#= j #> - //<# } #>); - //// - //<# for (int j = 1; j <= i; j++) { #> - //// if (!(this._subdivisionOverride<#= j #> is null)) - //// pointOfDivision<#= j #> = this._subdivisionOverride<#= j #>(parent.Bounds, additions); - //// else - //// pointOfDivision<#= j #> = values<#= j #>(median_axis<#= j #>); - //// - //<# } #> - //// parent.PointOfDivision = new Omnitree.Vector<<#= chain_AxisX #>>(pointOfDivision1 - //<# for (int j = 2; j <= i; j++) { #>, pointOfDivision<#= j #> - //<# } #>); - //// - //// // divide the values along the medians - //// IMap, <#= child_index_type #>> collection_map = new MapHashLinked, <#= child_index_type #>>(); - //// additions((T value) => - //// { - //// <#= child_index_type #> index = DetermineChildIndex(parent.PointOfDivision.Value, LocateVector(value)); - //// IList list = null; - //// if (collection_map.TryGet(index, out list)) - //// { - //// list.Add(value); - //// } - //// else - //// { - //// if (parent_count < 100000) - //// list = new ListArray(); - //// else - //// list = new ListLinked(); - //// collection_map.Add(index, list); - //// list.Add(value); - //// } - //// }); - //// - //// if (depth == 1 && allowMultithreading) - //// { - //// // NOTE: Must assign placeholders before multithreading so that the threads do not overwrite each other - //// collection_map.Keys((<#= child_index_type #> key) => { parent[key] = new Node(Omnitree.Bounds<<#= chain_AxisX #>>.None, parent, key); }); - //// IAsyncResult[] handles = new IAsyncResult[Environment.ProcessorCount]; - //// for (int i = 0; i < handles.Length; i++) - //// { - //// int multiTheadSafe_i = i; // used as catpure variable below making it multithread-safe - //// handles[i] = ParallelThread.Run(() => - //// { - //// Step.EveryNth, <#= child_index_type #>>>(collection_map.Pairs, multiTheadSafe_i + 1)( - //// (Link, <#= child_index_type #>> link) => - //// { - //// ReversedChildBuilding(parent, link._2, depth, link._1.Stepper, link._1.Count, - //<# for (int j = 1; j <= i; j++) { #>median_axis<#= j #>, - //<# } #>initial_count, - //<# for (int j = 1; j <= i; j++) { #>values<#= j #>, - //<# } #>allowMultithreading); - //// }); - //// }); - //// } - //// - //// foreach (IAsyncResult handle in handles) - //// { - //// handle.AsyncWaitHandle.WaitOne(); - //// } - //// } - //// else - //// { - //// collection_map.Pairs((Link, <#= child_index_type #>> link) => - //// { - //// ReversedChildBuilding(parent, link._2, depth, link._1.Stepper, link._1.Count, - //<# for (int j = 1; j <= i; j++) { #>median_axis<#= j #>, - //<# } #>initial_count, - //<# for (int j = 1; j <= i; j++) { #>values<#= j #>, - //<# } #>allowMultithreading); - //// }); - //// } - //// - //// int count = 0; - //// foreach (Node node in parent.Children) - //// count += node.Count; - //// return count; - //// } - //// - //// int ReversedChildBuilding(Node parent, <#= child_index_type #> child_index, int depth, Action> additions, int count, - //<# for (int j = 1; j <= i; j++) { #>int prevmed<#= j #>, - //<# } #>int initial_count, - //<# for (int j = 1; j <= i; j++) { #>GetIndex> values<#= j #>, - //<# } #>bool allowMultithreading) - //// { - //// Omnitree.Bounds<<#= chain_AxisX #>> child_bounds = DetermineChildBounds(parent, child_index); - //// if (depth >= _load || count <= _load) - //// { - //// Node new_leaf = new Node(child_bounds, parent, child_index); - //// additions((T value) => { new_leaf.Add(value); }); - //// parent[new_leaf.Index] = new_leaf; - //// return new_leaf.Count; - //// } - //// else - //// { - //// Node new_branch = new Node(Omnitree.Vector<<#= chain_AxisX #>>.Default, child_bounds, parent, child_index); - //// parent[new_branch.Index] = new_branch; - //// new_branch.Count = Add(new_branch, depth + 1, child_index, additions, count, - //<# for (int j = 1; j <= i; j++) { #>prevmed<#= j #>, - //<# } #>count, - //<# for (int j = 1; j <= i; j++) { #>values<#= j #>, - //<# } #>allowMultithreading); - //// return new_branch.Count; - //// } - //// } - //// - //// /// Gets the indeces of the median values at the given position during bulk additions. - //// internal void GetMedianIndexes(int count, <#= child_index_type #> child_index, int depth, - //<# for (int j = 1; j <= i; j++) { #>int previous<#= j #>, - //<# } #>out int index1 - //<# for (int j = 2; j <= i; j++) { #>, out int index<#= j #> - //<# } #>) - //// { - //// if (depth == 1) - //// { - //<# for (int j = 1; j <= i; j++) { #> - //// index<#= j #> = (count - 1) / 2; - //<# } #> - //// return; - //// } - //// - //// int splits = Compute.Power(2, depth); - //// int mid_child_range = count / splits; - //// - //<# for (int j = i; j >= 1; j--) { #> - //// if (child_index >= <#= (2 << (j - 1)) / 2 #>) - //// { - //// index<#= j #> = previous<#= j #> + mid_child_range; - //// child_index -= <#= (2 << (j - 1)) / 2 #>; - //// } - //// else - //// { - //// index<#= j #> = previous<#= j #> - mid_child_range; - //// } - //// - //<# } #> - //// } - - //#endregion - - //<# } #> - - //#region single - - // /// Tries to add a value. - // /// The value to be added. - // /// The exception that occurred if the add failed. - // /// True if successful or false if not. - // public bool TryAdd(T value, out Exception exception) - // { - // Add(value); - // exception = null; - // return true; - // } - - // /// Adds an item to the tree. - // /// The item to be added. - // public void Add(T addition) - // { - // if (this._top.Count == int.MaxValue) - // throw new System.InvalidOperationException("(Count == int.MaxValue) max Omnitree size reached (change ints to longs if you need to)."); - - // // dynamic tree sizes - // Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load); - - // Omnitree.Bounds<<#= chain_AxisX #>> bounds = GetBoundings(addition); - - // // grow the first branch of the tree - // if (!this._top.PointOfDivision.HasValue && this._top.Count >= _load) - // { - // Node top = this._top; - - // // create the new branch from the median values - // this._top = new Node(DetermineMedians(top), Omnitree.Bounds<<#= chain_AxisX #>>.None, null, -1); - - // // iterate through the elements and add them to the appropriate children - // for (Node.ValueNode list = top.Head; !(list is null); list = list.Next) - // Add(list.Value, this._top, GetBoundings(list.Value), 0); - // } - - // this.Add(addition, this._top, bounds, 0); - // } - - // /// Recursive version of the add function. - // /// The item to be added. - // /// The current node for tree trversal. - // /// The bounds of the addition. - // /// The current depth of iteration. - // internal void Add(T addition, Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds, int depth) - // { - // if (!node.PointOfDivision.HasValue) - // { - // //Leaf leaf = node as Leaf; - // if (depth >= _load || !(node.Count >= _load)) - // { - // node.Add(addition); - // return; - // } - // else - // { - // //Node parent = node.Parent; - // //<#= child_index_type #> child_index = this.DetermineChildIndex(parent.PointOfDivision, location); - // //Node growth = new Node(DetermineMedians(leaf), leaf.Bounds, parent, child_index); - // //parent[child_index] = growth; - - // Node growth = new Node(DetermineMedians(node), node.Bounds, node.Parent, node.Index); - // node.Parent[node.Index] = growth; - - // for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) - // { - // Omnitree.Bounds<<#= chain_AxisX #>> temp_bounds = GetBoundings(list.Value); - // if (EncapsulationCheck(growth.Bounds, temp_bounds)) - // Add(list.Value, growth, temp_bounds, depth); - // else - // { - // ReduceParentCounts(node.Parent, 1); - // Add(list.Value, this._top, temp_bounds, depth); - // } - // } - - // Add(addition, growth, bounds, depth); - // return; - // } - // } - // else - // { - // //Node branch = node as Node; - // <#= child_index_type #> child_index = this.DetermineChildIndex(node.PointOfDivision.Value, bounds); // determine the child "index" (0 through 2^Dimensions) the addition belongs in - - // // if -1, then the bounds of the addition straddle the point of division (keep it in current node) - // if (child_index == -1) - // { - // node.Add(addition); - // return; - // } - - // Node child_node = node[child_index]; - - // // null children in branches are just empty leaves - // if (child_node is null) - // { - // Node new_node = new Node(DetermineChildBounds(node, child_index), node, child_index); - // node[child_index] = new_node; - // new_node.Add(addition); - // } - // else - // // child exists already, continue adding - // Add(addition, child_node, bounds, depth + 1); - - // node.Count++; - // return; - // } - // } - - // internal Omnitree.Vector<<#= chain_AxisX #>> DetermineMedians(Node node) - // { - // try - // { - // // extract the values - //<# for (int j = 1; j <= i; j++) { #> - // Omnitree.Bound>[] values<#= j #> = new Omnitree.Bound>[node.Count * 2]; - //<# } #> - // Node.ValueNode for_current = node.Head; // used in for loop - // for (int i = 0; i < node.Count; i++, for_current = for_current.Next) - // this._getBounds(for_current.Value, - // out values1[i * 2], out values1[i * 2 + 1] - //<# for (int j = 2; j <= i; j++) { #>, - // out values<#= j #>[i * 2], out values<#= j #>[i * 2 + 1] - //<# } #> - // ); - // return new Omnitree.Vector<<#= chain_AxisX #>>( - // Omnitree.SubDivide(values1, this._defaultCompare1 ? Compare.Default : this._compare1) - //<# for (int j = 2; j <= i; j++) { #>, - // Omnitree.SubDivide(values<#= j #>, this._defaultCompare<#= j #> ? Compare.Default : this._compare<#= j #>) - //<# } #> - // ); - // } - // catch - // { - // // extract the values - //<# for (int j = 1; j <= i; j++) { #> - // ArrayJagged>> values<#= j #> = new ArrayJagged>>(node.Count * 2); - //<# } #> - // Node.ValueNode for_current = node.Head; // used in for loop - // for (int i = 0; i < node.Count; i++, for_current = for_current.Next) - // { - //<# for (int j = 1; j <= i; j++) { #> - // Omnitree.Bound> min<#= j #>; Omnitree.Bound> max<#= j #>; - //<# } #> - // this._getBounds(for_current.Value, - // out min1, out max1 - //<# for (int j = 2; j <= i; j++) { #>, - // out min<#= j #>, out max<#= j #> - //<# } #> - // ); - //<# for (int j = 1; j <= i; j++) { #> - // values<#= j #>[i * 2] = min<#= j #>; values<#= j #>[i * 2 + 1] = max<#= j #>; - //<# } #> - // } - // return new Omnitree.Vector<<#= chain_AxisX #>>( - // Omnitree.SubDivide(values1, this._defaultCompare1 ? Compare.Default : this._compare1) - //<# for (int j = 2; j <= i; j++) { #> - // , Omnitree.SubDivide(values<#= j #>, this._defaultCompare<#= j #> ? Compare.Default : this._compare<#= j #>) - //<# } #> - // ); - // } - // } - - //#endregion - - //#region Add Helpers - - // internal Omnitree.Bounds<<#= chain_AxisX #>> DetermineChildBounds(Node node, <#= child_index_type #> child_index) - // { - // // the node parameter should always have a point of division value for this function - // Omnitree.Vector<<#= chain_AxisX #>> pointOfDivision = node.PointOfDivision.Value; - - //<# for (int j = i; j >= 1; j--) { #> - // Omnitree.Bound> min<#= j #>, max<#= j #>; - // if (child_index >= <#= (2 << (j - 1)) / 2 #>) - // { - // min<#= j #> = pointOfDivision.Axis<#= j #>; - // max<#= j #> = node.Bounds.Max<#= j #>; - // child_index -= <#= (2 << (j - 1)) / 2 #>; - // } - // else - // { - // min<#= j #> = node.Bounds.Min<#= j #>; - // max<#= j #> = pointOfDivision.Axis<#= j #>; - // } - - //<# } #> - // return new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>); - // } - - //#endregion - - //#endregion - - //#region Clear - - // /// Returns the tree to an empty state. - // public void Clear() - // { - // this._top = new Node(Omnitree.Bounds<<#= chain_AxisX #>>.None, null, -1); - // Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load); - // } - - //#endregion - - //#region Clone - - // /// Creates a shallow clone of this data structure. - // /// A shallow clone of this data structure. - // public OmnitreeBoundsLinked> Clone() - // { - // return new OmnitreeBoundsLinked>(this); - // } - - //#endregion - - //#region Count - - // /// Counts the number of items encapsulated by a sub space. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // /// The number of items in the provided sub space. - // public int CountSubSpaceEncapsulated(<#= chain_AxisX_minX_AxisX_maxX #>) - // { - // return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>)); - // } - // /// Counts the number of items encapsulated by a sub space. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // /// The number of items in the provided sub space. - // public int CountSubSpaceEncapsulated(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>) - // { - // return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>)); - // } - // /// Counts the number of items encapsulated by a sub space. - // <#= documentation_AxisX_axisX #> - // /// The number of items in the provided sub space. - // public int CountSubSpaceEncapsulated(<#= chain_AxisX_axisX #>) - // { - // return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_axisX_axisX #>)); - // } - // /// Counts the number of items encapsulated by a sub space. - // <#= documentation_AxisX_axisX #> - // /// The number of items in the provided sub space. - // public int CountSubSpaceEncapsulated(<#= chain_BoundAxisX_axisX #>) - // { - // return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_axisX_axisX #>)); - // } - - // /// Counts the number of items overlapped by a sub space. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // /// The number of items in the provided sub space. - // public int CountSubSpaceOverlapped(<#= chain_AxisX_minX_AxisX_maxX #>) - // { - // return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>)); - // } - // /// Counts the number of items overlapped by a sub space. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // /// The number of items in the provided sub space. - // public int CountSubSpaceOverlapped(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>) - // { - // return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>)); - // } - // /// Counts the number of items overlapped by a sub space. - // <#= documentation_AxisX_axisX #> - // /// The number of items in the provided sub space. - // public int CountSubSpaceOverlapped(<#= chain_AxisX_axisX #>) - // { - // return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_axisX_axisX #>)); - // } - // /// Counts the number of items overlapped by a sub space. - // <#= documentation_AxisX_axisX #> - // /// The number of items in the provided sub space. - // public int CountSubSpaceOverlapped(<#= chain_BoundAxisX_axisX #>) - // { - // return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_axisX_axisX #>)); - // } - - // internal int CountSubSpaceEncapsulated(Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds) - // { - // return CountSubSpaceBase(_top, bounds, (a, b) => EncapsulationCheck(a, b)); - // } - - // internal int CountSubSpaceOverlapped(Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds) - // { - // return CountSubSpaceBase(_top, bounds, (a, b) => InclusionCheck(a, b)); - // } - - // internal int CountSubSpaceBase( - // Node node, - // Omnitree.Bounds<<#= chain_AxisX #>> bounds, - // Omnitree.SpatialCheck>, Omnitree.Bounds<<#= chain_AxisX #>>> spatialCheck) - // { - // // adjust min/max values - // int count = 0; - // if (EncapsulationCheck(bounds, node.Bounds)) - // count += node.Count; - // else if (!node.PointOfDivision.HasValue) - // { - // for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) - // if (spatialCheck(bounds, GetBoundings(list.Value))) - // count++; - // } - // else - // { - // Node branch = node as Node; - // if (!StraddlesLines(branch.Bounds, branch.PointOfDivision.Value)) - // { - // <#= child_index_type #> child_index = DetermineChildIndex(branch.PointOfDivision.Value, bounds); - // Node child = branch[child_index]; - // if (!(child is null)) - // count += this.CountSubSpaceBase(child, bounds, spatialCheck); - // } - // else - // { - // foreach (Node child in node.Children) - // count += this.CountSubSpaceBase(child, bounds, spatialCheck); - // } - // } - // return count; - // } - - //#endregion - - //#region Update - - // /// Iterates through the entire tree and ensures each item is in the proper leaf. - // public void Update() - // { - // this.Update(this._top, 0); - // } - - // /// Recursive version of the Update method. - // /// The current node of iteration. - // /// The current depth of iteration. - // internal int Update(Node node, int depth) - // { - // int removals = 0; - - // { - // Node branch = node as Node; - // int skipped = 0; - // for (int i = 0; i + skipped < branch.Children.Length; ) - // { - // removals += this.Update(branch.Children[i], depth + 1); - // if (branch.Children[i].Count == 0) - // branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1]; - // else - // i++; - // } - // Node[] newArray = new Node[branch.Children.Length - skipped]; - // Array.Copy(branch.Children, newArray, newArray.Length); - // branch.Children = newArray; - - // if (branch.Count < _load && branch.Count != 0) - // ShrinkChild(branch.Parent, branch.Index); - // } - - // { - // Node.ValueNode current = node.Head; - // Node.ValueNode previous = null; - // while (!(current is null)) - // { - // Omnitree.Bounds<<#= chain_AxisX #>> bounds = GetBoundings(current.Value); - // if (!this.EncapsulationCheck(node.Bounds, bounds)) - // { - // removals++; - // T updated = current.Value; - // if (previous is null) - // { - // node.Head = current.Next; - // goto HeadRemoved; - // } - // else - // previous.Next = current.Next; - - // Node whereToAdd = GetEncapsulationParent(node.Parent, bounds); - - // if (whereToAdd is null) - // throw new System.Exception("an item was updated outside the range of the omnitree"); - - // this.Add(updated, whereToAdd, bounds, whereToAdd.Depth); - // } - // previous = current; - // HeadRemoved: - // current = current.Next; - // } - // } - - // node.Count -= removals; - // return removals; - // } - - // /// Iterates through the provided dimensions and ensures each item is in the proper leaf. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // public void Update(<#= chain_AxisX_minX_AxisX_maxX #>) - // { - // this.Update(new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>), this._top, 0); - // } - // /// Iterates through the provided dimensions and ensures each item is in the proper leaf. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // public void Update(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>) - // { - // this.Update(new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>), this._top, 0); - // } - // /// Iterates through the provided dimensions and ensures each item is in the proper leaf. - // <#= documentation_AxisX_axisX #> - // public void Update(<#= chain_AxisX_axisX #>) - // { - // this.Update(new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_axisX_axisX #>), this._top, 0); - // } - // /// Iterates through the provided dimensions and ensures each item is in the proper leaf. - // <#= documentation_AxisX_axisX #> - // public void Update(<#= chain_BoundAxisX_axisX #>) - // { - // this.Update(new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_axisX_axisX #>), this._top, 0); - // } - // internal int Update(Omnitree.Bounds<<#= chain_AxisX #>> bounds, Node node, int depth) - // { - // if (!InclusionCheck(bounds, node.Bounds)) - // return 0; - - // int removals = 0; - - // { - // Node branch = node as Node; - // int skipped = 0; - // for (int i = 0; i + skipped < branch.Children.Length; ) - // { - // removals += this.Update(branch.Children[i], depth + 1); - // if (branch.Children[i].Count == 0) - // branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1]; - // else - // i++; - // } - // Node[] newArray = new Node[branch.Children.Length - skipped]; - // Array.Copy(branch.Children, newArray, newArray.Length); - // branch.Children = newArray; - - // if (branch.Count < _load && branch.Count != 0) - // ShrinkChild(branch.Parent, branch.Index); - // } - - // { - // Node.ValueNode current = node.Head; - // Node.ValueNode previous = null; - // while (!(current is null)) - // { - // Omnitree.Bounds<<#= chain_AxisX #>> item_bounds = GetBoundings(current.Value); - // if (!this.EncapsulationCheck(node.Bounds, item_bounds)) - // { - // removals++; - // T updated = current.Value; - // if (previous is null) - // { - // node.Head = current.Next; - // goto HeadRemoved; - // } - // else - // previous.Next = current.Next; - // Node whereToAdd = GetEncapsulationParent(node.Parent, item_bounds); - // if (whereToAdd is null) - // throw new System.Exception("an item was updates outside the range of the omnitree"); - // this.Add(updated, whereToAdd, item_bounds, whereToAdd.Depth); - // } - // previous = current; - // HeadRemoved: - // current = current.Next; - // } - // } - - // node.Count -= removals; - // return removals; - // } - - //#endregion - - //#region Remove - - // /// Removes all the items qualified by the delegate. - // /// The predicate to qualify removals. - // public void Remove(Predicate where) - // { - // this.Remove(this._top, where); - // Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load); - // } - - // /// Recursive version of the remove method. - // /// The current node of traversal. - // /// The predicate to qualify removals. - // internal int Remove(Node node, Predicate where) - // { - // int removals = 0; - - // // children - // if (!(node.Children is null)) - // { - // int skipped = 0; - // for (int i = 0; i + skipped < node.Children.Length; ) - // { - // removals += this.Remove(node.Children[i], where); - // if (node.Children[i].Count == 0) - // node.Children[i] = node.Children[node.Children.Length - skipped++ - 1]; - // else - // i++; - // } - // Node[] newArray = new Node[node.Children.Length - skipped]; - // Array.Copy(node.Children, newArray, newArray.Length); - // node.Children = newArray; - - // if (node.Count < _load && node.Count != 0) - // ShrinkChild(node.Parent, node.Index); - // } - - // // items - // while (!(node.Head is null) && where(node.Head.Value)) - // { - // node.Head = node.Head.Next; - // removals++; - // } - // if (!(node.Head is null)) - // { - // Node.ValueNode list = node.Head; - // while (!(list.Next is null)) - // { - // if (where(list.Next.Value)) - // { - // list.Next = list.Next.Next; - // removals++; - // } - // } - // } - - // node.Count -= removals; - // return removals; - // } - - // /// Removes all the items encapsulated in a given space. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // /// The number of items that were removed. - // public void RemoveEncapsulated(<#= chain_AxisX_minX_AxisX_maxX #>) - // { - // this.RemoveEncapsulated(this._top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>)); - // } - // /// Removes all the items encapsulated in a given space. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // /// The number of items that were removed. - // public void RemoveEncapsulated(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>) - // { - // this.RemoveEncapsulated(this._top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>)); - // } - // /// Removes all the items encapsulated in a given space. - // <#= documentation_AxisX_axisX #> - // public void RemoveEncapsulated(<#= chain_BoundAxisX_axisX #>) - // { - // this.RemoveEncapsulated(this._top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_axisX_axisX #>)); - // } - // internal int RemoveEncapsulated(Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds) - // { - // int removals = this.RemoveBase(node, bounds, (a, b) => this.EncapsulationCheck(a, b)); - // Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load); - // return removals; - // } - - // /// Removes all the items overlapping a given space. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // /// The number of items that were removed. - // public void RemoveOverlapped(<#= chain_AxisX_minX_AxisX_maxX #>) - // { - // this.RemoveOverlapped(this._top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>)); - // } - // /// Removes all the items overlapping a given space. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // /// The number of items that were removed. - // public void RemoveOverlapped(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>) - // { - // this.RemoveOverlapped(this._top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>)); - // } - // internal int RemoveOverlapped(Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds) - // { - // int removals = this.RemoveBase(node, bounds, (a, b) => this.InclusionCheck(a, b)); - // Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load); - // return removals; - // } - - // internal int RemoveBase( - // Node node, - // Omnitree.Bounds<<#= chain_AxisX #>> bounds, - // Omnitree.SpatialCheck>, Omnitree.Bounds<<#= chain_AxisX #>>> spatialCheck) - // { - // int removals = 0; - // if (InclusionCheck(bounds, node.Bounds)) - // { - // // items - // Node.ValueNode current_node = node.Head; - // Node.ValueNode previous_node = null; - // while (!(current_node is null)) - // { - // Node.ValueNode temp_previous = current_node; - // if (spatialCheck(bounds, GetBoundings(current_node.Value))) - // { - // removals++; - // if (current_node == node.Head) - // node.Head = node.Head.Next; - // else - // { - // previous_node.Next = current_node.Next; - // temp_previous = previous_node; - // } - // } - // previous_node = temp_previous; - // current_node = current_node.Next; - // } - - // // children - // if (!(node.Children is null)) - // { - // int skipped = 0; - // for (int i = 0; i + skipped < node.Children.Length; ) - // { - // removals += this.RemoveBase(node.Children[i], bounds, spatialCheck); - // if (node.Children[i].Count == 0) - // node.Children[i] = node.Children[node.Children.Length - skipped++ - 1]; - // else - // i++; - // } - // Node[] newArray = new Node[node.Children.Length - skipped]; - // Array.Copy(node.Children, newArray, newArray.Length); - // node.Children = newArray; - - // // convert this branch back into a leaf - // // Note: if count is zero, it will be chopped off - // if (node.Count < _load && node.Count > 0) - // ShrinkChild(node.Parent, node.Index); - // } - // } - - // node.Count -= removals; - // return removals; - // } - - // /// Removes all the items in a given space validated by a predicate. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // /// The equality constraint of the removal. - // public void RemoveEncapsulated(<#= chain_AxisX_minX_AxisX_maxX #>, Predicate where) - // { - // this.RemoveEncapsulated(this._top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>), where); - // } - // /// Removes all the items in a given space validated by a predicate. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // /// The equality constraint of the removal. - // public void RemoveEncapsulated(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>, Predicate where) - // { - // this.RemoveEncapsulated(this._top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>), where); - // } - // internal int RemoveEncapsulated(Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds, Predicate where) - // { - // int removals = RemoveBase(node, bounds, where, (a, b) => this.EncapsulationCheck(a, b)); - // Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load); - // return removals; - // } - - // /// Removes all the items in a given space validated by a predicate. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // /// The equality constraint of the removal. - // public void RemoveOverlapped(<#= chain_AxisX_minX_AxisX_maxX #>, Predicate where) - // { - // this.RemoveOverlapped(this._top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>), where); - // } - // /// Removes all the items in a given space validated by a predicate. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // /// The equality constraint of the removal. - // public void RemoveOverlapped(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>, Predicate where) - // { - // this.RemoveOverlapped(this._top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>), where); - // } - // internal int RemoveOverlapped(Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds, Predicate where) - // { - // int removals = RemoveBase(node, bounds, where, (a, b) => this.InclusionCheck(a, b)); - // Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load); - // return removals; - // } - - // internal int RemoveBase( - // Node node, - // Omnitree.Bounds<<#= chain_AxisX #>> bounds, - // Predicate where, - // Omnitree.SpatialCheck>, Omnitree.Bounds<<#= chain_AxisX #>>> spatialCheck) - // { - // if (!InclusionCheck(node.Bounds, bounds)) - // return 0; - // int removals = 0; - - // // items - // Node.ValueNode current = node.Head; - // Node.ValueNode previous = null; - // while (!(current is null)) - // { - // if (spatialCheck(bounds, GetBoundings(current.Value)) && where(current.Value)) - // { - // removals++; - // if (previous is null) - // { - // node.Head = current.Next; - // goto HeadRemoved; - // } - // else - // previous.Next = current.Next; - // } - // previous = current; - // HeadRemoved: - // current = current.Next; - // } - - // // children - // if (!(node.Children is null)) - // { - // int skipped = 0; - // for (int i = 0; i + skipped < node.Children.Length; ) - // { - // removals += this.RemoveBase(node.Children[i], bounds, where, spatialCheck); - // if (node.Children[i].Count == 0) - // node.Children[i] = node.Children[node.Children.Length - skipped++ - 1]; - // else - // i++; - // } - // Node[] newArray = new Node[node.Children.Length - skipped]; - // Array.Copy(node.Children, newArray, newArray.Length); - // node.Children = newArray; - - // if (node.Count < _load && node.Count != 0) - // ShrinkChild(node.Parent, node.Index); - // } - - // node.Count -= removals; - // return removals; - // } - - // /// Tries to remove a value. - // /// The value to remove. - // /// The exception that occurred if the remove failed. - // /// True if successful or false if not. - // public bool TryRemove(T value, out Exception exception) - // { - // Remove(value); - // exception = null; - // return true; - // } - - // /// Removes all instances of a given value. - // public void Remove(T removal) => Omnitree.Remove(this, removal); - - // /// Removes all instances of a given value. - // public void Remove(T removal, Func equate) => Omnitree.Remove(this, removal, equate); - - // /// Removes all the items in a given space. - // <#= documentation_axisX #> - // /// The number of items that were removed. - // public void RemoveOverlapped(Axis1 axis1 - //<# for (int j = 2; j <= i; j++) { #> - // , Axis<#= j #> axis<#= j #> - //<# } #> - // ) - // { - // this.RemoveOverlapped(axis1, axis1 - //<# for (int j = 2; j <= i; j++) { #> - // , axis<#= j #>, axis<#= j #> - //<# } #> - // ); - // Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load); - // } - - // /// Removes all the items in a given space validated by a predicate. - // <#= documentation_axisX #> - // /// The equality constraint of the removal. - // public void RemoveOverlapped(<#= chain_AxisX_axisX #>, Predicate where) - // { - // this.RemoveOverlapped(axis1, axis1 - //<# for (int j = 2; j <= i; j++) { #> - // , axis<#= j #>, axis<#= j #> - //<# } #> - // , where); - // Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load); - // } - - //#endregion - - //#region Stepper And IEnumerable - - // /// Traverses every item in the tree and performs the delegate in them. - // /// The delegate to perform on every item in the tree. - // public void Stepper(Action step) => - // this.Stepper(step, this._top); - - // internal void Stepper(Action step, Node node) - // { - // Node.ValueNode list = node.Head; - // while (!(list is null)) - // { - // step(list.Value); - // list = list.Next; - // } - // if (!(node.Children is null)) - // foreach (Node child in node.Children) - // this.Stepper(step, child); - // } - - // /// Traverses every item in the tree and performs the delegate in them. - // /// The delegate to perform on every item in the tree. - // public StepStatus Stepper(Func step) => - // Stepper(step, _top); - - // internal StepStatus Stepper(Func step, Node node) - // { - // StepStatus status = StepStatus.Continue; - - // for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) - // if ((status = step(list.Value)) != StepStatus.Continue) - // break; - - // if (!(node.Children is null)) - // foreach (Node child in node.Children) - // if ((status = Stepper(step, child)) != StepStatus.Continue) - // break; - - // return status; - // } - - // /// Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions. - // /// The delegate to perform on all items in the tree within the given bounds. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // public void StepperEncapsulated(Action step, <#= chain_AxisX_minX_AxisX_maxX #>) => - // StepperEncapsulated(step, _top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>)); - - // /// Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions. - // /// The delegate to perform on all items in the tree within the given bounds. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // public void StepperEncapsulated(Action step, <#= chain_BoundAxisX_minX_BoundAxisX_maxX #>) => - // StepperEncapsulated(step, _top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>)); - - // internal void StepperEncapsulated(Action step, Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds) => - // StepperBase(step, node, bounds, (a, b) => this.EncapsulationCheck(a, b)); - - // /// Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions. - // /// The delegate to perform on all items in the tree within the given bounds. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // public void StepperOverlapped(Action step, <#= chain_AxisX_minX_AxisX_maxX #>) => - // StepperOverlapped(step, _top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>)); - - // /// Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions. - // /// The delegate to perform on all items in the tree within the given bounds. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // public void StepperOverlapped(Action step, <#= chain_BoundAxisX_minX_BoundAxisX_maxX #>) => - // StepperOverlapped(step, _top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>)); - - // internal void StepperOverlapped(Action step, Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds) => - // StepperBase(step, node, bounds, (a, b) => this.InclusionCheck(a, b)); - - // internal void StepperBase( - // Action step, - // Node node, - // Omnitree.Bounds<<#= chain_AxisX #>> bounds, - // Omnitree.SpatialCheck>, Omnitree.Bounds<<#= chain_AxisX #>>> spatialCheck) - // { - // for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) - // if (spatialCheck(bounds, GetBoundings(list.Value))) - // step(list.Value); - - // if (!(node.Children is null)) - // { - // foreach (Node child in node.Children) - // // optimization: stop bounds checking if space encapsulates node - // if (EncapsulationCheck(bounds, child.Bounds)) - // this.Stepper(step, child); - // else if (InclusionCheck(child.Bounds, bounds)) - // this.StepperBase(step, child, bounds, spatialCheck); - // } - // } - - // /// Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions. - // /// The delegate to perform on all items in the tree within the given bounds. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // public StepStatus StepperEncapsulated(Func step, <#= chain_AxisX_minX_AxisX_maxX #>) => - // StepperEncapsulated(step, _top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>)); - - // /// Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions. - // /// The delegate to perform on all items in the tree within the given bounds. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // public StepStatus StepperEncapsulated(Func step, <#= chain_BoundAxisX_minX_BoundAxisX_maxX #>) => - // StepperEncapsulated(step, _top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>)); - - // internal StepStatus StepperEncapsulated(Func step, Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds) => - // StepperBase(step, node, bounds, (a, b) => this.EncapsulationCheck(a, b)); - - // /// Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions. - // /// The delegate to perform on all items in the tree within the given bounds. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // public StepStatus StepperOverlapped(Func step, <#= chain_AxisX_minX_AxisX_maxX #>) => - // StepperOverlapped(step, _top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>)); - - // /// Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions. - // /// The delegate to perform on all items in the tree within the given bounds. - // <#= documentation_AxisX_minX_AxisX_maxX #> - // public StepStatus StepperOverlapped(Func step, <#= chain_BoundAxisX_minX_BoundAxisX_maxX #>) => - // StepperOverlapped(step, _top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>)); - - // internal StepStatus StepperOverlapped(Func step, Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds) => - // StepperBase(step, node, bounds, (a, b) => this.InclusionCheck(a, b)); - - // internal StepStatus StepperBase( - // Func step, - // Node node, - // Omnitree.Bounds<<#= chain_AxisX #>> bounds, - // Omnitree.SpatialCheck>, Omnitree.Bounds<<#= chain_AxisX #>>> spatialCheck) - // { - // StepStatus status = StepStatus.Continue; - - // for (Node.ValueNode list = node.Head; !(list is null); list = list.Next) - // if (spatialCheck(bounds, GetBoundings(list.Value)) && - // (status = step(list.Value)) != StepStatus.Continue) - // break; - - // if (!(node.Children is null)) - // { - // foreach (Node child in node.Children) - // // optimization: stop bounds checking if space encapsulates node - // if (EncapsulationCheck(bounds, child.Bounds) && - // (status = this.Stepper(step, child)) != StepStatus.Continue) - // break; - // else if (!InclusionCheck(child.Bounds, bounds) && - // (status = this.StepperBase(step, child, bounds, spatialCheck)) != StepStatus.Continue) - // break; - // } - - // return status; - // } - - // /// Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions. - // /// The delegate to perform on all items in the tree within the given bounds. - // <#= documentation_axisX #> - // public void StepperOverlapped(Action step, <#= chain_AxisX_axisX #>) => - // StepperOverlapped(step, this._top, new Omnitree.Bounds<<#= chain_AxisX #>>(axis1, axis1 - //<# for (int j = 2; j <= i; j++) { #> - // , axis<#= j #>, axis<#= j #> - //<# } #> - // )); - - // /// Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions. - // /// The delegate to perform on all items in the tree within the given bounds. - // <#= documentation_axisX #> - // public StepStatus StepperOverlapped(Func step, <#= chain_AxisX_axisX #>) => - // StepperOverlapped(step, this._top, new Omnitree.Bounds<<#= chain_AxisX #>>(axis1, axis1 - //<# for (int j = 2; j <= i; j++) { #> - // , axis<#= j #>, axis<#= j #> - //<# } #> - // )); - - // System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); - - // public System.Collections.Generic.IEnumerator GetEnumerator() - // { - // // Note: this can be optimized. - // IList list = new ListLinked(); - // Stepper(x => list.Add(x)); - // return list.GetEnumerator(); - // } - - //#endregion - - //#region Helpers - - // internal bool StraddlesLines(Omnitree.Bounds<<#= chain_AxisX #>> bounds, Omnitree.Vector<<#= chain_AxisX #>> vector) => - // Omnitree.StraddlesLines(bounds, vector - //<# for (int j = 1; j <= i; j++) { #> - // , _compare<#= j #> - //<# } #> - // ); - - // /// Computes the child index that contains the desired dimensions. - // /// The point of division to compare against. - // /// The dimensions to determine the child index. - // /// The computed child index based on the coordinates relative to the center of the node. - // internal <#= child_index_type #> DetermineChildIndex(Omnitree.Vector<<#= chain_AxisX #>> pointOfDivision, Omnitree.Bounds<<#= chain_AxisX #>> bounds) - // { - // // make sure a child encapsulates the bounds (otherwise the bounds cannot move down the tree) - // if (StraddlesLines(bounds, pointOfDivision)) - // return -1; - - // <#= child_index_type #> child = 0; - //<# for (int j = 1; j <= i; j++) { #> - // if (!bounds.Min<#= j #>.Exists || !(this._compare<#= j #>(bounds.Min<#= j #>.Value, pointOfDivision.Axis<#= j #>) == CompareResult.Less)) - // child += 1 << <#= j - 1 #>; - //<# } #> - // return child; - // } - - // /// Converts a branch back into a leaf when the count is reduced. - // /// The parent to shrink a child of. - // /// The index of the child to shrink. - // internal void ShrinkChild(Node parent, <#= child_index_type #> child_index) - // { - // Node leaf; - // Node removal = null; - // if (parent is null) // top of tree - // { - // removal = this._top; - // leaf = new Node(Omnitree.Bounds<<#= chain_AxisX #>>.None, null, -1); - // this._top = leaf; - // } - // else // non-top branch - // { - // removal = parent[child_index]; - // leaf = new Node(removal.Bounds, removal.Parent, removal.Index); - // parent[child_index] = leaf; - // } - - // this.Stepper((T step) => { leaf.Add(step); }, removal); - // } - - // /// Reduces the counts of all the parents of a given node by a given amount. - // /// The starting parent of the reduction. - // /// The amount to reduce the parent counts by. - // internal void ReduceParentCounts(Node parent, int reduction) - // { - // IncreaseParentCounts(parent, -reduction); - // } - - // /// Increases the counts of all the parents of a given node by a given amount. - // /// The starting parent of the increase. - // /// The amount to increase the parent counts by. - // internal void IncreaseParentCounts(Node parent, int increase) - // { - // Node node = parent; - // while (!(node is null)) - // { - // node.Count += increase; - // node = node.Parent; - // } - // } - - // /// Checks a node for inclusion (overlap) between two bounds. - // /// True if the spaces overlap; False if not. - // internal bool InclusionCheck(Omnitree.Bounds<<#= chain_AxisX #>> a, Omnitree.Bounds<<#= chain_AxisX #>> b) => - // Omnitree.InclusionCheck(a, b - //<# for (int j = 1; j <= i; j++) { #> - // , _compare<#= j #> - //<# } #> - // ); - - // /// Checks if a space encapsulates a point. - // /// True if the space encapsulates the point; False if not. - // internal bool EncapsulationCheck(Omnitree.Bounds<<#= chain_AxisX #>> bounds, Omnitree.Vector<<#= chain_AxisX #>> vector) => - // Omnitree.EncapsulationCheck(bounds, vector - //<# for (int j = 1; j <= i; j++) { #> - // , _compare<#= j #> - //<# } #> - // ); - - // /// Checks if a space (left) encapsulates another space (right). - // /// True if the left space encapsulates the right; False if not. - // internal bool EncapsulationCheck(Omnitree.Bounds<<#= chain_AxisX #>> a, Omnitree.Bounds<<#= chain_AxisX #>> b) => - // Omnitree.EncapsulationCheck(a, b - //<# for (int j = 1; j <= i; j++) { #> - // , _compare<#= j #> - //<# } #> - // ); - - // /// Checks for equality between two locations. - // /// True if equal; False if not; - // internal bool EqualsCheck(Omnitree.Vector<<#= chain_AxisX #>> a, Omnitree.Vector<<#= chain_AxisX #>> b) => - // Omnitree.EqualsCheck(a, b - //<# for (int j = 1; j <= i; j++) { #> - // , Equate.FromCompare(_compare<#= j #>) - //<# } #> - // ); - - // /// Gets the nearest parent that encapsulates a location. - // /// The starting node to find the encapsulating parent of the location. - // /// The bounds to get the encapsulating parent from. - // /// The nearest node that encapsulates the given location. - // internal Node GetEncapsulationParent(Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds) - // { - // while (!(node is null) && !EncapsulationCheck(node.Bounds, bounds)) - // { - // node = node.Parent; - // } - // return node; - // } - - // internal Omnitree.Bounds<<#= chain_AxisX #>> GetBoundings(T value) - // { - //<# for (int j = 1; j <= i; j++) { #> - // Omnitree.Bound> min<#= j #>; Omnitree.Bound> max<#= j #>; - //<# } #> - // this._getBounds(value, - // out min1, out max1 - //<# for (int j = 2; j <= i; j++) { #>, - // out min<#= j #>, out max<#= j #> - //<# } #> - // ); - // return new Omnitree.Bounds<<#= chain_AxisX #>>( - // min1, max1 - //<# for (int j = 2; j <= i; j++) { #>, - // min<#= j #>, max<#= j #> - //<# } #> - // ); - // } - - //#endregion - - //#endregion - // } - - //#endregion - //<# } #> - - //#endregion - //} - - - - //File.WriteAllText("../../../temp.cs", file.ToString()); + File.WriteAllText(Path.GetDirectoryName(sourcefilepath()) + Path.Combine("..", "..","..","Sources","Towel", "DataStructures", "Omnitree2.cs"), file.ToString()); } } } diff --git a/Tools/Towel_Generating/Towel_Generating.csproj b/Tools/Towel_Generating/Towel_Generating.csproj index 6201e2a8..f80c073d 100644 --- a/Tools/Towel_Generating/Towel_Generating.csproj +++ b/Tools/Towel_Generating/Towel_Generating.csproj @@ -5,6 +5,6 @@ net5.0 - + From 7122385dff59ed5392d9b3a250401602187a429b Mon Sep 17 00:00:00 2001 From: Zachary Patten Date: Mon, 16 Nov 2020 20:33:03 -0500 Subject: [PATCH 20/30] omnitree code gen updates --- Tools/Towel_Generating/Omnitree.cs | 24 ++++++++++++++++++- .../Towel_Generating/Towel_Generating.csproj | 2 +- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/Tools/Towel_Generating/Omnitree.cs b/Tools/Towel_Generating/Omnitree.cs index 55d2e8f4..631794f0 100644 --- a/Tools/Towel_Generating/Omnitree.cs +++ b/Tools/Towel_Generating/Omnitree.cs @@ -253,8 +253,30 @@ internal static void Generate( file.AppendLine($@" // todo"); file.AppendLine($@" }}"); file.AppendLine($@""); - file.AppendLine($@" public interface OmnitreePoints $"A{n}", ", ")}, {Join(1..(i + 1), n => $"Compare{n}", ", ")}> : IOmnitree $"A{n}", ", ")}, {Join(1..(i + 1), n => $"Compare{n}", ", ")}>"); + file.AppendLine($@" public class OmnitreePoints $"A{n}", ", ")}, {Join(1..(i + 1), n => $"Compare{n}", ", ")}, Locate> : IOmnitree $"A{n}", ", ")}, {Join(1..(i + 1), n => $"Compare{n}", ", ")}>"); + for (int j = 1; j <= i; j++) + { + file.AppendLine($@" where Compare{j} : struct, IFunc"); + } + file.AppendLine($@" where Locate : struct, IFunc $"A{n}", ", ")}{(i is 1 ? "" : ")")}>"); file.AppendLine($@" {{"); + file.AppendLine($@" internal readonly static {(i > 30 ? "BigInteger" : "int")} ChildrenPerNode = {(i > 30 ? $"BigInteger.Pow(2, {i})" : $"{Math.Pow(2, i)}")};"); + file.AppendLine($@""); + file.AppendLine($@" internal Node _top;"); + file.AppendLine($@" /// Caches the next time to calculate loads (lower count)."); + file.AppendLine($@" internal int _naturalLogLower = 1;"); + file.AppendLine($@" /// Caches the next time to calculate loads (upper count)."); + file.AppendLine($@" internal int _naturalLogUpper = 1;"); + file.AppendLine($@" /// ln(count); min = _defaultLoad."); + file.AppendLine($@" internal int _load = 1;"); + for (int j = 1; j <= i; j++) + { + file.AppendLine($@" internal Compare{j} _compare{j};"); + } + file.AppendLine($@" internal Locate _locate;"); + + + file.AppendLine($@" }}"); file.AppendLine($@""); file.AppendLine($@" #endregion OmnitreePoints"); diff --git a/Tools/Towel_Generating/Towel_Generating.csproj b/Tools/Towel_Generating/Towel_Generating.csproj index f80c073d..eb631890 100644 --- a/Tools/Towel_Generating/Towel_Generating.csproj +++ b/Tools/Towel_Generating/Towel_Generating.csproj @@ -5,6 +5,6 @@ net5.0 - + From ecb612b1f48faf8fb74f84c93bfd2612bfe16391 Mon Sep 17 00:00:00 2001 From: Zachary Patten Date: Mon, 16 Nov 2020 22:38:21 -0500 Subject: [PATCH 21/30] System.Range GetEnumerator + ToIEnumerable (change) --- Sources/Towel/Extensions.cs | 31 +++++++++++++++++++++++++++---- Sources/Towel/Towel.xml | 7 +++++++ Tools/Towel_Testing/Extensions.cs | 24 +++++++++++++++++++++++- 3 files changed, 57 insertions(+), 5 deletions(-) diff --git a/Sources/Towel/Extensions.cs b/Sources/Towel/Extensions.cs index 88b6a073..36a0286d 100644 --- a/Sources/Towel/Extensions.cs +++ b/Sources/Towel/Extensions.cs @@ -1437,16 +1437,39 @@ public static bool IsDefined(this T value) where T : Enum => /// Converts a to an . /// The to convert int a . /// The resulting of the conversion. + /// range.Start.IsFromEnd + /// range.End.IsFromEnd internal static System.Collections.Generic.IEnumerable ToIEnumerable(this Range range) { - int a = range.Start.Value < range.End.Value ? range.Start.Value : range.End.Value; - int b = range.Start.Value > range.End.Value ? range.Start.Value : range.End.Value; - for (int i = a; i < b; i++) + if (range.Start.IsFromEnd) { - yield return i; + throw new ArgumentException($"{nameof(range)}.{nameof(range.Start)}.{nameof(range.Start.IsFromEnd)}", nameof(range)); + } + if (range.End.IsFromEnd) + { + throw new ArgumentException($"{nameof(range)}.{nameof(range.End)}.{nameof(range.End.IsFromEnd)}", nameof(range)); + } + if (range.End.Value < range.Start.Value) + { + for (int i = range.Start.Value; i > range.End.Value; i--) + { + yield return i; + } + } + else + { + for (int i = range.Start.Value; i < range.End.Value; i++) + { + yield return i; + } } } + /// Returns an that iterates through the . + /// The range to get the of. + /// An that iterates through the . + public static System.Collections.Generic.IEnumerator GetEnumerator(this Range range) => ToIEnumerable(range).GetEnumerator(); + #endregion #region Step diff --git a/Sources/Towel/Towel.xml b/Sources/Towel/Towel.xml index 99a26a1b..aa00e4c4 100644 --- a/Sources/Towel/Towel.xml +++ b/Sources/Towel/Towel.xml @@ -15618,6 +15618,13 @@ Converts a to an . The to convert int a . The resulting of the conversion. + range.Start.IsFromEnd + range.End.IsFromEnd + + + Returns an that iterates through the . + The range to get the of. + An that iterates through the . Adds a step to the gaps (in-betweens) of another step funtion. diff --git a/Tools/Towel_Testing/Extensions.cs b/Tools/Towel_Testing/Extensions.cs index 0e8c410e..d3d5acd7 100644 --- a/Tools/Towel_Testing/Extensions.cs +++ b/Tools/Towel_Testing/Extensions.cs @@ -1,7 +1,9 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using System; using Towel; +using static Towel.Statics; using Towel.DataStructures; +using System.Linq; namespace Towel_Testing { @@ -228,6 +230,26 @@ [TestMethod] public void Random_NextDecimal() } #endregion + + #region System.Range + + [TestMethod] public void GetEnumerator_Range() + { + Assert.IsTrue(Equate((0..4).ToIEnumerable().ToArray(), new[] { 0, 1, 2, 3 })); + Assert.IsTrue(Equate((4..0).ToIEnumerable().ToArray(), new[] { 4, 3, 2, 1 })); + + Assert.IsTrue(Equate((11..14).ToIEnumerable().ToArray(), new[] { 11, 12, 13 })); + Assert.IsTrue(Equate((14..11).ToIEnumerable().ToArray(), new[] { 14, 13, 12 })); + + //// unfortuntately System.Range syntax does not support negative values + //Assert.IsTrue(Equate((0..-3).ToIEnumerable().ToArray(), new[] { 0, -1, -2 })); + //Assert.IsTrue(Equate((-3..0).ToIEnumerable().ToArray(), new[] { -3, -2, -1 })); + + Assert.ThrowsException(() => (^0..4).ToIEnumerable().ToArray()); + Assert.ThrowsException(() => (0..^4).ToIEnumerable().ToArray()); + Assert.ThrowsException(() => (^0..^4).ToIEnumerable().ToArray()); + } + + #endregion } } - From 487c6a4a1526b310e44eaa4c19d0cfa50c3308f2 Mon Sep 17 00:00:00 2001 From: Zachary Patten Date: Thu, 19 Nov 2020 00:04:04 -0500 Subject: [PATCH 22/30] IsOrdered FilterOrdered SortCycle --- Examples/BasicsAndExtensions/Program.cs | 135 ++++++------ Sources/Towel/Statics.cs | 277 +++++++++++++++++++++--- Sources/Towel/Towel.xml | 46 +++- Tools/Towel_Benchmarking/Sort.cs | 6 + Tools/Towel_Testing/Statics.cs | 96 +++----- 5 files changed, 398 insertions(+), 162 deletions(-) diff --git a/Examples/BasicsAndExtensions/Program.cs b/Examples/BasicsAndExtensions/Program.cs index 7d9662f1..1e9ecb97 100644 --- a/Examples/BasicsAndExtensions/Program.cs +++ b/Examples/BasicsAndExtensions/Program.cs @@ -241,103 +241,108 @@ static void Main() Console.WriteLine(" Sorting Algorithms----------------------"); Console.WriteLine(); - int[] dataSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; - Console.Write($" Data Set: {string.Join(", ", dataSet.Select(x => x.ToString()))}"); - Console.WriteLine(); - // Shuffling (Randomizing) - Shuffle(dataSet); - Console.Write($" Shuffle (Randomizing): {string.Join(", ", dataSet.Select(x => x.ToString()))}"); - Console.WriteLine(); - - void ShuffleDataSet() - { - Console.WriteLine(" shuffling dataSet..."); - Shuffle(dataSet); - } + int[] dataSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; string DataSetToString() => string.Join(", ", dataSet.Select(x => x.ToString())); - Console.WriteLine(); + Console.WriteLine($" Data Set: {DataSetToString()}"); + + Shuffle(dataSet); + Console.WriteLine($" Shuffle: {DataSetToString()}"); - // Bubble SortBubble(dataSet); - Console.Write($" Bubble: {DataSetToString()}"); - Console.WriteLine(); + Console.WriteLine($" Bubble: {DataSetToString()}"); - // Selection - ShuffleDataSet(); + Shuffle(dataSet); SortSelection(dataSet); - Console.Write($" Selection: {DataSetToString()}"); - Console.WriteLine(); + Console.WriteLine($" Selection: {DataSetToString()}"); - // Insertion - ShuffleDataSet(); + Shuffle(dataSet); SortInsertion(dataSet); - Console.Write($" Insertion: {DataSetToString()}"); - Console.WriteLine(); + Console.WriteLine($" Insertion: {DataSetToString()}"); - // Quick - ShuffleDataSet(); + Shuffle(dataSet); SortQuick(dataSet); - Console.Write($" Quick: {DataSetToString()}"); - Console.WriteLine(); + Console.WriteLine($" Quick: {DataSetToString()}"); - // Merge - ShuffleDataSet(); + Shuffle(dataSet); SortMerge(dataSet); - Console.Write($" Merge: {DataSetToString()}"); - Console.WriteLine(); + Console.WriteLine($" Merge: {DataSetToString()}"); - // Heap - ShuffleDataSet(); + Shuffle(dataSet); SortHeap(dataSet); - Console.Write($" Heap: {DataSetToString()}"); - Console.WriteLine(); + Console.WriteLine($" Heap: {DataSetToString()}"); - // OddEven - ShuffleDataSet(); + Shuffle(dataSet); SortOddEven(dataSet); - Console.Write($" OddEven: {DataSetToString()}"); - Console.WriteLine(); + Console.WriteLine($" OddEven: {DataSetToString()}"); - // Slow - ShuffleDataSet(); + Shuffle(dataSet); SortSlow(dataSet); - Console.Write($" Slow: {DataSetToString()}"); - Console.WriteLine(); + Console.WriteLine($" Slow: {DataSetToString()}"); - // Cocktail - ShuffleDataSet(); + Shuffle(dataSet); SortCocktail(dataSet); - Console.Write($" Cocktail: {DataSetToString()}"); - Console.WriteLine(); + Console.WriteLine($" Cocktail: {DataSetToString()}"); - // Shell - ShuffleDataSet(); + Shuffle(dataSet); SortShell(dataSet); - Console.Write($" Shell: {DataSetToString()}"); - Console.WriteLine(); + Console.WriteLine($" Shell: {DataSetToString()}"); - // Gnome - ShuffleDataSet(); + Shuffle(dataSet); SortGnome(dataSet); - Console.Write($" Gnome: {DataSetToString()}"); - Console.WriteLine(); + Console.WriteLine($" Gnome: {DataSetToString()}"); - // Comb - ShuffleDataSet(); + Shuffle(dataSet); SortComb(dataSet); - Console.Write($" Comb: {DataSetToString()}"); + Console.WriteLine($" Comb: {DataSetToString()}"); + + Shuffle(dataSet); + SortCycle(dataSet); + Console.WriteLine($" Cycle: {DataSetToString()}"); + + Shuffle(dataSet); + Console.WriteLine(" Bogo: Disabled (usually very slow...)"); + //SortBogo(dataSet); + //Console.WriteLine($" Bogo: {DataSetToString()}"); + Console.WriteLine(); + } + #endregion + + #region IsOrdered + { + int[] a = { 1, 2, 3, 4, 5 }; // least to greatest + int[] b = { 5, 4, 3, 2, 1 }; // greatest to least + int[] c = { 1, 5, 3, 4, 2 }; // unordered + string[] d = { "a", "ba", "cba", "dcba", }; // least to greatest (strings) - // Bogo - ShuffleDataSet(); - Console.Write(" Bogo: Disabled (usually very slow...)"); - //Sort.Bogo(dataSet); - //Console.Write(" Bogo: " + string.Join(", ", dataSet.Select(x => x.ToString()))); + Console.WriteLine(" IsOrdered------------------------------------"); Console.WriteLine(); + Console.WriteLine($" IsOrdered({string.Join(", ", a)}) := {IsOrdered(a)}"); + Console.WriteLine($" IsOrdered({string.Join(", ", b)}, (a, b) => Compare(b, a)) := {IsOrdered(b, (a, b) => Compare(b, a))}"); + Console.WriteLine($" IsOrdered({string.Join(", ", c)}) := {IsOrdered(c)}"); + Console.WriteLine($" IsOrdered({string.Join(", ", d)}) := {IsOrdered(d)}"); + Console.WriteLine(); + } + #endregion + #region FilterOrdered + { + int[] a = { 1, 2, 3 }; + int[] b = { 1, -1, 2, -2, 3, -3 }; + + Console.WriteLine(" FilterOrdered------------------------------------"); + Console.WriteLine(); + Console.WriteLine(" Filters out values that are not in order."); + Console.WriteLine(); + Console.Write($" FilterOrdered({string.Join(", ", a)}) :="); + FilterOrdered(a, i => Console.Write(" " + i)); + Console.WriteLine(); + Console.Write($" FilterOrdered({string.Join(", ", b)}) :="); + FilterOrdered(b, i => Console.Write(" " + i)); + Console.WriteLine(); Console.WriteLine(); } #endregion diff --git a/Sources/Towel/Statics.cs b/Sources/Towel/Statics.cs index 4f0f3557..0a92c18c 100644 --- a/Sources/Towel/Statics.cs +++ b/Sources/Towel/Statics.cs @@ -4625,10 +4625,10 @@ public static void SortSelection(Span span, Func? com public static void SortSelection(Span span, Compare compare = default) where Compare : struct, IFunc { - for (int i = 0; i <= span.Length - 1; i++) + for (int i = 0; i < span.Length; i++) { int min = i; - for (int j = i + 1; j <= span.Length - 2; j++) + for (int j = i + 1; j < span.Length; j++) { if (compare.Do(span[j], span[min]) is Less) { @@ -5260,21 +5260,10 @@ public static void SortBogo(int start, int end, Co where Set : struct, IAction where Random : struct, IFunc { - while (!SortBogoCheck(start, end)) + while (!IsOrdered(start, end, compare, get)) { Shuffle(start, end, get, set, random); } - bool SortBogoCheck(int start, int end) - { - for (int i = start; i <= end - 1; i++) - { - if (compare.Do(get.Do(i), get.Do(i + 1)) is Greater) - { - return false; - } - } - return true; - } } /// @@ -5291,20 +5280,9 @@ public static void SortBogo(Span span, Compare compare = where Compare : struct, IFunc where Random : struct, IFunc { - while (!SortBogoCheck(span)) - { - Shuffle(span, random); - } - bool SortBogoCheck(Span span) + while (!IsOrdered(span, compare)) { - for (int i = 1; i < span.Length; i++) - { - if (compare.Do(span[i - 1], span[i]) is Greater) - { - return false; - } - } - return true; + Shuffle(span, random); } } @@ -5570,7 +5548,7 @@ public static void SortShell(Span span, Compare compare = default #region SortCocktail - /// Sorts values using the shell sort algorithm. + /// Sorts values using the cocktail sort algorithm. /// [Obsolete(TowelConstants.NotIntended, true)] internal static void SortCocktail_XML() => throw new DocumentationMethodException(); @@ -5661,6 +5639,249 @@ public static void SortCocktail(Span span, Compare compare = defa #endregion + #region SortCycle + + /// Sorts values using the shell cycle algorithm. + /// + [Obsolete(TowelConstants.NotIntended, true)] + internal static void SortCycle_XML() => throw new DocumentationMethodException(); + + /// + public static void SortCycle(int start, int end, Func get, Action set, Func? compare = null) => + SortCycle, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); + + /// + public static void SortCycle(int start, int end, Compare compare = default, Get get = default, Set set = default) + where Compare : struct, IFunc + where Get : struct, IFunc + where Set : struct, IAction + { + for (int i = start; i < end; i++) + { + T pivot = get.Do(i); + int index = i; + for (int j = i + 1; j <= end; j++) + { + if (compare.Do(get.Do(j), pivot) is Less) + { + index++; + } + } + if (index == i) + { + continue; + } + while (compare.Do(pivot, get.Do(index)) is Equal) + { + index++; + } + if (index != i) + { + T temp = pivot; + pivot = get.Do(index); + set.Do(index, temp); + } + while (index != i) + { + index = i; + for (int j = i + 1; j <= end; j++) + { + if (compare.Do(get.Do(j), pivot) is Less) + { + index++; + } + } + while (compare.Do(pivot, get.Do(index)) is Equal) + { + index += 1; + } + if (compare.Do(pivot, get.Do(index)) is not Equal) + { + T temp = pivot; + pivot = get.Do(index); + set.Do(index, temp); + } + } + } + } + + /// + public static void SortCycle(Span span, Func? compare = null) => + SortCycle>(span, compare ?? Compare); + + /// + public static void SortCycle(Span span, Compare compare = default) + where Compare : struct, IFunc + { + for (int i = 0; i < span.Length - 1; i++) + { + T pivot = span[i]; + int index = i; + for (int j = i + 1; j < span.Length; j++) + { + if (compare.Do(span[j], pivot) is Less) + { + index++; + } + } + if (index == i) + { + continue; + } + while (compare.Do(pivot, span[index]) is Equal) + { + index++; + } + if (index != i) + { + Swap(ref span[index], ref pivot); + } + while (index != i) + { + index = i; + for (int j = i + 1; j < span.Length; j++) + { + if (compare.Do(span[j], pivot) is Less) + { + index++; + } + } + while (compare.Do(pivot, span[index]) is Equal) + { + index += 1; + } + if (compare.Do(pivot, span[index]) is not Equal) + { + Swap(ref span[index], ref pivot); + } + } + } + } + + #endregion + + #endregion + + #region FilterOrdered + + public static void FilterOrdered(int start, int end, Func get, Action step, Func? compare = null) => + FilterOrdered, ActionRuntime, FuncRuntime>(start, end, get, step, compare ?? Compare); + + public static void FilterOrdered(int start, int end, Get get = default, Step step = default, Compare compare = default) + where Get : struct, IFunc + where Step : struct, IAction + where Compare : struct, IFunc + { + if (start <= end) + { + step.Do(get.Do(start)); + } + for (int i = start; i <= end; i++) + { + if (compare.Do(get.Do(i - 1), get.Do(i)) is not Greater) + { + step.Do(get.Do(i)); + } + } + } + + public static void FilterOrdered(ReadOnlySpan span, Action step, Func? compare = null) => + FilterOrdered, FuncRuntime>(span, step, compare ?? Compare); + + public static void FilterOrdered(ReadOnlySpan span, Step step = default, Compare compare = default) + where Step : struct, IAction + where Compare : struct, IFunc + { + if (!span.IsEmpty) + { + step.Do(span[0]); + } + for (int i = 1; i < span.Length; i++) + { + if (compare.Do(span[i - 1], span[i]) is not Greater) + { + step.Do(span[i]); + } + } + } + + #endregion + + #region IsOrdered + +#pragma warning disable CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name +#pragma warning disable CS1572 // XML comment has a param tag, but there is no parameter by that name + /// The type of values to sort. + /// The compare function. + /// The get function. + /// The compare function. + /// The get function. + /// The starting index of the sort. + /// The ending index of the sort. + /// The span to be sorted. + [Obsolete(TowelConstants.NotIntended, true)] + internal static void IsOrdered_XML() => throw new DocumentationMethodException(); +#pragma warning restore CS1572 // XML comment has a param tag, but there is no parameter by that name +#pragma warning restore CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name + + /// + public static bool IsOrdered(int start, int end, Func get, Func? compare = null) => + IsOrdered, FuncRuntime>(start, end, compare ?? Compare, get); + + /// + public static bool IsOrdered(int start, int end, Compare compare = default, Get get = default) + where Compare : struct, IFunc + where Get : struct, IFunc + { + for (int i = start + 1; i <= end; i++) + { + if (compare.Do(get.Do(i - 1), get.Do(i)) is Greater) + { + return false; + } + } + return true; + } + + /// + public static bool IsOrdered(ReadOnlySpan span, Func? compare = null) => + IsOrdered>(span, compare ?? Compare); + + /// + public static bool IsOrdered(ReadOnlySpan span, Compare compare = default) + where Compare : struct, IFunc + { + for (int i = 1; i < span.Length; i++) + { + if (compare.Do(span[i - 1], span[i]) is Greater) + { + return false; + } + } + return true; + } + + /// + public static bool IsOrdered(this System.Collections.Generic.IEnumerable enumerable, Func? compare = null) => + IsOrdered>(enumerable, compare ?? Compare); + + /// + public static bool IsOrdered(this System.Collections.Generic.IEnumerable enumerable, Compare compare = default) + where Compare : struct, IFunc + { + System.Collections.Generic.IEnumerator enumerator = enumerable.GetEnumerator(); + T previous = enumerator.Current; + while (enumerator.MoveNext()) + { + if (compare.Do(previous, enumerator.Current) is Greater) + { + return false; + } + previous = enumerator.Current; + } + return true; + } + #endregion #region NextUnique diff --git a/Sources/Towel/Towel.xml b/Sources/Towel/Towel.xml index aa00e4c4..baa76ebd 100644 --- a/Sources/Towel/Towel.xml +++ b/Sources/Towel/Towel.xml @@ -31809,7 +31809,7 @@ - Sorts values using the shell sort algorithm. + Sorts values using the cocktail sort algorithm. @@ -31824,6 +31824,50 @@ + + Sorts values using the shell cycle algorithm. + + + + + + + + + + + + + + + + The type of values to sort. + The compare function. + The get function. + The compare function. + The get function. + The starting index of the sort. + The ending index of the sort. + The span to be sorted. + + + + + + + + + + + + + + + + + + + Generates unique random values in the diff --git a/Tools/Towel_Benchmarking/Sort.cs b/Tools/Towel_Benchmarking/Sort.cs index 37a97938..2ee38f63 100644 --- a/Tools/Towel_Benchmarking/Sort.cs +++ b/Tools/Towel_Benchmarking/Sort.cs @@ -95,6 +95,12 @@ [Benchmark] public void CocktailRunTime() => [Benchmark] public void CocktailCompileTime() => SortCocktail(Values); + [Benchmark] public void CycleRunTime() => + SortCycle(Values); + + [Benchmark] public void CycleCompileTime() => + SortCycle(Values); + [Benchmark] public void SlowRunTime() { if (Values.Length > 10) diff --git a/Tools/Towel_Testing/Statics.cs b/Tools/Towel_Testing/Statics.cs index 4e277e7b..4ab93748 100644 --- a/Tools/Towel_Testing/Statics.cs +++ b/Tools/Towel_Testing/Statics.cs @@ -1591,18 +1591,6 @@ [TestMethod] public void SearchBinary_Test() public const int SortSize = 10; public const int SortRandomSeed = 7; - public static bool IsLeastToGreatest(T[] array) - { - for (int i = 0; i < array.Length - 1; i++) - { - if (Compare(array[i], array[i + 1]) is Greater) - { - return false; - } - } - return true; - } - public static void TestAlgorithm( Action> algorithm, Action> algorithmPartial, @@ -1614,9 +1602,9 @@ void Test(int sizeAdjusted) int[] array = new int[sizeAdjusted]; Extensions.Iterate(sizeAdjusted, i => array[i] = i); Shuffle(array, random); - Assert.IsFalse(IsLeastToGreatest(array), "Test failed (invalid randomization)."); + Assert.IsFalse(IsOrdered(array), "Test failed (invalid randomization)."); algorithm(array, Compare); - Assert.IsTrue(IsLeastToGreatest(array), "Sorting algorithm failed."); + Assert.IsTrue(IsOrdered(array), "Sorting algorithm failed."); } Test(sizeOverride ?? SortSize); // Even Data Set @@ -1641,7 +1629,7 @@ public void Shuffle_Testing() int[] array = new int[SortSize]; Extensions.Iterate(SortSize, i => array[i] = i); Shuffle(array, random); - Assert.IsFalse(IsLeastToGreatest(array)); + Assert.IsFalse(IsOrdered(array)); } [TestMethod] @@ -1705,22 +1693,23 @@ public void Cocktail_Testing() => TestAlgorithm( (array, compare) => SortCocktail(0, array.Length - 1, i => array[i], (i, v) => array[i] = v, compare), (array, start, end, compare) => SortCocktail(start, end, i => array[i], (i, v) => array[i] = v, compare)); + [TestMethod] + public void Cycle_Testing() => TestAlgorithm( + (array, compare) => SortCycle(0, array.Length - 1, i => array[i], (i, v) => array[i] = v, compare), + (array, start, end, compare) => SortCycle(start, end, i => array[i], (i, v) => array[i] = v, compare)); + [TestMethod] public void Bogo_Testing() => TestAlgorithm( (array, compare) => SortBogo(array, compare), (array, start, end, compare) => SortBogo(start, end, i => array[i], (i, v) => array[i] = v, compare), 6); - [TestMethod] public void BubbleSpan_Test() { Span span = new[] { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; SortBubble(span); - for (int i = 1; i < span.Length; i++) - { - Assert.IsTrue(span[i - 1] <= span[i]); - } + IsOrdered(span); } [TestMethod] @@ -1728,10 +1717,7 @@ public void InsertionSpan_Test() { Span span = new[] { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; SortInsertion(span); - for (int i = 1; i < span.Length; i++) - { - Assert.IsTrue(span[i - 1] <= span[i]); - } + IsOrdered(span); } [TestMethod] @@ -1739,10 +1725,7 @@ public void SelectionSpan_Test() { Span span = new[] { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; SortInsertion(span); - for (int i = 1; i < span.Length; i++) - { - Assert.IsTrue(span[i - 1] <= span[i]); - } + IsOrdered(span); } [TestMethod] @@ -1750,10 +1733,7 @@ public void MergeSpan_Test() { Span span = new[] { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; SortMerge(span); - for (int i = 1; i < span.Length; i++) - { - Assert.IsTrue(span[i - 1] <= span[i]); - } + IsOrdered(span); } [TestMethod] @@ -1761,10 +1741,7 @@ public void QuickSpan_Test() { Span span = new[] { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; SortQuick(span); - for (int i = 1; i < span.Length; i++) - { - Assert.IsTrue(span[i - 1] <= span[i]); - } + IsOrdered(span); } [TestMethod] @@ -1772,10 +1749,7 @@ public void HeapSpan_Test() { Span span = new[] { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; SortHeap(span); - for (int i = 1; i < span.Length; i++) - { - Assert.IsTrue(span[i - 1] <= span[i]); - } + IsOrdered(span); } [TestMethod] @@ -1783,10 +1757,7 @@ public void OddEvenSpan_Test() { Span span = new[] { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; SortOddEven(span); - for (int i = 1; i < span.Length; i++) - { - Assert.IsTrue(span[i - 1] <= span[i]); - } + IsOrdered(span); } [TestMethod] @@ -1794,10 +1765,7 @@ public void SlowSpan_Test() { Span span = new[] { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; SortSlow(span); - for (int i = 1; i < span.Length; i++) - { - Assert.IsTrue(span[i - 1] <= span[i]); - } + IsOrdered(span); } [TestMethod] @@ -1805,10 +1773,7 @@ public void GnomeSpan_Test() { Span span = new[] { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; SortGnome(span); - for (int i = 1; i < span.Length; i++) - { - Assert.IsTrue(span[i - 1] <= span[i]); - } + IsOrdered(span); } [TestMethod] @@ -1816,10 +1781,7 @@ public void CombSpan_Test() { Span span = new[] { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; SortComb(span); - for (int i = 1; i < span.Length; i++) - { - Assert.IsTrue(span[i - 1] <= span[i]); - } + IsOrdered(span); } [TestMethod] @@ -1827,10 +1789,7 @@ public void ShellSpan_Test() { Span span = new[] { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; SortShell(span); - for (int i = 1; i < span.Length; i++) - { - Assert.IsTrue(span[i - 1] <= span[i]); - } + IsOrdered(span); } [TestMethod] @@ -1838,10 +1797,14 @@ public void CocktailSpan_Test() { Span span = new[] { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; SortCocktail(span); - for (int i = 1; i < span.Length; i++) - { - Assert.IsTrue(span[i - 1] <= span[i]); - } + IsOrdered(span); + } + + [TestMethod] public void CycleSpan_Test() + { + Span span = new[] { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; + SortCycle(span); + IsOrdered(span); } [TestMethod] @@ -1849,10 +1812,7 @@ public void BogoSpan_Test() { Span span = new[] { 5, 4, 3, 2, 1, 0 }; SortBogo(span); - for (int i = 1; i < span.Length; i++) - { - Assert.IsTrue(span[i - 1] <= span[i]); - } + IsOrdered(span); } #endregion From 332cd65f181e6e5d9f81f788269f8f1b013d2b1a Mon Sep 17 00:00:00 2001 From: Zachary Patten Date: Fri, 20 Nov 2020 20:54:53 -0500 Subject: [PATCH 23/30] Code Clean Up, TryParseRomanNumeral, SortPancake, SortStooge --- Examples/GraphSearch/Program.cs | 237 +- .../Towel/Extensions-NumericEnglishWords.cs | 272 + Sources/Towel/Extensions-Random.cs | 437 ++ Sources/Towel/Extensions.cs | 776 +-- Sources/Towel/Statics-Permutations.cs | 219 + Sources/Towel/Statics-Random.cs | 183 + Sources/Towel/Statics-RomanNumerals.cs | 103 + Sources/Towel/Statics-SearchingAlgorithms.cs | 582 ++ Sources/Towel/Statics-SequenceAnalysis.cs | 1250 +++++ Sources/Towel/Statics-SortingAlgorithms.cs | 1331 +++++ Sources/Towel/Statics-Structs.cs | 68 + Sources/Towel/Statics-SyntaxHacks.cs | 536 ++ Sources/Towel/Statics-Trigonometry.cs | 525 ++ Sources/Towel/Statics.cs | 4702 +---------------- Sources/Towel/Towel.xml | 4001 +++++++------- Tools/Towel_Benchmarking/Sort.cs | 12 + Tools/Towel_Testing/Statics.cs | 11 +- 17 files changed, 7792 insertions(+), 7453 deletions(-) create mode 100644 Sources/Towel/Extensions-NumericEnglishWords.cs create mode 100644 Sources/Towel/Extensions-Random.cs create mode 100644 Sources/Towel/Statics-Permutations.cs create mode 100644 Sources/Towel/Statics-Random.cs create mode 100644 Sources/Towel/Statics-RomanNumerals.cs create mode 100644 Sources/Towel/Statics-SearchingAlgorithms.cs create mode 100644 Sources/Towel/Statics-SequenceAnalysis.cs create mode 100644 Sources/Towel/Statics-SortingAlgorithms.cs create mode 100644 Sources/Towel/Statics-Structs.cs create mode 100644 Sources/Towel/Statics-SyntaxHacks.cs create mode 100644 Sources/Towel/Statics-Trigonometry.cs diff --git a/Examples/GraphSearch/Program.cs b/Examples/GraphSearch/Program.cs index 86fdee5e..ac468efc 100644 --- a/Examples/GraphSearch/Program.cs +++ b/Examples/GraphSearch/Program.cs @@ -124,6 +124,125 @@ static void Neighbors(int node, Action step) } #endregion + #region char[][] 2D Example + { + Console.WriteLine(" Graph Searching (char[][] 2D Example)---------------------"); + Console.WriteLine(); + Console.WriteLine(" Board: "); + + // Set Up Map (not necessarily required, but we need something to path find) + + char[][] board = + { + "███████████".ToCharArray(), + "█ █".ToCharArray(), + "█ █ █ █".ToCharArray(), + "█ █ █ █".ToCharArray(), + "█E █ P █".ToCharArray(), + "███████████".ToCharArray(), + }; + + int columns = 11; + int rows = 6; + + Vector2 enemyLocation = default; + Vector2 playerLocation = default; + + for (int i = 0; i < rows; i++) + { + for (int j = 0; j < columns; j++) + { + if (board[i][j] is 'E') + { + enemyLocation = new Vector2(i, j); + } + if (board[i][j] is 'P') + { + playerLocation = new Vector2(i, j); + } + } + } + + // Write Board To Console + + for (int i = 0; i < rows; i++) + { + Console.Write(" "); + for (int j = 0; j < columns; j++) + { + Console.Write(board[i][j]); + } + Console.WriteLine(); + } + Console.WriteLine(); + + // Make Path Finding Functions + + SetHashLinked alreadyUsed = new SetHashLinked(); + + void Neighbors(Vector2 currentLocation, Action neighbors) + { + float x = currentLocation.X; + float y = currentLocation.Y; + + void HandleNeighbor(Vector2 neighbor) + { + if (!alreadyUsed.Contains(neighbor) && board[(int)neighbor.X][(int)neighbor.Y] is not '█') + { + alreadyUsed.Add(neighbor); + neighbors(neighbor); + } + } + + HandleNeighbor(new Vector2(x - 1, y)); // north + HandleNeighbor(new Vector2(x, y + 1)); // east + HandleNeighbor(new Vector2(x + 1, y)); // south + HandleNeighbor(new Vector2(x, y - 1)); // west + } + + float Heuristic(Vector2 node) => Vector2.Distance(node, playerLocation); + + bool Goal(Vector2 node) => Vector2.Distance(node, playerLocation) < 1; + + // Run The Path Finding Algorithm + + Action> path = + SearchGraph( + enemyLocation, + Neighbors, + Heuristic, + Goal); + + // Print Path To Console + + Vector2[] pathAsArray = path.ToArray(); + Console.WriteLine(" Path:"); + foreach (Vector2 node in pathAsArray) + { + Console.WriteLine(" " + node); + } + Console.WriteLine(); + Console.WriteLine(" Board (with path):"); + + // Print Map With Path To Console + + foreach (Vector2 node in pathAsArray) + { + board[(int)node.X][(int)node.Y] = ':'; + } + for (int i = 0; i < rows; i++) + { + Console.Write(" "); + for (int j = 0; j < columns; j++) + { + Console.Write(board[i][j]); + } + Console.WriteLine(); + } + } + Console.WriteLine(); + #endregion + #region Vector Game-Style Example { Console.WriteLine(" Graph Searching (Vector Game-Style Example)-------------------"); @@ -316,124 +435,6 @@ bool goalFunction(Vector currentLocation) } #endregion - #region char[][] 2D Example - { - Console.WriteLine(" Graph Searching (char[][] 2D Example)---------------------"); - Console.WriteLine(); - Console.WriteLine(" Board: "); - - // Set Up Map (not necessarily required, but we need something to path find) - - char[][] board = - { - "███████████".ToCharArray(), - "█ █".ToCharArray(), - "█ █ █ █".ToCharArray(), - "█ █ █ █".ToCharArray(), - "█E █ P █".ToCharArray(), - "███████████".ToCharArray(), - }; - - int columns = 11; - int rows = 6; - - Vector2 enemyLocation = default; - Vector2 playerLocation = default; - - for (int i = 0; i < rows; i++) - { - for (int j = 0; j < columns; j++) - { - if (board[i][j] is 'E') - { - enemyLocation = new Vector2(i, j); - } - if (board[i][j] is 'P') - { - playerLocation = new Vector2(i, j); - } - } - } - - // Write Board To Console - - for (int i = 0; i < rows; i++) - { - Console.Write(" "); - for (int j = 0; j < columns; j++) - { - Console.Write(board[i][j]); - } - Console.WriteLine(); - } - Console.WriteLine(); - - // Make Path Finding Functions - - SetHashLinked alreadyUsed = new SetHashLinked(); - - void Neighbors(Vector2 currentLocation, Action neighbors) - { - float x = currentLocation.X; - float y = currentLocation.Y; - - void HandleNeighbor(Vector2 neighbor) - { - if (!alreadyUsed.Contains(neighbor) && board[(int)neighbor.X][(int)neighbor.Y] is not '█') - { - alreadyUsed.Add(neighbor); - neighbors(neighbor); - } - } - - HandleNeighbor(new Vector2(x - 1, y)); // north - HandleNeighbor(new Vector2(x, y + 1)); // east - HandleNeighbor(new Vector2(x + 1, y)); // south - HandleNeighbor(new Vector2(x, y - 1)); // west - } - - float Heuristic(Vector2 node) => Vector2.Distance(node, playerLocation); - - bool Goal(Vector2 node) => Vector2.Distance(node, playerLocation) < 1; - - // Run The Path Finding Algorithm - - Action> path = - SearchGraph( - enemyLocation, - Neighbors, - Heuristic, - Goal); - - // Print Path To Console - - Vector2[] pathAsArray = path.ToArray(); - Console.WriteLine(" Path:"); - foreach (Vector2 node in pathAsArray) - { - Console.WriteLine(" " + node); - } - Console.WriteLine(); - Console.WriteLine(" Board (with path):"); - - // Print Map With Path To Console - - foreach (Vector2 node in pathAsArray) - { - board[(int)node.X][(int)node.Y] = ':'; - } - for (int i = 0; i < rows; i++) - { - Console.Write(" "); - for (int j = 0; j < columns; j++) - { - Console.Write(board[i][j]); - } - Console.WriteLine(); - } - } - #endregion - Console.WriteLine(); Console.WriteLine("============================================"); Console.WriteLine("Example Complete..."); diff --git a/Sources/Towel/Extensions-NumericEnglishWords.cs b/Sources/Towel/Extensions-NumericEnglishWords.cs new file mode 100644 index 00000000..3737efda --- /dev/null +++ b/Sources/Towel/Extensions-NumericEnglishWords.cs @@ -0,0 +1,272 @@ +using System; +using System.Text; + +namespace Towel +{ + /// Contains Extension methods on common System types. + public static partial class Extensions + { + internal static class ToEnglishWordsDefinitions + { + internal static string[] Digit = + { + /* 0 */ null!, + /* 1 */ "One", + /* 2 */ "Two", + /* 3 */ "Three", + /* 4 */ "Four", + /* 5 */ "Five", + /* 6 */ "Six", + /* 7 */ "Seven", + /* 8 */ "Eight", + /* 9 */ "Nine", + }; + + internal static string[] FractionalSufix = + { + /* 0 */ null!, + /* 1 */ "Tenths", + /* 2 */ "Hundredths", + /* 3 */ "Thousandths", + /* 4 */ "Ten-Thousandths", + /* 5 */ "Hundred-Thousandths", + /* 6 */ "Millionths", + /* 7 */ "Ten-Millionths", + /* 8 */ "Hundred-Millionths", + /* 9 */ "Billionths", + /* 10 */ "Ten-Billionths", + /* 11 */ "Hundred-Billionths", + /* 12 */ "Trilionths", + /* 13 */ "Ten-Trilionths", + /* 14 */ "Hundred-Trilionths", + /* 15 */ "Quadrillionths", + /* 16 */ "Ten-Quadrillionths", + /* 17 */ "Hundred-Quadrillionths", + /* 18 */ "Quintrillionths", + /* 19 */ "Ten-Quintrillionths", + /* 20 */ "Hundred-Quintrillionths", + /* 21 */ "Sextillionths", + /* 22 */ "Ten-Sextillionths", + /* 23 */ "Hundred-Sextillionths", + /* 24 */ "Septillionths", + /* 25 */ "Ten-Septillionths", + /* 26 */ "Hundred-Septillionths", + /* 27 */ "Octillionths", + /* 28 */ "Ten-Octillionths", + /* 29 */ "Hundred-Octillionths", + }; + + internal static string[] Ten = + { + /* 0 */ null!, + /* 1 */ "Ten", + /* 2 */ "Twenty", + /* 3 */ "Thirty", + /* 4 */ "Forty", + /* 5 */ "Fifty", + /* 6 */ "Sixty", + /* 7 */ "Seventy", + /* 8 */ "Eighty", + /* 9 */ "Ninety", + }; + + internal static string[] Teen = + { + /* 0 */ null!, + /* 1 */ "Eleven", + /* 2 */ "Twelve", + /* 3 */ "Thirteen", + /* 4 */ "Fourteen", + /* 5 */ "Fifteen", + /* 6 */ "Sixteen", + /* 7 */ "Seventeen", + /* 8 */ "Eighteen", + /* 9 */ "Nineteen", + }; + + internal static string[] Group = + { + /* 0 */ null!, + /* 1 */ null!, + /* 2 */ "Thousand", + /* 3 */ "Million", + /* 4 */ "Billion", + /* 5 */ "Trillion", + /* 6 */ "Quadrillion", + /* 7 */ "Quintillion", + /* 8 */ "Sextillion", + /* 9 */ "Septillion", + /* 10 */ "Octillion", + }; + } + + internal static string ToEnglishWords(ReadOnlySpan number) + { + if (number.Length == 1 && number[0] == '0') + { + return "Zero"; + } + StringBuilder stringBuilder = new StringBuilder(); + bool spaceNeeded = false; + if (number[0] == '-') + { + Append("Negative"); + spaceNeeded = true; + number = number[1..]; + } + if (number[0] == '0') + { + number = number[1..]; + } + int decimalIndex = number.IndexOf('.'); + if (decimalIndex != 0) + { + ReadOnlySpan wholeNumber = decimalIndex >= 0 + ? number[0..decimalIndex] + : number; + WholeNumber(wholeNumber); + } + if (decimalIndex >= 0) + { + if (decimalIndex != 0) + { + AppendLeadingSpace(); + Append("And"); + } + ReadOnlySpan fractionalNumber = number[(decimalIndex + 1)..]; + WholeNumber(fractionalNumber); + AppendLeadingSpace(); + Append(ToEnglishWordsDefinitions.FractionalSufix[fractionalNumber.Length]); + } + string result = stringBuilder.ToString(); + return result; + + void Append(string @string) => stringBuilder.Append(@string); + + void AppendLeadingSpace() + { + if (!spaceNeeded) + { + spaceNeeded = true; + } + else + { + Append(" "); + } + } + + void WholeNumber(ReadOnlySpan wholeNumber) + { + // A "digit group" is a set of hundreds + tens + ones digits. + // In the number 123456789 the digit groups are the following: 123, 456, 789 + // In the number 12345 the digit groups are the following: 12, 345 + + int mod3 = wholeNumber.Length % 3; + int digitGroup = wholeNumber.Length / 3 + (mod3 == 0 ? 0 : 1); + while (digitGroup > 0) + { + int i__X = (wholeNumber.Length - (digitGroup - 1) * 3) - 1; // index of ones digit + int i_X_ = i__X - 1; // index of tens digit + int iX__ = i_X_ - 1; // index of hundreds digit + + char c__X = wholeNumber[i__X]; // character of ones digit + char c_X_ = i_X_ >= 0 ? wholeNumber[i_X_] : '0'; // character of tens digit + char cX__ = iX__ >= 0 ? wholeNumber[iX__] : '0'; // character of hundreds digit + + if (c__X > '0' || c_X_ > '0' || cX__ > '0') + { + DigitGroup(cX__, c_X_, c__X); + if (digitGroup > 1) + { + AppendLeadingSpace(); + Append(ToEnglishWordsDefinitions.Group[digitGroup]); + } + } + digitGroup--; + } + } + + void DigitGroup(char hundredsDigit, char tensDigit, char onesDigit) + { + int hundred = hundredsDigit - '0'; + int ten = tensDigit - '0'; + int one = onesDigit - '0'; + if (hundred > 0) + { + AppendLeadingSpace(); + Append(ToEnglishWordsDefinitions.Digit[hundred]); + Append(" Hundred"); + } + if (ten > 0) + { + AppendLeadingSpace(); + if (one == 0) + { + Append(ToEnglishWordsDefinitions.Ten[ten]); + } + else if (ten == 1) + { + Append(ToEnglishWordsDefinitions.Teen[one]); + } + else + { + Append(ToEnglishWordsDefinitions.Ten[ten]); + Append("-"); + Append(ToEnglishWordsDefinitions.Digit[one]); + } + } + else if (one > 0) + { + AppendLeadingSpace(); + Append(ToEnglishWordsDefinitions.Digit[one]); + } + } + } + + /// Converts a to the English words representation. + /// The value to convert to English words representation. + /// The English words representation of the value. + public static string ToEnglishWords(this decimal @decimal) => ToEnglishWords(@decimal.ToString(System.Globalization.CultureInfo.InvariantCulture)); + + /// Converts a to the English words representation. + /// The value to convert to English words representation. + /// The English words representation of the value. + public static string ToEnglishWords(this int @int) => ToEnglishWords(@int.ToString(System.Globalization.CultureInfo.InvariantCulture)); + + /// Converts a to the English words representation. + /// The value to convert to English words representation. + /// The English words representation of the value. + public static string ToEnglishWords(this long @long) => ToEnglishWords(@long.ToString(System.Globalization.CultureInfo.InvariantCulture)); + + /// Converts a to the English words representation. + /// The value to convert to English words representation. + /// The English words representation of the value. + public static string ToEnglishWords(this byte @byte) => ToEnglishWords(@byte.ToString(System.Globalization.CultureInfo.InvariantCulture)); + + /// Converts a to the English words representation. + /// The value to convert to English words representation. + /// The English words representation of the value. + public static string ToEnglishWords(this sbyte @sbyte) => ToEnglishWords(@sbyte.ToString(System.Globalization.CultureInfo.InvariantCulture)); + + /// Converts a to the English words representation. + /// The value to convert to English words representation. + /// The English words representation of the value. + public static string ToEnglishWords(this uint @uint) => ToEnglishWords(@uint.ToString(System.Globalization.CultureInfo.InvariantCulture)); + + /// Converts a to the English words representation. + /// The value to convert to English words representation. + /// The English words representation of the value. + public static string ToEnglishWords(this ulong @ulong) => ToEnglishWords(@ulong.ToString(System.Globalization.CultureInfo.InvariantCulture)); + + /// Converts a to the English words representation. + /// The value to convert to English words representation. + /// The English words representation of the value. + public static string ToEnglishWords(this short @short) => ToEnglishWords(@short.ToString(System.Globalization.CultureInfo.InvariantCulture)); + + /// Converts a to the English words representation. + /// The value to convert to English words representation. + /// The English words representation of the value. + public static string ToEnglishWords(this ushort @ushort) => ToEnglishWords(@ushort.ToString(System.Globalization.CultureInfo.InvariantCulture)); + + } +} diff --git a/Sources/Towel/Extensions-Random.cs b/Sources/Towel/Extensions-Random.cs new file mode 100644 index 00000000..07ed3dd8 --- /dev/null +++ b/Sources/Towel/Extensions-Random.cs @@ -0,0 +1,437 @@ +using System; +using static Towel.Statics; + +namespace Towel +{ + /// Contains Extension methods on common System types. + public static partial class Extensions + { + /// Generates a random value. + /// The random generation algorithm. + /// A randomly generated value. + public static bool NextBool(this Random random) => random.Next(2) == 0; + + /// Generates a random value. + /// The random generation algorithm. + /// A randomly generated value. + public static byte NextByte(this Random random) => (byte)random.Next(byte.MinValue, byte.MaxValue); + + /// Generates a random of a given length using the System.Random generator. + /// The random generation algorithm. + /// The length of the randomized to generate. + /// The generated randomized . + public static string NextString(this Random random, int length) + { + _ = random ?? throw new ArgumentNullException(nameof(random)); + if (length < 1) + { + throw new ArgumentException("(" + nameof(length) + " < 1)"); + } + char[] randomstring = new char[length]; + for (int i = 0; i < randomstring.Length; i++) + { + randomstring[i] = (char)random.Next(char.MinValue, char.MaxValue); + } + return new string(randomstring); + } + + /// Generates a random of a given length using the System.Random generator with a specific set of characters. + /// The random generation algorithm. + /// The length of the randomized to generate. + /// The set of allowable characters. + /// The generated randomized . + public static string NextString(this Random random, int length, char[] characterPool) + { + _ = random ?? throw new ArgumentNullException(nameof(random)); + _ = characterPool ?? throw new ArgumentNullException(nameof(characterPool)); + if (length < 1) + { + throw new ArgumentException("(" + nameof(length) + " < 1)"); + } + if (characterPool.Length < 1) + { + throw new ArgumentException("(" + nameof(characterPool) + "." + nameof(characterPool.Length) + " < 1)"); + } + char[] randomstring = new char[length]; + for (int i = 0; i < randomstring.Length; i++) + { + randomstring[i] = random.Choose(characterPool); + } + return new string(randomstring); + } + + internal const string UpperCaseEnglishCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + internal const string LowerCaseEnglishCharacters = "abcdefghijklmnopqrstuvwxyz"; + internal const string EnglishDigits = "0123456789"; + + /// Generates a random English alphanumeric of a given length (includes upper and lower case characters). + /// The random generation algorithm. + /// The length of the randomized alphanumeric to generate. + /// The generated randomized alphanumeric . + public static string NextEnglishAlphaNumericString(this Random random, int length) => + NextString(random, length, (UpperCaseEnglishCharacters + LowerCaseEnglishCharacters + EnglishDigits).ToCharArray()); + + /// Generates a random English alphanumeric of a given length (upper case characters only). + /// The random generation algorithm. + /// The length of the randomized alphanumeric to generate. + /// The generated randomized alphanumeric . + public static string NextUpperCaseEnglishAlphaNumericString(this Random random, int length) => + NextString(random, length, (UpperCaseEnglishCharacters + EnglishDigits).ToCharArray()); + + /// Generates a random English alphanumeric of a given length (lower case characters only). + /// The random generation algorithm. + /// The length of the randomized alphanumeric to generate. + /// The generated randomized alphanumeric . + public static string NextLowerCaseEnglishAlphaNumericString(this Random random, int length) => + NextString(random, length, (LowerCaseEnglishCharacters + EnglishDigits).ToCharArray()); + + /// Generates a random English numeric of a given length. + /// The random generation algorithm. + /// The length of the randomized numeric to generate. + /// The generated randomized numeric . + public static string NumericEnglishString(this Random random, int length) => + NextString(random, length, EnglishDigits.ToCharArray()); + + /// Generates a random English alhpabetical of a given length (includes upper and lower case characters). + /// The random generation algorithm. + /// The length of the randomized alphabetical to generate. + /// The generated randomized alphabetical . + public static string NextEnglishAlphabeticString(this Random random, int length) => + NextString(random, length, (UpperCaseEnglishCharacters + LowerCaseEnglishCharacters).ToCharArray()); + + /// Generates a random English alhpabetical of a given length (upper case characters only). + /// The random generation algorithm. + /// The length of the randomized alphabetical to generate. + /// The generated randomized alphabetical . + public static string NextUpperCaseEnglishAlphabeticString(this Random random, int length) => + NextString(random, length, (UpperCaseEnglishCharacters).ToCharArray()); + + /// Generates a random English alhpabetical of a given length (lower case characters only). + /// The random generation algorithm. + /// The length of the randomized alphabetical to generate. + /// The generated randomized alphabetical . + public static string NextLowerCaseEnglishAlphabeticString(this Random random, int length) => + NextString(random, length, (LowerCaseEnglishCharacters).ToCharArray()); + + /// Generates a random char value. + /// The random generation algorithm. + /// A randomly generated char value. + public static char NextChar(this Random random) => + NextChar(random, char.MinValue, char.MaxValue); + + /// Generates a random char value. + /// The random generation algorithm. + /// Minimum allowed value of the random generation. + /// Maximum allowed value of the random generation. + /// A randomly generated char value. + public static char NextChar(this Random random, char min, char max) => + (char)random.Next(min, max); + + /// Generates a random long value. + /// The random generation algorithm. + /// A randomly generated long value. + public static long NextLong(this Random random) => + NextLong(random, long.MaxValue); + + /// Generates a random long value. + /// The random generation algorithm. + /// Maximum allowed value of the random generation. + /// A randomly generated long value. + public static long NextLong(this Random random, long max) => + NextLong(random, 0, max); + + /// Generates a random long value. + /// The random generation algorithm. + /// Minimum allowed value of the random generation. + /// Maximum allowed value of the random generation. + /// A randomly generated long value. + public static long NextLong(this Random random, long min, long max) + { + _ = random ?? throw new ArgumentNullException(nameof(random)); + if (min > max) + { + throw new ArgumentException("!(" + nameof(min) + " <= " + nameof(max) + ")"); + } + byte[] buffer = new byte[8]; + random.NextBytes(buffer); + long longRand = BitConverter.ToInt64(buffer, 0); + return Math.Abs(longRand % (max - min)) + min; + } + + /// Generates a random value. + /// The random generation algorithm. + /// A randomly generated value. + public static decimal NextDecimal(this Random random) => + new decimal( + random.Next(int.MinValue, int.MaxValue), + random.Next(int.MinValue, int.MaxValue), + random.Next(int.MinValue, int.MaxValue), + random.NextBool(), + (byte)random.Next(29)); + + /// Generates a random value. + /// The random generation algorithm. + /// The minimum allowed value of the random generation. + /// The maximum allowed value of the random generation. + /// A randomly generated value. + /// Called if the range of random generation is too large and therefore invalid. + public static decimal NextDecimal(this Random random, decimal min, decimal max) + { + try + { + decimal next = NextDecimal(random); + return checked((next < 0 ? -next : next) % (max - min) + min); + } + catch (OverflowException exception) + { + throw new ArgumentOutOfRangeException("The bounds of random generation were to large (min...max).", exception); + } + } + + /// Generates a random DateTime value. + /// The random generation algorithm. + /// A randomly generated DateTime value. + public static DateTime NextDateTime(this Random random) => + NextDateTime(random, DateTime.MaxValue); + + /// Generates a random DateTime value. + /// The random generation algorithm. + /// The maximum allowed value of the random generation. + /// A randomly generated DateTime value. + public static DateTime NextDateTime(this Random random, DateTime max) => + NextDateTime(random, DateTime.MinValue, max); + + /// Generates a random DateTime value. + /// The random generation algorithm. + /// The minimum allowed value of the random generation. + /// The maximum allowed value of the random generation. + /// A randomly generated DateTime value. + public static DateTime NextDateTime(this Random random, DateTime min, DateTime max) + { + _ = random ?? throw new ArgumentNullException(nameof(random)); + if (min > max) + { + throw new ArgumentException("!(" + nameof(min) + " <= " + nameof(max) + ")"); + } + TimeSpan randomTimeSpan = NextTimeSpan(random, TimeSpan.Zero, max - min); + return min.Add(randomTimeSpan); + } + + /// Generates a random TimeSpan value. + /// The random generation algorithm. + /// A randomly generated TimeSpan value. + public static TimeSpan NextTimeSpan(this Random random) => + NextTimeSpan(random, TimeSpan.MaxValue); + + /// Generates a random TimeSpan value. + /// The random generation algorithm. + /// The maximum allowed value of the random generation. + /// A randomly generated TimeSpan value. + public static TimeSpan NextTimeSpan(this Random random, TimeSpan max) => + NextTimeSpan(random, TimeSpan.Zero, max); + + /// Generates a random TimeSpan value. + /// The random generation algorithm. + /// The minimum allowed value of the random generation. + /// The maximum allowed value of the random generation. + /// A randomly generated TimeSpan value. + public static TimeSpan NextTimeSpan(this Random random, TimeSpan min, TimeSpan max) + { + _ = random ?? throw new ArgumentNullException(nameof(random)); + if (min > max) + { + throw new ArgumentException("!(" + nameof(min) + " <= " + nameof(max) + ")"); + } + long tickRange = max.Ticks - min.Ticks; + long randomLong = random.NextLong(0, tickRange); + return TimeSpan.FromTicks(min.Ticks + randomLong); + } + + /// + /// Generates unique random values in the + /// [..] range where is + /// inclusive and is exclusive. + /// + /// The function to perform on each generated value. + /// The random to generation algorithm. + /// The number of values to generate. + /// Inclusive endpoint of the random generation range. + /// Exclusive endpoint of the random generation range. + /// The function to perform on each generated value. + public static void NextUnique(this Random random, int count, int minValue, int maxValue, Step step = default) + where Step : struct, IAction => + NextUnique(count, minValue, maxValue, random ?? new Random(), step); + + /// + /// Generates unique random values in the + /// [..] range where is + /// inclusive and is exclusive. + /// + /// The function to perform on each generated value. + /// The random to generation algorithm. + /// The number of values to generate. + /// Inclusive endpoint of the random generation range. + /// Exclusive endpoint of the random generation range. + /// The function to perform on each generated value. + [Obsolete("It is recommended you use " + nameof(NextUnique) + " method instead.", false)] + public static void NextUniqueRollTracking(this Random random, int count, int minValue, int maxValue, Step step = default) + where Step : struct, IAction => + NextUniqueRollTracking(count, minValue, maxValue, random ?? new Random(), step); + + /// + /// Generates unique random values in the + /// [..] range where is + /// inclusive and is exclusive. + /// + /// The function to perform on each generated value. + /// The random to generation algorithm. + /// The number of values to generate. + /// Inclusive endpoint of the random generation range. + /// Exclusive endpoint of the random generation range. + /// The function to perform on each generated value. + [Obsolete("It is recommended you use " + nameof(NextUnique) + " method instead.", false)] + public static void NextUniquePoolTracking(this Random random, int count, int minValue, int maxValue, Step step = default) + where Step : struct, IAction => + NextUniquePoolTracking(count, minValue, maxValue, random ?? new Random(), step); + + /// + /// Generates unique random values in the + /// [..] range where is + /// inclusive and is exclusive. + /// + /// The random to generation algorithm. + /// The number of values to generate. + /// Inclusive endpoint of the random generation range. + /// Exclusive endpoint of the random generation range. + /// The function to perform on each generated value. + public static void NextUnique(this Random random, int count, int minValue, int maxValue, Action step) + { + if (step is null) + throw new ArgumentNullException(nameof(step)); + NextUnique>(random, count, minValue, maxValue, step); + } + + /// + /// Generates unique random values in the + /// [..] range where is + /// inclusive and is exclusive. + /// + /// The random to generation algorithm. + /// The number of values to generate. + /// Inclusive endpoint of the random generation range. + /// Exclusive endpoint of the random generation range. + public static int[] NextUnique(this Random random, int count, int minValue, int maxValue) => + Statics.NextUnique(count, minValue, maxValue, random ?? new Random()); + + /// Chooses an item at random (all equally weighted). + /// The generic type of the items to choose from. + /// The random algorithm for index generation. + /// The values to choose from. + /// A randomly selected value from the supplied options. + public static T Choose(this Random random, params T[] values) => + values[random.Next(values.Length)]; + + /// Selects a random value from a collection of weighted options. + /// The generic type to select a random instance of. + /// The random algorithm. + /// The pool of weighted values to choose from. + /// A randomly selected value from the weighted pool. + public static T Next(this Random random, params (T Value, double Weight)[] pool) => + random.Next((System.Collections.Generic.IEnumerable<(T Value, double Weight)>)pool); + + /// Selects a random value from a collection of weighted options. + /// The generic type to select a random instance of. + /// The random algorithm. + /// The pool of weighted values to choose from. + /// The total weight of all the values in the pool. + /// A randomly selected value from the weighted pool. + public static T Next(this Random random, double totalWeight, params (T Value, double Weight)[] pool) => + random.Next(pool, totalWeight); + + /// Selects a random value from a collection of weighted options. + /// The generic type to select a random instance of. + /// The random algorithm. + /// The pool of weighted values to choose from. + /// The total weight of all the values in the pool. + /// A randomly selected value from the weighted pool. + public static T Next(this Random random, System.Collections.Generic.IEnumerable<(T Value, double Weight)> pool, double? totalWeight = null) + { + if (!totalWeight.HasValue) + { + totalWeight = 0; + foreach (var (Value, Weight) in pool) + { + if (Weight < 0) + throw new ArgumentOutOfRangeException(nameof(pool), $"A value in {nameof(pool)} had a weight less than zero."); + totalWeight += Weight; + } + } + else + { + if (totalWeight < 0) + throw new ArgumentOutOfRangeException(nameof(totalWeight), $"The provided {nameof(totalWeight)} of the {nameof(pool)} was less than zero."); + } + if (totalWeight == 0) + throw new ArgumentOutOfRangeException(nameof(pool), $"The total weight of all values in the {nameof(pool)} was zero."); + if (double.IsInfinity(totalWeight.Value)) + throw new ArgumentOutOfRangeException(nameof(pool), $"The total weight of all values in the {nameof(pool)} was an infinite double."); + double randomDouble = random.NextDouble(); + double range = 0; + foreach (var (Value, Weight) in pool) + { + range += Weight; + if (range > totalWeight) + throw new ArgumentOutOfRangeException(nameof(totalWeight), $"The provided {nameof(totalWeight)} of the {nameof(pool)} was less than the actual total weight."); + if (randomDouble < range / totalWeight) + return Value; + } + throw new TowelBugException("There is a bug in the code."); + } + +#if false + + //public static T Next(this Random random, StepperBreak<(T Value, double Weight)> pool, double? totalWeight = null) + //{ + // if (!totalWeight.HasValue) + // { + // totalWeight = 0; + // pool(x => + // { + // if (x.Weight < 0) + // throw new ArgumentOutOfRangeException("A value in the pool had a weight less than zero."); + // totalWeight += x.Weight; + // return Continue; + // }); + // } + // else + // { + // if (totalWeight < 0) + // throw new ArgumentOutOfRangeException("The provided total weight of the pool was less than zero."); + // } + // if (totalWeight == 0) + // throw new ArgumentOutOfRangeException("The total weight of all values in the pool was zero."); + // if (double.IsInfinity(totalWeight.Value)) + // throw new ArgumentOutOfRangeException("The total weight of all values in the pool was an infinite double."); + // double randomDouble = random.NextDouble(); + // double range = 0; + // T @return = default; + // StepStatus status = pool(x => + // { + // range += x.Weight; + // if (range > totalWeight) + // throw new ArgumentOutOfRangeException("The provided total weight of the pool was less than the actual total weight."); + // if (randomDouble < range / totalWeight) + // { + // @return = x.Value; + // return Break; + // } + // return Continue; + // }); + // return status is Break + // ? @return + // : throw new TowelBugException("There is a bug in the code."); + //} + +#endif + } +} diff --git a/Sources/Towel/Extensions.cs b/Sources/Towel/Extensions.cs index 36a0286d..dc750e9c 100644 --- a/Sources/Towel/Extensions.cs +++ b/Sources/Towel/Extensions.cs @@ -9,7 +9,7 @@ namespace Towel { /// Contains Extension methods on common System types. - public static class Extensions + public static partial class Extensions { #region System.String @@ -370,493 +370,6 @@ public static int CountLines(this string str) => #endregion - #region System.Random - - #region int - - internal static CompareResult ToCompareResult(this int result) => - result < 0 - ? Less - : result > 0 - ? Greater - : Equal; - - #endregion - - #region bool - - /// Generates a random value. - /// The random generation algorithm. - /// A randomly generated value. - public static bool NextBool(this Random random) => random.Next(2) == 0; - - #endregion - - #region byte - - /// Generates a random value. - /// The random generation algorithm. - /// A randomly generated value. - public static byte NextByte(this Random random) => (byte)random.Next(byte.MinValue, byte.MaxValue); - - #endregion - - #region string - - /// Generates a random of a given length using the System.Random generator. - /// The random generation algorithm. - /// The length of the randomized to generate. - /// The generated randomized . - public static string NextString(this Random random, int length) - { - _ = random ?? throw new ArgumentNullException(nameof(random)); - if (length < 1) - { - throw new ArgumentException("(" + nameof(length) + " < 1)"); - } - char[] randomstring = new char[length]; - for (int i = 0; i < randomstring.Length; i++) - { - randomstring[i] = (char)random.Next(char.MinValue, char.MaxValue); - } - return new string(randomstring); - } - - /// Generates a random of a given length using the System.Random generator with a specific set of characters. - /// The random generation algorithm. - /// The length of the randomized to generate. - /// The set of allowable characters. - /// The generated randomized . - public static string NextString(this Random random, int length, char[] characterPool) - { - _ = random ?? throw new ArgumentNullException(nameof(random)); - _ = characterPool ?? throw new ArgumentNullException(nameof(characterPool)); - if (length < 1) - { - throw new ArgumentException("(" + nameof(length) + " < 1)"); - } - if (characterPool.Length < 1) - { - throw new ArgumentException("(" + nameof(characterPool) + "." + nameof(characterPool.Length) + " < 1)"); - } - char[] randomstring = new char[length]; - for (int i = 0; i < randomstring.Length; i++) - { - randomstring[i] = random.Choose(characterPool); - } - return new string(randomstring); - } - - internal const string UpperCaseEnglishCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - internal const string LowerCaseEnglishCharacters = "abcdefghijklmnopqrstuvwxyz"; - internal const string EnglishDigits = "0123456789"; - - /// Generates a random English alphanumeric of a given length (includes upper and lower case characters). - /// The random generation algorithm. - /// The length of the randomized alphanumeric to generate. - /// The generated randomized alphanumeric . - public static string NextEnglishAlphaNumericString(this Random random, int length) => - NextString(random, length, (UpperCaseEnglishCharacters + LowerCaseEnglishCharacters + EnglishDigits).ToCharArray()); - - /// Generates a random English alphanumeric of a given length (upper case characters only). - /// The random generation algorithm. - /// The length of the randomized alphanumeric to generate. - /// The generated randomized alphanumeric . - public static string NextUpperCaseEnglishAlphaNumericString(this Random random, int length) => - NextString(random, length, (UpperCaseEnglishCharacters + EnglishDigits).ToCharArray()); - - /// Generates a random English alphanumeric of a given length (lower case characters only). - /// The random generation algorithm. - /// The length of the randomized alphanumeric to generate. - /// The generated randomized alphanumeric . - public static string NextLowerCaseEnglishAlphaNumericString(this Random random, int length) => - NextString(random, length, (LowerCaseEnglishCharacters + EnglishDigits).ToCharArray()); - - /// Generates a random English numeric of a given length. - /// The random generation algorithm. - /// The length of the randomized numeric to generate. - /// The generated randomized numeric . - public static string NumericEnglishString(this Random random, int length) => - NextString(random, length, EnglishDigits.ToCharArray()); - - /// Generates a random English alhpabetical of a given length (includes upper and lower case characters). - /// The random generation algorithm. - /// The length of the randomized alphabetical to generate. - /// The generated randomized alphabetical . - public static string NextEnglishAlphabeticString(this Random random, int length) => - NextString(random, length, (UpperCaseEnglishCharacters + LowerCaseEnglishCharacters).ToCharArray()); - - /// Generates a random English alhpabetical of a given length (upper case characters only). - /// The random generation algorithm. - /// The length of the randomized alphabetical to generate. - /// The generated randomized alphabetical . - public static string NextUpperCaseEnglishAlphabeticString(this Random random, int length) => - NextString(random, length, (UpperCaseEnglishCharacters).ToCharArray()); - - /// Generates a random English alhpabetical of a given length (lower case characters only). - /// The random generation algorithm. - /// The length of the randomized alphabetical to generate. - /// The generated randomized alphabetical . - public static string NextLowerCaseEnglishAlphabeticString(this Random random, int length) => - NextString(random, length, (LowerCaseEnglishCharacters).ToCharArray()); - - #endregion - - #region char - - /// Generates a random char value. - /// The random generation algorithm. - /// A randomly generated char value. - public static char NextChar(this Random random) => - NextChar(random, char.MinValue, char.MaxValue); - - /// Generates a random char value. - /// The random generation algorithm. - /// Minimum allowed value of the random generation. - /// Maximum allowed value of the random generation. - /// A randomly generated char value. - public static char NextChar(this Random random, char min, char max) => - (char)random.Next(min, max); - - #endregion - - #region long - - /// Generates a random long value. - /// The random generation algorithm. - /// A randomly generated long value. - public static long NextLong(this Random random) => - NextLong(random, long.MaxValue); - - /// Generates a random long value. - /// The random generation algorithm. - /// Maximum allowed value of the random generation. - /// A randomly generated long value. - public static long NextLong(this Random random, long max) => - NextLong(random, 0, max); - - /// Generates a random long value. - /// The random generation algorithm. - /// Minimum allowed value of the random generation. - /// Maximum allowed value of the random generation. - /// A randomly generated long value. - public static long NextLong(this Random random, long min, long max) - { - _ = random ?? throw new ArgumentNullException(nameof(random)); - if (min > max) - { - throw new ArgumentException("!(" + nameof(min) + " <= " + nameof(max) + ")"); - } - byte[] buffer = new byte[8]; - random.NextBytes(buffer); - long longRand = BitConverter.ToInt64(buffer, 0); - return Math.Abs(longRand % (max - min)) + min; - } - - #endregion - - #region decimal - - /// Generates a random value. - /// The random generation algorithm. - /// A randomly generated value. - public static decimal NextDecimal(this Random random) => - new decimal( - random.Next(int.MinValue, int.MaxValue), - random.Next(int.MinValue, int.MaxValue), - random.Next(int.MinValue, int.MaxValue), - random.NextBool(), - (byte)random.Next(29)); - - /// Generates a random value. - /// The random generation algorithm. - /// The minimum allowed value of the random generation. - /// The maximum allowed value of the random generation. - /// A randomly generated value. - /// Called if the range of random generation is too large and therefore invalid. - public static decimal NextDecimal(this Random random, decimal min, decimal max) - { - try - { - decimal next = NextDecimal(random); - return checked((next < 0 ? -next : next) % (max - min) + min); - } - catch (OverflowException exception) - { - throw new ArgumentOutOfRangeException("The bounds of random generation were to large (min...max).", exception); - } - } - - #endregion - - #region DateTime - - /// Generates a random DateTime value. - /// The random generation algorithm. - /// A randomly generated DateTime value. - public static DateTime NextDateTime(this Random random) => - NextDateTime(random, DateTime.MaxValue); - - /// Generates a random DateTime value. - /// The random generation algorithm. - /// The maximum allowed value of the random generation. - /// A randomly generated DateTime value. - public static DateTime NextDateTime(this Random random, DateTime max) => - NextDateTime(random, DateTime.MinValue, max); - - /// Generates a random DateTime value. - /// The random generation algorithm. - /// The minimum allowed value of the random generation. - /// The maximum allowed value of the random generation. - /// A randomly generated DateTime value. - public static DateTime NextDateTime(this Random random, DateTime min, DateTime max) - { - _ = random ?? throw new ArgumentNullException(nameof(random)); - if (min > max) - { - throw new ArgumentException("!(" + nameof(min) + " <= " + nameof(max) + ")"); - } - TimeSpan randomTimeSpan = NextTimeSpan(random, TimeSpan.Zero, max - min); - return min.Add(randomTimeSpan); - } - - #endregion - - #region TimeSpan - - /// Generates a random TimeSpan value. - /// The random generation algorithm. - /// A randomly generated TimeSpan value. - public static TimeSpan NextTimeSpan(this Random random) => - NextTimeSpan(random, TimeSpan.MaxValue); - - /// Generates a random TimeSpan value. - /// The random generation algorithm. - /// The maximum allowed value of the random generation. - /// A randomly generated TimeSpan value. - public static TimeSpan NextTimeSpan(this Random random, TimeSpan max) => - NextTimeSpan(random, TimeSpan.Zero, max); - - /// Generates a random TimeSpan value. - /// The random generation algorithm. - /// The minimum allowed value of the random generation. - /// The maximum allowed value of the random generation. - /// A randomly generated TimeSpan value. - public static TimeSpan NextTimeSpan(this Random random, TimeSpan min, TimeSpan max) - { - _ = random ?? throw new ArgumentNullException(nameof(random)); - if (min > max) - { - throw new ArgumentException("!(" + nameof(min) + " <= " + nameof(max) + ")"); - } - long tickRange = max.Ticks - min.Ticks; - long randomLong = random.NextLong(0, tickRange); - return TimeSpan.FromTicks(min.Ticks + randomLong); - } - - #endregion - - #region NextUnique - - /// - /// Generates unique random values in the - /// [..] range where is - /// inclusive and is exclusive. - /// - /// The function to perform on each generated value. - /// The random to generation algorithm. - /// The number of values to generate. - /// Inclusive endpoint of the random generation range. - /// Exclusive endpoint of the random generation range. - /// The function to perform on each generated value. - public static void NextUnique(this Random random, int count, int minValue, int maxValue, Step step = default) - where Step : struct, IAction => - NextUnique(count, minValue, maxValue, random ?? new Random(), step); - - /// - /// Generates unique random values in the - /// [..] range where is - /// inclusive and is exclusive. - /// - /// The function to perform on each generated value. - /// The random to generation algorithm. - /// The number of values to generate. - /// Inclusive endpoint of the random generation range. - /// Exclusive endpoint of the random generation range. - /// The function to perform on each generated value. - [Obsolete("It is recommended you use " + nameof(NextUnique) + " method instead.", false)] - public static void NextUniqueRollTracking(this Random random, int count, int minValue, int maxValue, Step step = default) - where Step : struct, IAction => - NextUniqueRollTracking(count, minValue, maxValue, random ?? new Random(), step); - - /// - /// Generates unique random values in the - /// [..] range where is - /// inclusive and is exclusive. - /// - /// The function to perform on each generated value. - /// The random to generation algorithm. - /// The number of values to generate. - /// Inclusive endpoint of the random generation range. - /// Exclusive endpoint of the random generation range. - /// The function to perform on each generated value. - [Obsolete("It is recommended you use " + nameof(NextUnique) + " method instead.", false)] - public static void NextUniquePoolTracking(this Random random, int count, int minValue, int maxValue, Step step = default) - where Step : struct, IAction => - NextUniquePoolTracking(count, minValue, maxValue, random ?? new Random(), step); - - /// - /// Generates unique random values in the - /// [..] range where is - /// inclusive and is exclusive. - /// - /// The random to generation algorithm. - /// The number of values to generate. - /// Inclusive endpoint of the random generation range. - /// Exclusive endpoint of the random generation range. - /// The function to perform on each generated value. - public static void NextUnique(this Random random, int count, int minValue, int maxValue, Action step) - { - if (step is null) - throw new ArgumentNullException(nameof(step)); - NextUnique>(random, count, minValue, maxValue, step); - } - - /// - /// Generates unique random values in the - /// [..] range where is - /// inclusive and is exclusive. - /// - /// The random to generation algorithm. - /// The number of values to generate. - /// Inclusive endpoint of the random generation range. - /// Exclusive endpoint of the random generation range. - public static int[] NextUnique(this Random random, int count, int minValue, int maxValue) => - Statics.NextUnique(count, minValue, maxValue, random ?? new Random()); - - #endregion - - #region Choose - - /// Chooses an item at random (all equally weighted). - /// The generic type of the items to choose from. - /// The random algorithm for index generation. - /// The values to choose from. - /// A randomly selected value from the supplied options. - public static T Choose(this Random random, params T[] values) => - values[random.Next(values.Length)]; - - #endregion - - #region Next (Weighted) - - /// Selects a random value from a collection of weighted options. - /// The generic type to select a random instance of. - /// The random algorithm. - /// The pool of weighted values to choose from. - /// A randomly selected value from the weighted pool. - public static T Next(this Random random, params (T Value, double Weight)[] pool) => - random.Next((System.Collections.Generic.IEnumerable<(T Value, double Weight)>)pool); - - /// Selects a random value from a collection of weighted options. - /// The generic type to select a random instance of. - /// The random algorithm. - /// The pool of weighted values to choose from. - /// The total weight of all the values in the pool. - /// A randomly selected value from the weighted pool. - public static T Next(this Random random, double totalWeight, params (T Value, double Weight)[] pool) => - random.Next(pool, totalWeight); - - /// Selects a random value from a collection of weighted options. - /// The generic type to select a random instance of. - /// The random algorithm. - /// The pool of weighted values to choose from. - /// The total weight of all the values in the pool. - /// A randomly selected value from the weighted pool. - public static T Next(this Random random, System.Collections.Generic.IEnumerable<(T Value, double Weight)> pool, double? totalWeight = null) - { - if (!totalWeight.HasValue) - { - totalWeight = 0; - foreach (var (Value, Weight) in pool) - { - if (Weight < 0) - throw new ArgumentOutOfRangeException(nameof(pool), $"A value in {nameof(pool)} had a weight less than zero."); - totalWeight += Weight; - } - } - else - { - if (totalWeight < 0) - throw new ArgumentOutOfRangeException(nameof(totalWeight), $"The provided {nameof(totalWeight)} of the {nameof(pool)} was less than zero."); - } - if (totalWeight == 0) - throw new ArgumentOutOfRangeException(nameof(pool), $"The total weight of all values in the {nameof(pool)} was zero."); - if (double.IsInfinity(totalWeight.Value)) - throw new ArgumentOutOfRangeException(nameof(pool), $"The total weight of all values in the {nameof(pool)} was an infinite double."); - double randomDouble = random.NextDouble(); - double range = 0; - foreach (var (Value, Weight) in pool) - { - range += Weight; - if (range > totalWeight) - throw new ArgumentOutOfRangeException(nameof(totalWeight), $"The provided {nameof(totalWeight)} of the {nameof(pool)} was less than the actual total weight."); - if (randomDouble < range / totalWeight) - return Value; - } - throw new TowelBugException("There is a bug in the code."); - } - -#if false - - //public static T Next(this Random random, StepperBreak<(T Value, double Weight)> pool, double? totalWeight = null) - //{ - // if (!totalWeight.HasValue) - // { - // totalWeight = 0; - // pool(x => - // { - // if (x.Weight < 0) - // throw new ArgumentOutOfRangeException("A value in the pool had a weight less than zero."); - // totalWeight += x.Weight; - // return Continue; - // }); - // } - // else - // { - // if (totalWeight < 0) - // throw new ArgumentOutOfRangeException("The provided total weight of the pool was less than zero."); - // } - // if (totalWeight == 0) - // throw new ArgumentOutOfRangeException("The total weight of all values in the pool was zero."); - // if (double.IsInfinity(totalWeight.Value)) - // throw new ArgumentOutOfRangeException("The total weight of all values in the pool was an infinite double."); - // double randomDouble = random.NextDouble(); - // double range = 0; - // T @return = default; - // StepStatus status = pool(x => - // { - // range += x.Weight; - // if (range > totalWeight) - // throw new ArgumentOutOfRangeException("The provided total weight of the pool was less than the actual total weight."); - // if (randomDouble < range / totalWeight) - // { - // @return = x.Value; - // return Break; - // } - // return Continue; - // }); - // return status is Break - // ? @return - // : throw new TowelBugException("There is a bug in the code."); - //} - -#endif - - #endregion - - #endregion - #region Array #region Stepper @@ -1088,276 +601,41 @@ public static T[][] ConstructRectangularJaggedArray(int length1, int length2) /// Constructs a square jagged array of the desired dimensions. /// The generic type to store in the jagged array. - /// The length of each dimension. + /// The length of the first dimension. + /// The length of the second dimension. + /// The function to initialize the values with. /// The constructed jagged array. - public static T[][] ConstructSquareJaggedArray(int sideLength) => - ConstructRectangularJaggedArray(sideLength, sideLength); - - #endregion - - #region To English Words - - internal static class ToEnglishWordsDefinitions + public static T[][] ConstructRectangularJaggedArray(int length1, int length2, Func func) { - internal static string[] Digit = - { - /* 0 */ null!, - /* 1 */ "One", - /* 2 */ "Two", - /* 3 */ "Three", - /* 4 */ "Four", - /* 5 */ "Five", - /* 6 */ "Six", - /* 7 */ "Seven", - /* 8 */ "Eight", - /* 9 */ "Nine", - }; - - internal static string[] FractionalSufix = - { - /* 0 */ null!, - /* 1 */ "Tenths", - /* 2 */ "Hundredths", - /* 3 */ "Thousandths", - /* 4 */ "Ten-Thousandths", - /* 5 */ "Hundred-Thousandths", - /* 6 */ "Millionths", - /* 7 */ "Ten-Millionths", - /* 8 */ "Hundred-Millionths", - /* 9 */ "Billionths", - /* 10 */ "Ten-Billionths", - /* 11 */ "Hundred-Billionths", - /* 12 */ "Trilionths", - /* 13 */ "Ten-Trilionths", - /* 14 */ "Hundred-Trilionths", - /* 15 */ "Quadrillionths", - /* 16 */ "Ten-Quadrillionths", - /* 17 */ "Hundred-Quadrillionths", - /* 18 */ "Quintrillionths", - /* 19 */ "Ten-Quintrillionths", - /* 20 */ "Hundred-Quintrillionths", - /* 21 */ "Sextillionths", - /* 22 */ "Ten-Sextillionths", - /* 23 */ "Hundred-Sextillionths", - /* 24 */ "Septillionths", - /* 25 */ "Ten-Septillionths", - /* 26 */ "Hundred-Septillionths", - /* 27 */ "Octillionths", - /* 28 */ "Ten-Octillionths", - /* 29 */ "Hundred-Octillionths", - }; - - internal static string[] Ten = - { - /* 0 */ null!, - /* 1 */ "Ten", - /* 2 */ "Twenty", - /* 3 */ "Thirty", - /* 4 */ "Forty", - /* 5 */ "Fifty", - /* 6 */ "Sixty", - /* 7 */ "Seventy", - /* 8 */ "Eighty", - /* 9 */ "Ninety", - }; - - internal static string[] Teen = - { - /* 0 */ null!, - /* 1 */ "Eleven", - /* 2 */ "Twelve", - /* 3 */ "Thirteen", - /* 4 */ "Fourteen", - /* 5 */ "Fifteen", - /* 6 */ "Sixteen", - /* 7 */ "Seventeen", - /* 8 */ "Eighteen", - /* 9 */ "Nineteen", - }; - - internal static string[] Group = - { - /* 0 */ null!, - /* 1 */ null!, - /* 2 */ "Thousand", - /* 3 */ "Million", - /* 4 */ "Billion", - /* 5 */ "Trillion", - /* 6 */ "Quadrillion", - /* 7 */ "Quintillion", - /* 8 */ "Sextillion", - /* 9 */ "Septillion", - /* 10 */ "Octillion", - }; - } - - internal static string ToEnglishWords(ReadOnlySpan number) - { - if (number.Length == 1 && number[0] == '0') - { - return "Zero"; - } - StringBuilder stringBuilder = new StringBuilder(); - bool spaceNeeded = false; - if (number[0] == '-') - { - Append("Negative"); - spaceNeeded = true; - number = number[1..]; - } - if (number[0] == '0') - { - number = number[1..]; - } - int decimalIndex = number.IndexOf('.'); - if (decimalIndex != 0) - { - ReadOnlySpan wholeNumber = decimalIndex >= 0 - ? number[0..decimalIndex] - : number; - WholeNumber(wholeNumber); - } - if (decimalIndex >= 0) - { - if (decimalIndex != 0) - { - AppendLeadingSpace(); - Append("And"); - } - ReadOnlySpan fractionalNumber = number[(decimalIndex + 1)..]; - WholeNumber(fractionalNumber); - AppendLeadingSpace(); - Append(ToEnglishWordsDefinitions.FractionalSufix[fractionalNumber.Length]); - } - string result = stringBuilder.ToString(); - return result; - - void Append(string @string) => stringBuilder.Append(@string); - - void AppendLeadingSpace() - { - if (!spaceNeeded) - { - spaceNeeded = true; - } - else - { - Append(" "); - } - } - - void WholeNumber(ReadOnlySpan wholeNumber) + T[][] jaggedArray = new T[length1][]; + for (int i = 0; i < length1; i++) { - // A "digit group" is a set of hundreds + tens + ones digits. - // In the number 123456789 the digit groups are the following: 123, 456, 789 - // In the number 12345 the digit groups are the following: 12, 345 - - int mod3 = wholeNumber.Length % 3; - int digitGroup = wholeNumber.Length / 3 + (mod3 == 0 ? 0 : 1); - while (digitGroup > 0) - { - int i__X = (wholeNumber.Length - (digitGroup - 1) * 3) - 1; // index of ones digit - int i_X_ = i__X - 1; // index of tens digit - int iX__ = i_X_ - 1; // index of hundreds digit - - char c__X = wholeNumber[i__X]; // character of ones digit - char c_X_ = i_X_ >= 0 ? wholeNumber[i_X_] : '0'; // character of tens digit - char cX__ = iX__ >= 0 ? wholeNumber[iX__] : '0'; // character of hundreds digit - - if (c__X > '0' || c_X_ > '0' || cX__ > '0') - { - DigitGroup(cX__, c_X_, c__X); - if (digitGroup > 1) - { - AppendLeadingSpace(); - Append(ToEnglishWordsDefinitions.Group[digitGroup]); - } - } - digitGroup--; - } + jaggedArray[i] = new T[length2]; } - - void DigitGroup(char hundredsDigit, char tensDigit, char onesDigit) + for (int i = 0; i < length1; i++) { - int hundred = hundredsDigit - '0'; - int ten = tensDigit - '0'; - int one = onesDigit - '0'; - if (hundred > 0) - { - AppendLeadingSpace(); - Append(ToEnglishWordsDefinitions.Digit[hundred]); - Append(" Hundred"); - } - if (ten > 0) + for (int j = 0; j < length2; j++) { - AppendLeadingSpace(); - if (one == 0) - { - Append(ToEnglishWordsDefinitions.Ten[ten]); - } - else if (ten == 1) - { - Append(ToEnglishWordsDefinitions.Teen[one]); - } - else - { - Append(ToEnglishWordsDefinitions.Ten[ten]); - Append("-"); - Append(ToEnglishWordsDefinitions.Digit[one]); - } - } - else if (one > 0) - { - AppendLeadingSpace(); - Append(ToEnglishWordsDefinitions.Digit[one]); + jaggedArray[i][j] = func(i, j); } } + return jaggedArray; } - /// Converts a to the English words representation. - /// The value to convert to English words representation. - /// The English words representation of the value. - public static string ToEnglishWords(this decimal @decimal) => ToEnglishWords(@decimal.ToString(System.Globalization.CultureInfo.InvariantCulture)); - - /// Converts a to the English words representation. - /// The value to convert to English words representation. - /// The English words representation of the value. - public static string ToEnglishWords(this int @int) => ToEnglishWords(@int.ToString(System.Globalization.CultureInfo.InvariantCulture)); - - /// Converts a to the English words representation. - /// The value to convert to English words representation. - /// The English words representation of the value. - public static string ToEnglishWords(this long @long) => ToEnglishWords(@long.ToString(System.Globalization.CultureInfo.InvariantCulture)); - - /// Converts a to the English words representation. - /// The value to convert to English words representation. - /// The English words representation of the value. - public static string ToEnglishWords(this byte @byte) => ToEnglishWords(@byte.ToString(System.Globalization.CultureInfo.InvariantCulture)); - - /// Converts a to the English words representation. - /// The value to convert to English words representation. - /// The English words representation of the value. - public static string ToEnglishWords(this sbyte @sbyte) => ToEnglishWords(@sbyte.ToString(System.Globalization.CultureInfo.InvariantCulture)); - - /// Converts a to the English words representation. - /// The value to convert to English words representation. - /// The English words representation of the value. - public static string ToEnglishWords(this uint @uint) => ToEnglishWords(@uint.ToString(System.Globalization.CultureInfo.InvariantCulture)); - - /// Converts a to the English words representation. - /// The value to convert to English words representation. - /// The English words representation of the value. - public static string ToEnglishWords(this ulong @ulong) => ToEnglishWords(@ulong.ToString(System.Globalization.CultureInfo.InvariantCulture)); - - /// Converts a to the English words representation. - /// The value to convert to English words representation. - /// The English words representation of the value. - public static string ToEnglishWords(this short @short) => ToEnglishWords(@short.ToString(System.Globalization.CultureInfo.InvariantCulture)); - - /// Converts a to the English words representation. - /// The value to convert to English words representation. - /// The English words representation of the value. - public static string ToEnglishWords(this ushort @ushort) => ToEnglishWords(@ushort.ToString(System.Globalization.CultureInfo.InvariantCulture)); + /// Constructs a square jagged array of the desired dimensions. + /// The generic type to store in the jagged array. + /// The length of each dimension. + /// The constructed jagged array. + public static T[][] ConstructSquareJaggedArray(int sideLength) => + ConstructRectangularJaggedArray(sideLength, sideLength); + + /// Constructs a square jagged array of the desired dimensions. + /// The generic type to store in the jagged array. + /// The length of each dimension. + /// The function to initialize the values with. + /// The constructed jagged array. + public static T[][] ConstructSquareJaggedArray(int sideLength, Func func) => + ConstructRectangularJaggedArray(sideLength, sideLength, func); #endregion @@ -1439,7 +717,7 @@ public static bool IsDefined(this T value) where T : Enum => /// The resulting of the conversion. /// range.Start.IsFromEnd /// range.End.IsFromEnd - internal static System.Collections.Generic.IEnumerable ToIEnumerable(this Range range) + public static System.Collections.Generic.IEnumerable ToIEnumerable(this Range range) { if (range.Start.IsFromEnd) { diff --git a/Sources/Towel/Statics-Permutations.cs b/Sources/Towel/Statics-Permutations.cs new file mode 100644 index 00000000..9644a924 --- /dev/null +++ b/Sources/Towel/Statics-Permutations.cs @@ -0,0 +1,219 @@ +using System; + +namespace Towel +{ + /// Root type of the static functional methods in Towel. + public static partial class Statics + { +#pragma warning disable CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name +#pragma warning disable CS1572 // XML comment has a param tag, but there is no parameter by that name + /// The generic element type of the indexed collection. + /// The action to perform on each permutation. + /// The status checker for cancellation. + /// The get index operation of the collection. + /// The set index operation of the collection. + /// The starting index of the values to permute. + /// The ending index of the values to permute. + /// The action to perform on each permutation. + /// The status checker for cancellation. + /// The get index operation of the collection. + /// The set index operation of the collection. + /// The array to iterate the permutations of. + /// The list to iterate the permutations of. + /// The span of the permutation. + [Obsolete(TowelConstants.NotIntended, true)] + internal static void PermuteXML() => throw new DocumentationMethodException(); + /// Iterates through all the permutations of an indexed collection (using a recursive algorithm). + /// + [Obsolete(TowelConstants.NotIntended, true)] + internal static void PermuteRecursive_XML() => throw new DocumentationMethodException(); + /// Iterates through all the permutations of an indexed collection (using an iterative algorithm). + /// + [Obsolete(TowelConstants.NotIntended, true)] + internal static void PermuteIterative_XML() => throw new DocumentationMethodException(); +#pragma warning restore CS1572 // XML comment has a param tag, but there is no parameter by that name +#pragma warning restore CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name + + /// + public static void PermuteRecursive(int start, int end, Action action, Func get, Action set) => + PermuteRecursive, ActionRuntime>(start, end, action, default, get, set); + + /// + public static void PermuteRecursive(int start, int end, Action action, Func status, Func get, Action set) => + PermuteRecursive, FuncRuntime, ActionRuntime>(start, end, action, status, get, set); + + /// + public static void PermuteRecursive(int start, int end, Action action = default, Get get = default, Set set = default) + where Action : struct, IAction + where Get : struct, IFunc + where Set : struct, IAction => + PermuteRecursive(start, end, action, default, get, set); + + /// + public static void PermuteRecursive(int start, int end, Action action = default, Status status = default, Get get = default, Set set = default) + where Action : struct, IAction + where Status : struct, IFunc + where Get : struct, IFunc + where Set : struct, IAction + { + Permute(start, end); + StepStatus Permute(int a, int b) + { + if (a == b) + { + action.Do(); + return status.Do(); + } + for (int i = a; i <= b; i++) + { + Swap(a, i); + if (Permute(a + 1, b) is Break) + { + return Break; + } + Swap(a, i); + } + return Continue; + } + void Swap(int a, int b) + { + T temp = get.Do(a); + set.Do(a, get.Do(b)); + set.Do(b, temp); + } + } + + /// + public static void PermuteRecursive(Span span, Action action) => + PermuteRecursive(span, action); + + /// + public static void PermuteRecursive(Span span, Action action = default) + where Action : struct, IAction => + PermuteRecursive(span, action); + + /// + public static void PermuteRecursive(Span span, Action action, Status status = default) + where Status : struct, IFunc => + PermuteRecursive(span, action, status); + + /// + public static void PermuteRecursive(Span span, Action action = default, Status status = default) + where Action : struct, IAction + where Status : struct, IFunc + { + Permute(span, 0, span.Length - 1); + StepStatus Permute(Span span, int a, int b) + { + if (a == b) + { + action.Do(); + return status.Do(); + } + for (int i = a; i <= b; i++) + { + Swap(span, a, i); + if (Permute(span, a + 1, b) is Break) + { + return Break; + } + Swap(span, a, i); + } + return Continue; + } + static void Swap(Span span, int a, int b) + { + T temp = span[a]; + span[a] = span[b]; + span[b] = temp; + } + } + + /// + public static void PermuteIterative(int start, int end, Action action, Func get, Action set) => + PermuteIterative, ActionRuntime>(start, end, action, default, get, set); + + /// + public static void PermuteIterative(int start, int end, Action action, Func status, Func get, Action set) => + PermuteIterative, FuncRuntime, ActionRuntime>(start, end, action, status, get, set); + + /// + public static void PermuteIterative(int start, int end, Action action = default, Get get = default, Set set = default) + where Action : struct, IAction + where Get : struct, IFunc + where Set : struct, IAction => + PermuteIterative(start, end, action, default, get, set); + + /// + public static void PermuteIterative(int start, int end, Action action = default, Status status = default, Get get = default, Set set = default) + where Action : struct, IAction + where Status : struct, IFunc + where Get : struct, IFunc + where Set : struct, IAction + { + action.Do(); + int[] indeces = new int[end + 2 - start]; + for (int i = 0; i < indeces.Length; i++) + { + indeces[i] = i; + } + for (int i = start + 1; i < end + 1 && status.Do() is Continue; action.Do()) + { + indeces[i]--; + Swap(i, i % 2 == 1 ? indeces[i] : 0); + for (i = 1; indeces[i] == 0; i++) + { + indeces[i] = i; + } + } + void Swap(int a, int b) + { + T temp = get.Do(a); + set.Do(a, get.Do(b)); + set.Do(b, temp); + } + } + + /// + public static void PermuteIterative(Span span, Action action) => + PermuteIterative(span, action); + + /// + public static void PermuteIterative(Span span, Action action = default) + where Action : struct, IAction => + PermuteIterative(span, action); + + /// + public static void PermuteIterative(Span span, Action action, Status status = default) + where Status : struct, IFunc => + PermuteIterative(span, action, status); + + /// + public static void PermuteIterative(Span span, Action action = default, Status status = default) + where Action : struct, IAction + where Status : struct, IFunc + { + action.Do(); + int[] indeces = new int[span.Length - 1 + 2]; + for (int i = 0; i < indeces.Length; i++) + { + indeces[i] = i; + } + for (int i = 1; i < span.Length && status.Do() is Continue; action.Do()) + { + indeces[i]--; + Swap(span, i, i % 2 == 1 ? indeces[i] : 0); + for (i = 1; indeces[i] == 0; i++) + { + indeces[i] = i; + } + } + static void Swap(Span span, int a, int b) + { + T temp = span[a]; + span[a] = span[b]; + span[b] = temp; + } + } + } +} diff --git a/Sources/Towel/Statics-Random.cs b/Sources/Towel/Statics-Random.cs new file mode 100644 index 00000000..38321756 --- /dev/null +++ b/Sources/Towel/Statics-Random.cs @@ -0,0 +1,183 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Towel +{ + /// Root type of the static functional methods in Towel. + public static partial class Statics + { + /// + /// Generates unique random values in the + /// [..] range where is + /// inclusive and is exclusive. + /// + /// The function to perform on each generated value. + /// The random to generation algorithm. + /// The random to generation algorithm. + /// The number of values to generate. + /// Inclusive endpoint of the random generation range. + /// Exclusive endpoint of the random generation range. + /// The function to perform on each generated value. + public static void NextUnique(int count, int minValue, int maxValue, Random random = default, Step step = default) + where Step : struct, IAction + where Random : struct, IFunc + { + if (count < Math.Sqrt(maxValue - minValue)) + { + NextUniqueRollTracking(count, minValue, maxValue, random, step); + } + else + { + NextUniquePoolTracking(count, minValue, maxValue, random, step); + } + } + + /// + /// Generates unique random values in the + /// [..] range where is + /// inclusive and is exclusive. + /// + /// The function to perform on each generated value. + /// The random to generation algorithm. + /// The random to generation algorithm. + /// The number of values to generate. + /// Inclusive endpoint of the random generation range. + /// Exclusive endpoint of the random generation range. + /// The function to perform on each generated value. + public static void NextUniqueRollTracking(int count, int minValue, int maxValue, Random random = default, Step step = default) + where Step : struct, IAction + where Random : struct, IFunc + { + if (maxValue < minValue) + { + throw new ArgumentOutOfRangeException(nameof(maxValue), $"{nameof(minValue)} > {nameof(maxValue)}"); + } + if (count < 0) + { + throw new ArgumentOutOfRangeException(nameof(count), $"{nameof(count)} < 0"); + } + if (maxValue - minValue < count) + { + throw new ArgumentOutOfRangeException(nameof(count), $"{nameof(count)} is larger than {nameof(maxValue)} - {nameof(minValue)}."); + } + // Algorithm B: O(.5*count^2), Ω(count), ε(.5*count^2) + Node? head = null; + for (int i = 0; i < count; i++) // Θ(count) + { + int roll = random.Do(minValue, maxValue - i); + if (roll < minValue || roll >= maxValue - i) + { + throw new ArgumentException("The Random provided returned a value outside the requested range."); + } + Node? node = head; + Node? previous = null; + while (node is not null && node.Value <= roll) // O(count / 2), Ω(0), ε(count / 2) + { + roll++; + previous = node; + node = node.Next; + } + step.Do(roll); + if (previous is null) + { + head = new Node() { Value = roll, Next = head, }; + } + else + { + previous.Next = new Node() { Value = roll, Next = previous.Next }; + } + } + } + internal class Node + { + internal int Value; + internal Node? Next; + } + + /// + /// Generates unique random values in the + /// [..] range where is + /// inclusive and is exclusive. + /// + /// The function to perform on each generated value. + /// The random to generation algorithm. + /// The random to generation algorithm. + /// The number of values to generate. + /// Inclusive endpoint of the random generation range. + /// Exclusive endpoint of the random generation range. + /// The function to perform on each generated value. + public static void NextUniquePoolTracking(int count, int minValue, int maxValue, Random random = default, Step step = default) + where Step : struct, IAction + where Random : struct, IFunc + { + if (maxValue < minValue) + { + throw new ArgumentOutOfRangeException(nameof(maxValue), $"{nameof(minValue)} > {nameof(maxValue)}"); + } + if (count < 0) + { + throw new ArgumentOutOfRangeException(nameof(count), $"{nameof(count)} < 0"); + } + if (maxValue - minValue < count) + { + throw new ArgumentOutOfRangeException(nameof(count), $"{nameof(count)} is larger than {nameof(maxValue)} - {nameof(minValue)}."); + } + // Algorithm B: Θ(range + count) + int pool = maxValue - minValue; + int[] array = new int[pool]; + for (int i = 0, j = minValue; j < maxValue; i++, j++) // Θ(range) + array[i] = j; + for (int i = 0; i < count; i++) // Θ(count) + { + int rollIndex = random.Do(0, pool); + if (rollIndex < 0 || rollIndex >= pool) + { + throw new ArgumentException("The Random provided returned a value outside the requested range."); + } + int roll = array[rollIndex]; + array[rollIndex] = array[--pool]; + step.Do(roll); + } + } + + /// + /// Generates unique random values in the + /// [..] range where is + /// inclusive and is exclusive. + /// + /// The random to generation algorithm. + /// The random to generation algorithm. + /// The number of values to generate. + /// Inclusive endpoint of the random generation range. + /// Exclusive endpoint of the random generation range. + /// The function to perform on each generated value. + public static void NextUnique(int count, int minValue, int maxValue, Action step, Random random = default) + where Random : struct, IFunc + { + _ = step ?? throw new ArgumentNullException(nameof(step)); + NextUnique, Random>(count, minValue, maxValue, random, step); + } + + /// + /// Generates unique random values in the + /// [..] range where is + /// inclusive and is exclusive. + /// + /// The random to generation algorithm. + /// The random to generation algorithm. + /// The number of values to generate. + /// Inclusive endpoint of the random generation range. + /// Exclusive endpoint of the random generation range. + public static int[] NextUnique(int count, int minValue, int maxValue, Random random = default) + where Random : struct, IFunc + { + int[] values = new int[count]; + int i = 0; + NextUnique, Random>(count, minValue, maxValue, random, new Action(value => values[i++] = value)); + return values; + } + } +} diff --git a/Sources/Towel/Statics-RomanNumerals.cs b/Sources/Towel/Statics-RomanNumerals.cs new file mode 100644 index 00000000..904da2ce --- /dev/null +++ b/Sources/Towel/Statics-RomanNumerals.cs @@ -0,0 +1,103 @@ +namespace Towel +{ + /// Root type of the static functional methods in Towel. + public static partial class Statics + { + internal readonly static int[] RomanNumeralDigits = + { + /* 0:I */ 1, + /* 1:V */ 5, + /* 2:X */ 10, + /* 3:L */ 50, + /* 4:C */ 100, + /* 5:D */ 500, + /* 6:M */ 1000, + }; + + internal readonly static int[] RomanNumeralDigitsAllowsPrefixes = + { + /* 0:I */ default, + /* 1:V */ 0, + /* 2:X */ 0, + /* 3:L */ 2, + /* 4:C */ 2, + /* 5:D */ 4, + /* 6:M */ 4, + }; + + internal readonly static bool[] RomanNumeralDigitsAllowsDuplicates = + { + /* 0:I */ true, + /* 1:V */ false, + /* 2:X */ true, + /* 3:L */ false, + /* 4:C */ true, + /* 5:D */ false, + /* 6:M */ true, + }; + + /// Attempts to parse a Roman Numeral into an value. + /// The Roman Numeral to parse into an value. + /// + /// ( Success, Value) + /// - Success: true if the parse was successful or false if not + /// - Value: the parsed value if the parse was successful or default if not + /// + public static (bool Success, int Value) TryParseRomanNumeral(string @string) + { + if (@string is null || + @string.Length < 1) + { + return (false, default); + } + int result = 0; + int a = default; + int? b = null; + int? c = null; + int? d = null; + bool handled = false; + foreach (char @char in @string) + { + switch (@char) + { + case 'I': a = 0; break; + case 'V': a = 1; break; + case 'X': a = 2; break; + case 'L': a = 3; break; + case 'C': a = 4; break; + case 'D': a = 5; break; + case 'M': a = 6; break; + default: return (false, default); + }; + if ((c.HasValue && c.Value < a) || + (a == b && a == c && a == d) || + ((b.HasValue && b.Value < a && b.Value != RomanNumeralDigitsAllowsPrefixes[a])) || + (b == a && !RomanNumeralDigitsAllowsDuplicates[a])) + { + return (false, default); + } + else if (!handled && b.HasValue && b.Value < a) + { + result += RomanNumeralDigits[a] - RomanNumeralDigits[b.Value]; + handled = true; + } + else if (handled) + { + handled = false; + } + else if (b.HasValue) + { + result += RomanNumeralDigits[b.Value]; + } + d = c; + c = b; + b = a; + } + if (!handled) + { + result += RomanNumeralDigits[a]; + } + return (true, result); + } + } +} diff --git a/Sources/Towel/Statics-SearchingAlgorithms.cs b/Sources/Towel/Statics-SearchingAlgorithms.cs new file mode 100644 index 00000000..ba0dd521 --- /dev/null +++ b/Sources/Towel/Statics-SearchingAlgorithms.cs @@ -0,0 +1,582 @@ +using System; +using Towel.DataStructures; + +namespace Towel +{ + /// Root type of the static functional methods in Towel. + public static partial class Statics + { + #region SearchBinary + +#pragma warning disable CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name +#pragma warning disable CS1572 // XML comment has a param tag, but there is no parameter by that name +#pragma warning disable CS1734 // XML comment has a paramref tag, but there is no parameter by that name +#pragma warning disable CS1735 // XML comment has a typeparamref tag, but there is no type parameter by that name + /// Performs a binary search on sorted indexed data. + /// The type of elements to search through. + /// The function for getting an element at an index. + /// The function for sifting through the elements. + /// The compare function. + /// The starting index of the binary search. + /// The number of elements to be searched after the starting . + /// The function for getting an element at an index. + /// The function for comparing the the elements to th desired target. + /// The array search. + /// The element to search for. + /// The compare function. + /// The span of the binary search. + /// + /// ( Found, Index, Value) + /// - Found: True if a match was found; False if not. + /// - Index: The resulting index of the search that will always be <= the desired match. + /// - Value: The resulting value of the binary search if a match was found or default if not. + /// + [Obsolete(TowelConstants.NotIntended, true)] + internal static void SearchBinary_XML() => throw new DocumentationMethodException(); +#pragma warning restore CS1735 // XML comment has a typeparamref tag, but there is no type parameter by that name +#pragma warning restore CS1734 // XML comment has a paramref tag, but there is no parameter by that name +#pragma warning restore CS1572 // XML comment has a param tag, but there is no parameter by that name +#pragma warning restore CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name + +#if false // keeping this for future reference; array types are supports by the ReadOnlySpan overloads + + /// + public static (bool Found, int Index, T Value) SearchBinary(T[] array, T element, Func compare = default) + { + _ = array ?? throw new ArgumentNullException(nameof(array)); + return SearchBinary, SiftFromCompareAndValue>>(0, array.Length, array, new SiftFromCompareAndValue>(element, compare ?? Compare)); + } + + /// + public static (bool Found, int Index, T Value) SearchBinary(T[] array, T element, Compare compare = default) + where Compare : IFunc + { + _ = array ?? throw new ArgumentNullException(nameof(array)); + return SearchBinary, SiftFromCompareAndValue>(0, array.Length, array, new SiftFromCompareAndValue(element, compare)); + } + + /// + public static (bool Found, int Index, T Value) SearchBinary(T[] array, Func sift) + { + _ = array ?? throw new ArgumentNullException(nameof(array)); + return SearchBinary, FuncRuntime>(0, array.Length, array, sift); + } + + /// + public static (bool Found, int Index, T Value) SearchBinary(T[] array, Sift sift = default) + where Sift : IFunc + { + _ = array ?? throw new ArgumentNullException(nameof(array)); + return SearchBinary, Sift>(0, array.Length, array, sift); + } + +#endif + + /// + public static (bool Found, int Index, T? Value) SearchBinary(int length, Func get, Func sift) + { + _ = get ?? throw new ArgumentNullException(nameof(get)); + _ = sift ?? throw new ArgumentNullException(nameof(sift)); + return SearchBinary, FuncRuntime>(0, length, get, sift); + } + + /// + public static (bool Found, int Index, T? Value) SearchBinary(int index, int length, Get get = default, Sift sift = default) + where Get : struct, IFunc + where Sift : struct, IFunc + { + if (length <= 0) + { + throw new ArgumentOutOfRangeException(nameof(length), length, "!(" + nameof(length) + " > 0)"); + } + if (index < 0) + { + throw new ArgumentOutOfRangeException(nameof(index), index, "!(" + nameof(index) + " > 0)"); + } + if (length > int.MaxValue / 2 && index > int.MaxValue / 2) + { + throw new ArgumentOutOfRangeException($"{nameof(length)} > {int.MaxValue / 2} && {nameof(index)} / {int.MaxValue / 2}", default(Exception)); + } + int low = index; + int hi = index + length - 1; + while (low <= hi) + { + int median = low + (hi - low) / 2; + T value = get.Do(median); + CompareResult compareResult = sift.Do(value); + switch (compareResult) + { + case Less: low = median + 1; break; + case Greater: hi = median - 1; break; + case Equal: return (true, median, value); + default: + throw compareResult.IsDefined() + ? (Exception)new TowelBugException($"Unhandled {nameof(CompareResult)} value: {compareResult}.") + : new ArgumentException($"Invalid {nameof(Sift)} function; an undefined {nameof(CompareResult)} was returned.", nameof(sift)); + } + } + return (false, Math.Min(low, hi), default); + } + + /// + public static (bool Found, int Index, T? Value) SearchBinary(ReadOnlySpan span, T element, Func? compare = default) => + SearchBinary>>(span, new SiftFromCompareAndValue>(element, compare ?? Compare)); + + /// + public static (bool Found, int Index, T? Value) SearchBinary(ReadOnlySpan span, Func sift) + { + _ = sift ?? throw new ArgumentNullException(nameof(sift)); + return SearchBinary>(span, sift); + } + + /// + public static (bool Found, int Index, T? Value) SearchBinary(ReadOnlySpan span, T element, Compare compare = default) + where Compare : struct, IFunc => + SearchBinary>(span, new SiftFromCompareAndValue(element, compare)); + + /// + public static (bool Found, int Index, T? Value) SearchBinary(ReadOnlySpan span, Sift sift = default) + where Sift : struct, IFunc + { + if (span.IsEmpty) + { + throw new ArgumentException($@"{nameof(span)}.{nameof(span.IsEmpty)}", nameof(span)); + } + int low = 0; + int hi = span.Length - 1; + while (low <= hi) + { + int median = low + (hi - low) / 2; + T value = span[median]; + CompareResult compareResult = sift.Do(value); + switch (compareResult) + { + case Less: low = median + 1; break; + case Greater: hi = median - 1; break; + case Equal: return (true, median, value); + default: + throw compareResult.IsDefined() + ? (Exception)new TowelBugException($"Unhandled {nameof(CompareResult)} value: {compareResult}.") + : new ArgumentException($"Invalid {nameof(Sift)} function; an undefined {nameof(CompareResult)} was returned.", nameof(sift)); + } + } + return (false, Math.Min(low, hi), default); + } + + #endregion + + #region Search Graph Algorithms + + #region Publics + + /// The status of a graph search algorithm. + public enum GraphSearchStatus + { + /// Graph search was not broken. + Continue = StepStatus.Continue, + /// Graph search was broken. + Break = StepStatus.Break, + /// Graph search found the goal. + Goal = 2, + } + + /// Syntax sugar hacks. + public static class GraphSyntax + { + /// This is a syntax sugar hack to allow implicit conversions from StepStatus to GraphSearchStatus. + public struct GraphSearchStatusStruct + { + internal readonly GraphSearchStatus Value; + /// Constructs a new graph search status. + /// The status of the graph search. + public GraphSearchStatusStruct(GraphSearchStatus value) => Value = value; + /// Converts a into a . + /// The to convert. + public static implicit operator GraphSearchStatusStruct(GraphSearchStatus value) => new GraphSearchStatusStruct(value); + /// Converts a into a . + /// The to convert. + public static implicit operator GraphSearchStatusStruct(StepStatus value) => new GraphSearchStatusStruct((GraphSearchStatus)value); + /// Converts a into a . + /// The to convert. + public static implicit operator GraphSearchStatus(GraphSearchStatusStruct value) => value.Value; + } + } + + /// Step function for all neigbors of a given node. + /// The node type of the graph being searched. + /// The node to step through all the neighbors of. + /// Step function to perform on all neighbors. + public delegate void SearchNeighbors(Node current, Action neighbors); + /// Computes the heuristic value of a given node in a graph (smaller values mean closer to goal node). + /// The node type of the graph being searched. + /// The numeric to use when performing calculations. + /// The node to compute the heuristic value of. + /// The computed heuristic value for this node. + public delegate Numeric SearchHeuristic(Node node); + /// Computes the cost of moving from the current node to a specific neighbor. + /// The node type of the graph being searched. + /// The numeric to use when performing calculations. + /// The current (starting) node. + /// The node to compute the cost of movign to. + /// The computed cost value of movign from current to neighbor. + public delegate Numeric SearchCost(Node current, Node neighbor); + /// Predicate for determining if we have reached the goal node. + /// The node type of the graph being searched. + /// The current node. + /// True if the current node is a/the goal node; False if not. + public delegate bool SearchGoal(Node current); + /// Checks the status of a graph search. + /// The node type of the search. + /// The current node of the search. + /// The status of the search. + public delegate GraphSyntax.GraphSearchStatusStruct SearchCheck(Node current); + + #endregion + + #region Internals + + internal abstract class BaseAlgorithmNode + where AlgorithmNode : BaseAlgorithmNode + { + internal AlgorithmNode? Previous; + internal Node Value; + + internal BaseAlgorithmNode(Node value, AlgorithmNode? previous = null) + { + Value = value; + Previous = previous; + } + } + + internal class BreadthFirstSearch : BaseAlgorithmNode, Node> + { + internal BreadthFirstSearch(Node value, BreadthFirstSearch? previous = null) + : base(value: value, previous: previous) { } + } + + internal class DijkstraNode : BaseAlgorithmNode, Node> + { + internal Numeric Priority; + + internal DijkstraNode(Node value, Numeric priority, DijkstraNode? previous = null) + : base(value: value, previous: previous) + { + Priority = priority; + } + } + + internal class AstarNode : BaseAlgorithmNode, Node> + { + internal Numeric Priority; + internal Numeric Cost; + + internal AstarNode(Node value, Numeric priority, Numeric cost, AstarNode? previous = null) + : base(value: value, previous: previous) + { + Priority = priority; + Cost = cost; + } + } + + internal class PathNode + { + internal Node Value; + internal PathNode? Next; + + internal PathNode(Node value, PathNode? next = null) + { + Value = value; + Next = next; + } + } + + internal static Action> BuildPath(BaseAlgorithmNode node) + where AlgorithmNode : BaseAlgorithmNode + { + PathNode? start = null; + for (BaseAlgorithmNode? current = node; current is not null; current = current.Previous) + { + PathNode? temp = start; + start = new PathNode( + value: current.Value, + next: temp); + } + return step => + { + PathNode? current = start; + while (current is not null) + { + step(current.Value); + current = current.Next; + } + }; + } + + internal struct AStarPriorityCompare : IFunc, AstarNode, CompareResult> + { + // NOTE: Typical A* implementations prioritize smaller values + public CompareResult Do(AstarNode a, AstarNode b) => + Compare(b.Priority, a.Priority); + } + + internal struct DijkstraPriorityCompare : IFunc, DijkstraNode, CompareResult> + { + // NOTE: Typical A* implementations prioritize smaller values + public CompareResult Do(DijkstraNode a, DijkstraNode b) => + Compare(b.Priority, a.Priority); + } + + #endregion + + #region Graph (Shared) + +#pragma warning disable CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name +#pragma warning disable CS1572 // XML comment has a param tag, but there is no parameter by that name + /// The node type of the graph being searched. + /// The numeric to use when performing calculations. + /// The node to start at. + /// Step function for all neigbors of a given node. + /// Computes the heuristic value of a given node in a graph. + /// Computes the cost of moving from the current node to a specific neighbor. + /// Checks the status of the search. + /// The total cost of the path if a path was found. + /// The goal of the search. + /// The graph to perform the search on. + /// Stepper of the shortest path or null if no path exists. + [Obsolete(TowelConstants.NotIntended, true)] + internal static void SearchGraph_XML() => throw new DocumentationMethodException(); +#pragma warning restore CS1572 // XML comment has a param tag, but there is no parameter by that name +#pragma warning restore CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name + + #endregion + + #region A* Algorithm + + /// Runs the A* search algorithm on a graph. + /// + [Obsolete(TowelConstants.NotIntended, true)] + internal static void Graph_Astar_XML() => throw new DocumentationMethodException(); + + /// + public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchCost cost, SearchGoal goal, out Numeric? totalCost) => + SearchGraph(start, neighbors, heuristic, cost, node => goal(node) ? GraphSearchStatus.Goal : GraphSearchStatus.Continue, out totalCost); + + /// + public static Action>? SearchGraph(Node start, IGraph graph, SearchHeuristic heuristic, SearchCost cost, SearchGoal goal, out Numeric? totalCost) => + SearchGraph(start, graph.Neighbors, heuristic, cost, goal, out totalCost); + + /// + public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchCost cost, Node goal, out Numeric? totalCost) => + SearchGraph(start, neighbors, heuristic, cost, goal, Equate, out totalCost); + + /// + public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchCost cost, Node goal, Func equate, out Numeric? totalCost) => + SearchGraph(start, neighbors, heuristic, cost, node => equate(node, goal), out totalCost); + + /// + public static Action>? SearchGraph(Node start, IGraph graph, SearchHeuristic heuristic, SearchCost cost, Node goal, out Numeric? totalCost) => + SearchGraph(start, graph, heuristic, cost, goal, Equate, out totalCost); + + /// + public static Action>? SearchGraph(Node start, IGraph graph, SearchHeuristic heuristic, SearchCost cost, Node goal, Func equate, out Numeric? totalCost) => + SearchGraph(start, graph.Neighbors, heuristic, cost, node => equate(node, goal), out totalCost); + + /// + public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchCost cost, SearchCheck check, out Numeric? totalCost) + { + // using a heap (aka priority queue) to store nodes based on their computed A* f(n) value + IHeap> fringe = new HeapArray, AStarPriorityCompare>(); + + // push starting node + fringe.Enqueue( + new AstarNode( + value: start, + priority: Constant.Zero, + cost: Constant.Zero, + previous: null)); + + // run the algorithm + while (fringe.Count != 0) + { + AstarNode current = fringe.Dequeue(); + GraphSearchStatus status = check(current.Value); + if (status is GraphSearchStatus.Break) + { + break; + } + else if (status is GraphSearchStatus.Goal) + { + totalCost = current.Cost; + return BuildPath(current); + } + else + { + neighbors(current.Value, + neighbor => + { + Numeric costValue = Addition(current.Cost, cost(current.Value, neighbor)); + fringe.Enqueue( + new AstarNode( + value: neighbor, + priority: Addition(heuristic(neighbor), costValue), + cost: costValue, + previous: current)); + }); + } + } + totalCost = default; + return null; // goal node was not reached (no path exists) + } + + #endregion + + #region Dijkstra Algorithm + + /// Runs the Dijkstra search algorithm on a graph. + /// + [Obsolete(TowelConstants.NotIntended, true)] + internal static void Graph_Dijkstra_XML() => throw new DocumentationMethodException(); + + /// + public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchGoal goal) => + SearchGraph(start, neighbors, heuristic, node => goal(node) ? GraphSearchStatus.Goal : GraphSearchStatus.Continue); + + /// + public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, Node goal) => + SearchGraph(start, neighbors, heuristic, goal, Equate); + + /// + public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, Node goal, Func equate) => + SearchGraph(start, neighbors, heuristic, node => equate(node, goal)); + + /// + public static Action>? SearchGraph(Node start, IGraph graph, SearchHeuristic heuristic, Node goal) => + SearchGraph(start, graph, heuristic, goal, Equate); + + /// + public static Action>? SearchGraph(Node start, IGraph graph, SearchHeuristic heuristic, Node goal, Func equate) => + SearchGraph(start, graph.Neighbors, heuristic, node => equate(node, goal)); + + /// + public static Action>? SearchGraph(Node start, IGraph graph, SearchHeuristic heuristic, SearchGoal goal) => + SearchGraph(start, graph.Neighbors, heuristic, goal); + + /// + public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchCheck check) + { + // using a heap (aka priority queue) to store nodes based on their computed heuristic value + IHeap> fringe = new HeapArray, DijkstraPriorityCompare>(); + + // push starting node + fringe.Enqueue( + new DijkstraNode( + value: start, + priority: Constant.Zero, + previous: null)); + + // run the algorithm + while (fringe.Count != 0) + { + DijkstraNode current = fringe.Dequeue(); + GraphSearchStatus status = check(current.Value); + if (status is GraphSearchStatus.Break) + { + break; + } + if (status is GraphSearchStatus.Goal) + { + return BuildPath(current); + } + else + { + neighbors(current.Value, + neighbor => + { + fringe.Enqueue( + new DijkstraNode( + value: neighbor, + priority: heuristic(neighbor), + previous: current)); + }); + } + } + return null; // goal node was not reached (no path exists) + } + + #endregion + + #region BreadthFirstSearch Algorithm + + /// Runs the Breadth-First-Search search algorithm on a graph. + /// + [Obsolete(TowelConstants.NotIntended, true)] + internal static void Graph_BreadthFirstSearch_XML() => throw new DocumentationMethodException(); + + /// + public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchGoal goal) => + SearchGraph(start, neighbors, node => goal(node) ? GraphSearchStatus.Goal : GraphSearchStatus.Continue); + + /// + public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, Node goal) => + SearchGraph(start, neighbors, goal, Equate); + + /// + public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, Node goal, Func equate) => + SearchGraph(start, neighbors, node => equate(node, goal)); + + /// + public static Action>? SearchGraph(Node start, IGraph graph, Node goal) => + SearchGraph(start, graph, goal, Equate); + + /// + public static Action>? SearchGraph(Node start, IGraph graph, Node goal, Func equate) => + SearchGraph(start, graph.Neighbors, node => equate(node, goal)); + + /// + public static Action>? SearchGraph(Node start, IGraph graph, SearchGoal goal) => + SearchGraph(start, graph.Neighbors, goal); + + /// + public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchCheck check) + { + IQueue> fringe = new QueueLinked>(); + + // push starting node + fringe.Enqueue( + new BreadthFirstSearch( + value: start, + previous: null)); + + // run the algorithm + while (fringe.Count != 0) + { + BreadthFirstSearch current = fringe.Dequeue(); + GraphSearchStatus status = check(current.Value); + if (status is GraphSearchStatus.Break) + { + break; + } + if (status is GraphSearchStatus.Goal) + { + return BuildPath(current); + } + else + { + neighbors(current.Value, + neighbor => + { + fringe.Enqueue( + new BreadthFirstSearch( + value: neighbor, + previous: current)); + }); + } + } + return null; // goal node was not reached (no path exists) + } + + #endregion + + #endregion + } +} diff --git a/Sources/Towel/Statics-SequenceAnalysis.cs b/Sources/Towel/Statics-SequenceAnalysis.cs new file mode 100644 index 00000000..01054d42 --- /dev/null +++ b/Sources/Towel/Statics-SequenceAnalysis.cs @@ -0,0 +1,1250 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Towel.DataStructures; + +namespace Towel +{ + /// Root type of the static functional methods in Towel. + public static partial class Statics + { + #region Maximum + + /// Computes the maximum of two numeric values. + /// The numeric type of the operation. + /// The first operand of the maximum operation. + /// The second operand of the maximum operation. + /// The computed maximum of the provided values. + public static T Maximum(T a, T b) => + GreaterThanOrEqual(a, b) ? a : b; + + /// Computes the maximum of multiple numeric values. + /// The numeric type of the operation. + /// The first operand of the maximum operation. + /// The second operand of the maximum operation. + /// The third operand of the maximum operation. + /// The remaining operands of the maximum operation. + /// The computed maximum of the provided values. + public static T Maximum(T a, T b, T c, params T[] d) => + Maximum(step => { step(a); step(b); step(c); d.ToStepper()(step); }); + + /// Computes the maximum of multiple numeric values. + /// The numeric type of the operation. + /// The set of data to compute the maximum of. + /// The computed maximum of the provided values. + public static T Maximum(Action> stepper) => + OperationOnStepper(stepper, Maximum); + + public static (int Index, T Value) Maximum(ReadOnlySpan span, Compare compare = default) + where Compare : struct, IFunc + { + if (span.IsEmpty) + { + throw new ArgumentException($"{nameof(span)}.{nameof(span.IsEmpty)}", nameof(span)); + } + int index = 0; + for (int i = 1; i < span.Length; i++) + { + if (compare.Do(span[i], span[index]) is Greater) + { + index = i; + } + } + return (index, span[index]); + } + + #endregion + + #region Minimum + + /// Computes the minimum of two numeric values. + /// The numeric type of the operation. + /// The first operand of the minimum operation. + /// The second operand of the minimum operation. + /// The computed minimum of the provided values. + public static T Minimum(T a, T b) => + LessThanOrEqual(a, b) ? a : b; + + /// Computes the minimum of multiple numeric values. + /// The numeric type of the operation. + /// The first operand of the minimum operation. + /// The second operand of the minimum operation. + /// The third operand of the minimum operation. + /// The remaining operands of the minimum operation. + /// The computed minimum of the provided values. + public static T Minimum(T a, T b, T c, params T[] d) => + Minimum(step => { step(a); step(b); step(c); d.ToStepper()(step); }); + + /// Computes the minimum of multiple numeric values. + /// The numeric type of the operation. + /// The set of data to compute the minimum of. + /// The computed minimum of the provided values. + public static T Minimum(Action> stepper) => + OperationOnStepper(stepper, Minimum); + + /// Computes the minimum of multiple numeric values. + /// The first operand of the minimum operation. + /// The second operand of the minimum operation. + /// The third operand of the minimum operation. + /// The computed minimum of the provided values. + public static int Minimum(int a, int b, int c) => Math.Min(Math.Min(a, b), c); + + public static (int Index, T Value) Minimum(ReadOnlySpan span, Compare compare = default) + where Compare : struct, IFunc + { + if (span.IsEmpty) + { + throw new ArgumentException($"{nameof(span)}.{nameof(span.IsEmpty)}", nameof(span)); + } + int index = 0; + for (int i = 1; i < span.Length; i++) + { + if (compare.Do(span[i], span[index]) is Less) + { + index = i; + } + } + return (index, span[index]); + } + + #endregion + + #region Range + + /// Gets the range (minimum and maximum) of a set of data. + /// The numeric type of the operation. + /// /// The set of data to get the range of. + /// The minimum of the set of data. + /// The maximum of the set of data. + /// Throws when stepper is null. + /// Throws when stepper is empty. + public static void Range(out T minimum, out T maximum, Action> stepper) => + Range(stepper, out minimum, out maximum); + + /// Gets the range (minimum and maximum) of a set of data. + /// The numeric type of the operation. + /// /// The set of data to get the range of. + /// The minimum of the set of data. + /// The maximum of the set of data. + /// Throws when stepper is null. + /// Throws when stepper is empty. + public static void Range(Action> stepper, out T minimum, out T maximum) + { + _ = stepper ?? throw new ArgumentNullException(nameof(stepper)); + // Note: can't use out parameters as capture variables + T min = default; + T max = default; + bool assigned = false; + stepper(a => + { + if (assigned) + { + min = LessThan(a, min) ? a : min; + max = LessThan(max, a) ? a : max; + } + else + { + min = a; + max = a; + assigned = true; + } + }); + if (!assigned) + { + throw new ArgumentException("The argument is empty.", nameof(stepper)); + } + minimum = min!; + maximum = max!; + } + + public static ((int MinIndex, T MinValue), (int MaxIndex, T MaxValue)) Range(ReadOnlySpan span, Compare compare = default) + where Compare : struct, IFunc + { + if (span.IsEmpty) + { + throw new ArgumentException($"{nameof(span)}.{nameof(span.IsEmpty)}", nameof(span)); + } + int minIndex = 0; + int maxIndex = 0; + for (int i = 1; i < span.Length; i++) + { + if (compare.Do(span[i], span[minIndex]) is Less) + { + minIndex = i; + } + if (compare.Do(span[i], span[maxIndex]) is Greater) + { + maxIndex = i; + } + } + return ((minIndex, span[minIndex]), (maxIndex, span[maxIndex])); + } + + #endregion + + #region Mode + + /// Gets the mode(s) of a data set. + /// The generic type of the data. + /// The action to perform on every mode value found. + /// The first value of the data set. + /// The rest of the data set. + public static void Mode(Action step, T a, params T[] b) => + Mode(x => { x(a); b.ToStepper()(x); }, step); + + /// Gets the mode(s) of a data set. + /// The generic type of the data. + /// The action to perform on every mode value found. + /// The equality delegate. + /// The first value of the data set. + /// The rest of the data set. + public static void Mode(Action step, Func equate, T a, params T[] b) => + Mode(x => { x(a); b.ToStepper()(x); }, step, equate, null); + + /// Gets the mode(s) of a data set. + /// The generic type of the data. + /// The action to perform on every mode value found. + /// The hash code delegate + /// The first value of the data set. + /// The rest of the data set. + public static void Mode(Action step, Func hash, T a, params T[] b) => + Mode(x => { x(a); b.ToStepper()(x); }, step, null, hash); + + /// Gets the mode(s) of a data set. + /// The generic type of the data. + /// The action to perform on every mode value found. + /// The equality delegate. + /// The hash code delegate + /// The first value of the data set. + /// The rest of the data set. + public static void Mode(Action step, Func equate, Func hash, T a, params T[] b) => + Mode(x => { x(a); b.ToStepper()(x); }, step, equate, hash); + + /// Gets the mode(s) of a data set. + /// The generic type of the data. + /// The data set. + /// The action to perform on every mode value found. + /// The equality delegate. + /// The hash code delegate + /// The modes of the data set. + public static void Mode(Action> stepper, Action step, Func? equate = null, Func? hash = null) + { + int maxOccurences = -1; + IMap map = new MapHashLinked(equate, hash); + stepper(a => + { + if (map.Contains(a)) + { + int occurences = ++map[a]; + maxOccurences = Math.Max(occurences, maxOccurences); + } + else + { + map[a] = 1; + maxOccurences = Math.Max(1, maxOccurences); + } + }); + map.Stepper((value, key) => + { + if (value == maxOccurences) + { + step(key); + } + }); + } + + #endregion + + #region Mean + + /// Computes the mean of a set of numerical values. + /// The numeric type of the operation. + /// The first value of the set of data to compute the mean of. + /// The remaining values in the data set to compute the mean of. + /// The computed mean of the set of data. + public static T Mean(T a, params T[] b) => + Mean(step => { step(a); b.ToStepper()(step); }); + + /// Computes the mean of a set of numerical values. + /// The numeric type of the operation. + /// The set of data to compute the mean of. + /// The computed mean of the set of data. + public static T Mean(Action> stepper) + { + _ = stepper ?? throw new ArgumentNullException(nameof(stepper)); + T i = Constant.Zero; + T sum = Constant.Zero; + stepper(step => + { + i = Addition(i, Constant.One); + sum = Addition(sum, step); + }); + if (Equate(i, Constant.Zero)) + { + throw new ArgumentException("The argument is empty.", nameof(stepper)); + } + return Division(sum, i); + } + + #endregion + + #region Median + + /// Computes the median of a set of data. + /// The numeric type of the operation. + /// The comparison algorithm to sort the data by. + /// The set of data to compute the median of. + /// The computed median value of the set of data. + public static T Median(Func compare, params T[] values) + { + _ = compare ?? throw new ArgumentNullException(nameof(compare)); + _ = values ?? throw new ArgumentNullException(nameof(values)); + // standard algorithm (sort and grab middle value) + SortMerge(values, compare); + if (values.Length % 2 == 1) // odd... just grab middle value + { + return values[values.Length / 2]; + } + else // even... must perform a mean of the middle two values + { + T leftMiddle = values[(values.Length / 2) - 1]; + T rightMiddle = values[values.Length / 2]; + return Division(Addition(leftMiddle, rightMiddle), Constant.Two); + } + } + + /// Computes the median of a set of data. + /// The numeric type of the operation. + /// The comparison algorithm to sort the data by. + /// The set of data to compute the median of. + /// The computed median value of the set of data. + public static T Median(Func compare, Action> stepper) + { + _ = stepper ?? throw new ArgumentNullException(nameof(stepper)); + return Median(compare, stepper.ToArray()); + } + + /// Computes the median of a set of data. + /// The numeric type of the operation. + /// The set of data to compute the median of. + /// The computed median value of the set of data. + public static T Median(params T[] values) + { + return Median(Compare, values); + } + + /// Computes the median of a set of data. + /// The numeric type of the operation. + /// The set of data to compute the median of. + /// The computed median value of the set of data. + public static T Median(Action> stepper) + { + _ = stepper ?? throw new ArgumentNullException(nameof(stepper)); + return Median(Compare, stepper.ToArray()); + } + + #region Possible Optimization (Still in Development) + + //public static T Median(Func compare, Hash hash, Func equate, params T[] values) + //{ + // // this is an optimized median algorithm, but it only works on odd sets without duplicates + // if (hash is not null && equate is not null && values.Length % 2 == 1 && !values.ToStepper().ContainsDuplicates(equate, hash)) + // { + // int medianIndex = 0; + // OddNoDupesMedianImplementation(values, values.Length, ref medianIndex, compare); + // return values[medianIndex]; + // } + // else + // { + // return Median(compare, values); + // } + //} + + //public static T Median(Func compare, Hash hash, Func equate, Stepper stepper) + //{ + // return Median(compare, hash, equate, stepper.ToArray()); + //} + + ///// Fast algorithm for median computation, but only works on data with an odd number of values without duplicates. + //internal static void OddNoDupesMedianImplementation(T[] a, int n, ref int k, Func compare) + //{ + // int L = 0; + // int R = n - 1; + // k = n / 2; + // int i; int j; + // while (L < R) + // { + // T x = a[k]; + // i = L; j = R; + // OddNoDupesMedianImplementation_Split(a, n, x, ref i, ref j, compare); + // if (j <= k) L = i; + // if (i >= k) R = j; + // } + //} + + //internal static void OddNoDupesMedianImplementation_Split(T[] a, int n, T x, ref int i, ref int j, Func compare) + //{ + // do + // { + // while (compare(a[i], x) == Comparison.Less) i++; + // while (compare(a[j], x) == Comparison.Greater) j--; + // T t = a[i]; + // a[i] = a[j]; + // a[j] = t; + // } while (i < j); + //} + + #endregion + + #endregion + + #region GeometricMean + + /// Computes the geometric mean of a set of numbers. + /// The numeric type of the computation. + /// The set of numbres to compute the geometric mean of. + /// The computed geometric mean of the set of numbers. + public static T GeometricMean(Action> stepper) + { + T multiple = Constant.One; + T count = Constant.Zero; + stepper(i => + { + count = Addition(count, Constant.One); + multiple = Multiplication(multiple, i); + }); + return Root(multiple, count); + } + + #endregion + + #region Variance + + /// Computes the variance of a set of numbers. + /// The numeric type of the computation. + /// The set of numbers to compute the variance of. + /// The computed variance of the set of numbers. + public static T Variance(Action> stepper) + { + T mean = Mean(stepper); + T variance = Constant.Zero; + T count = Constant.Zero; + stepper(i => + { + T i_minus_mean = Subtraction(i, mean); + variance = Addition(variance, Multiplication(i_minus_mean, i_minus_mean)); + count = Addition(count, Constant.One); + }); + return Division(variance, count); + } + + #endregion + + #region StandardDeviation + + /// Computes the standard deviation of a set of numbers. + /// The numeric type of the computation. + /// The set of numbers to compute the standard deviation of. + /// The computed standard deviation of the set of numbers. + public static T StandardDeviation(Action> stepper) => + SquareRoot(Variance(stepper)); + + #endregion + + #region MeanDeviation + + /// The mean deviation of a set of numbers. + /// The numeric type of the computation. + /// The set of numbers to compute the mean deviation of. + /// The computed mean deviation of the set of numbers. + public static T MeanDeviation(Action> stepper) + { + T mean = Mean(stepper); + T temp = Constant.Zero; + T count = Constant.Zero; + stepper(i => + { + temp = Addition(temp, AbsoluteValue(Subtraction(i, mean))); + count = Addition(count, Constant.One); + }); + return Division(temp, count); + } + + #endregion + + #region Quantiles + + /// Computes the quantiles of a set of data. + /// The generic data type. + /// The number of quantiles to compute. + /// The data stepper. + /// The computed quantiles of the data set. + public static T[] Quantiles(int quantiles, Action> stepper) + { + if (quantiles < 1) + { + throw new ArgumentOutOfRangeException(nameof(quantiles), quantiles, "!(" + nameof(quantiles) + " >= 1)"); + } + int count = stepper.Count(); + T[] ordered = new T[count]; + int a = 0; + stepper(i => { ordered[a++] = i; }); + SortQuick(ordered, Compare); + T[] resultingQuantiles = new T[quantiles + 1]; + resultingQuantiles[0] = ordered[0]; + resultingQuantiles[^1] = ordered[^1]; + T QUANTILES_PLUS_1 = Convert(quantiles + 1); + T ORDERED_LENGTH = Convert(ordered.Length); + for (int i = 1; i < quantiles; i++) + { + T I = Convert(i); + T temp = Division(ORDERED_LENGTH, Multiplication(QUANTILES_PLUS_1, I)); + if (IsInteger(temp)) + { + resultingQuantiles[i] = ordered[Convert(temp)]; + } + else + { + resultingQuantiles[i] = Division(Addition(ordered[Convert(temp)], ordered[Convert(temp) + 1]), Constant.Two); + } + } + return resultingQuantiles; + } + + #endregion + + #region Correlation + + // /// Computes the median of a set of values. + // internal static Compute.Delegates.Correlation Correlation_internal = (Stepper a, Stepper b) => + // { + // throw new System.NotImplementedException("I introduced an error here when I removed the stepref off of structure. will fix soon"); + + // Compute.Correlation_internal = + // Meta.Compile( + // string.Concat( + // @"(Stepper<", Meta.ConvertTypeToCsharpSource(typeof(T)), "> _a, Stepper<", Meta.ConvertTypeToCsharpSource(typeof(T)), @"> _b) => + //{ + // ", Meta.ConvertTypeToCsharpSource(typeof(T)), " a_mean = Compute<", Meta.ConvertTypeToCsharpSource(typeof(T)), @">.Mean(_a); + // ", Meta.ConvertTypeToCsharpSource(typeof(T)), " b_mean = Compute<", Meta.ConvertTypeToCsharpSource(typeof(T)), @">.Mean(_b); + // List<", Meta.ConvertTypeToCsharpSource(typeof(T)), "> a_temp = new List_Linked<", Meta.ConvertTypeToCsharpSource(typeof(T)), @">(); + // _a((", Meta.ConvertTypeToCsharpSource(typeof(T)), @" i) => { a_temp.Add(i - b_mean); }); + // List<", Meta.ConvertTypeToCsharpSource(typeof(T)), "> b_temp = new List_Linked<", Meta.ConvertTypeToCsharpSource(typeof(T)), @">(); + // _b((", Meta.ConvertTypeToCsharpSource(typeof(T)), @" i) => { b_temp.Add(i - a_mean); }); + // ", Meta.ConvertTypeToCsharpSource(typeof(T)), "[] a_cross_b = new ", Meta.ConvertTypeToCsharpSource(typeof(T)), @"[a_temp.Count * b_temp.Count]; + // int count = 0; + // a_temp.Stepper((", Meta.ConvertTypeToCsharpSource(typeof(T)), @" i_a) => + // { + // b_temp.Stepper((", Meta.ConvertTypeToCsharpSource(typeof(T)), @" i_b) => + // { + // a_cross_b[count++] = i_a * i_b; + // }); + // }); + // a_temp.Stepper((ref ", Meta.ConvertTypeToCsharpSource(typeof(T)), @" i) => { i *= i; }); + // b_temp.Stepper((ref ", Meta.ConvertTypeToCsharpSource(typeof(T)), @" i) => { i *= i; }); + // ", Meta.ConvertTypeToCsharpSource(typeof(T)), @" sum_a_cross_b = 0; + // foreach (", Meta.ConvertTypeToCsharpSource(typeof(T)), @" i in a_cross_b) + // sum_a_cross_b += i; + // ", Meta.ConvertTypeToCsharpSource(typeof(T)), @" sum_a_temp = 0; + // a_temp.Stepper((", Meta.ConvertTypeToCsharpSource(typeof(T)), @" i) => { sum_a_temp += i; }); + // ", Meta.ConvertTypeToCsharpSource(typeof(T)), @" sum_b_temp = 0; + // b_temp.Stepper((", Meta.ConvertTypeToCsharpSource(typeof(T)), @" i) => { sum_b_temp += i; }); + // return sum_a_cross_b / Compute<", Meta.ConvertTypeToCsharpSource(typeof(T)), @">.sqrt(sum_a_temp * sum_b_temp); + //}")); + + // return Compute.Correlation_internal(a, b); + // }; + + // public static T Correlation(Stepper a, Stepper b) + // { + // return Correlation_internal(a, b); + // } + #endregion + + #region Occurences + + /// Counts the number of occurences of each item. + /// The generic type to count the occerences of. + /// The first value in the data. + /// The rest of the data. + /// The occurence map of the data. + public static IMap Occurences(T a, params T[] b) => + Occurences(step => { step(a); b.ToStepper()(step); }); + + /// Counts the number of occurences of each item. + /// The generic type to count the occerences of. + /// The equality delegate. + /// The first value in the data. + /// The rest of the data. + /// The occurence map of the data. + public static IMap Occurences(Func equate, T a, params T[] b) => + Occurences(step => { step(a); b.ToStepper()(step); }, equate, null); + + /// Counts the number of occurences of each item. + /// The generic type to count the occerences of. + /// The hash code delegate. + /// The first value in the data. + /// The rest of the data. + /// The occurence map of the data. + public static IMap Occurences(Func hash, T a, params T[] b) => + Occurences(step => { step(a); b.ToStepper()(step); }, null, hash); + + /// Counts the number of occurences of each item. + /// The generic type to count the occerences of. + /// The equality delegate. + /// The hash code delegate. + /// The first value in the data. + /// The rest of the data. + /// The occurence map of the data. + public static IMap Occurences(Func equate, Func hash, T a, params T[] b) => + Occurences(step => { step(a); b.ToStepper()(step); }, equate, hash); + + /// Counts the number of occurences of each item. + /// The generic type to count the occerences of. + /// The data to count the occurences of. + /// The equality delegate. + /// The hash code delegate. + /// The occurence map of the data. + public static IMap Occurences(Action> stepper, Func? equate = null, Func? hash = null) + { + IMap map = new MapHashLinked(equate, hash); + stepper(a => + { + if (map.Contains(a)) + { + map[a]++; + } + else + { + map[a] = 1; + } + }); + return map; + } + + #endregion + + #region Hamming Distance + + /// Computes the Hamming distance (using an iterative algorithm). + /// The element type of the sequences. + /// The get index function for the first sequence. + /// The get index function for the second sequence. + /// The equality check function. + /// The length of the sequences. + /// The get index function for the first sequence. + /// The get index function for the second sequence. + /// The equality check function. + /// The computed Hamming distance of the two sequences. + public static int HammingDistance( + int length, + GetA a = default, + GetB b = default, + Equals equals = default) + where GetA : struct, IFunc + where GetB : struct, IFunc + where Equals : struct, IFunc + { + if (length < 0) + { + throw new ArgumentOutOfRangeException(nameof(length), length, $@"{nameof(length)} < 0"); + } + int distance = 0; + for (int i = 0; i < length; i++) + { + if (!equals.Do(a.Do(i), b.Do(i))) + { + distance++; + } + } + return distance; + } + + /// Computes the Hamming distance (using an recursive algorithm). + /// The first sequence of the operation. + /// The second sequence of the operation. + /// The computed Hamming distance of the two sequences. + public static int HammingDistance(ReadOnlySpan a, ReadOnlySpan b) => + HammingDistance(a, b); + + /// Computes the Hamming distance (using an recursive algorithm). + /// The element type of the sequences. + /// The equality check function. + /// The first sequence. + /// The second sequence. + /// The equality check function. + /// The computed Hamming distance of the two sequences. + public static int HammingDistance( + ReadOnlySpan a, + ReadOnlySpan b, + Equals equals = default) + where Equals : struct, IFunc + { + if (a.Length != b.Length) + { + throw new ArgumentException($@"{nameof(a)}.{nameof(a.Length)} ({a.Length}) != {nameof(b)}.{nameof(b.Length)} ({b.Length})"); + } + int distance = 0; + for (int i = 0; i < a.Length; i++) + { + if (!equals.Do(a[i], b[i])) + { + distance++; + } + } + return distance; + } + + #endregion + + #region Levenshtein distance + + /// Computes the Levenshtein distance (using an recursive algorithm). + /// The element type of the sequences. + /// The get index function for the first sequence. + /// The get index function for the second sequence. + /// The equality check function. + /// The length of the first sequence. + /// The length of the second sequence. + /// The get index function for the first sequence. + /// The get index function for the second sequence. + /// The equality check function. + /// The computed Levenshtein distance of the two sequences. + public static int LevenshteinDistanceRecursive( + int a_length, + int b_length, + GetA a = default, + GetB b = default, + Equals equals = default) + where GetA : struct, IFunc + where GetB : struct, IFunc + where Equals : struct, IFunc + { + if (a_length < 0) + { + throw new ArgumentOutOfRangeException(nameof(a_length), a_length, $@"{nameof(a_length)} < 0"); + } + if (b_length < 0) + { + throw new ArgumentOutOfRangeException(nameof(b_length), b_length, $@"{nameof(b_length)} < 0"); + } + int LDR(int ai, int bi) + { + int _ai = ai + 1; + int _bi = bi + 1; + return + ai >= a_length ? + bi >= b_length ? 0 : + 1 + LDR(ai, _bi) : + bi >= b_length ? 1 + LDR(_ai, bi) : + equals.Do(a.Do(ai), b.Do(bi)) ? LDR(_ai, _bi) : + 1 + Minimum(LDR(ai, _bi), LDR(_ai, bi), LDR(_ai, _bi)); + } + return LDR(0, 0); + } + + /// Computes the Levenshtein distance (using an recursive algorithm). + /// The first sequence of the operation. + /// The second sequence of the operation. + /// The computed Levenshtein distance of the two sequences. + public static int LevenshteinDistanceRecursive(ReadOnlySpan a, ReadOnlySpan b) => + LevenshteinDistanceRecursive(a, b); + + /// Computes the Levenshtein distance (using an recursive algorithm). + /// The element type of the sequences. + /// The equality check function. + /// The first sequence. + /// The second sequence. + /// The equality check function. + /// The computed Levenshtein distance of the two sequences. + public static int LevenshteinDistanceRecursive( + ReadOnlySpan a, + ReadOnlySpan b, + Equals equals = default) + where Equals : struct, IFunc + { + int LDR( + ReadOnlySpan a, + ReadOnlySpan b, + int ai, int bi) + { + int _ai = ai + 1; + int _bi = bi + 1; + return + ai >= a.Length ? + bi >= b.Length ? 0 : + 1 + LDR(a, b, ai, _bi) : + bi >= b.Length ? 1 + LDR(a, b, _ai, bi) : + equals.Do(a[ai], b[bi]) ? LDR(a, b, _ai, _bi) : + 1 + Minimum(LDR(a, b, ai, _bi), LDR(a, b, _ai, bi), LDR(a, b, _ai, _bi)); + } + return LDR(a, b, 0, 0); + } + + /// Computes the Levenshtein distance (using an iterative algorithm). + /// The element type of the sequences. + /// The get index function for the first sequence. + /// The get index function for the second sequence. + /// The equality check function. + /// The length of the first sequence. + /// The length of the second sequence. + /// The get index function for the first sequence. + /// The get index function for the second sequence. + /// The equality check function. + /// The computed Levenshtein distance of the two sequences. + public static int LevenshteinDistanceIterative( + int a_length, + int b_length, + GetA a = default, + GetB b = default, + Equals equals = default) + where GetA : struct, IFunc + where GetB : struct, IFunc + where Equals : struct, IFunc + { + if (a_length < 0) + { + throw new ArgumentOutOfRangeException(nameof(a_length), a_length, $@"{nameof(a_length)} < 0"); + } + if (b_length < 0) + { + throw new ArgumentOutOfRangeException(nameof(b_length), b_length, $@"{nameof(b_length)} < 0"); + } + a_length++; + b_length++; + int[,] matrix = new int[a_length, b_length]; + for (int i = 1; i < a_length; i++) + { + matrix[i, 0] = i; + } + for (int i = 1; i < b_length; i++) + { + matrix[0, i] = i; + } + for (int bi = 1; bi < b_length; bi++) + { + for (int ai = 1; ai < a_length; ai++) + { + int _ai = ai - 1; + int _bi = bi - 1; + matrix[ai, bi] = Minimum( + matrix[_ai, bi] + 1, + matrix[ai, _bi] + 1, + !equals.Do(a.Do(_ai), b.Do(_bi)) ? matrix[_ai, _bi] + 1 : matrix[_ai, _bi]); + } + } + return matrix[a_length - 1, b_length - 1]; + } + + /// Computes the Levenshtein distance (using an iterative algorithm). + /// The first sequence of the operation. + /// The second sequence of the operation. + /// The computed Levenshtein distance of the two sequences. + public static int LevenshteinDistanceIterative(ReadOnlySpan a, ReadOnlySpan b) => + LevenshteinDistanceIterative(a, b); + + /// Computes the Levenshtein distance (using an iterative algorithm). + /// The element type of the sequences. + /// The equality check function. + /// The first sequence. + /// The second sequence. + /// The equality check function. + /// The computed Levenshtein distance of the two sequences. + public static int LevenshteinDistanceIterative( + ReadOnlySpan a, + ReadOnlySpan b, + Equals equals = default) + where Equals : struct, IFunc + { + int a_length = a.Length + 1; + int b_length = b.Length + 1; + int[,] matrix = new int[a_length, b_length]; + for (int i = 1; i < a_length; i++) + { + matrix[i, 0] = i; + } + for (int i = 1; i < b_length; i++) + { + matrix[0, i] = i; + } + for (int bi = 1; bi < b_length; bi++) + { + for (int ai = 1; ai < a_length; ai++) + { + int _ai = ai - 1; + int _bi = bi - 1; + matrix[ai, bi] = Minimum( + matrix[_ai, bi] + 1, + matrix[ai, _bi] + 1, + !equals.Do(a[_ai], b[_bi]) ? matrix[_ai, _bi] + 1 : matrix[_ai, _bi]); + } + } + return matrix[a_length - 1, b_length - 1]; + } + + #endregion + + #region FilterOrdered + + public static void FilterOrdered(int start, int end, Func get, Action step, Func? compare = null) => + FilterOrdered, ActionRuntime, FuncRuntime>(start, end, get, step, compare ?? Compare); + + public static void FilterOrdered(int start, int end, Get get = default, Step step = default, Compare compare = default) + where Get : struct, IFunc + where Step : struct, IAction + where Compare : struct, IFunc + { + if (start <= end) + { + step.Do(get.Do(start)); + } + for (int i = start; i <= end; i++) + { + if (compare.Do(get.Do(i - 1), get.Do(i)) is not Greater) + { + step.Do(get.Do(i)); + } + } + } + + public static void FilterOrdered(ReadOnlySpan span, Action step, Func? compare = null) => + FilterOrdered, FuncRuntime>(span, step, compare ?? Compare); + + public static void FilterOrdered(ReadOnlySpan span, Step step = default, Compare compare = default) + where Step : struct, IAction + where Compare : struct, IFunc + { + if (!span.IsEmpty) + { + step.Do(span[0]); + } + for (int i = 1; i < span.Length; i++) + { + if (compare.Do(span[i - 1], span[i]) is not Greater) + { + step.Do(span[i]); + } + } + } + + #endregion + + #region IsOrdered + +#pragma warning disable CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name +#pragma warning disable CS1572 // XML comment has a param tag, but there is no parameter by that name + /// The type of values to sort. + /// The compare function. + /// The get function. + /// The compare function. + /// The get function. + /// The starting index of the sort. + /// The ending index of the sort. + /// The span to be sorted. + [Obsolete(TowelConstants.NotIntended, true)] + internal static void IsOrdered_XML() => throw new DocumentationMethodException(); +#pragma warning restore CS1572 // XML comment has a param tag, but there is no parameter by that name +#pragma warning restore CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name + + /// + public static bool IsOrdered(int start, int end, Func get, Func? compare = null) => + IsOrdered, FuncRuntime>(start, end, compare ?? Compare, get); + + /// + public static bool IsOrdered(int start, int end, Compare compare = default, Get get = default) + where Compare : struct, IFunc + where Get : struct, IFunc + { + for (int i = start + 1; i <= end; i++) + { + if (compare.Do(get.Do(i - 1), get.Do(i)) is Greater) + { + return false; + } + } + return true; + } + + /// + public static bool IsOrdered(ReadOnlySpan span, Func? compare = null) => + IsOrdered>(span, compare ?? Compare); + + /// + public static bool IsOrdered(ReadOnlySpan span, Compare compare = default) + where Compare : struct, IFunc + { + for (int i = 1; i < span.Length; i++) + { + if (compare.Do(span[i - 1], span[i]) is Greater) + { + return false; + } + } + return true; + } + + /// + public static bool IsOrdered(this System.Collections.Generic.IEnumerable enumerable, Func? compare = null) => + IsOrdered>(enumerable, compare ?? Compare); + + /// + public static bool IsOrdered(this System.Collections.Generic.IEnumerable enumerable, Compare compare = default) + where Compare : struct, IFunc + { + System.Collections.Generic.IEnumerator enumerator = enumerable.GetEnumerator(); + T previous = enumerator.Current; + while (enumerator.MoveNext()) + { + if (compare.Do(previous, enumerator.Current) is Greater) + { + return false; + } + previous = enumerator.Current; + } + return true; + } + + #endregion + + #region IsPalindrome + + /// Determines if a sequence is a palindrome. + /// The element type of the sequence. + /// The inclusive starting index of the palindrome check. + /// The inclusive ending index of the palindrome check. + /// The element equate function. + /// The get index function of the sequence. + /// True if the sequence is a palindrome; False if not. + public static bool IsPalindrome(int start, int end, Func get, Func? equate = default) => + IsPalindrome, FuncRuntime>(start, end, get, equate ?? Equate); + + /// Determines if a sequence is a palindrome. + /// The element type of the sequence. + /// The get index function of the sequence. + /// The inclusive starting index of the palindrome check. + /// The inclusive ending index of the palindrome check. + /// The element equate function. + /// The get index function of the sequence. + /// True if the sequence is a palindrome; False if not. + public static bool IsPalindrome(int start, int end, Get get = default, Func? equate = default) + where Get : struct, IFunc => + IsPalindrome>(start, end, get, equate ?? Equate); + + /// Determines if a sequence is a palindrome. + /// The element type of the sequence. + /// The element equate function. + /// The get index function of the sequence. + /// The inclusive starting index of the palindrome check. + /// The inclusive ending index of the palindrome check. + /// The element equate function. + /// The get index function of the sequence. + /// True if the sequence is a palindrome; False if not. + public static bool IsPalindrome(int start, int end, Get get = default, Equate equate = default) + where Get : struct, IFunc + where Equate : struct, IFunc + { + int middle = (end - start) / 2 + start; + for (int i = start; i <= middle; i++) + { + if (!equate.Do(get.Do(i), get.Do(end - i + start))) + { + return false; + } + } + return true; + } + + /// Determines if a sequence is a palindrome. + /// The span to check. + /// True if the sequence is a palindrome; False if not. + public static bool IsPalindrome(ReadOnlySpan span) => + IsPalindrome(span); + + /// Determines if a sequence is a palindrome. + /// The element type of the sequence. + /// The span to check. + /// The element equate function. + /// True if the sequence is a palindrome; False if not. + public static bool IsPalindrome(ReadOnlySpan span, Func? equate = default) => + IsPalindrome>(span, equate ?? Equate); + + /// Determines if a sequence is a palindrome. + /// The element type of the sequence. + /// The element equate function. + /// The span to check. + /// The element equate function. + /// True if the sequence is a palindrome; False if not. + public static bool IsPalindrome(ReadOnlySpan span, Equate equate = default) + where Equate : struct, IFunc + { + int middle = span.Length / 2; + for (int i = 0; i < middle; i++) + { + if (!equate.Do(span[i], span[^(i + 1)])) + { + return false; + } + } + return true; + } + + #endregion + + #region IsInterleaved + + #region XML + +#pragma warning disable CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name +#pragma warning disable CS1572 // XML comment has a param tag, but there is no parameter by that name +#pragma warning disable CS1734 // XML comment has a paramref tag, but there is no parameter by that name +#pragma warning disable CS1735 // XML comment has a typeparamref tag, but there is no type parameter by that name + + /// The element type of the sequences. + /// The first sequence to determine if is interleaved of. + /// The second sequence to determine if is interleaved of. + /// The sequence to determine if it is interleaved from and . + /// The function for equating values. + /// True if is interleaved of and or False if not. + /// + /// + /// IsInterleaved("abc", "xyz", "axbycz") // True + /// IsInterleaved("abc", "xyz", "cbazyx") // False (order not preserved) + /// IsInterleaved("abc", "xyz", "012345") // False + /// + /// + internal static void IsInterleaved_XML() => throw new DocumentationMethodException(); + + /// + /// + /// Determines if is interleved of and , + /// meaning that it contains all elements of and + /// while retaining the order of the respective elements. Uses a recursive algorithm. + /// + /// Runtime: O(2^(Min(.Length + .Length, .Length))), Ω(1) + /// Memory: O(1) + /// + /// + internal static void IsInterleavedRecursive_XML() => throw new DocumentationMethodException(); + + /// + /// Determines if is interleved of and , + /// meaning that it contains all elements of and + /// while retaining the order of the respective elements. Uses a interative algorithm. + /// Runtime: O(Min(.Length * .Length))), Ω(1) + /// Memory: O(.Length * .Length) + /// + /// + internal static void IsInterleavedIterative_XML() => throw new DocumentationMethodException(); + +#pragma warning restore CS1735 // XML comment has a typeparamref tag, but there is no type parameter by that name +#pragma warning restore CS1734 // XML comment has a paramref tag, but there is no parameter by that name +#pragma warning restore CS1572 // XML comment has a param tag, but there is no parameter by that name +#pragma warning restore CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name + + #endregion + + /// + public static bool IsInterleavedRecursive(ReadOnlySpan a, ReadOnlySpan b, ReadOnlySpan c, Func? equate = default) => + IsInterleavedRecursive>(a, b, c, equate ?? Equate); + + /// + public static bool IsInterleavedRecursive(ReadOnlySpan a, ReadOnlySpan b, ReadOnlySpan c) => + IsInterleavedRecursive(a, b, c); + + /// + public static bool IsInterleavedRecursive(ReadOnlySpan a, ReadOnlySpan b, ReadOnlySpan c, Equate equate = default) + where Equate : struct, IFunc + { + if (a.Length + b.Length != c.Length) + { + return false; + } + + bool Implementation(ReadOnlySpan a, ReadOnlySpan b, ReadOnlySpan c) => + a.IsEmpty && b.IsEmpty && c.IsEmpty || + ( + !c.IsEmpty && + ( + (!a.IsEmpty && equate.Do(a[0], c[0]) && Implementation(a[1..], b, c[1..])) || + (!b.IsEmpty && equate.Do(b[0], c[0]) && Implementation(a, b[1..], c[1..])) + ) + ); + + return Implementation(a, b, c); + } + + /// + public static bool IsInterleavedIterative(ReadOnlySpan a, ReadOnlySpan b, ReadOnlySpan c, Func? equate = default) => + IsInterleavedIterative>(a, b, c, equate ?? Equate); + + /// + public static bool IsInterleavedIterative(ReadOnlySpan a, ReadOnlySpan b, ReadOnlySpan c) => + IsInterleavedIterative(a, b, c); + + /// + public static bool IsInterleavedIterative(ReadOnlySpan a, ReadOnlySpan b, ReadOnlySpan c, Equate equate = default) + where Equate : struct, IFunc + { + if (a.Length + b.Length != c.Length) + { + return false; + } + bool[,] d = new bool[a.Length + 1, b.Length + 1]; + for (int i = 0; i <= a.Length; ++i) + { + for (int j = 0; j <= b.Length; ++j) + { + d[i, j] = + (i == 0 && j == 0) || + ( + i == 0 ? (equate.Do(b[j - 1], c[j - 1]) && d[i, j - 1]) : + j == 0 ? (equate.Do(a[i - 1], c[i - 1]) && d[i - 1, j]) : + equate.Do(a[i - 1], c[i + j - 1]) && !equate.Do(b[j - 1], c[i + j - 1]) ? d[i - 1, j] : + !equate.Do(a[i - 1], c[i + j - 1]) && equate.Do(b[j - 1], c[i + j - 1]) ? d[i, j - 1] : + equate.Do(a[i - 1], c[i + j - 1]) && equate.Do(b[j - 1], c[i + j - 1]) && (d[i - 1, j] || d[i, j - 1]) + ); + + #region expanded version + + //if (i == 0 && j == 0) + //{ + // d[i, j] = true; + //} + //else if (i == 0) + //{ + // if (equate.Do(b[j - 1], c[j - 1])) + // { + // d[i, j] = d[i, j - 1]; + // } + //} + //else if (j == 0) + //{ + // if (equate.Do(a[i - 1], c[i - 1])) + // { + // d[i, j] = d[i - 1, j]; + // } + //} + //else if (equate.Do(a[i - 1], c[i + j - 1]) && !equate.Do(b[j - 1], c[i + j - 1])) + //{ + // d[i, j] = d[i - 1, j]; + //} + //else if (!equate.Do(a[i - 1], c[i + j - 1]) && equate.Do(b[j - 1], c[i + j - 1])) + //{ + // d[i, j] = d[i, j - 1]; + //} + //else if (equate.Do(a[i - 1], c[i + j - 1]) && equate.Do(b[j - 1], c[i + j - 1])) + //{ + // d[i, j] = d[i - 1, j] || d[i, j - 1]; + //} + + #endregion + } + } + return d[a.Length, b.Length]; + } + + #endregion + } +} diff --git a/Sources/Towel/Statics-SortingAlgorithms.cs b/Sources/Towel/Statics-SortingAlgorithms.cs new file mode 100644 index 00000000..8e1ce1a1 --- /dev/null +++ b/Sources/Towel/Statics-SortingAlgorithms.cs @@ -0,0 +1,1331 @@ +using System; + +namespace Towel +{ + /// Root type of the static functional methods in Towel. + public static partial class Statics + { + #region Shuffle + +#pragma warning disable CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name +#pragma warning disable CS1572 // XML comment has a param tag, but there is no parameter by that name + /// + /// Sorts values into a randomized order. + /// Runtime: O(n) + /// Memory: O(1) + /// + /// The type of values to sort. + /// The get function. + /// The set function. + /// The starting index of the shuffle. + /// The ending index of the shuffle. + /// The get function. + /// The set function. + /// The random to shuffle with. + /// The array to shuffle. + [Obsolete(TowelConstants.NotIntended, true)] + internal static void Shuffle_XML() => throw new DocumentationMethodException(); +#pragma warning restore CS1572 // XML comment has a param tag, but there is no parameter by that name +#pragma warning restore CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name + + /// + public static void Shuffle(int start, int end, Func get, Action set, Random? random = null) => + Shuffle, ActionRuntime>(start, end, get, set, random); + + /// + public static void Shuffle(int start, int end, Get get = default, Set set = default, Random? random = null) + where Get : struct, IFunc + where Set : struct, IAction => + Shuffle(start, end, get, set, random ?? new Random()); + + /// + public static void Shuffle(int start, int end, Get get = default, Set set = default, Random random = default) + where Get : struct, IFunc + where Set : struct, IAction + where Random : struct, IFunc + { + for (int i = start; i <= end; i++) + { + int randomIndex = random.Do(start, end); + // Swap + T temp = get.Do(i); + set.Do(i, get.Do(randomIndex)); + set.Do(randomIndex, temp); + } + } + + /// + public static void Shuffle(Span span, Random? random = null) => + Shuffle(span, random ?? new Random()); + + /// + public static void Shuffle(Span span, Random random = default) + where Random : struct, IFunc + { + for (int i = 0; i < span.Length; i++) + { + int index = random.Do(0, span.Length); + Swap(ref span[i], ref span[index]); + } + } + + #endregion + + #region Sort_XML +#pragma warning disable CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name +#pragma warning disable CS1572 // XML comment has a param tag, but there is no parameter by that name + /// The type of values to sort. + /// The compare function. + /// The get function. + /// The set function. + /// The compare function. + /// The get function. + /// The set function. + /// The starting index of the sort. + /// The ending index of the sort. + /// The array to be sorted. + /// The span to be sorted. + [Obsolete(TowelConstants.NotIntended, true)] + internal static void Sort_XML() => throw new DocumentationMethodException(); +#pragma warning restore CS1572 // XML comment has a param tag, but there is no parameter by that name +#pragma warning restore CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name + #endregion + + #region SortBubble + + /// + /// Sorts values using the bubble sort algorithm. + /// Runtime: Ω(n), ε(n^2), O(n^2) + /// Memory: O(1) + /// Stable: True + /// + /// + [Obsolete(TowelConstants.NotIntended, true)] + internal static void SortBubble_XML() => throw new DocumentationMethodException(); + + /// + public static void SortBubble(int start, int end, Func get, Action set, Func? compare = null) => + SortBubble, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); + + /// + public static void SortBubble(int start, int end, Compare compare = default, Get get = default, Set set = default) + where Compare : struct, IFunc + where Get : struct, IFunc + where Set : struct, IAction + { + for (int i = start; i <= end; i++) + { + for (int j = start; j <= end - 1; j++) + { + if (compare.Do(get.Do(j), get.Do(j + 1)) is Greater) + { + // Swap + T temp = get.Do(j + 1); + set.Do(j + 1, get.Do(j)); + set.Do(j, temp); + } + } + } + } + + /// + public static void SortBubble(Span span, Func? compare = null) => + SortBubble>(span, compare ?? Compare); + + /// + public static void SortBubble(Span span, Compare compare = default) + where Compare : struct, IFunc + { + for (int i = 0; i <= span.Length - 1; i++) + { + for (int j = 0; j <= span.Length - 2; j++) + { + if (compare.Do(span[j], span[j + 1]) is Greater) + { + Swap(ref span[j], ref span[j + 1]); + } + } + } + } + + #endregion + + #region SortSelection + + /// + /// Sorts values using the selection sort algoritm. + /// Runtime: Ω(n^2), ε(n^2), O(n^2) + /// Memory: O(1) + /// Stable: False + /// + /// + [Obsolete(TowelConstants.NotIntended, true)] + internal static void SortSelection_XML() => throw new DocumentationMethodException(); + + /// + public static void SortSelection(int start, int end, Func get, Action set, Func? compare = null) => + SortSelection, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); + + /// + public static void SortSelection(int start, int end, Compare compare = default, Get get = default, Set set = default) + where Compare : struct, IFunc + where Get : struct, IFunc + where Set : struct, IAction + { + for (int i = start; i <= end; i++) + { + int min = i; + for (int j = i + 1; j <= end; j++) + { + if (compare.Do(get.Do(j), get.Do(min)) is Less) + { + min = j; + } + } + // Swap + T temp = get.Do(min); + set.Do(min, get.Do(i)); + set.Do(i, temp); + } + } + + /// + public static void SortSelection(Span span, Func? compare = null) => + SortSelection>(span, compare ?? Compare); + + /// + public static void SortSelection(Span span, Compare compare = default) + where Compare : struct, IFunc + { + for (int i = 0; i < span.Length; i++) + { + int min = i; + for (int j = i + 1; j < span.Length; j++) + { + if (compare.Do(span[j], span[min]) is Less) + { + min = j; + } + } + Swap(ref span[min], ref span[i]); + } + } + + #endregion + + #region SortInsertion + + /// + /// Sorts values using the insertion sort algorithm. + /// Runtime: Ω(n), ε(n^2), O(n^2) + /// Memory: O(1) + /// Stable: True + /// + /// + [Obsolete(TowelConstants.NotIntended, true)] + internal static void SortInsertion_XML() => throw new DocumentationMethodException(); + + /// + public static void SortInsertion(int start, int end, Func get, Action set, Func? compare = null) => + SortInsertion, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); + + /// + public static void SortInsertion(int start, int end, Compare compare = default, Get get = default, Set set = default) + where Compare : struct, IFunc + where Get : struct, IFunc + where Set : struct, IAction + { + for (int i = start + 1; i <= end; i++) + { + T temp = get.Do(i); + int j = i; + for (; j > start && compare.Do(get.Do(j - 1), temp) is Greater; j--) + { + set.Do(j, get.Do(j - 1)); + } + set.Do(j, temp); + } + } + + /// + public static void SortInsertion(Span span, Func? compare = null) => + SortInsertion>(span, compare ?? Compare); + + /// + public static void SortInsertion(Span span, Compare compare = default) + where Compare : struct, IFunc + { + for (int i = 1; i <= span.Length - 1; i++) + { + T temp = span[i]; + int j; + for (j = i; j > 0 && compare.Do(span[j - 1], temp) is Greater; j--) + { + span[j] = span[j - 1]; + } + span[j] = temp; + } + } + + #endregion + + #region SortQuick + + /// + /// Sorts values using the quick sort algorithm. + /// Runtime: Ω(n*ln(n)), ε(n*ln(n)), O(n^2) + /// Memory: ln(n) + /// Stable: False + /// + /// + [Obsolete(TowelConstants.NotIntended, true)] + internal static void SortQuick_XML() => throw new DocumentationMethodException(); + + /// + public static void SortQuick(int start, int end, Func get, Action set, Func? compare = null) => + SortQuick, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); + + /// + public static void SortQuick(int start, int end, Compare compare = default, Get get = default, Set set = default) + where Compare : struct, IFunc + where Get : struct, IFunc + where Set : struct, IAction + { + SortQuick_Recursive(start, end - start + 1); + + void SortQuick_Recursive(int start, int length) + { + if (length > 1) + { + T pivot = get.Do(start); + int i = start; + int j = start + length - 1; + int k = j; + while (i <= j) + { + if (compare.Do(get.Do(j), pivot) is Less) + { + Swap(i++, j); + } + else if (compare.Do(get.Do(j), pivot) is Equal) + { + j--; + } + else + { + Swap(k--, j--); + } + } + SortQuick_Recursive(start, i - start); + SortQuick_Recursive(k + 1, start + length - (k + 1)); + } + } + void Swap(int a, int b) + { + T temp = get.Do(a); + set.Do(a, get.Do(b)); + set.Do(b, temp); + } + } + + /// + public static void SortQuick(Span span, Func? compare = null) => + SortQuick>(span, compare ?? Compare); + + /// + public static void SortQuick(Span span, Compare compare = default) + where Compare : struct, IFunc + { + SortQuick_Recursive(span, 0, span.Length); + + void SortQuick_Recursive(Span span, int startIndex, int len) + { + if (len > 1) + { + T pivot = span[startIndex]; + int i = startIndex; + int j = startIndex + len - 1; + int k = j; + while (i <= j) + { + if (compare.Do(span[j], pivot) is Less) + { + Swap(ref span[i++], ref span[j]); + } + else if (compare.Do(span[j], pivot) is Equal) + { + j--; + } + else + { + Swap(ref span[k--], ref span[j--]); + } + } + SortQuick_Recursive(span, startIndex, i - startIndex); + SortQuick_Recursive(span, k + 1, startIndex + len - (k + 1)); + } + } + } + + #endregion + + #region SortMerge + + /// + /// Sorts values using the merge sort algorithm. + /// Runtime: Ω(n*ln(n)), ε(n*ln(n)), O(n*ln(n)) + /// Memory: Θ(n) + /// Stable: True + /// + /// + [Obsolete(TowelConstants.NotIntended, true)] + internal static void SortMerge_XML() => throw new DocumentationMethodException(); + + /// + public static void SortMerge(int start, int end, Func get, Action set, Func? compare = null) => + SortMerge, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); + + /// + public static void SortMerge(int start, int end, Compare compare = default, Get get = default, Set set = default) + where Compare : struct, IFunc + where Get : struct, IFunc + where Set : struct, IAction + { + SortMerge_Recursive(start, end - start + 1); + + void SortMerge_Recursive(int start, int length) + { + if (length > 1) + { + int half = length / 2; + SortMerge_Recursive(start, half); + SortMerge_Recursive(start + half, length - half); + T[] sorted = new T[length]; + int i = start; + int j = start + half; + int k = 0; + while (i < start + half && j < start + length) + { + if (compare.Do(get.Do(i), get.Do(j)) is Greater) + { + sorted[k++] = get.Do(j++); + } + else + { + sorted[k++] = get.Do(i++); + } + } + for (int h = 0; h < start + half - i; h++) + { + sorted[k + h] = get.Do(i + h); + } + for (int h = 0; h < start + length - j; h++) + { + sorted[k + h] = get.Do(j + h); + } + for (int h = 0; h < length; h++) + { + set.Do(start + h, sorted[0 + h]); + } + } + } + } + + /// + public static void SortMerge(Span span, Func? compare = null) => + SortMerge>(span, compare ?? Compare); + + /// + public static void SortMerge(Span span, Compare compare = default) + where Compare : struct, IFunc + { + SortMerge_Recursive(span); + + void SortMerge_Recursive(Span span) + { + if (span.Length > 1) + { + int half = span.Length / 2; + SortMerge_Recursive(span[..half]); + SortMerge_Recursive(span[half..]); + T[] sorted = new T[span.Length]; + int i = 0; + int j = half; + int k = 0; + while (i < half && j < span.Length) + { + if (compare.Do(span[i], span[j]) is Greater) + { + sorted[k++] = span[j++]; + } + else + { + sorted[k++] = span[i++]; + } + } + for (int h = 0; h < half - i; h++) + { + sorted[k + h] = span[i + h]; + } + for (int h = 0; h < span.Length - j; h++) + { + sorted[k + h] = span[j + h]; + } + for (int h = 0; h < span.Length; h++) + { + span[h] = sorted[0 + h]; + } + } + } + } + + #endregion + + #region SortHeap + + /// + /// Sorts values using the heap sort algorithm. + /// Runtime: Ω(n*ln(n)), ε(n*ln(n)), O(n^2) + /// Memory: O(1) + /// Stable: False + /// + /// + [Obsolete(TowelConstants.NotIntended, true)] + internal static void SortHeap_XML() => throw new DocumentationMethodException(); + + /// + public static void SortHeap(int start, int end, Func get, Action set, Func? compare = null) => + SortHeap, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); + + /// + public static void SortHeap(int start, int end, Compare compare = default, Get get = default, Set set = default) + where Compare : struct, IFunc + where Get : struct, IFunc + where Set : struct, IAction + { + int heapSize = end - start + 1; + for (int i = heapSize / 2; i >= 0; i--) + { + MaxSortHeapify(heapSize + start, i, start); + } + for (int i = end; i >= start; i--) + { + Swap(start, i); + heapSize--; + MaxSortHeapify(heapSize + start, 0, start); + } + void MaxSortHeapify(int heapSize, int index, int offset) + { + int left = ((index + 1) * 2 - 1) + offset; + int right = ((index + 1) * 2) + offset; + index += offset; + int largest = index; + if (left < heapSize && compare.Do(get.Do(left), get.Do(largest)) is Greater) + { + largest = left; + } + if (right < heapSize && compare.Do(get.Do(right), get.Do(largest)) is Greater) + { + largest = right; + } + if (largest != index) + { + Swap(index, largest); + MaxSortHeapify(heapSize, largest - offset, offset); + } + } + void Swap(int a, int b) + { + T temp = get.Do(a); + set.Do(a, get.Do(b)); + set.Do(b, temp); + } + } + + /// + public static void SortHeap(Span span, Func? compare = null) => + SortHeap>(span, compare ?? Compare); + + /// + public static void SortHeap(Span span, Compare compare = default) + where Compare : struct, IFunc + { + int start = 0; + int end = span.Length - 1; + int heapSize = end - start + 1; + for (int i = heapSize / 2; i >= 0; i--) + { + MaxSortHeapify(span, heapSize + start, i, start); + } + for (int i = end; i >= start; i--) + { + Swap(ref span[start], ref span[i]); + heapSize--; + MaxSortHeapify(span, heapSize + start, 0, start); + } + void MaxSortHeapify(Span span, int heapSize, int index, int offset) + { + int left = ((index + 1) * 2 - 1) + offset; + int right = ((index + 1) * 2) + offset; + index += offset; + int largest = index; + if (left < heapSize && compare.Do(span[left], span[largest]) is Greater) + { + largest = left; + } + if (right < heapSize && compare.Do(span[right], span[largest]) is Greater) + { + largest = right; + } + if (largest != index) + { + Swap(ref span[index], ref span[largest]); + MaxSortHeapify(span, heapSize, largest - offset, offset); + } + } + } + + #endregion + + #region SortOddEven + + /// + /// Sorts values using the odd even sort algorithm. + /// Runtime: Ω(n), ε(n^2), O(n^2) + /// Memory: O(1) + /// Stable: True + /// + /// + [Obsolete(TowelConstants.NotIntended, true)] + internal static void SortOddEven_XML() => throw new DocumentationMethodException(); + + /// + public static void SortOddEven(int start, int end, Func get, Action set, Func? compare = null) => + SortOddEven, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); + + /// + public static void SortOddEven(int start, int end, Compare compare = default, Get get = default, Set set = default) + where Compare : struct, IFunc + where Get : struct, IFunc + where Set : struct, IAction + { + bool sorted = false; + while (!sorted) + { + sorted = true; + for (int i = start; i < end; i += 2) + { + if (compare.Do(get.Do(i), get.Do(i + 1)) is Greater) + { + Swap(i, i + 1); + sorted = false; + } + } + for (int i = start + 1; i < end; i += 2) + { + if (compare.Do(get.Do(i), get.Do(i + 1)) is Greater) + { + Swap(i, i + 1); + sorted = false; + } + } + void Swap(int a, int b) + { + T temp = get.Do(a); + set.Do(a, get.Do(b)); + set.Do(b, temp); + } + } + } + + /// + public static void SortOddEven(Span span, Func? compare = null) => + SortOddEven>(span, compare ?? Compare); + + /// + public static void SortOddEven(Span span, Compare compare = default) + where Compare : struct, IFunc + { + bool sorted = false; + while (!sorted) + { + sorted = true; + for (int i = 0; i < span.Length - 1; i += 2) + { + if (compare.Do(span[i], span[i + 1]) is Greater) + { + Swap(ref span[i], ref span[i + 1]); + sorted = false; + } + } + for (int i = 1; i < span.Length - 1; i += 2) + { + if (compare.Do(span[i], span[i + 1]) is Greater) + { + Swap(ref span[i], ref span[i + 1]); + sorted = false; + } + } + } + } + + #endregion + + #region SortCounting + +#if false + + ///// Method specifically for computing object keys in the SortCounting Sort algorithm. + ///// The type of instances in the array to be sorted. + ///// The instance to compute a counting key for. + ///// The counting key computed from the provided instance. + //public delegate int ComputeSortCountingKey(T instance); + + ///// + ///// Sorts an entire array in non-decreasing order using the heap sort algorithm. + ///// Runtime: Θ(Max(key)) + ///// Memory: Max(Key) + ///// Stable: True + ///// + ///// The type of objects stored within the array. + ///// Method specifically for computing object keys in the SortCounting Sort algorithm. + ///// The array to be sorted + //public static void SortCounting(ComputeSortCountingKey computeSortCountingKey, T[] array) + //{ + // throw new System.NotImplementedException(); + + // // This code needs revision and conversion + // int[] count = new int[array.Length]; + // int maxKey = 0; + // for (int i = 0; i < array.Length; i++) + // { + // int key = computeSortCountingKey(array[i]) / array.Length; + // count[key] += 1; + // if (key > maxKey) + // maxKey = key; + // } + + // int total = 0; + // for (int i = 0; i < maxKey; i++) + // { + // int oldCount = count[i]; + // count[i] = total; + // total += oldCount; + // } + + // T[] output = new T[maxKey]; + // for (int i = 0; i < array.Length; i++) + // { + // int key = computeSortCountingKey(array[i]); + // output[count[key]] = array[i]; + // count[computeSortCountingKey(array[i])] += 1; + // } + //} + + //public static void SortCounting(ComputeSortCountingKey computeSortCountingKey, T[] array, int start, int end) + //{ + // throw new System.NotImplementedException(); + //} + + //public static void SortCounting(ComputeSortCountingKey computeSortCountingKey, Get get, Assign set, int start, int end) + //{ + // throw new System.NotImplementedException(); + //} + +#endif + + #endregion + + #region SortBogo + + /// + /// Sorts values using the bogo sort algorithm. + /// Runtime: Ω(n), ε(n*n!), O(∞) + /// Memory: O(1) + /// Stable: False + /// + /// + [Obsolete(TowelConstants.NotIntended, true)] + internal static void SortBogo_XML() => throw new DocumentationMethodException(); + + /// + public static void SortBogo(int start, int end, Func get, Action set, Func? compare = null, Random? random = null) => + SortBogo, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set, random); + + /// + public static void SortBogo(int start, int end, Compare compare = default, Get get = default, Set set = default, Random? random = null) + where Compare : struct, IFunc + where Get : struct, IFunc + where Set : struct, IAction => + SortBogo(start, end, compare, get, set, random ?? new Random()); + + /// + public static void SortBogo(int start, int end, Compare compare = default, Get get = default, Set set = default, Random random = default) + where Compare : struct, IFunc + where Get : struct, IFunc + where Set : struct, IAction + where Random : struct, IFunc + { + while (!IsOrdered(start, end, compare, get)) + { + Shuffle(start, end, get, set, random); + } + } + + /// + public static void SortBogo(Span span, Func? compare = null, Random? random = null) => + SortBogo>(span, compare ?? Compare, random ?? new Random()); + + /// + public static void SortBogo(Span span, Compare compare = default, Random? random = null) + where Compare : struct, IFunc => + SortBogo(span, compare, random ?? new Random()); + + /// + public static void SortBogo(Span span, Compare compare = default, Random random = default) + where Compare : struct, IFunc + where Random : struct, IFunc + { + while (!IsOrdered(span, compare)) + { + Shuffle(span, random); + } + } + + #endregion + + #region SortSlow + + /// Sorts values using the slow sort algorithm. + /// + [Obsolete(TowelConstants.NotIntended, true)] + internal static void SortSlow_XML() => throw new DocumentationMethodException(); + + /// + public static void SortSlow(int start, int end, Func get, Action set, Func? compare = null) => + SortSlow, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); + + /// + public static void SortSlow(int start, int end, Compare compare = default, Get get = default, Set set = default) + where Compare : struct, IFunc + where Get : struct, IFunc + where Set : struct, IAction + { + SortSlowRecursive(start, end); + void SortSlowRecursive(int i, int j) + { + if (i >= j) + { + return; + } + int mid = (i + j) / 2; + SortSlowRecursive(i, mid); + SortSlowRecursive(mid + 1, j); + if (compare.Do(get.Do(j), get.Do(mid)) is Less) + { + // Swap + T temp = get.Do(j); + set.Do(j, get.Do(mid)); + set.Do(mid, temp); + } + SortSlowRecursive(i, j - 1); + } + } + + /// + public static void SortSlow(Span span, Func? compare = null) => + SortSlow>(span, compare ?? Compare); + + /// + public static void SortSlow(Span span, Compare compare = default) + where Compare : struct, IFunc + { + SortSlowRecursive(span, 0, span.Length - 1); + void SortSlowRecursive(Span span, int i, int j) + { + if (i >= j) + { + return; + } + int mid = (i + j) / 2; + SortSlowRecursive(span, i, mid); + SortSlowRecursive(span, mid + 1, j); + if (compare.Do(span[j], span[mid]) is Less) + { + Swap(ref span[j], ref span[mid]); + } + SortSlowRecursive(span, i, j - 1); + } + } + + #endregion + + #region SortGnome + + /// Sorts values using the gnome sort algorithm. + /// + [Obsolete(TowelConstants.NotIntended, true)] + internal static void SortGnome_XML() => throw new DocumentationMethodException(); + + /// + public static void SortGnome(int start, int end, Func get, Action set, Func? compare = null) => + SortGnome, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); + + /// + public static void SortGnome(int start, int end, Compare compare = default, Get get = default, Set set = default) + where Compare : struct, IFunc + where Get : struct, IFunc + where Set : struct, IAction + { + int i = start; + while (i <= end) + { + if (i == start || compare.Do(get.Do(i), get.Do(i - 1)) != Less) + { + i++; + } + else + { + // Swap + T temp = get.Do(i); + set.Do(i, get.Do(i - 1)); + set.Do(i - 1, temp); + i--; + } + } + } + + /// + public static void SortGnome(Span span, Func? compare = null) => + SortGnome>(span, compare ?? Compare); + + /// + public static void SortGnome(Span span, Compare compare = default) + where Compare : struct, IFunc + { + int i = 0; + while (i < span.Length) + { + if (i == 0 || compare.Do(span[i], span[i - 1]) != Less) + { + i++; + } + else + { + Swap(ref span[i], ref span[i - 1]); + i--; + } + } + } + + #endregion + + #region SortComb + + /// Sorts values using the comb sort algorithm. + /// + [Obsolete(TowelConstants.NotIntended, true)] + internal static void SortComb_XML() => throw new DocumentationMethodException(); + + /// + public static void SortComb(int start, int end, Func get, Action set, Func? compare = null) => + SortComb, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); + + /// + public static void SortComb(int start, int end, Compare compare = default, Get get = default, Set set = default) + where Compare : struct, IFunc + where Get : struct, IFunc + where Set : struct, IAction + { + const double shrink = 1.3; + int gap = end - start + 1; + bool sorted = false; + while (!sorted) + { + gap = (int)(gap / shrink); + if (gap <= 1) + { + gap = 1; + sorted = true; + } + for (int i = start; i + gap <= end; i++) + { + if (compare.Do(get.Do(i), get.Do(i + gap)) is Greater) + { + T temp = get.Do(i); + set.Do(i, get.Do(i + gap)); + set.Do(i + gap, temp); + sorted = false; + } + } + } + } + + /// + public static void SortComb(Span span, Func? compare = null) => + SortComb>(span, compare ?? Compare); + + /// + public static void SortComb(Span span, Compare compare = default) + where Compare : struct, IFunc + { + const double shrink = 1.3; + int gap = span.Length; + bool sorted = false; + while (!sorted) + { + gap = (int)(gap / shrink); + if (gap <= 1) + { + gap = 1; + sorted = true; + } + for (int i = 0; i + gap < span.Length; i++) + { + if (compare.Do(span[i], span[i + gap]) is Greater) + { + Swap(ref span[i], ref span[i + gap]); + sorted = false; + } + } + } + } + + #endregion + + #region SortShell + + /// Sorts values using the shell sort algorithm. + /// + [Obsolete(TowelConstants.NotIntended, true)] + internal static void SortShell_XML() => throw new DocumentationMethodException(); + + /// + public static void SortShell(int start, int end, Func get, Action set, Func? compare = null) => + SortShell, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); + + /// + public static void SortShell(int start, int end, Compare compare = default, Get get = default, Set set = default) + where Compare : struct, IFunc + where Get : struct, IFunc + where Set : struct, IAction + { + int[] gaps = { 701, 301, 132, 57, 23, 10, 4, 1 }; + foreach (int gap in gaps) + { + for (int i = gap + start; i <= end; i++) + { + T temp = get.Do(i); + int j = i; + for (; j >= gap && compare.Do(get.Do(j - gap), temp) is Greater; j -= gap) + { + set.Do(j, get.Do(j - gap)); + } + set.Do(j, temp); + } + } + } + + /// + public static void SortShell(Span span, Func? compare = null) => + SortShell>(span, compare ?? Compare); + + /// + public static void SortShell(Span span, Compare compare = default) + where Compare : struct, IFunc + { + int[] gaps = { 701, 301, 132, 57, 23, 10, 4, 1 }; + foreach (int gap in gaps) + { + for (int i = gap; i < span.Length; i++) + { + T temp = span[i]; + int j = i; + for (; j >= gap && compare.Do(span[j - gap], temp) is Greater; j -= gap) + { + span[j] = span[j - gap]; + } + span[j] = temp; + } + } + } + + #endregion + + #region SortCocktail + + /// Sorts values using the cocktail sort algorithm. + /// + [Obsolete(TowelConstants.NotIntended, true)] + internal static void SortCocktail_XML() => throw new DocumentationMethodException(); + + /// + public static void SortCocktail(int start, int end, Func get, Action set, Func? compare = null) => + SortCocktail, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); + + /// + public static void SortCocktail(int start, int end, Compare compare = default, Get get = default, Set set = default) + where Compare : struct, IFunc + where Get : struct, IFunc + where Set : struct, IAction + { + while (true) + { + bool swapped = false; + for (int i = start; i <= end - 1; i++) + { + if (compare.Do(get.Do(i), get.Do(i + 1)) is Greater) + { + T temp = get.Do(i); + set.Do(i, get.Do(i + 1)); + set.Do(i + 1, temp); + swapped = true; + } + } + if (!swapped) + { + break; + } + swapped = false; + for (int i = end - 1; i >= start; i--) + { + if (compare.Do(get.Do(i), get.Do(i + 1)) is Greater) + { + T temp = get.Do(i); + set.Do(i, get.Do(i + 1)); + set.Do(i + 1, temp); + swapped = true; + } + } + if (!swapped) + { + break; + } + } + } + + /// + public static void SortCocktail(Span span, Func? compare = null) => + SortCocktail>(span, compare ?? Compare); + + /// + public static void SortCocktail(Span span, Compare compare = default) + where Compare : struct, IFunc + { + while (true) + { + bool swapped = false; + for (int i = 0; i < span.Length - 1; i++) + { + if (compare.Do(span[i], span[i + 1]) is Greater) + { + Swap(ref span[i], ref span[i + 1]); + swapped = true; + } + } + if (!swapped) + { + break; + } + swapped = false; + for (int i = span.Length - 2; i >= 0; i--) + { + if (compare.Do(span[i], span[i + 1]) is Greater) + { + Swap(ref span[i], ref span[i + 1]); + swapped = true; + } + } + if (!swapped) + { + break; + } + } + } + + #endregion + + #region SortCycle + + /// Sorts values using the shell cycle algorithm. + /// + [Obsolete(TowelConstants.NotIntended, true)] + internal static void SortCycle_XML() => throw new DocumentationMethodException(); + + /// + public static void SortCycle(int start, int end, Func get, Action set, Func? compare = null) => + SortCycle, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); + + /// + public static void SortCycle(int start, int end, Compare compare = default, Get get = default, Set set = default) + where Compare : struct, IFunc + where Get : struct, IFunc + where Set : struct, IAction + { + for (int i = start; i < end; i++) + { + T pivot = get.Do(i); + int index = i; + for (int j = i + 1; j <= end; j++) + { + if (compare.Do(get.Do(j), pivot) is Less) + { + index++; + } + } + if (index == i) + { + continue; + } + while (compare.Do(pivot, get.Do(index)) is Equal) + { + index++; + } + if (index != i) + { + T temp = pivot; + pivot = get.Do(index); + set.Do(index, temp); + } + while (index != i) + { + index = i; + for (int j = i + 1; j <= end; j++) + { + if (compare.Do(get.Do(j), pivot) is Less) + { + index++; + } + } + while (compare.Do(pivot, get.Do(index)) is Equal) + { + index += 1; + } + if (compare.Do(pivot, get.Do(index)) is not Equal) + { + T temp = pivot; + pivot = get.Do(index); + set.Do(index, temp); + } + } + } + } + + /// + public static void SortCycle(Span span, Func? compare = null) => + SortCycle>(span, compare ?? Compare); + + /// + public static void SortCycle(Span span, Compare compare = default) + where Compare : struct, IFunc + { + for (int i = 0; i < span.Length - 1; i++) + { + T pivot = span[i]; + int index = i; + for (int j = i + 1; j < span.Length; j++) + { + if (compare.Do(span[j], pivot) is Less) + { + index++; + } + } + if (index == i) + { + continue; + } + while (compare.Do(pivot, span[index]) is Equal) + { + index++; + } + if (index != i) + { + Swap(ref span[index], ref pivot); + } + while (index != i) + { + index = i; + for (int j = i + 1; j < span.Length; j++) + { + if (compare.Do(span[j], pivot) is Less) + { + index++; + } + } + while (compare.Do(pivot, span[index]) is Equal) + { + index += 1; + } + if (compare.Do(pivot, span[index]) is not Equal) + { + Swap(ref span[index], ref pivot); + } + } + } + } + + #endregion + + #region SortPancake + + /// Sorts values using the shell pancake algorithm. + /// + [Obsolete(TowelConstants.NotIntended, true)] + internal static void SortPancake_XML() => throw new DocumentationMethodException(); + + /// + public static void SortPancake(Span span, Func? compare = null) => + SortPancake>(span, compare ?? Compare); + + /// + public static void SortPancake(Span span, Compare compare = default) + where Compare : struct, IFunc + { + for (int i = span.Length; i > 1; i--) + { + var (index, _) = Maximum(span[0..i], compare); + if (index != i - 1) + { + span[0..(index + 1)].Reverse(); + span[0..i].Reverse(); + } + } + } + + #endregion + + #region SortStooge + + /// Sorts values using the shell stooge algorithm. + /// + [Obsolete(TowelConstants.NotIntended, true)] + internal static void SortStooge_XML() => throw new DocumentationMethodException(); + + /// + public static void SortStooge(Span span, Func? compare = null) => + SortStooge>(span, compare ?? Compare); + + /// + public static void SortStooge(Span span, Compare compare = default) + where Compare : struct, IFunc + { + if (span.Length < 2) + { + return; + } + if (compare.Do(span[0], span[^1]) is Greater) + { + Swap(ref span[0], ref span[^1]); + } + if (span.Length > 2) + { + int third = span.Length / 3; + SortStooge(span[third..], compare); + SortStooge(span[..^third], compare); + SortStooge(span[third..], compare); + } + } + + #endregion + } +} diff --git a/Sources/Towel/Statics-Structs.cs b/Sources/Towel/Statics-Structs.cs new file mode 100644 index 00000000..1f3986b2 --- /dev/null +++ b/Sources/Towel/Statics-Structs.cs @@ -0,0 +1,68 @@ +using System; + +namespace Towel +{ + /// Root type of the static functional methods in Towel. + public static partial class Statics + { + /// Default int compare. + public struct IntCompare : IFunc + { + /// Default int compare. + /// The left hand side of the compare. + /// The right ahnd side of the compare. + /// The result of the comparison. + public CompareResult Do(int a, int b) => ToCompareResult(a.CompareTo(b)); + } + + /// Compares two char values for equality. + public struct CharEquate : IFunc + { + /// Compares two char values for equality. + /// The first operand of the equality check. + /// The second operand of the equality check. + /// True if equal; False if not. + public bool Do(char a, char b) => a == b; + } + + /// Built in Compare struct for runtime computations. + /// The generic type of the values to compare. + /// The compare function. + public struct SiftFromCompareAndValue : IFunc + where Compare : struct, IFunc + { + internal Compare CompareFunction; + internal T Value; + + /// The invocation of the compile time delegate. + public CompareResult Do(T a) => CompareFunction.Do(a, Value); + + /// Creates a compile-time-resolved sifting function to be passed into another type. + /// The value for future values to be compared against. + /// The compare function. + public SiftFromCompareAndValue(T value, Compare compare = default) + { + Value = value; + CompareFunction = compare; + } + } + + /// Compile time resulution to the value. + public struct StepStatusContinue : IFunc + { + /// Returns . + /// + public StepStatus Do() => Continue; + } + + /// Struct wrapper for the method as an . + public struct RandomNextIntMinValueIntMaxValue : IFunc + { + internal Random _random; + /// + public int Do(int minValue, int maxValue) => _random.Next(minValue, maxValue); + /// Casts a to a struct wrapper. + public static implicit operator RandomNextIntMinValueIntMaxValue(Random random) => new RandomNextIntMinValueIntMaxValue() { _random = random, }; + } + } +} diff --git a/Sources/Towel/Statics-SyntaxHacks.cs b/Sources/Towel/Statics-SyntaxHacks.cs new file mode 100644 index 00000000..afc960db --- /dev/null +++ b/Sources/Towel/Statics-SyntaxHacks.cs @@ -0,0 +1,536 @@ +using System; +using System.Linq; +using Towel.DataStructures; + +namespace Towel +{ + /// Root type of the static functional methods in Towel. + public static partial class Statics + { + #region Keywords + + /// Stepper was not broken. + public const StepStatus Continue = StepStatus.Continue; + /// Stepper was broken. + public const StepStatus Break = StepStatus.Break; + /// The Goal was found. + public const GraphSearchStatus Goal = GraphSearchStatus.Goal; + /// The left operand is less than the right operand. + public const CompareResult Less = CompareResult.Less; + /// The left operand is equal to the right operand. + public const CompareResult Equal = CompareResult.Equal; + /// The left operand is greater than the right operand. + public const CompareResult Greater = CompareResult.Greater; + /// There is no bound. + public const Omnitree.Keyword None = Omnitree.Keyword.None; + /// The default case in a Switch statement (true). + public const SwitchSyntax.Keyword Default = SwitchSyntax.Keyword.Default; + + #endregion + + #region Switch + + /// Syntax sugar Switch statements. + /// The possible actions of the Switch statement. + public static void Switch(params (SwitchSyntax.Condition, Action)[] possibleActions) => + SwitchSyntax.Do(possibleActions); + + /// Syntax sugar Switch statements. + /// The generic type parameter to the Switch statement. + /// The value argument of the Switch statement. + /// The delegate for the Switch statement. + public static SwitchSyntax.ParamsAction, Action> Switch(T value) => + SwitchSyntax.Do(value); + + /// Definitions for Switch syntax. + public static class SwitchSyntax + { + /// Delegate with params intended to be used with the Switch syntax. + public delegate void ParamsAction(params (A, B)[] values); + + internal static ParamsAction, Action> Do(T value) => + possibleActions => + { + foreach (var possibleAction in possibleActions) + { + if (possibleAction.Item1.Resolve(value)) + { + possibleAction.Item2(); + return; + } + } + }; + + internal static void Do(params (Condition Condition, Action Action)[] possibleActions) + { + foreach (var possibleAction in possibleActions) + { + if (possibleAction.Condition) + { + possibleAction.Action(); + return; + } + } + } + + /// Intended to be used with Switch syntax. + public enum Keyword + { + /// The default keyword for the the Switch syntax. + Default, + } + + /// Represents the result of a conditional expression inside Switch syntax. + /// The generic type of the Switch condition for equality checks. + public abstract class Condition + { + /// Resolves the condition to a bool. + public abstract bool Resolve(T b); + /// Casts a to a bool using an equality check. + public static implicit operator Condition(T value) => new Value(a: value); + /// Uses the bool as the condition result. + public static implicit operator Condition(bool result) => new Bool { Result = result, }; + /// Converts a keyword to a condition result (for "Default" case). +#pragma warning disable IDE0079 // Remove unnecessary suppression +#pragma warning disable IDE0060 // Remove unused parameter + public static implicit operator Condition(Keyword keyword) => new Default(); +#pragma warning restore IDE0060 // Remove unused parameter +#pragma warning restore IDE0079 // Remove unnecessary suppression + } + + internal class Value : Condition + { + /// The value of this condition for an equality check. + internal T A; + public override bool Resolve(T b) => Equate(A, b); + public Value(T a) + { + A = a; + } + } + + internal class Bool : Condition + { + internal bool Result; + public override bool Resolve(T b) => Result; + } + + internal class Default : Condition + { + public override bool Resolve(T b) => true; + } + + /// Represents the result of a conditional expression inside Switch syntax. + public abstract class Condition + { + /// Resolves the condition to a bool. + public abstract bool Resolve(); + /// Uses the bool as the condition result. + public static implicit operator Condition(bool result) => new Bool { Result = result, }; +#pragma warning disable IDE0079 // Remove unnecessary suppression +#pragma warning disable IDE0060 // Remove unused parameter + /// Converts a keyword to a condition result (for "Default" case). + public static implicit operator Condition(Keyword keyword) => new Default(); +#pragma warning restore IDE0060 // Remove unused parameter +#pragma warning restore IDE0079 // Remove unnecessary suppression + /// Converts a condition to a bool using the Resolve method. + public static implicit operator bool(Condition condition) => condition.Resolve(); + } + + internal class Bool : Condition + { + internal bool Result; + public override bool Resolve() => Result; + } + + internal class Default : Condition + { + public override bool Resolve() => true; + } + } + + #endregion + + #region Chance + +#pragma warning disable CA2211 // Non-constant fields should not be visible +#pragma warning disable IDE0079 // Remove unnecessary suppression +#pragma warning disable IDE0075 // Simplify conditional expression +#pragma warning disable IDE0060 // Remove unused parameter + + /// Allows chance syntax with "using static Towel.Syntax;". + /// 25% Chance + public static ChanceSyntax Chance => default; + + /// Struct that allows percentage syntax that will be evaluated at runtime. + public struct ChanceSyntax + { + /// The random algorithm currently being used by chance syntax. + public static Random Algorithm = new Random(); + + /// Creates a chance from a percentage that will be evaluated at runtime. + /// The value of the percentage. + /// The chance syntax struct object. + /// True if the the chance hits. False if not. + public static bool operator %(double percentage, ChanceSyntax chance) => + percentage < 0d ? throw new ArgumentOutOfRangeException(nameof(chance)) : + percentage > 100d ? throw new ArgumentOutOfRangeException(nameof(chance)) : + percentage is 100d ? true : + percentage is 0d ? false : + Algorithm.NextDouble() < percentage / 100d; + } + +#pragma warning restore IDE0060 // Remove unused parameter +#pragma warning restore IDE0075 // Simplify conditional expression +#pragma warning restore IDE0079 // Remove unnecessary suppression +#pragma warning restore CA2211 // Non-constant fields should not be visible + + #endregion + + #region Inequality + + /// Used for inequality syntax. + /// The generic type of elements the inequality is being used on. + public struct Inequality + { + internal bool Cast; + internal T A; + + /// Contructs a new . + /// The initial value of the running inequality. + public static implicit operator Inequality(T a) => + new Inequality() + { + Cast = true, + A = a, + }; + /// Adds a greater than operation to a running inequality. + /// The current running inequality and left hand operand. + /// The value of the right hand operand of the greater than operation. + /// A running inequality with the additonal greater than operation. + public static OperatorValidated.Inequality operator >(Inequality a, T b) => + !a.Cast ? throw new InequalitySyntaxException() : + new OperatorValidated.Inequality(Compare(a.A, b) == Greater, b); + /// Adds a less than operation to a running inequality. + /// The current running inequality and left hand operand. + /// The value of the right hand operand of the less than operation. + /// A running inequality with the additonal less than operation. + public static OperatorValidated.Inequality operator <(Inequality a, T b) => + !a.Cast ? throw new InequalitySyntaxException() : + new OperatorValidated.Inequality(Compare(a.A, b) == Less, b); + /// Adds a greater than or equal operation to a running inequality. + /// The current running inequality and left hand operand. + /// The value of the right hand operand of the greater than or equal operation. + /// A running inequality with the additonal greater than or equal operation. + public static OperatorValidated.Inequality operator >=(Inequality a, T b) => + !a.Cast ? throw new InequalitySyntaxException() : + new OperatorValidated.Inequality(Compare(a.A, b) != Less, b); + /// Adds a less than or equal operation to a running inequality. + /// The current running inequality and left hand operand. + /// The value of the right hand operand of the less than or equal operation. + /// A running inequality with the additonal less than or equal operation. + public static OperatorValidated.Inequality operator <=(Inequality a, T b) => + !a.Cast ? throw new InequalitySyntaxException() : + new OperatorValidated.Inequality(Compare(a.A, b) != Greater, b); + /// Adds an equal operation to a running inequality. + /// The current running inequality and left hand operand. + /// The value of the right hand operand of the equal operation. + /// A running inequality with the additonal equal operation. + public static OperatorValidated.Inequality operator ==(Inequality a, T b) => + !a.Cast ? throw new InequalitySyntaxException() : + new OperatorValidated.Inequality(Equate(a.A, b), b); + /// Adds an inequal operation to a running inequality. + /// The current running inequality and left hand operand. + /// The value of the right hand operand of the inequal operation. + /// A running inequality with the additonal inequal operation. + public static OperatorValidated.Inequality operator !=(Inequality a, T b) => + !a.Cast ? throw new InequalitySyntaxException() : + new OperatorValidated.Inequality(Inequate(a.A, b), b); + +#pragma warning disable CS0809 // Obsolete member overrides non-obsolete member + /// This member is not intended to be invoked. + /// This member is not intended to be invoked. + [Obsolete(TowelConstants.NotIntended, true)] + public override string ToString() => throw new InequalitySyntaxException(); + /// This member is not intended to be invoked. + /// This member is not intended to be invoked. + /// This member is not intended to be invoked. + [Obsolete(TowelConstants.NotIntended, true)] + public override bool Equals(object? obj) => throw new InequalitySyntaxException(); + /// This member is not intended to be invoked. + /// This member is not intended to be invoked. + [Obsolete(TowelConstants.NotIntended, true)] + public override int GetHashCode() => throw new InequalitySyntaxException(); +#pragma warning restore CS0809 // Obsolete member overrides non-obsolete member + } + + /// Helper type for inequality syntax. Contains an Inequality type that has been operator validated. + public static partial class OperatorValidated + { + /// Used for inequality syntax. + /// The generic type of elements the inequality is being used on. + public struct Inequality + { + internal readonly bool Result; + internal readonly T A; + + internal Inequality(bool result, T a) + { + Result = result; + A = a; + } + /// Converts this running inequality into the result of the expression. + /// The inequality to convert into the result of the expression. + public static implicit operator bool(Inequality inequality) => + inequality.Result; + /// Adds a greater than operation to a running inequality. + /// The current running inequality and left hand operand. + /// The value of the right hand operand of the greater than operation. + /// A running inequality with the additonal greater than operation. + public static Inequality operator >(Inequality a, T b) => + new Inequality(a.Result && Compare(a.A, b) == Greater, b); + /// Adds a less than operation to a running inequality. + /// The current running inequality and left hand operand. + /// The value of the right hand operand of the less than operation. + /// A running inequality with the additonal less than operation. + public static Inequality operator <(Inequality a, T b) => + new Inequality(a.Result && Compare(a.A, b) == Less, b); + /// Adds a greater than or equal operation to a running inequality. + /// The current running inequality and left hand operand. + /// The value of the right hand operand of the greater than or equal operation. + /// A running inequality with the additonal greater than or equal operation. + public static Inequality operator >=(Inequality a, T b) => + new Inequality(a.Result && Compare(a.A, b) != Less, b); + /// Adds a less than or equal operation to a running inequality. + /// The current running inequality and left hand operand. + /// The value of the right hand operand of the less than or equal operation. + /// A running inequality with the additonal less than or equal operation. + public static Inequality operator <=(Inequality a, T b) => + new Inequality(a.Result && Compare(a.A, b) != Greater, b); + /// Adds an equal operation to a running inequality. + /// The current running inequality and left hand operand. + /// The value of the right hand operand of the equal operation. + /// A running inequality with the additonal equal operation. + public static Inequality operator ==(Inequality a, T b) => + new Inequality(a.Result && Equate(a.A, b), b); + /// Adds an inequal operation to a running inequality. + /// The current running inequality and left hand operand. + /// The value of the right hand operand of the inequal operation. + /// A running inequality with the additonal inequal operation. + public static Inequality operator !=(Inequality a, T b) => + new Inequality(a.Result && Inequate(a.A, b), b); + /// Converts the result of this inequality to a . + /// The result of this inequality converted to a . + public override string ToString() => Result.ToString(); +#pragma warning disable CS0809 // Obsolete member overrides non-obsolete member + /// This member is not intended to be invoked. + /// This member is not intended to be invoked. + /// This member is not intended to be invoked. + [Obsolete(TowelConstants.NotIntended, true)] + public override bool Equals(object? obj) => throw new InequalitySyntaxException(); + /// This member is not intended to be invoked. + /// This member is not intended to be invoked. + [Obsolete(TowelConstants.NotIntended, true)] + public override int GetHashCode() => throw new InequalitySyntaxException(); +#pragma warning restore CS0809 // Obsolete member overrides non-obsolete member + } + } + + #endregion + + #region UniversalQuantification + + /// Universal Quantification Operator. + /// The element type of the universal quantification to declare. + /// The values of the universal quantification. + /// The declared universal quantification. + public static UniversalQuantification(params T[] values) => new UniversalQuantification(values); + + /// Universal Quantification. + /// The element type of the universal quantification. + public struct UniversalQuantification : + System.Collections.Generic.IEnumerable, + System.Collections.Generic.IList, + Towel.DataStructures.IArray + { + internal T[] Value; + + /// Constructs a new universal quantification from an array. + /// The array value of the universal quantification. + internal UniversalQuantification(T[] array) => Value = array; + + #region Towel.Datastructures.IArray + /// The number of values in this universal quantification. + [Obsolete(TowelConstants.NotIntended, true)] + public int Length => Value.Length; + /// Iterates each value in this universal quantification and performs an action for each element. + /// The action to perform on every step of the iteration. + [Obsolete(TowelConstants.NotIntended, true)] + public void Stepper(Action step) => Value.Stepper(step); + /// Iterates each value in this universal quantification and performs an action for each element. + [Obsolete(TowelConstants.NotIntended, true)] + public StepStatus Stepper(Func step) => Value.Stepper(step); + #endregion + + #region System.Collections.Generic.IList + /// Index property for get/set operations. + /// The index to get/set. + /// The value at the provided index. + [Obsolete(TowelConstants.NotIntended, true)] + public T this[int index] + { + get => Value[index]; + set => Value[index] = value; + } + /// Gets the number of elements in this universal quantification. + public int Count => Value.Length; + /// Gets a value indicating whether the is read-only. + public bool IsReadOnly => false; + /// Adds an item to this universal quantifier. + /// The item to add to this universal quantifier. + [Obsolete(TowelConstants.NotIntended, true)] + public void Add(T item) + { + T[] newValue = new T[Value.Length + 1]; + Array.Copy(Value, newValue, Value.Length); + newValue[Value.Length] = item; + Value = newValue; + } + /// Not intended to be invoked directly. + [Obsolete(TowelConstants.NotIntended, true)] + public void Clear() => Value = Array.Empty(); + /// Not intended to be invoked directly. + [Obsolete(TowelConstants.NotIntended, true)] + public bool Contains(T item) => Value.Contains(item); + /// Not intended to be invoked directly. + [Obsolete(TowelConstants.NotIntended, true)] + public void CopyTo(T[] array, int arrayIndex) => + Array.Copy(Value, 0, array, arrayIndex, Value.Length); + /// Not intended to be invoked directly. + [Obsolete(TowelConstants.NotIntended, true)] + public int IndexOf(T item) => Array.IndexOf(Value, item); + /// Not intended to be invoked directly. + [Obsolete(TowelConstants.NotIntended, true)] + public void Insert(int index, T item) + { + T[] newValue = new T[Value.Length + 1]; + for (int i = 0; i < newValue.Length; i++) + { + newValue[i] = i == index + ? item + : i < index + ? Value[i] + : Value[i - 1]; + } + Value = newValue; + } + /// Not intended to be invoked directly. + [Obsolete(TowelConstants.NotIntended, true)] + public bool Remove(T item) + { + T[] newValue = new T[Value.Length - 1]; + bool found = false; + for (int i = 0; i < Value.Length; i++) + { + if (Equate(Value[i], item)) + { + found = true; + } + else if (found) + { + newValue[i] = Value[i - 1]; + } + else + { + newValue[i] = Value[i]; + } + } + if (!found) + { + return false; + } + Value = newValue; + return true; + } + /// Not intended to be invoked directly. + [Obsolete(TowelConstants.NotIntended, true)] + public void RemoveAt(int index) + { + T[] newValue = new T[Value.Length - 1]; + for (int i = 0; i < Value.Length; i++) + { + if (i != index) + { + if (i < index) + { + newValue[i] = Value[i]; + } + else + { + newValue[i] = Value[i - 1]; + } + } + } + Value = newValue; + } + #endregion + + #region System.Collections.Generic.IEnumerable + /// Gets the for this universal quantification. + /// The for this universal quantification. + [Obsolete(TowelConstants.NotIntended, true)] + public System.Collections.Generic.IEnumerator GetEnumerator() => ((System.Collections.Generic.IEnumerable)Value).GetEnumerator(); + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => Value.GetEnumerator(); + #endregion + + #region Implicit Casting Operators + + /// Converts a universal quantification to an array. + /// The universal quantification to be converted. + public static implicit operator T[](UniversalQuantification universalQuantification) => universalQuantification.Value; + /// Converts a universal quantification to a . + /// The universal quantification to be converted. + public static implicit operator System.Collections.Generic.List(UniversalQuantification universalQuantification) => new System.Collections.Generic.List(universalQuantification.Value); + /// Converts a universal quantification to an . + /// The universal quantification to be converted. + public static implicit operator System.Collections.Generic.HashSet(UniversalQuantification universalQuantification) => new System.Collections.Generic.HashSet(universalQuantification.Value); + /// Converts a universal quantification to a . + /// The universal quantification to be converted. + public static implicit operator System.Collections.Generic.LinkedList(UniversalQuantification universalQuantification) => new System.Collections.Generic.LinkedList(universalQuantification.Value); + /// Converts a universal quantification to an . + /// The universal quantification to be converted. + public static implicit operator System.Collections.Generic.Stack(UniversalQuantification universalQuantification) => new System.Collections.Generic.Stack(universalQuantification.Value); + /// Converts a universal quantification to an . + /// The universal quantification to be converted. + public static implicit operator System.Collections.Generic.Queue(UniversalQuantification universalQuantification) => new System.Collections.Generic.Queue(universalQuantification.Value); + /// Converts a universal quantification to a sorted . + /// The universal quantification to be converted. + public static implicit operator System.Collections.Generic.SortedSet(UniversalQuantification universalQuantification) => new System.Collections.Generic.SortedSet(universalQuantification.Value); + /// Converts a universal quantification to an Action<Action<T>>. + /// The universal quantification to be converted. + public static implicit operator Action>(UniversalQuantification universalQuantification) => universalQuantification.Value.ToStepper(); + /// Converts a universal quantification to an . + /// The universal quantification to be converted. + public static implicit operator StepperRef(UniversalQuantification universalQuantification) => universalQuantification.Value.ToStepperRef(); + /// Converts a universal quantification to an Func<Func<T, StepStatus>, StepStatus>. + /// The universal quantification to be converted. + public static implicit operator Func, StepStatus>(UniversalQuantification universalQuantification) => universalQuantification.Value.ToStepperBreak(); + /// Converts a universal quantification to an . + /// The universal quantification to be converted. + public static implicit operator StepperRefBreak(UniversalQuantification universalQuantification) => universalQuantification.Value.ToStepperRefBreak(); + /// Converts a universal quantification to an . + /// The universal quantification to be converted. + public static implicit operator Towel.DataStructures.Array(UniversalQuantification universalQuantification) => universalQuantification.Value; + /// Converts a universal quantification to an . + /// The universal quantification to be converted. + public static implicit operator Towel.DataStructures.ListArray(UniversalQuantification universalQuantification) => new ListArray(universalQuantification.Value, universalQuantification.Value.Length); + /// Converts a universal quantification to an . + /// The universal quantification to be converted. + public static implicit operator Towel.DataStructures.StackArray(UniversalQuantification universalQuantification) => new StackArray(universalQuantification.Value, universalQuantification.Value.Length); + + #endregion + } + + #endregion + } +} diff --git a/Sources/Towel/Statics-Trigonometry.cs b/Sources/Towel/Statics-Trigonometry.cs new file mode 100644 index 00000000..6f72a324 --- /dev/null +++ b/Sources/Towel/Statics-Trigonometry.cs @@ -0,0 +1,525 @@ +using System; +using Towel.Measurements; + +namespace Towel +{ + /// Root type of the static functional methods in Towel. + public static partial class Statics + { + #region Sine + + /// Computes the sine ratio of an angle using the relative talor series. Accurate but slow. + /// The numeric type of the operation. + /// The angle to compute the sine ratio of. + /// Determines if coputation should continue or is accurate enough. + /// The taylor series computed sine ratio of the provided angle. + public static T SineTaylorSeries(Angle a, Predicate? predicate = null) + { + // Series: sine(x) = x - (x^3 / 3!) + (x^5 / 5!) - (x^7 / 7!) + (x^9 / 9!) + ... + // more terms in computation inproves accuracy + + // Note: there is room for optimization (custom runtime compilation) + + T x = a[Angle.Units.Radians]; + T sine = x; + T previous; + bool isAddTerm = false; + T i = Constant.Three; + T xSquared = Multiplication(x, x); + T xRunningPower = x; + T xRunningFactorial = Constant.One; + do + { + xRunningPower = Multiplication(xRunningPower, xSquared); + xRunningFactorial = Multiplication(xRunningFactorial, Multiplication(i, Subtraction(i, Constant.One))); + previous = sine; + if (isAddTerm) + { + sine = Addition(sine, Division(xRunningPower, xRunningFactorial)); + } + else + { + sine = Subtraction(sine, Division(xRunningPower, xRunningFactorial)); + } + isAddTerm = !isAddTerm; + i = Addition(i, Constant.Two); + } while (Inequate(sine, previous) && (predicate is null || !predicate(sine))); + return sine; + } + + /// Computes the sine ratio of an angle using the system's sine function. WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). + /// The numeric type of the operation. + /// The angle to compute the sine ratio of. + /// The sine ratio of the provided angle. + /// WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). + public static T SineSystem(Angle a) + { + T b = a[Angle.Units.Radians]; + double c = Convert(b); + double d = Math.Sin(c); + T e = Convert(d); + return e; + } + + /// Estimates the sine ratio using piecewise quadratic equations. Fast but NOT very accurate. + /// The numeric type of the operation. + /// The angle to compute the quadratic estimated sine ratio of. + /// The quadratic estimation of the sine ratio of the provided angle. + public static T SineQuadratic(Angle a) + { + // Piecewise Functions: + // y = (-4/π^2)(x - (π/2))^2 + 1 + // y = (4/π^2)(x - (3π/2))^2 - 1 + + T adjusted = Remainder(a[Angle.Units.Radians], Constant.Pi2); + if (IsNegative(adjusted)) + { + adjusted = Addition(adjusted, Constant.Pi2); + } + if (LessThan(adjusted, Constant.Pi)) + { + T xMinusPiOver2 = Subtraction(adjusted, Constant.PiOver2); + T xMinusPiOver2Squared = Multiplication(xMinusPiOver2, xMinusPiOver2); + return Addition(Multiplication(Constant.Negative4OverPiSquared, xMinusPiOver2Squared), Constant.One); + } + else + { + T xMinus3PiOver2 = Subtraction(adjusted, Constant.Pi3Over2); + T xMinus3PiOver2Squared = Multiplication(xMinus3PiOver2, xMinus3PiOver2); + return Subtraction(Multiplication(Constant.FourOverPiSquared, xMinus3PiOver2Squared), Constant.One); + } + } + + #endregion + + #region Cosine + + /// Computes the cosine ratio of an angle using the relative talor series. Accurate but slow. + /// The numeric type of the operation. + /// The angle to compute the cosine ratio of. + /// Determines if coputation should continue or is accurate enough. + /// The taylor series computed cosine ratio of the provided angle. + public static T CosineTaylorSeries(Angle a, Predicate? predicate = null) + { + // Series: cosine(x) = 1 - (x^2 / 2!) + (x^4 / 4!) - (x^6 / 6!) + (x^8 / 8!) - ... + // more terms in computation inproves accuracy + + // Note: there is room for optimization (custom runtime compilation) + + T x = a[Angle.Units.Radians]; + T cosine = Constant.One; + T previous; + T xSquared = Multiplication(x, x); + T xRunningPower = Constant.One; + T xRunningFactorial = Constant.One; + bool isAddTerm = false; + T i = Constant.Two; + do + { + xRunningPower = Multiplication(xRunningPower, xSquared); + xRunningFactorial = Multiplication(xRunningFactorial, Multiplication(i, Subtraction(i, Constant.One))); + previous = cosine; + if (isAddTerm) + { + cosine = Addition(cosine, Division(xRunningPower, xRunningFactorial)); + } + else + { + cosine = Subtraction(cosine, Division(xRunningPower, xRunningFactorial)); + } + isAddTerm = !isAddTerm; + i = Addition(i, Constant.Two); + } while (Inequate(cosine, previous) && (predicate is null || !predicate(cosine))); + return cosine; + } + + /// Computes the cosine ratio of an angle using the system's cosine function. WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). + /// The numeric type of the operation. + /// The angle to compute the cosine ratio of. + /// The cosine ratio of the provided angle. + /// WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). + public static T CosineSystem(Angle a) + { + T b = a[Angle.Units.Radians]; + double c = Convert(b); + double d = Math.Cos(c); + T e = Convert(d); + return e; + } + + /// Estimates the cosine ratio using piecewise quadratic equations. Fast but NOT very accurate. + /// The numeric type of the operation. + /// The angle to compute the quadratic estimated cosine ratio of. + /// The quadratic estimation of the cosine ratio of the provided angle. + public static T CosineQuadratic(Angle a) + { + Angle piOver2Radians = new Angle(Constant.PiOver2, Angle.Units.Radians); + return SineQuadratic(a - piOver2Radians); + } + + #endregion + + #region Tangent + + /// Computes the tangent ratio of an angle using the relative talor series. Accurate but slow. + /// The numeric type of the operation. + /// The angle to compute the tangent ratio of. + /// The taylor series computed tangent ratio of the provided angle. + public static T TangentTaylorSeries(Angle a) + { + return Division(SineTaylorSeries(a), CosineTaylorSeries(a)); + } + + /// Computes the tangent ratio of an angle using the system's tangent function. WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). + /// The numeric type of the operation. + /// The angle to compute the tangent ratio of. + /// The tangent ratio of the provided angle. + /// WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). + public static T TangentSystem(Angle a) + { + T b = a[Angle.Units.Radians]; + double c = Convert(b); + double d = Math.Tan(c); + T e = Convert(d); + return e; + } + + /// Estimates the tangent ratio using piecewise quadratic equations. Fast but NOT very accurate. + /// The numeric type of the operation. + /// The angle to compute the quadratic estimated tangent ratio of. + /// The quadratic estimation of the tangent ratio of the provided angle. + public static T TangentQuadratic(Angle a) + { + return Division(SineQuadratic(a), CosineQuadratic(a)); + } + + #endregion + + #region Cosecant + + /// Computes the cosecant ratio of an angle using the system's sine function. WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). + /// The numeric type of the operation. + /// The angle to compute the cosecant ratio of. + /// The cosecant ratio of the provided angle. + /// WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). + public static T CosecantSystem(Angle a) + { + return Division(Constant.One, SineSystem(a)); + } + + /// Estimates the cosecant ratio using piecewise quadratic equations. Fast but NOT very accurate. + /// The numeric type of the operation. + /// The angle to compute the quadratic estimated cosecant ratio of. + /// The quadratic estimation of the cosecant ratio of the provided angle. + public static T CosecantQuadratic(Angle a) + { + return Division(Constant.One, SineQuadratic(a)); + } + + #endregion + + #region Secant + + /// Computes the secant ratio of an angle using the system's cosine function. WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). + /// The numeric type of the operation. + /// The angle to compute the secant ratio of. + /// The secant ratio of the provided angle. + /// WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). + public static T SecantSystem(Angle a) + { + return Division(Constant.One, CosineSystem(a)); + } + + /// Estimates the secant ratio using piecewise quadratic equations. Fast but NOT very accurate. + /// The numeric type of the operation. + /// The angle to compute the quadratic estimated secant ratio of. + /// The quadratic estimation of the secant ratio of the provided angle. + public static T SecantQuadratic(Angle a) + { + return Division(Constant.One, CosineQuadratic(a)); + } + + #endregion + + #region Cotangent + + /// Computes the cotangent ratio of an angle using the system's tangent function. WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). + /// The numeric type of the operation. + /// The angle to compute the cotangent ratio of. + /// The cotangent ratio of the provided angle. + /// WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). + public static T CotangentSystem(Angle a) + { + return Division(Constant.One, TangentSystem(a)); + } + + /// Estimates the cotangent ratio using piecewise quadratic equations. Fast but NOT very accurate. + /// The numeric type of the operation. + /// The angle to compute the quadratic estimated cotangent ratio of. + /// The quadratic estimation of the cotangent ratio of the provided angle. + public static T CotangentQuadratic(Angle a) + { + return Division(Constant.One, TangentQuadratic(a)); + } + + #endregion + + #region InverseSine + + //public static Angle InverseSine(T a) + //{ + // return InverseSineImplementation.Function(a); + //} + + //internal static class InverseSineImplementation + //{ + // internal static Func> Function = a => + // { + // // optimization for specific known types + // if (TypeDescriptor.GetConverter(typeof(T)).CanConvertTo(typeof(double))) + // { + // ParameterExpression A = Expression.Parameter(typeof(T)); + // Expression BODY = Expression.Call(typeof(Angle).GetMethod(nameof(Angle.Factory_Radians), BindingFlags.Static), Expression.Call(typeof(Math).GetMethod(nameof(Math.Asin)), A)); + // Function = Expression.Lambda>>(BODY, A).Compile(); + // return Function(a); + // } + // throw new NotImplementedException(); + // }; + //} + + #endregion + + #region InverseCosine + + //public static Angle InverseCosine(T a) + //{ + // return InverseCosineImplementation.Function(a); + //} + + //internal static class InverseCosineImplementation + //{ + // internal static Func> Function = a => + // { + // // optimization for specific known types + // if (TypeDescriptor.GetConverter(typeof(T)).CanConvertTo(typeof(double))) + // { + // ParameterExpression A = Expression.Parameter(typeof(T)); + // Expression BODY = Expression.Call(typeof(Angle).GetMethod(nameof(Angle.Factory_Radians), BindingFlags.Static), Expression.Call(typeof(Math).GetMethod(nameof(Math.Acos)), A)); + // Function = Expression.Lambda>>(BODY, A).Compile(); + // return Function(a); + // } + // throw new NotImplementedException(); + // }; + //} + + #endregion + + #region InverseTangent + + //public static Angle InverseTangent(T a) + //{ + // return InverseTangentImplementation.Function(a); + //} + + //internal static class InverseTangentImplementation + //{ + // internal static Func> Function = a => + // { + // // optimization for specific known types + // if (TypeDescriptor.GetConverter(typeof(T)).CanConvertTo(typeof(double))) + // { + // ParameterExpression A = Expression.Parameter(typeof(T)); + // Expression BODY = Expression.Call(typeof(Angle).GetMethod(nameof(Angle.Factory_Radians), BindingFlags.Static), Expression.Call(typeof(Math).GetMethod(nameof(Math.Atan)), A)); + // Function = Expression.Lambda>>(BODY, A).Compile(); + // return Function(a); + // } + // throw new NotImplementedException(); + // }; + //} + + #endregion + + #region InverseCosecant + + //public static Angle InverseCosecant(T a) + //{ + // return Angle.Factory_Radians(Divide(Constant.One, InverseSine(a).Radians)); + //} + + #endregion + + #region InverseSecant + + //public static Angle InverseSecant(T a) + //{ + // return Angle.Factory_Radians(Divide(Constant.One, InverseCosine(a).Radians)); + //} + + #endregion + + #region InverseCotangent + + //public static Angle InverseCotangent(T a) + //{ + // return Angle.Factory_Radians(Divide(Constant.One, InverseTangent(a).Radians)); + //} + + #endregion + + #region HyperbolicSine + + //public static T HyperbolicSine(Angle a) + //{ + // return HyperbolicSineImplementation.Function(a); + //} + + //internal static class HyperbolicSineImplementation + //{ + // internal static Func, T> Function = (Angle a) => + // { + // // optimization for specific known types + // if (TypeDescriptor.GetConverter(typeof(T)).CanConvertTo(typeof(double))) + // { + // ParameterExpression A = Expression.Parameter(typeof(T)); + // Expression BODY = Expression.Call(typeof(Math).GetMethod(nameof(Math.Sinh)), Expression.Convert(Expression.Property(A, typeof(Angle).GetProperty(nameof(a.Radians))), typeof(double))); + // Function = Expression.Lambda, T>>(BODY, A).Compile(); + // return Function(a); + // } + // throw new NotImplementedException(); + // }; + //} + + #endregion + + #region HyperbolicCosine + + //public static T HyperbolicCosine(Angle a) + //{ + // return HyperbolicCosineImplementation.Function(a); + //} + + //internal static class HyperbolicCosineImplementation + //{ + // internal static Func, T> Function = (Angle a) => + // { + // // optimization for specific known types + // if (TypeDescriptor.GetConverter(typeof(T)).CanConvertTo(typeof(double))) + // { + // ParameterExpression A = Expression.Parameter(typeof(T)); + // Expression BODY = Expression.Call(typeof(Math).GetMethod(nameof(Math.Cosh)), Expression.Convert(Expression.Property(A, typeof(Angle).GetProperty(nameof(a.Radians))), typeof(double))); + // Function = Expression.Lambda, T>>(BODY, A).Compile(); + // return Function(a); + // } + // throw new NotImplementedException(); + // }; + //} + + #endregion + + #region HyperbolicTangent + + //public static T HyperbolicTangent(Angle a) + //{ + // return HyperbolicTangentImplementation.Function(a); + //} + + //internal static class HyperbolicTangentImplementation + //{ + // internal static Func, T> Function = (Angle a) => + // { + // // optimization for specific known types + // if (TypeDescriptor.GetConverter(typeof(T)).CanConvertTo(typeof(double))) + // { + // ParameterExpression A = Expression.Parameter(typeof(T)); + // Expression BODY = Expression.Call(typeof(Math).GetMethod(nameof(Math.Tanh)), Expression.Convert(Expression.Property(A, typeof(Angle).GetProperty(nameof(a.Radians))), typeof(double))); + // Function = Expression.Lambda, T>>(BODY, A).Compile(); + // return Function(a); + // } + // throw new NotImplementedException(); + // }; + //} + + #endregion + + #region HyperbolicCosecant + + //public static T HyperbolicCosecant(Angle a) + //{ + // return Divide(Constant.One, HyperbolicSine(a)); + //} + + #endregion + + #region HyperbolicSecant + + //public static T HyperbolicSecant(Angle a) + //{ + // return Divide(Constant.One, HyperbolicCosine(a)); + //} + + #endregion + + #region HyperbolicCotangent + + //public static T HyperbolicCotangent(Angle a) + //{ + // return Divide(Constant.One, HyperbolicTangent(a)); + //} + + #endregion + + #region InverseHyperbolicSine + + //public static Angle InverseHyperbolicSine(T a) + //{ + // throw new NotImplementedException(); + //} + + #endregion + + #region InverseHyperbolicCosine + + //public static Angle InverseHyperbolicCosine(T a) + //{ + // throw new NotImplementedException(); + //} + + #endregion + + #region InverseHyperbolicTangent + + //public static Angle InverseHyperbolicTangent(T a) + //{ + // throw new NotImplementedException(); + //} + + #endregion + + #region InverseHyperbolicCosecant + + //public static Angle InverseHyperbolicCosecant(T a) + //{ + // throw new NotImplementedException(); + //} + + #endregion + + #region InverseHyperbolicSecant + + //public static Angle InverseHyperbolicSecant(T a) + //{ + // throw new NotImplementedException(); + //} + + #endregion + + #region InverseHyperbolicCotangent + + //public static Angle InverseHyperbolicCotangent(T a) + //{ + // throw new NotImplementedException(); + //} + + #endregion + } +} diff --git a/Sources/Towel/Statics.cs b/Sources/Towel/Statics.cs index 0a92c18c..36eceb33 100644 --- a/Sources/Towel/Statics.cs +++ b/Sources/Towel/Statics.cs @@ -10,7 +10,7 @@ namespace Towel { /// Root type of the static functional methods in Towel. - public static class Statics + public static partial class Statics { #region Internals @@ -68,6 +68,8 @@ internal static T OperationOnStepper(Action> stepper, Func : throw new ArgumentException($"{nameof(stepper)} is empty.", nameof(stepper)); } + internal static CompareResult ToCompareResult(int result) => result < 0 ? Less : (result > 0 ? Greater : Equal); + #endregion #region Swap @@ -240,532 +242,6 @@ public static string Join(Range range, Func func, string seperator) #endregion - #region Keywords - - /// Stepper was not broken. - public const StepStatus Continue = StepStatus.Continue; - /// Stepper was broken. - public const StepStatus Break = StepStatus.Break; - /// The Goal was found. - public const GraphSearchStatus Goal = GraphSearchStatus.Goal; - /// The left operand is less than the right operand. - public const CompareResult Less = CompareResult.Less; - /// The left operand is equal to the right operand. - public const CompareResult Equal = CompareResult.Equal; - /// The left operand is greater than the right operand. - public const CompareResult Greater = CompareResult.Greater; - /// There is no bound. - public const Omnitree.Keyword None = Omnitree.Keyword.None; - /// The default case in a Switch statement (true). - public const SwitchSyntax.Keyword Default = SwitchSyntax.Keyword.Default; - - #endregion - - #region Switch - - /// Syntax sugar Switch statements. - /// The possible actions of the Switch statement. - public static void Switch(params (SwitchSyntax.Condition, Action)[] possibleActions) => - SwitchSyntax.Do(possibleActions); - - /// Syntax sugar Switch statements. - /// The generic type parameter to the Switch statement. - /// The value argument of the Switch statement. - /// The delegate for the Switch statement. - public static SwitchSyntax.ParamsAction, Action> Switch(T value) => - SwitchSyntax.Do(value); - - /// Definitions for Switch syntax. - public static class SwitchSyntax - { - /// Delegate with params intended to be used with the Switch syntax. - public delegate void ParamsAction(params (A, B)[] values); - - internal static ParamsAction, Action> Do(T value) => - possibleActions => - { - foreach (var possibleAction in possibleActions) - { - if (possibleAction.Item1.Resolve(value)) - { - possibleAction.Item2(); - return; - } - } - }; - - internal static void Do(params (Condition Condition, Action Action)[] possibleActions) - { - foreach (var possibleAction in possibleActions) - { - if (possibleAction.Condition) - { - possibleAction.Action(); - return; - } - } - } - - /// Intended to be used with Switch syntax. - public enum Keyword - { - /// The default keyword for the the Switch syntax. - Default, - } - - /// Represents the result of a conditional expression inside Switch syntax. - /// The generic type of the Switch condition for equality checks. - public abstract class Condition - { - /// Resolves the condition to a bool. - public abstract bool Resolve(T b); - /// Casts a to a bool using an equality check. - public static implicit operator Condition(T value) => new Value(a: value); - /// Uses the bool as the condition result. - public static implicit operator Condition(bool result) => new Bool { Result = result, }; - /// Converts a keyword to a condition result (for "Default" case). -#pragma warning disable IDE0079 // Remove unnecessary suppression -#pragma warning disable IDE0060 // Remove unused parameter - public static implicit operator Condition(Keyword keyword) => new Default(); -#pragma warning restore IDE0060 // Remove unused parameter -#pragma warning restore IDE0079 // Remove unnecessary suppression - } - - internal class Value : Condition - { - /// The value of this condition for an equality check. - internal T A; - public override bool Resolve(T b) => Equate(A, b); - public Value(T a) - { - A = a; - } - } - - internal class Bool : Condition - { - internal bool Result; - public override bool Resolve(T b) => Result; - } - - internal class Default : Condition - { - public override bool Resolve(T b) => true; - } - - /// Represents the result of a conditional expression inside Switch syntax. - public abstract class Condition - { - /// Resolves the condition to a bool. - public abstract bool Resolve(); - /// Uses the bool as the condition result. - public static implicit operator Condition(bool result) => new Bool { Result = result, }; -#pragma warning disable IDE0079 // Remove unnecessary suppression -#pragma warning disable IDE0060 // Remove unused parameter - /// Converts a keyword to a condition result (for "Default" case). - public static implicit operator Condition(Keyword keyword) => new Default(); -#pragma warning restore IDE0060 // Remove unused parameter -#pragma warning restore IDE0079 // Remove unnecessary suppression - /// Converts a condition to a bool using the Resolve method. - public static implicit operator bool(Condition condition) => condition.Resolve(); - } - - internal class Bool : Condition - { - internal bool Result; - public override bool Resolve() => Result; - } - - internal class Default : Condition - { - public override bool Resolve() => true; - } - } - - #endregion - - #region Chance - -#pragma warning disable CA2211 // Non-constant fields should not be visible -#pragma warning disable IDE0079 // Remove unnecessary suppression -#pragma warning disable IDE0075 // Simplify conditional expression -#pragma warning disable IDE0060 // Remove unused parameter - - /// Allows chance syntax with "using static Towel.Syntax;". - /// 25% Chance - public static ChanceSyntax Chance => default; - - /// Struct that allows percentage syntax that will be evaluated at runtime. - public struct ChanceSyntax - { - /// The random algorithm currently being used by chance syntax. - public static Random Algorithm = new Random(); - - /// Creates a chance from a percentage that will be evaluated at runtime. - /// The value of the percentage. - /// The chance syntax struct object. - /// True if the the chance hits. False if not. - public static bool operator %(double percentage, ChanceSyntax chance) => - percentage < 0d ? throw new ArgumentOutOfRangeException(nameof(chance)) : - percentage > 100d ? throw new ArgumentOutOfRangeException(nameof(chance)) : - percentage is 100d ? true : - percentage is 0d ? false : - Algorithm.NextDouble() < percentage / 100d; - } - -#pragma warning restore IDE0060 // Remove unused parameter -#pragma warning restore IDE0075 // Simplify conditional expression -#pragma warning restore IDE0079 // Remove unnecessary suppression -#pragma warning restore CA2211 // Non-constant fields should not be visible - - #endregion - - #region Inequality - - /// Used for inequality syntax. - /// The generic type of elements the inequality is being used on. - public struct Inequality - { - internal bool Cast; - internal T A; - - /// Contructs a new . - /// The initial value of the running inequality. - public static implicit operator Inequality(T a) => - new Inequality() - { - Cast = true, - A = a, - }; - /// Adds a greater than operation to a running inequality. - /// The current running inequality and left hand operand. - /// The value of the right hand operand of the greater than operation. - /// A running inequality with the additonal greater than operation. - public static OperatorValidated.Inequality operator >(Inequality a, T b) => - !a.Cast ? throw new InequalitySyntaxException() : - new OperatorValidated.Inequality(Compare(a.A, b) == Greater, b); - /// Adds a less than operation to a running inequality. - /// The current running inequality and left hand operand. - /// The value of the right hand operand of the less than operation. - /// A running inequality with the additonal less than operation. - public static OperatorValidated.Inequality operator <(Inequality a, T b) => - !a.Cast ? throw new InequalitySyntaxException() : - new OperatorValidated.Inequality(Compare(a.A, b) == Less, b); - /// Adds a greater than or equal operation to a running inequality. - /// The current running inequality and left hand operand. - /// The value of the right hand operand of the greater than or equal operation. - /// A running inequality with the additonal greater than or equal operation. - public static OperatorValidated.Inequality operator >=(Inequality a, T b) => - !a.Cast ? throw new InequalitySyntaxException() : - new OperatorValidated.Inequality(Compare(a.A, b) != Less, b); - /// Adds a less than or equal operation to a running inequality. - /// The current running inequality and left hand operand. - /// The value of the right hand operand of the less than or equal operation. - /// A running inequality with the additonal less than or equal operation. - public static OperatorValidated.Inequality operator <=(Inequality a, T b) => - !a.Cast ? throw new InequalitySyntaxException() : - new OperatorValidated.Inequality(Compare(a.A, b) != Greater, b); - /// Adds an equal operation to a running inequality. - /// The current running inequality and left hand operand. - /// The value of the right hand operand of the equal operation. - /// A running inequality with the additonal equal operation. - public static OperatorValidated.Inequality operator ==(Inequality a, T b) => - !a.Cast ? throw new InequalitySyntaxException() : - new OperatorValidated.Inequality(Equate(a.A, b), b); - /// Adds an inequal operation to a running inequality. - /// The current running inequality and left hand operand. - /// The value of the right hand operand of the inequal operation. - /// A running inequality with the additonal inequal operation. - public static OperatorValidated.Inequality operator !=(Inequality a, T b) => - !a.Cast ? throw new InequalitySyntaxException() : - new OperatorValidated.Inequality(Inequate(a.A, b), b); - -#pragma warning disable CS0809 // Obsolete member overrides non-obsolete member - /// This member is not intended to be invoked. - /// This member is not intended to be invoked. - [Obsolete(TowelConstants.NotIntended, true)] - public override string ToString() => throw new InequalitySyntaxException(); - /// This member is not intended to be invoked. - /// This member is not intended to be invoked. - /// This member is not intended to be invoked. - [Obsolete(TowelConstants.NotIntended, true)] - public override bool Equals(object? obj) => throw new InequalitySyntaxException(); - /// This member is not intended to be invoked. - /// This member is not intended to be invoked. - [Obsolete(TowelConstants.NotIntended, true)] - public override int GetHashCode() => throw new InequalitySyntaxException(); -#pragma warning restore CS0809 // Obsolete member overrides non-obsolete member - } - - /// Helper type for inequality syntax. Contains an Inequality type that has been operator validated. - public static partial class OperatorValidated - { - /// Used for inequality syntax. - /// The generic type of elements the inequality is being used on. - public struct Inequality - { - internal readonly bool Result; - internal readonly T A; - - internal Inequality(bool result, T a) - { - Result = result; - A = a; - } - /// Converts this running inequality into the result of the expression. - /// The inequality to convert into the result of the expression. - public static implicit operator bool(Inequality inequality) => - inequality.Result; - /// Adds a greater than operation to a running inequality. - /// The current running inequality and left hand operand. - /// The value of the right hand operand of the greater than operation. - /// A running inequality with the additonal greater than operation. - public static Inequality operator >(Inequality a, T b) => - new Inequality(a.Result && Compare(a.A, b) == Greater, b); - /// Adds a less than operation to a running inequality. - /// The current running inequality and left hand operand. - /// The value of the right hand operand of the less than operation. - /// A running inequality with the additonal less than operation. - public static Inequality operator <(Inequality a, T b) => - new Inequality(a.Result && Compare(a.A, b) == Less, b); - /// Adds a greater than or equal operation to a running inequality. - /// The current running inequality and left hand operand. - /// The value of the right hand operand of the greater than or equal operation. - /// A running inequality with the additonal greater than or equal operation. - public static Inequality operator >=(Inequality a, T b) => - new Inequality(a.Result && Compare(a.A, b) != Less, b); - /// Adds a less than or equal operation to a running inequality. - /// The current running inequality and left hand operand. - /// The value of the right hand operand of the less than or equal operation. - /// A running inequality with the additonal less than or equal operation. - public static Inequality operator <=(Inequality a, T b) => - new Inequality(a.Result && Compare(a.A, b) != Greater, b); - /// Adds an equal operation to a running inequality. - /// The current running inequality and left hand operand. - /// The value of the right hand operand of the equal operation. - /// A running inequality with the additonal equal operation. - public static Inequality operator ==(Inequality a, T b) => - new Inequality(a.Result && Equate(a.A, b), b); - /// Adds an inequal operation to a running inequality. - /// The current running inequality and left hand operand. - /// The value of the right hand operand of the inequal operation. - /// A running inequality with the additonal inequal operation. - public static Inequality operator !=(Inequality a, T b) => - new Inequality(a.Result && Inequate(a.A, b), b); - /// Converts the result of this inequality to a . - /// The result of this inequality converted to a . - public override string ToString() => Result.ToString(); -#pragma warning disable CS0809 // Obsolete member overrides non-obsolete member - /// This member is not intended to be invoked. - /// This member is not intended to be invoked. - /// This member is not intended to be invoked. - [Obsolete(TowelConstants.NotIntended, true)] - public override bool Equals(object? obj) => throw new InequalitySyntaxException(); - /// This member is not intended to be invoked. - /// This member is not intended to be invoked. - [Obsolete(TowelConstants.NotIntended, true)] - public override int GetHashCode() => throw new InequalitySyntaxException(); -#pragma warning restore CS0809 // Obsolete member overrides non-obsolete member - } - } - - #endregion - - #region UniversalQuantification - - /// Universal Quantification Operator. - /// The element type of the universal quantification to declare. - /// The values of the universal quantification. - /// The declared universal quantification. - public static UniversalQuantification(params T[] values) => new UniversalQuantification(values); - - /// Universal Quantification. - /// The element type of the universal quantification. - public struct UniversalQuantification : - System.Collections.Generic.IEnumerable, - System.Collections.Generic.IList, - Towel.DataStructures.IArray - { - internal T[] Value; - - /// Constructs a new universal quantification from an array. - /// The array value of the universal quantification. - internal UniversalQuantification(T[] array) => Value = array; - - #region Towel.Datastructures.IArray - /// The number of values in this universal quantification. - [Obsolete(TowelConstants.NotIntended, true)] - public int Length => Value.Length; - /// Iterates each value in this universal quantification and performs an action for each element. - /// The action to perform on every step of the iteration. - [Obsolete(TowelConstants.NotIntended, true)] - public void Stepper(Action step) => Value.Stepper(step); - /// Iterates each value in this universal quantification and performs an action for each element. - [Obsolete(TowelConstants.NotIntended, true)] - public StepStatus Stepper(Func step) => Value.Stepper(step); - #endregion - - #region System.Collections.Generic.IList - /// Index property for get/set operations. - /// The index to get/set. - /// The value at the provided index. - [Obsolete(TowelConstants.NotIntended, true)] - public T this[int index] - { - get => Value[index]; - set => Value[index] = value; - } - /// Gets the number of elements in this universal quantification. - public int Count => Value.Length; - /// Gets a value indicating whether the is read-only. - public bool IsReadOnly => false; - /// Adds an item to this universal quantifier. - /// The item to add to this universal quantifier. - [Obsolete(TowelConstants.NotIntended, true)] - public void Add(T item) - { - T[] newValue = new T[Value.Length + 1]; - Array.Copy(Value, newValue, Value.Length); - newValue[Value.Length] = item; - Value = newValue; - } - /// Not intended to be invoked directly. - [Obsolete(TowelConstants.NotIntended, true)] - public void Clear() => Value = Array.Empty(); - /// Not intended to be invoked directly. - [Obsolete(TowelConstants.NotIntended, true)] - public bool Contains(T item) => Value.Contains(item); - /// Not intended to be invoked directly. - [Obsolete(TowelConstants.NotIntended, true)] - public void CopyTo(T[] array, int arrayIndex) => - Array.Copy(Value, 0, array, arrayIndex, Value.Length); - /// Not intended to be invoked directly. - [Obsolete(TowelConstants.NotIntended, true)] - public int IndexOf(T item) => Array.IndexOf(Value, item); - /// Not intended to be invoked directly. - [Obsolete(TowelConstants.NotIntended, true)] - public void Insert(int index, T item) - { - T[] newValue = new T[Value.Length + 1]; - for (int i = 0; i < newValue.Length; i++) - { - newValue[i] = i == index - ? item - : i < index - ? Value[i] - : Value[i - 1]; - } - Value = newValue; - } - /// Not intended to be invoked directly. - [Obsolete(TowelConstants.NotIntended, true)] - public bool Remove(T item) - { - T[] newValue = new T[Value.Length - 1]; - bool found = false; - for (int i = 0; i < Value.Length; i++) - { - if (Equate(Value[i], item)) - { - found = true; - } - else if (found) - { - newValue[i] = Value[i - 1]; - } - else - { - newValue[i] = Value[i]; - } - } - if (!found) - { - return false; - } - Value = newValue; - return true; - } - /// Not intended to be invoked directly. - [Obsolete(TowelConstants.NotIntended, true)] - public void RemoveAt(int index) - { - T[] newValue = new T[Value.Length - 1]; - for (int i = 0; i < Value.Length; i++) - { - if (i != index) - { - if (i < index) - { - newValue[i] = Value[i]; - } - else - { - newValue[i] = Value[i - 1]; - } - } - } - Value = newValue; - } - #endregion - - #region System.Collections.Generic.IEnumerable - /// Gets the for this universal quantification. - /// The for this universal quantification. - [Obsolete(TowelConstants.NotIntended, true)] - public System.Collections.Generic.IEnumerator GetEnumerator() => ((System.Collections.Generic.IEnumerable)Value).GetEnumerator(); - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => Value.GetEnumerator(); - #endregion - - #region Implicit Casting Operators - - /// Converts a universal quantification to an array. - /// The universal quantification to be converted. - public static implicit operator T[](UniversalQuantification universalQuantification) => universalQuantification.Value; - /// Converts a universal quantification to a . - /// The universal quantification to be converted. - public static implicit operator System.Collections.Generic.List(UniversalQuantification universalQuantification) => new System.Collections.Generic.List(universalQuantification.Value); - /// Converts a universal quantification to an . - /// The universal quantification to be converted. - public static implicit operator System.Collections.Generic.HashSet(UniversalQuantification universalQuantification) => new System.Collections.Generic.HashSet(universalQuantification.Value); - /// Converts a universal quantification to a . - /// The universal quantification to be converted. - public static implicit operator System.Collections.Generic.LinkedList(UniversalQuantification universalQuantification) => new System.Collections.Generic.LinkedList(universalQuantification.Value); - /// Converts a universal quantification to an . - /// The universal quantification to be converted. - public static implicit operator System.Collections.Generic.Stack(UniversalQuantification universalQuantification) => new System.Collections.Generic.Stack(universalQuantification.Value); - /// Converts a universal quantification to an . - /// The universal quantification to be converted. - public static implicit operator System.Collections.Generic.Queue(UniversalQuantification universalQuantification) => new System.Collections.Generic.Queue(universalQuantification.Value); - /// Converts a universal quantification to a sorted . - /// The universal quantification to be converted. - public static implicit operator System.Collections.Generic.SortedSet(UniversalQuantification universalQuantification) => new System.Collections.Generic.SortedSet(universalQuantification.Value); - /// Converts a universal quantification to an Action<Action<T>>. - /// The universal quantification to be converted. - public static implicit operator Action>(UniversalQuantification universalQuantification) => universalQuantification.Value.ToStepper(); - /// Converts a universal quantification to an . - /// The universal quantification to be converted. - public static implicit operator StepperRef(UniversalQuantification universalQuantification) => universalQuantification.Value.ToStepperRef(); - /// Converts a universal quantification to an Func<Func<T, StepStatus>, StepStatus>. - /// The universal quantification to be converted. - public static implicit operator Func, StepStatus>(UniversalQuantification universalQuantification) => universalQuantification.Value.ToStepperBreak(); - /// Converts a universal quantification to an . - /// The universal quantification to be converted. - public static implicit operator StepperRefBreak(UniversalQuantification universalQuantification) => universalQuantification.Value.ToStepperRefBreak(); - /// Converts a universal quantification to an . - /// The universal quantification to be converted. - public static implicit operator Towel.DataStructures.Array(UniversalQuantification universalQuantification) => universalQuantification.Value; - /// Converts a universal quantification to an . - /// The universal quantification to be converted. - public static implicit operator Towel.DataStructures.ListArray(UniversalQuantification universalQuantification) => new ListArray(universalQuantification.Value, universalQuantification.Value.Length); - /// Converts a universal quantification to an . - /// The universal quantification to be converted. - public static implicit operator Towel.DataStructures.StackArray(UniversalQuantification universalQuantification) => new StackArray(universalQuantification.Value, universalQuantification.Value.Length); - - #endregion - } - - #endregion - #region Equate #if false @@ -1158,7 +634,7 @@ internal static class CompareImplementation !(typeof(A).IsPrimitive && typeof(B).IsPrimitive)) { CompareImplementation.Function = - (a, b) => System.Collections.Generic.Comparer.Default.Compare(a, b).ToCompareResult(); + (a, b) => ToCompareResult(System.Collections.Generic.Comparer.Default.Compare(a, b)); } else { @@ -1932,71 +1408,6 @@ internal static class AbsoluteValueImplementation #endregion - #region Maximum - - /// Computes the maximum of two numeric values. - /// The numeric type of the operation. - /// The first operand of the maximum operation. - /// The second operand of the maximum operation. - /// The computed maximum of the provided values. - public static T Maximum(T a, T b) => - GreaterThanOrEqual(a, b) ? a : b; - - /// Computes the maximum of multiple numeric values. - /// The numeric type of the operation. - /// The first operand of the maximum operation. - /// The second operand of the maximum operation. - /// The third operand of the maximum operation. - /// The remaining operands of the maximum operation. - /// The computed maximum of the provided values. - public static T Maximum(T a, T b, T c, params T[] d) => - Maximum(step => { step(a); step(b); step(c); d.ToStepper()(step); }); - - /// Computes the maximum of multiple numeric values. - /// The numeric type of the operation. - /// The set of data to compute the maximum of. - /// The computed maximum of the provided values. - public static T Maximum(Action> stepper) => - OperationOnStepper(stepper, Maximum); - - #endregion - - #region Minimum - - /// Computes the minimum of two numeric values. - /// The numeric type of the operation. - /// The first operand of the minimum operation. - /// The second operand of the minimum operation. - /// The computed minimum of the provided values. - public static T Minimum(T a, T b) => - LessThanOrEqual(a, b) ? a : b; - - /// Computes the minimum of multiple numeric values. - /// The numeric type of the operation. - /// The first operand of the minimum operation. - /// The second operand of the minimum operation. - /// The third operand of the minimum operation. - /// The remaining operands of the minimum operation. - /// The computed minimum of the provided values. - public static T Minimum(T a, T b, T c, params T[] d) => - Minimum(step => { step(a); step(b); step(c); d.ToStepper()(step); }); - - /// Computes the minimum of multiple numeric values. - /// The numeric type of the operation. - /// The set of data to compute the minimum of. - /// The computed minimum of the provided values. - public static T Minimum(Action> stepper) => - OperationOnStepper(stepper, Minimum); - - /// Computes the minimum of multiple numeric values. - /// The first operand of the minimum operation. - /// The second operand of the minimum operation. - /// The third operand of the minimum operation. - /// The computed minimum of the provided values. - public static int Minimum(int a, int b, int c) => Math.Min(Math.Min(a, b), c); - - #endregion - #region Clamp /// Gets a value restricted to a minimum and maximum range. @@ -2301,4067 +1712,134 @@ public static T BinomialCoefficient(T N, T n) #endregion - #region Occurences - - /// Counts the number of occurences of each item. - /// The generic type to count the occerences of. - /// The first value in the data. - /// The rest of the data. - /// The occurence map of the data. - public static IMap Occurences(T a, params T[] b) => - Occurences(step => { step(a); b.ToStepper()(step); }); - - /// Counts the number of occurences of each item. - /// The generic type to count the occerences of. - /// The equality delegate. - /// The first value in the data. - /// The rest of the data. - /// The occurence map of the data. - public static IMap Occurences(Func equate, T a, params T[] b) => - Occurences(step => { step(a); b.ToStepper()(step); }, equate, null); - - /// Counts the number of occurences of each item. - /// The generic type to count the occerences of. - /// The hash code delegate. - /// The first value in the data. - /// The rest of the data. - /// The occurence map of the data. - public static IMap Occurences(Func hash, T a, params T[] b) => - Occurences(step => { step(a); b.ToStepper()(step); }, null, hash); - - /// Counts the number of occurences of each item. - /// The generic type to count the occerences of. - /// The equality delegate. - /// The hash code delegate. - /// The first value in the data. - /// The rest of the data. - /// The occurence map of the data. - public static IMap Occurences(Func equate, Func hash, T a, params T[] b) => - Occurences(step => { step(a); b.ToStepper()(step); }, equate, hash); - - /// Counts the number of occurences of each item. - /// The generic type to count the occerences of. - /// The data to count the occurences of. - /// The equality delegate. - /// The hash code delegate. - /// The occurence map of the data. - public static IMap Occurences(Action> stepper, Func? equate = null, Func? hash = null) + #region Exponential + + /// Computes the exponentional of a value [e ^ ]. + /// The generic type of the operation. + /// The value to compute the exponentional of. + /// The exponential of the value [e ^ ]. + public static T Exponential(T a) { - IMap map = new MapHashLinked(equate, hash); - stepper(a => - { - if (map.Contains(a)) - { - map[a]++; - } - else - { - map[a] = 1; - } - }); - return map; + throw new NotImplementedException(); } #endregion - #region Mode - - /// Gets the mode(s) of a data set. - /// The generic type of the data. - /// The action to perform on every mode value found. - /// The first value of the data set. - /// The rest of the data set. - public static void Mode(Action step, T a, params T[] b) => - Mode(x => { x(a); b.ToStepper()(x); }, step); - - /// Gets the mode(s) of a data set. - /// The generic type of the data. - /// The action to perform on every mode value found. - /// The equality delegate. - /// The first value of the data set. - /// The rest of the data set. - public static void Mode(Action step, Func equate, T a, params T[] b) => - Mode(x => { x(a); b.ToStepper()(x); }, step, equate, null); - - /// Gets the mode(s) of a data set. - /// The generic type of the data. - /// The action to perform on every mode value found. - /// The hash code delegate - /// The first value of the data set. - /// The rest of the data set. - public static void Mode(Action step, Func hash, T a, params T[] b) => - Mode(x => { x(a); b.ToStepper()(x); }, step, null, hash); - - /// Gets the mode(s) of a data set. - /// The generic type of the data. - /// The action to perform on every mode value found. - /// The equality delegate. - /// The hash code delegate - /// The first value of the data set. - /// The rest of the data set. - public static void Mode(Action step, Func equate, Func hash, T a, params T[] b) => - Mode(x => { x(a); b.ToStepper()(x); }, step, equate, hash); - - /// Gets the mode(s) of a data set. - /// The generic type of the data. - /// The data set. - /// The action to perform on every mode value found. - /// The equality delegate. - /// The hash code delegate - /// The modes of the data set. - public static void Mode(Action> stepper, Action step, Func? equate = null, Func? hash = null) + #region NaturalLogarithm + + /// Computes the natural logarithm of a value [ln()]. + /// The generic type of the operation. + /// The value to compute the natural log of. + /// The natural log of the provided value [ln()]. + public static T NaturalLogarithm(T a) => + NaturalLogarithmImplementation.Function(a); + + internal static class NaturalLogarithmImplementation { - int maxOccurences = -1; - IMap map = new MapHashLinked(equate, hash); - stepper(a => - { - if (map.Contains(a)) - { - int occurences = ++map[a]; - maxOccurences = Math.Max(occurences, maxOccurences); - } - else - { - map[a] = 1; - maxOccurences = Math.Max(1, maxOccurences); - } - }); - map.Stepper((value, key) => + internal static Func Function = a => { - if (value == maxOccurences) + // optimization for specific known types + if (TypeDescriptor.GetConverter(typeof(T)).CanConvertTo(typeof(double))) { - step(key); + ParameterExpression A = Expression.Parameter(typeof(T)); + MethodInfo? Math_Log = typeof(Math).GetMethod("Log"); + if (Math_Log is not null) + { + Expression BODY = Expression.Call(Math_Log, A); + Function = Expression.Lambda>(BODY, A).Compile(); + return Function(a); + } } - }); + throw new NotImplementedException(); + }; } #endregion - #region Mean - - /// Computes the mean of a set of numerical values. - /// The numeric type of the operation. - /// The first value of the set of data to compute the mean of. - /// The remaining values in the data set to compute the mean of. - /// The computed mean of the set of data. - public static T Mean(T a, params T[] b) => - Mean(step => { step(a); b.ToStepper()(step); }); + #region LinearRegression2D - /// Computes the mean of a set of numerical values. + /// Computes the best fit line from a set of points in 2D space [y = slope * x + y_intercept]. /// The numeric type of the operation. - /// The set of data to compute the mean of. - /// The computed mean of the set of data. - public static T Mean(Action> stepper) + /// The points to compute the best fit line of. + /// The slope of the computed best fit line [y = slope * x + y_intercept]. + /// The y intercept of the computed best fit line [y = slope * x + y_intercept]. + public static void LinearRegression2D(Action> points, out T slope, out T y_intercept) { - _ = stepper ?? throw new ArgumentNullException(nameof(stepper)); - T i = Constant.Zero; - T sum = Constant.Zero; - stepper(step => + _ = points ?? throw new ArgumentNullException(nameof(points)); + int count = 0; + T sumx = Constant.Zero; + T sumy = Constant.Zero; + points((T x, T y) => { - i = Addition(i, Constant.One); - sum = Addition(sum, step); + sumx = Addition(sumx, x); + sumy = Addition(sumy, y); + count++; }); - if (Equate(i, Constant.Zero)) - { - throw new ArgumentException("The argument is empty.", nameof(stepper)); - } - return Division(sum, i); - } - - #endregion - - #region Median - - /// Computes the median of a set of data. - /// The numeric type of the operation. - /// The comparison algorithm to sort the data by. - /// The set of data to compute the median of. - /// The computed median value of the set of data. - public static T Median(Func compare, params T[] values) - { - _ = compare ?? throw new ArgumentNullException(nameof(compare)); - _ = values ?? throw new ArgumentNullException(nameof(values)); - // standard algorithm (sort and grab middle value) - SortMerge(values, compare); - if (values.Length % 2 == 1) // odd... just grab middle value + if (count < 2) { - return values[values.Length / 2]; + throw new MathematicsException("At least 3 points must be provided for linear regressions"); } - else // even... must perform a mean of the middle two values + T tcount = Convert(count); + T meanx = Division(sumx, tcount); + T meany = Division(sumy, tcount); + T variancex = Constant.Zero; + T variancey = Constant.Zero; + points((T x, T y) => { - T leftMiddle = values[(values.Length / 2) - 1]; - T rightMiddle = values[values.Length / 2]; - return Division(Addition(leftMiddle, rightMiddle), Constant.Two); - } - } - - /// Computes the median of a set of data. - /// The numeric type of the operation. - /// The comparison algorithm to sort the data by. - /// The set of data to compute the median of. - /// The computed median value of the set of data. - public static T Median(Func compare, Action> stepper) - { - _ = stepper ?? throw new ArgumentNullException(nameof(stepper)); - return Median(compare, stepper.ToArray()); - } - - /// Computes the median of a set of data. - /// The numeric type of the operation. - /// The set of data to compute the median of. - /// The computed median value of the set of data. - public static T Median(params T[] values) - { - return Median(Compare, values); - } - - /// Computes the median of a set of data. - /// The numeric type of the operation. - /// The set of data to compute the median of. - /// The computed median value of the set of data. - public static T Median(Action> stepper) - { - _ = stepper ?? throw new ArgumentNullException(nameof(stepper)); - return Median(Compare, stepper.ToArray()); + T offset = Subtraction(x, meanx); + variancey = Addition(variancey, Multiplication(offset, Subtraction(y, meany))); + variancex = Addition(variancex, Multiplication(offset, offset)); + }); + slope = Division(variancey, variancex); + y_intercept = Subtraction(meany, Multiplication(slope, meanx)); } - #region Possible Optimization (Still in Development) - - //public static T Median(Func compare, Hash hash, Func equate, params T[] values) - //{ - // // this is an optimized median algorithm, but it only works on odd sets without duplicates - // if (hash is not null && equate is not null && values.Length % 2 == 1 && !values.ToStepper().ContainsDuplicates(equate, hash)) - // { - // int medianIndex = 0; - // OddNoDupesMedianImplementation(values, values.Length, ref medianIndex, compare); - // return values[medianIndex]; - // } - // else - // { - // return Median(compare, values); - // } - //} - - //public static T Median(Func compare, Hash hash, Func equate, Stepper stepper) - //{ - // return Median(compare, hash, equate, stepper.ToArray()); - //} - - ///// Fast algorithm for median computation, but only works on data with an odd number of values without duplicates. - //internal static void OddNoDupesMedianImplementation(T[] a, int n, ref int k, Func compare) - //{ - // int L = 0; - // int R = n - 1; - // k = n / 2; - // int i; int j; - // while (L < R) - // { - // T x = a[k]; - // i = L; j = R; - // OddNoDupesMedianImplementation_Split(a, n, x, ref i, ref j, compare); - // if (j <= k) L = i; - // if (i >= k) R = j; - // } - //} - - //internal static void OddNoDupesMedianImplementation_Split(T[] a, int n, T x, ref int i, ref int j, Func compare) - //{ - // do - // { - // while (compare(a[i], x) == Comparison.Less) i++; - // while (compare(a[j], x) == Comparison.Greater) j--; - // T t = a[i]; - // a[i] = a[j]; - // a[j] = t; - // } while (i < j); - //} - #endregion - #endregion + #region FactorPrimes - #region GeometricMean + /// Factors the primes numbers of a numeric integer value. + /// The numeric type of the operation. + /// The value to factor the prime numbers of. + /// The action to perform on all found prime factors. + public static void FactorPrimes(T a, Action step) => + FactorPrimesImplementation.Function(a, step); - /// Computes the geometric mean of a set of numbers. - /// The numeric type of the computation. - /// The set of numbres to compute the geometric mean of. - /// The computed geometric mean of the set of numbers. - public static T GeometricMean(Action> stepper) + internal static class FactorPrimesImplementation { - T multiple = Constant.One; - T count = Constant.Zero; - stepper(i => + internal static Action> Function = (a, x) => { - count = Addition(count, Constant.One); - multiple = Multiplication(multiple, i); - }); - return Root(multiple, count); - } - - #endregion - - #region Variance - - /// Computes the variance of a set of numbers. - /// The numeric type of the computation. - /// The set of numbers to compute the variance of. - /// The computed variance of the set of numbers. - public static T Variance(Action> stepper) - { - T mean = Mean(stepper); - T variance = Constant.Zero; - T count = Constant.Zero; - stepper(i => - { - T i_minus_mean = Subtraction(i, mean); - variance = Addition(variance, Multiplication(i_minus_mean, i_minus_mean)); - count = Addition(count, Constant.One); - }); - return Division(variance, count); - } - - #endregion - - #region StandardDeviation - - /// Computes the standard deviation of a set of numbers. - /// The numeric type of the computation. - /// The set of numbers to compute the standard deviation of. - /// The computed standard deviation of the set of numbers. - public static T StandardDeviation(Action> stepper) => - SquareRoot(Variance(stepper)); - - #endregion - - #region MeanDeviation - - /// The mean deviation of a set of numbers. - /// The numeric type of the computation. - /// The set of numbers to compute the mean deviation of. - /// The computed mean deviation of the set of numbers. - public static T MeanDeviation(Action> stepper) - { - T mean = Mean(stepper); - T temp = Constant.Zero; - T count = Constant.Zero; - stepper(i => - { - temp = Addition(temp, AbsoluteValue(Subtraction(i, mean))); - count = Addition(count, Constant.One); - }); - return Division(temp, count); - } - - #endregion - - #region Range - - /// Gets the range (minimum and maximum) of a set of data. - /// The numeric type of the operation. - /// /// The set of data to get the range of. - /// The minimum of the set of data. - /// The maximum of the set of data. - /// Throws when stepper is null. - /// Throws when stepper is empty. - public static void Range(out T minimum, out T maximum, Action> stepper) => - Range(stepper, out minimum, out maximum); - - /// Gets the range (minimum and maximum) of a set of data. - /// The numeric type of the operation. - /// /// The set of data to get the range of. - /// The minimum of the set of data. - /// The maximum of the set of data. - /// Throws when stepper is null. - /// Throws when stepper is empty. - public static void Range(Action> stepper, out T minimum, out T maximum) - { - _ = stepper ?? throw new ArgumentNullException(nameof(stepper)); - // Note: can't use out parameters as capture variables - T min = default; - T max = default; - bool assigned = false; - stepper(a => - { - if (assigned) - { - min = LessThan(a, min) ? a : min; - max = LessThan(max, a) ? a : max; - } - else - { - min = a; - max = a; - assigned = true; - } - }); - if (!assigned) - { - throw new ArgumentException("The argument is empty.", nameof(stepper)); - } - minimum = min!; - maximum = max!; - } - - #endregion - - #region Quantiles - - /// Computes the quantiles of a set of data. - /// The generic data type. - /// The number of quantiles to compute. - /// The data stepper. - /// The computed quantiles of the data set. - public static T[] Quantiles(int quantiles, Action> stepper) - { - if (quantiles < 1) - { - throw new ArgumentOutOfRangeException(nameof(quantiles), quantiles, "!(" + nameof(quantiles) + " >= 1)"); - } - int count = stepper.Count(); - T[] ordered = new T[count]; - int a = 0; - stepper(i => { ordered[a++] = i; }); - SortQuick(ordered, Compare); - T[] resultingQuantiles = new T[quantiles + 1]; - resultingQuantiles[0] = ordered[0]; - resultingQuantiles[^1] = ordered[^1]; - T QUANTILES_PLUS_1 = Convert(quantiles + 1); - T ORDERED_LENGTH = Convert(ordered.Length); - for (int i = 1; i < quantiles; i++) - { - T I = Convert(i); - T temp = Division(ORDERED_LENGTH, Multiplication(QUANTILES_PLUS_1, I)); - if (IsInteger(temp)) - { - resultingQuantiles[i] = ordered[Convert(temp)]; - } - else - { - resultingQuantiles[i] = Division(Addition(ordered[Convert(temp)], ordered[Convert(temp) + 1]), Constant.Two); - } - } - return resultingQuantiles; - } - - #endregion - - #region Correlation - - // /// Computes the median of a set of values. - // internal static Compute.Delegates.Correlation Correlation_internal = (Stepper a, Stepper b) => - // { - // throw new System.NotImplementedException("I introduced an error here when I removed the stepref off of structure. will fix soon"); - - // Compute.Correlation_internal = - // Meta.Compile( - // string.Concat( - // @"(Stepper<", Meta.ConvertTypeToCsharpSource(typeof(T)), "> _a, Stepper<", Meta.ConvertTypeToCsharpSource(typeof(T)), @"> _b) => - //{ - // ", Meta.ConvertTypeToCsharpSource(typeof(T)), " a_mean = Compute<", Meta.ConvertTypeToCsharpSource(typeof(T)), @">.Mean(_a); - // ", Meta.ConvertTypeToCsharpSource(typeof(T)), " b_mean = Compute<", Meta.ConvertTypeToCsharpSource(typeof(T)), @">.Mean(_b); - // List<", Meta.ConvertTypeToCsharpSource(typeof(T)), "> a_temp = new List_Linked<", Meta.ConvertTypeToCsharpSource(typeof(T)), @">(); - // _a((", Meta.ConvertTypeToCsharpSource(typeof(T)), @" i) => { a_temp.Add(i - b_mean); }); - // List<", Meta.ConvertTypeToCsharpSource(typeof(T)), "> b_temp = new List_Linked<", Meta.ConvertTypeToCsharpSource(typeof(T)), @">(); - // _b((", Meta.ConvertTypeToCsharpSource(typeof(T)), @" i) => { b_temp.Add(i - a_mean); }); - // ", Meta.ConvertTypeToCsharpSource(typeof(T)), "[] a_cross_b = new ", Meta.ConvertTypeToCsharpSource(typeof(T)), @"[a_temp.Count * b_temp.Count]; - // int count = 0; - // a_temp.Stepper((", Meta.ConvertTypeToCsharpSource(typeof(T)), @" i_a) => - // { - // b_temp.Stepper((", Meta.ConvertTypeToCsharpSource(typeof(T)), @" i_b) => - // { - // a_cross_b[count++] = i_a * i_b; - // }); - // }); - // a_temp.Stepper((ref ", Meta.ConvertTypeToCsharpSource(typeof(T)), @" i) => { i *= i; }); - // b_temp.Stepper((ref ", Meta.ConvertTypeToCsharpSource(typeof(T)), @" i) => { i *= i; }); - // ", Meta.ConvertTypeToCsharpSource(typeof(T)), @" sum_a_cross_b = 0; - // foreach (", Meta.ConvertTypeToCsharpSource(typeof(T)), @" i in a_cross_b) - // sum_a_cross_b += i; - // ", Meta.ConvertTypeToCsharpSource(typeof(T)), @" sum_a_temp = 0; - // a_temp.Stepper((", Meta.ConvertTypeToCsharpSource(typeof(T)), @" i) => { sum_a_temp += i; }); - // ", Meta.ConvertTypeToCsharpSource(typeof(T)), @" sum_b_temp = 0; - // b_temp.Stepper((", Meta.ConvertTypeToCsharpSource(typeof(T)), @" i) => { sum_b_temp += i; }); - // return sum_a_cross_b / Compute<", Meta.ConvertTypeToCsharpSource(typeof(T)), @">.sqrt(sum_a_temp * sum_b_temp); - //}")); - - // return Compute.Correlation_internal(a, b); - // }; - - // public static T Correlation(Stepper a, Stepper b) - // { - // return Correlation_internal(a, b); - // } - #endregion - - #region Exponential - - /// Computes the exponentional of a value [e ^ ]. - /// The generic type of the operation. - /// The value to compute the exponentional of. - /// The exponential of the value [e ^ ]. - public static T Exponential(T a) - { - throw new NotImplementedException(); - } - - #endregion - - #region NaturalLogarithm - - /// Computes the natural logarithm of a value [ln()]. - /// The generic type of the operation. - /// The value to compute the natural log of. - /// The natural log of the provided value [ln()]. - public static T NaturalLogarithm(T a) => - NaturalLogarithmImplementation.Function(a); - - internal static class NaturalLogarithmImplementation - { - internal static Func Function = a => - { - // optimization for specific known types - if (TypeDescriptor.GetConverter(typeof(T)).CanConvertTo(typeof(double))) - { - ParameterExpression A = Expression.Parameter(typeof(T)); - MethodInfo? Math_Log = typeof(Math).GetMethod("Log"); - if (Math_Log is not null) - { - Expression BODY = Expression.Call(Math_Log, A); - Function = Expression.Lambda>(BODY, A).Compile(); - return Function(a); - } - } - throw new NotImplementedException(); - }; - } - - #endregion - - #region Trigonometry Functions - - #region Sine - - /// Computes the sine ratio of an angle using the relative talor series. Accurate but slow. - /// The numeric type of the operation. - /// The angle to compute the sine ratio of. - /// Determines if coputation should continue or is accurate enough. - /// The taylor series computed sine ratio of the provided angle. - public static T SineTaylorSeries(Angle a, Predicate? predicate = null) - { - // Series: sine(x) = x - (x^3 / 3!) + (x^5 / 5!) - (x^7 / 7!) + (x^9 / 9!) + ... - // more terms in computation inproves accuracy - - // Note: there is room for optimization (custom runtime compilation) - - T x = a[Angle.Units.Radians]; - T sine = x; - T previous; - bool isAddTerm = false; - T i = Constant.Three; - T xSquared = Multiplication(x, x); - T xRunningPower = x; - T xRunningFactorial = Constant.One; - do - { - xRunningPower = Multiplication(xRunningPower, xSquared); - xRunningFactorial = Multiplication(xRunningFactorial, Multiplication(i, Subtraction(i, Constant.One))); - previous = sine; - if (isAddTerm) - { - sine = Addition(sine, Division(xRunningPower, xRunningFactorial)); - } - else - { - sine = Subtraction(sine, Division(xRunningPower, xRunningFactorial)); - } - isAddTerm = !isAddTerm; - i = Addition(i, Constant.Two); - } while (Inequate(sine, previous) && (predicate is null || !predicate(sine))); - return sine; - } - - /// Computes the sine ratio of an angle using the system's sine function. WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). - /// The numeric type of the operation. - /// The angle to compute the sine ratio of. - /// The sine ratio of the provided angle. - /// WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). - public static T SineSystem(Angle a) - { - T b = a[Angle.Units.Radians]; - double c = Convert(b); - double d = Math.Sin(c); - T e = Convert(d); - return e; - } - - /// Estimates the sine ratio using piecewise quadratic equations. Fast but NOT very accurate. - /// The numeric type of the operation. - /// The angle to compute the quadratic estimated sine ratio of. - /// The quadratic estimation of the sine ratio of the provided angle. - public static T SineQuadratic(Angle a) - { - // Piecewise Functions: - // y = (-4/π^2)(x - (π/2))^2 + 1 - // y = (4/π^2)(x - (3π/2))^2 - 1 - - T adjusted = Remainder(a[Angle.Units.Radians], Constant.Pi2); - if (IsNegative(adjusted)) - { - adjusted = Addition(adjusted, Constant.Pi2); - } - if (LessThan(adjusted, Constant.Pi)) - { - T xMinusPiOver2 = Subtraction(adjusted, Constant.PiOver2); - T xMinusPiOver2Squared = Multiplication(xMinusPiOver2, xMinusPiOver2); - return Addition(Multiplication(Constant.Negative4OverPiSquared, xMinusPiOver2Squared), Constant.One); - } - else - { - T xMinus3PiOver2 = Subtraction(adjusted, Constant.Pi3Over2); - T xMinus3PiOver2Squared = Multiplication(xMinus3PiOver2, xMinus3PiOver2); - return Subtraction(Multiplication(Constant.FourOverPiSquared, xMinus3PiOver2Squared), Constant.One); - } - } - - #endregion - - #region Cosine - - /// Computes the cosine ratio of an angle using the relative talor series. Accurate but slow. - /// The numeric type of the operation. - /// The angle to compute the cosine ratio of. - /// Determines if coputation should continue or is accurate enough. - /// The taylor series computed cosine ratio of the provided angle. - public static T CosineTaylorSeries(Angle a, Predicate? predicate = null) - { - // Series: cosine(x) = 1 - (x^2 / 2!) + (x^4 / 4!) - (x^6 / 6!) + (x^8 / 8!) - ... - // more terms in computation inproves accuracy - - // Note: there is room for optimization (custom runtime compilation) - - T x = a[Angle.Units.Radians]; - T cosine = Constant.One; - T previous; - T xSquared = Multiplication(x, x); - T xRunningPower = Constant.One; - T xRunningFactorial = Constant.One; - bool isAddTerm = false; - T i = Constant.Two; - do - { - xRunningPower = Multiplication(xRunningPower, xSquared); - xRunningFactorial = Multiplication(xRunningFactorial, Multiplication(i, Subtraction(i, Constant.One))); - previous = cosine; - if (isAddTerm) - { - cosine = Addition(cosine, Division(xRunningPower, xRunningFactorial)); - } - else - { - cosine = Subtraction(cosine, Division(xRunningPower, xRunningFactorial)); - } - isAddTerm = !isAddTerm; - i = Addition(i, Constant.Two); - } while (Inequate(cosine, previous) && (predicate is null || !predicate(cosine))); - return cosine; - } - - /// Computes the cosine ratio of an angle using the system's cosine function. WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). - /// The numeric type of the operation. - /// The angle to compute the cosine ratio of. - /// The cosine ratio of the provided angle. - /// WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). - public static T CosineSystem(Angle a) - { - T b = a[Angle.Units.Radians]; - double c = Convert(b); - double d = Math.Cos(c); - T e = Convert(d); - return e; - } - - /// Estimates the cosine ratio using piecewise quadratic equations. Fast but NOT very accurate. - /// The numeric type of the operation. - /// The angle to compute the quadratic estimated cosine ratio of. - /// The quadratic estimation of the cosine ratio of the provided angle. - public static T CosineQuadratic(Angle a) - { - Angle piOver2Radians = new Angle(Constant.PiOver2, Angle.Units.Radians); - return SineQuadratic(a - piOver2Radians); - } - - #endregion - - #region Tangent - - /// Computes the tangent ratio of an angle using the relative talor series. Accurate but slow. - /// The numeric type of the operation. - /// The angle to compute the tangent ratio of. - /// The taylor series computed tangent ratio of the provided angle. - public static T TangentTaylorSeries(Angle a) - { - return Division(SineTaylorSeries(a), CosineTaylorSeries(a)); - } - - /// Computes the tangent ratio of an angle using the system's tangent function. WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). - /// The numeric type of the operation. - /// The angle to compute the tangent ratio of. - /// The tangent ratio of the provided angle. - /// WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). - public static T TangentSystem(Angle a) - { - T b = a[Angle.Units.Radians]; - double c = Convert(b); - double d = Math.Tan(c); - T e = Convert(d); - return e; - } - - /// Estimates the tangent ratio using piecewise quadratic equations. Fast but NOT very accurate. - /// The numeric type of the operation. - /// The angle to compute the quadratic estimated tangent ratio of. - /// The quadratic estimation of the tangent ratio of the provided angle. - public static T TangentQuadratic(Angle a) - { - return Division(SineQuadratic(a), CosineQuadratic(a)); - } - - #endregion - - #region Cosecant - - /// Computes the cosecant ratio of an angle using the system's sine function. WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). - /// The numeric type of the operation. - /// The angle to compute the cosecant ratio of. - /// The cosecant ratio of the provided angle. - /// WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). - public static T CosecantSystem(Angle a) - { - return Division(Constant.One, SineSystem(a)); - } - - /// Estimates the cosecant ratio using piecewise quadratic equations. Fast but NOT very accurate. - /// The numeric type of the operation. - /// The angle to compute the quadratic estimated cosecant ratio of. - /// The quadratic estimation of the cosecant ratio of the provided angle. - public static T CosecantQuadratic(Angle a) - { - return Division(Constant.One, SineQuadratic(a)); - } - - #endregion - - #region Secant - - /// Computes the secant ratio of an angle using the system's cosine function. WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). - /// The numeric type of the operation. - /// The angle to compute the secant ratio of. - /// The secant ratio of the provided angle. - /// WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). - public static T SecantSystem(Angle a) - { - return Division(Constant.One, CosineSystem(a)); - } - - /// Estimates the secant ratio using piecewise quadratic equations. Fast but NOT very accurate. - /// The numeric type of the operation. - /// The angle to compute the quadratic estimated secant ratio of. - /// The quadratic estimation of the secant ratio of the provided angle. - public static T SecantQuadratic(Angle a) - { - return Division(Constant.One, CosineQuadratic(a)); - } - - #endregion - - #region Cotangent - - /// Computes the cotangent ratio of an angle using the system's tangent function. WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). - /// The numeric type of the operation. - /// The angle to compute the cotangent ratio of. - /// The cotangent ratio of the provided angle. - /// WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). - public static T CotangentSystem(Angle a) - { - return Division(Constant.One, TangentSystem(a)); - } - - /// Estimates the cotangent ratio using piecewise quadratic equations. Fast but NOT very accurate. - /// The numeric type of the operation. - /// The angle to compute the quadratic estimated cotangent ratio of. - /// The quadratic estimation of the cotangent ratio of the provided angle. - public static T CotangentQuadratic(Angle a) - { - return Division(Constant.One, TangentQuadratic(a)); - } - - #endregion - - #region InverseSine - - //public static Angle InverseSine(T a) - //{ - // return InverseSineImplementation.Function(a); - //} - - //internal static class InverseSineImplementation - //{ - // internal static Func> Function = a => - // { - // // optimization for specific known types - // if (TypeDescriptor.GetConverter(typeof(T)).CanConvertTo(typeof(double))) - // { - // ParameterExpression A = Expression.Parameter(typeof(T)); - // Expression BODY = Expression.Call(typeof(Angle).GetMethod(nameof(Angle.Factory_Radians), BindingFlags.Static), Expression.Call(typeof(Math).GetMethod(nameof(Math.Asin)), A)); - // Function = Expression.Lambda>>(BODY, A).Compile(); - // return Function(a); - // } - // throw new NotImplementedException(); - // }; - //} - - #endregion - - #region InverseCosine - - //public static Angle InverseCosine(T a) - //{ - // return InverseCosineImplementation.Function(a); - //} - - //internal static class InverseCosineImplementation - //{ - // internal static Func> Function = a => - // { - // // optimization for specific known types - // if (TypeDescriptor.GetConverter(typeof(T)).CanConvertTo(typeof(double))) - // { - // ParameterExpression A = Expression.Parameter(typeof(T)); - // Expression BODY = Expression.Call(typeof(Angle).GetMethod(nameof(Angle.Factory_Radians), BindingFlags.Static), Expression.Call(typeof(Math).GetMethod(nameof(Math.Acos)), A)); - // Function = Expression.Lambda>>(BODY, A).Compile(); - // return Function(a); - // } - // throw new NotImplementedException(); - // }; - //} - - #endregion - - #region InverseTangent - - //public static Angle InverseTangent(T a) - //{ - // return InverseTangentImplementation.Function(a); - //} - - //internal static class InverseTangentImplementation - //{ - // internal static Func> Function = a => - // { - // // optimization for specific known types - // if (TypeDescriptor.GetConverter(typeof(T)).CanConvertTo(typeof(double))) - // { - // ParameterExpression A = Expression.Parameter(typeof(T)); - // Expression BODY = Expression.Call(typeof(Angle).GetMethod(nameof(Angle.Factory_Radians), BindingFlags.Static), Expression.Call(typeof(Math).GetMethod(nameof(Math.Atan)), A)); - // Function = Expression.Lambda>>(BODY, A).Compile(); - // return Function(a); - // } - // throw new NotImplementedException(); - // }; - //} - - #endregion - - #region InverseCosecant - - //public static Angle InverseCosecant(T a) - //{ - // return Angle.Factory_Radians(Divide(Constant.One, InverseSine(a).Radians)); - //} - - #endregion - - #region InverseSecant - - //public static Angle InverseSecant(T a) - //{ - // return Angle.Factory_Radians(Divide(Constant.One, InverseCosine(a).Radians)); - //} - - #endregion - - #region InverseCotangent - - //public static Angle InverseCotangent(T a) - //{ - // return Angle.Factory_Radians(Divide(Constant.One, InverseTangent(a).Radians)); - //} - - #endregion - - #region HyperbolicSine - - //public static T HyperbolicSine(Angle a) - //{ - // return HyperbolicSineImplementation.Function(a); - //} - - //internal static class HyperbolicSineImplementation - //{ - // internal static Func, T> Function = (Angle a) => - // { - // // optimization for specific known types - // if (TypeDescriptor.GetConverter(typeof(T)).CanConvertTo(typeof(double))) - // { - // ParameterExpression A = Expression.Parameter(typeof(T)); - // Expression BODY = Expression.Call(typeof(Math).GetMethod(nameof(Math.Sinh)), Expression.Convert(Expression.Property(A, typeof(Angle).GetProperty(nameof(a.Radians))), typeof(double))); - // Function = Expression.Lambda, T>>(BODY, A).Compile(); - // return Function(a); - // } - // throw new NotImplementedException(); - // }; - //} - - #endregion - - #region HyperbolicCosine - - //public static T HyperbolicCosine(Angle a) - //{ - // return HyperbolicCosineImplementation.Function(a); - //} - - //internal static class HyperbolicCosineImplementation - //{ - // internal static Func, T> Function = (Angle a) => - // { - // // optimization for specific known types - // if (TypeDescriptor.GetConverter(typeof(T)).CanConvertTo(typeof(double))) - // { - // ParameterExpression A = Expression.Parameter(typeof(T)); - // Expression BODY = Expression.Call(typeof(Math).GetMethod(nameof(Math.Cosh)), Expression.Convert(Expression.Property(A, typeof(Angle).GetProperty(nameof(a.Radians))), typeof(double))); - // Function = Expression.Lambda, T>>(BODY, A).Compile(); - // return Function(a); - // } - // throw new NotImplementedException(); - // }; - //} - - #endregion - - #region HyperbolicTangent - - //public static T HyperbolicTangent(Angle a) - //{ - // return HyperbolicTangentImplementation.Function(a); - //} - - //internal static class HyperbolicTangentImplementation - //{ - // internal static Func, T> Function = (Angle a) => - // { - // // optimization for specific known types - // if (TypeDescriptor.GetConverter(typeof(T)).CanConvertTo(typeof(double))) - // { - // ParameterExpression A = Expression.Parameter(typeof(T)); - // Expression BODY = Expression.Call(typeof(Math).GetMethod(nameof(Math.Tanh)), Expression.Convert(Expression.Property(A, typeof(Angle).GetProperty(nameof(a.Radians))), typeof(double))); - // Function = Expression.Lambda, T>>(BODY, A).Compile(); - // return Function(a); - // } - // throw new NotImplementedException(); - // }; - //} - - #endregion - - #region HyperbolicCosecant - - //public static T HyperbolicCosecant(Angle a) - //{ - // return Divide(Constant.One, HyperbolicSine(a)); - //} - - #endregion - - #region HyperbolicSecant - - //public static T HyperbolicSecant(Angle a) - //{ - // return Divide(Constant.One, HyperbolicCosine(a)); - //} - - #endregion - - #region HyperbolicCotangent - - //public static T HyperbolicCotangent(Angle a) - //{ - // return Divide(Constant.One, HyperbolicTangent(a)); - //} - - #endregion - - #region InverseHyperbolicSine - - public static Angle InverseHyperbolicSine(T a) - { - throw new NotImplementedException(); - } - - #endregion - - #region InverseHyperbolicCosine - - public static Angle InverseHyperbolicCosine(T a) - { - throw new NotImplementedException(); - } - - #endregion - - #region InverseHyperbolicTangent - - public static Angle InverseHyperbolicTangent(T a) - { - throw new NotImplementedException(); - } - - #endregion - - #region InverseHyperbolicCosecant - - public static Angle InverseHyperbolicCosecant(T a) - { - throw new NotImplementedException(); - } - - #endregion - - #region InverseHyperbolicSecant - - public static Angle InverseHyperbolicSecant(T a) - { - throw new NotImplementedException(); - } - - #endregion - - #region InverseHyperbolicCotangent - - public static Angle InverseHyperbolicCotangent(T a) - { - throw new NotImplementedException(); - } - - #endregion - - #endregion - - #region LinearRegression2D - - /// Computes the best fit line from a set of points in 2D space [y = slope * x + y_intercept]. - /// The numeric type of the operation. - /// The points to compute the best fit line of. - /// The slope of the computed best fit line [y = slope * x + y_intercept]. - /// The y intercept of the computed best fit line [y = slope * x + y_intercept]. - public static void LinearRegression2D(Action> points, out T slope, out T y_intercept) - { - _ = points ?? throw new ArgumentNullException(nameof(points)); - int count = 0; - T sumx = Constant.Zero; - T sumy = Constant.Zero; - points((T x, T y) => - { - sumx = Addition(sumx, x); - sumy = Addition(sumy, y); - count++; - }); - if (count < 2) - { - throw new MathematicsException("At least 3 points must be provided for linear regressions"); - } - T tcount = Convert(count); - T meanx = Division(sumx, tcount); - T meany = Division(sumy, tcount); - T variancex = Constant.Zero; - T variancey = Constant.Zero; - points((T x, T y) => - { - T offset = Subtraction(x, meanx); - variancey = Addition(variancey, Multiplication(offset, Subtraction(y, meany))); - variancex = Addition(variancex, Multiplication(offset, offset)); - }); - slope = Division(variancey, variancex); - y_intercept = Subtraction(meany, Multiplication(slope, meanx)); - } - - #endregion - - #region FactorPrimes - - /// Factors the primes numbers of a numeric integer value. - /// The numeric type of the operation. - /// The value to factor the prime numbers of. - /// The action to perform on all found prime factors. - public static void FactorPrimes(T a, Action step) => - FactorPrimesImplementation.Function(a, step); - - internal static class FactorPrimesImplementation - { - internal static Action> Function = (a, x) => - { - Function = (A, step) => - { - if (!IsInteger(A)) - { - throw new ArgumentOutOfRangeException(nameof(A), A, "!(" + nameof(A) + "." + nameof(IsInteger) + ")"); - } - if (IsNegative(A)) - { - A = AbsoluteValue(A); - step(Convert(-1)); - } - while (IsEven(A)) - { - step(Constant.Two); - A = Division(A, Constant.Two); - } - for (T i = Constant.Three; LessThanOrEqual(i, SquareRoot(A)); i = Addition(i, Constant.Two)) - { - while (Equate(Remainder(A, i), Constant.Zero)) - { - step(i); - A = Division(A, i); - } - } - if (GreaterThan(A, Constant.Two)) - { - step(A); - } - }; - Function(a, x); - }; - } - - #endregion - - #region Hamming Distance - - /// Computes the Hamming distance (using an iterative algorithm). - /// The element type of the sequences. - /// The get index function for the first sequence. - /// The get index function for the second sequence. - /// The equality check function. - /// The length of the sequences. - /// The get index function for the first sequence. - /// The get index function for the second sequence. - /// The equality check function. - /// The computed Hamming distance of the two sequences. - public static int HammingDistance( - int length, - GetA a = default, - GetB b = default, - Equals equals = default) - where GetA : struct, IFunc - where GetB : struct, IFunc - where Equals : struct, IFunc - { - if (length < 0) - { - throw new ArgumentOutOfRangeException(nameof(length), length, $@"{nameof(length)} < 0"); - } - int distance = 0; - for (int i = 0; i < length; i++) - { - if (!equals.Do(a.Do(i), b.Do(i))) - { - distance++; - } - } - return distance; - } - - /// Computes the Hamming distance (using an recursive algorithm). - /// The first sequence of the operation. - /// The second sequence of the operation. - /// The computed Hamming distance of the two sequences. - public static int HammingDistance(ReadOnlySpan a, ReadOnlySpan b) => - HammingDistance(a, b); - - /// Computes the Hamming distance (using an recursive algorithm). - /// The element type of the sequences. - /// The equality check function. - /// The first sequence. - /// The second sequence. - /// The equality check function. - /// The computed Hamming distance of the two sequences. - public static int HammingDistance( - ReadOnlySpan a, - ReadOnlySpan b, - Equals equals = default) - where Equals : struct, IFunc - { - if (a.Length != b.Length) - { - throw new ArgumentException($@"{nameof(a)}.{nameof(a.Length)} ({a.Length}) != {nameof(b)}.{nameof(b.Length)} ({b.Length})"); - } - int distance = 0; - for (int i = 0; i < a.Length; i++) - { - if (!equals.Do(a[i], b[i])) - { - distance++; - } - } - return distance; - } - - #endregion - - #region Levenshtein distance - - /// Computes the Levenshtein distance (using an recursive algorithm). - /// The element type of the sequences. - /// The get index function for the first sequence. - /// The get index function for the second sequence. - /// The equality check function. - /// The length of the first sequence. - /// The length of the second sequence. - /// The get index function for the first sequence. - /// The get index function for the second sequence. - /// The equality check function. - /// The computed Levenshtein distance of the two sequences. - public static int LevenshteinDistanceRecursive( - int a_length, - int b_length, - GetA a = default, - GetB b = default, - Equals equals = default) - where GetA : struct, IFunc - where GetB : struct, IFunc - where Equals : struct, IFunc - { - if (a_length < 0) - { - throw new ArgumentOutOfRangeException(nameof(a_length), a_length, $@"{nameof(a_length)} < 0"); - } - if (b_length < 0) - { - throw new ArgumentOutOfRangeException(nameof(b_length), b_length, $@"{nameof(b_length)} < 0"); - } - int LDR(int ai, int bi) - { - int _ai = ai + 1; - int _bi = bi + 1; - return - ai >= a_length ? - bi >= b_length ? 0 : - 1 + LDR(ai, _bi) : - bi >= b_length ? 1 + LDR(_ai, bi) : - equals.Do(a.Do(ai), b.Do(bi)) ? LDR(_ai, _bi) : - 1 + Minimum(LDR(ai, _bi), LDR(_ai, bi), LDR(_ai, _bi)); - } - return LDR(0, 0); - } - - /// Computes the Levenshtein distance (using an recursive algorithm). - /// The first sequence of the operation. - /// The second sequence of the operation. - /// The computed Levenshtein distance of the two sequences. - public static int LevenshteinDistanceRecursive(ReadOnlySpan a, ReadOnlySpan b) => - LevenshteinDistanceRecursive(a, b); - - /// Computes the Levenshtein distance (using an recursive algorithm). - /// The element type of the sequences. - /// The equality check function. - /// The first sequence. - /// The second sequence. - /// The equality check function. - /// The computed Levenshtein distance of the two sequences. - public static int LevenshteinDistanceRecursive( - ReadOnlySpan a, - ReadOnlySpan b, - Equals equals = default) - where Equals : struct, IFunc - { - int LDR( - ReadOnlySpan a, - ReadOnlySpan b, - int ai, int bi) - { - int _ai = ai + 1; - int _bi = bi + 1; - return - ai >= a.Length ? - bi >= b.Length ? 0 : - 1 + LDR(a, b, ai, _bi) : - bi >= b.Length ? 1 + LDR(a, b, _ai, bi) : - equals.Do(a[ai], b[bi]) ? LDR(a, b, _ai, _bi) : - 1 + Minimum(LDR(a, b, ai, _bi), LDR(a, b, _ai, bi), LDR(a, b, _ai, _bi)); - } - return LDR(a, b, 0, 0); - } - - /// Computes the Levenshtein distance (using an iterative algorithm). - /// The element type of the sequences. - /// The get index function for the first sequence. - /// The get index function for the second sequence. - /// The equality check function. - /// The length of the first sequence. - /// The length of the second sequence. - /// The get index function for the first sequence. - /// The get index function for the second sequence. - /// The equality check function. - /// The computed Levenshtein distance of the two sequences. - public static int LevenshteinDistanceIterative( - int a_length, - int b_length, - GetA a = default, - GetB b = default, - Equals equals = default) - where GetA : struct, IFunc - where GetB : struct, IFunc - where Equals : struct, IFunc - { - if (a_length < 0) - { - throw new ArgumentOutOfRangeException(nameof(a_length), a_length, $@"{nameof(a_length)} < 0"); - } - if (b_length < 0) - { - throw new ArgumentOutOfRangeException(nameof(b_length), b_length, $@"{nameof(b_length)} < 0"); - } - a_length++; - b_length++; - int[,] matrix = new int[a_length, b_length]; - for (int i = 1; i < a_length; i++) - { - matrix[i, 0] = i; - } - for (int i = 1; i < b_length; i++) - { - matrix[0, i] = i; - } - for (int bi = 1; bi < b_length; bi++) - { - for (int ai = 1; ai < a_length; ai++) - { - int _ai = ai - 1; - int _bi = bi - 1; - matrix[ai, bi] = Minimum( - matrix[_ai, bi] + 1, - matrix[ai, _bi] + 1, - !equals.Do(a.Do(_ai), b.Do(_bi)) ? matrix[_ai, _bi] + 1 : matrix[_ai, _bi]); - } - } - return matrix[a_length - 1, b_length - 1]; - } - - /// Computes the Levenshtein distance (using an iterative algorithm). - /// The first sequence of the operation. - /// The second sequence of the operation. - /// The computed Levenshtein distance of the two sequences. - public static int LevenshteinDistanceIterative(ReadOnlySpan a, ReadOnlySpan b) => - LevenshteinDistanceIterative(a, b); - - /// Computes the Levenshtein distance (using an iterative algorithm). - /// The element type of the sequences. - /// The equality check function. - /// The first sequence. - /// The second sequence. - /// The equality check function. - /// The computed Levenshtein distance of the two sequences. - public static int LevenshteinDistanceIterative( - ReadOnlySpan a, - ReadOnlySpan b, - Equals equals = default) - where Equals : struct, IFunc - { - int a_length = a.Length + 1; - int b_length = b.Length + 1; - int[,] matrix = new int[a_length, b_length]; - for (int i = 1; i < a_length; i++) - { - matrix[i, 0] = i; - } - for (int i = 1; i < b_length; i++) - { - matrix[0, i] = i; - } - for (int bi = 1; bi < b_length; bi++) - { - for (int ai = 1; ai < a_length; ai++) - { - int _ai = ai - 1; - int _bi = bi - 1; - matrix[ai, bi] = Minimum( - matrix[_ai, bi] + 1, - matrix[ai, _bi] + 1, - !equals.Do(a[_ai], b[_bi]) ? matrix[_ai, _bi] + 1 : matrix[_ai, _bi]); - } - } - return matrix[a_length - 1, b_length - 1]; - } - - #endregion - - #region Permute - - #region XML - -#pragma warning disable CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name -#pragma warning disable CS1572 // XML comment has a param tag, but there is no parameter by that name - /// The generic element type of the indexed collection. - /// The action to perform on each permutation. - /// The status checker for cancellation. - /// The get index operation of the collection. - /// The set index operation of the collection. - /// The starting index of the values to permute. - /// The ending index of the values to permute. - /// The action to perform on each permutation. - /// The status checker for cancellation. - /// The get index operation of the collection. - /// The set index operation of the collection. - /// The array to iterate the permutations of. - /// The list to iterate the permutations of. - /// The span of the permutation. - [Obsolete(TowelConstants.NotIntended, true)] - internal static void PermuteXML() => throw new DocumentationMethodException(); - /// Iterates through all the permutations of an indexed collection (using a recursive algorithm). - /// - [Obsolete(TowelConstants.NotIntended, true)] - internal static void PermuteRecursive_XML() => throw new DocumentationMethodException(); - /// Iterates through all the permutations of an indexed collection (using an iterative algorithm). - /// - [Obsolete(TowelConstants.NotIntended, true)] - internal static void PermuteIterative_XML() => throw new DocumentationMethodException(); -#pragma warning restore CS1572 // XML comment has a param tag, but there is no parameter by that name -#pragma warning restore CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name - - #endregion - - /// - public static void PermuteRecursive(int start, int end, Action action, Func get, Action set) => - PermuteRecursive, ActionRuntime>(start, end, action, default, get, set); - - /// - public static void PermuteRecursive(int start, int end, Action action, Func status, Func get, Action set) => - PermuteRecursive, FuncRuntime, ActionRuntime>(start, end, action, status, get, set); - - /// - public static void PermuteRecursive(int start, int end, Action action = default, Get get = default, Set set = default) - where Action : struct, IAction - where Get : struct, IFunc - where Set : struct, IAction => - PermuteRecursive(start, end, action, default, get, set); - - /// - public static void PermuteRecursive(int start, int end, Action action = default, Status status = default, Get get = default, Set set = default) - where Action : struct, IAction - where Status : struct, IFunc - where Get : struct, IFunc - where Set : struct, IAction - { - Permute(start, end); - StepStatus Permute(int a, int b) - { - if (a == b) - { - action.Do(); - return status.Do(); - } - for (int i = a; i <= b; i++) - { - Swap(a, i); - if (Permute(a + 1, b) is Break) - { - return Break; - } - Swap(a, i); - } - return Continue; - } - void Swap(int a, int b) - { - T temp = get.Do(a); - set.Do(a, get.Do(b)); - set.Do(b, temp); - } - } - - /// - public static void PermuteRecursive(Span span, Action action) => - PermuteRecursive(span, action); - - /// - public static void PermuteRecursive(Span span, Action action = default) - where Action : struct, IAction => - PermuteRecursive(span, action); - - /// - public static void PermuteRecursive(Span span, Action action, Status status = default) - where Status : struct, IFunc => - PermuteRecursive(span, action, status); - - /// - public static void PermuteRecursive(Span span, Action action = default, Status status = default) - where Action : struct, IAction - where Status : struct, IFunc - { - Permute(span, 0, span.Length - 1); - StepStatus Permute(Span span, int a, int b) - { - if (a == b) - { - action.Do(); - return status.Do(); - } - for (int i = a; i <= b; i++) - { - Swap(span, a, i); - if (Permute(span, a + 1, b) is Break) - { - return Break; - } - Swap(span, a, i); - } - return Continue; - } - static void Swap(Span span, int a, int b) - { - T temp = span[a]; - span[a] = span[b]; - span[b] = temp; - } - } - - /// - public static void PermuteIterative(int start, int end, Action action, Func get, Action set) => - PermuteIterative, ActionRuntime>(start, end, action, default, get, set); - - /// - public static void PermuteIterative(int start, int end, Action action, Func status, Func get, Action set) => - PermuteIterative, FuncRuntime, ActionRuntime>(start, end, action, status, get, set); - - /// - public static void PermuteIterative(int start, int end, Action action = default, Get get = default, Set set = default) - where Action : struct, IAction - where Get : struct, IFunc - where Set : struct, IAction => - PermuteIterative(start, end, action, default, get, set); - - /// - public static void PermuteIterative(int start, int end, Action action = default, Status status = default, Get get = default, Set set = default) - where Action : struct, IAction - where Status : struct, IFunc - where Get : struct, IFunc - where Set : struct, IAction - { - action.Do(); - int[] indeces = new int[end + 2 - start]; - for (int i = 0; i < indeces.Length; i++) - { - indeces[i] = i; - } - for (int i = start + 1; i < end + 1 && status.Do() is Continue; action.Do()) - { - indeces[i]--; - Swap(i, i % 2 == 1 ? indeces[i] : 0); - for (i = 1; indeces[i] == 0; i++) - { - indeces[i] = i; - } - } - void Swap(int a, int b) - { - T temp = get.Do(a); - set.Do(a, get.Do(b)); - set.Do(b, temp); - } - } - - /// - public static void PermuteIterative(Span span, Action action) => - PermuteIterative(span, action); - - /// - public static void PermuteIterative(Span span, Action action = default) - where Action : struct, IAction => - PermuteIterative(span, action); - - /// - public static void PermuteIterative(Span span, Action action, Status status = default) - where Status : struct, IFunc => - PermuteIterative(span, action, status); - - /// - public static void PermuteIterative(Span span, Action action = default, Status status = default) - where Action : struct, IAction - where Status : struct, IFunc - { - action.Do(); - int[] indeces = new int[span.Length - 1 + 2]; - for (int i = 0; i < indeces.Length; i++) - { - indeces[i] = i; - } - for (int i = 1; i < span.Length && status.Do() is Continue; action.Do()) - { - indeces[i]--; - Swap(span, i, i % 2 == 1 ? indeces[i] : 0); - for (i = 1; indeces[i] == 0; i++) - { - indeces[i] = i; - } - } - static void Swap(Span span, int a, int b) - { - T temp = span[a]; - span[a] = span[b]; - span[b] = temp; - } - } - - #endregion - - #region SearchBinary - -#pragma warning disable CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name -#pragma warning disable CS1572 // XML comment has a param tag, but there is no parameter by that name -#pragma warning disable CS1734 // XML comment has a paramref tag, but there is no parameter by that name -#pragma warning disable CS1735 // XML comment has a typeparamref tag, but there is no type parameter by that name - /// Performs a binary search on sorted indexed data. - /// The type of elements to search through. - /// The function for getting an element at an index. - /// The function for sifting through the elements. - /// The compare function. - /// The starting index of the binary search. - /// The number of elements to be searched after the starting . - /// The function for getting an element at an index. - /// The function for comparing the the elements to th desired target. - /// The array search. - /// The element to search for. - /// The compare function. - /// The span of the binary search. - /// - /// ( Found, Index, Value) - /// - Found: True if a match was found; False if not. - /// - Index: The resulting index of the search that will always be <= the desired match. - /// - Value: The resulting value of the binary search if a match was found or default if not. - /// - [Obsolete(TowelConstants.NotIntended, true)] - internal static void SearchBinary_XML() => throw new DocumentationMethodException(); -#pragma warning restore CS1735 // XML comment has a typeparamref tag, but there is no type parameter by that name -#pragma warning restore CS1734 // XML comment has a paramref tag, but there is no parameter by that name -#pragma warning restore CS1572 // XML comment has a param tag, but there is no parameter by that name -#pragma warning restore CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name - - #if false // keeping this for future reference; array types are supports by the ReadOnlySpan overloads - - /// - public static (bool Found, int Index, T Value) SearchBinary(T[] array, T element, Func compare = default) - { - _ = array ?? throw new ArgumentNullException(nameof(array)); - return SearchBinary, SiftFromCompareAndValue>>(0, array.Length, array, new SiftFromCompareAndValue>(element, compare ?? Compare)); - } - - /// - public static (bool Found, int Index, T Value) SearchBinary(T[] array, T element, Compare compare = default) - where Compare : IFunc - { - _ = array ?? throw new ArgumentNullException(nameof(array)); - return SearchBinary, SiftFromCompareAndValue>(0, array.Length, array, new SiftFromCompareAndValue(element, compare)); - } - - /// - public static (bool Found, int Index, T Value) SearchBinary(T[] array, Func sift) - { - _ = array ?? throw new ArgumentNullException(nameof(array)); - return SearchBinary, FuncRuntime>(0, array.Length, array, sift); - } - - /// - public static (bool Found, int Index, T Value) SearchBinary(T[] array, Sift sift = default) - where Sift : IFunc - { - _ = array ?? throw new ArgumentNullException(nameof(array)); - return SearchBinary, Sift>(0, array.Length, array, sift); - } - - #endif - - /// - public static (bool Found, int Index, T? Value) SearchBinary(int length, Func get, Func sift) - { - _ = get ?? throw new ArgumentNullException(nameof(get)); - _ = sift ?? throw new ArgumentNullException(nameof(sift)); - return SearchBinary, FuncRuntime>(0, length, get, sift); - } - - /// - public static (bool Found, int Index, T? Value) SearchBinary(int index, int length, Get get = default, Sift sift = default) - where Get : struct, IFunc - where Sift : struct, IFunc - { - if (length <= 0) - { - throw new ArgumentOutOfRangeException(nameof(length), length, "!(" + nameof(length) + " > 0)"); - } - if (index < 0) - { - throw new ArgumentOutOfRangeException(nameof(index), index, "!(" + nameof(index) + " > 0)"); - } - if (length > int.MaxValue / 2 && index > int.MaxValue / 2) - { - throw new ArgumentOutOfRangeException($"{nameof(length)} > {int.MaxValue / 2} && {nameof(index)} / {int.MaxValue / 2}", default(Exception)); - } - int low = index; - int hi = index + length - 1; - while (low <= hi) - { - int median = low + (hi - low) / 2; - T value = get.Do(median); - CompareResult compareResult = sift.Do(value); - switch (compareResult) - { - case Less: low = median + 1; break; - case Greater: hi = median - 1; break; - case Equal: return (true, median, value); - default: - throw compareResult.IsDefined() - ? (Exception)new TowelBugException($"Unhandled {nameof(CompareResult)} value: {compareResult}.") - : new ArgumentException($"Invalid {nameof(Sift)} function; an undefined {nameof(CompareResult)} was returned.", nameof(sift)); - } - } - return (false, Math.Min(low, hi), default); - } - - /// - public static (bool Found, int Index, T? Value) SearchBinary(ReadOnlySpan span, T element, Func? compare = default) => - SearchBinary>>(span, new SiftFromCompareAndValue>(element, compare ?? Compare)); - - /// - public static (bool Found, int Index, T? Value) SearchBinary(ReadOnlySpan span, Func sift) - { - _ = sift ?? throw new ArgumentNullException(nameof(sift)); - return SearchBinary>(span, sift); - } - - /// - public static (bool Found, int Index, T? Value) SearchBinary(ReadOnlySpan span, T element, Compare compare = default) - where Compare : struct, IFunc => - SearchBinary>(span, new SiftFromCompareAndValue(element, compare)); - - /// - public static (bool Found, int Index, T? Value) SearchBinary(ReadOnlySpan span, Sift sift = default) - where Sift : struct, IFunc - { - if (span.IsEmpty) - { - throw new ArgumentException($@"{nameof(span)}.{nameof(span.IsEmpty)}", nameof(span)); - } - int low = 0; - int hi = span.Length - 1; - while (low <= hi) - { - int median = low + (hi - low) / 2; - T value = span[median]; - CompareResult compareResult = sift.Do(value); - switch (compareResult) - { - case Less: low = median + 1; break; - case Greater: hi = median - 1; break; - case Equal: return (true, median, value); - default: - throw compareResult.IsDefined() - ? (Exception)new TowelBugException($"Unhandled {nameof(CompareResult)} value: {compareResult}.") - : new ArgumentException($"Invalid {nameof(Sift)} function; an undefined {nameof(CompareResult)} was returned.", nameof(sift)); - } - } - return (false, Math.Min(low, hi), default); - } - - #endregion - - #region Search Graph Algorithms - - #region Publics - - /// The status of a graph search algorithm. - public enum GraphSearchStatus - { - /// Graph search was not broken. - Continue = StepStatus.Continue, - /// Graph search was broken. - Break = StepStatus.Break, - /// Graph search found the goal. - Goal = 2, - } - - /// Syntax sugar hacks. - public static class GraphSyntax - { - /// This is a syntax sugar hack to allow implicit conversions from StepStatus to GraphSearchStatus. - public struct GraphSearchStatusStruct - { - internal readonly GraphSearchStatus Value; - /// Constructs a new graph search status. - /// The status of the graph search. - public GraphSearchStatusStruct(GraphSearchStatus value) => Value = value; - /// Converts a into a . - /// The to convert. - public static implicit operator GraphSearchStatusStruct(GraphSearchStatus value) => new GraphSearchStatusStruct(value); - /// Converts a into a . - /// The to convert. - public static implicit operator GraphSearchStatusStruct(StepStatus value) => new GraphSearchStatusStruct((GraphSearchStatus)value); - /// Converts a into a . - /// The to convert. - public static implicit operator GraphSearchStatus(GraphSearchStatusStruct value) => value.Value; - } - } - - /// Step function for all neigbors of a given node. - /// The node type of the graph being searched. - /// The node to step through all the neighbors of. - /// Step function to perform on all neighbors. - public delegate void SearchNeighbors(Node current, Action neighbors); - /// Computes the heuristic value of a given node in a graph (smaller values mean closer to goal node). - /// The node type of the graph being searched. - /// The numeric to use when performing calculations. - /// The node to compute the heuristic value of. - /// The computed heuristic value for this node. - public delegate Numeric SearchHeuristic(Node node); - /// Computes the cost of moving from the current node to a specific neighbor. - /// The node type of the graph being searched. - /// The numeric to use when performing calculations. - /// The current (starting) node. - /// The node to compute the cost of movign to. - /// The computed cost value of movign from current to neighbor. - public delegate Numeric SearchCost(Node current, Node neighbor); - /// Predicate for determining if we have reached the goal node. - /// The node type of the graph being searched. - /// The current node. - /// True if the current node is a/the goal node; False if not. - public delegate bool SearchGoal(Node current); - /// Checks the status of a graph search. - /// The node type of the search. - /// The current node of the search. - /// The status of the search. - public delegate GraphSyntax.GraphSearchStatusStruct SearchCheck(Node current); - - #endregion - - #region Internals - - internal abstract class BaseAlgorithmNode - where AlgorithmNode : BaseAlgorithmNode - { - internal AlgorithmNode? Previous; - internal Node Value; - - internal BaseAlgorithmNode(Node value, AlgorithmNode? previous = null) - { - Value = value; - Previous = previous; - } - } - - internal class BreadthFirstSearch : BaseAlgorithmNode, Node> - { - internal BreadthFirstSearch(Node value, BreadthFirstSearch? previous = null) - : base(value: value, previous: previous) { } - } - - internal class DijkstraNode : BaseAlgorithmNode, Node> - { - internal Numeric Priority; - - internal DijkstraNode(Node value, Numeric priority, DijkstraNode? previous = null) - : base(value: value, previous: previous) - { - Priority = priority; - } - } - - internal class AstarNode : BaseAlgorithmNode, Node> - { - internal Numeric Priority; - internal Numeric Cost; - - internal AstarNode(Node value, Numeric priority, Numeric cost, AstarNode? previous = null) - : base(value: value, previous: previous) - { - Priority = priority; - Cost = cost; - } - } - - internal class PathNode - { - internal Node Value; - internal PathNode? Next; - - internal PathNode(Node value, PathNode? next = null) - { - Value = value; - Next = next; - } - } - - internal static Action> BuildPath(BaseAlgorithmNode node) - where AlgorithmNode : BaseAlgorithmNode - { - PathNode? start = null; - for (BaseAlgorithmNode? current = node; current is not null; current = current.Previous) - { - PathNode? temp = start; - start = new PathNode( - value: current.Value, - next: temp); - } - return step => - { - PathNode? current = start; - while (current is not null) - { - step(current.Value); - current = current.Next; - } - }; - } - - internal struct AStarPriorityCompare : IFunc, AstarNode, CompareResult> - { - // NOTE: Typical A* implementations prioritize smaller values - public CompareResult Do(AstarNode a, AstarNode b) => - Compare(b.Priority, a.Priority); - } - - internal struct DijkstraPriorityCompare : IFunc, DijkstraNode, CompareResult> - { - // NOTE: Typical A* implementations prioritize smaller values - public CompareResult Do(DijkstraNode a, DijkstraNode b) => - Compare(b.Priority, a.Priority); - } - - #endregion - - #region Graph (Shared) - -#pragma warning disable CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name -#pragma warning disable CS1572 // XML comment has a param tag, but there is no parameter by that name - /// The node type of the graph being searched. - /// The numeric to use when performing calculations. - /// The node to start at. - /// Step function for all neigbors of a given node. - /// Computes the heuristic value of a given node in a graph. - /// Computes the cost of moving from the current node to a specific neighbor. - /// Checks the status of the search. - /// The total cost of the path if a path was found. - /// The goal of the search. - /// The graph to perform the search on. - /// Stepper of the shortest path or null if no path exists. - [Obsolete(TowelConstants.NotIntended, true)] - internal static void SearchGraph_XML() => throw new DocumentationMethodException(); -#pragma warning restore CS1572 // XML comment has a param tag, but there is no parameter by that name -#pragma warning restore CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name - - #endregion - - #region A* Algorithm - - /// Runs the A* search algorithm on a graph. - /// - [Obsolete(TowelConstants.NotIntended, true)] - internal static void Graph_Astar_XML() => throw new DocumentationMethodException(); - - /// - public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchCost cost, SearchGoal goal, out Numeric? totalCost) => - SearchGraph(start, neighbors, heuristic, cost, node => goal(node) ? GraphSearchStatus.Goal : GraphSearchStatus.Continue, out totalCost); - - /// - public static Action>? SearchGraph(Node start, IGraph graph, SearchHeuristic heuristic, SearchCost cost, SearchGoal goal, out Numeric? totalCost) => - SearchGraph(start, graph.Neighbors, heuristic, cost, goal, out totalCost); - - /// - public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchCost cost, Node goal, out Numeric? totalCost) => - SearchGraph(start, neighbors, heuristic, cost, goal, Equate, out totalCost); - - /// - public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchCost cost, Node goal, Func equate, out Numeric? totalCost) => - SearchGraph(start, neighbors, heuristic, cost, node => equate(node, goal), out totalCost); - - /// - public static Action>? SearchGraph(Node start, IGraph graph, SearchHeuristic heuristic, SearchCost cost, Node goal, out Numeric? totalCost) => - SearchGraph(start, graph, heuristic, cost, goal, Equate, out totalCost); - - /// - public static Action>? SearchGraph(Node start, IGraph graph, SearchHeuristic heuristic, SearchCost cost, Node goal, Func equate, out Numeric? totalCost) => - SearchGraph(start, graph.Neighbors, heuristic, cost, node => equate(node, goal), out totalCost); - - /// - public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchCost cost, SearchCheck check, out Numeric? totalCost) - { - // using a heap (aka priority queue) to store nodes based on their computed A* f(n) value - IHeap> fringe = new HeapArray, AStarPriorityCompare>(); - - // push starting node - fringe.Enqueue( - new AstarNode( - value: start, - priority: Constant.Zero, - cost: Constant.Zero, - previous: null)); - - // run the algorithm - while (fringe.Count != 0) - { - AstarNode current = fringe.Dequeue(); - GraphSearchStatus status = check(current.Value); - if (status is GraphSearchStatus.Break) - { - break; - } - else if (status is GraphSearchStatus.Goal) - { - totalCost = current.Cost; - return BuildPath(current); - } - else - { - neighbors(current.Value, - neighbor => - { - Numeric costValue = Addition(current.Cost, cost(current.Value, neighbor)); - fringe.Enqueue( - new AstarNode( - value: neighbor, - priority: Addition(heuristic(neighbor), costValue), - cost: costValue, - previous: current)); - }); - } - } - totalCost = default; - return null; // goal node was not reached (no path exists) - } - - #endregion - - #region Dijkstra Algorithm - - /// Runs the Dijkstra search algorithm on a graph. - /// - [Obsolete(TowelConstants.NotIntended, true)] - internal static void Graph_Dijkstra_XML() => throw new DocumentationMethodException(); - - /// - public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchGoal goal) => - SearchGraph(start, neighbors, heuristic, node => goal(node) ? GraphSearchStatus.Goal : GraphSearchStatus.Continue); - - /// - public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, Node goal) => - SearchGraph(start, neighbors, heuristic, goal, Equate); - - /// - public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, Node goal, Func equate) => - SearchGraph(start, neighbors, heuristic, node => equate(node, goal)); - - /// - public static Action>? SearchGraph(Node start, IGraph graph, SearchHeuristic heuristic, Node goal) => - SearchGraph(start, graph, heuristic, goal, Equate); - - /// - public static Action>? SearchGraph(Node start, IGraph graph, SearchHeuristic heuristic, Node goal, Func equate) => - SearchGraph(start, graph.Neighbors, heuristic, node => equate(node, goal)); - - /// - public static Action>? SearchGraph(Node start, IGraph graph, SearchHeuristic heuristic, SearchGoal goal) => - SearchGraph(start, graph.Neighbors, heuristic, goal); - - /// - public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchHeuristic heuristic, SearchCheck check) - { - // using a heap (aka priority queue) to store nodes based on their computed heuristic value - IHeap> fringe = new HeapArray, DijkstraPriorityCompare>(); - - // push starting node - fringe.Enqueue( - new DijkstraNode( - value: start, - priority: Constant.Zero, - previous: null)); - - // run the algorithm - while (fringe.Count != 0) - { - DijkstraNode current = fringe.Dequeue(); - GraphSearchStatus status = check(current.Value); - if (status is GraphSearchStatus.Break) - { - break; - } - if (status is GraphSearchStatus.Goal) - { - return BuildPath(current); - } - else - { - neighbors(current.Value, - neighbor => - { - fringe.Enqueue( - new DijkstraNode( - value: neighbor, - priority: heuristic(neighbor), - previous: current)); - }); - } - } - return null; // goal node was not reached (no path exists) - } - - #endregion - - #region BreadthFirstSearch Algorithm - - /// Runs the Breadth-First-Search search algorithm on a graph. - /// - [Obsolete(TowelConstants.NotIntended, true)] - internal static void Graph_BreadthFirstSearch_XML() => throw new DocumentationMethodException(); - - /// - public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchGoal goal) => - SearchGraph(start, neighbors, node => goal(node) ? GraphSearchStatus.Goal : GraphSearchStatus.Continue); - - /// - public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, Node goal) => - SearchGraph(start, neighbors, goal, Equate); - - /// - public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, Node goal, Func equate) => - SearchGraph(start, neighbors, node => equate(node, goal)); - - /// - public static Action>? SearchGraph(Node start, IGraph graph, Node goal) => - SearchGraph(start, graph, goal, Equate); - - /// - public static Action>? SearchGraph(Node start, IGraph graph, Node goal, Func equate) => - SearchGraph(start, graph.Neighbors, node => equate(node, goal)); - - /// - public static Action>? SearchGraph(Node start, IGraph graph, SearchGoal goal) => - SearchGraph(start, graph.Neighbors, goal); - - /// - public static Action>? SearchGraph(Node start, SearchNeighbors neighbors, SearchCheck check) - { - IQueue> fringe = new QueueLinked>(); - - // push starting node - fringe.Enqueue( - new BreadthFirstSearch( - value: start, - previous: null)); - - // run the algorithm - while (fringe.Count != 0) - { - BreadthFirstSearch current = fringe.Dequeue(); - GraphSearchStatus status = check(current.Value); - if (status is GraphSearchStatus.Break) - { - break; - } - if (status is GraphSearchStatus.Goal) - { - return BuildPath(current); - } - else - { - neighbors(current.Value, - neighbor => - { - fringe.Enqueue( - new BreadthFirstSearch( - value: neighbor, - previous: current)); - }); - } - } - return null; // goal node was not reached (no path exists) - } - - #endregion - - #endregion - - #region Sort - - #region XML -#pragma warning disable CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name -#pragma warning disable CS1572 // XML comment has a param tag, but there is no parameter by that name - /// The type of values to sort. - /// The compare function. - /// The get function. - /// The set function. - /// The compare function. - /// The get function. - /// The set function. - /// The starting index of the sort. - /// The ending index of the sort. - /// The array to be sorted. - /// The span to be sorted. - [Obsolete(TowelConstants.NotIntended, true)] - internal static void Sort_XML() => throw new DocumentationMethodException(); -#pragma warning restore CS1572 // XML comment has a param tag, but there is no parameter by that name -#pragma warning restore CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name - #endregion - - #region SortBubble - - /// - /// Sorts values using the bubble sort algorithm. - /// Runtime: Ω(n), ε(n^2), O(n^2) - /// Memory: O(1) - /// Stable: True - /// - /// - [Obsolete(TowelConstants.NotIntended, true)] - internal static void SortBubble_XML() => throw new DocumentationMethodException(); - - /// - public static void SortBubble(int start, int end, Func get, Action set, Func? compare = null) => - SortBubble, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); - - /// - public static void SortBubble(int start, int end, Compare compare = default, Get get = default, Set set = default) - where Compare : struct, IFunc - where Get : struct, IFunc - where Set : struct, IAction - { - for (int i = start; i <= end; i++) - { - for (int j = start; j <= end - 1; j++) - { - if (compare.Do(get.Do(j), get.Do(j + 1)) is Greater) - { - // Swap - T temp = get.Do(j + 1); - set.Do(j + 1, get.Do(j)); - set.Do(j, temp); - } - } - } - } - - /// - public static void SortBubble(Span span, Func? compare = null) => - SortBubble>(span, compare ?? Compare); - - /// - public static void SortBubble(Span span, Compare compare = default) - where Compare : struct, IFunc - { - for (int i = 0; i <= span.Length - 1; i++) - { - for (int j = 0; j <= span.Length - 2; j++) - { - if (compare.Do(span[j], span[j + 1]) is Greater) - { - Swap(ref span[j], ref span[j + 1]); - } - } - } - } - - #endregion - - #region SortSelection - - /// - /// Sorts values using the selection sort algoritm. - /// Runtime: Ω(n^2), ε(n^2), O(n^2) - /// Memory: O(1) - /// Stable: False - /// - /// - [Obsolete(TowelConstants.NotIntended, true)] - internal static void SortSelection_XML() => throw new DocumentationMethodException(); - - /// - public static void SortSelection(int start, int end, Func get, Action set, Func? compare = null) => - SortSelection, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); - - /// - public static void SortSelection(int start, int end, Compare compare = default, Get get = default, Set set = default) - where Compare : struct, IFunc - where Get : struct, IFunc - where Set : struct, IAction - { - for (int i = start; i <= end; i++) - { - int min = i; - for (int j = i + 1; j <= end; j++) - { - if (compare.Do(get.Do(j), get.Do(min)) is Less) - { - min = j; - } - } - // Swap - T temp = get.Do(min); - set.Do(min, get.Do(i)); - set.Do(i, temp); - } - } - - /// - public static void SortSelection(Span span, Func? compare = null) => - SortSelection>(span, compare ?? Compare); - - /// - public static void SortSelection(Span span, Compare compare = default) - where Compare : struct, IFunc - { - for (int i = 0; i < span.Length; i++) - { - int min = i; - for (int j = i + 1; j < span.Length; j++) - { - if (compare.Do(span[j], span[min]) is Less) - { - min = j; - } - } - Swap(ref span[min], ref span[i]); - } - } - - #endregion - - #region SortInsertion - - /// - /// Sorts values using the insertion sort algorithm. - /// Runtime: Ω(n), ε(n^2), O(n^2) - /// Memory: O(1) - /// Stable: True - /// - /// - [Obsolete(TowelConstants.NotIntended, true)] - internal static void SortInsertion_XML() => throw new DocumentationMethodException(); - - /// - public static void SortInsertion(int start, int end, Func get, Action set, Func? compare = null) => - SortInsertion, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); - - /// - public static void SortInsertion(int start, int end, Compare compare = default, Get get = default, Set set = default) - where Compare : struct, IFunc - where Get : struct, IFunc - where Set : struct, IAction - { - for (int i = start + 1; i <= end; i++) - { - T temp = get.Do(i); - int j = i; - for (; j > start && compare.Do(get.Do(j - 1), temp) is Greater; j--) - { - set.Do(j, get.Do(j - 1)); - } - set.Do(j, temp); - } - } - - /// - public static void SortInsertion(Span span, Func? compare = null) => - SortInsertion>(span, compare ?? Compare); - - /// - public static void SortInsertion(Span span, Compare compare = default) - where Compare : struct, IFunc - { - for (int i = 1; i <= span.Length - 1; i++) - { - T temp = span[i]; - int j; - for (j = i; j > 0 && compare.Do(span[j - 1], temp) is Greater; j--) - { - span[j] = span[j - 1]; - } - span[j] = temp; - } - } - - #endregion - - #region SortQuick - - /// - /// Sorts values using the quick sort algorithm. - /// Runtime: Ω(n*ln(n)), ε(n*ln(n)), O(n^2) - /// Memory: ln(n) - /// Stable: False - /// - /// - [Obsolete(TowelConstants.NotIntended, true)] - internal static void SortQuick_XML() => throw new DocumentationMethodException(); - - /// - public static void SortQuick(int start, int end, Func get, Action set, Func? compare = null) => - SortQuick, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); - - /// - public static void SortQuick(int start, int end, Compare compare = default, Get get = default, Set set = default) - where Compare : struct, IFunc - where Get : struct, IFunc - where Set : struct, IAction - { - SortQuick_Recursive(start, end - start + 1); - - void SortQuick_Recursive(int start, int length) - { - if (length > 1) - { - T pivot = get.Do(start); - int i = start; - int j = start + length - 1; - int k = j; - while (i <= j) - { - if (compare.Do(get.Do(j), pivot) is Less) - { - Swap(i++, j); - } - else if (compare.Do(get.Do(j), pivot) is Equal) - { - j--; - } - else - { - Swap(k--, j--); - } - } - SortQuick_Recursive(start, i - start); - SortQuick_Recursive(k + 1, start + length - (k + 1)); - } - } - void Swap(int a, int b) - { - T temp = get.Do(a); - set.Do(a, get.Do(b)); - set.Do(b, temp); - } - } - - /// - public static void SortQuick(Span span, Func? compare = null) => - SortQuick>(span, compare ?? Compare); - - /// - public static void SortQuick(Span span, Compare compare = default) - where Compare : struct, IFunc - { - SortQuick_Recursive(span, 0, span.Length); - - void SortQuick_Recursive(Span span, int startIndex, int len) - { - if (len > 1) - { - T pivot = span[startIndex]; - int i = startIndex; - int j = startIndex + len - 1; - int k = j; - while (i <= j) - { - if (compare.Do(span[j], pivot) is Less) - { - Swap(ref span[i++], ref span[j]); - } - else if (compare.Do(span[j], pivot) is Equal) - { - j--; - } - else - { - Swap(ref span[k--], ref span[j--]); - } - } - SortQuick_Recursive(span, startIndex, i - startIndex); - SortQuick_Recursive(span, k + 1, startIndex + len - (k + 1)); - } - } - } - - #endregion - - #region SortMerge - - /// - /// Sorts values using the merge sort algorithm. - /// Runtime: Ω(n*ln(n)), ε(n*ln(n)), O(n*ln(n)) - /// Memory: Θ(n) - /// Stable: True - /// - /// - [Obsolete(TowelConstants.NotIntended, true)] - internal static void SortMerge_XML() => throw new DocumentationMethodException(); - - /// - public static void SortMerge(int start, int end, Func get, Action set, Func? compare = null) => - SortMerge, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); - - /// - public static void SortMerge(int start, int end, Compare compare = default, Get get = default, Set set = default) - where Compare : struct, IFunc - where Get : struct, IFunc - where Set : struct, IAction - { - SortMerge_Recursive(start, end - start + 1); - - void SortMerge_Recursive(int start, int length) - { - if (length > 1) - { - int half = length / 2; - SortMerge_Recursive(start, half); - SortMerge_Recursive(start + half, length - half); - T[] sorted = new T[length]; - int i = start; - int j = start + half; - int k = 0; - while (i < start + half && j < start + length) - { - if (compare.Do(get.Do(i), get.Do(j)) is Greater) - { - sorted[k++] = get.Do(j++); - } - else - { - sorted[k++] = get.Do(i++); - } - } - for (int h = 0; h < start + half - i; h++) - { - sorted[k + h] = get.Do(i + h); - } - for (int h = 0; h < start + length - j; h++) - { - sorted[k + h] = get.Do(j + h); - } - for (int h = 0; h < length; h++) - { - set.Do(start + h, sorted[0 + h]); - } - } - } - } - - /// - public static void SortMerge(Span span, Func? compare = null) => - SortMerge>(span, compare ?? Compare); - - /// - public static void SortMerge(Span span, Compare compare = default) - where Compare : struct, IFunc - { - SortMerge_Recursive(span); - - void SortMerge_Recursive(Span span) - { - if (span.Length > 1) - { - int half = span.Length / 2; - SortMerge_Recursive(span[..half]); - SortMerge_Recursive(span[half..]); - T[] sorted = new T[span.Length]; - int i = 0; - int j = half; - int k = 0; - while (i < half && j < span.Length) - { - if (compare.Do(span[i], span[j]) is Greater) - { - sorted[k++] = span[j++]; - } - else - { - sorted[k++] = span[i++]; - } - } - for (int h = 0; h < half - i; h++) - { - sorted[k + h] = span[i + h]; - } - for (int h = 0; h < span.Length - j; h++) - { - sorted[k + h] = span[j + h]; - } - for (int h = 0; h < span.Length; h++) - { - span[h] = sorted[0 + h]; - } - } - } - } - - #endregion - - #region SortHeap - - /// - /// Sorts values using the heap sort algorithm. - /// Runtime: Ω(n*ln(n)), ε(n*ln(n)), O(n^2) - /// Memory: O(1) - /// Stable: False - /// - /// - [Obsolete(TowelConstants.NotIntended, true)] - internal static void SortHeap_XML() => throw new DocumentationMethodException(); - - /// - public static void SortHeap(int start, int end, Func get, Action set, Func? compare = null) => - SortHeap, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); - - /// - public static void SortHeap(int start, int end, Compare compare = default, Get get = default, Set set = default) - where Compare : struct, IFunc - where Get : struct, IFunc - where Set : struct, IAction - { - int heapSize = end - start + 1; - for (int i = heapSize / 2; i >= 0; i--) - { - MaxSortHeapify(heapSize + start, i, start); - } - for (int i = end; i >= start; i--) - { - Swap(start, i); - heapSize--; - MaxSortHeapify(heapSize + start, 0, start); - } - void MaxSortHeapify(int heapSize, int index, int offset) - { - int left = ((index + 1) * 2 - 1) + offset; - int right = ((index + 1) * 2) + offset; - index += offset; - int largest = index; - if (left < heapSize && compare.Do(get.Do(left), get.Do(largest)) is Greater) - { - largest = left; - } - if (right < heapSize && compare.Do(get.Do(right), get.Do(largest)) is Greater) - { - largest = right; - } - if (largest != index) - { - Swap(index, largest); - MaxSortHeapify(heapSize, largest - offset, offset); - } - } - void Swap(int a, int b) - { - T temp = get.Do(a); - set.Do(a, get.Do(b)); - set.Do(b, temp); - } - } - - /// - public static void SortHeap(Span span, Func? compare = null) => - SortHeap>(span, compare ?? Compare); - - /// - public static void SortHeap(Span span, Compare compare = default) - where Compare : struct, IFunc - { - int start = 0; - int end = span.Length - 1; - int heapSize = end - start + 1; - for (int i = heapSize / 2; i >= 0; i--) - { - MaxSortHeapify(span, heapSize + start, i, start); - } - for (int i = end; i >= start; i--) - { - Swap(ref span[start], ref span[i]); - heapSize--; - MaxSortHeapify(span, heapSize + start, 0, start); - } - void MaxSortHeapify(Span span, int heapSize, int index, int offset) - { - int left = ((index + 1) * 2 - 1) + offset; - int right = ((index + 1) * 2) + offset; - index += offset; - int largest = index; - if (left < heapSize && compare.Do(span[left], span[largest]) is Greater) - { - largest = left; - } - if (right < heapSize && compare.Do(span[right], span[largest]) is Greater) - { - largest = right; - } - if (largest != index) - { - Swap(ref span[index], ref span[largest]); - MaxSortHeapify(span, heapSize, largest - offset, offset); - } - } - } - - #endregion - - #region SortOddEven - - /// - /// Sorts values using the odd even sort algorithm. - /// Runtime: Ω(n), ε(n^2), O(n^2) - /// Memory: O(1) - /// Stable: True - /// - /// - [Obsolete(TowelConstants.NotIntended, true)] - internal static void SortOddEven_XML() => throw new DocumentationMethodException(); - - /// - public static void SortOddEven(int start, int end, Func get, Action set, Func? compare = null) => - SortOddEven, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); - - /// - public static void SortOddEven(int start, int end, Compare compare = default, Get get = default, Set set = default) - where Compare : struct, IFunc - where Get : struct, IFunc - where Set : struct, IAction - { - bool sorted = false; - while (!sorted) - { - sorted = true; - for (int i = start; i < end; i += 2) - { - if (compare.Do(get.Do(i), get.Do(i + 1)) is Greater) - { - Swap(i, i + 1); - sorted = false; - } - } - for (int i = start + 1; i < end; i += 2) - { - if (compare.Do(get.Do(i), get.Do(i + 1)) is Greater) - { - Swap(i, i + 1); - sorted = false; - } - } - void Swap(int a, int b) - { - T temp = get.Do(a); - set.Do(a, get.Do(b)); - set.Do(b, temp); - } - } - } - - /// - public static void SortOddEven(Span span, Func? compare = null) => - SortOddEven>(span, compare ?? Compare); - - /// - public static void SortOddEven(Span span, Compare compare = default) - where Compare : struct, IFunc - { - bool sorted = false; - while (!sorted) - { - sorted = true; - for (int i = 0; i < span.Length - 1; i += 2) - { - if (compare.Do(span[i], span[i + 1]) is Greater) - { - Swap(ref span[i], ref span[i + 1]); - sorted = false; - } - } - for (int i = 1; i < span.Length - 1; i += 2) - { - if (compare.Do(span[i], span[i + 1]) is Greater) - { - Swap(ref span[i], ref span[i + 1]); - sorted = false; - } - } - } - } - - #endregion - - #region SortCounting - -#if false - - ///// Method specifically for computing object keys in the SortCounting Sort algorithm. - ///// The type of instances in the array to be sorted. - ///// The instance to compute a counting key for. - ///// The counting key computed from the provided instance. - //public delegate int ComputeSortCountingKey(T instance); - - ///// - ///// Sorts an entire array in non-decreasing order using the heap sort algorithm. - ///// Runtime: Θ(Max(key)) - ///// Memory: Max(Key) - ///// Stable: True - ///// - ///// The type of objects stored within the array. - ///// Method specifically for computing object keys in the SortCounting Sort algorithm. - ///// The array to be sorted - //public static void SortCounting(ComputeSortCountingKey computeSortCountingKey, T[] array) - //{ - // throw new System.NotImplementedException(); - - // // This code needs revision and conversion - // int[] count = new int[array.Length]; - // int maxKey = 0; - // for (int i = 0; i < array.Length; i++) - // { - // int key = computeSortCountingKey(array[i]) / array.Length; - // count[key] += 1; - // if (key > maxKey) - // maxKey = key; - // } - - // int total = 0; - // for (int i = 0; i < maxKey; i++) - // { - // int oldCount = count[i]; - // count[i] = total; - // total += oldCount; - // } - - // T[] output = new T[maxKey]; - // for (int i = 0; i < array.Length; i++) - // { - // int key = computeSortCountingKey(array[i]); - // output[count[key]] = array[i]; - // count[computeSortCountingKey(array[i])] += 1; - // } - //} - - //public static void SortCounting(ComputeSortCountingKey computeSortCountingKey, T[] array, int start, int end) - //{ - // throw new System.NotImplementedException(); - //} - - //public static void SortCounting(ComputeSortCountingKey computeSortCountingKey, Get get, Assign set, int start, int end) - //{ - // throw new System.NotImplementedException(); - //} - -#endif - - #endregion - - #region Shuffle - -#pragma warning disable CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name -#pragma warning disable CS1572 // XML comment has a param tag, but there is no parameter by that name - /// - /// Sorts values into a randomized order. - /// Runtime: O(n) - /// Memory: O(1) - /// - /// The type of values to sort. - /// The get function. - /// The set function. - /// The starting index of the shuffle. - /// The ending index of the shuffle. - /// The get function. - /// The set function. - /// The random to shuffle with. - /// The array to shuffle. - [Obsolete(TowelConstants.NotIntended, true)] - internal static void Shuffle_XML() => throw new DocumentationMethodException(); -#pragma warning restore CS1572 // XML comment has a param tag, but there is no parameter by that name -#pragma warning restore CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name - - /// - public static void Shuffle(int start, int end, Func get, Action set, Random? random = null) => - Shuffle, ActionRuntime>(start, end, get, set, random); - - /// - public static void Shuffle(int start, int end, Get get = default, Set set = default, Random? random = null) - where Get : struct, IFunc - where Set : struct, IAction => - Shuffle(start, end, get, set, random ?? new Random()); - - /// - public static void Shuffle(int start, int end, Get get = default, Set set = default, Random random = default) - where Get : struct, IFunc - where Set : struct, IAction - where Random : struct, IFunc - { - for (int i = start; i <= end; i++) - { - int randomIndex = random.Do(start, end); - // Swap - T temp = get.Do(i); - set.Do(i, get.Do(randomIndex)); - set.Do(randomIndex, temp); - } - } - - /// - public static void Shuffle(Span span, Random? random = null) => - Shuffle(span, random ?? new Random()); - - /// - public static void Shuffle(Span span, Random random = default) - where Random : struct, IFunc - { - for (int i = 0; i < span.Length; i++) - { - int index = random.Do(0, span.Length); - Swap(ref span[i], ref span[index]); - } - } - - #endregion - - #region SortBogo - - /// - /// Sorts values using the bogo sort algorithm. - /// Runtime: Ω(n), ε(n*n!), O(∞) - /// Memory: O(1) - /// Stable: False - /// - /// - [Obsolete(TowelConstants.NotIntended, true)] - internal static void SortBogo_XML() => throw new DocumentationMethodException(); - - /// - public static void SortBogo(int start, int end, Func get, Action set, Func? compare = null, Random? random = null) => - SortBogo, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set, random); - - /// - public static void SortBogo(int start, int end, Compare compare = default, Get get = default, Set set = default, Random? random = null) - where Compare : struct, IFunc - where Get : struct, IFunc - where Set : struct, IAction => - SortBogo(start, end, compare, get, set, random ?? new Random()); - - /// - public static void SortBogo(int start, int end, Compare compare = default, Get get = default, Set set = default, Random random = default) - where Compare : struct, IFunc - where Get : struct, IFunc - where Set : struct, IAction - where Random : struct, IFunc - { - while (!IsOrdered(start, end, compare, get)) - { - Shuffle(start, end, get, set, random); - } - } - - /// - public static void SortBogo(Span span, Func? compare = null, Random? random = null) => - SortBogo>(span, compare ?? Compare, random ?? new Random()); - - /// - public static void SortBogo(Span span, Compare compare = default, Random? random = null) - where Compare : struct, IFunc => - SortBogo(span, compare, random ?? new Random()); - - /// - public static void SortBogo(Span span, Compare compare = default, Random random = default) - where Compare : struct, IFunc - where Random : struct, IFunc - { - while (!IsOrdered(span, compare)) - { - Shuffle(span, random); - } - } - - #endregion - - #region SortSlow - - /// Sorts values using the slow sort algorithm. - /// - [Obsolete(TowelConstants.NotIntended, true)] - internal static void SortSlow_XML() => throw new DocumentationMethodException(); - - /// - public static void SortSlow(int start, int end, Func get, Action set, Func? compare = null) => - SortSlow, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); - - /// - public static void SortSlow(int start, int end, Compare compare = default, Get get = default, Set set = default) - where Compare : struct, IFunc - where Get : struct, IFunc - where Set : struct, IAction - { - SortSlowRecursive(start, end); - void SortSlowRecursive(int i, int j) - { - if (i >= j) - { - return; - } - int mid = (i + j) / 2; - SortSlowRecursive(i, mid); - SortSlowRecursive(mid + 1, j); - if (compare.Do(get.Do(j), get.Do(mid)) is Less) - { - // Swap - T temp = get.Do(j); - set.Do(j, get.Do(mid)); - set.Do(mid, temp); - } - SortSlowRecursive(i, j - 1); - } - } - - /// - public static void SortSlow(Span span, Func? compare = null) => - SortSlow>(span, compare ?? Compare); - - /// - public static void SortSlow(Span span, Compare compare = default) - where Compare : struct, IFunc - { - SortSlowRecursive(span, 0, span.Length - 1); - void SortSlowRecursive(Span span, int i, int j) - { - if (i >= j) - { - return; - } - int mid = (i + j) / 2; - SortSlowRecursive(span, i, mid); - SortSlowRecursive(span, mid + 1, j); - if (compare.Do(span[j], span[mid]) is Less) - { - Swap(ref span[j], ref span[mid]); - } - SortSlowRecursive(span, i, j - 1); - } - } - - #endregion - - #region SortGnome - - /// Sorts values using the gnome sort algorithm. - /// - [Obsolete(TowelConstants.NotIntended, true)] - internal static void SortGnome_XML() => throw new DocumentationMethodException(); - - /// - public static void SortGnome(int start, int end, Func get, Action set, Func? compare = null) => - SortGnome, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); - - /// - public static void SortGnome(int start, int end, Compare compare = default, Get get = default, Set set = default) - where Compare : struct, IFunc - where Get : struct, IFunc - where Set : struct, IAction - { - int i = start; - while (i <= end) - { - if (i == start || compare.Do(get.Do(i), get.Do(i - 1)) != Less) - { - i++; - } - else - { - // Swap - T temp = get.Do(i); - set.Do(i, get.Do(i - 1)); - set.Do(i - 1, temp); - i--; - } - } - } - - /// - public static void SortGnome(Span span, Func? compare = null) => - SortGnome>(span, compare ?? Compare); - - /// - public static void SortGnome(Span span, Compare compare = default) - where Compare : struct, IFunc - { - int i = 0; - while (i < span.Length) - { - if (i == 0 || compare.Do(span[i], span[i - 1]) != Less) - { - i++; - } - else - { - Swap(ref span[i], ref span[i - 1]); - i--; - } - } - } - - #endregion - - #region SortComb - - /// Sorts values using the comb sort algorithm. - /// - [Obsolete(TowelConstants.NotIntended, true)] - internal static void SortComb_XML() => throw new DocumentationMethodException(); - - /// - public static void SortComb(int start, int end, Func get, Action set, Func? compare = null) => - SortComb, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); - - /// - public static void SortComb(int start, int end, Compare compare = default, Get get = default, Set set = default) - where Compare : struct, IFunc - where Get : struct, IFunc - where Set : struct, IAction - { - const double shrink = 1.3; - int gap = end - start + 1; - bool sorted = false; - while (!sorted) - { - gap = (int)(gap / shrink); - if (gap <= 1) - { - gap = 1; - sorted = true; - } - for (int i = start; i + gap <= end; i++) - { - if (compare.Do(get.Do(i), get.Do(i + gap)) is Greater) - { - T temp = get.Do(i); - set.Do(i, get.Do(i + gap)); - set.Do(i + gap, temp); - sorted = false; - } - } - } - } - - /// - public static void SortComb(Span span, Func? compare = null) => - SortComb>(span, compare ?? Compare); - - /// - public static void SortComb(Span span, Compare compare = default) - where Compare : struct, IFunc - { - const double shrink = 1.3; - int gap = span.Length; - bool sorted = false; - while (!sorted) - { - gap = (int)(gap / shrink); - if (gap <= 1) - { - gap = 1; - sorted = true; - } - for (int i = 0; i + gap < span.Length; i++) - { - if (compare.Do(span[i], span[i + gap]) is Greater) - { - Swap(ref span[i], ref span[i + gap]); - sorted = false; - } - } - } - } - - #endregion - - #region SortShell - - /// Sorts values using the shell sort algorithm. - /// - [Obsolete(TowelConstants.NotIntended, true)] - internal static void SortShell_XML() => throw new DocumentationMethodException(); - - /// - public static void SortShell(int start, int end, Func get, Action set, Func? compare = null) => - SortShell, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); - - /// - public static void SortShell(int start, int end, Compare compare = default, Get get = default, Set set = default) - where Compare : struct, IFunc - where Get : struct, IFunc - where Set : struct, IAction - { - int[] gaps = { 701, 301, 132, 57, 23, 10, 4, 1 }; - foreach (int gap in gaps) - { - for (int i = gap + start; i <= end; i++) - { - T temp = get.Do(i); - int j = i; - for (; j >= gap && compare.Do(get.Do(j - gap), temp) is Greater; j -= gap) - { - set.Do(j, get.Do(j - gap)); - } - set.Do(j, temp); - } - } - } - - /// - public static void SortShell(Span span, Func? compare = null) => - SortShell>(span, compare ?? Compare); - - /// - public static void SortShell(Span span, Compare compare = default) - where Compare : struct, IFunc - { - int[] gaps = { 701, 301, 132, 57, 23, 10, 4, 1 }; - foreach (int gap in gaps) - { - for (int i = gap; i < span.Length; i++) - { - T temp = span[i]; - int j = i; - for (; j >= gap && compare.Do(span[j - gap], temp) is Greater; j -= gap) - { - span[j] = span[j - gap]; - } - span[j] = temp; - } - } - } - - #endregion - - #region SortCocktail - - /// Sorts values using the cocktail sort algorithm. - /// - [Obsolete(TowelConstants.NotIntended, true)] - internal static void SortCocktail_XML() => throw new DocumentationMethodException(); - - /// - public static void SortCocktail(int start, int end, Func get, Action set, Func? compare = null) => - SortCocktail, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); - - /// - public static void SortCocktail(int start, int end, Compare compare = default, Get get = default, Set set = default) - where Compare : struct, IFunc - where Get : struct, IFunc - where Set : struct, IAction - { - while (true) - { - bool swapped = false; - for (int i = start; i <= end - 1; i++) - { - if (compare.Do(get.Do(i), get.Do(i + 1)) is Greater) - { - T temp = get.Do(i); - set.Do(i, get.Do(i + 1)); - set.Do(i + 1, temp); - swapped = true; - } - } - if (!swapped) - { - break; - } - swapped = false; - for (int i = end - 1; i >= start; i--) - { - if (compare.Do(get.Do(i), get.Do(i + 1)) is Greater) - { - T temp = get.Do(i); - set.Do(i, get.Do(i + 1)); - set.Do(i + 1, temp); - swapped = true; - } - } - if (!swapped) - { - break; - } - } - } - - /// - public static void SortCocktail(Span span, Func? compare = null) => - SortCocktail>(span, compare ?? Compare); - - /// - public static void SortCocktail(Span span, Compare compare = default) - where Compare : struct, IFunc - { - while (true) - { - bool swapped = false; - for (int i = 0; i < span.Length - 1; i++) - { - if (compare.Do(span[i], span[i + 1]) is Greater) - { - Swap(ref span[i], ref span[i + 1]); - swapped = true; - } - } - if (!swapped) - { - break; - } - swapped = false; - for (int i = span.Length - 2; i >= 0; i--) - { - if (compare.Do(span[i], span[i + 1]) is Greater) - { - Swap(ref span[i], ref span[i + 1]); - swapped = true; - } - } - if (!swapped) - { - break; - } - } - } - - #endregion - - #region SortCycle - - /// Sorts values using the shell cycle algorithm. - /// - [Obsolete(TowelConstants.NotIntended, true)] - internal static void SortCycle_XML() => throw new DocumentationMethodException(); - - /// - public static void SortCycle(int start, int end, Func get, Action set, Func? compare = null) => - SortCycle, FuncRuntime, ActionRuntime>(start, end, compare ?? Compare, get, set); - - /// - public static void SortCycle(int start, int end, Compare compare = default, Get get = default, Set set = default) - where Compare : struct, IFunc - where Get : struct, IFunc - where Set : struct, IAction - { - for (int i = start; i < end; i++) - { - T pivot = get.Do(i); - int index = i; - for (int j = i + 1; j <= end; j++) - { - if (compare.Do(get.Do(j), pivot) is Less) - { - index++; - } - } - if (index == i) - { - continue; - } - while (compare.Do(pivot, get.Do(index)) is Equal) - { - index++; - } - if (index != i) - { - T temp = pivot; - pivot = get.Do(index); - set.Do(index, temp); - } - while (index != i) + Function = (A, step) => { - index = i; - for (int j = i + 1; j <= end; j++) - { - if (compare.Do(get.Do(j), pivot) is Less) - { - index++; - } - } - while (compare.Do(pivot, get.Do(index)) is Equal) + if (!IsInteger(A)) { - index += 1; + throw new ArgumentOutOfRangeException(nameof(A), A, "!(" + nameof(A) + "." + nameof(IsInteger) + ")"); } - if (compare.Do(pivot, get.Do(index)) is not Equal) + if (IsNegative(A)) { - T temp = pivot; - pivot = get.Do(index); - set.Do(index, temp); + A = AbsoluteValue(A); + step(Convert(-1)); } - } - } - } - - /// - public static void SortCycle(Span span, Func? compare = null) => - SortCycle>(span, compare ?? Compare); - - /// - public static void SortCycle(Span span, Compare compare = default) - where Compare : struct, IFunc - { - for (int i = 0; i < span.Length - 1; i++) - { - T pivot = span[i]; - int index = i; - for (int j = i + 1; j < span.Length; j++) - { - if (compare.Do(span[j], pivot) is Less) + while (IsEven(A)) { - index++; + step(Constant.Two); + A = Division(A, Constant.Two); } - } - if (index == i) - { - continue; - } - while (compare.Do(pivot, span[index]) is Equal) - { - index++; - } - if (index != i) - { - Swap(ref span[index], ref pivot); - } - while (index != i) - { - index = i; - for (int j = i + 1; j < span.Length; j++) + for (T i = Constant.Three; LessThanOrEqual(i, SquareRoot(A)); i = Addition(i, Constant.Two)) { - if (compare.Do(span[j], pivot) is Less) + while (Equate(Remainder(A, i), Constant.Zero)) { - index++; + step(i); + A = Division(A, i); } } - while (compare.Do(pivot, span[index]) is Equal) - { - index += 1; - } - if (compare.Do(pivot, span[index]) is not Equal) + if (GreaterThan(A, Constant.Two)) { - Swap(ref span[index], ref pivot); + step(A); } - } - } - } - - #endregion - - #endregion - - #region FilterOrdered - - public static void FilterOrdered(int start, int end, Func get, Action step, Func? compare = null) => - FilterOrdered, ActionRuntime, FuncRuntime>(start, end, get, step, compare ?? Compare); - - public static void FilterOrdered(int start, int end, Get get = default, Step step = default, Compare compare = default) - where Get : struct, IFunc - where Step : struct, IAction - where Compare : struct, IFunc - { - if (start <= end) - { - step.Do(get.Do(start)); - } - for (int i = start; i <= end; i++) - { - if (compare.Do(get.Do(i - 1), get.Do(i)) is not Greater) - { - step.Do(get.Do(i)); - } - } - } - - public static void FilterOrdered(ReadOnlySpan span, Action step, Func? compare = null) => - FilterOrdered, FuncRuntime>(span, step, compare ?? Compare); - - public static void FilterOrdered(ReadOnlySpan span, Step step = default, Compare compare = default) - where Step : struct, IAction - where Compare : struct, IFunc - { - if (!span.IsEmpty) - { - step.Do(span[0]); - } - for (int i = 1; i < span.Length; i++) - { - if (compare.Do(span[i - 1], span[i]) is not Greater) - { - step.Do(span[i]); - } - } - } - - #endregion - - #region IsOrdered - -#pragma warning disable CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name -#pragma warning disable CS1572 // XML comment has a param tag, but there is no parameter by that name - /// The type of values to sort. - /// The compare function. - /// The get function. - /// The compare function. - /// The get function. - /// The starting index of the sort. - /// The ending index of the sort. - /// The span to be sorted. - [Obsolete(TowelConstants.NotIntended, true)] - internal static void IsOrdered_XML() => throw new DocumentationMethodException(); -#pragma warning restore CS1572 // XML comment has a param tag, but there is no parameter by that name -#pragma warning restore CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name - - /// - public static bool IsOrdered(int start, int end, Func get, Func? compare = null) => - IsOrdered, FuncRuntime>(start, end, compare ?? Compare, get); - - /// - public static bool IsOrdered(int start, int end, Compare compare = default, Get get = default) - where Compare : struct, IFunc - where Get : struct, IFunc - { - for (int i = start + 1; i <= end; i++) - { - if (compare.Do(get.Do(i - 1), get.Do(i)) is Greater) - { - return false; - } - } - return true; - } - - /// - public static bool IsOrdered(ReadOnlySpan span, Func? compare = null) => - IsOrdered>(span, compare ?? Compare); - - /// - public static bool IsOrdered(ReadOnlySpan span, Compare compare = default) - where Compare : struct, IFunc - { - for (int i = 1; i < span.Length; i++) - { - if (compare.Do(span[i - 1], span[i]) is Greater) - { - return false; - } - } - return true; - } - - /// - public static bool IsOrdered(this System.Collections.Generic.IEnumerable enumerable, Func? compare = null) => - IsOrdered>(enumerable, compare ?? Compare); - - /// - public static bool IsOrdered(this System.Collections.Generic.IEnumerable enumerable, Compare compare = default) - where Compare : struct, IFunc - { - System.Collections.Generic.IEnumerator enumerator = enumerable.GetEnumerator(); - T previous = enumerator.Current; - while (enumerator.MoveNext()) - { - if (compare.Do(previous, enumerator.Current) is Greater) - { - return false; - } - previous = enumerator.Current; - } - return true; - } - - #endregion - - #region NextUnique - - /// - /// Generates unique random values in the - /// [..] range where is - /// inclusive and is exclusive. - /// - /// The function to perform on each generated value. - /// The random to generation algorithm. - /// The random to generation algorithm. - /// The number of values to generate. - /// Inclusive endpoint of the random generation range. - /// Exclusive endpoint of the random generation range. - /// The function to perform on each generated value. - public static void NextUnique(int count, int minValue, int maxValue, Random random = default, Step step = default) - where Step : struct, IAction - where Random : struct, IFunc - { -#pragma warning disable CS0618 - if (count < Math.Sqrt(maxValue - minValue)) - { - NextUniqueRollTracking(count, minValue, maxValue, random, step); - } - else - { - NextUniquePoolTracking(count, minValue, maxValue, random, step); - } -#pragma warning restore CS0618 - } - - /// - /// Generates unique random values in the - /// [..] range where is - /// inclusive and is exclusive. - /// - /// The function to perform on each generated value. - /// The random to generation algorithm. - /// The random to generation algorithm. - /// The number of values to generate. - /// Inclusive endpoint of the random generation range. - /// Exclusive endpoint of the random generation range. - /// The function to perform on each generated value. - [Obsolete("It is recommended you use " + nameof(NextUnique) + " method instead.", false)] - public static void NextUniqueRollTracking(int count, int minValue, int maxValue, Random random = default, Step step = default) - where Step : struct, IAction - where Random : struct, IFunc - { - if (maxValue < minValue) - { - throw new ArgumentOutOfRangeException(nameof(maxValue), $"{nameof(minValue)} > {nameof(maxValue)}"); - } - if (count < 0) - { - throw new ArgumentOutOfRangeException(nameof(count), $"{nameof(count)} < 0"); - } - if (maxValue - minValue < count) - { - throw new ArgumentOutOfRangeException(nameof(count), $"{nameof(count)} is larger than {nameof(maxValue)} - {nameof(minValue)}."); - } - // Algorithm B: O(.5*count^2), Ω(count), ε(.5*count^2) - Node? head = null; - for (int i = 0; i < count; i++) // Θ(count) - { - int roll = random.Do(minValue, maxValue - i); - if (roll < minValue || roll >= maxValue - i) - { - throw new ArgumentException("The Random provided returned a value outside the requested range."); - } - Node? node = head; - Node? previous = null; - while (node is not null && node.Value <= roll) // O(count / 2), Ω(0), ε(count / 2) - { - roll++; - previous = node; - node = node.Next; - } - step.Do(roll); - if (previous is null) - { - head = new Node() { Value = roll, Next = head, }; - } - else - { - previous.Next = new Node() { Value = roll, Next = previous.Next }; - } - } - } - internal class Node - { - internal int Value; - internal Node? Next; - } - - /// - /// Generates unique random values in the - /// [..] range where is - /// inclusive and is exclusive. - /// - /// The function to perform on each generated value. - /// The random to generation algorithm. - /// The random to generation algorithm. - /// The number of values to generate. - /// Inclusive endpoint of the random generation range. - /// Exclusive endpoint of the random generation range. - /// The function to perform on each generated value. - [Obsolete("It is recommended you use " + nameof(NextUnique) + " method instead.", false)] - public static void NextUniquePoolTracking(int count, int minValue, int maxValue, Random random = default, Step step = default) - where Step : struct, IAction - where Random : struct, IFunc - { - if (maxValue < minValue) - { - throw new ArgumentOutOfRangeException(nameof(maxValue), $"{nameof(minValue)} > {nameof(maxValue)}"); - } - if (count < 0) - { - throw new ArgumentOutOfRangeException(nameof(count), $"{nameof(count)} < 0"); - } - if (maxValue - minValue < count) - { - throw new ArgumentOutOfRangeException(nameof(count), $"{nameof(count)} is larger than {nameof(maxValue)} - {nameof(minValue)}."); - } - // Algorithm B: Θ(range + count) - int pool = maxValue - minValue; - int[] array = new int[pool]; - for (int i = 0, j = minValue; j < maxValue; i++, j++) // Θ(range) - array[i] = j; - for (int i = 0; i < count; i++) // Θ(count) - { - int rollIndex = random.Do(0, pool); - if (rollIndex < 0 || rollIndex >= pool) - { - throw new ArgumentException("The Random provided returned a value outside the requested range."); - } - int roll = array[rollIndex]; - array[rollIndex] = array[--pool]; - step.Do(roll); - } - } - - /// - /// Generates unique random values in the - /// [..] range where is - /// inclusive and is exclusive. - /// - /// The random to generation algorithm. - /// The random to generation algorithm. - /// The number of values to generate. - /// Inclusive endpoint of the random generation range. - /// Exclusive endpoint of the random generation range. - /// The function to perform on each generated value. - public static void NextUnique(int count, int minValue, int maxValue, Action step, Random random = default) - where Random : struct, IFunc - { - _ = step ?? throw new ArgumentNullException(nameof(step)); - NextUnique, Random>(count, minValue, maxValue, random, step); - } - - /// - /// Generates unique random values in the - /// [..] range where is - /// inclusive and is exclusive. - /// - /// The random to generation algorithm. - /// The random to generation algorithm. - /// The number of values to generate. - /// Inclusive endpoint of the random generation range. - /// Exclusive endpoint of the random generation range. - public static int[] NextUnique(int count, int minValue, int maxValue, Random random = default) - where Random : struct, IFunc - { - int[] values = new int[count]; - int i = 0; - NextUnique, Random>(count, minValue, maxValue, random, new Action(value => values[i++] = value)); - return values; - } - - #endregion - - #region IsPalindrome - - /// Determines if a sequence is a palindrome. - /// The element type of the sequence. - /// The inclusive starting index of the palindrome check. - /// The inclusive ending index of the palindrome check. - /// The element equate function. - /// The get index function of the sequence. - /// True if the sequence is a palindrome; False if not. - public static bool IsPalindrome(int start, int end, Func get, Func? equate = default) => - IsPalindrome , FuncRuntime>(start, end, get, equate ?? Equate); - - /// Determines if a sequence is a palindrome. - /// The element type of the sequence. - /// The get index function of the sequence. - /// The inclusive starting index of the palindrome check. - /// The inclusive ending index of the palindrome check. - /// The element equate function. - /// The get index function of the sequence. - /// True if the sequence is a palindrome; False if not. - public static bool IsPalindrome(int start, int end, Get get = default, Func? equate = default) - where Get : struct, IFunc => - IsPalindrome>(start, end, get, equate ?? Equate); - - /// Determines if a sequence is a palindrome. - /// The element type of the sequence. - /// The element equate function. - /// The get index function of the sequence. - /// The inclusive starting index of the palindrome check. - /// The inclusive ending index of the palindrome check. - /// The element equate function. - /// The get index function of the sequence. - /// True if the sequence is a palindrome; False if not. - public static bool IsPalindrome(int start, int end, Get get = default, Equate equate = default) - where Get : struct, IFunc - where Equate : struct, IFunc - { - int middle = (end - start) / 2 + start; - for (int i = start; i <= middle; i++) - { - if (!equate.Do(get.Do(i), get.Do(end - i + start))) - { - return false; - } - } - return true; - } - - /// Determines if a sequence is a palindrome. - /// The span to check. - /// True if the sequence is a palindrome; False if not. - public static bool IsPalindrome(ReadOnlySpan span) => - IsPalindrome(span); - - /// Determines if a sequence is a palindrome. - /// The element type of the sequence. - /// The span to check. - /// The element equate function. - /// True if the sequence is a palindrome; False if not. - public static bool IsPalindrome(ReadOnlySpan span, Func? equate = default) => - IsPalindrome>(span, equate ?? Equate); - - /// Determines if a sequence is a palindrome. - /// The element type of the sequence. - /// The element equate function. - /// The span to check. - /// The element equate function. - /// True if the sequence is a palindrome; False if not. - public static bool IsPalindrome(ReadOnlySpan span, Equate equate = default) - where Equate : struct, IFunc - { - int middle = span.Length / 2; - for (int i = 0; i < middle; i++) - { - if(!equate.Do(span[i], span[^(i + 1)])) - { - return false; - } - } - return true; - } - - #endregion - - #region IsInterleaved - - #region XML - -#pragma warning disable CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name -#pragma warning disable CS1572 // XML comment has a param tag, but there is no parameter by that name -#pragma warning disable CS1734 // XML comment has a paramref tag, but there is no parameter by that name -#pragma warning disable CS1735 // XML comment has a typeparamref tag, but there is no type parameter by that name - - /// The element type of the sequences. - /// The first sequence to determine if is interleaved of. - /// The second sequence to determine if is interleaved of. - /// The sequence to determine if it is interleaved from and . - /// The function for equating values. - /// True if is interleaved of and or False if not. - /// - /// - /// IsInterleaved("abc", "xyz", "axbycz") // True - /// IsInterleaved("abc", "xyz", "cbazyx") // False (order not preserved) - /// IsInterleaved("abc", "xyz", "012345") // False - /// - /// - internal static void IsInterleaved_XML() => throw new DocumentationMethodException(); - - /// - /// - /// Determines if is interleved of and , - /// meaning that it contains all elements of and - /// while retaining the order of the respective elements. Uses a recursive algorithm. - /// - /// Runtime: O(2^(Min(.Length + .Length, .Length))), Ω(1) - /// Memory: O(1) - /// - /// - internal static void IsInterleavedRecursive_XML() => throw new DocumentationMethodException(); - - /// - /// Determines if is interleved of and , - /// meaning that it contains all elements of and - /// while retaining the order of the respective elements. Uses a interative algorithm. - /// Runtime: O(Min(.Length * .Length))), Ω(1) - /// Memory: O(.Length * .Length) - /// - /// - internal static void IsInterleavedIterative_XML() => throw new DocumentationMethodException(); - -#pragma warning restore CS1735 // XML comment has a typeparamref tag, but there is no type parameter by that name -#pragma warning restore CS1734 // XML comment has a paramref tag, but there is no parameter by that name -#pragma warning restore CS1572 // XML comment has a param tag, but there is no parameter by that name -#pragma warning restore CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name - - #endregion - - /// - public static bool IsInterleavedRecursive(ReadOnlySpan a, ReadOnlySpan b, ReadOnlySpan c, Func? equate = default) => - IsInterleavedRecursive>(a, b, c, equate ?? Equate); - - /// - public static bool IsInterleavedRecursive(ReadOnlySpan a, ReadOnlySpan b, ReadOnlySpan c) => - IsInterleavedRecursive(a, b, c); - - /// - public static bool IsInterleavedRecursive(ReadOnlySpan a, ReadOnlySpan b, ReadOnlySpan c, Equate equate = default) - where Equate : struct, IFunc - { - if (a.Length + b.Length != c.Length) - { - return false; - } - - bool Implementation(ReadOnlySpan a, ReadOnlySpan b, ReadOnlySpan c) => - a.IsEmpty && b.IsEmpty && c.IsEmpty || - ( - !c.IsEmpty && - ( - (!a.IsEmpty && equate.Do(a[0], c[0]) && Implementation(a[1..], b, c[1..])) || - (!b.IsEmpty && equate.Do(b[0], c[0]) && Implementation(a, b[1..], c[1..])) - ) - ); - - return Implementation(a, b, c); - } - - /// - public static bool IsInterleavedIterative(ReadOnlySpan a, ReadOnlySpan b, ReadOnlySpan c, Func? equate = default) => - IsInterleavedIterative>(a, b, c, equate ?? Equate); - - /// - public static bool IsInterleavedIterative(ReadOnlySpan a, ReadOnlySpan b, ReadOnlySpan c) => - IsInterleavedIterative(a, b, c); - - /// - public static bool IsInterleavedIterative(ReadOnlySpan a, ReadOnlySpan b, ReadOnlySpan c, Equate equate = default) - where Equate : struct, IFunc - { - if (a.Length + b.Length != c.Length) - { - return false; - } - bool[,] d = new bool[a.Length + 1, b.Length + 1]; - for (int i = 0; i <= a.Length; ++i) - { - for (int j = 0; j <= b.Length; ++j) - { - d[i, j] = - (i == 0 && j == 0) || - ( - i == 0 ? (equate.Do(b[j - 1], c[j - 1]) && d[i, j - 1]) : - j == 0 ? (equate.Do(a[i - 1], c[i - 1]) && d[i - 1, j]) : - equate.Do(a[i - 1], c[i + j - 1]) && !equate.Do(b[j - 1], c[i + j - 1]) ? d[i - 1, j] : - !equate.Do(a[i - 1], c[i + j - 1]) && equate.Do(b[j - 1], c[i + j - 1]) ? d[i, j - 1] : - equate.Do(a[i - 1], c[i + j - 1]) && equate.Do(b[j - 1], c[i + j - 1]) && (d[i - 1, j] || d[i, j - 1]) - ); - - #region expanded version - - //if (i == 0 && j == 0) - //{ - // d[i, j] = true; - //} - //else if (i == 0) - //{ - // if (equate.Do(b[j - 1], c[j - 1])) - // { - // d[i, j] = d[i, j - 1]; - // } - //} - //else if (j == 0) - //{ - // if (equate.Do(a[i - 1], c[i - 1])) - // { - // d[i, j] = d[i - 1, j]; - // } - //} - //else if (equate.Do(a[i - 1], c[i + j - 1]) && !equate.Do(b[j - 1], c[i + j - 1])) - //{ - // d[i, j] = d[i - 1, j]; - //} - //else if (!equate.Do(a[i - 1], c[i + j - 1]) && equate.Do(b[j - 1], c[i + j - 1])) - //{ - // d[i, j] = d[i, j - 1]; - //} - //else if (equate.Do(a[i - 1], c[i + j - 1]) && equate.Do(b[j - 1], c[i + j - 1])) - //{ - // d[i, j] = d[i - 1, j] || d[i, j - 1]; - //} - - #endregion - } - } - return d[a.Length, b.Length]; - } - - #endregion - - #region Structs - - /// Default int compare. - public struct IntCompare : IFunc - { - /// Default int compare. - /// The left hand side of the compare. - /// The right ahnd side of the compare. - /// The result of the comparison. - public CompareResult Do(int a, int b) => a.CompareTo(b).ToCompareResult(); - } - - /// Compares two char values for equality. - public struct CharEquate : IFunc - { - /// Compares two char values for equality. - /// The first operand of the equality check. - /// The second operand of the equality check. - /// True if equal; False if not. - public bool Do(char a, char b) => a == b; - } - - /// Built in Compare struct for runtime computations. - /// The generic type of the values to compare. - /// The compare function. - public struct SiftFromCompareAndValue : IFunc - where Compare : struct, IFunc - { - internal Compare CompareFunction; - internal T Value; - - /// The invocation of the compile time delegate. - public CompareResult Do(T a) => CompareFunction.Do(a, Value); - - /// Creates a compile-time-resolved sifting function to be passed into another type. - /// The value for future values to be compared against. - /// The compare function. - public SiftFromCompareAndValue(T value, Compare compare = default) - { - Value = value; - CompareFunction = compare; - } - } - - /// Compile time resulution to the value. - public struct StepStatusContinue : IFunc - { - /// Returns . - /// - public StepStatus Do() => Continue; - } - - /// Struct wrapper for the method as an . - public struct RandomNextIntMinValueIntMaxValue : IFunc - { - internal Random _random; - /// - public int Do(int minValue, int maxValue) => _random.Next(minValue, maxValue); - /// Casts a to a struct wrapper. - public static implicit operator RandomNextIntMinValueIntMaxValue(Random random) => new RandomNextIntMinValueIntMaxValue() { _random = random, }; + }; + Function(a, x); + }; } #endregion diff --git a/Sources/Towel/Towel.xml b/Sources/Towel/Towel.xml index baa76ebd..44f66de7 100644 --- a/Sources/Towel/Towel.xml +++ b/Sources/Towel/Towel.xml @@ -14983,157 +14983,53 @@ Contains Extension methods on common System types. + Contains Extension methods on common System types. + Contains Extension methods on common System types. - - Returns a new in which all occurrences of Unicode patterns in this instance are replaced with a relative Unicode replacements. - Uses Regex without a timeout. - The to perform the replacements on. - The patterns and relative replacements to apply to this . - A new in which all occurrences of Unicode patterns in this instance are replaced with a relative Unicode replacements. - Thrown if any of the parameters are null or contain null values. - Thrown if is empty, contains empty patterns, or contains duplicate patterns. - - - Returns a new in which all occurrences of Unicode patterns in this instance are replaced with a relative Unicode replacements. Caches internal values relative to the instance of rules. - Uses Regex without a timeout. This method is not thread-safe. - The to perform the replacements on. - The patterns and relative replacements to apply to this . - A new in which all occurrences of Unicode patterns in this instance are replaced with a relative Unicode replacements. - Thrown if any of the parameters are null or contain null values. - Thrown if is empty, contains empty patterns, or contains duplicate patterns. - - - Cache for the method. - - - Clears the cache for the method. - - - Removes a rule set from the method cache if it exists. - The rule set to remove from the cache. - - - Checks if a string contains any of a collections on characters. - The string to see if it contains any of the specified characters. - The characters to check if the string contains any of them. - True if the string contains any of the provided characters. False if not. - - - Removes carriage returns and then replaces all new line characters with System.Environment.NewLine. - The string to standardize the new lines of. - The new line standardized string. - - - Creates a string of a repreated string a provided number of times. - The string to repeat. - The number of repetitions of the string to repeat. - The string of the repeated string to repeat. - - - Splits the string into the individual lines. - The string to get the lines of. - an array of the individual lines of the string. - - - Indents every line in a string with a single tab character. - /// The string to indent the lines of. - The indented string. - - - Indents every line in a string with a given number of tab characters. - The string to indent the lines of. - The number of tabs of the indention. - The indented string. - - - Indents after every new line sequence found between two string indeces. - The string to be indented. - The starting index to look for new line sequences to indent. - The starting index to look for new line sequences to indent. - The indented string. - - - Indents after every new line sequence found between two string indeces. - The string to be indented. - The number of tabs of this indention. - The starting index to look for new line sequences to indent. - The starting index to look for new line sequences to indent. - The indented string. - - - Indents a range of line numbers in a string. - The string to indent specified lines of. - The line number to start line indention on. - The line number to stop line indention on. - The string with the specified lines indented. - - - Indents a range of line numbers in a string. - The string to indent specified lines of. - The number of tabs for the indention. - The line number to start line indention on. - The line number to stop line indention on. - The string with the specified lines indented. - - - Adds a string onto the beginning of every line in a string. - The string to pad. - The padding to add to the front of every line. - The padded string. + + Converts a to the English words representation. + The value to convert to English words representation. + The English words representation of the value. - - Adds a string onto the end of every line in a string. - The string to pad. - The padding to add to the front of every line. - The padded string. + + Converts a to the English words representation. + The value to convert to English words representation. + The English words representation of the value. - - Adds a string after every new line squence found between two indeces of a string. - The string to be padded. - The padding to apply after every newline sequence found. - The starting index of the string to search for new line sequences. - The ending index of the string to search for new line sequences. - The padded string. + + Converts a to the English words representation. + The value to convert to English words representation. + The English words representation of the value. - - Adds a string before every new line squence found between two indeces of a string. - The string to be padded. - The padding to apply before every newline sequence found. - The starting index of the string to search for new line sequences. - The ending index of the string to search for new line sequences. - The padded string. + + Converts a to the English words representation. + The value to convert to English words representation. + The English words representation of the value. - - Adds a string after every new line squence found between two indeces of a string. - The string to be padded. - The padding to apply after every newline sequence found. - The starting index of the line in the string to pad. - The ending index of the line in the string to pad. - The padded string. + + Converts a to the English words representation. + The value to convert to English words representation. + The English words representation of the value. - - Adds a string before every new line squence found between two indeces of a string. - The string to be padded. - The padding to apply before every newline sequence found. - The starting index of the line in the string to pad. - The ending index of the line in the string to pad. - The padded string. + + Converts a to the English words representation. + The value to convert to English words representation. + The English words representation of the value. - - Reverses the characters in a string. - The string to reverse the characters of. - The reversed character string. + + Converts a to the English words representation. + The value to convert to English words representation. + The English words representation of the value. - - Removes all the characters from a string based on a predicate. - The string to remove characters from. - The predicate determining removal of each character. - The string after removing any predicated characters. + + Converts a to the English words representation. + The value to convert to English words representation. + The English words representation of the value. - - Counts the number of lines in the string. - The string to get the line count of. - The number of lines in the string. + + Converts a to the English words representation. + The value to convert to English words representation. + The English words representation of the value. Generates a random value. @@ -15371,60 +15267,211 @@ The total weight of all the values in the pool. A randomly selected value from the weighted pool. - - Traverses an array and performs an operation on each value. - The element type in the array. - The operation to perform on each value of th traversal. - The array to traverse. - The operation to perform on each value of th traversal. - The status of the traversal. - - - Traverses an array and performs an operation on each value. - The element type in the array. - The array to traverse. - The operation to perform on each value of th traversal. - The status of the traversal. + + Returns a new in which all occurrences of Unicode patterns in this instance are replaced with a relative Unicode replacements. + Uses Regex without a timeout. + The to perform the replacements on. + The patterns and relative replacements to apply to this . + A new in which all occurrences of Unicode patterns in this instance are replaced with a relative Unicode replacements. + Thrown if any of the parameters are null or contain null values. + Thrown if is empty, contains empty patterns, or contains duplicate patterns. - - Traverses an array and performs an operation on each value. - The element type in the array. - The operation to perform on each value of th traversal. - The array to traverse. - The operation to perform on each value of th traversal. - The status of the traversal. + + Returns a new in which all occurrences of Unicode patterns in this instance are replaced with a relative Unicode replacements. Caches internal values relative to the instance of rules. + Uses Regex without a timeout. This method is not thread-safe. + The to perform the replacements on. + The patterns and relative replacements to apply to this . + A new in which all occurrences of Unicode patterns in this instance are replaced with a relative Unicode replacements. + Thrown if any of the parameters are null or contain null values. + Thrown if is empty, contains empty patterns, or contains duplicate patterns. - - Traverses an array and performs an operation on each value. - The element type in the array. - The array to traverse. - The operation to perform on each value of th traversal. - The status of the traversal. + + Cache for the method. - - Traverses an array and performs an operation on each value. - The element type in the array. - The operation to perform on each value of th traversal. - The array to traverse. - The operation to perform on each value of th traversal. - The status of the traversal. + + Clears the cache for the method. - - Traverses an array and performs an operation on each value. - The element type in the array. - The array to traverse. - The operation to perform on each value of th traversal. - The status of the traversal. + + Removes a rule set from the method cache if it exists. + The rule set to remove from the cache. - - Traverses an array and performs an operation on each value. - The element type in the array. - The array to traverse. - The operation to perform on each value of th traversal. - The status of the traversal. + + Checks if a string contains any of a collections on characters. + The string to see if it contains any of the specified characters. + The characters to check if the string contains any of them. + True if the string contains any of the provided characters. False if not. - - Traverses an array and performs an operation on each value. + + Removes carriage returns and then replaces all new line characters with System.Environment.NewLine. + The string to standardize the new lines of. + The new line standardized string. + + + Creates a string of a repreated string a provided number of times. + The string to repeat. + The number of repetitions of the string to repeat. + The string of the repeated string to repeat. + + + Splits the string into the individual lines. + The string to get the lines of. + an array of the individual lines of the string. + + + Indents every line in a string with a single tab character. + /// The string to indent the lines of. + The indented string. + + + Indents every line in a string with a given number of tab characters. + The string to indent the lines of. + The number of tabs of the indention. + The indented string. + + + Indents after every new line sequence found between two string indeces. + The string to be indented. + The starting index to look for new line sequences to indent. + The starting index to look for new line sequences to indent. + The indented string. + + + Indents after every new line sequence found between two string indeces. + The string to be indented. + The number of tabs of this indention. + The starting index to look for new line sequences to indent. + The starting index to look for new line sequences to indent. + The indented string. + + + Indents a range of line numbers in a string. + The string to indent specified lines of. + The line number to start line indention on. + The line number to stop line indention on. + The string with the specified lines indented. + + + Indents a range of line numbers in a string. + The string to indent specified lines of. + The number of tabs for the indention. + The line number to start line indention on. + The line number to stop line indention on. + The string with the specified lines indented. + + + Adds a string onto the beginning of every line in a string. + The string to pad. + The padding to add to the front of every line. + The padded string. + + + Adds a string onto the end of every line in a string. + The string to pad. + The padding to add to the front of every line. + The padded string. + + + Adds a string after every new line squence found between two indeces of a string. + The string to be padded. + The padding to apply after every newline sequence found. + The starting index of the string to search for new line sequences. + The ending index of the string to search for new line sequences. + The padded string. + + + Adds a string before every new line squence found between two indeces of a string. + The string to be padded. + The padding to apply before every newline sequence found. + The starting index of the string to search for new line sequences. + The ending index of the string to search for new line sequences. + The padded string. + + + Adds a string after every new line squence found between two indeces of a string. + The string to be padded. + The padding to apply after every newline sequence found. + The starting index of the line in the string to pad. + The ending index of the line in the string to pad. + The padded string. + + + Adds a string before every new line squence found between two indeces of a string. + The string to be padded. + The padding to apply before every newline sequence found. + The starting index of the line in the string to pad. + The ending index of the line in the string to pad. + The padded string. + + + Reverses the characters in a string. + The string to reverse the characters of. + The reversed character string. + + + Removes all the characters from a string based on a predicate. + The string to remove characters from. + The predicate determining removal of each character. + The string after removing any predicated characters. + + + Counts the number of lines in the string. + The string to get the line count of. + The number of lines in the string. + + + Traverses an array and performs an operation on each value. + The element type in the array. + The operation to perform on each value of th traversal. + The array to traverse. + The operation to perform on each value of th traversal. + The status of the traversal. + + + Traverses an array and performs an operation on each value. + The element type in the array. + The array to traverse. + The operation to perform on each value of th traversal. + The status of the traversal. + + + Traverses an array and performs an operation on each value. + The element type in the array. + The operation to perform on each value of th traversal. + The array to traverse. + The operation to perform on each value of th traversal. + The status of the traversal. + + + Traverses an array and performs an operation on each value. + The element type in the array. + The array to traverse. + The operation to perform on each value of th traversal. + The status of the traversal. + + + Traverses an array and performs an operation on each value. + The element type in the array. + The operation to perform on each value of th traversal. + The array to traverse. + The operation to perform on each value of th traversal. + The status of the traversal. + + + Traverses an array and performs an operation on each value. + The element type in the array. + The array to traverse. + The operation to perform on each value of th traversal. + The status of the traversal. + + + Traverses an array and performs an operation on each value. + The element type in the array. + The array to traverse. + The operation to perform on each value of th traversal. + The status of the traversal. + + + Traverses an array and performs an operation on each value. The element type in the array. The operation to perform on each value of th traversal. The array to traverse. @@ -15533,56 +15580,26 @@ The length of the second dimension. The constructed jagged array. + + Constructs a square jagged array of the desired dimensions. + The generic type to store in the jagged array. + The length of the first dimension. + The length of the second dimension. + The function to initialize the values with. + The constructed jagged array. + Constructs a square jagged array of the desired dimensions. The generic type to store in the jagged array. The length of each dimension. The constructed jagged array. - - Converts a to the English words representation. - The value to convert to English words representation. - The English words representation of the value. - - - Converts a to the English words representation. - The value to convert to English words representation. - The English words representation of the value. - - - Converts a to the English words representation. - The value to convert to English words representation. - The English words representation of the value. - - - Converts a to the English words representation. - The value to convert to English words representation. - The English words representation of the value. - - - Converts a to the English words representation. - The value to convert to English words representation. - The English words representation of the value. - - - Converts a to the English words representation. - The value to convert to English words representation. - The English words representation of the value. - - - Converts a to the English words representation. - The value to convert to English words representation. - The English words representation of the value. - - - Converts a to the English words representation. - The value to convert to English words representation. - The English words representation of the value. - - - Converts a to the English words representation. - The value to convert to English words representation. - The English words representation of the value. + + Constructs a square jagged array of the desired dimensions. + The generic type to store in the jagged array. + The length of each dimension. + The function to initialize the values with. + The constructed jagged array. Times an action using System.DateTime. @@ -29950,2142 +29967,2180 @@ Root type of the static functional methods in Towel. + Root type of the static functional methods in Towel. + Root type of the static functional methods in Towel. + Root type of the static functional methods in Towel. + Root type of the static functional methods in Towel. + Root type of the static functional methods in Towel. + Root type of the static functional methods in Towel. + Root type of the static functional methods in Towel. + Root type of the static functional methods in Towel. + Root type of the static functional methods in Towel. - - a * b + c + + The generic element type of the indexed collection. + The action to perform on each permutation. + The status checker for cancellation. + The get index operation of the collection. + The set index operation of the collection. + The starting index of the values to permute. + The ending index of the values to permute. + The action to perform on each permutation. + The status checker for cancellation. + The get index operation of the collection. + The set index operation of the collection. + The array to iterate the permutations of. + The list to iterate the permutations of. + The span of the permutation. - - d - a * b / c + + Iterates through all the permutations of an indexed collection (using a recursive algorithm). + - - Swaps two values. - The type of values to swap. - The first value of the swap. - The second value of the swap. + + Iterates through all the permutations of an indexed collection (using an iterative algorithm). + - - Gets the file path of the current location in source code. - Intended to leave default. This value is set by the compiler via . - The file path of the current location in source code. + + - - Gets the member name of the current location in source code. - Intended to leave default. This value is set by the compiler via . - The member name of the current location in source code. + + - - Gets the line number of the current location in source code. - Intended to leave default. This value is set by the compiler via . - The line number of the current location in source code. + + - - Tries to parse a into a value of the type . - The type to parse the into a value of. - The to parse into a value ot type . - - ( Success, Value) - - Success: True if the parse was successful; False if not. - - Value: The value if the parse was successful or default if not. - + + - - Static wrapper for the instance based "object.GetHashCode" function. - The generic type of the hash operation. - The item to get the hash code of. - The computed hash code using the base GetHashCode instance method. + + - - Converts from to . - The type of the value to convert. - The type to convert teh value to. - The value to convert. - The value of type. + + - - Iterates a and joins the results of a System.Func<int, string> seperated by a . - The range of values to use use on the <System.Func{int, string> . - The System.Func<int, string>. - The seperator to join the values with. - The resulting of the join. + + - - Stepper was not broken. + + - - Stepper was broken. + + - - The Goal was found. + + - - The left operand is less than the right operand. + + - - The left operand is equal to the right operand. + + - - The left operand is greater than the right operand. + + - - There is no bound. + + - - The default case in a Switch statement (true). + + - - Syntax sugar Switch statements. - The possible actions of the Switch statement. + + - - Syntax sugar Switch statements. - The generic type parameter to the Switch statement. - The value argument of the Switch statement. - The delegate for the Switch statement. + + + Generates unique random values in the + [..] range where is + inclusive and is exclusive. + + The function to perform on each generated value. + The random to generation algorithm. + The random to generation algorithm. + The number of values to generate. + Inclusive endpoint of the random generation range. + Exclusive endpoint of the random generation range. + The function to perform on each generated value. - - Definitions for Switch syntax. + + + Generates unique random values in the + [..] range where is + inclusive and is exclusive. + + The function to perform on each generated value. + The random to generation algorithm. + The random to generation algorithm. + The number of values to generate. + Inclusive endpoint of the random generation range. + Exclusive endpoint of the random generation range. + The function to perform on each generated value. - - Delegate with params intended to be used with the Switch syntax. + + + Generates unique random values in the + [..] range where is + inclusive and is exclusive. + + The function to perform on each generated value. + The random to generation algorithm. + The random to generation algorithm. + The number of values to generate. + Inclusive endpoint of the random generation range. + Exclusive endpoint of the random generation range. + The function to perform on each generated value. - - Intended to be used with Switch syntax. + + + Generates unique random values in the + [..] range where is + inclusive and is exclusive. + + The random to generation algorithm. + The random to generation algorithm. + The number of values to generate. + Inclusive endpoint of the random generation range. + Exclusive endpoint of the random generation range. + The function to perform on each generated value. - - The default keyword for the the Switch syntax. + + + Generates unique random values in the + [..] range where is + inclusive and is exclusive. + + The random to generation algorithm. + The random to generation algorithm. + The number of values to generate. + Inclusive endpoint of the random generation range. + Exclusive endpoint of the random generation range. - - Represents the result of a conditional expression inside Switch syntax. - The generic type of the Switch condition for equality checks. + + Attempts to parse a Roman Numeral into an value. + The Roman Numeral to parse into an value. + + ( Success, Value) + - Success: true if the parse was successful or false if not + - Value: the parsed value if the parse was successful or default if not + - - Resolves the condition to a bool. + + Performs a binary search on sorted indexed data. + The type of elements to search through. + The function for getting an element at an index. + The function for sifting through the elements. + The compare function. + The starting index of the binary search. + The number of elements to be searched after the starting . + The function for getting an element at an index. + The function for comparing the the elements to th desired target. + The array search. + The element to search for. + The compare function. + The span of the binary search. + + ( Found, Index, Value) + - Found: True if a match was found; False if not. + - Index: The resulting index of the search that will always be <= the desired match. + - Value: The resulting value of the binary search if a match was found or default if not. + - - Casts a to a bool using an equality check. + + - - Uses the bool as the condition result. + + - - Converts a keyword to a condition result (for "Default" case). + + - - The value of this condition for an equality check. + + - - Represents the result of a conditional expression inside Switch syntax. + + - - Resolves the condition to a bool. + + - - Uses the bool as the condition result. + + The status of a graph search algorithm. - - Converts a keyword to a condition result (for "Default" case). + + Graph search was not broken. - - Converts a condition to a bool using the Resolve method. + + Graph search was broken. - - Allows chance syntax with "using static Towel.Syntax;". - 25% Chance + + Graph search found the goal. - - Struct that allows percentage syntax that will be evaluated at runtime. + + Syntax sugar hacks. - - The random algorithm currently being used by chance syntax. + + This is a syntax sugar hack to allow implicit conversions from StepStatus to GraphSearchStatus. - - Creates a chance from a percentage that will be evaluated at runtime. - The value of the percentage. - The chance syntax struct object. - True if the the chance hits. False if not. + + Constructs a new graph search status. + The status of the graph search. - - Used for inequality syntax. - The generic type of elements the inequality is being used on. + + Converts a into a . + The to convert. - - Contructs a new . - The initial value of the running inequality. + + Converts a into a . + The to convert. - - Adds a greater than operation to a running inequality. - The current running inequality and left hand operand. - The value of the right hand operand of the greater than operation. - A running inequality with the additonal greater than operation. + + Converts a into a . + The to convert. - - Adds a less than operation to a running inequality. - The current running inequality and left hand operand. - The value of the right hand operand of the less than operation. - A running inequality with the additonal less than operation. + + Step function for all neigbors of a given node. + The node type of the graph being searched. + The node to step through all the neighbors of. + Step function to perform on all neighbors. - - Adds a greater than or equal operation to a running inequality. - The current running inequality and left hand operand. - The value of the right hand operand of the greater than or equal operation. - A running inequality with the additonal greater than or equal operation. + + Computes the heuristic value of a given node in a graph (smaller values mean closer to goal node). + The node type of the graph being searched. + The numeric to use when performing calculations. + The node to compute the heuristic value of. + The computed heuristic value for this node. - - Adds a less than or equal operation to a running inequality. - The current running inequality and left hand operand. - The value of the right hand operand of the less than or equal operation. - A running inequality with the additonal less than or equal operation. + + Computes the cost of moving from the current node to a specific neighbor. + The node type of the graph being searched. + The numeric to use when performing calculations. + The current (starting) node. + The node to compute the cost of movign to. + The computed cost value of movign from current to neighbor. - - Adds an equal operation to a running inequality. - The current running inequality and left hand operand. - The value of the right hand operand of the equal operation. - A running inequality with the additonal equal operation. + + Predicate for determining if we have reached the goal node. + The node type of the graph being searched. + The current node. + True if the current node is a/the goal node; False if not. - - Adds an inequal operation to a running inequality. - The current running inequality and left hand operand. - The value of the right hand operand of the inequal operation. - A running inequality with the additonal inequal operation. + + Checks the status of a graph search. + The node type of the search. + The current node of the search. + The status of the search. - - This member is not intended to be invoked. - This member is not intended to be invoked. + + The node type of the graph being searched. + The numeric to use when performing calculations. + The node to start at. + Step function for all neigbors of a given node. + Computes the heuristic value of a given node in a graph. + Computes the cost of moving from the current node to a specific neighbor. + Checks the status of the search. + The total cost of the path if a path was found. + The goal of the search. + The graph to perform the search on. + Stepper of the shortest path or null if no path exists. - - This member is not intended to be invoked. - This member is not intended to be invoked. - This member is not intended to be invoked. + + Runs the A* search algorithm on a graph. + - - This member is not intended to be invoked. - This member is not intended to be invoked. + + - - Helper type for inequality syntax. Contains an Inequality type that has been operator validated. + + - - Used for inequality syntax. - The generic type of elements the inequality is being used on. + + - - Converts this running inequality into the result of the expression. - The inequality to convert into the result of the expression. + + - - Adds a greater than operation to a running inequality. - The current running inequality and left hand operand. - The value of the right hand operand of the greater than operation. - A running inequality with the additonal greater than operation. + + - - Adds a less than operation to a running inequality. - The current running inequality and left hand operand. - The value of the right hand operand of the less than operation. - A running inequality with the additonal less than operation. + + - - Adds a greater than or equal operation to a running inequality. - The current running inequality and left hand operand. - The value of the right hand operand of the greater than or equal operation. - A running inequality with the additonal greater than or equal operation. + + - - Adds a less than or equal operation to a running inequality. - The current running inequality and left hand operand. - The value of the right hand operand of the less than or equal operation. - A running inequality with the additonal less than or equal operation. + + Runs the Dijkstra search algorithm on a graph. + - - Adds an equal operation to a running inequality. - The current running inequality and left hand operand. - The value of the right hand operand of the equal operation. - A running inequality with the additonal equal operation. + + - - Adds an inequal operation to a running inequality. - The current running inequality and left hand operand. - The value of the right hand operand of the inequal operation. - A running inequality with the additonal inequal operation. + + - - Converts the result of this inequality to a . - The result of this inequality converted to a . + + - - This member is not intended to be invoked. - This member is not intended to be invoked. - This member is not intended to be invoked. + + - - This member is not intended to be invoked. - This member is not intended to be invoked. + + - - Universal Quantification Operator. - The element type of the universal quantification to declare. - The values of the universal quantification. - The declared universal quantification. + + - - Universal Quantification. - The element type of the universal quantification. + + - - Constructs a new universal quantification from an array. - The array value of the universal quantification. + + Runs the Breadth-First-Search search algorithm on a graph. + - - The number of values in this universal quantification. + + - - Iterates each value in this universal quantification and performs an action for each element. - The action to perform on every step of the iteration. + + - - Iterates each value in this universal quantification and performs an action for each element. + + - - Index property for get/set operations. - The index to get/set. - The value at the provided index. + + - - Gets the number of elements in this universal quantification. + + - - Gets a value indicating whether the is read-only. + + - - Adds an item to this universal quantifier. - The item to add to this universal quantifier. + + - - Not intended to be invoked directly. + + Computes the maximum of two numeric values. + The numeric type of the operation. + The first operand of the maximum operation. + The second operand of the maximum operation. + The computed maximum of the provided values. - - Not intended to be invoked directly. + + Computes the maximum of multiple numeric values. + The numeric type of the operation. + The first operand of the maximum operation. + The second operand of the maximum operation. + The third operand of the maximum operation. + The remaining operands of the maximum operation. + The computed maximum of the provided values. - - Not intended to be invoked directly. + + Computes the maximum of multiple numeric values. + The numeric type of the operation. + The set of data to compute the maximum of. + The computed maximum of the provided values. - - Not intended to be invoked directly. + + Computes the minimum of two numeric values. + The numeric type of the operation. + The first operand of the minimum operation. + The second operand of the minimum operation. + The computed minimum of the provided values. - - Not intended to be invoked directly. + + Computes the minimum of multiple numeric values. + The numeric type of the operation. + The first operand of the minimum operation. + The second operand of the minimum operation. + The third operand of the minimum operation. + The remaining operands of the minimum operation. + The computed minimum of the provided values. - - Not intended to be invoked directly. + + Computes the minimum of multiple numeric values. + The numeric type of the operation. + The set of data to compute the minimum of. + The computed minimum of the provided values. - - Not intended to be invoked directly. + + Computes the minimum of multiple numeric values. + The first operand of the minimum operation. + The second operand of the minimum operation. + The third operand of the minimum operation. + The computed minimum of the provided values. - - Gets the for this universal quantification. - The for this universal quantification. + + Gets the range (minimum and maximum) of a set of data. + The numeric type of the operation. + /// The set of data to get the range of. + The minimum of the set of data. + The maximum of the set of data. + Throws when stepper is null. + Throws when stepper is empty. - - Converts a universal quantification to an array. - The universal quantification to be converted. + + Gets the range (minimum and maximum) of a set of data. + The numeric type of the operation. + /// The set of data to get the range of. + The minimum of the set of data. + The maximum of the set of data. + Throws when stepper is null. + Throws when stepper is empty. - - Converts a universal quantification to a . - The universal quantification to be converted. + + Gets the mode(s) of a data set. + The generic type of the data. + The action to perform on every mode value found. + The first value of the data set. + The rest of the data set. - - Converts a universal quantification to an . - The universal quantification to be converted. + + Gets the mode(s) of a data set. + The generic type of the data. + The action to perform on every mode value found. + The equality delegate. + The first value of the data set. + The rest of the data set. - - Converts a universal quantification to a . - The universal quantification to be converted. + + Gets the mode(s) of a data set. + The generic type of the data. + The action to perform on every mode value found. + The hash code delegate + The first value of the data set. + The rest of the data set. - - Converts a universal quantification to an . - The universal quantification to be converted. + + Gets the mode(s) of a data set. + The generic type of the data. + The action to perform on every mode value found. + The equality delegate. + The hash code delegate + The first value of the data set. + The rest of the data set. - - Converts a universal quantification to an . - The universal quantification to be converted. + + Gets the mode(s) of a data set. + The generic type of the data. + The data set. + The action to perform on every mode value found. + The equality delegate. + The hash code delegate + The modes of the data set. - - Converts a universal quantification to a sorted . - The universal quantification to be converted. + + Computes the mean of a set of numerical values. + The numeric type of the operation. + The first value of the set of data to compute the mean of. + The remaining values in the data set to compute the mean of. + The computed mean of the set of data. - - Converts a universal quantification to an Action<Action<T>>. - The universal quantification to be converted. + + Computes the mean of a set of numerical values. + The numeric type of the operation. + The set of data to compute the mean of. + The computed mean of the set of data. - - Converts a universal quantification to an . - The universal quantification to be converted. + + Computes the median of a set of data. + The numeric type of the operation. + The comparison algorithm to sort the data by. + The set of data to compute the median of. + The computed median value of the set of data. - - Converts a universal quantification to an Func<Func<T, StepStatus>, StepStatus>. - The universal quantification to be converted. + + Computes the median of a set of data. + The numeric type of the operation. + The comparison algorithm to sort the data by. + The set of data to compute the median of. + The computed median value of the set of data. - - Converts a universal quantification to an . - The universal quantification to be converted. + + Computes the median of a set of data. + The numeric type of the operation. + The set of data to compute the median of. + The computed median value of the set of data. - - Converts a universal quantification to an . - The universal quantification to be converted. + + Computes the median of a set of data. + The numeric type of the operation. + The set of data to compute the median of. + The computed median value of the set of data. - - Converts a universal quantification to an . - The universal quantification to be converted. + + Computes the geometric mean of a set of numbers. + The numeric type of the computation. + The set of numbres to compute the geometric mean of. + The computed geometric mean of the set of numbers. - - Converts a universal quantification to an . - The universal quantification to be converted. + + Computes the variance of a set of numbers. + The numeric type of the computation. + The set of numbers to compute the variance of. + The computed variance of the set of numbers. - - Checks for equality of two values [ == ]. - The type of the operation. - The left operand. - The right operand. - The result of the equality check. + + Computes the standard deviation of a set of numbers. + The numeric type of the computation. + The set of numbers to compute the standard deviation of. + The computed standard deviation of the set of numbers. - - Checks for equality among multiple values [ == == == ...]. - The numeric type of the operation. - The first operand of the equality check. - The second operand of the equality check. - The remaining operands of the equality check. - True if all operands are equal or false if not. + + The mean deviation of a set of numbers. + The numeric type of the computation. + The set of numbers to compute the mean deviation of. + The computed mean deviation of the set of numbers. - - Determines if two sequences are equal. - The element type of the sequences. - The first sequence of the equate. - The second sequence of the equate. - The element equate function. - The inclusive starting index to equate from. - The inclusive ending index to equate to. - The first sequence of the equate. - The second sequence of the equate. - The element equate function. - True if the spans are equal; False if not. + + Computes the quantiles of a set of data. + The generic data type. + The number of quantiles to compute. + The data stepper. + The computed quantiles of the data set. - - Determines if two spans are equal. - The element type of the spans. - The first span of the equate. - The second span of the equate. - The element equate function. - True if the spans are equal; False if not. + + Counts the number of occurences of each item. + The generic type to count the occerences of. + The first value in the data. + The rest of the data. + The occurence map of the data. - - Determines if two spans are equal. - The element type of the spans. - The element equate function. - The first span of the equate. - The second span of the equate. - The element equate function. - True if the spans are equal; False if not. + + Counts the number of occurences of each item. + The generic type to count the occerences of. + The equality delegate. + The first value in the data. + The rest of the data. + The occurence map of the data. - - Determines if two spans are equal. - The element type of the spans. - The inclusive starting index to equate from. - The inclusive ending index to equate to. - The first span of the equate. - The second span of the equate. - The element equate function. - True if the spans are equal; False if not. + + Counts the number of occurences of each item. + The generic type to count the occerences of. + The hash code delegate. + The first value in the data. + The rest of the data. + The occurence map of the data. - - Determines if two spans are equal. - The element type of the spans. - The element equate function. - The inclusive starting index to equate from. - The inclusive ending index to equate to. - The first span of the equate. - The second span of the equate. - The element equate function. - True if the spans are equal; False if not. - - - Checks for inequality of two values [ != ]. - The type of the left operand. - The type of the right operand. - The type of the return. - The left operand. - The right operand. - The result of the inequality. - - - Checks for inequality of two values [ != ]. - The numeric type of the operation. - The first operand of the inequality check. - The second operand of the inequality check. - The result of the inequality check. - - - Checks if one value is less than another [ < ]. - The type of the left operand. - The type of the right operand. - The type of the return. - The left operand. - The right operand. - The result of the less than operation. - - - Checks if one value is less than another [ < ]. - The numeric type of the operation. - The first operand of the less than check. - The second operand of the less than check. - The result of the less than check. - - - Checks if one value is greater than another [ > ]. - The type of the left operand. - The type of the right operand. - The type of the return. - The left operand. - The right operand. - The result of the greater than operation. - - - Checks if one value is greater than another [ > ]. - The numeric type of the operation. - The first operand of the greater than check. - The second operand of the greater than check. - The result of the greater than check. + + Counts the number of occurences of each item. + The generic type to count the occerences of. + The equality delegate. + The hash code delegate. + The first value in the data. + The rest of the data. + The occurence map of the data. - - Checks if one value is less than or equal to another [ <= ]. - The type of the left operand. - The type of the right operand. - The type of the return. - The left operand. - The right operand. - The result of the less than or equal to operation. + + Counts the number of occurences of each item. + The generic type to count the occerences of. + The data to count the occurences of. + The equality delegate. + The hash code delegate. + The occurence map of the data. - - Checks if one value is less than or equal to another [ <= ]. - The numeric type of the operation. - The first operand of the less than or equal to check. - The second operand of the less than or equal to check. - The result of the less than or equal to check. + + Computes the Hamming distance (using an iterative algorithm). + The element type of the sequences. + The get index function for the first sequence. + The get index function for the second sequence. + The equality check function. + The length of the sequences. + The get index function for the first sequence. + The get index function for the second sequence. + The equality check function. + The computed Hamming distance of the two sequences. - - Checks if one value is less greater or equal to another [ >= ]. - The type of the left operand. - The type of the right operand. - The type of the return. - The left operand. - The right operand. - The result of the greater than or equal to operation. + + Computes the Hamming distance (using an recursive algorithm). + The first sequence of the operation. + The second sequence of the operation. + The computed Hamming distance of the two sequences. - - Checks if one value is greater than or equal to another [ >= ]. - The numeric type of the operation. - The first operand of the greater than or equal to check. - The second operand of the greater than or equal to check. - The result of the greater than or equal to check. + + Computes the Hamming distance (using an recursive algorithm). + The element type of the sequences. + The equality check function. + The first sequence. + The second sequence. + The equality check function. + The computed Hamming distance of the two sequences. - - Compares two values. - The type of values to compare. - The first value of the comparison. - The second value of the comparison. - The result of the comparison. + + Computes the Levenshtein distance (using an recursive algorithm). + The element type of the sequences. + The get index function for the first sequence. + The get index function for the second sequence. + The equality check function. + The length of the first sequence. + The length of the second sequence. + The get index function for the first sequence. + The get index function for the second sequence. + The equality check function. + The computed Levenshtein distance of the two sequences. - - Negates a value [-]. - The type of the value to negate. - The resulting type of the negation. - The value to negate. - The result of the negation [-]. + + Computes the Levenshtein distance (using an recursive algorithm). + The first sequence of the operation. + The second sequence of the operation. + The computed Levenshtein distance of the two sequences. - - Negates a value [-]. - The type of the value to negate. - The value to negate. - The result of the negation [-]. + + Computes the Levenshtein distance (using an recursive algorithm). + The element type of the sequences. + The equality check function. + The first sequence. + The second sequence. + The equality check function. + The computed Levenshtein distance of the two sequences. - - Adds two values [ + ]. - The type of the left operand. - The type of the right operand. - The type of the return. - The left operand. - The right operand. - The result of the addition [ + ]. + + Computes the Levenshtein distance (using an iterative algorithm). + The element type of the sequences. + The get index function for the first sequence. + The get index function for the second sequence. + The equality check function. + The length of the first sequence. + The length of the second sequence. + The get index function for the first sequence. + The get index function for the second sequence. + The equality check function. + The computed Levenshtein distance of the two sequences. - - Adds two values [ + ]. - The numeric type of the operation. - The left operand. - The right operand. - The result of the addition [ + ]. + + Computes the Levenshtein distance (using an iterative algorithm). + The first sequence of the operation. + The second sequence of the operation. + The computed Levenshtein distance of the two sequences. - - Adds multiple values [ + + + ...]. - The type of the operation. - The first operand of the addition. - The second operand of the addition. - The third operand of the addition. - The remaining operands of the addition. - The result of the addition [ + + + ...]. + + Computes the Levenshtein distance (using an iterative algorithm). + The element type of the sequences. + The equality check function. + The first sequence. + The second sequence. + The equality check function. + The computed Levenshtein distance of the two sequences. - - Adds multiple values [step1 + step2 + step3 + ...]. - The type of the operation. - The stepper of the values to add. - The result of the addition [step1 + step2 + step3 + ...]. + + The type of values to sort. + The compare function. + The get function. + The compare function. + The get function. + The starting index of the sort. + The ending index of the sort. + The span to be sorted. - - Subtracts two values [ - ]. - The type of the left operand. - The type of the right operand. - The type of the return. - The left operand. - The right operand. - The result of the subtraction [ - ]. + + - - Subtracts two values [ - ]. - The type of the operation. - The left operand. - The right operand. - The result of the subtraction [ - ]. + + - - Subtracts multiple values [ - - - ...]. - The type of the operation. - The first operand. - The second operand. - The third operand. - The remaining values. - The result of the subtraction [ - - - ...]. + + - - Subtracts multiple numeric values [step1 - step2 - step3 - ...]. - The numeric type of the operation. - The stepper containing the values. - The result of the subtraction [step1 - step2 - step3 - ...]. + + - - Multiplies two values [ * ]. - The type of the left operand. - The type of the right operand. - The type of the return. - The left operand. - The right operand. - The result of the multiplication [ * ]. + + - - Multiplies two values [ * ]. - The type of the operation. - The left operand. - The right operand. - The result of the multiplication [ * ]. + + - - Multiplies multiple values [ * * * ...]. - The type of the operation. - The first operand. - The second operand. - The third operand. - The remaining values. - The result of the multiplication [ * * * ...]. + + Determines if a sequence is a palindrome. + The element type of the sequence. + The inclusive starting index of the palindrome check. + The inclusive ending index of the palindrome check. + The element equate function. + The get index function of the sequence. + True if the sequence is a palindrome; False if not. - - Multiplies multiple values [step1 * step2 * step3 * ...]. - The type of the operation. - The stepper containing the values. - The result of the multiplication [step1 * step2 * step3 * ...]. + + Determines if a sequence is a palindrome. + The element type of the sequence. + The get index function of the sequence. + The inclusive starting index of the palindrome check. + The inclusive ending index of the palindrome check. + The element equate function. + The get index function of the sequence. + True if the sequence is a palindrome; False if not. - - Divides two values [ / ]. - The type of the left operand. - The type of the right operand. - The type of the return. - The left operand. - The right operand. - The result of the division [ / ]. + + Determines if a sequence is a palindrome. + The element type of the sequence. + The element equate function. + The get index function of the sequence. + The inclusive starting index of the palindrome check. + The inclusive ending index of the palindrome check. + The element equate function. + The get index function of the sequence. + True if the sequence is a palindrome; False if not. - - Divides two values [ / ]. - The type of the operation. - The left operand. - The right operand. - The result of the division [ / ]. + + Determines if a sequence is a palindrome. + The span to check. + True if the sequence is a palindrome; False if not. - - Divides multiple values [ / / / ...]. - The type of the operation. - The first operand of the division. - The second operand of the division. - The third operand of the division. - The remaining values of the division. - The result of the division [ / / / ...]. + + Determines if a sequence is a palindrome. + The element type of the sequence. + The span to check. + The element equate function. + True if the sequence is a palindrome; False if not. - - Divides multiple values [step1 / step2 / step3 / ...]. - The type of the operation. - The stepper containing the values. - The result of the division [step1 / step2 / step3 / ...]. + + Determines if a sequence is a palindrome. + The element type of the sequence. + The element equate function. + The span to check. + The element equate function. + True if the sequence is a palindrome; False if not. - - Remainders two values [ % ]. - The type of the left operand. - The type of the right operand. - The type of the return. - The left operand. - The right operand. - The result of the remainder operation [ % ]. + + The element type of the sequences. + The first sequence to determine if is interleaved of. + The second sequence to determine if is interleaved of. + The sequence to determine if it is interleaved from and . + The function for equating values. + True if is interleaved of and or False if not. + + + IsInterleaved("abc", "xyz", "axbycz") // True + IsInterleaved("abc", "xyz", "cbazyx") // False (order not preserved) + IsInterleaved("abc", "xyz", "012345") // False + + - - Modulos two numeric values [ % ]. - The numeric type of the operation. - The first operand of the modulation. - The second operand of the modulation. - The result of the modulation. + + + + Determines if is interleved of and , + meaning that it contains all elements of and + while retaining the order of the respective elements. Uses a recursive algorithm. + + Runtime: O(2^(Min(.Length + .Length, .Length))), Ω(1) + Memory: O(1) + + - - Modulos multiple numeric values [ % % % ...]. - The numeric type of the operation. - The first operand of the modulation. - The second operand of the modulation. - The third operand of the modulation. - The remaining values of the modulation. - The result of the modulation. + + + Determines if is interleved of and , + meaning that it contains all elements of and + while retaining the order of the respective elements. Uses a interative algorithm. + Runtime: O(Min(.Length * .Length))), Ω(1) + Memory: O(.Length * .Length) + + - - Modulos multiple numeric values [step_1 % step_2 % step_3...]. - The numeric type of the operation. - The stepper containing the values. - The result of the modulation. + + - - Inverts a numeric value [1 / a]. - The numeric type of the operation. - The numeric value to invert. - The result of the inversion. + + - - Powers two numeric values [a ^ b]. - The numeric type of the operation. - The first operand of the power. - The first operand of the power. - The result of the power. + + - - Powers multiple numeric values [a ^ b ^ c...]. - The numeric type of the operation. - The first operand of the power. - The second operand of the power. - The third operand of the power. - The remaining values of the power. - The result of the power. + + - - Powers multiple numeric values [step_1 ^ step_2 ^ step_3...]. - The numeric type of the operation. - The stepper containing the values. - The result of the power. + + - - Square roots a numeric value [√a]. - The numeric type of the operation. - The numeric value to square root. - The result of the square root. + + - - Roots two numeric values [a ^ (1 / b)]. - The numeric type of the operation. - The base of the root. - The root of the operation. - The result of the root. + + + Sorts values into a randomized order. + Runtime: O(n) + Memory: O(1) + + The type of values to sort. + The get function. + The set function. + The starting index of the shuffle. + The ending index of the shuffle. + The get function. + The set function. + The random to shuffle with. + The array to shuffle. - - Computes the logarithm of a value. - The numeric type of the operation. - The value to compute the logarithm of. - The base of the logarithm to compute. - The computed logarithm value. + + - - Determines if a numerical value is an integer. - The numeric type of the operation. - The value to determine integer status of. - Whether or not the value is an integer. + + - - Determines if a numerical value is non-negative. - The numeric type of the operation. - The value to determine non-negative status of. - Whether or not the value is non-negative. + + - - Determines if a numerical value is negative. - The numeric type of the operation. - The value to determine negative status of. - Whether or not the value is negative. + + - - Determines if a numerical value is positive. - The numeric type of the operation. - The value to determine positive status of. - Whether or not the value is positive. + + - - Determines if a numerical value is even. - The numeric type of the operation. - The value to determine even status of. - Whether or not the value is even. + + The type of values to sort. + The compare function. + The get function. + The set function. + The compare function. + The get function. + The set function. + The starting index of the sort. + The ending index of the sort. + The array to be sorted. + The span to be sorted. - - Determines if a numerical value is odd. - The numeric type of the operation. - The value to determine odd status of. - Whether or not the value is odd. + + + Sorts values using the bubble sort algorithm. + Runtime: Ω(n), ε(n^2), O(n^2) + Memory: O(1) + Stable: True + + - - Determines if a numerical value is prime. - The numeric type of the operation. - The value to determine prime status of. - Whether or not the value is prime. + + - - Gets the absolute value of a value. - The numeric type of the operation. - The value to get the absolute value of. - The absolute value of the provided value. + + - - Computes the maximum of two numeric values. - The numeric type of the operation. - The first operand of the maximum operation. - The second operand of the maximum operation. - The computed maximum of the provided values. + + - - Computes the maximum of multiple numeric values. - The numeric type of the operation. - The first operand of the maximum operation. - The second operand of the maximum operation. - The third operand of the maximum operation. - The remaining operands of the maximum operation. - The computed maximum of the provided values. + + - - Computes the maximum of multiple numeric values. - The numeric type of the operation. - The set of data to compute the maximum of. - The computed maximum of the provided values. + + + Sorts values using the selection sort algoritm. + Runtime: Ω(n^2), ε(n^2), O(n^2) + Memory: O(1) + Stable: False + + - - Computes the minimum of two numeric values. - The numeric type of the operation. - The first operand of the minimum operation. - The second operand of the minimum operation. - The computed minimum of the provided values. + + - - Computes the minimum of multiple numeric values. - The numeric type of the operation. - The first operand of the minimum operation. - The second operand of the minimum operation. - The third operand of the minimum operation. - The remaining operands of the minimum operation. - The computed minimum of the provided values. + + - - Computes the minimum of multiple numeric values. - The numeric type of the operation. - The set of data to compute the minimum of. - The computed minimum of the provided values. + + - - Computes the minimum of multiple numeric values. - The first operand of the minimum operation. - The second operand of the minimum operation. - The third operand of the minimum operation. - The computed minimum of the provided values. + + - - Gets a value restricted to a minimum and maximum range. - The numeric type of the operation. - The value to clamp. - The minimum of the range to clamp the value by. - The maximum of the range to clamp the value by. - The value restricted to the provided range. + + + Sorts values using the insertion sort algorithm. + Runtime: Ω(n), ε(n^2), O(n^2) + Memory: O(1) + Stable: True + + - - Checks for equality between two numeric values with a range of possibly leniency. - The numeric type of the operation. - The first operand of the equality check. - The second operand of the equality check. - The allowed distance between the values to still be considered equal. - True if the values are within the allowed leniency of each other. False if not. + + + + + - - Computes the greatest common factor of a set of numbers. - The numeric type of the computation. - The first operand of the greatest common factor computation. - The second operand of the greatest common factor computation. - The remaining operands of the greatest common factor computation. - The computed greatest common factor of the set of numbers. + + - - Computes the greatest common factor of a set of numbers. - The numeric type of the computation. - The set of numbers to compute the greatest common factor of. - The computed greatest common factor of the set of numbers. + + - - Computes the least common multiple of a set of numbers. - The numeric type of the operation. - The first operand of the least common muiltiple computation. - The second operand of the least common muiltiple computation. - The remaining operands of the least common muiltiple computation. - The computed least common least common multiple of the set of numbers. + + + Sorts values using the quick sort algorithm. + Runtime: Ω(n*ln(n)), ε(n*ln(n)), O(n^2) + Memory: ln(n) + Stable: False + + - - Computes the least common multiple of a set of numbers. - The numeric type of the operation. - The set of numbers to compute the least common multiple of. - The computed least common least common multiple of the set of numbers. + + - - Linearly interpolations a value. - The numeric type of the operation. - The value along the first dimension to compute the linear interpolation for. - A known starting point along the first dimension. - A known ending point along the first dimension. - A known starting point along the second dimension. - A known ending point along the second dimension. - The linearly interpolated value. + + - - Computes the factorial of a numeric value [!] == [ * ( - 1) * ( - 2) * ... * 1]. - The numeric type of the operation. - The integer value to compute the factorial of. - The computed factorial value. - Thrown when the parameter is not an integer value. - Thrown when the parameter is less than zero. + + - - Computes the combinations of values using the grouping definitions. - The numeric type of the operation. - The number of values to compute the combinations of. - The groups and how many values fall into each group. - The computed number of combinations. + + - - Computes the Binomial coefficient (N choose n). - The numeric type of the computation. - The size of the entire set (N choose n). - The size of the subset (N choose n). - The computed binomial coefficient (N choose n). + + + Sorts values using the merge sort algorithm. + Runtime: Ω(n*ln(n)), ε(n*ln(n)), O(n*ln(n)) + Memory: Θ(n) + Stable: True + + - - Counts the number of occurences of each item. - The generic type to count the occerences of. - The first value in the data. - The rest of the data. - The occurence map of the data. + + - - Counts the number of occurences of each item. - The generic type to count the occerences of. - The equality delegate. - The first value in the data. - The rest of the data. - The occurence map of the data. + + - - Counts the number of occurences of each item. - The generic type to count the occerences of. - The hash code delegate. - The first value in the data. - The rest of the data. - The occurence map of the data. + + - - Counts the number of occurences of each item. - The generic type to count the occerences of. - The equality delegate. - The hash code delegate. - The first value in the data. - The rest of the data. - The occurence map of the data. + + - - Counts the number of occurences of each item. - The generic type to count the occerences of. - The data to count the occurences of. - The equality delegate. - The hash code delegate. - The occurence map of the data. + + + Sorts values using the heap sort algorithm. + Runtime: Ω(n*ln(n)), ε(n*ln(n)), O(n^2) + Memory: O(1) + Stable: False + + - - Gets the mode(s) of a data set. - The generic type of the data. - The action to perform on every mode value found. - The first value of the data set. - The rest of the data set. + + - - Gets the mode(s) of a data set. - The generic type of the data. - The action to perform on every mode value found. - The equality delegate. - The first value of the data set. - The rest of the data set. + + - - Gets the mode(s) of a data set. - The generic type of the data. - The action to perform on every mode value found. - The hash code delegate - The first value of the data set. - The rest of the data set. + + - - Gets the mode(s) of a data set. - The generic type of the data. - The action to perform on every mode value found. - The equality delegate. - The hash code delegate - The first value of the data set. - The rest of the data set. + + - - Gets the mode(s) of a data set. - The generic type of the data. - The data set. - The action to perform on every mode value found. - The equality delegate. - The hash code delegate - The modes of the data set. + + + Sorts values using the odd even sort algorithm. + Runtime: Ω(n), ε(n^2), O(n^2) + Memory: O(1) + Stable: True + + - - Computes the mean of a set of numerical values. - The numeric type of the operation. - The first value of the set of data to compute the mean of. - The remaining values in the data set to compute the mean of. - The computed mean of the set of data. + + - - Computes the mean of a set of numerical values. - The numeric type of the operation. - The set of data to compute the mean of. - The computed mean of the set of data. + + - - Computes the median of a set of data. - The numeric type of the operation. - The comparison algorithm to sort the data by. - The set of data to compute the median of. - The computed median value of the set of data. + + - - Computes the median of a set of data. - The numeric type of the operation. - The comparison algorithm to sort the data by. - The set of data to compute the median of. - The computed median value of the set of data. + + - - Computes the median of a set of data. - The numeric type of the operation. - The set of data to compute the median of. - The computed median value of the set of data. + + + Sorts values using the bogo sort algorithm. + Runtime: Ω(n), ε(n*n!), O(∞) + Memory: O(1) + Stable: False + + - - Computes the median of a set of data. - The numeric type of the operation. - The set of data to compute the median of. - The computed median value of the set of data. + + - - Computes the geometric mean of a set of numbers. - The numeric type of the computation. - The set of numbres to compute the geometric mean of. - The computed geometric mean of the set of numbers. + + - - Computes the variance of a set of numbers. - The numeric type of the computation. - The set of numbers to compute the variance of. - The computed variance of the set of numbers. + + + + + + + + - - Computes the standard deviation of a set of numbers. - The numeric type of the computation. - The set of numbers to compute the standard deviation of. - The computed standard deviation of the set of numbers. + + - - The mean deviation of a set of numbers. - The numeric type of the computation. - The set of numbers to compute the mean deviation of. - The computed mean deviation of the set of numbers. + + Sorts values using the slow sort algorithm. + - - Gets the range (minimum and maximum) of a set of data. - The numeric type of the operation. - /// The set of data to get the range of. - The minimum of the set of data. - The maximum of the set of data. - Throws when stepper is null. - Throws when stepper is empty. + + - - Gets the range (minimum and maximum) of a set of data. - The numeric type of the operation. - /// The set of data to get the range of. - The minimum of the set of data. - The maximum of the set of data. - Throws when stepper is null. - Throws when stepper is empty. + + - - Computes the quantiles of a set of data. - The generic data type. - The number of quantiles to compute. - The data stepper. - The computed quantiles of the data set. + + - - Computes the exponentional of a value [e ^ ]. - The generic type of the operation. - The value to compute the exponentional of. - The exponential of the value [e ^ ]. + + - - Computes the natural logarithm of a value [ln()]. - The generic type of the operation. - The value to compute the natural log of. - The natural log of the provided value [ln()]. + + Sorts values using the gnome sort algorithm. + - - Computes the sine ratio of an angle using the relative talor series. Accurate but slow. - The numeric type of the operation. - The angle to compute the sine ratio of. - Determines if coputation should continue or is accurate enough. - The taylor series computed sine ratio of the provided angle. + + - - Computes the sine ratio of an angle using the system's sine function. WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). - The numeric type of the operation. - The angle to compute the sine ratio of. - The sine ratio of the provided angle. - WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). + + - - Estimates the sine ratio using piecewise quadratic equations. Fast but NOT very accurate. - The numeric type of the operation. - The angle to compute the quadratic estimated sine ratio of. - The quadratic estimation of the sine ratio of the provided angle. + + - - Computes the cosine ratio of an angle using the relative talor series. Accurate but slow. - The numeric type of the operation. - The angle to compute the cosine ratio of. - Determines if coputation should continue or is accurate enough. - The taylor series computed cosine ratio of the provided angle. + + - - Computes the cosine ratio of an angle using the system's cosine function. WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). - The numeric type of the operation. - The angle to compute the cosine ratio of. - The cosine ratio of the provided angle. - WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). + + Sorts values using the comb sort algorithm. + - - Estimates the cosine ratio using piecewise quadratic equations. Fast but NOT very accurate. - The numeric type of the operation. - The angle to compute the quadratic estimated cosine ratio of. - The quadratic estimation of the cosine ratio of the provided angle. + + - - Computes the tangent ratio of an angle using the relative talor series. Accurate but slow. - The numeric type of the operation. - The angle to compute the tangent ratio of. - The taylor series computed tangent ratio of the provided angle. + + - - Computes the tangent ratio of an angle using the system's tangent function. WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). - The numeric type of the operation. - The angle to compute the tangent ratio of. - The tangent ratio of the provided angle. - WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). + + - - Estimates the tangent ratio using piecewise quadratic equations. Fast but NOT very accurate. - The numeric type of the operation. - The angle to compute the quadratic estimated tangent ratio of. - The quadratic estimation of the tangent ratio of the provided angle. + + - - Computes the cosecant ratio of an angle using the system's sine function. WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). - The numeric type of the operation. - The angle to compute the cosecant ratio of. - The cosecant ratio of the provided angle. - WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). + + Sorts values using the shell sort algorithm. + - - Estimates the cosecant ratio using piecewise quadratic equations. Fast but NOT very accurate. - The numeric type of the operation. - The angle to compute the quadratic estimated cosecant ratio of. - The quadratic estimation of the cosecant ratio of the provided angle. + + - - Computes the secant ratio of an angle using the system's cosine function. WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). - The numeric type of the operation. - The angle to compute the secant ratio of. - The secant ratio of the provided angle. - WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). + + - - Estimates the secant ratio using piecewise quadratic equations. Fast but NOT very accurate. - The numeric type of the operation. - The angle to compute the quadratic estimated secant ratio of. - The quadratic estimation of the secant ratio of the provided angle. + + - - Computes the cotangent ratio of an angle using the system's tangent function. WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). - The numeric type of the operation. - The angle to compute the cotangent ratio of. - The cotangent ratio of the provided angle. - WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). + + - - Estimates the cotangent ratio using piecewise quadratic equations. Fast but NOT very accurate. - The numeric type of the operation. - The angle to compute the quadratic estimated cotangent ratio of. - The quadratic estimation of the cotangent ratio of the provided angle. + + Sorts values using the cocktail sort algorithm. + - - Computes the best fit line from a set of points in 2D space [y = slope * x + y_intercept]. - The numeric type of the operation. - The points to compute the best fit line of. - The slope of the computed best fit line [y = slope * x + y_intercept]. - The y intercept of the computed best fit line [y = slope * x + y_intercept]. + + - - Factors the primes numbers of a numeric integer value. - The numeric type of the operation. - The value to factor the prime numbers of. - The action to perform on all found prime factors. + + - - Computes the Hamming distance (using an iterative algorithm). - The element type of the sequences. - The get index function for the first sequence. - The get index function for the second sequence. - The equality check function. - The length of the sequences. - The get index function for the first sequence. - The get index function for the second sequence. - The equality check function. - The computed Hamming distance of the two sequences. + + - - Computes the Hamming distance (using an recursive algorithm). - The first sequence of the operation. - The second sequence of the operation. - The computed Hamming distance of the two sequences. + + - - Computes the Hamming distance (using an recursive algorithm). - The element type of the sequences. - The equality check function. - The first sequence. - The second sequence. - The equality check function. - The computed Hamming distance of the two sequences. + + Sorts values using the shell cycle algorithm. + - - Computes the Levenshtein distance (using an recursive algorithm). - The element type of the sequences. - The get index function for the first sequence. - The get index function for the second sequence. - The equality check function. - The length of the first sequence. - The length of the second sequence. - The get index function for the first sequence. - The get index function for the second sequence. - The equality check function. - The computed Levenshtein distance of the two sequences. + + - - Computes the Levenshtein distance (using an recursive algorithm). - The first sequence of the operation. - The second sequence of the operation. - The computed Levenshtein distance of the two sequences. + + - - Computes the Levenshtein distance (using an recursive algorithm). - The element type of the sequences. - The equality check function. - The first sequence. - The second sequence. - The equality check function. - The computed Levenshtein distance of the two sequences. + + + + + + + + Sorts values using the shell pancake algorithm. + - - Computes the Levenshtein distance (using an iterative algorithm). - The element type of the sequences. - The get index function for the first sequence. - The get index function for the second sequence. - The equality check function. - The length of the first sequence. - The length of the second sequence. - The get index function for the first sequence. - The get index function for the second sequence. - The equality check function. - The computed Levenshtein distance of the two sequences. + + - - Computes the Levenshtein distance (using an iterative algorithm). - The first sequence of the operation. - The second sequence of the operation. - The computed Levenshtein distance of the two sequences. + + - - Computes the Levenshtein distance (using an iterative algorithm). - The element type of the sequences. - The equality check function. - The first sequence. - The second sequence. - The equality check function. - The computed Levenshtein distance of the two sequences. + + Sorts values using the shell stooge algorithm. + - - The generic element type of the indexed collection. - The action to perform on each permutation. - The status checker for cancellation. - The get index operation of the collection. - The set index operation of the collection. - The starting index of the values to permute. - The ending index of the values to permute. - The action to perform on each permutation. - The status checker for cancellation. - The get index operation of the collection. - The set index operation of the collection. - The array to iterate the permutations of. - The list to iterate the permutations of. - The span of the permutation. + + - - Iterates through all the permutations of an indexed collection (using a recursive algorithm). - + + - - Iterates through all the permutations of an indexed collection (using an iterative algorithm). - + + Default int compare. - - + + Default int compare. + The left hand side of the compare. + The right ahnd side of the compare. + The result of the comparison. - - + + Compares two char values for equality. - - + + Compares two char values for equality. + The first operand of the equality check. + The second operand of the equality check. + True if equal; False if not. - - + + Built in Compare struct for runtime computations. + The generic type of the values to compare. + The compare function. - - + + The invocation of the compile time delegate. - - + + Creates a compile-time-resolved sifting function to be passed into another type. + The value for future values to be compared against. + The compare function. - - + + Compile time resulution to the value. - - + + Returns . + - - + + Struct wrapper for the method as an . - - + + - - + + Casts a to a struct wrapper. - - + + Stepper was not broken. - - + + Stepper was broken. - - + + The Goal was found. - - + + The left operand is less than the right operand. - - + + The left operand is equal to the right operand. - - Performs a binary search on sorted indexed data. - The type of elements to search through. - The function for getting an element at an index. - The function for sifting through the elements. - The compare function. - The starting index of the binary search. - The number of elements to be searched after the starting . - The function for getting an element at an index. - The function for comparing the the elements to th desired target. - The array search. - The element to search for. - The compare function. - The span of the binary search. - - ( Found, Index, Value) - - Found: True if a match was found; False if not. - - Index: The resulting index of the search that will always be <= the desired match. - - Value: The resulting value of the binary search if a match was found or default if not. - + + The left operand is greater than the right operand. - - + + There is no bound. - - + + The default case in a Switch statement (true). - - + + Syntax sugar Switch statements. + The possible actions of the Switch statement. - - + + Syntax sugar Switch statements. + The generic type parameter to the Switch statement. + The value argument of the Switch statement. + The delegate for the Switch statement. - - + + Definitions for Switch syntax. - - + + Delegate with params intended to be used with the Switch syntax. - - The status of a graph search algorithm. + + Intended to be used with Switch syntax. - - Graph search was not broken. + + The default keyword for the the Switch syntax. - - Graph search was broken. + + Represents the result of a conditional expression inside Switch syntax. + The generic type of the Switch condition for equality checks. - - Graph search found the goal. + + Resolves the condition to a bool. - - Syntax sugar hacks. + + Casts a to a bool using an equality check. - - This is a syntax sugar hack to allow implicit conversions from StepStatus to GraphSearchStatus. + + Uses the bool as the condition result. - - Constructs a new graph search status. - The status of the graph search. + + Converts a keyword to a condition result (for "Default" case). - - Converts a into a . - The to convert. + + The value of this condition for an equality check. - - Converts a into a . - The to convert. + + Represents the result of a conditional expression inside Switch syntax. - - Converts a into a . - The to convert. + + Resolves the condition to a bool. - - Step function for all neigbors of a given node. - The node type of the graph being searched. - The node to step through all the neighbors of. - Step function to perform on all neighbors. + + Uses the bool as the condition result. - - Computes the heuristic value of a given node in a graph (smaller values mean closer to goal node). - The node type of the graph being searched. - The numeric to use when performing calculations. - The node to compute the heuristic value of. - The computed heuristic value for this node. + + Converts a keyword to a condition result (for "Default" case). - - Computes the cost of moving from the current node to a specific neighbor. - The node type of the graph being searched. - The numeric to use when performing calculations. - The current (starting) node. - The node to compute the cost of movign to. - The computed cost value of movign from current to neighbor. + + Converts a condition to a bool using the Resolve method. - - Predicate for determining if we have reached the goal node. - The node type of the graph being searched. - The current node. - True if the current node is a/the goal node; False if not. + + Allows chance syntax with "using static Towel.Syntax;". + 25% Chance + + + Struct that allows percentage syntax that will be evaluated at runtime. + + + The random algorithm currently being used by chance syntax. - - Checks the status of a graph search. - The node type of the search. - The current node of the search. - The status of the search. + + Creates a chance from a percentage that will be evaluated at runtime. + The value of the percentage. + The chance syntax struct object. + True if the the chance hits. False if not. - - The node type of the graph being searched. - The numeric to use when performing calculations. - The node to start at. - Step function for all neigbors of a given node. - Computes the heuristic value of a given node in a graph. - Computes the cost of moving from the current node to a specific neighbor. - Checks the status of the search. - The total cost of the path if a path was found. - The goal of the search. - The graph to perform the search on. - Stepper of the shortest path or null if no path exists. + + Used for inequality syntax. + The generic type of elements the inequality is being used on. - - Runs the A* search algorithm on a graph. - + + Contructs a new . + The initial value of the running inequality. - - + + Adds a greater than operation to a running inequality. + The current running inequality and left hand operand. + The value of the right hand operand of the greater than operation. + A running inequality with the additonal greater than operation. - - + + Adds a less than operation to a running inequality. + The current running inequality and left hand operand. + The value of the right hand operand of the less than operation. + A running inequality with the additonal less than operation. - - + + Adds a greater than or equal operation to a running inequality. + The current running inequality and left hand operand. + The value of the right hand operand of the greater than or equal operation. + A running inequality with the additonal greater than or equal operation. - - + + Adds a less than or equal operation to a running inequality. + The current running inequality and left hand operand. + The value of the right hand operand of the less than or equal operation. + A running inequality with the additonal less than or equal operation. - - + + Adds an equal operation to a running inequality. + The current running inequality and left hand operand. + The value of the right hand operand of the equal operation. + A running inequality with the additonal equal operation. - - + + Adds an inequal operation to a running inequality. + The current running inequality and left hand operand. + The value of the right hand operand of the inequal operation. + A running inequality with the additonal inequal operation. - - + + This member is not intended to be invoked. + This member is not intended to be invoked. - - Runs the Dijkstra search algorithm on a graph. - + + This member is not intended to be invoked. + This member is not intended to be invoked. + This member is not intended to be invoked. - - + + This member is not intended to be invoked. + This member is not intended to be invoked. - - + + Helper type for inequality syntax. Contains an Inequality type that has been operator validated. - - + + Used for inequality syntax. + The generic type of elements the inequality is being used on. - - + + Converts this running inequality into the result of the expression. + The inequality to convert into the result of the expression. - - + + Adds a greater than operation to a running inequality. + The current running inequality and left hand operand. + The value of the right hand operand of the greater than operation. + A running inequality with the additonal greater than operation. - - + + Adds a less than operation to a running inequality. + The current running inequality and left hand operand. + The value of the right hand operand of the less than operation. + A running inequality with the additonal less than operation. - - + + Adds a greater than or equal operation to a running inequality. + The current running inequality and left hand operand. + The value of the right hand operand of the greater than or equal operation. + A running inequality with the additonal greater than or equal operation. - - Runs the Breadth-First-Search search algorithm on a graph. - + + Adds a less than or equal operation to a running inequality. + The current running inequality and left hand operand. + The value of the right hand operand of the less than or equal operation. + A running inequality with the additonal less than or equal operation. - - + + Adds an equal operation to a running inequality. + The current running inequality and left hand operand. + The value of the right hand operand of the equal operation. + A running inequality with the additonal equal operation. - - + + Adds an inequal operation to a running inequality. + The current running inequality and left hand operand. + The value of the right hand operand of the inequal operation. + A running inequality with the additonal inequal operation. - - + + Converts the result of this inequality to a . + The result of this inequality converted to a . - - + + This member is not intended to be invoked. + This member is not intended to be invoked. + This member is not intended to be invoked. - - + + This member is not intended to be invoked. + This member is not intended to be invoked. - - + + Universal Quantification Operator. + The element type of the universal quantification to declare. + The values of the universal quantification. + The declared universal quantification. - - + + Universal Quantification. + The element type of the universal quantification. - - The type of values to sort. - The compare function. - The get function. - The set function. - The compare function. - The get function. - The set function. - The starting index of the sort. - The ending index of the sort. - The array to be sorted. - The span to be sorted. + + Constructs a new universal quantification from an array. + The array value of the universal quantification. - - - Sorts values using the bubble sort algorithm. - Runtime: Ω(n), ε(n^2), O(n^2) - Memory: O(1) - Stable: True - - + + The number of values in this universal quantification. - - + + Iterates each value in this universal quantification and performs an action for each element. + The action to perform on every step of the iteration. - - + + Iterates each value in this universal quantification and performs an action for each element. - - + + Index property for get/set operations. + The index to get/set. + The value at the provided index. - - + + Gets the number of elements in this universal quantification. - - - Sorts values using the selection sort algoritm. - Runtime: Ω(n^2), ε(n^2), O(n^2) - Memory: O(1) - Stable: False - - + + Gets a value indicating whether the is read-only. - - + + Adds an item to this universal quantifier. + The item to add to this universal quantifier. - - + + Not intended to be invoked directly. - - + + Not intended to be invoked directly. - - + + Not intended to be invoked directly. - - - Sorts values using the insertion sort algorithm. - Runtime: Ω(n), ε(n^2), O(n^2) - Memory: O(1) - Stable: True - - + + Not intended to be invoked directly. - - + + Not intended to be invoked directly. - - + + Not intended to be invoked directly. - - + + Not intended to be invoked directly. - - + + Gets the for this universal quantification. + The for this universal quantification. - - - Sorts values using the quick sort algorithm. - Runtime: Ω(n*ln(n)), ε(n*ln(n)), O(n^2) - Memory: ln(n) - Stable: False - - + + Converts a universal quantification to an array. + The universal quantification to be converted. - - + + Converts a universal quantification to a . + The universal quantification to be converted. - - + + Converts a universal quantification to an . + The universal quantification to be converted. - - + + Converts a universal quantification to a . + The universal quantification to be converted. - - + + Converts a universal quantification to an . + The universal quantification to be converted. - - - Sorts values using the merge sort algorithm. - Runtime: Ω(n*ln(n)), ε(n*ln(n)), O(n*ln(n)) - Memory: Θ(n) - Stable: True - - + + Converts a universal quantification to an . + The universal quantification to be converted. - - + + Converts a universal quantification to a sorted . + The universal quantification to be converted. - - + + Converts a universal quantification to an Action<Action<T>>. + The universal quantification to be converted. - - + + Converts a universal quantification to an . + The universal quantification to be converted. - - + + Converts a universal quantification to an Func<Func<T, StepStatus>, StepStatus>. + The universal quantification to be converted. - - - Sorts values using the heap sort algorithm. - Runtime: Ω(n*ln(n)), ε(n*ln(n)), O(n^2) - Memory: O(1) - Stable: False - - + + Converts a universal quantification to an . + The universal quantification to be converted. - - + + Converts a universal quantification to an . + The universal quantification to be converted. - - + + Converts a universal quantification to an . + The universal quantification to be converted. - - + + Converts a universal quantification to an . + The universal quantification to be converted. - - + + Computes the sine ratio of an angle using the relative talor series. Accurate but slow. + The numeric type of the operation. + The angle to compute the sine ratio of. + Determines if coputation should continue or is accurate enough. + The taylor series computed sine ratio of the provided angle. - - - Sorts values using the odd even sort algorithm. - Runtime: Ω(n), ε(n^2), O(n^2) - Memory: O(1) - Stable: True - - + + Computes the sine ratio of an angle using the system's sine function. WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). + The numeric type of the operation. + The angle to compute the sine ratio of. + The sine ratio of the provided angle. + WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). - - + + Estimates the sine ratio using piecewise quadratic equations. Fast but NOT very accurate. + The numeric type of the operation. + The angle to compute the quadratic estimated sine ratio of. + The quadratic estimation of the sine ratio of the provided angle. - - + + Computes the cosine ratio of an angle using the relative talor series. Accurate but slow. + The numeric type of the operation. + The angle to compute the cosine ratio of. + Determines if coputation should continue or is accurate enough. + The taylor series computed cosine ratio of the provided angle. - - + + Computes the cosine ratio of an angle using the system's cosine function. WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). + The numeric type of the operation. + The angle to compute the cosine ratio of. + The cosine ratio of the provided angle. + WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). - - + + Estimates the cosine ratio using piecewise quadratic equations. Fast but NOT very accurate. + The numeric type of the operation. + The angle to compute the quadratic estimated cosine ratio of. + The quadratic estimation of the cosine ratio of the provided angle. - - - Sorts values into a randomized order. - Runtime: O(n) - Memory: O(1) - - The type of values to sort. - The get function. - The set function. - The starting index of the shuffle. - The ending index of the shuffle. - The get function. - The set function. - The random to shuffle with. - The array to shuffle. + + Computes the tangent ratio of an angle using the relative talor series. Accurate but slow. + The numeric type of the operation. + The angle to compute the tangent ratio of. + The taylor series computed tangent ratio of the provided angle. - - + + Computes the tangent ratio of an angle using the system's tangent function. WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). + The numeric type of the operation. + The angle to compute the tangent ratio of. + The tangent ratio of the provided angle. + WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). - - + + Estimates the tangent ratio using piecewise quadratic equations. Fast but NOT very accurate. + The numeric type of the operation. + The angle to compute the quadratic estimated tangent ratio of. + The quadratic estimation of the tangent ratio of the provided angle. - - + + Computes the cosecant ratio of an angle using the system's sine function. WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). + The numeric type of the operation. + The angle to compute the cosecant ratio of. + The cosecant ratio of the provided angle. + WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). - - + + Estimates the cosecant ratio using piecewise quadratic equations. Fast but NOT very accurate. + The numeric type of the operation. + The angle to compute the quadratic estimated cosecant ratio of. + The quadratic estimation of the cosecant ratio of the provided angle. - - + + Computes the secant ratio of an angle using the system's cosine function. WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). + The numeric type of the operation. + The angle to compute the secant ratio of. + The secant ratio of the provided angle. + WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). - - - Sorts values using the bogo sort algorithm. - Runtime: Ω(n), ε(n*n!), O(∞) - Memory: O(1) - Stable: False - - + + Estimates the secant ratio using piecewise quadratic equations. Fast but NOT very accurate. + The numeric type of the operation. + The angle to compute the quadratic estimated secant ratio of. + The quadratic estimation of the secant ratio of the provided angle. - - + + Computes the cotangent ratio of an angle using the system's tangent function. WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). + The numeric type of the operation. + The angle to compute the cotangent ratio of. + The cotangent ratio of the provided angle. + WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures). - - + + Estimates the cotangent ratio using piecewise quadratic equations. Fast but NOT very accurate. + The numeric type of the operation. + The angle to compute the quadratic estimated cotangent ratio of. + The quadratic estimation of the cotangent ratio of the provided angle. - - + + a * b + c - - + + d - a * b / c + + + Swaps two values. + The type of values to swap. + The first value of the swap. + The second value of the swap. - - + + Gets the file path of the current location in source code. + Intended to leave default. This value is set by the compiler via . + The file path of the current location in source code. - - + + Gets the member name of the current location in source code. + Intended to leave default. This value is set by the compiler via . + The member name of the current location in source code. - - Sorts values using the slow sort algorithm. - + + Gets the line number of the current location in source code. + Intended to leave default. This value is set by the compiler via . + The line number of the current location in source code. - - + + Tries to parse a into a value of the type . + The type to parse the into a value of. + The to parse into a value ot type . + + ( Success, Value) + - Success: True if the parse was successful; False if not. + - Value: The value if the parse was successful or default if not. + - - + + Static wrapper for the instance based "object.GetHashCode" function. + The generic type of the hash operation. + The item to get the hash code of. + The computed hash code using the base GetHashCode instance method. - - + + Converts from to . + The type of the value to convert. + The type to convert teh value to. + The value to convert. + The value of type. - - + + Iterates a and joins the results of a System.Func<int, string> seperated by a . + The range of values to use use on the <System.Func{int, string> . + The System.Func<int, string>. + The seperator to join the values with. + The resulting of the join. - - Sorts values using the gnome sort algorithm. - + + Checks for equality of two values [ == ]. + The type of the operation. + The left operand. + The right operand. + The result of the equality check. - - + + Checks for equality among multiple values [ == == == ...]. + The numeric type of the operation. + The first operand of the equality check. + The second operand of the equality check. + The remaining operands of the equality check. + True if all operands are equal or false if not. - - + + Determines if two sequences are equal. + The element type of the sequences. + The first sequence of the equate. + The second sequence of the equate. + The element equate function. + The inclusive starting index to equate from. + The inclusive ending index to equate to. + The first sequence of the equate. + The second sequence of the equate. + The element equate function. + True if the spans are equal; False if not. - - + + Determines if two spans are equal. + The element type of the spans. + The first span of the equate. + The second span of the equate. + The element equate function. + True if the spans are equal; False if not. - - + + Determines if two spans are equal. + The element type of the spans. + The element equate function. + The first span of the equate. + The second span of the equate. + The element equate function. + True if the spans are equal; False if not. - - Sorts values using the comb sort algorithm. - + + Determines if two spans are equal. + The element type of the spans. + The inclusive starting index to equate from. + The inclusive ending index to equate to. + The first span of the equate. + The second span of the equate. + The element equate function. + True if the spans are equal; False if not. - - + + Determines if two spans are equal. + The element type of the spans. + The element equate function. + The inclusive starting index to equate from. + The inclusive ending index to equate to. + The first span of the equate. + The second span of the equate. + The element equate function. + True if the spans are equal; False if not. - - + + Checks for inequality of two values [ != ]. + The type of the left operand. + The type of the right operand. + The type of the return. + The left operand. + The right operand. + The result of the inequality. - - + + Checks for inequality of two values [ != ]. + The numeric type of the operation. + The first operand of the inequality check. + The second operand of the inequality check. + The result of the inequality check. - - + + Checks if one value is less than another [ < ]. + The type of the left operand. + The type of the right operand. + The type of the return. + The left operand. + The right operand. + The result of the less than operation. - - Sorts values using the shell sort algorithm. - + + Checks if one value is less than another [ < ]. + The numeric type of the operation. + The first operand of the less than check. + The second operand of the less than check. + The result of the less than check. - - + + Checks if one value is greater than another [ > ]. + The type of the left operand. + The type of the right operand. + The type of the return. + The left operand. + The right operand. + The result of the greater than operation. - - + + Checks if one value is greater than another [ > ]. + The numeric type of the operation. + The first operand of the greater than check. + The second operand of the greater than check. + The result of the greater than check. - - + + Checks if one value is less than or equal to another [ <= ]. + The type of the left operand. + The type of the right operand. + The type of the return. + The left operand. + The right operand. + The result of the less than or equal to operation. - - + + Checks if one value is less than or equal to another [ <= ]. + The numeric type of the operation. + The first operand of the less than or equal to check. + The second operand of the less than or equal to check. + The result of the less than or equal to check. - - Sorts values using the cocktail sort algorithm. - + + Checks if one value is less greater or equal to another [ >= ]. + The type of the left operand. + The type of the right operand. + The type of the return. + The left operand. + The right operand. + The result of the greater than or equal to operation. - - + + Checks if one value is greater than or equal to another [ >= ]. + The numeric type of the operation. + The first operand of the greater than or equal to check. + The second operand of the greater than or equal to check. + The result of the greater than or equal to check. - - + + Compares two values. + The type of values to compare. + The first value of the comparison. + The second value of the comparison. + The result of the comparison. - - + + Negates a value [-]. + The type of the value to negate. + The resulting type of the negation. + The value to negate. + The result of the negation [-]. - - + + Negates a value [-]. + The type of the value to negate. + The value to negate. + The result of the negation [-]. - - Sorts values using the shell cycle algorithm. - + + Adds two values [ + ]. + The type of the left operand. + The type of the right operand. + The type of the return. + The left operand. + The right operand. + The result of the addition [ + ]. - - + + Adds two values [ + ]. + The numeric type of the operation. + The left operand. + The right operand. + The result of the addition [ + ]. - - + + Adds multiple values [ + + + ...]. + The type of the operation. + The first operand of the addition. + The second operand of the addition. + The third operand of the addition. + The remaining operands of the addition. + The result of the addition [ + + + ...]. - - + + Adds multiple values [step1 + step2 + step3 + ...]. + The type of the operation. + The stepper of the values to add. + The result of the addition [step1 + step2 + step3 + ...]. - - + + Subtracts two values [ - ]. + The type of the left operand. + The type of the right operand. + The type of the return. + The left operand. + The right operand. + The result of the subtraction [ - ]. - - The type of values to sort. - The compare function. - The get function. - The compare function. - The get function. - The starting index of the sort. - The ending index of the sort. - The span to be sorted. + + Subtracts two values [ - ]. + The type of the operation. + The left operand. + The right operand. + The result of the subtraction [ - ]. - - + + Subtracts multiple values [ - - - ...]. + The type of the operation. + The first operand. + The second operand. + The third operand. + The remaining values. + The result of the subtraction [ - - - ...]. - - + + Subtracts multiple numeric values [step1 - step2 - step3 - ...]. + The numeric type of the operation. + The stepper containing the values. + The result of the subtraction [step1 - step2 - step3 - ...]. - - + + Multiplies two values [ * ]. + The type of the left operand. + The type of the right operand. + The type of the return. + The left operand. + The right operand. + The result of the multiplication [ * ]. - - + + Multiplies two values [ * ]. + The type of the operation. + The left operand. + The right operand. + The result of the multiplication [ * ]. - - + + Multiplies multiple values [ * * * ...]. + The type of the operation. + The first operand. + The second operand. + The third operand. + The remaining values. + The result of the multiplication [ * * * ...]. - - + + Multiplies multiple values [step1 * step2 * step3 * ...]. + The type of the operation. + The stepper containing the values. + The result of the multiplication [step1 * step2 * step3 * ...]. - - - Generates unique random values in the - [..] range where is - inclusive and is exclusive. - - The function to perform on each generated value. - The random to generation algorithm. - The random to generation algorithm. - The number of values to generate. - Inclusive endpoint of the random generation range. - Exclusive endpoint of the random generation range. - The function to perform on each generated value. + + Divides two values [ / ]. + The type of the left operand. + The type of the right operand. + The type of the return. + The left operand. + The right operand. + The result of the division [ / ]. - - - Generates unique random values in the - [..] range where is - inclusive and is exclusive. - - The function to perform on each generated value. - The random to generation algorithm. - The random to generation algorithm. - The number of values to generate. - Inclusive endpoint of the random generation range. - Exclusive endpoint of the random generation range. - The function to perform on each generated value. + + Divides two values [ / ]. + The type of the operation. + The left operand. + The right operand. + The result of the division [ / ]. - - - Generates unique random values in the - [..] range where is - inclusive and is exclusive. - - The function to perform on each generated value. - The random to generation algorithm. - The random to generation algorithm. - The number of values to generate. - Inclusive endpoint of the random generation range. - Exclusive endpoint of the random generation range. - The function to perform on each generated value. + + Divides multiple values [ / / / ...]. + The type of the operation. + The first operand of the division. + The second operand of the division. + The third operand of the division. + The remaining values of the division. + The result of the division [ / / / ...]. - - - Generates unique random values in the - [..] range where is - inclusive and is exclusive. - - The random to generation algorithm. - The random to generation algorithm. - The number of values to generate. - Inclusive endpoint of the random generation range. - Exclusive endpoint of the random generation range. - The function to perform on each generated value. + + Divides multiple values [step1 / step2 / step3 / ...]. + The type of the operation. + The stepper containing the values. + The result of the division [step1 / step2 / step3 / ...]. - - - Generates unique random values in the - [..] range where is - inclusive and is exclusive. - - The random to generation algorithm. - The random to generation algorithm. - The number of values to generate. - Inclusive endpoint of the random generation range. - Exclusive endpoint of the random generation range. + + Remainders two values [ % ]. + The type of the left operand. + The type of the right operand. + The type of the return. + The left operand. + The right operand. + The result of the remainder operation [ % ]. - - Determines if a sequence is a palindrome. - The element type of the sequence. - The inclusive starting index of the palindrome check. - The inclusive ending index of the palindrome check. - The element equate function. - The get index function of the sequence. - True if the sequence is a palindrome; False if not. + + Modulos two numeric values [ % ]. + The numeric type of the operation. + The first operand of the modulation. + The second operand of the modulation. + The result of the modulation. - - Determines if a sequence is a palindrome. - The element type of the sequence. - The get index function of the sequence. - The inclusive starting index of the palindrome check. - The inclusive ending index of the palindrome check. - The element equate function. - The get index function of the sequence. - True if the sequence is a palindrome; False if not. + + Modulos multiple numeric values [ % % % ...]. + The numeric type of the operation. + The first operand of the modulation. + The second operand of the modulation. + The third operand of the modulation. + The remaining values of the modulation. + The result of the modulation. - - Determines if a sequence is a palindrome. - The element type of the sequence. - The element equate function. - The get index function of the sequence. - The inclusive starting index of the palindrome check. - The inclusive ending index of the palindrome check. - The element equate function. - The get index function of the sequence. - True if the sequence is a palindrome; False if not. + + Modulos multiple numeric values [step_1 % step_2 % step_3...]. + The numeric type of the operation. + The stepper containing the values. + The result of the modulation. - - Determines if a sequence is a palindrome. - The span to check. - True if the sequence is a palindrome; False if not. + + Inverts a numeric value [1 / a]. + The numeric type of the operation. + The numeric value to invert. + The result of the inversion. + + + Powers two numeric values [a ^ b]. + The numeric type of the operation. + The first operand of the power. + The first operand of the power. + The result of the power. - - Determines if a sequence is a palindrome. - The element type of the sequence. - The span to check. - The element equate function. - True if the sequence is a palindrome; False if not. + + Powers multiple numeric values [a ^ b ^ c...]. + The numeric type of the operation. + The first operand of the power. + The second operand of the power. + The third operand of the power. + The remaining values of the power. + The result of the power. - - Determines if a sequence is a palindrome. - The element type of the sequence. - The element equate function. - The span to check. - The element equate function. - True if the sequence is a palindrome; False if not. + + Powers multiple numeric values [step_1 ^ step_2 ^ step_3...]. + The numeric type of the operation. + The stepper containing the values. + The result of the power. - - The element type of the sequences. - The first sequence to determine if is interleaved of. - The second sequence to determine if is interleaved of. - The sequence to determine if it is interleaved from and . - The function for equating values. - True if is interleaved of and or False if not. - - - IsInterleaved("abc", "xyz", "axbycz") // True - IsInterleaved("abc", "xyz", "cbazyx") // False (order not preserved) - IsInterleaved("abc", "xyz", "012345") // False - - + + Square roots a numeric value [√a]. + The numeric type of the operation. + The numeric value to square root. + The result of the square root. - - - - Determines if is interleved of and , - meaning that it contains all elements of and - while retaining the order of the respective elements. Uses a recursive algorithm. - - Runtime: O(2^(Min(.Length + .Length, .Length))), Ω(1) - Memory: O(1) - - + + Roots two numeric values [a ^ (1 / b)]. + The numeric type of the operation. + The base of the root. + The root of the operation. + The result of the root. - - - Determines if is interleved of and , - meaning that it contains all elements of and - while retaining the order of the respective elements. Uses a interative algorithm. - Runtime: O(Min(.Length * .Length))), Ω(1) - Memory: O(.Length * .Length) - - + + Computes the logarithm of a value. + The numeric type of the operation. + The value to compute the logarithm of. + The base of the logarithm to compute. + The computed logarithm value. - - + + Determines if a numerical value is an integer. + The numeric type of the operation. + The value to determine integer status of. + Whether or not the value is an integer. - - + + Determines if a numerical value is non-negative. + The numeric type of the operation. + The value to determine non-negative status of. + Whether or not the value is non-negative. - - + + Determines if a numerical value is negative. + The numeric type of the operation. + The value to determine negative status of. + Whether or not the value is negative. - - + + Determines if a numerical value is positive. + The numeric type of the operation. + The value to determine positive status of. + Whether or not the value is positive. - - + + Determines if a numerical value is even. + The numeric type of the operation. + The value to determine even status of. + Whether or not the value is even. - - + + Determines if a numerical value is odd. + The numeric type of the operation. + The value to determine odd status of. + Whether or not the value is odd. - - Default int compare. + + Determines if a numerical value is prime. + The numeric type of the operation. + The value to determine prime status of. + Whether or not the value is prime. - - Default int compare. - The left hand side of the compare. - The right ahnd side of the compare. - The result of the comparison. + + Gets the absolute value of a value. + The numeric type of the operation. + The value to get the absolute value of. + The absolute value of the provided value. - - Compares two char values for equality. + + Gets a value restricted to a minimum and maximum range. + The numeric type of the operation. + The value to clamp. + The minimum of the range to clamp the value by. + The maximum of the range to clamp the value by. + The value restricted to the provided range. - - Compares two char values for equality. + + Checks for equality between two numeric values with a range of possibly leniency. + The numeric type of the operation. The first operand of the equality check. The second operand of the equality check. - True if equal; False if not. + The allowed distance between the values to still be considered equal. + True if the values are within the allowed leniency of each other. False if not. - - Built in Compare struct for runtime computations. - The generic type of the values to compare. - The compare function. + + Computes the greatest common factor of a set of numbers. + The numeric type of the computation. + The first operand of the greatest common factor computation. + The second operand of the greatest common factor computation. + The remaining operands of the greatest common factor computation. + The computed greatest common factor of the set of numbers. - - The invocation of the compile time delegate. + + Computes the greatest common factor of a set of numbers. + The numeric type of the computation. + The set of numbers to compute the greatest common factor of. + The computed greatest common factor of the set of numbers. - - Creates a compile-time-resolved sifting function to be passed into another type. - The value for future values to be compared against. - The compare function. + + Computes the least common multiple of a set of numbers. + The numeric type of the operation. + The first operand of the least common muiltiple computation. + The second operand of the least common muiltiple computation. + The remaining operands of the least common muiltiple computation. + The computed least common least common multiple of the set of numbers. - - Compile time resulution to the value. + + Computes the least common multiple of a set of numbers. + The numeric type of the operation. + The set of numbers to compute the least common multiple of. + The computed least common least common multiple of the set of numbers. - - Returns . - + + Linearly interpolations a value. + The numeric type of the operation. + The value along the first dimension to compute the linear interpolation for. + A known starting point along the first dimension. + A known ending point along the first dimension. + A known starting point along the second dimension. + A known ending point along the second dimension. + The linearly interpolated value. - - Struct wrapper for the method as an . + + Computes the factorial of a numeric value [!] == [ * ( - 1) * ( - 2) * ... * 1]. + The numeric type of the operation. + The integer value to compute the factorial of. + The computed factorial value. + Thrown when the parameter is not an integer value. + Thrown when the parameter is less than zero. - - + + Computes the combinations of values using the grouping definitions. + The numeric type of the operation. + The number of values to compute the combinations of. + The groups and how many values fall into each group. + The computed number of combinations. - - Casts a to a struct wrapper. + + Computes the Binomial coefficient (N choose n). + The numeric type of the computation. + The size of the entire set (N choose n). + The size of the subset (N choose n). + The computed binomial coefficient (N choose n). + + + Computes the exponentional of a value [e ^ ]. + The generic type of the operation. + The value to compute the exponentional of. + The exponential of the value [e ^ ]. + + + Computes the natural logarithm of a value [ln()]. + The generic type of the operation. + The value to compute the natural log of. + The natural log of the provided value [ln()]. + + + Computes the best fit line from a set of points in 2D space [y = slope * x + y_intercept]. + The numeric type of the operation. + The points to compute the best fit line of. + The slope of the computed best fit line [y = slope * x + y_intercept]. + The y intercept of the computed best fit line [y = slope * x + y_intercept]. + + + Factors the primes numbers of a numeric integer value. + The numeric type of the operation. + The value to factor the prime numbers of. + The action to perform on all found prime factors. Status of iteration. diff --git a/Tools/Towel_Benchmarking/Sort.cs b/Tools/Towel_Benchmarking/Sort.cs index 2ee38f63..85c636a7 100644 --- a/Tools/Towel_Benchmarking/Sort.cs +++ b/Tools/Towel_Benchmarking/Sort.cs @@ -101,6 +101,18 @@ [Benchmark] public void CycleRunTime() => [Benchmark] public void CycleCompileTime() => SortCycle(Values); + [Benchmark] public void PancakeRunTime() => + SortPancake(Values); + + [Benchmark] public void PancakeCompileTime() => + SortPancake(Values); + + [Benchmark] public void StoogeRunTime() => + SortStooge(Values); + + [Benchmark] public void StoogeCompileTime() => + SortStooge(Values); + [Benchmark] public void SlowRunTime() { if (Values.Length > 10) diff --git a/Tools/Towel_Testing/Statics.cs b/Tools/Towel_Testing/Statics.cs index 4ab93748..98861f55 100644 --- a/Tools/Towel_Testing/Statics.cs +++ b/Tools/Towel_Testing/Statics.cs @@ -1698,6 +1698,16 @@ public void Cycle_Testing() => TestAlgorithm( (array, compare) => SortCycle(0, array.Length - 1, i => array[i], (i, v) => array[i] = v, compare), (array, start, end, compare) => SortCycle(start, end, i => array[i], (i, v) => array[i] = v, compare)); + [TestMethod] + public void Pancake_Testing() => TestAlgorithm( + (array, compare) => SortPancake(array, compare), + (array, start, end, compare) => Assert.Inconclusive()); + + [TestMethod] + public void Stooge_Testing() => TestAlgorithm( + (array, compare) => SortStooge(array, compare), + (array, start, end, compare) => Assert.Inconclusive()); + [TestMethod] public void Bogo_Testing() => TestAlgorithm( (array, compare) => SortBogo(array, compare), @@ -2008,6 +2018,5 @@ [TestMethod] public void IsInterleavedIterative_Testing() } #endregion - } } From a3cd9add5d5e50786aac902aab0ae74184163408 Mon Sep 17 00:00:00 2001 From: Zachary Patten Date: Fri, 20 Nov 2020 20:57:28 -0500 Subject: [PATCH 24/30] fixes #72 --- Examples/BasicsAndExtensions/Program.cs | 2 +- Sources/Towel/Statics-SequenceAnalysis.cs | 4 ++-- Sources/Towel/Towel.xml | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Examples/BasicsAndExtensions/Program.cs b/Examples/BasicsAndExtensions/Program.cs index 1e9ecb97..2a02df81 100644 --- a/Examples/BasicsAndExtensions/Program.cs +++ b/Examples/BasicsAndExtensions/Program.cs @@ -410,7 +410,7 @@ static void Main() { string a = "book"; string b = "barf"; - Console.WriteLine($@" Recursive(""{a}"", ""{b}""): {HammingDistance(a, b)}"); + Console.WriteLine($@" HammingDistance(""{a}"", ""{b}""): {HammingDistance(a, b)}"); } Console.WriteLine(); } diff --git a/Sources/Towel/Statics-SequenceAnalysis.cs b/Sources/Towel/Statics-SequenceAnalysis.cs index 01054d42..35b0bc49 100644 --- a/Sources/Towel/Statics-SequenceAnalysis.cs +++ b/Sources/Towel/Statics-SequenceAnalysis.cs @@ -662,14 +662,14 @@ public static int HammingDistance( return distance; } - /// Computes the Hamming distance (using an recursive algorithm). + /// Computes the Hamming distance (using an iterative algorithm). /// The first sequence of the operation. /// The second sequence of the operation. /// The computed Hamming distance of the two sequences. public static int HammingDistance(ReadOnlySpan a, ReadOnlySpan b) => HammingDistance(a, b); - /// Computes the Hamming distance (using an recursive algorithm). + /// Computes the Hamming distance (using an iterative algorithm). /// The element type of the sequences. /// The equality check function. /// The first sequence. diff --git a/Sources/Towel/Towel.xml b/Sources/Towel/Towel.xml index 44f66de7..7e39b179 100644 --- a/Sources/Towel/Towel.xml +++ b/Sources/Towel/Towel.xml @@ -30552,13 +30552,13 @@ The computed Hamming distance of the two sequences. - Computes the Hamming distance (using an recursive algorithm). + Computes the Hamming distance (using an iterative algorithm). The first sequence of the operation. The second sequence of the operation. The computed Hamming distance of the two sequences. - Computes the Hamming distance (using an recursive algorithm). + Computes the Hamming distance (using an iterative algorithm). The element type of the sequences. The equality check function. The first sequence. From 697870a0aa8ca1eb220ee69a220be620e37b7d66 Mon Sep 17 00:00:00 2001 From: Zachary Patten Date: Fri, 20 Nov 2020 21:11:10 -0500 Subject: [PATCH 25/30] GH workflows to .NET 5 --- .github/workflows/Towel Continuous Integration.yml | 2 +- .github/workflows/Towel Deployment.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/Towel Continuous Integration.yml b/.github/workflows/Towel Continuous Integration.yml index 1859c97f..6caa9822 100644 --- a/.github/workflows/Towel Continuous Integration.yml +++ b/.github/workflows/Towel Continuous Integration.yml @@ -22,7 +22,7 @@ jobs: - name: setup dotnet uses: actions/setup-dotnet@v1 with: - dotnet-version: 5.0.100-rc.2.20479.15 + dotnet-version: 5.0.100 - name: dotnet build run: dotnet build --configuration 'Release' - name: dotnet test diff --git a/.github/workflows/Towel Deployment.yml b/.github/workflows/Towel Deployment.yml index 23632290..2eb40390 100644 --- a/.github/workflows/Towel Deployment.yml +++ b/.github/workflows/Towel Deployment.yml @@ -10,7 +10,7 @@ jobs: - name: setup dotnet uses: actions/setup-dotnet@v1 with: - dotnet-version: 5.0.100-rc.2.20479.15 + dotnet-version: 5.0.100 - name: dotnet pack run: dotnet pack Sources/Towel/Towel.csproj --configuration Release /p:Version=${{ github.event.release.tag_name }} /p:PackageReleaseNotes="See https://github.com/ZacharyPatten/Towel/releases/tag/${{ github.event.release.tag_name }}" - name: archive nuget From 873a9ff9f7c1bd5fa3a0afb8d9cebb203feb9a47 Mon Sep 17 00:00:00 2001 From: Zachary Patten Date: Fri, 20 Nov 2020 21:20:42 -0500 Subject: [PATCH 26/30] updating nugets --- Tools/Towel_Benchmarking/Towel_Benchmarking.csproj | 2 +- Tools/Towel_Testing/Towel_Testing.csproj | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Tools/Towel_Benchmarking/Towel_Benchmarking.csproj b/Tools/Towel_Benchmarking/Towel_Benchmarking.csproj index ec92ad73..c27ae834 100644 --- a/Tools/Towel_Benchmarking/Towel_Benchmarking.csproj +++ b/Tools/Towel_Benchmarking/Towel_Benchmarking.csproj @@ -5,7 +5,7 @@ net5.0 - + diff --git a/Tools/Towel_Testing/Towel_Testing.csproj b/Tools/Towel_Testing/Towel_Testing.csproj index 12cce47a..be5f1f60 100644 --- a/Tools/Towel_Testing/Towel_Testing.csproj +++ b/Tools/Towel_Testing/Towel_Testing.csproj @@ -9,11 +9,11 @@ 1701;1702;1591 - 1701;1702;1591 + 1701;1702;1591 - + From fa8cb7af1c1a68e7b0fb9d52856e975f5db224b6 Mon Sep 17 00:00:00 2001 From: Zachary Patten Date: Fri, 20 Nov 2020 21:45:37 -0500 Subject: [PATCH 27/30] added git attributes --- .gitattributes | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..3f3c4fd6 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +* text=auto +*.png binary From 721882ad506143509c92997a737f86ef2dee93a8 Mon Sep 17 00:00:00 2001 From: Zachary Patten Date: Fri, 20 Nov 2020 21:45:58 -0500 Subject: [PATCH 28/30] Readme Updates --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index ba295d79..4d6b3e03 100644 --- a/README.md +++ b/README.md @@ -802,6 +802,9 @@ SortGnome(...); SortShell(...); SortBogo(...); SortSlow(...); +SortCycle(...); +SortPancake(...); +SortStooge(...); // Note: supports System.ReadOnlySpan and any (non ref struct) int-indexed type SearchBinary(...); @@ -846,6 +849,9 @@ string ConvertToCSharpSourceDefinition(this Type type); string ToEnglishWords(this decimal @decimal); // Example: 12 -> "Twelve" +int TryParseRomanNumeral(string @string); +// Example: "IX" -> 9 + // Reflection Extensions To Access XML Documentation string GetDocumentation(this Type type); string GetDocumentation(this FieldInfo fieldInfo); From 704057f14fd31f5ef9a0855559a7715e5393750e Mon Sep 17 00:00:00 2001 From: Zachary Patten Date: Sat, 21 Nov 2020 00:18:06 -0500 Subject: [PATCH 29/30] Roman Numeral field name changed --- Sources/Towel/Statics-RomanNumerals.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/Towel/Statics-RomanNumerals.cs b/Sources/Towel/Statics-RomanNumerals.cs index 904da2ce..76792252 100644 --- a/Sources/Towel/Statics-RomanNumerals.cs +++ b/Sources/Towel/Statics-RomanNumerals.cs @@ -14,7 +14,7 @@ public static partial class Statics /* 6:M */ 1000, }; - internal readonly static int[] RomanNumeralDigitsAllowsPrefixes = + internal readonly static int[] RomanNumeralDigitsAllowedPrefix = { /* 0:I */ default, /* 1:V */ 0, @@ -71,7 +71,7 @@ public static (bool Success, int Value) TryParseRomanNumeral(string @string) }; if ((c.HasValue && c.Value < a) || (a == b && a == c && a == d) || - ((b.HasValue && b.Value < a && b.Value != RomanNumeralDigitsAllowsPrefixes[a])) || + ((b.HasValue && b.Value < a && b.Value != RomanNumeralDigitsAllowedPrefix[a])) || (b == a && !RomanNumeralDigitsAllowsDuplicates[a])) { return (false, default); From 71add55f06b04716b067c7dfafa26adc36f1aca1 Mon Sep 17 00:00:00 2001 From: Zachary Patten Date: Sat, 21 Nov 2020 00:18:24 -0500 Subject: [PATCH 30/30] benchmarks update --- Tools/Towel_Benchmarking/Sort.cs | 16 +- Tools/docfx_project/articles/benchmarks.md | 532 +++++++++++---------- 2 files changed, 290 insertions(+), 258 deletions(-) diff --git a/Tools/Towel_Benchmarking/Sort.cs b/Tools/Towel_Benchmarking/Sort.cs index 85c636a7..360f8fee 100644 --- a/Tools/Towel_Benchmarking/Sort.cs +++ b/Tools/Towel_Benchmarking/Sort.cs @@ -107,11 +107,23 @@ [Benchmark] public void PancakeRunTime() => [Benchmark] public void PancakeCompileTime() => SortPancake(Values); - [Benchmark] public void StoogeRunTime() => + [Benchmark] public void StoogeRunTime() + { + if (Values.Length > 1000) + { + throw new Exception("Too Slow."); + } SortStooge(Values); + } - [Benchmark] public void StoogeCompileTime() => + [Benchmark] public void StoogeCompileTime() + { + if (Values.Length > 1000) + { + throw new Exception("Too Slow."); + } SortStooge(Values); + } [Benchmark] public void SlowRunTime() { diff --git a/Tools/docfx_project/articles/benchmarks.md b/Tools/docfx_project/articles/benchmarks.md index c6e25d05..17bc741b 100644 --- a/Tools/docfx_project/articles/benchmarks.md +++ b/Tools/docfx_project/articles/benchmarks.md @@ -10,114 +10,134 @@ The source code for all becnhmarks are in [Tools/Towel.Benchmarking](https://git ``` ini -BenchmarkDotNet=v0.12.0, OS=Windows 10.0.18363 +BenchmarkDotNet=v0.12.1, OS=Windows 10.0.18363.1198 (1909/November2018Update/19H2) Intel Core i7-4790K CPU 4.00GHz (Haswell), 1 CPU, 8 logical and 4 physical cores -.NET Core SDK=5.0.100-rc.1.20452.10 - [Host] : .NET Core 3.1.8 (CoreCLR 4.700.20.41105, CoreFX 4.700.20.41903), X64 RyuJIT - Job-ZKCIBR : .NET Core 3.1.8 (CoreCLR 4.700.20.41105, CoreFX 4.700.20.41903), X64 RyuJIT +.NET Core SDK=5.0.100 + [Host] : .NET Core 5.0.0 (CoreCLR 5.0.20.51904, CoreFX 5.0.20.51904), X64 RyuJIT + Job-BQFFMI : .NET Core 5.0.0 (CoreCLR 5.0.20.51904, CoreFX 5.0.20.51904), X64 RyuJIT InvocationCount=1 UnrollFactor=1 ``` | Method | N | Mean | Error | StdDev | Median | |------------------------- |------ |-----------------:|------------------:|------------------:|-----------------:| -| **SystemArraySort** | **10** | **476.5 ns** | **15.78 ns** | **42.67 ns** | **500.0 ns** | -| SystemArraySortDelegate | 10 | 645.4 ns | 20.53 ns | 59.55 ns | 600.0 ns | -| SystemArraySortIComparer | 10 | 3,120.6 ns | 66.31 ns | 158.88 ns | 3,100.0 ns | -| BubbleRunTime | 10 | 1,976.2 ns | 43.23 ns | 79.05 ns | 2,000.0 ns | -| BubbleCompileTime | 10 | 480.0 ns | 14.02 ns | 40.21 ns | 500.0 ns | -| SelectionRunTime | 10 | 1,844.1 ns | 267.22 ns | 758.07 ns | 1,500.0 ns | -| SelectionCompileTime | 10 | 380.4 ns | 14.14 ns | 39.89 ns | 400.0 ns | -| InsertionRunTime | 10 | 1,442.4 ns | 32.67 ns | 72.41 ns | 1,400.0 ns | -| InsertionCompileTime | 10 | 236.0 ns | 17.06 ns | 50.29 ns | 200.0 ns | -| QuickRunTime | 10 | 1,798.3 ns | 38.63 ns | 84.79 ns | 1,800.0 ns | -| QuickCompileTime | 10 | 544.9 ns | 19.14 ns | 55.84 ns | 500.0 ns | -| MergeRunTime | 10 | 1,696.2 ns | 37.54 ns | 78.35 ns | 1,700.0 ns | -| MergeCompileTime | 10 | 1,772.7 ns | 294.60 ns | 864.00 ns | 1,300.0 ns | -| HeapRunTime | 10 | 2,530.0 ns | 53.07 ns | 79.44 ns | 2,500.0 ns | -| HeapCompileTime | 10 | 1,637.3 ns | 36.58 ns | 74.73 ns | 1,600.0 ns | -| OddEvenRunTime | 10 | 2,089.0 ns | 323.56 ns | 907.31 ns | 1,700.0 ns | -| OddEvenCompileTime | 10 | 362.0 ns | 16.54 ns | 48.78 ns | 400.0 ns | -| GnomeRunTime | 10 | 1,723.9 ns | 38.03 ns | 93.30 ns | 1,700.0 ns | -| GnomeCompileTime | 10 | 400.0 ns | 0.00 ns | 0.00 ns | 400.0 ns | -| CombRunTime | 10 | 1,545.5 ns | 34.76 ns | 74.08 ns | 1,500.0 ns | -| CombCompileTime | 10 | 351.0 ns | 19.58 ns | 57.73 ns | 300.0 ns | -| ShellRunTime | 10 | 1,438.8 ns | 32.72 ns | 77.76 ns | 1,400.0 ns | -| ShellCompileTime | 10 | 1,566.7 ns | 301.69 ns | 884.79 ns | 1,100.0 ns | -| CocktailRunTime | 10 | 2,173.3 ns | 228.90 ns | 638.08 ns | 1,900.0 ns | -| CocktailCompileTime | 10 | 468.7 ns | 20.46 ns | 60.01 ns | 500.0 ns | -| SlowRunTime | 10 | 5,664.3 ns | 71.44 ns | 63.33 ns | 5,700.0 ns | -| SlowCompileTime | 10 | 4,722.2 ns | 93.76 ns | 100.33 ns | 4,700.0 ns | -| BogoRunTime | 10 | 348,409,920.6 ns | 100,596,876.19 ns | 291,849,778.49 ns | 269,969,000.0 ns | -| BogoCompileTime | 10 | 347,184,452.6 ns | 96,283,325.77 ns | 279,335,386.55 ns | 295,738,800.0 ns | -| **SystemArraySort** | **1000** | **28,684.6 ns** | **493.39 ns** | **412.00 ns** | **28,600.0 ns** | -| SystemArraySortDelegate | 1000 | 64,800.0 ns | 976.99 ns | 762.77 ns | 64,550.0 ns | -| SystemArraySortIComparer | 1000 | 77,868.4 ns | 2,053.15 ns | 2,282.07 ns | 77,300.0 ns | -| BubbleRunTime | 1000 | 5,091,730.9 ns | 101,322.99 ns | 242,763.42 ns | 5,034,550.0 ns | -| BubbleCompileTime | 1000 | 1,582,448.0 ns | 49,845.54 ns | 146,970.71 ns | 1,526,950.0 ns | -| SelectionRunTime | 1000 | 2,990,598.0 ns | 234,394.18 ns | 691,116.53 ns | 3,339,850.0 ns | -| SelectionCompileTime | 1000 | 897,590.2 ns | 17,855.33 ns | 47,349.79 ns | 886,600.0 ns | -| InsertionRunTime | 1000 | 1,752,852.2 ns | 39,726.95 ns | 76,540.34 ns | 1,730,050.0 ns | -| InsertionCompileTime | 1000 | 283,010.3 ns | 8,318.96 ns | 24,134.81 ns | 294,200.0 ns | -| QuickRunTime | 1000 | 175,508.2 ns | 3,464.97 ns | 6,919.92 ns | 174,700.0 ns | -| QuickCompileTime | 1000 | 57,376.0 ns | 1,142.97 ns | 2,308.86 ns | 57,050.0 ns | -| MergeRunTime | 1000 | 122,831.0 ns | 2,440.34 ns | 3,577.02 ns | 123,000.0 ns | -| MergeCompileTime | 1000 | 62,775.0 ns | 1,231.23 ns | 1,417.88 ns | 62,700.0 ns | -| HeapRunTime | 1000 | 386,460.9 ns | 7,709.37 ns | 18,619.01 ns | 386,600.0 ns | -| HeapCompileTime | 1000 | 344,105.5 ns | 6,836.67 ns | 14,569.51 ns | 340,500.0 ns | -| OddEvenRunTime | 1000 | 3,219,749.0 ns | 296,402.27 ns | 873,948.78 ns | 3,759,250.0 ns | -| OddEvenCompileTime | 1000 | 920,867.0 ns | 25,097.76 ns | 72,813.15 ns | 906,600.0 ns | -| GnomeRunTime | 1000 | 3,684,235.1 ns | 91,476.53 ns | 155,334.09 ns | 3,635,000.0 ns | -| GnomeCompileTime | 1000 | 775,531.7 ns | 15,367.77 ns | 40,753.14 ns | 771,100.0 ns | -| CombRunTime | 1000 | 215,395.0 ns | 8,990.71 ns | 10,353.72 ns | 210,400.0 ns | -| CombCompileTime | 1000 | 51,766.7 ns | 635.36 ns | 496.04 ns | 51,550.0 ns | -| ShellRunTime | 1000 | 137,058.3 ns | 1,665.96 ns | 1,300.67 ns | 137,100.0 ns | -| ShellCompileTime | 1000 | 53,066.7 ns | 884.59 ns | 690.63 ns | 52,850.0 ns | -| CocktailRunTime | 1000 | 4,109,638.3 ns | 87,453.26 ns | 170,570.88 ns | 4,052,200.0 ns | -| CocktailCompileTime | 1000 | 1,063,801.0 ns | 24,536.05 ns | 70,792.11 ns | 1,048,500.0 ns | +| **SystemArraySort** | **10** | **373.6 ns** | **23.93 ns** | **65.52 ns** | **400.0 ns** | +| SystemArraySortDelegate | 10 | 731.8 ns | 23.06 ns | 63.51 ns | 750.0 ns | +| SystemArraySortIComparer | 10 | 3,086.4 ns | 64.29 ns | 78.95 ns | 3,050.0 ns | +| BubbleRunTime | 10 | 1,787.0 ns | 38.30 ns | 80.79 ns | 1,750.0 ns | +| BubbleCompileTime | 10 | 500.0 ns | 0.00 ns | 0.00 ns | 500.0 ns | +| SelectionRunTime | 10 | 1,476.9 ns | 31.39 ns | 42.97 ns | 1,500.0 ns | +| SelectionCompileTime | 10 | 386.8 ns | 13.37 ns | 34.03 ns | 400.0 ns | +| InsertionRunTime | 10 | 1,258.5 ns | 28.86 ns | 60.24 ns | 1,300.0 ns | +| InsertionCompileTime | 10 | 250.0 ns | 0.00 ns | 0.00 ns | 250.0 ns | +| QuickRunTime | 10 | 1,721.1 ns | 36.41 ns | 89.31 ns | 1,700.0 ns | +| QuickCompileTime | 10 | 529.2 ns | 15.93 ns | 40.84 ns | 550.0 ns | +| MergeRunTime | 10 | 1,647.6 ns | 34.83 ns | 80.03 ns | 1,700.0 ns | +| MergeCompileTime | 10 | 1,257.6 ns | 27.00 ns | 72.99 ns | 1,300.0 ns | +| HeapRunTime | 10 | 2,296.7 ns | 48.79 ns | 73.03 ns | 2,250.0 ns | +| HeapCompileTime | 10 | 1,506.5 ns | 31.89 ns | 89.94 ns | 1,500.0 ns | +| OddEvenRunTime | 10 | 1,527.9 ns | 32.49 ns | 73.33 ns | 1,500.0 ns | +| OddEvenCompileTime | 10 | 395.0 ns | 9.83 ns | 21.98 ns | 400.0 ns | +| GnomeRunTime | 10 | 1,527.1 ns | 34.21 ns | 83.27 ns | 1,500.0 ns | +| GnomeCompileTime | 10 | 473.0 ns | 21.48 ns | 63.33 ns | 500.0 ns | +| CombRunTime | 10 | 1,521.5 ns | 32.41 ns | 84.23 ns | 1,500.0 ns | +| CombCompileTime | 10 | 295.0 ns | 9.83 ns | 21.98 ns | 300.0 ns | +| ShellRunTime | 10 | 1,407.8 ns | 31.03 ns | 82.82 ns | 1,450.0 ns | +| ShellCompileTime | 10 | 967.2 ns | 19.91 ns | 47.32 ns | 1,000.0 ns | +| CocktailRunTime | 10 | 1,766.7 ns | 37.17 ns | 70.71 ns | 1,800.0 ns | +| CocktailCompileTime | 10 | 386.9 ns | 12.63 ns | 33.94 ns | 400.0 ns | +| CycleRunTime | 10 | 2,065.2 ns | 45.29 ns | 57.28 ns | 2,100.0 ns | +| CycleCompileTime | 10 | 664.9 ns | 17.26 ns | 50.09 ns | 700.0 ns | +| PancakeRunTime | 10 | 1,883.9 ns | 86.64 ns | 237.17 ns | 1,800.0 ns | +| PancakeCompileTime | 10 | 731.2 ns | 25.30 ns | 73.00 ns | 700.0 ns | +| StoogeRunTime | 10 | 9,792.3 ns | 179.37 ns | 149.79 ns | 9,800.0 ns | +| StoogeCompileTime | 10 | 8,236.7 ns | 165.95 ns | 155.23 ns | 8,250.0 ns | +| SlowRunTime | 10 | 4,060.5 ns | 112.55 ns | 296.51 ns | 4,000.0 ns | +| SlowCompileTime | 10 | 2,887.9 ns | 68.76 ns | 201.66 ns | 2,900.0 ns | +| BogoRunTime | 10 | 408,640,771.9 ns | 120,405,364.98 ns | 347,397,008.15 ns | 306,325,400.0 ns | +| BogoCompileTime | 10 | 366,271,451.6 ns | 97,933,882.34 ns | 280,990,666.77 ns | 280,804,700.0 ns | +| **SystemArraySort** | **1000** | **27,376.9 ns** | **400.64 ns** | **334.55 ns** | **27,200.0 ns** | +| SystemArraySortDelegate | 1000 | 64,900.0 ns | 1,283.51 ns | 1,200.60 ns | 65,300.0 ns | +| SystemArraySortIComparer | 1000 | 74,223.1 ns | 1,345.26 ns | 1,123.35 ns | 74,500.0 ns | +| BubbleRunTime | 1000 | 3,954,363.0 ns | 57,961.23 ns | 111,671.62 ns | 3,935,950.0 ns | +| BubbleCompileTime | 1000 | 1,422,964.7 ns | 22,019.39 ns | 35,557.21 ns | 1,416,250.0 ns | +| SelectionRunTime | 1000 | 2,784,468.8 ns | 51,721.92 ns | 50,797.84 ns | 2,781,000.0 ns | +| SelectionCompileTime | 1000 | 739,492.2 ns | 14,496.94 ns | 33,598.86 ns | 745,400.0 ns | +| InsertionRunTime | 1000 | 1,363,592.9 ns | 26,749.20 ns | 23,712.47 ns | 1,365,950.0 ns | +| InsertionCompileTime | 1000 | 245,661.1 ns | 4,882.42 ns | 8,157.43 ns | 240,200.0 ns | +| QuickRunTime | 1000 | 138,744.4 ns | 2,741.17 ns | 2,933.02 ns | 136,700.0 ns | +| QuickCompileTime | 1000 | 60,723.1 ns | 1,008.06 ns | 841.78 ns | 60,800.0 ns | +| MergeRunTime | 1000 | 102,642.1 ns | 1,274.23 ns | 1,416.30 ns | 102,700.0 ns | +| MergeCompileTime | 1000 | 60,565.7 ns | 1,192.85 ns | 1,959.88 ns | 60,200.0 ns | +| HeapRunTime | 1000 | 324,035.7 ns | 6,412.83 ns | 11,726.22 ns | 318,800.0 ns | +| HeapCompileTime | 1000 | 279,686.7 ns | 5,487.56 ns | 5,133.07 ns | 280,500.0 ns | +| OddEvenRunTime | 1000 | 3,077,887.0 ns | 58,226.69 ns | 112,183.07 ns | 3,040,950.0 ns | +| OddEvenCompileTime | 1000 | 782,177.1 ns | 15,456.97 ns | 25,396.25 ns | 780,000.0 ns | +| GnomeRunTime | 1000 | 2,999,268.4 ns | 59,654.41 ns | 102,900.92 ns | 2,980,350.0 ns | +| GnomeCompileTime | 1000 | 616,600.0 ns | 12,266.74 ns | 27,937.58 ns | 611,400.0 ns | +| CombRunTime | 1000 | 177,127.0 ns | 3,523.23 ns | 9,762.86 ns | 173,600.0 ns | +| CombCompileTime | 1000 | 52,820.0 ns | 186.05 ns | 174.03 ns | 52,800.0 ns | +| ShellRunTime | 1000 | 114,646.2 ns | 2,008.40 ns | 1,677.11 ns | 113,600.0 ns | +| ShellCompileTime | 1000 | 51,540.0 ns | 1,011.03 ns | 1,349.69 ns | 51,000.0 ns | +| CocktailRunTime | 1000 | 3,317,374.2 ns | 64,838.69 ns | 99,015.52 ns | 3,290,000.0 ns | +| CocktailCompileTime | 1000 | 1,041,636.0 ns | 20,656.81 ns | 52,202.40 ns | 1,027,700.0 ns | +| CycleRunTime | 1000 | 5,980,266.2 ns | 118,709.73 ns | 291,196.99 ns | 5,928,800.0 ns | +| CycleCompileTime | 1000 | 2,306,741.4 ns | 46,009.61 ns | 125,950.55 ns | 2,283,500.0 ns | +| PancakeRunTime | 1000 | 3,178,159.0 ns | 58,921.35 ns | 103,195.99 ns | 3,154,700.0 ns | +| PancakeCompileTime | 1000 | 527,375.8 ns | 11,455.86 ns | 33,235.52 ns | 515,350.0 ns | +| StoogeRunTime | 1000 | 401,364,786.7 ns | 7,218,995.96 ns | 6,752,653.30 ns | 400,306,300.0 ns | +| StoogeCompileTime | 1000 | 266,373,092.9 ns | 2,447,164.00 ns | 2,169,347.15 ns | 266,326,000.0 ns | | SlowRunTime | 1000 | NA | NA | NA | NA | | SlowCompileTime | 1000 | NA | NA | NA | NA | | BogoRunTime | 1000 | NA | NA | NA | NA | | BogoCompileTime | 1000 | NA | NA | NA | NA | -| **SystemArraySort** | **10000** | **375,588.2 ns** | **7,159.17 ns** | **7,351.95 ns** | **374,600.0 ns** | -| SystemArraySortDelegate | 10000 | 882,028.6 ns | 13,078.25 ns | 11,593.53 ns | 879,050.0 ns | -| SystemArraySortIComparer | 10000 | 1,023,307.7 ns | 19,933.85 ns | 27,285.67 ns | 1,019,150.0 ns | -| BubbleRunTime | 10000 | 528,211,900.0 ns | 881,965.43 ns | 781,839.38 ns | 528,035,200.0 ns | -| BubbleCompileTime | 10000 | 181,560,513.3 ns | 2,627,085.18 ns | 2,457,377.11 ns | 180,623,300.0 ns | -| SelectionRunTime | 10000 | 212,526,813.3 ns | 2,282,016.46 ns | 2,134,599.61 ns | 211,880,200.0 ns | -| SelectionCompileTime | 10000 | 87,702,120.0 ns | 730,295.57 ns | 683,118.93 ns | 87,626,300.0 ns | -| InsertionRunTime | 10000 | 100,515,369.2 ns | 399,236.14 ns | 333,380.26 ns | 100,502,100.0 ns | -| InsertionCompileTime | 10000 | 23,704,820.0 ns | 460,820.33 ns | 431,051.62 ns | 23,787,900.0 ns | -| QuickRunTime | 10000 | 2,300,021.9 ns | 73,932.91 ns | 115,104.63 ns | 2,272,750.0 ns | -| QuickCompileTime | 10000 | 736,716.7 ns | 10,410.63 ns | 8,127.94 ns | 734,950.0 ns | -| MergeRunTime | 10000 | 1,605,363.8 ns | 31,941.39 ns | 62,299.23 ns | 1,591,700.0 ns | -| MergeCompileTime | 10000 | 777,888.5 ns | 15,554.01 ns | 21,290.51 ns | 771,400.0 ns | -| HeapRunTime | 10000 | 1,813,392.6 ns | 75,455.52 ns | 198,780.02 ns | 1,726,600.0 ns | -| HeapCompileTime | 10000 | 2,778,552.0 ns | 626,971.35 ns | 1,848,639.16 ns | 1,254,400.0 ns | -| OddEvenRunTime | 10000 | 249,007,246.2 ns | 783,602.86 ns | 654,343.88 ns | 248,769,600.0 ns | -| OddEvenCompileTime | 10000 | 98,183,846.7 ns | 771,000.03 ns | 721,193.91 ns | 97,977,500.0 ns | -| GnomeRunTime | 10000 | 192,898,900.0 ns | 1,776,236.67 ns | 1,661,492.89 ns | 192,680,100.0 ns | -| GnomeCompileTime | 10000 | 73,236,420.0 ns | 916,576.37 ns | 857,366.10 ns | 73,181,800.0 ns | -| CombRunTime | 10000 | 2,451,925.0 ns | 197,472.37 ns | 582,251.73 ns | 2,730,650.0 ns | -| CombCompileTime | 10000 | 722,571.4 ns | 11,346.35 ns | 10,058.25 ns | 720,500.0 ns | -| ShellRunTime | 10000 | 1,973,082.1 ns | 116,071.31 ns | 333,030.35 ns | 2,049,300.0 ns | -| ShellCompileTime | 10000 | 785,991.3 ns | 15,949.16 ns | 38,519.02 ns | 770,400.0 ns | -| CocktailRunTime | 10000 | 235,964,593.3 ns | 1,158,553.71 ns | 1,083,711.86 ns | 235,888,000.0 ns | -| CocktailCompileTime | 10000 | 109,647,266.7 ns | 756,960.54 ns | 708,061.36 ns | 109,853,500.0 ns | +| **SystemArraySort** | **10000** | **377,969.2 ns** | **7,559.28 ns** | **6,312.34 ns** | **376,000.0 ns** | +| SystemArraySortDelegate | 10000 | 872,571.4 ns | 17,393.41 ns | 28,577.88 ns | 869,400.0 ns | +| SystemArraySortIComparer | 10000 | 1,011,947.4 ns | 20,569.63 ns | 59,676.23 ns | 991,300.0 ns | +| BubbleRunTime | 10000 | 424,016,446.2 ns | 2,577,204.80 ns | 2,152,082.73 ns | 424,601,400.0 ns | +| BubbleCompileTime | 10000 | 175,176,506.7 ns | 1,969,299.84 ns | 1,842,084.29 ns | 175,173,100.0 ns | +| SelectionRunTime | 10000 | 182,416,121.4 ns | 899,828.11 ns | 797,674.18 ns | 182,294,400.0 ns | +| SelectionCompileTime | 10000 | 63,572,453.3 ns | 1,005,208.06 ns | 940,272.25 ns | 63,640,400.0 ns | +| InsertionRunTime | 10000 | 87,353,211.1 ns | 1,641,611.43 ns | 1,756,505.84 ns | 86,837,050.0 ns | +| InsertionCompileTime | 10000 | 23,283,000.0 ns | 323,235.82 ns | 302,354.99 ns | 23,255,300.0 ns | +| QuickRunTime | 10000 | 1,852,821.4 ns | 36,896.49 ns | 32,707.78 ns | 1,844,550.0 ns | +| QuickCompileTime | 10000 | 803,142.9 ns | 15,336.17 ns | 13,595.12 ns | 799,450.0 ns | +| MergeRunTime | 10000 | 1,307,386.0 ns | 61,643.60 ns | 181,757.54 ns | 1,355,100.0 ns | +| MergeCompileTime | 10000 | 745,082.9 ns | 14,834.55 ns | 24,373.59 ns | 749,900.0 ns | +| HeapRunTime | 10000 | 4,353,192.0 ns | 83,442.36 ns | 111,393.16 ns | 4,359,200.0 ns | +| HeapCompileTime | 10000 | 3,757,913.8 ns | 74,486.55 ns | 109,181.42 ns | 3,744,200.0 ns | +| OddEvenRunTime | 10000 | 214,996,207.1 ns | 3,505,409.28 ns | 3,107,454.02 ns | 214,684,050.0 ns | +| OddEvenCompileTime | 10000 | 88,363,146.7 ns | 1,240,145.97 ns | 1,160,033.31 ns | 88,172,300.0 ns | +| GnomeRunTime | 10000 | 186,955,626.7 ns | 1,872,062.50 ns | 1,751,128.42 ns | 186,499,500.0 ns | +| GnomeCompileTime | 10000 | 57,804,820.0 ns | 358,605.75 ns | 335,440.04 ns | 57,729,000.0 ns | +| CombRunTime | 10000 | 2,269,483.3 ns | 43,621.32 ns | 56,720.04 ns | 2,263,150.0 ns | +| CombCompileTime | 10000 | 715,031.8 ns | 14,017.13 ns | 17,214.29 ns | 719,000.0 ns | +| ShellRunTime | 10000 | 1,675,561.5 ns | 23,374.25 ns | 19,518.56 ns | 1,678,000.0 ns | +| ShellCompileTime | 10000 | 738,593.5 ns | 14,513.86 ns | 27,963.28 ns | 737,400.0 ns | +| CocktailRunTime | 10000 | 210,972,130.8 ns | 3,805,184.72 ns | 5,208,579.80 ns | 209,136,000.0 ns | +| CocktailCompileTime | 10000 | 104,287,557.1 ns | 1,857,076.57 ns | 1,646,250.01 ns | 103,847,800.0 ns | +| CycleRunTime | 10000 | 601,703,246.7 ns | 6,858,433.28 ns | 6,415,382.74 ns | 602,074,700.0 ns | +| CycleCompileTime | 10000 | 235,052,414.3 ns | 2,129,956.56 ns | 1,888,151.02 ns | 234,151,250.0 ns | +| PancakeRunTime | 10000 | 193,687,771.4 ns | 1,840,584.01 ns | 1,631,629.79 ns | 193,974,550.0 ns | +| PancakeCompileTime | 10000 | 45,405,792.9 ns | 602,539.69 ns | 534,135.74 ns | 45,538,750.0 ns | +| StoogeRunTime | 10000 | NA | NA | NA | NA | +| StoogeCompileTime | 10000 | NA | NA | NA | NA | | SlowRunTime | 10000 | NA | NA | NA | NA | | SlowCompileTime | 10000 | NA | NA | NA | NA | | BogoRunTime | 10000 | NA | NA | NA | NA | | BogoCompileTime | 10000 | NA | NA | NA | NA | Benchmarks with issues: - Sort_Benchmarks.SlowRunTime: Job-ZKCIBR(InvocationCount=1, UnrollFactor=1) [N=1000] - Sort_Benchmarks.SlowCompileTime: Job-ZKCIBR(InvocationCount=1, UnrollFactor=1) [N=1000] - Sort_Benchmarks.BogoRunTime: Job-ZKCIBR(InvocationCount=1, UnrollFactor=1) [N=1000] - Sort_Benchmarks.BogoCompileTime: Job-ZKCIBR(InvocationCount=1, UnrollFactor=1) [N=1000] - Sort_Benchmarks.SlowRunTime: Job-ZKCIBR(InvocationCount=1, UnrollFactor=1) [N=10000] - Sort_Benchmarks.SlowCompileTime: Job-ZKCIBR(InvocationCount=1, UnrollFactor=1) [N=10000] - Sort_Benchmarks.BogoRunTime: Job-ZKCIBR(InvocationCount=1, UnrollFactor=1) [N=10000] - Sort_Benchmarks.BogoCompileTime: Job-ZKCIBR(InvocationCount=1, UnrollFactor=1) [N=10000] + Sort_Benchmarks.SlowRunTime: Job-BQFFMI(InvocationCount=1, UnrollFactor=1) [N=1000] + Sort_Benchmarks.SlowCompileTime: Job-BQFFMI(InvocationCount=1, UnrollFactor=1) [N=1000] + Sort_Benchmarks.BogoRunTime: Job-BQFFMI(InvocationCount=1, UnrollFactor=1) [N=1000] + Sort_Benchmarks.BogoCompileTime: Job-BQFFMI(InvocationCount=1, UnrollFactor=1) [N=1000] + Sort_Benchmarks.StoogeRunTime: Job-BQFFMI(InvocationCount=1, UnrollFactor=1) [N=10000] + Sort_Benchmarks.StoogeCompileTime: Job-BQFFMI(InvocationCount=1, UnrollFactor=1) [N=10000] + Sort_Benchmarks.SlowRunTime: Job-BQFFMI(InvocationCount=1, UnrollFactor=1) [N=10000] + Sort_Benchmarks.SlowCompileTime: Job-BQFFMI(InvocationCount=1, UnrollFactor=1) [N=10000] + Sort_Benchmarks.BogoRunTime: Job-BQFFMI(InvocationCount=1, UnrollFactor=1) [N=10000] + Sort_Benchmarks.BogoCompileTime: Job-BQFFMI(InvocationCount=1, UnrollFactor=1) [N=10000] # Data Structures @@ -125,46 +145,46 @@ The source code for all becnhmarks are in [Tools/Towel.Benchmarking](https://git ``` ini -BenchmarkDotNet=v0.12.0, OS=Windows 10.0.18363 +BenchmarkDotNet=v0.12.1, OS=Windows 10.0.18363.1198 (1909/November2018Update/19H2) Intel Core i7-4790K CPU 4.00GHz (Haswell), 1 CPU, 8 logical and 4 physical cores -.NET Core SDK=5.0.100-rc.1.20452.10 - [Host] : .NET Core 3.1.8 (CoreCLR 4.700.20.41105, CoreFX 4.700.20.41903), X64 RyuJIT - DefaultJob : .NET Core 3.1.8 (CoreCLR 4.700.20.41105, CoreFX 4.700.20.41903), X64 RyuJIT +.NET Core SDK=5.0.100 + [Host] : .NET Core 5.0.0 (CoreCLR 5.0.20.51904, CoreFX 5.0.20.51904), X64 RyuJIT + DefaultJob : .NET Core 5.0.0 (CoreCLR 5.0.20.51904, CoreFX 5.0.20.51904), X64 RyuJIT ``` -| Method | RandomTestData | Mean | Error | StdDev | -|------------------------------- |--------------------- |-----------------:|----------------:|----------------:| -| ListArray_Add | Towel(...)son[] [27] | 963.2 ns | 6.52 ns | 6.10 ns | -| ListArray_Add | Towel(...)son[] [27] | 2,035,842.5 ns | 18,823.29 ns | 17,607.32 ns | -| ListArray_AddWithCapacity | Towel(...)son[] [27] | 623.3 ns | 2.14 ns | 1.78 ns | -| ListArray_AddWithCapacity | Towel(...)son[] [27] | 1,594,337.3 ns | 9,843.56 ns | 8,726.06 ns | -| Add | Towel(...)son[] [27] | 1,255.1 ns | 24.99 ns | 26.74 ns | -| Add | Towel(...)son[] [27] | 2,588,119.8 ns | 30,657.49 ns | 27,177.07 ns | -| QueueArray_Enqueue | Towel(...)son[] [27] | 1,531.0 ns | 20.50 ns | 19.17 ns | -| QueueArray_Enqueue | Towel(...)son[] [27] | 3,094,074.6 ns | 25,860.20 ns | 24,189.65 ns | -| QueueArray_EnqueueWithCapacity | Towel(...)son[] [27] | 782.1 ns | 14.97 ns | 14.70 ns | -| QueueArray_EnqueueWithCapacity | Towel(...)son[] [27] | 1,621,417.3 ns | 20,138.13 ns | 18,837.22 ns | -| QueueLinked_Enqueue | Towel(...)son[] [27] | 1,040.8 ns | 13.55 ns | 12.67 ns | -| QueueLinked_Enqueue | Towel(...)son[] [27] | 2,375,892.9 ns | 30,222.14 ns | 26,791.14 ns | -| StackArray_Push | Towel(...)son[] [27] | 1,005.4 ns | 5.49 ns | 4.87 ns | -| StackArray_Push | Towel(...)son[] [27] | 2,765,587.7 ns | 9,648.74 ns | 8,553.35 ns | -| StackArray_PushWithCapacity | Towel(...)son[] [27] | 522.3 ns | 2.11 ns | 1.76 ns | -| StackArray_PushWithCapacity | Towel(...)son[] [27] | 1,450,710.2 ns | 14,544.67 ns | 12,893.47 ns | -| StackLinked_Push | Towel(...)son[] [27] | 1,011.8 ns | 10.15 ns | 9.49 ns | -| StackLinked_Push | Towel(...)son[] [27] | 2,414,910.8 ns | 45,902.85 ns | 42,937.55 ns | -| AvlTreeLinked_AddRunTime | Towel(...)son[] [27] | 63,596.4 ns | 767.54 ns | 717.96 ns | -| AvlTreeLinked_AddRunTime | Towel(...)son[] [27] | 264,524,833.3 ns | 5,203,594.52 ns | 4,867,445.54 ns | -| AvlTreeLinked_AddCompileTime | Towel(...)son[] [27] | 63,154.6 ns | 217.25 ns | 181.41 ns | -| AvlTreeLinked_AddCompileTime | Towel(...)son[] [27] | 261,191,700.0 ns | 3,299,321.67 ns | 2,924,762.72 ns | -| RedBlackTree_AddRunTime | Towel(...)son[] [27] | 71,869.3 ns | 244.19 ns | 203.91 ns | -| RedBlackTree_AddRunTime | Towel(...)son[] [27] | 247,596,395.6 ns | 2,756,212.87 ns | 2,578,163.23 ns | -| RedBlackTree_AddCompileTime | Towel(...)son[] [27] | 69,429.1 ns | 214.10 ns | 189.80 ns | -| RedBlackTree_AddCompileTime | Towel(...)son[] [27] | 253,333,080.0 ns | 3,015,928.60 ns | 2,821,101.48 ns | -| SetHashLinked_AddRunTime | Towel(...)son[] [27] | 5,664.4 ns | 34.30 ns | 30.40 ns | -| SetHashLinked_AddRunTime | Towel(...)son[] [27] | 36,965,666.7 ns | 673,118.14 ns | 629,635.12 ns | -| SetHashLinked_AddCompileTime | Towel(...)son[] [27] | 4,584.7 ns | 20.36 ns | 15.90 ns | -| SetHashLinked_AddCompileTime | Towel(...)son[] [27] | 35,193,594.8 ns | 459,667.39 ns | 407,483.17 ns | +| Method | RandomTestData | Mean | Error | StdDev | Median | +|------------------------------- |--------------- |-----------------:|----------------:|-----------------:|-----------------:| +| **ListArray_Add** | **Person[100000]** | **2,220,841.2 ns** | **41,526.07 ns** | **36,811.78 ns** | **2,211,234.4 ns** | +| ListArray_AddWithCapacity | Person[100000] | 1,638,193.4 ns | 12,819.78 ns | 11,364.40 ns | 1,639,400.1 ns | +| Add | Person[100000] | 2,463,200.7 ns | 49,257.41 ns | 103,900.59 ns | 2,429,375.2 ns | +| QueueArray_Enqueue | Person[100000] | 2,969,548.7 ns | 59,356.80 ns | 147,819.02 ns | 2,965,686.7 ns | +| QueueArray_EnqueueWithCapacity | Person[100000] | 2,820,271.4 ns | 27,131.10 ns | 24,051.01 ns | 2,814,930.7 ns | +| QueueLinked_Enqueue | Person[100000] | 2,064,972.5 ns | 16,182.77 ns | 15,137.37 ns | 2,065,725.0 ns | +| StackArray_Push | Person[100000] | 2,603,447.9 ns | 31,568.63 ns | 29,529.31 ns | 2,592,617.2 ns | +| StackArray_PushWithCapacity | Person[100000] | 1,381,933.3 ns | 9,664.79 ns | 9,040.45 ns | 1,382,645.7 ns | +| StackLinked_Push | Person[100000] | 2,047,188.9 ns | 39,796.88 ns | 39,085.86 ns | 2,061,384.8 ns | +| AvlTreeLinked_AddRunTime | Person[100000] | 215,499,238.5 ns | 4,302,211.21 ns | 6,698,024.54 ns | 211,333,366.7 ns | +| AvlTreeLinked_AddCompileTime | Person[100000] | 236,006,146.4 ns | 7,349,520.87 ns | 21,322,292.70 ns | 232,342,400.0 ns | +| RedBlackTree_AddRunTime | Person[100000] | 219,557,622.2 ns | 4,384,980.99 ns | 7,326,318.16 ns | 218,696,650.0 ns | +| RedBlackTree_AddCompileTime | Person[100000] | 221,010,511.0 ns | 7,631,399.77 ns | 22,501,354.42 ns | 207,026,866.7 ns | +| SetHashLinked_AddRunTime | Person[100000] | 34,458,951.8 ns | 302,179.84 ns | 252,333.85 ns | 34,463,266.7 ns | +| SetHashLinked_AddCompileTime | Person[100000] | 35,764,827.2 ns | 847,782.05 ns | 2,499,704.50 ns | 35,313,506.2 ns | +| **ListArray_Add** | **Person[100]** | **1,038.6 ns** | **7.54 ns** | **6.30 ns** | **1,038.4 ns** | +| ListArray_AddWithCapacity | Person[100] | 797.1 ns | 15.54 ns | 19.09 ns | 789.8 ns | +| Add | Person[100] | 1,358.1 ns | 26.86 ns | 43.37 ns | 1,347.8 ns | +| QueueArray_Enqueue | Person[100] | 1,211.0 ns | 35.77 ns | 103.78 ns | 1,164.2 ns | +| QueueArray_EnqueueWithCapacity | Person[100] | 980.4 ns | 7.85 ns | 7.34 ns | 979.7 ns | +| QueueLinked_Enqueue | Person[100] | 1,049.9 ns | 5.98 ns | 4.99 ns | 1,048.2 ns | +| StackArray_Push | Person[100] | 1,044.0 ns | 6.10 ns | 5.10 ns | 1,043.4 ns | +| StackArray_PushWithCapacity | Person[100] | 503.4 ns | 2.10 ns | 1.97 ns | 503.4 ns | +| StackLinked_Push | Person[100] | 1,002.8 ns | 7.47 ns | 6.62 ns | 1,002.3 ns | +| AvlTreeLinked_AddRunTime | Person[100] | 49,930.0 ns | 959.00 ns | 1,280.24 ns | 49,959.2 ns | +| AvlTreeLinked_AddCompileTime | Person[100] | 51,511.8 ns | 1,023.19 ns | 1,531.47 ns | 50,546.8 ns | +| RedBlackTree_AddRunTime | Person[100] | 57,721.9 ns | 1,148.32 ns | 1,410.24 ns | 58,476.9 ns | +| RedBlackTree_AddCompileTime | Person[100] | 56,844.1 ns | 1,126.60 ns | 1,882.30 ns | 57,075.9 ns | +| SetHashLinked_AddRunTime | Person[100] | 6,134.5 ns | 29.92 ns | 24.98 ns | 6,133.7 ns | +| SetHashLinked_AddCompileTime | Person[100] | 4,967.4 ns | 61.37 ns | 57.41 ns | 4,946.5 ns | # Random @@ -172,27 +192,27 @@ The source code for all becnhmarks are in [Tools/Towel.Benchmarking](https://git ``` ini -BenchmarkDotNet=v0.12.0, OS=Windows 10.0.18363 +BenchmarkDotNet=v0.12.1, OS=Windows 10.0.18363.1198 (1909/November2018Update/19H2) Intel Core i7-4790K CPU 4.00GHz (Haswell), 1 CPU, 8 logical and 4 physical cores -.NET Core SDK=5.0.100-rc.1.20452.10 - [Host] : .NET Core 3.1.8 (CoreCLR 4.700.20.41105, CoreFX 4.700.20.41903), X64 RyuJIT - Job-ZKCIBR : .NET Core 3.1.8 (CoreCLR 4.700.20.41105, CoreFX 4.700.20.41903), X64 RyuJIT +.NET Core SDK=5.0.100 + [Host] : .NET Core 5.0.0 (CoreCLR 5.0.20.51904, CoreFX 5.0.20.51904), X64 RyuJIT + Job-BQFFMI : .NET Core 5.0.0 (CoreCLR 5.0.20.51904, CoreFX 5.0.20.51904), X64 RyuJIT InvocationCount=1 UnrollFactor=1 ``` -| Method | N | Mean | Error | StdDev | Median | -|----------------------------- |------- |-------------:|------------:|------------:|-------------:| -| **Next_IEnumerable_TotalWeight** | **10** | **2.556 us** | **0.2915 us** | **0.8175 us** | **2.100 us** | -| Next_IEnumerable | 10 | 2.410 us | 0.0550 us | 0.1478 us | 2.400 us | -| **Next_IEnumerable_TotalWeight** | **100** | **4.098 us** | **0.3785 us** | **1.0551 us** | **3.500 us** | -| Next_IEnumerable | 100 | 4.983 us | 0.1282 us | 0.2312 us | 5.000 us | -| **Next_IEnumerable_TotalWeight** | **1000** | **17.706 us** | **0.8182 us** | **2.3475 us** | **17.200 us** | -| Next_IEnumerable | 1000 | 33.939 us | 1.5423 us | 4.4004 us | 32.600 us | -| **Next_IEnumerable_TotalWeight** | **10000** | **136.041 us** | **8.8173 us** | **9.0548 us** | **131.500 us** | -| Next_IEnumerable | 10000 | 330.240 us | 12.9513 us | 37.9838 us | 323.900 us | -| **Next_IEnumerable_TotalWeight** | **100000** | **1,327.625 us** | **26.3989 us** | **61.7065 us** | **1,303.400 us** | -| Next_IEnumerable | 100000 | 2,876.262 us | 179.3327 us | 528.7664 us | 3,045.800 us | +| Method | N | Mean | Error | StdDev | Median | +|----------------------------- |------- |-------------:|-----------:|------------:|-------------:| +| **Next_IEnumerable_TotalWeight** | **10** | **2.249 μs** | **0.1355 μs** | **0.3731 μs** | **2.150 μs** | +| Next_IEnumerable | 10 | 2.244 μs | 0.0483 μs | 0.1175 μs | 2.200 μs | +| **Next_IEnumerable_TotalWeight** | **100** | **3.228 μs** | **0.0680 μs** | **0.0996 μs** | **3.200 μs** | +| Next_IEnumerable | 100 | 4.865 μs | 0.0994 μs | 0.1518 μs | 4.900 μs | +| **Next_IEnumerable_TotalWeight** | **1000** | **14.377 μs** | **0.2815 μs** | **0.2351 μs** | **14.400 μs** | +| Next_IEnumerable | 1000 | 29.842 μs | 0.5778 μs | 0.8823 μs | 29.500 μs | +| **Next_IEnumerable_TotalWeight** | **10000** | **126.187 μs** | **2.3495 μs** | **2.1977 μs** | **126.400 μs** | +| Next_IEnumerable | 10000 | 275.433 μs | 3.9165 μs | 3.6635 μs | 273.000 μs | +| **Next_IEnumerable_TotalWeight** | **100000** | **1,280.184 μs** | **25.0843 μs** | **39.0532 μs** | **1,260.550 μs** | +| Next_IEnumerable | 100000 | 2,914.506 μs | 57.9758 μs | 137.7857 μs | 2,877.200 μs | # [Numeric] To English Words @@ -200,21 +220,21 @@ The source code for all becnhmarks are in [Tools/Towel.Benchmarking](https://git ``` ini -BenchmarkDotNet=v0.12.0, OS=Windows 10.0.18363 +BenchmarkDotNet=v0.12.1, OS=Windows 10.0.18363.1198 (1909/November2018Update/19H2) Intel Core i7-4790K CPU 4.00GHz (Haswell), 1 CPU, 8 logical and 4 physical cores -.NET Core SDK=5.0.100-rc.1.20452.10 - [Host] : .NET Core 3.1.8 (CoreCLR 4.700.20.41105, CoreFX 4.700.20.41903), X64 RyuJIT - DefaultJob : .NET Core 3.1.8 (CoreCLR 4.700.20.41105, CoreFX 4.700.20.41903), X64 RyuJIT +.NET Core SDK=5.0.100 + [Host] : .NET Core 5.0.0 (CoreCLR 5.0.20.51904, CoreFX 5.0.20.51904), X64 RyuJIT + DefaultJob : .NET Core 5.0.0 (CoreCLR 5.0.20.51904, CoreFX 5.0.20.51904), X64 RyuJIT ``` -| Method | Range | Mean | Error | StdDev | -|----------------------- |------- |---------:|---------:|---------:| -| **Decimal_ToEnglishWords** | **10** | **72.75 ms** | **0.382 ms** | **0.338 ms** | -| **Decimal_ToEnglishWords** | **100** | **71.27 ms** | **0.247 ms** | **0.219 ms** | -| **Decimal_ToEnglishWords** | **1000** | **65.85 ms** | **0.226 ms** | **0.189 ms** | -| **Decimal_ToEnglishWords** | **10000** | **68.44 ms** | **0.337 ms** | **0.298 ms** | -| **Decimal_ToEnglishWords** | **100000** | **68.87 ms** | **0.870 ms** | **0.813 ms** | +| Method | Range | Mean | Error | StdDev | Median | +|----------------------- |------- |---------:|---------:|---------:|---------:| +| **Decimal_ToEnglishWords** | **10** | **70.89 ms** | **0.756 ms** | **0.670 ms** | **70.84 ms** | +| **Decimal_ToEnglishWords** | **100** | **71.26 ms** | **1.402 ms** | **1.500 ms** | **70.69 ms** | +| **Decimal_ToEnglishWords** | **1000** | **62.99 ms** | **1.246 ms** | **1.903 ms** | **61.89 ms** | +| **Decimal_ToEnglishWords** | **10000** | **65.44 ms** | **0.225 ms** | **0.210 ms** | **65.36 ms** | +| **Decimal_ToEnglishWords** | **100000** | **65.56 ms** | **0.596 ms** | **0.528 ms** | **65.77 ms** | # Permute @@ -222,65 +242,65 @@ The source code for all becnhmarks are in [Tools/Towel.Benchmarking](https://git ``` ini -BenchmarkDotNet=v0.12.0, OS=Windows 10.0.18363 +BenchmarkDotNet=v0.12.1, OS=Windows 10.0.18363.1198 (1909/November2018Update/19H2) Intel Core i7-4790K CPU 4.00GHz (Haswell), 1 CPU, 8 logical and 4 physical cores -.NET Core SDK=5.0.100-rc.1.20452.10 - [Host] : .NET Core 3.1.8 (CoreCLR 4.700.20.41105, CoreFX 4.700.20.41903), X64 RyuJIT - Job-ZKCIBR : .NET Core 3.1.8 (CoreCLR 4.700.20.41105, CoreFX 4.700.20.41903), X64 RyuJIT +.NET Core SDK=5.0.100 + [Host] : .NET Core 5.0.0 (CoreCLR 5.0.20.51904, CoreFX 5.0.20.51904), X64 RyuJIT + Job-BQFFMI : .NET Core 5.0.0 (CoreCLR 5.0.20.51904, CoreFX 5.0.20.51904), X64 RyuJIT InvocationCount=1 UnrollFactor=1 ``` -| Method | N | Mean | Error | StdDev | Median | -|---------------- |--- |-------------------:|-----------------:|-----------------:|-------------------:| -| **Recursive** | **1** | **290.8 ns** | **10.62 ns** | **29.06 ns** | **300.0 ns** | -| Iterative | 1 | 993.4 ns | 43.67 ns | 111.16 ns | 1,000.0 ns | -| RecursiveStruct | 1 | 176.3 ns | 15.06 ns | 42.73 ns | 200.0 ns | -| IterativeStruct | 1 | 1,492.9 ns | 337.87 ns | 990.90 ns | 1,000.0 ns | -| **Recursive** | **2** | **400.0 ns** | **0.00 ns** | **0.00 ns** | **400.0 ns** | -| Iterative | 2 | 1,029.5 ns | 26.49 ns | 72.97 ns | 1,000.0 ns | -| RecursiveStruct | 2 | 323.5 ns | 42.58 ns | 43.72 ns | 300.0 ns | -| IterativeStruct | 2 | 1,456.6 ns | 316.21 ns | 927.38 ns | 1,000.0 ns | -| **Recursive** | **3** | **589.6 ns** | **15.64 ns** | **30.87 ns** | **600.0 ns** | -| Iterative | 3 | 1,628.3 ns | 319.19 ns | 936.13 ns | 1,100.0 ns | -| RecursiveStruct | 3 | 564.3 ns | 17.92 ns | 52.27 ns | 600.0 ns | -| IterativeStruct | 3 | 1,492.9 ns | 320.46 ns | 939.85 ns | 1,000.0 ns | -| **Recursive** | **4** | **1,300.0 ns** | **29.93 ns** | **74.54 ns** | **1,300.0 ns** | -| Iterative | 4 | 1,971.4 ns | 288.96 ns | 842.92 ns | 1,500.0 ns | -| RecursiveStruct | 4 | 1,093.8 ns | 25.45 ns | 25.00 ns | 1,100.0 ns | -| IterativeStruct | 4 | 1,681.6 ns | 278.17 ns | 811.43 ns | 1,300.0 ns | -| **Recursive** | **5** | **4,809.7 ns** | **133.83 ns** | **379.66 ns** | **5,000.0 ns** | -| Iterative | 5 | 2,861.4 ns | 61.04 ns | 162.92 ns | 2,900.0 ns | -| RecursiveStruct | 5 | 4,230.6 ns | 112.51 ns | 328.20 ns | 4,400.0 ns | -| IterativeStruct | 5 | 2,836.1 ns | 255.78 ns | 742.07 ns | 2,600.0 ns | -| **Recursive** | **6** | **26,031.9 ns** | **794.16 ns** | **2,226.90 ns** | **27,100.0 ns** | -| Iterative | 6 | 11,505.4 ns | 368.80 ns | 1,040.22 ns | 11,400.0 ns | -| RecursiveStruct | 6 | 23,266.3 ns | 527.40 ns | 1,487.55 ns | 24,100.0 ns | -| IterativeStruct | 6 | 9,005.1 ns | 420.85 ns | 1,227.63 ns | 9,500.0 ns | -| **Recursive** | **7** | **179,527.1 ns** | **4,458.07 ns** | **12,862.54 ns** | **185,250.0 ns** | -| Iterative | 7 | 70,106.9 ns | 1,396.67 ns | 3,452.22 ns | 70,650.0 ns | -| RecursiveStruct | 7 | 160,771.1 ns | 3,210.39 ns | 8,171.46 ns | 161,850.0 ns | -| IterativeStruct | 7 | 51,457.6 ns | 2,532.71 ns | 7,428.01 ns | 53,100.0 ns | -| **Recursive** | **8** | **1,277,079.2 ns** | **112,618.85 ns** | **324,931.15 ns** | **1,380,650.0 ns** | -| Iterative | 8 | 549,762.2 ns | 10,745.88 ns | 20,445.16 ns | 551,200.0 ns | -| RecursiveStruct | 8 | 1,254,614.0 ns | 24,961.42 ns | 50,423.30 ns | 1,254,250.0 ns | -| IterativeStruct | 8 | 412,090.7 ns | 14,467.32 ns | 41,972.33 ns | 427,700.0 ns | -| **Recursive** | **9** | **4,712,122.4 ns** | **100,712.56 ns** | **272,282.25 ns** | **4,651,800.0 ns** | -| Iterative | 9 | 4,784,983.9 ns | 106,671.09 ns | 162,898.02 ns | 4,770,700.0 ns | -| RecursiveStruct | 9 | 4,347,445.7 ns | 86,039.06 ns | 226,661.30 ns | 4,304,100.0 ns | -| IterativeStruct | 9 | 2,693,905.0 ns | 328,783.33 ns | 969,425.06 ns | 3,148,900.0 ns | -| **Recursive** | **10** | **44,466,333.3 ns** | **695,222.78 ns** | **650,311.82 ns** | **44,210,200.0 ns** | -| Iterative | 10 | 22,862,104.3 ns | 448,490.49 ns | 567,196.87 ns | 22,645,300.0 ns | -| RecursiveStruct | 10 | 42,560,269.2 ns | 687,196.44 ns | 573,840.15 ns | 42,688,700.0 ns | -| IterativeStruct | 10 | 13,990,683.3 ns | 273,603.30 ns | 409,516.54 ns | 13,932,700.0 ns | -| **Recursive** | **11** | **514,467,876.9 ns** | **2,451,207.70 ns** | **2,046,869.45 ns** | **514,123,300.0 ns** | -| Iterative | 11 | 249,272,342.9 ns | 1,355,880.84 ns | 1,201,953.05 ns | 249,310,450.0 ns | -| RecursiveStruct | 11 | 468,063,853.3 ns | 4,238,022.48 ns | 3,964,248.86 ns | 466,432,200.0 ns | -| IterativeStruct | 11 | 151,132,000.0 ns | 1,288,450.93 ns | 1,142,178.19 ns | 150,951,050.0 ns | -| **Recursive** | **12** | **6,177,772,966.7 ns** | **73,324,436.57 ns** | **68,587,723.46 ns** | **6,129,063,100.0 ns** | -| Iterative | 12 | 2,966,728,490.0 ns | 3,708,905.09 ns | 3,469,312.12 ns | 2,966,516,550.0 ns | -| RecursiveStruct | 12 | 5,582,501,335.7 ns | 67,418,310.47 ns | 59,764,576.19 ns | 5,574,910,200.0 ns | -| IterativeStruct | 12 | 1,821,838,092.9 ns | 5,106,766.30 ns | 4,527,015.31 ns | 1,822,382,050.0 ns | +| Method | N | Mean | Error | StdDev | Median | +|---------------- |--- |-------------------:|------------------:|------------------:|-------------------:| +| **Recursive** | **1** | **300.0 ns** | **0.00 ns** | **0.00 ns** | **300.0 ns** | +| Iterative | 1 | 971.1 ns | 26.48 ns | 73.81 ns | 1,000.0 ns | +| RecursiveStruct | 1 | 172.7 ns | 16.02 ns | 46.99 ns | 200.0 ns | +| IterativeStruct | 1 | 876.1 ns | 35.67 ns | 98.25 ns | 900.0 ns | +| **Recursive** | **2** | **300.0 ns** | **0.00 ns** | **0.00 ns** | **300.0 ns** | +| Iterative | 2 | 994.3 ns | 34.54 ns | 95.12 ns | 1,000.0 ns | +| RecursiveStruct | 2 | 269.4 ns | 16.63 ns | 48.50 ns | 300.0 ns | +| IterativeStruct | 2 | 927.6 ns | 28.24 ns | 77.29 ns | 900.0 ns | +| **Recursive** | **3** | **600.0 ns** | **0.00 ns** | **0.00 ns** | **600.0 ns** | +| Iterative | 3 | 1,111.2 ns | 29.15 ns | 78.82 ns | 1,150.0 ns | +| RecursiveStruct | 3 | 452.6 ns | 18.91 ns | 54.27 ns | 500.0 ns | +| IterativeStruct | 3 | 984.2 ns | 21.42 ns | 36.95 ns | 1,000.0 ns | +| **Recursive** | **4** | **1,047.4 ns** | **24.75 ns** | **53.80 ns** | **1,000.0 ns** | +| Iterative | 4 | 1,323.6 ns | 38.38 ns | 105.06 ns | 1,350.0 ns | +| RecursiveStruct | 4 | 1,037.0 ns | 24.60 ns | 61.25 ns | 1,000.0 ns | +| IterativeStruct | 4 | 1,266.2 ns | 27.30 ns | 69.98 ns | 1,300.0 ns | +| **Recursive** | **5** | **3,987.5 ns** | **82.09 ns** | **80.62 ns** | **4,000.0 ns** | +| Iterative | 5 | 2,478.4 ns | 103.64 ns | 285.45 ns | 2,400.0 ns | +| RecursiveStruct | 5 | 3,888.5 ns | 77.89 ns | 65.04 ns | 3,850.0 ns | +| IterativeStruct | 5 | 2,052.7 ns | 39.21 ns | 83.57 ns | 2,100.0 ns | +| **Recursive** | **6** | **22,625.0 ns** | **332.77 ns** | **259.81 ns** | **22,750.0 ns** | +| Iterative | 6 | 8,557.9 ns | 173.10 ns | 192.40 ns | 8,500.0 ns | +| RecursiveStruct | 6 | 21,932.3 ns | 370.74 ns | 866.59 ns | 21,700.0 ns | +| IterativeStruct | 6 | 7,300.0 ns | 138.28 ns | 115.47 ns | 7,300.0 ns | +| **Recursive** | **7** | **159,697.0 ns** | **3,305.13 ns** | **9,693.38 ns** | **155,000.0 ns** | +| Iterative | 7 | 53,107.7 ns | 732.46 ns | 611.64 ns | 52,900.0 ns | +| RecursiveStruct | 7 | 154,221.7 ns | 3,049.41 ns | 8,139.50 ns | 150,600.0 ns | +| IterativeStruct | 7 | 49,341.0 ns | 1,987.96 ns | 5,861.54 ns | 46,400.0 ns | +| **Recursive** | **8** | **1,276,934.0 ns** | **25,387.46 ns** | **52,993.09 ns** | **1,258,300.0 ns** | +| Iterative | 8 | 461,081.5 ns | 9,216.40 ns | 19,440.51 ns | 459,850.0 ns | +| RecursiveStruct | 8 | 1,216,315.0 ns | 21,022.95 ns | 37,368.27 ns | 1,203,100.0 ns | +| IterativeStruct | 8 | 369,595.9 ns | 7,329.12 ns | 18,252.06 ns | 364,100.0 ns | +| **Recursive** | **9** | **4,774,364.0 ns** | **98,051.46 ns** | **271,700.12 ns** | **4,693,800.0 ns** | +| Iterative | 9 | 3,911,729.6 ns | 76,388.25 ns | 107,085.66 ns | 3,885,500.0 ns | +| RecursiveStruct | 9 | 10,976,614.3 ns | 175,435.47 ns | 155,518.97 ns | 10,971,350.0 ns | +| IterativeStruct | 9 | 3,258,482.4 ns | 63,297.55 ns | 65,001.93 ns | 3,241,500.0 ns | +| **Recursive** | **10** | **46,189,421.4 ns** | **311,005.39 ns** | **275,698.17 ns** | **46,242,800.0 ns** | +| Iterative | 10 | 18,386,800.0 ns | 349,204.94 ns | 326,646.52 ns | 18,320,900.0 ns | +| RecursiveStruct | 10 | 42,757,413.3 ns | 498,034.42 ns | 465,861.70 ns | 42,864,800.0 ns | +| IterativeStruct | 10 | 14,422,250.0 ns | 270,887.26 ns | 289,846.33 ns | 14,353,100.0 ns | +| **Recursive** | **11** | **598,429,991.7 ns** | **8,606,436.50 ns** | **6,719,339.51 ns** | **598,243,500.0 ns** | +| Iterative | 11 | 202,086,675.0 ns | 1,114,766.42 ns | 870,336.30 ns | 202,033,050.0 ns | +| RecursiveStruct | 11 | 475,726,523.1 ns | 1,933,078.86 ns | 1,614,208.40 ns | 476,409,300.0 ns | +| IterativeStruct | 11 | 162,835,157.1 ns | 3,169,662.55 ns | 3,773,257.80 ns | 161,651,200.0 ns | +| **Recursive** | **12** | **6,349,684,185.7 ns** | **118,931,964.55 ns** | **105,430,088.76 ns** | **6,330,535,550.0 ns** | +| Iterative | 12 | 2,468,558,357.1 ns | 29,911,467.96 ns | 26,515,737.25 ns | 2,463,466,100.0 ns | +| RecursiveStruct | 12 | 5,829,397,746.2 ns | 44,463,411.79 ns | 37,128,962.60 ns | 5,815,656,900.0 ns | +| IterativeStruct | 12 | 1,951,315,707.1 ns | 4,256,182.02 ns | 3,772,994.50 ns | 1,952,321,350.0 ns | # Map vs Dictionary (Add) @@ -288,28 +308,28 @@ The source code for all becnhmarks are in [Tools/Towel.Benchmarking](https://git ``` ini -BenchmarkDotNet=v0.12.0, OS=Windows 10.0.18363 +BenchmarkDotNet=v0.12.1, OS=Windows 10.0.18363.1198 (1909/November2018Update/19H2) Intel Core i7-4790K CPU 4.00GHz (Haswell), 1 CPU, 8 logical and 4 physical cores -.NET Core SDK=5.0.100-rc.1.20452.10 - [Host] : .NET Core 3.1.8 (CoreCLR 4.700.20.41105, CoreFX 4.700.20.41903), X64 RyuJIT - DefaultJob : .NET Core 3.1.8 (CoreCLR 4.700.20.41105, CoreFX 4.700.20.41903), X64 RyuJIT +.NET Core SDK=5.0.100 + [Host] : .NET Core 5.0.0 (CoreCLR 5.0.20.51904, CoreFX 5.0.20.51904), X64 RyuJIT + DefaultJob : .NET Core 5.0.0 (CoreCLR 5.0.20.51904, CoreFX 5.0.20.51904), X64 RyuJIT ``` | Method | N | Mean | Error | StdDev | |------------- |------ |-------------:|------------:|------------:| -| **MapDelegates** | **10** | **512.3 ns** | **6.07 ns** | **5.38 ns** | -| MapStructs | 10 | 435.5 ns | 3.62 ns | 3.21 ns | -| Dictionary | 10 | 249.6 ns | 0.94 ns | 0.79 ns | -| **MapDelegates** | **100** | **4,164.9 ns** | **15.83 ns** | **14.03 ns** | -| MapStructs | 100 | 3,711.3 ns | 8.72 ns | 8.16 ns | -| Dictionary | 100 | 2,198.2 ns | 12.64 ns | 10.55 ns | -| **MapDelegates** | **1000** | **33,653.4 ns** | **385.06 ns** | **360.18 ns** | -| MapStructs | 1000 | 29,771.6 ns | 120.02 ns | 100.22 ns | -| Dictionary | 1000 | 21,078.6 ns | 82.18 ns | 76.87 ns | -| **MapDelegates** | **10000** | **617,945.4 ns** | **6,062.47 ns** | **5,374.22 ns** | -| MapStructs | 10000 | 582,379.9 ns | 4,567.55 ns | 3,814.11 ns | -| Dictionary | 10000 | 296,027.0 ns | 1,504.60 ns | 1,256.41 ns | +| **MapDelegates** | **10** | **2,408.4 ns** | **56.18 ns** | **149.96 ns** | +| MapStructs | 10 | 431.4 ns | 3.11 ns | 2.76 ns | +| Dictionary | 10 | 212.9 ns | 3.75 ns | 4.88 ns | +| **MapDelegates** | **100** | **4,231.1 ns** | **70.42 ns** | **62.43 ns** | +| MapStructs | 100 | 3,595.4 ns | 22.37 ns | 20.93 ns | +| Dictionary | 100 | 1,804.4 ns | 34.91 ns | 55.36 ns | +| **MapDelegates** | **1000** | **33,570.6 ns** | **333.35 ns** | **311.82 ns** | +| MapStructs | 1000 | 28,424.8 ns | 99.77 ns | 88.45 ns | +| Dictionary | 1000 | 17,510.2 ns | 140.16 ns | 109.43 ns | +| **MapDelegates** | **10000** | **511,985.1 ns** | **2,254.90 ns** | **2,109.23 ns** | +| MapStructs | 10000 | 483,271.4 ns | 9,418.26 ns | 9,671.86 ns | +| Dictionary | 10000 | 246,583.2 ns | 1,839.56 ns | 1,536.11 ns | # Map vs Dictionary (Look Up) @@ -317,29 +337,29 @@ The source code for all becnhmarks are in [Tools/Towel.Benchmarking](https://git ``` ini -BenchmarkDotNet=v0.12.0, OS=Windows 10.0.18363 +BenchmarkDotNet=v0.12.1, OS=Windows 10.0.18363.1198 (1909/November2018Update/19H2) Intel Core i7-4790K CPU 4.00GHz (Haswell), 1 CPU, 8 logical and 4 physical cores -.NET Core SDK=5.0.100-rc.1.20452.10 - [Host] : .NET Core 3.1.8 (CoreCLR 4.700.20.41105, CoreFX 4.700.20.41903), X64 RyuJIT - Job-ZKCIBR : .NET Core 3.1.8 (CoreCLR 4.700.20.41105, CoreFX 4.700.20.41903), X64 RyuJIT +.NET Core SDK=5.0.100 + [Host] : .NET Core 5.0.0 (CoreCLR 5.0.20.51904, CoreFX 5.0.20.51904), X64 RyuJIT + Job-BQFFMI : .NET Core 5.0.0 (CoreCLR 5.0.20.51904, CoreFX 5.0.20.51904), X64 RyuJIT InvocationCount=1 UnrollFactor=1 ``` | Method | N | Mean | Error | StdDev | Median | |------------- |------ |-------------:|-------------:|-------------:|-------------:| -| **MapDelegates** | **10** | **714.8 ns** | **32.53 ns** | **45.60 ns** | **700.0 ns** | -| MapStructs | 10 | 218.8 ns | 41.04 ns | 40.31 ns | 200.0 ns | -| Dictionary | 10 | 361.3 ns | 20.15 ns | 57.17 ns | 400.0 ns | -| **MapDelegates** | **100** | **2,158.6 ns** | **46.55 ns** | **68.23 ns** | **2,100.0 ns** | -| MapStructs | 100 | 795.0 ns | 19.42 ns | 22.36 ns | 800.0 ns | -| Dictionary | 100 | 1,051.4 ns | 24.90 ns | 62.47 ns | 1,000.0 ns | -| **MapDelegates** | **1000** | **17,393.8 ns** | **339.67 ns** | **333.60 ns** | **17,300.0 ns** | -| MapStructs | 1000 | 7,083.3 ns | 49.86 ns | 38.92 ns | 7,100.0 ns | -| Dictionary | 1000 | 8,300.0 ns | 165.55 ns | 146.76 ns | 8,250.0 ns | -| **MapDelegates** | **10000** | **153,867.7 ns** | **11,274.79 ns** | **33,067.01 ns** | **166,500.0 ns** | -| MapStructs | 10000 | 69,869.2 ns | 1,390.03 ns | 1,160.74 ns | 70,200.0 ns | -| Dictionary | 10000 | 80,023.1 ns | 1,132.03 ns | 945.30 ns | 80,100.0 ns | +| **MapDelegates** | **10** | **595.8 ns** | **15.70 ns** | **20.41 ns** | **600.0 ns** | +| MapStructs | 10 | 334.3 ns | 16.27 ns | 47.73 ns | 300.0 ns | +| Dictionary | 10 | 239.4 ns | 19.37 ns | 56.82 ns | 200.0 ns | +| **MapDelegates** | **100** | **2,179.3 ns** | **46.05 ns** | **67.50 ns** | **2,200.0 ns** | +| MapStructs | 100 | 1,248.4 ns | 28.76 ns | 66.65 ns | 1,200.0 ns | +| Dictionary | 100 | 969.4 ns | 21.90 ns | 49.88 ns | 1,000.0 ns | +| **MapDelegates** | **1000** | **17,333.3 ns** | **137.45 ns** | **107.31 ns** | **17,300.0 ns** | +| MapStructs | 1000 | 9,548.8 ns | 171.66 ns | 455.22 ns | 9,400.0 ns | +| Dictionary | 1000 | 8,341.7 ns | 115.32 ns | 90.03 ns | 8,400.0 ns | +| **MapDelegates** | **10000** | **152,481.2 ns** | **11,036.78 ns** | **31,843.64 ns** | **162,600.0 ns** | +| MapStructs | 10000 | 92,978.6 ns | 1,152.26 ns | 1,021.45 ns | 93,050.0 ns | +| Dictionary | 10000 | 82,206.1 ns | 1,647.85 ns | 2,613.66 ns | 82,100.0 ns | # Span vs Array Sorting @@ -347,27 +367,27 @@ The source code for all becnhmarks are in [Tools/Towel.Benchmarking](https://git ``` ini -BenchmarkDotNet=v0.12.0, OS=Windows 10.0.18363 +BenchmarkDotNet=v0.12.1, OS=Windows 10.0.18363.1198 (1909/November2018Update/19H2) Intel Core i7-4790K CPU 4.00GHz (Haswell), 1 CPU, 8 logical and 4 physical cores -.NET Core SDK=5.0.100-rc.1.20452.10 - [Host] : .NET Core 3.1.8 (CoreCLR 4.700.20.41105, CoreFX 4.700.20.41903), X64 RyuJIT - Job-ZKCIBR : .NET Core 3.1.8 (CoreCLR 4.700.20.41105, CoreFX 4.700.20.41903), X64 RyuJIT +.NET Core SDK=5.0.100 + [Host] : .NET Core 5.0.0 (CoreCLR 5.0.20.51904, CoreFX 5.0.20.51904), X64 RyuJIT + Job-BQFFMI : .NET Core 5.0.0 (CoreCLR 5.0.20.51904, CoreFX 5.0.20.51904), X64 RyuJIT InvocationCount=1 UnrollFactor=1 ``` | Method | N | Mean | Error | StdDev | Median | |----------------------- |------ |-----------------:|----------------:|----------------:|-----------------:| -| **ArrayBubbleRunTime** | **10** | **2,027.7 ns** | **43.69 ns** | **85.22 ns** | **2,000.0 ns** | -| ArrayBubbleCompileTime | 10 | 536.7 ns | 20.53 ns | 59.88 ns | 500.0 ns | -| SpanBubbleRunTime | 10 | 2,126.3 ns | 44.06 ns | 76.00 ns | 2,100.0 ns | -| SpanBubbleCompileTime | 10 | 450.0 ns | 20.73 ns | 61.13 ns | 400.0 ns | -| **ArrayBubbleRunTime** | **1000** | **6,184,537.0 ns** | **670,352.44 ns** | **1,976,549.29 ns** | **4,938,950.0 ns** | -| ArrayBubbleCompileTime | 1000 | 1,758,985.3 ns | 36,695.24 ns | 105,285.52 ns | 1,732,300.0 ns | -| SpanBubbleRunTime | 1000 | 5,828,465.0 ns | 617,791.74 ns | 1,821,572.88 ns | 4,612,150.0 ns | -| SpanBubbleCompileTime | 1000 | 1,442,844.0 ns | 74,397.07 ns | 219,361.45 ns | 1,340,600.0 ns | -| **ArrayBubbleRunTime** | **10000** | **490,926,392.9 ns** | **1,007,005.29 ns** | **892,683.96 ns** | **491,241,500.0 ns** | -| ArrayBubbleCompileTime | 10000 | 192,653,735.7 ns | 1,218,264.51 ns | 1,079,959.75 ns | 192,520,800.0 ns | -| SpanBubbleRunTime | 10000 | 475,065,076.9 ns | 1,637,935.30 ns | 1,367,750.16 ns | 474,994,300.0 ns | -| SpanBubbleCompileTime | 10000 | 181,612,793.3 ns | 684,740.86 ns | 640,507.03 ns | 181,776,400.0 ns | +| **ArrayBubbleRunTime** | **10** | **2,021.1 ns** | **42.35 ns** | **92.07 ns** | **2,000.0 ns** | +| ArrayBubbleCompileTime | 10 | 350.0 ns | 0.00 ns | 0.00 ns | 350.0 ns | +| SpanBubbleRunTime | 10 | 1,857.1 ns | 38.47 ns | 70.34 ns | 1,900.0 ns | +| SpanBubbleCompileTime | 10 | 454.0 ns | 18.31 ns | 53.97 ns | 500.0 ns | +| **ArrayBubbleRunTime** | **1000** | **4,595,196.6 ns** | **91,854.98 ns** | **203,544.28 ns** | **4,523,800.0 ns** | +| ArrayBubbleCompileTime | 1000 | 1,715,342.9 ns | 33,551.09 ns | 55,125.41 ns | 1,707,600.0 ns | +| SpanBubbleRunTime | 1000 | 6,496,293.8 ns | 128,580.56 ns | 200,184.45 ns | 6,443,550.0 ns | +| SpanBubbleCompileTime | 1000 | 1,510,602.7 ns | 29,881.82 ns | 75,515.18 ns | 1,483,400.0 ns | +| **ArrayBubbleRunTime** | **10000** | **488,559,106.7 ns** | **7,100,330.50 ns** | **6,641,653.56 ns** | **485,937,400.0 ns** | +| ArrayBubbleCompileTime | 10000 | 194,363,291.3 ns | 3,715,210.03 ns | 4,698,551.13 ns | 193,171,800.0 ns | +| SpanBubbleRunTime | 10000 | 424,195,800.0 ns | 4,705,578.81 ns | 3,929,371.42 ns | 424,222,100.0 ns | +| SpanBubbleCompileTime | 10000 | 169,649,621.4 ns | 950,523.61 ns | 842,614.42 ns | 169,528,100.0 ns |