@@ -730,10 +730,9 @@ static void Recursive(in PowersOf1e9 powersOf1e9, ReadOnlySpan<byte> digits, Spa
730730 Recursive ( powersOf1e9 , digitsUpper , upperBuffer ) ;
731731 upperBuffer = upperBuffer . Slice ( 0 , BigIntegerCalculator . ActualLength ( upperBuffer ) ) ;
732732 ReadOnlySpan < uint > multiplier = powersOf1e9 . GetSpan ( log2 ) ;
733- Span < uint > bitsUpper = bits . Slice ( 0 , upperBuffer . Length + multiplier . Length ) ;
734-
735733 int multiplierTrailingZeroCountUInt32 = ( MaxPartialDigits * ( 1 << log2 ) ) >> 5 ;
736- multiplier = multiplier . Slice ( multiplierTrailingZeroCountUInt32 ) ;
734+
735+ Span < uint > bitsUpper = bits . Slice ( 0 , upperBuffer . Length + multiplier . Length + multiplierTrailingZeroCountUInt32 ) ;
737736 bitsUpper = bitsUpper . Slice ( multiplierTrailingZeroCountUInt32 ) ;
738737
739738 if ( multiplier . Length < upperBuffer . Length )
@@ -896,41 +895,42 @@ internal readonly ref struct PowersOf1e9
896895 // for (int i = 0; i + 1 < indexes.Length; i++)
897896 // {
898897 // int length = unchecked((int)(digitRatio * (1 << i)) + 1);
898+ // length -= (9*(1<<i)) >> 5;
899899 // indexes[i+1] = indexes[i] + length;
900900 // }
901901 private static ReadOnlySpan < int > Indexes => new int [ ] {
902902 0 ,
903903 1 ,
904904 3 ,
905- 7 ,
906- 15 ,
907- 30 ,
908- 60 ,
909- 120 ,
910- 240 ,
911- 480 ,
912- 959 ,
913- 1916 ,
914- 3830 ,
915- 7657 ,
916- 15311 ,
917- 30619 ,
918- 61234 ,
919- 122464 ,
920- 244924 ,
921- 489844 ,
922- 979683 ,
923- 1959360 ,
924- 3918713 ,
925- 7837419 ,
926- 15674831 ,
927- 31349655 ,
928- 62699302 ,
929- 125398596 ,
930- 250797183 ,
931- 501594357 ,
932- 1003188704 ,
933- 2006377398 ,
905+ 6 ,
906+ 12 ,
907+ 23 ,
908+ 44 ,
909+ 86 ,
910+ 170 ,
911+ 338 ,
912+ 673 ,
913+ 1342 ,
914+ 2680 ,
915+ 5355 ,
916+ 10705 ,
917+ 21405 ,
918+ 42804 ,
919+ 85602 ,
920+ 171198 ,
921+ 342390 ,
922+ 684773 ,
923+ 1369538 ,
924+ 2739067 ,
925+ 5478125 ,
926+ 10956241 ,
927+ 21912473 ,
928+ 43824936 ,
929+ 87649862 ,
930+ 175299713 ,
931+ 484817143 ,
932+ 969634274 ,
933+ 1939268536 ,
934934 } ;
935935
936936 public PowersOf1e9 ( Span < uint > pow1E9 )
@@ -948,14 +948,29 @@ public PowersOf1e9(Span<uint> pow1E9)
948948 break ;
949949 Span < uint > dst = pow1E9 . Slice ( toExclusive , src . Length << 1 ) ;
950950 BigIntegerCalculator . Square ( src , dst ) ;
951+ if ( dst [ 0 ] == 0 )
952+ {
953+ dst . Slice ( 1 ) . CopyTo ( dst ) ;
954+ dst [ ^ 1 ] = 0 ;
955+ }
951956 int from = toExclusive ;
952957 toExclusive = Indexes [ i + 1 ] ;
953958 src = pow1E9 . Slice ( from , toExclusive - from ) ;
959+ Debug . Assert ( toExclusive == pow1E9 . Length || pow1E9 [ toExclusive ] == 0 ) ;
960+ }
961+ #if DEBUG
962+ for ( int i = 0 ; i + 1 < Indexes . Length ; i ++ )
963+ {
964+ int startIndex = Indexes [ i ] ;
965+ int endIndex = Indexes [ i + 1 ] ;
966+ if ( endIndex >= pow1E9 . Length ) break ;
967+ Debug . Assert ( pow1E9 [ startIndex ] != 0 ) ;
954968 }
969+ #endif
955970 }
956971 public ReadOnlySpan < uint > GetSpan ( int index )
957972 {
958- // Returns 1E9^(1<<index)
973+ // Returns 1E9^(1<<index) >> (32*(9*(1<<index)/32)
959974 int from = Indexes [ index ] ;
960975 int toExclusive = Indexes [ index + 1 ] ;
961976 return pow1E9 [ from ..toExclusive ] ;
@@ -1007,36 +1022,35 @@ public void CalculatePowerOfTen(int trailingZeroCount, Span<uint> bits)
10071022 // Copy first
10081023 int fi = BitOperations . TrailingZeroCount ( trailingPartialCount ) ;
10091024 {
1010- ReadOnlySpan < uint > first = GetSpan ( fi ) ;
1011- first . CopyTo ( curBits ) ;
1012- curLength = first . Length ;
10131025 curTrailingZeroCount = MaxPartialDigits * ( 1 << fi ) ;
10141026 trailingPartialCount >>= fi ;
10151027 trailingPartialCount >>= 1 ;
1028+
1029+ ReadOnlySpan < uint > first = GetSpan ( fi ) ;
1030+ first . CopyTo ( curBits . Slice ( curTrailingZeroCount >> 5 ) ) ;
1031+
1032+ curLength = first . Length ;
10161033 }
10171034
10181035
10191036 for ( int i = fi + 1 ; trailingPartialCount != 0 && i + 1 < Indexes . Length ; i ++ , trailingPartialCount >>= 1 )
10201037 {
1021- Debug . Assert ( GetSpan ( i ) . Length >= curLength ) ;
1038+ Debug . Assert ( GetSpan ( i ) . Length >= curLength - ( curTrailingZeroCount >> 5 ) ) ;
10221039 if ( ( trailingPartialCount & 1 ) != 0 )
10231040 {
1024- ReadOnlySpan < uint > power = GetSpan ( i ) ;
1025- Span < uint > src = curBits . Slice ( 0 , curLength ) ;
1026- Span < uint > dst = otherBits . Slice ( 0 , curLength += power . Length ) ;
1027-
10281041 int powerTrailingZeroCount = MaxPartialDigits * ( 1 << i ) ;
10291042 int powerTrailingZeroCountUInt32 = powerTrailingZeroCount >> 5 ;
10301043 int curTrailingZeroCountUInt32 = curTrailingZeroCount >> 5 ;
10311044
1032- Debug . Assert ( powerTrailingZeroCountUInt32 < power . Length
1033- && power . Slice ( 0 , powerTrailingZeroCountUInt32 ) . Trim ( 0u ) . Length == 0
1034- && power [ powerTrailingZeroCountUInt32 ] != 0 ) ;
1045+ ReadOnlySpan < uint > power = GetSpan ( i ) ;
1046+ Span < uint > src = curBits . Slice ( 0 , curLength ) ;
1047+ Span < uint > dst = otherBits . Slice ( 0 , curLength += power . Length + powerTrailingZeroCountUInt32 ) ;
1048+
10351049 Debug . Assert ( curTrailingZeroCountUInt32 < src . Length
10361050 && src . Slice ( 0 , curTrailingZeroCountUInt32 ) . Trim ( 0u ) . Length == 0
10371051 && src [ curTrailingZeroCountUInt32 ] != 0 ) ;
10381052
1039- BigIntegerCalculator . Multiply ( power . Slice ( powerTrailingZeroCountUInt32 ) , src . Slice ( curTrailingZeroCountUInt32 ) , dst . Slice ( powerTrailingZeroCountUInt32 + curTrailingZeroCountUInt32 ) ) ;
1053+ BigIntegerCalculator . Multiply ( power , src . Slice ( curTrailingZeroCountUInt32 ) , dst . Slice ( powerTrailingZeroCountUInt32 + curTrailingZeroCountUInt32 ) ) ;
10401054
10411055 curTrailingZeroCount += powerTrailingZeroCount ;
10421056
0 commit comments