@@ -862,6 +862,7 @@ static BigInteger NumberBufferToBigInteger(ReadOnlySpan<uint> result, bool isNeg
862
862
}
863
863
internal readonly ref struct PowersOf1e9
864
864
{
865
+ // Holds 1000000000^(1<<<n).
865
866
private readonly ReadOnlySpan < uint > pow1E9 ;
866
867
public const uint TenPowMaxPartial = 1000000000 ;
867
868
public const int MaxPartialDigits = 9 ;
@@ -879,7 +880,8 @@ internal readonly ref struct PowersOf1e9
879
880
// length -= (9*(1<<i)) >> 5;
880
881
// indexes[i+1] = indexes[i] + length;
881
882
// }
882
- private static ReadOnlySpan < int > Indexes => new int [ ] {
883
+ private static ReadOnlySpan < int > Indexes => new int [ ]
884
+ {
883
885
0 ,
884
886
1 ,
885
887
3 ,
@@ -914,40 +916,91 @@ internal readonly ref struct PowersOf1e9
914
916
1939268536 ,
915
917
} ;
916
918
919
+ // The PowersOf1e9 structure holds 1000000000^(1<<<n). However, if the lower element is zero,
920
+ // it is truncated. Therefore, if the lower element becomes zero in the process of calculating
921
+ // 1000000000^(1<<<n), it must be truncated. If 1000000000^(1<<<<n) is calculated in advance
922
+ // for less than 6, there is no need to consider the case where the lower element becomes zero
923
+ // during the calculation process, since 1000000000^(1<<<<n) mod 32 is always zero.
924
+ private static ReadOnlySpan < uint > FivePowers1E9 => new uint [ ]
925
+ {
926
+ // 1000000000^(1<<0)
927
+ 1000000000 ,
928
+ // 1000000000^(1<<1)
929
+ 2808348672 ,
930
+ 232830643 ,
931
+ // 1000000000^(1<<2)
932
+ 3008077584 ,
933
+ 2076772117 ,
934
+ 12621774 ,
935
+ // 1000000000^(1<<3)
936
+ 4130660608 ,
937
+ 835571558 ,
938
+ 1441351422 ,
939
+ 977976457 ,
940
+ 264170013 ,
941
+ 37092 ,
942
+ // 1000000000^(1<<4)
943
+ 767623168 ,
944
+ 4241160024 ,
945
+ 1260959332 ,
946
+ 2541775228 ,
947
+ 2965753944 ,
948
+ 1796720685 ,
949
+ 484800439 ,
950
+ 1311835347 ,
951
+ 2945126454 ,
952
+ 3563705203 ,
953
+ 1375821026 ,
954
+ // 1000000000^(1<<5)
955
+ 3940379521 ,
956
+ 184513341 ,
957
+ 2872588323 ,
958
+ 2214530454 ,
959
+ 38258512 ,
960
+ 2980860351 ,
961
+ 114267010 ,
962
+ 2188874685 ,
963
+ 234079247 ,
964
+ 2101059099 ,
965
+ 1948702207 ,
966
+ 947446250 ,
967
+ 864457656 ,
968
+ 507589568 ,
969
+ 1321007357 ,
970
+ 3911984176 ,
971
+ 1011110295 ,
972
+ 2382358050 ,
973
+ 2389730781 ,
974
+ 730678769 ,
975
+ 440721283 ,
976
+ } ;
977
+
917
978
public PowersOf1e9 ( Span < uint > pow1E9 )
918
979
{
980
+ Debug . Assert ( pow1E9 . Length >= 1 ) ;
981
+ Debug . Assert ( Indexes [ 6 ] == FivePowers1E9 . Length ) ;
982
+ if ( pow1E9 . Length < Indexes [ 7 ] )
983
+ {
984
+ this . pow1E9 = FivePowers1E9 ;
985
+ return ;
986
+ }
987
+ FivePowers1E9 . CopyTo ( pow1E9 . Slice ( 0 , FivePowers1E9 . Length ) ) ;
919
988
this . pow1E9 = pow1E9 ;
920
989
921
- Debug . Assert ( pow1E9 . Length >= 1 ) ;
922
- pow1E9 [ 0 ] = TenPowMaxPartial ;
923
- ReadOnlySpan < uint > src = pow1E9 . Slice ( 0 , 1 ) ;
924
- int toExclusive = 1 ;
925
- for ( int i = 1 ; i + 1 < Indexes . Length ; i ++ )
990
+ ReadOnlySpan < uint > src = pow1E9 . Slice ( Indexes [ 5 ] , Indexes [ 6 ] - Indexes [ 5 ] ) ;
991
+ int toExclusive = Indexes [ 6 ] ;
992
+ for ( int i = 6 ; i + 1 < Indexes . Length ; i ++ )
926
993
{
927
994
Debug . Assert ( 2 * src . Length - ( Indexes [ i + 1 ] - Indexes [ i ] ) is 0 or 1 ) ;
928
995
if ( pow1E9 . Length - toExclusive < ( src . Length << 1 ) )
929
996
break ;
930
997
Span < uint > dst = pow1E9 . Slice ( toExclusive , src . Length << 1 ) ;
931
998
BigIntegerCalculator . Square ( src , dst ) ;
932
- if ( dst [ 0 ] == 0 )
933
- {
934
- dst . Slice ( 1 ) . CopyTo ( dst ) ;
935
- dst [ ^ 1 ] = 0 ;
936
- }
937
999
int from = toExclusive ;
938
1000
toExclusive = Indexes [ i + 1 ] ;
939
1001
src = pow1E9 . Slice ( from , toExclusive - from ) ;
940
1002
Debug . Assert ( toExclusive == pow1E9 . Length || pow1E9 [ toExclusive ] == 0 ) ;
941
1003
}
942
- #if DEBUG
943
- for ( int i = 0 ; i + 1 < Indexes . Length ; i ++ )
944
- {
945
- int startIndex = Indexes [ i ] ;
946
- int endIndex = Indexes [ i + 1 ] ;
947
- if ( endIndex >= pow1E9 . Length ) break ;
948
- Debug . Assert ( pow1E9 [ startIndex ] != 0 ) ;
949
- }
950
- #endif
951
1004
}
952
1005
953
1006
public static int GetBufferSize ( int digits )
0 commit comments