@@ -730,10 +730,9 @@ static void Recursive(in PowersOf1e9 powersOf1e9, ReadOnlySpan<byte> digits, Spa
730
730
Recursive ( powersOf1e9 , digitsUpper , upperBuffer ) ;
731
731
upperBuffer = upperBuffer . Slice ( 0 , BigIntegerCalculator . ActualLength ( upperBuffer ) ) ;
732
732
ReadOnlySpan < uint > multiplier = powersOf1e9 . GetSpan ( log2 ) ;
733
- Span < uint > bitsUpper = bits . Slice ( 0 , upperBuffer . Length + multiplier . Length ) ;
734
-
735
733
int multiplierTrailingZeroCountUInt32 = ( MaxPartialDigits * ( 1 << log2 ) ) >> 5 ;
736
- multiplier = multiplier . Slice ( multiplierTrailingZeroCountUInt32 ) ;
734
+
735
+ Span < uint > bitsUpper = bits . Slice ( 0 , upperBuffer . Length + multiplier . Length + multiplierTrailingZeroCountUInt32 ) ;
737
736
bitsUpper = bitsUpper . Slice ( multiplierTrailingZeroCountUInt32 ) ;
738
737
739
738
if ( multiplier . Length < upperBuffer . Length )
@@ -896,41 +895,42 @@ internal readonly ref struct PowersOf1e9
896
895
// for (int i = 0; i + 1 < indexes.Length; i++)
897
896
// {
898
897
// int length = unchecked((int)(digitRatio * (1 << i)) + 1);
898
+ // length -= (9*(1<<i)) >> 5;
899
899
// indexes[i+1] = indexes[i] + length;
900
900
// }
901
901
private static ReadOnlySpan < int > Indexes => new int [ ] {
902
902
0 ,
903
903
1 ,
904
904
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 ,
934
934
} ;
935
935
936
936
public PowersOf1e9 ( Span < uint > pow1E9 )
@@ -948,14 +948,29 @@ public PowersOf1e9(Span<uint> pow1E9)
948
948
break ;
949
949
Span < uint > dst = pow1E9 . Slice ( toExclusive , src . Length << 1 ) ;
950
950
BigIntegerCalculator . Square ( src , dst ) ;
951
+ if ( dst [ 0 ] == 0 )
952
+ {
953
+ dst . Slice ( 1 ) . CopyTo ( dst ) ;
954
+ dst [ ^ 1 ] = 0 ;
955
+ }
951
956
int from = toExclusive ;
952
957
toExclusive = Indexes [ i + 1 ] ;
953
958
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 ) ;
954
968
}
969
+ #endif
955
970
}
956
971
public ReadOnlySpan < uint > GetSpan ( int index )
957
972
{
958
- // Returns 1E9^(1<<index)
973
+ // Returns 1E9^(1<<index) >> (32*(9*(1<<index)/32)
959
974
int from = Indexes [ index ] ;
960
975
int toExclusive = Indexes [ index + 1 ] ;
961
976
return pow1E9 [ from ..toExclusive ] ;
@@ -1007,36 +1022,35 @@ public void CalculatePowerOfTen(int trailingZeroCount, Span<uint> bits)
1007
1022
// Copy first
1008
1023
int fi = BitOperations . TrailingZeroCount ( trailingPartialCount ) ;
1009
1024
{
1010
- ReadOnlySpan < uint > first = GetSpan ( fi ) ;
1011
- first . CopyTo ( curBits ) ;
1012
- curLength = first . Length ;
1013
1025
curTrailingZeroCount = MaxPartialDigits * ( 1 << fi ) ;
1014
1026
trailingPartialCount >>= fi ;
1015
1027
trailingPartialCount >>= 1 ;
1028
+
1029
+ ReadOnlySpan < uint > first = GetSpan ( fi ) ;
1030
+ first . CopyTo ( curBits . Slice ( curTrailingZeroCount >> 5 ) ) ;
1031
+
1032
+ curLength = first . Length ;
1016
1033
}
1017
1034
1018
1035
1019
1036
for ( int i = fi + 1 ; trailingPartialCount != 0 && i + 1 < Indexes . Length ; i ++ , trailingPartialCount >>= 1 )
1020
1037
{
1021
- Debug . Assert ( GetSpan ( i ) . Length >= curLength ) ;
1038
+ Debug . Assert ( GetSpan ( i ) . Length >= curLength - ( curTrailingZeroCount >> 5 ) ) ;
1022
1039
if ( ( trailingPartialCount & 1 ) != 0 )
1023
1040
{
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
-
1028
1041
int powerTrailingZeroCount = MaxPartialDigits * ( 1 << i ) ;
1029
1042
int powerTrailingZeroCountUInt32 = powerTrailingZeroCount >> 5 ;
1030
1043
int curTrailingZeroCountUInt32 = curTrailingZeroCount >> 5 ;
1031
1044
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
+
1035
1049
Debug . Assert ( curTrailingZeroCountUInt32 < src . Length
1036
1050
&& src . Slice ( 0 , curTrailingZeroCountUInt32 ) . Trim ( 0u ) . Length == 0
1037
1051
&& src [ curTrailingZeroCountUInt32 ] != 0 ) ;
1038
1052
1039
- BigIntegerCalculator . Multiply ( power . Slice ( powerTrailingZeroCountUInt32 ) , src . Slice ( curTrailingZeroCountUInt32 ) , dst . Slice ( powerTrailingZeroCountUInt32 + curTrailingZeroCountUInt32 ) ) ;
1053
+ BigIntegerCalculator . Multiply ( power , src . Slice ( curTrailingZeroCountUInt32 ) , dst . Slice ( powerTrailingZeroCountUInt32 + curTrailingZeroCountUInt32 ) ) ;
1040
1054
1041
1055
curTrailingZeroCount += powerTrailingZeroCount ;
1042
1056
0 commit comments