Skip to content

Commit edc6a57

Browse files
committed
Shrink PowersOf1e9
1 parent b5dbf47 commit edc6a57

File tree

1 file changed

+59
-45
lines changed

1 file changed

+59
-45
lines changed

src/libraries/System.Runtime.Numerics/src/System/Number.BigInteger.cs

+59-45
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)