@@ -862,6 +862,7 @@ static BigInteger NumberBufferToBigInteger(ReadOnlySpan<uint> result, bool isNeg
862862 }
863863 internal readonly ref struct PowersOf1e9
864864 {
865+ // Holds 1000000000^(1<<<n).
865866 private readonly ReadOnlySpan < uint > pow1E9 ;
866867 public const uint TenPowMaxPartial = 1000000000 ;
867868 public const int MaxPartialDigits = 9 ;
@@ -879,7 +880,8 @@ internal readonly ref struct PowersOf1e9
879880 // length -= (9*(1<<i)) >> 5;
880881 // indexes[i+1] = indexes[i] + length;
881882 // }
882- private static ReadOnlySpan < int > Indexes => new int [ ] {
883+ private static ReadOnlySpan < int > Indexes => new int [ ]
884+ {
883885 0 ,
884886 1 ,
885887 3 ,
@@ -914,40 +916,91 @@ internal readonly ref struct PowersOf1e9
914916 1939268536 ,
915917 } ;
916918
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+
917978 public PowersOf1e9 ( Span < uint > pow1E9 )
918979 {
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 ) ) ;
919988 this . pow1E9 = pow1E9 ;
920989
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 ++ )
926993 {
927994 Debug . Assert ( 2 * src . Length - ( Indexes [ i + 1 ] - Indexes [ i ] ) is 0 or 1 ) ;
928995 if ( pow1E9 . Length - toExclusive < ( src . Length << 1 ) )
929996 break ;
930997 Span < uint > dst = pow1E9 . Slice ( toExclusive , src . Length << 1 ) ;
931998 BigIntegerCalculator . Square ( src , dst ) ;
932- if ( dst [ 0 ] == 0 )
933- {
934- dst . Slice ( 1 ) . CopyTo ( dst ) ;
935- dst [ ^ 1 ] = 0 ;
936- }
937999 int from = toExclusive ;
9381000 toExclusive = Indexes [ i + 1 ] ;
9391001 src = pow1E9 . Slice ( from , toExclusive - from ) ;
9401002 Debug . Assert ( toExclusive == pow1E9 . Length || pow1E9 [ toExclusive ] == 0 ) ;
9411003 }
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
9511004 }
9521005
9531006 public static int GetBufferSize ( int digits )
0 commit comments