< Summary

Class:Towel.Statics
Assembly:Towel
File(s):File 1: /home/runner/work/Towel/Towel/Sources/Towel/SpanBuilder.cs
File 2: /home/runner/work/Towel/Towel/Sources/Towel/Statics-Combinations.cs
File 3: /home/runner/work/Towel/Towel/Sources/Towel/Statics-Extensions.cs
File 4: /home/runner/work/Towel/Towel/Sources/Towel/Statics-NumericEnglishWords.cs
File 5: /home/runner/work/Towel/Towel/Sources/Towel/Statics-Permutations.cs
File 6: /home/runner/work/Towel/Towel/Sources/Towel/Statics-Random.cs
File 7: /home/runner/work/Towel/Towel/Sources/Towel/Statics-RomanNumerals.cs
File 8: /home/runner/work/Towel/Towel/Sources/Towel/Statics-SearchingAlgorithms.cs
File 9: /home/runner/work/Towel/Towel/Sources/Towel/Statics-SequenceAnalysis.cs
File 10: /home/runner/work/Towel/Towel/Sources/Towel/Statics-SortingAlgorithms.cs
File 11: /home/runner/work/Towel/Towel/Sources/Towel/Statics-Structs.cs
File 12: /home/runner/work/Towel/Towel/Sources/Towel/Statics-SyntaxHacks.cs
File 13: /home/runner/work/Towel/Towel/Sources/Towel/Statics-Trigonometry.cs
File 14: /home/runner/work/Towel/Towel/Sources/Towel/Statics-Tuple.cs
File 15: /home/runner/work/Towel/Towel/Sources/Towel/Statics.cs
Covered lines:3746
Uncovered lines:1687
Coverable lines:5433
Total lines:11729
Line coverage:68.9% (3746 of 5433)
Covered branches:1674
Total branches:2492
Branch coverage:67.1% (1674 of 2492)

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
File 1: AppendLine(...)100%2100%
File 1: AppendLine(...)100%2100%
File 1: AppendLine(...)100%1100%
File 2: Combinations(...)100%1100%
File 2: Combinations(...)100%1100%
File 2: Combinations(...)100%10%
File 2: Combinations(...)100%6100%
File 3: Replace(...)100%16100%
File 3: ContainsAny(...)0%120%
File 3: RemoveCarriageReturns(...)100%10%
File 3: StandardizeNewLines(...)100%10%
File 3: Repeat(...)0%60%
File 3: SplitLines(...)0%20%
File 3: IndentLines(...)100%10%
File 3: IndentLines(...)100%10%
File 3: IndentNewLinesBetweenIndeces(...)100%10%
File 3: IndentNewLinesBetweenIndeces(...)100%10%
File 3: IndentLineNumbers(...)100%10%
File 3: IndentLineNumbers(...)100%10%
File 3: PadLinesLeft(...)0%60%
File 3: PadSubstringLinesRight(...)0%60%
File 3: PadLinesLeftBetweenIndeces(...)0%120%
File 3: PadLinesRightBetweenIndeces(...)0%120%
File 3: PadLinesLeft(...)0%140%
File 3: PadLinesRight(...)0%140%
File 3: Reverse(...)100%10%
File 3: Remove(...)0%40%
File 3: CountLines(...)100%10%
File 3: XML_Stepper()100%1100%
File 3: XML_StepperBreak()100%1100%
File 3: Stepper(...)100%10%
File 3: Stepper(...)100%10%
File 3: StepperBreak(...)0%20%
File 3: StepperBreak(...)100%10%
File 3: Stepper(...)100%10%
File 3: Stepper(...)100%10%
File 3: Stepper(...)100%10%
File 3: StepperBreak(...)0%40%
File 3: Stepper(...)50%2100%
File 3: Stepper(...)100%1100%
File 3: StepperBreak(...)0%20%
File 3: StepperBreak(...)100%1100%
File 3: Stepper(...)100%10%
File 3: Stepper(...)100%10%
File 3: Stepper(...)100%10%
File 3: StepperBreak(...)75%477.77%
File 3: BuildArray(...)0%20%
File 3: Format(...)0%20%
File 3: Format(...)0%20%
File 3: ConstructRectangularJaggedArray(...)100%2100%
File 3: ConstructRectangularJaggedArray(...)0%60%
File 3: ConstructSquareJaggedArray(...)100%1100%
File 3: ConstructSquareJaggedArray(...)100%10%
File 3: Time_DateTime(...)100%10%
File 3: Time_StopWatch(...)100%10%
File 3: TryFirst(...)0%20%
File 3: CreateDelegate(...)100%10%
File 3: IsDefined(...)100%1100%
File 3: ToIEnumerable()100%10100%
File 3: GetEnumerator(...)100%10%
File 3: ToSpan(...)100%1100%
File 3: ToSpan(...)50%2100%
File 3: ToSpan(...)100%10%
File 3: ToArray(...)100%1100%
File 3: ToArray(...)50%2100%
File 3: ToArray(...)100%10100%
File 3: Select(...)50%2100%
File 3: Select()100%10100%
File 3: Gaps(...)0%20%
File 3: Convert(...)100%10%
File 3: Append(...)100%10%
File 3: Build(...)100%10%
File 3: Concat(...)0%20%
File 3: Where(...)0%20%
File 3: Iterate(...)100%2100%
File 3: ToStepper(...)100%2100%
File 3: ToStepperBreak(...)0%40%
File 3: ToArray(...)100%10%
File 3: Count(...)100%10%
File 3: EveryNth(...)0%60%
File 3: ContainsDuplicates(...)0%20%
File 3: ContainsDuplicates(...)0%20%
File 3: ContainsDuplicates(...)100%10%
File 3: ContainsDuplicates(...)100%10%
File 3: Any(...)0%20%
File 3: Any(...)0%20%
File 3: ConcatToString(...)100%10%
File 3: ToCompareResult(...)100%4100%
File 4: .cctor()100%1100%
File 4: ToEnglishWords(...)100%26100%
File 4: WholeNumber(...)100%16100%
File 4: DigitGroup(...)100%10100%
File 4: ToEnglishWords(...)100%10%
File 4: ToEnglishWords(...)100%10%
File 4: ToEnglishWords(...)100%10%
File 4: ToEnglishWords(...)100%10%
File 4: ToEnglishWords(...)100%10%
File 4: ToEnglishWords(...)100%10%
File 4: ToEnglishWords(...)100%10%
File 4: ToEnglishWords(...)100%10%
File 4: ToEnglishWords(...)100%1100%
File 4: TryParse(...)100%1100%
File 4: TryParseEnglishWordsToDecimal(...)100%1100%
File 4: TryParse(...)100%10%
File 4: TryParseEnglishWordsToLong(...)100%10%
File 4: TryParse(...)100%10%
File 4: TryParseEnglishWordsToUlong(...)100%10%
File 4: TryParse(...)100%10%
File 4: TryParseEnglishWordsToInt(...)100%10%
File 4: TryParse(...)100%10%
File 4: TryParseEnglishWordsToUint(...)100%10%
File 4: TryParse(...)100%10%
File 4: TryParseEnglishWordsToShort(...)100%10%
File 4: TryParse(...)100%10%
File 4: TryParseEnglishWordsToUshort(...)100%10%
File 4: TryParse(...)100%10%
File 4: TryParseEnglishWordsToByte(...)100%10%
File 4: TryParse(...)100%10%
File 4: TryParseEnglishWordsToSbyte(...)100%10%
File 4: TryParseEnglishWords(...)92.15%20491.53%
File 4: GetNextDigit(...)100%18100%
File 4: GetTeensDigit(...)100%18100%
File 4: GetNextTensDigit(...)100%18100%
File 4: GetNextExplicitDigitGroup(...)100%18100%
File 4: GetNextFractionalSuffix(...)98.27%58100%
File 5: XML_Permute()100%1100%
File 5: XML_PermuteRecursive()100%1100%
File 5: XML_PermuteIterative()100%1100%
File 5: PermuteRecursive(...)100%1100%
File 5: PermuteRecursive(...)100%10%
File 5: PermuteRecursive(...)100%10%
File 5: PermuteRecursive(...)100%1100%
File 5: PermuteRecursive(...)100%1100%
File 5: PermuteRecursive(...)100%10%
File 5: PermuteRecursive(...)100%10%
File 5: PermuteRecursive(...)100%1100%
File 5: PermuteIterative(...)100%1100%
File 5: PermuteIterative(...)100%10%
File 5: PermuteIterative(...)100%10%
File 5: PermuteIterative(...)100%10100%
File 5: PermuteIterative(...)100%1100%
File 5: PermuteIterative(...)100%10%
File 5: PermuteIterative(...)100%10%
File 5: PermuteIterative(...)100%10100%
File 6: Next(...)0%20%
File 6: NextRollTracking(...)76.66%3087.5%
File 6: NextPoolTracking(...)72.72%2287.87%
File 6: Next(...)0%60%
File 6: NextRollTracking(...)0%60%
File 6: NextPoolTracking(...)0%60%
File 6: Next(...)0%40%
File 6: NextRollTracking(...)100%4100%
File 6: NextPoolTracking(...)50%4100%
File 6: NextUnique(...)100%2100%
File 6: NextUniqueRollTracking(...)83.33%18100%
File 6: NextUniquePoolTracking(...)81.25%16100%
File 6: NextUnique(...)50%6100%
File 6: NextUniqueRollTracking(...)0%60%
File 6: NextUniquePoolTracking(...)0%60%
File 6: NextUnique(...)0%60%
File 6: NextUniqueRollTracking(...)100%6100%
File 6: NextUniquePoolTracking(...)100%6100%
File 6: NextUnique(...)0%20%
File 6: NextUniqueRollTracking(...)79.41%3493.1%
File 6: NextUniquePoolTracking(...)70.83%2490.47%
File 6: NextUnique(...)0%60%
File 6: NextUniqueRollTracking(...)0%60%
File 6: NextUniquePoolTracking(...)0%60%
File 6: NextUnique(...)0%60%
File 6: NextUniqueRollTracking(...)100%6100%
File 6: NextUniquePoolTracking(...)50%6100%
File 6: NextBool(...)100%1100%
File 6: NextByte(...)100%10%
File 6: NextString(...)0%60%
File 6: NextString(...)0%100%
File 6: NextEnglishAlphaNumericString(...)100%10%
File 6: NextUpperCaseEnglishAlphaNumericString(...)100%10%
File 6: NextLowerCaseEnglishAlphaNumericString(...)100%10%
File 6: NumericEnglishString(...)100%10%
File 6: NextEnglishAlphabeticString(...)100%10%
File 6: NextUpperCaseEnglishAlphabeticString(...)100%10%
File 6: NextLowerCaseEnglishAlphabeticString(...)100%10%
File 6: NextChar(...)100%10%
File 6: NextChar(...)100%10%
File 6: NextDecimal(...)100%1100%
File 6: NextDecimal(...)100%2100%
File 6: NextDateTime(...)100%10%
File 6: NextDateTime(...)100%10%
File 6: NextDateTime(...)0%40%
File 6: NextTimeSpan(...)100%10%
File 6: NextTimeSpan(...)100%10%
File 6: NextTimeSpan(...)0%40%
File 6: Next(...)0%20%
File 6: NextRollTracking(...)0%20%
File 6: NextPoolTracking(...)0%20%
File 6: Next(...)0%20%
File 6: NextRollTracking(...)50%2100%
File 6: NextPoolTracking(...)50%2100%
File 6: Next(...)0%20%
File 6: NextRollTracking(...)0%20%
File 6: NextPoolTracking(...)0%20%
File 6: NextUnique(...)50%2100%
File 6: NextUniqueRollTracking(...)0%20%
File 6: NextUniquePoolTracking(...)0%20%
File 6: NextUnique(...)0%20%
File 6: NextUniqueRollTracking(...)0%20%
File 6: NextUniquePoolTracking(...)0%20%
File 6: NextUnique(...)0%20%
File 6: NextUniqueRollTracking(...)0%20%
File 6: NextUniquePoolTracking(...)0%20%
File 6: NextUnique(...)0%20%
File 6: NextUniqueRollTracking(...)0%20%
File 6: NextUniquePoolTracking(...)0%20%
File 6: NextUnique(...)0%20%
File 6: NextUniqueRollTracking(...)50%2100%
File 6: NextUniquePoolTracking(...)50%2100%
File 6: NextUnique(...)0%20%
File 6: NextUniqueRollTracking(...)0%20%
File 6: NextUniquePoolTracking(...)0%20%
File 6: From(...)0%40%
File 6: From(...)0%20%
File 6: From(...)0%40%
File 6: Next(...)100%10%
File 6: Next(...)100%10%
File 6: Next(...)0%240%
File 7: .cctor()100%1100%
File 7: TryParseRomanNumeral(...)92.3%5296%
File 7: TryToRomanNumeral(...)100%32100%
File 8: XML_SearchBinary()100%1100%
File 8: SearchBinary(...)0%40%
File 8: SearchBinary(...)0%160%
File 8: SearchBinary(...)100%2100%
File 8: SearchBinary(...)50%275%
File 8: SearchBinary(...)100%10%
File 8: SearchBinary(...)90%10100%
File 8: .ctor(...)100%1100%
File 8: op_Implicit(...)100%1100%
File 8: op_Implicit(...)100%10%
File 8: op_Implicit(...)100%1100%
File 8: .ctor(...)100%1100%
File 8: .ctor(...)100%1100%
File 8: .ctor(...)100%10%
File 8: .ctor(...)100%1100%
File 8: .ctor(...)100%1100%
File 8: BuildPath(...)100%4100%
File 8: Invoke(...)100%1100%
File 8: Invoke(...)100%10%
File 8: XML_SearchGraph()100%1100%
File 8: XML_SearchGraph_Astar()100%1100%
File 8: SearchGraph(...)100%2100%
File 8: SearchGraph(...)100%10%
File 8: SearchGraph(...)100%10%
File 8: SearchGraph(...)100%10%
File 8: SearchGraph(...)100%1100%
File 8: SearchGraph(...)100%1100%
File 8: SearchGraph(...)66.66%688.88%
File 8: AStarSearch(...)75%4100%
File 8: AStarSearch(...)0%60%
File 8: XML_SearchGraph_Dijkstra()100%1100%
File 8: SearchGraph(...)0%20%
File 8: SearchGraph(...)100%10%
File 8: SearchGraph(...)100%10%
File 8: SearchGraph(...)100%10%
File 8: SearchGraph(...)100%10%
File 8: SearchGraph(...)100%10%
File 8: SearchGraph(...)0%60%
File 8: DijkstraSearch(...)83.33%6100%
File 8: DijkstraSearch(...)0%80%
File 8: XML_SearchGraph_BreadthFirst()100%1100%
File 8: SearchGraph(...)100%2100%
File 8: SearchGraph(...)100%10%
File 8: SearchGraph(...)100%10%
File 8: SearchGraph(...)100%1100%
File 8: SearchGraph(...)100%1100%
File 8: SearchGraph(...)100%10%
File 8: SearchGraph(...)66.66%689.65%
File 8: PerformBredthFirstSearch(...)100%2100%
File 8: PerformBredthFirstSearch(...)0%60%
File 9: EquateSequence(...)0%40%
File 9: EquateSequence(...)100%2100%
File 9: EquateSequence(...)80%1073.33%
File 9: EquateSet(...)100%4100%
File 9: EquateSet(...)100%10100%
File 9: EquateOccurences(...)0%40%
File 9: EquateOccurences(...)100%10%
File 9: XML_Maximum()100%1100%
File 9: Maximum(...)100%2100%
File 9: Maximum(...)0%20%
File 9: Maximum(...)83.33%685.71%
File 9: XML_MaximumValue_Two()100%1100%
File 9: MaximumValue(...)100%2100%
File 9: MaximumValue(...)100%2100%
File 9: XML_MaximumValue()100%1100%
File 9: MaximumValue(...)100%2100%
File 9: MaximumValue(...)0%20%
File 9: MaximumValue(...)83.33%685.71%
File 9: MaximumIndex(...)50%1060.71%
File 9: XML_MaximumIndex()100%1100%
File 9: MaximumIndex(...)100%2100%
File 9: MaximumIndex(...)0%20%
File 9: MaximumIndex(...)83.33%685.71%
File 9: XML_Minimum()100%1100%
File 9: Minimum(...)100%2100%
File 9: Minimum(...)0%20%
File 9: Minimum(...)83.33%685.71%
File 9: XML_MinimumValue_Two()100%1100%
File 9: MinimumValue(...)100%2100%
File 9: MinimumValue(...)50%2100%
File 9: XML_MinimumValue()100%1100%
File 9: MinimumValue(...)100%2100%
File 9: MinimumValue(...)0%20%
File 9: MinimumValue(...)83.33%685.71%
File 9: XML_MinimumIndex()100%1100%
File 9: MinimumIndex(...)100%2100%
File 9: MinimumIndex(...)0%20%
File 9: MinimumIndex(...)83.33%685.71%
File 9: Range(...)100%10%
File 9: Range(...)0%100%
File 9: Range(...)0%80%
File 9: Mode(...)100%1100%
File 9: Mode(...)100%10%
File 9: Mode(...)100%10%
File 9: Mode(...)100%10%
File 9: Mode(...)100%4100%
File 9: Mean(...)100%10%
File 9: Mean(...)0%40%
File 9: Median(...)66.66%6100%
File 9: Median(...)0%20%
File 9: Median(...)100%1100%
File 9: Median(...)0%20%
File 9: GeometricMean(...)100%10%
File 9: Variance(...)100%10%
File 9: StandardDeviation(...)100%10%
File 9: MeanDeviation(...)100%10%
File 9: Quantiles(...)0%60%
File 9: Occurences(...)100%10%
File 9: Occurences(...)100%10%
File 9: Occurences(...)100%10%
File 9: Occurences(...)100%10%
File 9: Occurences(...)0%20%
File 9: HammingDistance(...)0%60%
File 9: HammingDistance(...)100%1100%
File 9: HammingDistance(...)100%6100%
File 9: LevenshteinDistanceRecursive(...)0%40%
File 9: LevenshteinDistanceRecursive(...)100%10%
File 9: LevenshteinDistanceRecursive(...)100%10%
File 9: LevenshteinDistanceIterative(...)0%140%
File 9: LevenshteinDistanceIterative(...)100%10%
File 9: LevenshteinDistanceIterative(...)0%100%
File 9: XML_FilterOrdered()100%1100%
File 9: XML_FilterOrderedEnumerable()100%1100%
File 9: FilterOrdered(...)0%20%
File 9: FilterOrdered(...)0%60%
File 9: FilterOrdered(...)0%20%
File 9: FilterOrdered(...)0%60%
File 9: FilterOrdered(...)100%2100%
File 9: FilterOrdered()100%6100%
File 9: XML_IsOrdered()100%1100%
File 9: IsOrdered(...)100%2100%
File 9: IsOrdered(...)100%4100%
File 9: IsOrdered(...)100%2100%
File 9: IsOrdered(...)100%4100%
File 9: IsOrdered(...)100%2100%
File 9: IsOrdered(...)100%6100%
File 9: XML_IsPalindrome()100%1100%
File 9: IsPalindrome(...)100%2100%
File 9: IsPalindrome(...)100%4100%
File 9: IsPalindrome(...)100%1100%
File 9: IsPalindrome(...)100%2100%
File 9: IsPalindrome(...)100%4100%
File 9: XML_IsInterleaved()100%1100%
File 9: XML_IsInterleavedRecursive()100%1100%
File 9: XML_IsInterleavedIterative()100%1100%
File 9: IsInterleavedRecursive(...)0%20%
File 9: IsInterleavedRecursive(...)100%1100%
File 9: IsInterleavedRecursive(...)100%2100%
File 9: IsInterleavedIterative(...)0%20%
File 9: IsInterleavedIterative(...)100%1100%
File 9: IsInterleavedIterative(...)87.5%32100%
File 9: IsReorderOf(...)100%4100%
File 9: IsReorderOf(...)100%14100%
File 9: ContainsDuplicates(...)100%4100%
File 9: ContainsDuplicates(...)100%4100%
File 9: Contains(...)100%2100%
File 9: Contains(...)100%4100%
File 9: Any(...)100%2100%
File 9: Any(...)100%4100%
File 9: GetLeast(...)91.66%12100%
File 9: GetLeast(...)100%10100%
File 9: GetGreatest(...)100%1100%
File 9: GetGreatest(...)100%1100%
File 9: GetGreatest(...)100%2100%
File 9: GetGreatest(...)0%20%
File 9: GetLeast(...)100%2100%
File 9: GetLeast(...)0%20%
File 9: CombineRanges(...)71.42%14100%
File 10: Reverse(...)100%1100%
File 10: Reverse(...)100%6100%
File 10: XML_Shuffle()100%1100%
File 10: Shuffle(...)100%10%
File 10: Shuffle(...)0%20%
File 10: Shuffle(...)100%2100%
File 10: Shuffle(...)100%2100%
File 10: Shuffle(...)100%2100%
File 10: XML_Sort()100%1100%
File 10: XML_SortBubble()100%1100%
File 10: SortBubble(...)100%2100%
File 10: SortBubble(...)100%6100%
File 10: SortBubble(...)100%2100%
File 10: SortBubble(...)100%6100%
File 10: XML_SortSelection()100%1100%
File 10: SortSelection(...)100%2100%
File 10: SortSelection(...)100%6100%
File 10: SortSelection(...)100%2100%
File 10: SortSelection(...)100%6100%
File 10: XML_SortInsertion()100%1100%
File 10: SortInsertion(...)100%2100%
File 10: SortInsertion(...)100%6100%
File 10: SortInsertion(...)100%2100%
File 10: SortInsertion(...)100%6100%
File 10: XML_SortQuick()100%1100%
File 10: SortQuick(...)100%2100%
File 10: SortQuick(...)100%1100%
File 10: SortQuick(...)100%2100%
File 10: SortQuick(...)100%1100%
File 10: XML_SortMerge()100%1100%
File 10: SortMerge(...)100%2100%
File 10: SortMerge(...)100%1100%
File 10: SortMerge(...)100%2100%
File 10: SortMerge(...)100%1100%
File 10: XML_SortHeap()100%1100%
File 10: SortHeap(...)100%2100%
File 10: SortHeap(...)100%4100%
File 10: SortHeap(...)100%2100%
File 10: SortHeap(...)100%4100%
File 10: XML_SortOddEven()100%1100%
File 10: SortOddEven(...)100%2100%
File 10: SortOddEven(...)100%10100%
File 10: SortOddEven(...)100%2100%
File 10: SortOddEven(...)100%10100%
File 10: XML_SortBogo()100%1100%
File 10: SortBogo(...)100%2100%
File 10: SortBogo(...)100%2100%
File 10: SortBogo(...)100%2100%
File 10: SortBogo(...)100%4100%
File 10: SortBogo(...)50%2100%
File 10: SortBogo(...)100%2100%
File 10: XML_SortSlow()100%1100%
File 10: SortSlow(...)100%2100%
File 10: SortSlow(...)100%1100%
File 10: SortSlow(...)100%2100%
File 10: SortSlow(...)100%1100%
File 10: XML_SortGnome()100%1100%
File 10: SortGnome(...)100%2100%
File 10: SortGnome(...)100%6100%
File 10: SortGnome(...)100%2100%
File 10: SortGnome(...)100%6100%
File 10: XML_SortComb()100%1100%
File 10: SortComb(...)100%2100%
File 10: SortComb(...)100%8100%
File 10: SortComb(...)100%2100%
File 10: SortComb(...)100%8100%
File 10: XML_SortShell()100%1100%
File 10: SortShell(...)100%2100%
File 10: SortShell(...)100%8100%
File 10: SortShell(...)100%2100%
File 10: SortShell(...)100%8100%
File 10: XML_SortCocktail()100%1100%
File 10: SortCocktail(...)100%2100%
File 10: SortCocktail(...)100%12100%
File 10: SortCocktail(...)100%2100%
File 10: SortCocktail(...)100%12100%
File 10: XML_SortCycle()100%1100%
File 10: SortCycle(...)100%2100%
File 10: SortCycle(...)95.45%2293.75%
File 10: SortCycle(...)100%2100%
File 10: SortCycle(...)95.45%2293.18%
File 10: XML_SortPancake()100%1100%
File 10: SortPancake(...)100%2100%
File 10: SortPancake(...)100%4100%
File 10: SortPancake(...)100%2100%
File 10: SortPancake(...)100%4100%
File 10: XML_SortStooge()100%1100%
File 10: SortStooge(...)100%2100%
File 10: SortStooge(...)100%6100%
File 10: SortStooge(...)100%2100%
File 10: SortStooge(...)100%6100%
File 10: XML_SortTim()100%1100%
File 10: SortTim(...)100%2100%
File 10: SortTim(...)100%22100%
File 10: SortTim(...)100%2100%
File 10: SortTim(...)100%18100%
File 10: SortCounting(...)0%40%
File 10: SortCounting(...)50%6100%
File 10: SortCounting(...)100%10%
File 10: SortCounting(...)100%4100%
File 10: SortCounting(...)90%1091.3%
File 10: SortCounting(...)100%10%
File 10: SortCounting(...)100%1100%
File 10: SortCounting(...)100%4100%
File 10: SortCounting(...)87.5%890%
File 10: SortRadix(...)0%40%
File 10: SortRadix(...)50%6100%
File 10: SortRadix(...)100%10%
File 10: SortRadix(...)100%6100%
File 10: SortRadix(...)100%10%
File 10: SortRadix(...)100%1100%
File 10: SortRadix(...)87.5%889.47%
File 10: Invoke(...)100%1100%
File 10: SortPidgeonHole(...)50%4100%
File 10: SortPidgeonHole(...)81.25%1687.09%
File 10: SortPidgeonHole(...)85.71%1492.59%
File 10: XML_SortIntro()100%1100%
File 10: SortIntro(...)100%2100%
File 10: SortIntro(...)100%2100%
File 10: SortIntro(...)94.44%1888.88%
File 10: PickPivotAndPartition(...)100%16100%
File 10: SortIntro(...)100%2100%
File 10: SortIntro(...)100%2100%
File 10: SortIntro(...)95%2090.62%
File 10: PickPivotAndPartition(...)100%16100%
File 11: Invoke(...)100%1100%
File 11: Invoke(...)100%1100%
File 11: Invoke(...)100%1100%
File 11: Invoke(...)100%1100%
File 11: Invoke(...)100%1100%
File 11: Invoke(...)100%1100%
File 11: op_Implicit(...)100%1100%
File 11: Invoke(...)100%1100%
File 11: Invoke(...)100%10%
File 11: Invoke(...)100%1100%
File 11: Invoke(...)100%1100%
File 11: Invoke(...)100%1100%
File 11: Invoke(...)100%1100%
File 11: op_Implicit(...)100%1100%
File 11: Invoke(...)100%1100%
File 11: op_Implicit(...)100%1100%
File 11: Invoke(...)100%1100%
File 11: .ctor(...)100%1100%
File 11: Invoke(...)100%10%
File 11: .ctor(...)100%10%
File 11: Invoke()100%1100%
File 11: Invoke(...)100%1100%
File 11: op_Implicit(...)100%1100%
File 11: Invoke(...)100%1100%
File 11: op_Implicit(...)100%1100%
File 11: Invoke(...)100%1100%
File 11: op_Implicit(...)100%1100%
File 11: Invoke(...)100%1100%
File 11: op_Implicit(...)100%1100%
File 11: Invoke(...)100%1100%
File 11: op_Implicit(...)100%1100%
File 12: Switch(...)100%10%
File 12: Switch(...)100%10%
File 12: Do(...)0%40%
File 12: Do(...)0%40%
File 12: op_Implicit(...)100%10%
File 12: op_Implicit(...)100%10%
File 12: op_Implicit(...)100%10%
File 12: Resolve(...)100%10%
File 12: .ctor(...)100%10%
File 12: Resolve(...)100%10%
File 12: Resolve(...)100%10%
File 12: op_Implicit(...)100%10%
File 12: op_Implicit(...)100%10%
File 12: op_Implicit(...)100%10%
File 12: Resolve()100%10%
File 12: Resolve()100%10%
File 12: get_Chance()100%10%
File 12: op_Modulus(...)0%80%
File 12: op_Implicit(...)100%10%
File 12: op_GreaterThan(...)0%20%
File 12: op_LessThan(...)0%20%
File 12: op_GreaterThanOrEqual(...)0%20%
File 12: op_LessThanOrEqual(...)0%20%
File 12: op_Equality(...)0%20%
File 12: op_Inequality(...)0%20%
File 12: ToString()100%10%
File 12: Equals(...)100%10%
File 12: GetHashCode()100%10%
File 12: .ctor(...)100%10%
File 12: op_Implicit(...)100%10%
File 12: op_GreaterThan(...)0%20%
File 12: op_LessThan(...)0%20%
File 12: op_GreaterThanOrEqual(...)0%20%
File 12: op_LessThanOrEqual(...)0%20%
File 12: op_Equality(...)0%20%
File 12: op_Inequality(...)0%20%
File 12: ToString()100%10%
File 12: Equals(...)100%10%
File 12: GetHashCode()100%10%
File 12: Ɐ(...)100%1100%
File 12: .ctor(...)100%1100%
File 12: get_Length()100%10%
File 12: StepperBreak(...)100%10%
File 12: ToArray()100%10%
File 12: get_Item(...)100%10%
File 12: set_Item(...)100%10%
File 12: get_Count()100%1100%
File 12: get_IsReadOnly()100%10%
File 12: Add(...)100%10%
File 12: Clear()100%10%
File 12: Contains(...)100%10%
File 12: CopyTo(...)100%1100%
File 12: IndexOf(...)100%10%
File 12: Insert(...)0%60%
File 12: Remove(...)0%80%
File 12: RemoveAt(...)0%60%
File 12: GetEnumerator()100%1100%
File 12: System.Collections.IEnumerable.GetEnumerator()100%10%
File 12: op_Implicit(...)100%10%
File 12: op_Implicit(...)100%10%
File 12: op_Implicit(...)100%1100%
File 12: op_Implicit(...)100%10%
File 12: op_Implicit(...)100%1100%
File 12: op_Implicit(...)100%10%
File 12: op_Implicit(...)100%10%
File 12: op_Implicit(...)100%10%
File 12: op_Implicit(...)100%10%
File 12: op_Implicit(...)100%10%
File 12: op_Implicit(...)100%10%
File 12: op_Implicit(...)100%10%
File 12: op_Implicit(...)100%10%
File 12: op_Implicit(...)100%10%
File 12: op_Implicit(...)100%10%
File 12: op_Implicit(...)100%10%
File 13: SineTaylorSeries(...)87.5%8100%
File 13: SineSystem(...)100%10%
File 13: SineQuadratic(...)0%40%
File 13: CosineTaylorSeries(...)87.5%8100%
File 13: CosineSystem(...)100%10%
File 13: CosineQuadratic(...)100%10%
File 13: TangentTaylorSeries(...)100%10%
File 13: TangentSystem(...)100%10%
File 13: TangentQuadratic(...)100%10%
File 13: CosecantSystem(...)100%10%
File 13: CosecantQuadratic(...)100%10%
File 13: SecantSystem(...)100%10%
File 13: SecantQuadratic(...)100%10%
File 13: CotangentSystem(...)100%10%
File 13: CotangentQuadratic(...)100%10%
File 14: GetEnumerator()100%2100%
File 14: GetEnumerator()0%20%
File 14: GetEnumerator()100%10%
File 14: GetEnumerator()0%20%
File 14: GetEnumerator()100%10%
File 14: GetEnumerator()0%20%
File 14: GetEnumerator()100%10%
File 14: GetEnumerator()0%20%
File 14: GetEnumerator()100%10%
File 14: GetEnumerator()0%20%
File 14: GetEnumerator()100%10%
File 14: GetEnumerator()0%20%
File 14: GetEnumerator()100%10%
File 14: GetEnumerator()0%20%
File 14: GetEnumerator()100%10%
File 15: .cctor()100%1100%
File 15: .cctor()100%1100%
File 15: OperationOnStepper(...)66.66%6100%
File 15: Swap(...)100%1100%
File 15: Swap(...)100%1100%
File 15: sourcedirectory(...)100%10%
File 15: sourcefilepath(...)100%1100%
File 15: sourcemembername(...)100%1100%
File 15: sourcelinenumber(...)100%1100%
File 15: sourceof(...)100%1100%
File 15: sourceof(...)100%1100%
File 15: TryParse(...)100%1100%
File 15: .cctor()77.27%2294.59%
File 15: Hash(...)50%2100%
File 15: Convert(...)100%1100%
File 15: .cctor()100%1100%
File 15: Join(...)100%10%
File 15: Equate(...)100%1100%
File 15: Equate(...)80%10100%
File 15: .cctor()22.72%2271.79%
File 15: Inequate(...)100%1100%
File 15: Inequate(...)100%1100%
File 15: .cctor()100%1100%
File 15: LessThan(...)100%1100%
File 15: LessThan(...)100%1100%
File 15: .cctor()100%1100%
File 15: GreaterThan(...)100%1100%
File 15: GreaterThan(...)100%1100%
File 15: .cctor()100%1100%
File 15: LessThanOrEqual(...)100%1100%
File 15: LessThanOrEqual(...)100%1100%
File 15: .cctor()100%1100%
File 15: GreaterThanOrEqual(...)100%1100%
File 15: GreaterThanOrEqual(...)100%1100%
File 15: .cctor()100%1100%
File 15: Compare(...)100%1100%
File 15: .cctor()46.87%3294.54%
File 15: Negation(...)100%1100%
File 15: Negation(...)100%1100%
File 15: .cctor()100%1100%
File 15: Addition(...)100%1100%
File 15: Addition(...)100%1100%
File 15: Addition(...)100%1100%
File 15: Addition(...)100%1100%
File 15: .cctor()100%1100%
File 15: Subtraction(...)100%1100%
File 15: Subtraction(...)100%1100%
File 15: Subtraction(...)100%1100%
File 15: Subtraction(...)100%1100%
File 15: .cctor()100%1100%
File 15: Multiplication(...)100%1100%
File 15: Multiplication(...)100%1100%
File 15: Multiplication(...)100%1100%
File 15: Multiplication(...)100%1100%
File 15: .cctor()100%1100%
File 15: Division(...)100%1100%
File 15: Division(...)100%1100%
File 15: Division(...)100%1100%
File 15: Division(...)100%1100%
File 15: .cctor()100%1100%
File 15: Remainder(...)100%1100%
File 15: Remainder(...)100%1100%
File 15: Remainder(...)100%1100%
File 15: Remainder(...)100%1100%
File 15: .cctor()100%1100%
File 15: Inversion(...)100%1100%
File 15: Power(...)100%1100%
File 15: Power(...)100%10%
File 15: Power(...)100%10%
File 15: .cctor()14.28%1448.71%
File 15: SquareRoot(...)100%1100%
File 15: .cctor()100%2100%
File 15: Root(...)100%1100%
File 15: Logarithm(...)100%10%
File 15: .cctor()100%10%
File 15: IsInteger(...)100%1100%
File 15: .cctor()50%281.25%
File 15: IsNonNegative(...)100%10%
File 15: .cctor()0%20%
File 15: IsNegative(...)100%1100%
File 15: .cctor()100%2100%
File 15: IsPositive(...)100%1100%
File 15: .cctor()50%278.57%
File 15: IsEven(...)100%1100%
File 15: .cctor()50%278.57%
File 15: IsOdd(...)100%1100%
File 15: .cctor()50%284.21%
File 15: IsPrime(...)100%1100%
File 15: .cctor()87.5%1692.3%
File 15: AbsoluteValue(...)100%1100%
File 15: .cctor()100%1100%
File 15: Clamp(...)100%4100%
File 15: EqualToLeniency(...)100%1100%
File 15: .cctor()100%1100%
File 15: GreatestCommonFactor(...)100%1100%
File 15: GreatestCommonFactor(...)68.75%1681.81%
File 15: LeastCommonMultiple(...)100%1100%
File 15: LeastCommonMultiple(...)60%1080%
File 15: LinearInterpolation(...)0%100%
File 15: Factorial(...)100%1100%
File 15: .cctor()70%1073.07%
File 15: CombinationsCount(...)0%120%
File 15: BinomialCoefficient(...)33.33%1246.66%
File 15: Exponential(...)100%10%
File 15: NaturalLogarithm(...)100%10%
File 15: .cctor()0%40%
File 15: LinearRegression2D(...)0%40%
File 15: FactorPrimes(...)100%1100%
File 15: .cctor()85.71%1481.81%

File(s)

/home/runner/work/Towel/Towel/Sources/Towel/SpanBuilder.cs

#LineLine coverage
 1namespace Towel;
 2
 3/// <summary>Represents a <see cref="Span{T}"/> in the process of being initialized.</summary>
 4/// <typeparam name="T">The type of values in the <see cref="Span{T}"/>.</typeparam>
 5public ref struct SpanBuilder<T>
 6{
 7  internal Span<T> _span;
 8  internal int _i;
 9
 10  /// <summary>Constructs a new <see cref="SpanBuilder{T}"/>.</summary>
 11  /// <param name="span">The <see cref="Span{T}"/> to initialize.</param>
 12  public SpanBuilder(Span<T> span)
 13  {
 14    _span = span;
 15    _i = 0;
 16  }
 17
 18  /// <summary>Appends a <typeparamref name="T"/> to this <see cref="SpanBuilder{T}"/>.</summary>
 19  /// <param name="value">The <typeparamref name="T"/> to append to this <see cref="SpanBuilder{T}"/>.</param>
 20  public void Append(T value)
 21  {
 22    if (_i >= _span.Length) throw new InvalidOperationException("The span to append was larger than span being appended 
 23    AppendInternal(value);
 24  }
 25
 26  /// <summary>Appends a <typeparamref name="T"/> span to this <see cref="SpanBuilder{T}"/>.</summary>
 27  /// <param name="span">The <typeparamref name="T"/> span to append to this <see cref="SpanBuilder{T}"/>.</param>
 28  public void Append(ReadOnlySpan<T> span)
 29  {
 30    if (_i + span.Length > _span.Length) throw new InvalidOperationException("The span to append was larger than span be
 31    AppendInternal(span);
 32  }
 33
 34  internal void AppendInternal(T value) => _span[_i++] = value;
 35  internal void AppendInternal(ReadOnlySpan<T> span)
 36  {
 37    span.CopyTo(_span[_i..(_i + span.Length)]);
 38    _i += span.Length;
 39  }
 40
 41  /// <summary>Converts a <see cref="SpanBuilder{T}"/> to a <see cref="ReadOnlySpan{T}"/>.</summary>
 42  /// <param name="spanBuilder">The <see cref="SpanBuilder{T}"/> to convert to a <see cref="ReadOnlySpan{T}"/>.</param>
 43  public static implicit operator ReadOnlySpan<T>(SpanBuilder<T> spanBuilder) => spanBuilder._span[..spanBuilder._i];
 44
 45  /// <summary>Converts a <see cref="SpanBuilder{T}"/> to a <see cref="Span{T}"/>.</summary>
 46  /// <param name="spanBuilder">The <see cref="SpanBuilder{T}"/> to convert to a <see cref="Span{T}"/>.</param>
 47  public static implicit operator Span<T>(SpanBuilder<T> spanBuilder) => spanBuilder._span[..spanBuilder._i];
 48
 49  /// <summary>Converts a <see cref="Span{T}"/> to a <see cref="SpanBuilder{T}"/>.</summary>
 50  /// <param name="span">The <see cref="Span{T}"/> to convert to a <see cref="SpanBuilder{T}"/>.</param>
 51  public static implicit operator SpanBuilder<T>(Span<T> span) => new(span);
 52}
 53
 54/// <summary>Root type of the static functional methods in Towel.</summary>
 55public static partial class Statics
 56{
 57  /// <summary>Appends a <see cref="char"/> followed by <see cref="Environment.NewLine"/> to a <paramref name="spanBuild
 58  /// <param name="spanBuilder">The <see cref="SpanBuilder{T}"/> to append to.</param>
 59  /// <param name="value">The <see cref="char"/> to append to the <paramref name="spanBuilder"/>.</param>
 60  public static void AppendLine(this ref SpanBuilder<char> spanBuilder, char value)
 361  {
 462    if (spanBuilder._i + 1 + Environment.NewLine.Length > spanBuilder._span.Length) throw new InvalidOperationException(
 263    spanBuilder.AppendInternal(value);
 264    spanBuilder.AppendInternal(Environment.NewLine);
 265  }
 66
 67  /// <summary>Appends a <see cref="char"/> span followed by <see cref="Environment.NewLine"/> to a <paramref name="span
 68  /// <param name="spanBuilder">The <see cref="SpanBuilder{T}"/> to append to.</param>
 69  /// <param name="span">The <see cref="char"/> span to append to the <paramref name="spanBuilder"/>.</param>
 70  public static void AppendLine(this ref SpanBuilder<char> spanBuilder, ReadOnlySpan<char> span)
 371  {
 472    if (spanBuilder._i + span.Length + Environment.NewLine.Length > spanBuilder._span.Length) throw new InvalidOperation
 273    spanBuilder.AppendInternal(span);
 274    spanBuilder.AppendInternal(Environment.NewLine);
 275  }
 76
 77  /// <summary>Appends a <see cref="Environment.NewLine"/> to a <paramref name="spanBuilder"/>.</summary>
 78  /// <param name="spanBuilder">The <see cref="SpanBuilder{T}"/> to append to.</param>
 79  public static void AppendLine(this ref SpanBuilder<char> spanBuilder)
 380  {
 381    spanBuilder.Append(Environment.NewLine);
 182  }
 83}

/home/runner/work/Towel/Towel/Sources/Towel/Statics-Combinations.cs

#LineLine coverage
 1namespace Towel;
 2
 3/// <summary>Root type of the static functional methods in Towel.</summary>
 4public static partial class Statics
 5{
 6  /// <summary>Iterates through all combinations of the provided per-index element values.</summary>
 7  /// <typeparam name="T">The element type of the combinations to iterate.</typeparam>
 8  /// <param name="elementPosibilities">The possible element values at each index.</param>
 9  /// <param name="action">The action to perform on each possible combination.</param>
 10  public static void Combinations<T>(T[][] elementPosibilities, Action_ReadOnlySpan<T> action) =>
 1211    Combinations<T, Action_ReadOnlySpan_Runtime<T>>(elementPosibilities, action);
 12
 13  /// <summary>Iterates through all combinations of the provided per-index element values.</summary>
 14  /// <typeparam name="T">The element type of the combinations to iterate.</typeparam>
 15  /// <typeparam name="TAction">The action to perform on each combination.</typeparam>
 16  /// <param name="elementPosibilities">The possible element values at each index.</param>
 17  /// <param name="action">The action to perform on each possible combination.</param>
 18  public static void Combinations<T, TAction>(T[][] elementPosibilities, TAction action = default)
 19    where TAction : struct, IAction_ReadOnlySpan<T> =>
 1220    Combinations<T, TAction, Func_int_int_JaggedArray_Length0<T>, Func_int_int_T_JaggedArray_Get<T>>(
 1221      elementPosibilities.Length,
 1222      action,
 1223      elementPosibilities,
 1224      elementPosibilities);
 25
 26  /// <summary>Iterates through all combinations of the provided per-index element values.</summary>
 27  /// <typeparam name="T">The element type of the combinations to iterate.</typeparam>
 28  /// <param name="length">The length of the spans to iterate.</param>
 29  /// <param name="action">The action to perform on each combination.</param>
 30  /// <param name="indexPossibilities">The function to get the possible element values at each index.</param>
 31  /// <param name="valueAt">The action to perform on each possible combination.</param>
 32  public static void Combinations<T>(int length, Action_ReadOnlySpan<T> action, Func<int, int> indexPossibilities, Func<
 033    Combinations<T, Action_ReadOnlySpan_Runtime<T>, SFunc<int, int>, SFunc<int, int, T>>(length, action, indexPossibilit
 34
 35  /// <summary>Iterates through all combinations of the provided per-index element values.</summary>
 36  /// <typeparam name="T">The element type of the combinations to iterate.</typeparam>
 37  /// <typeparam name="TAction">Thetype of action to perform on each combination.</typeparam>
 38  /// <typeparam name="TIndexPossibilities">The type of function to get the possible element values at each index.</type
 39  /// <typeparam name="TValueAt">The type of action to perform on each possible combination.</typeparam>
 40  /// <param name="length">The length of the spans to iterate.</param>
 41  /// <param name="action">The action to perform on each combination.</param>
 42  /// <param name="indexPossibilities">The function to get the possible element values at each index.</param>
 43  /// <param name="valueAt">The action to perform on each possible combination.</param>
 44  public static void Combinations<T, TAction, TIndexPossibilities, TValueAt>(
 45    int length,
 46    TAction action = default,
 47    TIndexPossibilities indexPossibilities = default,
 48    TValueAt valueAt = default)
 49    where TAction : struct, IAction_ReadOnlySpan<T>
 50    where TIndexPossibilities : struct, IFunc<int, int>
 51    where TValueAt : struct, IFunc<int, int, T>
 1252  {
 1253    Span<int> digits = stackalloc int[length];
 1254    Span<T> span = new T[length];
 8255    for (int i = 0; i < span.Length; i++)
 2956    {
 2957      digits[i] = 0;
 2958      span[i] = valueAt.Invoke(i, 0);
 2959    }
 8260    while (true)
 8261    {
 8262      action.Invoke(span);
 8263      int digit = 0;
 13764      while (true)
 13765      {
 13766        if (digit >= length)
 1267        {
 1268          return;
 69        }
 12570        digits[digit]++;
 12571        if (digits[digit] >= indexPossibilities.Invoke(digit))
 5572        {
 5573          digits[digit] = 0;
 5574          span[digit] = valueAt.Invoke(digit, digits[digit]);
 5575          digit++;
 5576        }
 77        else
 7078        {
 7079          span[digit] = valueAt.Invoke(digit, digits[digit]);
 7080          break;
 81        }
 5582      }
 7083    }
 1284  }
 85}

/home/runner/work/Towel/Towel/Sources/Towel/Statics-Extensions.cs

#LineLine coverage
 1using System.Diagnostics;
 2using System.Reflection;
 3using System.Text;
 4using System.Text.RegularExpressions;
 5
 6namespace Towel;
 7
 8/// <summary>Root type of the static functional methods in Towel.</summary>
 9public static partial class Statics
 10{
 11  #region System.String
 12
 13  #region Replace (multiple replace)
 14
 15  /// <summary>Returns a new <see cref="string"/> in which all occurrences of Unicode <see cref="string"/> patterns in t
 16  /// <remarks>Uses Regex without a timeout.</remarks>
 17  /// <param name="original">The <see cref="string"/> to perform the replacements on.</param>
 18  /// <param name="rules">The patterns and relative replacements to apply to this <see cref="string"/>.</param>
 19  /// <returns>A new <see cref="string"/> in which all occurrences of Unicode <see cref="string"/> patterns in this inst
 20  /// <exception cref="ArgumentNullException">Thrown if any of the parameters are null or contain null values.</exceptio
 21  /// <exception cref="ArgumentException">Thrown if <paramref name="rules"/> is empty, <paramref name="rules"/> contains
 22  public static string Replace(this string original, params (string A, string B)[] rules)
 923  {
 1024    if (original is null) throw new ArgumentNullException(nameof(original));
 925    if (rules is null) throw new ArgumentNullException(nameof(rules));
 826    if (rules.Length is 0) throw new ArgumentException(paramName: nameof(rules), message: $"{nameof(rules)}.{nameof(rule
 627    MapHashLinked<string, string, StringEquate, StringHash> map = new(expectedCount: rules.Length);
 3628    foreach (var (a, b) in rules)
 1129    {
 1230      if (a is null) throw new ArgumentNullException(paramName: nameof(rules), message: $"{nameof(rules)} contains null 
 1131      if (b is null) throw new ArgumentNullException(paramName: nameof(rules), message: $"{nameof(rules)} contains null 
 1032      if (a.Length is 0) throw new ArgumentException(paramName: nameof(rules), message: $"{nameof(rules)} contains 0 len
 833      var (success, exception) = map.TryAdd(a, b);
 834      if (!success)
 135      {
 136        throw new ArgumentException($"{nameof(rules)} contains duplicate {nameof(a)}s", exception);
 37      }
 738    }
 239    string regexPattern = string.Join("|", map.GetKeys());
 740    return Regex.Replace(original, regexPattern, match => map[match.Value], RegexOptions.None, Regex.InfiniteMatchTimeou
 241  }
 42
 43  #endregion
 44
 45  /// <summary>Checks if a string contains any of a collections on characters.</summary>
 46  /// <param name="string">The string to see if it contains any of the specified characters.</param>
 47  /// <param name="chars">The characters to check if the string contains any of them.</param>
 48  /// <returns>True if the string contains any of the provided characters. False if not.</returns>
 49  public static bool ContainsAny(this string @string, params char[] chars)
 050  {
 051    if (chars is null) throw new ArgumentNullException(nameof(chars));
 052    if (@string is null) throw new ArgumentNullException(nameof(@string));
 053    if (chars.Length < 1)
 054    {
 055      throw new InvalidOperationException("Attempting a contains check with an empty set.");
 56    }
 57
 058    SetHashLinked<char, CharEquate, CharHash> set = new();
 059    foreach (char c in chars)
 060    {
 061      set.Add(c);
 062    }
 063    foreach (char c in @string)
 064    {
 065      if (set.Contains(c))
 066      {
 067        return true;
 68      }
 069    }
 070    return false;
 071  }
 72
 73  internal static string RemoveCarriageReturns(this string @string) =>
 074    @string.Replace("\r", string.Empty);
 75
 76  /// <summary>Removes carriage returns and then replaces all new line characters with System.Environment.NewLine.</summ
 77  /// <param name="string">The string to standardize the new lines of.</param>
 78  /// <returns>The new line standardized string.</returns>
 79  internal static string StandardizeNewLines(this string @string) =>
 080    @string.RemoveCarriageReturns().Replace("\n", Environment.NewLine);
 81
 82  /// <summary>Creates a string of a repreated string a provided number of times.</summary>
 83  /// <param name="string">The string to repeat.</param>
 84  /// <param name="count">The number of repetitions of the string to repeat.</param>
 85  /// <returns>The string of the repeated string to repeat.</returns>
 86  public static string Repeat(this string @string, int count)
 087  {
 088    if (@string is null) throw new ArgumentNullException(nameof(@string));
 089    if (sourceof(count < 0, out string c1)) throw new ArgumentOutOfRangeException(nameof(count), count, c1);
 090    string[] sets = new string[count];
 091    for (int i = 0; i < count; i++)
 092    {
 093      sets[i] = @string;
 094    }
 095    return string.Concat(sets);
 096  }
 97
 98  /// <summary>Splits the string into the individual lines.</summary>
 99  /// <param name="string">The string to get the lines of.</param>
 100  /// <returns>an array of the individual lines of the string.</returns>
 101  public static string[] SplitLines(this string @string)
 0102  {
 0103    if (@string is null) throw new ArgumentNullException(nameof(@string));
 0104    return @string.RemoveCarriageReturns().Split('\n');
 0105  }
 106
 107  /// <summary>Indents every line in a string with a single tab character.</summary>
 108  /// <param name="string">The string to indent the lines of.</param>
 109  /// <returns>The indented string.</returns>
 110  public static string IndentLines(this string @string) =>
 0111    PadLinesLeft(@string, "\t");
 112
 113  /// <summary>Indents every line in a string with a given number of tab characters.</summary>
 114  /// <param name="string">The string to indent the lines of.</param>
 115  /// <param name="count">The number of tabs of the indention.</param>
 116  /// <returns>The indented string.</returns>
 117  public static string IndentLines(this string @string, int count) =>
 0118    PadLinesLeft(@string, new string('\t', count));
 119
 120  /// <summary>Indents after every new line sequence found between two string indeces.</summary>
 121  /// <param name="string">The string to be indented.</param>
 122  /// <param name="start">The starting index to look for new line sequences to indent.</param>
 123  /// <param name="end">The ending index to look for new line sequences to indent.</param>
 124  /// <returns>The indented string.</returns>
 125  public static string IndentNewLinesBetweenIndeces(this string @string, int start, int end) =>
 0126    PadLinesLeftBetweenIndeces(@string, "\t", start, end);
 127
 128  /// <summary>Indents after every new line sequence found between two string indeces.</summary>
 129  /// <param name="string">The string to be indented.</param>
 130  /// <param name="count">The number of tabs of this indention.</param>
 131  /// <param name="start">The starting index to look for new line sequences to indent.</param>
 132  /// <param name="end">The ending index to look for new line sequences to indent.</param>
 133  /// <returns>The indented string.</returns>
 134  public static string IndentNewLinesBetweenIndeces(this string @string, int count, int start, int end) =>
 0135    PadLinesLeftBetweenIndeces(@string, new string('\t', count), start, end);
 136
 137  /// <summary>Indents a range of line numbers in a string.</summary>
 138  /// <param name="string">The string to indent specified lines of.</param>
 139  /// <param name="startingLineNumber">The line number to start line indention on.</param>
 140  /// <param name="endingLineNumber">The line number to stop line indention on.</param>
 141  /// <returns>The string with the specified lines indented.</returns>
 142  public static string IndentLineNumbers(this string @string, int startingLineNumber, int endingLineNumber) =>
 0143    PadLinesLeft(@string, "\t", startingLineNumber, endingLineNumber);
 144
 145  /// <summary>Indents a range of line numbers in a string.</summary>
 146  /// <param name="string">The string to indent specified lines of.</param>
 147  /// <param name="count">The number of tabs for the indention.</param>
 148  /// <param name="startingLineNumber">The line number to start line indention on.</param>
 149  /// <param name="endingLineNumber">The line number to stop line indention on.</param>
 150  /// <returns>The string with the specified lines indented.</returns>
 151  public static string IndentLineNumbers(this string @string, int count, int startingLineNumber, int endingLineNumber) =
 0152    PadLinesLeft(@string, new string('\t', count), startingLineNumber, endingLineNumber);
 153
 154  /// <summary>Adds a string onto the beginning of every line in a string.</summary>
 155  /// <param name="string">The string to pad.</param>
 156  /// <param name="padding">The padding to add to the front of every line.</param>
 157  /// <returns>The padded string.</returns>
 158  public static string PadLinesLeft(this string @string, string padding)
 0159  {
 0160    if (@string is null) throw new ArgumentNullException(nameof(@string));
 0161    if (padding is null) throw new ArgumentNullException(nameof(padding));
 0162    if (padding.CompareTo(string.Empty) is 0)
 0163    {
 0164      return @string;
 165    }
 0166    return string.Concat(padding, @string.RemoveCarriageReturns().Replace("\n", Environment.NewLine + padding));
 0167  }
 168
 169  /// <summary>Adds a string onto the end of every line in a string.</summary>
 170  /// <param name="string">The string to pad.</param>
 171  /// <param name="padding">The padding to add to the front of every line.</param>
 172  /// <returns>The padded string.</returns>
 173  public static string PadSubstringLinesRight(this string @string, string padding)
 0174  {
 0175    if (@string is null) throw new ArgumentNullException(nameof(@string));
 0176    if (padding is null) throw new ArgumentNullException(nameof(padding));
 0177    if (padding.CompareTo(string.Empty) is 0)
 0178    {
 0179      return @string;
 180    }
 0181    return string.Concat(@string.RemoveCarriageReturns().Replace("\n", padding + Environment.NewLine), padding);
 0182  }
 183
 184  /// <summary>Adds a string after every new line squence found between two indeces of a string.</summary>
 185  /// <param name="string">The string to be padded.</param>
 186  /// <param name="padding">The padding to apply after every newline sequence found.</param>
 187  /// <param name="start">The starting index of the string to search for new line sequences.</param>
 188  /// <param name="end">The ending index of the string to search for new line sequences.</param>
 189  /// <returns>The padded string.</returns>
 190  public static string PadLinesLeftBetweenIndeces(this string @string, string padding, int start, int end)
 0191  {
 0192    if (@string is null) throw new ArgumentNullException(nameof(@string));
 0193    if (padding is null) throw new ArgumentNullException(nameof(padding));
 0194    if (start < 0 || start >= @string.Length)
 0195    {
 0196      throw new ArgumentOutOfRangeException(nameof(start), start, "!(0 <= " + nameof(start) + " <= " + nameof(@string) +
 197    }
 0198    if (end >= @string.Length || end < start)
 0199    {
 0200      throw new ArgumentOutOfRangeException(nameof(end), end, "!(" + nameof(start) + " <= " + nameof(end) + " <= " + nam
 201    }
 0202    string header = @string[..start].StandardizeNewLines();
 0203    string body = string.Concat(@string[start..end].RemoveCarriageReturns().Replace("\n", Environment.NewLine + padding)
 0204    string footer = @string[end..].StandardizeNewLines();
 0205    return string.Concat(header, body, footer);
 0206  }
 207
 208  /// <summary>Adds a string before every new line squence found between two indeces of a string.</summary>
 209  /// <param name="string">The string to be padded.</param>
 210  /// <param name="padding">The padding to apply before every newline sequence found.</param>
 211  /// <param name="start">The starting index of the string to search for new line sequences.</param>
 212  /// <param name="end">The ending index of the string to search for new line sequences.</param>
 213  /// <returns>The padded string.</returns>
 214  public static string PadLinesRightBetweenIndeces(this string @string, string padding, int start, int end)
 0215  {
 0216    if (@string is null) throw new ArgumentNullException(nameof(@string));
 0217    if (padding is null) throw new ArgumentNullException(nameof(padding));
 0218    if (start < 0 || start >= @string.Length)
 0219    {
 0220      throw new ArgumentOutOfRangeException(nameof(start), start, "!(0 <= " + nameof(start) + " <= " + nameof(@string) +
 221    }
 0222    if (end >= @string.Length || end < start)
 0223    {
 0224      throw new ArgumentOutOfRangeException(nameof(end), end, "!(" + nameof(start) + " <= " + nameof(end) + " <= " + nam
 225    }
 0226    string header = @string[..start].StandardizeNewLines();
 0227    string body = string.Concat(@string[start..end].RemoveCarriageReturns().Replace("\n", padding + Environment.NewLine)
 0228    string footer = @string[end..].StandardizeNewLines();
 0229    return string.Concat(header, body, footer);
 0230  }
 231
 232  /// <summary>Adds a string after every new line squence found between two indeces of a string.</summary>
 233  /// <param name="string">The string to be padded.</param>
 234  /// <param name="padding">The padding to apply after every newline sequence found.</param>
 235  /// <param name="startingLineNumber">The starting index of the line in the string to pad.</param>
 236  /// <param name="endingLineNumber">The ending index of the line in the string to pad.</param>
 237  /// <returns>The padded string.</returns>
 238  public static string PadLinesLeft(this string @string, string padding, int startingLineNumber, int endingLineNumber)
 0239  {
 0240    if (@string is null) throw new ArgumentNullException(nameof(@string));
 0241    if (padding is null) throw new ArgumentNullException(nameof(padding));
 0242    string[] lines = @string.SplitLines();
 0243    if (startingLineNumber < 0 || startingLineNumber >= lines.Length)
 0244    {
 0245      throw new ArgumentOutOfRangeException(nameof(startingLineNumber));
 246    }
 0247    if (endingLineNumber >= lines.Length || endingLineNumber < startingLineNumber)
 0248    {
 0249      throw new ArgumentOutOfRangeException(nameof(endingLineNumber));
 250    }
 0251    for (int i = startingLineNumber; i <= endingLineNumber; i++)
 0252    {
 0253      lines[i] = padding + lines[i];
 0254    }
 0255    return string.Concat(lines);
 0256  }
 257
 258  /// <summary>Adds a string before every new line squence found between two indeces of a string.</summary>
 259  /// <param name="string">The string to be padded.</param>
 260  /// <param name="padding">The padding to apply before every newline sequence found.</param>
 261  /// <param name="startingLineNumber">The starting index of the line in the string to pad.</param>
 262  /// <param name="endingLineNumber">The ending index of the line in the string to pad.</param>
 263  /// <returns>The padded string.</returns>
 264  public static string PadLinesRight(this string @string, string padding, int startingLineNumber, int endingLineNumber)
 0265  {
 0266    if (@string is null) throw new ArgumentNullException(nameof(@string));
 0267    if (padding is null) throw new ArgumentNullException(nameof(padding));
 0268    string[] lines = @string.SplitLines();
 0269    if (startingLineNumber < 0 || startingLineNumber >= lines.Length)
 0270    {
 0271      throw new ArgumentOutOfRangeException(nameof(startingLineNumber), startingLineNumber, "!(0 <= " + nameof(startingL
 272    }
 0273    if (endingLineNumber >= lines.Length || endingLineNumber < startingLineNumber)
 0274    {
 0275      throw new ArgumentOutOfRangeException(nameof(endingLineNumber), endingLineNumber, "!(" + nameof(startingLineNumber
 276    }
 0277    for (int i = startingLineNumber; i <= endingLineNumber; i++)
 0278    {
 0279      lines[i] += padding;
 0280    }
 0281    return string.Concat(lines);
 0282  }
 283
 284  /// <summary>Reverses the characters in a string.</summary>
 285  /// <param name="string">The string to reverse the characters of.</param>
 286  /// <returns>The reversed character string.</returns>
 287  public static string Reverse(this string @string)
 0288  {
 0289    char[] characters = @string.ToCharArray();
 0290    Array.Reverse(characters);
 0291    return new string(characters);
 0292  }
 293
 294  /// <summary>Removes all the characters from a string based on a predicate.</summary>
 295  /// <param name="string">The string to remove characters from.</param>
 296  /// <param name="where">The predicate determining removal of each character.</param>
 297  /// <returns>The string after removing any predicated characters.</returns>
 298  public static string Remove(this string @string, Predicate<char> where)
 0299  {
 0300    StringBuilder stringBuilder = new();
 0301    foreach (char c in @string)
 0302    {
 0303      if (!where(c))
 0304      {
 0305        stringBuilder.Append(c);
 0306      }
 0307    }
 0308    return stringBuilder.ToString();
 0309  }
 310
 311  /// <summary>Counts the number of lines in the string.</summary>
 312  /// <param name="str">The string to get the line count of.</param>
 313  /// <returns>The number of lines in the string.</returns>
 314  public static int CountLines(this string str) =>
 0315    Regex.Matches(str.StandardizeNewLines(), Environment.NewLine).Count + 1;
 316
 317  #endregion
 318
 319  #region XML_Stepper
 320
 321#pragma warning disable CS1735, CS1572, CS1711, SA1625, SA1617
 322
 323  /// <summary>Performs a method on every value in a sequence.</summary>
 324  /// <typeparam name="T">The type of values in the sequence.</typeparam>
 325  /// <typeparam name="TStep">The type of method to perform on every <typeparamref name="T"/> value.</typeparam>
 326  /// <param name="span">The sequence of <typeparamref name="T"/> values.</param>
 327  /// <param name="array">The sequence of <typeparamref name="T"/> values.</param>
 328  /// <param name="step">The method to perform on every <typeparamref name="T"/> value.</param>
 329  /// <param name="start">The inclusive starting index.</param>
 330  /// <param name="end">The exclusive ending index.</param>
 331  [Obsolete(NotIntended, true)]
 1332  public static void XML_Stepper() => throw new DocumentationMethodException();
 333
 334  /// <inheritdoc cref="XML_Stepper"/>
 335  /// <returns><see cref="StepStatus"/></returns>
 336  [Obsolete(NotIntended, true)]
 1337  public static void XML_StepperBreak() => throw new DocumentationMethodException();
 338
 339#pragma warning restore CS1735, CS1572, CS1711, SA1625, SA1617
 340
 341  #endregion
 342
 343  #region Span
 344
 345  #region Stepper
 346
 347  /// <inheritdoc cref="XML_Stepper"/>
 348  public static void Stepper<T>(this ReadOnlySpan<T> span, Action<T> step) =>
 0349    Stepper<T, SAction<T>>(span, step);
 350
 351  /// <inheritdoc cref="XML_Stepper"/>
 352  public static void Stepper<T, TStep>(this ReadOnlySpan<T> span, TStep step = default)
 353    where TStep : struct, IAction<T> =>
 0354    StepperBreak<T, StepBreakFromAction<T, TStep>>(span, step);
 355
 356  /// <inheritdoc cref="XML_StepperBreak"/>
 357  public static StepStatus StepperBreak<T>(this ReadOnlySpan<T> span, Func<T, StepStatus> step)
 0358  {
 0359    if (step is null) throw new ArgumentNullException(nameof(step));
 0360    return StepperBreak<T, SFunc<T, StepStatus>>(span, step);
 0361  }
 362
 363  /// <inheritdoc cref="XML_StepperBreak"/>
 364  public static StepStatus StepperBreak<T, TStep>(this ReadOnlySpan<T> span, TStep step = default)
 365    where TStep : struct, IFunc<T, StepStatus> =>
 0366    StepperBreak<T, TStep>(span, 0, span.Length, step);
 367
 368  /// <inheritdoc cref="XML_Stepper"/>
 369  public static void Stepper<T>(this ReadOnlySpan<T> span, int start, int end, Action<T> step) =>
 0370    Stepper<T, SAction<T>>(span, start, end, step);
 371
 372  /// <inheritdoc cref="XML_Stepper"/>
 373  public static void Stepper<T, TStep>(this ReadOnlySpan<T> span, int start, int end, TStep step = default)
 374    where TStep : struct, IAction<T> =>
 0375    StepperBreak<T, StepBreakFromAction<T, TStep>>(span, start, end, step);
 376
 377  /// <inheritdoc cref="XML_StepperBreak"/>
 378  public static StepStatus Stepper<T>(this ReadOnlySpan<T> span, int start, int end, Func<T, StepStatus> step) =>
 0379    StepperBreak<T, SFunc<T, StepStatus>>(span, start, end, step);
 380
 381  /// <inheritdoc cref="XML_StepperBreak"/>
 382  public static StepStatus StepperBreak<T, TStep>(this ReadOnlySpan<T> span, int start, int end, TStep step = default)
 383    where TStep : struct, IFunc<T, StepStatus>
 0384  {
 0385    for (int i = start; i < end; i++)
 0386    {
 0387      if (step.Invoke(span[i]) is Break)
 0388      {
 0389        return Break;
 390      }
 0391    }
 0392    return Continue;
 0393  }
 394
 395  #endregion
 396
 397  #endregion
 398
 399  #region Array
 400
 401  #region Stepper
 402
 403  /// <inheritdoc cref="XML_Stepper"/>
 404  public static void Stepper<T>(this T[] array, Action<T> step)
 167405  {
 167406    if (step is null) throw new ArgumentNullException(nameof(step));
 167407    Stepper<T, SAction<T>>(array, step);
 167408  }
 409
 410  /// <inheritdoc cref="XML_Stepper"/>
 411  public static void Stepper<T, TStep>(this T[] array, TStep step = default)
 412    where TStep : struct, IAction<T> =>
 167413    StepperBreak<T, StepBreakFromAction<T, TStep>>(array, step);
 414
 415  /// <inheritdoc cref="XML_StepperBreak"/>
 416  public static StepStatus StepperBreak<T>(this T[] array, Func<T, StepStatus> step)
 0417  {
 0418    if (step is null) throw new ArgumentNullException(nameof(step));
 0419    return StepperBreak<T, SFunc<T, StepStatus>>(array, step);
 0420  }
 421
 422  /// <inheritdoc cref="XML_StepperBreak"/>
 423  public static StepStatus StepperBreak<T, TStep>(this T[] array, TStep step = default)
 424    where TStep : struct, IFunc<T, StepStatus> =>
 167425    StepperBreak<T, TStep>(array, 0, array.Length, step);
 426
 427  /// <inheritdoc cref="XML_Stepper"/>
 428  public static void Stepper<T>(this T[] array, int start, int end, Action<T> step) =>
 0429    Stepper<T, SAction<T>>(array, start, end, step);
 430
 431  /// <inheritdoc cref="XML_Stepper"/>
 432  public static void Stepper<T, TStep>(this T[] array, int start, int end, TStep step = default)
 433    where TStep : struct, IAction<T> =>
 0434    StepperBreak<T, StepBreakFromAction<T, TStep>>(array, start, end, step);
 435
 436  /// <inheritdoc cref="XML_StepperBreak"/>
 437  public static StepStatus Stepper<T>(this T[] array, int start, int end, Func<T, StepStatus> step) =>
 0438    StepperBreak<T, SFunc<T, StepStatus>>(array, start, end, step);
 439
 440  /// <inheritdoc cref="XML_StepperBreak"/>
 441  public static StepStatus StepperBreak<T, TStep>(this T[] array, int start, int end, TStep step = default)
 442    where TStep : struct, IFunc<T, StepStatus>
 1658443  {
 1916992444    for (int i = start; i < end; i++)
 956838445    {
 956838446      if (step.Invoke(array[i]) is Break)
 0447      {
 0448        return Break;
 449      }
 956838450    }
 1658451    return Continue;
 1658452  }
 453
 454  #endregion
 455
 456  /// <summary>Builds an array from a size and initialization delegate.</summary>
 457  /// <typeparam name="T">The generic type of the array.</typeparam>
 458  /// <param name="size">The size of the array to build.</param>
 459  /// <param name="func">The initialization pattern.</param>
 460  /// <returns>The built array.</returns>
 461  public static T[] BuildArray<T>(int size, Func<int, T> func)
 0462  {
 0463    T[] array = new T[size];
 0464    for (int i = 0; i < size; i++)
 0465    {
 0466      array[i] = func(i);
 0467    }
 0468    return array;
 0469  }
 470
 471  /// <summary>Formats an array so that all values are the same.</summary>
 472  /// <typeparam name="T">The generic type of the array to format.</typeparam>
 473  /// <param name="array">The array to format.</param>
 474  /// <param name="value">The value to format all entries in the array with.</param>
 475  public static void Format<T>(this T[] array, T value)
 0476  {
 0477    for (int i = 0; i < array.Length; i++)
 0478    {
 0479      array[i] = value;
 0480    }
 0481  }
 482
 483  /// <summary>Formats an array so that all values are the same.</summary>
 484  /// <typeparam name="T">The generic type of the array to format.</typeparam>
 485  /// <param name="array">The array to format.</param>
 486  /// <param name="func">The per-index format function.</param>
 487  public static void Format<T>(this T[] array, Func<int, T> func)
 0488  {
 0489    for (int i = 0; i < array.Length; i++)
 0490    {
 0491      array[i] = func(i);
 0492    }
 0493  }
 494
 495  /// <summary>Constructs a square jagged array of the desired dimensions.</summary>
 496  /// <typeparam name="T">The generic type to store in the jagged array.</typeparam>
 497  /// <param name="length1">The length of the first dimension.</param>
 498  /// <param name="length2">The length of the second dimension.</param>
 499  /// <returns>The constructed jagged array.</returns>
 500  public static T[][] ConstructRectangularJaggedArray<T>(int length1, int length2)
 7501  {
 7502    T[][] jaggedArray = new T[length1][];
 78503    for (int i = 0; i < length1; i++)
 32504    {
 32505      jaggedArray[i] = new T[length2];
 32506    }
 7507    return jaggedArray;
 7508  }
 509
 510  /// <summary>Constructs a square jagged array of the desired dimensions.</summary>
 511  /// <typeparam name="T">The generic type to store in the jagged array.</typeparam>
 512  /// <param name="length1">The length of the first dimension.</param>
 513  /// <param name="length2">The length of the second dimension.</param>
 514  /// <param name="func">The function to initialize the values with.</param>
 515  /// <returns>The constructed jagged array.</returns>
 516  public static T[][] ConstructRectangularJaggedArray<T>(int length1, int length2, Func<int, int, T> func)
 0517  {
 0518    T[][] jaggedArray = new T[length1][];
 0519    for (int i = 0; i < length1; i++)
 0520    {
 0521      jaggedArray[i] = new T[length2];
 0522    }
 0523    for (int i = 0; i < length1; i++)
 0524    {
 0525      for (int j = 0; j < length2; j++)
 0526      {
 0527        jaggedArray[i][j] = func(i, j);
 0528      }
 0529    }
 0530    return jaggedArray;
 0531  }
 532
 533  /// <summary>Constructs a square jagged array of the desired dimensions.</summary>
 534  /// <typeparam name="T">The generic type to store in the jagged array.</typeparam>
 535  /// <param name="sideLength">The length of each dimension.</param>
 536  /// <returns>The constructed jagged array.</returns>
 537  public static T[][] ConstructSquareJaggedArray<T>(int sideLength) =>
 7538    ConstructRectangularJaggedArray<T>(sideLength, sideLength);
 539
 540  /// <summary>Constructs a square jagged array of the desired dimensions.</summary>
 541  /// <typeparam name="T">The generic type to store in the jagged array.</typeparam>
 542  /// <param name="sideLength">The length of each dimension.</param>
 543  /// <param name="func">The function to initialize the values with.</param>
 544  /// <returns>The constructed jagged array.</returns>
 545  public static T[][] ConstructSquareJaggedArray<T>(int sideLength, Func<int, int, T> func) =>
 0546    ConstructRectangularJaggedArray<T>(sideLength, sideLength, func);
 547
 548  #endregion
 549
 550  #region System.Action
 551
 552  /// <summary>Times an action using System.DateTime.</summary>
 553  /// <param name="action">The action to time.</param>
 554  /// <returns>The TimeSpan the action took to complete.</returns>
 555  public static TimeSpan Time_DateTime(this Action action)
 0556  {
 0557    DateTime a = DateTime.Now;
 0558    action();
 0559    DateTime b = DateTime.Now;
 0560    return b - a;
 0561  }
 562
 563  /// <summary>Times an action using System.Diagnostics.Stopwatch.</summary>
 564  /// <param name="action">The action to time.</param>
 565  /// <returns>The TimeSpan the action took to complete.</returns>
 566  public static TimeSpan Time_StopWatch(this Action action)
 0567  {
 0568    Stopwatch watch = new();
 0569    watch.Restart();
 0570    action();
 0571    watch.Stop();
 0572    return watch.Elapsed;
 0573  }
 574
 575  #endregion
 576
 577  #region System.Collections.Generic.IEnumerable<T>
 578
 579  /// <summary>Tries to get the first value in an <see cref="System.Collections.Generic.IEnumerable{T}"/>.</summary>
 580  /// <typeparam name="T">The generic type of <see cref="System.Collections.Generic.IEnumerable{T}"/>.</typeparam>
 581  /// <param name="iEnumerable">The IEnumerable to try to get the first value of.</param>
 582  /// <param name="first">The first value of the <see cref="System.Collections.Generic.IEnumerable{T}"/> or default if e
 583  /// <returns>True if the <see cref="System.Collections.Generic.IEnumerable{T}"/> has a first value or false if it is e
 584  public static bool TryFirst<T>(this System.Collections.Generic.IEnumerable<T> iEnumerable, out T? first)
 0585  {
 0586    foreach (T value in iEnumerable)
 0587    {
 0588      first = value;
 0589      return true;
 590    }
 0591    first = default;
 0592    return false;
 0593  }
 594
 595  #endregion
 596
 597  #region System.Reflection.MethodInfo
 598
 599  /// <summary>Creates a delegate of the specified type from this <see cref="MethodInfo"/>.</summary>
 600  /// <typeparam name="TDelegate">The type of the delegate to create.</typeparam>
 601  /// <param name="methodInfo">The <see cref="MethodInfo"/> to create the delegate from.</param>
 602  /// <returns>The delegate for this <see cref="MethodInfo"/>.</returns>
 603  /// <remarks>This extension is syntax sugar so you don't have to cast the return.</remarks>
 604  public static TDelegate CreateDelegate<TDelegate>(this MethodInfo methodInfo)
 605    where TDelegate : Delegate =>
 0606    (TDelegate)methodInfo.CreateDelegate(typeof(TDelegate));
 607
 608  #endregion
 609
 610  #region Enum (Generic)
 611
 612  /// <inheritdoc cref="Enum.IsDefined{TEnum}"/>
 1613  public static bool IsDefined<TEnum>(this TEnum value) where TEnum : struct, Enum => Enum.IsDefined<TEnum>(value);
 614
 615  #endregion
 616
 617  #region System.Range
 618
 619  /// <summary>Converts a <see cref="System.Range"/> to an <see cref="System.Collections.Generic.IEnumerable{T}"/>.</sum
 620  /// <param name="range">The <see cref="System.Range"/> to convert int a <see cref="System.Collections.Generic.IEnumera
 621  /// <returns>The resulting <see cref="System.Collections.Generic.IEnumerable{T}"/> of the conversion.</returns>
 622  /// <exception cref="ArgumentException">range.Start.IsFromEnd</exception>
 623  /// <exception cref="ArgumentException">range.End.IsFromEnd</exception>
 624  public static System.Collections.Generic.IEnumerable<int> ToIEnumerable(this Range range)
 7625  {
 7626    if (range.Start.IsFromEnd)
 2627    {
 2628      throw new ArgumentException($"{nameof(range)}.{nameof(range.Start)}.{nameof(range.Start.IsFromEnd)}", nameof(range
 629    }
 5630    if (range.End.IsFromEnd)
 1631    {
 1632      throw new ArgumentException($"{nameof(range)}.{nameof(range.End)}.{nameof(range.End.IsFromEnd)}", nameof(range));
 633    }
 4634    if (range.End.Value < range.Start.Value)
 2635    {
 18636      for (int i = range.Start.Value; i > range.End.Value; i--)
 7637      {
 7638        yield return i;
 7639      }
 2640    }
 641    else
 2642    {
 18643      for (int i = range.Start.Value; i < range.End.Value; i++)
 7644      {
 7645        yield return i;
 7646      }
 2647    }
 4648  }
 649
 650  /// <summary>Returns an <see cref="System.Collections.Generic.IEnumerator{T}"/> that iterates through the <paramref na
 651  /// <param name="range">The range to get the <see cref="System.Collections.Generic.IEnumerator{T}"/> of.</param>
 652  /// <returns>An <see cref="System.Collections.Generic.IEnumerator{T}"/> that iterates through the <paramref name="rang
 0653  public static System.Collections.Generic.IEnumerator<int> GetEnumerator(this Range range) => ToIEnumerable(range).GetE
 654
 655  /// <inheritdoc cref="ToSpan{T, TSelect}(Range, TSelect)" />
 656  public static Span<int> ToSpan(this Range range) =>
 660657    ToArray<int, Identity<int>>(range);
 658
 659  /// <inheritdoc cref="ToSpan{T, TSelect}(Range, TSelect)" />
 660  public static Span<T> ToSpan<T>(this Range range, Func<int, T> select)
 1152661  {
 1152662    if (select is null) throw new ArgumentNullException(nameof(select));
 1152663    return ToArray<T, SFunc<int, T>>(range, select);
 1152664  }
 665
 666  /// <summary>Converts a <paramref name="range"/> to a to an span of values.</summary>
 667  /// <typeparam name="T">The resulting element type of the span.</typeparam>
 668  /// <typeparam name="TSelect">The type of method for selecting a <typeparamref name="T"/> based on an <see cref="int"/
 669  /// <param name="range">The range of values to convert into an span.</param>
 670  /// <param name="select">The method for selecting a <typeparamref name="T"/> based on an <see cref="int"/>.</param>
 671  /// <returns>An span of the values of the <paramref name="range"/>.</returns>
 672  public static Span<T> ToSpan<T, TSelect>(this Range range, TSelect select = default)
 673    where TSelect : struct, IFunc<int, T> =>
 0674    ToArray<T, TSelect>(range, select);
 675
 676  /// <inheritdoc cref="ToArray{T, TSelect}(Range, TSelect)"/>
 677  public static int[] ToArray(this Range range) =>
 742678    ToArray<int, Identity<int>>(range);
 679
 680  /// <inheritdoc cref="ToArray{T, TSelect}(Range, TSelect)"/>
 681  public static T[] ToArray<T>(this Range range, Func<int, T> select)
 2374682  {
 2374683    if (select is null) throw new ArgumentNullException(nameof(select));
 2374684    return ToArray<T, SFunc<int, T>>(range, select);
 2374685  }
 686
 687  /// <summary>Converts a <paramref name="range"/> to a to an array of values.</summary>
 688  /// <typeparam name="T">The resulting element type of the array.</typeparam>
 689  /// <typeparam name="TSelect">The type of method for selecting a <typeparamref name="T"/> based on an <see cref="int"/
 690  /// <param name="range">The range of values to convert into an array.</param>
 691  /// <param name="select">The method for selecting a <typeparamref name="T"/> based on an <see cref="int"/>.</param>
 692  /// <returns>An array of the values of the <paramref name="range"/>.</returns>
 693  public static T[] ToArray<T, TSelect>(this Range range, TSelect select = default)
 694    where TSelect : struct, IFunc<int, T>
 4928695  {
 4928696    if (range.Start.IsFromEnd)
 2697    {
 2698      throw new ArgumentException($"{nameof(range)}.{nameof(range.Start)}.{nameof(range.Start.IsFromEnd)}", nameof(range
 699    }
 4926700    if (range.End.IsFromEnd)
 3701    {
 3702      throw new ArgumentException($"{nameof(range)}.{nameof(range.End)}.{nameof(range.End.IsFromEnd)}", nameof(range));
 703    }
 4923704    T[] array = new T[Math.Abs(range.Start.Value - range.End.Value)];
 4923705    int index = 0;
 4923706    if (range.End.Value < range.Start.Value)
 2872707    {
 845098708      for (int i = range.Start.Value; i > range.End.Value; i--)
 419677709      {
 419677710        array[index++] = select.Invoke(i);
 419677711      }
 2872712    }
 713    else
 2051714    {
 1341920715      for (int i = range.Start.Value; i < range.End.Value; i++)
 668909716      {
 668909717        array[index++] = select.Invoke(i);
 668909718      }
 2051719    }
 4923720    return array;
 4923721  }
 722
 723  /// <inheritdoc cref="Select{T, TSelect}(Range, TSelect)"/>
 724  public static System.Collections.Generic.IEnumerable<T> Select<T>(this Range range, Func<int, T> select)
 27725  {
 27726    if (select is null) throw new ArgumentNullException(nameof(select));
 27727    return Select<T, SFunc<int, T>>(range, select);
 27728  }
 729
 730  /// <summary>Projects each element of a sequence into a new form.</summary>
 731  /// <typeparam name="T">The type of the value returned by selector.</typeparam>
 732  /// <typeparam name="TSelect">The type of function for selecting a <typeparamref name="T"/> based on an <see cref="int
 733  /// <param name="range">A sequence of values to invoke a transform function on.</param>
 734  /// <param name="select">The function for selecting a <typeparamref name="T"/> based on an <see cref="int"/>.</param>
 735  /// <returns>An <see cref="System.Collections.Generic.IEnumerable{T}"/> whose elements are the result of invoking the 
 736  public static System.Collections.Generic.IEnumerable<T> Select<T, TSelect>(this Range range, TSelect select = default)
 737    where TSelect : struct, IFunc<int, T>
 27738  {
 27739    if (range.Start.IsFromEnd)
 2740    {
 2741      throw new ArgumentException($"{nameof(range)}.{nameof(range.Start)}.{nameof(range.Start.IsFromEnd)}", nameof(range
 742    }
 25743    if (range.End.IsFromEnd)
 3744    {
 3745      throw new ArgumentException($"{nameof(range)}.{nameof(range.End)}.{nameof(range.End.IsFromEnd)}", nameof(range));
 746    }
 22747    if (range.End.Value < range.Start.Value)
 6748    {
 38749      for (int i = range.Start.Value; i > range.End.Value; i--)
 13750      {
 13751        yield return select.Invoke(i);
 13752      }
 6753    }
 754    else
 16755    {
 90756      for (int i = range.Start.Value; i < range.End.Value; i++)
 29757      {
 29758        yield return select.Invoke(i);
 29759      }
 16760    }
 22761  }
 762
 763  #endregion
 764
 765  #region Step
 766
 767  /// <summary>Adds a step to the gaps (in-betweens) of another step funtion.</summary>
 768  /// <typeparam name="T">The generic type of the step function.</typeparam>
 769  /// <param name="step">The step to add a gap step to.</param>
 770  /// <param name="gapStep">The step to perform in the gaps.</param>
 771  /// <returns>The combined step + gapStep function.</returns>
 772  public static Action<T> Gaps<T>(this Action<T> step, Action<T> gapStep)
 0773  {
 0774    bool first = true;
 0775    return
 0776      x =>
 0777      {
 0778        if (!first)
 0779        {
 0780          gapStep(x);
 0781        }
 0782        step(x);
 0783        first = false;
 0784      };
 0785  }
 786
 787  #endregion
 788
 789  #region Stepper
 790
 791  /// <summary>Converts the values in this stepper to another type.</summary>
 792  /// <typeparam name="TA">The generic type of the values of the original stepper.</typeparam>
 793  /// <typeparam name="TB">The generic type of the values to convert the stepper into.</typeparam>
 794  /// <param name="stepper">The stepper to convert.</param>
 795  /// <param name="func">The conversion function.</param>
 796  /// <returns>The converted stepper.</returns>
 797  public static Action<Action<TB>> Convert<TA, TB>(this Action<Action<TA>> stepper, Func<TA, TB> func) =>
 0798    b => stepper(a => b(func(a)));
 799
 800  /// <summary>Appends values to the stepper.</summary>
 801  /// <typeparam name="T">The generic type of the stepper.</typeparam>
 802  /// <param name="stepper">The stepper to append to.</param>
 803  /// <param name="values">The values to append to the stepper.</param>
 804  /// <returns>The resulting stepper with the appended values.</returns>
 805  public static Action<Action<T>> Append<T>(this Action<Action<T>> stepper, params T[] values) =>
 0806    stepper.Concat(values.ToStepper());
 807
 808  /// <summary>Builds a stepper from values.</summary>
 809  /// <typeparam name="T">The generic type of the stepper to build.</typeparam>
 810  /// <param name="values">The values to build the stepper from.</param>
 811  /// <returns>The resulting stepper function for the provided values.</returns>
 812  public static Action<Action<T>> Build<T>(params T[] values) =>
 0813    values.ToStepper();
 814
 815  /// <summary>Concatenates steppers.</summary>
 816  /// <typeparam name="T">The generic type of the stepper.</typeparam>
 817  /// <param name="stepper">The first stepper of the contactenation.</param>
 818  /// <param name="otherSteppers">The other steppers of the concatenation.</param>
 819  /// <returns>The concatenated steppers as a single stepper.</returns>
 820  public static Action<Action<T>> Concat<T>(this Action<Action<T>> stepper, params Action<Action<T>>[] otherSteppers) =>
 0821    step =>
 0822    {
 0823      stepper(step);
 0824      foreach (Action<Action<T>> otherStepper in otherSteppers)
 0825      {
 0826        otherStepper(step);
 0827      }
 0828    };
 829
 830  /// <summary>Filters a stepper using a where predicate.</summary>
 831  /// <typeparam name="T">The generic type of the stepper.</typeparam>
 832  /// <param name="stepper">The stepper to filter.</param>
 833  /// <param name="predicate">The predicate of the where filter.</param>
 834  /// <returns>The filtered stepper.</returns>
 835  public static Action<Action<T>> Where<T>(this Action<Action<T>> stepper, Func<T, bool> predicate) =>
 0836    step => stepper(x =>
 0837    {
 0838      if (predicate(x))
 0839      {
 0840        step(x);
 0841      }
 0842    });
 843
 844  /// <summary>Steps through a set number of integers.</summary>
 845  /// <param name="iterations">The number of times to iterate.</param>
 846  /// <param name="step">The step function.</param>
 847  public static void Iterate(int iterations, Action<int> step)
 36848  {
 4003272849    for (int i = 0; i < iterations; i++)
 2001600850    {
 2001600851      step(i);
 2001600852    }
 36853  }
 854
 855  /// <summary>Converts an IEnumerable into a stepper delegate./></summary>
 856  /// <typeparam name="T">The generic type being iterated.</typeparam>
 857  /// <param name="iEnumerable">The IEnumerable to convert.</param>
 858  /// <returns>The stepper delegate comparable to the IEnumerable provided.</returns>
 859  public static Action<Action<T>> ToStepper<T>(this System.Collections.Generic.IEnumerable<T> iEnumerable) =>
 383860    step =>
 383861    {
 1397862      foreach (T value in iEnumerable)
 124863      {
 124864        step(value);
 124865      }
 766866    };
 867
 868  /// <summary>Converts an IEnumerable into a stepper delegate./></summary>
 869  /// <typeparam name="T">The generic type being iterated.</typeparam>
 870  /// <param name="iEnumerable">The IEnumerable to convert.</param>
 871  /// <returns>The stepper delegate comparable to the IEnumerable provided.</returns>
 872  public static Func<Func<T, StepStatus>, StepStatus> ToStepperBreak<T>(this System.Collections.Generic.IEnumerable<T> i
 0873    step =>
 0874    {
 0875      foreach (T value in iEnumerable)
 0876      {
 0877        if (step(value) is Break)
 0878        {
 0879          return Break;
 0880        }
 0881      }
 0882      return Continue;
 0883    };
 884
 885  /// <summary>Converts the stepper into an array.</summary>
 886  /// <typeparam name="T">The generic type of the stepper.</typeparam>
 887  /// <param name="stepper">The stepper to convert.</param>
 888  /// <returns>The array created from the stepper.</returns>
 889  public static T[] ToArray<T>(this Action<Action<T>> stepper)
 0890  {
 0891    int count = stepper.Count();
 0892    T[] array = new T[count];
 0893    int i = 0;
 0894    stepper(x => array[i++] = x);
 0895    return array;
 0896  }
 897
 898  /// <summary>Counts the number of items in the stepper.</summary>
 899  /// <typeparam name="T">The generic type of the stepper.</typeparam>
 900  /// <param name="stepper">The stepper to count the items of.</param>
 901  /// <returns>The number of items in the stepper.</returns>
 902  public static int Count<T>(this Action<Action<T>> stepper)
 0903  {
 0904    int count = 0;
 0905    stepper(step => count++);
 0906    return count;
 0907  }
 908
 909  /// <summary>Reduces the stepper to be every nth value.</summary>
 910  /// <typeparam name="T">The generic type of the stepper.</typeparam>
 911  /// <param name="stepper">The stepper to reduce.</param>
 912  /// <param name="nth">Represents the values to reduce the stepper to; "5" means every 5th value.</param>
 913  /// <returns>The reduced stepper function.</returns>
 914  public static Action<Action<T>> EveryNth<T>(this Action<Action<T>> stepper, int nth)
 0915  {
 0916    if (stepper is null) throw new ArgumentNullException(nameof(stepper));
 0917    if (nth <= 0)
 0918    {
 0919      throw new ArgumentOutOfRangeException(nameof(nth), nth, "!(" + nameof(nth) + " > 0)");
 920    }
 0921    int i = 1;
 0922    return step => stepper(x =>
 0923    {
 0924      if (i == nth)
 0925      {
 0926        step(x);
 0927        i = 1;
 0928      }
 0929      else
 0930      {
 0931        i++;
 0932      }
 0933    });
 0934  }
 935
 936  /// <summary>Determines if the data contains any duplicates.</summary>
 937  /// <typeparam name="T">The generic type of the data.</typeparam>
 938  /// <param name="stepper">The stepper function for the data.</param>
 939  /// <param name="equate">An equality function for the data</param>
 940  /// <param name="hash">A hashing function for the data.</param>
 941  /// <returns>True if the data contains duplicates. False if not.</returns>
 942  public static bool ContainsDuplicates<T>(this Func<Func<T, StepStatus>, StepStatus> stepper, Func<T, T, bool>? equate 
 0943  {
 0944    bool duplicateFound = false;
 0945    var set = SetHashLinked.New(equate, hash);
 0946    stepper(x =>
 0947    {
 0948      if (set.Contains(x))
 0949      {
 0950        duplicateFound = true;
 0951        return Break;
 0952      }
 0953      else
 0954      {
 0955        set.Add(x);
 0956        return Continue;
 0957      }
 0958    });
 0959    return duplicateFound;
 0960  }
 961
 962  /// <summary>Determines if the data contains any duplicates.</summary>
 963  /// <typeparam name="T">The generic type of the data.</typeparam>
 964  /// <param name="stepper">The stepper function for the data.</param>
 965  /// <param name="equate">An equality function for the data</param>
 966  /// <param name="hash">A hashing function for the data.</param>
 967  /// <returns>True if the data contains duplicates. False if not.</returns>
 968  /// <remarks>Use the StepperBreak overload if possible. It is more effiecient.</remarks>
 969  public static bool ContainsDuplicates<T>(this Action<Action<T>> stepper, Func<T, T, bool>? equate = null, Func<T, int>
 0970  {
 0971    bool duplicateFound = false;
 0972    var set = SetHashLinked.New(equate, hash);
 0973    stepper(x =>
 0974    {
 0975      if (set.Contains(x))
 0976      {
 0977        duplicateFound = true;
 0978      }
 0979      else
 0980      {
 0981        set.Add(x);
 0982      }
 0983    });
 0984    return duplicateFound;
 0985  }
 986
 987  /// <summary>Determines if the data contains any duplicates.</summary>
 988  /// <typeparam name="T">The generic type of the data.</typeparam>
 989  /// <param name="stepper">The stepper function for the data.</param>
 990  /// <returns>True if the data contains duplicates. False if not.</returns>
 991  public static bool ContainsDuplicates<T>(this Func<Func<T, StepStatus>, StepStatus> stepper) =>
 0992    ContainsDuplicates(stepper, Equate, Hash);
 993
 994  /// <summary>Determines if the data contains any duplicates.</summary>
 995  /// <typeparam name="T">The generic type of the data.</typeparam>
 996  /// <param name="stepper">The stepper function for the data.</param>
 997  /// <returns>True if the data contains duplicates. False if not.</returns>
 998  /// <remarks>Use the StepperBreak overload if possible. It is more effiecient.</remarks>
 999  public static bool ContainsDuplicates<T>(this Action<Action<T>> stepper) =>
 01000    ContainsDuplicates(stepper, Equate, Hash);
 1001
 1002  /// <summary>Determines if the stepper contains any of the predicated values.</summary>
 1003  /// <typeparam name="T">The generic type of the stepper.</typeparam>
 1004  /// <param name="stepper">The stepper to determine if any predicated values exist.</param>
 1005  /// <param name="where">The predicate.</param>
 1006  /// <returns>True if any of the predicated values exist or </returns>
 1007  public static bool Any<T>(this Action<Action<T>> stepper, Predicate<T> where)
 01008  {
 01009    bool any = false;
 01010    stepper(x => any = any || where(x));
 01011    return any;
 01012  }
 1013
 1014  /// <summary>Determines if the stepper contains any of the predicated values.</summary>
 1015  /// <typeparam name="T">The generic type of the stepper.</typeparam>
 1016  /// <param name="stepper">The stepper to determine if any predicated values exist.</param>
 1017  /// <param name="where">The predicate.</param>
 1018  /// <returns>True if any of the predicated values exist or </returns>
 1019  public static bool Any<T>(this Func<Func<T, StepStatus>, StepStatus> stepper, Predicate<T> where)
 01020  {
 01021    bool any = false;
 01022    stepper(x => (any = where(x))
 01023      ? Break
 01024      : Continue);
 01025    return any;
 01026  }
 1027
 1028  /// <summary>Converts a stepper into a string of the concatenated chars.</summary>
 1029  /// <param name="stepper">The stepper to concatenate the values into a string.</param>
 1030  /// <returns>The string of the concatenated chars.</returns>
 1031  public static string ConcatToString(this Action<Action<char>> stepper)
 01032  {
 01033    StringBuilder stringBuilder = new();
 01034    stepper(c => stringBuilder.Append(c));
 01035    return stringBuilder.ToString();
 01036  }
 1037
 1038  #endregion
 1039
 1040  #region int
 1041
 1042  /// <summary>Converts an <see cref="int"/> to the relative <see cref="CompareResult"/>.</summary>
 1043  /// <param name="compareResult">The <see cref="int"/> to convert to the relative <see cref="CompareResult"/>.</param>
 1044  /// <returns>
 1045  /// <paramref name="compareResult"/> &lt; 0 =&gt; <see cref="CompareResult.Less"/><br/>
 1046  /// <paramref name="compareResult"/> &gt; 0 =&gt; <see cref="CompareResult.Greater"/><br/>
 1047  /// <paramref name="compareResult"/> is 0 =&gt; <see cref="CompareResult.Equal"/>
 1048  /// </returns>
 1049  public static CompareResult ToCompareResult(this int compareResult) =>
 24271050    compareResult switch
 24271051    {
 8431052      < 0 => Less,
 15741053      > 0 => Greater,
 101054      0 => Equal,
 24271055    };
 1056
 1057  #endregion
 1058}

/home/runner/work/Towel/Towel/Sources/Towel/Statics-NumericEnglishWords.cs

#LineLine coverage
 1namespace Towel;
 2
 3/// <summary>Root type of the static functional methods in Towel.</summary>
 4public static partial class Statics
 5{
 16  internal static string[] ToEnglishWordsDigit =
 17  {
 18    /* 0 */ null!,
 19    /* 1 */ "One",
 110    /* 2 */ "Two",
 111    /* 3 */ "Three",
 112    /* 4 */ "Four",
 113    /* 5 */ "Five",
 114    /* 6 */ "Six",
 115    /* 7 */ "Seven",
 116    /* 8 */ "Eight",
 117    /* 9 */ "Nine",
 118  };
 19
 120  internal static string[] ToEnglishWordsFractionalSufix =
 121  {
 122    /*  0 */ null!,
 123    /*  1 */ "Tenths",
 124    /*  2 */ "Hundredths",
 125    /*  3 */ "Thousandths",
 126    /*  4 */ "Ten-Thousandths",
 127    /*  5 */ "Hundred-Thousandths",
 128    /*  6 */ "Millionths",
 129    /*  7 */ "Ten-Millionths",
 130    /*  8 */ "Hundred-Millionths",
 131    /*  9 */ "Billionths",
 132    /* 10 */ "Ten-Billionths",
 133    /* 11 */ "Hundred-Billionths",
 134    /* 12 */ "Trillionths",
 135    /* 13 */ "Ten-Trillionths",
 136    /* 14 */ "Hundred-Trillionths",
 137    /* 15 */ "Quadrillionths",
 138    /* 16 */ "Ten-Quadrillionths",
 139    /* 17 */ "Hundred-Quadrillionths",
 140    /* 18 */ "Quintillionths",
 141    /* 19 */ "Ten-Quintillionths",
 142    /* 20 */ "Hundred-Quintillionths",
 143    /* 21 */ "Sextillionths",
 144    /* 22 */ "Ten-Sextillionths",
 145    /* 23 */ "Hundred-Sextillionths",
 146    /* 24 */ "Septillionths",
 147    /* 25 */ "Ten-Septillionths",
 148    /* 26 */ "Hundred-Septillionths",
 149    /* 27 */ "Octillionths",
 150    /* 28 */ "Ten-Octillionths",
 151    /* 29 */ "Hundred-Octillionths",
 152  };
 53
 154  internal static string[] ToEnglishWordsTen =
 155  {
 156    /* 0 */ null!,
 157    /* 1 */ "Ten",
 158    /* 2 */ "Twenty",
 159    /* 3 */ "Thirty",
 160    /* 4 */ "Forty",
 161    /* 5 */ "Fifty",
 162    /* 6 */ "Sixty",
 163    /* 7 */ "Seventy",
 164    /* 8 */ "Eighty",
 165    /* 9 */ "Ninety",
 166  };
 67
 168  internal static string[] ToEnglishWordsTeen =
 169  {
 170    /* 0 */ null!,
 171    /* 1 */ "Eleven",
 172    /* 2 */ "Twelve",
 173    /* 3 */ "Thirteen",
 174    /* 4 */ "Fourteen",
 175    /* 5 */ "Fifteen",
 176    /* 6 */ "Sixteen",
 177    /* 7 */ "Seventeen",
 178    /* 8 */ "Eighteen",
 179    /* 9 */ "Nineteen",
 180  };
 81
 182  internal static string[] ToEnglishWordsGroup =
 183  {
 184    /*  0 */ null!,
 185    /*  1 */ null!,
 186    /*  2 */ "Thousand",
 187    /*  3 */ "Million",
 188    /*  4 */ "Billion",
 189    /*  5 */ "Trillion",
 190    /*  6 */ "Quadrillion",
 191    /*  7 */ "Quintillion",
 192    /*  8 */ "Sextillion",
 193    /*  9 */ "Septillion",
 194    /* 10 */ "Octillion",
 195  };
 96
 97  internal const int NumberToStringBufferSize = 35;
 98  internal const int EnglishWordsBufferSize = 450;
 99
 100  internal static string ToEnglishWords(ReadOnlySpan<char> number)
 2097094101  {
 2097094102    if (number.Length is 1 && number[0] is '0')
 4103    {
 4104      return "Zero";
 105    }
 2097090106    SpanBuilder<char> span = stackalloc char[EnglishWordsBufferSize];
 2097090107    if (number[0] is '-')
 10047108    {
 10047109      span.Append("Negative");
 10047110      number = number[1..];
 10047111    }
 2097090112    if (number[0] is '0')
 2000060113    {
 2000060114      number = number[1..];
 2000060115    }
 2097090116    int decimalIndex = number.IndexOf('.');
 2097090117    if (decimalIndex >= 0)
 2020074118    {
 2244514119      while (number[^1] is '0')
 224440120      {
 224440121        number = number[..^1];
 224440122      }
 2020074123      if (number.Length - 1 == decimalIndex)
 2124      {
 2125        number = number[..^1];
 2126        decimalIndex = -1;
 2127      }
 2020074128    }
 2097090129    if (number.Length is 0)
 1130    {
 1131      return "Zero";
 132    }
 2097089133    if (decimalIndex is not 0)
 97030134    {
 97030135      ReadOnlySpan<char> wholeNumber = number[..(decimalIndex >= 0 ? decimalIndex : ^0)];
 97030136      WholeNumber(ref span, wholeNumber);
 97030137    }
 2097089138    if (decimalIndex >= 0)
 2020072139    {
 2020072140      if (decimalIndex != 0)
 20013141      {
 20013142        span.Append(" And");
 20013143      }
 2020072144      ReadOnlySpan<char> fractionalNumber = number[(decimalIndex + 1)..];
 2020072145      WholeNumber(ref span, fractionalNumber);
 2020072146      span.Append(' ');
 2020072147      span.Append(ToEnglishWordsFractionalSufix[fractionalNumber.Length]);
 2020072148    }
 2097089149    Span<char> result = span;
 2097089150    return new string(result[(result[0] is ' ' ? 1 : 0)..]);
 2097094151  }
 152
 153  internal static void WholeNumber(ref SpanBuilder<char> span, ReadOnlySpan<char> wholeNumber)
 2117102154  {
 155    // A "digit group" is a set of hundreds + tens + ones digits.
 156    // In the number 123456789 the digit groups are the following: 123, 456, 789
 157    // In the number 12345 the digit groups are the following: 12, 345
 158
 2117102159    int mod3 = wholeNumber.Length % 3;
 2117102160    int digitGroup = wholeNumber.Length / 3 + (mod3 is 0 ? 0 : 1);
 8147223161    while (digitGroup > 0)
 6030121162    {
 6030121163      int i__X = (wholeNumber.Length - (digitGroup - 1) * 3) - 1; // index of ones digit
 6030121164      int i_X_ = i__X - 1;                                        // index of tens digit
 6030121165      int iX__ = i_X_ - 1;                                        // index of hundreds digit
 166
 6030121167      char c__X = wholeNumber[i__X];                   // character of ones digit
 6030121168      char c_X_ = i_X_ >= 0 ? wholeNumber[i_X_] : '0'; // character of tens digit
 6030121169      char cX__ = iX__ >= 0 ? wholeNumber[iX__] : '0'; // character of hundreds digit
 170
 6030121171      if (c__X > '0' || c_X_ > '0' || cX__ > '0')
 5123400172      {
 5123400173        DigitGroup(ref span, cX__, c_X_, c__X);
 5123400174        if (digitGroup > 1)
 3006405175        {
 3006405176          span.Append(' ');
 3006405177          span.Append(ToEnglishWordsGroup[digitGroup]);
 3006405178        }
 5123400179      }
 6030121180      digitGroup--;
 6030121181    }
 2117102182  }
 183
 184  internal static void DigitGroup(ref SpanBuilder<char> span, char hundredsDigit, char tensDigit, char onesDigit)
 5123400185  {
 5123400186    int hundred = hundredsDigit - '0';
 5123400187    int ten = tensDigit - '0';
 5123400188    int one = onesDigit - '0';
 5123400189    if (hundred > 0)
 3684238190    {
 3684238191      span.Append(' ');
 3684238192      span.Append(ToEnglishWordsDigit[hundred]);
 3684238193      span.Append(" Hundred");
 3684238194    }
 5123400195    if (ten > 0)
 3765516196    {
 3765516197      span.Append(' ');
 3765516198      if (one is 0)
 194777199      {
 194777200        span.Append(ToEnglishWordsTen[ten]);
 194777201      }
 3570739202      else if (ten is 1)
 403971203      {
 403971204        span.Append(ToEnglishWordsTeen[one]);
 403971205      }
 206      else
 3166768207      {
 3166768208        span.Append(ToEnglishWordsTen[ten]);
 3166768209        span.Append('-');
 3166768210        span.Append(ToEnglishWordsDigit[one]);
 3166768211      }
 3765516212    }
 1357884213    else if (one > 0)
 1339210214    {
 1339210215      span.Append(' ');
 1339210216      span.Append(ToEnglishWordsDigit[one]);
 1339210217    }
 5123400218  }
 219
 220  /// <summary>Converts a <see cref="byte"/> to the English words <see cref="string"/> representation.</summary>
 221  /// <param name="byte">The <see cref="byte"/> value to convert to English words <see cref="string"/> representation.</
 222  /// <returns>The English words <see cref="string"/> representation of the <see cref="byte"/> value.</returns>
 223  public static string ToEnglishWords(this byte @byte)
 0224  {
 0225    Span<char> span = stackalloc char[NumberToStringBufferSize];
 0226    @byte.TryFormat(span, out int length, provider: System.Globalization.CultureInfo.InvariantCulture);
 0227    return ToEnglishWords(span[..length]);
 0228  }
 229
 230  /// <summary>Converts a <see cref="sbyte"/> to the English words <see cref="string"/> representation.</summary>
 231  /// <param name="sbyte">The <see cref="sbyte"/> value to convert to English words <see cref="string"/> representation.
 232  /// <returns>The English words <see cref="string"/> representation of the <see cref="sbyte"/> value.</returns>
 233  public static string ToEnglishWords(this sbyte @sbyte)
 0234  {
 0235    Span<char> span = stackalloc char[NumberToStringBufferSize];
 0236    @sbyte.TryFormat(span, out int length, provider: System.Globalization.CultureInfo.InvariantCulture);
 0237    return ToEnglishWords(span[..length]);
 0238  }
 239
 240  /// <summary>Converts a <see cref="short"/> to the English words <see cref="string"/> representation.</summary>
 241  /// <param name="short">The <see cref="short"/> value to convert to English words <see cref="string"/> representation.
 242  /// <returns>The English words <see cref="string"/> representation of the <see cref="short"/> value.</returns>
 243  public static string ToEnglishWords(this short @short)
 0244  {
 0245    Span<char> span = stackalloc char[NumberToStringBufferSize];
 0246    @short.TryFormat(span, out int length, provider: System.Globalization.CultureInfo.InvariantCulture);
 0247    return ToEnglishWords(span[..length]);
 0248  }
 249
 250  /// <summary>Converts a <see cref="ushort"/> to the English words <see cref="string"/> representation.</summary>
 251  /// <param name="ushort">The <see cref="ushort"/> value to convert to English words <see cref="string"/> representatio
 252  /// <returns>The English words <see cref="string"/> representation of the <see cref="ushort"/> value.</returns>
 253  public static string ToEnglishWords(this ushort @ushort)
 0254  {
 0255    Span<char> span = stackalloc char[NumberToStringBufferSize];
 0256    @ushort.TryFormat(span, out int length, provider: System.Globalization.CultureInfo.InvariantCulture);
 0257    return ToEnglishWords(span[..length]);
 0258  }
 259
 260  /// <summary>Converts a <see cref="int"/> to the English words <see cref="string"/> representation.</summary>
 261  /// <param name="int">The <see cref="int"/> value to convert to English words <see cref="string"/> representation.</pa
 262  /// <returns>The English words <see cref="string"/> representation of the <see cref="int"/> value.</returns>
 263  public static string ToEnglishWords(this int @int)
 0264  {
 0265    Span<char> span = stackalloc char[NumberToStringBufferSize];
 0266    @int.TryFormat(span, out int length, provider: System.Globalization.CultureInfo.InvariantCulture);
 0267    return ToEnglishWords(span[..length]);
 0268  }
 269
 270  /// <summary>Converts a <see cref="uint"/> to the English words <see cref="string"/> representation.</summary>
 271  /// <param name="uint">The <see cref="uint"/> value to convert to English words <see cref="string"/> representation.</
 272  /// <returns>The English words <see cref="string"/> representation of the <see cref="uint"/> value.</returns>
 273  public static string ToEnglishWords(this uint @uint)
 0274  {
 0275    Span<char> span = stackalloc char[NumberToStringBufferSize];
 0276    @uint.TryFormat(span, out int length, provider: System.Globalization.CultureInfo.InvariantCulture);
 0277    return ToEnglishWords(span[..length]);
 0278  }
 279
 280  /// <summary>Converts a <see cref="long"/> to the English words <see cref="string"/> representation.</summary>
 281  /// <param name="long">The <see cref="long"/> value to convert to English words <see cref="string"/> representation.</
 282  /// <returns>The English words <see cref="string"/> representation of the <see cref="long"/> value.</returns>
 283  public static string ToEnglishWords(this long @long)
 0284  {
 0285    Span<char> span = stackalloc char[NumberToStringBufferSize];
 0286    @long.TryFormat(span, out int length, provider: System.Globalization.CultureInfo.InvariantCulture);
 0287    return ToEnglishWords(span[..length]);
 0288  }
 289
 290  /// <summary>Converts a <see cref="ulong"/> to the English words <see cref="string"/> representation.</summary>
 291  /// <param name="ulong">The <see cref="ulong"/> value to convert to English words <see cref="string"/> representation.
 292  /// <returns>The English words <see cref="string"/> representation of the <see cref="ulong"/> value.</returns>
 293  public static string ToEnglishWords(this ulong @ulong)
 0294  {
 0295    Span<char> span = stackalloc char[NumberToStringBufferSize];
 0296    @ulong.TryFormat(span, out int length, provider: System.Globalization.CultureInfo.InvariantCulture);
 0297    return ToEnglishWords(span[..length]);
 0298  }
 299
 300  /// <summary>Converts a <see cref="decimal"/> to the English words <see cref="string"/> representation.</summary>
 301  /// <param name="decimal">The <see cref="decimal"/> value to convert to English words <see cref="string"/> representat
 302  /// <returns>The English words <see cref="string"/> representation of the <see cref="ulong"/> value.</returns>
 303  public static string ToEnglishWords(this decimal @decimal)
 2097094304  {
 2097094305    Span<char> span = stackalloc char[NumberToStringBufferSize];
 2097094306    @decimal.TryFormat(span, out int length, provider: System.Globalization.CultureInfo.InvariantCulture);
 2097094307    return ToEnglishWords(span[..length]);
 2097094308  }
 309
 310  internal interface ITryParseReadOnlySpan<T>
 311  {
 312    (bool Success, T Value) TryParse(ReadOnlySpan<char> span);
 313  }
 314
 315#pragma warning disable IDE1006 // Naming Styles
 316
 317  internal struct decimal_TryParse : ITryParseReadOnlySpan<decimal>
 318  {
 2097091319    public (bool, decimal) TryParse(ReadOnlySpan<char> span) => (decimal.TryParse(span, out decimal result), result);
 320  }
 321
 322  /// <inheritdoc cref="TryParseEnglishWords{T, TTryParse}(ReadOnlySpan{char})" />
 323  public static (bool Success, decimal Value) TryParseEnglishWordsToDecimal(ReadOnlySpan<char> span) =>
 2097134324    TryParseEnglishWords<decimal, decimal_TryParse>(span);
 325
 326  internal struct long_TryParse : ITryParseReadOnlySpan<long>
 327  {
 0328    public (bool, long) TryParse(ReadOnlySpan<char> span) => (long.TryParse(span, out long result), result);
 329  }
 330
 331  /// <inheritdoc cref="TryParseEnglishWords{T, TTryParse}(ReadOnlySpan{char})" />
 332  public static (bool Success, long Value) TryParseEnglishWordsToLong(ReadOnlySpan<char> span) =>
 0333    TryParseEnglishWords<long, long_TryParse>(span);
 334
 335  internal struct ulong_TryParse : ITryParseReadOnlySpan<ulong>
 336  {
 0337    public (bool, ulong) TryParse(ReadOnlySpan<char> span) => (ulong.TryParse(span, out ulong result), result);
 338  }
 339
 340  /// <inheritdoc cref="TryParseEnglishWords{T, TTryParse}(ReadOnlySpan{char})" />
 341  public static (bool Success, ulong Value) TryParseEnglishWordsToUlong(ReadOnlySpan<char> span) =>
 0342    TryParseEnglishWords<ulong, ulong_TryParse>(span);
 343
 344  internal struct int_TryParse : ITryParseReadOnlySpan<int>
 345  {
 0346    public (bool, int) TryParse(ReadOnlySpan<char> span) => (int.TryParse(span, out int result), result);
 347  }
 348
 349  /// <inheritdoc cref="TryParseEnglishWords{T, TTryParse}(ReadOnlySpan{char})" />
 350  public static (bool Success, int Value) TryParseEnglishWordsToInt(ReadOnlySpan<char> span) =>
 0351    TryParseEnglishWords<int, int_TryParse>(span);
 352
 353  internal struct uint_TryParse : ITryParseReadOnlySpan<uint>
 354  {
 0355    public (bool, uint) TryParse(ReadOnlySpan<char> span) => (uint.TryParse(span, out uint result), result);
 356  }
 357
 358  /// <inheritdoc cref="TryParseEnglishWords{T, TTryParse}(ReadOnlySpan{char})" />
 359  public static (bool Success, uint Value) TryParseEnglishWordsToUint(ReadOnlySpan<char> span) =>
 0360    TryParseEnglishWords<uint, uint_TryParse>(span);
 361
 362  internal struct short_TryParse : ITryParseReadOnlySpan<short>
 363  {
 0364    public (bool, short) TryParse(ReadOnlySpan<char> span) => (short.TryParse(span, out short result), result);
 365  }
 366
 367  /// <inheritdoc cref="TryParseEnglishWords{T, TTryParse}(ReadOnlySpan{char})" />
 368  public static (bool Success, short Value) TryParseEnglishWordsToShort(ReadOnlySpan<char> span) =>
 0369    TryParseEnglishWords<short, short_TryParse>(span);
 370
 371  internal struct ushort_TryParse : ITryParseReadOnlySpan<ushort>
 372  {
 0373    public (bool, ushort) TryParse(ReadOnlySpan<char> span) => (ushort.TryParse(span, out ushort result), result);
 374  }
 375
 376  /// <inheritdoc cref="TryParseEnglishWords{T, TTryParse}(ReadOnlySpan{char})" />
 377  public static (bool Success, ushort Value) TryParseEnglishWordsToUshort(ReadOnlySpan<char> span) =>
 0378    TryParseEnglishWords<ushort, ushort_TryParse>(span);
 379
 380  internal struct byte_TryParse : ITryParseReadOnlySpan<byte>
 381  {
 0382    public (bool, byte) TryParse(ReadOnlySpan<char> span) => (byte.TryParse(span, out byte result), result);
 383  }
 384
 385  /// <inheritdoc cref="TryParseEnglishWords{T, TTryParse}(ReadOnlySpan{char})" />
 386  public static (bool Success, byte Value) TryParseEnglishWordsToByte(ReadOnlySpan<char> span) =>
 0387    TryParseEnglishWords<byte, byte_TryParse>(span);
 388
 389  internal struct sbyte_TryParse : ITryParseReadOnlySpan<sbyte>
 390  {
 0391    public (bool, sbyte) TryParse(ReadOnlySpan<char> span) => (sbyte.TryParse(span, out sbyte result), result);
 392  }
 393
 394  /// <inheritdoc cref="TryParseEnglishWords{T, TTryParse}(ReadOnlySpan{char})" />
 395  public static (bool Success, sbyte Value) TryParseEnglishWordsToSbyte(ReadOnlySpan<char> span) =>
 0396    TryParseEnglishWords<sbyte, sbyte_TryParse>(span);
 397
 398#pragma warning restore IDE1006 // Naming Styles
 399
 400  /// <summary>Attempts to parse a string of English words to a numeric value.</summary>
 401  /// <typeparam name="T">The numerical type to parse the string into.</typeparam>
 402  /// <typeparam name="TTryParse">The type of tryparse function for the numeric type.</typeparam>
 403  /// <param name="span">The span to attempt to parse.</param>
 404  /// <returns>True and the value if successful or False and default if not.</returns>
 405  internal static (bool Success, T? Value) TryParseEnglishWords<T, TTryParse>(ReadOnlySpan<char> span)
 406    where TTryParse : struct, ITryParseReadOnlySpan<T>
 2097134407  {
 408
 409#warning TODO: clean this code up :P
 410
 411    const string Negative = "Negative ";
 412    const string Zero = "Zero";
 413    const string Hundred = "Hundred";
 414    const string And = "And ";
 415
 2097134416    Span<char> digits = stackalloc char[35];
 2097134417    int digits_i = 0;
 418
 2097134419    Span<char> fractionalDigits = stackalloc char[35];
 2097134420    int fractionalDigits_i = 0;
 421
 2097134422    bool parsingFraction = false;
 2097134423    int? previousDigitGroup = null;
 424
 2097134425    if (span.StartsWith(Zero))
 5426    {
 5427      return (true, default);
 428    }
 2097129429    if (span.StartsWith(Negative))
 10047430    {
 10047431      digits[digits_i++] = '-';
 10047432      span = span[Negative.Length..];
 10047433    }
 7220547434    while (!span.IsEmpty)
 5123456435    {
 5123456436      char a = '0';
 5123456437      char b = '0';
 5123456438      char c = '0';
 5123456439      int? fractionalSuffix = null;
 5123456440      int digitGroup = 1;
 441
 5123456442      char? tempTeens = GetTeensDigit(ref span);
 5123456443      if (tempTeens is not null)
 54212444      {
 54212445        if (b is not '0' || c is not '0')
 0446        {
 0447          return (false, default);
 448        }
 54212449        if (span.Length > 0)
 53506450        {
 53506451          if (span[0] is not ' ')
 1452          {
 1453            return (false, default);
 454          }
 455          else
 53505456          {
 53505457            span = span[1..];
 53505458            if (span.Length is 0)
 0459            {
 0460              return (false, default);
 461            }
 53505462          }
 53505463        }
 54211464        b = '1';
 54211465        c = tempTeens.Value;
 54211466      }
 467
 5123455468      if (c is '0')
 5069244469      {
 5069244470        char? temp2 = GetNextTensDigit(ref span);
 5069244471        if (temp2 is not null)
 395510472        {
 395510473          b = temp2.Value;
 395510474          if (span.Length > 0)
 394806475          {
 394806476            if (span[0] is '-')
 368717477            {
 368717478              span = span[1..];
 368717479              char? temp3 = GetNextDigit(ref span);
 368717480              if (temp3 is null)
 2481              {
 2482                return (false, default);
 483              }
 484              else
 368715485              {
 368715486                if (span.Length > 0)
 363167487                {
 363167488                  if (span[0] is not ' ')
 1489                  {
 1490                    return (false, default);
 491                  }
 492                  else
 363166493                  {
 363166494                    span = span[1..];
 363166495                    if (span.Length is 0)
 1496                    {
 1497                      return (false, default);
 498                    }
 363165499                  }
 363165500                }
 368713501                c = temp3.Value;
 368713502              }
 368713503            }
 26089504            else if (span.Length > 0)
 26089505            {
 26089506              if (span[0] is not ' ')
 1507              {
 1508                return (false, default);
 509              }
 510              else
 26088511              {
 26088512                span = span[1..];
 26088513                if (span.Length is 0)
 0514                {
 0515                  return (false, default);
 516                }
 26088517              }
 26088518            }
 394801519          }
 395505520        }
 5069239521      }
 522
 5123450523      if (a is '0' && b is '0' && c is '0')
 4673734524      {
 4673734525        char? temp1 = GetNextDigit(ref span);
 4673734526        if (temp1 is not null)
 4673730527        {
 4673730528          if (span.Length > 0)
 4673008529          {
 4673008530            if (span[0] is not ' ')
 5531            {
 5532              return (false, default);
 533            }
 534            else
 4673003535            {
 4673003536              span = span[1..];
 4673003537              if (span.Length is 0)
 3538              {
 3539                return (false, default);
 540              }
 4673000541            }
 4673000542            fractionalSuffix ??= GetNextFractionalSuffix(ref span);
 4673000543            if (fractionalSuffix is not null)
 20329544            {
 20329545              c = temp1.Value;
 20329546              goto FractionalSuffix;
 547            }
 4652671548            if (span.StartsWith(Hundred))
 3684243549            {
 3684243550              a = temp1.Value;
 3684243551              span = span[Hundred.Length..];
 3684243552              if (span.Length > 0)
 3683544553              {
 3683544554                if (span[0] is not ' ')
 1555                {
 1556                  return (false, default);
 557                }
 558                else
 3683543559                {
 3683543560                  span = span[1..];
 3683543561                  if (span.Length is 0)
 1562                  {
 1563                    return (false, default);
 564                  }
 3683542565                }
 3683542566              }
 3684241567            }
 568            else
 968428569            {
 968428570              c = temp1.Value;
 968428571            }
 4652669572          }
 573          else
 722574          {
 722575            c = temp1.Value;
 722576          }
 4653391577        }
 4653395578      }
 5103111579      if (b is '0' && c is '0')
 3684245580      {
 3684245581        char? tempTeens2 = GetTeensDigit(ref span);
 3684245582        if (tempTeens2 is not null)
 349762583        {
 349762584          if (b is not '0' || c is not '0')
 0585          {
 0586            return (false, default);
 587          }
 349762588          if (span.Length > 0)
 343526589          {
 343526590            if (span[0] is not ' ')
 0591            {
 0592              return (false, default);
 593            }
 594            else
 343526595            {
 343526596              span = span[1..];
 343526597              if (span.Length is 0)
 0598              {
 0599                return (false, default);
 600              }
 343526601            }
 343526602          }
 349762603          b = '1';
 349762604          c = tempTeens2.Value;
 349762605        }
 3684245606      }
 5103111607      if (b is '0' && c is '0')
 3334483608      {
 3334483609        char? temp2 = GetNextTensDigit(ref span);
 3334483610        if (temp2 is not null)
 2966041611        {
 2966041612          b = temp2.Value;
 2966041613          if (span.Length > 0)
 2959808614          {
 2959808615            if (span[0] is '-')
 2798055616            {
 2798055617              span = span[1..];
 2798055618              char? temp3 = GetNextDigit(ref span);
 2798055619              if (temp3 is null)
 0620              {
 0621                return (false, default);
 622              }
 623              else
 2798055624              {
 2798055625                if (span.Length > 0)
 2748205626                {
 2748205627                  if (span[0] is not ' ')
 0628                  {
 0629                    return (false, default);
 630                  }
 631                  else
 2748205632                  {
 2748205633                    span = span[1..];
 2748205634                    if (span.Length is 0)
 0635                    {
 0636                      return (false, default);
 637                    }
 2748205638                  }
 2748205639                }
 2798055640                c = temp3.Value;
 2798055641              }
 2798055642            }
 161753643            else if (span.Length > 0)
 161753644            {
 161753645              if (span[0] is not ' ')
 0646              {
 0647                return (false, default);
 648              }
 649              else
 161753650              {
 161753651                span = span[1..];
 161753652                if (span.Length is 0)
 0653                {
 0654                  return (false, default);
 655                }
 161753656              }
 161753657            }
 2959808658          }
 2966041659        }
 3334483660      }
 5103111661      if (b is '0' && c is '0')
 368442662      {
 368442663        char? temp3 = GetNextDigit(ref span);
 368442664        if (temp3 is not null)
 349764665        {
 349764666          c = temp3.Value;
 349764667          if (span.Length > 0)
 343527668          {
 343527669            if (span[0] is not ' ')
 0670            {
 0671              return (false, default);
 672            }
 673            else
 343527674            {
 343527675              span = span[1..];
 343527676              if (span.Length is 0)
 1677              {
 1678                return (false, default);
 679              }
 343526680            }
 343526681          }
 349763682        }
 368441683      }
 684
 5103110685      if (span.Length > 0)
 5026175686      {
 5026175687        fractionalSuffix ??= GetNextFractionalSuffix(ref span);
 5026175688        if (fractionalSuffix is not null)
 1999749689        {
 1999749690          goto FractionalSuffix;
 691        }
 3026426692        int? explicitDigitGroup = GetNextExplicitDigitGroup(ref span);
 3026426693        if (explicitDigitGroup is not null)
 3006413694        {
 3006413695          digitGroup = explicitDigitGroup.Value;
 3006413696          if (span.Length > 0)
 3006322697          {
 3006322698            if (span[0] is not ' ')
 1699            {
 1700              return (false, default);
 701            }
 702            else
 3006321703            {
 3006321704              span = span[1..];
 3006321705              if (span.Length is 0)
 1706              {
 1707                return (false, default);
 708              }
 3006320709            }
 3006320710          }
 3006411711        }
 3026424712      }
 713
 5123437714    FractionalSuffix:
 715
 5123437716      if (!parsingFraction)
 5087219717      {
 5087219718        if (previousDigitGroup is not null)
 2990109719        {
 2990109720          int digitGroupDifference = previousDigitGroup.Value - digitGroup;
 2990109721          if (digitGroupDifference < 1)
 11722          {
 11723            return (false, default);
 724          }
 5982084725          for (int j = 1; j < digitGroupDifference; j++)
 944726          {
 944727            digits[digits_i++] = '0';
 944728            digits[digits_i++] = '0';
 944729            digits[digits_i++] = '0';
 944730          }
 2990098731        }
 5087208732        if (previousDigitGroup is not null || a is not '0')
 3964547733        {
 3964547734          digits[digits_i++] = a;
 3964547735        }
 5087208736        if (previousDigitGroup is not null || b is not '0' || a is not '0')
 4143119737        {
 4143119738          digits[digits_i++] = b;
 4143119739        }
 5087208740        digits[digits_i++] = c;
 5087208741      }
 742      else
 36218743      {
 36218744        if (previousDigitGroup is not null)
 16201745        {
 16201746          int digitGroupDifference = previousDigitGroup.Value - digitGroup;
 16201747          if (digitGroupDifference < 1)
 1748          {
 1749            return (false, default);
 750          }
 32400751          for (int j = 1; j < digitGroupDifference; j++)
 0752          {
 0753            fractionalDigits[fractionalDigits_i++] = '0';
 0754            fractionalDigits[fractionalDigits_i++] = '0';
 0755            fractionalDigits[fractionalDigits_i++] = '0';
 0756          }
 16200757        }
 36217758        if (previousDigitGroup is not null || a is not '0')
 19443759        {
 19443760          fractionalDigits[fractionalDigits_i++] = a;
 19443761        }
 36217762        if (previousDigitGroup is not null || b is not '0' || a is not '0')
 19929763        {
 19929764          fractionalDigits[fractionalDigits_i++] = b;
 19929765        }
 36217766        fractionalDigits[fractionalDigits_i++] = c;
 36217767      }
 5123425768      previousDigitGroup = digitGroup;
 5123425769      if (span.StartsWith(And))
 20018770      {
 20018771        if (fractionalSuffix is not null)
 0772        {
 0773          return (false, default);
 774        }
 20018775        if (parsingFraction)
 1776        {
 1777          return (false, default);
 778        }
 20017779        if (previousDigitGroup is not null)
 20017780        {
 40070781          for (int j = previousDigitGroup.Value; j > 1; j--)
 18782          {
 18783            digits[digits_i++] = '0';
 18784            digits[digits_i++] = '0';
 18785            digits[digits_i++] = '0';
 18786          }
 20017787        }
 20017788        digits[digits_i++] = '.';
 20017789        previousDigitGroup = null;
 20017790        parsingFraction = true;
 20017791        span = span[And.Length..];
 20017792      }
 793
 5123424794      fractionalSuffix ??= GetNextFractionalSuffix(ref span);
 5123424795      if (fractionalSuffix is not null)
 2020078796      {
 2020078797        if (span.Length > 0)
 6798        {
 6799          return (false, default);
 800        }
 2020072801        if (parsingFraction)
 20013802        {
 44462803          for (int i = 0; i < fractionalSuffix.Value - fractionalDigits_i; i++)
 2218804          {
 2218805            digits[digits_i++] = '0';
 2218806          }
 20013807          fractionalDigits[..fractionalDigits_i].CopyTo(digits[digits_i..(digits_i + fractionalDigits_i)]);
 20013808          digits_i += fractionalDigits_i;
 20013809        }
 810        else
 2000059811        {
 2000059812          bool isNegative = digits[0] is '-';
 2000059813          int offset = fractionalSuffix.Value - (isNegative ? digits_i - 1 : digits_i);
 814          int i;
 29333644815          for (i = digits_i + 1; i >= 2 && digits[i - 2] is not '-'; i--)
 12666763816          {
 12666763817            digits[i + offset] = digits[i - 2];
 12666763818          }
 6223846819          for (int j = 0; j < offset; j++)
 1111864820          {
 1111864821            digits[(isNegative ? 3 : 2) + j] = '0';
 1111864822          }
 2000059823          digits[isNegative ? 2 : 1] = '.';
 2000059824          digits[isNegative ? 1 : 0] = '0';
 2000059825          digits_i += 2 + offset;
 2000059826        }
 2020072827      }
 5123418828    }
 2097091829    if (previousDigitGroup is not null)
 2097089830    {
 4194428831      for (int j = 1; j < previousDigitGroup.Value; j++)
 125832      {
 125833        digits[digits_i++] = '0';
 125834        digits[digits_i++] = '0';
 125835        digits[digits_i++] = '0';
 125836      }
 2097089837    }
 2097091838    return default(TTryParse).TryParse(digits[..digits_i]);
 2097134839  }
 840
 841#pragma warning disable SA1501 // Statement should not be on a single line
 842
 843  internal static char? GetNextDigit(ref ReadOnlySpan<char> span)
 8208948844  {
 845    const string One   = "One";
 846    const string Two   = "Two";
 847    const string Three = "Three";
 848    const string Four  = "Four";
 849    const string Five  = "Five";
 850    const string Six   = "Six";
 851    const string Seven = "Seven";
 852    const string Eight = "Eight";
 853    const string Nine  = "Nine";
 854
 13582212855    if (span.StartsWith(One))   { span = span[One.Length..];   return '1'; }
 8817599856    if (span.StartsWith(Two))   { span = span[Two.Length..];   return '2'; }
 8017659857    if (span.StartsWith(Three)) { span = span[Three.Length..]; return '3'; }
 7217722858    if (span.StartsWith(Four))  { span = span[Four.Length..];  return '4'; }
 6417844859    if (span.StartsWith(Five))  { span = span[Five.Length..];  return '5'; }
 5617934860    if (span.StartsWith(Six))   { span = span[Six.Length..];   return '6'; }
 4818028861    if (span.StartsWith(Seven)) { span = span[Seven.Length..]; return '7'; }
 4018144862    if (span.StartsWith(Eight)) { span = span[Eight.Length..]; return '8'; }
 3218252863    if (span.StartsWith(Nine))  { span = span[Nine.Length..];  return '9'; }
 864
 18684865    return null;
 8208948866  }
 867
 868  internal static char? GetTeensDigit(ref ReadOnlySpan<char> span)
 8807701869  {
 870    const string Eleven    = "Eleven";
 871    const string Twelve    = "Twelve";
 872    const string Thirteen  = "Thirteen";
 873    const string Fourteen  = "Fourteen";
 874    const string Fifteen   = "Fifteen";
 875    const string Sixteen   = "Sixteen";
 876    const string Seventeen = "Seventeen";
 877    const string Eighteen  = "Eighteen";
 878    const string Nineteen  = "Nineteen";
 879
 8942389880    if (span.StartsWith(Eleven))    { span = span[Eleven.Length..];    return '1'; }
 8897457881    if (span.StartsWith(Twelve))    { span = span[Twelve.Length..];    return '2'; }
 8852579882    if (span.StartsWith(Thirteen))  { span = span[Thirteen.Length..];  return '3'; }
 8807693883    if (span.StartsWith(Fourteen))  { span = span[Fourteen.Length..];  return '4'; }
 8762801884    if (span.StartsWith(Fifteen))   { span = span[Fifteen.Length..];   return '5'; }
 8717917885    if (span.StartsWith(Sixteen))   { span = span[Sixteen.Length..];   return '6'; }
 8673039886    if (span.StartsWith(Seventeen)) { span = span[Seventeen.Length..]; return '7'; }
 8628147887    if (span.StartsWith(Eighteen))  { span = span[Eighteen.Length..];  return '8'; }
 8583263888    if (span.StartsWith(Nineteen))  { span = span[Nineteen.Length..];  return '9'; }
 889
 8403727890    return null;
 8807701891  }
 892
 893  internal static char? GetNextTensDigit(ref ReadOnlySpan<char> span)
 8403727894  {
 895    const string Ten     = "Ten";
 896    const string Twenty  = "Twenty";
 897    const string Thirty  = "Thirty";
 898    const string Forty   = "Forty";
 899    const string Fifty   = "Fifty";
 900    const string Sixty   = "Sixty";
 901    const string Seventy = "Seventy";
 902    const string Eighty  = "Eighty";
 903    const string Ninety  = "Ninety";
 904
 8471092905    if (span.StartsWith(Ten))     { span = span[Ten.Length..];     return '1'; }
 9633472906    if (span.StartsWith(Twenty))  { span = span[Twenty.Length..];  return '2'; }
 9216039907    if (span.StartsWith(Thirty))  { span = span[Thirty.Length..];  return '3'; }
 8798638908    if (span.StartsWith(Forty))   { span = span[Forty.Length..];   return '4'; }
 8381250909    if (span.StartsWith(Fifty))   { span = span[Fifty.Length..];   return '5'; }
 7963878910    if (span.StartsWith(Sixty))   { span = span[Sixty.Length..];   return '6'; }
 7546478911    if (span.StartsWith(Seventy)) { span = span[Seventy.Length..]; return '7'; }
 7129088912    if (span.StartsWith(Eighty))  { span = span[Eighty.Length..];  return '8'; }
 6711712913    if (span.StartsWith(Ninety))  { span = span[Ninety.Length..];  return '9'; }
 914
 5042176915    return null;
 8403727916  }
 917
 918  internal static int? GetNextExplicitDigitGroup(ref ReadOnlySpan<char> span)
 3026426919  {
 920    const string Thousand    = "Thousand";
 921    const string Million     = "Million";
 922    const string Billion     = "Billion";
 923    const string Trillion    = "Trillion";
 924    const string Quadrillion = "Quadrillion";
 925    const string Quintillion = "Quintillion";
 926    const string Sextillion  = "Sextillion";
 927    const string Septillion  = "Septillion";
 928    const string Octillion   = "Octillion";
 929
 9345563930    if (span.StartsWith(Thousand))    { span = span[Thousand.Length..];    return 2; }
 3620062931    if (span.StartsWith(Million))     { span = span[Million.Length..];     return 3; }
 20054932    if (span.StartsWith(Billion))     { span = span[Billion.Length..];     return 4; }
 20050933    if (span.StartsWith(Trillion))    { span = span[Trillion.Length..];    return 5; }
 20046934    if (span.StartsWith(Quadrillion)) { span = span[Quadrillion.Length..]; return 6; }
 20042935    if (span.StartsWith(Quintillion)) { span = span[Quintillion.Length..]; return 7; }
 20038936    if (span.StartsWith(Sextillion))  { span = span[Sextillion.Length..];  return 8; }
 20034937    if (span.StartsWith(Septillion))  { span = span[Septillion.Length..];  return 9; }
 20033938    if (span.StartsWith(Octillion))   { span = span[Octillion.Length..];   return 10; }
 939
 20013940    return null;
 3026426941  }
 942
 943  internal static int? GetNextFractionalSuffix(ref ReadOnlySpan<char> span)
 12802521944  {
 945    const string Tenths = "Tenths";
 946    const string Hundredths = "Hundredths";
 947    const string Thousandths = "Thousandths";
 948    const string Ten_Thousandths = "Ten-Thousandths";
 949    const string Hundred_Thousandths = "Hundred-Thousandths";
 950    const string Millionths = "Millionths";
 951    const string Ten_Millionths = "Ten-Millionths";
 952    const string Hundred_Millionths = "Hundred-Millionths";
 953    const string Billionths = "Billionths";
 954    const string Ten_Billionths = "Ten-Billionths";
 955    const string Hundred_Billionths = "Hundred-Billionths";
 956    const string Trillionths = "Trillionths";
 957    const string Ten_Trillionths = "Ten-Trillionths";
 958    const string Hundred_Trillionths = "Hundred-Trillionths";
 959    const string Quadrillionths = "Quadrillionths";
 960    const string Ten_Quadrillionths = "Ten-Quadrillionths";
 961    const string Hundred_Quadrillionths = "Hundred-Quadrillionths";
 962    const string Quintrillionths = "Quintillionths";
 963    const string Ten_Quintrillionths = "Ten-Quintillionths";
 964    const string Hundred_Quintrillionths = "Hundred-Quintillionths";
 965    const string Sextillionths = "Sextillionths";
 966    const string Ten_Sextillionths = "Ten-Sextillionths";
 967    const string Hundred_Sextillionths = "Hundred-Sextillionths";
 968    const string Septillionths = "Septillionths";
 969    const string Ten_Septillionths = "Ten-Septillionths";
 970    const string Hundred_Septillionths = "Hundred-Septillionths";
 971    const string Octillionths = "Octillionths";
 972    const string Ten_Octillionths = "Ten-Octillionths";
 973    const string Hundred_Octillionths = "Hundred-Octillionths";
 974
 12802620975    if (span.StartsWith(Tenths))                  { span = span[Tenths.Length..];                  return  1; }
 12803112976    if (span.StartsWith(Hundredths))              { span = span[Hundredths.Length..];              return  2; }
 12808235977    if (span.StartsWith(Thousandths))             { span = span[Thousandths.Length..];             return  3; }
 12859704978    if (span.StartsWith(Ten_Thousandths))         { span = span[Ten_Thousandths.Length..];         return  4; }
 12834498979    if (span.StartsWith(Hundred_Thousandths))     { span = span[Hundred_Thousandths.Length..];     return  5; }
 13302496980    if (span.StartsWith(Millionths))              { span = span[Millionths.Length..];              return  6; }
 17982494981    if (span.StartsWith(Ten_Millionths))          { span = span[Ten_Millionths.Length..];          return  7; }
 10782492982    if (span.StartsWith(Hundred_Millionths))      { span = span[Hundred_Millionths.Length..];      return  8; }
 10782490983    if (span.StartsWith(Billionths))              { span = span[Billionths.Length..];              return  9; }
 10782488984    if (span.StartsWith(Ten_Billionths))          { span = span[Ten_Billionths.Length..];          return 10; }
 10782486985    if (span.StartsWith(Hundred_Billionths))      { span = span[Hundred_Billionths.Length..];      return 11; }
 10782484986    if (span.StartsWith(Trillionths))             { span = span[Trillionths.Length..];             return 12; }
 10782482987    if (span.StartsWith(Ten_Trillionths))         { span = span[Ten_Trillionths.Length..];         return 13; }
 10782480988    if (span.StartsWith(Hundred_Trillionths))     { span = span[Hundred_Trillionths.Length..];     return 14; }
 10782478989    if (span.StartsWith(Quadrillionths))          { span = span[Quadrillionths.Length..];          return 15; }
 10782476990    if (span.StartsWith(Ten_Quadrillionths))      { span = span[Ten_Quadrillionths.Length..];      return 16; }
 10782474991    if (span.StartsWith(Hundred_Quadrillionths))  { span = span[Hundred_Quadrillionths.Length..];  return 17; }
 10782472992    if (span.StartsWith(Quintrillionths))         { span = span[Quintrillionths.Length..];         return 18; }
 10782470993    if (span.StartsWith(Ten_Quintrillionths))     { span = span[Ten_Quintrillionths.Length..];     return 19; }
 10782468994    if (span.StartsWith(Hundred_Quintrillionths)) { span = span[Hundred_Quintrillionths.Length..]; return 20; }
 10782466995    if (span.StartsWith(Sextillionths))           { span = span[Sextillionths.Length..];           return 21; }
 10782464996    if (span.StartsWith(Ten_Sextillionths))       { span = span[Ten_Sextillionths.Length..];       return 22; }
 10782462997    if (span.StartsWith(Hundred_Sextillionths))   { span = span[Hundred_Sextillionths.Length..];   return 23; }
 10782460998    if (span.StartsWith(Septillionths))           { span = span[Septillionths.Length..];           return 24; }
 10782458999    if (span.StartsWith(Ten_Septillionths))       { span = span[Ten_Septillionths.Length..];       return 25; }
 107824561000    if (span.StartsWith(Hundred_Septillionths))   { span = span[Hundred_Septillionths.Length..];   return 26; }
 107824541001    if (span.StartsWith(Octillionths))            { span = span[Octillionths.Length..];            return 27; }
 107824551002    if (span.StartsWith(Ten_Octillionths))        { span = span[Ten_Octillionths.Length..];        return 28; }
 107824431003    if (span.StartsWith(Hundred_Octillionths))    { span = span[Hundred_Octillionths.Length..];    return 29; }
 1004
 107824431005    return null;
 128025211006  }
 1007
 1008#pragma warning restore SA1501 // Statement should not be on a single line
 1009}

/home/runner/work/Towel/Towel/Sources/Towel/Statics-Permutations.cs

#LineLine coverage
 1namespace Towel;
 2
 3/// <summary>Root type of the static functional methods in Towel.</summary>
 4public static partial class Statics
 5{
 6#pragma warning disable CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name
 7#pragma warning disable CS1572 // XML comment has a param tag, but there is no parameter by that name
 8#pragma warning disable SA1604 // Element documentation should have summary
 9
 10  /// <typeparam name="T">The generic element type of the indexed collection.</typeparam>
 11  /// <typeparam name="TAction">The type of action to perform on each permutation.</typeparam>
 12  /// <typeparam name="TStatus">The type of status checker for cancellation.</typeparam>
 13  /// <typeparam name="TGet">The type of get index operation of the collection.</typeparam>
 14  /// <typeparam name="TSet">The type of set index operation of the collection.</typeparam>
 15  /// <param name="start">The starting index of the values to permute.</param>
 16  /// <param name="end">The ending index of the values to permute.</param>
 17  /// <param name="action">The action to perform on each permutation.</param>
 18  /// <param name="status">The status checker for cancellation.</param>
 19  /// <param name="get">The get index operation of the collection.</param>
 20  /// <param name="set">The set index operation of the collection.</param>
 21  /// <param name="array">The array to iterate the permutations of.</param>
 22  /// <param name="list">The list to iterate the permutations of.</param>
 23  /// <param name="span">The span of the permutation.</param>
 24  [Obsolete(NotIntended, true)]
 125  public static void XML_Permute() => throw new DocumentationMethodException();
 26
 27#pragma warning restore SA1604 // Element documentation should have summary
 28
 29  /// <summary>Iterates through all the permutations of an indexed collection (using a recursive algorithm).</summary>
 30  /// <inheritdoc cref="XML_Permute"/>
 31  [Obsolete(NotIntended, true)]
 132  public static void XML_PermuteRecursive() => throw new DocumentationMethodException();
 33
 34  /// <summary>Iterates through all the permutations of an indexed collection (using an iterative algorithm).</summary>
 35  /// <inheritdoc cref="XML_Permute"/>
 36  [Obsolete(NotIntended, true)]
 137  public static void XML_PermuteIterative() => throw new DocumentationMethodException();
 38
 39#pragma warning restore CS1572 // XML comment has a param tag, but there is no parameter by that name
 40#pragma warning restore CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name
 41
 42  /// <inheritdoc cref="XML_PermuteRecursive"/>
 43  public static void PermuteRecursive<T>(int start, int end, Action action, Func<int, T> get, Action<int, T> set) =>
 444    PermuteRecursive<T, SAction, StepStatusContinue, SFunc<int, T>, SAction<int, T>>(start, end, action, default, get, s
 45
 46  /// <inheritdoc cref="XML_PermuteRecursive"/>
 47  public static void PermuteRecursive<T>(int start, int end, Action action, Func<StepStatus> status, Func<int, T> get, A
 048    PermuteRecursive<T, SAction, SFunc<StepStatus>, SFunc<int, T>, SAction<int, T>>(start, end, action, status, get, set
 49
 50  /// <inheritdoc cref="XML_PermuteRecursive"/>
 51  public static void PermuteRecursive<T, TAction, TGet, TSet>(int start, int end, TAction action = default, TGet get = d
 52    where TAction : struct, IAction
 53    where TGet : struct, IFunc<int, T>
 54    where TSet : struct, IAction<int, T> =>
 055    PermuteRecursive<T, TAction, StepStatusContinue, TGet, TSet>(start, end, action, default, get, set);
 56
 57  /// <inheritdoc cref="XML_PermuteRecursive"/>
 58  public static void PermuteRecursive<T, TAction, TStatus, TGet, TSet>(int start, int end, TAction action = default, TSt
 59    where TAction : struct, IAction
 60    where TStatus : struct, IFunc<StepStatus>
 61    where TGet : struct, IFunc<int, T>
 62    where TSet : struct, IAction<int, T>
 463  {
 464    Permute(start, end);
 65    StepStatus Permute(int a, int b)
 5566    {
 5567      if (a == b)
 3368      {
 3369        action.Invoke();
 3370        return status.Invoke();
 71      }
 14672      for (int i = a; i <= b; i++)
 5173      {
 5174        Swap<T, TGet, TSet>(a, i, get, set);
 5175        if (Permute(a + 1, b) is Break)
 076        {
 077          return Break;
 78        }
 5179        Swap<T, TGet, TSet>(a, i, get, set);
 5180      }
 2281      return Continue;
 5582    }
 483  }
 84
 85  /// <inheritdoc cref="XML_PermuteRecursive"/>
 86  public static void PermuteRecursive<T>(Span<T> span, Action action) =>
 487    PermuteRecursive<T, SAction, StepStatusContinue>(span, action);
 88
 89  /// <inheritdoc cref="XML_PermuteRecursive"/>
 90  public static void PermuteRecursive<T, TAction>(Span<T> span, TAction action = default)
 91    where TAction : struct, IAction =>
 092    PermuteRecursive<T, TAction, StepStatusContinue>(span, action);
 93
 94  /// <inheritdoc cref="XML_PermuteRecursive"/>
 95  public static void PermuteRecursive<T, TStatus>(Span<T> span, Action action, TStatus status = default)
 96    where TStatus : struct, IFunc<StepStatus> =>
 097    PermuteRecursive<T, SAction, TStatus>(span, action, status);
 98
 99  /// <inheritdoc cref="XML_PermuteRecursive"/>
 100  public static void PermuteRecursive<T, TAction, TStatus>(Span<T> span, TAction action = default, TStatus status = defa
 101    where TAction : struct, IAction
 102    where TStatus : struct, IFunc<StepStatus>
 4103  {
 4104    Permute(span, 0, span.Length - 1);
 105    StepStatus Permute(Span<T> span, int a, int b)
 55106    {
 55107      if (a == b)
 33108      {
 33109        action.Invoke();
 33110        return status.Invoke();
 111      }
 146112      for (int i = a; i <= b; i++)
 51113      {
 51114        Swap<T>(ref span[a], ref span[i]);
 51115        if (Permute(span, a + 1, b) is Break)
 0116        {
 0117          return Break;
 118        }
 51119        Swap<T>(ref span[a], ref span[i]);
 51120      }
 22121      return Continue;
 55122    }
 4123  }
 124
 125  /// <inheritdoc cref="XML_PermuteIterative"/>
 126  public static void PermuteIterative<T>(int start, int end, Action action, Func<int, T> get, Action<int, T> set) =>
 4127    PermuteIterative<T, SAction, StepStatusContinue, SFunc<int, T>, SAction<int, T>>(start, end, action, default, get, s
 128
 129  /// <inheritdoc cref="XML_PermuteIterative"/>
 130  public static void PermuteIterative<T>(int start, int end, Action action, Func<StepStatus> status, Func<int, T> get, A
 0131    PermuteIterative<T, SAction, SFunc<StepStatus>, SFunc<int, T>, SAction<int, T>>(start, end, action, status, get, set
 132
 133  /// <inheritdoc cref="XML_PermuteIterative"/>
 134  public static void PermuteIterative<T, TAction, TGet, TSet>(int start, int end, TAction action = default, TGet get = d
 135    where TAction : struct, IAction
 136    where TGet : struct, IFunc<int, T>
 137    where TSet : struct, IAction<int, T> =>
 0138    PermuteIterative<T, TAction, StepStatusContinue, TGet, TSet>(start, end, action, default, get, set);
 139
 140  /// <inheritdoc cref="XML_PermuteIterative"/>
 141  public static void PermuteIterative<T, TAction, TStatus, TGet, TSet>(int start, int end, TAction action = default, TSt
 142    where TAction : struct, IAction
 143    where TStatus : struct, IFunc<StepStatus>
 144    where TGet : struct, IFunc<int, T>
 145    where TSet : struct, IAction<int, T>
 4146  {
 4147    action.Invoke();
 4148    int[] indeces = new int[end + 2 - start];
 36149    for (int i = 0; i < indeces.Length; i++)
 14150    {
 14151      indeces[i] = i;
 14152    }
 66153    for (int i = start + 1; i < end + 1 && status.Invoke() is Continue; action.Invoke())
 29154    {
 29155      indeces[i]--;
 29156      Swap<T, TGet, TSet>(i, i % 2 is 1 ? indeces[i] : 0, get, set);
 102157      for (i = 1; indeces[i] is 0; i++)
 22158      {
 22159        indeces[i] = i;
 22160      }
 29161    }
 4162  }
 163
 164  /// <inheritdoc cref="XML_PermuteIterative"/>
 165  public static void PermuteIterative<T>(Span<T> span, Action action) =>
 4166    PermuteIterative<T, SAction, StepStatusContinue>(span, action);
 167
 168  /// <inheritdoc cref="XML_PermuteIterative"/>
 169  public static void PermuteIterative<T, TAction>(Span<T> span, TAction action = default)
 170    where TAction : struct, IAction =>
 0171    PermuteIterative<T, TAction, StepStatusContinue>(span, action);
 172
 173  /// <inheritdoc cref="XML_PermuteIterative"/>
 174  public static void PermuteIterative<T, TStatus>(Span<T> span, Action action, TStatus status = default)
 175    where TStatus : struct, IFunc<StepStatus> =>
 0176    PermuteIterative<T, SAction, TStatus>(span, action, status);
 177
 178  /// <inheritdoc cref="XML_PermuteIterative"/>
 179  public static void PermuteIterative<T, TAction, TStatus>(Span<T> span, TAction action = default, TStatus status = defa
 180    where TAction : struct, IAction
 181    where TStatus : struct, IFunc<StepStatus>
 4182  {
 4183    action.Invoke();
 4184    int[] indeces = new int[span.Length - 1 + 2];
 36185    for (int i = 0; i < indeces.Length; i++)
 14186    {
 14187      indeces[i] = i;
 14188    }
 66189    for (int i = 1; i < span.Length && status.Invoke() is Continue; action.Invoke())
 29190    {
 29191      indeces[i]--;
 29192      Swap<T>(ref span[i], ref span[i % 2 is 1 ? indeces[i] : 0]);
 102193      for (i = 1; indeces[i] is 0; i++)
 22194      {
 22195        indeces[i] = i;
 22196      }
 29197    }
 4198  }
 199}

/home/runner/work/Towel/Towel/Sources/Towel/Statics-Random.cs

#LineLine coverage
 1namespace Towel;
 2
 3/// <summary>Root type of the static functional methods in Towel.</summary>
 4public static partial class Statics
 5{
 6  #region Next (with exclusions)
 7
 8  /// <summary>
 9  /// Generates <paramref name="count"/> random <see cref="int"/> values in the
 10  /// [<paramref name="minValue"/>..<paramref name="maxValue"/>] range where <paramref name="minValue"/> is
 11  /// inclusive and <paramref name="maxValue"/> is exclusive.
 12  /// </summary>
 13  /// <typeparam name="TStep">The type of function to perform on each generated <see cref="int"/> value.</typeparam>
 14  /// <typeparam name="TRandom">The type of random to generation algorithm.</typeparam>
 15  /// <param name="count">The number of <see cref="int"/> values to generate.</param>
 16  /// <param name="minValue">Inclusive endpoint of the random generation range.</param>
 17  /// <param name="maxValue">Exclusive endpoint of the random generation range.</param>
 18  /// <param name="excluded">Values that should be excluded during generation.</param>
 19  /// <param name="random">The random to generation algorithm.</param>
 20  /// <param name="step">The function to perform on each generated <see cref="int"/> value.</param>
 21  public static void Next<TStep, TRandom>(int count, int minValue, int maxValue, ReadOnlySpan<int> excluded, TRandom ran
 22    where TStep : struct, IAction<int>
 23    where TRandom : struct, IFunc<int, int, int>
 024  {
 025    if (count * excluded.Length + .5 * Math.Pow(excluded.Length, 2) < (maxValue - minValue) + count + 2 * excluded.Lengt
 026    {
 027      NextRollTracking(count, minValue, maxValue, excluded, random, step);
 028    }
 29    else
 030    {
 031      NextPoolTracking(count, minValue, maxValue, excluded, random, step);
 032    }
 033  }
 34
 35  /// <inheritdoc cref="Next{TStep, TRandom}(int, int, int, ReadOnlySpan{int}, TRandom, TStep)"></inheritdoc>
 36  public static void NextRollTracking<TStep, TRandom>(int count, int minValue, int maxValue, ReadOnlySpan<int> excluded,
 37    where TStep : struct, IAction<int>
 38    where TRandom : struct, IFunc<int, int, int>
 100239  {
 100240    if (sourceof(maxValue < minValue, out string c1)) throw new ArgumentOutOfRangeException(nameof(maxValue), c1);
 100241    if (sourceof(count < 0, out string c2)) throw new ArgumentOutOfRangeException(nameof(count), c2);
 42    // Algorithm B: O(count * excluded.Length + .5*excluded.Length^2)
 100243    Node<int>? head = null;
 100244    int excludeCount = 0;
 20302645    foreach (int i in excluded) // Θ(excluded.Length)
 10001046    {
 10001047      if (i < minValue || i >= maxValue)
 048      {
 049        continue;
 50      }
 10001051      Node<int>? node = head;
 10001052      Node<int>? previous = null;
 249474353      while (node is not null && node.Value <= i) // O(.5*excluded.Length), Ω(0), ε(.5*excluded.Length)
 239955754      {
 239955755        if (node.Value == i)
 482456        {
 482457          goto Continue;
 58        }
 239473359        previous = node;
 239473360        node = node.Next;
 239473361      }
 9518662      excludeCount++;
 9518663      if (previous is null)
 505964      {
 505965        head = new Node<int>() { Value = i, Next = head, };
 505966      }
 67      else
 9012768      {
 9012769        previous.Next = new Node<int>() { Value = i, Next = previous.Next };
 9012770      }
 10001071    Continue:
 10001072      continue;
 73    }
 100274    if (excludeCount >= maxValue - minValue)
 075    {
 076      throw new ArgumentException($"{nameof(excluded)}.{nameof(excluded.Length)} >= {nameof(count)}");
 77    }
 1402478    for (int i = 0; i < count; i++) // Θ(count)
 601079    {
 601080      int roll = random.Invoke(minValue, maxValue - excludeCount);
 601081      if (roll < minValue || roll >= maxValue - excludeCount)
 082      {
 083        throw new ArgumentException("The Random provided returned a value outside the requested range.");
 84      }
 601085      Node<int>? node = head;
 29370386      while (node is not null && node.Value <= roll) // O(excluded.Length), Ω(0)
 28769387      {
 28769388        roll++;
 28769389        node = node.Next;
 28769390      }
 601091      step.Invoke(roll);
 601092    }
 100293  }
 94
 95  /// <inheritdoc cref="Next{TStep, TRandom}(int, int, int, ReadOnlySpan{int}, TRandom, TStep)"></inheritdoc>
 96  public static void NextPoolTracking<TStep, TRandom>(int count, int minValue, int maxValue, ReadOnlySpan<int> excluded,
 97    where TStep : struct, IAction<int>
 98    where TRandom : struct, IFunc<int, int, int>
 100299  {
 1002100    if (sourceof(maxValue < minValue, out string c1)) throw new ArgumentOutOfRangeException(nameof(maxValue), c1);
 1002101    if (sourceof(count < 0, out string c2)) throw new ArgumentOutOfRangeException(nameof(count), c2);
 102    // Algorithm: Θ(range + count + 2*excluded.Length)
 1002103    SetHashLinked<int, Int32Equate, Int32Hash> set = new(expectedCount: excluded.Length); // Θ(excluded)
 203026104    foreach (int value in excluded)
 100010105    {
 100010106      if (minValue <= value && value < maxValue)
 100010107      {
 100010108        set.TryAdd(value);
 100010109      }
 100010110    }
 1002111    if (set.Count >= maxValue - minValue)
 0112    {
 0113      throw new ArgumentException($"{nameof(excluded)}.{nameof(excluded.Length)} >= {nameof(maxValue)} - {nameof(minValu
 114    }
 1002115    int pool = maxValue - minValue - set.Count;
 1002116    Span<int> span = new int[pool];
 2002828117    for (int i = 0, j = minValue; i < pool; j++) // Θ(range + excluded.Length)
 999911118    {
 999911119      if (!set.Contains(j))
 904887120      {
 904887121        span[i++] = j;
 904887122      }
 999911123    }
 14024124    for (int i = 0; i < count; i++) // Θ(count)
 6010125    {
 6010126      int rollIndex = random.Invoke(0, pool);
 6010127      if (rollIndex < 0 || rollIndex >= pool)
 0128      {
 0129        throw new ArgumentException("The Random provided returned a value outside the requested range.");
 130      }
 6010131      int roll = span[rollIndex];
 6010132      step.Invoke(roll);
 6010133    }
 1002134  }
 135
 136  #region Overloads
 137
 138  /// <inheritdoc cref="Next{TStep, TRandom}(int, int, int, ReadOnlySpan{int}, TRandom, TStep)"></inheritdoc>
 139  /// <param name="step">The function to perform on each randomly generated value.</param>
 140#pragma warning disable CS1573 // Parameter has no matching param tag in the XML comment (but other parameters do)
 141  public static void Next<TRandom>(int count, int minValue, int maxValue, ReadOnlySpan<int> excluded, Action<int> step, 
 142#pragma warning restore CS1573 // Parameter has no matching param tag in the XML comment (but other parameters do)
 143    where TRandom : struct, IFunc<int, int, int>
 0144  {
 0145    if (step is null) throw new ArgumentNullException(nameof(step));
 0146    if (sourceof(maxValue < minValue, out string c1)) throw new ArgumentOutOfRangeException(nameof(maxValue), c1);
 0147    if (sourceof(count < 0, out string c2)) throw new ArgumentOutOfRangeException(nameof(count), c2);
 0148    Next<SAction<int>, TRandom>(count, minValue, maxValue, excluded, random, step);
 0149  }
 150
 151  /// <inheritdoc cref="Next{TRandom}(int, int, int, ReadOnlySpan{int}, Action{int}, TRandom)"></inheritdoc>
 152  public static void NextRollTracking<TRandom>(int count, int minValue, int maxValue, ReadOnlySpan<int> excluded, Action
 153    where TRandom : struct, IFunc<int, int, int>
 0154  {
 0155    if (step is null) throw new ArgumentNullException(nameof(step));
 0156    if (sourceof(maxValue < minValue, out string c1)) throw new ArgumentOutOfRangeException(nameof(maxValue), c1);
 0157    if (sourceof(count < 0, out string c2)) throw new ArgumentOutOfRangeException(nameof(count), c2);
 0158    NextRollTracking<SAction<int>, TRandom>(count, minValue, maxValue, excluded, random, step);
 0159  }
 160
 161  /// <inheritdoc cref="Next{TRandom}(int, int, int, ReadOnlySpan{int}, Action{int}, TRandom)"></inheritdoc>
 162  public static void NextPoolTracking<TRandom>(int count, int minValue, int maxValue, ReadOnlySpan<int> excluded, Action
 163    where TRandom : struct, IFunc<int, int, int>
 0164  {
 0165    if (step is null) throw new ArgumentNullException(nameof(step));
 0166    if (sourceof(maxValue < minValue, out string c1)) throw new ArgumentOutOfRangeException(nameof(maxValue), c1);
 0167    if (sourceof(count < 0, out string c2)) throw new ArgumentOutOfRangeException(nameof(count), c2);
 0168    NextPoolTracking<SAction<int>, TRandom>(count, minValue, maxValue, excluded, random, step);
 0169  }
 170
 171  /// <inheritdoc cref="Next{TStep, TRandom}(int, int, int, ReadOnlySpan{int}, TRandom, TStep)"></inheritdoc>
 172  /// <returns>The randomly generated values.</returns>
 173  public static int[] Next<TRandom>(int count, int minValue, int maxValue, ReadOnlySpan<int> excluded, TRandom random = 
 174    where TRandom : struct, IFunc<int, int, int>
 0175  {
 0176    if (sourceof(maxValue < minValue, out string c1)) throw new ArgumentOutOfRangeException(nameof(maxValue), c1);
 0177    if (sourceof(count < 0, out string c2)) throw new ArgumentOutOfRangeException(nameof(count), c2);
 0178    int[] values = new int[count];
 0179    Next<FillArray<int>, TRandom>(count, minValue, maxValue, excluded, random, values);
 0180    return values;
 0181  }
 182
 183  /// <inheritdoc cref="Next{TRandom}(int, int, int, ReadOnlySpan{int}, TRandom)"/>
 184  public static int[] NextRollTracking<TRandom>(int count, int minValue, int maxValue, ReadOnlySpan<int> excluded, TRand
 185    where TRandom : struct, IFunc<int, int, int>
 1006186  {
 1008187    if (sourceof(maxValue < minValue, out string c1)) throw new ArgumentOutOfRangeException(nameof(maxValue), c1);
 1006188    if (sourceof(count < 0, out string c2)) throw new ArgumentOutOfRangeException(nameof(count), c2);
 1002189    int[] values = new int[count];
 1002190    NextRollTracking<FillArray<int>, TRandom>(count, minValue, maxValue, excluded, random, values);
 1002191    return values;
 1002192  }
 193
 194  /// <inheritdoc cref="Next{TRandom}(int, int, int, ReadOnlySpan{int}, TRandom)"/>
 195  public static int[] NextPoolTracking<TRandom>(int count, int minValue, int maxValue, ReadOnlySpan<int> excluded, TRand
 196    where TRandom : struct, IFunc<int, int, int>
 1002197  {
 1002198    if (sourceof(maxValue < minValue, out string c1)) throw new ArgumentOutOfRangeException(nameof(maxValue), c1);
 1002199    if (sourceof(count < 0, out string c2)) throw new ArgumentOutOfRangeException(nameof(count), c2);
 1002200    int[] values = new int[count];
 1002201    NextPoolTracking<FillArray<int>, TRandom>(count, minValue, maxValue, excluded, random, values);
 1002202    return values;
 1002203  }
 204
 205  #endregion
 206
 207  #endregion
 208
 209  #region NextUnique
 210
 211  /// <summary>
 212  /// Generates <paramref name="count"/> unique random <see cref="int"/> values in the
 213  /// [<paramref name="minValue"/>..<paramref name="maxValue"/>] range where <paramref name="minValue"/> is
 214  /// inclusive and <paramref name="maxValue"/> is exclusive.
 215  /// </summary>
 216  /// <typeparam name="TStep">The type of function to perform on each generated <see cref="int"/> value.</typeparam>
 217  /// <typeparam name="TRandom">The type of random to generation algorithm.</typeparam>
 218  /// <param name="count">The number of <see cref="int"/> values to generate.</param>
 219  /// <param name="minValue">Inclusive endpoint of the random generation range.</param>
 220  /// <param name="maxValue">Exclusive endpoint of the random generation range.</param>
 221  /// <param name="random">The random to generation algorithm.</param>
 222  /// <param name="step">The function to perform on each generated <see cref="int"/> value.</param>
 223  public static void NextUnique<TStep, TRandom>(int count, int minValue, int maxValue, TRandom random = default, TStep s
 224    where TStep : struct, IAction<int>
 225    where TRandom : struct, IFunc<int, int, int>
 20010226  {
 20010227    if (count < Math.Sqrt(maxValue - minValue))
 10005228    {
 10005229      NextUniqueRollTracking(count, minValue, maxValue, random, step);
 10003230    }
 231    else
 10005232    {
 10005233      NextUniquePoolTracking(count, minValue, maxValue, random, step);
 10003234    }
 20006235  }
 236
 237  /// <inheritdoc cref="NextUnique{TStep, TRandom}(int, int, int, TRandom, TStep)"/>
 238  public static void NextUniqueRollTracking<TStep, TRandom>(int count, int minValue, int maxValue, TRandom random = defa
 239    where TStep : struct, IAction<int>
 240    where TRandom : struct, IFunc<int, int, int>
 10011241  {
 10011242    if (sourceof(maxValue < minValue, out string c1)) throw new ArgumentOutOfRangeException(nameof(maxValue), c1);
 10011243    if (sourceof(count < 0, out string c2)) throw new ArgumentOutOfRangeException(nameof(count), c2);
 10011244    if (sourceof(maxValue - minValue < count, out string c3)) throw new ArgumentOutOfRangeException(nameof(count), c3);
 245#if stackalloc
 246      if (count <= 128)
 247      {
 248        // Algorithm B: Θ(.5*count^2)
 249        Span<int> span = stackalloc int[count];
 250        for (int i = 0; i < count; i++) // Θ(count)
 251        {
 252          int roll = random.Do(minValue, maxValue - i);
 253          if (roll < minValue || roll >= maxValue - i)
 254          {
 255            throw new ArgumentException("The Random provided returned a value outside the requested range.");
 256          }
 257          int index = 0;
 258          for (; index < i && span[index] <= roll; index++)
 259          {
 260            roll++;
 261          }
 262          step.Do(roll);
 263          for (int j = i; j > index; j--)
 264          {
 265            span[j] = span[j - 1];
 266          }
 267          span[index] = roll;
 268        }
 269      }
 270      else
 271      {
 272#endif
 273    // Algorithm: O(.5*count^2), Ω(count), ε(.5*count^2)
 10011274    Node<int>? head = null;
 120112275    for (int i = 0; i < count; i++) // Θ(count)
 50047276    {
 50047277      int roll = random.Invoke(minValue, maxValue - i);
 50047278      if (roll < minValue || roll >= maxValue - i)
 2279      {
 2280        throw new ArgumentException("The Random provided returned a value outside the requested range.");
 281      }
 50045282      Node<int>? node = head;
 50045283      Node<int>? previous = null;
 100346284      while (node is not null && node.Value <= roll) // O(.5*count), Ω(0), ε(.5*count)
 50301285      {
 50301286        roll++;
 50301287        previous = node;
 50301288        node = node.Next;
 50301289      }
 50045290      step.Invoke(roll);
 50045291      if (previous is null)
 22741292      {
 22741293        head = new Node<int>() { Value = roll, Next = head, };
 22741294      }
 295      else
 27304296      {
 27304297        previous.Next = new Node<int>() { Value = roll, Next = previous.Next };
 27304298      }
 50045299    }
 300#if stackalloc
 301      }
 302#endif
 10009303  }
 304
 305  /// <inheritdoc cref="NextUnique{TStep, TRandom}(int, int, int, TRandom, TStep)"/>
 306  public static void NextUniquePoolTracking<TStep, TRandom>(int count, int minValue, int maxValue, TRandom random = defa
 307    where TStep : struct, IAction<int>
 308    where TRandom : struct, IFunc<int, int, int>
 10011309  {
 10011310    if (sourceof(maxValue < minValue, out string c1)) throw new ArgumentOutOfRangeException(nameof(maxValue), c1);
 10011311    if (sourceof(count < 0, out string c2)) throw new ArgumentOutOfRangeException(nameof(count), c2);
 10011312    if (sourceof(maxValue - minValue < count, out string c3)) throw new ArgumentOutOfRangeException(nameof(count), c3);
 313    // Algorithm: Θ(range + count)
 10011314    int pool = maxValue - minValue;
 10011315    Span<int> span = sizeof(int) * pool <= Stackalloc ? stackalloc int[pool] : new int[pool];
 30049578316    for (int i = 0, j = minValue; j < maxValue; i++, j++) // Θ(range)
 10006515317    {
 10006515318      span[i] = j;
 10006515319    }
 2020682320    for (int i = 0; i < count; i++) // Θ(count)
 1000332321    {
 1000332322      int rollIndex = random.Invoke(0, pool);
 1000332323      if (rollIndex < 0 || rollIndex >= pool)
 2324      {
 2325        throw new ArgumentException("The Random provided returned a value outside the requested range.");
 326      }
 1000330327      int roll = span[rollIndex];
 1000330328      span[rollIndex] = span[--pool];
 1000330329      step.Invoke(roll);
 1000330330    }
 10009331  }
 332
 333  #region Overloads
 334
 335  /// <inheritdoc cref="NextUnique{TStep, TRandom}(int, int, int, TRandom, TStep)"></inheritdoc>
 336  /// <param name="step">The function to perform on each randomly generated value.</param>
 337#pragma warning disable CS1573 // Parameter has no matching param tag in the XML comment (but other parameters do)
 338  public static void NextUnique<TRandom>(int count, int minValue, int maxValue, Action<int> step, TRandom random = defau
 339#pragma warning restore CS1573 // Parameter has no matching param tag in the XML comment (but other parameters do)
 340    where TRandom : struct, IFunc<int, int, int>
 20010341  {
 20010342    if (step is null) throw new ArgumentNullException(nameof(step));
 20010343    if (sourceof(maxValue < minValue, out string c1)) throw new ArgumentOutOfRangeException(nameof(maxValue), c1);
 20010344    if (sourceof(count < 0, out string c2)) throw new ArgumentOutOfRangeException(nameof(count), c2);
 20010345    NextUnique<SAction<int>, TRandom>(count, minValue, maxValue, random, step);
 20006346  }
 347
 348  /// <inheritdoc cref="NextUnique{TRandom}(int, int, int, Action{int}, TRandom)"></inheritdoc>
 349  public static void NextUniqueRollTracking<TRandom>(int count, int minValue, int maxValue, Action<int> step, TRandom ra
 350    where TRandom : struct, IFunc<int, int, int>
 0351  {
 0352    if (step is null) throw new ArgumentNullException(nameof(step));
 0353    if (sourceof(maxValue < minValue, out string c1)) throw new ArgumentOutOfRangeException(nameof(maxValue), c1);
 0354    if (sourceof(count < 0, out string c2)) throw new ArgumentOutOfRangeException(nameof(count), c2);
 0355    NextUniqueRollTracking<SAction<int>, TRandom>(count, minValue, maxValue, random, step);
 0356  }
 357
 358  /// <inheritdoc cref="NextUnique{TRandom}(int, int, int, Action{int}, TRandom)"></inheritdoc>
 359  public static void NextUniquePoolTracking<TRandom>(int count, int minValue, int maxValue, Action<int> step, TRandom ra
 360    where TRandom : struct, IFunc<int, int, int>
 0361  {
 0362    if (step is null) throw new ArgumentNullException(nameof(step));
 0363    if (sourceof(maxValue < minValue, out string c1)) throw new ArgumentOutOfRangeException(nameof(maxValue), c1);
 0364    if (sourceof(count < 0, out string c2)) throw new ArgumentOutOfRangeException(nameof(count), c2);
 0365    NextUniquePoolTracking<SAction<int>, TRandom>(count, minValue, maxValue, random, step);
 0366  }
 367
 368  /// <inheritdoc cref="NextUnique{TStep, TRandom}(int, int, int, TRandom, TStep)"></inheritdoc>
 369  /// <returns>The randomly generated values.</returns>
 370  public static int[] NextUnique<TRandom>(int count, int minValue, int maxValue, TRandom random = default)
 371    where TRandom : struct, IFunc<int, int, int>
 0372  {
 0373    if (sourceof(maxValue < minValue, out string c1)) throw new ArgumentOutOfRangeException(nameof(maxValue), c1);
 0374    if (sourceof(count < 0, out string c2)) throw new ArgumentOutOfRangeException(nameof(count), c2);
 0375    if (sourceof(maxValue - minValue < count, out string c3)) throw new ArgumentOutOfRangeException(nameof(count), c3);
 0376    int[] values = new int[count];
 0377    NextUnique<FillArray<int>, TRandom>(count, minValue, maxValue, random, values);
 0378    return values;
 0379  }
 380
 381  /// <inheritdoc cref="NextUnique{TRandom}(int, int, int, TRandom)"></inheritdoc>
 382  public static int[] NextUniqueRollTracking<TRandom>(int count, int minValue, int maxValue, TRandom random = default)
 383    where TRandom : struct, IFunc<int, int, int>
 9384  {
 10385    if (sourceof(maxValue < minValue, out string c1)) throw new ArgumentOutOfRangeException(nameof(maxValue), c1);
 9386    if (sourceof(count < 0, out string c2)) throw new ArgumentOutOfRangeException(nameof(count), c2);
 8387    if (sourceof(maxValue - minValue < count, out string c3)) throw new ArgumentOutOfRangeException(nameof(count), c3);
 6388    int[] values = new int[count];
 6389    NextUniqueRollTracking<FillArray<int>, TRandom>(count, minValue, maxValue, random, values);
 6390    return values;
 6391  }
 392
 393  /// <inheritdoc cref="NextUnique{TRandom}(int, int, int, TRandom)"></inheritdoc>
 394  public static int[] NextUniquePoolTracking<TRandom>(int count, int minValue, int maxValue, TRandom random = default)
 395    where TRandom : struct, IFunc<int, int, int>
 9396  {
 10397    if (sourceof(maxValue < minValue, out string c1)) throw new ArgumentOutOfRangeException(nameof(maxValue), c1);
 9398    if (sourceof(count < 0, out string c2)) throw new ArgumentOutOfRangeException(nameof(count), c2);
 8399    if (sourceof(maxValue - minValue < count, out string c3)) throw new ArgumentOutOfRangeException(nameof(count), c3);
 6400    int[] values = new int[count];
 6401    NextUniquePoolTracking<FillArray<int>, TRandom>(count, minValue, maxValue, random, values);
 6402    return values;
 6403  }
 404
 405  #endregion
 406
 407  #endregion
 408
 409  #region NextUnique (with exclusions)
 410
 411  /// <summary>
 412  /// Generates <paramref name="count"/> unique random <see cref="int"/> values in the
 413  /// [<paramref name="minValue"/>..<paramref name="maxValue"/>] range where <paramref name="minValue"/> is
 414  /// inclusive and <paramref name="maxValue"/> is exclusive.
 415  /// </summary>
 416  /// <typeparam name="TStep">The type of function to perform on each generated <see cref="int"/> value.</typeparam>
 417  /// <typeparam name="TRandom">The type of random to generation algorithm.</typeparam>
 418  /// <param name="count">The number of <see cref="int"/> values to generate.</param>
 419  /// <param name="minValue">Inclusive endpoint of the random generation range.</param>
 420  /// <param name="maxValue">Exclusive endpoint of the random generation range.</param>
 421  /// <param name="excluded">Values that should be excluded during generation.</param>
 422  /// <param name="random">The random to generation algorithm.</param>
 423  /// <param name="step">The function to perform on each generated <see cref="int"/> value.</param>
 424  public static void NextUnique<TStep, TRandom>(int count, int minValue, int maxValue, ReadOnlySpan<int> excluded, TRand
 425    where TStep : struct, IAction<int>
 426    where TRandom : struct, IFunc<int, int, int>
 0427  {
 0428    if (count + excluded.Length < Math.Sqrt(maxValue - minValue))
 0429    {
 0430      NextUniqueRollTracking(count, minValue, maxValue, excluded, random, step);
 0431    }
 432    else
 0433    {
 0434      NextUniquePoolTracking(count, minValue, maxValue, excluded, random, step);
 0435    }
 0436  }
 437
 438  /// <inheritdoc cref="NextUnique{TStep, TRandom}(int, int, int, ReadOnlySpan{int}, TRandom, TStep)"/>
 439  public static void NextUniqueRollTracking<TStep, TRandom>(int count, int minValue, int maxValue, ReadOnlySpan<int> exc
 440    where TStep : struct, IAction<int>
 441    where TRandom : struct, IFunc<int, int, int>
 1004442  {
 1004443    if (sourceof(maxValue < minValue, out string c1)) throw new ArgumentOutOfRangeException(nameof(maxValue), c1);
 1004444    if (sourceof(count < 0, out string c2)) throw new ArgumentOutOfRangeException(nameof(count), c2);
 1004445    if (sourceof(maxValue - minValue < count, out string c3)) throw new ArgumentOutOfRangeException(nameof(count), c3);
 446#if stackalloc
 447      if (count + excluded.Length <= 128)
 448      {
 449        // Algorithm B: Θ(.5*count^2)
 450        int excludeCount = 0;
 451        Span<int> span = stackalloc int[count + excluded.Length];
 452        {
 453          foreach (int exclude in excluded)
 454          {
 455            if (minValue <= exclude && exclude < maxValue)
 456            {
 457              int index = 0;
 458              for (; index < excludeCount && exclude > span[index]; index++)
 459              {
 460                if (span[index] == exclude)
 461                {
 462                  goto Continue;
 463                }
 464              }
 465              for (int j = excludeCount + 1; j > index; j--)
 466              {
 467                span[j] = span[j - 1];
 468              }
 469              span[excludeCount++] = exclude;
 470            }
 471          Continue:
 472            continue;
 473          }
 474        }
 475        if (maxValue - minValue - excludeCount < count)
 476        {
 477          throw new ArgumentException($"{nameof(maxValue)} - {nameof(minValue)} - {nameof(excluded)}.Length [{maxValue -
 478        }
 479        for (int i = 0; i < count; i++) // Θ(count)
 480        {
 481          int roll = random.Do(minValue, maxValue - i + excludeCount);
 482          if (roll < minValue || roll >= maxValue - i + excludeCount)
 483          {
 484            throw new ArgumentException("The Random provided returned a value outside the requested range.");
 485          }
 486          int index = 0;
 487          for (; index < i + excludeCount && span[index] <= roll; index++)
 488          {
 489            roll++;
 490          }
 491          step.Do(roll);
 492          for (int j = i + excludeCount; j > index; j--)
 493          {
 494            span[j] = span[j - 1];
 495          }
 496          span[index] = roll;
 497        }
 498      }
 499      else
 500      {
 501#endif
 502    // Algorithm B: O(.5*(count + excluded.Length)^2 + .5*excluded.Length^2), Ω(count + excluded.Length), ε(.5*(count + 
 1004503    Node<int>? head = null;
 1004504    int excludeCount = 0;
 203036505    foreach (int i in excluded) // Θ(excluded.Length)
 100012506    {
 100012507      if (i < minValue || i >= maxValue)
 0508      {
 0509        continue;
 510      }
 100012511      Node<int>? node = head;
 100012512      Node<int>? previous = null;
 2501326513      while (node is not null && node.Value <= i) // O(.5*excluded.Length), Ω(0), ε(.5*excluded.Length)
 2406096514      {
 2406096515        if (node.Value == i)
 4782516        {
 4782517          goto Continue;
 518        }
 2401314519        previous = node;
 2401314520        node = node.Next;
 2401314521      }
 95230522      excludeCount++;
 95230523      if (previous is null)
 5069524      {
 5069525        head = new Node<int>() { Value = i, Next = head, };
 5069526      }
 527      else
 90161528      {
 90161529        previous.Next = new Node<int>() { Value = i, Next = previous.Next };
 90161530      }
 100012531    Continue:
 100012532      continue;
 533    }
 1004534    if (maxValue - minValue - excludeCount < count)
 2535    {
 2536      throw new ArgumentException($"{nameof(maxValue)} - {nameof(minValue)} - {nameof(excluded)}.Length [{maxValue - min
 537    }
 14024538    for (int i = 0; i < count; i++) // Θ(count)
 6010539    {
 6010540      int roll = random.Invoke(minValue, maxValue - i - excludeCount);
 6010541      if (roll < minValue || roll >= maxValue - i - excludeCount)
 0542      {
 0543        throw new ArgumentException("The Random provided returned a value outside the requested range.");
 544      }
 6010545      Node<int>? node = head;
 6010546      Node<int>? previous = null;
 299720547      while (node is not null && node.Value <= roll) // O(.5*(count + excluded.Length)), Ω(0), ε(.5*(count + excluded.Le
 293710548      {
 293710549        roll++;
 293710550        previous = node;
 293710551        node = node.Next;
 293710552      }
 6010553      step.Invoke(roll);
 6010554      if (previous is null)
 77555      {
 77556        head = new Node<int>() { Value = roll, Next = head, };
 77557      }
 558      else
 5933559      {
 5933560        previous.Next = new Node<int>() { Value = roll, Next = previous.Next };
 5933561      }
 6010562    }
 563#if stackalloc
 564      }
 565#endif
 1002566  }
 567
 568  /// <inheritdoc cref="NextUnique{TStep, TRandom}(int, int, int, ReadOnlySpan{int}, TRandom, TStep)"/>
 569  public static void NextUniquePoolTracking<TStep, TRandom>(int count, int minValue, int maxValue, ReadOnlySpan<int> exc
 570    where TStep : struct, IAction<int>
 571    where TRandom : struct, IFunc<int, int, int>
 1002572  {
 573    // Algorithm: Θ(range + count + 2*excluded.Length)
 1002574    SetHashLinked<int, Int32Equate, Int32Hash> set = new(expectedCount: excluded.Length); // Θ(excluded)
 203026575    foreach (int value in excluded)
 100010576    {
 100010577      if (minValue <= value && value < maxValue)
 100010578      {
 100010579        set.TryAdd(value);
 100010580      }
 100010581    }
 1002582    if (maxValue - minValue - set.Count < count)
 0583    {
 0584      throw new ArgumentException($"{nameof(maxValue)} - {nameof(minValue)} - {nameof(excluded)}.Length [{maxValue - min
 585    }
 1002586    if (sourceof(maxValue < minValue, out string c2)) throw new ArgumentOutOfRangeException(nameof(maxValue), c2);
 1002587    if (sourceof(count < 0, out string c3)) throw new ArgumentOutOfRangeException(nameof(count), c3);
 1002588    if (sourceof(maxValue - minValue < count, out string c4)) throw new ArgumentOutOfRangeException(nameof(count), c4);
 1002589    int pool = maxValue - minValue - set.Count;
 1002590    Span<int> span =
 1002591#if stackalloc
 1002592        pool <= 128
 1002593        ?
 1002594        stackalloc int[pool]
 1002595        :
 1002596#endif
 1002597        new int[pool];
 2002812598    for (int i = 0, j = minValue; i < pool; j++) // Θ(range + excluded.Length)
 999903599    {
 999903600      if (!set.Contains(j))
 904770601      {
 904770602        span[i++] = j;
 904770603      }
 999903604    }
 14024605    for (int i = 0; i < count; i++) // Θ(count)
 6010606    {
 6010607      int rollIndex = random.Invoke(0, pool);
 6010608      if (rollIndex < 0 || rollIndex >= pool)
 0609      {
 0610        throw new ArgumentException("The Random provided returned a value outside the requested range.");
 611      }
 6010612      int roll = span[rollIndex];
 6010613      span[rollIndex] = span[--pool];
 6010614      step.Invoke(roll);
 6010615    }
 1002616  }
 617
 618  #region Overloads
 619
 620  /// <inheritdoc cref="NextUnique{TStep, TRandom}(int, int, int, ReadOnlySpan{int}, TRandom, TStep)"></inheritdoc>
 621  /// <param name="step">The function to perform on each randomly generated value.</param>
 622#pragma warning disable CS1573 // Parameter has no matching param tag in the XML comment (but other parameters do)
 623  public static void NextUnique<TRandom>(int count, int minValue, int maxValue, ReadOnlySpan<int> excluded, Action<int> 
 624#pragma warning restore CS1573 // Parameter has no matching param tag in the XML comment (but other parameters do)
 625      where TRandom : struct, IFunc<int, int, int>
 0626  {
 0627    if (step is null) throw new ArgumentNullException(nameof(step));
 0628    if (sourceof(maxValue < minValue, out string c1)) throw new ArgumentOutOfRangeException(nameof(maxValue), c1);
 0629    if (sourceof(count < 0, out string c2)) throw new ArgumentOutOfRangeException(nameof(count), c2);
 0630    NextUnique<SAction<int>, TRandom>(count, minValue, maxValue, excluded, random, step);
 0631  }
 632
 633  /// <inheritdoc cref="NextUnique{Random}(int, int, int, ReadOnlySpan{int}, Action{int}, Random)"></inheritdoc>
 634  public static void NextUniqueRollTracking<TRandom>(int count, int minValue, int maxValue, ReadOnlySpan<int> excluded, 
 635    where TRandom : struct, IFunc<int, int, int>
 0636  {
 0637    if (step is null) throw new ArgumentNullException(nameof(step));
 0638    if (sourceof(maxValue < minValue, out string c1)) throw new ArgumentOutOfRangeException(nameof(maxValue), c1);
 0639    if (sourceof(count < 0, out string c2)) throw new ArgumentOutOfRangeException(nameof(count), c2);
 0640    NextUniqueRollTracking<SAction<int>, TRandom>(count, minValue, maxValue, excluded, random, step);
 0641  }
 642
 643  /// <inheritdoc cref="NextUnique{Random}(int, int, int, ReadOnlySpan{int}, Action{int}, Random)"></inheritdoc>
 644  public static void NextUniquePoolTracking<TRandom>(int count, int minValue, int maxValue, ReadOnlySpan<int> excluded, 
 645    where TRandom : struct, IFunc<int, int, int>
 0646  {
 0647    if (step is null) throw new ArgumentNullException(nameof(step));
 0648    if (sourceof(maxValue < minValue, out string c1)) throw new ArgumentOutOfRangeException(nameof(maxValue), c1);
 0649    if (sourceof(count < 0, out string c2)) throw new ArgumentOutOfRangeException(nameof(count), c2);
 0650    NextUniquePoolTracking<SAction<int>, TRandom>(count, minValue, maxValue, excluded, random, step);
 0651  }
 652
 653  /// <inheritdoc cref="NextUnique{Step, Random}(int, int, int, ReadOnlySpan{int}, Random, Step)"/>
 654  /// <returns>The randomly generated values.</returns>
 655  public static int[] NextUnique<TRandom>(int count, int minValue, int maxValue, ReadOnlySpan<int> excluded, TRandom ran
 656    where TRandom : struct, IFunc<int, int, int>
 0657  {
 0658    if (sourceof(maxValue < minValue, out string c1)) throw new ArgumentOutOfRangeException(nameof(maxValue), c1);
 0659    if (sourceof(count < 0, out string c2)) throw new ArgumentOutOfRangeException(nameof(count), c2);
 0660    if (sourceof(maxValue - minValue < count, out string c3)) throw new ArgumentOutOfRangeException(nameof(count), c3);
 0661    int[] values = new int[count];
 0662    NextUnique<FillArray<int>, TRandom>(count, minValue, maxValue, excluded, random, values);
 0663    return values;
 0664  }
 665
 666  /// <inheritdoc cref="NextUnique{Random}(int, int, int, ReadOnlySpan{int}, Random)"/>
 667  public static int[] NextUniqueRollTracking<TRandom>(int count, int minValue, int maxValue, ReadOnlySpan<int> excluded,
 668    where TRandom : struct, IFunc<int, int, int>
 1010669  {
 1012670    if (sourceof(maxValue < minValue, out string c1)) throw new ArgumentOutOfRangeException(nameof(maxValue), c1);
 1010671    if (sourceof(count < 0, out string c2)) throw new ArgumentOutOfRangeException(nameof(count), c2);
 1008672    if (sourceof(maxValue - minValue < count, out string c3)) throw new ArgumentOutOfRangeException(nameof(count), c3);
 1004673    int[] values = new int[count];
 1004674    NextUniqueRollTracking<FillArray<int>, TRandom>(count, minValue, maxValue, excluded, random, values);
 1002675    return values;
 1002676  }
 677
 678  /// <inheritdoc cref="NextUnique{Random}(int, int, int, ReadOnlySpan{int}, Random)"/>
 679  public static int[] NextUniquePoolTracking<TRandom>(int count, int minValue, int maxValue, ReadOnlySpan<int> excluded,
 680    where TRandom : struct, IFunc<int, int, int>
 1002681  {
 1002682    if (sourceof(maxValue < minValue, out string c1)) throw new ArgumentOutOfRangeException(nameof(maxValue), c1);
 1002683    if (sourceof(count < 0, out string c2)) throw new ArgumentOutOfRangeException(nameof(count), c2);
 1002684    if (sourceof(maxValue - minValue < count, out string c3)) throw new ArgumentOutOfRangeException(nameof(count), c3);
 1002685    int[] values = new int[count];
 1002686    NextUniquePoolTracking<FillArray<int>, TRandom>(count, minValue, maxValue, excluded, random, values);
 1002687    return values;
 1002688  }
 689
 690  #endregion
 691
 692  #endregion
 693
 694  #region Extensions
 695
 696  /// <summary>Generates a random <see cref="bool"/> value.</summary>
 697  /// <param name="random">The random generation algorithm.</param>
 698  /// <returns>A randomly generated <see cref="bool"/> value.</returns>
 411699  public static bool NextBool(this Random random) => random.Next(2) is 0;
 700
 701  /// <summary>Generates a random <see cref="byte"/> value.</summary>
 702  /// <param name="random">The random generation algorithm.</param>
 703  /// <returns>A randomly generated <see cref="byte"/> value.</returns>
 0704  public static byte NextByte(this Random random) => (byte)random.Next(byte.MinValue, byte.MaxValue);
 705
 706  /// <summary>Generates a random <see cref="string"/> of a given length using the System.Random generator.</summary>
 707  /// <param name="random">The random generation algorithm.</param>
 708  /// <param name="length">The length of the randomized <see cref="string"/> to generate.</param>
 709  /// <returns>The generated randomized <see cref="string"/>.</returns>
 710  public static string NextString(this Random random, int length)
 0711  {
 0712    if (random is null) throw new ArgumentNullException(nameof(random));
 0713    if (sourceof(length < 0, out string c))  throw new ArgumentOutOfRangeException(nameof(length), c);
 0714    char[] randomstring = new char[length];
 0715    for (int i = 0; i < randomstring.Length; i++)
 0716    {
 0717      randomstring[i] = (char)random.Next(char.MinValue, char.MaxValue);
 0718    }
 0719    return new string(randomstring);
 0720  }
 721
 722  /// <summary>Generates a random <see cref="string"/> of a given length using the System.Random generator with a specif
 723  /// <param name="random">The random generation algorithm.</param>
 724  /// <param name="length">The length of the randomized <see cref="string"/> to generate.</param>
 725  /// <param name="characterPool">The set of allowable characters.</param>
 726  /// <returns>The generated randomized <see cref="string"/>.</returns>
 727  public static string NextString(this Random random, int length, char[] characterPool)
 0728  {
 0729    if (random is null) throw new ArgumentNullException(nameof(random));
 0730    if (characterPool is null) throw new ArgumentNullException(nameof(characterPool));
 0731    if (length < 1)
 0732    {
 0733      throw new ArgumentException("(" + nameof(length) + " < 1)");
 734    }
 0735    if (characterPool.Length < 1)
 0736    {
 0737      throw new ArgumentException("(" + nameof(characterPool) + "." + nameof(characterPool.Length) + " < 1)");
 738    }
 0739    char[] randomstring = new char[length];
 0740    for (int i = 0; i < randomstring.Length; i++)
 0741    {
 0742      randomstring[i] = random.From(characterPool);
 0743    }
 0744    return new string(randomstring);
 0745  }
 746
 747  internal const string UpperCaseEnglishCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 748  internal const string LowerCaseEnglishCharacters = "abcdefghijklmnopqrstuvwxyz";
 749  internal const string EnglishDigits = "0123456789";
 750
 751  /// <summary>Generates a random English alphanumeric <see cref="string"/> of a given length (includes upper and lower 
 752  /// <param name="random">The random generation algorithm.</param>
 753  /// <param name="length">The length of the randomized alphanumeric <see cref="string"/> to generate.</param>
 754  /// <returns>The generated randomized alphanumeric <see cref="string"/>.</returns>
 755  public static string NextEnglishAlphaNumericString(this Random random, int length) =>
 0756    NextString(random, length, (UpperCaseEnglishCharacters + LowerCaseEnglishCharacters + EnglishDigits).ToCharArray());
 757
 758  /// <summary>Generates a random English alphanumeric <see cref="string"/> of a given length (upper case characters onl
 759  /// <param name="random">The random generation algorithm.</param>
 760  /// <param name="length">The length of the randomized alphanumeric <see cref="string"/> to generate.</param>
 761  /// <returns>The generated randomized alphanumeric <see cref="string"/>.</returns>
 762  public static string NextUpperCaseEnglishAlphaNumericString(this Random random, int length) =>
 0763    NextString(random, length, (UpperCaseEnglishCharacters + EnglishDigits).ToCharArray());
 764
 765  /// <summary>Generates a random English alphanumeric <see cref="string"/> of a given length (lower case characters onl
 766  /// <param name="random">The random generation algorithm.</param>
 767  /// <param name="length">The length of the randomized alphanumeric <see cref="string"/> to generate.</param>
 768  /// <returns>The generated randomized alphanumeric <see cref="string"/>.</returns>
 769  public static string NextLowerCaseEnglishAlphaNumericString(this Random random, int length) =>
 0770    NextString(random, length, (LowerCaseEnglishCharacters + EnglishDigits).ToCharArray());
 771
 772  /// <summary>Generates a random English numeric <see cref="string"/> of a given length.</summary>
 773  /// <param name="random">The random generation algorithm.</param>
 774  /// <param name="length">The length of the randomized numeric <see cref="string"/> to generate.</param>
 775  /// <returns>The generated randomized numeric <see cref="string"/>.</returns>
 776  public static string NumericEnglishString(this Random random, int length) =>
 0777    NextString(random, length, EnglishDigits.ToCharArray());
 778
 779  /// <summary>Generates a random English alhpabetical <see cref="string"/> of a given length (includes upper and lower 
 780  /// <param name="random">The random generation algorithm.</param>
 781  /// <param name="length">The length of the randomized alphabetical <see cref="string"/> to generate.</param>
 782  /// <returns>The generated randomized alphabetical <see cref="string"/>.</returns>
 783  public static string NextEnglishAlphabeticString(this Random random, int length) =>
 0784    NextString(random, length, (UpperCaseEnglishCharacters + LowerCaseEnglishCharacters).ToCharArray());
 785
 786  /// <summary>Generates a random English alhpabetical <see cref="string"/> of a given length (upper case characters onl
 787  /// <param name="random">The random generation algorithm.</param>
 788  /// <param name="length">The length of the randomized alphabetical <see cref="string"/> to generate.</param>
 789  /// <returns>The generated randomized alphabetical <see cref="string"/>.</returns>
 790  public static string NextUpperCaseEnglishAlphabeticString(this Random random, int length) =>
 0791    NextString(random, length, UpperCaseEnglishCharacters.ToCharArray());
 792
 793  /// <summary>Generates a random English alhpabetical <see cref="string"/> of a given length (lower case characters onl
 794  /// <param name="random">The random generation algorithm.</param>
 795  /// <param name="length">The length of the randomized alphabetical <see cref="string"/> to generate.</param>
 796  /// <returns>The generated randomized alphabetical <see cref="string"/>.</returns>
 797  public static string NextLowerCaseEnglishAlphabeticString(this Random random, int length) =>
 0798    NextString(random, length, LowerCaseEnglishCharacters.ToCharArray());
 799
 800  /// <summary>Generates a random char value.</summary>
 801  /// <param name="random">The random generation algorithm.</param>
 802  /// <returns>A randomly generated char value.</returns>
 803  public static char NextChar(this Random random) =>
 0804    NextChar(random, char.MinValue, char.MaxValue);
 805
 806  /// <summary>Generates a random char value.</summary>
 807  /// <param name="random">The random generation algorithm.</param>
 808  /// <param name="min">Minimum allowed value of the random generation.</param>
 809  /// <param name="max">Maximum allowed value of the random generation.</param>
 810  /// <returns>A randomly generated char value.</returns>
 811  public static char NextChar(this Random random, char min, char max) =>
 0812    (char)random.Next(min, max);
 813
 814  /// <summary>Generates a random <see cref="decimal"/> value.</summary>
 815  /// <param name="random">The random generation algorithm.</param>
 816  /// <returns>A randomly generated <see cref="decimal"/> value.</returns>
 411817  public static decimal NextDecimal(this Random random) => new(
 411818    random.Next(int.MinValue, int.MaxValue),
 411819    random.Next(int.MinValue, int.MaxValue),
 411820    random.Next(int.MinValue, int.MaxValue),
 411821    random.NextBool(),
 411822    (byte)random.Next(29));
 823
 824  /// <summary>Generates a random <see cref="decimal"/> value.</summary>
 825  /// <param name="random">The random generation algorithm.</param>
 826  /// <param name="min">The minimum allowed value of the random generation.</param>
 827  /// <param name="max">The maximum allowed value of the random generation.</param>
 828  /// <returns>A randomly generated <see cref="decimal"/> value.</returns>
 829  /// <exception cref="ArgumentOutOfRangeException">Called if the range of random generation is too large and therefore 
 830  public static decimal NextDecimal(this Random random, decimal min, decimal max)
 410831  {
 832    try
 410833    {
 410834      decimal next = NextDecimal(random);
 410835      return checked((next < 0 ? -next : next) % (max - min) + min);
 836    }
 1837    catch (OverflowException exception)
 1838    {
 1839      throw new ArgumentOutOfRangeException("The bounds of random generation were to large (min...max).", exception);
 840    }
 409841  }
 842
 843  /// <summary>Generates a random DateTime value.</summary>
 844  /// <param name="random">The random generation algorithm.</param>
 845  /// <returns>A randomly generated DateTime value.</returns>
 846  public static DateTime NextDateTime(this Random random) =>
 0847    NextDateTime(random, DateTime.MaxValue);
 848
 849  /// <summary>Generates a random DateTime value.</summary>
 850  /// <param name="random">The random generation algorithm.</param>
 851  /// <param name="max">The maximum allowed value of the random generation.</param>
 852  /// <returns>A randomly generated DateTime value.</returns>
 853  public static DateTime NextDateTime(this Random random, DateTime max) =>
 0854    NextDateTime(random, DateTime.MinValue, max);
 855
 856  /// <summary>Generates a random DateTime value.</summary>
 857  /// <param name="random">The random generation algorithm.</param>
 858  /// <param name="min">The minimum allowed value of the random generation.</param>
 859  /// <param name="max">The maximum allowed value of the random generation.</param>
 860  /// <returns>A randomly generated DateTime value.</returns>
 861  public static DateTime NextDateTime(this Random random, DateTime min, DateTime max)
 0862  {
 0863    if (random is null) throw new ArgumentNullException(nameof(random));
 0864    if (sourceof(min > max, out string c)) throw new ArgumentException(c);
 0865    TimeSpan randomTimeSpan = NextTimeSpan(random, TimeSpan.Zero, max - min);
 0866    return min.Add(randomTimeSpan);
 0867  }
 868
 869  /// <summary>Generates a random TimeSpan value.</summary>
 870  /// <param name="random">The random generation algorithm.</param>
 871  /// <returns>A randomly generated TimeSpan value.</returns>
 872  public static TimeSpan NextTimeSpan(this Random random) =>
 0873    NextTimeSpan(random, TimeSpan.MaxValue);
 874
 875  /// <summary>Generates a random TimeSpan value.</summary>
 876  /// <param name="random">The random generation algorithm.</param>
 877  /// <param name="max">The maximum allowed value of the random generation.</param>
 878  /// <returns>A randomly generated TimeSpan value.</returns>
 879  public static TimeSpan NextTimeSpan(this Random random, TimeSpan max) =>
 0880    NextTimeSpan(random, TimeSpan.Zero, max);
 881
 882  /// <summary>Generates a random TimeSpan value.</summary>
 883  /// <param name="random">The random generation algorithm.</param>
 884  /// <param name="min">The minimum allowed value of the random generation.</param>
 885  /// <param name="max">The maximum allowed value of the random generation.</param>
 886  /// <returns>A randomly generated TimeSpan value.</returns>
 887  public static TimeSpan NextTimeSpan(this Random random, TimeSpan min, TimeSpan max)
 0888  {
 0889    if (random is null) throw new ArgumentNullException(nameof(random));
 0890    if (sourceof(min > max, out string c)) throw new ArgumentException(c);
 0891    long tickRange = max.Ticks - min.Ticks;
 0892    long randomLong = random.NextInt64(0, tickRange);
 0893    return TimeSpan.FromTicks(min.Ticks + randomLong);
 0894  }
 895
 896  #region Next (with exclusions)
 897
 898  /// <inheritdoc cref="Next{Random}(int, int, int, ReadOnlySpan{int}, Action{int}, Random)"/>
 899  public static void Next(this Random random, int count, int minValue, int maxValue, ReadOnlySpan<int> excluded, Action<
 0900    Next<RandomNextIntMinValueIntMaxValue>(count, minValue, maxValue, excluded, step, random ?? new Random());
 901
 902  /// <inheritdoc cref="Next(Random, int, int, int, ReadOnlySpan{int}, Action{int})"/>
 903  public static void NextRollTracking(this Random random, int count, int minValue, int maxValue, ReadOnlySpan<int> exclu
 0904    NextRollTracking<RandomNextIntMinValueIntMaxValue>(count, minValue, maxValue, excluded, step, random ?? new Random()
 905
 906  /// <inheritdoc cref="Next(Random, int, int, int, ReadOnlySpan{int}, Action{int})"/>
 907  public static void NextPoolTracking(this Random random, int count, int minValue, int maxValue, ReadOnlySpan<int> exclu
 0908    NextPoolTracking<RandomNextIntMinValueIntMaxValue>(count, minValue, maxValue, excluded, step, random ?? new Random()
 909
 910  /// <inheritdoc cref="Next{Random}(int, int, int, ReadOnlySpan{int}, Random)"/>
 911  public static int[] Next(this Random random, int count, int minValue, int maxValue, ReadOnlySpan<int> excluded) =>
 0912    Next<RandomNextIntMinValueIntMaxValue>(count, minValue, maxValue, excluded, random ?? new Random());
 913
 914  /// <inheritdoc cref="Next(Random, int, int, int, ReadOnlySpan{int})"/>
 915  public static int[] NextRollTracking(this Random random, int count, int minValue, int maxValue, ReadOnlySpan<int> excl
 1000916    NextRollTracking<RandomNextIntMinValueIntMaxValue>(count, minValue, maxValue, excluded, random ?? new Random());
 917
 918  /// <inheritdoc cref="Next(Random, int, int, int, ReadOnlySpan{int})"/>
 919  public static int[] NextPoolTracking(this Random random, int count, int minValue, int maxValue, ReadOnlySpan<int> excl
 1000920    NextPoolTracking<RandomNextIntMinValueIntMaxValue>(count, minValue, maxValue, excluded, random ?? new Random());
 921
 922  /// <inheritdoc cref="Next{Step, Random}(int, int, int, ReadOnlySpan{int}, Random, Step)"/>
 923  public static void Next<TStep>(this Random random, int count, int minValue, int maxValue, ReadOnlySpan<int> excluded, 
 924    where TStep : struct, IAction<int> =>
 0925    Next<TStep, RandomNextIntMinValueIntMaxValue>(count, minValue, maxValue, excluded, random ?? new Random(), step);
 926
 927  /// <inheritdoc cref="Next{Step}(Random, int, int, int, ReadOnlySpan{int}, Step)"/>
 928  public static void NextRollTracking<TStep>(this Random random, int count, int minValue, int maxValue, ReadOnlySpan<int
 929    where TStep : struct, IAction<int> =>
 0930    NextRollTracking<TStep, RandomNextIntMinValueIntMaxValue>(count, minValue, maxValue, excluded, random ?? new Random(
 931
 932  /// <inheritdoc cref="Next{Step}(Random, int, int, int, ReadOnlySpan{int}, Step)"/>
 933  public static void NextPoolTracking<TStep>(this Random random, int count, int minValue, int maxValue, ReadOnlySpan<int
 934    where TStep : struct, IAction<int> =>
 0935    NextPoolTracking<TStep, RandomNextIntMinValueIntMaxValue>(count, minValue, maxValue, excluded, random ?? new Random(
 936
 937  #endregion
 938
 939  #region NextUnique
 940
 941  /// <inheritdoc cref="NextUnique{Random}(int, int, int, Action{int}, Random)"/>
 942  public static void NextUnique(this Random random, int count, int minValue, int maxValue, Action<int> step) =>
 20010943    NextUnique<RandomNextIntMinValueIntMaxValue>(count, minValue, maxValue, step, random ?? new Random());
 944
 945  /// <inheritdoc cref="NextUnique(Random, int, int, int, Action{int})"/>
 946  public static void NextUniqueRollTracking(this Random random, int count, int minValue, int maxValue, Action<int> step)
 0947    NextUniqueRollTracking<RandomNextIntMinValueIntMaxValue>(count, minValue, maxValue, step, random ?? new Random());
 948
 949  /// <inheritdoc cref="NextUnique(Random, int, int, int, Action{int})"/>
 950  public static void NextUniquePoolTracking(this Random random, int count, int minValue, int maxValue, Action<int> step)
 0951    NextUniquePoolTracking<RandomNextIntMinValueIntMaxValue>(count, minValue, maxValue, step, random ?? new Random());
 952
 953  /// <inheritdoc cref="NextUnique{Random}(int, int, int, Random)"/>
 954  public static int[] NextUnique(this Random random, int count, int minValue, int maxValue) =>
 0955    NextUnique<RandomNextIntMinValueIntMaxValue>(count, minValue, maxValue, random ?? new Random());
 956
 957  /// <inheritdoc cref="NextUnique(Random, int, int, int)"/>
 958  public static int[] NextUniqueRollTracking(this Random random, int count, int minValue, int maxValue) =>
 0959    NextUniqueRollTracking<RandomNextIntMinValueIntMaxValue>(count, minValue, maxValue, random ?? new Random());
 960
 961  /// <inheritdoc cref="NextUnique(Random, int, int, int)"/>
 962  public static int[] NextUniquePoolTracking(this Random random, int count, int minValue, int maxValue) =>
 0963    NextUniquePoolTracking<RandomNextIntMinValueIntMaxValue>(count, minValue, maxValue, random ?? new Random());
 964
 965  /// <inheritdoc cref="NextUnique{Step, Random}(int, int, int, Random, Step)"/>
 966  public static void NextUnique<TStep>(this Random random, int count, int minValue, int maxValue, TStep step = default)
 967    where TStep : struct, IAction<int> =>
 0968    NextUnique<TStep, RandomNextIntMinValueIntMaxValue>(count, minValue, maxValue, random ?? new Random(), step);
 969
 970  /// <inheritdoc cref="NextUnique{Step}(Random, int, int, int, Step)"/>
 971  public static void NextUniqueRollTracking<TStep>(this Random random, int count, int minValue, int maxValue, TStep step
 972    where TStep : struct, IAction<int> =>
 0973    NextUniqueRollTracking<TStep, RandomNextIntMinValueIntMaxValue>(count, minValue, maxValue, random ?? new Random(), s
 974
 975  /// <inheritdoc cref="NextUnique{Step}(Random, int, int, int, Step)"/>
 976  public static void NextUniquePoolTracking<TStep>(this Random random, int count, int minValue, int maxValue, TStep step
 977    where TStep : struct, IAction<int> =>
 0978    NextUniquePoolTracking<TStep, RandomNextIntMinValueIntMaxValue>(count, minValue, maxValue, random ?? new Random(), s
 979
 980  #endregion
 981
 982  #region NextUnique (with exclusions)
 983
 984  /// <inheritdoc cref="NextUnique{Random}(int, int, int, ReadOnlySpan{int}, Action{int}, Random)"/>
 985  public static void NextUnique(this Random random, int count, int minValue, int maxValue, ReadOnlySpan<int> excluded, A
 0986    NextUnique<RandomNextIntMinValueIntMaxValue>(count, minValue, maxValue, excluded, step, random ?? new Random());
 987
 988  /// <inheritdoc cref="NextUnique(Random, int, int, int, ReadOnlySpan{int}, Action{int})"/>
 989  public static void NextUniqueRollTracking(this Random random, int count, int minValue, int maxValue, ReadOnlySpan<int>
 0990    NextUniqueRollTracking<RandomNextIntMinValueIntMaxValue>(count, minValue, maxValue, excluded, step, random ?? new Ra
 991
 992  /// <inheritdoc cref="NextUnique(Random, int, int, int, ReadOnlySpan{int}, Action{int})"/>
 993  public static void NextUniquePoolTracking(this Random random, int count, int minValue, int maxValue, ReadOnlySpan<int>
 0994    NextUniquePoolTracking<RandomNextIntMinValueIntMaxValue>(count, minValue, maxValue, excluded, step, random ?? new Ra
 995
 996  /// <inheritdoc cref="NextUnique{Random}(int, int, int, ReadOnlySpan{int}, Random)"/>
 997  public static int[] NextUnique(this Random random, int count, int minValue, int maxValue, ReadOnlySpan<int> excluded) 
 0998    NextUnique<RandomNextIntMinValueIntMaxValue>(count, minValue, maxValue, excluded, random ?? new Random());
 999
 1000  /// <inheritdoc cref="NextUnique(Random, int, int, int, ReadOnlySpan{int})"/>
 1001  public static int[] NextUniqueRollTracking(this Random random, int count, int minValue, int maxValue, ReadOnlySpan<int
 10001002    NextUniqueRollTracking<RandomNextIntMinValueIntMaxValue>(count, minValue, maxValue, excluded, random ?? new Random()
 1003
 1004  /// <inheritdoc cref="NextUnique(Random, int, int, int, ReadOnlySpan{int})"/>
 1005  public static int[] NextUniquePoolTracking(this Random random, int count, int minValue, int maxValue, ReadOnlySpan<int
 10001006    NextUniquePoolTracking<RandomNextIntMinValueIntMaxValue>(count, minValue, maxValue, excluded, random ?? new Random()
 1007
 1008  /// <inheritdoc cref="NextUnique{Step, Random}(int, int, int, ReadOnlySpan{int}, Random, Step)"/>
 1009  public static void NextUnique<TStep>(this Random random, int count, int minValue, int maxValue, ReadOnlySpan<int> excl
 1010    where TStep : struct, IAction<int> =>
 01011    NextUnique<TStep, RandomNextIntMinValueIntMaxValue>(count, minValue, maxValue, excluded, random ?? new Random(), ste
 1012
 1013  /// <inheritdoc cref="NextUnique{Step}(Random, int, int, int, ReadOnlySpan{int}, Step)"/>
 1014  public static void NextUniqueRollTracking<TStep>(this Random random, int count, int minValue, int maxValue, ReadOnlySp
 1015    where TStep : struct, IAction<int> =>
 01016    NextUniqueRollTracking<TStep, RandomNextIntMinValueIntMaxValue>(count, minValue, maxValue, excluded, random ?? new R
 1017
 1018  /// <inheritdoc cref="NextUnique{Step}(Random, int, int, int, ReadOnlySpan{int}, Step)"/>
 1019  public static void NextUniquePoolTracking<TStep>(this Random random, int count, int minValue, int maxValue, ReadOnlySp
 1020    where TStep : struct, IAction<int> =>
 01021    NextUniquePoolTracking<TStep, RandomNextIntMinValueIntMaxValue>(count, minValue, maxValue, excluded, random ?? new R
 1022
 1023  #endregion
 1024
 1025  /// <summary>Chooses a value at random from <paramref name="values"/>.</summary>
 1026  /// <typeparam name="T">The generic type of the items to choose from.</typeparam>
 1027  /// <param name="random">The random algorithm for index generation.</param>
 1028  /// <param name="values">The values to choose from.</param>
 1029  /// <returns>A randomly selected value from the supplied options.</returns>
 1030  public static T From<T>(this Random random, params T[] values)
 01031  {
 01032    if (values is null) throw new ArgumentNullException(nameof(values));
 01033    if (sourceof(values.Length < 1, out string c)) throw new ArgumentException(c, nameof(values));
 01034    return values[random.Next(values.Length)];
 01035  }
 1036
 1037  /// <inheritdoc cref="From{T}(Random, T[])"/>
 1038  public static T From<T>(this Random random, ReadOnlySpan<T> values)
 01039  {
 01040    if (sourceof(values.IsEmpty, out string c)) throw new ArgumentException(c, nameof(values));
 01041    return values[random.Next(values.Length)];
 01042  }
 1043
 1044  /// <inheritdoc cref="From{T}(Random, T[])"/>
 1045  public static T From<T>(this Random random, System.Collections.Generic.IList<T> values)
 01046  {
 01047    if (values is null) throw new ArgumentNullException(nameof(values));
 01048    if (sourceof(values.Count < 1, out string c)) throw new ArgumentException(c);
 01049    return values[random.Next(values.Count)];
 01050  }
 1051
 1052  /// <summary>Selects a random value from a collection of weighted options.</summary>
 1053  /// <typeparam name="T">The generic type to select a random instance of.</typeparam>
 1054  /// <param name="random">The random algorithm.</param>
 1055  /// <param name="pool">The pool of weighted values to choose from.</param>
 1056  /// <returns>A randomly selected value from the weighted pool.</returns>
 1057  public static T Next<T>(this Random random, params (T Value, double Weight)[] pool) =>
 01058    random.Next((System.Collections.Generic.IEnumerable<(T Value, double Weight)>)pool);
 1059
 1060  /// <summary>Selects a random value from a collection of weighted options.</summary>
 1061  /// <typeparam name="T">The generic type to select a random instance of.</typeparam>
 1062  /// <param name="random">The random algorithm.</param>
 1063  /// <param name="totalWeight">The total weight of all the values in the pool.</param>
 1064  /// <param name="pool">The pool of weighted values to choose from.</param>
 1065  /// <returns>A randomly selected value from the weighted pool.</returns>
 1066  public static T Next<T>(this Random random, double totalWeight, params (T Value, double Weight)[] pool) =>
 01067    random.Next(pool, totalWeight);
 1068
 1069  /// <summary>Selects a random value from a collection of weighted options.</summary>
 1070  /// <typeparam name="T">The generic type to select a random instance of.</typeparam>
 1071  /// <param name="random">The random algorithm.</param>
 1072  /// <param name="pool">The pool of weighted values to choose from.</param>
 1073  /// <param name="totalWeight">The total weight of all the values in the pool.</param>
 1074  /// <returns>A randomly selected value from the weighted pool.</returns>
 1075  public static T Next<T>(this Random random, System.Collections.Generic.IEnumerable<(T Value, double Weight)> pool, dou
 01076  {
 01077    if (!totalWeight.HasValue)
 01078    {
 01079      totalWeight = 0;
 01080      foreach (var (Value, Weight) in pool)
 01081      {
 01082        if (Weight < 0)
 01083          throw new ArgumentOutOfRangeException(nameof(pool), $"A value in {nameof(pool)} had a weight less than zero.")
 01084        totalWeight += Weight;
 01085      }
 01086    }
 1087    else
 01088    {
 01089      if (totalWeight < 0)
 01090        throw new ArgumentOutOfRangeException(nameof(totalWeight), $"The provided {nameof(totalWeight)} of the {nameof(p
 01091    }
 01092    if (totalWeight is 0)
 01093      throw new ArgumentOutOfRangeException(nameof(pool), $"The total weight of all values in the {nameof(pool)} was zer
 01094    if (double.IsInfinity(totalWeight.Value))
 01095      throw new ArgumentOutOfRangeException(nameof(pool), $"The total weight of all values in the {nameof(pool)} was an 
 01096    double randomDouble = random.NextDouble();
 01097    double range = 0;
 01098    foreach (var (Value, Weight) in pool)
 01099    {
 01100      range += Weight;
 01101      if (range > totalWeight)
 01102        throw new ArgumentOutOfRangeException(nameof(totalWeight), $"The provided {nameof(totalWeight)} of the {nameof(p
 01103      if (randomDouble < range / totalWeight)
 01104        return Value;
 01105    }
 01106    throw new TowelBugException("There is a bug in the code.");
 01107  }
 1108
 1109#if false
 1110
 1111    //public static T Next<T>(this Random random, StepperBreak<(T Value, double Weight)> pool, double? totalWeight = nul
 1112    //{
 1113    //  if (!totalWeight.HasValue)
 1114    //  {
 1115    //    totalWeight = 0;
 1116    //    pool(x =>
 1117    //    {
 1118    //      if (x.Weight < 0)
 1119    //        throw new ArgumentOutOfRangeException("A value in the pool had a weight less than zero.");
 1120    //      totalWeight += x.Weight;
 1121    //      return Continue;
 1122    //    });
 1123    //  }
 1124    //  else
 1125    //  {
 1126    //    if (totalWeight < 0)
 1127    //      throw new ArgumentOutOfRangeException("The provided total weight of the pool was less than zero.");
 1128    //  }
 1129    //  if (totalWeight is 0)
 1130    //    throw new ArgumentOutOfRangeException("The total weight of all values in the pool was zero.");
 1131    //  if (double.IsInfinity(totalWeight.Value))
 1132    //    throw new ArgumentOutOfRangeException("The total weight of all values in the pool was an infinite double.");
 1133    //  double randomDouble = random.NextDouble();
 1134    //  double range = 0;
 1135    //  T @return = default;
 1136    //  StepStatus status = pool(x =>
 1137    //  {
 1138    //    range += x.Weight;
 1139    //    if (range > totalWeight)
 1140    //      throw new ArgumentOutOfRangeException("The provided total weight of the pool was less than the actual total 
 1141    //    if (randomDouble < range / totalWeight)
 1142    //    {
 1143    //      @return = x.Value;
 1144    //      return Break;
 1145    //    }
 1146    //    return Continue;
 1147    //  });
 1148    //  return status is Break
 1149    //    ? @return
 1150    //    : throw new TowelBugException("There is a bug in the code.");
 1151    //}
 1152
 1153#endif
 1154
 1155  #endregion
 1156}

/home/runner/work/Towel/Towel/Sources/Towel/Statics-RomanNumerals.cs

#LineLine coverage
 1namespace Towel;
 2
 3/// <summary>Root type of the static functional methods in Towel.</summary>
 4public static partial class Statics
 5{
 16  internal static readonly int[] RomanNumeralDigits =
 17  {
 18    /* 0:I */ 1,
 19    /* 1:V */ 5,
 110    /* 2:X */ 10,
 111    /* 3:L */ 50,
 112    /* 4:C */ 100,
 113    /* 5:D */ 500,
 114    /* 6:M */ 1000,
 115  };
 16
 117  internal static readonly int[] RomanNumeralDigitsAllowedPrefix =
 118  {
 119    /* 0:I */ default,
 120    /* 1:V */ 0,
 121    /* 2:X */ 0,
 122    /* 3:L */ 2,
 123    /* 4:C */ 2,
 124    /* 5:D */ 4,
 125    /* 6:M */ 4,
 126  };
 27
 128  internal static readonly bool[] RomanNumeralDigitsAllowsDuplicates =
 129  {
 130    /* 0:I */ true,
 131    /* 1:V */ false,
 132    /* 2:X */ true,
 133    /* 3:L */ false,
 134    /* 4:C */ true,
 135    /* 5:D */ false,
 136    /* 6:M */ true,
 137  };
 38
 39  /// <summary>Attempts to parse a Roman Numeral string into an <see cref="int"/> value.</summary>
 40  /// <param name="span">The Roman Numeral string to parse into an <see cref="int"/> value.</param>
 41  /// <returns>
 42  /// - <see cref="bool"/> Success: true if the parse was successful or false if not<br/>
 43  /// - <see cref="int"/> Value: the parsed value if the parse was successful or default if not
 44  /// </returns>
 45  public static (bool Success, int Value) TryParseRomanNumeral(ReadOnlySpan<char> span)
 405846  {
 405847    if (span.Length < 1)
 248    {
 249      return (false, default);
 50    }
 405651    int result = 0;
 405652    int a = default;
 405653    int? b = null;
 405654    int? c = null;
 405655    int? d = null;
 405656    bool handled = false;
 7254257    foreach (char @char in span)
 3018958    {
 3018959      switch (@char)
 60      {
 1134261        case 'I': a = 0; break;
 405062        case 'V': a = 1; break;
 1215063        case 'X': a = 2; break;
 402264        case 'L': a = 3; break;
 1200265        case 'C': a = 4; break;
 400266        case 'D': a = 5; break;
 1280267        case 'M': a = 6; break;
 468        default: return (false, default);
 69      }
 3018570      if ((c.HasValue && c.Value < a) ||
 3018571        (a == b && a == c && a == d) ||
 3018572        (b.HasValue && b.Value < a && b.Value != RomanNumeralDigitsAllowedPrefix[a]) ||
 3018573        (b == a && !RomanNumeralDigitsAllowsDuplicates[a]))
 074      {
 075        return (false, default);
 76      }
 3018577      else if (!handled && b.HasValue && b.Value < a)
 242078      {
 242079        result += RomanNumeralDigits[a] - RomanNumeralDigits[b.Value];
 242080        handled = true;
 242081      }
 2776582      else if (handled)
 152183      {
 152184        handled = false;
 152185      }
 2624486      else if (b.HasValue)
 2219187      {
 2219188        result += RomanNumeralDigits[b.Value];
 2219189      }
 3018590      d = c;
 3018591      c = b;
 3018592      b = a;
 3018593    }
 405294    if (!handled)
 315395    {
 315396      result += RomanNumeralDigits[a];
 315397    }
 405298    return (true, result);
 405899  }
 100
 101  /// <summary>Converts an <see cref="int"/> <paramref name="value"/> to a roman numeral <see cref="string"/>?.</summary
 102  /// <param name="value">The value to represent as a roman numeral. [min: 1] [max: 3999]</param>
 103  /// <returns>
 104  /// - <see cref="bool"/> Success: true if <paramref name="value"/> was converted to a roman numeral <see cref="string"
 105  /// - <see cref="string"/>? RomanNumeral: the resulting roman numeral <see cref="string"/>? if successful or null if n
 106  /// </returns>
 107  public static (bool Success, string? RomanNumeral) TryToRomanNumeral(int value)
 4056108  {
 4060109    if (value < 1 || value > 3999) return (false, null);
 4052110    SpanBuilder<char> span = stackalloc char[15];
 31816111    while (value > 0)
 27764112    {
 27764113      switch (value)
 114      {
 18003115        case >= 1000: span.Append( 'M'); value -= 1000; break;
 1200116        case >=  900: span.Append("CM"); value -=  900; break;
 4803117        case >=  500: span.Append( 'D'); value -=  500; break;
 1200118        case >=  400: span.Append("CD"); value -=  400; break;
 14403119        case >=  100: span.Append( 'C'); value -=  100; break;
 1200120        case >=   90: span.Append("XC"); value -=   90; break;
 4803121        case >=   50: span.Append( 'L'); value -=   50; break;
 1230122        case >=   40: span.Append("XL"); value -=   40; break;
 14580123        case >=   10: span.Append( 'X'); value -=   10; break;
 1215124        case >=    9: span.Append("IX"); value -=    9; break;
 4860125        case >=    5: span.Append( 'V'); value -=    5; break;
 1215126        case >=    4: span.Append("IV"); value -=    4; break;
 14580127        case >=    1: span.Append( 'I'); value -=    1; break;
 128      }
 27764129    }
 4052130    return (true, new string(span));
 4056131  }
 132}

/home/runner/work/Towel/Towel/Sources/Towel/Statics-SearchingAlgorithms.cs

#LineLine coverage
 1namespace Towel;
 2
 3/// <summary>Root type of the static functional methods in Towel.</summary>
 4public static partial class Statics
 5{
 6  #region SearchBinary
 7
 8#pragma warning disable CS1711, CS1572, CS1734, CS1735, SA1617
 9
 10  /// <summary>Performs a binary search on sorted indexed data.</summary>
 11  /// <typeparam name="T">The type of values to search through.</typeparam>
 12  /// <typeparam name="TGet">The type of function for getting an element at an index.</typeparam>
 13  /// <typeparam name="TSift">The type of function for sifting through the values.</typeparam>
 14  /// <typeparam name="TCompare">The type of compare function.</typeparam>
 15  /// <param name="index">The starting index of the binary search.</param>
 16  /// <param name="length">The number of values to be searched after the starting <paramref name="index"/>.</param>
 17  /// <param name="get">The function for getting an element at an index.</param>
 18  /// <param name="sift">The function for comparing the the values to th desired target.</param>
 19  /// <param name="array">The array search.</param>
 20  /// <param name="element">The element to search for.</param>
 21  /// <param name="compare">The compare function.</param>
 22  /// <param name="span">The span of the binary search.</param>
 23  /// <returns>
 24  /// - <see cref="bool"/> Found: True if a match was found; False if not.<br/>
 25  /// - <see cref="int"/> Index: The resulting index of the search that will always be &lt;= the desired match.<br/>
 26  /// - <typeparamref name="T"/> Value: The resulting value of the binary search if a match was found or default if not.
 27  /// </returns>
 28  [Obsolete(NotIntended, true)]
 129  public static void XML_SearchBinary() => throw new DocumentationMethodException();
 30
 31#pragma warning restore CS1711, CS1572, CS1734, CS1735, SA1617
 32
 33  /// <inheritdoc cref="XML_SearchBinary"/>
 34  public static (bool Found, int Index, T? Value) SearchBinary<T>(int length, Func<int, T> get, Func<T, CompareResult> s
 035  {
 036    if (get is null) throw new ArgumentNullException(nameof(get));
 037    if (sift is null) throw new ArgumentNullException(nameof(sift));
 038    return SearchBinary<T, SFunc<int, T>, SFunc<T, CompareResult>>(0, length, get, sift);
 039  }
 40
 41  /// <inheritdoc cref="XML_SearchBinary"/>
 42  public static (bool Found, int Index, T? Value) SearchBinary<T, TGet, TSift>(int index, int length, TGet get = default
 43    where TGet : struct, IFunc<int, T>
 44    where TSift : struct, IFunc<T, CompareResult>
 045  {
 046    if (length <= 0)
 047    {
 048      throw new ArgumentOutOfRangeException(nameof(length), length, "!(" + nameof(length) + " > 0)");
 49    }
 050    if (index < 0)
 051    {
 052      throw new ArgumentOutOfRangeException(nameof(index), index, "!(" + nameof(index) + " > 0)");
 53    }
 054    if (length > int.MaxValue / 2 && index > int.MaxValue / 2)
 055    {
 056      throw new ArgumentOutOfRangeException($"{nameof(length)} > {int.MaxValue / 2} && {nameof(index)} / {int.MaxValue /
 57    }
 058    int low = index;
 059    int hi = index + length - 1;
 060    while (low <= hi)
 061    {
 062      int median = low + (hi - low) / 2;
 063      T value = get.Invoke(median);
 064      CompareResult compareResult = sift.Invoke(value);
 065      switch (compareResult)
 66      {
 067        case Less: low = median + 1; break;
 068        case Greater: hi = median - 1; break;
 069        case Equal: return (true, median, value);
 70        default:
 071          throw compareResult.IsDefined()
 072          ? (Exception)new TowelBugException($"Unhandled {nameof(CompareResult)} value: {compareResult}.")
 073          : new ArgumentException($"Invalid {nameof(TSift)} function; an undefined {nameof(CompareResult)} was returned.
 74      }
 075    }
 076    return (false, Math.Min(low, hi), default);
 077  }
 78
 79  /// <inheritdoc cref="XML_SearchBinary"/>
 80  public static (bool Found, int Index, T? Value) SearchBinary<T>(ReadOnlySpan<T> span, T element, Func<T, T, CompareRes
 4181    SearchBinary<T, SiftFromCompareAndValue<T, SFunc<T, T, CompareResult>>>(span, new SiftFromCompareAndValue<T, SFunc<T
 82
 83  /// <inheritdoc cref="XML_SearchBinary"/>
 84  public static (bool Found, int Index, T? Value) SearchBinary<T>(ReadOnlySpan<T> span, Func<T, CompareResult> sift)
 185  {
 186    if (sift is null) throw new ArgumentNullException(nameof(sift));
 187    return SearchBinary<T, SFunc<T, CompareResult>>(span, sift);
 088  }
 89
 90  /// <inheritdoc cref="XML_SearchBinary"/>
 91  public static (bool Found, int Index, T? Value) SearchBinary<T, TCompare>(ReadOnlySpan<T> span, T element, TCompare co
 92    where TCompare : struct, IFunc<T, T, CompareResult> =>
 093    SearchBinary<T, SiftFromCompareAndValue<T, TCompare>>(span, new SiftFromCompareAndValue<T, TCompare>(element, compar
 94
 95  /// <inheritdoc cref="XML_SearchBinary"/>
 96  public static (bool Found, int Index, T? Value) SearchBinary<T, TSift>(ReadOnlySpan<T> span, TSift sift = default)
 97    where TSift : struct, IFunc<T, CompareResult>
 4298  {
 4299    if (span.IsEmpty)
 1100    {
 1101      throw new ArgumentException($@"{nameof(span)}.{nameof(span.IsEmpty)}", nameof(span));
 102    }
 41103    int low = 0;
 41104    int hi = span.Length - 1;
 149105    while (low <= hi)
 128106    {
 128107      int median = low + (hi - low) / 2;
 128108      T value = span[median];
 128109      CompareResult compareResult = sift.Invoke(value);
 128110      switch (compareResult)
 111      {
 126112        case Less: low = median + 1; break;
 90113        case Greater: hi = median - 1; break;
 19114        case Equal: return (true, median, value);
 115        default:
 1116          throw compareResult.IsDefined()
 1117          ? (Exception)new TowelBugException($"Unhandled {nameof(CompareResult)} value: {compareResult}.")
 1118          : new ArgumentException($"Invalid {nameof(TSift)} function; an undefined {nameof(CompareResult)} was returned.
 119      }
 108120    }
 21121    return (false, Math.Min(low, hi), default);
 40122  }
 123
 124  #endregion
 125
 126  #region Search Graph Algorithms
 127
 128  #region Publics
 129
 130  /// <summary>The status of a graph search algorithm.</summary>
 131  public enum GraphSearchStatus
 132  {
 133    /// <summary>Graph search was not broken.</summary>
 134    Continue = StepStatus.Continue,
 135    /// <summary>Graph search was broken.</summary>
 136    Break = StepStatus.Break,
 137    /// <summary>Graph search found the goal.</summary>
 138    Goal = 2,
 139  }
 140
 141  /// <summary>Syntax sugar hacks.</summary>
 142  public static class GraphSyntax
 143  {
 144    /// <summary>This is a syntax sugar hack to allow implicit conversions from StepStatus to GraphSearchStatus.</summar
 145    public struct GraphSearchStatusStruct
 146    {
 147      internal readonly GraphSearchStatus Value;
 148      /// <summary>Constructs a new graph search status.</summary>
 149      /// <param name="value">The status of the graph search.</param>
 33150      public GraphSearchStatusStruct(GraphSearchStatus value) => Value = value;
 151      /// <summary>Converts a <see cref="GraphSearchStatus"/> into a <see cref="GraphSearchStatusStruct"/>.</summary>
 152      /// <param name="value">The <see cref="GraphSearchStatus"/> to convert.</param>
 33153      public static implicit operator GraphSearchStatusStruct(GraphSearchStatus value) => new(value);
 154      /// <summary>Converts a <see cref="StepStatus"/> into a <see cref="GraphSearchStatusStruct"/>.</summary>
 155      /// <param name="value">The <see cref="StepStatus"/> to convert.</param>
 0156      public static implicit operator GraphSearchStatusStruct(StepStatus value) => new((GraphSearchStatus)value);
 157      /// <summary>Converts a <see cref="GraphSearchStatusStruct"/> into a <see cref="GraphSearchStatus"/>.</summary>
 158      /// <param name="value">The <see cref="GraphSearchStatusStruct"/> to convert.</param>
 33159      public static implicit operator GraphSearchStatus(GraphSearchStatusStruct value) => value.Value;
 160    }
 161  }
 162
 163  /// <summary>Step function for all neigbors of a given node.</summary>
 164  /// <typeparam name="TNode">The node type of the graph being searched.</typeparam>
 165  /// <param name="current">The node to step through all the neighbors of.</param>
 166  /// <param name="neighbors">Step function to perform on all neighbors.</param>
 167  public delegate void SearchNeighbors<TNode>(TNode current, Action<TNode> neighbors);
 168  /// <summary>Computes the heuristic value of a given node in a graph (smaller values mean closer to goal node).</summa
 169  /// <typeparam name="TNode">The node type of the graph being searched.</typeparam>
 170  /// <typeparam name="TNumeric">The numeric to use when performing calculations.</typeparam>
 171  /// <param name="node">The node to compute the heuristic value of.</param>
 172  /// <returns>The computed heuristic value for this node.</returns>
 173  public delegate TNumeric SearchHeuristic<TNode, TNumeric>(TNode node);
 174  /// <summary>Computes the cost of moving from the current node to a specific neighbor.</summary>
 175  /// <typeparam name="TNode">The node type of the graph being searched.</typeparam>
 176  /// <typeparam name="TNumeric">The numeric to use when performing calculations.</typeparam>
 177  /// <param name="current">The current (starting) node.</param>
 178  /// <param name="neighbor">The node to compute the cost of movign to.</param>
 179  /// <returns>The computed cost value of movign from current to neighbor.</returns>
 180  public delegate TNumeric SearchCost<TNode, TNumeric>(TNode current, TNode neighbor);
 181  /// <summary>Predicate for determining if we have reached the goal node.</summary>
 182  /// <typeparam name="TNode">The node type of the graph being searched.</typeparam>
 183  /// <param name="current">The current node.</param>
 184  /// <returns>True if the current node is a/the goal node; False if not.</returns>
 185  public delegate bool SearchGoal<TNode>(TNode current);
 186  /// <summary>Checks the status of a graph search.</summary>
 187  /// <typeparam name="TNode">The node type of the search.</typeparam>
 188  /// <param name="current">The current node of the search.</param>
 189  /// <returns>The status of the search.</returns>
 190  public delegate GraphSyntax.GraphSearchStatusStruct SearchCheck<TNode>(TNode current);
 191
 192  #endregion
 193
 194  #region Internals
 195
 196  internal abstract class BaseAlgorithmNode<TAlgorithmNode, TNode>
 197    where TAlgorithmNode : BaseAlgorithmNode<TAlgorithmNode, TNode>
 198  {
 199    internal TAlgorithmNode? Previous;
 200    internal TNode Value;
 201
 48202    internal BaseAlgorithmNode(TNode value, TAlgorithmNode? previous = null)
 48203    {
 48204      Value = value;
 48205      Previous = previous;
 48206    }
 207  }
 208
 209  internal class BreadthFirstSearch<TNode> : BaseAlgorithmNode<BreadthFirstSearch<TNode>, TNode>
 210  {
 211    internal BreadthFirstSearch(TNode value, BreadthFirstSearch<TNode>? previous = null)
 36212      : base(value: value, previous: previous) { }
 213  }
 214
 215  internal class DijkstraNode<TNode, TNumeric> : BaseAlgorithmNode<DijkstraNode<TNode, TNumeric>, TNode>
 216  {
 217    internal TNumeric Priority;
 218
 219    internal DijkstraNode(TNode value, TNumeric priority, DijkstraNode<TNode, TNumeric>? previous = null)
 0220      : base(value: value, previous: previous)
 0221    {
 0222      Priority = priority;
 0223    }
 224  }
 225
 226  internal class AstarNode<TNode, TNumeric> : BaseAlgorithmNode<AstarNode<TNode, TNumeric>, TNode>
 227  {
 228    internal TNumeric Priority;
 229    internal TNumeric Cost;
 230
 231    internal AstarNode(TNode value, TNumeric priority, TNumeric cost, AstarNode<TNode, TNumeric>? previous = null)
 36232      : base(value: value, previous: previous)
 36233    {
 36234      Priority = priority;
 36235      Cost = cost;
 36236    }
 237  }
 238
 239  internal class PathNode<TNode>
 240  {
 241    internal TNode Value;
 242    internal PathNode<TNode>? Next;
 243
 13244    internal PathNode(TNode value, PathNode<TNode>? next = null)
 13245    {
 13246      Value = value;
 13247      Next = next;
 13248    }
 249  }
 250
 251  internal static Action<Action<TNode>> BuildPath<TAlgorithmNode, TNode>(BaseAlgorithmNode<TAlgorithmNode, TNode> node)
 252    where TAlgorithmNode : BaseAlgorithmNode<TAlgorithmNode, TNode>
 3253  {
 3254    PathNode<TNode>? start = null;
 32255    for (BaseAlgorithmNode<TAlgorithmNode, TNode>? current = node; current is not null; current = current.Previous)
 13256    {
 13257      PathNode<TNode>? temp = start;
 13258      start = new PathNode<TNode>(
 13259        value: current.Value,
 13260        next: temp);
 13261    }
 3262    return step =>
 3263    {
 3264      PathNode<TNode>? current = start;
 16265      while (current is not null)
 13266      {
 13267        step(current.Value);
 13268        current = current.Next;
 13269      }
 6270    };
 3271  }
 272
 273  internal struct AStarPriorityCompare<TNode, TNumeric> : IFunc<AstarNode<TNode, TNumeric>, AstarNode<TNode, TNumeric>, 
 274  {
 275    // NOTE: Typical A* implementations prioritize smaller values
 276    public CompareResult Invoke(AstarNode<TNode, TNumeric> a, AstarNode<TNode, TNumeric> b) =>
 98277      Compare(b.Priority, a.Priority);
 278  }
 279
 280  internal struct DijkstraPriorityCompare<TNode, TNumeric> : IFunc<DijkstraNode<TNode, TNumeric>, DijkstraNode<TNode, TN
 281  {
 282    // NOTE: Typical A* implementations prioritize smaller values
 283    public CompareResult Invoke(DijkstraNode<TNode, TNumeric> a, DijkstraNode<TNode, TNumeric> b) =>
 0284      Compare(b.Priority, a.Priority);
 285  }
 286
 287  #endregion
 288
 289  #region Graph (Shared)
 290
 291#pragma warning disable CS1711, CS1572, SA1604, SA1617
 292
 293  /// <typeparam name="TNode">The node type of the graph being searched.</typeparam>
 294  /// <typeparam name="TNumeric">The numeric to use when performing calculations.</typeparam>
 295  /// <param name="start">The node to start at.</param>
 296  /// <param name="neighbors">Step function for all neigbors of a given node.</param>
 297  /// <param name="heuristic">Computes the heuristic value of a given node in a graph.</param>
 298  /// <param name="cost">Computes the cost of moving from the current node to a specific neighbor.</param>
 299  /// <param name="check">Checks the status of the search.</param>
 300  /// <param name="totalCost">The total cost of the path if a path was found.</param>
 301  /// <param name="goal">The goal of the search.</param>
 302  /// <param name="graph">The graph to perform the search on.</param>
 303  /// <returns>Stepper of the shortest path or null if no path exists.</returns>
 304  [Obsolete(NotIntended, true)]
 1305  public static void XML_SearchGraph() => throw new DocumentationMethodException();
 306
 307#pragma warning restore CS1711, CS1572, SA1604, SA1617
 308
 309  #endregion
 310
 311  #region A* Algorithm
 312
 313  /// <summary>Runs the A* search algorithm on a graph.</summary>
 314  /// <inheritdoc cref="XML_SearchGraph"/>
 315  [Obsolete(NotIntended, true)]
 1316  public static void XML_SearchGraph_Astar() => throw new DocumentationMethodException();
 317
 318  /// <inheritdoc cref="XML_SearchGraph_Astar"/>
 319  public static Action<Action<TNode>>? SearchGraph<TNode, TNumeric>(TNode start, SearchNeighbors<TNode> neighbors, Searc
 28320    SearchGraph(start, neighbors, heuristic, cost, node => goal(node) ? GraphSearchStatus.Goal : GraphSearchStatus.Conti
 321
 322  /// <inheritdoc cref="XML_SearchGraph_Astar"/>
 323  public static Action<Action<TNode>>? SearchGraph<TNode, TNumeric>(TNode start, IGraph<TNode> graph, SearchHeuristic<TN
 0324    SearchGraph(start, graph.Neighbors, heuristic, cost, goal, out totalCost);
 325
 326  /// <inheritdoc cref="XML_SearchGraph_Astar"/>
 327  public static Action<Action<TNode>>? SearchGraph<TNode, TNumeric>(TNode start, SearchNeighbors<TNode> neighbors, Searc
 0328    SearchGraph(start, neighbors, heuristic, cost, goal, Equate, out totalCost);
 329
 330  /// <inheritdoc cref="XML_SearchGraph_Astar"/>
 331  public static Action<Action<TNode>>? SearchGraph<TNode, TNumeric>(TNode start, SearchNeighbors<TNode> neighbors, Searc
 0332    SearchGraph(start, neighbors, heuristic, cost, node => equate(node, goal), out totalCost);
 333
 334  /// <inheritdoc cref="XML_SearchGraph_Astar"/>
 335  public static Action<Action<TNode>>? SearchGraph<TNode, TNumeric>(TNode start, IGraph<TNode> graph, SearchHeuristic<TN
 2336    SearchGraph(start, graph, heuristic, cost, goal, Equate, out totalCost);
 337
 338  /// <inheritdoc cref="XML_SearchGraph_Astar"/>
 339  public static Action<Action<TNode>>? SearchGraph<TNode, TNumeric>(TNode start, IGraph<TNode> graph, SearchHeuristic<TN
 28340    SearchGraph(start, graph.Neighbors, heuristic, cost, node => equate(node, goal), out totalCost);
 341
 342  /// <inheritdoc cref="XML_SearchGraph_Astar"/>
 343  public static Action<Action<TNode>>? SearchGraph<TNode, TNumeric>(TNode start, SearchNeighbors<TNode> neighbors, Searc
 2344  {
 345    // using a heap (aka priority queue) to store nodes based on their computed A* f(n) value
 2346    HeapArray<AstarNode<TNode, TNumeric>, AStarPriorityCompare<TNode, TNumeric>> fringe = new();
 347
 348    // push starting node
 2349    fringe.Enqueue(
 2350      new AstarNode<TNode, TNumeric>(
 2351        value: start,
 2352        priority: Constant<TNumeric>.Zero,
 2353        cost: Constant<TNumeric>.Zero,
 2354        previous: null));
 355
 356    // run the algorithm
 26357    while (fringe.Count != 0)
 26358    {
 26359      AstarNode<TNode, TNumeric> current = fringe.Dequeue();
 26360      GraphSearchStatus status = check(current.Value);
 26361      if (status is GraphSearchStatus.Break)
 0362      {
 0363        break;
 364      }
 26365      else if (status is GraphSearchStatus.Goal)
 2366      {
 2367        totalCost = current.Cost;
 2368        return BuildPath(current);
 369      }
 370      else
 24371      {
 24372        neighbors(current.Value,
 24373          neighbor =>
 34374          {
 34375            TNumeric costValue = Addition(current.Cost, cost(current.Value, neighbor));
 34376            fringe.Enqueue(
 34377              new AstarNode<TNode, TNumeric>(
 34378                value: neighbor,
 34379                priority: Addition(heuristic(neighbor), costValue),
 34380                cost: costValue,
 34381                previous: current));
 58382          });
 24383      }
 24384    }
 0385    totalCost = default;
 0386    return null; // goal node was not reached (no path exists)
 2387  }
 388
 389  /// <summary>Perfoms A* Search on the graph</summary>
 390  /// <param name="graph">The weighted graph object</param>
 391  /// <param name="Source">The node to begin search from</param>
 392  /// <param name="Destination">The node to search</param>
 393  /// <param name="CustomHeuristic">The heuristic function of the node</param>
 394  /// <param name="TotalWeight">The total cost or weight incurred from source to destination</param>
 395  /// <typeparam name="TNode">The Node type of the graph</typeparam>
 396  /// <typeparam name="TNumeric">The Numeric type of the weighted graph</typeparam>
 397  /// <returns>IEnumerable of the ordered sequence of nodes from source to destination</returns>
 398  public static System.Collections.Generic.IEnumerable<TNode> AStarSearch<TNode, TNumeric>(this IGraphWeighted<TNode, TN
 1399  {
 1400    ListArray<TNode> path = new();
 1401    var graphPath = SearchGraph<TNode, TNumeric>(start: Source, graph: graph, heuristic: CustomHeuristic, cost: graph.Ge
 1402    TotalWeight = totalWeight ?? Constant<TNumeric>.Zero;
 6403    graphPath?.Invoke(n => path.Add(n));
 1404    return path;
 1405  }
 406
 407  /// <summary>Perfoms A* Search on the graph and executes action on every node in path</summary>
 408  /// <param name="graph">The weighted graph object</param>
 409  /// <param name="Source">The node to begin search from</param>
 410  /// <param name="Destination">The node to search</param>
 411  /// <param name="CustomHeuristic">The heuristic function of the node</param>
 412  /// <param name="action">The action to perform for every node on path</param>
 413  /// <param name="TotalWeight">The total cost or weight incurred from source to destination</param>
 414  /// <typeparam name="TNode">The Node type of the graph</typeparam>
 415  /// <typeparam name="TNumeric">The Numeric type of the weighted graph</typeparam>
 416  public static void AStarSearch<TNode, TNumeric>(this IGraphWeighted<TNode, TNumeric> graph, TNode Source, TNode Destin
 0417  {
 0418    var graphPath = SearchGraph<TNode, TNumeric>(start: Source, graph: graph, heuristic: CustomHeuristic, cost: graph.Ge
 0419    TotalWeight = totalWeight ?? Constant<TNumeric>.Zero;
 0420    if (graphPath != null && action != null) graphPath(n => action(n));
 0421  }
 422
 423  #endregion
 424
 425  #region Dijkstra Algorithm
 426
 427  /// <summary>Runs the Dijkstra search algorithm on a graph.</summary>
 428  /// <inheritdoc cref="XML_SearchGraph"/>
 429  [Obsolete(NotIntended, true)]
 1430  public static void XML_SearchGraph_Dijkstra() => throw new DocumentationMethodException();
 431
 432  /// <inheritdoc cref="XML_SearchGraph_Dijkstra"/>
 433  public static Action<Action<TNode>>? SearchGraph<TNode, TNumeric>(TNode start, SearchNeighbors<TNode> neighbors, Searc
 0434    SearchGraph(start, neighbors, heuristic, node => goal(node) ? GraphSearchStatus.Goal : GraphSearchStatus.Continue);
 435
 436  /// <inheritdoc cref="XML_SearchGraph_Dijkstra"/>
 437  public static Action<Action<TNode>>? SearchGraph<TNode, TNumeric>(TNode start, SearchNeighbors<TNode> neighbors, Searc
 0438    SearchGraph(start, neighbors, heuristic, goal, Equate);
 439
 440  /// <inheritdoc cref="XML_SearchGraph_Dijkstra"/>
 441  public static Action<Action<TNode>>? SearchGraph<TNode, TNumeric>(TNode start, SearchNeighbors<TNode> neighbors, Searc
 0442    SearchGraph(start, neighbors, heuristic, node => equate(node, goal));
 443
 444  /// <inheritdoc cref="XML_SearchGraph_Dijkstra"/>
 445  public static Action<Action<TNode>>? SearchGraph<TNode, TNumeric>(TNode start, IGraph<TNode> graph, SearchHeuristic<TN
 0446    SearchGraph(start, graph, heuristic, goal, Equate);
 447
 448  /// <inheritdoc cref="XML_SearchGraph_Dijkstra"/>
 449  public static Action<Action<TNode>>? SearchGraph<TNode, TNumeric>(TNode start, IGraph<TNode> graph, SearchHeuristic<TN
 0450    SearchGraph(start, graph.Neighbors, heuristic, node => equate(node, goal));
 451
 452  /// <inheritdoc cref="XML_SearchGraph_Dijkstra"/>
 453  public static Action<Action<TNode>>? SearchGraph<TNode, TNumeric>(TNode start, IGraph<TNode> graph, SearchHeuristic<TN
 0454    SearchGraph(start, graph.Neighbors, heuristic, goal);
 455
 456  /// <inheritdoc cref="XML_SearchGraph_Dijkstra"/>
 457  public static Action<Action<TNode>>? SearchGraph<TNode, TNumeric>(TNode start, SearchNeighbors<TNode> neighbors, Searc
 0458  {
 459    // using a heap (aka priority queue) to store nodes based on their computed heuristic value
 0460    HeapArray<DijkstraNode<TNode, TNumeric>, DijkstraPriorityCompare<TNode, TNumeric>> fringe = new();
 461
 462    // push starting node
 0463    fringe.Enqueue(
 0464      new DijkstraNode<TNode, TNumeric>(
 0465        value: start,
 0466        priority: Constant<TNumeric>.Zero,
 0467        previous: null));
 468
 469    // run the algorithm
 0470    while (fringe.Count != 0)
 0471    {
 0472      DijkstraNode<TNode, TNumeric> current = fringe.Dequeue();
 0473      GraphSearchStatus status = check(current.Value);
 0474      if (status is GraphSearchStatus.Break)
 0475      {
 0476        break;
 477      }
 0478      if (status is GraphSearchStatus.Goal)
 0479      {
 0480        return BuildPath(current);
 481      }
 482      else
 0483      {
 0484        neighbors(current.Value,
 0485          neighbor =>
 0486          {
 0487            fringe.Enqueue(
 0488              new DijkstraNode<TNode, TNumeric>(
 0489                value: neighbor,
 0490                priority: heuristic(neighbor),
 0491                previous: current));
 0492          });
 0493      }
 0494    }
 0495    return null; // goal node was not reached (no path exists)
 0496  }
 497
 498  /// <summary>Performs Dijkstra search on graph</summary>
 499  /// <param name="graph">The weighted graph object to search</param>
 500  /// <param name="Source">The node to begin searching from</param>
 501  /// <param name="Destination">The node to search</param>
 502  /// <param name="TotalWeight">The total cost or weight incurred from the Soruce to the Destination node</param>
 503  /// <typeparam name="TNode">The Node Type of the graph</typeparam>
 504  /// <typeparam name="TNumeric">The Numeric Type of the graph</typeparam>
 505  /// <returns>IEnumerable of the ordered nodes in path from source to destination</returns>
 506  public static System.Collections.Generic.IEnumerable<TNode> DijkstraSearch<TNode, TNumeric>(this IGraphWeighted<TNode,
 1507  {
 1508    ListArray<TNode> path = new();
 18509    var graphPath = SearchGraph<TNode, TNumeric>(start: Source, graph: graph, heuristic: (x) => Constant<TNumeric>.Zero,
 1510    TotalWeight = totalWeight ?? Constant<TNumeric>.Zero;
 6511    graphPath?.Invoke(n => path.Add(n));
 1512    return path;
 1513  }
 514
 515  /// <summary>Performs Dijkstra Search and executes action on every node in path</summary>
 516  /// <param name="graph">The weighted graph object to search</param>
 517  /// <param name="Source">The node to begin searching from</param>
 518  /// <param name="Destination">The destination node to search</param>
 519  /// <param name="action">The action to execute for every node on the path</param>
 520  /// <param name="TotalWeight">The Total cost or weight incurred from the Source to the Destination node</param>
 521  /// <typeparam name="TNode">The Node Type of the graph</typeparam>
 522  /// <typeparam name="TNumeric">The Numeric Type of the graph</typeparam>
 523  public static void DijkstraSearch<TNode, TNumeric>(this IGraphWeighted<TNode, TNumeric> graph, TNode Source, TNode Des
 0524  {
 0525    var graphPath = SearchGraph<TNode, TNumeric>(start: Source, graph: graph, heuristic: (x) => Constant<TNumeric>.Zero,
 0526    TotalWeight = totalWeight ?? Constant<TNumeric>.Zero;
 0527    if (action == null) return;
 0528    graphPath?.Invoke(n => action(n));
 0529  }
 530
 531  #endregion
 532
 533  #region BreadthFirstSearch Algorithm
 534
 535  /// <summary>Runs the Breadth-First-Search search algorithm on a graph.</summary>
 536  /// <inheritdoc cref="XML_SearchGraph"/>
 537  [Obsolete(NotIntended, true)]
 1538  public static void XML_SearchGraph_BreadthFirst() => throw new DocumentationMethodException();
 539
 540  /// <inheritdoc cref="XML_SearchGraph_BreadthFirst"/>
 541  public static Action<Action<TNode>>? SearchGraph<TNode>(TNode start, SearchNeighbors<TNode> neighbors, SearchGoal<TNod
 8542    SearchGraph(start, neighbors, node => goal(node) ? GraphSearchStatus.Goal : GraphSearchStatus.Continue);
 543
 544  /// <inheritdoc cref="XML_SearchGraph_BreadthFirst"/>
 545  public static Action<Action<TNode>>? SearchGraph<TNode>(TNode start, SearchNeighbors<TNode> neighbors, TNode goal) =>
 0546    SearchGraph(start, neighbors, goal, Equate);
 547
 548  /// <inheritdoc cref="XML_SearchGraph_BreadthFirst"/>
 549  public static Action<Action<TNode>>? SearchGraph<TNode>(TNode start, SearchNeighbors<TNode> neighbors, TNode goal, Fun
 0550    SearchGraph(start, neighbors, node => equate(node, goal));
 551
 552  /// <inheritdoc cref="XML_SearchGraph_BreadthFirst"/>
 553  public static Action<Action<TNode>>? SearchGraph<TNode>(TNode start, IGraph<TNode> graph, TNode goal) =>
 1554    SearchGraph(start, graph, goal, Equate);
 555
 556  /// <inheritdoc cref="XML_SearchGraph_BreadthFirst"/>
 557  public static Action<Action<TNode>>? SearchGraph<TNode>(TNode start, IGraph<TNode> graph, TNode goal, Func<TNode, TNod
 8558    SearchGraph(start, graph.Neighbors, node => equate(node, goal));
 559
 560  /// <inheritdoc cref="XML_SearchGraph_BreadthFirst"/>
 561  public static Action<Action<TNode>>? SearchGraph<TNode>(TNode start, IGraph<TNode> graph, SearchGoal<TNode> goal) =>
 0562    SearchGraph(start, graph.Neighbors, goal);
 563
 564  /// <inheritdoc cref="XML_SearchGraph_BreadthFirst"/>
 565  public static Action<Action<TNode>>? SearchGraph<TNode>(TNode start, SearchNeighbors<TNode> neighbors, SearchCheck<TNo
 1566  {
 1567    IQueue<BreadthFirstSearch<TNode>> fringe = new QueueLinked<BreadthFirstSearch<TNode>>();
 568
 569    // push starting node
 1570    fringe.Enqueue(
 1571      new BreadthFirstSearch<TNode>(
 1572        value: start,
 1573        previous: null));
 574
 575    // run the algorithm
 7576    while (fringe.Count != 0)
 7577    {
 7578      BreadthFirstSearch<TNode> current = fringe.Dequeue();
 7579      GraphSearchStatus status = check(current.Value);
 7580      if (status is GraphSearchStatus.Break)
 0581      {
 0582        break;
 583      }
 7584      if (status is GraphSearchStatus.Goal)
 1585      {
 1586        return BuildPath(current);
 587      }
 588      else
 6589      {
 6590        neighbors(current.Value,
 6591          neighbor =>
 11592          {
 11593            fringe.Enqueue(
 11594              new BreadthFirstSearch<TNode>(
 11595                value: neighbor,
 11596                previous: current));
 17597          });
 6598      }
 6599    }
 0600    return null; // goal node was not reached (no path exists)
 1601  }
 602
 603  /// <summary>Performs Breadth First Search and returns the path as ordered sequence of nodes</summary>
 604  /// <param name="graph">The IGraph object</param>
 605  /// <param name="Source">The node to begin the Breadth First Search from</param>
 606  /// <param name="Destination">The node to search</param>
 607  /// <typeparam name="TNode">The Node Type of the Graph</typeparam>
 608  /// <returns>IEnumerable of the Nodes found along the path</returns>
 609  public static System.Collections.Generic.IEnumerable<TNode> PerformBredthFirstSearch<TNode>(this IGraph<TNode> graph, 
 1610  {
 1611    ListArray<TNode> path = new();
 1612    var graphPath = SearchGraph<TNode>(start: Source, graph: graph, goal: Destination);
 4613    graphPath?.Invoke(n => path.Add(n));
 1614    return path;
 1615  }
 616
 617  /// <summary>Performs Breadth First Search and executes the specified action on every ordered node to in the path sear
 618  /// <param name="graph">The IGraph object</param>
 619  /// <param name="Source">The node to begin Breadth First Search from</param>
 620  /// <param name="Destination">The node to search</param>
 621  /// <param name="action">The action to perform</param>
 622  /// <typeparam name="TNode">The Node Type of the graph</typeparam>
 623  public static void PerformBredthFirstSearch<TNode>(this IGraph<TNode> graph, TNode Source, TNode Destination, Action<T
 0624  {
 0625    if (action != null)
 0626    {
 0627      var graphPath = SearchGraph<TNode>(start: Source, graph: graph, goal: Destination);
 0628      if (action != null && graphPath != null) graphPath(n => action(n));
 0629    }
 0630  }
 631
 632  #endregion
 633
 634  #endregion
 635}

/home/runner/work/Towel/Towel/Sources/Towel/Statics-SequenceAnalysis.cs

#LineLine coverage
 1namespace Towel;
 2
 3/// <summary>Root type of the static functional methods in Towel.</summary>
 4public static partial class Statics
 5{
 6  #region EquateSequence
 7
 8  /// <summary>Determines if two sequences are equal.</summary>
 9  /// <typeparam name="T">The element type of the sequences.</typeparam>
 10  /// <typeparam name="TA">The type of first sequence of the equate.</typeparam>
 11  /// <typeparam name="TB">The type of second sequence of the equate.</typeparam>
 12  /// <typeparam name="TEquate">The type of element equate function.</typeparam>
 13  /// <param name="start">The inclusive starting index to equate from.</param>
 14  /// <param name="end">The inclusive ending index to equate to.</param>
 15  /// <param name="a">The first sequence of the equate.</param>
 16  /// <param name="b">The second sequence of the equate.</param>
 17  /// <param name="equate">The element equate function.</param>
 18  /// <returns>True if the spans are equal; False if not.</returns>
 19  public static bool EquateSequence<T, TA, TB, TEquate>(int start, int end, TA a = default, TB b = default, TEquate equa
 20    where TA : struct, IFunc<int, T>
 21    where TB : struct, IFunc<int, T>
 22    where TEquate : struct, IFunc<T, T, bool>
 023  {
 024    for (int i = start; i <= end; i++)
 025    {
 026      if (!equate.Invoke(a.Invoke(i), b.Invoke(i)))
 027      {
 028        return false;
 29      }
 030    }
 031    return true;
 032  }
 33
 34  /// <summary>Determines if two spans are equal.</summary>
 35  /// <typeparam name="T">The element type of the spans.</typeparam>
 36  /// <param name="a">The first span of the equate.</param>
 37  /// <param name="b">The second span of the equate.</param>
 38  /// <param name="equate">The element equate function.</param>
 39  /// <returns>True if the spans are equal; False if not.</returns>
 40  public static bool EquateSequence<T>(ReadOnlySpan<T> a, ReadOnlySpan<T> b, Func<T, T, bool>? equate = default) =>
 144041    EquateSequence<T, SFunc<T, T, bool>>(a, b, equate ?? Equate);
 42
 43  /// <summary>Determines if two spans are equal.</summary>
 44  /// <typeparam name="T">The element type of the spans.</typeparam>
 45  /// <typeparam name="TEquate">The type of element equate function.</typeparam>
 46  /// <param name="a">The first span of the equate.</param>
 47  /// <param name="b">The second span of the equate.</param>
 48  /// <param name="equate">The element equate function.</param>
 49  /// <returns>True if the spans are equal; False if not.</returns>
 50  public static bool EquateSequence<T, TEquate>(ReadOnlySpan<T> a, ReadOnlySpan<T> b, TEquate equate = default)
 51    where TEquate : struct, IFunc<T, T, bool>
 144052  {
 144053    if (a.IsEmpty && b.IsEmpty)
 8554    {
 8555      return true;
 56    }
 135557    if (a.Length != b.Length)
 058    {
 059      return false;
 60    }
 38763261    for (int i = 0; i < a.Length; i++)
 19246162    {
 19246163      if (!equate.Invoke(a[i], b[i]))
 064      {
 065        return false;
 66      }
 19246167    }
 135568    return true;
 144069  }
 70
 71  #endregion
 72
 73  #region EquateSet
 74
 75  /// <summary>Determines if neither span contains an element the other does not.</summary>
 76  /// <typeparam name="T">The element type of each span.</typeparam>
 77  /// <param name="a">The first span.</param>
 78  /// <param name="b">The second span.</param>
 79  /// <param name="equate">The function for determining equality of values.</param>
 80  /// <param name="hash">The function for hashing the values.</param>
 81  /// <returns>True if neither span contains an element the other does not.</returns>
 82  public static bool EquateSet<T>(ReadOnlySpan<T> a, ReadOnlySpan<T> b, Func<T, T, bool>? equate = default, Func<T, int>
 14183    EquateSet<T, SFunc<T, T, bool>, SFunc<T, int>>(a, b, equate ?? Equate, hash ?? Hash);
 84
 85  /// <summary>Determines if neither span contains an element the other does not.</summary>
 86  /// <typeparam name="T">The element type of each span.</typeparam>
 87  /// <typeparam name="TEquate">The type of function for determining equality of values.</typeparam>
 88  /// <typeparam name="THash">The type of function for hashing the values.</typeparam>
 89  /// <param name="a">The first span.</param>
 90  /// <param name="b">The second span.</param>
 91  /// <param name="equate">The function for determining equality of values.</param>
 92  /// <param name="hash">The function for hashing the values.</param>
 93  /// <returns>True if neither span contains an element the other does not.</returns>
 94  public static bool EquateSet<T, TEquate, THash>(ReadOnlySpan<T> a, ReadOnlySpan<T> b, TEquate equate = default, THash 
 95    where TEquate : struct, IFunc<T, T, bool>
 96    where THash : struct, IFunc<T, int>
 14197  {
 14198    if (a.IsEmpty && b.IsEmpty)
 699    {
 6100      return true;
 101    }
 135102    SetHashLinked<T, TEquate, THash> a_counts = new(
 135103      equate: equate,
 135104      hash: hash,
 135105      expectedCount: a.Length);
 135106    SetHashLinked<T, TEquate, THash> b_counts = new(
 135107      equate: equate,
 135108      hash: hash,
 135109      expectedCount: a.Length);
 1431110    foreach (T value in a)
 513111    {
 513112      a_counts.TryAdd(value);
 513113    }
 1425114    foreach (T value in b)
 512115    {
 512116      if (!a_counts.Contains(value))
 4117      {
 4118        return false;
 119      }
 508120      b_counts.TryAdd(value);
 508121    }
 131122    return a_counts.Count == b_counts.Count;
 141123  }
 124
 125  #endregion
 126
 127  #region EquateOccurences
 128
 129  /// <inheritdoc cref="IsReorderOf{T, TEquate, THash}(ReadOnlySpan{T}, ReadOnlySpan{T}, TEquate, THash)"/>
 130  public static bool EquateOccurences<T>(ReadOnlySpan<T> a, ReadOnlySpan<T> b, Func<T, T, bool>? equate = default, Func<
 0131    IsReorderOf<T, SFunc<T, T, bool>, SFunc<T, int>>(a, b, equate ?? Equate, hash ?? Hash);
 132
 133  /// <inheritdoc cref="IsReorderOf{T, TEquate, THash}(ReadOnlySpan{T}, ReadOnlySpan{T}, TEquate, THash)"/>
 134  public static bool EquateOccurences<T, TEquate, THash>(ReadOnlySpan<T> a, ReadOnlySpan<T> b, TEquate equate = default,
 135    where TEquate : struct, IFunc<T, T, bool>
 136    where THash : struct, IFunc<T, int> =>
 0137    IsReorderOf(a, b, equate, hash);
 138
 139  #endregion
 140
 141  #region Maximum
 142
 143#pragma warning disable CS1711, CS1572, CS1735, SA1617
 144
 145  /// <summary>Finds the maximum value in a sequence.</summary>
 146  /// <typeparam name="T">The type of values in the sequence.</typeparam>
 147  /// <typeparam name="TCompare">The type of function for comparing <typeparamref name="T"/> values.</typeparam>
 148  /// <param name="compare">The function for comparing <typeparamref name="T"/> values.</param>
 149  /// <param name="values">The values to find the maximum value in.</param>
 150  /// <param name="span">The span of values to find the maximum value in.</param>
 151  /// <returns>
 152  /// - <see cref="int"/> Index: the index of the first occurence of the maximum value<br/>
 153  /// - <typeparamref name="T"/> Value: the maximum value in the sequence
 154  /// </returns>
 155  [Obsolete(NotIntended, true)]
 1156  public static void XML_Maximum() => throw new DocumentationMethodException();
 157
 158#pragma warning restore CS1711, CS1572, CS1735, SA1617
 159
 160  /// <inheritdoc cref="XML_Maximum"/>
 161  public static (int Index, T Value) Maximum<T>(Func<T, T, CompareResult>? compare = null, params T[] values) =>
 15162    Maximum<T, SFunc<T, T, CompareResult>>(values, compare ?? Compare);
 163
 164  /// <inheritdoc cref="XML_Maximum"/>
 165  public static (int Index, T Value) Maximum<T>(ReadOnlySpan<T> span, Func<T, T, CompareResult>? compare = null) =>
 0166    Maximum<T, SFunc<T, T, CompareResult>>(span, compare ?? Compare);
 167
 168  /// <inheritdoc cref="XML_Maximum"/>
 169  public static (int Index, T Value) Maximum<T, TCompare>(ReadOnlySpan<T> span, TCompare compare = default)
 170    where TCompare : struct, IFunc<T, T, CompareResult>
 15171  {
 15172    if (span.IsEmpty)
 0173    {
 0174      throw new ArgumentException($"{nameof(span)}.{nameof(span.IsEmpty)}", nameof(span));
 175    }
 15176    int index = 0;
 330177    for (int i = 1; i < span.Length; i++)
 150178    {
 150179      if (compare.Invoke(span[i], span[index]) is Greater)
 63180      {
 63181        index = i;
 63182      }
 150183    }
 15184    return (index, span[index]);
 15185  }
 186
 187  #endregion
 188
 189  #region MaximumValue
 190
 191#pragma warning disable CS1711, CS1572, SA1617, CS1735
 192
 193  /// <summary>Finds the maximum between two values.</summary>
 194  /// <typeparam name="T">The type of values to compare.</typeparam>
 195  /// <typeparam name="TCompare">The type of function for comparing <typeparamref name="T"/> values.</typeparam>
 196  /// <param name="compare">The function for comparing <typeparamref name="T"/> values.</param>
 197  /// <param name="a">The first value to compare.</param>
 198  /// <param name="b">The second value to compare.</param>
 199  /// <returns>The maximum of the two values.</returns>
 200  [Obsolete(NotIntended, true)]
 1201  public static void XML_MaximumValue_Two() => throw new DocumentationMethodException();
 202
 203#pragma warning restore CS1711, CS1572, SA1617, CS1735
 204
 205  /// <inheritdoc cref="XML_MaximumValue_Two"/>
 206  public static T MaximumValue<T>(T a, T b, Func<T, T, CompareResult>? compare = null) =>
 10207    MaximumValue<T, SFunc<T, T, CompareResult>>(a, b, compare ?? Compare);
 208
 209  /// <inheritdoc cref="XML_MaximumValue_Two"/>
 210  public static T MaximumValue<T, TCompare>(T a, T b, TCompare compare = default)
 211    where TCompare : struct, IFunc<T, T, CompareResult> =>
 10212    compare.Invoke(b, a) is Greater ? b : a;
 213
 214#pragma warning disable CS1711, CS1735, CS1572, SA1617
 215
 216  /// <summary>Finds the maximum value in a sequence.</summary>
 217  /// <typeparam name="T">The type of values in the sequence.</typeparam>
 218  /// <typeparam name="TCompare">The type of function for comparing <typeparamref name="T"/> values.</typeparam>
 219  /// <param name="compare">The function for comparing <typeparamref name="T"/> values.</param>
 220  /// <param name="values">The values to find the maximum value in.</param>
 221  /// <param name="span">The span of values to find the maximum value in.</param>
 222  /// <returns>The maximum value in the sequence.</returns>
 223  [Obsolete(NotIntended, true)]
 1224  public static void XML_MaximumValue() => throw new DocumentationMethodException();
 225
 226#pragma warning restore CS1711, CS1735, CS1572, SA1617
 227
 228  /// <inheritdoc cref="XML_MaximumValue"/>
 229  public static T MaximumValue<T>(Func<T, T, CompareResult>? compare = null, params T[] values) =>
 15230    MaximumValue<T, SFunc<T, T, CompareResult>>(values, compare ?? Compare);
 231
 232  /// <inheritdoc cref="XML_MaximumValue"/>
 233  public static T MaximumValue<T>(ReadOnlySpan<T> span, Func<T, T, CompareResult>? compare = null) =>
 0234    MaximumValue<T, SFunc<T, T, CompareResult>>(span, compare ?? Compare);
 235
 236  /// <inheritdoc cref="XML_MaximumValue"/>
 237  public static T MaximumValue<T, TCompare>(ReadOnlySpan<T> span, TCompare compare = default)
 238    where TCompare : struct, IFunc<T, T, CompareResult>
 15239  {
 15240    if (span.IsEmpty)
 0241    {
 0242      throw new ArgumentException($"{nameof(span)}.{nameof(span.IsEmpty)}", nameof(span));
 243    }
 15244    T max = span[0];
 330245    for (int i = 1; i < span.Length; i++)
 150246    {
 150247      if (compare.Invoke(span[i], max) is Greater)
 63248      {
 63249        max = span[i];
 63250      }
 150251    }
 15252    return max;
 15253  }
 254
 255  #endregion
 256
 257  #region MaximumIndex
 258
 259  /// <summary>Finds the maximum value in a sequence.</summary>
 260  /// <typeparam name="T">The type of values in the sequence.</typeparam>
 261  /// <typeparam name="TGet">The type of the get method.</typeparam>
 262  /// <typeparam name="TCompare">The type of method for comparing <typeparamref name="T"/> values.</typeparam>
 263  /// <param name="start">The inclusive starting index to find the maximum of.</param>
 264  /// <param name="end">The inclusive ending index to find the maximum of.</param>
 265  /// <param name="get">The the get method.</param>
 266  /// <param name="compare">The method for comparing <typeparamref name="T"/> values.</param>
 267  /// <returns>The index of the first occurence of the maximum value in the sequence.</returns>
 268  public static int MaximumIndex<T, TGet, TCompare>(int start, int end, TGet get, TCompare compare = default)
 269    where TCompare : struct, IFunc<T, T, CompareResult>
 270    where TGet : struct, IFunc<int, T>
 12253271  {
 12253272    T max = get.Invoke(start);
 12253273    int maxi = start;
 12253274    if (start <= end)
 12253275    {
 11088126276      for (int i = start + 1; i <= end; i++)
 5531810277      {
 5531810278        T ivalue = get.Invoke(i);
 5531810279        if (compare.Invoke(ivalue, max) is Greater)
 63908280        {
 63908281          maxi = i;
 63908282          max = ivalue;
 63908283        }
 5531810284      }
 12253285    }
 286    else
 0287    {
 0288      for (int i = start - 1; i >= end; i--)
 0289      {
 0290        T ivalue = get.Invoke(i);
 0291        if (compare.Invoke(ivalue, max) is Greater)
 0292        {
 0293          maxi = i;
 0294          max = ivalue;
 0295        }
 0296      }
 0297    }
 12253298    return maxi;
 12253299  }
 300
 301#pragma warning disable CS1711, CS1572, SA1617, CS1735
 302
 303  /// <summary>Finds the maximum value in a sequence.</summary>
 304  /// <typeparam name="T">The type of values in the sequence.</typeparam>
 305  /// <typeparam name="TCompare">The type of function for comparing <typeparamref name="T"/> values.</typeparam>
 306  /// <param name="compare">The function for comparing <typeparamref name="T"/> values.</param>
 307  /// <param name="values">The values to find the maximum value in.</param>
 308  /// <param name="span">The span of values to find the maximum value in.</param>
 309  /// <returns>The index of the first occurence of the maximum value in the sequence.</returns>
 310  [Obsolete(NotIntended, true)]
 1311  public static void XML_MaximumIndex() => throw new DocumentationMethodException();
 312
 313#pragma warning restore CS1711, CS1572, SA1617, CS1735
 314
 315  /// <inheritdoc cref="XML_MaximumIndex"/>
 316  public static int MaximumIndex<T>(Func<T, T, CompareResult>? compare = null, params T[] values) =>
 15317    MaximumIndex<T, SFunc<T, T, CompareResult>>(values, compare ?? Compare);
 318
 319  /// <inheritdoc cref="XML_MaximumIndex"/>
 320  public static int MaximumIndex<T>(ReadOnlySpan<T> span, Func<T, T, CompareResult>? compare = null) =>
 0321    MaximumIndex<T, SFunc<T, T, CompareResult>>(span, compare ?? Compare);
 322
 323  /// <inheritdoc cref="XML_MaximumIndex"/>
 324  public static int MaximumIndex<T, TCompare>(ReadOnlySpan<T> span, TCompare compare = default)
 325    where TCompare : struct, IFunc<T, T, CompareResult>
 12268326  {
 12268327    if (span.IsEmpty)
 0328    {
 0329      throw new ArgumentException($"{nameof(span)}.{nameof(span.IsEmpty)}", nameof(span));
 330    }
 12268331    int max = 0;
 11088456332    for (int i = 1; i < span.Length; i++)
 5531960333    {
 5531960334      if (compare.Invoke(span[i], span[max]) is Greater)
 63971335      {
 63971336        max = i;
 63971337      }
 5531960338    }
 12268339    return max;
 12268340  }
 341
 342  #endregion
 343
 344  #region Minimum
 345
 346#pragma warning disable CS1711, CS1572, CS1735, SA1617
 347
 348  /// <summary>Finds the minimum value in a sequence.</summary>
 349  /// <typeparam name="T">The type of values in the sequence.</typeparam>
 350  /// <typeparam name="TCompare">The type of function for comparing <typeparamref name="T"/> values.</typeparam>
 351  /// <param name="compare">The function for comparing <typeparamref name="T"/> values.</param>
 352  /// <param name="values">The values to find the minimum value in.</param>
 353  /// <param name="span">The span of values to find the minimum value in.</param>
 354  /// <returns>
 355  /// - <see cref="int"/> Index: the index of the first occurence of the minimum value<br/>
 356  /// - <typeparamref name="T"/> Value: the minimum value in the sequence
 357  /// </returns>
 358  [Obsolete(NotIntended, true)]
 1359  public static void XML_Minimum() => throw new DocumentationMethodException();
 360
 361#pragma warning restore CS1711, CS1572, CS1735, SA1617
 362
 363  /// <inheritdoc cref="XML_Minimum"/>
 364  public static (int Index, T Value) Minimum<T>(Func<T, T, CompareResult>? compare = null, params T[] values) =>
 15365    Minimum<T, SFunc<T, T, CompareResult>>(values, compare ?? Compare);
 366
 367  /// <inheritdoc cref="XML_Minimum"/>
 368  public static (int Index, T Value) Minimum<T>(ReadOnlySpan<T> span, Func<T, T, CompareResult>? compare = null) =>
 0369    Minimum<T, SFunc<T, T, CompareResult>>(span, compare ?? Compare);
 370
 371  /// <inheritdoc cref="XML_Minimum"/>
 372  public static (int Index, T Value) Minimum<T, TCompare>(ReadOnlySpan<T> span, TCompare compare = default)
 373    where TCompare : struct, IFunc<T, T, CompareResult>
 15374  {
 15375    if (span.IsEmpty)
 0376    {
 0377      throw new ArgumentException($"{nameof(span)}.{nameof(span.IsEmpty)}", nameof(span));
 378    }
 15379    int index = 0;
 330380    for (int i = 1; i < span.Length; i++)
 150381    {
 150382      if (compare.Invoke(span[i], span[index]) is Less)
 63383      {
 63384        index = i;
 63385      }
 150386    }
 15387    return (index, span[index]);
 15388  }
 389
 390  #endregion
 391
 392  #region MinimumValue
 393
 394#pragma warning disable CS1711, CS1572, CS1735, SA1617
 395
 396  /// <summary>Finds the minimum between two values.</summary>
 397  /// <typeparam name="T">The type of values to compare.</typeparam>
 398  /// <typeparam name="TCompare">The type of function for comparing <typeparamref name="T"/> values.</typeparam>
 399  /// <param name="compare">The function for comparing <typeparamref name="T"/> values.</param>
 400  /// <param name="a">The first value to compare.</param>
 401  /// <param name="b">The second value to compare.</param>
 402  /// <returns>The minimum of the two values.</returns>
 403  [Obsolete(NotIntended, true)]
 1404  public static void XML_MinimumValue_Two() => throw new DocumentationMethodException();
 405
 406#pragma warning restore CS1711, CS1572, CS1735, SA1617
 407
 408  /// <inheritdoc cref="XML_MinimumValue_Two"/>
 409  public static T MinimumValue<T>(T a, T b, Func<T, T, CompareResult>? compare = null) =>
 6410    MinimumValue<T, SFunc<T, T, CompareResult>>(a, b, compare ?? Compare);
 411
 412  /// <inheritdoc cref="XML_MinimumValue_Two"/>
 413  public static T MinimumValue<T, TCompare>(T a, T b, TCompare compare = default)
 414    where TCompare : struct, IFunc<T, T, CompareResult> =>
 6415    compare.Invoke(b, a) is Less ? b : a;
 416
 417#pragma warning disable CS1711, CS1735, CS1572, SA1617
 418
 419  /// <summary>Finds the minimum value in a sequence.</summary>
 420  /// <typeparam name="T">The type of values in the sequence.</typeparam>
 421  /// <typeparam name="TCompare">The type of function for comparing <typeparamref name="T"/> values.</typeparam>
 422  /// <param name="compare">The function for comparing <typeparamref name="T"/> values.</param>
 423  /// <param name="values">The values to find the minimum value in.</param>
 424  /// <param name="span">The span of values to find the minimum value in.</param>
 425  /// <returns>The minimum value in the sequence.</returns>
 426  [Obsolete(NotIntended, true)]
 1427  public static void XML_MinimumValue() => throw new DocumentationMethodException();
 428
 429#pragma warning restore CS1711, CS1735, CS1572, SA1617
 430
 431  /// <inheritdoc cref="XML_MinimumValue"/>
 432  public static T MinimumValue<T>(Func<T, T, CompareResult>? compare = null, params T[] values) =>
 15433    MinimumValue<T, SFunc<T, T, CompareResult>>(values, compare ?? Compare);
 434
 435  /// <inheritdoc cref="XML_MinimumValue"/>
 436  public static T MinimumValue<T>(ReadOnlySpan<T> span, Func<T, T, CompareResult>? compare = null) =>
 0437    MinimumValue<T, SFunc<T, T, CompareResult>>(span, compare ?? Compare);
 438
 439  /// <inheritdoc cref="XML_MinimumValue"/>
 440  public static T MinimumValue<T, TCompare>(ReadOnlySpan<T> span, TCompare compare = default)
 441    where TCompare : struct, IFunc<T, T, CompareResult>
 15442  {
 15443    if (span.IsEmpty)
 0444    {
 0445      throw new ArgumentException($"{nameof(span)}.{nameof(span.IsEmpty)}", nameof(span));
 446    }
 15447    T min = span[0];
 330448    for (int i = 1; i < span.Length; i++)
 150449    {
 150450      if (compare.Invoke(span[i], min) is Less)
 63451      {
 63452        min = span[i];
 63453      }
 150454    }
 15455    return min;
 15456  }
 457
 458  #endregion
 459
 460  #region MinimumIndex
 461
 462#pragma warning disable CS1711, CS1572, CS1735, SA1617
 463
 464  /// <summary>Finds the minimum value in a sequence.</summary>
 465  /// <typeparam name="T">The type of values in the sequence.</typeparam>
 466  /// <typeparam name="TCompare">The type of function for comparing <typeparamref name="T"/> values.</typeparam>
 467  /// <param name="compare">The function for comparing <typeparamref name="T"/> values.</param>
 468  /// <param name="values">The values to find the minimum value in.</param>
 469  /// <param name="span">The span of values to find the minimum value in.</param>
 470  /// <returns>The index of the first occurence of the minimum value in the sequence.</returns>
 471  [Obsolete(NotIntended, true)]
 472
 1473  public static void XML_MinimumIndex() => throw new DocumentationMethodException();
 474
 475#pragma warning restore CS1711, CS1572, CS1735, SA1617
 476
 477  /// <inheritdoc cref="XML_MinimumIndex"/>
 478  public static int MinimumIndex<T>(Func<T, T, CompareResult>? compare = null, params T[] values) =>
 15479    MinimumIndex<T, SFunc<T, T, CompareResult>>(values, compare ?? Compare);
 480
 481  /// <inheritdoc cref="XML_MinimumIndex"/>
 482  public static int MinimumIndex<T>(ReadOnlySpan<T> span, Func<T, T, CompareResult>? compare = null) =>
 0483    MinimumIndex<T, SFunc<T, T, CompareResult>>(span, compare ?? Compare);
 484
 485  /// <inheritdoc cref="XML_MinimumIndex"/>
 486  public static int MinimumIndex<T, TCompare>(ReadOnlySpan<T> span, TCompare compare = default)
 487    where TCompare : struct, IFunc<T, T, CompareResult>
 15488  {
 15489    if (span.IsEmpty)
 0490    {
 0491      throw new ArgumentException($"{nameof(span)}.{nameof(span.IsEmpty)}", nameof(span));
 492    }
 15493    int min = 0;
 330494    for (int i = 1; i < span.Length; i++)
 150495    {
 150496      if (compare.Invoke(span[i], span[min]) is Less)
 63497      {
 63498        min = i;
 63499      }
 150500    }
 15501    return min;
 15502  }
 503
 504  #endregion
 505
 506  #region Range
 507
 508  /// <summary>Gets the range (minimum and maximum) of a set of data.</summary>
 509  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 510  /// <param name="minimum">The minimum of the set of data.</param>
 511  /// <param name="maximum">The maximum of the set of data.</param>
 512  /// <param name="stepper">The set of data to get the range of.</param>
 513  /// <exception cref="ArgumentNullException">Throws when stepper is null.</exception>
 514  /// <exception cref="ArgumentException">Throws when stepper is empty.</exception>
 515  public static void Range<T>(out T minimum, out T maximum, Action<Action<T>> stepper) =>
 0516    Range(stepper, out minimum, out maximum);
 517
 518  /// <summary>Gets the range (minimum and maximum) of a set of data.</summary>
 519  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 520  /// <param name="stepper">The set of data to get the range of.</param>
 521  /// <param name="minimum">The minimum of the set of data.</param>
 522  /// <param name="maximum">The maximum of the set of data.</param>
 523  /// <exception cref="ArgumentNullException">Throws when stepper is null.</exception>
 524  /// <exception cref="ArgumentException">Throws when stepper is empty.</exception>
 525  public static void Range<T>(Action<Action<T>> stepper, out T minimum, out T maximum)
 0526  {
 0527    if (stepper is null) throw new ArgumentNullException(nameof(stepper));
 528    // Note: can't use out parameters as capture variables
 0529    T? min = default;
 0530    T? max = default;
 0531    bool assigned = false;
 0532    stepper(a =>
 0533    {
 0534      if (assigned)
 0535      {
 0536        min = LessThan(a, min) ? a : min;
 0537        max = LessThan(max, a) ? a : max;
 0538      }
 0539      else
 0540      {
 0541        min = a;
 0542        max = a;
 0543        assigned = true;
 0544      }
 0545    });
 0546    if (!assigned)
 0547    {
 0548      throw new ArgumentException("The argument is empty.", nameof(stepper));
 549    }
 0550    minimum = min!;
 0551    maximum = max!;
 0552  }
 553
 554  /// <summary>Finds the minimum and maximum values from a sequence of <typeparamref name="T"/> values.</summary>
 555  /// <typeparam name="T">The type of values in the sequence.</typeparam>
 556  /// <typeparam name="TCompare">The type of function for comparing <typeparamref name="T"/> values.</typeparam>
 557  /// <param name="span">The sequence of <typeparamref name="T"/> values to filter.</param>
 558  /// <param name="compare">The function for comparing <typeparamref name="T"/> values.</param>
 559  /// <returns>
 560  /// - (<see cref="int"/> Index, <typeparamref name="T"/> Value) Min<br/>
 561  /// - (<see cref="int"/> Index, <typeparamref name="T"/> Value) Max
 562  /// </returns>
 563  public static ((int Index, T Value) Min, (int Index, T Value) Max) Range<T, TCompare>(ReadOnlySpan<T> span, TCompare c
 564    where TCompare : struct, IFunc<T, T, CompareResult>
 0565  {
 0566    if (span.IsEmpty)
 0567    {
 0568      throw new ArgumentException($"{nameof(span)}.{nameof(span.IsEmpty)}", nameof(span));
 569    }
 0570    int minIndex = 0;
 0571    int maxIndex = 0;
 0572    for (int i = 1; i < span.Length; i++)
 0573    {
 0574      if (compare.Invoke(span[i], span[minIndex]) is Less)
 0575      {
 0576        minIndex = i;
 0577      }
 0578      if (compare.Invoke(span[i], span[maxIndex]) is Greater)
 0579      {
 0580        maxIndex = i;
 0581      }
 0582    }
 0583    return ((minIndex, span[minIndex]), (maxIndex, span[maxIndex]));
 0584  }
 585
 586  #endregion
 587
 588  #region Mode
 589
 590  /// <summary>Gets the mode(s) of a data set.</summary>
 591  /// <typeparam name="T">The generic type of the data.</typeparam>
 592  /// <param name="step">The action to perform on every mode value found.</param>
 593  /// <param name="a">The first value of the data set.</param>
 594  /// <param name="b">The rest of the data set.</param>
 595  public static void Mode<T>(Action<T> step, T a, params T[] b) =>
 20596    Mode<T>(x => { x(a); b.ToStepper()(x); }, step);
 597
 598  /// <summary>Gets the mode(s) of a data set.</summary>
 599  /// <typeparam name="T">The generic type of the data.</typeparam>
 600  /// <param name="step">The action to perform on every mode value found.</param>
 601  /// <param name="equate">The equality delegate.</param>
 602  /// <param name="a">The first value of the data set.</param>
 603  /// <param name="b">The rest of the data set.</param>
 604  public static void Mode<T>(Action<T> step, Func<T, T, bool> equate, T a, params T[] b) =>
 0605    Mode<T>(x => { x(a); b.ToStepper()(x); }, step, equate, null);
 606
 607  /// <summary>Gets the mode(s) of a data set.</summary>
 608  /// <typeparam name="T">The generic type of the data.</typeparam>
 609  /// <param name="step">The action to perform on every mode value found.</param>
 610  /// <param name="hash">The hash code delegate</param>
 611  /// <param name="a">The first value of the data set.</param>
 612  /// <param name="b">The rest of the data set.</param>
 613  public static void Mode<T>(Action<T> step, Func<T, int> hash, T a, params T[] b) =>
 0614    Mode<T>(x => { x(a); b.ToStepper()(x); }, step, null, hash);
 615
 616  /// <summary>Gets the mode(s) of a data set.</summary>
 617  /// <typeparam name="T">The generic type of the data.</typeparam>
 618  /// <param name="step">The action to perform on every mode value found.</param>
 619  /// <param name="equate">The equality delegate.</param>
 620  /// <param name="hash">The hash code delegate</param>
 621  /// <param name="a">The first value of the data set.</param>
 622  /// <param name="b">The rest of the data set.</param>
 623  public static void Mode<T>(Action<T> step, Func<T, T, bool> equate, Func<T, int> hash, T a, params T[] b) =>
 0624    Mode<T>(x => { x(a); b.ToStepper()(x); }, step, equate, hash);
 625
 626  /// <summary>Gets the mode(s) of a data set.</summary>
 627  /// <typeparam name="T">The generic type of the data.</typeparam>
 628  /// <param name="stepper">The data set.</param>
 629  /// <param name="step">The action to perform on every mode value found.</param>
 630  /// <param name="equate">The equality delegate.</param>
 631  /// <param name="hash">The hash code delegate</param>
 632  public static void Mode<T>(Action<Action<T>> stepper, Action<T> step, Func<T, T, bool>? equate = null, Func<T, int>? h
 4633  {
 4634    int maxOccurences = -1;
 4635    IMap<int, T> map = MapHashLinked.New<int, T>(equate, hash);
 4636    stepper(a =>
 24637    {
 24638      if (map.Contains(a))
 4639      {
 4640        int occurences = ++map[a];
 4641        maxOccurences = Math.Max(occurences, maxOccurences);
 4642      }
 4643      else
 20644      {
 20645        map[a] = 1;
 20646        maxOccurences = Math.Max(1, maxOccurences);
 20647      }
 28648    });
 4649    map.Pairs(x =>
 20650    {
 20651      if (x.Value == maxOccurences)
 4652      {
 4653        step(x.Key);
 4654      }
 24655    });
 4656  }
 657
 658  #endregion
 659
 660  #region Mean
 661
 662  /// <summary>Computes the mean of a set of numerical values.</summary>
 663  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 664  /// <param name="a">The first value of the set of data to compute the mean of.</param>
 665  /// <param name="b">The remaining values in the data set to compute the mean of.</param>
 666  /// <returns>The computed mean of the set of data.</returns>
 667  public static T Mean<T>(T a, params T[] b) =>
 0668    Mean<T>(step => { step(a); b.ToStepper()(step); });
 669
 670  /// <summary>Computes the mean of a set of numerical values.</summary>
 671  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 672  /// <param name="stepper">The set of data to compute the mean of.</param>
 673  /// <returns>The computed mean of the set of data.</returns>
 674  public static T Mean<T>(Action<Action<T>> stepper)
 0675  {
 0676    if (stepper is null) throw new ArgumentNullException(nameof(stepper));
 0677    T i = Constant<T>.Zero;
 0678    T sum = Constant<T>.Zero;
 0679    stepper(step =>
 0680    {
 0681      i = Addition(i, Constant<T>.One);
 0682      sum = Addition(sum, step);
 0683    });
 0684    if (Equate(i, Constant<T>.Zero))
 0685    {
 0686      throw new ArgumentException("The argument is empty.", nameof(stepper));
 687    }
 0688    return Division(sum, i);
 0689  }
 690
 691  #endregion
 692
 693  #region Median
 694
 695  /// <summary>Computes the median of a set of data.</summary>
 696  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 697  /// <param name="compare">The comparison algorithm to sort the data by.</param>
 698  /// <param name="values">The set of data to compute the median of.</param>
 699  /// <returns>The computed median value of the set of data.</returns>
 700  public static T Median<T>(Func<T, T, CompareResult> compare, params T[] values)
 15701  {
 15702    if (compare is null) throw new ArgumentNullException(nameof(compare));
 15703    if (values is null) throw new ArgumentNullException(nameof(values));
 704    // standard algorithm (sort and grab middle value)
 15705    SortMerge(values, compare);
 15706    if (values.Length % 2 is 1) // odd... just grab middle value
 12707    {
 12708      return values[values.Length / 2];
 709    }
 710    else // even... must perform a mean of the middle two values
 3711    {
 3712      T leftMiddle = values[(values.Length / 2) - 1];
 3713      T rightMiddle = values[values.Length / 2];
 3714      return Division(Addition(leftMiddle, rightMiddle), Constant<T>.Two);
 715    }
 15716  }
 717
 718  /// <summary>Computes the median of a set of data.</summary>
 719  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 720  /// <param name="compare">The comparison algorithm to sort the data by.</param>
 721  /// <param name="stepper">The set of data to compute the median of.</param>
 722  /// <returns>The computed median value of the set of data.</returns>
 723  public static T Median<T>(Func<T, T, CompareResult> compare, Action<Action<T>> stepper)
 0724  {
 0725    if (stepper is null) throw new ArgumentNullException(nameof(stepper));
 0726    return Median<T>(compare, stepper.ToArray());
 0727  }
 728
 729  /// <summary>Computes the median of a set of data.</summary>
 730  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 731  /// <param name="values">The set of data to compute the median of.</param>
 732  /// <returns>The computed median value of the set of data.</returns>
 733  public static T Median<T>(params T[] values)
 15734  {
 15735    return Median(Compare, values);
 15736  }
 737
 738  /// <summary>Computes the median of a set of data.</summary>
 739  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 740  /// <param name="stepper">The set of data to compute the median of.</param>
 741  /// <returns>The computed median value of the set of data.</returns>
 742  public static T Median<T>(Action<Action<T>> stepper)
 0743  {
 0744    if (stepper is null) throw new ArgumentNullException(nameof(stepper));
 0745    return Median(Compare, stepper.ToArray());
 0746  }
 747
 748  #region Possible Optimization (Still in Development)
 749
 750  // public static T Median<T>(Func<T, T, CompareResult> compare, Hash<T> hash, Func<T, T, bool> equate, params T[] valu
 751  // {
 752  //     // this is an optimized median algorithm, but it only works on odd sets without duplicates
 753  //     if (hash is not null && equate is not null && values.Length % 2 is 1 && !values.ToStepper().ContainsDuplicates(
 754  //     {
 755  //         int medianIndex = 0;
 756  //         OddNoDupesMedianImplementation(values, values.Length, ref medianIndex, compare);
 757  //         return values[medianIndex];
 758  //     }
 759  //     else
 760  //     {
 761  //         return Median(compare, values);
 762  //     }
 763  // }
 764
 765  // public static T Median<T>(Func<T, T, CompareResult> compare, Hash<T> hash, Func<T, T, bool> equate, Stepper<T> step
 766  // {
 767  //     return Median(compare, hash, equate, stepper.ToArray());
 768  // }
 769
 770  ///// <summary>Fast algorithm for median computation, but only works on data with an odd number of values without dupl
 771  // internal static void OddNoDupesMedianImplementation<T>(T[] a, int n, ref int k, Func<T, T, CompareResult> compare)
 772  // {
 773  //     int L = 0;
 774  //     int R = n - 1;
 775  //     k = n / 2;
 776  //     int i; int j;
 777  //     while (L < R)
 778  //     {
 779  //         T x = a[k];
 780  //         i = L; j = R;
 781  //         OddNoDupesMedianImplementation_Split(a, n, x, ref i, ref j, compare);
 782  //         if (j <= k) L = i;
 783  //         if (i >= k) R = j;
 784  //     }
 785  // }
 786
 787  // internal static void OddNoDupesMedianImplementation_Split<T>(T[] a, int n, T x, ref int i, ref int j, Func<T, T, Co
 788  // {
 789  //     do
 790  //     {
 791  //         while (compare(a[i], x) is Less) i++;
 792  //         while (compare(a[j], x) is Greater) j--;
 793  //         T t = a[i];
 794  //         a[i] = a[j];
 795  //         a[j] = t;
 796  //     } while (i < j);
 797  // }
 798
 799  #endregion
 800
 801  #endregion
 802
 803  #region GeometricMean
 804
 805  /// <summary>Computes the geometric mean of a set of numbers.</summary>
 806  /// <typeparam name="T">The numeric type of the computation.</typeparam>
 807  /// <param name="stepper">The set of numbres to compute the geometric mean of.</param>
 808  /// <returns>The computed geometric mean of the set of numbers.</returns>
 809  public static T GeometricMean<T>(Action<Action<T>> stepper)
 0810  {
 0811    T multiple = Constant<T>.One;
 0812    T count = Constant<T>.Zero;
 0813    stepper(i =>
 0814    {
 0815      count = Addition(count, Constant<T>.One);
 0816      multiple = Multiplication(multiple, i);
 0817    });
 0818    return Root(multiple, count);
 0819  }
 820
 821  #endregion
 822
 823  #region Variance
 824
 825  /// <summary>Computes the variance of a set of numbers.</summary>
 826  /// <typeparam name="T">The numeric type of the computation.</typeparam>
 827  /// <param name="stepper">The set of numbers to compute the variance of.</param>
 828  /// <returns>The computed variance of the set of numbers.</returns>
 829  public static T Variance<T>(Action<Action<T>> stepper)
 0830  {
 0831    T mean = Mean(stepper);
 0832    T variance = Constant<T>.Zero;
 0833    T count = Constant<T>.Zero;
 0834    stepper(i =>
 0835    {
 0836      T i_minus_mean = Subtraction(i, mean);
 0837      variance = Addition(variance, Multiplication(i_minus_mean, i_minus_mean));
 0838      count = Addition(count, Constant<T>.One);
 0839    });
 0840    return Division(variance, count);
 0841  }
 842
 843  #endregion
 844
 845  #region StandardDeviation
 846
 847  /// <summary>Computes the standard deviation of a set of numbers.</summary>
 848  /// <typeparam name="T">The numeric type of the computation.</typeparam>
 849  /// <param name="stepper">The set of numbers to compute the standard deviation of.</param>
 850  /// <returns>The computed standard deviation of the set of numbers.</returns>
 851  public static T StandardDeviation<T>(Action<Action<T>> stepper) =>
 0852    SquareRoot(Variance(stepper));
 853
 854  #endregion
 855
 856  #region MeanDeviation
 857
 858  /// <summary>The mean deviation of a set of numbers.</summary>
 859  /// <typeparam name="T">The numeric type of the computation.</typeparam>
 860  /// <param name="stepper">The set of numbers to compute the mean deviation of.</param>
 861  /// <returns>The computed mean deviation of the set of numbers.</returns>
 862  public static T MeanDeviation<T>(Action<Action<T>> stepper)
 0863  {
 0864    T mean = Mean(stepper);
 0865    T temp = Constant<T>.Zero;
 0866    T count = Constant<T>.Zero;
 0867    stepper(i =>
 0868    {
 0869      temp = Addition(temp, AbsoluteValue(Subtraction(i, mean)));
 0870      count = Addition(count, Constant<T>.One);
 0871    });
 0872    return Division(temp, count);
 0873  }
 874
 875  #endregion
 876
 877  #region Quantiles
 878
 879  /// <summary>Computes the quantiles of a set of data.</summary>
 880  /// <typeparam name="T">The generic data type.</typeparam>
 881  /// <param name="quantiles">The number of quantiles to compute.</param>
 882  /// <param name="stepper">The data stepper.</param>
 883  /// <returns>The computed quantiles of the data set.</returns>
 884  public static T[] Quantiles<T>(int quantiles, Action<Action<T>> stepper)
 0885  {
 0886    if (quantiles < 1)
 0887    {
 0888      throw new ArgumentOutOfRangeException(nameof(quantiles), quantiles, "!(" + nameof(quantiles) + " >= 1)");
 889    }
 0890    int count = stepper.Count();
 0891    T[] ordered = new T[count];
 0892    int a = 0;
 0893    stepper(i => { ordered[a++] = i; });
 0894    SortQuick<T>(ordered, Compare);
 0895    T[] resultingQuantiles = new T[quantiles + 1];
 0896    resultingQuantiles[0] = ordered[0];
 0897    resultingQuantiles[^1] = ordered[^1];
 0898    T QUANTILES_PLUS_1 = Convert<int, T>(quantiles + 1);
 0899    T ORDERED_LENGTH = Convert<int, T>(ordered.Length);
 0900    for (int i = 1; i < quantiles; i++)
 0901    {
 0902      T I = Convert<int, T>(i);
 0903      T temp = Division(ORDERED_LENGTH, Multiplication<T>(QUANTILES_PLUS_1, I));
 0904      if (IsInteger(temp))
 0905      {
 0906        resultingQuantiles[i] = ordered[Convert<T, int>(temp)];
 0907      }
 908      else
 0909      {
 0910        resultingQuantiles[i] = Division(Addition(ordered[Convert<T, int>(temp)], ordered[Convert<T, int>(temp) + 1]), C
 0911      }
 0912    }
 0913    return resultingQuantiles;
 0914  }
 915
 916  #endregion
 917
 918  #region Correlation
 919
 920#if false
 921
 922    //        /// <summary>Computes the median of a set of values.</summary>
 923    //        internal static Compute.Delegates.Correlation Correlation_internal = (Stepper<T> a, Stepper<T> b) =>
 924    //        {
 925    //            throw new System.NotImplementedException("I introduced an error here when I removed the stepref off of
 926
 927    //            Compute.Correlation_internal =
 928    //        Meta.Compile<Compute.Delegates.Correlation>(
 929    //        string.Concat(
 930    //        @"(Stepper<", Meta.ConvertTypeToCsharpSource(typeof(T)), "> _a, Stepper<", Meta.ConvertTypeToCsharpSource(
 931    //{
 932    //  ", Meta.ConvertTypeToCsharpSource(typeof(T)), " a_mean = Compute<", Meta.ConvertTypeToCsharpSource(typeof(T)), @
 933    //  ", Meta.ConvertTypeToCsharpSource(typeof(T)), " b_mean = Compute<", Meta.ConvertTypeToCsharpSource(typeof(T)), @
 934    //  List<", Meta.ConvertTypeToCsharpSource(typeof(T)), "> a_temp = new List_Linked<", Meta.ConvertTypeToCsharpSource
 935    //  _a((", Meta.ConvertTypeToCsharpSource(typeof(T)), @" i) => { a_temp.Add(i - b_mean); });
 936    //  List<", Meta.ConvertTypeToCsharpSource(typeof(T)), "> b_temp = new List_Linked<", Meta.ConvertTypeToCsharpSource
 937    //  _b((", Meta.ConvertTypeToCsharpSource(typeof(T)), @" i) => { b_temp.Add(i - a_mean); });
 938    //  ", Meta.ConvertTypeToCsharpSource(typeof(T)), "[] a_cross_b = new ", Meta.ConvertTypeToCsharpSource(typeof(T)), 
 939    //  int count = 0;
 940    //  a_temp.Stepper((", Meta.ConvertTypeToCsharpSource(typeof(T)), @" i_a) =>
 941    //  {
 942    //    b_temp.Stepper((", Meta.ConvertTypeToCsharpSource(typeof(T)), @" i_b) =>
 943    //    {
 944    //      a_cross_b[count++] = i_a * i_b;
 945    //    });
 946    //  });
 947    //  a_temp.Stepper((ref ", Meta.ConvertTypeToCsharpSource(typeof(T)), @" i) => { i *= i; });
 948    //  b_temp.Stepper((ref ", Meta.ConvertTypeToCsharpSource(typeof(T)), @" i) => { i *= i; });
 949    //  ", Meta.ConvertTypeToCsharpSource(typeof(T)), @" sum_a_cross_b = 0;
 950    //  foreach (", Meta.ConvertTypeToCsharpSource(typeof(T)), @" i in a_cross_b)
 951    //    sum_a_cross_b += i;
 952    //  ", Meta.ConvertTypeToCsharpSource(typeof(T)), @" sum_a_temp = 0;
 953    //  a_temp.Stepper((", Meta.ConvertTypeToCsharpSource(typeof(T)), @" i) => { sum_a_temp += i; });
 954    //  ", Meta.ConvertTypeToCsharpSource(typeof(T)), @" sum_b_temp = 0;
 955    //  b_temp.Stepper((", Meta.ConvertTypeToCsharpSource(typeof(T)), @" i) => { sum_b_temp += i; });
 956    //  return sum_a_cross_b / Compute<", Meta.ConvertTypeToCsharpSource(typeof(T)), @">.sqrt(sum_a_temp * sum_b_temp);
 957    //}"));
 958
 959    //            return Compute.Correlation_internal(a, b);
 960    //        };
 961
 962    //        public static T Correlation(Stepper<T> a, Stepper<T> b)
 963    //        {
 964    //            return Correlation_internal(a, b);
 965    //        }
 966
 967#endif
 968
 969  #endregion
 970
 971  #region Occurences
 972
 973  /// <summary>Counts the number of occurences of each item.</summary>
 974  /// <typeparam name="T">The generic type to count the occerences of.</typeparam>
 975  /// <param name="a">The first value in the data.</param>
 976  /// <param name="b">The rest of the data.</param>
 977  /// <returns>The occurence map of the data.</returns>
 978  public static IMap<int, T> Occurences<T>(T a, params T[] b) =>
 0979    Occurences<T>(step => { step(a); b.ToStepper()(step); });
 980
 981  /// <summary>Counts the number of occurences of each item.</summary>
 982  /// <typeparam name="T">The generic type to count the occerences of.</typeparam>
 983  /// <param name="equate">The equality delegate.</param>
 984  /// <param name="a">The first value in the data.</param>
 985  /// <param name="b">The rest of the data.</param>
 986  /// <returns>The occurence map of the data.</returns>
 987  public static IMap<int, T> Occurences<T>(Func<T, T, bool> equate, T a, params T[] b) =>
 0988    Occurences<T>(step => { step(a); b.ToStepper()(step); }, equate, null);
 989
 990  /// <summary>Counts the number of occurences of each item.</summary>
 991  /// <typeparam name="T">The generic type to count the occerences of.</typeparam>
 992  /// <param name="hash">The hash code delegate.</param>
 993  /// <param name="a">The first value in the data.</param>
 994  /// <param name="b">The rest of the data.</param>
 995  /// <returns>The occurence map of the data.</returns>
 996  public static IMap<int, T> Occurences<T>(Func<T, int> hash, T a, params T[] b) =>
 0997    Occurences<T>(step => { step(a); b.ToStepper()(step); }, null, hash);
 998
 999  /// <summary>Counts the number of occurences of each item.</summary>
 1000  /// <typeparam name="T">The generic type to count the occerences of.</typeparam>
 1001  /// <param name="equate">The equality delegate.</param>
 1002  /// <param name="hash">The hash code delegate.</param>
 1003  /// <param name="a">The first value in the data.</param>
 1004  /// <param name="b">The rest of the data.</param>
 1005  /// <returns>The occurence map of the data.</returns>
 1006  public static IMap<int, T> Occurences<T>(Func<T, T, bool> equate, Func<T, int> hash, T a, params T[] b) =>
 01007    Occurences<T>(step => { step(a); b.ToStepper()(step); }, equate, hash);
 1008
 1009  /// <summary>Counts the number of occurences of each item.</summary>
 1010  /// <typeparam name="T">The generic type to count the occerences of.</typeparam>
 1011  /// <param name="stepper">The data to count the occurences of.</param>
 1012  /// <param name="equate">The equality delegate.</param>
 1013  /// <param name="hash">The hash code delegate.</param>
 1014  /// <returns>The occurence map of the data.</returns>
 1015  public static IMap<int, T> Occurences<T>(Action<Action<T>> stepper, Func<T, T, bool>? equate = null, Func<T, int>? has
 01016  {
 01017    IMap<int, T> map = MapHashLinked.New<int, T>(equate, hash);
 01018    stepper(a =>
 01019    {
 01020      if (map.Contains(a))
 01021      {
 01022        map[a]++;
 01023      }
 01024      else
 01025      {
 01026        map[a] = 1;
 01027      }
 01028    });
 01029    return map;
 01030  }
 1031
 1032  #endregion
 1033
 1034  #region Hamming Distance
 1035
 1036  /// <summary>Computes the Hamming distance (using an iterative algorithm).</summary>
 1037  /// <typeparam name="T">The element type of the sequences.</typeparam>
 1038  /// <typeparam name="TGetA">The type of get index function for the first sequence.</typeparam>
 1039  /// <typeparam name="TGetB">The type of get index function for the second sequence.</typeparam>
 1040  /// <typeparam name="TEquate">The type of equality check function.</typeparam>
 1041  /// <param name="length">The length of the sequences.</param>
 1042  /// <param name="a">The get index function for the first sequence.</param>
 1043  /// <param name="b">The get index function for the second sequence.</param>
 1044  /// <param name="equate">The equality check function.</param>
 1045  /// <returns>The computed Hamming distance of the two sequences.</returns>
 1046  public static int HammingDistance<T, TGetA, TGetB, TEquate>(
 1047    int length,
 1048    TGetA a = default,
 1049    TGetB b = default,
 1050    TEquate equate = default)
 1051    where TGetA : struct, IFunc<int, T>
 1052    where TGetB : struct, IFunc<int, T>
 1053    where TEquate : struct, IFunc<T, T, bool>
 01054  {
 01055    if (length < 0)
 01056    {
 01057      throw new ArgumentOutOfRangeException(nameof(length), length, $@"{nameof(length)} < 0");
 1058    }
 01059    int distance = 0;
 01060    for (int i = 0; i < length; i++)
 01061    {
 01062      if (!equate.Invoke(a.Invoke(i), b.Invoke(i)))
 01063      {
 01064        distance++;
 01065      }
 01066    }
 01067    return distance;
 01068  }
 1069
 1070  /// <summary>Computes the Hamming distance (using an iterative algorithm).</summary>
 1071  /// <param name="a">The first sequence of the operation.</param>
 1072  /// <param name="b">The second sequence of the operation.</param>
 1073  /// <returns>The computed Hamming distance of the two sequences.</returns>
 1074  public static int HammingDistance(ReadOnlySpan<char> a, ReadOnlySpan<char> b) =>
 151075    HammingDistance<char, CharEquate>(a, b);
 1076
 1077  /// <summary>Computes the Hamming distance (using an iterative algorithm).</summary>
 1078  /// <typeparam name="T">The element type of the sequences.</typeparam>
 1079  /// <typeparam name="TEquate">The type of equality check function.</typeparam>
 1080  /// <param name="a">The first sequence.</param>
 1081  /// <param name="b">The second sequence.</param>
 1082  /// <param name="equate">The equality check function.</param>
 1083  /// <returns>The computed Hamming distance of the two sequences.</returns>
 1084  public static int HammingDistance<T, TEquate>(
 1085    ReadOnlySpan<T> a,
 1086    ReadOnlySpan<T> b,
 1087    TEquate equate = default)
 1088    where TEquate : struct, IFunc<T, T, bool>
 151089  {
 151090    if (a.Length != b.Length)
 21091    {
 21092      throw new ArgumentException($@"{nameof(a)}.{nameof(a.Length)} ({a.Length}) != {nameof(b)}.{nameof(b.Length)} ({b.L
 1093    }
 131094    int distance = 0;
 841095    for (int i = 0; i < a.Length; i++)
 291096    {
 291097      if (!equate.Invoke(a[i], b[i]))
 141098      {
 141099        distance++;
 141100      }
 291101    }
 131102    return distance;
 131103  }
 1104
 1105  #endregion
 1106
 1107  #region Levenshtein distance
 1108
 1109  /// <summary>Computes the Levenshtein distance (using an recursive algorithm).</summary>
 1110  /// <typeparam name="T">The element type of the sequences.</typeparam>
 1111  /// <typeparam name="TGetA">The type of get index function for the first sequence.</typeparam>
 1112  /// <typeparam name="TGetB">The type of get index function for the second sequence.</typeparam>
 1113  /// <typeparam name="TEquate">The type of equality check function.</typeparam>
 1114  /// <param name="a_length">The length of the first sequence.</param>
 1115  /// <param name="b_length">The length of the second sequence.</param>
 1116  /// <param name="a">The get index function for the first sequence.</param>
 1117  /// <param name="b">The get index function for the second sequence.</param>
 1118  /// <param name="equate">The equality check function.</param>
 1119  /// <returns>The computed Levenshtein distance of the two sequences.</returns>
 1120  public static int LevenshteinDistanceRecursive<T, TGetA, TGetB, TEquate>(
 1121    int a_length,
 1122    int b_length,
 1123    TGetA a = default,
 1124    TGetB b = default,
 1125    TEquate equate = default)
 1126    where TGetA : struct, IFunc<int, T>
 1127    where TGetB : struct, IFunc<int, T>
 1128    where TEquate : struct, IFunc<T, T, bool>
 01129  {
 01130    if (a_length < 0)
 01131    {
 01132      throw new ArgumentOutOfRangeException(nameof(a_length), a_length, $@"{nameof(a_length)} < 0");
 1133    }
 01134    if (b_length < 0)
 01135    {
 01136      throw new ArgumentOutOfRangeException(nameof(b_length), b_length, $@"{nameof(b_length)} < 0");
 1137    }
 1138    int LDR(int ai, int bi)
 01139    {
 01140      int _ai = ai + 1;
 01141      int _bi = bi + 1;
 01142      return
 01143        ai >= a_length ?
 01144        bi >= b_length ? 0 :
 01145        1 + LDR(ai, _bi) :
 01146      bi >= b_length ? 1 + LDR(_ai, bi) :
 01147      equate.Invoke(a.Invoke(ai), b.Invoke(bi)) ? LDR(_ai, _bi) :
 01148      1 + MinimumValue(default, LDR(ai, _bi), LDR(_ai, bi), LDR(_ai, _bi));
 01149    }
 01150    return LDR(0, 0);
 01151  }
 1152
 1153  /// <summary>Computes the Levenshtein distance (using an recursive algorithm).</summary>
 1154  /// <param name="a">The first sequence of the operation.</param>
 1155  /// <param name="b">The second sequence of the operation.</param>
 1156  /// <returns>The computed Levenshtein distance of the two sequences.</returns>
 1157  public static int LevenshteinDistanceRecursive(ReadOnlySpan<char> a, ReadOnlySpan<char> b) =>
 01158    LevenshteinDistanceRecursive<char, CharEquate>(a, b);
 1159
 1160  /// <summary>Computes the Levenshtein distance (using an recursive algorithm).</summary>
 1161  /// <typeparam name="T">The element type of the sequences.</typeparam>
 1162  /// <typeparam name="TEquate">The type of equality check function.</typeparam>
 1163  /// <param name="a">The first sequence.</param>
 1164  /// <param name="b">The second sequence.</param>
 1165  /// <param name="equate">The equality check function.</param>
 1166  /// <returns>The computed Levenshtein distance of the two sequences.</returns>
 1167  public static int LevenshteinDistanceRecursive<T, TEquate>(
 1168    ReadOnlySpan<T> a,
 1169    ReadOnlySpan<T> b,
 1170    TEquate equate = default)
 1171    where TEquate : struct, IFunc<T, T, bool>
 01172  {
 1173    int LDR(
 1174      ReadOnlySpan<T> a,
 1175      ReadOnlySpan<T> b,
 1176      int ai, int bi)
 01177    {
 01178      int _ai = ai + 1;
 01179      int _bi = bi + 1;
 01180      return
 01181        ai >= a.Length ?
 01182        bi >= b.Length ? 0 :
 01183        1 + LDR(a, b, ai, _bi) :
 01184      bi >= b.Length ? 1 + LDR(a, b, _ai, bi) :
 01185      equate.Invoke(a[ai], b[bi]) ? LDR(a, b, _ai, _bi) :
 01186      1 + MinimumValue(default, LDR(a, b, ai, _bi), LDR(a, b, _ai, bi), LDR(a, b, _ai, _bi));
 01187    }
 01188    return LDR(a, b, 0, 0);
 01189  }
 1190
 1191  /// <summary>Computes the Levenshtein distance (using an iterative algorithm).</summary>
 1192  /// <typeparam name="T">The element type of the sequences.</typeparam>
 1193  /// <typeparam name="TGetA">The type of get index function for the first sequence.</typeparam>
 1194  /// <typeparam name="TGetB">The type of get index function for the second sequence.</typeparam>
 1195  /// <typeparam name="TEquate">The type of equality check function.</typeparam>
 1196  /// <param name="a_length">The length of the first sequence.</param>
 1197  /// <param name="b_length">The length of the second sequence.</param>
 1198  /// <param name="a">The get index function for the first sequence.</param>
 1199  /// <param name="b">The get index function for the second sequence.</param>
 1200  /// <param name="equate">The equality check function.</param>
 1201  /// <returns>The computed Levenshtein distance of the two sequences.</returns>
 1202  public static int LevenshteinDistanceIterative<T, TGetA, TGetB, TEquate>(
 1203    int a_length,
 1204    int b_length,
 1205    TGetA a = default,
 1206    TGetB b = default,
 1207    TEquate equate = default)
 1208    where TGetA : struct, IFunc<int, T>
 1209    where TGetB : struct, IFunc<int, T>
 1210    where TEquate : struct, IFunc<T, T, bool>
 01211  {
 01212    if (a_length < 0)
 01213    {
 01214      throw new ArgumentOutOfRangeException(nameof(a_length), a_length, $@"{nameof(a_length)} < 0");
 1215    }
 01216    if (b_length < 0)
 01217    {
 01218      throw new ArgumentOutOfRangeException(nameof(b_length), b_length, $@"{nameof(b_length)} < 0");
 1219    }
 01220    a_length++;
 01221    b_length++;
 01222    int[,] matrix = new int[a_length, b_length];
 01223    for (int i = 1; i < a_length; i++)
 01224    {
 01225      matrix[i, 0] = i;
 01226    }
 01227    for (int i = 1; i < b_length; i++)
 01228    {
 01229      matrix[0, i] = i;
 01230    }
 01231    for (int bi = 1; bi < b_length; bi++)
 01232    {
 01233      for (int ai = 1; ai < a_length; ai++)
 01234      {
 01235        int _ai = ai - 1;
 01236        int _bi = bi - 1;
 01237        matrix[ai, bi] = MinimumValue(default,
 01238          matrix[_ai, bi] + 1,
 01239          matrix[ai, _bi] + 1,
 01240          !equate.Invoke(a.Invoke(_ai), b.Invoke(_bi)) ? matrix[_ai, _bi] + 1 : matrix[_ai, _bi]);
 01241      }
 01242    }
 01243    return matrix[a_length - 1, b_length - 1];
 01244  }
 1245
 1246  /// <summary>Computes the Levenshtein distance (using an iterative algorithm).</summary>
 1247  /// <param name="a">The first sequence of the operation.</param>
 1248  /// <param name="b">The second sequence of the operation.</param>
 1249  /// <returns>The computed Levenshtein distance of the two sequences.</returns>
 1250  public static int LevenshteinDistanceIterative(ReadOnlySpan<char> a, ReadOnlySpan<char> b) =>
 01251    LevenshteinDistanceIterative<char, CharEquate>(a, b);
 1252
 1253  /// <summary>Computes the Levenshtein distance (using an iterative algorithm).</summary>
 1254  /// <typeparam name="T">The element type of the sequences.</typeparam>
 1255  /// <typeparam name="TEquate">The type of equality check function.</typeparam>
 1256  /// <param name="a">The first sequence.</param>
 1257  /// <param name="b">The second sequence.</param>
 1258  /// <param name="equate">The equality check function.</param>
 1259  /// <returns>The computed Levenshtein distance of the two sequences.</returns>
 1260  public static int LevenshteinDistanceIterative<T, TEquate>(
 1261    ReadOnlySpan<T> a,
 1262    ReadOnlySpan<T> b,
 1263    TEquate equate = default)
 1264    where TEquate : struct, IFunc<T, T, bool>
 01265  {
 01266    int a_length = a.Length + 1;
 01267    int b_length = b.Length + 1;
 01268    int[,] matrix = new int[a_length, b_length];
 01269    for (int i = 1; i < a_length; i++)
 01270    {
 01271      matrix[i, 0] = i;
 01272    }
 01273    for (int i = 1; i < b_length; i++)
 01274    {
 01275      matrix[0, i] = i;
 01276    }
 01277    for (int bi = 1; bi < b_length; bi++)
 01278    {
 01279      for (int ai = 1; ai < a_length; ai++)
 01280      {
 01281        int _ai = ai - 1;
 01282        int _bi = bi - 1;
 01283        matrix[ai, bi] = MinimumValue(default,
 01284          matrix[_ai, bi] + 1,
 01285          matrix[ai, _bi] + 1,
 01286          !equate.Invoke(a[_ai], b[_bi]) ? matrix[_ai, _bi] + 1 : matrix[_ai, _bi]);
 01287      }
 01288    }
 01289    return matrix[a_length - 1, b_length - 1];
 01290  }
 1291
 1292  #endregion
 1293
 1294  #region FilterOrdered
 1295
 1296  #region XML
 1297
 1298#pragma warning disable CS1711, CS1572, CS1735, SA1617
 1299
 1300  /// <summary>Filters a sequence to only values that are in order.</summary>
 1301  /// <typeparam name="T">The type of values in the sequence.</typeparam>
 1302  /// <typeparam name="TGet">The type of function to get a value at an index.</typeparam>
 1303  /// <typeparam name="TStep">The type of action to perform on every value that is in order.</typeparam>
 1304  /// <typeparam name="TCompare">The type of function for comparing <typeparamref name="T"/> values.</typeparam>
 1305  /// <param name="start">The starting index of the sequence.</param>
 1306  /// <param name="end">The ending index of the sequence.</param>
 1307  /// <param name="get">The function to get a value at an index.</param>
 1308  /// <param name="step">The action to perform on every value that is in order.</param>
 1309  /// <param name="compare">The function for comparing <typeparamref name="T"/> values.</param>
 1310  /// <param name="span">The sequence of <typeparamref name="T"/> values to filter.</param>
 1311  [Obsolete(NotIntended, true)]
 11312  public static void XML_FilterOrdered() => throw new DocumentationMethodException();
 1313
 1314  /// <inheritdoc cref="XML_FilterOrdered"/>
 1315  /// <param name="enumerable">The sequence of <typeparamref name="T"/> values to filter.</param>
 1316  /// <returns>The sequence of filtered values.</returns>
 1317  [Obsolete(NotIntended, true)]
 11318  public static void XML_FilterOrderedEnumerable() => throw new DocumentationMethodException();
 1319
 1320#pragma warning restore CS1711, CS1572, CS1735, SA1617
 1321
 1322  #endregion
 1323
 1324  /// <inheritdoc cref="XML_FilterOrdered"/>
 1325  public static void FilterOrdered<T>(int start, int end, Func<int, T> get, Action<T> step, Func<T, T, CompareResult>? c
 01326    FilterOrdered<T, SFunc<int, T>, SAction<T>, SFunc<T, T, CompareResult>>(start, end, get, step, compare ?? Compare);
 1327
 1328  /// <inheritdoc cref="XML_FilterOrdered"/>
 1329  public static void FilterOrdered<T, TGet, TStep, TCompare>(int start, int end, TGet get = default, TStep step = defaul
 1330    where TGet : struct, IFunc<int, T>
 1331    where TStep : struct, IAction<T>
 1332    where TCompare : struct, IFunc<T, T, CompareResult>
 01333  {
 01334    if (start <= end)
 01335    {
 01336      step.Invoke(get.Invoke(start));
 01337    }
 01338    for (int i = start; i <= end; i++)
 01339    {
 01340      if (compare.Invoke(get.Invoke(i - 1), get.Invoke(i)) is not Greater)
 01341      {
 01342        step.Invoke(get.Invoke(i));
 01343      }
 01344    }
 01345  }
 1346
 1347  /// <inheritdoc cref="XML_FilterOrdered"/>
 1348  public static void FilterOrdered<T>(ReadOnlySpan<T> span, Action<T> step, Func<T, T, CompareResult>? compare = null) =
 01349    FilterOrdered<T, SAction<T>, SFunc<T, T, CompareResult>>(span, step, compare ?? Compare);
 1350
 1351  /// <inheritdoc cref="XML_FilterOrdered"/>
 1352  public static void FilterOrdered<T, TStep, TCompare>(ReadOnlySpan<T> span, TStep step = default, TCompare compare = de
 1353    where TStep : struct, IAction<T>
 1354    where TCompare : struct, IFunc<T, T, CompareResult>
 01355  {
 01356    if (!span.IsEmpty)
 01357    {
 01358      step.Invoke(span[0]);
 01359    }
 01360    for (int i = 1; i < span.Length; i++)
 01361    {
 01362      if (compare.Invoke(span[i - 1], span[i]) is not Greater)
 01363      {
 01364        step.Invoke(span[i]);
 01365      }
 01366    }
 01367  }
 1368
 1369  /// <inheritdoc cref="XML_FilterOrderedEnumerable"/>
 1370  public static System.Collections.Generic.IEnumerable<T> FilterOrdered<T>(this System.Collections.Generic.IEnumerable<T
 61371    FilterOrdered<T, SFunc<T, T, CompareResult>>(enumerable, compare ?? Compare);
 1372
 1373  /// <inheritdoc cref="XML_FilterOrderedEnumerable"/>
 1374  public static System.Collections.Generic.IEnumerable<T> FilterOrdered<T, TCompare>(this System.Collections.Generic.IEn
 1375    where TCompare : struct, IFunc<T, T, CompareResult>
 61376  {
 61377    using System.Collections.Generic.IEnumerator<T> enumerator = enumerable.GetEnumerator();
 61378    if (enumerator.MoveNext())
 51379    {
 51380      T previous = enumerator.Current;
 51381      yield return enumerator.Current;
 131382      while (enumerator.MoveNext())
 81383      {
 81384        if (compare.Invoke(previous, enumerator.Current) is not Greater)
 51385        {
 51386          yield return enumerator.Current;
 51387        }
 81388        previous = enumerator.Current;
 81389      }
 51390    }
 61391  }
 1392
 1393  #endregion
 1394
 1395  #region IsOrdered
 1396
 1397#pragma warning disable SA1604, CS1711, CS1572
 1398
 1399  /// <typeparam name="T">The type of values to sort.</typeparam>
 1400  /// <typeparam name="TCompare">The type of compare function.</typeparam>
 1401  /// <typeparam name="TGet">The type of get function.</typeparam>
 1402  /// <param name="compare">The compare function.</param>
 1403  /// <param name="get">The get function.</param>
 1404  /// <param name="start">The starting index of the sort.</param>
 1405  /// <param name="end">The ending index of the sort.</param>
 1406  /// <param name="span">The span to be sorted.</param>
 1407  [Obsolete(NotIntended, true)]
 11408  public static void XML_IsOrdered() => throw new DocumentationMethodException();
 1409
 1410#pragma warning restore SA1604, CS1711, CS1572
 1411
 1412  /// <inheritdoc cref="XML_IsOrdered"/>
 1413  public static bool IsOrdered<T>(int start, int end, Func<int, T> get, Func<T, T, CompareResult>? compare = null) =>
 141414    IsOrdered<T, SFunc<T, T, CompareResult>, SFunc<int, T>>(start, end, compare ?? Compare, get);
 1415
 1416  /// <inheritdoc cref="XML_IsOrdered"/>
 1417  public static bool IsOrdered<T, TCompare, TGet>(int start, int end, TCompare compare = default, TGet get = default)
 1418    where TCompare : struct, IFunc<T, T, CompareResult>
 1419    where TGet : struct, IFunc<int, T>
 20811420  {
 71681421    for (int i = start + 1; i <= end; i++)
 35391422    {
 35391423      if (compare.Invoke(get.Invoke(i - 1), get.Invoke(i)) is Greater)
 20361424      {
 20361425        return false;
 1426      }
 15031427    }
 451428    return true;
 20811429  }
 1430
 1431  /// <inheritdoc cref="XML_IsOrdered"/>
 1432  public static bool IsOrdered<T>(ReadOnlySpan<T> span, Func<T, T, CompareResult>? compare = null) =>
 56391433    IsOrdered<T, SFunc<T, T, CompareResult>>(span, compare ?? Compare);
 1434
 1435  /// <inheritdoc cref="XML_IsOrdered"/>
 1436  public static bool IsOrdered<T, TCompare>(ReadOnlySpan<T> span, TCompare compare = default)
 1437    where TCompare : struct, IFunc<T, T, CompareResult>
 109411438  {
 7930601439    for (int i = 1; i < span.Length; i++)
 3933551440    {
 3933551441      if (compare.Invoke(span[i - 1], span[i]) is Greater)
 77661442      {
 77661443        return false;
 1444      }
 3855891445    }
 31751446    return true;
 109411447  }
 1448
 1449  /// <inheritdoc cref="XML_IsOrdered"/>
 1450  public static bool IsOrdered<T>(this System.Collections.Generic.IEnumerable<T> enumerable, Func<T, T, CompareResult>? 
 181451    IsOrdered<T, SFunc<T, T, CompareResult>>(enumerable, compare ?? Compare);
 1452
 1453  /// <inheritdoc cref="XML_IsOrdered"/>
 1454  public static bool IsOrdered<T, TCompare>(this System.Collections.Generic.IEnumerable<T> enumerable, TCompare compare 
 1455    where TCompare : struct, IFunc<T, T, CompareResult>
 181456  {
 181457    using System.Collections.Generic.IEnumerator<T> enumerator = enumerable.GetEnumerator();
 181458    if (!enumerator.MoveNext())
 21459    {
 21460      return true;
 1461    }
 161462    T previous = enumerator.Current;
 301463    while (enumerator.MoveNext())
 201464    {
 201465      if (compare.Invoke(previous, enumerator.Current) is Greater)
 61466      {
 61467        return false;
 1468      }
 141469      previous = enumerator.Current;
 141470    }
 101471    return true;
 181472  }
 1473
 1474  #endregion
 1475
 1476  #region IsPalindrome
 1477
 1478#pragma warning disable CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name
 1479#pragma warning disable CS1572 // XML comment has a param tag, but there is no parameter by that name
 1480#pragma warning disable SA1617 // Void return value should not be documented
 1481#pragma warning disable CS1735 // XML comment has a typeparamref tag, but there is no type parameter by that name
 1482
 1483  /// <summary>Determines if a sequence is a palindrome.</summary>
 1484  /// <typeparam name="T">The type of values in the sequence.</typeparam>
 1485  /// <typeparam name="TGet">The type of method to get a <typeparamref name="T"/> value from an <see cref="int"/> index.
 1486  /// <typeparam name="TEquate">The type of method for comparing <typeparamref name="T"/> values for equality.</typepara
 1487  /// <param name="start">The inclusive starting index of the palindrome check.</param>
 1488  /// <param name="end">The inclusive ending index of the palindrome check.</param>
 1489  /// <param name="get">The method to get a <typeparamref name="T"/> value from an <see cref="int"/> index.</param>
 1490  /// <param name="equate">The method for comparing <typeparamref name="T"/> values for equality.</param>
 1491  /// <param name="span">The sequence to check.</param>
 1492  /// <returns>True if the sequence is a palindrome; False if not.</returns>
 1493  [Obsolete(NotIntended, true)]
 11494  public static void XML_IsPalindrome() => throw new DocumentationMethodException();
 1495
 1496#pragma warning restore CS1735 // XML comment has a typeparamref tag, but there is no type parameter by that name
 1497#pragma warning restore SA1617 // Void return value should not be documented
 1498#pragma warning restore CS1572 // XML comment has a param tag, but there is no parameter by that name
 1499#pragma warning restore CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name
 1500
 1501  /// <inheritdoc cref="XML_IsPalindrome"/>
 1502  public static bool IsPalindrome<T>(int start, int end, Func<int, T> get, Func<T, T, bool>? equate = default) =>
 361503    IsPalindrome<T, SFunc<int, T>, SFunc<T, T, bool>>(start, end, get, equate ?? Equate);
 1504
 1505  /// <inheritdoc cref="XML_IsPalindrome"/>
 1506  public static bool IsPalindrome<T, TGet, TEquate>(int start, int end, TGet get = default, TEquate equate = default)
 1507    where TGet : struct, IFunc<int, T>
 1508    where TEquate : struct, IFunc<T, T, bool>
 361509  {
 361510    int middle = (end - start) / 2 + start;
 1721511    for (int i = start; i <= middle; i++)
 661512    {
 661513      if (!equate.Invoke(get.Invoke(i), get.Invoke(end - i + start)))
 161514      {
 161515        return false;
 1516      }
 501517    }
 201518    return true;
 361519  }
 1520
 1521  /// <inheritdoc cref="XML_IsPalindrome"/>
 1522  public static bool IsPalindrome(ReadOnlySpan<char> span) =>
 141523    IsPalindrome<char, CharEquate>(span);
 1524
 1525  /// <inheritdoc cref="XML_IsPalindrome"/>
 1526  public static bool IsPalindrome<T>(ReadOnlySpan<T> span, Func<T, T, bool>? equate = default) =>
 141527    IsPalindrome<T, SFunc<T, T, bool>>(span, equate ?? Equate);
 1528
 1529  /// <inheritdoc cref="XML_IsPalindrome"/>
 1530  public static bool IsPalindrome<T, TEquate>(ReadOnlySpan<T> span, TEquate equate = default)
 1531    where TEquate : struct, IFunc<T, T, bool>
 281532  {
 281533    int middle = span.Length / 2;
 1241534    for (int i = 0; i < middle; i++)
 461535    {
 461536      if (!equate.Invoke(span[i], span[^(i + 1)]))
 121537      {
 121538        return false;
 1539      }
 341540    }
 161541    return true;
 281542  }
 1543
 1544  #endregion
 1545
 1546  #region IsInterleaved
 1547
 1548  #region XML
 1549
 1550#pragma warning disable SA1604, CS1572, CS1734, SA1617, CS1735, CS1711
 1551
 1552  /// <typeparam name="T">The element type of the sequences.</typeparam>
 1553  /// <param name="a">The first sequence to determine if <paramref name="c"/> is interleaved of.</param>
 1554  /// <param name="b">The second sequence to determine if <paramref name="c"/> is interleaved of.</param>
 1555  /// <param name="c">The sequence to determine if it is interleaved from <paramref name="a"/> and <paramref name="b"/>.
 1556  /// <param name="equate">The function for equating <typeparamref name="T"/> values.</param>
 1557  /// <returns>True if <paramref name="c"/> is interleaved of <paramref name="a"/> and <paramref name="b"/> or False if 
 1558  /// <example>
 1559  /// <code>
 1560  /// IsInterleaved("abc", "xyz", "axbycz") // True
 1561  /// IsInterleaved("abc", "xyz", "cbazyx") // False (order not preserved)
 1562  /// IsInterleaved("abc", "xyz", "012345") // False
 1563  /// </code>
 1564  /// </example>
 1565  [Obsolete(NotIntended, true)]
 11566  public static void XML_IsInterleaved() => throw new DocumentationMethodException();
 1567
 1568  /// <summary>
 1569  /// Determines if <paramref name="c"/> is interleved of <paramref name="a"/> and <paramref name="b"/>,
 1570  /// meaning that <paramref name="c"/> it contains all values of <paramref name="a"/> and <paramref name="b"/>
 1571  /// while retaining the order of the respective values. Uses a recursive algorithm.<br/>
 1572  /// Runtime: O(2^(Min(<paramref name="a"/>.Length + <paramref name="b"/>.Length, <paramref name="c"/>.Length))), Ω(1)<
 1573  /// Memory: O(1)
 1574  /// </summary>
 1575  /// <inheritdoc cref="XML_IsInterleaved"/>
 1576  [Obsolete(NotIntended, true)]
 11577  public static void XML_IsInterleavedRecursive() => throw new DocumentationMethodException();
 1578
 1579  /// <summary>
 1580  /// Determines if <paramref name="c"/> is interleved of <paramref name="a"/> and <paramref name="b"/>,
 1581  /// meaning that <paramref name="c"/> it contains all values of <paramref name="a"/> and <paramref name="b"/>
 1582  /// while retaining the order of the respective values. Uses a interative algorithm.<br/>
 1583  /// Runtime: O(Min(<paramref name="a"/>.Length * <paramref name="b"/>.Length))), Ω(1)<br/>
 1584  /// Memory: O(<paramref name="a"/>.Length * <paramref name="b"/>.Length)
 1585  /// </summary>
 1586  /// <inheritdoc cref="XML_IsInterleaved"/>
 1587  [Obsolete(NotIntended, true)]
 11588  public static void XML_IsInterleavedIterative() => throw new DocumentationMethodException();
 1589
 1590#pragma warning restore SA1604, CS1572, CS1734, SA1617, CS1735, CS1711
 1591
 1592  #endregion
 1593
 1594  /// <inheritdoc cref="XML_IsInterleavedRecursive"/>
 1595  public static bool IsInterleavedRecursive<T>(ReadOnlySpan<T> a, ReadOnlySpan<T> b, ReadOnlySpan<T> c, Func<T, T, bool>
 01596    IsInterleavedRecursive<T, SFunc<T, T, bool>>(a, b, c, equate ?? Equate);
 1597
 1598  /// <inheritdoc cref="XML_IsInterleavedRecursive"/>
 1599  public static bool IsInterleavedRecursive(ReadOnlySpan<char> a, ReadOnlySpan<char> b, ReadOnlySpan<char> c) =>
 191600    IsInterleavedRecursive<char, CharEquate>(a, b, c);
 1601
 1602  /// <inheritdoc cref="XML_IsInterleavedRecursive"/>
 1603  public static bool IsInterleavedRecursive<T, TEquate>(ReadOnlySpan<T> a, ReadOnlySpan<T> b, ReadOnlySpan<T> c, TEquate
 1604    where TEquate : struct, IFunc<T, T, bool>
 191605  {
 191606    if (a.Length + b.Length != c.Length)
 51607    {
 51608      return false;
 1609    }
 1610
 1611    bool Implementation(ReadOnlySpan<T> a, ReadOnlySpan<T> b, ReadOnlySpan<T> c) =>
 781612      a.IsEmpty && b.IsEmpty && c.IsEmpty ||
 781613      (
 781614        !c.IsEmpty &&
 781615        (
 781616          (!a.IsEmpty && equate.Invoke(a[0], c[0]) && Implementation(a[1..], b, c[1..])) ||
 781617          (!b.IsEmpty && equate.Invoke(b[0], c[0]) && Implementation(a, b[1..], c[1..]))
 781618        )
 781619      );
 1620
 141621    return Implementation(a, b, c);
 191622  }
 1623
 1624  /// <inheritdoc cref="XML_IsInterleavedIterative"/>
 1625  public static bool IsInterleavedIterative<T>(ReadOnlySpan<T> a, ReadOnlySpan<T> b, ReadOnlySpan<T> c, Func<T, T, bool>
 01626    IsInterleavedIterative<T, SFunc<T, T, bool>>(a, b, c, equate ?? Equate);
 1627
 1628  /// <inheritdoc cref="XML_IsInterleavedRecursive"/>
 1629  public static bool IsInterleavedIterative(ReadOnlySpan<char> a, ReadOnlySpan<char> b, ReadOnlySpan<char> c) =>
 171630    IsInterleavedIterative<char, CharEquate>(a, b, c);
 1631
 1632  /// <inheritdoc cref="XML_IsInterleavedIterative"/>
 1633  public static bool IsInterleavedIterative<T, TEquate>(ReadOnlySpan<T> a, ReadOnlySpan<T> b, ReadOnlySpan<T> c, TEquate
 1634    where TEquate : struct, IFunc<T, T, bool>
 171635  {
 171636    if (a.Length + b.Length != c.Length)
 51637    {
 51638      return false;
 1639    }
 121640    bool[,] d = new bool[a.Length + 1, b.Length + 1];
 961641    for (int i = 0; i <= a.Length; ++i)
 361642    {
 3121643      for (int j = 0; j <= b.Length; ++j)
 1201644      {
 1201645        d[i, j] =
 1201646          (i is 0 && j is 0) ||
 1201647          (
 1201648            i is 0 ? (equate.Invoke(b[j - 1], c[j - 1]) && d[i, j - 1]) :
 1201649            j is 0 ? (equate.Invoke(a[i - 1], c[i - 1]) && d[i - 1, j]) :
 1201650            equate.Invoke(a[i - 1], c[i + j - 1]) && !equate.Invoke(b[j - 1], c[i + j - 1]) ? d[i - 1, j] :
 1201651            !equate.Invoke(a[i - 1], c[i + j - 1]) && equate.Invoke(b[j - 1], c[i + j - 1]) ? d[i, j - 1] :
 1201652            equate.Invoke(a[i - 1], c[i + j - 1]) && equate.Invoke(b[j - 1], c[i + j - 1]) && (d[i - 1, j] || d[i, j - 1
 1201653          );
 1654
 1655        #region expanded version
 1656
 1657        // if (i is 0 && j is 0)
 1658        // {
 1659        //     d[i, j] = true;
 1660        // }
 1661        // else if (i is 0)
 1662        // {
 1663        //     if (equate.Do(b[j - 1], c[j - 1]))
 1664        //     {
 1665        //         d[i, j] = d[i, j - 1];
 1666        //     }
 1667        // }
 1668        // else if (j is 0)
 1669        // {
 1670        //     if (equate.Do(a[i - 1], c[i - 1]))
 1671        //     {
 1672        //         d[i, j] = d[i - 1, j];
 1673        //     }
 1674        // }
 1675        // else if (equate.Do(a[i - 1], c[i + j - 1]) && !equate.Do(b[j - 1], c[i + j - 1]))
 1676        // {
 1677        //     d[i, j] = d[i - 1, j];
 1678        // }
 1679        // else if (!equate.Do(a[i - 1], c[i + j - 1]) && equate.Do(b[j - 1], c[i + j - 1]))
 1680        // {
 1681        //     d[i, j] = d[i, j - 1];
 1682        // }
 1683        // else if (equate.Do(a[i - 1], c[i + j - 1]) && equate.Do(b[j - 1], c[i + j - 1]))
 1684        // {
 1685        //     d[i, j] = d[i - 1, j] || d[i, j - 1];
 1686        // }
 1687
 1688        #endregion
 1201689      }
 361690    }
 121691    return d[a.Length, b.Length];
 171692  }
 1693
 1694  #endregion
 1695
 1696  #region IsReorderOf
 1697
 1698  /// <inheritdoc cref="IsReorderOf{T, TEquate, THash}(ReadOnlySpan{T}, ReadOnlySpan{T}, TEquate, THash)"/>
 1699  public static bool IsReorderOf<T>(ReadOnlySpan<T> a, ReadOnlySpan<T> b, Func<T, T, bool>? equate = null, Func<T, int>?
 381700    IsReorderOf<T, SFunc<T, T, bool>, SFunc<T, int>>(a, b, equate ?? Equate, hash ?? Hash);
 1701
 1702  /// <summary>Checks if two spans are re-orders of each other meaning they contain the same number of each element.</su
 1703  /// <typeparam name="T">The element type of each span.</typeparam>
 1704  /// <typeparam name="TEquate">The type of method for determining equality of values.</typeparam>
 1705  /// <typeparam name="THash">The type of method for hashing the values.</typeparam>
 1706  /// <param name="a">The first span.</param>
 1707  /// <param name="b">The second span.</param>
 1708  /// <param name="equate">The method for determining equality of values.</param>
 1709  /// <param name="hash">The method for hashing the values.</param>
 1710  /// <returns>True if both spans contain the same number of each element.</returns>
 1711  public static bool IsReorderOf<T, TEquate, THash>(ReadOnlySpan<T> a, ReadOnlySpan<T> b, TEquate equate = default, THas
 1712    where TEquate : struct, IFunc<T, T, bool>
 1713    where THash : struct, IFunc<T, int>
 381714  {
 381715    if (a.IsEmpty && b.IsEmpty)
 41716    {
 41717      return true;
 1718    }
 341719    if (a.Length != b.Length)
 141720    {
 141721      return false;
 1722    }
 201723    MapHashLinked<int, T, TEquate, THash> counts = new(equate: equate, hash: hash, expectedCount: a.Length);
 2001724    foreach (T value in a)
 701725    {
 701726      counts.AddOrUpdate<int, T, Int32Increment>(value, 1);
 701727    }
 1741728    foreach (T value in b)
 621729    {
 621730      var (success, _, _, count) = counts.TryUpdate<Int32Decrement>(value);
 621731      if (!success || count is -1)
 101732      {
 101733        return false;
 1734      }
 521735    }
 101736    return true;
 381737  }
 1738
 1739  #endregion
 1740
 1741  #region ContainsDuplicates
 1742
 1743  /// <summary>Determines if the span contains any duplicate values.</summary>
 1744  /// <typeparam name="T">The element type of the span.</typeparam>
 1745  /// <param name="span">The span to look for duplicates in.</param>
 1746  /// <param name="equate">The function for equating values.</param>
 1747  /// <param name="hash">The function for hashing values.</param>
 1748  /// <returns>True if the span contains duplicates.</returns>
 1749  public static bool ContainsDuplicates<T>(Span<T> span, Func<T, T, bool>? equate = null, Func<T, int>? hash = null) =>
 20191750    ContainsDuplicates<T, SFunc<T, T, bool>, SFunc<T, int>>(span, equate ?? Equate, hash ?? Hash);
 1751
 1752  /// <summary>Determines if the span contains any duplicate values.</summary>
 1753  /// <typeparam name="T">The element type of the span.</typeparam>
 1754  /// <typeparam name="TEquate">The type of function for equating values.</typeparam>
 1755  /// <typeparam name="THash">The type of function for hashing values.</typeparam>
 1756  /// <param name="span">The span to look for duplicates in.</param>
 1757  /// <param name="equate">The function for equating values.</param>
 1758  /// <param name="hash">The function for hashing values.</param>
 1759  /// <returns>True if the span contains duplicates.</returns>
 1760  public static bool ContainsDuplicates<T, TEquate, THash>(Span<T> span, TEquate equate = default, THash hash = default)
 1761    where TEquate : struct, IFunc<T, T, bool>
 1762    where THash : struct, IFunc<T, int>
 20191763  {
 20191764    SetHashLinked<T, TEquate, THash> set = new(equate: equate, hash: hash, expectedCount: span.Length);
 301611765    foreach (T element in span)
 120551766    {
 120551767      if (!set.TryAdd(element).Success)
 61768      {
 61769        return true;
 1770      }
 120491771    }
 20131772    return false;
 20191773  }
 1774
 1775  #endregion
 1776
 1777  #region Contains
 1778
 1779  /// <summary>Determines if a span contains a value.</summary>
 1780  /// <typeparam name="T">The element type of the span.</typeparam>
 1781  /// <param name="span">The span to check for the value in.</param>
 1782  /// <param name="value">The value to look for.</param>
 1783  /// <param name="equate">The function for equating values.</param>
 1784  /// <returns>True if the value was found.</returns>
 1785  public static bool Contains<T>(Span<T> span, T value, Func<T, T, bool>? equate = null) =>
 240181786    Contains<T, SFunc<T, T, bool>>(span, value, equate ?? Equate);
 1787
 1788  /// <summary>Determines if a span contains a value.</summary>
 1789  /// <typeparam name="T">The element type of the span.</typeparam>
 1790  /// <typeparam name="TEquate">The type of function for equating values.</typeparam>
 1791  /// <param name="span">The span to check for the value in.</param>
 1792  /// <param name="value">The value to look for.</param>
 1793  /// <param name="equate">The function for equating values.</param>
 1794  /// <returns>True if the value was found.</returns>
 1795  public static bool Contains<T, TEquate>(Span<T> span, T value, TEquate equate = default)
 1796    where TEquate : struct, IFunc<T, T, bool>
 240181797  {
 48721041798    foreach (T element in span)
 24000281799    {
 24000281800      if (equate.Invoke(value, element))
 61801      {
 61802        return true;
 1803      }
 24000221804    }
 240121805    return false;
 240181806  }
 1807
 1808  #endregion
 1809
 1810  #region Any
 1811
 1812  /// <summary>Determines if a span contains any predicated values.</summary>
 1813  /// <typeparam name="T">The element type of the span.</typeparam>
 1814  /// <param name="span">The span to scan for predicated values in.</param>
 1815  /// <param name="predicate">The predicate of the values.</param>
 1816  /// <returns>True if a predicated was found.</returns>
 1817  public static bool Any<T>(Span<T> span, Func<T, bool> predicate)
 120181818  {
 120181819    if (predicate is null)
 11820    {
 11821      throw new ArgumentNullException(nameof(predicate));
 1822    }
 120171823    return Any<T, SFunc<T, bool>>(span, predicate);
 120171824  }
 1825
 1826  /// <summary>Determines if a span contains a value.</summary>
 1827  /// <typeparam name="T">The element type of the span.</typeparam>
 1828  /// <typeparam name="TPredicate">The function for equating values.</typeparam>
 1829  /// <param name="span">The span to check for the value in.</param>
 1830  /// <param name="predicate">The value to look for.</param>
 1831  /// <returns>True if a predicated was found.</returns>
 1832  public static bool Any<T, TPredicate>(Span<T> span, TPredicate predicate = default)
 1833    where TPredicate : struct, IFunc<T, bool>
 120171834  {
 1801321835    foreach (T element in span)
 720431836    {
 720431837      if (predicate.Invoke(element))
 51838      {
 51839        return true;
 1840      }
 720381841    }
 120121842    return false;
 120171843  }
 1844
 1845  #endregion
 1846
 1847  #region Get X Least/Greatest
 1848
 1849  /// <summary>Gets the <paramref name="count"/> least values from <paramref name="values"/> in <strong>no particular or
 1850  /// <typeparam name="T">The type of <paramref name="values"/>.</typeparam>
 1851  /// <typeparam name="TCompare">The type of function for comparing <typeparamref name="T"/> instances.</typeparam>
 1852  /// <param name="values">The values to get <paramref name="count"/> values from.</param>
 1853  /// <param name="count">The number of items to get from <paramref name="values"/>.</param>
 1854  /// <param name="compare">The function for comparing <typeparamref name="T"/> instances.</param>
 1855  /// <returns>The <paramref name="count"/> least values from <paramref name="values"/> in <strong>no particular order</
 1856  public static T[] GetLeast<T, TCompare>(System.Collections.Generic.IEnumerable<T> values, int count, TCompare compare 
 1857    where TCompare : struct, IFunc<T, T, CompareResult>
 301858  {
 301859    if (values is null) throw new ArgumentNullException(nameof(values));
 341860    if (count <= 0) throw new ArgumentOutOfRangeException(nameof(count), count, $@"{nameof(count)} <= 0");
 261861    HeapArray<T, TCompare> heap = new(minimumCapacity: count + 1, compare: compare);
 1981862    foreach (T value in values)
 601863    {
 601864      heap.Enqueue(value);
 601865      if (heap.Count > count)
 221866      {
 221867        heap.Dequeue();
 221868      }
 601869    }
 281870    if (heap.Count is 0) throw new ArgumentException($"{nameof(values)}.Count() is 0", nameof(values));
 261871    if (heap.Count < count) throw new ArgumentOutOfRangeException(nameof(count), count, $@"{nameof(count)} > {nameof(val
 221872    return heap.ToArray();
 221873  }
 1874
 1875  /// <summary>Gets the <paramref name="count"/> least values from <paramref name="values"/> in <strong>no particular or
 1876  /// <typeparam name="T">The type of <paramref name="values"/>.</typeparam>
 1877  /// <typeparam name="TCompare">The type of function for comparing <typeparamref name="T"/> instances.</typeparam>
 1878  /// <param name="values">The values to get <paramref name="count"/> values from.</param>
 1879  /// <param name="count">The number of items to get from <paramref name="values"/>.</param>
 1880  /// <param name="compare">The function for comparing <typeparamref name="T"/> instances.</param>
 1881  /// <returns>The <paramref name="count"/> least values from <paramref name="values"/> in <strong>no particular order</
 1882  public static T[] GetLeast<T, TCompare>(ReadOnlySpan<T> values, int count, TCompare compare = default)
 1883    where TCompare : struct, IFunc<T, T, CompareResult>
 301884  {
 321885    if (values.IsEmpty) throw new ArgumentException($"{nameof(values)}.{nameof(values.IsEmpty)}", nameof(values));
 321886    if (count <= 0) throw new ArgumentOutOfRangeException(nameof(count), count, $@"{nameof(count)} <= 0");
 261887    if (count > values.Length) throw new ArgumentOutOfRangeException(nameof(count), count, $@"{nameof(count)} > {nameof(
 221888    HeapArray<T, TCompare> heap = new(minimumCapacity: count + 1, compare: compare);
 1821889    foreach (T value in values)
 581890    {
 581891      heap.Enqueue(value);
 581892      if (heap.Count > count)
 221893      {
 221894        heap.Dequeue();
 221895      }
 581896    }
 221897    return heap.ToArray();
 221898  }
 1899
 1900  /// <summary>Gets the <paramref name="count"/> greatest values from <paramref name="values"/> in <strong>no particular
 1901  /// <typeparam name="T">The type of <paramref name="values"/>.</typeparam>
 1902  /// <typeparam name="TCompare">The type of function for comparing <typeparamref name="T"/> instances.</typeparam>
 1903  /// <param name="values">The values to get <paramref name="count"/> values from.</param>
 1904  /// <param name="count">The number of items to get from <paramref name="values"/>.</param>
 1905  /// <param name="compare">The function for comparing <typeparamref name="T"/> instances.</param>
 1906  /// <returns>The <paramref name="count"/> greatest values from <paramref name="values"/> in <strong>no particular orde
 1907  public static T[] GetGreatest<T, TCompare>(System.Collections.Generic.IEnumerable<T> values, int count, TCompare compa
 1908    where TCompare : struct, IFunc<T, T, CompareResult> =>
 151909    GetLeast<T, CompareInvert<T, TCompare>>(values, count, compare);
 1910
 1911  /// <summary>Gets the <paramref name="count"/> greatest values from <paramref name="values"/> in <strong>no particular
 1912  /// <typeparam name="T">The type of <paramref name="values"/>.</typeparam>
 1913  /// <typeparam name="TCompare">The type of function for comparing <typeparamref name="T"/> instances.</typeparam>
 1914  /// <param name="values">The values to get <paramref name="count"/> values from.</param>
 1915  /// <param name="count">The number of items to get from <paramref name="values"/>.</param>
 1916  /// <param name="compare">The function for comparing <typeparamref name="T"/> instances.</param>
 1917  /// <returns>The <paramref name="count"/> greatest values from <paramref name="values"/> in <strong>no particular orde
 1918  public static T[] GetGreatest<T, TCompare>(ReadOnlySpan<T> values, int count, TCompare compare = default)
 1919    where TCompare : struct, IFunc<T, T, CompareResult> =>
 151920    GetLeast<T, CompareInvert<T, TCompare>>(values, count, compare);
 1921
 1922  /// <summary>Gets the <paramref name="count"/> greatest values from <paramref name="values"/> in <strong>no particular
 1923  /// <typeparam name="T">The type of <paramref name="values"/>.</typeparam>
 1924  /// <param name="values">The values to get <paramref name="count"/> values from.</param>
 1925  /// <param name="count">The number of items to get from <paramref name="values"/>.</param>
 1926  /// <param name="compare">The function for comparing <typeparamref name="T"/> instances.</param>
 1927  /// <returns>The <paramref name="count"/> greatest values from <paramref name="values"/> in <strong>no particular orde
 1928  public static T[] GetGreatest<T>(System.Collections.Generic.IEnumerable<T> values, int count, Func<T, T, CompareResult
 151929    GetGreatest<T, SFunc<T, T, CompareResult>>(values, count, compare ?? Compare);
 1930
 1931  /// <summary>Gets the <paramref name="count"/> greatest values from <paramref name="values"/> in <strong>no particular
 1932  /// <typeparam name="T">The type of <paramref name="values"/>.</typeparam>
 1933  /// <param name="values">The values to get <paramref name="count"/> values from.</param>
 1934  /// <param name="count">The number of items to get from <paramref name="values"/>.</param>
 1935  /// <param name="compare">The function for comparing <typeparamref name="T"/> instances.</param>
 1936  /// <returns>The <paramref name="count"/> greatest values from <paramref name="values"/> in <strong>no particular orde
 1937  public static T[] GetGreatest<T>(ReadOnlySpan<T> values, int count, Func<T, T, CompareResult>? compare = null) =>
 01938    GetGreatest<T, SFunc<T, T, CompareResult>>(values, count, compare ?? Compare);
 1939
 1940  /// <summary>Gets the <paramref name="count"/> least values from <paramref name="values"/> in <strong>no particular or
 1941  /// <typeparam name="T">The type of <paramref name="values"/>.</typeparam>
 1942  /// <param name="values">The values to get <paramref name="count"/> values from.</param>
 1943  /// <param name="count">The number of items to get from <paramref name="values"/>.</param>
 1944  /// <param name="compare">The function for comparing <typeparamref name="T"/> instances.</param>
 1945  /// <returns>The <paramref name="count"/> least values from <paramref name="values"/> in <strong>no particular order</
 1946  public static T[] GetLeast<T>(System.Collections.Generic.IEnumerable<T> values, int count, Func<T, T, CompareResult>? 
 151947    GetLeast<T, SFunc<T, T, CompareResult>>(values, count, compare ?? Compare);
 1948
 1949  /// <summary>Gets the <paramref name="count"/> least values from <paramref name="values"/> in <strong>no particular or
 1950  /// <typeparam name="T">The type of <paramref name="values"/>.</typeparam>
 1951  /// <param name="values">The values to get <paramref name="count"/> values from.</param>
 1952  /// <param name="count">The number of items to get from <paramref name="values"/>.</param>
 1953  /// <param name="compare">The function for comparing <typeparamref name="T"/> instances.</param>
 1954  /// <returns>The <paramref name="count"/> least values from <paramref name="values"/> in <strong>no particular order</
 1955  public static T[] GetLeast<T>(ReadOnlySpan<T> values, int count, Func<T, T, CompareResult>? compare = null) =>
 01956    GetLeast<T, SFunc<T, T, CompareResult>>(values, count, compare ?? Compare);
 1957
 1958  #endregion
 1959
 1960  #region CombineRanges
 1961
 1962  /// <summary>Simplifies a sequence of ranges by merging ranges without gaps between them.</summary>
 1963  /// <typeparam name="T">The type of values in the sequances of ranges to combine.</typeparam>
 1964  /// <param name="ranges">The ranges to be simplified.</param>
 1965  /// <returns>A potentially smaller sequence of ranges that have been merged if there were no gaps in no particular ord
 1966  public static System.Collections.Generic.IEnumerable<(T A, T B)> CombineRanges<T>(System.Collections.Generic.IEnumerab
 31967  {
 31968    if (ranges is null) throw new ArgumentNullException(nameof(ranges));
 31969    OmnitreeBoundsLinked<(T A, T B), T> omnitree =
 31970      new(
 31971      ((T A, T B) x, out T min1, out T max1) =>
 331972      {
 331973        min1 = x.A;
 331974        max1 = x.B;
 361975      });
 331976    foreach (var (A, B) in ranges)
 121977    {
 121978      if (Compare(B, A) is Less) throw new ArgumentException($"Invalid range in {nameof(ranges)}: Item2 < Item1.", nameo
 121979      bool overlap = false;
 121980      T min = default!;
 121981      T max = default!;
 121982      omnitree.StepperOverlapped(x =>
 61983      {
 61984        min = !overlap ? x.A : MinimumValue(min, x.A);
 61985        max = !overlap ? x.B : MaximumValue(max, x.B);
 61986        overlap = true;
 181987      }, A, B);
 121988      if (overlap)
 61989      {
 61990        min = MinimumValue(min, A);
 61991        max = MaximumValue(max, B);
 61992        omnitree.RemoveOverlapped(min, max);
 61993        omnitree.Add((min, max));
 61994      }
 1995      else
 61996      {
 61997        omnitree.Add((A, B));
 61998      }
 121999    }
 32000    return omnitree;
 32001  }
 2002
 2003  #endregion
 2004}

/home/runner/work/Towel/Towel/Sources/Towel/Statics-SortingAlgorithms.cs

#LineLine coverage
 1namespace Towel;
 2
 3/// <summary>Root type of the static functional methods in Towel.</summary>
 4public static partial class Statics
 5{
 6  #region Reverse
 7
 8  /// <inheritdoc cref="Reverse{T, TGet, TSet}(int, int, TGet, TSet)"/>
 9  public static void Reverse<T>(int start, int end, Func<int, T> get, Action<int, T> set) =>
 3410    Reverse<T, SFunc<int, T>, SAction<int, T>>(start, end, get, set);
 11
 12  /// <summary>Reverses the values in an <see cref="int"/> indexed sequence.</summary>
 13  /// <typeparam name="T">The type of values to reverse.</typeparam>
 14  /// <typeparam name="TGet">The type of the get function.</typeparam>
 15  /// <typeparam name="TSet">The type of the set function.</typeparam>
 16  /// <param name="start">The starting index of the reverse.</param>
 17  /// <param name="end">The ending index of the reverse.</param>
 18  /// <param name="get">The get function.</param>
 19  /// <param name="set">The set function.</param>
 20  public static void Reverse<T, TGet, TSet>(int start, int end, TGet get = default, TSet set = default)
 21    where TGet : struct, IFunc<int, T>
 22    where TSet : struct, IAction<int, T>
 2418223  {
 2418224    if (start <= end)
 2416625    {
 2416626      int mid = start + (end - start) / 2;
 1253797227      for (int a = start, b = end; a <= mid; a++, b--)
 415515828      {
 415515829        Swap<T, TGet, TSet>(a, b, get, set);
 415515830      }
 2416631    }
 32    else
 1633    {
 1634      int mid = start - (start - end) / 2;
 16235      for (int a = start, b = end; a >= mid; a--, b++)
 3836      {
 3837        Swap<T, TGet, TSet>(a, b, get, set);
 3838      }
 1639    }
 2418240  }
 41
 42  #endregion
 43
 44  #region Shuffle
 45
 46#pragma warning disable CS1711, CS1572
 47
 48  /// <summary>
 49  /// Sorts values into a randomized order.<br/>
 50  /// Runtime: O(n)<br/>
 51  /// Memory: O(1)
 52  /// </summary>
 53  /// <typeparam name="T">The type of values to shuffle.</typeparam>
 54  /// <typeparam name="TGet">The type of the get function.</typeparam>
 55  /// <typeparam name="TSet">The type of the set function.</typeparam>
 56  /// <param name="start">The starting index of the shuffle.</param>
 57  /// <param name="end">The ending index of the shuffle.</param>
 58  /// <param name="get">The get function.</param>
 59  /// <param name="set">The set function.</param>
 60  /// <param name="random">The random to shuffle with.</param>
 61  /// <param name="span">The span to shuffle.</param>
 62  [Obsolete(NotIntended, true)]
 163  public static void XML_Shuffle() => throw new DocumentationMethodException();
 64
 65#pragma warning restore CS1711, CS1572
 66
 67  /// <inheritdoc cref="XML_Shuffle"/>
 68  public static void Shuffle<T>(int start, int end, Func<int, T> get, Action<int, T> set, Random? random = null) =>
 069    Shuffle<T, SFunc<int, T>, SAction<int, T>>(start, end, get, set, random);
 70
 71  /// <inheritdoc cref="XML_Shuffle"/>
 72  public static void Shuffle<T, TGet, TSet>(int start, int end, TGet get = default, TSet set = default, Random? random =
 73    where TGet : struct, IFunc<int, T>
 74    where TSet : struct, IAction<int, T> =>
 075    Shuffle<T, TGet, TSet, RandomNextIntMinValueIntMaxValue>(start, end, get, set, random ?? new Random());
 76
 77  /// <inheritdoc cref="XML_Shuffle"/>
 78  public static void Shuffle<T, TGet, TSet, TRandom>(int start, int end, TGet get = default, TSet set = default, TRandom
 79    where TGet : struct, IFunc<int, T>
 80    where TSet : struct, IAction<int, T>
 81    where TRandom : struct, IFunc<int, int, int>
 203082  {
 2619683    for (int i = start; i <= end; i++)
 1106884    {
 1106885      int randomIndex = random.Invoke(start, end);
 1106886      Swap<T, TGet, TSet>(i, randomIndex, get, set);
 1106887    }
 203088  }
 89
 90  /// <inheritdoc cref="XML_Shuffle"/>
 91  public static void Shuffle<T>(Span<T> span, Random? random = null) =>
 266292    Shuffle<T, RandomNextIntMinValueIntMaxValue>(span, random ?? new Random());
 93
 94  /// <inheritdoc cref="XML_Shuffle"/>
 95  public static void Shuffle<T, TRandom>(Span<T> span, TRandom random = default)
 96    where TRandom : struct, IFunc<int, int, int>
 792797  {
 179736098    for (int i = 0; i < span.Length; i++)
 89075399    {
 890753100      int index = random.Invoke(0, span.Length);
 890753101      Swap(ref span[i], ref span[index]);
 890753102    }
 7927103  }
 104
 105  #endregion
 106
 107  #region XML
 108
 109#pragma warning disable SA1604, CS1572, CS1711
 110
 111  /// <typeparam name="T">The type of values to sort.</typeparam>
 112  /// <typeparam name="TCompare">The type of compare function.</typeparam>
 113  /// <typeparam name="TGet">The type of get function.</typeparam>
 114  /// <typeparam name="TSet">The type of set function.</typeparam>
 115  /// <param name="compare">The compare function.</param>
 116  /// <param name="get">The get function.</param>
 117  /// <param name="set">The set function.</param>
 118  /// <param name="start">The starting index of the sort.</param>
 119  /// <param name="end">The ending index of the sort.</param>
 120  /// <param name="array">The array to be sorted.</param>
 121  /// <param name="span">The span to be sorted.</param>
 122  [Obsolete(NotIntended, true)]
 1123  public static void XML_Sort() => throw new DocumentationMethodException();
 124
 125#pragma warning restore SA1604, CS1572, CS1711
 126
 127  #endregion
 128
 129  #region SortBubble
 130
 131  /// <summary>
 132  /// Sorts values using the bubble sort algorithm.<br/>
 133  /// Runtime: Ω(n), ε(n^2), O(n^2)<br/>
 134  /// Memory: O(1)<br/>
 135  /// Stable: True
 136  /// </summary>
 137  /// <inheritdoc cref="XML_Sort"/>
 138  [Obsolete(NotIntended, true)]
 1139  public static void XML_SortBubble() => throw new DocumentationMethodException();
 140
 141  /// <inheritdoc cref="XML_SortBubble"/>
 142  public static void SortBubble<T>(int start, int end, Func<int, T> get, Action<int, T> set, Func<T, T, CompareResult>? 
 83143    SortBubble<T, SFunc<int, T>, SAction<int, T>, SFunc<T, T, CompareResult>>(start, end, get, set, compare ?? Compare);
 144
 145  /// <inheritdoc cref="XML_SortBubble"/>
 146  public static void SortBubble<T, TGet, TSet, TCompare>(int start, int end, TGet get = default, TSet set = default, TCo
 147    where TCompare : struct, IFunc<T, T, CompareResult>
 148    where TGet : struct, IFunc<int, T>
 149    where TSet : struct, IAction<int, T>
 83150  {
 24828151    for (int i = start; i <= end; i++)
 12331152    {
 22151902153      for (int j = start; j <= end - 1; j++)
 11063620154      {
 11063620155        if (compare.Invoke(get.Invoke(j), get.Invoke(j + 1)) is Greater)
 2786905156        {
 2786905157          Swap<T, TGet, TSet>(j + 1, j, get, set);
 2786905158        }
 11063620159      }
 12331160    }
 83161  }
 162
 163  /// <inheritdoc cref="XML_SortBubble"/>
 164  public static void SortBubble<T>(Span<T> span, Func<T, T, CompareResult>? compare = null) =>
 83165    SortBubble<T, SFunc<T, T, CompareResult>>(span, compare ?? Compare);
 166
 167  /// <inheritdoc cref="XML_SortBubble"/>
 168  public static void SortBubble<T, TCompare>(Span<T> span, TCompare compare = default)
 169    where TCompare : struct, IFunc<T, T, CompareResult>
 83170  {
 24828171    for (int i = 0; i <= span.Length - 1; i++)
 12331172    {
 22151902173      for (int j = 0; j <= span.Length - 2; j++)
 11063620174      {
 11063620175        if (compare.Invoke(span[j], span[j + 1]) is Greater)
 2786905176        {
 2786905177          Swap(ref span[j], ref span[j + 1]);
 2786905178        }
 11063620179      }
 12331180    }
 83181  }
 182
 183  #endregion
 184
 185  #region SortSelection
 186
 187  /// <summary>
 188  /// Sorts values using the selection sort algoritm.<br/>
 189  /// Runtime: Ω(n^2), ε(n^2), O(n^2)<br/>
 190  /// Memory: O(1)<br/>
 191  /// Stable: False
 192  /// </summary>
 193  /// <inheritdoc cref="XML_Sort"/>
 194  [Obsolete(NotIntended, true)]
 1195  public static void XML_SortSelection() => throw new DocumentationMethodException();
 196
 197  /// <inheritdoc cref="XML_SortSelection"/>
 198  public static void SortSelection<T>(int start, int end, Func<int, T> get, Action<int, T> set, Func<T, T, CompareResult
 83199    SortSelection<T, SFunc<int, T>, SAction<int, T>, SFunc<T, T, CompareResult>>(start, end, get, set, compare ?? Compar
 200
 201  /// <inheritdoc cref="XML_SortSelection"/>
 202  public static void SortSelection<T, TGet, TSet, TCompare>(int start, int end, TGet get = default, TSet set = default, 
 203    where TCompare : struct, IFunc<T, T, CompareResult>
 204    where TGet : struct, IFunc<int, T>
 205    where TSet : struct, IAction<int, T>
 83206  {
 24828207    for (int i = start; i <= end; i++)
 12331208    {
 12331209      int min = i;
 11088282210      for (int j = i + 1; j <= end; j++)
 5531810211      {
 5531810212        if (compare.Invoke(get.Invoke(j), get.Invoke(min)) is Less)
 63822213        {
 63822214          min = j;
 63822215        }
 5531810216      }
 12331217      Swap<T, TGet, TSet>(min, i, get, set);
 12331218    }
 83219  }
 220
 221  /// <inheritdoc cref="XML_SortSelection"/>
 222  public static void SortSelection<T>(Span<T> span, Func<T, T, CompareResult>? compare = null) =>
 83223    SortSelection<T, SFunc<T, T, CompareResult>>(span, compare ?? Compare);
 224
 225  /// <inheritdoc cref="XML_SortSelection"/>
 226  public static void SortSelection<T, TCompare>(Span<T> span, TCompare compare = default)
 227    where TCompare : struct, IFunc<T, T, CompareResult>
 83228  {
 24828229    for (int i = 0; i < span.Length; i++)
 12331230    {
 12331231      int min = i;
 11088282232      for (int j = i + 1; j < span.Length; j++)
 5531810233      {
 5531810234        if (compare.Invoke(span[j], span[min]) is Less)
 63822235        {
 63822236          min = j;
 63822237        }
 5531810238      }
 12331239      Swap(ref span[min], ref span[i]);
 12331240    }
 83241  }
 242
 243  #endregion
 244
 245  #region SortInsertion
 246
 247  /// <summary>
 248  /// Sorts values using the insertion sort algorithm.<br/>
 249  /// Runtime: Ω(n), ε(n^2), O(n^2)<br/>
 250  /// Memory: O(1)<br/>
 251  /// Stable: True
 252  /// </summary>
 253  /// <inheritdoc cref="XML_Sort"/>
 254  [Obsolete(NotIntended, true)]
 1255  public static void XML_SortInsertion() => throw new DocumentationMethodException();
 256
 257  /// <inheritdoc cref="XML_SortInsertion"/>
 258  public static void SortInsertion<T>(int start, int end, Func<int, T> get, Action<int, T> set, Func<T, T, CompareResult
 83259    SortInsertion<T, SFunc<int, T>, SAction<int, T>, SFunc<T, T, CompareResult>>(start, end, get, set, compare ?? Compar
 260
 261  /// <inheritdoc cref="XML_SortInsertion"/>
 262  public static void SortInsertion<T, TGet, TSet, TCompare>(int start, int end, TGet get = default, TSet set = default, 
 263    where TCompare : struct, IFunc<T, T, CompareResult>
 264    where TGet : struct, IFunc<int, T>
 265    where TSet : struct, IAction<int, T>
 1596266  {
 72046267    for (int i = start + 1; i <= end; i++)
 34427268    {
 34427269      T temp = get.Invoke(i);
 34427270      int j = i;
 5873387271      for (; j > start && compare.Invoke(get.Invoke(j - 1), temp) is Greater; j--)
 2919480272      {
 2919480273        set.Invoke(j, get.Invoke(j - 1));
 2919480274      }
 34427275      set.Invoke(j, temp);
 34427276    }
 1596277  }
 278
 279  /// <inheritdoc cref="XML_SortInsertion"/>
 280  public static void SortInsertion<T>(Span<T> span, Func<T, T, CompareResult>? compare = null) =>
 83281    SortInsertion<T, SFunc<T, T, CompareResult>>(span, compare ?? Compare);
 282
 283  /// <inheritdoc cref="XML_SortInsertion"/>
 284  public static void SortInsertion<T, TCompare>(Span<T> span, TCompare compare = default)
 285    where TCompare : struct, IFunc<T, T, CompareResult>
 1596286  {
 71306287    for (int i = 1; i <= span.Length - 1; i++)
 34057288    {
 34057289      T temp = span[i];
 290      int j;
 5885644291      for (j = i; j > 0 && compare.Invoke(span[j - 1], temp) is Greater; j--)
 2908765292      {
 2908765293        span[j] = span[j - 1];
 2908765294      }
 34057295      span[j] = temp;
 34057296    }
 1596297  }
 298
 299  #endregion
 300
 301  #region SortQuick
 302
 303  /// <summary>
 304  /// Sorts values using the quick sort algorithm.<br/>
 305  /// Runtime: Ω(n*ln(n)), ε(n*ln(n)), O(n^2)<br/>
 306  /// Memory: ln(n)<br/>
 307  /// Stable: False
 308  /// </summary>
 309  /// <inheritdoc cref="XML_Sort"/>
 310  [Obsolete(NotIntended, true)]
 1311  public static void XML_SortQuick() => throw new DocumentationMethodException();
 312
 313  /// <inheritdoc cref="XML_SortQuick"/>
 314  public static void SortQuick<T>(int start, int end, Func<int, T> get, Action<int, T> set, Func<T, T, CompareResult>? c
 83315    SortQuick<T, SFunc<int, T>, SAction<int, T>, SFunc<T, T, CompareResult>>(start, end, get, set, compare ?? Compare);
 316
 317  /// <inheritdoc cref="XML_SortQuick"/>
 318  public static void SortQuick<T, TGet, TSet, TCompare>(int start, int end, TGet get = default, TSet set = default, TCom
 319    where TCompare : struct, IFunc<T, T, CompareResult>
 320    where TGet : struct, IFunc<int, T>
 321    where TSet : struct, IAction<int, T>
 83322  {
 83323    SortQuick_Recursive(start, end - start + 1);
 324
 325    void SortQuick_Recursive(int start, int length)
 16387326    {
 16387327      if (length > 1)
 8152328      {
 8152329        T pivot = get.Invoke(start);
 8152330        int i = start;
 8152331        int j = start + length - 1;
 8152332        int k = j;
 139363333        while (i <= j)
 131211334        {
 131211335          if (compare.Invoke(get.Invoke(j), pivot) is Less)
 65692336          {
 65692337            Swap<T, TGet, TSet>(i++, j, get, set);
 65692338          }
 65519339          else if (compare.Invoke(get.Invoke(j), pivot) is Equal)
 8188340          {
 8188341            j--;
 8188342          }
 343          else
 57331344          {
 57331345            Swap<T, TGet, TSet>(k--, j--, get, set);
 57331346          }
 131211347        }
 8152348        SortQuick_Recursive(start, i - start);
 8152349        SortQuick_Recursive(k + 1, start + length - (k + 1));
 8152350      }
 16387351    }
 83352  }
 353
 354  /// <inheritdoc cref="XML_SortQuick"/>
 355  public static void SortQuick<T>(Span<T> span, Func<T, T, CompareResult>? compare = null) =>
 105356    SortQuick<T, SFunc<T, T, CompareResult>>(span, compare ?? Compare);
 357
 358  /// <inheritdoc cref="XML_SortQuick"/>
 359  public static void SortQuick<T, TCompare>(Span<T> span, TCompare compare = default)
 360    where TCompare : struct, IFunc<T, T, CompareResult>
 105361  {
 105362    SortQuick_Recursive(span, 0, span.Length);
 363
 364    void SortQuick_Recursive(Span<T> span, int startIndex, int len)
 16453365    {
 16453366      if (len > 1)
 8174367      {
 8174368        T pivot = span[startIndex];
 8174369        int i = startIndex;
 8174370        int j = startIndex + len - 1;
 8174371        int k = j;
 139429372        while (i <= j)
 131255373        {
 131255374          if (compare.Invoke(span[j], pivot) is Less)
 65699375          {
 65699376            Swap(ref span[i++], ref span[j]);
 65699377          }
 65556378          else if (compare.Invoke(span[j], pivot) is Equal)
 8220379          {
 8220380            j--;
 8220381          }
 382          else
 57336383          {
 57336384            Swap(ref span[k--], ref span[j--]);
 57336385          }
 131255386        }
 8174387        SortQuick_Recursive(span, startIndex, i - startIndex);
 8174388        SortQuick_Recursive(span, k + 1, startIndex + len - (k + 1));
 8174389      }
 16453390    }
 105391  }
 392
 393  #endregion
 394
 395  #region SortMerge
 396
 397  /// <summary>
 398  /// Sorts values using the merge sort algorithm.<br/>
 399  /// Runtime: Ω(n*ln(n)), ε(n*ln(n)), O(n*ln(n))<br/>
 400  /// Memory: Θ(n)<br/>
 401  /// Stable: True
 402  /// </summary>
 403  /// <inheritdoc cref="XML_Sort"/>
 404  [Obsolete(NotIntended, true)]
 1405  public static void XML_SortMerge() => throw new DocumentationMethodException();
 406
 407  /// <inheritdoc cref="XML_SortMerge"/>
 408  public static void SortMerge<T>(int start, int end, Func<int, T> get, Action<int, T> set, Func<T, T, CompareResult>? c
 83409    SortMerge<T, SFunc<int, T>, SAction<int, T>, SFunc<T, T, CompareResult>>(start, end, get, set, compare ?? Compare);
 410
 411  /// <inheritdoc cref="XML_SortMerge"/>
 412  public static void SortMerge<T, TGet, TSet, TCompare>(int start, int end, TGet get = default, TSet set = default, TCom
 413    where TCompare : struct, IFunc<T, T, CompareResult>
 414    where TGet : struct, IFunc<int, T>
 415    where TSet : struct, IAction<int, T>
 83416  {
 83417    SortMerge_Recursive(start, end - start + 1);
 418
 419    void SortMerge_Recursive(int start, int length)
 24589420    {
 24589421      if (length > 1)
 12253422      {
 12253423        int half = length / 2;
 12253424        SortMerge_Recursive(start, half);
 12253425        SortMerge_Recursive(start + half, length - half);
 12253426        Span<T> sorted = new T[length];
 12253427        int i = start;
 12253428        int j = start + half;
 12253429        int k = 0;
 114147430        while (i < start + half && j < start + length)
 101894431        {
 101894432          if (compare.Invoke(get.Invoke(i), get.Invoke(j)) is Greater)
 51777433          {
 51777434            sorted[k++] = get.Invoke(j++);
 51777435          }
 436          else
 50117437          {
 50117438            sorted[k++] = get.Invoke(i++);
 50117439          }
 101894440        }
 39788441        for (int h = 0; h < start + half - i; h++)
 7641442        {
 7641443          sorted[k + h] = get.Invoke(i + h);
 7641444        }
 40058445        for (int h = 0; h < start + length - j; h++)
 7776446        {
 7776447          sorted[k + h] = get.Invoke(j + h);
 7776448        }
 259128449        for (int h = 0; h < length; h++)
 117311450        {
 117311451          set.Invoke(start + h, sorted[0 + h]);
 117311452        }
 12253453      }
 24589454    }
 83455  }
 456
 457  /// <inheritdoc cref="XML_SortMerge"/>
 458  public static void SortMerge<T>(Span<T> span, Func<T, T, CompareResult>? compare = null) =>
 98459    SortMerge<T, SFunc<T, T, CompareResult>>(span, compare ?? Compare);
 460
 461  /// <inheritdoc cref="XML_SortMerge"/>
 462  public static void SortMerge<T, TCompare>(Span<T> span, TCompare compare = default)
 463    where TCompare : struct, IFunc<T, T, CompareResult>
 98464  {
 98465    SortMerge_Recursive(span);
 466
 467    void SortMerge_Recursive(Span<T> span)
 24730468    {
 24730469      if (span.Length > 1)
 12316470      {
 12316471        int half = span.Length / 2;
 12316472        SortMerge_Recursive(span[..half]);
 12316473        SortMerge_Recursive(span[half..]);
 12316474        T[] sorted = new T[span.Length];
 12316475        int i = 0;
 12316476        int j = half;
 12316477        int k = 0;
 114299478        while (i < half && j < span.Length)
 101983479        {
 101983480          if (compare.Invoke(span[i], span[j]) is Greater)
 51793481          {
 51793482            sorted[k++] = span[j++];
 51793483          }
 484          else
 50190485          {
 50190486            sorted[k++] = span[i++];
 50190487          }
 101983488        }
 39930489        for (int h = 0; h < half - i; h++)
 7649490        {
 7649491          sorted[k + h] = span[i + h];
 7649492        }
 40374493        for (int h = 0; h < span.Length - j; h++)
 7871494        {
 7871495          sorted[k + h] = span[j + h];
 7871496        }
 259638497        for (int h = 0; h < span.Length; h++)
 117503498        {
 117503499          span[h] = sorted[0 + h];
 117503500        }
 12316501      }
 24730502    }
 98503  }
 504
 505  #endregion
 506
 507  #region SortHeap
 508
 509  /// <summary>
 510  /// Sorts values using the heap sort algorithm.<br/>
 511  /// Runtime: Ω(n*ln(n)), ε(n*ln(n)), O(n^2)<br/>
 512  /// Memory: O(1)<br/>
 513  /// Stable: False
 514  /// </summary>
 515  /// <inheritdoc cref="XML_Sort"/>
 516  [Obsolete(NotIntended, true)]
 1517  public static void XML_SortHeap() => throw new DocumentationMethodException();
 518
 519  /// <inheritdoc cref="XML_SortHeap"/>
 520  public static void SortHeap<T>(int start, int end, Func<int, T> get, Action<int, T> set, Func<T, T, CompareResult>? co
 83521    SortHeap<T, SFunc<int, T>, SAction<int, T>, SFunc<T, T, CompareResult>>(start, end, get, set, compare ?? Compare);
 522
 523  /// <inheritdoc cref="XML_SortHeap"/>
 524  public static void SortHeap<T, TGet, TSet, TCompare>(int start, int end, TGet get = default, TSet set = default, TComp
 525    where TCompare : struct, IFunc<T, T, CompareResult>
 526    where TGet : struct, IFunc<int, T>
 527    where TSet : struct, IAction<int, T>
 83528  {
 83529    int heapSize = end - start + 1;
 12620530    for (int i = heapSize / 2; i >= 0; i--)
 6227531    {
 6227532      MaxSortHeapify(heapSize + start, i, start);
 6227533    }
 24828534    for (int i = end; i >= start; i--)
 12331535    {
 12331536      Swap<T, TGet, TSet>(start, i, get, set);
 12331537      heapSize--;
 12331538      MaxSortHeapify(heapSize + start, 0, start);
 12331539    }
 540    void MaxSortHeapify(int heapSize, int index, int offset)
 112437541    {
 112437542      int left = ((index + 1) * 2 - 1) + offset;
 112437543      int right = ((index + 1) * 2) + offset;
 112437544      index += offset;
 112437545      int largest = index;
 112437546      if (left < heapSize && compare.Invoke(get.Invoke(left), get.Invoke(largest)) is Greater)
 90360547      {
 90360548        largest = left;
 90360549      }
 112437550      if (right < heapSize && compare.Invoke(get.Invoke(right), get.Invoke(largest)) is Greater)
 44994551      {
 44994552        largest = right;
 44994553      }
 112437554      if (largest != index)
 93879555      {
 93879556        Swap<T, TGet, TSet>(index, largest, get, set);
 93879557        MaxSortHeapify(heapSize, largest - offset, offset);
 93879558      }
 112437559    }
 83560  }
 561
 562  /// <inheritdoc cref="XML_SortHeap"/>
 563  public static void SortHeap<T>(Span<T> span, Func<T, T, CompareResult>? compare = null) =>
 83564    SortHeap<T, SFunc<T, T, CompareResult>>(span, compare ?? Compare);
 565
 566  /// <inheritdoc cref="XML_SortHeap"/>
 567  public static void SortHeap<T, TCompare>(Span<T> span, TCompare compare = default)
 568    where TCompare : struct, IFunc<T, T, CompareResult>
 83569  {
 83570    int start = 0;
 83571    int end = span.Length - 1;
 83572    int heapSize = end - start + 1;
 12620573    for (int i = heapSize / 2; i >= 0; i--)
 6227574    {
 6227575      MaxSortHeapify(span, heapSize + start, i, start);
 6227576    }
 24828577    for (int i = end; i >= start; i--)
 12331578    {
 12331579      Swap(ref span[start], ref span[i]);
 12331580      heapSize--;
 12331581      MaxSortHeapify(span, heapSize + start, 0, start);
 12331582    }
 583    void MaxSortHeapify(Span<T> span, int heapSize, int index, int offset)
 112437584    {
 112437585      int left = ((index + 1) * 2 - 1) + offset;
 112437586      int right = ((index + 1) * 2) + offset;
 112437587      index += offset;
 112437588      int largest = index;
 112437589      if (left < heapSize && compare.Invoke(span[left], span[largest]) is Greater)
 90360590      {
 90360591        largest = left;
 90360592      }
 112437593      if (right < heapSize && compare.Invoke(span[right], span[largest]) is Greater)
 44994594      {
 44994595        largest = right;
 44994596      }
 112437597      if (largest != index)
 93879598      {
 93879599        Swap(ref span[index], ref span[largest]);
 93879600        MaxSortHeapify(span, heapSize, largest - offset, offset);
 93879601      }
 112437602    }
 83603  }
 604
 605  #endregion
 606
 607  #region SortOddEven
 608
 609  /// <summary>
 610  /// Sorts values using the odd even sort algorithm.<br/>
 611  /// Runtime: Ω(n), ε(n^2), O(n^2)<br/>
 612  /// Memory: O(1)<br/>
 613  /// Stable: True
 614  /// </summary>
 615  /// <inheritdoc cref="XML_Sort"/>
 616  [Obsolete(NotIntended, true)]
 1617  public static void XML_SortOddEven() => throw new DocumentationMethodException();
 618
 619  /// <inheritdoc cref="XML_SortOddEven"/>
 620  public static void SortOddEven<T>(int start, int end, Func<int, T> get, Action<int, T> set, Func<T, T, CompareResult>?
 83621    SortOddEven<T, SFunc<int, T>, SAction<int, T>, SFunc<T, T, CompareResult>>(start, end, get, set, compare ?? Compare)
 622
 623  /// <inheritdoc cref="XML_SortOddEven"/>
 624  public static void SortOddEven<T, TGet, TSet, TCompare>(int start, int end, TGet get = default, TSet set = default, TC
 625    where TCompare : struct, IFunc<T, T, CompareResult>
 626    where TGet : struct, IFunc<int, T>
 627    where TSet : struct, IAction<int, T>
 83628  {
 83629    bool sorted = false;
 6115630    while (!sorted)
 6032631    {
 6032632      sorted = true;
 5387232633      for (int i = start; i < end; i += 2)
 2687584634      {
 2687584635        if (compare.Invoke(get.Invoke(i), get.Invoke(i + 1)) is Greater)
 1393774636        {
 1393774637          Swap<T, TGet, TSet>(i, i + 1, get, set);
 1393774638          sorted = false;
 1393774639        }
 2687584640      }
 5381704641      for (int i = start + 1; i < end; i += 2)
 2684820642      {
 2684820643        if (compare.Invoke(get.Invoke(i), get.Invoke(i + 1)) is Greater)
 1393131644        {
 1393131645          Swap<T, TGet, TSet>(i, i + 1, get, set);
 1393131646          sorted = false;
 1393131647        }
 2684820648      }
 6032649    }
 83650  }
 651
 652  /// <inheritdoc cref="XML_SortOddEven"/>
 653  public static void SortOddEven<T>(Span<T> span, Func<T, T, CompareResult>? compare = null) =>
 83654    SortOddEven<T, SFunc<T, T, CompareResult>>(span, compare ?? Compare);
 655
 656  /// <inheritdoc cref="XML_SortOddEven"/>
 657  public static void SortOddEven<T, TCompare>(Span<T> span, TCompare compare = default)
 658    where TCompare : struct, IFunc<T, T, CompareResult>
 83659  {
 83660    bool sorted = false;
 6115661    while (!sorted)
 6032662    {
 6032663      sorted = true;
 5387232664      for (int i = 0; i < span.Length - 1; i += 2)
 2687584665      {
 2687584666        if (compare.Invoke(span[i], span[i + 1]) is Greater)
 1393774667        {
 1393774668          Swap(ref span[i], ref span[i + 1]);
 1393774669          sorted = false;
 1393774670        }
 2687584671      }
 5381704672      for (int i = 1; i < span.Length - 1; i += 2)
 2684820673      {
 2684820674        if (compare.Invoke(span[i], span[i + 1]) is Greater)
 1393131675        {
 1393131676          Swap(ref span[i], ref span[i + 1]);
 1393131677          sorted = false;
 1393131678        }
 2684820679      }
 6032680    }
 83681  }
 682
 683  #endregion
 684
 685  #region SortBogo
 686
 687  /// <summary>
 688  /// Sorts values using the bogo sort algorithm.<br/>
 689  /// Runtime: Ω(n), ε(n*n!), O(∞)<br/>
 690  /// Memory: O(1)<br/>
 691  /// Stable: False
 692  /// </summary>
 693  /// <inheritdoc cref="XML_Sort"/>
 694  [Obsolete(NotIntended, true)]
 1695  public static void XML_SortBogo() => throw new DocumentationMethodException();
 696
 697  /// <inheritdoc cref="XML_SortBogo"/>
 698  public static void SortBogo<T>(int start, int end, Func<int, T> get, Action<int, T> set, Func<T, T, CompareResult>? co
 37699    SortBogo<T, SFunc<int, T>, SAction<int, T>, SFunc<T, T, CompareResult>>(start, end, get, set, compare ?? Compare, ra
 700
 701  /// <inheritdoc cref="XML_SortBogo"/>
 702  public static void SortBogo<T, TGet, TSet, TCompare>(int start, int end, TGet get = default, TSet set = default, TComp
 703    where TCompare : struct, IFunc<T, T, CompareResult>
 704    where TGet : struct, IFunc<int, T>
 705    where TSet : struct, IAction<int, T> =>
 37706    SortBogo<T, TGet, TSet, TCompare, RandomNextIntMinValueIntMaxValue>(start, end, get, set, compare, random ?? new Ran
 707
 708  /// <inheritdoc cref="XML_SortBogo"/>
 709  public static void SortBogo<T, TGet, TSet, TCompare, TRandom>(int start, int end, TGet get = default, TSet set = defau
 710    where TCompare : struct, IFunc<T, T, CompareResult>
 711    where TGet : struct, IFunc<int, T>
 712    where TSet : struct, IAction<int, T>
 713    where TRandom : struct, IFunc<int, int, int>
 37714  {
 2067715    while (!IsOrdered<T, TCompare, TGet>(start, end, compare, get))
 2030716    {
 2030717      Shuffle<T, TGet, TSet, TRandom>(start, end, get, set, random);
 2030718    }
 37719  }
 720
 721  /// <inheritdoc cref="XML_SortBogo"/>
 722  public static void SortBogo<T>(Span<T> span, Func<T, T, CompareResult>? compare = null, Random? random = null) =>
 37723    SortBogo<T, SFunc<T, T, CompareResult>>(span, compare ?? Compare, random ?? new Random());
 724
 725  /// <inheritdoc cref="XML_SortBogo"/>
 726  public static void SortBogo<T, TCompare>(Span<T> span, TCompare compare = default, Random? random = null)
 727    where TCompare : struct, IFunc<T, T, CompareResult> =>
 37728    SortBogo<T, TCompare, RandomNextIntMinValueIntMaxValue>(span, compare, random ?? new Random());
 729
 730  /// <inheritdoc cref="XML_SortBogo"/>
 731  public static void SortBogo<T, TCompare, TRandom>(Span<T> span, TCompare compare = default, TRandom random = default)
 732    where TCompare : struct, IFunc<T, T, CompareResult>
 733    where TRandom : struct, IFunc<int, int, int>
 37734  {
 5302735    while (!IsOrdered<T, TCompare>(span, compare))
 5265736    {
 5265737      Shuffle(span, random);
 5265738    }
 37739  }
 740
 741  #endregion
 742
 743  #region SortSlow
 744
 745  /// <summary>Sorts values using the slow sort algorithm.</summary>
 746  /// <inheritdoc cref="XML_Sort"/>
 747  [Obsolete(NotIntended, true)]
 1748  public static void XML_SortSlow() => throw new DocumentationMethodException();
 749
 750  /// <inheritdoc cref="XML_SortSlow"/>
 751  public static void SortSlow<T>(int start, int end, Func<int, T> get, Action<int, T> set, Func<T, T, CompareResult>? co
 62752    SortSlow<T, SFunc<int, T>, SAction<int, T>, SFunc<T, T, CompareResult>>(start, end, get, set, compare ?? Compare);
 753
 754  /// <inheritdoc cref="XML_SortSlow"/>
 755  public static void SortSlow<T, TGet, TSet, TCompare>(int start, int end, TGet get = default, TSet set = default, TComp
 756    where TCompare : struct, IFunc<T, T, CompareResult>
 757    where TGet : struct, IFunc<int, T>
 758    where TSet : struct, IAction<int, T>
 62759  {
 62760    SortSlowRecursive(start, end);
 761    void SortSlowRecursive(int i, int j)
 5543762    {
 5543763      if (i >= j)
 3716764      {
 3716765        return;
 766      }
 1827767      int mid = (i + j) / 2;
 1827768      SortSlowRecursive(i, mid);
 1827769      SortSlowRecursive(mid + 1, j);
 1827770      if (compare.Invoke(get.Invoke(j), get.Invoke(mid)) is Less)
 583771      {
 583772        Swap<T, TGet, TSet>(j, mid, get, set);
 583773      }
 1827774      SortSlowRecursive(i, j - 1);
 5543775    }
 62776  }
 777
 778  /// <inheritdoc cref="XML_SortSlow"/>
 779  public static void SortSlow<T>(Span<T> span, Func<T, T, CompareResult>? compare = null) =>
 62780    SortSlow<T, SFunc<T, T, CompareResult>>(span, compare ?? Compare);
 781
 782  /// <inheritdoc cref="XML_SortSlow"/>
 783  public static void SortSlow<T, TCompare>(Span<T> span, TCompare compare = default)
 784    where TCompare : struct, IFunc<T, T, CompareResult>
 62785  {
 62786    SortSlowRecursive(span, 0, span.Length - 1);
 787    void SortSlowRecursive(Span<T> span, int i, int j)
 5543788    {
 5543789      if (i >= j)
 3716790      {
 3716791        return;
 792      }
 1827793      int mid = (i + j) / 2;
 1827794      SortSlowRecursive(span, i, mid);
 1827795      SortSlowRecursive(span, mid + 1, j);
 1827796      if (compare.Invoke(span[j], span[mid]) is Less)
 583797      {
 583798        Swap(ref span[j], ref span[mid]);
 583799      }
 1827800      SortSlowRecursive(span, i, j - 1);
 5543801    }
 62802  }
 803
 804  #endregion
 805
 806  #region SortGnome
 807
 808  /// <summary>Sorts values using the gnome sort algorithm.</summary>
 809  /// <inheritdoc cref="XML_Sort"/>
 810  [Obsolete(NotIntended, true)]
 1811  public static void XML_SortGnome() => throw new DocumentationMethodException();
 812
 813  /// <inheritdoc cref="XML_SortGnome"/>
 814  public static void SortGnome<T>(int start, int end, Func<int, T> get, Action<int, T> set, Func<T, T, CompareResult>? c
 83815    SortGnome<T, SFunc<int, T>, SAction<int, T>, SFunc<T, T, CompareResult>>(start, end, get, set, compare ?? Compare);
 816
 817  /// <inheritdoc cref="XML_SortGnome"/>
 818  public static void SortGnome<T, TGet, TSet, TCompare>(int start, int end, TGet get = default, TSet set = default, TCom
 819    where TCompare : struct, IFunc<T, T, CompareResult>
 820    where TGet : struct, IFunc<int, T>
 821    where TSet : struct, IAction<int, T>
 83822  {
 83823    int i = start;
 5586224824    while (i <= end)
 5586141825    {
 5586141826      if (i == start || compare.Invoke(get.Invoke(i), get.Invoke(i - 1)) != Less)
 2799236827      {
 2799236828        i++;
 2799236829      }
 830      else
 2786905831      {
 2786905832        Swap<T, TGet, TSet>(i, i - 1, get, set);
 2786905833        i--;
 2786905834      }
 5586141835    }
 83836  }
 837
 838  /// <inheritdoc cref="XML_SortGnome"/>
 839  public static void SortGnome<T>(Span<T> span, Func<T, T, CompareResult>? compare = null) =>
 83840    SortGnome<T, SFunc<T, T, CompareResult>>(span, compare ?? Compare);
 841
 842  /// <inheritdoc cref="XML_SortGnome"/>
 843  public static void SortGnome<T, TCompare>(Span<T> span, TCompare compare = default)
 844    where TCompare : struct, IFunc<T, T, CompareResult>
 83845  {
 83846    int i = 0;
 5586224847    while (i < span.Length)
 5586141848    {
 5586141849      if (i is 0 || compare.Invoke(span[i], span[i - 1]) != Less)
 2799236850      {
 2799236851        i++;
 2799236852      }
 853      else
 2786905854      {
 2786905855        Swap(ref span[i], ref span[i - 1]);
 2786905856        i--;
 2786905857      }
 5586141858    }
 83859  }
 860
 861  #endregion
 862
 863  #region SortComb
 864
 865  /// <summary>Sorts values using the comb sort algorithm.</summary>
 866  /// <inheritdoc cref="XML_Sort"/>
 867  [Obsolete(NotIntended, true)]
 1868  public static void XML_SortComb() => throw new DocumentationMethodException();
 869
 870  /// <inheritdoc cref="XML_SortComb"/>
 871  public static void SortComb<T>(int start, int end, Func<int, T> get, Action<int, T> set, Func<T, T, CompareResult>? co
 83872    SortComb<T, SFunc<int, T>, SAction<int, T>, SFunc<T, T, CompareResult>>(start, end, get, set, compare ?? Compare);
 873
 874  /// <inheritdoc cref="XML_SortComb"/>
 875  public static void SortComb<T, TGet, TSet, TCompare>(int start, int end, TGet get = default, TSet set = default, TComp
 876    where TCompare : struct, IFunc<T, T, CompareResult>
 877    where TGet : struct, IFunc<int, T>
 878    where TSet : struct, IAction<int, T>
 83879  {
 880    const double shrink = 1.3;
 83881    int gap = end - start + 1;
 83882    bool sorted = false;
 780883    while (!sorted)
 697884    {
 697885      gap = (int)(gap / shrink);
 697886      if (gap <= 1)
 197887      {
 197888        gap = 1;
 197889        sorted = true;
 197890      }
 525504891      for (int i = start; i + gap <= end; i++)
 262055892      {
 262055893        if (compare.Invoke(get.Invoke(i), get.Invoke(i + gap)) is Greater)
 52356894        {
 52356895          Swap<T, TGet, TSet>(i, i + gap, get, set);
 52356896          sorted = false;
 52356897        }
 262055898      }
 697899    }
 83900  }
 901
 902  /// <inheritdoc cref="XML_SortComb"/>
 903  public static void SortComb<T>(Span<T> span, Func<T, T, CompareResult>? compare = null) =>
 83904    SortComb<T, SFunc<T, T, CompareResult>>(span, compare ?? Compare);
 905
 906  /// <inheritdoc cref="XML_SortComb"/>
 907  public static void SortComb<T, TCompare>(Span<T> span, TCompare compare = default)
 908    where TCompare : struct, IFunc<T, T, CompareResult>
 83909  {
 910    const double shrink = 1.3;
 83911    int gap = span.Length;
 83912    bool sorted = false;
 780913    while (!sorted)
 697914    {
 697915      gap = (int)(gap / shrink);
 697916      if (gap <= 1)
 197917      {
 197918        gap = 1;
 197919        sorted = true;
 197920      }
 525504921      for (int i = 0; i + gap < span.Length; i++)
 262055922      {
 262055923        if (compare.Invoke(span[i], span[i + gap]) is Greater)
 52356924        {
 52356925          Swap(ref span[i], ref span[i + gap]);
 52356926          sorted = false;
 52356927        }
 262055928      }
 697929    }
 83930  }
 931
 932  #endregion
 933
 934  #region SortShell
 935
 936  /// <summary>Sorts values using the shell sort algorithm.</summary>
 937  /// <inheritdoc cref="XML_Sort"/>
 938  [Obsolete(NotIntended, true)]
 1939  public static void XML_SortShell() => throw new DocumentationMethodException();
 940
 941  /// <inheritdoc cref="XML_SortShell"/>
 942  public static void SortShell<T>(int start, int end, Func<int, T> get, Action<int, T> set, Func<T, T, CompareResult>? c
 83943    SortShell<T, SFunc<int, T>, SAction<int, T>, SFunc<T, T, CompareResult>>(start, end, get, set, compare ?? Compare);
 944
 945  /// <inheritdoc cref="XML_SortShell"/>
 946  public static void SortShell<T, TGet, TSet, TCompare>(int start, int end, TGet get = default, TSet set = default, TCom
 947    where TCompare : struct, IFunc<T, T, CompareResult>
 948    where TGet : struct, IFunc<int, T>
 949    where TSet : struct, IAction<int, T>
 83950  {
 83951    int[] gaps = { 701, 301, 132, 57, 23, 10, 4, 1 };
 1577952    foreach (int gap in gaps)
 664953    {
 159076954      for (int i = gap + start; i <= end; i++)
 78874955      {
 78874956        T temp = get.Invoke(i);
 78874957        int j = i;
 233930958        for (; j >= gap + start && compare.Invoke(get.Invoke(j - gap), temp) is Greater; j -= gap)
 77528959        {
 77528960          set.Invoke(j, get.Invoke(j - gap));
 77528961        }
 78874962        set.Invoke(j, temp);
 78874963      }
 664964    }
 83965  }
 966
 967  /// <inheritdoc cref="XML_SortShell"/>
 968  public static void SortShell<T>(Span<T> span, Func<T, T, CompareResult>? compare = null) =>
 83969    SortShell<T, SFunc<T, T, CompareResult>>(span, compare ?? Compare);
 970
 971  /// <inheritdoc cref="XML_SortShell"/>
 972  public static void SortShell<T, TCompare>(Span<T> span, TCompare compare = default)
 973    where TCompare : struct, IFunc<T, T, CompareResult>
 83974  {
 83975    int[] gaps = { 701, 301, 132, 57, 23, 10, 4, 1 };
 1577976    foreach (int gap in gaps)
 664977    {
 159076978      for (int i = gap; i < span.Length; i++)
 78874979      {
 78874980        T temp = span[i];
 78874981        int j = i;
 233930982        for (; j >= gap && compare.Invoke(span[j - gap], temp) is Greater; j -= gap)
 77528983        {
 77528984          span[j] = span[j - gap];
 77528985        }
 78874986        span[j] = temp;
 78874987      }
 664988    }
 83989  }
 990
 991  #endregion
 992
 993  #region SortCocktail
 994
 995  /// <summary>Sorts values using the cocktail sort algorithm.</summary>
 996  /// <inheritdoc cref="XML_Sort"/>
 997  [Obsolete(NotIntended, true)]
 1998  public static void XML_SortCocktail() => throw new DocumentationMethodException();
 999
 1000  /// <inheritdoc cref="XML_SortCocktail"/>
 1001  public static void SortCocktail<T>(int start, int end, Func<int, T> get, Action<int, T> set, Func<T, T, CompareResult>
 831002    SortCocktail<T, SFunc<int, T>, SAction<int, T>, SFunc<T, T, CompareResult>>(start, end, compare ?? Compare, get, set
 1003
 1004  /// <inheritdoc cref="XML_SortCocktail"/>
 1005  public static void SortCocktail<T, TGet, TSet, TCompare>(int start, int end, TCompare compare = default, TGet get = de
 1006    where TCompare : struct, IFunc<T, T, CompareResult>
 1007    where TGet : struct, IFunc<int, T>
 1008    where TSet : struct, IAction<int, T>
 831009  {
 32431010    while (true)
 32431011    {
 32431012      bool swapped = false;
 56902701013      for (int i = start; i <= end - 1; i++)
 28418921014      {
 28418921015        if (compare.Invoke(get.Invoke(i), get.Invoke(i + 1)) is Greater)
 13896231016        {
 13896231017          Swap<T, TGet, TSet>(i, i + 1, get, set);
 13896231018          swapped = true;
 13896231019        }
 28418921020      }
 32431021      if (!swapped)
 421022      {
 421023        break;
 1024      }
 32011025      swapped = false;
 56832621026      for (int i = end - 1; i >= start; i--)
 28384301027      {
 28384301028        if (compare.Invoke(get.Invoke(i), get.Invoke(i + 1)) is Greater)
 13972821029        {
 13972821030          Swap<T, TGet, TSet>(i, i + 1, get, set);
 13972821031          swapped = true;
 13972821032        }
 28384301033      }
 32011034      if (!swapped)
 411035      {
 411036        break;
 1037      }
 31601038    }
 831039  }
 1040
 1041  /// <inheritdoc cref="XML_SortCocktail"/>
 1042  public static void SortCocktail<T>(Span<T> span, Func<T, T, CompareResult>? compare = null) =>
 831043    SortCocktail<T, SFunc<T, T, CompareResult>>(span, compare ?? Compare);
 1044
 1045  /// <inheritdoc cref="XML_SortCocktail"/>
 1046  public static void SortCocktail<T, TCompare>(Span<T> span, TCompare compare = default)
 1047    where TCompare : struct, IFunc<T, T, CompareResult>
 831048  {
 32431049    while (true)
 32431050    {
 32431051      bool swapped = false;
 56902701052      for (int i = 0; i < span.Length - 1; i++)
 28418921053      {
 28418921054        if (compare.Invoke(span[i], span[i + 1]) is Greater)
 13896231055        {
 13896231056          Swap(ref span[i], ref span[i + 1]);
 13896231057          swapped = true;
 13896231058        }
 28418921059      }
 32431060      if (!swapped)
 421061      {
 421062        break;
 1063      }
 32011064      swapped = false;
 56832621065      for (int i = span.Length - 2; i >= 0; i--)
 28384301066      {
 28384301067        if (compare.Invoke(span[i], span[i + 1]) is Greater)
 13972821068        {
 13972821069          Swap(ref span[i], ref span[i + 1]);
 13972821070          swapped = true;
 13972821071        }
 28384301072      }
 32011073      if (!swapped)
 411074      {
 411075        break;
 1076      }
 31601077    }
 831078  }
 1079
 1080  #endregion
 1081
 1082  #region SortCycle
 1083
 1084  /// <summary>Sorts values using the cycle algorithm.</summary>
 1085  /// <inheritdoc cref="XML_Sort"/>
 1086  [Obsolete(NotIntended, true)]
 11087  public static void XML_SortCycle() => throw new DocumentationMethodException();
 1088
 1089  /// <inheritdoc cref="XML_SortCycle"/>
 1090  public static void SortCycle<T>(int start, int end, Func<int, T> get, Action<int, T> set, Func<T, T, CompareResult>? c
 831091    SortCycle<T, SFunc<int, T>, SAction<int, T>, SFunc<T, T, CompareResult>>(start, end, get, set, compare ?? Compare);
 1092
 1093  /// <inheritdoc cref="XML_SortCycle"/>
 1094  public static void SortCycle<T, TGet, TSet, TCompare>(int start, int end, TGet get = default, TSet set = default, TCom
 1095    where TCompare : struct, IFunc<T, T, CompareResult>
 1096    where TGet : struct, IFunc<int, T>
 1097    where TSet : struct, IAction<int, T>
 831098  {
 246721099    for (int i = start; i < end; i++)
 122531100    {
 122531101      T pivot = get.Invoke(i);
 122531102      int index = i;
 110881261103      for (int j = i + 1; j <= end; j++)
 55318101104      {
 55318101105        if (compare.Invoke(get.Invoke(j), pivot) is Less)
 307731106        {
 307731107          index++;
 307731108        }
 55318101109      }
 122531110      if (index == i)
 120741111      {
 120741112        continue;
 1113      }
 1791114      while (compare.Invoke(pivot, get.Invoke(index)) is Equal)
 01115      {
 01116        index++;
 01117      }
 1791118      if (index != i)
 1791119      {
 1791120        T temp = pivot;
 1791121        pivot = get.Invoke(index);
 1791122        set.Invoke(index, temp);
 1791123      }
 122701124      while (index != i)
 120911125      {
 120911126        index = i;
 219161561127        for (int j = i + 1; j <= end; j++)
 109459871128        {
 109459871129          if (compare.Invoke(get.Invoke(j), pivot) is Less)
 54435951130          {
 54435951131            index++;
 54435951132          }
 109459871133        }
 121271134        while (compare.Invoke(pivot, get.Invoke(index)) is Equal)
 361135        {
 361136          index += 1;
 361137        }
 120911138        if (compare.Invoke(pivot, get.Invoke(index)) is not Equal)
 120911139        {
 120911140          T temp = pivot;
 120911141          pivot = get.Invoke(index);
 120911142          set.Invoke(index, temp);
 120911143        }
 120911144      }
 1791145    }
 831146  }
 1147
 1148  /// <inheritdoc cref="XML_SortCycle"/>
 1149  public static void SortCycle<T>(Span<T> span, Func<T, T, CompareResult>? compare = null) =>
 831150    SortCycle<T, SFunc<T, T, CompareResult>>(span, compare ?? Compare);
 1151
 1152  /// <inheritdoc cref="XML_SortCycle"/>
 1153  public static void SortCycle<T, TCompare>(Span<T> span, TCompare compare = default)
 1154    where TCompare : struct, IFunc<T, T, CompareResult>
 831155  {
 246721156    for (int i = 0; i < span.Length - 1; i++)
 122531157    {
 122531158      T pivot = span[i];
 122531159      int index = i;
 110881261160      for (int j = i + 1; j < span.Length; j++)
 55318101161      {
 55318101162        if (compare.Invoke(span[j], pivot) is Less)
 307731163        {
 307731164          index++;
 307731165        }
 55318101166      }
 122531167      if (index == i)
 120741168      {
 120741169        continue;
 1170      }
 1791171      while (compare.Invoke(pivot, span[index]) is Equal)
 01172      {
 01173        index++;
 01174      }
 1791175      if (index != i)
 1791176      {
 1791177        Swap(ref span[index], ref pivot);
 1791178      }
 122701179      while (index != i)
 120911180      {
 120911181        index = i;
 219161561182        for (int j = i + 1; j < span.Length; j++)
 109459871183        {
 109459871184          if (compare.Invoke(span[j], pivot) is Less)
 54435951185          {
 54435951186            index++;
 54435951187          }
 109459871188        }
 121271189        while (compare.Invoke(pivot, span[index]) is Equal)
 361190        {
 361191          index += 1;
 361192        }
 120911193        if (compare.Invoke(pivot, span[index]) is not Equal)
 120911194        {
 120911195          Swap(ref span[index], ref pivot);
 120911196        }
 120911197      }
 1791198    }
 831199  }
 1200
 1201  #endregion
 1202
 1203  #region SortPancake
 1204
 1205  /// <summary>Sorts values using the pancake algorithm.</summary>
 1206  /// <inheritdoc cref="XML_Sort"/>
 1207  [Obsolete(NotIntended, true)]
 11208  public static void XML_SortPancake() => throw new DocumentationMethodException();
 1209
 1210  /// <inheritdoc cref="XML_SortPancake"/>
 1211  public static void SortPancake<T>(int start, int end, Func<int, T> get, Action<int, T> set, Func<T, T, CompareResult>?
 831212    SortPancake<T, SFunc<int, T>, SAction<int, T>, SFunc<T, T, CompareResult>>(start, end, get, set, compare ?? Compare)
 1213
 1214  /// <inheritdoc cref="XML_SortPancake"/>
 1215  public static void SortPancake<T, TGet, TSet, TCompare>(int start, int end, TGet get = default, TSet set = default, TC
 1216    where TCompare : struct, IFunc<T, T, CompareResult>
 1217    where TGet : struct, IFunc<int, T>
 1218    where TSet : struct, IAction<int, T>
 831219  {
 246721220    for (int i = end; i > start; i--)
 122531221    {
 122531222      int index = MaximumIndex<T, TGet, TCompare>(start, i, get, compare);
 122531223      if (index != i)
 120741224      {
 120741225        Reverse<T, TGet, TSet>(start, index, get, set);
 120741226        Reverse<T, TGet, TSet>(start, i, get, set);
 120741227      }
 122531228    }
 831229  }
 1230
 1231  /// <inheritdoc cref="XML_SortPancake"/>
 1232  public static void SortPancake<T>(Span<T> span, Func<T, T, CompareResult>? compare = null) =>
 831233    SortPancake<T, SFunc<T, T, CompareResult>>(span, compare ?? Compare);
 1234
 1235  /// <inheritdoc cref="XML_SortPancake"/>
 1236  public static void SortPancake<T, TCompare>(Span<T> span, TCompare compare = default)
 1237    where TCompare : struct, IFunc<T, T, CompareResult>
 831238  {
 246721239    for (int i = span.Length; i > 1; i--)
 122531240    {
 122531241      int index = MaximumIndex<T, TCompare>(span[0..i], compare);
 122531242      if (index != i - 1)
 120741243      {
 120741244        span[0..(index + 1)].Reverse();
 120741245        span[0..i].Reverse();
 120741246      }
 122531247    }
 831248  }
 1249
 1250  #endregion
 1251
 1252  #region SortStooge
 1253
 1254  /// <summary>Sorts values using the stooge algorithm.</summary>
 1255  /// <inheritdoc cref="XML_Sort"/>
 1256  [Obsolete(NotIntended, true)]
 11257  public static void XML_SortStooge() => throw new DocumentationMethodException();
 1258
 1259  /// <inheritdoc cref="XML_SortStooge"/>
 1260  public static void SortStooge<T>(int start, int end, Func<int, T> get, Action<int, T> set, Func<T, T, CompareResult>? 
 671261    SortStooge<T, SFunc<int, T>, SAction<int, T>, SFunc<T, T, CompareResult>>(start, end, get, set, compare ?? Compare);
 1262
 1263  /// <inheritdoc cref="XML_SortPancake"/>
 1264  public static void SortStooge<T, TGet, TSet, TCompare>(int start, int end, TGet get = default, TSet set = default, TCo
 1265    where TCompare : struct, IFunc<T, T, CompareResult>
 1266    where TGet : struct, IFunc<int, T>
 1267    where TSet : struct, IAction<int, T>
 13346351268  {
 13346351269    int n = end - start + 1;
 13346351270    if (n < 2)
 101271    {
 101272      return;
 1273    }
 13346251274    if (compare.Invoke(get.Invoke(start), get.Invoke(end)) is Greater)
 124261275    {
 124261276      Swap<T, TGet, TSet>(start, end, get, set);
 124261277    }
 13346251278    if (n > 2)
 4448561279    {
 4448561280      int third = n / 3;
 4448561281      SortStooge<T, TGet, TSet, TCompare>(start, end - third, get, set, compare);
 4448561282      SortStooge<T, TGet, TSet, TCompare>(start + third, end, get, set, compare);
 4448561283      SortStooge<T, TGet, TSet, TCompare>(start, end - third, get, set, compare);
 4448561284    }
 13346351285  }
 1286
 1287  /// <inheritdoc cref="XML_SortStooge"/>
 1288  public static void SortStooge<T>(Span<T> span, Func<T, T, CompareResult>? compare = null) =>
 671289    SortStooge<T, SFunc<T, T, CompareResult>>(span, compare ?? Compare);
 1290
 1291  /// <inheritdoc cref="XML_SortStooge"/>
 1292  public static void SortStooge<T, TCompare>(Span<T> span, TCompare compare = default)
 1293    where TCompare : struct, IFunc<T, T, CompareResult>
 13346351294  {
 13346351295    if (span.Length < 2)
 101296    {
 101297      return;
 1298    }
 13346251299    if (compare.Invoke(span[0], span[^1]) is Greater)
 124581300    {
 124581301      Swap(ref span[0], ref span[^1]);
 124581302    }
 13346251303    if (span.Length > 2)
 4448561304    {
 4448561305      int third = span.Length / 3;
 4448561306      SortStooge(span[third..], compare);
 4448561307      SortStooge(span[..^third], compare);
 4448561308      SortStooge(span[third..], compare);
 4448561309    }
 13346351310  }
 1311
 1312  #endregion
 1313
 1314  #region SortTim
 1315
 1316  /// <summary>
 1317  /// Sorts values using the Tim sort algorithm.<br/>
 1318  /// Runtime: Ω(n), ε(n*ln(n)), O(n*ln(n))<br/>
 1319  /// Memory: O(n)<br/>
 1320  /// Stable: True
 1321  /// </summary>
 1322  /// <inheritdoc cref="XML_Sort"/>
 1323  [Obsolete(NotIntended, true)]
 11324  public static void XML_SortTim() => throw new DocumentationMethodException();
 1325
 1326  /// <inheritdoc cref="XML_SortHeap"/>
 1327  public static void SortTim<T>(int start, int end, Func<int, T> get, Action<int, T> set, Func<T, T, CompareResult>? com
 831328    SortTim<T, SFunc<int, T>, SAction<int, T>, SFunc<T, T, CompareResult>>(start, end, get, set, compare ?? Compare);
 1329
 1330  /// <inheritdoc cref="XML_SortTim"/>
 1331  public static void SortTim<T, TGet, TSet, TCompare>(int start, int end, TGet get = default, TSet set = default, TCompa
 1332    where TCompare : struct, IFunc<T, T, CompareResult>
 1333    where TGet : struct, IFunc<int, T>
 1334    where TSet : struct, IAction<int, T>
 831335  {
 1336    const int block = 32;
 831337    int n = end - start + 1;
 10621338    for (int i = start; i < n; i += block)
 4481339    {
 4481340      SortInsertion<T, TGet, TSet, TCompare>(i, Math.Min(i + block, start + n - 1), get, set, compare);
 4481341    }
 3161342    for (int size = block; size < n; size *= 2)
 751343    {
 8921344      for (int left = start; left < n; left += 2 * size)
 3711345      {
 3711346        int mid = left + size - 1;
 3711347        int right = Math.Min(left + 2 * size, n + start) - 1;
 3711348        if (mid < right)
 3701349        {
 1350          // Merge
 3701351          Span<T> a = new T[mid - left + 1];
 3701352          Span<T> b = new T[right - mid];
 595561353          for (int i = 0; i < a.Length; i++)
 294081354          {
 294081355            a[i] = get.Invoke(left + i);
 294081356          }
 557621357          for (int i = 0; i < b.Length; i++)
 275111358          {
 275111359            b[i] = get.Invoke(mid + 1 + i);
 275111360          }
 3701361          int ai = 0;    // index of a
 3701362          int bi = 0;    // index of b
 3701363          int si = left; // index of span
 1127621364          for (; ai < a.Length && bi < b.Length; si++)
 561961365          {
 561961366            if (compare.Invoke(a[ai], b[bi]) is not Greater)
 291191367            {
 291191368              set.Invoke(si, a[ai]);
 291191369              ai++;
 291191370            }
 1371            else
 270771372            {
 270771373              set.Invoke(si, b[bi]);
 270771374              bi++;
 270771375            }
 561961376          }
 12371377          for (; ai < a.Length; si++, ai++)
 2891378          {
 2891379            set.Invoke(si, a[ai]);
 2891380          }
 16721381          for (; bi < b.Length; si++, bi++)
 4341382          {
 4341383            set.Invoke(si, b[bi]);
 4341384          }
 3701385        }
 3711386      }
 751387    }
 831388  }
 1389
 1390  /// <inheritdoc cref="XML_SortTim"/>
 1391  public static void SortTim<T>(Span<T> span, Func<T, T, CompareResult>? compare = null) =>
 831392    SortTim<T, SFunc<T, T, CompareResult>>(span, compare ?? Compare);
 1393
 1394  /// <inheritdoc cref="XML_SortTim"/>
 1395  public static void SortTim<T, TCompare>(Span<T> span, TCompare compare = default)
 1396    where TCompare : struct, IFunc<T, T, CompareResult>
 831397  {
 1398    const int block = 32;
 10621399    for (int i = 0; i < span.Length; i += block)
 4481400    {
 4481401      SortInsertion(span[i..Math.Min(i + block, span.Length)], compare);
 4481402    }
 3161403    for (int size = block; size < span.Length; size *= 2)
 751404    {
 8921405      for (int left = 0; left < span.Length; left += 2 * size)
 3711406      {
 3711407        int mid = left + size - 1;
 3711408        int right = Math.Min(left + 2 * size, span.Length);
 3711409        if (mid < right)
 3701410        {
 1411          // Merge
 3701412          Span<T> a = span[left..(mid + 1)].ToArray();
 3701413          Span<T> b = span[(mid + 1)..right].ToArray();
 3701414          int ai = 0;    // index of a
 3701415          int bi = 0;    // index of b
 3701416          int si = left; // index of span
 1126061417          for (; ai < a.Length && bi < b.Length; si++)
 561181418          {
 561181419            if (compare.Invoke(a[ai], b[bi]) is not Greater)
 288581420            {
 288581421              span[si] = a[ai];
 288581422              ai++;
 288581423            }
 1424            else
 272601425            {
 272601426              span[si] = b[bi];
 272601427              bi++;
 272601428            }
 561181429          }
 20201430          for (; ai < a.Length; si++, ai++)
 5501431          {
 5501432            span[si] = a[ai];
 5501433          }
 11231434          for (; bi < b.Length; si++, bi++)
 2511435          {
 2511436            span[si] = b[bi];
 2511437          }
 3701438        }
 3711439      }
 751440    }
 831441  }
 1442
 1443  #endregion
 1444
 1445  #region SortCounting
 1446
 1447  /// <inheritdoc cref="SortCounting{T, TSelect, TGet, TSet}(int, int, TSelect, TGet, TSet)"/>
 1448  public static void SortCounting(int start, int end, Func<int, uint> get, Action<int, uint> set)
 01449  {
 01450    if (get is null) throw new ArgumentNullException(nameof(get));
 01451    if (set is null) throw new ArgumentNullException(nameof(set));
 01452    SortCounting<uint, Identity<uint>, SFunc<int, uint>, SAction<int, uint>>(start, end, default, get, set);
 01453  }
 1454
 1455  /// <inheritdoc cref="SortCounting{T, TSelect, TGet, TSet}(int, int, TSelect, TGet, TSet)"/>
 1456  public static void SortCounting<T>(int start, int end, Func<T, uint> select, Func<int, T> get, Action<int, T> set)
 351457  {
 351458    if (select is null) throw new ArgumentNullException(nameof(select));
 351459    if (get is null) throw new ArgumentNullException(nameof(get));
 351460    if (set is null) throw new ArgumentNullException(nameof(set));
 351461    SortCounting<T, SFunc<T, uint>, SFunc<int, T>, SAction<int, T>>(start, end, select, get, set);
 351462  }
 1463
 1464  /// <inheritdoc cref="SortCounting{T, TSelect, TGet, TSet}(int, int, TSelect, TGet, TSet)"/>
 1465  public static void SortCounting<TGet, TSet>(int start, int end, TGet get = default, TSet set = default)
 1466    where TGet : struct, IFunc<int, uint>
 1467    where TSet : struct, IAction<int, uint> =>
 01468    SortCounting<uint, Identity<uint>, TGet, TSet>(start, end, default, get, set);
 1469
 1470  /// <summary>
 1471  /// Sorts values using the counting sort algorithm.<br/>
 1472  /// Runtime: Θ(Max(<paramref name="select"/>(n)))<br/>
 1473  /// Memory: Θ(Max(<paramref name="select"/>(n)))<br/>
 1474  /// Stable: True
 1475  /// </summary>
 1476  /// <typeparam name="T">The type of values to sort.</typeparam>
 1477  /// <typeparam name="TSelect">The type of method for selecting an <see cref="int"/> values from <typeparamref name="T"
 1478  /// <typeparam name="TGet">The type of get function.</typeparam>
 1479  /// <typeparam name="TSet">The type of set function.</typeparam>
 1480  /// <param name="start">The starting index of the sort.</param>
 1481  /// <param name="end">The ending index of the sort.</param>
 1482  /// <param name="select">The method for selecting <see cref="int"/> values from <typeparamref name="T"/> values.</para
 1483  /// <param name="get">The get function.</param>
 1484  /// <param name="set">The set function.</param>
 1485  public static void SortCounting<T, TSelect, TGet, TSet>(int start, int end, TSelect select = default, TGet get = defau
 1486    where TSelect : struct, IFunc<T, uint>
 1487    where TGet : struct, IFunc<int, T>
 1488    where TSet : struct, IAction<int, T>
 351489  {
 351490    if (end - start + 1 < 2)
 41491    {
 41492      return;
 1493    }
 311494    Span<T> sortingSpan = new T[end - start + 1];
 311495    uint max = 0;
 111121496    for (int i = start; i <= end; i++)
 55251497    {
 55251498      uint temp = select.Invoke(get.Invoke(i));
 55251499      max = Math.Max(max, temp);
 55251500    }
 311501    SortCounting(start, end, select, get, set, sortingSpan, max);
 351502  }
 1503
 1504  internal static void SortCounting<T, TSelect, TGet, TSet>(int start, int end, TSelect select, TGet get, TSet set, Span
 1505    where TSelect : struct, IFunc<T, uint>
 1506    where TGet : struct, IFunc<int, T>
 1507    where TSet : struct, IAction<int, T>
 1321508  {
 1321509    if (end - start + 1 != sortingSpan.Length)
 01510    {
 01511      throw new TowelBugException(message: $"{nameof(end)} - {nameof(start)} + 1 != {nameof(sortingSpan)}.{nameof(sortin
 1512    }
 1321513    int[] count = new int[max + 1];
 572761514    for (int i = start; i <= end; i++)
 285061515    {
 285061516      count[select.Invoke(get.Invoke(i))]++;
 285061517    }
 156775521518    for (int i = 1; i <= max; i++)
 78386441519    {
 78386441520      count[i] += count[i - 1];
 78386441521    }
 572761522    for (int i = end; i >= start; i--)
 285061523    {
 285061524      sortingSpan[count[select.Invoke(get.Invoke(i))] - 1] = get.Invoke(i);
 285061525      count[select.Invoke(get.Invoke(i))]--;
 285061526    }
 859141527    for (int a = start, b = 0; a <= end; a++, b++)
 285061528    {
 285061529      set.Invoke(a, sortingSpan[b]);
 285061530    }
 1321531  }
 1532
 1533  /// <inheritdoc cref="SortCounting{T, TGetKey}(Span{T}, TGetKey)"/>
 1534  public static void SortCounting(Span<uint> span) =>
 01535    SortCounting<uint, Identity<uint>>(span);
 1536
 1537  /// <inheritdoc cref="SortCounting{T, TGetKey}(Span{T}, TGetKey)"/>
 1538  public static void SortCounting<T>(Span<T> span, Func<T, uint> select) =>
 351539    SortCounting<T, SFunc<T, uint>>(span, select);
 1540
 1541  /// <summary>
 1542  /// Sorts values using the counting sort algorithm.<br/>
 1543  /// Runtime: Θ(Max(<paramref name="select"/>(<paramref name="span"/>)))<br/>
 1544  /// Memory: Θ(Max(<paramref name="select"/>(<paramref name="span"/>)))<br/>
 1545  /// Stable: True
 1546  /// </summary>
 1547  /// <typeparam name="T">The type of values to sort.</typeparam>
 1548  /// <typeparam name="TSelect">The type of method for selecting an <see cref="int"/> values from <typeparamref name="T"
 1549  /// <param name="span">The span to be sorted.</param>
 1550  /// <param name="select">The method for selecting <see cref="int"/> values from <typeparamref name="T"/> values.</para
 1551  public static void SortCounting<T, TSelect>(Span<T> span, TSelect select = default)
 1552    where TSelect : struct, IFunc<T, uint>
 351553  {
 351554    if (span.Length < 2)
 41555    {
 41556      return;
 1557    }
 311558    Span<T> sortingSpan = new T[span.Length];
 311559    uint max = uint.MinValue;
 111431560    foreach (T t in span)
 55251561    {
 55251562      uint temp = select.Invoke(t);
 55251563      max = Math.Max(max, temp);
 55251564    }
 311565    SortCounting(span, select, sortingSpan, max);
 351566  }
 1567
 1568  internal static void SortCounting<T, TSelect>(Span<T> span, TSelect select, Span<T> sortingSpan, uint max)
 1569    where TSelect : struct, IFunc<T, uint>
 1321570  {
 1321571    if (span.Length != sortingSpan.Length)
 01572    {
 01573      throw new TowelBugException(message: $"{nameof(span)}.{nameof(span.Length)} != {nameof(sortingSpan)}.{nameof(sorti
 1574    }
 1321575    int[] count = new int[max + 1];
 572761576    for (int i = 0; i < span.Length; i++)
 285061577    {
 285061578      count[select.Invoke(span[i])]++;
 285061579    }
 156775521580    for (int i = 1; i <= max; i++)
 78386441581    {
 78386441582      count[i] += count[i - 1];
 78386441583    }
 572761584    for (int i = span.Length - 1; i >= 0; i--)
 285061585    {
 285061586      sortingSpan[count[select.Invoke(span[i])] - 1] = span[i];
 285061587      count[select.Invoke(span[i])]--;
 285061588    }
 1321589    sortingSpan.CopyTo(span);
 1321590  }
 1591
 1592  #endregion
 1593
 1594  #region SortRadix
 1595
 1596  /// <inheritdoc cref="SortRadix{T, TSelect, TGet, TSet}(int, int, TSelect, TGet, TSet)"/>
 1597  public static void SortRadix(int start, int end, Func<int, uint> get, Action<int, uint> set)
 01598  {
 01599    if (get is null) throw new ArgumentNullException(nameof(get));
 01600    if (set is null) throw new ArgumentNullException(nameof(set));
 01601    SortRadix<uint, Identity<uint>, SFunc<int, uint>, SAction<int, uint>>(start, end, default, get, set);
 01602  }
 1603
 1604  /// <inheritdoc cref="SortRadix{T, TSelect, TGet, TSet}(int, int, TSelect, TGet, TSet)"/>
 1605  public static void SortRadix<T>(int start, int end, Func<T, uint> select, Func<int, T> get, Action<int, T> set)
 351606  {
 351607    if (select is null) throw new ArgumentNullException(nameof(select));
 351608    if (get is null) throw new ArgumentNullException(nameof(get));
 351609    if (set is null) throw new ArgumentNullException(nameof(set));
 351610    SortRadix<T, SFunc<T, uint>, SFunc<int, T>, SAction<int, T>>(start, end, select, get, set);
 351611  }
 1612
 1613  /// <inheritdoc cref="SortRadix{T, TSelect, TGet, TSet}(int, int, TSelect, TGet, TSet)"/>
 1614  public static void SortRadix<TGet, TSet>(int start, int end, TGet get = default, TSet set = default)
 1615    where TGet : struct, IFunc<int, uint>
 1616    where TSet : struct, IAction<int, uint> =>
 01617    SortRadix<uint, Identity<uint>, TGet, TSet>(start, end, default, get, set);
 1618
 1619  /// <summary>
 1620  /// Sorts values using the radix sort algorithm.
 1621  /// </summary>
 1622  /// <typeparam name="T">The type of values to sort.</typeparam>
 1623  /// <typeparam name="TSelect">The type of method for selecting an <see cref="int"/> values from <typeparamref name="T"
 1624  /// <typeparam name="TGet">The type of get function.</typeparam>
 1625  /// <typeparam name="TSet">The type of set function.</typeparam>
 1626  /// <param name="start">The starting index of the sort.</param>
 1627  /// <param name="end">The ending index of the sort.</param>
 1628  /// <param name="select">The method for selecting <see cref="int"/> values from <typeparamref name="T"/> values.</para
 1629  /// <param name="get">The get function.</param>
 1630  /// <param name="set">The set function.</param>
 1631  public static void SortRadix<T, TSelect, TGet, TSet>(int start, int end, TSelect select = default, TGet get = default,
 1632    where TSelect : struct, IFunc<T, uint>
 1633    where TGet : struct, IFunc<int, T>
 1634    where TSet : struct, IAction<int, T>
 351635  {
 351636    if (end - start + 1 < 2)
 41637    {
 41638      return;
 1639    }
 311640    uint max = uint.MinValue;
 111121641    for (int i = start; i <= end; i++)
 55251642    {
 55251643      uint temp = select.Invoke(get.Invoke(i));
 55251644      max = Math.Max(max, temp);
 55251645    }
 311646    Span<T> sortingSpan = new T[end - start + 1];
 2641647    for (uint divisor = 1; max / divisor > 0; divisor *= 10)
 1011648    {
 1011649      SortCounting<T, SortRadixSelect<T, TSelect>, TGet, TSet>(start, end, new() { Select = select, Divisor = divisor },
 1011650    }
 351651  }
 1652
 1653  /// <inheritdoc cref="SortRadix{T, TGetKey}(Span{T}, TGetKey)"/>
 1654  public static void SortRadix(Span<uint> span) =>
 01655    SortRadix<uint, Identity<uint>>(span);
 1656
 1657  /// <inheritdoc cref="SortRadix{T, TGetKey}(Span{T}, TGetKey)"/>
 1658  public static void SortRadix<T>(Span<T> span, Func<T, uint> select) =>
 351659    SortRadix<T, SFunc<T, uint>>(span, select);
 1660
 1661  /// <summary>
 1662  /// Sorts values using the radix sort algorithm.
 1663  /// </summary>
 1664  /// <typeparam name="T">The type of values to sort.</typeparam>
 1665  /// <typeparam name="TSelect">The type of method for selecting an <see cref="int"/> values from <typeparamref name="T"
 1666  /// <param name="span">The span to be sorted.</param>
 1667  /// <param name="select">The method for selecting <see cref="int"/> values from <typeparamref name="T"/> values.</para
 1668  public static void SortRadix<T, TSelect>(Span<T> span, TSelect select = default)
 1669    where TSelect : struct, IFunc<T, uint>
 351670  {
 351671    if (span.Length < 2)
 41672    {
 41673      return;
 1674    }
 311675    uint max = uint.MinValue;
 111431676    foreach (T t in span)
 55251677    {
 55251678      uint temp = select.Invoke(t);
 55251679      if (temp < 0)
 01680      {
 01681        throw new ArgumentException(message: $"a value exists in {nameof(span)} where {nameof(select)} is less than 0");
 1682      }
 55251683      max = Math.Max(max, temp);
 55251684    }
 311685    Span<T> sortingSpan = new T[span.Length];
 2641686    for (uint divisor = 1; max / divisor > 0; divisor *= 10)
 1011687    {
 1011688      SortCounting<T, SortRadixSelect<T, TSelect>>(span, new() { Select = select, Divisor = divisor }, sortingSpan, max)
 1011689    }
 351690  }
 1691
 1692  internal struct SortRadixSelect<T, TSelect> : IFunc<T, uint>
 1693    where TSelect : struct, IFunc<T, uint>
 1694  {
 1695    internal TSelect Select;
 1696    internal uint Divisor;
 1697
 1378861698    public uint Invoke(T a) => Select.Invoke(a) / Divisor;
 1699  }
 1700
 1701  #endregion
 1702
 1703  #region SortPidgeonHole
 1704
 1705  /// <inheritdoc cref="SortPidgeonHole{TGet, TSet}(int, int, TGet, TSet)"/>
 1706  public static void SortPidgeonHole(int start, int end, Func<int, int> get, Action<int, int> set)
 831707  {
 831708    if (get is null) throw new ArgumentNullException(nameof(get));
 831709    if (set is null) throw new ArgumentNullException(nameof(set));
 831710    SortPidgeonHole<SFunc<int, int>, SAction<int, int>>(start, end, get, set);
 831711  }
 1712
 1713  /// <summary>
 1714  /// Sorts values using the pidgeon hole sort algorithm.
 1715  /// </summary>
 1716  /// <typeparam name="TGet">The type of get function.</typeparam>
 1717  /// <typeparam name="TSet">The type of set function.</typeparam>
 1718  /// <param name="start">The starting index of the sort.</param>
 1719  /// <param name="end">The ending index of the sort.</param>
 1720  /// <param name="get">The get function.</param>
 1721  /// <param name="set">The set function.</param>
 1722  public static void SortPidgeonHole<TGet, TSet>(int start, int end, TGet get = default, TSet set = default)
 1723    where TGet : struct, IFunc<int, int>
 1724    where TSet : struct, IAction<int, int>
 831725  {
 831726    if (end - start + 1 < 2)
 101727    {
 101728      return;
 1729    }
 731730    int min = int.MaxValue;
 731731    int max = int.MinValue;
 247981732    for (int i = start; i <= end; i++)
 123261733    {
 123261734      int temp = get.Invoke(i);
 123261735      if (i < 0)
 01736      {
 01737        throw new ArgumentException(message: $"a value exists in the sequence that is less than 0");
 1738      }
 123261739      max = Math.Max(max, temp);
 123261740      min = Math.Min(min, temp);
 123261741    }
 731742    if (min < int.MinValue / 2 && max > -(int.MinValue / 2))
 01743    {
 01744      throw new OverflowException($"the range of values in the sequence exceends the range of the int data type");
 1745    }
 731746    Span<int> holes = new int[max - min + 1];
 247981747    for (int i = start; i <= end; i++)
 123261748    {
 123261749      holes[get.Invoke(i) - min]++;
 123261750    }
 71325611751    for (int hole = 0, i = start; hole < holes.Length; hole++)
 35661711752    {
 71569941753      for (int j = 0; j < holes[hole]; j++)
 123261754      {
 123261755        set.Invoke(i++, hole + min);
 123261756      }
 35661711757    }
 831758  }
 1759
 1760  /// <summary>
 1761  /// Sorts values using the pidgeon hole sort algorithm.
 1762  /// </summary>
 1763  /// <param name="span">The span to be sorted.</param>
 1764  public static void SortPidgeonHole(Span<int> span)
 831765  {
 831766    if (span.Length < 2)
 101767    {
 101768      return;
 1769    }
 731770    int min = int.MaxValue;
 731771    int max = int.MinValue;
 248711772    foreach (int i in span)
 123261773    {
 123261774      max = Math.Max(max, i);
 123261775      min = Math.Min(min, i);
 123261776    }
 731777    if (min < int.MinValue / 2 && max > -(int.MinValue / 2))
 01778    {
 01779      throw new OverflowException($"the range of values in {nameof(span)} exceends the range of the int data type");
 1780    }
 731781    Span<int> holes = new int[max - min + 1];
 248711782    foreach (int i in span)
 123261783    {
 123261784      holes[i - min]++;
 123261785    }
 71325611786    for (int hole = 0, i = 0; hole < holes.Length; hole++)
 35661711787    {
 71569941788      for (int j = 0; j < holes[hole]; j++)
 123261789      {
 123261790        span[i++] = hole + min;
 123261791      }
 35661711792    }
 831793  }
 1794
 1795  #endregion
 1796
 1797  #region IntroSort
 1798
 1799  /// <summary>
 1800  /// Sorts values using the introspective sort algorithm.<br/>
 1801  /// Runtime: Ω(n*ln(n)), ε(n*ln(n)), O(n*ln(n))<br/>
 1802  /// Memory: Θ(n)<br/>
 1803  /// Stable: False
 1804  /// </summary>
 1805  /// <inheritdoc cref="XML_Sort"/>
 1806  /// <citation>
 1807  /// The code for introspective sort was forked from the dotnet/runtime repo. Here is their license:
 1808  /// https://github.com/dotnet/runtime/blob/358ee3c9f61d8c11f7cac067307db1b2d6690f3c/src/libraries/System.Private.CoreL
 1809  ///
 1810  /// The MIT License (MIT)
 1811  ///
 1812  /// Copyright(c) .NET Foundation and Contributors
 1813  ///
 1814  /// All rights reserved.
 1815  ///
 1816  /// Permission is hereby granted, free of charge, to any person obtaining a copy
 1817  /// of this software and associated documentation files(the "Software"), to deal
 1818  /// in the Software without restriction, including without limitation the rights
 1819  /// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 1820  /// copies of the Software, and to permit persons to whom the Software is
 1821  /// furnished to do so, subject to the following conditions:
 1822  ///
 1823  /// The above copyright notice and this permission notice shall be included in all
 1824  /// copies or substantial portions of the Software.
 1825  ///
 1826  /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 1827  /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 1828  /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
 1829  /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 1830  /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 1831  /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 1832  /// SOFTWARE.
 1833  /// </citation>
 1834  [Obsolete(NotIntended, true)]
 11835  public static void XML_SortIntro() => throw new DocumentationMethodException();
 1836
 1837  internal const int IntrosortSizeThreshold = 16;
 1838
 1839  /// <inheritdoc cref="XML_SortIntro"/>
 1840  public static void SortIntro<T>(int start, int end, Func<int, T> get, Action<int, T> set, Func<T, T, CompareResult>? c
 831841    SortIntro<T, SFunc<int, T>, SAction<int, T>, SFunc<T, T, CompareResult>>(start, end, get, set, compare ?? Compare);
 1842
 1843  /// <inheritdoc cref="XML_SortIntro"/>
 1844  public static void SortIntro<T, TGet, TSet, TCompare>(int start, int end, TGet get = default, TSet set = default, TCom
 1845    where TCompare : struct, IFunc<T, T, CompareResult>
 1846    where TGet : struct, IFunc<int, T>
 1847    where TSet : struct, IAction<int, T>
 831848  {
 831849    if (end - start > 0)
 731850    {
 731851      SortIntro<T, TGet, TSet, TCompare>(start, end, 2 * (System.Numerics.BitOperations.Log2((uint)(end - start)) + 1), 
 731852    }
 831853  }
 1854
 1855  internal static void SortIntro<T, TGet, TSet, TCompare>(int lo, int hi, int depthLimit, TGet get = default, TSet set =
 1856    where TCompare : struct, IFunc<T, T, CompareResult>
 1857    where TGet : struct, IFunc<int, T>
 1858    where TSet : struct, IAction<int, T>
 11701859  {
 22671860    while (hi > lo)
 22551861    {
 22551862      int partitionSize = hi - lo + 1;
 22551863      if (partitionSize <= IntrosortSizeThreshold)
 11581864      {
 11581865        if (partitionSize is 2)
 481866        {
 791867          if (compare.Invoke(get.Invoke(lo), get.Invoke(hi)) is Greater) Swap<T, TGet, TSet>(lo, hi, get, set);
 481868          return;
 1869        }
 1870
 11101871        if (partitionSize is 3)
 451872        {
 671873          if (compare.Invoke(get.Invoke(lo), get.Invoke(hi - 1)) is Greater) Swap<T, TGet, TSet>(lo, hi - 1, get, set);
 571874          if (compare.Invoke(get.Invoke(lo), get.Invoke(hi)) is Greater) Swap<T, TGet, TSet>(lo, hi, get, set);
 721875          if (compare.Invoke(get.Invoke(hi - 1), get.Invoke(hi)) is Greater) Swap<T, TGet, TSet>(hi - 1, hi, get, set);
 451876          return;
 1877        }
 10651878        SortInsertion<T, TGet, TSet, TCompare>(lo, hi, get, set, compare);
 10651879        return;
 1880      }
 10971881      if (depthLimit is 0)
 01882      {
 01883        SortHeap<T, TGet, TSet, TCompare>(lo, hi, get, set, compare);
 01884        return;
 1885      }
 10971886      int p = PickPivotAndPartition<T, TGet, TSet, TCompare>(lo, hi, get, set, compare);
 10971887      SortIntro<T, TGet, TSet, TCompare>(p + 1, hi, --depthLimit, get, set, compare);
 10971888      hi = p - 1;
 10971889    }
 11701890  }
 1891
 1892  internal static int PickPivotAndPartition<T, TGet, TSet, TCompare>(int lo, int hi, TGet get = default, TSet set = defa
 1893    where TCompare : struct, IFunc<T, T, CompareResult>
 1894    where TGet : struct, IFunc<int, T>
 1895    where TSet : struct, IAction<int, T>
 10971896  {
 10971897    int mid = lo + (hi - lo) / 2;
 16421898    if (compare.Invoke(get.Invoke(lo), get.Invoke(mid)) is Greater) Swap<T, TGet, TSet>(lo, mid, get, set);
 14961899    if (compare.Invoke(get.Invoke(lo), get.Invoke(hi)) is Greater) Swap<T, TGet, TSet>(lo, hi, get, set);
 18421900    if (compare.Invoke(get.Invoke(mid), get.Invoke(hi)) is Greater) Swap<T, TGet, TSet>(mid, hi, get, set);
 10971901    T pivot = get.Invoke(mid);
 10971902    Swap<T, TGet, TSet>(mid, hi - 1, get, set);
 10971903    int left = lo;
 10971904    int right = hi - 1;
 174821905    while (left < right)
 174821906    {
 406311907      while (compare.Invoke(get.Invoke(++left), pivot) is Less)
 231491908      {
 1909        // spin
 231491910      }
 414531911      while (compare.Invoke(pivot, get.Invoke(--right)) is Less)
 239711912      {
 1913        // spin
 239711914      }
 174821915      if (left >= right)
 10971916      {
 10971917        break;
 1918      }
 163851919      Swap<T, TGet, TSet>(left, right, get, set);
 163851920    }
 10971921    if (left != hi - 1)
 10901922    {
 10901923      Swap<T, TGet, TSet>(left, hi - 1, get, set);
 10901924    }
 10971925    return left;
 10971926  }
 1927
 1928  /// <inheritdoc cref="XML_SortIntro"/>
 1929  public static void SortIntro<T>(Span<T> span, Func<T, T, CompareResult>? compare = null) =>
 831930    SortIntro<T, SFunc<T, T, CompareResult>>(span, compare ?? Compare);
 1931
 1932  /// <inheritdoc cref="XML_SortIntro"/>
 1933  public static void SortIntro<T, TCompare>(Span<T> span, TCompare compare = default)
 1934    where TCompare : struct, IFunc<T, T, CompareResult>
 831935  {
 831936    if (span.Length > 1)
 731937    {
 731938      SortIntro(span, 2 * (System.Numerics.BitOperations.Log2((uint)span.Length) + 1), compare);
 731939    }
 831940  }
 1941
 1942  internal static void SortIntro<T, TCompare>(Span<T> span, int depthLimit, TCompare compare = default)
 1943    where TCompare : struct, IFunc<T, T, CompareResult>
 11701944  {
 11701945    if (span.Length > 1)
 11631946    {
 11631947      int lo = 0;
 11631948      int hi = span.Length - 1;
 22601949      while (hi > lo)
 22551950      {
 22551951        int partitionSize = hi - lo + 1;
 22551952        if (partitionSize <= IntrosortSizeThreshold)
 11581953        {
 11581954          if (partitionSize is 2)
 481955          {
 791956            if (compare.Invoke(span[lo], span[hi]) is Greater) Swap(ref span[lo], ref span[hi]);
 481957            return;
 1958          }
 11101959          if (partitionSize is 3)
 451960          {
 671961            if (compare.Invoke(span[lo], span[hi - 1]) is Greater) Swap(ref span[lo], ref span[hi - 1]);
 571962            if (compare.Invoke(span[lo], span[hi]) is Greater) Swap(ref span[lo], ref span[hi]);
 721963            if (compare.Invoke(span[hi - 1], span[hi]) is Greater) Swap(ref span[hi - 1], ref span[hi]);
 451964            return;
 1965          }
 10651966          SortInsertion(span[lo..(hi + 1)], compare);
 10651967          return;
 1968        }
 10971969        if (depthLimit is 0)
 01970        {
 01971          SortHeap(span[lo..(hi + 1)], compare);
 01972          return;
 1973        }
 10971974        int p = PickPivotAndPartition(span, lo, hi, compare);
 10971975        SortIntro(span[(p + 1)..(hi + 1)], --depthLimit, compare);
 10971976        hi = p - 1;
 10971977      }
 51978    }
 11701979  }
 1980
 1981  internal static int PickPivotAndPartition<T, TCompare>(Span<T> span, int lo, int hi, TCompare compare = default)
 1982    where TCompare : struct, IFunc<T, T, CompareResult>
 10971983  {
 10971984    int mid = lo + (hi - lo) / 2;
 16421985    if (compare.Invoke(span[lo], span[mid]) is Greater) Swap(ref span[lo], ref span[mid]);
 14961986    if (compare.Invoke(span[lo], span[hi]) is Greater) Swap(ref span[lo], ref span[hi]);
 18421987    if (compare.Invoke(span[mid], span[hi]) is Greater) Swap(ref span[mid], ref span[hi]);
 10971988    T pivot = span[mid];
 10971989    Swap(ref span[mid], ref span[hi - 1]);
 10971990    int left = lo;
 10971991    int right = hi - 1;
 174821992    while (left < right)
 174821993    {
 406311994      while (compare.Invoke(span[++left], pivot) is Less)
 231491995      {
 1996        // spin
 231491997      }
 414531998      while (compare.Invoke(pivot, span[--right]) is Less)
 239711999      {
 2000        // spin
 239712001      }
 174822002      if (left >= right)
 10972003      {
 10972004        break;
 2005      }
 163852006      Swap(ref span[left], ref span[right]);
 163852007    }
 10972008    if (left != hi - 1)
 10902009    {
 10902010      Swap(ref span[left], ref span[hi - 1]);
 10902011    }
 10972012    return left;
 10972013  }
 2014
 2015  #endregion
 2016}

/home/runner/work/Towel/Towel/Sources/Towel/Statics-Structs.cs

#LineLine coverage
 1namespace Towel;
 2
 3/// <summary>Root type of the static functional methods in Towel.</summary>
 4public static partial class Statics
 5{
 6  #region Int32
 7
 8  /// <summary>Hashing function for <see cref="int"/>.</summary>
 9  public struct Int32Hash : IFunc<int, int>
 10  {
 11    /// <inheritdoc cref="Func{T1, TResult}.Invoke(T1)"/>
 219985412    public int Invoke(int a) => a;
 13  }
 14
 15  /// <summary>Equality checking function for <see cref="int"/>.</summary>
 16  public struct Int32Equate : IFunc<int, int, bool>
 17  {
 18    /// <inheritdoc cref="Func{T1, T2, TResult}.Invoke(T1, T2)"/>
 129471619    public bool Invoke(int a, int b) => a == b;
 20  }
 21
 22  /// <summary>Comparing function for <see cref="int"/>.</summary>
 23  public struct Int32Compare : IFunc<int, int, CompareResult>
 24  {
 25    /// <inheritdoc cref="Func{T1, T2, TResult}.Invoke(T1, T2)"/>
 4226    public CompareResult Invoke(int a, int b) => a.CompareTo(b).ToCompareResult();
 27  }
 28
 29  internal struct Int32Increment : IFunc<int, int>
 30  {
 2831    public int Invoke(int a) => a + 1;
 32  }
 33
 34  internal struct Int32Decrement : IFunc<int, int>
 35  {
 6036    public int Invoke(int a) => a - 1;
 37  }
 38
 39  internal struct Int32Add : IFunc<int, int>
 40  {
 41    internal int Value;
 42
 200043    public int Invoke(int a) => a + Value;
 44
 300045    public static implicit operator Int32Add(int value) => new() { Value = value };
 46  }
 47
 48  #endregion
 49
 50  #region Char
 51
 52  /// <summary>Equality checking function for <see cref="char"/>.</summary>
 53  public struct CharEquate : IFunc<char, char, bool>
 54  {
 55    /// <inheritdoc cref="Func{T1, T2, TResult}.Invoke(T1, T2)"/>
 36656    public bool Invoke(char a, char b) => a == b;
 57  }
 58
 59  /// <summary>Hashing function for <see cref="char"/>.</summary>
 60  public struct CharHash : IFunc<char, int>
 61  {
 62    /// <inheritdoc cref="Func{T1, TResult}.Invoke(T1)"/>
 063    public int Invoke(char a) => a;
 64  }
 65
 66  #endregion
 67
 68  #region String
 69
 70  /// <summary>Equality checking function for <see cref="string"/>.</summary>
 71  public struct StringEquate : IFunc<string, string, bool>
 72  {
 73    /// <inheritdoc cref="Func{T1, T2, TResult}.Invoke(T1, T2)"/>
 106674    public bool Invoke(string a, string b) => a == b;
 75  }
 76
 77  /// <summary>Hashing function for <see cref="string"/>.</summary>
 78  public struct StringHash : IFunc<string, int>
 79  {
 80    /// <inheritdoc cref="Func{T1, TResult}.Invoke(T1)"/>
 301381    public int Invoke(string a) => a.GetHashCode();
 82  }
 83
 84  #endregion
 85
 86  /// <summary>Built in function type to return the value passed in.</summary>
 87  /// <typeparam name="T">The type of value to be passed in and returned.</typeparam>
 88  public struct Identity<T> : IFunc<T, T>
 89  {
 90    /// <inheritdoc cref="Func{T1, TResult}.Invoke(T1)"/>
 45687591    public T Invoke(T arg1) => arg1;
 92  }
 93
 94  /// <summary>Built in struct for runtime computations.</summary>
 95  /// <typeparam name="T">The generic type of the values.</typeparam>
 96  /// <typeparam name="TStep">The Step function.</typeparam>
 97  public struct StepBreakFromAction<T, TStep> : IFunc<T, StepStatus>
 98    where TStep : struct, IAction<T>
 99  {
 100    internal TStep StepFunction;
 101
 102    /// <inheritdoc cref="Func{T1, TResult}.Invoke(T1)"/>
 103    public StepStatus Invoke(T value)
 2042698104    {
 2042698105      StepFunction.Invoke(value);
 2042698106      return Continue;
 2042698107    }
 108
 109    /// <summary>Implicitly wraps runtime computation inside a compile time struct.</summary>
 110    /// <param name="step">The runtime Step delegate.</param>
 5214111    public static implicit operator StepBreakFromAction<T, TStep>(TStep step) => new() { StepFunction = step, };
 112  }
 113
 114  /// <summary>Inverts the results of a comparison.</summary>
 115  /// <typeparam name="T">The types being compared.</typeparam>
 116  /// <typeparam name="TCompare">The type of the compare function.</typeparam>
 117  public struct CompareInvert<T, TCompare> : IFunc<T, T, CompareResult>
 118    where TCompare : struct, IFunc<T, T, CompareResult>
 119  {
 120    internal TCompare _compare;
 121    /// <inheritdoc cref="Func{T1, T2, TResult}.Invoke(T1, T2)"/>
 42122    public CompareResult Invoke(T a, T b) => _compare.Invoke(b, a);
 123    /// <summary>Inverts a <typeparamref name="TCompare"/>.</summary>
 124    /// <param name="compare">The <typeparamref name="TCompare"/> to invert.</param>
 30125    public static implicit operator CompareInvert<T, TCompare>(TCompare compare) => new() { _compare = compare, };
 126  }
 127
 128  /// <summary>Built in Compare struct for runtime computations.</summary>
 129  /// <typeparam name="T">The generic type of the values to compare.</typeparam>
 130  /// <typeparam name="TCompare">The compare function.</typeparam>
 131  public struct SiftFromCompareAndValue<T, TCompare> : IFunc<T, CompareResult>
 132    where TCompare : struct, IFunc<T, T, CompareResult>
 133  {
 134    internal TCompare CompareFunction;
 135    internal T Value;
 136
 137    /// <inheritdoc cref="Func{T1, TResult}.Invoke(T1)"/>
 29292138    public CompareResult Invoke(T a) => CompareFunction.Invoke(a, Value);
 139
 140    /// <summary>Creates a compile-time-resolved sifting function to be passed into another type.</summary>
 141    /// <param name="value">The value for future values to be compared against.</param>
 142    /// <param name="compare">The compare function.</param>
 143    public SiftFromCompareAndValue(T value, TCompare compare = default)
 3881144    {
 3881145      Value = value;
 3881146      CompareFunction = compare;
 3881147    }
 148  }
 149
 150  /// <summary>Built in Compare struct for runtime computations.</summary>
 151  /// <typeparam name="T">The generic type of the values to compare.</typeparam>
 152  /// <typeparam name="TEquate">The equality check function.</typeparam>
 153  public struct PredicateFromEquateAndValue<T, TEquate> : IFunc<T, bool>
 154    where TEquate : struct, IFunc<T, T, bool>
 155  {
 156    internal TEquate Equate;
 157    internal T Value;
 158
 159    /// <inheritdoc cref="Func{T1, T2, TResult}.Invoke(T1, T2)"/>
 0160    public bool Invoke(T a) => Equate.Invoke(a, Value);
 161
 162    /// <summary>Creates a compile-time-resolved sifting function to be passed into another type.</summary>
 163    /// <param name="value">The value for future values to be compared against.</param>
 164    /// <param name="equate">The compare function.</param>
 165    public PredicateFromEquateAndValue(T value, TEquate equate = default)
 0166    {
 0167      Value = value;
 0168      Equate = equate;
 0169    }
 170  }
 171
 172  /// <summary>Compile time resulution to the <see cref="StepStatus.Continue"/> value.</summary>
 173  public struct StepStatusContinue : IFunc<StepStatus>
 174  {
 175    /// <summary>Returns <see cref="StepStatus.Continue"/>.</summary>
 176    /// <returns><see cref="StepStatus.Continue"/></returns>
 124177    public StepStatus Invoke() => Continue;
 178  }
 179
 180  /// <summary>Struct wrapper for the <see cref="Random.Next(int, int)"/> method as an <see cref="IFunc{T1, T2, TResult}
 181  public struct RandomNextIntMinValueIntMaxValue : IFunc<int, int, int>
 182  {
 183    internal Random _random;
 184    /// <inheritdoc cref="Func{T1, T2, TResult}.Invoke(T1, T2)"/>
 1976140185    public int Invoke(int minValue, int maxValue) => _random.Next(minValue, maxValue);
 186
 187    /// <summary>Converts a <see cref="Random"/> to a <see cref="RandomNextIntMinValueIntMaxValue"/>.</summary>
 188    /// <param name="random">The <see cref="Random"/> to convert into a <see cref="RandomNextIntMinValueIntMaxValue"/>.<
 26746189    public static implicit operator RandomNextIntMinValueIntMaxValue(Random random) => new() { _random = random, };
 190  }
 191
 192  /// <summary>Encapsulates a method that has a single <see cref="ReadOnlySpan{T}"/> parameter and does not return a val
 193  /// <typeparam name="T">The type of the <see cref="ReadOnlySpan{T}"/> parameter of the method that this delegate encap
 194  /// <param name="readOnlySpan">The <see cref="ReadOnlySpan{T}"/> parameter of the method that this delegate encapsulat
 195  public delegate void Action_ReadOnlySpan<T>(ReadOnlySpan<T> readOnlySpan);
 196
 197  /// <inheritdoc cref="Action_ReadOnlySpan{T1}"/>
 198  public interface IAction_ReadOnlySpan<T>
 199  {
 200    /// <inheritdoc cref="Action_ReadOnlySpan{T1}.Invoke(ReadOnlySpan{T1})"/>
 201    void Invoke(ReadOnlySpan<T> readOnlySpan);
 202  }
 203
 204  /// <inheritdoc cref="Action_ReadOnlySpan{T1}"/>
 205  public struct Action_ReadOnlySpan_Runtime<T> : IAction_ReadOnlySpan<T>
 206  {
 207    internal Action_ReadOnlySpan<T> Action;
 208
 209    /// <inheritdoc cref="Action_ReadOnlySpan{T1}.Invoke(ReadOnlySpan{T1})"/>
 82210    public void Invoke(ReadOnlySpan<T> readOnlySpan) => Action(readOnlySpan);
 211
 212    /// <summary>Wraps an <see cref="Action_ReadOnlySpan{T1}"/> in an <see cref="Action_ReadOnlySpan_Runtime{T1}"/>.</su
 213    /// <param name="action">The <see cref="Action_ReadOnlySpan{T1}"/> wrapped in an <see cref="Action_ReadOnlySpan_Runt
 12214    public static implicit operator Action_ReadOnlySpan_Runtime<T>(Action_ReadOnlySpan<T> action) => new() { Action = ac
 215  }
 216
 217  #region Arrays
 218
 219  internal struct FillArray<T> : IAction<T>
 220  {
 221    internal int Index;
 222    internal T[] Array;
 223
 33788224    public void Invoke(T arg1) => Array[Index++] = arg1;
 225
 4034226    public static implicit operator FillArray<T>(T[] array) => new() { Array = array, };
 227  }
 228
 229  internal struct Func_int_int_JaggedArray_Length0<T> : IFunc<int, int>
 230  {
 231    internal T[][] JaggedArray;
 125232    public int Invoke(int index) => JaggedArray[index].Length;
 233
 12234    public static implicit operator Func_int_int_JaggedArray_Length0<T>(T[][] jaggedArray) => new() { JaggedArray = jagg
 235  }
 236
 237  internal struct Func_int_int_T_JaggedArray_Get<T> : IFunc<int, int, T>
 238  {
 239    internal T[][] JaggedArray;
 154240    public T Invoke(int index1, int index2) => JaggedArray[index1][index2];
 241
 12242    public static implicit operator Func_int_int_T_JaggedArray_Get<T>(T[][] jaggedArray) => new() { JaggedArray = jagged
 243  }
 244
 245  #endregion
 246}

/home/runner/work/Towel/Towel/Sources/Towel/Statics-SyntaxHacks.cs

#LineLine coverage
 1namespace Towel;
 2
 3/// <summary>Root type of the static functional methods in Towel.</summary>
 4public static partial class Statics
 5{
 6  #region Keywords
 7
 8  /// <summary>Stepper was not broken.</summary>
 9  public const StepStatus Continue = StepStatus.Continue;
 10  /// <summary>Stepper was broken.</summary>
 11  public const StepStatus Break = StepStatus.Break;
 12  /// <summary>The Goal was found.</summary>
 13  public const GraphSearchStatus Goal = GraphSearchStatus.Goal;
 14  /// <summary>The left operand is less than the right operand.</summary>
 15  public const CompareResult Less = CompareResult.Less;
 16  /// <summary>The left operand is equal to the right operand.</summary>
 17  public const CompareResult Equal = CompareResult.Equal;
 18  /// <summary>The left operand is greater than the right operand.</summary>
 19  public const CompareResult Greater = CompareResult.Greater;
 20  /// <summary>There is no bound.</summary>
 21  public const Omnitree.Keyword None = Omnitree.Keyword.None;
 22  /// <summary>The default case in a Switch statement (true).</summary>
 23  public const SwitchSyntax.Keyword Default = SwitchSyntax.Keyword.Default;
 24
 25  #endregion
 26
 27  #region Switch
 28
 29  /// <summary>Syntax sugar Switch statements.</summary>
 30  /// <param name="possibleActions">The possible actions of the Switch statement.</param>
 31  public static void Switch(params (SwitchSyntax.Condition, Action)[] possibleActions) =>
 032    SwitchSyntax.Do(possibleActions);
 33
 34  /// <summary>Syntax sugar Switch statements.</summary>
 35  /// <typeparam name="T">The generic type parameter to the Switch statement.</typeparam>
 36  /// <param name="value">The value argument of the Switch statement.</param>
 37  /// <returns>The delegate for the Switch statement.</returns>
 38  public static SwitchSyntax.ParamsAction<SwitchSyntax.Condition<T>, Action> Switch<T>(T value) =>
 039    SwitchSyntax.Do<T>(value);
 40
 41  /// <summary>Definitions for Switch syntax.</summary>
 42  public static class SwitchSyntax
 43  {
 44    /// <summary>Delegate with params intended to be used with the Switch syntax.</summary>
 45    /// <typeparam name="TA">The first type in the value tuples in the array.</typeparam>
 46    /// <typeparam name="TB">The second type in the value tuples in the array.</typeparam>
 47    /// <param name="values">The param values.</param>
 48    public delegate void ParamsAction<TA, TB>(params (TA, TB)[] values);
 49
 50    internal static ParamsAction<Condition<T>, Action> Do<T>(T value) =>
 051      possibleActions =>
 052      {
 053        foreach (var possibleAction in possibleActions)
 054        {
 055          if (possibleAction.Item1.Resolve(value))
 056          {
 057            possibleAction.Item2();
 058            return;
 059          }
 060        }
 061      };
 62
 63    internal static void Do(params (Condition Condition, Action Action)[] possibleActions)
 064    {
 065      foreach (var possibleAction in possibleActions)
 066      {
 067        if (possibleAction.Condition)
 068        {
 069          possibleAction.Action();
 070          return;
 71        }
 072      }
 073    }
 74
 75    /// <summary>Intended to be used with Switch syntax.</summary>
 76    public enum Keyword
 77    {
 78      /// <summary>The default keyword for the the Switch syntax.</summary>
 79      Default,
 80    }
 81
 82    /// <summary>Represents the result of a conditional expression inside Switch syntax.</summary>
 83    /// <typeparam name="T">The generic type of the Switch condition for equality checks.</typeparam>
 84    public abstract class Condition<T>
 85    {
 86      /// <summary>Resolves the condition to a bool.</summary>
 87      /// <param name="b">The right value to compare this condition to.</param>
 88      /// <returns>The result of the condition.</returns>
 89      public abstract bool Resolve(T b);
 90
 91      /// <summary>Casts a <typeparamref name="T"/> to a bool using an equality check.</summary>
 92      /// <param name="value">The value this condition will compare with.</param>
 093      public static implicit operator Condition<T>(T value) => new Value<T>(a: value);
 94
 95      /// <summary>Uses the bool as the condition result.</summary>
 96      /// <param name="result">The <see cref="bool"/>result of this condition.</param>
 097      public static implicit operator Condition<T>(bool result) => new Bool<T> { Result = result, };
 98
 99#pragma warning disable IDE0079 // Remove unnecessary suppression
 100#pragma warning disable IDE0060 // Remove unused parameter
 101
 102      /// <summary>Converts a keyword to a condition result (for "Default" case).</summary>
 103      /// <param name="keyword"><see cref="Keyword.Default"/></param>
 0104      public static implicit operator Condition<T>(Keyword keyword) => new Default<T>();
 105
 106#pragma warning restore IDE0060 // Remove unused parameter
 107#pragma warning restore IDE0079 // Remove unnecessary suppression
 108    }
 109
 110    internal class Value<T> : Condition<T>
 111    {
 112      /// <summary>The value of this condition for an equality check.</summary>
 113      internal T A;
 0114      public override bool Resolve(T b) => Equate(A, b);
 0115      public Value(T a)
 0116      {
 0117        A = a;
 0118      }
 119    }
 120
 121    internal class Bool<T> : Condition<T>
 122    {
 123      internal bool Result;
 0124      public override bool Resolve(T b) => Result;
 125    }
 126
 127    internal class Default<T> : Condition<T>
 128    {
 0129      public override bool Resolve(T b) => true;
 130    }
 131
 132    /// <summary>Represents the result of a conditional expression inside Switch syntax.</summary>
 133    public abstract class Condition
 134    {
 135      /// <summary>Resolves the condition to a bool.</summary>
 136      /// <returns>The result of the condition.</returns>
 137      public abstract bool Resolve();
 138
 139      /// <summary>Uses the bool as the condition result.</summary>
 140      /// <param name="result">The <see cref="bool"/>result of this condition.</param>
 0141      public static implicit operator Condition(bool result) => new Bool { Result = result, };
 142
 143#pragma warning disable IDE0079 // Remove unnecessary suppression
 144#pragma warning disable IDE0060 // Remove unused parameter
 145
 146      /// <summary>Converts a keyword to a condition result (for "Default" case).</summary>
 147      /// <param name="keyword"><see cref="Keyword.Default"/></param>
 0148      public static implicit operator Condition(Keyword keyword) => new Default();
 149
 150#pragma warning restore IDE0060 // Remove unused parameter
 151#pragma warning restore IDE0079 // Remove unnecessary suppression
 152
 153      /// <summary>Converts a condition to a bool using the Resolve method.</summary>
 154      /// <param name="condition">The condition to resolve to a <see cref="bool"/> value.</param>
 0155      public static implicit operator bool(Condition condition) => condition.Resolve();
 156    }
 157
 158    internal class Bool : Condition
 159    {
 160      internal bool Result;
 0161      public override bool Resolve() => Result;
 162    }
 163
 164    internal class Default : Condition
 165    {
 0166      public override bool Resolve() => true;
 167    }
 168  }
 169
 170  #endregion
 171
 172  #region Chance
 173
 174#pragma warning disable CA2211 // Non-constant fields should not be visible
 175#pragma warning disable IDE0079 // Remove unnecessary suppression
 176#pragma warning disable IDE0075 // Simplify conditional expression
 177#pragma warning disable IDE0060 // Remove unused parameter
 178
 179  /// <summary>Allows chance syntax with "using static Towel.Syntax;".</summary>
 180  /// <example>25% Chance</example>
 0181  public static ChanceSyntax Chance => default;
 182
 183  /// <summary>Struct that allows percentage syntax that will be evaluated at runtime.</summary>
 184  public struct ChanceSyntax
 185  {
 186    /// <summary>Creates a chance from a percentage that will be evaluated at runtime.</summary>
 187    /// <param name="percentage">The value of the percentage.</param>
 188    /// <param name="chance">The chance syntax struct object.</param>
 189    /// <returns>True if the the chance hits. False if not.</returns>
 190    public static bool operator %(double percentage, ChanceSyntax chance) =>
 0191      percentage < 0d ? throw new ArgumentOutOfRangeException(nameof(chance)) :
 0192      percentage > 100d ? throw new ArgumentOutOfRangeException(nameof(chance)) :
 0193      percentage is 100d ? true :
 0194      percentage is 0d ? false :
 0195      Random.Shared.NextDouble() < percentage / 100d;
 196  }
 197
 198#pragma warning restore IDE0060 // Remove unused parameter
 199#pragma warning restore IDE0075 // Simplify conditional expression
 200#pragma warning restore IDE0079 // Remove unnecessary suppression
 201#pragma warning restore CA2211 // Non-constant fields should not be visible
 202
 203  #endregion
 204
 205  #region Inequality
 206
 207  /// <summary>Used for inequality syntax.</summary>
 208  /// <typeparam name="T">The generic type of elements the inequality is being used on.</typeparam>
 209  public struct Inequality<T>
 210  {
 211    internal bool Cast;
 212    internal T A;
 213
 214    /// <summary>Contructs a new <see cref="Inequality{T}"/>.</summary>
 215    /// <param name="a">The initial value of the running inequality.</param>
 216    public static implicit operator Inequality<T>(T a) =>
 0217      new()
 0218      {
 0219        Cast = true,
 0220        A = a,
 0221      };
 222
 223    /// <summary>Adds a greater than operation to a running inequality.</summary>
 224    /// <param name="a">The current running inequality and left hand operand.</param>
 225    /// <param name="b">The value of the right hand operand of the greater than operation.</param>
 226    /// <returns>A running inequality with the additonal greater than operation.</returns>
 227    public static OperatorValidated.Inequality<T> operator >(Inequality<T> a, T b) =>
 0228      !a.Cast ? throw new InequalitySyntaxException() :
 0229      new OperatorValidated.Inequality<T>(Compare(a.A, b) == Greater, b);
 230
 231    /// <summary>Adds a less than operation to a running inequality.</summary>
 232    /// <param name="a">The current running inequality and left hand operand.</param>
 233    /// <param name="b">The value of the right hand operand of the less than operation.</param>
 234    /// <returns>A running inequality with the additonal less than operation.</returns>
 235    public static OperatorValidated.Inequality<T> operator <(Inequality<T> a, T b) =>
 0236      !a.Cast ? throw new InequalitySyntaxException() :
 0237      new OperatorValidated.Inequality<T>(Compare(a.A, b) == Less, b);
 238
 239    /// <summary>Adds a greater than or equal operation to a running inequality.</summary>
 240    /// <param name="a">The current running inequality and left hand operand.</param>
 241    /// <param name="b">The value of the right hand operand of the greater than or equal operation.</param>
 242    /// <returns>A running inequality with the additonal greater than or equal operation.</returns>
 243    public static OperatorValidated.Inequality<T> operator >=(Inequality<T> a, T b) =>
 0244      !a.Cast ? throw new InequalitySyntaxException() :
 0245      new OperatorValidated.Inequality<T>(Compare(a.A, b) != Less, b);
 246
 247    /// <summary>Adds a less than or equal operation to a running inequality.</summary>
 248    /// <param name="a">The current running inequality and left hand operand.</param>
 249    /// <param name="b">The value of the right hand operand of the less than or equal operation.</param>
 250    /// <returns>A running inequality with the additonal less than or equal operation.</returns>
 251    public static OperatorValidated.Inequality<T> operator <=(Inequality<T> a, T b) =>
 0252      !a.Cast ? throw new InequalitySyntaxException() :
 0253      new OperatorValidated.Inequality<T>(Compare(a.A, b) != Greater, b);
 254
 255    /// <summary>Adds an equal operation to a running inequality.</summary>
 256    /// <param name="a">The current running inequality and left hand operand.</param>
 257    /// <param name="b">The value of the right hand operand of the equal operation.</param>
 258    /// <returns>A running inequality with the additonal equal operation.</returns>
 259    public static OperatorValidated.Inequality<T> operator ==(Inequality<T> a, T b) =>
 0260      !a.Cast ? throw new InequalitySyntaxException() :
 0261      new OperatorValidated.Inequality<T>(Equate(a.A, b), b);
 262
 263    /// <summary>Adds an inequal operation to a running inequality.</summary>
 264    /// <param name="a">The current running inequality and left hand operand.</param>
 265    /// <param name="b">The value of the right hand operand of the inequal operation.</param>
 266    /// <returns>A running inequality with the additonal inequal operation.</returns>
 267    public static OperatorValidated.Inequality<T> operator !=(Inequality<T> a, T b) =>
 0268      !a.Cast ? throw new InequalitySyntaxException() :
 0269      new OperatorValidated.Inequality<T>(Inequate(a.A, b), b);
 270
 271#pragma warning disable CS0809 // Obsolete member overrides non-obsolete member
 272
 273    /// <summary>This member is not intended to be invoked.</summary>
 274    /// <inheritdoc/>
 275    [Obsolete(NotIntended, true)]
 0276    public override string ToString() => throw new InequalitySyntaxException();
 277
 278    /// <summary>This member is not intended to be invoked.</summary>
 279    /// <inheritdoc/>
 280    [Obsolete(NotIntended, true)]
 0281    public override bool Equals(object? obj) => throw new InequalitySyntaxException();
 282
 283    /// <summary>This member is not intended to be invoked.</summary>
 284    /// <inheritdoc/>
 285    [Obsolete(NotIntended, true)]
 0286    public override int GetHashCode() => throw new InequalitySyntaxException();
 287
 288#pragma warning restore CS0809 // Obsolete member overrides non-obsolete member
 289  }
 290
 291  /// <summary>Helper type for inequality syntax. Contains an Inequality type that has been operator validated.</summary
 292  public static partial class OperatorValidated
 293  {
 294    /// <summary>Used for inequality syntax.</summary>
 295    /// <typeparam name="T">The generic type of elements the inequality is being used on.</typeparam>
 296    public struct Inequality<T>
 297    {
 298      internal readonly bool Result;
 299      internal readonly T A;
 300
 301      internal Inequality(bool result, T a)
 0302      {
 0303        Result = result;
 0304        A = a;
 0305      }
 306      /// <summary>Converts this running inequality into the result of the expression.</summary>
 307      /// <param name="inequality">The inequality to convert into the result of the expression.</param>
 0308      public static implicit operator bool(Inequality<T> inequality) => inequality.Result;
 309
 310      /// <summary>Adds a greater than operation to a running inequality.</summary>
 311      /// <param name="a">The current running inequality and left hand operand.</param>
 312      /// <param name="b">The value of the right hand operand of the greater than operation.</param>
 313      /// <returns>A running inequality with the additonal greater than operation.</returns>
 0314      public static Inequality<T> operator >(Inequality<T> a, T b) => new(a.Result && Compare(a.A, b) == Greater, b);
 315
 316      /// <summary>Adds a less than operation to a running inequality.</summary>
 317      /// <param name="a">The current running inequality and left hand operand.</param>
 318      /// <param name="b">The value of the right hand operand of the less than operation.</param>
 319      /// <returns>A running inequality with the additonal less than operation.</returns>
 0320      public static Inequality<T> operator <(Inequality<T> a, T b) => new(a.Result && Compare(a.A, b) == Less, b);
 321
 322      /// <summary>Adds a greater than or equal operation to a running inequality.</summary>
 323      /// <param name="a">The current running inequality and left hand operand.</param>
 324      /// <param name="b">The value of the right hand operand of the greater than or equal operation.</param>
 325      /// <returns>A running inequality with the additonal greater than or equal operation.</returns>
 0326      public static Inequality<T> operator >=(Inequality<T> a, T b) => new(a.Result && Compare(a.A, b) != Less, b);
 327
 328      /// <summary>Adds a less than or equal operation to a running inequality.</summary>
 329      /// <param name="a">The current running inequality and left hand operand.</param>
 330      /// <param name="b">The value of the right hand operand of the less than or equal operation.</param>
 331      /// <returns>A running inequality with the additonal less than or equal operation.</returns>
 0332      public static Inequality<T> operator <=(Inequality<T> a, T b) => new(a.Result && Compare(a.A, b) != Greater, b);
 333
 334      /// <summary>Adds an equal operation to a running inequality.</summary>
 335      /// <param name="a">The current running inequality and left hand operand.</param>
 336      /// <param name="b">The value of the right hand operand of the equal operation.</param>
 337      /// <returns>A running inequality with the additonal equal operation.</returns>
 0338      public static Inequality<T> operator ==(Inequality<T> a, T b) => new(a.Result && Equate(a.A, b), b);
 339
 340      /// <summary>Adds an inequal operation to a running inequality.</summary>
 341      /// <param name="a">The current running inequality and left hand operand.</param>
 342      /// <param name="b">The value of the right hand operand of the inequal operation.</param>
 343      /// <returns>A running inequality with the additonal inequal operation.</returns>
 0344      public static Inequality<T> operator !=(Inequality<T> a, T b) => new(a.Result && Inequate(a.A, b), b);
 345
 346      /// <summary>Converts the result of this inequality to a <see cref="string"/>.</summary>
 347      /// <inheritdoc/>
 0348      public override string ToString() => Result.ToString();
 349
 350#pragma warning disable CS0809 // Obsolete member overrides non-obsolete member
 351
 352      /// <summary>This member is not intended to be invoked.</summary>
 353      /// <inheritdoc/>
 354      [Obsolete(NotIntended, true)]
 0355      public override bool Equals(object? obj) => throw new InequalitySyntaxException();
 356
 357      /// <summary>This member is not intended to be invoked.</summary>
 358      /// <inheritdoc/>
 359      [Obsolete(NotIntended, true)]
 0360      public override int GetHashCode() => throw new InequalitySyntaxException();
 361
 362#pragma warning restore CS0809 // Obsolete member overrides non-obsolete member
 363    }
 364  }
 365
 366  #endregion
 367
 368  #region UniversalQuantification
 369
 370#pragma warning disable CS0618 // Type or member is obsolete
 371
 372  /// <summary>Universal Quantification Operator.</summary>
 373  /// <typeparam name="T">The element type of the universal quantification to declare.</typeparam>
 374  /// <param name="values">The values of the universal quantification.</param>
 375  /// <returns>The declared universal quantification.</returns>
 250376  public static UniversalQuantification<T> Ɐ<T>(params T[] values) => new(values);
 377
 378#pragma warning restore CS0618 // Type or member is obsolete
 379
 380  /// <summary>Universal Quantification.</summary>
 381  /// <typeparam name="T">The element type of the universal quantification.</typeparam>
 382  public struct UniversalQuantification<T> :
 383    System.Collections.Generic.IEnumerable<T>,
 384    System.Collections.Generic.IList<T>,
 385    IArray<T>
 386  {
 387    internal T[] Value;
 388
 389    /// <summary>Not intended to be invoked directly.</summary>
 390    /// <param name="array">The array value of the universal quantification.</param>
 391    [Obsolete(NotIntended, false)]
 250392    internal UniversalQuantification(T[] array) => Value = array;
 393
 394    #region Towel.Datastructures.IArray<T>
 395
 396    /// <summary>Not intended to be invoked directly.</summary>
 397    /// <inheritdoc/>
 398    [Obsolete(NotIntended, false)]
 0399    public int Length => Value.Length;
 400
 401    /// <summary>Not intended to be invoked directly.</summary>
 402    /// <inheritdoc/>
 403    [Obsolete(NotIntended, false)]
 404    public StepStatus StepperBreak<TStep>(TStep step = default)
 405      where TStep : struct, IFunc<T, StepStatus> =>
 0406      Value.StepperBreak(step);
 407
 408    /// <summary>Not intended to be invoked directly.</summary>
 409    /// <inheritdoc/>
 410    [Obsolete(NotIntended, false)]
 0411    public T[] ToArray() => Value;
 412
 413    #endregion
 414
 415    #region System.Collections.Generic.IList<T>
 416
 417    /// <summary>Not intended to be invoked directly.</summary>
 418    /// <inheritdoc/>
 419    [Obsolete(NotIntended, false)]
 420    public T this[int index]
 421    {
 0422      get => Value[index];
 0423      set => Value[index] = value;
 424    }
 425
 426    /// <summary>Not intended to be invoked directly.</summary>
 427    /// <inheritdoc/>
 428    [Obsolete(NotIntended, false)]
 4429    public int Count => Value.Length;
 430
 431    /// <summary>Not intended to be invoked directly.</summary>
 432    /// <inheritdoc/>
 433    [Obsolete(NotIntended, false)]
 0434    public bool IsReadOnly => false;
 435
 436    /// <summary>Not intended to be invoked directly.</summary>
 437    /// <inheritdoc/>
 438    [Obsolete(NotIntended, false)]
 439    public void Add(T item)
 0440    {
 0441      T[] newValue = new T[Value.Length + 1];
 0442      Array.Copy(Value, newValue, Value.Length);
 0443      newValue[Value.Length] = item;
 0444      Value = newValue;
 0445    }
 446
 447    /// <summary>Not intended to be invoked directly.</summary>
 448    [Obsolete(NotIntended, false)]
 0449    public void Clear() => Value = Array.Empty<T>();
 450
 451    /// <summary>Not intended to be invoked directly.</summary>
 452    /// <inheritdoc/>
 453    [Obsolete(NotIntended, false)]
 0454    public bool Contains(T item) => Value.Contains(item);
 455
 456    /// <summary>Not intended to be invoked directly.</summary>
 457    /// <inheritdoc/>
 458    [Obsolete(NotIntended, false)]
 459    public void CopyTo(T[] array, int arrayIndex) =>
 4460      Array.Copy(Value, 0, array, arrayIndex, Value.Length);
 461
 462    /// <summary>Not intended to be invoked directly.</summary>
 463    /// <inheritdoc/>
 464    [Obsolete(NotIntended, false)]
 0465    public int IndexOf(T item) => Array.IndexOf(Value, item);
 466
 467    /// <summary>Not intended to be invoked directly.</summary>
 468    /// <inheritdoc/>
 469    [Obsolete(NotIntended, false)]
 470    public void Insert(int index, T item)
 0471    {
 0472      T[] newValue = new T[Value.Length + 1];
 0473      for (int i = 0; i < newValue.Length; i++)
 0474      {
 0475        newValue[i] = i == index
 0476          ? item
 0477          : i < index
 0478            ? Value[i]
 0479            : Value[i - 1];
 0480      }
 0481      Value = newValue;
 0482    }
 483
 484    /// <summary>Not intended to be invoked directly.</summary>
 485    /// <inheritdoc/>
 486    [Obsolete(NotIntended, false)]
 487    public bool Remove(T item)
 0488    {
 0489      T[] newValue = new T[Value.Length - 1];
 0490      bool found = false;
 0491      for (int i = 0; i < Value.Length; i++)
 0492      {
 0493        if (Equate(Value[i], item))
 0494        {
 0495          found = true;
 0496        }
 0497        else if (found)
 0498        {
 0499          newValue[i] = Value[i - 1];
 0500        }
 501        else
 0502        {
 0503          newValue[i] = Value[i];
 0504        }
 0505      }
 0506      if (!found)
 0507      {
 0508        return false;
 509      }
 0510      Value = newValue;
 0511      return true;
 0512    }
 513
 514    /// <summary>Not intended to be invoked directly.</summary>
 515    /// <inheritdoc/>
 516    [Obsolete(NotIntended, false)]
 517    public void RemoveAt(int index)
 0518    {
 0519      T[] newValue = new T[Value.Length - 1];
 0520      for (int i = 0; i < Value.Length; i++)
 0521      {
 0522        if (i != index)
 0523        {
 0524          if (i < index)
 0525          {
 0526            newValue[i] = Value[i];
 0527          }
 528          else
 0529          {
 0530            newValue[i] = Value[i - 1];
 0531          }
 0532        }
 0533      }
 0534      Value = newValue;
 0535    }
 536    #endregion
 537
 538    #region System.Collections.Generic.IEnumerable<T>
 539
 540    /// <summary>Not intended to be invoked directly.</summary>
 541    /// <inheritdoc/>
 542    [Obsolete(NotIntended, false)]
 70543    public System.Collections.Generic.IEnumerator<T> GetEnumerator() => ((System.Collections.Generic.IEnumerable<T>)Valu
 544
 545    /// <summary>Not intended to be invoked directly.</summary>
 546    /// <inheritdoc/>
 547    [Obsolete(NotIntended, false)]
 0548    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => Value.GetEnumerator();
 549
 550    #endregion
 551
 552    #region Implicit Casting Operators
 553
 554    /// <summary>Converts a universal quantification to a memory.</summary>
 555    /// <param name="universalQuantification">The universal quantification to be converted.</param>
 0556    public static implicit operator ReadOnlyMemory<T>(UniversalQuantification<T> universalQuantification) => universalQu
 557    /// <summary>Converts a universal quantification to a memory.</summary>
 558    /// <param name="universalQuantification">The universal quantification to be converted.</param>
 0559    public static implicit operator Memory<T>(UniversalQuantification<T> universalQuantification) => universalQuantifica
 560    /// <summary>Converts a universal quantification to a span.</summary>
 561    /// <param name="universalQuantification">The universal quantification to be converted.</param>
 80562    public static implicit operator ReadOnlySpan<T>(UniversalQuantification<T> universalQuantification) => universalQuan
 563    /// <summary>Converts a universal quantification to a span.</summary>
 564    /// <param name="universalQuantification">The universal quantification to be converted.</param>
 0565    public static implicit operator Span<T>(UniversalQuantification<T> universalQuantification) => universalQuantificati
 566    /// <summary>Converts a universal quantification to an array.</summary>
 567    /// <param name="universalQuantification">The universal quantification to be converted.</param>
 92568    public static implicit operator T[](UniversalQuantification<T> universalQuantification) => universalQuantification.V
 569    /// <summary>Converts a universal quantification to a <see cref="System.Collections.Generic.List{T}"/>.</summary>
 570    /// <param name="universalQuantification">The universal quantification to be converted.</param>
 0571    public static implicit operator System.Collections.Generic.List<T>(UniversalQuantification<T> universalQuantificatio
 572    /// <summary>Converts a universal quantification to an <see cref="System.Collections.Generic.HashSet{T}"/>.</summary
 573    /// <param name="universalQuantification">The universal quantification to be converted.</param>
 0574    public static implicit operator System.Collections.Generic.HashSet<T>(UniversalQuantification<T> universalQuantifica
 575    /// <summary>Converts a universal quantification to a <see cref="System.Collections.Generic.LinkedList{T}"/>.</summa
 576    /// <param name="universalQuantification">The universal quantification to be converted.</param>
 0577    public static implicit operator System.Collections.Generic.LinkedList<T>(UniversalQuantification<T> universalQuantif
 578    /// <summary>Converts a universal quantification to an <see cref="System.Collections.Generic.Stack{T}"/>.</summary>
 579    /// <param name="universalQuantification">The universal quantification to be converted.</param>
 0580    public static implicit operator System.Collections.Generic.Stack<T>(UniversalQuantification<T> universalQuantificati
 581    /// <summary>Converts a universal quantification to an <see cref="System.Collections.Generic.Queue{T}"/>.</summary>
 582    /// <param name="universalQuantification">The universal quantification to be converted.</param>
 0583    public static implicit operator System.Collections.Generic.Queue<T>(UniversalQuantification<T> universalQuantificati
 584    /// <summary>Converts a universal quantification to a sorted <see cref="System.Collections.Generic.SortedSet{T}"/>.<
 585    /// <param name="universalQuantification">The universal quantification to be converted.</param>
 0586    public static implicit operator System.Collections.Generic.SortedSet<T>(UniversalQuantification<T> universalQuantifi
 587    /// <summary>Converts a universal quantification to an Action&lt;Action&lt;T&gt;&gt;.</summary>
 588    /// <param name="universalQuantification">The universal quantification to be converted.</param>
 0589    public static implicit operator Action<Action<T>>(UniversalQuantification<T> universalQuantification) => universalQu
 590    /// <summary>Converts a universal quantification to an Func&lt;Func&lt;T, StepStatus&gt;, StepStatus&gt;.</summary>
 591    /// <param name="universalQuantification">The universal quantification to be converted.</param>
 0592    public static implicit operator Func<Func<T, StepStatus>, StepStatus>(UniversalQuantification<T> universalQuantifica
 593    /// <summary>Converts a universal quantification to an <see cref="Array{T}"/>.</summary>
 594    /// <param name="universalQuantification">The universal quantification to be converted.</param>
 0595    public static implicit operator Towel.DataStructures.Array<T>(UniversalQuantification<T> universalQuantification) =>
 596    /// <summary>Converts a universal quantification to an <see cref="ListArray{T}"/>.</summary>
 597    /// <param name="universalQuantification">The universal quantification to be converted.</param>
 0598    public static implicit operator Towel.DataStructures.ListArray<T>(UniversalQuantification<T> universalQuantification
 599    /// <summary>Converts a universal quantification to an <see cref="StackArray{T}"/>.</summary>
 600    /// <param name="universalQuantification">The universal quantification to be converted.</param>
 0601    public static implicit operator Towel.DataStructures.StackArray<T>(UniversalQuantification<T> universalQuantificatio
 602
 603    #endregion
 604  }
 605
 606  #endregion
 607}

/home/runner/work/Towel/Towel/Sources/Towel/Statics-Trigonometry.cs

#LineLine coverage
 1namespace Towel;
 2
 3/// <summary>Root type of the static functional methods in Towel.</summary>
 4public static partial class Statics
 5{
 6  #region Sine
 7
 8  /// <summary>Computes the sine ratio of an angle using the relative talor series. Accurate but slow.</summary>
 9  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 10  /// <param name="a">The angle to compute the sine ratio of.</param>
 11  /// <param name="predicate">Determines if coputation should continue or is accurate enough.</param>
 12  /// <returns>The taylor series computed sine ratio of the provided angle.</returns>
 13  public static T SineTaylorSeries<T>(Angle<T> a, Predicate<T>? predicate = null)
 714  {
 15    // Series: sine(x) = x - (x^3 / 3!) + (x^5 / 5!) - (x^7 / 7!) + (x^9 / 9!) + ...
 16    // more terms in computation inproves accuracy
 17
 18    // Note: there is room for optimization (custom runtime compilation)
 19
 720    T x = a[Angle.Units.Radians];
 721    T sine = x;
 22    T previous;
 723    bool isAddTerm = false;
 724    T i = Constant<T>.Three;
 725    T xSquared = Multiplication(x, x);
 726    T xRunningPower = x;
 727    T xRunningFactorial = Constant<T>.One;
 28    do
 10729    {
 10730      xRunningPower = Multiplication(xRunningPower, xSquared);
 10731      xRunningFactorial = Multiplication(xRunningFactorial, Multiplication(i, Subtraction(i, Constant<T>.One)));
 10732      previous = sine;
 10733      if (isAddTerm)
 5134      {
 5135        sine = Addition(sine, Division(xRunningPower, xRunningFactorial));
 5136      }
 37      else
 5638      {
 5639        sine = Subtraction(sine, Division(xRunningPower, xRunningFactorial));
 5640      }
 10741      isAddTerm = !isAddTerm;
 10742      i = Addition(i, Constant<T>.Two);
 21443    } while (Inequate(sine, previous) && (predicate is null || !predicate(sine)));
 744    return sine;
 745  }
 46
 47  /// <summary>Computes the sine ratio of an angle using the system's sine function. WARNING! CONVERSION TO/FROM DOUBLE 
 48  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 49  /// <param name="a">The angle to compute the sine ratio of.</param>
 50  /// <returns>The sine ratio of the provided angle.</returns>
 51  /// <remarks>WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures).</remarks>
 52  public static T SineSystem<T>(Angle<T> a)
 053  {
 054    T b = a[Angle.Units.Radians];
 055    double c = Convert<T, double>(b);
 056    double d = Math.Sin(c);
 057    T e = Convert<double, T>(d);
 058    return e;
 059  }
 60
 61  /// <summary>Estimates the sine ratio using piecewise quadratic equations. Fast but NOT very accurate.</summary>
 62  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 63  /// <param name="a">The angle to compute the quadratic estimated sine ratio of.</param>
 64  /// <returns>The quadratic estimation of the sine ratio of the provided angle.</returns>
 65  public static T SineQuadratic<T>(Angle<T> a)
 066  {
 67    // Piecewise Functions:
 68    // y = (-4/π^2)(x - (π/2))^2 + 1
 69    // y = (4/π^2)(x - (3π/2))^2 - 1
 70
 071    T adjusted = Remainder(a[Angle.Units.Radians], Constant<T>.Pi2);
 072    if (IsNegative(adjusted))
 073    {
 074      adjusted = Addition(adjusted, Constant<T>.Pi2);
 075    }
 076    if (LessThan(adjusted, Constant<T>.Pi))
 077    {
 078      T xMinusPiOver2 = Subtraction(adjusted, Constant<T>.PiOver2);
 079      T xMinusPiOver2Squared = Multiplication(xMinusPiOver2, xMinusPiOver2);
 080      return Addition(Multiplication(Constant<T>.Negative4OverPiSquared, xMinusPiOver2Squared), Constant<T>.One);
 81    }
 82    else
 083    {
 084      T xMinus3PiOver2 = Subtraction(adjusted, Constant<T>.Pi3Over2);
 085      T xMinus3PiOver2Squared = Multiplication(xMinus3PiOver2, xMinus3PiOver2);
 086      return Subtraction(Multiplication(Constant<T>.FourOverPiSquared, xMinus3PiOver2Squared), Constant<T>.One);
 87    }
 088  }
 89
 90  #endregion
 91
 92  #region Cosine
 93
 94  /// <summary>Computes the cosine ratio of an angle using the relative talor series. Accurate but slow.</summary>
 95  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 96  /// <param name="a">The angle to compute the cosine ratio of.</param>
 97  /// <param name="predicate">Determines if coputation should continue or is accurate enough.</param>
 98  /// <returns>The taylor series computed cosine ratio of the provided angle.</returns>
 99  public static T CosineTaylorSeries<T>(Angle<T> a, Predicate<T>? predicate = null)
 7100  {
 101    // Series: cosine(x) = 1 - (x^2 / 2!) + (x^4 / 4!) - (x^6 / 6!) + (x^8 / 8!) - ...
 102    // more terms in computation inproves accuracy
 103
 104    // Note: there is room for optimization (custom runtime compilation)
 105
 7106    T x = a[Angle.Units.Radians];
 7107    T cosine = Constant<T>.One;
 108    T previous;
 7109    T xSquared = Multiplication(x, x);
 7110    T xRunningPower = Constant<T>.One;
 7111    T xRunningFactorial = Constant<T>.One;
 7112    bool isAddTerm = false;
 7113    T i = Constant<T>.Two;
 114    do
 125115    {
 125116      xRunningPower = Multiplication(xRunningPower, xSquared);
 125117      xRunningFactorial = Multiplication(xRunningFactorial, Multiplication(i, Subtraction(i, Constant<T>.One)));
 125118      previous = cosine;
 125119      if (isAddTerm)
 61120      {
 61121        cosine = Addition(cosine, Division(xRunningPower, xRunningFactorial));
 61122      }
 123      else
 64124      {
 64125        cosine = Subtraction(cosine, Division(xRunningPower, xRunningFactorial));
 64126      }
 125127      isAddTerm = !isAddTerm;
 125128      i = Addition(i, Constant<T>.Two);
 250129    } while (Inequate(cosine, previous) && (predicate is null || !predicate(cosine)));
 7130    return cosine;
 7131  }
 132
 133  /// <summary>Computes the cosine ratio of an angle using the system's cosine function. WARNING! CONVERSION TO/FROM DOU
 134  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 135  /// <param name="a">The angle to compute the cosine ratio of.</param>
 136  /// <returns>The cosine ratio of the provided angle.</returns>
 137  /// <remarks>WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures).</remarks>
 138  public static T CosineSystem<T>(Angle<T> a)
 0139  {
 0140    T b = a[Angle.Units.Radians];
 0141    double c = Convert<T, double>(b);
 0142    double d = Math.Cos(c);
 0143    T e = Convert<double, T>(d);
 0144    return e;
 0145  }
 146
 147  /// <summary>Estimates the cosine ratio using piecewise quadratic equations. Fast but NOT very accurate.</summary>
 148  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 149  /// <param name="a">The angle to compute the quadratic estimated cosine ratio of.</param>
 150  /// <returns>The quadratic estimation of the cosine ratio of the provided angle.</returns>
 151  public static T CosineQuadratic<T>(Angle<T> a)
 0152  {
 0153    Angle<T> piOver2Radians = new(Constant<T>.PiOver2, Angle.Units.Radians);
 0154    return SineQuadratic(a - piOver2Radians);
 0155  }
 156
 157  #endregion
 158
 159  #region Tangent
 160
 161  /// <summary>Computes the tangent ratio of an angle using the relative talor series. Accurate but slow.</summary>
 162  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 163  /// <param name="a">The angle to compute the tangent ratio of.</param>
 164  /// <returns>The taylor series computed tangent ratio of the provided angle.</returns>
 165  public static T TangentTaylorSeries<T>(Angle<T> a)
 0166  {
 0167    return Division(SineTaylorSeries(a), CosineTaylorSeries(a));
 0168  }
 169
 170  /// <summary>Computes the tangent ratio of an angle using the system's tangent function. WARNING! CONVERSION TO/FROM D
 171  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 172  /// <param name="a">The angle to compute the tangent ratio of.</param>
 173  /// <returns>The tangent ratio of the provided angle.</returns>
 174  /// <remarks>WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures).</remarks>
 175  public static T TangentSystem<T>(Angle<T> a)
 0176  {
 0177    T b = a[Angle.Units.Radians];
 0178    double c = Convert<T, double>(b);
 0179    double d = Math.Tan(c);
 0180    T e = Convert<double, T>(d);
 0181    return e;
 0182  }
 183
 184  /// <summary>Estimates the tangent ratio using piecewise quadratic equations. Fast but NOT very accurate.</summary>
 185  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 186  /// <param name="a">The angle to compute the quadratic estimated tangent ratio of.</param>
 187  /// <returns>The quadratic estimation of the tangent ratio of the provided angle.</returns>
 188  public static T TangentQuadratic<T>(Angle<T> a)
 0189  {
 0190    return Division(SineQuadratic(a), CosineQuadratic(a));
 0191  }
 192
 193  #endregion
 194
 195  #region Cosecant
 196
 197  /// <summary>Computes the cosecant ratio of an angle using the system's sine function. WARNING! CONVERSION TO/FROM DOU
 198  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 199  /// <param name="a">The angle to compute the cosecant ratio of.</param>
 200  /// <returns>The cosecant ratio of the provided angle.</returns>
 201  /// <remarks>WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures).</remarks>
 202  public static T CosecantSystem<T>(Angle<T> a)
 0203  {
 0204    return Division(Constant<T>.One, SineSystem(a));
 0205  }
 206
 207  /// <summary>Estimates the cosecant ratio using piecewise quadratic equations. Fast but NOT very accurate.</summary>
 208  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 209  /// <param name="a">The angle to compute the quadratic estimated cosecant ratio of.</param>
 210  /// <returns>The quadratic estimation of the cosecant ratio of the provided angle.</returns>
 211  public static T CosecantQuadratic<T>(Angle<T> a)
 0212  {
 0213    return Division(Constant<T>.One, SineQuadratic(a));
 0214  }
 215
 216  #endregion
 217
 218  #region Secant
 219
 220  /// <summary>Computes the secant ratio of an angle using the system's cosine function. WARNING! CONVERSION TO/FROM DOU
 221  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 222  /// <param name="a">The angle to compute the secant ratio of.</param>
 223  /// <returns>The secant ratio of the provided angle.</returns>
 224  /// <remarks>WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures).</remarks>
 225  public static T SecantSystem<T>(Angle<T> a)
 0226  {
 0227    return Division(Constant<T>.One, CosineSystem(a));
 0228  }
 229
 230  /// <summary>Estimates the secant ratio using piecewise quadratic equations. Fast but NOT very accurate.</summary>
 231  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 232  /// <param name="a">The angle to compute the quadratic estimated secant ratio of.</param>
 233  /// <returns>The quadratic estimation of the secant ratio of the provided angle.</returns>
 234  public static T SecantQuadratic<T>(Angle<T> a)
 0235  {
 0236    return Division(Constant<T>.One, CosineQuadratic(a));
 0237  }
 238
 239  #endregion
 240
 241  #region Cotangent
 242
 243  /// <summary>Computes the cotangent ratio of an angle using the system's tangent function. WARNING! CONVERSION TO/FROM
 244  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 245  /// <param name="a">The angle to compute the cotangent ratio of.</param>
 246  /// <returns>The cotangent ratio of the provided angle.</returns>
 247  /// <remarks>WARNING! CONVERSION TO/FROM DOUBLE (possible loss of significant figures).</remarks>
 248  public static T CotangentSystem<T>(Angle<T> a)
 0249  {
 0250    return Division(Constant<T>.One, TangentSystem(a));
 0251  }
 252
 253  /// <summary>Estimates the cotangent ratio using piecewise quadratic equations. Fast but NOT very accurate.</summary>
 254  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 255  /// <param name="a">The angle to compute the quadratic estimated cotangent ratio of.</param>
 256  /// <returns>The quadratic estimation of the cotangent ratio of the provided angle.</returns>
 257  public static T CotangentQuadratic<T>(Angle<T> a)
 0258  {
 0259    return Division(Constant<T>.One, TangentQuadratic(a));
 0260  }
 261
 262  #endregion
 263
 264  #region InverseSine
 265
 266  // public static Angle<T> InverseSine<T>(T a)
 267  // {
 268  //     return InverseSineImplementation<T>.Function(a);
 269  // }
 270
 271  // internal static class InverseSineImplementation<T>
 272  // {
 273  //     internal static Func<T, Angle<T>> Function = a =>
 274  //     {
 275  //         // optimization for specific known types
 276  //         if (TypeDescriptor.GetConverter(typeof(T)).CanConvertTo(typeof(double)))
 277  //         {
 278  //             ParameterExpression A = Expression.Parameter(typeof(T));
 279  //             Expression BODY = Expression.Call(typeof(Angle<T>).GetMethod(nameof(Angle<T>.Factory_Radians), BindingF
 280  //             Function = Expression.Lambda<Func<T, Angle<T>>>(BODY, A).Compile();
 281  //             return Function(a);
 282  //         }
 283  //         throw new NotImplementedException();
 284  //     };
 285  // }
 286
 287  #endregion
 288
 289  #region InverseCosine
 290
 291  // public static Angle<T> InverseCosine<T>(T a)
 292  // {
 293  //     return InverseCosineImplementation<T>.Function(a);
 294  // }
 295
 296  // internal static class InverseCosineImplementation<T>
 297  // {
 298  //     internal static Func<T, Angle<T>> Function = a =>
 299  //     {
 300  //         // optimization for specific known types
 301  //         if (TypeDescriptor.GetConverter(typeof(T)).CanConvertTo(typeof(double)))
 302  //         {
 303  //             ParameterExpression A = Expression.Parameter(typeof(T));
 304  //             Expression BODY = Expression.Call(typeof(Angle<T>).GetMethod(nameof(Angle<T>.Factory_Radians), BindingF
 305  //             Function = Expression.Lambda<Func<T, Angle<T>>>(BODY, A).Compile();
 306  //             return Function(a);
 307  //         }
 308  //         throw new NotImplementedException();
 309  //     };
 310  // }
 311
 312  #endregion
 313
 314  #region InverseTangent
 315
 316  // public static Angle<T> InverseTangent<T>(T a)
 317  // {
 318  //     return InverseTangentImplementation<T>.Function(a);
 319  // }
 320
 321  // internal static class InverseTangentImplementation<T>
 322  // {
 323  //     internal static Func<T, Angle<T>> Function = a =>
 324  //     {
 325  //         // optimization for specific known types
 326  //         if (TypeDescriptor.GetConverter(typeof(T)).CanConvertTo(typeof(double)))
 327  //         {
 328  //             ParameterExpression A = Expression.Parameter(typeof(T));
 329  //             Expression BODY = Expression.Call(typeof(Angle<T>).GetMethod(nameof(Angle<T>.Factory_Radians), BindingF
 330  //             Function = Expression.Lambda<Func<T, Angle<T>>>(BODY, A).Compile();
 331  //             return Function(a);
 332  //         }
 333  //         throw new NotImplementedException();
 334  //     };
 335  // }
 336
 337  #endregion
 338
 339  #region InverseCosecant
 340
 341  // public static Angle<T> InverseCosecant<T>(T a)
 342  // {
 343  //     return Angle<T>.Factory_Radians(Divide(Constant<T>.One, InverseSine(a).Radians));
 344  // }
 345
 346  #endregion
 347
 348  #region InverseSecant
 349
 350  // public static Angle<T> InverseSecant<T>(T a)
 351  // {
 352  //     return Angle<T>.Factory_Radians(Divide(Constant<T>.One, InverseCosine(a).Radians));
 353  // }
 354
 355  #endregion
 356
 357  #region InverseCotangent
 358
 359  // public static Angle<T> InverseCotangent<T>(T a)
 360  // {
 361  //     return Angle<T>.Factory_Radians(Divide(Constant<T>.One, InverseTangent(a).Radians));
 362  // }
 363
 364  #endregion
 365
 366  #region HyperbolicSine
 367
 368  // public static T HyperbolicSine<T>(Angle<T> a)
 369  // {
 370  //     return HyperbolicSineImplementation<T>.Function(a);
 371  // }
 372
 373  // internal static class HyperbolicSineImplementation<T>
 374  // {
 375  //     internal static Func<Angle<T>, T> Function = (Angle<T> a) =>
 376  //     {
 377  //         // optimization for specific known types
 378  //         if (TypeDescriptor.GetConverter(typeof(T)).CanConvertTo(typeof(double)))
 379  //         {
 380  //             ParameterExpression A = Expression.Parameter(typeof(T));
 381  //             Expression BODY = Expression.Call(typeof(Math).GetMethod(nameof(Math.Sinh)), Expression.Convert(Express
 382  //             Function = Expression.Lambda<Func<Angle<T>, T>>(BODY, A).Compile();
 383  //             return Function(a);
 384  //         }
 385  //         throw new NotImplementedException();
 386  //     };
 387  // }
 388
 389  #endregion
 390
 391  #region HyperbolicCosine
 392
 393  // public static T HyperbolicCosine<T>(Angle<T> a)
 394  // {
 395  //     return HyperbolicCosineImplementation<T>.Function(a);
 396  // }
 397
 398  // internal static class HyperbolicCosineImplementation<T>
 399  // {
 400  //     internal static Func<Angle<T>, T> Function = (Angle<T> a) =>
 401  //     {
 402  //         // optimization for specific known types
 403  //         if (TypeDescriptor.GetConverter(typeof(T)).CanConvertTo(typeof(double)))
 404  //         {
 405  //             ParameterExpression A = Expression.Parameter(typeof(T));
 406  //             Expression BODY = Expression.Call(typeof(Math).GetMethod(nameof(Math.Cosh)), Expression.Convert(Express
 407  //             Function = Expression.Lambda<Func<Angle<T>, T>>(BODY, A).Compile();
 408  //             return Function(a);
 409  //         }
 410  //         throw new NotImplementedException();
 411  //     };
 412  // }
 413
 414  #endregion
 415
 416  #region HyperbolicTangent
 417
 418  // public static T HyperbolicTangent<T>(Angle<T> a)
 419  // {
 420  //     return HyperbolicTangentImplementation<T>.Function(a);
 421  // }
 422
 423  // internal static class HyperbolicTangentImplementation<T>
 424  // {
 425  //     internal static Func<Angle<T>, T> Function = (Angle<T> a) =>
 426  //     {
 427  //         // optimization for specific known types
 428  //         if (TypeDescriptor.GetConverter(typeof(T)).CanConvertTo(typeof(double)))
 429  //         {
 430  //             ParameterExpression A = Expression.Parameter(typeof(T));
 431  //             Expression BODY = Expression.Call(typeof(Math).GetMethod(nameof(Math.Tanh)), Expression.Convert(Express
 432  //             Function = Expression.Lambda<Func<Angle<T>, T>>(BODY, A).Compile();
 433  //             return Function(a);
 434  //         }
 435  //         throw new NotImplementedException();
 436  //     };
 437  // }
 438
 439  #endregion
 440
 441  #region HyperbolicCosecant
 442
 443  // public static T HyperbolicCosecant<T>(Angle<T> a)
 444  // {
 445  //     return Divide(Constant<T>.One, HyperbolicSine(a));
 446  // }
 447
 448  #endregion
 449
 450  #region HyperbolicSecant
 451
 452  // public static T HyperbolicSecant<T>(Angle<T> a)
 453  // {
 454  //     return Divide(Constant<T>.One, HyperbolicCosine(a));
 455  // }
 456
 457  #endregion
 458
 459  #region HyperbolicCotangent
 460
 461  // public static T HyperbolicCotangent<T>(Angle<T> a)
 462  // {
 463  //     return Divide(Constant<T>.One, HyperbolicTangent(a));
 464  // }
 465
 466  #endregion
 467
 468  #region InverseHyperbolicSine
 469
 470  // public static Angle<T> InverseHyperbolicSine<T>(T a)
 471  // {
 472  //     throw new NotImplementedException();
 473  // }
 474
 475  #endregion
 476
 477  #region InverseHyperbolicCosine
 478
 479  // public static Angle<T> InverseHyperbolicCosine<T>(T a)
 480  // {
 481  //     throw new NotImplementedException();
 482  // }
 483
 484  #endregion
 485
 486  #region InverseHyperbolicTangent
 487
 488  // public static Angle<T> InverseHyperbolicTangent<T>(T a)
 489  // {
 490  //     throw new NotImplementedException();
 491  // }
 492
 493  #endregion
 494
 495  #region InverseHyperbolicCosecant
 496
 497  // public static Angle<T> InverseHyperbolicCosecant<T>(T a)
 498  // {
 499  //     throw new NotImplementedException();
 500  // }
 501
 502  #endregion
 503
 504  #region InverseHyperbolicSecant
 505
 506  // public static Angle<T> InverseHyperbolicSecant<T>(T a)
 507  // {
 508  //     throw new NotImplementedException();
 509  // }
 510
 511  #endregion
 512
 513  #region InverseHyperbolicCotangent
 514
 515  // public static Angle<T> InverseHyperbolicCotangent<T>(T a)
 516  // {
 517  //     throw new NotImplementedException();
 518  // }
 519
 520  #endregion
 521}

/home/runner/work/Towel/Towel/Sources/Towel/Statics-Tuple.cs

#LineLine coverage
 1//------------------------------------------------------------------------------
 2// <auto-generated>
 3// This code was generated from "Tools\Towel_Generating\TupleExtensionsGenerator.cs".
 4// </auto-generated>
 5//------------------------------------------------------------------------------
 6
 7namespace Towel;
 8
 9public static partial class Statics
 10{
 11  /// <summary>Gets an enumerator for a tuple.</summary>
 12  /// <param name="tuple">The tuple to get an enumerator for.</param>
 13  /// <returns>An enumerator for a tuple.</returns>
 14  public static System.Collections.Generic.IEnumerator<object> GetEnumerator(this System.Runtime.CompilerServices.ITuple
 19815  {
 673216    for (int i = 0; i < tuple.Length; i++)
 316817    {
 316818      yield return tuple[i];
 316819    }
 19820  }
 21
 22  /// <summary>Gets an enumerator for a tuple.</summary>
 23  /// <typeparam name="T">The type of values in the tuple.</typeparam>
 24  /// <param name="tuple">The tuple to get an enumerator for.</param>
 25  /// <returns>An enumerator for a tuple.</returns>
 26  public static System.Collections.Generic.IEnumerator<T> GetEnumerator<T>(this Tuple<T> tuple)
 027  {
 028    if (tuple is null) throw new ArgumentNullException(nameof(tuple));
 029    yield return tuple.Item1;
 030  }
 31
 32  /// <summary>Gets an enumerator for a tuple.</summary>
 33  /// <typeparam name="T">The type of values in the tuple.</typeparam>
 34  /// <param name="tuple">The tuple to get an enumerator for.</param>
 35  /// <returns>An enumerator for a tuple.</returns>
 36  public static System.Collections.Generic.IEnumerator<T> GetEnumerator<T>(this ValueTuple<T> tuple)
 037  {
 038    yield return tuple.Item1;
 039  }
 40
 41  /// <summary>Gets an enumerator for a tuple.</summary>
 42  /// <typeparam name="T">The type of values in the tuple.</typeparam>
 43  /// <param name="tuple">The tuple to get an enumerator for.</param>
 44  /// <returns>An enumerator for a tuple.</returns>
 45  public static System.Collections.Generic.IEnumerator<T> GetEnumerator<T>(this Tuple<T, T> tuple)
 046  {
 047    if (tuple is null) throw new ArgumentNullException(nameof(tuple));
 048    yield return tuple.Item1;
 049    yield return tuple.Item2;
 050  }
 51
 52  /// <summary>Gets an enumerator for a tuple.</summary>
 53  /// <typeparam name="T">The type of values in the tuple.</typeparam>
 54  /// <param name="tuple">The tuple to get an enumerator for.</param>
 55  /// <returns>An enumerator for a tuple.</returns>
 56  public static System.Collections.Generic.IEnumerator<T> GetEnumerator<T>(this (T, T) tuple)
 057  {
 058    yield return tuple.Item1;
 059    yield return tuple.Item2;
 060  }
 61
 62  /// <summary>Gets an enumerator for a tuple.</summary>
 63  /// <typeparam name="T">The type of values in the tuple.</typeparam>
 64  /// <param name="tuple">The tuple to get an enumerator for.</param>
 65  /// <returns>An enumerator for a tuple.</returns>
 66  public static System.Collections.Generic.IEnumerator<T> GetEnumerator<T>(this Tuple<T, T, T> tuple)
 067  {
 068    if (tuple is null) throw new ArgumentNullException(nameof(tuple));
 069    yield return tuple.Item1;
 070    yield return tuple.Item2;
 071    yield return tuple.Item3;
 072  }
 73
 74  /// <summary>Gets an enumerator for a tuple.</summary>
 75  /// <typeparam name="T">The type of values in the tuple.</typeparam>
 76  /// <param name="tuple">The tuple to get an enumerator for.</param>
 77  /// <returns>An enumerator for a tuple.</returns>
 78  public static System.Collections.Generic.IEnumerator<T> GetEnumerator<T>(this (T, T, T) tuple)
 079  {
 080    yield return tuple.Item1;
 081    yield return tuple.Item2;
 082    yield return tuple.Item3;
 083  }
 84
 85  /// <summary>Gets an enumerator for a tuple.</summary>
 86  /// <typeparam name="T">The type of values in the tuple.</typeparam>
 87  /// <param name="tuple">The tuple to get an enumerator for.</param>
 88  /// <returns>An enumerator for a tuple.</returns>
 89  public static System.Collections.Generic.IEnumerator<T> GetEnumerator<T>(this Tuple<T, T, T, T> tuple)
 090  {
 091    if (tuple is null) throw new ArgumentNullException(nameof(tuple));
 092    yield return tuple.Item1;
 093    yield return tuple.Item2;
 094    yield return tuple.Item3;
 095    yield return tuple.Item4;
 096  }
 97
 98  /// <summary>Gets an enumerator for a tuple.</summary>
 99  /// <typeparam name="T">The type of values in the tuple.</typeparam>
 100  /// <param name="tuple">The tuple to get an enumerator for.</param>
 101  /// <returns>An enumerator for a tuple.</returns>
 102  public static System.Collections.Generic.IEnumerator<T> GetEnumerator<T>(this (T, T, T, T) tuple)
 0103  {
 0104    yield return tuple.Item1;
 0105    yield return tuple.Item2;
 0106    yield return tuple.Item3;
 0107    yield return tuple.Item4;
 0108  }
 109
 110  /// <summary>Gets an enumerator for a tuple.</summary>
 111  /// <typeparam name="T">The type of values in the tuple.</typeparam>
 112  /// <param name="tuple">The tuple to get an enumerator for.</param>
 113  /// <returns>An enumerator for a tuple.</returns>
 114  public static System.Collections.Generic.IEnumerator<T> GetEnumerator<T>(this Tuple<T, T, T, T, T> tuple)
 0115  {
 0116    if (tuple is null) throw new ArgumentNullException(nameof(tuple));
 0117    yield return tuple.Item1;
 0118    yield return tuple.Item2;
 0119    yield return tuple.Item3;
 0120    yield return tuple.Item4;
 0121    yield return tuple.Item5;
 0122  }
 123
 124  /// <summary>Gets an enumerator for a tuple.</summary>
 125  /// <typeparam name="T">The type of values in the tuple.</typeparam>
 126  /// <param name="tuple">The tuple to get an enumerator for.</param>
 127  /// <returns>An enumerator for a tuple.</returns>
 128  public static System.Collections.Generic.IEnumerator<T> GetEnumerator<T>(this (T, T, T, T, T) tuple)
 0129  {
 0130    yield return tuple.Item1;
 0131    yield return tuple.Item2;
 0132    yield return tuple.Item3;
 0133    yield return tuple.Item4;
 0134    yield return tuple.Item5;
 0135  }
 136
 137  /// <summary>Gets an enumerator for a tuple.</summary>
 138  /// <typeparam name="T">The type of values in the tuple.</typeparam>
 139  /// <param name="tuple">The tuple to get an enumerator for.</param>
 140  /// <returns>An enumerator for a tuple.</returns>
 141  public static System.Collections.Generic.IEnumerator<T> GetEnumerator<T>(this Tuple<T, T, T, T, T, T> tuple)
 0142  {
 0143    if (tuple is null) throw new ArgumentNullException(nameof(tuple));
 0144    yield return tuple.Item1;
 0145    yield return tuple.Item2;
 0146    yield return tuple.Item3;
 0147    yield return tuple.Item4;
 0148    yield return tuple.Item5;
 0149    yield return tuple.Item6;
 0150  }
 151
 152  /// <summary>Gets an enumerator for a tuple.</summary>
 153  /// <typeparam name="T">The type of values in the tuple.</typeparam>
 154  /// <param name="tuple">The tuple to get an enumerator for.</param>
 155  /// <returns>An enumerator for a tuple.</returns>
 156  public static System.Collections.Generic.IEnumerator<T> GetEnumerator<T>(this (T, T, T, T, T, T) tuple)
 0157  {
 0158    yield return tuple.Item1;
 0159    yield return tuple.Item2;
 0160    yield return tuple.Item3;
 0161    yield return tuple.Item4;
 0162    yield return tuple.Item5;
 0163    yield return tuple.Item6;
 0164  }
 165
 166  /// <summary>Gets an enumerator for a tuple.</summary>
 167  /// <typeparam name="T">The type of values in the tuple.</typeparam>
 168  /// <param name="tuple">The tuple to get an enumerator for.</param>
 169  /// <returns>An enumerator for a tuple.</returns>
 170  public static System.Collections.Generic.IEnumerator<T> GetEnumerator<T>(this Tuple<T, T, T, T, T, T, T> tuple)
 0171  {
 0172    if (tuple is null) throw new ArgumentNullException(nameof(tuple));
 0173    yield return tuple.Item1;
 0174    yield return tuple.Item2;
 0175    yield return tuple.Item3;
 0176    yield return tuple.Item4;
 0177    yield return tuple.Item5;
 0178    yield return tuple.Item6;
 0179    yield return tuple.Item7;
 0180  }
 181
 182  /// <summary>Gets an enumerator for a tuple.</summary>
 183  /// <typeparam name="T">The type of values in the tuple.</typeparam>
 184  /// <param name="tuple">The tuple to get an enumerator for.</param>
 185  /// <returns>An enumerator for a tuple.</returns>
 186  public static System.Collections.Generic.IEnumerator<T> GetEnumerator<T>(this (T, T, T, T, T, T, T) tuple)
 0187  {
 0188    yield return tuple.Item1;
 0189    yield return tuple.Item2;
 0190    yield return tuple.Item3;
 0191    yield return tuple.Item4;
 0192    yield return tuple.Item5;
 0193    yield return tuple.Item6;
 0194    yield return tuple.Item7;
 0195  }
 196
 197}

/home/runner/work/Towel/Towel/Sources/Towel/Statics.cs

#LineLine coverage
 1using System.ComponentModel;
 2using System.IO;
 3using System.Linq.Expressions;
 4using System.Reflection;
 5using System.Runtime.CompilerServices;
 6
 7namespace Towel;
 8
 9/// <summary>Root type of the static functional methods in Towel.</summary>
 10public static partial class Statics
 11{
 12  #region Internals
 13
 14  #region Constants
 15
 16  /// <summary>Related: https://github.com/dotnet/roslyn/issues/49568</summary>
 17  internal const string NotIntended = "This member is not intended to be used.";
 18
 19  /// <summary>The max <see cref="byte"/>s to stackalloc.</summary>
 20  internal const int Stackalloc = 256;
 21
 22  #endregion
 23
 24  #region Optimizations
 25
 26  // These are some shared internal optimizations that I don't want to expose because it might confuse people.
 27  // If you need to use it, just copy this code into your own project.
 28
 29  internal static class MultiplyAddImplementation<T>
 30  {
 31    /// <summary>a * b + c</summary>
 532    internal static Func<T, T, T, T> Function = (a, b, c) =>
 533    {
 534      var A = Expression.Parameter(typeof(T));
 535      var B = Expression.Parameter(typeof(T));
 536      var C = Expression.Parameter(typeof(T));
 537      var BODY = Expression.Add(Expression.Multiply(A, B), C);
 538      Function = Expression.Lambda<Func<T, T, T, T>>(BODY, A, B, C).Compile();
 539      return Function(a, b, c);
 1040    };
 41  }
 42
 43  internal static class D_subtract_A_multiply_B_divide_C<T>
 44  {
 45    /// <summary>d - a * b / c</summary>
 446    internal static Func<T, T, T, T, T> Function = (a, b, c, d) =>
 447    {
 448      var A = Expression.Parameter(typeof(T));
 449      var B = Expression.Parameter(typeof(T));
 450      var C = Expression.Parameter(typeof(T));
 451      var D = Expression.Parameter(typeof(T));
 452      var BODY = Expression.Subtract(D, Expression.Divide(Expression.Multiply(A, B), C));
 453      Function = Expression.Lambda<Func<T, T, T, T, T>>(BODY, A, B, C, D).Compile();
 454      return Function(a, b, c, d);
 855    };
 56  }
 57
 58  #endregion
 59
 60  #region Helpers
 61
 62  internal static T OperationOnStepper<T>(Action<Action<T>> stepper, Func<T, T, T> operation)
 4463  {
 4464    if (stepper is null) throw new ArgumentNullException(nameof(stepper));
 4465    T? result = default;
 4466    bool assigned = false;
 4467    stepper(a =>
 13268    {
 13269      if (assigned)
 8870      {
 8871        result = operation(result!, a);
 8872      }
 4473      else
 4474      {
 4475        result = a;
 4476        assigned = true;
 4477      }
 17678    });
 4479    return assigned
 4480      ? result!
 4481      : throw new ArgumentException($"{nameof(stepper)} is empty.", nameof(stepper));
 4482  }
 83
 84  #endregion
 85
 86  #endregion
 87
 88  #region Swap
 89
 90  /// <summary>Swaps two values.</summary>
 91  /// <typeparam name="T">The type of values to swap.</typeparam>
 92  /// <param name="a">The first value of the swap.</param>
 93  /// <param name="b">The second value of the swap.</param>
 1238070194  public static void Swap<T>(ref T a, ref T b) => (a, b) = (b, a);
 95
 96  /// <summary>Swaps two values.</summary>
 97  /// <typeparam name="T">The type of values to swap.</typeparam>
 98  /// <typeparam name="TGet">The type of the get method.</typeparam>
 99  /// <typeparam name="TSet">The type of the set method.</typeparam>
 100  /// <param name="a">The index of the first value to swap.</param>
 101  /// <param name="b">The index of the second value to swap.</param>
 102  /// <param name="get">The the get method.</param>
 103  /// <param name="set">The the set method.</param>
 104  public static void Swap<T, TGet, TSet>(int a, int b, TGet get, TSet set)
 105    where TGet : struct, IFunc<int, T>
 106    where TSet : struct, IAction<int, T>
 15641297107  {
 15641297108    T temp = get.Invoke(a);
 15641297109    set.Invoke(a, get.Invoke(b));
 15641297110    set.Invoke(b, temp);
 15641297111  }
 112
 113  #endregion
 114
 115  #region source...
 116
 117#pragma warning disable IDE1006 // Naming Styles
 118
 119  /// <summary>Gets the directory path of the current location in source code.</summary>
 120  /// <param name="default">Intended to leave default. This value is set by the compiler via <see cref="CallerFilePathAt
 121  /// <returns>The directory path of the current location in source code.</returns>
 0122  public static string? sourcedirectory([CallerFilePath] string @default = default!) => Path.GetDirectoryName(@default);
 123
 124  /// <summary>Gets the file path of the current location in source code.</summary>
 125  /// <param name="default">Intended to leave default. This value is set by the compiler via <see cref="CallerFilePathAt
 126  /// <returns>The file path of the current location in source code.</returns>
 1127  public static string sourcefilepath([CallerFilePath] string @default = default!) => @default;
 128
 129  /// <summary>Gets the member name of the current location in source code.</summary>
 130  /// <param name="default">Intended to leave default. This value is set by the compiler via <see cref="CallerMemberName
 131  /// <returns>The member name of the current location in source code.</returns>
 1132  public static string sourcemembername([CallerMemberName] string @default = default!) => @default;
 133
 134  /// <summary>Gets the line number of the current location in source code.</summary>
 135  /// <param name="default">Intended to leave default. This value is set by the compiler via <see cref="CallerLineNumber
 136  /// <returns>The line number of the current location in source code.</returns>
 599137  public static int sourcelinenumber([CallerLineNumber] int @default = default) => @default;
 138
 139  /// <summary>Gets the source code and evaluation of an expression.</summary>
 140  /// <typeparam name="T">The type the expression will evaluate to.</typeparam>
 141  /// <param name="expression">The expression to evaluate and get the source of.</param>
 142  /// <param name="default">Intended to leave default. This value is set by the compiler via <see cref="CallerArgumentEx
 143  /// <returns>The source code and evaluation of the expression.</returns>
 1144  public static (T Value, string Source) sourceof<T>(T expression, [CallerArgumentExpression("expression")] string? @def
 145
 146  /// <summary>Gets the source code and evaluation of an expression.</summary>
 147  /// <typeparam name="T">The type the expression will evaluate to.</typeparam>
 148  /// <param name="expression">The expression to evaluate and get the source of.</param>
 149  /// <param name="source">The source code of the expression.</param>
 150  /// <param name="default">Intended to leave default. This value is set by the compiler via <see cref="CallerArgumentEx
 151  /// <returns>The evaluation of the expression.</returns>
 152  public static T sourceof<T>(T expression, out string source, [CallerArgumentExpression("expression")] string? @default
 121931153  {
 121931154    source = @default!;
 121931155    return expression;
 121931156  }
 157
 158#pragma warning restore IDE1006 // Naming Styles
 159
 160  #endregion
 161
 162  #region TryParse
 163
 164  /// <summary>Tries to parse a <see cref="string"/> into a value of the type <typeparamref name="T"/>.</summary>
 165  /// <typeparam name="T">The type to parse the <see cref="string"/> into a value of.</typeparam>
 166  /// <param name="string">The <see cref="string"/> to parse into a value ot type <typeparamref name="T"/>.</param>
 167  /// <returns>
 168  /// - <see cref="bool"/> Success: true if the parse was successful or false if not<br/>
 169  /// - <typeparamref name="T"/> Value: the value if the parse was successful or default if not
 170  /// </returns>
 171  public static (bool Success, T? Value) TryParse<T>(string @string) =>
 157172    (TryParseImplementation<T>.Function(@string, out T? value), value);
 173
 174  internal static class TryParseImplementation<T>
 175  {
 176    internal delegate TResult TryParse<T1, T2, TResult>(T1 arg1, out T2? arg2);
 177
 6178    internal static TryParse<string, T, bool> Function = (string @string, out T? value) =>
 6179    {
 6180      static bool Fail(string @string, out T? value)
 0181      {
 0182        value = default;
 0183        return false;
 0184      }
 6185      if (typeof(T).IsEnum)
 2186      {
 124187        foreach (MethodInfo methodInfo in typeof(Enum).GetMethods(
 2188          BindingFlags.Static |
 2189          BindingFlags.Public))
 60190        {
 60191          if (methodInfo.Name == nameof(Enum.TryParse) &&
 60192            methodInfo.IsGenericMethod &&
 60193            methodInfo.IsStatic &&
 60194            methodInfo.IsPublic &&
 60195            methodInfo.ReturnType == typeof(bool))
 2196          {
 2197            MethodInfo genericMethodInfo = methodInfo.MakeGenericMethod(typeof(T));
 2198            ParameterInfo[] parameters = genericMethodInfo.GetParameters();
 2199            if (parameters.Length is 2 &&
 2200              parameters[0].ParameterType == typeof(string) &&
 2201              parameters[1].ParameterType == typeof(T).MakeByRefType())
 2202            {
 2203              Function = genericMethodInfo.CreateDelegate<TryParse<string, T, bool>>();
 2204              return Function(@string, out value);
 6205            }
 0206          }
 58207        }
 0208        throw new TowelBugException("The System.Enum.TryParse method was not found via reflection.");
 6209      }
 6210      else
 4211      {
 4212        MethodInfo? methodInfo = Meta.GetTryParseMethod<T>();
 4213        Function = methodInfo is null
 4214          ? Fail
 4215          : methodInfo.CreateDelegate<TryParse<string, T, bool>>();
 4216        return Function(@string, out value);
 6217      }
 12218    };
 219  }
 220
 221  #endregion
 222
 223  #region Hash
 224
 225  /// <summary>Static wrapper for the instance based "object.GetHashCode" function.</summary>
 226  /// <typeparam name="T">The generic type of the hash operation.</typeparam>
 227  /// <param name="value">The item to get the hash code of.</param>
 228  /// <returns>The computed hash code using the base GetHashCode instance method.</returns>
 229  public static int Hash<T>(T value)
 8125808230  {
 8125808231    if (value is null) throw new ArgumentNullException(nameof(value));
 8125808232    return value.GetHashCode();
 8125808233  }
 234
 235  #endregion
 236
 237  #region Convert
 238
 239  /// <summary>Converts <paramref name="a"/> from <typeparamref name="TA"/> to <typeparamref name="TB"/>.</summary>
 240  /// <typeparam name="TA">The type of the value to convert.</typeparam>
 241  /// <typeparam name="TB">The type to convert the value to.</typeparam>
 242  /// <param name="a">The value to convert.</param>
 243  /// <returns>The <paramref name="a"/> value of <typeparamref name="TB"/> type.</returns>
 244  public static TB Convert<TA, TB>(TA a) =>
 5797245    ConvertImplementation<TA, TB>.Function(a);
 246
 247  internal static class ConvertImplementation<TA, TB>
 248  {
 18249    internal static Func<TA, TB> Function = a =>
 18250    {
 18251      ParameterExpression A = Expression.Parameter(typeof(TA));
 18252      Expression BODY = Expression.Convert(A, typeof(TB));
 18253      Function = Expression.Lambda<Func<TA, TB>>(BODY, A).Compile();
 18254      return Function(a);
 36255    };
 256  }
 257
 258  #endregion
 259
 260  #region Join
 261
 262  /// <summary>Iterates a <see cref="System.Range"/> and joins the results of a System.Func&lt;int, string&gt; seperated
 263  /// <param name="range">The range of values to use use on the &lt;System.Func{int, string&gt; <paramref name="func"/>.
 264  /// <param name="func">The System.Func&lt;int, string&gt;.</param>
 265  /// <param name="seperator">The <see cref="string"/> seperator to join the values with.</param>
 266  /// <returns>The resulting <see cref="string"/> of the join.</returns>
 267  public static string Join(Range range, Func<int, string> func, string seperator) =>
 0268    string.Join(seperator, range.ToIEnumerable().Select(func));
 269
 270  #endregion
 271
 272  #region Equate
 273
 274#if false
 275    /// <summary>Checks for equality of two values [<paramref name="a"/> == <paramref name="b"/>].</summary>
 276    /// <typeparam name="A">The type of the left operand.</typeparam>
 277    /// <typeparam name="B">The type of the right operand.</typeparam>
 278    /// <typeparam name="C">The type of the return.</typeparam>
 279    /// <param name="a">The left operand.</param>
 280    /// <param name="b">The right operand.</param>
 281    /// <returns>The result of the equality.</returns>
 282    public static C Equate<A, B, C>(A a, B b) =>
 283      EquateImplementation<A, B, C>.Function(a, b);
 284#endif
 285
 286  /// <summary>Checks for equality of two values [<paramref name="a"/> == <paramref name="b"/>].</summary>
 287  /// <typeparam name="T">The type of the operation.</typeparam>
 288  /// <param name="a">The left operand.</param>
 289  /// <param name="b">The right operand.</param>
 290  /// <returns>The result of the equality check.</returns>
 291  public static bool Equate<T>(T a, T b) =>
 6980773292    EquateImplementation<T, T, bool>.Function(a, b);
 293
 294  /// <summary>Checks for equality among multiple values [<paramref name="a"/> == <paramref name="b"/> == <paramref name
 295  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 296  /// <param name="a">The first operand of the equality check.</param>
 297  /// <param name="b">The second operand of the equality check.</param>
 298  /// <param name="c">The remaining operands of the equality check.</param>
 299  /// <returns>True if all operands are equal or false if not.</returns>
 300  public static bool Equate<T>(T a, T b, params T[] c)
 12301  {
 12302    if (c is null) throw new ArgumentNullException(nameof(c));
 12303    if (c.Length is 0) throw new ArgumentException("The array is empty.", nameof(c));
 12304    if (!Equate(a, b))
 6305    {
 6306      return false;
 307    }
 18308    for (int i = 0; i < c.Length; i++)
 6309    {
 6310      if (!Equate(a, c[i]))
 3311      {
 3312        return false;
 313      }
 3314    }
 3315    return true;
 12316  }
 317
 318  internal static class EquateImplementation<TA, TB, TC>
 319  {
 13320    internal static Func<TA, TB, TC> Function = (a, b) =>
 13321    {
 13322#warning TODO: kill this try catch
 13323      try
 13324      {
 13325        var A = Expression.Parameter(typeof(TA));
 13326        var B = Expression.Parameter(typeof(TB));
 13327        var BODY = Expression.Equal(A, B);
 9328        Function = Expression.Lambda<Func<TA, TB, TC>>(BODY, A, B).Compile();
 9329        return Function(a, b);
 13330      }
 4331      catch
 4332      {
 13333
 4334      }
 13335
 4336      if (typeof(TC) == typeof(bool))
 4337      {
 4338        EquateImplementation<TA, TB, bool>.Function =
 4339          (typeof(TA).IsValueType, typeof(TB).IsValueType) switch
 4340          {
 129341            (true,   true) => (A, B) => A!.Equals(B),
 0342            (true,  false) => (A, B) => A!.Equals(B),
 0343            (false,  true) => (A, B) => B!.Equals(A),
 4344            (false, false) =>
 0345              (A, B) =>
 0346                (A, B) switch
 0347                {
 0348                  (null, null) => true,
 0349                  (_,    null) => false,
 0350                  (null,    _) => false,
 0351                  _            => A.Equals(B),
 0352                },
 4353          };
 4354        return Function!(a, b);
 13355      }
 13356#warning TODO
 0357      throw new NotImplementedException();
 26358    };
 359  }
 360
 361  #endregion
 362
 363  #region Inequate
 364
 365  /// <summary>Checks for inequality of two values [<paramref name="a"/> != <paramref name="b"/>].</summary>
 366  /// <typeparam name="TA">The type of the left operand.</typeparam>
 367  /// <typeparam name="TB">The type of the right operand.</typeparam>
 368  /// <typeparam name="TC">The type of the return.</typeparam>
 369  /// <param name="a">The left operand.</param>
 370  /// <param name="b">The right operand.</param>
 371  /// <returns>The result of the inequality.</returns>
 372  public static TC Inequate<TA, TB, TC>(TA a, TB b) =>
 1188373    InequateImplementation<TA, TB, TC>.Function(a, b);
 374
 375  /// <summary>Checks for inequality of two values [<paramref name="a"/> != <paramref name="b"/>].</summary>
 376  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 377  /// <param name="a">The first operand of the inequality check.</param>
 378  /// <param name="b">The second operand of the inequality check.</param>
 379  /// <returns>The result of the inequality check.</returns>
 380  public static bool Inequate<T>(T a, T b) =>
 1188381    Inequate<T, T, bool>(a, b);
 382
 383  internal static class InequateImplementation<TA, TB, TC>
 384  {
 4385    internal static Func<TA, TB, TC> Function = (a, b) =>
 4386    {
 4387      var A = Expression.Parameter(typeof(TA));
 4388      var B = Expression.Parameter(typeof(TB));
 4389      var BODY = Expression.NotEqual(A, B);
 4390      Function = Expression.Lambda<Func<TA, TB, TC>>(BODY, A, B).Compile();
 4391      return Function(a, b);
 8392    };
 393  }
 394
 395  #endregion
 396
 397  #region LessThan
 398
 399  /// <summary>Checks if one value is less than another [<paramref name="a"/> &lt; <paramref name="b"/>].</summary>
 400  /// <typeparam name="TA">The type of the left operand.</typeparam>
 401  /// <typeparam name="TB">The type of the right operand.</typeparam>
 402  /// <typeparam name="TC">The type of the return.</typeparam>
 403  /// <param name="a">The left operand.</param>
 404  /// <param name="b">The right operand.</param>
 405  /// <returns>The result of the less than operation.</returns>
 406  public static TC LessThan<TA, TB, TC>(TA a, TB b) =>
 208068407    LessThanImplementation<TA, TB, TC>.Function(a, b);
 408
 409  /// <summary>Checks if one value is less than another [<paramref name="a"/> &lt; <paramref name="b"/>].</summary>
 410  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 411  /// <param name="a">The first operand of the less than check.</param>
 412  /// <param name="b">The second operand of the less than check.</param>
 413  /// <returns>The result of the less than check.</returns>
 414  public static bool LessThan<T>(T a, T b) =>
 208068415    LessThan<T, T, bool>(a, b);
 416
 417  internal static class LessThanImplementation<TA, TB, TC>
 418  {
 8419    internal static Func<TA, TB, TC> Function = (a, b) =>
 8420    {
 8421      var A = Expression.Parameter(typeof(TA));
 8422      var B = Expression.Parameter(typeof(TB));
 8423      var BODY = Expression.LessThan(A, B);
 8424      Function = Expression.Lambda<Func<TA, TB, TC>>(BODY, A, B).Compile();
 8425      return Function(a, b);
 16426    };
 427  }
 428
 429  #endregion
 430
 431  #region GreaterThan
 432
 433  /// <summary>Checks if one value is greater than another [<paramref name="a"/> &gt; <paramref name="b"/>].</summary>
 434  /// <typeparam name="TA">The type of the left operand.</typeparam>
 435  /// <typeparam name="TB">The type of the right operand.</typeparam>
 436  /// <typeparam name="TC">The type of the return.</typeparam>
 437  /// <param name="a">The left operand.</param>
 438  /// <param name="b">The right operand.</param>
 439  /// <returns>The result of the greater than operation.</returns>
 440  public static TC GreaterThan<TA, TB, TC>(TA a, TB b) =>
 757441    GreaterThanImplementation<TA, TB, TC>.Function(a, b);
 442
 443  /// <summary>Checks if one value is greater than another [<paramref name="a"/> &gt; <paramref name="b"/>].</summary>
 444  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 445  /// <param name="a">The first operand of the greater than check.</param>
 446  /// <param name="b">The second operand of the greater than check.</param>
 447  /// <returns>The result of the greater than check.</returns>
 448  public static bool GreaterThan<T>(T a, T b) =>
 757449    GreaterThan<T, T, bool>(a, b);
 450
 451  internal static class GreaterThanImplementation<TA, TB, TC>
 452  {
 8453    internal static Func<TA, TB, TC> Function = (a, b) =>
 8454    {
 8455      var A = Expression.Parameter(typeof(TA));
 8456      var B = Expression.Parameter(typeof(TB));
 8457      var BODY = Expression.GreaterThan(A, B);
 8458      Function = Expression.Lambda<Func<TA, TB, TC>>(BODY, A, B).Compile();
 8459      return Function(a, b);
 16460    };
 461  }
 462
 463  #endregion
 464
 465  #region LessThanOrEqual
 466
 467  /// <summary>Checks if one value is less than or equal to another [<paramref name="a"/> &lt;= <paramref name="b"/>].</
 468  /// <typeparam name="TA">The type of the left operand.</typeparam>
 469  /// <typeparam name="TB">The type of the right operand.</typeparam>
 470  /// <typeparam name="TC">The type of the return.</typeparam>
 471  /// <param name="a">The left operand.</param>
 472  /// <param name="b">The right operand.</param>
 473  /// <returns>The result of the less than or equal to operation.</returns>
 474  public static TC LessThanOrEqual<TA, TB, TC>(TA a, TB b) =>
 1439782475    LessThanOrEqualImplementation<TA, TB, TC>.Function(a, b);
 476
 477  /// <summary>Checks if one value is less than or equal to another [<paramref name="a"/> &lt;= <paramref name="b"/>].</
 478  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 479  /// <param name="a">The first operand of the less than or equal to check.</param>
 480  /// <param name="b">The second operand of the less than or equal to check.</param>
 481  /// <returns>The result of the less than or equal to check.</returns>
 482  public static bool LessThanOrEqual<T>(T a, T b) =>
 1439782483    LessThanOrEqual<T, T, bool>(a, b);
 484
 485  internal static class LessThanOrEqualImplementation<TA, TB, TC>
 486  {
 4487    internal static Func<TA, TB, TC> Function = (a, b) =>
 4488    {
 4489      var A = Expression.Parameter(typeof(TA));
 4490      var B = Expression.Parameter(typeof(TB));
 4491      var BODY = Expression.LessThanOrEqual(A, B);
 4492      Function = Expression.Lambda<Func<TA, TB, TC>>(BODY, A, B).Compile();
 4493      return Function(a, b);
 8494    };
 495  }
 496
 497  #endregion
 498
 499  #region GreaterThanOrEqual
 500
 501  /// <summary>Checks if one value is less greater or equal to another [<paramref name="a"/> &gt;= <paramref name="b"/>]
 502  /// <typeparam name="TA">The type of the left operand.</typeparam>
 503  /// <typeparam name="TB">The type of the right operand.</typeparam>
 504  /// <typeparam name="TC">The type of the return.</typeparam>
 505  /// <param name="a">The left operand.</param>
 506  /// <param name="b">The right operand.</param>
 507  /// <returns>The result of the greater than or equal to operation.</returns>
 508  public static TC GreaterThanOrEqual<TA, TB, TC>(TA a, TB b) =>
 24509    GreaterThanOrEqualImplementation<TA, TB, TC>.Function(a, b);
 510
 511  /// <summary>Checks if one value is greater than or equal to another [<paramref name="a"/> &gt;= <paramref name="b"/>]
 512  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 513  /// <param name="a">The first operand of the greater than or equal to check.</param>
 514  /// <param name="b">The second operand of the greater than or equal to check.</param>
 515  /// <returns>The result of the greater than or equal to check.</returns>
 516  public static bool GreaterThanOrEqual<T>(T a, T b) =>
 24517    GreaterThanOrEqual<T, T, bool>(a, b);
 518
 519  internal static class GreaterThanOrEqualImplementation<TA, TB, TC>
 520  {
 4521    internal static Func<TA, TB, TC> Function = (a, b) =>
 4522    {
 4523      var A = Expression.Parameter(typeof(TA));
 4524      var B = Expression.Parameter(typeof(TB));
 4525      var BODY = Expression.GreaterThanOrEqual(A, B);
 4526      Function = Expression.Lambda<Func<TA, TB, TC>>(BODY, A, B).Compile();
 4527      return Function(a, b);
 8528    };
 529  }
 530
 531  #endregion
 532
 533  #region Compare
 534
 535#if false
 536    /// <summary>Compares two values.</summary>
 537    /// <typeparam name="A">The type of the left operand.</typeparam>
 538    /// <typeparam name="B">The type of the right operand.</typeparam>
 539    /// <param name="a">The left operand.</param>
 540    /// <param name="b">The right operand.</param>
 541    /// <returns>The result of the comparison.</returns>
 542    public static C Compare<A, B, C>(A a, B b) =>
 543      CompareImplementation<A, B, C>.Function(a, b);
 544#endif
 545
 546  /// <summary>Compares two values.</summary>
 547  /// <typeparam name="T">The type of values to compare.</typeparam>
 548  /// <param name="a">The first value of the comparison.</param>
 549  /// <param name="b">The second value of the comparison.</param>
 550  /// <returns>The result of the comparison.</returns>
 551  public static CompareResult Compare<T>(T a, T b) =>
 864393975552    CompareImplementation<T, T, CompareResult>.Function(a, b);
 553
 554  internal static class CompareImplementation<TA, TB, TC>
 555  {
 7556    internal static Func<TA, TB, TC> Function = (a, b) =>
 7557    {
 7558      if (typeof(TC) == typeof(CompareResult))
 7559      {
 7560        if (typeof(TA) == typeof(TB) && a is IComparable<TB> &&
 7561          !(typeof(TA).IsPrimitive && typeof(TB).IsPrimitive))
 3562        {
 3563          CompareImplementation<TA, TA, CompareResult>.Function =
 2388564            (a, b) => System.Collections.Generic.Comparer<TA>.Default.Compare(a, b).ToCompareResult();
 3565        }
 7566        else
 4567        {
 4568          var A = Expression.Parameter(typeof(TA));
 4569          var B = Expression.Parameter(typeof(TB));
 7570
 4571          var lessThanPredicate =
 4572            typeof(TA).IsPrimitive && typeof(TB).IsPrimitive
 4573            ? Expression.LessThan(A, B)
 4574            : Meta.GetLessThanMethod<TA, TB, bool>() is not null
 4575              ? Expression.LessThan(A, B)
 4576              : Meta.GetGreaterThanMethod<TB, TA, bool>() is not null
 4577                ? Expression.GreaterThan(B, A)
 4578                : null;
 7579
 4580          var greaterThanPredicate =
 4581            typeof(TA).IsPrimitive && typeof(TB).IsPrimitive
 4582            ? Expression.GreaterThan(A, B)
 4583            : Meta.GetGreaterThanMethod<TA, TB, bool>() is not null
 4584              ? Expression.GreaterThan(A, B)
 4585              : Meta.GetLessThanMethod<TB, TA, bool>() is not null
 4586                ? Expression.LessThan(B, A)
 4587                : null;
 7588
 4589          if (lessThanPredicate is null || greaterThanPredicate is null)
 0590          {
 0591            throw new NotSupportedException("You attempted a comparison operation with unsupported types.");
 7592          }
 7593
 4594          var RETURN = Expression.Label(typeof(CompareResult));
 4595          var BODY = Expression.Block(
 4596            Expression.IfThen(
 4597              lessThanPredicate,
 4598              Expression.Return(RETURN, Expression.Constant(Less, typeof(CompareResult)))),
 4599            Expression.IfThen(
 4600              greaterThanPredicate,
 4601              Expression.Return(RETURN, Expression.Constant(Greater, typeof(CompareResult)))),
 4602            Expression.Return(RETURN, Expression.Constant(Equal, typeof(CompareResult))),
 4603            Expression.Label(RETURN, Expression.Constant(default(CompareResult), typeof(CompareResult))));
 4604          CompareImplementation<TA, TB, CompareResult>.Function = Expression.Lambda<Func<TA, TB, CompareResult>>(BODY, A
 4605        }
 7606        return Function!(a, b);
 7607      }
 7608#warning TODO
 0609      throw new NotImplementedException();
 14610    };
 611  }
 612
 613  #endregion
 614
 615  #region Negation
 616
 617  /// <summary>Negates a value [-<paramref name="a"/>].</summary>
 618  /// <typeparam name="TA">The type of the value to negate.</typeparam>
 619  /// <typeparam name="TB">The resulting type of the negation.</typeparam>
 620  /// <param name="a">The value to negate.</param>
 621  /// <returns>The result of the negation [-<paramref name="a"/>].</returns>
 622  public static TB Negation<TA, TB>(TA a) =>
 923623    NegationImplementation<TA, TB>.Function(a);
 624
 625  /// <summary>Negates a value [-<paramref name="a"/>].</summary>
 626  /// <typeparam name="T">The type of the value to negate.</typeparam>
 627  /// <param name="a">The value to negate.</param>
 628  /// <returns>The result of the negation [-<paramref name="a"/>].</returns>
 629  public static T Negation<T>(T a) =>
 923630    Negation<T, T>(a);
 631
 632  internal static class NegationImplementation<TA, TB>
 633  {
 8634    internal static Func<TA, TB> Function = a =>
 8635    {
 8636      var A = Expression.Parameter(typeof(TA));
 8637      var BODY = Expression.Negate(A);
 8638      Function = Expression.Lambda<Func<TA, TB>>(BODY, A).Compile();
 8639      return Function(a);
 16640    };
 641  }
 642
 643  #endregion
 644
 645  #region Addition
 646
 647  /// <summary>Adds two values [<paramref name="a"/> + <paramref name="b"/>].</summary>
 648  /// <typeparam name="TA">The type of the left operand.</typeparam>
 649  /// <typeparam name="TB">The type of the right operand.</typeparam>
 650  /// <typeparam name="TC">The type of the return.</typeparam>
 651  /// <param name="a">The left operand.</param>
 652  /// <param name="b">The right operand.</param>
 653  /// <returns>The result of the addition [<paramref name="a"/> + <paramref name="b"/>].</returns>
 654  public static TC Addition<TA, TB, TC>(TA a, TB b) =>
 1317332655    AdditionImplementation<TA, TB, TC>.Function(a, b);
 656
 657  /// <summary>Adds two values [<paramref name="a"/> + <paramref name="b"/>].</summary>
 658  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 659  /// <param name="a">The left operand.</param>
 660  /// <param name="b">The right operand.</param>
 661  /// <returns>The result of the addition [<paramref name="a"/> + <paramref name="b"/>].</returns>
 662  public static T Addition<T>(T a, T b) =>
 1317332663    Addition<T, T, T>(a, b);
 664
 665  /// <summary>Adds multiple values [<paramref name="a"/> + <paramref name="b"/> + <paramref name="c"/> + ...].</summary
 666  /// <typeparam name="T">The type of the operation.</typeparam>
 667  /// <param name="a">The first operand of the addition.</param>
 668  /// <param name="b">The second operand of the addition.</param>
 669  /// <param name="c">The third operand of the addition.</param>
 670  /// <param name="d">The remaining operands of the addition.</param>
 671  /// <returns>The result of the addition [<paramref name="a"/> + <paramref name="b"/> + <paramref name="c"/> + ...].</r
 672  public static T Addition<T>(T a, T b, T c, params T[] d) =>
 56673    Addition<T>(step => { step(a); step(b); step(c); d.ToStepper()(step); });
 674
 675  /// <summary>Adds multiple values [step1 + step2 + step3 + ...].</summary>
 676  /// <typeparam name="T">The type of the operation.</typeparam>
 677  /// <param name="stepper">The stepper of the values to add.</param>
 678  /// <returns>The result of the addition [step1 + step2 + step3 + ...].</returns>
 679  public static T Addition<T>(Action<Action<T>> stepper) =>
 12680    OperationOnStepper(stepper, Addition);
 681
 682  internal static class AdditionImplementation<TA, TB, TC>
 683  {
 4684    internal static Func<TA, TB, TC> Function = (a, b) =>
 4685    {
 4686      var A = Expression.Parameter(typeof(TA));
 4687      var B = Expression.Parameter(typeof(TB));
 4688      var BODY = Expression.Add(A, B);
 4689      Function = Expression.Lambda<Func<TA, TB, TC>>(BODY, A, B).Compile();
 4690      return Function(a, b);
 8691    };
 692  }
 693
 694  #endregion
 695
 696  #region Subtraction
 697
 698  /// <summary>Subtracts two values [<paramref name="a"/> - <paramref name="b"/>].</summary>
 699  /// <typeparam name="TA">The type of the left operand.</typeparam>
 700  /// <typeparam name="TB">The type of the right operand.</typeparam>
 701  /// <typeparam name="TC">The type of the return.</typeparam>
 702  /// <param name="a">The left operand.</param>
 703  /// <param name="b">The right operand.</param>
 704  /// <returns>The result of the subtraction [<paramref name="a"/> - <paramref name="b"/>].</returns>
 705  public static TC Subtraction<TA, TB, TC>(TA a, TB b) =>
 880706    SubtractionImplementation<TA, TB, TC>.Function(a, b);
 707
 708  /// <summary>Subtracts two values [<paramref name="a"/> - <paramref name="b"/>].</summary>
 709  /// <typeparam name="T">The type of the operation.</typeparam>
 710  /// <param name="a">The left operand.</param>
 711  /// <param name="b">The right operand.</param>
 712  /// <returns>The result of the subtraction [<paramref name="a"/> - <paramref name="b"/>].</returns>
 713  public static T Subtraction<T>(T a, T b) =>
 880714    Subtraction<T, T, T>(a, b);
 715
 716  /// <summary>Subtracts multiple values [<paramref name="a"/> - <paramref name="b"/> - <paramref name="c"/> - ...].</su
 717  /// <typeparam name="T">The type of the operation.</typeparam>
 718  /// <param name="a">The first operand.</param>
 719  /// <param name="b">The second operand.</param>
 720  /// <param name="c">The third operand.</param>
 721  /// <param name="d">The remaining values.</param>
 722  /// <returns>The result of the subtraction [<paramref name="a"/> - <paramref name="b"/> - <paramref name="c"/> - ...].
 723  public static T Subtraction<T>(T a, T b, T c, params T[] d) =>
 56724    Subtraction<T>(step => { step(a); step(b); step(c); d.ToStepper()(step); });
 725
 726  /// <summary>Subtracts multiple numeric values [step1 - step2 - step3 - ...].</summary>
 727  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 728  /// <param name="stepper">The stepper containing the values.</param>
 729  /// <returns>The result of the subtraction [step1 - step2 - step3 - ...].</returns>
 730  public static T Subtraction<T>(Action<Action<T>> stepper) =>
 8731    OperationOnStepper(stepper, Subtraction);
 732
 733  internal static class SubtractionImplementation<TA, TB, TC>
 734  {
 4735    internal static Func<TA, TB, TC> Function = (a, b) =>
 4736    {
 4737      var A = Expression.Parameter(typeof(TA));
 4738      var B = Expression.Parameter(typeof(TB));
 4739      var BODY = Expression.Subtract(A, B);
 4740      Function = Expression.Lambda<Func<TA, TB, TC>>(BODY, A, B).Compile();
 4741      return Function(a, b);
 8742    };
 743  }
 744
 745  #endregion
 746
 747  #region Multiplication
 748
 749  /// <summary>Multiplies two values [<paramref name="a"/> * <paramref name="b"/>].</summary>
 750  /// <typeparam name="TA">The type of the left operand.</typeparam>
 751  /// <typeparam name="TB">The type of the right operand.</typeparam>
 752  /// <typeparam name="TC">The type of the return.</typeparam>
 753  /// <param name="a">The left operand.</param>
 754  /// <param name="b">The right operand.</param>
 755  /// <returns>The result of the multiplication [<paramref name="a"/> * <paramref name="b"/>].</returns>
 756  public static TC Multiplication<TA, TB, TC>(TA a, TB b) =>
 3210757    MultiplicationImplementation<TA, TB, TC>.Function(a, b);
 758
 759  /// <summary>Multiplies two values [<paramref name="a"/> * <paramref name="b"/>].</summary>
 760  /// <typeparam name="T">The type of the operation.</typeparam>
 761  /// <param name="a">The left operand.</param>
 762  /// <param name="b">The right operand.</param>
 763  /// <returns>The result of the multiplication [<paramref name="a"/> * <paramref name="b"/>].</returns>
 764  public static T Multiplication<T>(T a, T b) =>
 3210765    Multiplication<T, T, T>(a, b);
 766
 767  /// <summary>Multiplies multiple values [<paramref name="a"/> * <paramref name="b"/> * <paramref name="c"/> * ...].</s
 768  /// <typeparam name="T">The type of the operation.</typeparam>
 769  /// <param name="a">The first operand.</param>
 770  /// <param name="b">The second operand.</param>
 771  /// <param name="c">The third operand.</param>
 772  /// <param name="d">The remaining values.</param>
 773  /// <returns>The result of the multiplication [<paramref name="a"/> * <paramref name="b"/> * <paramref name="c"/> * ..
 774  public static T Multiplication<T>(T a, T b, T c, params T[] d) =>
 56775    Multiplication<T>(step => { step(a); step(b); step(c); d.ToStepper()(step); });
 776
 777  /// <summary>Multiplies multiple values [step1 * step2 * step3 * ...].</summary>
 778  /// <typeparam name="T">The type of the operation.</typeparam>
 779  /// <param name="stepper">The stepper containing the values.</param>
 780  /// <returns>The result of the multiplication [step1 * step2 * step3 * ...].</returns>
 781  public static T Multiplication<T>(Action<Action<T>> stepper) =>
 8782    OperationOnStepper(stepper, Multiplication);
 783
 784  internal static class MultiplicationImplementation<TA, TB, TC>
 785  {
 4786    internal static Func<TA, TB, TC> Function = (a, b) =>
 4787    {
 4788      var A = Expression.Parameter(typeof(TA));
 4789      var B = Expression.Parameter(typeof(TB));
 4790      var BODY = Expression.Multiply(A, B);
 4791      Function = Expression.Lambda<Func<TA, TB, TC>>(BODY, A, B).Compile();
 4792      return Function(a, b);
 8793    };
 794  }
 795
 796  #endregion
 797
 798  #region Division
 799
 800  /// <summary>Divides two values [<paramref name="a"/> / <paramref name="b"/>].</summary>
 801  /// <typeparam name="TA">The type of the left operand.</typeparam>
 802  /// <typeparam name="TB">The type of the right operand.</typeparam>
 803  /// <typeparam name="TC">The type of the return.</typeparam>
 804  /// <param name="a">The left operand.</param>
 805  /// <param name="b">The right operand.</param>
 806  /// <returns>The result of the division [<paramref name="a"/> / <paramref name="b"/>].</returns>
 807  public static TC Division<TA, TB, TC>(TA a, TB b) =>
 1085808    DivisionImplementation<TA, TB, TC>.Function(a, b);
 809
 810  /// <summary>Divides two values [<paramref name="a"/> / <paramref name="b"/>].</summary>
 811  /// <typeparam name="T">The type of the operation.</typeparam>
 812  /// <param name="a">The left operand.</param>
 813  /// <param name="b">The right operand.</param>
 814  /// <returns>The result of the division [<paramref name="a"/> / <paramref name="b"/>].</returns>
 815  public static T Division<T>(T a, T b) =>
 1085816    Division<T, T, T>(a, b);
 817
 818  /// <summary>Divides multiple values [<paramref name="a"/> / <paramref name="b"/> / <paramref name="c"/> / ...].</summ
 819  /// <typeparam name="T">The type of the operation.</typeparam>
 820  /// <param name="a">The first operand of the division.</param>
 821  /// <param name="b">The second operand of the division.</param>
 822  /// <param name="c">The third operand of the division.</param>
 823  /// <param name="d">The remaining values of the division.</param>
 824  /// <returns>The result of the division [<paramref name="a"/> / <paramref name="b"/> / <paramref name="c"/> / ...].</r
 825  public static T Division<T>(T a, T b, T c, params T[] d) =>
 56826    Division<T>(step => { step(a); step(b); step(c); d.ToStepper()(step); });
 827
 828  /// <summary>Divides multiple values [step1 / step2 / step3 / ...].</summary>
 829  /// <typeparam name="T">The type of the operation.</typeparam>
 830  /// <param name="stepper">The stepper containing the values.</param>
 831  /// <returns>The result of the division [step1 / step2 / step3 / ...].</returns>
 832  public static T Division<T>(Action<Action<T>> stepper) =>
 8833    OperationOnStepper(stepper, Division);
 834
 835  internal static class DivisionImplementation<TA, TB, TC>
 836  {
 4837    internal static Func<TA, TB, TC> Function = (a, b) =>
 4838    {
 4839      var A = Expression.Parameter(typeof(TA));
 4840      var B = Expression.Parameter(typeof(TB));
 4841      var BODY = Expression.Divide(A, B);
 4842      Function = Expression.Lambda<Func<TA, TB, TC>>(BODY, A, B).Compile();
 4843      return Function(a, b);
 6844    };
 845  }
 846
 847  #endregion
 848
 849  #region Remainder
 850
 851  /// <summary>Remainders two values [<paramref name="a"/> % <paramref name="b"/>].</summary>
 852  /// <typeparam name="TA">The type of the left operand.</typeparam>
 853  /// <typeparam name="TB">The type of the right operand.</typeparam>
 854  /// <typeparam name="TC">The type of the return.</typeparam>
 855  /// <param name="a">The left operand.</param>
 856  /// <param name="b">The right operand.</param>
 857  /// <returns>The result of the remainder operation [<paramref name="a"/> % <paramref name="b"/>].</returns>
 858  public static TC Remainder<TA, TB, TC>(TA a, TB b) =>
 1356811859    RemainderImplementation<TA, TB, TC>.Function(a, b);
 860
 861  /// <summary>Modulos two numeric values [<paramref name="a"/> % <paramref name="b"/>].</summary>
 862  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 863  /// <param name="a">The first operand of the modulation.</param>
 864  /// <param name="b">The second operand of the modulation.</param>
 865  /// <returns>The result of the modulation.</returns>
 866  public static T Remainder<T>(T a, T b) =>
 1356811867    Remainder<T, T, T>(a, b);
 868
 869  /// <summary>Modulos multiple numeric values [<paramref name="a"/> % <paramref name="b"/> % <paramref name="c"/> % ...
 870  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 871  /// <param name="a">The first operand of the modulation.</param>
 872  /// <param name="b">The second operand of the modulation.</param>
 873  /// <param name="c">The third operand of the modulation.</param>
 874  /// <param name="d">The remaining values of the modulation.</param>
 875  /// <returns>The result of the modulation.</returns>
 876  public static T Remainder<T>(T a, T b, T c, params T[] d) =>
 56877    Remainder<T>(step => { step(a); step(b); step(c); d.ToStepper()(step); });
 878
 879  /// <summary>Modulos multiple numeric values [step_1 % step_2 % step_3...].</summary>
 880  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 881  /// <param name="stepper">The stepper containing the values.</param>
 882  /// <returns>The result of the modulation.</returns>
 883  public static T Remainder<T>(Action<Action<T>> stepper) =>
 8884    OperationOnStepper(stepper, Remainder);
 885
 886  internal static class RemainderImplementation<TA, TB, TC>
 887  {
 4888    internal static Func<TA, TB, TC> Function = (a, b) =>
 4889    {
 4890      var A = Expression.Parameter(typeof(TA));
 4891      var B = Expression.Parameter(typeof(TB));
 4892      var BODY = Expression.Modulo(A, B);
 4893      Function = Expression.Lambda<Func<TA, TB, TC>>(BODY, A, B).Compile();
 4894      return Function(a, b);
 8895    };
 896  }
 897
 898  #endregion
 899
 900  #region Inversion
 901
 902  /// <summary>Inverts a numeric value [1 / a].</summary>
 903  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 904  /// <param name="a">The numeric value to invert.</param>
 905  /// <returns>The result of the inversion.</returns>
 906  public static T Inversion<T>(T a) =>
 50907    Division(Constant<T>.One, a);
 908
 909  #endregion
 910
 911  #region Power
 912
 913  /// <summary>Powers two numeric values [a ^ b].</summary>
 914  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 915  /// <param name="a">The first operand of the power.</param>
 916  /// <param name="b">The second operand of the power.</param>
 917  /// <returns>The result of the power.</returns>
 918  public static T Power<T>(T a, T b) =>
 58919    PowerImplementation<T>.Function(a, b);
 920
 921  /// <summary>Powers multiple numeric values [a ^ b ^ c...].</summary>
 922  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 923  /// <param name="a">The first operand of the power.</param>
 924  /// <param name="b">The second operand of the power.</param>
 925  /// <param name="c">The third operand of the power.</param>
 926  /// <param name="d">The remaining values of the power.</param>
 927  /// <returns>The result of the power.</returns>
 928  public static T Power<T>(T a, T b, T c, params T[] d) =>
 0929    Power<T>(step => { step(a); step(b); step(c); d.ToStepper()(step); });
 930
 931  /// <summary>Powers multiple numeric values [step_1 ^ step_2 ^ step_3...].</summary>
 932  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 933  /// <param name="stepper">The stepper containing the values.</param>
 934  /// <returns>The result of the power.</returns>
 935  public static T Power<T>(Action<Action<T>> stepper) =>
 0936    OperationOnStepper(stepper, Power);
 937
 938  internal static class PowerImplementation<T>
 939  {
 4940    internal static Func<T, T, T> Function = (a, b) =>
 4941    {
 4942      // Note: this code needs to die.. but this works until it gets a better version
 4943
 4944      // optimization for specific known types
 4945      if (TypeDescriptor.GetConverter(typeof(T)).CanConvertTo(typeof(double)))
 4946      {
 4947        var A = Expression.Parameter(typeof(T));
 4948        var B = Expression.Parameter(typeof(T));
 4949        var Math_Pow = typeof(Math).GetMethod(nameof(Math.Pow));
 4950        if (Math_Pow is not null)
 4951        {
 4952          Expression BODY = Expression.Convert(Expression.Call(Math_Pow, Expression.Convert(A, typeof(double)), Expressi
 4953          Function = Expression.Lambda<Func<T, T, T>>(BODY, A, B).Compile();
 4954          return Function(a, b);
 4955        }
 0956      }
 4957
 0958      Function = (A, B) =>
 0959      {
 0960        if (IsInteger(B) && IsPositive(B) && LessThan(B, Convert<int, T>(int.MaxValue)))
 0961        {
 0962          T result = A;
 0963          int power = Convert<T, int>(B);
 0964          for (int i = 0; i < power; i++)
 0965          {
 0966            result = Multiplication(result, A);
 0967          }
 0968          return result;
 0969        }
 0970        else
 0971        {
 0972#warning TODO
 0973          throw new NotImplementedException("This feature is still in development.");
 0974        }
 0975      };
 4976
 0977      return Function(a, b);
 8978    };
 979  }
 980
 981  #endregion
 982
 983  #region SquareRoot
 984
 985  /// <summary>Square roots a numeric value [√a].</summary>
 986  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 987  /// <param name="a">The numeric value to square root.</param>
 988  /// <returns>The result of the square root.</returns>
 989  public static T SquareRoot<T>(T a) =>
 123299990    SquareRootImplementation<T>.Function(a);
 991
 992  internal static class SquareRootImplementation<T>
 993  {
 4994    internal static Func<T, T> Function = a =>
 35995    {
 4996        #region Optimization(int)
 4997
 35998        if (typeof(T) == typeof(int))
 1999      {
 41000        static int SquareRoot(int x)
 1232651001        {
 1232651002          if (x is 0 || x is 1)
 41003          {
 41004            return x;
 41005          }
 3697831006          int start = 1, end = x, ans = 0;
 7475801007          while (start <= end)
 6363791008          {
 6363791009            int mid = (start + end) / 2;
 6363791010            if (mid * mid == x)
 120601011            {
 120601012              return mid;
 41013            }
 6243191014            if (mid * mid < x)
 2188521015            {
 2188521016              start = mid + 1;
 2188521017              ans = mid;
 2188521018            }
 41019            else
 4054671020            {
 4054671021              end = mid - 1;
 4054671022            }
 6243191023          }
 1112011024          return ans;
 1232651025        }
 11026        SquareRootImplementation<int>.Function = SquareRoot;
 11027        return Function!(a);
 41028      }
 41029
 41030        #endregion
 41031
 341032        return Root(a, Constant<T>.Two);
 391033    };
 1034  }
 1035
 1036  #endregion
 1037
 1038  #region Root
 1039
 1040  /// <summary>Roots two numeric values [a ^ (1 / b)].</summary>
 1041  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 1042  /// <param name="a">The base of the root.</param>
 1043  /// <param name="b">The root of the operation.</param>
 1044  /// <returns>The result of the root.</returns>
 1045  public static T Root<T>(T a, T b) =>
 341046    Power(a, Inversion(b));
 1047
 1048  #endregion
 1049
 1050  #region Logarithm
 1051
 1052  /// <summary>Computes the logarithm of a value.</summary>
 1053  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 1054  /// <param name="value">The value to compute the logarithm of.</param>
 1055  /// <param name="base">The base of the logarithm to compute.</param>
 1056  /// <returns>The computed logarithm value.</returns>
 1057  public static T Logarithm<T>(T value, T @base) =>
 01058    LogarithmImplementation<T>.Function(value, @base);
 1059
 1060  internal static class LogarithmImplementation<T>
 1061  {
 01062    internal static Func<T, T, T> Function = (a, b) =>
 01063    {
 01064#warning TODO
 01065        throw new NotImplementedException();
 01066
 01067        // ParameterExpression A = Expression.Parameter(typeof(T));
 01068        // ParameterExpression B = Expression.Parameter(typeof(T));
 01069        // Expression BODY = ;
 01070        // Function = Expression.Lambda<Func<T, T, T>>(BODY, A, B).Compile();
 01071        // return Function(a, b);
 01072      };
 1073  }
 1074
 1075  #endregion
 1076
 1077  #region IsInteger
 1078
 1079  /// <summary>Determines if a numerical value is an integer.</summary>
 1080  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 1081  /// <param name="a">The value to determine integer status of.</param>
 1082  /// <returns>Whether or not the value is an integer.</returns>
 1083  public static bool IsInteger<T>(T a) =>
 2072941084    IsIntegerImplementation<T>.Function(a);
 1085
 1086  internal static class IsIntegerImplementation<T>
 1087  {
 41088    internal static Func<T, bool> Function = a =>
 41089    {
 41090      var methodInfo = Meta.GetIsIntegerMethod<T>();
 41091      if (methodInfo is not null)
 01092      {
 01093        Function = methodInfo.CreateDelegate<Func<T, bool>>();
 01094        return Function(a);
 41095      }
 41096
 41097      var A = Expression.Parameter(typeof(T));
 41098      var BODY = Expression.Equal(
 41099        Expression.Modulo(A, Expression.Constant(Constant<T>.One)),
 41100        Expression.Constant(Constant<T>.Zero));
 41101      Function = Expression.Lambda<Func<T, bool>>(BODY, A).Compile();
 41102      return Function(a);
 81103    };
 1104  }
 1105
 1106  #endregion
 1107
 1108  #region IsNonNegative
 1109
 1110  /// <summary>Determines if a numerical value is non-negative.</summary>
 1111  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 1112  /// <param name="a">The value to determine non-negative status of.</param>
 1113  /// <returns>Whether or not the value is non-negative.</returns>
 1114  public static bool IsNonNegative<T>(T a) =>
 01115    IsNonNegativeImplementation<T>.Function(a);
 1116
 1117  internal static class IsNonNegativeImplementation<T>
 1118  {
 01119    internal static Func<T, bool> Function = a =>
 01120    {
 01121      var methodInfo = Meta.GetIsNonNegativeMethod<T>();
 01122      if (methodInfo is not null)
 01123      {
 01124        Function = methodInfo.CreateDelegate<Func<T, bool>>();
 01125        return Function(a);
 01126      }
 01127
 01128      var A = Expression.Parameter(typeof(T));
 01129      var BODY = Expression.GreaterThanOrEqual(A, Expression.Constant(Constant<T>.Zero));
 01130      Function = Expression.Lambda<Func<T, bool>>(BODY, A).Compile();
 01131      return Function(a);
 01132    };
 1133  }
 1134
 1135  #endregion
 1136
 1137  #region IsNegative
 1138
 1139  /// <summary>Determines if a numerical value is negative.</summary>
 1140  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 1141  /// <param name="a">The value to determine negative status of.</param>
 1142  /// <returns>Whether or not the value is negative.</returns>
 1143  public static bool IsNegative<T>(T a) =>
 2191144    IsNegativeImplementation<T>.Function(a);
 1145
 1146  internal static class IsNegativeImplementation<T>
 1147  {
 41148    internal static Func<T, bool> Function = a =>
 41149    {
 41150      MethodInfo? methodInfo = Meta.GetIsNegativeMethod<T>();
 41151      if (methodInfo is not null)
 21152      {
 21153        Function = methodInfo.CreateDelegate<Func<T, bool>>();
 21154        return Function(a);
 41155      }
 41156
 21157      ParameterExpression A = Expression.Parameter(typeof(T));
 21158      LabelTarget RETURN = Expression.Label(typeof(bool));
 21159      Expression BODY = Expression.LessThan(A, Expression.Constant(Constant<T>.Zero));
 21160      Function = Expression.Lambda<Func<T, bool>>(BODY, A).Compile();
 21161      return Function(a);
 81162    };
 1163  }
 1164
 1165  #endregion
 1166
 1167  #region IsPositive
 1168
 1169  /// <summary>Determines if a numerical value is positive.</summary>
 1170  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 1171  /// <param name="a">The value to determine positive status of.</param>
 1172  /// <returns>Whether or not the value is positive.</returns>
 1173  public static bool IsPositive<T>(T a) =>
 761174    IsPositiveImplementation<T>.Function(a);
 1175
 1176  internal static class IsPositiveImplementation<T>
 1177  {
 41178    internal static Func<T, bool> Function = a =>
 41179    {
 41180      var methodInfo = Meta.GetIsPositiveMethod<T>();
 41181      if (methodInfo is not null)
 01182      {
 01183        Function = methodInfo.CreateDelegate<Func<T, bool>>();
 01184        return Function(a);
 41185      }
 41186
 41187      var A = Expression.Parameter(typeof(T));
 41188      var BODY = Expression.GreaterThan(A, Expression.Constant(Constant<T>.Zero));
 41189      Function = Expression.Lambda<Func<T, bool>>(BODY, A).Compile();
 41190      return Function(a);
 81191    };
 1192  }
 1193
 1194  #endregion
 1195
 1196  #region IsEven
 1197
 1198  /// <summary>Determines if a numerical value is even.</summary>
 1199  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 1200  /// <param name="a">The value to determine even status of.</param>
 1201  /// <returns>Whether or not the value is even.</returns>
 1202  public static bool IsEven<T>(T a) =>
 2075171203    IsEvenImplementation<T>.Function(a);
 1204
 1205  internal static class IsEvenImplementation<T>
 1206  {
 41207    internal static Func<T, bool> Function = a =>
 41208    {
 41209      MethodInfo? methodInfo = Meta.GetIsEvenMethod<T>();
 41210      if (methodInfo is not null)
 01211      {
 01212        Function = methodInfo.CreateDelegate<Func<T, bool>>();
 01213        return Function(a);
 41214      }
 41215
 41216      var A = Expression.Parameter(typeof(T));
 41217      var BODY = Expression.Equal(Expression.Modulo(A, Expression.Constant(Constant<T>.Two)), Expression.Constant(Consta
 41218      Function = Expression.Lambda<Func<T, bool>>(BODY, A).Compile();
 41219      return Function(a);
 81220    };
 1221  }
 1222
 1223  #endregion
 1224
 1225  #region IsOdd
 1226
 1227  /// <summary>Determines if a numerical value is odd.</summary>
 1228  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 1229  /// <param name="a">The value to determine odd status of.</param>
 1230  /// <returns>Whether or not the value is odd.</returns>
 1231  public static bool IsOdd<T>(T a) =>
 28001232    IsOddImplementation<T>.Function(a);
 1233
 1234  internal static class IsOddImplementation<T>
 1235  {
 81236    internal static Func<T, bool> Function = a =>
 81237    {
 81238      var methodInfo = Meta.GetIsOddMethod<T>();
 81239      if (methodInfo is not null)
 01240      {
 01241        Function = methodInfo.CreateDelegate<Func<T, bool>>();
 01242        return Function(a);
 81243      }
 81244
 81245      var A = Expression.Parameter(typeof(T));
 81246      Expression BODY =
 81247        Expression.Block(
 81248          Expression.IfThen(
 81249            Expression.LessThan(A, Expression.Constant(Constant<T>.Zero)),
 81250            Expression.Assign(A, Expression.Negate(A))),
 81251          Expression.Equal(Expression.Modulo(A, Expression.Constant(Constant<T>.Two)), Expression.Constant(Constant<T>.O
 81252      Function = Expression.Lambda<Func<T, bool>>(BODY, A).Compile();
 81253      return Function(a);
 161254    };
 1255  }
 1256
 1257  #endregion
 1258
 1259  #region IsPrime
 1260
 1261  /// <summary>Determines if a numerical value is prime.</summary>
 1262  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 1263  /// <param name="a">The value to determine prime status of.</param>
 1264  /// <returns>Whether or not the value is prime.</returns>
 1265  public static bool IsPrime<T>(T a) =>
 2063781266    IsPrimeImplementation<T>.Function(a);
 1267
 1268  internal static class IsPrimeImplementation<T>
 1269  {
 11270    internal static Func<T, bool> Function = a =>
 11271    {
 11272      var methodInfo = Meta.GetIsPrimeMethod<T>();
 11273      if (methodInfo is not null)
 01274      {
 01275        Function = methodInfo.CreateDelegate<Func<T, bool>>();
 01276        return Function(a);
 11277      }
 11278
 11279      // This can be optimized
 11280      Function = A =>
 2063781281      {
 2063781282        if (IsInteger(A) && !LessThan(A, Constant<T>.Two))
 2062711283        {
 2062711284          if (Equate(A, Constant<T>.Two))
 1761285          {
 1761286            return true;
 11287          }
 2060951288          if (IsEven(A))
 828501289          {
 828501290            return false;
 11291          }
 1232451292          T squareRoot = SquareRoot(A);
 28794761293          for (T divisor = Constant<T>.Three; LessThanOrEqual(divisor, squareRoot); divisor = Addition(divisor, Constant
 13549441294          {
 13549441295            if (Equate(Remainder<T>(A, divisor), Constant<T>.Zero))
 384511296            {
 384511297              return false;
 11298            }
 13164931299          }
 847941300          return true;
 11301        }
 11302        else
 1071303        {
 1071304          return false;
 11305        }
 2063791306      };
 11307      return Function(a);
 21308    };
 1309  }
 1310
 1311  #endregion
 1312
 1313  #region AbsoluteValue
 1314
 1315  /// <summary>Gets the absolute value of a value.</summary>
 1316  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 1317  /// <param name="a">The value to get the absolute value of.</param>
 1318  /// <returns>The absolute value of the provided value.</returns>
 1319  public static T AbsoluteValue<T>(T a) =>
 10041320    AbsoluteValueImplementation<T>.Function(a);
 1321
 1322  internal static class AbsoluteValueImplementation<T>
 1323  {
 81324    internal static Func<T, T> Function = a =>
 81325    {
 81326      ParameterExpression A = Expression.Parameter(typeof(T));
 81327      LabelTarget RETURN = Expression.Label(typeof(T));
 81328      Expression BODY = Expression.Block(
 81329        Expression.IfThenElse(
 81330          Expression.LessThan(A, Expression.Constant(Constant<T>.Zero)),
 81331          Expression.Return(RETURN, Expression.Negate(A)),
 81332          Expression.Return(RETURN, A)),
 81333        Expression.Label(RETURN, Expression.Constant(default(T), typeof(T))));
 81334      Function = Expression.Lambda<Func<T, T>>(BODY, A).Compile();
 81335      return Function(a);
 161336    };
 1337  }
 1338
 1339  #endregion
 1340
 1341  #region Clamp
 1342
 1343  /// <summary>Gets a value restricted to a minimum and maximum range.</summary>
 1344  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 1345  /// <param name="value">The value to clamp.</param>
 1346  /// <param name="minimum">The minimum of the range to clamp the value by.</param>
 1347  /// <param name="maximum">The maximum of the range to clamp the value by.</param>
 1348  /// <returns>The value restricted to the provided range.</returns>
 1349  public static T Clamp<T>(T value, T minimum, T maximum) =>
 241350    LessThan(value, minimum)
 241351    ? minimum
 241352    : GreaterThan(value, maximum)
 241353      ? maximum
 241354      : value;
 1355
 1356  #endregion
 1357
 1358  #region EqualToLeniency
 1359
 1360  /// <summary>Checks for equality between two numeric values with a range of possibly leniency.</summary>
 1361  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 1362  /// <param name="a">The first operand of the equality check.</param>
 1363  /// <param name="b">The second operand of the equality check.</param>
 1364  /// <param name="leniency">The allowed distance between the values to still be considered equal.</param>
 1365  /// <returns>True if the values are within the allowed leniency of each other. False if not.</returns>
 1366  public static bool EqualToLeniency<T>(T a, T b, T leniency) =>
 1367#warning TODO: add an ArgumentOutOfBounds check on leniency
 2141368    EqualToLeniencyImplementation<T>.Function(a, b, leniency);
 1369
 1370  internal static class EqualToLeniencyImplementation<T>
 1371  {
 41372    internal static Func<T, T, T, bool> Function = (T a, T b, T c) =>
 41373    {
 41374      var A = Expression.Parameter(typeof(T));
 41375      var B = Expression.Parameter(typeof(T));
 41376      var C = Expression.Parameter(typeof(T));
 41377      var D = Expression.Variable(typeof(T));
 41378      var RETURN = Expression.Label(typeof(bool));
 41379      var BODY = Expression.Block(Ɐ(D),
 41380        Expression.Assign(D, Expression.Subtract(A, B)),
 41381        Expression.IfThenElse(
 41382          Expression.LessThan(D, Expression.Constant(Constant<T>.Zero)),
 41383          Expression.Assign(D, Expression.Negate(D)),
 41384          Expression.Assign(D, D)),
 41385        Expression.Return(RETURN, Expression.LessThanOrEqual(D, C), typeof(bool)),
 41386        Expression.Label(RETURN, Expression.Constant(default(bool))));
 41387      Function = Expression.Lambda<Func<T, T, T, bool>>(BODY, A, B, C).Compile();
 41388      return Function(a, b, c);
 81389    };
 1390  }
 1391
 1392  #endregion
 1393
 1394  #region GreatestCommonFactor
 1395
 1396  /// <summary>Computes the greatest common factor of a set of numbers.</summary>
 1397  /// <typeparam name="T">The numeric type of the computation.</typeparam>
 1398  /// <param name="a">The first operand of the greatest common factor computation.</param>
 1399  /// <param name="b">The second operand of the greatest common factor computation.</param>
 1400  /// <param name="c">The remaining operands of the greatest common factor computation.</param>
 1401  /// <returns>The computed greatest common factor of the set of numbers.</returns>
 1402  public static T GreatestCommonFactor<T>(T a, T b, params T[] c) =>
 18901403    GreatestCommonFactor<T>(step => { step(a); step(b); c.ToStepper()(step); });
 1404
 1405  /// <summary>Computes the greatest common factor of a set of numbers.</summary>
 1406  /// <typeparam name="T">The numeric type of the computation.</typeparam>
 1407  /// <param name="stepper">The set of numbers to compute the greatest common factor of.</param>
 1408  /// <returns>The computed greatest common factor of the set of numbers.</returns>
 1409  public static T GreatestCommonFactor<T>(Action<Action<T>> stepper)
 3151410  {
 3151411    if (stepper is null) throw new ArgumentNullException(nameof(stepper));
 3151412    bool assigned = false;
 3151413    T answer = Constant<T>.Zero;
 3151414    stepper((T n) =>
 6501415    {
 6501416      if (n is null)
 01417      {
 01418        throw new ArgumentNullException(null, nameof(stepper) + " contians null values");
 3151419      }
 6501420      if (Equate(n, Constant<T>.Zero))
 01421      {
 01422        throw new ArgumentException("Encountered Zero (0) while computing the " + nameof(GreatestCommonFactor));
 3151423      }
 6501424      else if (!IsInteger(n))
 01425      {
 01426        throw new ArgumentException(nameof(stepper) + " contains non-integer value(s).");
 3151427      }
 6501428      if (!assigned)
 3151429      {
 3151430        answer = AbsoluteValue(n);
 3151431        assigned = true;
 3151432      }
 3151433      else
 3351434      {
 3351435        if (GreaterThan(answer, Constant<T>.One))
 1851436        {
 1851437          T a = answer;
 1851438          T b = n;
 5941439          while (Inequate(b, Constant<T>.Zero))
 4091440          {
 4091441            T remainder = Remainder(a, b);
 4091442            a = b;
 4091443            b = remainder;
 4091444          }
 1851445          answer = AbsoluteValue(a);
 1851446        }
 3351447      }
 9651448    });
 3151449    if (!assigned)
 01450    {
 01451      throw new ArgumentException(nameof(stepper) + " is empty.", nameof(stepper));
 1452    }
 3151453    return answer;
 3151454  }
 1455
 1456  #endregion
 1457
 1458  #region LeastCommonMultiple
 1459
 1460  /// <summary>Computes the least common multiple of a set of numbers.</summary>
 1461  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 1462  /// <param name="a">The first operand of the least common muiltiple computation.</param>
 1463  /// <param name="b">The second operand of the least common muiltiple computation.</param>
 1464  /// <param name="c">The remaining operands of the least common muiltiple computation.</param>
 1465  /// <returns>The computed least common least common multiple of the set of numbers.</returns>
 1466  public static T LeastCommonMultiple<T>(T a, T b, params T[] c) =>
 1441467    LeastCommonMultiple<T>(step => { step(a); step(b); c.ToStepper()(step); });
 1468
 1469  /// <summary>Computes the least common multiple of a set of numbers.</summary>
 1470  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 1471  /// <param name="stepper">The set of numbers to compute the least common multiple of.</param>
 1472  /// <returns>The computed least common least common multiple of the set of numbers.</returns>
 1473  public static T LeastCommonMultiple<T>(Action<Action<T>> stepper)
 241474  {
 241475    if (stepper is null) throw new ArgumentNullException(nameof(stepper));
 241476    bool assigned = false;
 241477    T? answer = default;
 241478    stepper(parameter =>
 1321479    {
 1321480      if (Equate(parameter, Constant<T>.Zero))
 01481      {
 01482        throw new ArgumentException(nameof(stepper) + " contains 0 value(s).");
 241483      }
 1321484      if (!IsInteger(parameter))
 01485      {
 01486        throw new ArgumentException(nameof(stepper) + " contains non-integer value(s).");
 241487      }
 1321488      parameter = AbsoluteValue(parameter);
 1321489      if (!assigned)
 241490      {
 241491        answer = parameter;
 241492        assigned = true;
 241493      }
 241494      else
 1081495      {
 1081496        answer = Division(Multiplication(answer, parameter), GreatestCommonFactor(answer, parameter));
 1081497      }
 1561498    });
 241499    if (!assigned)
 01500    {
 01501      throw new ArgumentException(nameof(stepper) + " is empty.", nameof(stepper));
 1502    }
 241503    return answer!;
 241504  }
 1505
 1506  #endregion
 1507
 1508  #region LinearInterpolation
 1509
 1510  /// <summary>Linearly interpolations a value.</summary>
 1511  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 1512  /// <param name="x">The value along the first dimension to compute the linear interpolation for.</param>
 1513  /// <param name="x0">A known starting point along the first dimension.</param>
 1514  /// <param name="x1">A known ending point along the first dimension.</param>
 1515  /// <param name="y0">A known starting point along the second dimension.</param>
 1516  /// <param name="y1">A known ending point along the second dimension.</param>
 1517  /// <returns>The linearly interpolated value.</returns>
 1518  public static T LinearInterpolation<T>(T x, T x0, T x1, T y0, T y1)
 01519  {
 01520    if (GreaterThan(x0, x1) ||
 01521      GreaterThan(x, x1) ||
 01522      LessThan(x, x0))
 01523    {
 01524      throw new ArgumentException($"!({nameof(x0)}[{x0}] <= {nameof(x)}[{x}] <= {nameof(x1)}[{x1}])");
 1525    }
 01526    if (Equate(x0, x1))
 01527    {
 01528      if (Inequate(y0, y1))
 01529      {
 01530        throw new ArgumentException($"{nameof(x0)}[{x0}] == {nameof(x1)}[{x1}] && {nameof(y0)}[{y0}] != {nameof(y1)}[{y1
 1531      }
 1532      else
 01533      {
 01534        return y0;
 1535      }
 1536    }
 01537    return Addition(y0, Division(Multiplication(Subtraction(x, x0), Subtraction(y1, y0)), Subtraction(x1, x0)));
 01538  }
 1539
 1540  #endregion
 1541
 1542  #region Factorial
 1543
 1544  /// <summary>Computes the factorial of a numeric value [<paramref name="a"/>!] == [<paramref name="a"/> * (<paramref n
 1545  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 1546  /// <param name="a">The integer value to compute the factorial of.</param>
 1547  /// <returns>The computed factorial value.</returns>
 1548  /// <exception cref="ArgumentOutOfRangeException">Thrown when the parameter is not an integer value.</exception>
 1549  /// <exception cref="ArgumentOutOfRangeException">Thrown when the parameter is less than zero.</exception>
 1550  public static T Factorial<T>(T a) =>
 801551    FactorialImplementation<T>.Function(a);
 1552
 1553  internal static class FactorialImplementation<T>
 1554  {
 41555    internal static Func<T, T> Function = a =>
 41556    {
 41557      var methodInfo = Meta.GetFactorialMethod<T>();
 41558      if (methodInfo is not null)
 01559      {
 01560        Function = methodInfo.CreateDelegate<Func<T, T>>();
 01561        return Function(a);
 41562      }
 41563
 41564      Function = A =>
 801565      {
 801566        if (!IsInteger(A))
 01567        {
 01568          throw new ArgumentOutOfRangeException(nameof(A), A, $"!{nameof(A)}[{A}].{nameof(IsInteger)}()");
 41569        }
 801570        if (LessThan(A, Constant<T>.Zero))
 01571        {
 01572          throw new ArgumentOutOfRangeException(nameof(A), A, $"!({nameof(A)}[{A}] >= 0)");
 41573        }
 801574        T result = Constant<T>.One;
 6401575        for (; GreaterThan(A, Constant<T>.One); A = Subtraction(A, Constant<T>.One))
 2801576          result = Multiplication(A, result);
 801577        return result;
 841578      };
 41579      return Function(a);
 81580    };
 1581  }
 1582
 1583  #endregion
 1584
 1585  #region Combinations
 1586
 1587  /// <summary>Computes the combinations of <paramref name="N"/> values using the <paramref name="n"/> grouping definiti
 1588  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 1589  /// <param name="N">The number of values to compute the combinations of.</param>
 1590  /// <param name="n">The groups and how many values fall into each group.</param>
 1591  /// <returns>The computed number of combinations.</returns>
 1592  public static T CombinationsCount<T>(T N, T[] n)
 01593  {
 01594    if (!IsInteger(N))
 01595    {
 01596      throw new ArgumentOutOfRangeException(nameof(N), N, $"!({nameof(N)}.{nameof(IsInteger)})");
 1597    }
 01598    T result = Factorial(N);
 01599    T sum = Constant<T>.Zero;
 01600    for (int i = 0; i < n.Length; i++)
 01601    {
 01602      if (!IsInteger(n[i]))
 01603      {
 01604        throw new ArgumentOutOfRangeException(nameof(n) + "[" + i + "]", n[i], "!(" + nameof(n) + "[" + i + "]." + nameo
 1605      }
 01606      result = Division(result, Factorial(n[i]));
 01607      sum = Addition(sum, n[i]);
 01608    }
 01609    if (GreaterThan(sum, N))
 01610    {
 01611      throw new ArgumentException("Aurguments out of range !(" + nameof(N) + " < Add(" + nameof(n) + ") [" + N + " < " +
 1612    }
 01613    return result;
 01614  }
 1615
 1616  #endregion
 1617
 1618  #region BinomialCoefficient
 1619
 1620  /// <summary>Computes the Binomial coefficient (N choose n).</summary>
 1621  /// <typeparam name="T">The numeric type of the computation.</typeparam>
 1622  /// <param name="N">The size of the entire set (N choose n).</param>
 1623  /// <param name="n">The size of the subset (N choose n).</param>
 1624  /// <returns>The computed binomial coefficient (N choose n).</returns>
 1625  public static T BinomialCoefficient<T>(T N, T n)
 201626  {
 201627    if (LessThan(N, Constant<T>.Zero))
 01628    {
 01629      throw new ArgumentOutOfRangeException(nameof(N), N, "!(" + nameof(N) + " >= 0)");
 1630    }
 201631    if (!IsInteger(N))
 01632    {
 01633      throw new ArgumentOutOfRangeException(nameof(N), N, "!(" + nameof(N) + "." + nameof(IsInteger) + ")");
 1634    }
 201635    if (!IsInteger(n))
 01636    {
 01637      throw new ArgumentOutOfRangeException(nameof(n), n, "!(" + nameof(n) + "." + nameof(IsInteger) + ")");
 1638    }
 201639    if (LessThan(N, n))
 01640    {
 01641      throw new ArgumentException("Arguments out of range !(" + nameof(N) + " <= " + nameof(n) + ") [" + N + " <= " + n 
 1642    }
 201643    return Division(Factorial(N), Multiplication(Factorial(n), Factorial(Subtraction(N, n))));
 201644  }
 1645
 1646  #endregion
 1647
 1648  #region Exponential
 1649
 1650  /// <summary>Computes the exponentional of a value [e ^ <paramref name="a"/>].</summary>
 1651  /// <typeparam name="T">The generic type of the operation.</typeparam>
 1652  /// <param name="a">The value to compute the exponentional of.</param>
 1653  /// <returns>The exponential of the value [e ^ <paramref name="a"/>].</returns>
 1654  public static T Exponential<T>(T a)
 01655  {
 1656#warning TODO
 01657    throw new NotImplementedException();
 1658  }
 1659
 1660  #endregion
 1661
 1662  #region NaturalLogarithm
 1663
 1664  /// <summary>Computes the natural logarithm of a value [ln(<paramref name="a"/>)].</summary>
 1665  /// <typeparam name="T">The generic type of the operation.</typeparam>
 1666  /// <param name="a">The value to compute the natural log of.</param>
 1667  /// <returns>The natural log of the provided value [ln(<paramref name="a"/>)].</returns>
 1668  public static T NaturalLogarithm<T>(T a) =>
 01669    NaturalLogarithmImplementation<T>.Function(a);
 1670
 1671  internal static class NaturalLogarithmImplementation<T>
 1672  {
 01673    internal static Func<T, T> Function = a =>
 01674    {
 01675      // optimization for specific known types
 01676      if (TypeDescriptor.GetConverter(typeof(T)).CanConvertTo(typeof(double)))
 01677      {
 01678        ParameterExpression A = Expression.Parameter(typeof(T));
 01679        MethodInfo? Math_Log = typeof(Math).GetMethod("Log");
 01680        if (Math_Log is not null)
 01681        {
 01682          Expression BODY = Expression.Call(Math_Log, A);
 01683          Function = Expression.Lambda<Func<T, T>>(BODY, A).Compile();
 01684          return Function(a);
 01685        }
 01686      }
 01687#warning TODO
 01688      throw new NotImplementedException();
 01689    };
 1690  }
 1691
 1692  #endregion
 1693
 1694  #region LinearRegression2D
 1695
 1696  /// <summary>Computes the best fit line from a set of points in 2D space [y = slope * x + y_intercept].</summary>
 1697  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 1698  /// <param name="points">The points to compute the best fit line of.</param>
 1699  /// <param name="slope">The slope of the computed best fit line [y = slope * x + y_intercept].</param>
 1700  /// <param name="y_intercept">The y intercept of the computed best fit line [y = slope * x + y_intercept].</param>
 1701  public static void LinearRegression2D<T>(Action<Action<T, T>> points, out T slope, out T y_intercept)
 01702  {
 01703    if (points is null) throw new ArgumentNullException(nameof(points));
 01704    int count = 0;
 01705    T sumx = Constant<T>.Zero;
 01706    T sumy = Constant<T>.Zero;
 01707    points((T x, T y) =>
 01708    {
 01709      sumx = Addition(sumx, x);
 01710      sumy = Addition(sumy, y);
 01711      count++;
 01712    });
 01713    if (count < 2)
 01714    {
 01715      throw new ArgumentException("At least 3 points must be provided for linear regressions");
 1716    }
 01717    T tcount = Convert<int, T>(count);
 01718    T meanx = Division(sumx, tcount);
 01719    T meany = Division(sumy, tcount);
 01720    T variancex = Constant<T>.Zero;
 01721    T variancey = Constant<T>.Zero;
 01722    points((T x, T y) =>
 01723    {
 01724      T offset = Subtraction(x, meanx);
 01725      variancey = Addition(variancey, Multiplication(offset, Subtraction(y, meany)));
 01726      variancex = Addition(variancex, Multiplication(offset, offset));
 01727    });
 01728    slope = Division(variancey, variancex);
 01729    y_intercept = Subtraction(meany, Multiplication(slope, meanx));
 01730  }
 1731
 1732  #endregion
 1733
 1734  #region FactorPrimes
 1735
 1736  /// <summary>Factors the primes numbers of a numeric integer value.</summary>
 1737  /// <typeparam name="T">The numeric type of the operation.</typeparam>
 1738  /// <param name="a">The value to factor the prime numbers of.</param>
 1739  /// <param name="step">The action to perform on all found prime factors.</param>
 1740  public static void FactorPrimes<T>(T a, Action<T> step) =>
 141741    FactorPrimesImplementation<T>.Function(a, step);
 1742
 1743  internal static class FactorPrimesImplementation<T>
 1744  {
 21745    internal static Action<T, Action<T>> Function = (a, x) =>
 21746    {
 21747      Function = (A, step) =>
 141748      {
 141749        if (!IsInteger(A))
 01750        {
 01751          throw new ArgumentOutOfRangeException(nameof(A), A, "!(" + nameof(A) + "." + nameof(IsInteger) + ")");
 21752        }
 141753        if (IsNegative(A))
 01754        {
 01755          A = AbsoluteValue(A);
 01756          step(Convert<int, T>(-1));
 01757        }
 221758        while (IsEven(A))
 81759        {
 81760          step(Constant<T>.Two);
 81761          A = Division(A, Constant<T>.Two);
 81762        }
 401763        for (T i = Constant<T>.Three; LessThanOrEqual(i, SquareRoot(A)); i = Addition(i, Constant<T>.Two))
 61764        {
 141765          while (Equate(Remainder(A, i), Constant<T>.Zero))
 81766          {
 81767            step(i);
 81768            A = Division(A, i);
 81769          }
 61770        }
 141771        if (GreaterThan(A, Constant<T>.Two))
 81772        {
 81773          step(A);
 81774        }
 161775      };
 21776      Function(a, x);
 41777    };
 1778  }
 1779
 1780  #endregion
 1781}

Methods/Properties

AppendLine(...)
AppendLine(...)
AppendLine(...)
Combinations(...)
Combinations(...)
Combinations(...)
Combinations(...)
Replace(...)
ContainsAny(...)
RemoveCarriageReturns(...)
StandardizeNewLines(...)
Repeat(...)
SplitLines(...)
IndentLines(...)
IndentLines(...)
IndentNewLinesBetweenIndeces(...)
IndentNewLinesBetweenIndeces(...)
IndentLineNumbers(...)
IndentLineNumbers(...)
PadLinesLeft(...)
PadSubstringLinesRight(...)
PadLinesLeftBetweenIndeces(...)
PadLinesRightBetweenIndeces(...)
PadLinesLeft(...)
PadLinesRight(...)
Reverse(...)
Remove(...)
CountLines(...)
XML_Stepper()
XML_StepperBreak()
Stepper(...)
Stepper(...)
StepperBreak(...)
StepperBreak(...)
Stepper(...)
Stepper(...)
Stepper(...)
StepperBreak(...)
Stepper(...)
Stepper(...)
StepperBreak(...)
StepperBreak(...)
Stepper(...)
Stepper(...)
Stepper(...)
StepperBreak(...)
BuildArray(...)
Format(...)
Format(...)
ConstructRectangularJaggedArray(...)
ConstructRectangularJaggedArray(...)
ConstructSquareJaggedArray(...)
ConstructSquareJaggedArray(...)
Time_DateTime(...)
Time_StopWatch(...)
TryFirst(...)
CreateDelegate(...)
IsDefined(...)
ToIEnumerable()
GetEnumerator(...)
ToSpan(...)
ToSpan(...)
ToSpan(...)
ToArray(...)
ToArray(...)
ToArray(...)
Select(...)
Select()
Gaps(...)
Convert(...)
Append(...)
Build(...)
Concat(...)
Where(...)
Iterate(...)
ToStepper(...)
ToStepperBreak(...)
ToArray(...)
Count(...)
EveryNth(...)
ContainsDuplicates(...)
ContainsDuplicates(...)
ContainsDuplicates(...)
ContainsDuplicates(...)
Any(...)
Any(...)
ConcatToString(...)
ToCompareResult(...)
.cctor()
ToEnglishWords(...)
WholeNumber(...)
DigitGroup(...)
ToEnglishWords(...)
ToEnglishWords(...)
ToEnglishWords(...)
ToEnglishWords(...)
ToEnglishWords(...)
ToEnglishWords(...)
ToEnglishWords(...)
ToEnglishWords(...)
ToEnglishWords(...)
TryParse(...)
TryParseEnglishWordsToDecimal(...)
TryParse(...)
TryParseEnglishWordsToLong(...)
TryParse(...)
TryParseEnglishWordsToUlong(...)
TryParse(...)
TryParseEnglishWordsToInt(...)
TryParse(...)
TryParseEnglishWordsToUint(...)
TryParse(...)
TryParseEnglishWordsToShort(...)
TryParse(...)
TryParseEnglishWordsToUshort(...)
TryParse(...)
TryParseEnglishWordsToByte(...)
TryParse(...)
TryParseEnglishWordsToSbyte(...)
TryParseEnglishWords(...)
GetNextDigit(...)
GetTeensDigit(...)
GetNextTensDigit(...)
GetNextExplicitDigitGroup(...)
GetNextFractionalSuffix(...)
XML_Permute()
XML_PermuteRecursive()
XML_PermuteIterative()
PermuteRecursive(...)
PermuteRecursive(...)
PermuteRecursive(...)
PermuteRecursive(...)
PermuteRecursive(...)
PermuteRecursive(...)
PermuteRecursive(...)
PermuteRecursive(...)
PermuteIterative(...)
PermuteIterative(...)
PermuteIterative(...)
PermuteIterative(...)
PermuteIterative(...)
PermuteIterative(...)
PermuteIterative(...)
PermuteIterative(...)
Next(...)
NextRollTracking(...)
NextPoolTracking(...)
Next(...)
NextRollTracking(...)
NextPoolTracking(...)
Next(...)
NextRollTracking(...)
NextPoolTracking(...)
NextUnique(...)
NextUniqueRollTracking(...)
NextUniquePoolTracking(...)
NextUnique(...)
NextUniqueRollTracking(...)
NextUniquePoolTracking(...)
NextUnique(...)
NextUniqueRollTracking(...)
NextUniquePoolTracking(...)
NextUnique(...)
NextUniqueRollTracking(...)
NextUniquePoolTracking(...)
NextUnique(...)
NextUniqueRollTracking(...)
NextUniquePoolTracking(...)
NextUnique(...)
NextUniqueRollTracking(...)
NextUniquePoolTracking(...)
NextBool(...)
NextByte(...)
NextString(...)
NextString(...)
NextEnglishAlphaNumericString(...)
NextUpperCaseEnglishAlphaNumericString(...)
NextLowerCaseEnglishAlphaNumericString(...)
NumericEnglishString(...)
NextEnglishAlphabeticString(...)
NextUpperCaseEnglishAlphabeticString(...)
NextLowerCaseEnglishAlphabeticString(...)
NextChar(...)
NextChar(...)
NextDecimal(...)
NextDecimal(...)
NextDateTime(...)
NextDateTime(...)
NextDateTime(...)
NextTimeSpan(...)
NextTimeSpan(...)
NextTimeSpan(...)
Next(...)
NextRollTracking(...)
NextPoolTracking(...)
Next(...)
NextRollTracking(...)
NextPoolTracking(...)
Next(...)
NextRollTracking(...)
NextPoolTracking(...)
NextUnique(...)
NextUniqueRollTracking(...)
NextUniquePoolTracking(...)
NextUnique(...)
NextUniqueRollTracking(...)
NextUniquePoolTracking(...)
NextUnique(...)
NextUniqueRollTracking(...)
NextUniquePoolTracking(...)
NextUnique(...)
NextUniqueRollTracking(...)
NextUniquePoolTracking(...)
NextUnique(...)
NextUniqueRollTracking(...)
NextUniquePoolTracking(...)
NextUnique(...)
NextUniqueRollTracking(...)
NextUniquePoolTracking(...)
From(...)
From(...)
From(...)
Next(...)
Next(...)
Next(...)
.cctor()
TryParseRomanNumeral(...)
TryToRomanNumeral(...)
XML_SearchBinary()
SearchBinary(...)
SearchBinary(...)
SearchBinary(...)
SearchBinary(...)
SearchBinary(...)
SearchBinary(...)
.ctor(...)
op_Implicit(...)
op_Implicit(...)
op_Implicit(...)
.ctor(...)
.ctor(...)
.ctor(...)
.ctor(...)
.ctor(...)
BuildPath(...)
Invoke(...)
Invoke(...)
XML_SearchGraph()
XML_SearchGraph_Astar()
SearchGraph(...)
SearchGraph(...)
SearchGraph(...)
SearchGraph(...)
SearchGraph(...)
SearchGraph(...)
SearchGraph(...)
AStarSearch(...)
AStarSearch(...)
XML_SearchGraph_Dijkstra()
SearchGraph(...)
SearchGraph(...)
SearchGraph(...)
SearchGraph(...)
SearchGraph(...)
SearchGraph(...)
SearchGraph(...)
DijkstraSearch(...)
DijkstraSearch(...)
XML_SearchGraph_BreadthFirst()
SearchGraph(...)
SearchGraph(...)
SearchGraph(...)
SearchGraph(...)
SearchGraph(...)
SearchGraph(...)
SearchGraph(...)
PerformBredthFirstSearch(...)
PerformBredthFirstSearch(...)
EquateSequence(...)
EquateSequence(...)
EquateSequence(...)
EquateSet(...)
EquateSet(...)
EquateOccurences(...)
EquateOccurences(...)
XML_Maximum()
Maximum(...)
Maximum(...)
Maximum(...)
XML_MaximumValue_Two()
MaximumValue(...)
MaximumValue(...)
XML_MaximumValue()
MaximumValue(...)
MaximumValue(...)
MaximumValue(...)
MaximumIndex(...)
XML_MaximumIndex()
MaximumIndex(...)
MaximumIndex(...)
MaximumIndex(...)
XML_Minimum()
Minimum(...)
Minimum(...)
Minimum(...)
XML_MinimumValue_Two()
MinimumValue(...)
MinimumValue(...)
XML_MinimumValue()
MinimumValue(...)
MinimumValue(...)
MinimumValue(...)
XML_MinimumIndex()
MinimumIndex(...)
MinimumIndex(...)
MinimumIndex(...)
Range(...)
Range(...)
Range(...)
Mode(...)
Mode(...)
Mode(...)
Mode(...)
Mode(...)
Mean(...)
Mean(...)
Median(...)
Median(...)
Median(...)
Median(...)
GeometricMean(...)
Variance(...)
StandardDeviation(...)
MeanDeviation(...)
Quantiles(...)
Occurences(...)
Occurences(...)
Occurences(...)
Occurences(...)
Occurences(...)
HammingDistance(...)
HammingDistance(...)
HammingDistance(...)
LevenshteinDistanceRecursive(...)
LevenshteinDistanceRecursive(...)
LevenshteinDistanceRecursive(...)
LevenshteinDistanceIterative(...)
LevenshteinDistanceIterative(...)
LevenshteinDistanceIterative(...)
XML_FilterOrdered()
XML_FilterOrderedEnumerable()
FilterOrdered(...)
FilterOrdered(...)
FilterOrdered(...)
FilterOrdered(...)
FilterOrdered(...)
FilterOrdered()
XML_IsOrdered()
IsOrdered(...)
IsOrdered(...)
IsOrdered(...)
IsOrdered(...)
IsOrdered(...)
IsOrdered(...)
XML_IsPalindrome()
IsPalindrome(...)
IsPalindrome(...)
IsPalindrome(...)
IsPalindrome(...)
IsPalindrome(...)
XML_IsInterleaved()
XML_IsInterleavedRecursive()
XML_IsInterleavedIterative()
IsInterleavedRecursive(...)
IsInterleavedRecursive(...)
IsInterleavedRecursive(...)
IsInterleavedIterative(...)
IsInterleavedIterative(...)
IsInterleavedIterative(...)
IsReorderOf(...)
IsReorderOf(...)
ContainsDuplicates(...)
ContainsDuplicates(...)
Contains(...)
Contains(...)
Any(...)
Any(...)
GetLeast(...)
GetLeast(...)
GetGreatest(...)
GetGreatest(...)
GetGreatest(...)
GetGreatest(...)
GetLeast(...)
GetLeast(...)
CombineRanges(...)
Reverse(...)
Reverse(...)
XML_Shuffle()
Shuffle(...)
Shuffle(...)
Shuffle(...)
Shuffle(...)
Shuffle(...)
XML_Sort()
XML_SortBubble()
SortBubble(...)
SortBubble(...)
SortBubble(...)
SortBubble(...)
XML_SortSelection()
SortSelection(...)
SortSelection(...)
SortSelection(...)
SortSelection(...)
XML_SortInsertion()
SortInsertion(...)
SortInsertion(...)
SortInsertion(...)
SortInsertion(...)
XML_SortQuick()
SortQuick(...)
SortQuick(...)
SortQuick(...)
SortQuick(...)
XML_SortMerge()
SortMerge(...)
SortMerge(...)
SortMerge(...)
SortMerge(...)
XML_SortHeap()
SortHeap(...)
SortHeap(...)
SortHeap(...)
SortHeap(...)
XML_SortOddEven()
SortOddEven(...)
SortOddEven(...)
SortOddEven(...)
SortOddEven(...)
XML_SortBogo()
SortBogo(...)
SortBogo(...)
SortBogo(...)
SortBogo(...)
SortBogo(...)
SortBogo(...)
XML_SortSlow()
SortSlow(...)
SortSlow(...)
SortSlow(...)
SortSlow(...)
XML_SortGnome()
SortGnome(...)
SortGnome(...)
SortGnome(...)
SortGnome(...)
XML_SortComb()
SortComb(...)
SortComb(...)
SortComb(...)
SortComb(...)
XML_SortShell()
SortShell(...)
SortShell(...)
SortShell(...)
SortShell(...)
XML_SortCocktail()
SortCocktail(...)
SortCocktail(...)
SortCocktail(...)
SortCocktail(...)
XML_SortCycle()
SortCycle(...)
SortCycle(...)
SortCycle(...)
SortCycle(...)
XML_SortPancake()
SortPancake(...)
SortPancake(...)
SortPancake(...)
SortPancake(...)
XML_SortStooge()
SortStooge(...)
SortStooge(...)
SortStooge(...)
SortStooge(...)
XML_SortTim()
SortTim(...)
SortTim(...)
SortTim(...)
SortTim(...)
SortCounting(...)
SortCounting(...)
SortCounting(...)
SortCounting(...)
SortCounting(...)
SortCounting(...)
SortCounting(...)
SortCounting(...)
SortCounting(...)
SortRadix(...)
SortRadix(...)
SortRadix(...)
SortRadix(...)
SortRadix(...)
SortRadix(...)
SortRadix(...)
Invoke(...)
SortPidgeonHole(...)
SortPidgeonHole(...)
SortPidgeonHole(...)
XML_SortIntro()
SortIntro(...)
SortIntro(...)
SortIntro(...)
PickPivotAndPartition(...)
SortIntro(...)
SortIntro(...)
SortIntro(...)
PickPivotAndPartition(...)
Invoke(...)
Invoke(...)
Invoke(...)
Invoke(...)
Invoke(...)
Invoke(...)
op_Implicit(...)
Invoke(...)
Invoke(...)
Invoke(...)
Invoke(...)
Invoke(...)
Invoke(...)
op_Implicit(...)
Invoke(...)
op_Implicit(...)
Invoke(...)
.ctor(...)
Invoke(...)
.ctor(...)
Invoke()
Invoke(...)
op_Implicit(...)
Invoke(...)
op_Implicit(...)
Invoke(...)
op_Implicit(...)
Invoke(...)
op_Implicit(...)
Invoke(...)
op_Implicit(...)
Switch(...)
Switch(...)
Do(...)
Do(...)
op_Implicit(...)
op_Implicit(...)
op_Implicit(...)
Resolve(...)
.ctor(...)
Resolve(...)
Resolve(...)
op_Implicit(...)
op_Implicit(...)
op_Implicit(...)
Resolve()
Resolve()
get_Chance()
op_Modulus(...)
op_Implicit(...)
op_GreaterThan(...)
op_LessThan(...)
op_GreaterThanOrEqual(...)
op_LessThanOrEqual(...)
op_Equality(...)
op_Inequality(...)
ToString()
Equals(...)
GetHashCode()
.ctor(...)
op_Implicit(...)
op_GreaterThan(...)
op_LessThan(...)
op_GreaterThanOrEqual(...)
op_LessThanOrEqual(...)
op_Equality(...)
op_Inequality(...)
ToString()
Equals(...)
GetHashCode()
Ɐ(...)
.ctor(...)
get_Length()
StepperBreak(...)
ToArray()
get_Item(...)
set_Item(...)
get_Count()
get_IsReadOnly()
Add(...)
Clear()
Contains(...)
CopyTo(...)
IndexOf(...)
Insert(...)
Remove(...)
RemoveAt(...)
GetEnumerator()
System.Collections.IEnumerable.GetEnumerator()
op_Implicit(...)
op_Implicit(...)
op_Implicit(...)
op_Implicit(...)
op_Implicit(...)
op_Implicit(...)
op_Implicit(...)
op_Implicit(...)
op_Implicit(...)
op_Implicit(...)
op_Implicit(...)
op_Implicit(...)
op_Implicit(...)
op_Implicit(...)
op_Implicit(...)
op_Implicit(...)
SineTaylorSeries(...)
SineSystem(...)
SineQuadratic(...)
CosineTaylorSeries(...)
CosineSystem(...)
CosineQuadratic(...)
TangentTaylorSeries(...)
TangentSystem(...)
TangentQuadratic(...)
CosecantSystem(...)
CosecantQuadratic(...)
SecantSystem(...)
SecantQuadratic(...)
CotangentSystem(...)
CotangentQuadratic(...)
GetEnumerator()
GetEnumerator()
GetEnumerator()
GetEnumerator()
GetEnumerator()
GetEnumerator()
GetEnumerator()
GetEnumerator()
GetEnumerator()
GetEnumerator()
GetEnumerator()
GetEnumerator()
GetEnumerator()
GetEnumerator()
GetEnumerator()
.cctor()
.cctor()
OperationOnStepper(...)
Swap(...)
Swap(...)
sourcedirectory(...)
sourcefilepath(...)
sourcemembername(...)
sourcelinenumber(...)
sourceof(...)
sourceof(...)
TryParse(...)
.cctor()
Hash(...)
Convert(...)
.cctor()
Join(...)
Equate(...)
Equate(...)
.cctor()
Inequate(...)
Inequate(...)
.cctor()
LessThan(...)
LessThan(...)
.cctor()
GreaterThan(...)
GreaterThan(...)
.cctor()
LessThanOrEqual(...)
LessThanOrEqual(...)
.cctor()
GreaterThanOrEqual(...)
GreaterThanOrEqual(...)
.cctor()
Compare(...)
.cctor()
Negation(...)
Negation(...)
.cctor()
Addition(...)
Addition(...)
Addition(...)
Addition(...)
.cctor()
Subtraction(...)
Subtraction(...)
Subtraction(...)
Subtraction(...)
.cctor()
Multiplication(...)
Multiplication(...)
Multiplication(...)
Multiplication(...)
.cctor()
Division(...)
Division(...)
Division(...)
Division(...)
.cctor()
Remainder(...)
Remainder(...)
Remainder(...)
Remainder(...)
.cctor()
Inversion(...)
Power(...)
Power(...)
Power(...)
.cctor()
SquareRoot(...)
.cctor()
Root(...)
Logarithm(...)
.cctor()
IsInteger(...)
.cctor()
IsNonNegative(...)
.cctor()
IsNegative(...)
.cctor()
IsPositive(...)
.cctor()
IsEven(...)
.cctor()
IsOdd(...)
.cctor()
IsPrime(...)
.cctor()
AbsoluteValue(...)
.cctor()
Clamp(...)
EqualToLeniency(...)
.cctor()
GreatestCommonFactor(...)
GreatestCommonFactor(...)
LeastCommonMultiple(...)
LeastCommonMultiple(...)
LinearInterpolation(...)
Factorial(...)
.cctor()
CombinationsCount(...)
BinomialCoefficient(...)
Exponential(...)
NaturalLogarithm(...)
.cctor()
LinearRegression2D(...)
FactorPrimes(...)
.cctor()