Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
thedavidmeister committed Nov 2, 2024
1 parent ca2b341 commit 238691b
Show file tree
Hide file tree
Showing 2 changed files with 6 additions and 123 deletions.
127 changes: 5 additions & 122 deletions src/lib/parse/literal/LibParseLiteralDecimal.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,133 +22,16 @@ import {LibParseError} from "../LibParseError.sol";
import {LibParse} from "../LibParse.sol";
import {LibDecimalFloatImplementation, LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol";

/// @dev The default is 18 decimal places for a fractional number.
uint256 constant DECIMAL_SCALE = 18;

library LibParseLiteralDecimal {
using LibParseError for ParseState;
using LibParseLiteralDecimal for ParseState;

function parseDecimalFloatPacked(ParseState memory state, uint256 start, uint256 end)
internal
pure
returns (uint256 cursor, uint256 packedFloat)
{
int256 signedCoefficient;
int256 exponent;
(cursor, signedCoefficient, exponent) = parseDecimalFloat(state, start, end);

// Prenormalize signed coefficients that are smaller than their
// normalized form at parse time, as this can save runtime gas that would
// be needed to normalize the value at runtime.
// We only do normalization that will scale up, to avoid causing
// unneccessary precision loss.
if (-1e37 < signedCoefficient && signedCoefficient < 1e37) {
(signedCoefficient, exponent) = LibDecimalFloatImplementation.normalize(signedCoefficient, exponent);
}

packedFloat = LibDecimalFloat.pack(signedCoefficient, exponent);

(int256 unpackedSignedCoefficient, int256 unpackedExponent) = LibDecimalFloat.unpack(packedFloat);
if (unpackedSignedCoefficient != signedCoefficient || unpackedExponent != exponent) {
revert DecimalLiteralPrecisionLoss(state.parseErrorOffset(start));
}
function parseDecimalFloatPacked(ParseState memory state) internal view returns (LibDecimalFloat.Data memory) {
LibDecimalFloat.Data memory result;
result = self.parseDecimalFloat();
self.assertEnd();
return result;
}

function parseDecimalFloat(ParseState memory state, uint256 start, uint256 end)
internal
pure
returns (uint256 cursor, int256 signedCoefficient, int256 exponent)
{
unchecked {
cursor = start;
cursor = LibParseChar.skipMask(cursor, end, CMASK_NEGATIVE_SIGN);
{
uint256 intStart = cursor;
cursor = LibParseChar.skipMask(cursor, end, CMASK_NUMERIC_0_9);
if (cursor == intStart) {
revert ZeroLengthDecimal(state.parseErrorOffset(start));
}
}
{
(uint256 success, int256 signedCoefficientTmp) =
LibParseDecimal.unsafeDecimalStringToSignedInt(start, cursor);
if (success == 0) {
revert DecimalLiteralOverflow(state.parseErrorOffset(start));
}
signedCoefficient = signedCoefficientTmp;
}

int256 fracValue = int256(LibParseChar.isMask(cursor, end, CMASK_DECIMAL_POINT));
if (fracValue != 0) {
cursor++;
uint256 fracStart = cursor;
cursor = LibParseChar.skipMask(cursor, end, CMASK_NUMERIC_0_9);
if (cursor == fracStart) {
revert MalformedDecimalPoint(state.parseErrorOffset(fracStart));
}
// Trailing zeros are allowed in fractional literals but should
// not be counted in the precision.
uint256 nonZeroCursor = cursor;
while (LibParseChar.isMask(nonZeroCursor - 1, end, CMASK_ZERO) == 1) {
nonZeroCursor--;
}

{
(uint256 fracSuccess, int256 fracValueTmp) =
LibParseDecimal.unsafeDecimalStringToSignedInt(fracStart, nonZeroCursor);
if (fracSuccess == 0) {
revert DecimalLiteralOverflow(state.parseErrorOffset(fracStart));
}
fracValue = fracValueTmp;
}
// Frac value inherits its sign from the coefficient.
if (fracValue < 0) {
revert MalformedDecimalPoint(state.parseErrorOffset(fracStart));
}
if (signedCoefficient < 0) {
fracValue = -fracValue;
}

// We want to _decrease_ the exponent by the number of digits in the
// fractional part.
exponent = int256(fracStart) - int256(nonZeroCursor);
uint256 scale = uint256(-exponent);
if (scale >= 77 && signedCoefficient != 0) {
revert DecimalLiteralPrecisionLoss(state.parseErrorOffset(start));
}
scale = 10 ** scale;
int256 rescaledIntValue = signedCoefficient * int256(scale);
if (rescaledIntValue / int256(scale) != signedCoefficient) {
revert DecimalLiteralPrecisionLoss(state.parseErrorOffset(start));
}
signedCoefficient = rescaledIntValue + fracValue;
}

int256 eValue = int256(LibParseChar.isMask(cursor, end, CMASK_E_NOTATION));
if (eValue != 0) {
cursor++;
uint256 eStart = cursor;
cursor = LibParseChar.skipMask(cursor, end, CMASK_NEGATIVE_SIGN);
{
uint256 digitsStart = cursor;
cursor = LibParseChar.skipMask(cursor, end, CMASK_NUMERIC_0_9);
if (cursor == digitsStart) {
revert MalformedExponentDigits(state.parseErrorOffset(digitsStart));
}
}

{
(uint256 eSuccess, int256 eValueTmp) =
LibParseDecimal.unsafeDecimalStringToSignedInt(eStart, cursor);
if (eSuccess == 0) {
revert DecimalLiteralOverflow(state.parseErrorOffset(eStart));
}
eValue = eValueTmp;
}

exponent += eValue;
}
}
}
}

0 comments on commit 238691b

Please sign in to comment.