Skip to content

Commit

Permalink
intDigits
Browse files Browse the repository at this point in the history
  • Loading branch information
kzrnm committed May 12, 2024
1 parent 7568c5b commit d785168
Showing 1 changed file with 31 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,29 @@ private static ParsingStatus NumberToBigInteger(ref NumberBuffer number, out Big
return ParsingStatus.Failed;
}

ReadOnlySpan<byte> intDigits = number.Digits.Slice(0, Math.Min(number.Scale, number.DigitsCount));
int intDigitsEnd = intDigits.IndexOf<byte>(0);
if (intDigitsEnd < 0)
{
// Check for nonzero digits after the decimal point.
ReadOnlySpan<byte> fracDigitsSpan = number.Digits.Slice(intDigits.Length);
for (int i = 0; i < fracDigitsSpan.Length; i++)
{
char digitChar = (char)fracDigitsSpan[i];
if (digitChar == '\0')
{
break;
}
if (digitChar != '0')
{
result = default;
return ParsingStatus.Failed;
}
}
}
else
intDigits = intDigits.Slice(0, intDigitsEnd);

const double digitRatio = 0.10381025297; // log_{2^32}(10)
int resultLength = checked((int)(number.Scale * digitRatio) + 1 + 2);
uint[]? resultBufferFromPool = null;
Expand All @@ -329,12 +352,13 @@ private static ParsingStatus NumberToBigInteger(ref NumberBuffer number, out Big
: resultBufferFromPool = ArrayPool<uint>.Shared.Rent(resultLength)).Slice(0, resultLength);
resultBuffer.Clear();

if (number.Scale <= BigIntegerParseNaiveThreshold
? !Naive(ref number, resultBuffer)
: !DivideAndConquer(ref number, resultBuffer))
if (number.Scale <= BigIntegerParseNaiveThreshold)
{
result = default;
return ParsingStatus.Failed;
Naive(ref number, intDigits, resultBuffer);
}
else
{
DivideAndConquer(ref number, intDigits, resultBuffer);
}

resultBuffer = resultBuffer.Slice(0, BigIntegerCalculator.ActualLength(resultBuffer));
Expand All @@ -351,30 +375,8 @@ private static ParsingStatus NumberToBigInteger(ref NumberBuffer number, out Big

return ParsingStatus.OK;

static bool DivideAndConquer(ref NumberBuffer number, scoped Span<uint> bits)
static bool DivideAndConquer(ref NumberBuffer number, ReadOnlySpan<byte> intDigits, scoped Span<uint> bits)
{
ReadOnlySpan<byte> intDigits = number.Digits.Slice(0, Math.Min(number.Scale, number.DigitsCount));
int intDigitsEnd = intDigits.IndexOf<byte>(0);
if (intDigitsEnd < 0)
{
// Check for nonzero digits after the decimal point.
ReadOnlySpan<byte> fracDigitsSpan = number.Digits.Slice(intDigits.Length);
for (int i = 0; i < fracDigitsSpan.Length; i++)
{
char digitChar = (char)fracDigitsSpan[i];
if (digitChar == '\0')
{
break;
}
if (digitChar != '0')
{
return false;
}
}
}
else
intDigits = intDigits.Slice(0, intDigitsEnd);

int totalDigitCount = Math.Min(number.DigitsCount, number.Scale);
int trailingZeroCount = number.Scale - totalDigitCount;

Expand Down Expand Up @@ -514,31 +516,8 @@ static int NaiveDigits(ReadOnlySpan<byte> intDigits, Span<uint> bits)
return resultLength;
}

static bool Naive(ref NumberBuffer number, scoped Span<uint> bits)
static bool Naive(ref NumberBuffer number, ReadOnlySpan<byte> intDigits, scoped Span<uint> bits)
{
ReadOnlySpan<byte> intDigits = number.Digits.Slice(0, Math.Min(number.Scale, number.DigitsCount));
int intDigitsEnd = intDigits.IndexOf<byte>(0);
if (intDigitsEnd < 0)
{
// Check for nonzero digits after the decimal point.
ReadOnlySpan<byte> fracDigitsSpan = number.Digits.Slice(intDigits.Length);
for (int i = 0; i < fracDigitsSpan.Length; i++)
{
char digitChar = (char)fracDigitsSpan[i];
if (digitChar == '\0')
{
break;
}
if (digitChar != '0')
{
return false;
}
}
}
else
intDigits = intDigits.Slice(0, intDigitsEnd);


int totalDigitCount = Math.Min(number.DigitsCount, number.Scale);
if (totalDigitCount == 0)
{
Expand Down

0 comments on commit d785168

Please sign in to comment.