@@ -403,8 +403,7 @@ static void DivideAndConquer(ReadOnlySpan<uint> base1E9, int totalDigitCount, in
403403 {
404404 int valueDigits = ( base1E9 . Length - 1 ) * PowersOf1e9 . MaxPartialDigits + FormattingHelpers . CountDigits ( base1E9 [ ^ 1 ] ) ;
405405
406- int log2 = PowersOf1e9 . GetMaxIndex ( Math . Max ( valueDigits , trailingZeroCount + 1 ) ) ;
407- int powersOf1e9BufferLength = PowersOf1e9 . GetBufferSize ( log2 ) ;
406+ int powersOf1e9BufferLength = PowersOf1e9 . GetBufferSize ( Math . Max ( valueDigits , trailingZeroCount + 1 ) , out int maxIndex ) ;
408407 uint [ ] ? powersOf1e9BufferFromPool = null ;
409408 Span < uint > powersOf1e9Buffer = (
410409 powersOf1e9BufferLength <= BigIntegerCalculator . StackAllocThreshold
@@ -424,7 +423,7 @@ static void DivideAndConquer(ReadOnlySpan<uint> base1E9, int totalDigitCount, in
424423 : leadingFromPool = ArrayPool < uint > . Shared . Rent ( leadingLength ) ) . Slice ( 0 , leadingLength ) ;
425424 leading . Clear ( ) ;
426425
427- Recursive ( powersOf1e9 , log2 , base1E9 , leading ) ;
426+ Recursive ( powersOf1e9 , maxIndex , base1E9 , leading ) ;
428427 leading = leading . Slice ( 0 , BigIntegerCalculator . ActualLength ( leading ) ) ;
429428
430429 powersOf1e9 . MultiplyPowerOfTen ( leading , trailingZeroCount , bits ) ;
@@ -434,7 +433,7 @@ static void DivideAndConquer(ReadOnlySpan<uint> base1E9, int totalDigitCount, in
434433 }
435434 else
436435 {
437- Recursive ( powersOf1e9 , log2 , base1E9 , bits ) ;
436+ Recursive ( powersOf1e9 , maxIndex , base1E9 , bits ) ;
438437 }
439438
440439 if ( powersOf1e9BufferFromPool != null )
@@ -461,12 +460,6 @@ static void Recursive(in PowersOf1e9 powersOf1e9, int powersOf1e9Index, ReadOnly
461460 ReadOnlySpan < uint > multiplier = powersOf1e9 . GetSpan ( powersOf1e9Index ) ;
462461 int multiplierTrailingZeroCount = PowersOf1e9 . OmittedLength ( powersOf1e9Index ) ;
463462
464- if ( multiplier1E9Length + multiplier1E9Length < base1E9 . Length )
465- {
466- RecursiveLarge ( powersOf1e9 , powersOf1e9Index , base1E9 , bits ) ;
467- return ;
468- }
469-
470463 Debug . Assert ( multiplier1E9Length < base1E9 . Length && base1E9 . Length <= multiplier1E9Length * 2 ) ;
471464
472465 int bufferLength = checked ( ( int ) ( digitRatio * PowersOf1e9 . MaxPartialDigits * multiplier1E9Length ) + 1 + 2 ) ;
@@ -496,67 +489,6 @@ static void Recursive(in PowersOf1e9 powersOf1e9, int powersOf1e9Index, ReadOnly
496489 ArrayPool < uint > . Shared . Return ( bufferFromPool ) ;
497490 }
498491
499- [ MethodImpl ( MethodImplOptions . NoInlining ) ]
500- static void RecursiveLarge (
501- in PowersOf1e9 powersOf1e9 , int powersOf1e9Index ,
502- ReadOnlySpan < uint > base1E9 , scoped Span < uint > bits )
503- {
504- int multiplier1E9Length = 1 << powersOf1e9Index ;
505- ReadOnlySpan < uint > multiplier = powersOf1e9 . GetSpan ( powersOf1e9Index ) ;
506- int multiplierTrailingZeroCount = PowersOf1e9 . OmittedLength ( powersOf1e9Index ) ;
507-
508- Span < uint > bitsDst = bits ;
509-
510- uint [ ] ? bits2FromPool = null ;
511- scoped Span < uint > bits2 = (
512- bits . Length <= BigIntegerCalculator . StackAllocThreshold
513- ? stackalloc uint [ BigIntegerCalculator . StackAllocThreshold ]
514- : bits2FromPool = ArrayPool < uint > . Shared . Rent ( bits . Length ) ) . Slice ( 0 , bits . Length ) ;
515- bits2 . Clear ( ) ;
516-
517- {
518- int upperLength = base1E9 . Length & ( multiplier1E9Length - 1 ) ;
519- if ( upperLength == 0 )
520- upperLength = multiplier1E9Length ;
521-
522- Recursive ( powersOf1e9 , powersOf1e9Index - 1 , base1E9 [ ^ upperLength ..] , bits2 ) ;
523-
524- base1E9 = base1E9 [ ..^ upperLength ] ;
525- }
526-
527- while ( base1E9 . Length > 0 )
528- {
529- ReadOnlySpan < uint > bitsPrev = bits2 . Slice ( 0 , BigIntegerCalculator . ActualLength ( bits2 ) ) ;
530-
531- Debug . Assert ( base1E9 . Length % multiplier1E9Length == 0 ) ;
532- Span < uint > bitsUpper = bits . Slice ( multiplierTrailingZeroCount , bitsPrev . Length + multiplier . Length ) ;
533- if ( multiplier . Length < bitsPrev . Length )
534- BigIntegerCalculator . Multiply ( bitsPrev , multiplier , bitsUpper ) ;
535- else
536- BigIntegerCalculator . Multiply ( multiplier , bitsPrev , bitsUpper ) ;
537-
538- bits2 . Clear ( ) ;
539- Recursive ( powersOf1e9 , powersOf1e9Index - 1 , base1E9 [ ^ multiplier1E9Length ..] , bits2 ) ;
540-
541- BigIntegerCalculator . AddSelf ( bits , bits2 ) ;
542-
543- base1E9 = base1E9 [ ..^ multiplier1E9Length ] ;
544-
545- Span < uint > bitsTmp = bits ;
546- bits = bits2 ;
547- bits2 = bitsTmp ;
548- bits . Clear ( ) ;
549- }
550-
551- if ( ! Unsafe . AreSame ( ref MemoryMarshal . GetReference ( bits2 ) , ref MemoryMarshal . GetReference ( bitsDst ) ) )
552- {
553- bits2 . CopyTo ( bitsDst ) ;
554- }
555-
556- if ( bits2FromPool != null )
557- ArrayPool < uint > . Shared . Return ( bits2FromPool ) ;
558- }
559-
560492 static void Naive ( ReadOnlySpan < uint > base1E9 , int trailingZeroCount , scoped Span < uint > bits )
561493 {
562494 if ( base1E9 . Length == 0 )
@@ -1024,11 +956,6 @@ internal readonly ref struct PowersOf1e9
1024956 // indexes[i+1] = indexes[i] + length;
1025957 // }
1026958 private static ReadOnlySpan < int > Indexes =>
1027- #if DEBUG
1028- IndexesArray ;
1029-
1030- public static int [ ] IndexesArray =
1031- #endif
1032959 [
1033960 0 ,
1034961 1 ,
@@ -1151,16 +1078,21 @@ public PowersOf1e9(Span<uint> pow1E9)
11511078 }
11521079 }
11531080
1154- public static int GetMaxIndex ( int digits )
1081+ public static int GetBufferSize ( int digits , out int maxIndex )
11551082 {
11561083 uint scale1E9 = ( uint ) ( digits - 1 ) / MaxPartialDigits ;
1157- return BitOperations . Log2 ( scale1E9 ) ;
1158- }
1084+ maxIndex = BitOperations . Log2 ( scale1E9 ) ;
1085+ int index = maxIndex + 1 ;
1086+ int bufferSize ;
1087+ if ( ( uint ) index < ( uint ) Indexes . Length )
1088+ bufferSize = Indexes [ index ] ;
1089+ else
1090+ {
1091+ maxIndex = Indexes . Length - 2 ;
1092+ bufferSize = Indexes [ ^ 1 ] ;
1093+ }
11591094
1160- public static int GetBufferSize ( int index )
1161- {
1162- ++ index ;
1163- return ( ( uint ) index < ( uint ) Indexes . Length ? Indexes [ index ] : Indexes [ ^ 1 ] ) + 1 ;
1095+ return ++ bufferSize ;
11641096 }
11651097
11661098 public ReadOnlySpan < uint > GetSpan ( int index )
0 commit comments