@@ -569,6 +569,7 @@ internal const
569
569
int
570
570
BigIntegerParseNaiveThreshold = 1233 ,
571
571
BigIntegerParseNaiveThresholdInRecursive = 9 * ( 1 << 7 ) ;
572
+
572
573
private static ParsingStatus NumberToBigInteger ( ref NumberBuffer number , out BigInteger result )
573
574
{
574
575
const uint TenPowMaxPartial = PowersOf1e9 . TenPowMaxPartial ;
@@ -647,7 +648,6 @@ static bool DivideAndConquer(ref NumberBuffer number, scoped Span<uint> bits)
647
648
648
649
PowersOf1e9 powersOf1e9 = new PowersOf1e9 ( powersOf1e9Buffer ) ;
649
650
650
- const double digitRatio = 0.103810253 ; // log_{2^32}(10)
651
651
652
652
if ( trailingZeroCount > 0 )
653
653
{
@@ -662,29 +662,10 @@ static bool DivideAndConquer(ref NumberBuffer number, scoped Span<uint> bits)
662
662
Recursive ( powersOf1e9 , intDigits , leading ) ;
663
663
leading = leading . Slice ( 0 , BigIntegerCalculator . ActualLength ( leading ) ) ;
664
664
665
- int trailingZeroBufferLength = checked ( ( int ) ( digitRatio * trailingZeroCount ) + 2 ) ;
666
- uint [ ] ? trailingZeroBufferFromPool = null ;
667
- Span < uint > trailingZeroBuffer = (
668
- trailingZeroBufferLength <= BigIntegerCalculator . StackAllocThreshold
669
- ? stackalloc uint [ BigIntegerCalculator . StackAllocThreshold ]
670
- : trailingZeroBufferFromPool = ArrayPool < uint > . Shared . Rent ( trailingZeroBufferLength ) ) . Slice ( 0 , trailingZeroBufferLength ) ;
671
- trailingZeroBuffer . Clear ( ) ;
672
-
673
- powersOf1e9 . CalculatePowerOfTen ( trailingZeroCount , trailingZeroBuffer ) ;
674
- trailingZeroBuffer = trailingZeroBuffer . Slice ( 0 , BigIntegerCalculator . ActualLength ( trailingZeroBuffer ) ) ;
675
-
676
- // Merge leading and trailing
677
- Span < uint > bitsResult = bits . Slice ( 0 , trailingZeroBuffer . Length + leading . Length ) ;
678
-
679
- if ( trailingZeroBuffer . Length < leading . Length )
680
- BigIntegerCalculator . Multiply ( leading , trailingZeroBuffer , bitsResult ) ;
681
- else
682
- BigIntegerCalculator . Multiply ( trailingZeroBuffer , leading , bitsResult ) ;
665
+ powersOf1e9 . MultiplyPowerOfTen ( leading , trailingZeroCount , bits ) ;
683
666
684
667
if ( leadingFromPool != null )
685
668
ArrayPool < uint > . Shared . Return ( leadingFromPool ) ;
686
- if ( trailingZeroBufferFromPool != null )
687
- ArrayPool < uint > . Shared . Return ( trailingZeroBufferFromPool ) ;
688
669
}
689
670
else
690
671
{
@@ -730,7 +711,7 @@ static void Recursive(in PowersOf1e9 powersOf1e9, ReadOnlySpan<byte> digits, Spa
730
711
Recursive ( powersOf1e9 , digitsUpper , upperBuffer ) ;
731
712
upperBuffer = upperBuffer . Slice ( 0 , BigIntegerCalculator . ActualLength ( upperBuffer ) ) ;
732
713
ReadOnlySpan < uint > multiplier = powersOf1e9 . GetSpan ( log2 ) ;
733
- int multiplierTrailingZeroCountUInt32 = ( MaxPartialDigits * ( 1 << log2 ) ) >> 5 ;
714
+ int multiplierTrailingZeroCountUInt32 = PowersOf1e9 . OmittedLength ( log2 ) ;
734
715
735
716
Span < uint > bitsUpper = bits . Slice ( 0 , upperBuffer . Length + multiplier . Length + multiplierTrailingZeroCountUInt32 ) ;
736
717
bitsUpper = bitsUpper . Slice ( multiplierTrailingZeroCountUInt32 ) ;
@@ -968,132 +949,124 @@ public PowersOf1e9(Span<uint> pow1E9)
968
949
}
969
950
#endif
970
951
}
952
+
953
+ public static int GetBufferSize ( int digits )
954
+ {
955
+ int scale1E9 = digits / MaxPartialDigits ;
956
+ int log2 = BitOperations . Log2 ( ( uint ) scale1E9 ) + 1 ;
957
+ return ( uint ) log2 < ( uint ) Indexes . Length ? Indexes [ log2 ] + 1 : Indexes [ ^ 1 ] ;
958
+ }
959
+
971
960
public ReadOnlySpan < uint > GetSpan ( int index )
972
961
{
973
- // Returns 1E9^(1<<index) >> (32*(9*(1<<index)/32)
962
+ // Returns 1E9^(1<<index) >> (32*(9*(1<<index)/32))
974
963
int from = Indexes [ index ] ;
975
964
int toExclusive = Indexes [ index + 1 ] ;
976
- return pow1E9 [ from .. toExclusive ] ;
965
+ return pow1E9 . Slice ( from , toExclusive - from ) ;
977
966
}
978
967
979
- public void CalculatePowerOfTen ( int trailingZeroCount , Span < uint > bits )
968
+ public static int OmittedLength ( int index )
980
969
{
981
- Debug . Assert ( bits . Length > unchecked ( ( int ) ( 0.934292276687070661 / 9 * trailingZeroCount ) ) + 1 ) ;
982
- Debug . Assert ( trailingZeroCount >= 0 ) ;
983
-
984
- int trailingPartialCount = Math . DivRem ( trailingZeroCount , MaxPartialDigits , out int remainingTrailingZeroCount ) ;
970
+ // Returns 9*(1<<index)/32
971
+ return ( MaxPartialDigits * ( 1 << index ) ) >> 5 ;
972
+ }
985
973
986
- if ( trailingPartialCount == 0 )
974
+ public void MultiplyPowerOfTen ( ReadOnlySpan < uint > left , int trailingZeroCount , Span < uint > bits )
975
+ {
976
+ Debug . Assert ( trailingZeroCount >= 0 ) ;
977
+ if ( trailingZeroCount <= UInt32PowersOfTen . Length )
987
978
{
988
- bits [ 0 ] = UInt32PowersOfTen [ remainingTrailingZeroCount ] ;
979
+ BigIntegerCalculator . Multiply ( left , UInt32PowersOfTen [ trailingZeroCount ] , bits . Slice ( 0 , left . Length + 1 ) ) ;
989
980
return ;
990
981
}
991
982
992
- int popCount = BitOperations . PopCount ( ( uint ) trailingPartialCount ) ;
983
+ uint [ ] ? powersOfTenFromPool = null ;
993
984
994
- int bits2Length = ( bits . Length + 1 ) >> 1 ;
995
- uint [ ] ? bits2FromPool = null ;
996
- scoped Span < uint > bits2 ;
997
- if ( popCount > 1 )
998
- {
999
- bits2 = (
1000
- bits2Length <= BigIntegerCalculator . StackAllocThreshold
1001
- ? stackalloc uint [ BigIntegerCalculator . StackAllocThreshold ]
1002
- : bits2FromPool = ArrayPool < uint > . Shared . Rent ( bits2Length ) ) . Slice ( 0 , bits2Length ) ;
1003
- bits2 . Clear ( ) ;
1004
- }
1005
- else
1006
- bits2 = default ;
1007
-
1008
- int curLength , curTrailingZeroCount ;
1009
- scoped Span < uint > curBits , otherBits ;
985
+ Span < uint > powersOfTen = (
986
+ bits . Length <= BigIntegerCalculator . StackAllocThreshold
987
+ ? stackalloc uint [ BigIntegerCalculator . StackAllocThreshold ]
988
+ : powersOfTenFromPool = ArrayPool < uint > . Shared . Rent ( bits . Length ) ) . Slice ( 0 , bits . Length ) ;
989
+ scoped Span < uint > powersOfTen2 = bits ;
1010
990
1011
- if ( ( popCount & 1 ) != 0 )
1012
- {
1013
- curBits = bits ;
1014
- otherBits = bits2 ;
1015
- }
1016
- else
1017
- {
1018
- curBits = bits2 ;
1019
- otherBits = bits ;
1020
- }
991
+ int trailingPartialCount = Math . DivRem ( trailingZeroCount , MaxPartialDigits , out int remainingTrailingZeroCount ) ;
1021
992
1022
- // Copy first
1023
993
int fi = BitOperations . TrailingZeroCount ( trailingPartialCount ) ;
1024
- {
1025
- curTrailingZeroCount = MaxPartialDigits * ( 1 << fi ) ;
1026
- trailingPartialCount >>= fi ;
1027
- trailingPartialCount >>= 1 ;
994
+ int omittedLength = OmittedLength ( fi ) ;
1028
995
1029
- ReadOnlySpan < uint > first = GetSpan ( fi ) ;
1030
- first . CopyTo ( curBits . Slice ( curTrailingZeroCount >> 5 ) ) ;
996
+ // Copy first
997
+ ReadOnlySpan < uint > first = GetSpan ( fi ) ;
998
+ int curLength = first . Length ;
999
+ trailingPartialCount >>= fi ;
1000
+ trailingPartialCount >>= 1 ;
1031
1001
1032
- curLength = first . Length ;
1002
+ if ( ( BitOperations . PopCount ( ( uint ) trailingPartialCount ) & 1 ) != 0 )
1003
+ {
1004
+ powersOfTen2 = powersOfTen ;
1005
+ powersOfTen = bits ;
1006
+ powersOfTen2 . Clear ( ) ;
1033
1007
}
1034
1008
1009
+ first . CopyTo ( powersOfTen ) ;
1035
1010
1036
- for ( int i = fi + 1 ; trailingPartialCount != 0 && i + 1 < Indexes . Length ; i ++ , trailingPartialCount >>= 1 )
1011
+ for ( ++ fi ; trailingPartialCount != 0 ; ++ fi , trailingPartialCount >>= 1 )
1037
1012
{
1038
- Debug . Assert ( GetSpan ( i ) . Length >= curLength - ( curTrailingZeroCount >> 5 ) ) ;
1013
+ Debug . Assert ( fi + 1 < Indexes . Length ) ;
1039
1014
if ( ( trailingPartialCount & 1 ) != 0 )
1040
1015
{
1041
- int powerTrailingZeroCount = MaxPartialDigits * ( 1 << i ) ;
1042
- int powerTrailingZeroCountUInt32 = powerTrailingZeroCount >> 5 ;
1043
- int curTrailingZeroCountUInt32 = curTrailingZeroCount >> 5 ;
1044
-
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
-
1049
- Debug . Assert ( curTrailingZeroCountUInt32 < src . Length
1050
- && src . Slice ( 0 , curTrailingZeroCountUInt32 ) . Trim ( 0u ) . Length == 0
1051
- && src [ curTrailingZeroCountUInt32 ] != 0 ) ;
1016
+ omittedLength += OmittedLength ( fi ) ;
1052
1017
1053
- BigIntegerCalculator . Multiply ( power , src . Slice ( curTrailingZeroCountUInt32 ) , dst . Slice ( powerTrailingZeroCountUInt32 + curTrailingZeroCountUInt32 ) ) ;
1018
+ ReadOnlySpan < uint > power = GetSpan ( fi ) ;
1019
+ Span < uint > src = powersOfTen . Slice ( 0 , curLength ) ;
1020
+ Span < uint > dst = powersOfTen2 . Slice ( 0 , curLength += power . Length ) ;
1054
1021
1055
- curTrailingZeroCount += powerTrailingZeroCount ;
1022
+ if ( power . Length < src . Length )
1023
+ BigIntegerCalculator . Multiply ( src , power , dst ) ;
1024
+ else
1025
+ BigIntegerCalculator . Multiply ( power , src , dst ) ;
1056
1026
1057
- Span < uint > tmp = curBits ;
1058
- curBits = otherBits ;
1059
- otherBits = tmp ;
1060
- otherBits . Clear ( ) ;
1027
+ Span < uint > tmp = powersOfTen ;
1028
+ powersOfTen = powersOfTen2 ;
1029
+ powersOfTen2 = tmp ;
1030
+ powersOfTen2 . Clear ( ) ;
1061
1031
1062
1032
// Trim
1063
- while ( -- curLength >= 0 && curBits [ curLength ] == 0 ) ;
1033
+ while ( -- curLength >= 0 && powersOfTen [ curLength ] == 0 ) ;
1064
1034
++ curLength ;
1065
1035
}
1066
1036
}
1067
1037
1068
- Debug . Assert ( Unsafe . AreSame ( ref bits [ 0 ] , ref curBits [ 0 ] ) ) ;
1038
+ Debug . Assert ( Unsafe . AreSame ( ref bits [ 0 ] , ref powersOfTen2 [ 0 ] ) ) ;
1069
1039
1070
- curBits = curBits . Slice ( 0 , curLength ) ;
1071
- uint multiplier = UInt32PowersOfTen [ remainingTrailingZeroCount ] ;
1072
- uint carry = 0 ;
1073
- for ( int i = ( curTrailingZeroCount >> 5 ) ; i < curBits . Length ; i ++ )
1074
- {
1075
- ulong p = ( ulong ) multiplier * curBits [ i ] + carry ;
1076
- curBits [ i ] = ( uint ) p ;
1077
- carry = ( uint ) ( p >> 32 ) ;
1078
- }
1040
+ powersOfTen = powersOfTen . Slice ( 0 , curLength ) ;
1041
+ Span < uint > bits2 = bits . Slice ( omittedLength , curLength += left . Length ) ;
1042
+ if ( left . Length < powersOfTen . Length )
1043
+ BigIntegerCalculator . Multiply ( powersOfTen , left , bits2 ) ;
1044
+ else
1045
+ BigIntegerCalculator . Multiply ( left , powersOfTen , bits2 ) ;
1079
1046
1080
- if ( carry != 0 )
1081
- {
1082
- bits [ curLength ] = carry ;
1083
- }
1047
+ if ( powersOfTenFromPool != null )
1048
+ ArrayPool < uint > . Shared . Return ( powersOfTenFromPool ) ;
1084
1049
1085
- if ( bits2FromPool != null )
1086
- ArrayPool < uint > . Shared . Return ( bits2FromPool ) ;
1087
- }
1050
+ if ( remainingTrailingZeroCount > 0 )
1051
+ {
1052
+ uint multiplier = UInt32PowersOfTen [ remainingTrailingZeroCount ] ;
1053
+ uint carry = 0 ;
1054
+ for ( int i = 0 ; i < bits2 . Length ; i ++ )
1055
+ {
1056
+ ulong p = ( ulong ) multiplier * bits2 [ i ] + carry ;
1057
+ bits2 [ i ] = ( uint ) p ;
1058
+ carry = ( uint ) ( p >> 32 ) ;
1059
+ }
1088
1060
1089
- public static int GetBufferSize ( int digits )
1090
- {
1091
- int scale1E9 = digits / MaxPartialDigits ;
1092
- int log2 = BitOperations . Log2 ( ( uint ) scale1E9 ) + 1 ;
1093
- return ( uint ) log2 < ( uint ) Indexes . Length ? Indexes [ log2 ] + 1 : Indexes [ ^ 1 ] ;
1061
+ if ( carry != 0 )
1062
+ {
1063
+ bits [ curLength ] = carry ;
1064
+ }
1065
+ }
1094
1066
}
1095
1067
}
1096
1068
1069
+
1097
1070
internal static char ParseFormatSpecifier ( ReadOnlySpan < char > format , out int digits )
1098
1071
{
1099
1072
digits = - 1 ;
0 commit comments