diff --git a/src/libraries/System.Runtime.Numerics/src/System/Number.BigInteger.cs b/src/libraries/System.Runtime.Numerics/src/System/Number.BigInteger.cs index 1e75a83cf1838e..02d25c09283eef 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Number.BigInteger.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Number.BigInteger.cs @@ -403,8 +403,7 @@ static void DivideAndConquer(ReadOnlySpan base1E9, int totalDigitCount, in { int valueDigits = (base1E9.Length - 1) * PowersOf1e9.MaxPartialDigits + FormattingHelpers.CountDigits(base1E9[^1]); - int log2 = PowersOf1e9.GetMaxIndex(Math.Max(valueDigits, trailingZeroCount + 1)); - int powersOf1e9BufferLength = PowersOf1e9.GetBufferSize(log2); + int powersOf1e9BufferLength = PowersOf1e9.GetBufferSize(Math.Max(valueDigits, trailingZeroCount + 1), out int maxIndex); uint[]? powersOf1e9BufferFromPool = null; Span powersOf1e9Buffer = ( powersOf1e9BufferLength <= BigIntegerCalculator.StackAllocThreshold @@ -424,7 +423,7 @@ static void DivideAndConquer(ReadOnlySpan base1E9, int totalDigitCount, in : leadingFromPool = ArrayPool.Shared.Rent(leadingLength)).Slice(0, leadingLength); leading.Clear(); - Recursive(powersOf1e9, log2, base1E9, leading); + Recursive(powersOf1e9, maxIndex, base1E9, leading); leading = leading.Slice(0, BigIntegerCalculator.ActualLength(leading)); powersOf1e9.MultiplyPowerOfTen(leading, trailingZeroCount, bits); @@ -434,7 +433,7 @@ static void DivideAndConquer(ReadOnlySpan base1E9, int totalDigitCount, in } else { - Recursive(powersOf1e9, log2, base1E9, bits); + Recursive(powersOf1e9, maxIndex, base1E9, bits); } if (powersOf1e9BufferFromPool != null) @@ -461,12 +460,6 @@ static void Recursive(in PowersOf1e9 powersOf1e9, int powersOf1e9Index, ReadOnly ReadOnlySpan multiplier = powersOf1e9.GetSpan(powersOf1e9Index); int multiplierTrailingZeroCount = PowersOf1e9.OmittedLength(powersOf1e9Index); - if (multiplier1E9Length + multiplier1E9Length < base1E9.Length) - { - RecursiveLarge(powersOf1e9, powersOf1e9Index, base1E9, bits); - return; - } - Debug.Assert(multiplier1E9Length < base1E9.Length && base1E9.Length <= multiplier1E9Length * 2); int bufferLength = checked((int)(digitRatio * PowersOf1e9.MaxPartialDigits * multiplier1E9Length) + 1 + 2); @@ -496,67 +489,6 @@ static void Recursive(in PowersOf1e9 powersOf1e9, int powersOf1e9Index, ReadOnly ArrayPool.Shared.Return(bufferFromPool); } - [MethodImpl(MethodImplOptions.NoInlining)] - static void RecursiveLarge( - in PowersOf1e9 powersOf1e9, int powersOf1e9Index, - ReadOnlySpan base1E9, scoped Span bits) - { - int multiplier1E9Length = 1 << powersOf1e9Index; - ReadOnlySpan multiplier = powersOf1e9.GetSpan(powersOf1e9Index); - int multiplierTrailingZeroCount = PowersOf1e9.OmittedLength(powersOf1e9Index); - - Span bitsDst = bits; - - uint[]? bits2FromPool = null; - scoped Span bits2 = ( - bits.Length <= BigIntegerCalculator.StackAllocThreshold - ? stackalloc uint[BigIntegerCalculator.StackAllocThreshold] - : bits2FromPool = ArrayPool.Shared.Rent(bits.Length)).Slice(0, bits.Length); - bits2.Clear(); - - { - int upperLength = base1E9.Length & (multiplier1E9Length - 1); - if (upperLength == 0) - upperLength = multiplier1E9Length; - - Recursive(powersOf1e9, powersOf1e9Index - 1, base1E9[^upperLength..], bits2); - - base1E9 = base1E9[..^upperLength]; - } - - while (base1E9.Length > 0) - { - ReadOnlySpan bitsPrev = bits2.Slice(0, BigIntegerCalculator.ActualLength(bits2)); - - Debug.Assert(base1E9.Length % multiplier1E9Length == 0); - Span bitsUpper = bits.Slice(multiplierTrailingZeroCount, bitsPrev.Length + multiplier.Length); - if (multiplier.Length < bitsPrev.Length) - BigIntegerCalculator.Multiply(bitsPrev, multiplier, bitsUpper); - else - BigIntegerCalculator.Multiply(multiplier, bitsPrev, bitsUpper); - - bits2.Clear(); - Recursive(powersOf1e9, powersOf1e9Index - 1, base1E9[^multiplier1E9Length..], bits2); - - BigIntegerCalculator.AddSelf(bits, bits2); - - base1E9 = base1E9[..^multiplier1E9Length]; - - Span bitsTmp = bits; - bits = bits2; - bits2 = bitsTmp; - bits.Clear(); - } - - if (!Unsafe.AreSame(ref MemoryMarshal.GetReference(bits2), ref MemoryMarshal.GetReference(bitsDst))) - { - bits2.CopyTo(bitsDst); - } - - if (bits2FromPool != null) - ArrayPool.Shared.Return(bits2FromPool); - } - static void Naive(ReadOnlySpan base1E9, int trailingZeroCount, scoped Span bits) { if (base1E9.Length == 0) @@ -1024,11 +956,6 @@ internal readonly ref struct PowersOf1e9 // indexes[i+1] = indexes[i] + length; // } private static ReadOnlySpan Indexes => -#if DEBUG - IndexesArray; - - public static int[] IndexesArray = -#endif [ 0, 1, @@ -1151,16 +1078,21 @@ public PowersOf1e9(Span pow1E9) } } - public static int GetMaxIndex(int digits) + public static int GetBufferSize(int digits, out int maxIndex) { uint scale1E9 = (uint)(digits - 1) / MaxPartialDigits; - return BitOperations.Log2(scale1E9); - } + maxIndex = BitOperations.Log2(scale1E9); + int index = maxIndex + 1; + int bufferSize; + if ((uint)index < (uint)Indexes.Length) + bufferSize = Indexes[index]; + else + { + maxIndex = Indexes.Length - 2; + bufferSize = Indexes[^1]; + } - public static int GetBufferSize(int index) - { - ++index; - return ((uint)index < (uint)Indexes.Length ? Indexes[index] : Indexes[^1]) + 1; + return ++bufferSize; } public ReadOnlySpan GetSpan(int index) diff --git a/src/libraries/System.Runtime.Numerics/tests/BigInteger/parse.cs b/src/libraries/System.Runtime.Numerics/tests/BigInteger/parse.cs index 25eae190a96e6a..85a2fcd182af7a 100644 --- a/src/libraries/System.Runtime.Numerics/tests/BigInteger/parse.cs +++ b/src/libraries/System.Runtime.Numerics/tests/BigInteger/parse.cs @@ -1220,28 +1220,5 @@ public static void RegressionIssueRuntime94610(string text) parseTest.RegressionIssueRuntime94610(text); })); } - - [Theory] - [MemberData(nameof(Cultures))] - [OuterLoop] - public static void Parse_RecursiveLarge(CultureInfo culture) - { -#if DEBUG - int[] defaultIndexesArray = Number.PowersOf1e9.IndexesArray; - try - { - Number.PowersOf1e9.IndexesArray = defaultIndexesArray[..4]; - BigIntTools.Utils.RunWithFakeThreshold(Number.BigIntegerParseNaiveThreshold, 0, () => - BigIntTools.Utils.RunWithFakeThreshold(Number.BigIntegerParseNaiveThresholdInRecursive, 10, () => - { - parseTest.RunParseToStringTests(culture); - })); - } - finally - { - Number.PowersOf1e9.IndexesArray = defaultIndexesArray; - } -#endif - } } }