diff --git a/.gas-snapshot b/.gas-snapshot index afc2226b..bf085913 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,319 +1,320 @@ -DecimalFloatAbsTest:testAbsDeployed(bytes32) (runs: 5107, μ: 3420593, ~: 3420533) -DecimalFloatAddTest:testAddDeployed(bytes32,bytes32) (runs: 5107, μ: 3426033, ~: 3426118) -DecimalFloatCeilTest:testCeilDeployed(bytes32) (runs: 5107, μ: 3420569, ~: 3420196) -DecimalFloatConstantsTest:testEDeployed() (gas: 3419726) -DecimalFloatConstantsTest:testMaxNegativeValueDeployed() (gas: 3419715) -DecimalFloatConstantsTest:testMaxPositiveValueDeployed() (gas: 3419716) -DecimalFloatConstantsTest:testMinNegativeValueDeployed() (gas: 3419691) -DecimalFloatConstantsTest:testMinPositiveValueDeployed() (gas: 3419692) -DecimalFloatConstantsTest:testZeroDeployed() (gas: 3419759) -DecimalFloatDivTest:testDivDeployed(bytes32,bytes32) (runs: 5107, μ: 3427574, ~: 3427696) -DecimalFloatEqTest:testEqDeployed(bytes32,bytes32) (runs: 5107, μ: 3420925, ~: 3420851) -DecimalFloatFloorTest:testFloorDeployed(bytes32) (runs: 5107, μ: 3420375, ~: 3420194) -DecimalFloatFormatTest:testFormatDeployed(bytes32,uint256) (runs: 5107, μ: 3446095, ~: 3452456) -DecimalFloatFracTest:testFracDeployed(bytes32) (runs: 5107, μ: 3420778, ~: 3420744) -DecimalFloatFromFixedDecimalLosslessTest:testFromFixedDecimalLosslessDeployed(uint256,uint8) (runs: 5107, μ: 3421370, ~: 3421312) -DecimalFloatFromFixedDecimalLossyTest:testFromFixedDecimalLossyDeployed(uint256,uint8) (runs: 5107, μ: 3421859, ~: 3421779) -DecimalFloatGtTest:testGtDeployed(bytes32,bytes32) (runs: 5107, μ: 3420867, ~: 3420793) -DecimalFloatGteTest:testGteDeployed(bytes32,bytes32) (runs: 5107, μ: 3420853, ~: 3420779) -DecimalFloatInvTest:testInvDeployed(bytes32) (runs: 5107, μ: 3426029, ~: 3426088) -DecimalFloatIsZeroTest:testIsZeroDeployed(bytes32) (runs: 5107, μ: 3420036, ~: 3420036) -DecimalFloatLtTest:testLtDeployed(bytes32,bytes32) (runs: 5107, μ: 3420844, ~: 3420770) -DecimalFloatLteTest:testLteDeployed(bytes32,bytes32) (runs: 5107, μ: 3420897, ~: 3420823) -DecimalFloatMaxTest:testMaxDeployed(bytes32,bytes32) (runs: 5107, μ: 3420906, ~: 3420845) -DecimalFloatMinTest:testMinDeployed(bytes32,bytes32) (runs: 5107, μ: 3420904, ~: 3420843) -DecimalFloatMinusTest:testMinusDeployed(bytes32) (runs: 5107, μ: 3420701, ~: 3420702) -DecimalFloatMulTest:testMulDeployed(bytes32,bytes32) (runs: 5107, μ: 3424539, ~: 3425315) -DecimalFloatPackLosslessTest:testPackDeployed(int224,int32) (runs: 5107, μ: 170044, ~: 170045) -DecimalFloatParseTest:testParseDeployed(string) (runs: 5107, μ: 3423275, ~: 3423144) -DecimalFloatPowTest:testPowDeployed(bytes32,bytes32) (runs: 5107, μ: 3435330, ~: 3433613) -DecimalFloatSqrtTest:testSqrtDeployed(bytes32) (runs: 5107, μ: 3435367, ~: 3434837) -DecimalFloatSubTest:testSubDeployed(bytes32,bytes32) (runs: 5107, μ: 3426357, ~: 3426443) -DecimalFloatToFixedDecimalLosslessTest:testToFixedDecimalLosslessDeployed(bytes32,uint8) (runs: 5107, μ: 3422003, ~: 3421886) -DecimalFloatToFixedDecimalLossyTest:testToFixedDecimalLossyDeployed(bytes32,uint8) (runs: 5107, μ: 3422096, ~: 3422370) -LibDecimalFloatAbsTest:testAbsMinValue(int32) (runs: 5107, μ: 5162, ~: 5162) -LibDecimalFloatAbsTest:testAbsNegative(int256,int32) (runs: 5107, μ: 10527, ~: 10754) -LibDecimalFloatAbsTest:testAbsNonNegative(int256,int32) (runs: 5107, μ: 9714, ~: 9463) +DecimalFloatAbsTest:testAbsDeployed(bytes32) (runs: 5096, μ: 3602249, ~: 3602188) +DecimalFloatAddTest:testAddDeployed(bytes32,bytes32) (runs: 5096, μ: 3607708, ~: 3607769) +DecimalFloatCeilTest:testCeilDeployed(bytes32) (runs: 5096, μ: 3602256, ~: 3601851) +DecimalFloatConstantsTest:testEDeployed() (gas: 3601381) +DecimalFloatConstantsTest:testMaxNegativeValueDeployed() (gas: 3601370) +DecimalFloatConstantsTest:testMaxPositiveValueDeployed() (gas: 3601371) +DecimalFloatConstantsTest:testMinNegativeValueDeployed() (gas: 3601346) +DecimalFloatConstantsTest:testMinPositiveValueDeployed() (gas: 3601347) +DecimalFloatConstantsTest:testZeroDeployed() (gas: 3601414) +DecimalFloatDivTest:testDivDeployed(bytes32,bytes32) (runs: 5096, μ: 3609317, ~: 3609464) +DecimalFloatEqTest:testEqDeployed(bytes32,bytes32) (runs: 5096, μ: 3602580, ~: 3602506) +DecimalFloatFloorTest:testFloorDeployed(bytes32) (runs: 5096, μ: 3602038, ~: 3601849) +DecimalFloatFormatTest:testFormatDeployed(bytes32,uint256) (runs: 5096, μ: 3627947, ~: 3632554) +DecimalFloatFracTest:testFracDeployed(bytes32) (runs: 5096, μ: 3602436, ~: 3602399) +DecimalFloatFromFixedDecimalLosslessTest:testFromFixedDecimalLosslessDeployed(uint256,uint8) (runs: 5096, μ: 3603018, ~: 3602967) +DecimalFloatFromFixedDecimalLossyTest:testFromFixedDecimalLossyDeployed(uint256,uint8) (runs: 5096, μ: 3603497, ~: 3603434) +DecimalFloatGtTest:testGtDeployed(bytes32,bytes32) (runs: 5096, μ: 3602520, ~: 3602448) +DecimalFloatGteTest:testGteDeployed(bytes32,bytes32) (runs: 5096, μ: 3602509, ~: 3602434) +DecimalFloatInvTest:testInvDeployed(bytes32) (runs: 5096, μ: 3607724, ~: 3607783) +DecimalFloatIsZeroTest:testIsZeroDeployed(bytes32) (runs: 5096, μ: 3601691, ~: 3601691) +DecimalFloatLtTest:testLtDeployed(bytes32,bytes32) (runs: 5096, μ: 3602497, ~: 3602425) +DecimalFloatLteTest:testLteDeployed(bytes32,bytes32) (runs: 5096, μ: 3602553, ~: 3602478) +DecimalFloatMaxTest:testMaxDeployed(bytes32,bytes32) (runs: 5096, μ: 3602560, ~: 3602500) +DecimalFloatMinTest:testMinDeployed(bytes32,bytes32) (runs: 5096, μ: 3602558, ~: 3602498) +DecimalFloatMinusTest:testMinusDeployed(bytes32) (runs: 5096, μ: 3602356, ~: 3602357) +DecimalFloatMulTest:testMulDeployed(bytes32,bytes32) (runs: 5096, μ: 3606276, ~: 3607066) +DecimalFloatPackLosslessTest:testPackDeployed(int224,int32) (runs: 5096, μ: 170044, ~: 170045) +DecimalFloatParseTest:testParseDeployed(string) (runs: 5096, μ: 3604930, ~: 3604799) +DecimalFloatPowTest:testPowDeployed(bytes32,bytes32) (runs: 5096, μ: 3655950, ~: 3631589) +DecimalFloatSqrtTest:testSqrtDeployed(bytes32) (runs: 5096, μ: 3618648, ~: 3620391) +DecimalFloatSubTest:testSubDeployed(bytes32,bytes32) (runs: 5096, μ: 3608116, ~: 3608144) +DecimalFloatToFixedDecimalLosslessTest:testToFixedDecimalLosslessDeployed(bytes32,uint8) (runs: 5096, μ: 3603609, ~: 3603530) +DecimalFloatToFixedDecimalLossyTest:testToFixedDecimalLossyDeployed(bytes32,uint8) (runs: 5096, μ: 3603727, ~: 3604014) +LibDecimalFloatAbsTest:testAbsMinValue(int32) (runs: 5038, μ: 5162, ~: 5162) +LibDecimalFloatAbsTest:testAbsNegative(int256,int32) (runs: 5096, μ: 10536, ~: 10754) +LibDecimalFloatAbsTest:testAbsNonNegative(int256,int32) (runs: 5096, μ: 9700, ~: 9316) LibDecimalFloatCeilTest:testCeilExamples() (gas: 35053) -LibDecimalFloatCeilTest:testCeilInRange(int224,int256) (runs: 5107, μ: 11143, ~: 10763) -LibDecimalFloatCeilTest:testCeilLessThanMin(int224,int256) (runs: 5107, μ: 10079, ~: 9840) -LibDecimalFloatCeilTest:testCeilNonNegative(int224,int256) (runs: 5107, μ: 8985, ~: 9237) -LibDecimalFloatCeilTest:testCeilNotReverts(bytes32) (runs: 5107, μ: 603, ~: 411) -LibDecimalFloatCeilTest:testCeilZero(int32) (runs: 5107, μ: 5428, ~: 5428) +LibDecimalFloatCeilTest:testCeilInRange(int224,int256) (runs: 5096, μ: 11142, ~: 10763) +LibDecimalFloatCeilTest:testCeilLessThanMin(int224,int256) (runs: 5096, μ: 10081, ~: 9840) +LibDecimalFloatCeilTest:testCeilNonNegative(int224,int256) (runs: 5096, μ: 8988, ~: 9237) +LibDecimalFloatCeilTest:testCeilNotReverts(bytes32) (runs: 5096, μ: 616, ~: 411) +LibDecimalFloatCeilTest:testCeilZero(int32) (runs: 5096, μ: 5428, ~: 5428) LibDecimalFloatConstantsTest:testFloatE() (gas: 3383) LibDecimalFloatConstantsTest:testFloatHalf() (gas: 3362) LibDecimalFloatConstantsTest:testFloatMaxNegativeValue() (gas: 3405) -LibDecimalFloatConstantsTest:testFloatMaxNegativeValueIsMax(bytes32) (runs: 5107, μ: 4505, ~: 4620) +LibDecimalFloatConstantsTest:testFloatMaxNegativeValueIsMax(bytes32) (runs: 5074, μ: 4503, ~: 4620) LibDecimalFloatConstantsTest:testFloatMaxPositiveValue() (gas: 3361) -LibDecimalFloatConstantsTest:testFloatMaxPositiveValueIsMax(bytes32) (runs: 5107, μ: 3545, ~: 3586) +LibDecimalFloatConstantsTest:testFloatMaxPositiveValueIsMax(bytes32) (runs: 5096, μ: 3544, ~: 3586) LibDecimalFloatConstantsTest:testFloatMinNegativeValue() (gas: 3361) -LibDecimalFloatConstantsTest:testFloatMinNegativeValueIsMin(bytes32) (runs: 5107, μ: 3496, ~: 3457) +LibDecimalFloatConstantsTest:testFloatMinNegativeValueIsMin(bytes32) (runs: 5096, μ: 3497, ~: 3457) LibDecimalFloatConstantsTest:testFloatMinPositiveValue() (gas: 3383) -LibDecimalFloatConstantsTest:testFloatMinPositiveValueIsMin(bytes32) (runs: 5107, μ: 4965, ~: 4896) +LibDecimalFloatConstantsTest:testFloatMinPositiveValueIsMin(bytes32) (runs: 5071, μ: 4966, ~: 4896) LibDecimalFloatConstantsTest:testFloatOne() (gas: 3384) LibDecimalFloatConstantsTest:testFloatTwo() (gas: 3406) LibDecimalFloatConstantsTest:testFloatZero() (gas: 3332) -LibDecimalFloatDecimalAddTest:testAddPacked(bytes32,bytes32) (runs: 5107, μ: 11217, ~: 11314) -LibDecimalFloatDecimalLosslessTest:testFromFixedDecimalLosslessFail(uint256,uint8) (runs: 5107, μ: 9616, ~: 9663) -LibDecimalFloatDecimalLosslessTest:testFromFixedDecimalLosslessMem(uint256,uint8) (runs: 5107, μ: 8187, ~: 8104) -LibDecimalFloatDecimalLosslessTest:testFromFixedDecimalLosslessPass(uint256,uint8) (runs: 5107, μ: 7452, ~: 7424) +LibDecimalFloatDecimalAddTest:testAddPacked(bytes32,bytes32) (runs: 5096, μ: 11224, ~: 11338) +LibDecimalFloatDecimalLosslessTest:testFromFixedDecimalLosslessFail(uint256,uint8) (runs: 4585, μ: 9617, ~: 9663) +LibDecimalFloatDecimalLosslessTest:testFromFixedDecimalLosslessMem(uint256,uint8) (runs: 5096, μ: 8181, ~: 8104) +LibDecimalFloatDecimalLosslessTest:testFromFixedDecimalLosslessPass(uint256,uint8) (runs: 5096, μ: 8226, ~: 8200) LibDecimalFloatDecimalLosslessTest:testToFixedDecimalLosslessFail() (gas: 4894) -LibDecimalFloatDecimalLosslessTest:testToFixedDecimalLosslessPacked(bytes32,uint8) (runs: 5107, μ: 6729, ~: 6161) -LibDecimalFloatDecimalLosslessTest:testToFixedDecimalLosslessPass(int256,int256,uint8) (runs: 5107, μ: 15813, ~: 15768) -LibDecimalFloatDecimalTest:testFixedDecimalRoundTripLossless(uint256,uint8) (runs: 5107, μ: 9111, ~: 9031) +LibDecimalFloatDecimalLosslessTest:testToFixedDecimalLosslessPacked(bytes32,uint8) (runs: 5096, μ: 6672, ~: 6161) +LibDecimalFloatDecimalLosslessTest:testToFixedDecimalLosslessPass(int256,int256,uint8) (runs: 5096, μ: 15793, ~: 15768) +LibDecimalFloatDecimalTest:testFixedDecimalRoundTripLossless(uint256,uint8) (runs: 5096, μ: 9102, ~: 9031) LibDecimalFloatDecimalTest:testFromFixedDecimalLossyComplicated() (gas: 685958) LibDecimalFloatDecimalTest:testFromFixedDecimalLossyMax() (gas: 673463) LibDecimalFloatDecimalTest:testFromFixedDecimalLossyOne() (gas: 686002) LibDecimalFloatDecimalTest:testFromFixedDecimalLossyOneMillion() (gas: 685937) LibDecimalFloatDecimalTest:testFromFixedDecimalLossyOverflow() (gas: 715261) -LibDecimalFloatDecimalTest:testFromFixedDecimalLossyPacked(uint256,uint8) (runs: 5107, μ: 9537, ~: 9452) -LibDecimalFloatDecimalTest:testFromFixedDecimalLossyTruncateOne(uint256,uint8) (runs: 5107, μ: 5978, ~: 5937) -LibDecimalFloatDecimalTest:testFromFixedDecimalLossyTruncateZero(uint256,uint8) (runs: 5107, μ: 6067, ~: 5860) -LibDecimalFloatDecimalTest:testToFixedDecimalLosslessScaleUp(int256,int256,uint8) (runs: 5103, μ: 15997, ~: 15929) -LibDecimalFloatDecimalTest:testToFixedDecimalLossyExponentOverflow(int256,int256,uint8) (runs: 5107, μ: 14963, ~: 14729) -LibDecimalFloatDecimalTest:testToFixedDecimalLossyIdentity(int256,uint8) (runs: 5107, μ: 10155, ~: 9957) -LibDecimalFloatDecimalTest:testToFixedDecimalLossyNegative(int256,int256,uint8) (runs: 5107, μ: 10825, ~: 11076) -LibDecimalFloatDecimalTest:testToFixedDecimalLossyPacked(bytes32,uint8) (runs: 5107, μ: 6813, ~: 6905) -LibDecimalFloatDecimalTest:testToFixedDecimalLossyScaleUpOverflow(int256,int256,uint8) (runs: 5100, μ: 15351, ~: 15612) -LibDecimalFloatDecimalTest:testToFixedDecimalLossyTruncate(int256,int256,uint8) (runs: 5107, μ: 14493, ~: 14212) +LibDecimalFloatDecimalTest:testFromFixedDecimalLossyPacked(uint256,uint8) (runs: 5096, μ: 9530, ~: 9452) +LibDecimalFloatDecimalTest:testFromFixedDecimalLossyTruncateOne(uint256,uint8) (runs: 5096, μ: 5971, ~: 5937) +LibDecimalFloatDecimalTest:testFromFixedDecimalLossyTruncateZero(uint256,uint8) (runs: 5096, μ: 6037, ~: 5860) +LibDecimalFloatDecimalTest:testToFixedDecimalLosslessScaleUp(int256,int256,uint8) (runs: 2628, μ: 15964, ~: 15794) +LibDecimalFloatDecimalTest:testToFixedDecimalLossyExponentOverflow(int256,int256,uint8) (runs: 5096, μ: 14958, ~: 14729) +LibDecimalFloatDecimalTest:testToFixedDecimalLossyIdentity(int256,uint8) (runs: 5096, μ: 10163, ~: 9957) +LibDecimalFloatDecimalTest:testToFixedDecimalLossyNegative(int256,int256,uint8) (runs: 5096, μ: 10825, ~: 11076) +LibDecimalFloatDecimalTest:testToFixedDecimalLossyPacked(bytes32,uint8) (runs: 5096, μ: 6773, ~: 6905) +LibDecimalFloatDecimalTest:testToFixedDecimalLossyScaleUpOverflow(int256,int256,uint8) (runs: 2478, μ: 15343, ~: 15612) +LibDecimalFloatDecimalTest:testToFixedDecimalLossyTruncate(int256,int256,uint8) (runs: 5096, μ: 14484, ~: 14210) LibDecimalFloatDecimalTest:testToFixedDecimalLossyTruncateLossless() (gas: 14500) -LibDecimalFloatDecimalTest:testToFixedDecimalLossyUnderflow(int256,int256,uint8) (runs: 5107, μ: 13738, ~: 13602) -LibDecimalFloatDecimalTest:testToFixedDecimalLossyZero(int256,uint8) (runs: 5107, μ: 4575, ~: 4575) -LibDecimalFloatDivTest:testDivByNegativeOneFloat(int224,int32) (runs: 5107, μ: 361760, ~: 358393) -LibDecimalFloatDivTest:testDivByOneFloat(int224,int32) (runs: 5107, μ: 336347, ~: 333291) -LibDecimalFloatDivTest:testDivPacked(bytes32,bytes32) (runs: 5107, μ: 12720, ~: 12850) -LibDecimalFloatEqTest:testEqPacked(bytes32,bytes32) (runs: 5107, μ: 5524, ~: 5450) -LibDecimalFloatEqTest:testEqXNotYExponents(bytes32,bytes32) (runs: 5107, μ: 4341, ~: 4234) -LibDecimalFloatEqTest:testEqZero(int32) (runs: 5107, μ: 5123, ~: 5123) +LibDecimalFloatDecimalTest:testToFixedDecimalLossyUnderflow(int256,int256,uint8) (runs: 5096, μ: 13740, ~: 13602) +LibDecimalFloatDecimalTest:testToFixedDecimalLossyZero(int256,uint8) (runs: 5096, μ: 4575, ~: 4575) +LibDecimalFloatDivTest:testDivByNegativeOneFloat(int224,int32) (runs: 5096, μ: 363066, ~: 359444) +LibDecimalFloatDivTest:testDivByOneFloat(int224,int32) (runs: 5096, μ: 339115, ~: 337119) +LibDecimalFloatDivTest:testDivPacked(bytes32,bytes32) (runs: 5096, μ: 12730, ~: 12880) +LibDecimalFloatEqTest:testEqPacked(bytes32,bytes32) (runs: 5096, μ: 5526, ~: 5450) +LibDecimalFloatEqTest:testEqXNotYExponents(bytes32,bytes32) (runs: 5096, μ: 4344, ~: 4234) +LibDecimalFloatEqTest:testEqZero(int32) (runs: 5096, μ: 5123, ~: 5123) LibDecimalFloatFloorTest:testFloorExamples() (gas: 39140) LibDecimalFloatFloorTest:testFloorGas0() (gas: 1003) LibDecimalFloatFloorTest:testFloorGasTiny() (gas: 902) LibDecimalFloatFloorTest:testFloorGasZero() (gas: 548) -LibDecimalFloatFloorTest:testFloorInRange(int224,int256) (runs: 5107, μ: 11101, ~: 11130) -LibDecimalFloatFloorTest:testFloorLessThanMin(int224,int256) (runs: 5107, μ: 10302, ~: 10314) -LibDecimalFloatFloorTest:testFloorNonNegative(int224,int256) (runs: 5107, μ: 9591, ~: 9851) -LibDecimalFloatFloorTest:testFloorNotReverts(bytes32) (runs: 5107, μ: 459, ~: 365) -LibDecimalFloatFracTest:testFracExamples() (gas: 40054) +LibDecimalFloatFloorTest:testFloorInRange(int224,int256) (runs: 5096, μ: 11105, ~: 11130) +LibDecimalFloatFloorTest:testFloorLessThanMin(int224,int256) (runs: 5096, μ: 10304, ~: 10314) +LibDecimalFloatFloorTest:testFloorNonNegative(int224,int256) (runs: 5096, μ: 9596, ~: 9851) +LibDecimalFloatFloorTest:testFloorNotReverts(bytes32) (runs: 5096, μ: 464, ~: 365) +LibDecimalFloatFracTest:testFracExamples() (gas: 64760) LibDecimalFloatFracTest:testFracGas0() (gas: 1003) LibDecimalFloatFracTest:testFracGasTiny() (gas: 888) LibDecimalFloatFracTest:testFracGasZero() (gas: 810) -LibDecimalFloatFracTest:testFracInRange(int224,int256) (runs: 5107, μ: 10917, ~: 10934) -LibDecimalFloatFracTest:testFracLessThanMin(int224,int256) (runs: 5107, μ: 10343, ~: 10351) -LibDecimalFloatFracTest:testFracNonNegative(int224,int256) (runs: 5107, μ: 9826, ~: 10087) -LibDecimalFloatFracTest:testFracNotReverts(bytes32) (runs: 5107, μ: 634, ~: 616) +LibDecimalFloatFracTest:testFracInRange(int224,int256) (runs: 5096, μ: 10923, ~: 10934) +LibDecimalFloatFracTest:testFracLessThanMin(int224,int256) (runs: 5096, μ: 10340, ~: 10351) +LibDecimalFloatFracTest:testFracNonNegative(int224,int256) (runs: 5096, μ: 9833, ~: 10087) +LibDecimalFloatFracTest:testFracNotReverts(bytes32) (runs: 5096, μ: 637, ~: 616) LibDecimalFloatGtTest:testGtGasAZero() (gas: 994) LibDecimalFloatGtTest:testGtGasBZero() (gas: 994) LibDecimalFloatGtTest:testGtGasBothZero() (gas: 746) LibDecimalFloatGtTest:testGtGasDifferentSigns() (gas: 1026) LibDecimalFloatGtTest:testGtGasExponentDiffOverflow() (gas: 1195) -LibDecimalFloatGtTest:testGtOneEAny(bytes32) (runs: 5107, μ: 3494, ~: 3494) -LibDecimalFloatGtTest:testGtReference(int224,int32,int224,int32) (runs: 5107, μ: 8120, ~: 6350) -LibDecimalFloatGtTest:testGtX(int224,int32) (runs: 5107, μ: 3907, ~: 3908) -LibDecimalFloatGtTest:testGtXEAnyVsXEAny(int256,int32,int32) (runs: 5107, μ: 10644, ~: 10384) -LibDecimalFloatGtTest:testGtXEAnyVsXEAnyNegative(int256,int32,int32) (runs: 5107, μ: 11196, ~: 11401) -LibDecimalFloatGtTest:testGtXNotY(bytes32,bytes32) (runs: 5107, μ: 4341, ~: 4232) -LibDecimalFloatGtTest:testGtXPositiveYNegative(int256,int32,int256,int32) (runs: 5107, μ: 13816, ~: 13647) -LibDecimalFloatGtTest:testGtXPositiveYZero(int256,int32,int32) (runs: 5107, μ: 10295, ~: 10047) -LibDecimalFloatGtTest:testGtZero(int32,int32) (runs: 5107, μ: 4783, ~: 4783) +LibDecimalFloatGtTest:testGtOneEAny(bytes32) (runs: 5096, μ: 3494, ~: 3494) +LibDecimalFloatGtTest:testGtReference(int224,int32,int224,int32) (runs: 5096, μ: 8166, ~: 6585) +LibDecimalFloatGtTest:testGtX(int224,int32) (runs: 5096, μ: 3907, ~: 3908) +LibDecimalFloatGtTest:testGtXEAnyVsXEAny(int256,int32,int32) (runs: 5096, μ: 10640, ~: 10384) +LibDecimalFloatGtTest:testGtXEAnyVsXEAnyNegative(int256,int32,int32) (runs: 5096, μ: 11200, ~: 11401) +LibDecimalFloatGtTest:testGtXNotY(bytes32,bytes32) (runs: 5096, μ: 4343, ~: 4232) +LibDecimalFloatGtTest:testGtXPositiveYNegative(int256,int32,int256,int32) (runs: 5096, μ: 13810, ~: 13647) +LibDecimalFloatGtTest:testGtXPositiveYZero(int256,int32,int32) (runs: 5096, μ: 10290, ~: 10047) +LibDecimalFloatGtTest:testGtZero(int32,int32) (runs: 5096, μ: 4783, ~: 4783) LibDecimalFloatGteTest:testGteGasAZero() (gas: 997) LibDecimalFloatGteTest:testGteGasBZero() (gas: 1041) LibDecimalFloatGteTest:testGteGasBothZero() (gas: 748) LibDecimalFloatGteTest:testGteGasDifferentSigns() (gas: 1048) LibDecimalFloatGteTest:testGteGasExponentDiffOverflow() (gas: 1154) -LibDecimalFloatGteTest:testGteOneEAny(bytes32) (runs: 5107, μ: 3494, ~: 3494) -LibDecimalFloatGteTest:testGteReference(int224,int32,int224,int32) (runs: 5107, μ: 8169, ~: 6396) -LibDecimalFloatGteTest:testGteX(int224,int32) (runs: 5107, μ: 3950, ~: 3951) -LibDecimalFloatGteTest:testGteXEAnyVsXEAny(int256,int32,int32) (runs: 5107, μ: 10675, ~: 10416) -LibDecimalFloatGteTest:testGteXEAnyVsXEAnyNegative(int256,int32,int32) (runs: 5107, μ: 11207, ~: 11413) -LibDecimalFloatGteTest:testGteXNotLtY(bytes32,bytes32) (runs: 5107, μ: 3948, ~: 3873) -LibDecimalFloatGteTest:testGteXPositiveYNegative(int256,int32,int256,int32) (runs: 5107, μ: 13844, ~: 13675) -LibDecimalFloatGteTest:testGteXPositiveYZero(int256,int32,int32) (runs: 5107, μ: 9572, ~: 9191) -LibDecimalFloatGteTest:testGteZero(int32,int32) (runs: 5107, μ: 4828, ~: 4828) +LibDecimalFloatGteTest:testGteOneEAny(bytes32) (runs: 5096, μ: 3494, ~: 3494) +LibDecimalFloatGteTest:testGteReference(int224,int32,int224,int32) (runs: 5096, μ: 8209, ~: 6618) +LibDecimalFloatGteTest:testGteX(int224,int32) (runs: 5096, μ: 3950, ~: 3951) +LibDecimalFloatGteTest:testGteXEAnyVsXEAny(int256,int32,int32) (runs: 5096, μ: 10671, ~: 10416) +LibDecimalFloatGteTest:testGteXEAnyVsXEAnyNegative(int256,int32,int32) (runs: 5096, μ: 11211, ~: 11413) +LibDecimalFloatGteTest:testGteXNotLtY(bytes32,bytes32) (runs: 5096, μ: 3950, ~: 3873) +LibDecimalFloatGteTest:testGteXPositiveYNegative(int256,int32,int256,int32) (runs: 5096, μ: 13838, ~: 13675) +LibDecimalFloatGteTest:testGteXPositiveYZero(int256,int32,int32) (runs: 5096, μ: 9570, ~: 9191) +LibDecimalFloatGteTest:testGteZero(int32,int32) (runs: 5096, μ: 4828, ~: 4828) LibDecimalFloatImplementationAddTest:testAdd123456789987654321() (gas: 5327) LibDecimalFloatImplementationAddTest:testAdd123456789e9987654321() (gas: 5377) -LibDecimalFloatImplementationAddTest:testAddNeverRevert(int256,int256,int256,int256) (runs: 5107, μ: 13733, ~: 13711) +LibDecimalFloatImplementationAddTest:testAddNeverRevert(int256,int256,int256,int256) (runs: 5096, μ: 13740, ~: 13711) LibDecimalFloatImplementationAddTest:testAddOneOneNotMaximized() (gas: 6950) LibDecimalFloatImplementationAddTest:testAddOneOnePreMaximized() (gas: 4496) LibDecimalFloatImplementationAddTest:testAddOneZero() (gas: 3644) LibDecimalFloatImplementationAddTest:testAddRevertMaxA() (gas: 6316) -LibDecimalFloatImplementationAddTest:testAddSameExponent(int256,int256) (runs: 5106, μ: 7692, ~: 7811) +LibDecimalFloatImplementationAddTest:testAddSameExponent(int256,int256) (runs: 4332, μ: 7682, ~: 7811) LibDecimalFloatImplementationAddTest:testAddZero() (gas: 3665) -LibDecimalFloatImplementationAddTest:testAddZeroAnyExponent(int128) (runs: 5107, μ: 9293, ~: 9271) +LibDecimalFloatImplementationAddTest:testAddZeroAnyExponent(int128) (runs: 5096, μ: 9293, ~: 9271) LibDecimalFloatImplementationAddTest:testAddZeroOne() (gas: 3664) -LibDecimalFloatImplementationAddTest:testAddZeroToAnyNonZero(int256,int256,int256) (runs: 5107, μ: 14047, ~: 14015) +LibDecimalFloatImplementationAddTest:testAddZeroToAnyNonZero(int256,int256,int256) (runs: 5046, μ: 14050, ~: 14015) LibDecimalFloatImplementationAddTest:testAddingSmallToLargeReturnsLargeExamples() (gas: 107395) -LibDecimalFloatImplementationAddTest:testAddingSmallToLargeReturnsLargeFuzz(int256,int256,int256,int256) (runs: 5099, μ: 18265, ~: 18316) +LibDecimalFloatImplementationAddTest:testAddingSmallToLargeReturnsLargeFuzz(int256,int256,int256,int256) (runs: 2462, μ: 18263, ~: 18319) LibDecimalFloatImplementationAddTest:testGasAddOne() (gas: 1861) LibDecimalFloatImplementationAddTest:testGasAddZero() (gas: 382) -LibDecimalFloatImplementationAddTest:testOverflowChecks(int256,int256) (runs: 5107, μ: 3879, ~: 3865) +LibDecimalFloatImplementationAddTest:testOverflowChecks(int256,int256) (runs: 5096, μ: 3878, ~: 3865) LibDecimalFloatImplementationCharacteristicMantissaTest:testCharacteristicMantissaExamples() (gas: 31315) -LibDecimalFloatImplementationCharacteristicMantissaTest:testCharacteristicMantissaNegExponentLarge(int256,int256) (runs: 5107, μ: 10532, ~: 10762) -LibDecimalFloatImplementationCharacteristicMantissaTest:testCharacteristicMantissaNegExponentSmall(int256) (runs: 5107, μ: 203163, ~: 203163) -LibDecimalFloatImplementationCharacteristicMantissaTest:testCharacteristicMantissaNonNegExponent(int256,int256) (runs: 5107, μ: 9905, ~: 9695) +LibDecimalFloatImplementationCharacteristicMantissaTest:testCharacteristicMantissaNegExponentLarge(int256,int256) (runs: 5096, μ: 10534, ~: 10762) +LibDecimalFloatImplementationCharacteristicMantissaTest:testCharacteristicMantissaNegExponentSmall(int256) (runs: 5096, μ: 203163, ~: 203163) +LibDecimalFloatImplementationCharacteristicMantissaTest:testCharacteristicMantissaNonNegExponent(int256,int256) (runs: 5096, μ: 9903, ~: 9695) LibDecimalFloatImplementationDivTest:testDiv1Over3() (gas: 7679) LibDecimalFloatImplementationDivTest:testDiv1Over3Gas0() (gas: 2566) LibDecimalFloatImplementationDivTest:testDiv1Over3Gas10() (gas: 21216) LibDecimalFloatImplementationDivTest:testDiv1Over9Over1Over3() (gas: 16036) LibDecimalFloatImplementationDivTest:testDiv1e18Over3() (gas: 7233) -LibDecimalFloatImplementationDivTest:testDivBy1(int256,int256) (runs: 5107, μ: 366516, ~: 371759) -LibDecimalFloatImplementationDivTest:testDivByNegativeOneFloat(int256,int256) (runs: 5107, μ: 369018, ~: 374524) -LibDecimalFloatImplementationDivTest:testDivMaxPositiveValueDenominatorNotRevert(int256,int256) (runs: 5107, μ: 2597, ~: 2645) -LibDecimalFloatImplementationDivTest:testDivNegative1Over3() (gas: 7774) +LibDecimalFloatImplementationDivTest:testDivBy1(int256,int256) (runs: 5096, μ: 367142, ~: 371759) +LibDecimalFloatImplementationDivTest:testDivByNegativeOneFloat(int256,int256) (runs: 5096, μ: 371411, ~: 378366) +LibDecimalFloatImplementationDivTest:testDivMaxPositiveValueDenominatorNotRevert(int256,int256) (runs: 5096, μ: 2606, ~: 2645) +LibDecimalFloatImplementationDivTest:testDivNegative1Over3() (gas: 7832) LibDecimalFloatImplementationDivTest:testDivOOMs5and2() (gas: 6676) LibDecimalFloatImplementationDivTest:testDivOOMsOverTen() (gas: 7614) LibDecimalFloatImplementationDivTest:testDivTenOverOOMs() (gas: 7573) -LibDecimalFloatImplementationDivTest:testDivZero(int256,int256) (runs: 5107, μ: 9938, ~: 9948) -LibDecimalFloatImplementationDivTest:testUnnormalizedThreesDiv0(int256,int256) (runs: 111, μ: 29911409, ~: 29825155) +LibDecimalFloatImplementationDivTest:testDivZero(int256,int256) (runs: 5096, μ: 9939, ~: 9948) +LibDecimalFloatImplementationDivTest:testUnnormalizedThreesDiv0(int256,int256) (runs: 100, μ: 29906250, ~: 29825292) LibDecimalFloatImplementationEqTest:testEqGasAZero() (gas: 430) LibDecimalFloatImplementationEqTest:testEqGasBZero() (gas: 473) LibDecimalFloatImplementationEqTest:testEqGasBothZero() (gas: 450) LibDecimalFloatImplementationEqTest:testEqGasDifferentSigns() (gas: 482) LibDecimalFloatImplementationEqTest:testEqGasExponentDiffOverflow() (gas: 533) -LibDecimalFloatImplementationEqTest:testEqNotReverts(int256,int256,int256,int256) (runs: 5107, μ: 654, ~: 679) -LibDecimalFloatImplementationEqTest:testEqOneEAny(int256,int256) (runs: 5107, μ: 3416, ~: 3416) -LibDecimalFloatImplementationEqTest:testEqReference(int256,int256,int256,int256) (runs: 5107, μ: 9902, ~: 11437) -LibDecimalFloatImplementationEqTest:testEqX(int256) (runs: 5107, μ: 3392, ~: 3392) -LibDecimalFloatImplementationEqTest:testEqXEAnyVsXEAny(int256,int256,int256) (runs: 5105, μ: 4718, ~: 4714) -LibDecimalFloatImplementationEqTest:testEqXEqY(int256,int256,int256,int256) (runs: 5107, μ: 732, ~: 753) -LibDecimalFloatImplementationEqTest:testEqXNotY(int256,int256,int256,int256) (runs: 5107, μ: 3928, ~: 3953) -LibDecimalFloatImplementationEqTest:testEqZero(int256,int256) (runs: 5107, μ: 3440, ~: 3440) +LibDecimalFloatImplementationEqTest:testEqNotReverts(int256,int256,int256,int256) (runs: 5096, μ: 654, ~: 679) +LibDecimalFloatImplementationEqTest:testEqOneEAny(int256,int256) (runs: 5096, μ: 3416, ~: 3416) +LibDecimalFloatImplementationEqTest:testEqReference(int256,int256,int256,int256) (runs: 5096, μ: 9885, ~: 11361) +LibDecimalFloatImplementationEqTest:testEqX(int256) (runs: 5096, μ: 3392, ~: 3392) +LibDecimalFloatImplementationEqTest:testEqXEAnyVsXEAny(int256,int256,int256) (runs: 5048, μ: 4717, ~: 4714) +LibDecimalFloatImplementationEqTest:testEqXEqY(int256,int256,int256,int256) (runs: 5096, μ: 729, ~: 753) +LibDecimalFloatImplementationEqTest:testEqXNotY(int256,int256,int256,int256) (runs: 5094, μ: 3928, ~: 3953) +LibDecimalFloatImplementationEqTest:testEqZero(int256,int256) (runs: 5096, μ: 3440, ~: 3440) LibDecimalFloatImplementationInvTest:testInv0() (gas: 4452) LibDecimalFloatImplementationInvTest:testInvGas0() (gas: 2248) -LibDecimalFloatImplementationInvTest:testInvReference(int256,int256) (runs: 5105, μ: 15287, ~: 15355) +LibDecimalFloatImplementationInvTest:testInvReference(int256,int256) (runs: 5046, μ: 15312, ~: 15362) LibDecimalFloatImplementationInvTest:testInvSlowGas0() (gas: 2560) -LibDecimalFloatImplementationLog10Test:testExactLogs() (gas: 1268680) -LibDecimalFloatImplementationLog10Test:testExactLookupsLog10() (gas: 1312843) -LibDecimalFloatImplementationLog10Test:testInterpolatedLookups() (gas: 1262722) -LibDecimalFloatImplementationLog10Test:testLog10One() (gas: 1496827) -LibDecimalFloatImplementationLog10Test:testSub1() (gas: 1264080) -LibDecimalFloatImplementationMaximizeTest:testMaximizedEverything(int256,int256) (runs: 5107, μ: 9803, ~: 9799) +LibDecimalFloatImplementationLog10Test:testExactLogs() (gas: 1256416) +LibDecimalFloatImplementationLog10Test:testExactLookupsLog10() (gas: 1303855) +LibDecimalFloatImplementationLog10Test:testInterpolatedLookups() (gas: 1251083) +LibDecimalFloatImplementationLog10Test:testLog10One() (gas: 1484551) +LibDecimalFloatImplementationLog10Test:testSub1() (gas: 1252762) +LibDecimalFloatImplementationLookupLogTableValTest:testLookupLogTableVal() (gas: 1364784) +LibDecimalFloatImplementationMaximizeTest:testMaximizedEverything(int256,int256) (runs: 5096, μ: 9797, ~: 9799) LibDecimalFloatImplementationMaximizeTest:testMaximizedExamples() (gas: 192873) -LibDecimalFloatImplementationMaximizeTest:testMaximizedIdempotent(int256,int256) (runs: 5107, μ: 10347, ~: 10319) -LibDecimalFloatImplementationMaximizeTest:testMaximizedReference(int256,int256) (runs: 5107, μ: 13690, ~: 14630) -LibDecimalFloatImplementationMinusTest:testMinusIsSubZero(int256,int256,int256) (runs: 5107, μ: 12935, ~: 12916) +LibDecimalFloatImplementationMaximizeTest:testMaximizedIdempotent(int256,int256) (runs: 5096, μ: 10342, ~: 10306) +LibDecimalFloatImplementationMaximizeTest:testMaximizedReference(int256,int256) (runs: 5096, μ: 13638, ~: 14511) +LibDecimalFloatImplementationMinusTest:testMinusIsSubZero(int256,int256,int256) (runs: 5096, μ: 12931, ~: 12907) LibDecimalFloatImplementationMulTest:testMul123456789987654321() (gas: 5559) -LibDecimalFloatImplementationMulTest:testMul123456789987654321WithExponents(int128,int128) (runs: 5107, μ: 15078, ~: 15160) -LibDecimalFloatImplementationMulTest:testMul1_3979_0_5() (gas: 6193) +LibDecimalFloatImplementationMulTest:testMul123456789987654321WithExponents(int128,int128) (runs: 5096, μ: 15072, ~: 15160) +LibDecimalFloatImplementationMulTest:testMul1_3979_0_5() (gas: 6354) LibDecimalFloatImplementationMulTest:testMul1e181e19() (gas: 5603) LibDecimalFloatImplementationMulTest:testMulGasOne() (gas: 1470) LibDecimalFloatImplementationMulTest:testMulGasZero() (gas: 325) LibDecimalFloatImplementationMulTest:testMulMaxSignedCoefficient() (gas: 6674) LibDecimalFloatImplementationMulTest:testMulNegativeOne() (gas: 5660) -LibDecimalFloatImplementationMulTest:testMulNegativeOneOne() (gas: 5659) -LibDecimalFloatImplementationMulTest:testMulNotRevertAnyExpectation(int256,int256,int256,int256) (runs: 5107, μ: 15243, ~: 14593) -LibDecimalFloatImplementationMulTest:testMulOneNegativeOne() (gas: 5635) +LibDecimalFloatImplementationMulTest:testMulNegativeOneOne() (gas: 5717) +LibDecimalFloatImplementationMulTest:testMulNotRevertAnyExpectation(int256,int256,int256,int256) (runs: 5096, μ: 15322, ~: 14638) +LibDecimalFloatImplementationMulTest:testMulOneNegativeOne() (gas: 5693) LibDecimalFloatImplementationMulTest:testMulOneOne() (gas: 5582) LibDecimalFloatImplementationMulTest:testMulOneZero() (gas: 4481) LibDecimalFloatImplementationMulTest:testMulZero0Exponent() (gas: 4503) -LibDecimalFloatImplementationMulTest:testMulZeroAnyExponent(int64,int64) (runs: 5107, μ: 4704, ~: 4704) +LibDecimalFloatImplementationMulTest:testMulZeroAnyExponent(int64,int64) (runs: 5096, μ: 4704, ~: 4704) LibDecimalFloatImplementationMulTest:testMulZeroOne() (gas: 4438) -LibDecimalFloatImplementationPow10Test:testExactLookupsPow10() (gas: 1286051) -LibDecimalFloatImplementationPow10Test:testExactPows() (gas: 1261212) -LibDecimalFloatImplementationPow10Test:testInterpolatedLookupsPower() (gas: 1295117) -LibDecimalFloatImplementationPow10Test:testNoRevert(int224,int32) (runs: 5105, μ: 1261081, ~: 1260769) -LibDecimalFloatImplementationPow10Test:testPow10One() (gas: 1524458) -LibDecimalFloatImplementationSubTest:testSubIsAdd(int256,int256,int256,int256) (runs: 5106, μ: 17105, ~: 17227) -LibDecimalFloatImplementationSubTest:testSubMinSignedValue(int256,int256,int256) (runs: 5107, μ: 15928, ~: 15913) +LibDecimalFloatImplementationPow10Test:testExactLookupsPow10() (gas: 1280808) +LibDecimalFloatImplementationPow10Test:testExactPows() (gas: 1251875) +LibDecimalFloatImplementationPow10Test:testInterpolatedLookupsPower() (gas: 1283443) +LibDecimalFloatImplementationPow10Test:testNoRevert(int224,int32) (runs: 3632, μ: 1249376, ~: 1247204) +LibDecimalFloatImplementationPow10Test:testPow10One() (gas: 1557235) +LibDecimalFloatImplementationSubTest:testSubIsAdd(int256,int256,int256,int256) (runs: 5079, μ: 17124, ~: 17237) +LibDecimalFloatImplementationSubTest:testSubMinSignedValue(int256,int256,int256) (runs: 5096, μ: 15937, ~: 15910) LibDecimalFloatImplementationSubTest:testSubOneFromMax() (gas: 7308) -LibDecimalFloatImplementationSubTest:testSubSelf(int224,int32) (runs: 5107, μ: 6203, ~: 6369) -LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest:testUnabsUnsignedMulOrDivLossyMixedAB(uint256,uint256,uint256,int256) (runs: 5107, μ: 9961, ~: 9888) -LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest:testUnabsUnsignedMulOrDivLossyMixedABOverflow(uint256,uint256,uint256,int256) (runs: 5107, μ: 11207, ~: 11200) -LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest:testUnabsUnsignedMulOrDivLossyMixedBA(uint256,uint256,uint256,int256) (runs: 5107, μ: 11205, ~: 11198) -LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest:testUnabsUnsignedMulOrDivLossyMixedBAOverflow(uint256,uint256,int256) (runs: 5107, μ: 9071, ~: 9018) -LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest:testUnabsUnsignedMulOrDivLossyNegative(uint256,uint256,uint256,int256) (runs: 5107, μ: 9969, ~: 9892) -LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest:testUnabsUnsignedMulOrDivLossyNegativeOverflow(uint256,uint256,uint256,int256) (runs: 5107, μ: 11201, ~: 11190) -LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest:testUnabsUnsignedMulOrDivLossyPositive(uint256,uint256,uint256,int256) (runs: 5107, μ: 9103, ~: 9033) -LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest:testUnabsUnsignedMulOrDivLossyPositiveOverflow(uint256,uint256,uint256,int256) (runs: 5107, μ: 11090, ~: 11086) +LibDecimalFloatImplementationSubTest:testSubSelf(int224,int32) (runs: 5096, μ: 6210, ~: 6369) +LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest:testUnabsUnsignedMulOrDivLossyMixedAB(uint256,uint256,uint256,int256) (runs: 5096, μ: 10020, ~: 9946) +LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest:testUnabsUnsignedMulOrDivLossyMixedABOverflow(uint256,uint256,uint256,int256) (runs: 5069, μ: 11502, ~: 11491) +LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest:testUnabsUnsignedMulOrDivLossyMixedBA(uint256,uint256,uint256,int256) (runs: 5069, μ: 11501, ~: 11489) +LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest:testUnabsUnsignedMulOrDivLossyMixedBAOverflow(uint256,uint256,int256) (runs: 5096, μ: 9143, ~: 9090) +LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest:testUnabsUnsignedMulOrDivLossyNegative(uint256,uint256,uint256,int256) (runs: 5096, μ: 9970, ~: 9892) +LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest:testUnabsUnsignedMulOrDivLossyNegativeOverflow(uint256,uint256,uint256,int256) (runs: 5069, μ: 11366, ~: 11351) +LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest:testUnabsUnsignedMulOrDivLossyPositive(uint256,uint256,uint256,int256) (runs: 5096, μ: 9104, ~: 9033) +LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest:testUnabsUnsignedMulOrDivLossyPositiveOverflow(uint256,uint256,uint256,int256) (runs: 5069, μ: 11255, ~: 11247) LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentExamples() (gas: 13427) -LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentLargerExponentOverflowRescaleRevert(int256,int256,int256) (runs: 5100, μ: 14474, ~: 14443) -LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentLargerExponentVeryLargeDiffRevert(int256,int256,int256) (runs: 5107, μ: 13332, ~: 13610) -LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentLargerTargetExponentNoRevert(int256,int256,int256) (runs: 5107, μ: 11684, ~: 11740) -LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentMaxOverflow(int256) (runs: 5107, μ: 3769, ~: 3769) -LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentSameExponentNoop(int256,int256) (runs: 5107, μ: 3721, ~: 3721) -LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentScaleDown(int256,int256,int256) (runs: 5107, μ: 12963, ~: 12925) -LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentScaleUpLargeDiffRevert(int256,int256,int256) (runs: 5107, μ: 13503, ~: 13803) -LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentScaleUpNotOverflow(int256,int256,int256) (runs: 5105, μ: 13616, ~: 13547) -LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentScaleUpOverflow(int256,int256,int256) (runs: 5098, μ: 14127, ~: 14110) -LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentSmallerExponentNoRevert(int256,int256,int256) (runs: 5103, μ: 13872, ~: 13668) -LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentTargetMoreThan76Larger(int256,int256,int256) (runs: 5107, μ: 12451, ~: 12552) -LibDecimalFloatInvTest:testInvMem(bytes32) (runs: 5107, μ: 11234, ~: 11322) -LibDecimalFloatIsZeroTest:testIsZeroDeployed(bytes32) (runs: 5107, μ: 3899, ~: 3899) -LibDecimalFloatIsZeroTest:testIsZeroEqZero(bytes32) (runs: 5107, μ: 3527, ~: 3527) -LibDecimalFloatIsZeroTest:testIsZeroExamples(int32) (runs: 5107, μ: 4467, ~: 4467) -LibDecimalFloatIsZeroTest:testNotIsZero(int224,int32) (runs: 5106, μ: 3922, ~: 3922) -LibDecimalFloatLog10Test:testLog10Packed(bytes32) (runs: 5107, μ: 1654716, ~: 1275943) +LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentLargerExponentOverflowRescaleRevert(int256,int256,int256) (runs: 1766, μ: 14447, ~: 14443) +LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentLargerExponentVeryLargeDiffRevert(int256,int256,int256) (runs: 5096, μ: 13322, ~: 13562) +LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentLargerTargetExponentNoRevert(int256,int256,int256) (runs: 5096, μ: 11677, ~: 11740) +LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentMaxOverflow(int256) (runs: 5096, μ: 3769, ~: 3769) +LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentSameExponentNoop(int256,int256) (runs: 5096, μ: 3721, ~: 3721) +LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentScaleDown(int256,int256,int256) (runs: 5096, μ: 12964, ~: 12925) +LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentScaleUpLargeDiffRevert(int256,int256,int256) (runs: 5096, μ: 13499, ~: 13803) +LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentScaleUpNotOverflow(int256,int256,int256) (runs: 3354, μ: 13494, ~: 13431) +LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentScaleUpOverflow(int256,int256,int256) (runs: 1742, μ: 14130, ~: 14155) +LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentSmallerExponentNoRevert(int256,int256,int256) (runs: 3330, μ: 13863, ~: 13668) +LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentTargetMoreThan76Larger(int256,int256,int256) (runs: 5096, μ: 12443, ~: 12552) +LibDecimalFloatInvTest:testInvMem(bytes32) (runs: 5096, μ: 11277, ~: 11334) +LibDecimalFloatIsZeroTest:testIsZeroDeployed(bytes32) (runs: 5096, μ: 3899, ~: 3899) +LibDecimalFloatIsZeroTest:testIsZeroEqZero(bytes32) (runs: 5096, μ: 3527, ~: 3527) +LibDecimalFloatIsZeroTest:testIsZeroExamples(int32) (runs: 5096, μ: 4467, ~: 4467) +LibDecimalFloatIsZeroTest:testNotIsZero(int224,int32) (runs: 5039, μ: 3922, ~: 3922) +LibDecimalFloatLog10Test:testLog10Packed(bytes32) (runs: 5096, μ: 1643338, ~: 1265071) LibDecimalFloatLtTest:testLtExamples() (gas: 4015) LibDecimalFloatLtTest:testLtGasAZero() (gas: 967) LibDecimalFloatLtTest:testLtGasBZero() (gas: 1033) LibDecimalFloatLtTest:testLtGasBothZero() (gas: 959) LibDecimalFloatLtTest:testLtGasDifferentSigns() (gas: 1021) LibDecimalFloatLtTest:testLtGasExponentDiffOverflow() (gas: 1105) -LibDecimalFloatLtTest:testLtNegativeVsPositive(int256,int32,int256,int32) (runs: 5107, μ: 13801, ~: 13645) -LibDecimalFloatLtTest:testLtNegativeVsZero(int256,int32,int32) (runs: 5107, μ: 10810, ~: 11029) -LibDecimalFloatLtTest:testLtOneEAny(int224,int32) (runs: 5107, μ: 3930, ~: 3931) -LibDecimalFloatLtTest:testLtReference(bytes32,bytes32) (runs: 5107, μ: 4666, ~: 4998) -LibDecimalFloatLtTest:testLtVsEqualVsGt(bytes32,bytes32) (runs: 5107, μ: 4321, ~: 4210) -LibDecimalFloatLtTest:testLtX(int224) (runs: 5107, μ: 3823, ~: 3824) -LibDecimalFloatLtTest:testLtXEAnyVsXEAny(int256,int32,int32) (runs: 5107, μ: 10609, ~: 10349) -LibDecimalFloatLtTest:testLtXEAnyVsXEAnyNegative(int256,int32,int32) (runs: 5107, μ: 11205, ~: 11411) -LibDecimalFloatLtTest:testLtZero(int32,int32) (runs: 5107, μ: 4161, ~: 4161) +LibDecimalFloatLtTest:testLtNegativeVsPositive(int256,int32,int256,int32) (runs: 5096, μ: 13806, ~: 13645) +LibDecimalFloatLtTest:testLtNegativeVsZero(int256,int32,int32) (runs: 5096, μ: 10813, ~: 11029) +LibDecimalFloatLtTest:testLtOneEAny(int224,int32) (runs: 5096, μ: 3930, ~: 3931) +LibDecimalFloatLtTest:testLtReference(bytes32,bytes32) (runs: 5096, μ: 4654, ~: 4998) +LibDecimalFloatLtTest:testLtVsEqualVsGt(bytes32,bytes32) (runs: 5096, μ: 4326, ~: 4210) +LibDecimalFloatLtTest:testLtX(int224) (runs: 5096, μ: 3823, ~: 3824) +LibDecimalFloatLtTest:testLtXEAnyVsXEAny(int256,int32,int32) (runs: 5096, μ: 10605, ~: 10349) +LibDecimalFloatLtTest:testLtXEAnyVsXEAnyNegative(int256,int32,int32) (runs: 5096, μ: 11209, ~: 11411) +LibDecimalFloatLtTest:testLtZero(int32,int32) (runs: 5096, μ: 4161, ~: 4161) LibDecimalFloatLteTest:testLteGasAZero() (gas: 1018) LibDecimalFloatLteTest:testLteGasBZero() (gas: 1020) LibDecimalFloatLteTest:testLteGasBothZero() (gas: 748) LibDecimalFloatLteTest:testLteGasDifferentSigns() (gas: 1028) LibDecimalFloatLteTest:testLteGasExponentDiffOverflow() (gas: 1134) -LibDecimalFloatLteTest:testLteOneEAny(bytes32) (runs: 5107, μ: 3493, ~: 3493) -LibDecimalFloatLteTest:testLteReference(int224,int32,int224,int32) (runs: 5107, μ: 8161, ~: 6367) -LibDecimalFloatLteTest:testLteX(int224,int32) (runs: 5107, μ: 3929, ~: 3930) -LibDecimalFloatLteTest:testLteXEAnyVsXEAny(int256,int32,int32) (runs: 5107, μ: 10632, ~: 10373) -LibDecimalFloatLteTest:testLteXEAnyVsXEAnyNegative(int256,int32,int32) (runs: 5107, μ: 11228, ~: 11435) -LibDecimalFloatLteTest:testLteXNotLtY(bytes32,bytes32) (runs: 5107, μ: 3881, ~: 3807) -LibDecimalFloatLteTest:testLteXPositiveYNegative(int256,int32,int256,int32) (runs: 5107, μ: 13153, ~: 12983) -LibDecimalFloatLteTest:testLteXPositiveYZero(int256,int32,int32) (runs: 5107, μ: 9593, ~: 9212) -LibDecimalFloatLteTest:testLteZero(int32,int32) (runs: 5107, μ: 4806, ~: 4806) -LibDecimalFloatMaxTest:testMaxX(bytes32) (runs: 5107, μ: 4246, ~: 4246) -LibDecimalFloatMaxTest:testMaxXY(bytes32,bytes32) (runs: 5107, μ: 4689, ~: 4613) -LibDecimalFloatMaxTest:testMaxXYEqual(bytes32) (runs: 5107, μ: 5272, ~: 5272) -LibDecimalFloatMaxTest:testMaxXYGreater(bytes32,bytes32) (runs: 5104, μ: 6129, ~: 6016) -LibDecimalFloatMaxTest:testMaxXYLess(bytes32,bytes32) (runs: 5099, μ: 6141, ~: 6027) -LibDecimalFloatMinTest:testMinX(bytes32) (runs: 5107, μ: 4268, ~: 4268) -LibDecimalFloatMinTest:testMinXY(bytes32,bytes32) (runs: 5107, μ: 4689, ~: 4613) -LibDecimalFloatMinTest:testMinXYEqual(bytes32) (runs: 5107, μ: 5292, ~: 5292) -LibDecimalFloatMinTest:testMinXYGreater(bytes32,bytes32) (runs: 5102, μ: 6074, ~: 5961) -LibDecimalFloatMinTest:testMinXYLess(bytes32,bytes32) (runs: 5101, μ: 6087, ~: 5972) -LibDecimalFloatMinusTest:testMinusPacked(bytes32) (runs: 5107, μ: 5606, ~: 5607) +LibDecimalFloatLteTest:testLteOneEAny(bytes32) (runs: 5096, μ: 3493, ~: 3493) +LibDecimalFloatLteTest:testLteReference(int224,int32,int224,int32) (runs: 5096, μ: 8206, ~: 6615) +LibDecimalFloatLteTest:testLteX(int224,int32) (runs: 5096, μ: 3929, ~: 3930) +LibDecimalFloatLteTest:testLteXEAnyVsXEAny(int256,int32,int32) (runs: 5096, μ: 10624, ~: 10373) +LibDecimalFloatLteTest:testLteXEAnyVsXEAnyNegative(int256,int32,int32) (runs: 5096, μ: 11234, ~: 11435) +LibDecimalFloatLteTest:testLteXNotLtY(bytes32,bytes32) (runs: 5096, μ: 3884, ~: 3807) +LibDecimalFloatLteTest:testLteXPositiveYNegative(int256,int32,int256,int32) (runs: 5096, μ: 13145, ~: 12983) +LibDecimalFloatLteTest:testLteXPositiveYZero(int256,int32,int32) (runs: 5096, μ: 9587, ~: 9212) +LibDecimalFloatLteTest:testLteZero(int32,int32) (runs: 5096, μ: 4806, ~: 4806) +LibDecimalFloatMaxTest:testMaxX(bytes32) (runs: 5096, μ: 4246, ~: 4246) +LibDecimalFloatMaxTest:testMaxXY(bytes32,bytes32) (runs: 5096, μ: 4691, ~: 4613) +LibDecimalFloatMaxTest:testMaxXYEqual(bytes32) (runs: 5096, μ: 5272, ~: 5272) +LibDecimalFloatMaxTest:testMaxXYGreater(bytes32,bytes32) (runs: 2538, μ: 6132, ~: 6016) +LibDecimalFloatMaxTest:testMaxXYLess(bytes32,bytes32) (runs: 2553, μ: 6146, ~: 6027) +LibDecimalFloatMinTest:testMinX(bytes32) (runs: 5096, μ: 4268, ~: 4268) +LibDecimalFloatMinTest:testMinXY(bytes32,bytes32) (runs: 5096, μ: 4691, ~: 4613) +LibDecimalFloatMinTest:testMinXYEqual(bytes32) (runs: 5096, μ: 5292, ~: 5292) +LibDecimalFloatMinTest:testMinXYGreater(bytes32,bytes32) (runs: 2543, μ: 6079, ~: 5961) +LibDecimalFloatMinTest:testMinXYLess(bytes32,bytes32) (runs: 2548, μ: 6090, ~: 5972) +LibDecimalFloatMinusTest:testMinusPacked(bytes32) (runs: 5096, μ: 5606, ~: 5607) LibDecimalFloatMixedTest:testDiv1Over3Mixed() (gas: 11766) -LibDecimalFloatMulTest:testMulPacked(bytes32,bytes32) (runs: 5107, μ: 9690, ~: 10464) -LibDecimalFloatPackTest:testPackExponentOverflow(int256,int256) (runs: 5105, μ: 11079, ~: 11267) -LibDecimalFloatPackTest:testPackNegativeExponentLossyZero(int256,int256) (runs: 5105, μ: 11952, ~: 12110) -LibDecimalFloatPackTest:testPackZero(int256) (runs: 5107, μ: 4469, ~: 4469) -LibDecimalFloatPackTest:testPartsRoundTrip(int224,int32) (runs: 5107, μ: 5484, ~: 5485) -LibDecimalFloatPow10Test:testPow10Packed(bytes32) (runs: 5107, μ: 1642626, ~: 1259111) -LibDecimalFloatPowTest:testNegativePowError(bytes32,bytes32) (runs: 5107, μ: 1248827, ~: 1248862) -LibDecimalFloatPowTest:testPowAZero(int32,bytes32) (runs: 5105, μ: 1246465, ~: 1246465) -LibDecimalFloatPowTest:testPowAZeroNegative(bytes32) (runs: 5099, μ: 1246849, ~: 1246849) -LibDecimalFloatPowTest:testPowBOne(bytes32) (runs: 5107, μ: 1551450, ~: 1551421) -LibDecimalFloatPowTest:testPowBZero(bytes32,int32) (runs: 5107, μ: 1246055, ~: 1246055) -LibDecimalFloatPowTest:testPows() (gas: 1325200) -LibDecimalFloatPowTest:testRoundTripFuzzPow(bytes32,bytes32) (runs: 5107, μ: 1266340, ~: 1261251) -LibDecimalFloatPowTest:testRoundTripSimple() (gas: 1670404) -LibDecimalFloatSqrtTest:testRoundTripFuzzSqrt(int224,int32) (runs: 5107, μ: 1305456, ~: 1309267) -LibDecimalFloatSqrtTest:testSqrt() (gas: 1300463) -LibDecimalFloatSqrtTest:testSqrtNegative(bytes32) (runs: 5107, μ: 1248764, ~: 1248826) -LibDecimalFloatSqrtTest:testSqrtRoundTrip() (gas: 1454921) -LibDecimalFloatSubTest:testSubPacked(bytes32,bytes32) (runs: 5107, μ: 12226, ~: 12283) +LibDecimalFloatMulTest:testMulPacked(bytes32,bytes32) (runs: 5096, μ: 9793, ~: 10566) +LibDecimalFloatPackTest:testPackExponentOverflow(int256,int256) (runs: 5046, μ: 11085, ~: 11267) +LibDecimalFloatPackTest:testPackNegativeExponentLossyZero(int256,int256) (runs: 5046, μ: 11957, ~: 12110) +LibDecimalFloatPackTest:testPackZero(int256) (runs: 5096, μ: 4469, ~: 4469) +LibDecimalFloatPackTest:testPartsRoundTrip(int224,int32) (runs: 5096, μ: 5484, ~: 5485) +LibDecimalFloatPow10Test:testPow10Packed(bytes32) (runs: 5096, μ: 1630425, ~: 1248021) +LibDecimalFloatPowTest:testNegativePowError(bytes32,bytes32) (runs: 5039, μ: 1235076, ~: 1235194) +LibDecimalFloatPowTest:testPowAZero(int32,bytes32) (runs: 3512, μ: 1234225, ~: 1234225) +LibDecimalFloatPowTest:testPowAZeroNegative(bytes32) (runs: 1609, μ: 1234609, ~: 1234609) +LibDecimalFloatPowTest:testPowBOne(bytes32) (runs: 5072, μ: 1539182, ~: 1539153) +LibDecimalFloatPowTest:testPowBZero(bytes32,int32) (runs: 5096, μ: 1233793, ~: 1233793) +LibDecimalFloatPowTest:testPows() (gas: 1635705) +LibDecimalFloatPowTest:testRoundTripFuzzPow(bytes32,bytes32) (runs: 5096, μ: 1281141, ~: 1255407) +LibDecimalFloatPowTest:testRoundTripSimple() (gas: 1874217) +LibDecimalFloatSqrtTest:testRoundTripFuzzSqrt(int224,int32) (runs: 5096, μ: 1297633, ~: 1300240) +LibDecimalFloatSqrtTest:testSqrt() (gas: 1297587) +LibDecimalFloatSqrtTest:testSqrtNegative(bytes32) (runs: 5078, μ: 1234789, ~: 1234907) +LibDecimalFloatSqrtTest:testSqrtRoundTrip() (gas: 1516148) +LibDecimalFloatSubTest:testSubPacked(bytes32,bytes32) (runs: 5096, μ: 12228, ~: 12283) LibFormatDecimalFloatCountSigFigs:testCountSigFigsExamples() (gas: 83596) -LibFormatDecimalFloatCountSigFigs:testCountSigFigsOne(int256) (runs: 5107, μ: 31874, ~: 31719) -LibFormatDecimalFloatCountSigFigs:testCountSigFigsZero(int256) (runs: 5107, μ: 3764, ~: 3764) -LibFormatDecimalFloatToDecimalStringTest:testFormatDecimalCustomSigFigs() (gas: 26919) -LibFormatDecimalFloatToDecimalStringTest:testFormatDecimalExamples() (gas: 976448) -LibFormatDecimalFloatToDecimalStringTest:testFormatDecimalRoundTripExamples() (gas: 488510) -LibFormatDecimalFloatToDecimalStringTest:testFormatDecimalRoundTripNegative(int256,uint256) (runs: 5107, μ: 71433, ~: 73873) -LibFormatDecimalFloatToDecimalStringTest:testFormatDecimalRoundTripNonNegative(uint256,uint256) (runs: 5107, μ: 54974, ~: 47705) -LibLogTableBytesTest:testToBytesAntiLogTableDec() (gas: 159794) -LibLogTableBytesTest:testToBytesAntiLogTableDecSmall() (gas: 162322) -LibLogTableBytesTest:testToBytesLogTableDec() (gas: 143165) -LibLogTableBytesTest:testToBytesLogTableDecSmall() (gas: 145706) +LibFormatDecimalFloatCountSigFigs:testCountSigFigsOne(int256) (runs: 5096, μ: 31877, ~: 31719) +LibFormatDecimalFloatCountSigFigs:testCountSigFigsZero(int256) (runs: 5096, μ: 3764, ~: 3764) +LibFormatDecimalFloatToDecimalStringTest:testFormatDecimalCustomSigFigs() (gas: 26551) +LibFormatDecimalFloatToDecimalStringTest:testFormatDecimalExamples() (gas: 964702) +LibFormatDecimalFloatToDecimalStringTest:testFormatDecimalRoundTripExamples() (gas: 482274) +LibFormatDecimalFloatToDecimalStringTest:testFormatDecimalRoundTripNegative(int256,uint256) (runs: 5096, μ: 71852, ~: 74944) +LibFormatDecimalFloatToDecimalStringTest:testFormatDecimalRoundTripNonNegative(uint256,uint256) (runs: 5096, μ: 55582, ~: 47513) +LibLogTableBytesTest:testToBytesAntiLogTableDec() (gas: 158047) +LibLogTableBytesTest:testToBytesAntiLogTableDecSmall() (gas: 160663) +LibLogTableBytesTest:testToBytesLogTableDec() (gas: 141790) +LibLogTableBytesTest:testToBytesLogTableDecSmall() (gas: 144156) LibLogTableBytesTest:testToBytesLogTableDecSmallAlt() (gas: 18375) LibParseDecimalFloatTest:testParseDecimalFloatEmpty() (gas: 4173) LibParseDecimalFloatTest:testParseDecimalFloatExponentRevert() (gas: 4169) @@ -321,8 +322,8 @@ LibParseDecimalFloatTest:testParseDecimalFloatExponentRevert2() (gas: 5336) LibParseDecimalFloatTest:testParseDecimalFloatExponentRevert3() (gas: 5444) LibParseDecimalFloatTest:testParseDecimalFloatExponentRevert4() (gas: 4147) LibParseDecimalFloatTest:testParseDecimalFloatNonDecimal() (gas: 4145) -LibParseDecimalFloatTest:testParseFormatterRoundTripBug0() (gas: 27142) -LibParseDecimalFloatTest:testParseLiteralDecimalFloatDecimals() (gas: 384619) +LibParseDecimalFloatTest:testParseFormatterRoundTripBug0() (gas: 27193) +LibParseDecimalFloatTest:testParseLiteralDecimalFloatDecimals() (gas: 381180) LibParseDecimalFloatTest:testParseLiteralDecimalFloatDotE() (gas: 4166) LibParseDecimalFloatTest:testParseLiteralDecimalFloatDotE0() (gas: 4167) LibParseDecimalFloatTest:testParseLiteralDecimalFloatDotRevert() (gas: 4145) @@ -331,14 +332,14 @@ LibParseDecimalFloatTest:testParseLiteralDecimalFloatDotRevert3() (gas: 5140) LibParseDecimalFloatTest:testParseLiteralDecimalFloatEDot() (gas: 4168) LibParseDecimalFloatTest:testParseLiteralDecimalFloatExponentRevert5() (gas: 4176) LibParseDecimalFloatTest:testParseLiteralDecimalFloatExponentRevert6() (gas: 4166) -LibParseDecimalFloatTest:testParseLiteralDecimalFloatExponents() (gas: 402907) -LibParseDecimalFloatTest:testParseLiteralDecimalFloatFuzz(uint256,uint8,bool) (runs: 5107, μ: 46025, ~: 37187) +LibParseDecimalFloatTest:testParseLiteralDecimalFloatExponents() (gas: 402701) +LibParseDecimalFloatTest:testParseLiteralDecimalFloatFuzz(uint256,uint8,bool) (runs: 5096, μ: 45905, ~: 37134) LibParseDecimalFloatTest:testParseLiteralDecimalFloatLeadingZeros() (gas: 59757) -LibParseDecimalFloatTest:testParseLiteralDecimalFloatNegativeE() (gas: 6120) +LibParseDecimalFloatTest:testParseLiteralDecimalFloatNegativeE() (gas: 6000) LibParseDecimalFloatTest:testParseLiteralDecimalFloatNegativeFrac() (gas: 5115) -LibParseDecimalFloatTest:testParseLiteralDecimalFloatPrecisionRevert0() (gas: 27741) -LibParseDecimalFloatTest:testParseLiteralDecimalFloatPrecisionRevert1() (gas: 24934) +LibParseDecimalFloatTest:testParseLiteralDecimalFloatPrecisionRevert0() (gas: 27808) +LibParseDecimalFloatTest:testParseLiteralDecimalFloatPrecisionRevert1() (gas: 24984) LibParseDecimalFloatTest:testParseLiteralDecimalFloatSpecific() (gas: 22959) -LibParseDecimalFloatTest:testParseLiteralDecimalFloatUnrelated() (gas: 51254) -LibParseDecimalFloatTest:testParsePacked(string) (runs: 5107, μ: 9810, ~: 9692) -TestDecimalFloatUnpackTest:testUnpackDeployed(bytes32) (runs: 5107, μ: 169646, ~: 169646) \ No newline at end of file +LibParseDecimalFloatTest:testParseLiteralDecimalFloatUnrelated() (gas: 51251) +LibParseDecimalFloatTest:testParsePacked(string) (runs: 5096, μ: 9811, ~: 9692) +TestDecimalFloatUnpackTest:testUnpackDeployed(bytes32) (runs: 5096, μ: 169646, ~: 169646) \ No newline at end of file diff --git a/flake.lock b/flake.lock index 2c5fe29f..133533ee 100644 --- a/flake.lock +++ b/flake.lock @@ -75,11 +75,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1741023058, - "narHash": "sha256-LSd/8CBlpDLjci5ANFJjP0w+dGdY/mqKsyUfhjGwnfs=", + "lastModified": 1758705030, + "narHash": "sha256-zYM8PiEXANNrtjfyGUc7w37/D/kCynp0cQS+wCQ77GI=", "owner": "shazow", "repo": "foundry.nix", - "rev": "66becfe20b7e688b8f2e5774609c4436cf202ba0", + "rev": "b59a55014050110170023e3e1c277c1d4a2f055b", "type": "github" }, "original": { @@ -104,11 +104,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1749104371, - "narHash": "sha256-m2NmOPd6XgBiskmUq/BS9Xxuf3z0ebnGVfSKNAO5NEM=", + "lastModified": 1758711836, + "narHash": "sha256-uBqPg7wNX2v6YUdTswH7wWU8wqb60cFZx0tHaWTGF30=", "owner": "nixos", "repo": "nixpkgs", - "rev": "48975d7f9b9960ed33c4e8561bcce20cc0c2de5b", + "rev": "46f97b78e825ae762c0224e3983c47687436a498", "type": "github" }, "original": { @@ -158,11 +158,11 @@ "solc": "solc" }, "locked": { - "lastModified": 1749284231, - "narHash": "sha256-2pxLmguxgvcIaoCrxrrJaod+Sen/HjULnibdjogNp14=", + "lastModified": 1758730752, + "narHash": "sha256-ZQ1INSsEWYgb1NdC5zo6nu1ObLzOCDI+wjiZ4222fQ8=", "owner": "rainprotocol", "repo": "rainix", - "rev": "f3ef7c9b21db154d6e57858aa2f59ce40e6677bb", + "rev": "cc7c9bbbd9b817aa3a6a5c994262e14fb0bc920c", "type": "github" }, "original": { @@ -182,11 +182,11 @@ "nixpkgs": "nixpkgs_3" }, "locked": { - "lastModified": 1749091064, - "narHash": "sha256-TGtYjzRX0sueFhwYsnNNFF5TTKnpnloznpIghLzxeXo=", + "lastModified": 1758681214, + "narHash": "sha256-8cW731vev6kfr58cILO2ZsjHwaPhm88dQ8Q6nTSjP9I=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "12419593ce78f2e8e1e89a373c6515885e218acb", + "rev": "b12ed88d8d33d4f3cbc842bf29fad93bb1437299", "type": "github" }, "original": { @@ -202,11 +202,11 @@ "solc-macos-amd64-list-json": "solc-macos-amd64-list-json" }, "locked": { - "lastModified": 1748780655, - "narHash": "sha256-mradCdMvjXwKd7kVFACB/d1CP2LLCyEgUu4vJCSzNLU=", + "lastModified": 1756368702, + "narHash": "sha256-cqEHv7uCV0LibmQphyiXZ1+jYtGjMNb9Pae4tfcAcF8=", "owner": "hellwolf", "repo": "solc.nix", - "rev": "3b6f3223ace5a7bc400b01a434d86bb1cb2593fb", + "rev": "d83e90df2fa8359a690f6baabf76099432193c3f", "type": "github" }, "original": { @@ -218,13 +218,13 @@ "solc-macos-amd64-list-json": { "flake": false, "locked": { - "narHash": "sha256-U5ckttxwKO13gIKggel6iybG5oTDbSidPR5nH3Gs+kY=", + "narHash": "sha256-AvITkfpNYgCypXuLJyqco0li+unVw39BAfdOZvd/SPE=", "type": "file", - "url": "https://github.com/ethereum/solc-bin/raw/30a3695/macosx-amd64/list.json" + "url": "https://github.com/argotorg/solc-bin/raw/26fc3fd/macosx-amd64/list.json" }, "original": { "type": "file", - "url": "https://github.com/ethereum/solc-bin/raw/30a3695/macosx-amd64/list.json" + "url": "https://github.com/argotorg/solc-bin/raw/26fc3fd/macosx-amd64/list.json" } }, "systems": { diff --git a/src/error/ErrDecimalFloat.sol b/src/error/ErrDecimalFloat.sol index e91bb87a..8f2a8ac3 100644 --- a/src/error/ErrDecimalFloat.sol +++ b/src/error/ErrDecimalFloat.sol @@ -41,3 +41,6 @@ error MaximizeOverflow(int256 signedCoefficient, int256 exponent); /// @param signedCoefficient The signed coefficient of the numerator. /// @param exponent The exponent of the numerator. error DivisionByZero(int256 signedCoefficient, int256 exponent); + +/// @dev Thrown when attempting to exponentiate a negative base. +error PowNegativeBase(int256 signedCoefficient, int256 exponent); diff --git a/src/error/ErrFormat.sol b/src/error/ErrFormat.sol new file mode 100644 index 00000000..6eb173e4 --- /dev/null +++ b/src/error/ErrFormat.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: LicenseRef-DCL-1.0 +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd +pragma solidity ^0.8.25; + +/// @dev Thrown when the exponent cannot be formatted. +/// @param exponent The exponent that cannot be formatted. +error UnformatableExponent(int256 exponent); diff --git a/src/generated/LogTables.pointers.sol b/src/generated/LogTables.pointers.sol index a19220fd..07b17ef8 100644 --- a/src/generated/LogTables.pointers.sol +++ b/src/generated/LogTables.pointers.sol @@ -14,11 +14,11 @@ bytes32 constant BYTECODE_HASH = bytes32(0x0000000000000000000000000000000000000 /// @dev Log tables. bytes constant LOG_TABLES = - hex"0000002b0056008000aa80d480fd8126814e8176019e01c501ec02130239825f828582aa82cf82f30318033c0360038303a603c983ec840e843084520473049504b604d704f78517853785578577859605b505d405f306118630864e866c868986a786c406e106fe071a07370753076f878b87a787c387de07f90814082f084a0864887f889988b388cd88e70900091a0933094c0965097e899789b089c889e109f90a110a290a410a588a708a878a9e8ab68acd0ae40afa0b110b280b3e8b548b6b8b818b978bad0bc20bd80bee0c030c180c2e0c430c580c6d0c810c960cab0cbf0cd40ce80cfc0d110d250d390d4c0d600d740d880d9b0dae0dc20dd50de80dfb0e0e0e210e340e470e5a0e6c0e7f0e910ea30eb60ec80eda0eec0efe0f100f220f340f450f570f690f7a0f8b0f9d0fae0fbf0fd00fe10ff2100310141025103610461057106810781088109910a910b910ca10da10ea10fa110a111a1129113911491158116811781187119611a611b511c411d411e311f212011210121f122e123d124b125a126912781286129512a312b212c012ce12dd12eb12f913071316132413321340134e135b136913771385139313a013ae13bb13c913d713e413f113ff140c1419142714341441144e145b146814751482148f149c14a914b614c314d014dc14e914f61502150f151b152815341541154d155915661572157e158a159715a315af15bb15c715d315df15eb15f71603160f161a16261632163e164916551661166c16781683168f169a16a616b116bd16c816d316df16ea16f51700170b17171722172d17381743174e17591764176f177a1785178f179a17a517b017bb17c517d017db17e517f017fa18051810181a1824182f18391844184e18581863186d18771882188c189618a018aa18b518bf18c918d318dd18e718f118fb1905190f19191923192c19361940194a1954195d19671971197a1984198e199719a119ab19b419be19c719d119da19e419ed19f61a001a091a131a1c1a251a2e1a381a411a4a1a531a5d1a661a6f1a781a811a8a1a931a9c1aa51aae1ab71ac01ac91ad21adb1ae41aed1af61aff1b081b101b191b221b2b1b341b3c1b451b4e1b561b5f1b681b701b791b821b8a1b931b9b1ba41bac1bb51bbd1bc61bce1bd61bdf1be71bf01bf81c001c091c111c191c221c2a1c321c3a1c431c4b1c531c5b1c631c6b1c741c7c1c841c8c1c941c9c1ca41cac1cb41cbc1cc41ccc1cd41cdc1ce41cec1cf41cfb1d031d0b1d131d1b1d231d2a1d321d3a1d421d491d511d591d601d681d701d771d7f1d871d8e1d961d9e1da51dad1db41dbc1dc31dcb1dd21dda1de11de91df01df81dff1e061e0e1e151e1d1e241e2b1e331e3a1e411e481e501e571e5e1e661e6d1e741e7b1e821e8a1e911e981e9f1ea61ead1eb41ebc1ec31eca1ed11ed81edf1ee61eed1ef41efb1f021f091f101f171f1e1f251f2c1f331f391f401f471f4e1f551f5c1f631f691f701f771f7e1f851f8b1f921f991fa01fa61fad1fb41fba1fc11fc81fce1fd51fdc1fe21fe91ff01ff61ffd2003200a20112017201e2024202b20312038203e2045204b20522058205f2065206b20722078207f2085208b20922098209f20a520ab20b220b820be20c420cb20d120d720de20e420ea20f020f720fd21032109210f2116211c21222128212e2134213a21412147214d21532159215f2165216b21712177217d21832189218f2195219b21a121a721ad21b321b921bf21c521cb21d121d721dd21e321e921ee21f421fa22002206220c22122217221d22232229222f2234223a22402246224b22512257225d22622268226e22742279227f2285228a22902296229b22a122a722ac22b222b722bd22c322c822ce22d322d922df22e422ea22ef22f522fa23002305230b23102316231b23212326232c23312337233c23412347234c23522357235d23622367236d23722377237d23822388238d23922398239d23a223a823ad23b223b723bd23c223c723cd23d223d723dc23e223e723ec23f123f623fc24012406240b24102416241b24202425242a242f2435243a243f24442449244e24532458245d24632468246d24722477247c24812486248b24902495249a249f24a424a924ae24b324b824bd24c224c724cc24d124d624db24e024e524ea24ef24f424f924fd25022507250c25112516251b252025252529252e25332538253d25422546254b25502555255a255e25632568256d25722576257b258025852589258e25932598259c25a125a625ab25af25b425b925bd25c225c725cb25d025d525d925de25e325e725ec25f125f525fa25ff26032608260d26112616261a261f26232628262d26312636263a263f26432648264d26512656265a265f26632668266c26712675267a267e26832687268c269026952699269e26a226a626ab26af26b426b826bd26c126c626ca26ce26d326d726dc26e026e426e926ed26f126f626fa26ff27032707270c2710271027102710271027102710271027102710"; + hex"0000002b0056008000aa80d480fd8126814e8176019e01c501ec02130239825f828582aa82cf82f30318033c0360038303a603c983ec840e843084520473049504b604d704f78517853785578577859605b505d405f306118630864e866c868986a786c406e106fe071a07370753076f878b87a787c387de07f90814082f084a0864887f889988b388cd88e70900091a0933094c0965097e899789b089c889e109f90a110a290a410a588a708a878a9e8ab68acd0ae40afa0b110b280b3e8b548b6b8b818b978bad0bc20bd80bee0c030c180c2e0c430c580c6d0c810c960cab0cbf0cd40ce80cfc0d110d250d390d4c0d600d740d880d9b0dae0dc20dd50de80dfb0e0e0e210e340e470e5a0e6c0e7f0e910ea30eb60ec80eda0eec0efe0f100f220f340f450f570f690f7a0f8b0f9d0fae0fbf0fd00fe10ff2100310141025103610461057106810781088109910a910b910ca10da10ea10fa110a111a1129113911491158116811781187119611a611b511c411d411e311f212011210121f122e123d124b125a126912781286129512a312b212c012ce12dd12eb12f913071316132413321340134e135b136913771385139313a013ae13bb13c913d713e413f113ff140c1419142714341441144e145b146814751482148f149c14a914b614c314d014dc14e914f61502150f151b152815341541154d155915661572157e158a159715a315af15bb15c715d315df15eb15f71603160f161a16261632163e164916551661166c16781683168f169a16a616b116bd16c816d316df16ea16f51700170b17171722172d17381743174e17591764176f177a1785178f179a17a517b017bb17c517d017db17e517f017fa18051810181a1824182f18391844184e18581863186d18771882188c189618a018aa18b518bf18c918d318dd18e718f118fb1905190f19191923192c19361940194a1954195d19671971197a1984198e199719a119ab19b419be19c719d119da19e419ed19f61a001a091a131a1c1a251a2e1a381a411a4a1a531a5d1a661a6f1a781a811a8a1a931a9c1aa51aae1ab71ac01ac91ad21adb1ae41aed1af61aff1b081b101b191b221b2b1b341b3c1b451b4e1b561b5f1b681b701b791b821b8a1b931b9b1ba41bac1bb51bbd1bc61bce1bd61bdf1be71bf01bf81c001c091c111c191c221c2a1c321c3a1c431c4b1c531c5b1c631c6b1c741c7c1c841c8c1c941c9c1ca41cac1cb41cbc1cc41ccc1cd41cdc1ce41cec1cf41cfb1d031d0b1d131d1b1d231d2a1d321d3a1d421d491d511d591d601d681d701d771d7f1d871d8e1d961d9e1da51dad1db41dbc1dc31dcb1dd21dda1de11de91df01df81dff1e061e0e1e151e1d1e241e2b1e331e3a1e411e481e501e571e5e1e661e6d1e741e7b1e821e8a1e911e981e9f1ea61ead1eb41ebc1ec31eca1ed11ed81edf1ee61eed1ef41efb1f021f091f101f171f1e1f251f2c1f331f391f401f471f4e1f551f5c1f631f691f701f771f7e1f851f8b1f921f991fa01fa61fad1fb41fba1fc11fc81fce1fd51fdc1fe21fe91ff01ff61ffd2003200a20112017201e2024202b20312038203e2045204b20522058205f2065206b20722078207f2085208b20922098209f20a520ab20b220b820be20c420cb20d120d720de20e420ea20f020f720fd21032109210f2116211c21222128212e2134213a21412147214d21532159215f2165216b21712177217d21832189218f2195219b21a121a721ad21b321b921bf21c521cb21d121d721dd21e321e921ee21f421fa22002206220c22122217221d22232229222f2234223a22402246224b22512257225d22622268226e22742279227f2285228a22902296229b22a122a722ac22b222b722bd22c322c822ce22d322d922df22e422ea22ef22f522fa23002305230b23102316231b23212326232c23312337233c23412347234c23522357235d23622367236d23722377237d23822388238d23922398239d23a223a823ad23b223b723bd23c223c723cd23d223d723dc23e223e723ec23f123f623fc24012406240b24102416241b24202425242a242f2435243a243f24442449244e24532458245d24632468246d24722477247c24812486248b24902495249a249f24a424a924ae24b324b824bd24c224c724cc24d124d624db24e024e524ea24ef24f424f924fd25022507250c25112516251b252025252529252e25332538253d25422546254b25502555255a255e25632568256d25722576257b258025852589258e25932598259c25a125a625ab25af25b425b925bd25c225c725cb25d025d525d925de25e325e725ec25f125f525fa25ff26032608260d26112616261a261f26232628262d26312636263a263f26432648264d26512656265a265f26632668266c26712675267a267e26832687268c269026952699269e26a226a626ab26af26b426b826bd26c126c626ca26ce26d326d726dc26e026e426e926ed26f126f626fa26ff27032707270c"; /// @dev Log tables small. bytes constant LOG_TABLES_SMALL = - hex"0004090d11151a1e22260004080c0f13171b1f230003070b0e1215191c200003070a0d1014171a1e000306090c0f1215181c000306090b0e1114171a000305080b0e10131618000305080a0d0f12141700020507090c0e10131500020407090b0d10121400020406080b0d0f111300020406080a0c0e101200020406080a0c0e0f110002040607090b0d0f110002040507090b0c0e100002030507090a0c0e0f0002030507080a0b0d0f000203050608090b0d0e000203050608090b0c0e000103040607090a0c0d000103040607090a0b0d000103040607080a0b0c00010304050708090b0c00010304050608090a0c00010304050608090a0b00010204050607090a0b00010204050607080a0b0001020305060708090a0001020305060708090a0001020304050708090a0001020304050608090a000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070708000102030405050607080001020304040506070800010203040405060708000102030304050607080001020303040506070800010202030405060707000102020304050606070001020203040506060700010202030405050607000102020304050506070001020203040505060700010102030404050607000101020304040506070001010203040405060600010102030404050606000101020303040506060001010203030405050600010102030304050506000101020303040505060001010203030405050600010102030304050506000101020303040405060001010202030404050600010102020304040506000101020203040405050001010202030404050500010102020304040505000101020203040405050001010202030304050500010102020303040505000101020203030404050001010202030304040500010102020303040405000101020203030404050001010202030304040500010102020303040405000101020203030404050001010202030304040500010102020303040405000101020203030404050000010102020303040400000101020203030404000001010202030304040000010102020303040400000101020203030404000001010202030304040000010102020303040400000101020203030404000001010202030304040000010102020303040400000101020203030404000001010202030304040000010102020303030400000000000000000000"; + hex"0004090d11151a1e22260004080c0f13171b1f230003070b0e1215191c200003070a0d1014171a1e000306090c0f1215181c000306090b0e1114171a000305080b0e10131618000305080a0d0f12141700020507090c0e10131500020407090b0d10121400020406080b0d0f111300020406080a0c0e101200020406080a0c0e0f110002040607090b0d0f110002040507090b0c0e100002030507090a0c0e0f0002030507080a0b0d0f000203050608090b0d0e000203050608090b0c0e000103040607090a0c0d000103040607090a0b0d000103040607080a0b0c00010304050708090b0c00010304050608090a0c00010304050608090a0b00010204050607090a0b00010204050607080a0b0001020305060708090a0001020305060708090a0001020304050708090a0001020304050608090a0001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060707080001020304050506070800010203040405060708000102030404050607080001020303040506070800010203030405060708000102020304050607070001020203040506060700010202030405060607000102020304050506070001020203040505060700010202030405050607000101020304040506070001010203040405060700010102030404050606000101020304040506060001010203030405060600010102030304050506000101020303040505060001010203030405050600010102030304050506000101020303040505060001010203030404050600010102020304040506000101020203040405060001010202030404050500010102020304040505000101020203040405050001010202030404050500010102020303040505000101020203030405050001010202030304040500010102020303040405000101020203030404050001010202030304040500010102020303040405000101020203030404050001010202030304040500010102020303040405000101020203030404050001010202030304040500000101020203030404000001010202030304040000010102020303040400000101020203030404000001010202030304040000010102020303040400000101020203030404000001010202030304040000010102020303040400000101020203030404000001010202030304040000010102020303040400000101020203030304"; /// @dev Log tables small alt. bytes constant LOG_TABLES_SMALL_ALT = @@ -26,8 +26,8 @@ bytes constant LOG_TABLES_SMALL_ALT = /// @dev Anti log tables. bytes constant ANTI_LOG_TABLES = - hex"03e803ea03ed03ef03f103f403f603f803fb03fd03ff0402040404060409040b040e0410041204150417041a041c041e0421042304260428042b042d04300432043404370439043c043e0441044304460448044b044e0450045304550458045a045d045f046204650467046a046c046f047204740477047a047c047f0481048404870489048c048f049104940497049a049c049f04a204a504a704aa04ad04af04b204b504b804bb04bd04c004c304c604c904cb04ce04d104d404d704da04dd04df04e204e504e804eb04ee04f104f404f704fa04fc04ff050205050508050b050e051105140517051a051d0520052305260529052c052f053205360539053c053f054205450548054b054e055105550558055b055e056105640568056b056e057105740578057b057e058105850588058b058e059205950598059b059f05a205a505a905ac05af05b305b605ba05bd05c005c405c705cb05ce05d105d505d805dc05df05e305e605ea05ed05f105f405f805fb05ff060206060609060d061006140618061b061f06220626062a062d063106350638063c064006430647064b064e06520656065a065d066106650669066c067006740678067c067f06830687068b068f06930697069a069e06a206a606aa06ae06b206b606ba06be06c206c606ca06ce06d206d606da06de06e206e606ea06ee06f206f606fa06ff07030707070b070f07130718071c072007240728072d073107350739073e07420746074a074f07530757075c076007640769076d07710776077a077f07830788078c079007950799079e07a207a707ab07b007b407b907be07c207c707cb07d007d407d907de07e207e707ec07f007f507fa07fe08030808080d08110816081b082008240829082e08330838083d08410846084b08500855085a085f08640869086e08730878087d08820887088c08910896089b08a008a508aa08af08b408ba08bf08c408c908ce08d308d908de08e308e808ee08f308f808fd09030908090d09130918091d09230928092e09330938093e09430949094e09540959095f0964096a096f0975097b09800986098b09910997099c09a209a809ad09b309b909bf09c409ca09d009d609db09e109e709ed09f309f909ff0a040a0a0a100a160a1c0a220a280a2e0a340a3a0a400a460a4c0a520a590a5f0a650a6b0a710a770a7d0a840a8a0a900a960a9c0aa30aa90aaf0ab60abc0ac20ac90acf0ad50adc0ae20ae90aef0af50afc0b020b090b0f0b160b1c0b230b2a0b300b370b3d0b440b4b0b510b580b5f0b650b6c0b730b7a0b800b870b8e0b950b9c0ba30ba90bb00bb70bbe0bc50bcc0bd30bda0be10be80bef0bf60bfd0c040c0b0c120c190c210c280c2f0c360c3d0c450c4c0c530c5a0c620c690c700c780c7f0c860c8e0c950c9c0ca40cab0cb30cba0cc20cc90cd10cd90ce00ce80cef0cf70cff0d060d0e0d160d1d0d250d2d0d350d3c0d440d4c0d540d5c0d640d6c0d730d7b0d830d8b0d930d9b0da30dab0db40dbc0dc40dcc0dd40ddc0de40ded0df50dfd0e050e0d0e160e1e0e260e2f0e370e400e480e500e590e610e6a0e720e7b0e830e8c0e950e9d0ea60eae0eb70ec00ec80ed10eda0ee30eeb0ef40efd0f060f0f0f180f210f2a0f320f3b0f440f4d0f560f600f690f720f7b0f840f8d0f960f9f0fa90fb20fbb0fc40fce0fd70fe00fea0ff30ffd1006100f10191022102c1036103f10491052105c1066106f10791083108c109610a010aa10b410bd10c710d110db10e510ef10f91103110d11171121112b11361140114a1154115e11691173117d11871192119c11a711b111bb11c611d011db11e511f011fb12051210121a12251230123b12451250125b12661271127c12861291129c12a712b212bd12c812d312df12ea12f51300130b13171322132d13381344134f135b13661371137d13881394139f13ab13b713c213ce13da13e513f113fd140914141420142c143814441450145c146814741480148c149814a414b114bd14c914d514e214ee14fa150715131520152c153915451552155e156b157715841591159e15aa15b715c415d115de15ea15f716041611161e162b1639164616531660166d167a1688169516a216b016bd16ca16d816e516f31700170e171c17291737174517521760176e177c178a179717a517b317c117cf17dd17ec17fa18081816182418321841184f185d186c187a1889189718a618b418c318d118e018ef18fd190c191b192a193919471956196519741983199219a119b119c019cf19de19ed19fd1a0c1a1b1a2b1a3a1a4a1a591a691a781a881a981aa71ab71ac71ad71ae71af61b061b161b261b361b461b561b671b771b871b971ba71bb81bc81bd91be91bf91c0a1c1a1c2b1c3c1c4c1c5d1c6e1c7f1c8f1ca01cb11cc21cd31ce41cf51d061d171d281d3a1d4b1d5c1d6e1d7f1d901da21db31dc51dd61de81dfa1e0b1e1d1e2f1e411e521e641e761e881e9a1eac1ebe1ed11ee31ef51f071f1a1f2c1f3e1f511f631f761f881f9b1fae1fc01fd31fe61ff9200c201e203120442057206b207e209120a420b720cb20de20f121052118212c213f21532167217a218e21a221b621ca21de21f22206221a222e22422256226a227f229322a822bc22d122e522fa230e23232338234c23612376238b23a023b523ca23df23f4240a241f2434244a245f2475248a24a024b524cb24e124f6250c25222538254e2564257a259025a625bd25d325e925ff2616262c2643265926702687269e26b426cb26e226f92710271027102710271027102710271027102710"; + hex"03e803ea03ed03ef03f103f403f603f803fb03fd03ff0402040404060409040b040e0410041204150417041a041c041e0421042304260428042b042d04300432043404370439043c043e0441044304460448044b044e0450045304550458045a045d045f046204650467046a046c046f047204740477047a047c047f0481048404870489048c048f049104940497049a049c049f04a204a504a704aa04ad04af04b204b504b804bb04bd04c004c304c604c904cb04ce04d104d404d704da04dd04df04e204e504e804eb04ee04f104f404f704fa04fc04ff050205050508050b050e051105140517051a051d0520052305260529052c052f053205360539053c053f054205450548054b054e055105550558055b055e056105640568056b056e057105740578057b057e058105850588058b058e059205950598059b059f05a205a505a905ac05af05b305b605ba05bd05c005c405c705cb05ce05d105d505d805dc05df05e305e605ea05ed05f105f405f805fb05ff060206060609060d061006140618061b061f06220626062a062d063106350638063c064006430647064b064e06520656065a065d066106650669066c067006740678067c067f06830687068b068f06930697069a069e06a206a606aa06ae06b206b606ba06be06c206c606ca06ce06d206d606da06de06e206e606ea06ee06f206f606fa06ff07030707070b070f07130718071c072007240728072d073107350739073e07420746074a074f07530757075c076007640769076d07710776077a077f07830788078c079007950799079e07a207a707ab07b007b407b907be07c207c707cb07d007d407d907de07e207e707ec07f007f507fa07fe08030808080d08110816081b082008240829082e08330838083d08410846084b08500855085a085f08640869086e08730878087d08820887088c08910896089b08a008a508aa08af08b408ba08bf08c408c908ce08d308d908de08e308e808ee08f308f808fd09030908090d09130918091d09230928092e09330938093e09430949094e09540959095f0964096a096f0975097b09800986098b09910997099c09a209a809ad09b309b909bf09c409ca09d009d609db09e109e709ed09f309f909ff0a040a0a0a100a160a1c0a220a280a2e0a340a3a0a400a460a4c0a520a590a5f0a650a6b0a710a770a7d0a840a8a0a900a960a9c0aa30aa90aaf0ab60abc0ac20ac90acf0ad50adc0ae20ae90aef0af50afc0b020b090b0f0b160b1c0b230b2a0b300b370b3d0b440b4b0b510b580b5f0b650b6c0b730b7a0b800b870b8e0b950b9c0ba30ba90bb00bb70bbe0bc50bcc0bd30bda0be10be80bef0bf60bfd0c040c0b0c120c190c210c280c2f0c360c3d0c450c4c0c530c5a0c620c690c700c780c7f0c860c8e0c950c9c0ca40cab0cb30cba0cc20cc90cd10cd90ce00ce80cef0cf70cff0d060d0e0d160d1d0d250d2d0d350d3c0d440d4c0d540d5c0d640d6c0d730d7b0d830d8b0d930d9b0da30dab0db40dbc0dc40dcc0dd40ddc0de40ded0df50dfd0e050e0d0e160e1e0e260e2f0e370e400e480e500e590e610e6a0e720e7b0e830e8c0e950e9d0ea60eae0eb70ec00ec80ed10eda0ee30eeb0ef40efd0f060f0f0f180f210f2a0f320f3b0f440f4d0f560f600f690f720f7b0f840f8d0f960f9f0fa90fb20fbb0fc40fce0fd70fe00fea0ff30ffd1006100f10191022102c1036103f10491052105c1066106f10791083108c109610a010aa10b410bd10c710d110db10e510ef10f91103110d11171121112b11361140114a1154115e11691173117d11871192119c11a711b111bb11c611d011db11e511f011fb12051210121a12251230123b12451250125b12661271127c12861291129c12a712b212bd12c812d312df12ea12f51300130b13171322132d13381344134f135b13661371137d13881394139f13ab13b713c213ce13da13e513f113fd140914141420142c143814441450145c146814741480148c149814a414b114bd14c914d514e214ee14fa150715131520152c153915451552155e156b157715841591159e15aa15b715c415d115de15ea15f716041611161e162b1639164616531660166d167a1688169516a216b016bd16ca16d816e516f31700170e171c17291737174517521760176e177c178a179717a517b317c117cf17dd17ec17fa18081816182418321841184f185d186c187a1889189718a618b418c318d118e018ef18fd190c191b192a193919471956196519741983199219a119b119c019cf19de19ed19fd1a0c1a1b1a2b1a3a1a4a1a591a691a781a881a981aa71ab71ac71ad71ae71af61b061b161b261b361b461b561b671b771b871b971ba71bb81bc81bd91be91bf91c0a1c1a1c2b1c3c1c4c1c5d1c6e1c7f1c8f1ca01cb11cc21cd31ce41cf51d061d171d281d3a1d4b1d5c1d6e1d7f1d901da21db31dc51dd61de81dfa1e0b1e1d1e2f1e411e521e641e761e881e9a1eac1ebe1ed11ee31ef51f071f1a1f2c1f3e1f511f631f761f881f9b1fae1fc01fd31fe61ff9200c201e203120442057206b207e209120a420b720cb20de20f121052118212c213f21532167217a218e21a221b621ca21de21f22206221a222e22422256226a227f229322a822bc22d122e522fa230e23232338234c23612376238b23a023b523ca23df23f4240a241f2434244a245f2475248a24a024b524cb24e124f6250c25222538254e2564257a259025a625bd25d325e925ff2616262c2643265926702687269e26b426cb26e226f9"; /// @dev Anti log tables small. bytes constant ANTI_LOG_TABLES_SMALL = - hex"0000000101010102020200000001010101020202000000010101010202020000000101010102020200000101010102020202000001010101020202020000010101010202020200000101010102020202000001010101020202030000010101010202020300000101010102020203000001010102020202030000010101020202020300000101010202020303000001010102020203030000010101020202030300000101010202020303000001010102020203030000010101020202030300000101010202030303000001010102020303030000010102020203030300000101020202030303000001010202020303040000010102020203030400000101020202030304000001010202030303040000010102020303030400000101020203030404000001010202030304040000010102020303040400000101020203030404000001010202030304040000010102020303040400010102020303040405000101020203030404050001010202030304040500010102020303040405000101020203030404050001010202030304050500010102020304040505000101020203040405050001010202030404050600010102030304040506000101020303040405060001010203030405050600010102030304050506000101020303040505060001010203040405060600010102030404050606000101020304040506070001020203040505060700010202030405050607000102020304050606070001020203040506060700010202030405060707000102030304050607080001020303040506070800010203040405060708000102030405050607080001020304050606070800010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607090a0001020304050708090a0001020304060708090a0001020305060708090a0001020405060708090b00010204050607080a0b00010204050607090a0b00010304050608090a0b00010304050608090a0c00010304050708090a0c00010304050708090b0c000103040507080a0b0c000103040607080a0b0d000103040607090a0b0d000103040607090a0c0d000203050608090b0c0e000203050608090b0c0e000203050608090b0d0e0002030506080a0b0d0f0002030507080a0c0d0f0002030507080a0c0d0f0002030507090a0c0e100002040507090b0c0e100002040507090b0d0e100002040607090b0d0f110002040608090b0d0f1100020406080a0c0e0f1100020406080a0c0e101200020406080a0c0e101200020406080a0c0f111300020406080b0d0f111300020407090b0d0f111400020407090b0d10121400020507090b0e10121400000000000000000000"; + hex"0000000101010102020200000001010101020202000000010101010202020000000101010102020200000101010102020202000001010101020202020000010101010202020200000101010102020202000001010101020202030000010101010202020300000101010102020203000001010102020202030000010101020202020300000101010202020303000001010102020203030000010101020202030300000101010202020303000001010102020203030000010101020202030300000101010202030303000001010102020303030000010102020203030300000101020202030303000001010202020303040000010102020203030400000101020202030304000001010202030303040000010102020303030400000101020203030404000001010202030304040000010102020303040400000101020203030404000001010202030304040000010102020303040400010102020303040405000101020203030404050001010202030304040500010102020303040405000101020203030404050001010202030304050500010102020304040505000101020203040405050001010202030404050600010102030304040506000101020303040405060001010203030405050600010102030304050506000101020303040505060001010203040405060600010102030404050606000101020304040506070001020203040505060700010202030405050607000102020304050606070001020203040506060700010202030405060707000102030304050607080001020303040506070800010203040405060708000102030405050607080001020304050606070800010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607090a0001020304050708090a0001020304060708090a0001020305060708090a0001020405060708090b00010204050607080a0b00010204050607090a0b00010304050608090a0b00010304050608090a0c00010304050708090a0c00010304050708090b0c000103040507080a0b0c000103040607080a0b0d000103040607090a0b0d000103040607090a0c0d000203050608090b0c0e000203050608090b0c0e000203050608090b0d0e0002030506080a0b0d0f0002030507080a0c0d0f0002030507080a0c0d0f0002030507090a0c0e100002040507090b0c0e100002040507090b0d0e100002040607090b0d0f110002040608090b0d0f1100020406080a0c0e0f1100020406080a0c0e101200020406080a0c0e101200020406080a0c0f111300020406080b0d0f111300020407090b0d0f111400020407090b0d10121400020507090b0e101214"; diff --git a/src/lib/LibDecimalFloat.sol b/src/lib/LibDecimalFloat.sol index 8f9ed14c..07d850f9 100644 --- a/src/lib/LibDecimalFloat.sol +++ b/src/lib/LibDecimalFloat.sol @@ -2,27 +2,16 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.25; -import { - LOG_TABLES, - LOG_TABLES_SMALL, - LOG_TABLES_SMALL_ALT, - ANTI_LOG_TABLES, - ANTI_LOG_TABLES_SMALL -} from "../generated/LogTables.pointers.sol"; import { ExponentOverflow, CoefficientOverflow, - Log10Zero, NegativeFixedDecimalConversion, LossyConversionFromFloat, LossyConversionToFloat, - ZeroNegativePower + ZeroNegativePower, + PowNegativeBase } from "../error/ErrDecimalFloat.sol"; -import { - LibDecimalFloatImplementation, - EXPONENT_MAX, - EXPONENT_MIN -} from "./implementation/LibDecimalFloatImplementation.sol"; +import {LibDecimalFloatImplementation} from "./implementation/LibDecimalFloatImplementation.sol"; type Float is bytes32; @@ -116,8 +105,12 @@ library LibDecimalFloat { // Catch an edge case where unsigned value looks like a negative // value when coerced. if (value > uint256(type(int256).max)) { + // value is divided by 10 so won't truncate when cast. + // forge-lint: disable-next-line(unsafe-typecast) return (int256(value / 10), exponent + 1, value % 10 == 0); } else { + // case that would truncate is handled above. + // forge-lint: disable-next-line(unsafe-typecast) return (int256(value), exponent, true); } } @@ -191,6 +184,7 @@ library LibDecimalFloat { return (0, true); } else { // Safe to do this conversion because we revert above on negative. + // forge-lint: disable-next-line(unsafe-typecast) uint256 unsignedCoefficient = uint256(signedCoefficient); int256 finalExponent; @@ -216,6 +210,9 @@ library LibDecimalFloat { // At this point, scale cannot revert, so it is safe to do // this unchecked. + // finalExponent is negative here so making it absolute will + // always fit in uint256. + // forge-lint: disable-next-line(unsafe-typecast) scale = 10 ** uint256(-finalExponent); fixedDecimal = unsignedCoefficient / scale; @@ -225,6 +222,8 @@ library LibDecimalFloat { return (fixedDecimal, fixedDecimal * scale == unsignedCoefficient); } } else if (finalExponent > 0) { + // finalExponent is positive here. + // forge-lint: disable-next-line(unsafe-typecast) scale = 10 ** uint256(finalExponent); fixedDecimal = unsignedCoefficient * scale; unchecked { @@ -298,6 +297,10 @@ library LibDecimalFloat { unchecked { int256 initialSignedCoefficient = signedCoefficient; int256 initialExponent = exponent; + // lossless is true if the signed coefficient fits in int224. + // truncation here is intentional if it happens as that is what we + // are testing for. + // forge-lint: disable-next-line(unsafe-typecast) lossless = int224(signedCoefficient) == signedCoefficient; // The reason that we can do unchecked exponent addition here is that @@ -310,6 +313,9 @@ library LibDecimalFloat { exponent += 5; } + // truncation here is intentional if it happens as that is what we + // are testing for. + // forge-lint: disable-next-line(unsafe-typecast) while (int224(signedCoefficient) != signedCoefficient) { signedCoefficient /= 10; ++exponent; @@ -320,6 +326,9 @@ library LibDecimalFloat { } } + // truncation here is intentional if it happens as that is what we + // are testing for. + // forge-lint: disable-next-line(unsafe-typecast) if (int32(exponent) != exponent) { // If the exponent is negative then this is a number too small // to pack. We return zero but it is not a lossless conversion. @@ -666,34 +675,64 @@ library LibDecimalFloat { /// logarithm tables. function pow(Float a, Float b, address tablesDataContract) internal view returns (Float) { (int256 signedCoefficientA, int256 exponentA) = a.unpack(); + if (b.isZero()) { return FLOAT_ONE; - } else if (signedCoefficientA == 0) { - if (b.lt(FLOAT_ZERO)) { - // If b is negative, and a is 0, so we revert. - revert ZeroNegativePower(b); - } + } else if (signedCoefficientA <= 0) { + if (signedCoefficientA == 0) { + if (b.lt(FLOAT_ZERO)) { + // If b is negative, and a is 0, so we revert. + revert ZeroNegativePower(b); + } - // If a is zero, then a^b is always zero, regardless of b. - // This is a special case because log10(0) is undefined. - return FLOAT_ZERO; + // If a is zero, then a^b is always zero, regardless of b. + // This is a special case because log10(0) is undefined. + return FLOAT_ZERO; + } else { + revert PowNegativeBase(signedCoefficientA, exponentA); + } } // Handle identity case for positive values of a, i.e. a^1. else if (b.eq(FLOAT_ONE) && a.gt(FLOAT_ZERO)) { return a; + } else if (b.lt(FLOAT_ZERO)) { + return pow(a.inv(), b.minus(), tablesDataContract); + } + + (int256 signedCoefficientB, int256 exponentB) = b.unpack(); + (int256 characteristicB, int256 mantissaB) = + LibDecimalFloatImplementation.characteristicMantissa(signedCoefficientB, exponentB); + + uint256 exponentBInteger = + uint256(LibDecimalFloatImplementation.withTargetExponent(characteristicB, exponentB, 0)); + + // Exponentiation by squaring. + (int256 signedCoefficientResult, int256 exponentResult) = (1, 0); + (int256 signedCoefficientBase, int256 exponentBase) = a.unpack(); + while (exponentBInteger >= 1) { + if (exponentBInteger & 0x01 == 0x01) { + (signedCoefficientResult, exponentResult) = LibDecimalFloatImplementation.mul( + signedCoefficientResult, exponentResult, signedCoefficientBase, exponentBase + ); + } + exponentBInteger >>= 1; + (signedCoefficientBase, exponentBase) = LibDecimalFloatImplementation.mul( + signedCoefficientBase, exponentBase, signedCoefficientBase, exponentBase + ); } (int256 signedCoefficientC, int256 exponentC) = LibDecimalFloatImplementation.log10(tablesDataContract, signedCoefficientA, exponentA); - (int256 signedCoefficientB, int256 exponentB) = b.unpack(); - (signedCoefficientC, exponentC) = - LibDecimalFloatImplementation.mul(signedCoefficientC, exponentC, signedCoefficientB, exponentB); + LibDecimalFloatImplementation.mul(signedCoefficientC, exponentC, mantissaB, exponentB); (signedCoefficientC, exponentC) = LibDecimalFloatImplementation.pow10(tablesDataContract, signedCoefficientC, exponentC); + (signedCoefficientC, exponentC) = + LibDecimalFloatImplementation.mul(signedCoefficientC, exponentC, signedCoefficientResult, exponentResult); + (Float c, bool lossless) = packLossy(signedCoefficientC, exponentC); // We don't care if power is lossy because it's an approximation anyway. (lossless); diff --git a/src/lib/format/LibFormatDecimalFloat.sol b/src/lib/format/LibFormatDecimalFloat.sol index 7acf1e6f..9712cec7 100644 --- a/src/lib/format/LibFormatDecimalFloat.sol +++ b/src/lib/format/LibFormatDecimalFloat.sol @@ -4,11 +4,12 @@ pragma solidity ^0.8.25; import {LibDecimalFloat, Float} from "../LibDecimalFloat.sol"; -import {LibFixedPointDecimalFormat} from "rain.math.fixedpoint/lib/format/LibFixedPointDecimalFormat.sol"; import {LibDecimalFloatImplementation} from "../../lib/implementation/LibDecimalFloatImplementation.sol"; import {Strings} from "openzeppelin-contracts/contracts/utils/Strings.sol"; +import {UnformatableExponent} from "../../error/ErrFormat.sol"; + library LibFormatDecimalFloat { function countSigFigs(int256 signedCoefficient, int256 exponent) internal pure returns (uint256) { if (signedCoefficient == 0) { @@ -32,8 +33,12 @@ library LibFormatDecimalFloat { // Adjust for exponent if (exponent < 0) { exponent = -exponent; + // exponent > 0 + // forge-lint: disable-next-line(unsafe-typecast) sigFigs = sigFigs > uint256(exponent) ? sigFigs : uint256(exponent); } else if (exponent > 0) { + // exponent > 0 + // forge-lint: disable-next-line(unsafe-typecast) sigFigs += uint256(exponent); } @@ -59,24 +64,49 @@ library LibFormatDecimalFloat { if (scientific) { (signedCoefficient, exponent) = LibDecimalFloatImplementation.maximizeFull(signedCoefficient, exponent); - bool isAtLeastE76 = signedCoefficient / 1e76 != 0; - scaleExponent = isAtLeastE76 ? uint256(76) : uint256(75); - scale = uint256(10) ** scaleExponent; + if (signedCoefficient / 1e76 != 0) { + scaleExponent = 76; + scale = 1e76; + } else { + scaleExponent = 75; + scale = 1e75; + } } else { if (exponent > 0) { + // exponent > 0 + // forge-lint: disable-next-line(unsafe-typecast) signedCoefficient *= int256(10) ** uint256(exponent); exponent = 0; } if (exponent < 0) { + if (exponent < -76) { + revert UnformatableExponent(exponent); + } + // negating a signed exponent will always fit in uint256. + // forge-lint: disable-next-line(unsafe-typecast) scale = uint256(10) ** uint256(-exponent); + // negating a signed exponent will always fit in uint256. + // forge-lint: disable-next-line(unsafe-typecast) scaleExponent = uint256(-exponent); } else { - scaleExponent = uint256(exponent); + // exponent is zero here. + scaleExponent = 0; } } - int256 integral = scale != 0 ? signedCoefficient / int256(scale) : signedCoefficient; - int256 fractional = scale != 0 ? signedCoefficient % int256(scale) : int256(0); + int256 integral = signedCoefficient; + int256 fractional = int256(0); + if (scale != 0) { + // scale is one of two possible values so won't truncate when cast + // or explicitly has a guard against it truncating. + // forge-lint: disable-next-line(unsafe-typecast) + integral = signedCoefficient / int256(scale); + // scale is one of two possible values so won't truncate when cast + // or explicitly has a guard against it truncating. + // forge-lint: disable-next-line(unsafe-typecast) + fractional = signedCoefficient % int256(scale); + } + bool isNeg = false; if (integral < 0) { isNeg = true; @@ -94,6 +124,9 @@ library LibFormatDecimalFloat { if (fractional != 0) { uint256 fracLeadingZeros = 0; uint256 fracScale = scale / 10; + // fracScale being 10x less than scale means it cannot overflow + // when cast to `int256`. + // forge-lint: disable-next-line(unsafe-typecast) while (fractional / int256(fracScale) == 0) { fracScale /= 10; fracLeadingZeros++; @@ -113,7 +146,10 @@ library LibFormatDecimalFloat { } string memory integralString = Strings.toString(integral); - + // scaleExponent comes from either hardcoded values or `exponent` which + // is an `int256` that was cast to `uint256` above, which can be cast + // back to `int256` without truncation. + // forge-lint: disable-next-line(unsafe-typecast) int256 displayExponent = exponent + int256(scaleExponent); string memory exponentString = (displayExponent == 0 || !scientific) ? "" : string.concat("e", Strings.toString(displayExponent)); diff --git a/src/lib/implementation/LibDecimalFloatImplementation.sol b/src/lib/implementation/LibDecimalFloatImplementation.sol index 3176065f..0d51ba02 100644 --- a/src/lib/implementation/LibDecimalFloatImplementation.sol +++ b/src/lib/implementation/LibDecimalFloatImplementation.sol @@ -11,13 +11,11 @@ import { MaximizeOverflow } from "../../error/ErrDecimalFloat.sol"; import { - LOG_TABLES, - LOG_TABLES_SMALL, - LOG_TABLES_SMALL_ALT, - ANTI_LOG_TABLES, - ANTI_LOG_TABLES_SMALL -} from "../../generated/LogTables.pointers.sol"; -import {LibDecimalFloat} from "../LibDecimalFloat.sol"; + LOG_TABLE_SIZE_BYTES, + LOG_TABLE_SIZE_BASE, + LOG_MANTISSA_LAST_INDEX, + ANTILOG_IDX_LAST_INDEX +} from "../table/LibLogTable.sol"; error WithTargetExponentOverflow(int256 signedCoefficient, int256 exponent, int256 targetExponent); @@ -80,9 +78,13 @@ library LibDecimalFloatImplementation { if (signedCoefficient == type(int256).min) { return uint256(type(int256).max) + 1; } else { + // signedCoefficient < 0 + // forge-lint: disable-next-line(unsafe-typecast) return uint256(-signedCoefficient); } } else { + // signedCoefficient >= 0 + // forge-lint: disable-next-line(unsafe-typecast) return uint256(signedCoefficient); } } @@ -93,26 +95,34 @@ library LibDecimalFloatImplementation { pure returns (int256, int256) { - unchecked { - // Need to minus the coefficient because a and b had different signs. - if ((a ^ b) < 0) { - if (signedCoefficientAbs > uint256(type(int256).max)) { - if (signedCoefficientAbs == uint256(type(int256).max) + 1) { - // Edge case where the absolute value is exactly - // type(int256).min. - return (type(int256).min, exponent); - } else { - return (-int256(signedCoefficientAbs / 10), exponent + 1); - } + // Need to minus the coefficient because a and b had different signs. + if ((a ^ b) < 0) { + if (signedCoefficientAbs > uint256(type(int256).max)) { + if (signedCoefficientAbs == uint256(type(int256).max) + 1) { + // Edge case where the absolute value is exactly + // type(int256).min. + return (type(int256).min, exponent); } else { - return (-int256(signedCoefficientAbs), exponent); + // signedCoefficientAbs divided by 10 so won't truncate when + // cast. + // forge-lint: disable-next-line(unsafe-typecast) + return (-int256(signedCoefficientAbs / 10), exponent + 1); } } else { - if (signedCoefficientAbs > uint256(type(int256).max)) { - return (int256(signedCoefficientAbs / 10), exponent + 1); - } else { - return (int256(signedCoefficientAbs), exponent); - } + // signedCoefficientAbs [0, type(int256).max] + // forge-lint: disable-next-line(unsafe-typecast) + return (-int256(signedCoefficientAbs), exponent); + } + } else { + if (signedCoefficientAbs > uint256(type(int256).max)) { + // signedCoefficientAbs divided by 10 so won't truncate when + // cast. + // forge-lint: disable-next-line(unsafe-typecast) + return (int256(signedCoefficientAbs / 10), exponent + 1); + } else { + // signedCoefficientAbs is bound to the int256 range. + // forge-lint: disable-next-line(unsafe-typecast) + return (int256(signedCoefficientAbs), exponent); } } } @@ -166,6 +176,8 @@ library LibDecimalFloatImplementation { } } + // adjustExponent [0, 76] + // forge-lint: disable-next-line(unsafe-typecast) exponent += int256(adjustExponent); (signedCoefficient, exponent) = unabsUnsignedMulOrDivLossy( @@ -404,6 +416,8 @@ library LibDecimalFloatImplementation { return (MAXIMIZED_ZERO_SIGNED_COEFFICIENT, MAXIMIZED_ZERO_EXPONENT); } + // underflowExponentBy [1, 76] + // forge-lint: disable-next-line(unsafe-typecast) signedCoefficient /= int256(10 ** uint256(underflowExponentBy)); if (signedCoefficient == 0) { exponent = MAXIMIZED_ZERO_EXPONENT; @@ -605,12 +619,18 @@ library LibDecimalFloatImplementation { // If the exponents are too far apart, then all the information in B // would be lost, so we can just ignore B and return A. unchecked { + // exponentA >= exponentB so exponentA - exponentB will fit in + // uint256. + // forge-lint: disable-next-line(unsafe-typecast) uint256 alignmentExponentDiff = uint256(exponentA - exponentB); // The early return here allows us to do unchecked pow on the // scaler and means we never revert due to overflow here. if (alignmentExponentDiff > ADD_MAX_EXPONENT_DIFF) { return (signedCoefficientA, exponentA); } + // alignmentExponentDiff can't be greater than 76 so will pow + // without truncation. + // forge-lint: disable-next-line(unsafe-typecast) signedCoefficientB /= int256(10 ** alignmentExponentDiff); } @@ -685,6 +705,32 @@ library LibDecimalFloatImplementation { return div(1e76, -76, signedCoefficient, exponent); } + function lookupLogTableVal(address tables, uint256 index) internal view returns (uint256 result) { + // Skip first byte of data contract. + uint256 smallTableOffset = LOG_TABLE_SIZE_BYTES + 1; + uint256 logTableSizeBase = LOG_TABLE_SIZE_BASE; + assembly ("memory-safe") { + // First byte of the data contract must be skipped. + // truncation from the div by 10 is intentional here to keep the + // main offset and small offset distinct. + // slither-disable-next-line divide-before-multiply + let mainOffset := add(1, mul(div(index, 10), 2)) + mstore(0, 0) + extcodecopy(tables, 30, mainOffset, 2) + let mainTableVal := mload(0) + + result := and(mainTableVal, 0x7FFF) + if iszero(iszero(and(mainTableVal, 0x8000))) { smallTableOffset := add(smallTableOffset, logTableSizeBase) } + + mstore(0, 0) + // truncation from the div by 100 is intentional here to keep the + // small table offset and small offset distinct. + // slither-disable-next-line divide-before-multiply + extcodecopy(tables, 31, add(smallTableOffset, add(mul(div(index, 100), 10), mod(index, 10))), 1) + result := add(result, mload(0)) + } + } + /// log10(x) for a float x. /// /// Internally uses log tables so is not perfectly accurate, but also doesn't @@ -740,64 +786,46 @@ library LibDecimalFloatImplementation { // Table lookup. { - int256 scale = 1e72; - assembly ("memory-safe") { - //slither-disable-next-line divide-before-multiply - function lookupTableVal(tables, index) -> result { - // First byte of the data contract must be skipped. - let mainOffset := add(1, mul(div(index, 10), 2)) - mstore(0, 0) - extcodecopy(tables, 30, mainOffset, 2) - let mainTableVal := mload(0) - - result := and(mainTableVal, 0x7FFF) - // Skip first byte of data contract then 1820 bytes - // of the log tables. - let smallTableOffset := 1821 - if iszero(iszero(and(mainTableVal, 0x8000))) { - // Small table is half the size of the main - // table. - smallTableOffset := add(smallTableOffset, 910) - } - - mstore(0, 0) - extcodecopy(tables, 31, add(smallTableOffset, add(mul(div(index, 100), 10), mod(index, 10))), 1) - result := add(result, mload(0)) + uint256 idx = 0; + unchecked { + { + uint256 scale = isAtLeastE76 ? 1e73 : 1e72; + // Truncate the signed coefficient to what we can look + // up in the table. + // Slither false positive because the truncation is + // deliberate here. + //slither-disable-start divide-before-multiply + // scale is one of two possible values so won't truncate + // when cast. + // forge-lint: disable-next-line(unsafe-typecast) + x1Coefficient = signedCoefficient / int256(scale); + // slither-disable-end divide-before-multiply + // x1Coefficient is positive here so won't truncate when + // cast. + // forge-lint: disable-next-line(unsafe-typecast) + idx = uint256(x1Coefficient - 1000); + // scale is one of two possible values so won't truncate + // when cast. + // forge-lint: disable-next-line(unsafe-typecast) + x1Coefficient = x1Coefficient * int256(scale); + // Technically we only need to do this if we need to + // interpolate but it's cheaper to just do an `add` + // unconditionally than pay for an `if` and often also + // do the `add`. + // scale is one of two possible values so won't truncate + // when cast. + // forge-lint: disable-next-line(unsafe-typecast) + x2Coefficient = x1Coefficient + int256(scale); } - // Need to increase the scale by one OOM here so that the - // signed coefficient has 4 digits always, to make it - // easy to calculate the idx. - if isAtLeastE76 { scale := mul(scale, 10) } - - // Truncate the signed coefficient to what we can look - // up in the table. - // Slither false positive because the truncation is - // deliberate here. - //slither-disable-next-line divide-before-multiply - x1Coefficient := div(signedCoefficient, scale) - let idx := sub(x1Coefficient, 1000) - x1Coefficient := mul(x1Coefficient, scale) - // Technically we only need to do this if we need to - // interpolate but it's cheaper to just do an `add` - // unconditionally than pay for an `if` and often also - // do the `add`. - x2Coefficient := add(x1Coefficient, scale) - - // If we don't bring the scale back down here we can get - // overflows when multiplying the output of the lookups. - // We are reusing the same scale variable to avoid a - // compiler stack overflow. - // Slither false positive here, this division is simply - // the inverse of the mul above. - //slither-disable-next-line divide-before-multiply - if isAtLeastE76 { scale := div(scale, 10) } - - y1Coefficient := mul(scale, lookupTableVal(tablesDataContract, idx)) + y1Coefficient = int256(1e72 * lookupLogTableVal(tablesDataContract, idx)); + y2Coefficient = y1Coefficient; // Only do the second lookup if we expect interpolation // to need it. - if iszero(eq(x1Coefficient, signedCoefficient)) { - y2Coefficient := mul(scale, lookupTableVal(tablesDataContract, add(idx, 1))) + if (x1Coefficient != signedCoefficient) { + y2Coefficient = idx == LOG_MANTISSA_LAST_INDEX + ? int256(1e76) + : int256(1e72 * lookupLogTableVal(tablesDataContract, idx + 1)); } } } @@ -850,8 +878,15 @@ library LibDecimalFloatImplementation { int256 characteristicExponent = exponent; { (int256 idx, bool interpolate, int256 scale) = mantissa4(mantissaCoefficient, exponent); - (int256 y1Coefficient, int256 y2Coefficient) = - lookupAntilogTableY1Y2(tablesDataContract, uint256(idx), interpolate); + // idx is positive here because the signedCoefficient is positive due + // to the opening `if` above. + int256 y1Coefficient = 9997; + int256 y2Coefficient = 10000; + if (idx != ANTILOG_IDX_LAST_INDEX) { + (y1Coefficient, y2Coefficient) = + // forge-lint: disable-next-line(unsafe-typecast) + lookupAntilogTableY1Y2(tablesDataContract, uint256(idx), interpolate); + } if (interpolate) { (signedCoefficient, exponent) = unitLinearInterpolation( idx * scale, mantissaCoefficient, (idx + 1) * scale, exponent, y1Coefficient, y2Coefficient, -4 @@ -1010,6 +1045,8 @@ library LibDecimalFloatImplementation { return (signedCoefficientA, 0); } } + // exponentDiff [0, 76] + // forge-lint: disable-next-line(unsafe-typecast) int256 scale = int256(10 ** uint256(exponentDiff)); int256 rescaled = signedCoefficientA * scale; @@ -1046,13 +1083,16 @@ library LibDecimalFloatImplementation { if (exponentDiff > 76 || exponentDiff <= 0) { return (MAXIMIZED_ZERO_SIGNED_COEFFICIENT); } - + // exponentDiff [1, 76] + // forge-lint: disable-next-line(unsafe-typecast) return signedCoefficient / int256(10 ** uint256(exponentDiff)); } else { int256 exponentDiff = exponent - targetExponent; if (exponentDiff > 76 || exponentDiff <= 0) { revert WithTargetExponentOverflow(signedCoefficient, exponent, targetExponent); } + // exponentDiff [1, 76] + // forge-lint: disable-next-line(unsafe-typecast) int256 scale = int256(10 ** uint256(exponentDiff)); int256 rescaled = signedCoefficient * scale; if (rescaled / scale != signedCoefficient) { @@ -1081,6 +1121,8 @@ library LibDecimalFloatImplementation { return (0, signedCoefficient); } + // exponent [-76, -1] + // forge-lint: disable-next-line(unsafe-typecast) int256 unit = int256(10 ** uint256(-exponent)); mantissa = signedCoefficient % unit; characteristic = signedCoefficient - mantissa; @@ -1104,36 +1146,39 @@ library LibDecimalFloatImplementation { return (0, false, 1); } else { // exponent is [-3, -1] + // forge-lint: disable-next-line(unsafe-typecast) return (signedCoefficient * int256(10 ** uint256(4 + exponent)), false, 1); } } } + // forge-lint: disable-next-line(mixed-case-function) function lookupAntilogTableY1Y2(address tablesDataContract, uint256 idx, bool lossyIdx) internal view returns (int256 y1Coefficient, int256 y2Coefficient) { + // 1 byte for start of data contract + // + 1800 for log tables + // + 900 for small log tables + // + 100 for alt small log tables + uint256 offsetSize = 1 + LOG_TABLE_SIZE_BYTES + LOG_TABLE_SIZE_BASE + 100; assembly ("memory-safe") { //slither-disable-next-line divide-before-multiply - function lookupTableVal(tables, index) -> result { - // 1 byte for start of data contract - // + 1820 for log tables - // + 910 for small log tables - // + 100 for alt small log tables - let offset := 2831 + function lookupTableVal(tables, offset, index) -> result { mstore(0, 0) extcodecopy(tables, 30, add(offset, mul(div(index, 10), 2)), 2) let mainTableVal := mload(0) - offset := add(offset, 2020) + // add size of the alt log table = 2000 + offset := add(offset, 2000) mstore(0, 0) extcodecopy(tables, 31, add(offset, add(mul(div(index, 100), 10), mod(index, 10))), 1) result := add(mainTableVal, mload(0)) } - y1Coefficient := lookupTableVal(tablesDataContract, idx) - if lossyIdx { y2Coefficient := lookupTableVal(tablesDataContract, add(idx, 1)) } + y1Coefficient := lookupTableVal(tablesDataContract, offsetSize, idx) + if lossyIdx { y2Coefficient := lookupTableVal(tablesDataContract, offsetSize, add(idx, 1)) } } } diff --git a/src/lib/parse/LibParseDecimalFloat.sol b/src/lib/parse/LibParseDecimalFloat.sol index b7508319..db6880dc 100644 --- a/src/lib/parse/LibParseDecimalFloat.sol +++ b/src/lib/parse/LibParseDecimalFloat.sol @@ -12,9 +12,8 @@ import { } from "rain.string/lib/parse/LibParseCMask.sol"; import {LibParseDecimal} from "rain.string/lib/parse/LibParseDecimal.sol"; import {MalformedExponentDigits, ParseDecimalPrecisionLoss, MalformedDecimalPoint} from "../../error/ErrParse.sol"; -import {ParseDecimalOverflow, ParseEmptyDecimalString} from "rain.string/error/ErrParse.sol"; +import {ParseEmptyDecimalString} from "rain.string/error/ErrParse.sol"; import {LibDecimalFloat, Float} from "../LibDecimalFloat.sol"; -import {LibDecimalFloatImplementation} from "../implementation/LibDecimalFloatImplementation.sol"; import {ParseDecimalFloatExcessCharacters} from "../../error/ErrParse.sol"; library LibParseDecimalFloat { @@ -76,20 +75,40 @@ library LibParseDecimalFloat { // We want to _decrease_ the exponent by the number of digits in the // fractional part. + // _technically_ these numbers could be out of range but in + // the intended use case that would imply a memory region that + // is physically impossible to exist. + // forge-lint: disable-next-line(unsafe-typecast) exponent = int256(fracStart) - int256(nonZeroCursor); - uint256 scale = uint256(-exponent); - if (scale > 67 && signedCoefficient != 0) { - return (ParseDecimalPrecisionLoss.selector, cursor, 0, 0); + // Should not be possible but guard against it in case. + if (exponent > 0) { + return (MalformedExponentDigits.selector, cursor, 0, 0); } - scale = 10 ** scale; - int256 rescaledIntValue = signedCoefficient * int256(scale); - if ( - rescaledIntValue / int256(scale) != signedCoefficient - || int224(rescaledIntValue) != rescaledIntValue - ) { - return (ParseDecimalPrecisionLoss.selector, cursor, 0, 0); + + if (signedCoefficient == 0) { + signedCoefficient = fracValue; + } else { + // exponent is non positive here. + // forge-lint: disable-next-line(unsafe-typecast) + uint256 scale = uint256(-exponent); + if (scale > 67) { + return (ParseDecimalPrecisionLoss.selector, cursor, 0, 0); + } + scale = 10 ** scale; + // scale [0, 1e67] + // forge-lint: disable-next-line(unsafe-typecast) + int256 rescaledIntValue = signedCoefficient * int256(scale); + // scale [0, 1e67] + // forge-lint: disable-next-line(unsafe-typecast) + bool mulDidOverflow = rescaledIntValue / int256(scale) != signedCoefficient; + // truncation is intentional as it is part of the check here. + // forge-lint: disable-next-line(unsafe-typecast) + bool mulDidTruncate = int224(rescaledIntValue) != rescaledIntValue; + if (mulDidOverflow || mulDidTruncate) { + return (ParseDecimalPrecisionLoss.selector, cursor, 0, 0); + } + signedCoefficient = rescaledIntValue + fracValue; } - signedCoefficient = rescaledIntValue + fracValue; } int256 eValue = int256(LibParseChar.isMask(cursor, end, CMASK_E_NOTATION)); diff --git a/src/lib/table/LibLogTable.sol b/src/lib/table/LibLogTable.sol index b0532088..febf2594 100644 --- a/src/lib/table/LibLogTable.sol +++ b/src/lib/table/LibLogTable.sol @@ -4,18 +4,34 @@ pragma solidity ^0.8.25; uint16 constant ALT_TABLE_FLAG = 0x8000; +/// @dev The cardinality of the log mantissa for log table lookup. +uint256 constant LOG_MANTISSA_IDX_CARDINALITY = 9000; +/// @dev The last index of the log mantissa for log table lookup. +uint256 constant LOG_MANTISSA_LAST_INDEX = LOG_MANTISSA_IDX_CARDINALITY - 1; + +int256 constant ANTILOG_IDX_CARDINALITY = 10000; +int256 constant ANTILOG_IDX_LAST_INDEX = ANTILOG_IDX_CARDINALITY - 1; + +// The base size of the log tables is 1/10th the cardinality because the smallest +// OOM is handled by the small table. Every value in the large table has a +// corresponding value in the small table, it is just that the large table has +// 2 byte values while the small table has 1 byte values. +uint256 constant LOG_TABLE_SIZE_BASE = LOG_MANTISSA_IDX_CARDINALITY / 10; +uint256 constant LOG_TABLE_SIZE_BYTES = LOG_TABLE_SIZE_BASE * 2; + /// @dev https://icap.org.pk/files/per/students/exam/notices/log-table.pdf library LibLogTable { - function toBytes(uint16[10][91] memory table) internal pure returns (bytes memory) { + function toBytes(uint16[10][90] memory table) internal pure returns (bytes memory) { bytes memory encoded; + uint256 tableSize = LOG_TABLE_SIZE_BYTES; assembly ("memory-safe") { encoded := mload(0x40) - mstore(0x40, add(encoded, add(1820, 0x20))) + mstore(0x40, add(encoded, add(tableSize, 0x20))) let cursor := sub(mload(0x40), 0x20) for { - let i := add(table, mul(0x20, 90)) + let i := add(table, mul(0x20, 89)) let j := mul(0x20, 9) } gt(cursor, encoded) { cursor := sub(cursor, 2) @@ -29,21 +45,22 @@ library LibLogTable { } } - mstore(cursor, 1820) + mstore(cursor, tableSize) } return encoded; } - function toBytes(uint8[10][91] memory table) internal pure returns (bytes memory) { + function toBytes(uint8[10][90] memory table) internal pure returns (bytes memory) { bytes memory encoded; + uint256 tableSize = LOG_TABLE_SIZE_BASE; assembly ("memory-safe") { encoded := mload(0x40) - mstore(0x40, add(encoded, add(910, 0x20))) + mstore(0x40, add(encoded, add(tableSize, 0x20))) let cursor := sub(mload(0x40), 0x20) for { - let i := add(table, mul(0x20, 90)) + let i := add(table, mul(0x20, 89)) let j := mul(0x20, 9) } gt(cursor, encoded) { cursor := sub(cursor, 1) @@ -57,21 +74,21 @@ library LibLogTable { } } - mstore(cursor, 910) + mstore(cursor, tableSize) } return encoded; } - function toBytes(uint8[10][101] memory table) internal pure returns (bytes memory) { + function toBytes(uint8[10][100] memory table) internal pure returns (bytes memory) { bytes memory encoded; assembly ("memory-safe") { encoded := mload(0x40) - mstore(0x40, add(encoded, add(1010, 0x20))) + mstore(0x40, add(encoded, add(1000, 0x20))) let cursor := sub(mload(0x40), 0x20) for { - let i := add(table, mul(0x20, 100)) + let i := add(table, mul(0x20, 99)) let j := mul(0x20, 9) } gt(cursor, encoded) { cursor := sub(cursor, 1) @@ -85,7 +102,7 @@ library LibLogTable { } } - mstore(cursor, 1010) + mstore(cursor, 1000) } return encoded; } @@ -118,16 +135,16 @@ library LibLogTable { return encoded; } - function toBytes(uint16[10][101] memory table) internal pure returns (bytes memory) { + function toBytes(uint16[10][100] memory table) internal pure returns (bytes memory) { bytes memory encoded; assembly ("memory-safe") { encoded := mload(0x40) - mstore(0x40, add(encoded, add(2020, 0x20))) + mstore(0x40, add(encoded, add(2000, 0x20))) let cursor := sub(mload(0x40), 0x20) for { - let i := add(table, mul(0x20, 100)) + let i := add(table, mul(0x20, 99)) let j := mul(0x20, 9) } gt(cursor, encoded) { cursor := sub(cursor, 2) @@ -141,12 +158,12 @@ library LibLogTable { } } - mstore(cursor, 2020) + mstore(cursor, 2000) } return encoded; } - function logTableDec() internal pure returns (uint16[10][91] memory) { + function logTableDec() internal pure returns (uint16[10][90] memory) { return [ [ 0, @@ -347,14 +364,11 @@ library LibLogTable { [9823, 9827, 9832, 9836, 9841, 9845, 9850, 9854, 9859, 9863], [9868, 9872, 9877, 9881, 9886, 9890, 9894, 9899, 9903, 9908], [9912, 9917, 9921, 9926, 9930, 9934, 9939, 9943, 9948, 9952], - [9956, 9961, 9965, 9969, 9974, 9978, 9983, 9987, 9991, 9996], - // This row is a placeholder for when we interpolate past the last - // entry in the table. The last entry is 10000, so we just use that. - [10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000] + [9956, 9961, 9965, 9969, 9974, 9978, 9983, 9987, 9991, 9996] ]; } - function logTableDecSmall() internal pure returns (uint8[10][91] memory) { + function logTableDecSmall() internal pure returns (uint8[10][90] memory) { return [ [0, 4, 9, 13, 17, 21, 26, 30, 34, 38], [0, 4, 8, 12, 15, 19, 23, 27, 31, 35], @@ -445,10 +459,7 @@ library LibLogTable { [0, 0, 1, 1, 2, 2, 3, 3, 4, 4], [0, 0, 1, 1, 2, 2, 3, 3, 4, 4], [0, 0, 1, 1, 2, 2, 3, 3, 4, 4], - [0, 0, 1, 1, 2, 2, 3, 3, 3, 4], - // This row is a placeholder for when we interpolate past the last - // entry in the table. - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + [0, 0, 1, 1, 2, 2, 3, 3, 3, 4] ]; } @@ -467,7 +478,7 @@ library LibLogTable { ]; } - function antiLogTableDec() internal pure returns (uint16[10][101] memory) { + function antiLogTableDec() internal pure returns (uint16[10][100] memory) { return [ [1000, 1002, 1005, 1007, 1009, 1012, 1014, 1016, 1019, 1021], [1023, 1026, 1028, 1030, 1033, 1035, 1038, 1040, 1042, 1045], @@ -568,14 +579,11 @@ library LibLogTable { [9120, 9141, 9162, 9183, 9204, 9226, 9247, 9268, 9290, 9311], [9333, 9354, 9376, 9397, 9419, 9441, 9462, 9484, 9506, 9528], [9550, 9572, 9594, 9616, 9638, 9661, 9683, 9705, 9727, 9750], - [9772, 9795, 9817, 9840, 9863, 9886, 9908, 9931, 9954, 9977], - // This row is a placeholder for when we need to interpolate from - // 9999 to 9999+1. - [10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000] + [9772, 9795, 9817, 9840, 9863, 9886, 9908, 9931, 9954, 9977] ]; } - function antiLogTableDecSmall() internal pure returns (uint8[10][101] memory) { + function antiLogTableDecSmall() internal pure returns (uint8[10][100] memory) { return [ [0, 0, 0, 1, 1, 1, 1, 2, 2, 2], [0, 0, 0, 1, 1, 1, 1, 2, 2, 2], @@ -676,10 +684,7 @@ library LibLogTable { [0, 2, 4, 6, 8, 11, 13, 15, 17, 19], [0, 2, 4, 7, 9, 11, 13, 15, 17, 20], [0, 2, 4, 7, 9, 11, 13, 16, 18, 20], - [0, 2, 5, 7, 9, 11, 14, 16, 18, 20], - // This row is a placeholder for when we need to interpolate from - // 9999 to 9999+1. - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + [0, 2, 5, 7, 9, 11, 14, 16, 18, 20] ]; } } diff --git a/test/abstract/LogTest.sol b/test/abstract/LogTest.sol index 74a6a170..0e06e637 100644 --- a/test/abstract/LogTest.sol +++ b/test/abstract/LogTest.sol @@ -3,6 +3,7 @@ pragma solidity =0.8.25; // Re-export console2 here for convenience. +// forge-lint: disable-next-line(unused-import) import {Test, console2} from "forge-std/Test.sol"; import {DataContractMemoryContainer, LibDataContract} from "rain.datacontract/lib/LibDataContract.sol"; import {LibDecimalFloatDeploy} from "src/lib/deploy/LibDecimalFloatDeploy.sol"; diff --git a/test/lib/LibDecimalFloatSlow.sol b/test/lib/LibDecimalFloatSlow.sol index e349723b..6d33a9e5 100644 --- a/test/lib/LibDecimalFloatSlow.sol +++ b/test/lib/LibDecimalFloatSlow.sol @@ -39,6 +39,9 @@ library LibDecimalFloatSlow { signedCoefficientAAbs, signedCoefficientBAbs, uint256(10) ** adjustExponent ); + // adjust exponent comes from looping an inc so can't possibly + // overflow in int256. + // forge-lint: disable-next-line(unsafe-typecast) exponent += int256(adjustExponent); int256 signedCoefficient; (signedCoefficient, exponent) = LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy( diff --git a/test/src/concrete/DecimalFloat.log10.t.sol b/test/src/concrete/DecimalFloat.log10.t.sol index 1877ff93..2de3cc8b 100644 --- a/test/src/concrete/DecimalFloat.log10.t.sol +++ b/test/src/concrete/DecimalFloat.log10.t.sol @@ -4,7 +4,6 @@ pragma solidity =0.8.25; import {LibDecimalFloat, Float} from "src/lib/LibDecimalFloat.sol"; import {LogTest} from "test/abstract/LogTest.sol"; -import {DecimalFloat} from "src/concrete/DecimalFloat.sol"; contract DecimalFloatLog10Test is LogTest { using LibDecimalFloat for Float; diff --git a/test/src/concrete/DecimalFloat.pow10.t.sol b/test/src/concrete/DecimalFloat.pow10.t.sol index f9a3844e..6a1f072e 100644 --- a/test/src/concrete/DecimalFloat.pow10.t.sol +++ b/test/src/concrete/DecimalFloat.pow10.t.sol @@ -3,7 +3,6 @@ pragma solidity =0.8.25; import {LibDecimalFloat, Float} from "src/lib/LibDecimalFloat.sol"; -import {DecimalFloat} from "src/concrete/DecimalFloat.sol"; import {LogTest} from "test/abstract/LogTest.sol"; contract DecimalFloatPow10Test is LogTest { diff --git a/test/src/lib/LibDecimalFloat.add.t.sol b/test/src/lib/LibDecimalFloat.add.t.sol index 9e707494..a381b4fc 100644 --- a/test/src/lib/LibDecimalFloat.add.t.sol +++ b/test/src/lib/LibDecimalFloat.add.t.sol @@ -3,10 +3,7 @@ pragma solidity =0.8.25; import {LibDecimalFloat, Float} from "src/lib/LibDecimalFloat.sol"; -import { - LibDecimalFloatImplementation, - ADD_MAX_EXPONENT_DIFF -} from "src/lib/implementation/LibDecimalFloatImplementation.sol"; +import {LibDecimalFloatImplementation} from "src/lib/implementation/LibDecimalFloatImplementation.sol"; import {Test} from "forge-std/Test.sol"; diff --git a/test/src/lib/LibDecimalFloat.ceil.t.sol b/test/src/lib/LibDecimalFloat.ceil.t.sol index b42c8781..ac6521d3 100644 --- a/test/src/lib/LibDecimalFloat.ceil.t.sol +++ b/test/src/lib/LibDecimalFloat.ceil.t.sol @@ -58,6 +58,8 @@ contract LibDecimalFloatCeilTest is Test { /// For exponents [-76,-1] the ceil is the + 1. function testCeilInRange(int224 x, int256 exponent) external pure { exponent = bound(exponent, -76, -1); + // exponent [-76, -1] + // forge-lint: disable-next-line(unsafe-typecast) int256 scale = int256(10 ** uint256(-exponent)); int256 characteristic = x / scale; diff --git a/test/src/lib/LibDecimalFloat.decimal.t.sol b/test/src/lib/LibDecimalFloat.decimal.t.sol index 4714a0c5..6f511bc5 100644 --- a/test/src/lib/LibDecimalFloat.decimal.t.sol +++ b/test/src/lib/LibDecimalFloat.decimal.t.sol @@ -3,9 +3,7 @@ pragma solidity =0.8.25; import {LibDecimalFloat, ExponentOverflow, NegativeFixedDecimalConversion, Float} from "src/lib/LibDecimalFloat.sol"; -import {LibDecimalFloatImplementation} from "src/lib/implementation/LibDecimalFloatImplementation.sol"; - -import {Test, console2, stdError} from "forge-std/Test.sol"; +import {Test, stdError} from "forge-std/Test.sol"; contract LibDecimalFloatDecimalTest is Test { using LibDecimalFloat for Float; @@ -206,6 +204,8 @@ contract LibDecimalFloatDecimalTest is Test { signedCoefficient = bound(signedCoefficient, 0, type(int256).max); (uint256 value, bool lossless) = LibDecimalFloat.toFixedDecimalLossy(signedCoefficient, -int256(uint256(decimals)), decimals); + // signedCoefficient is bound to the non negative int256 range. + // forge-lint: disable-next-line(unsafe-typecast) assertEq(value, uint256(signedCoefficient), "value"); assertEq(lossless, true, "lossless"); } @@ -245,7 +245,11 @@ contract LibDecimalFloatDecimalTest is Test { exponent = bound(exponent, -77 - int256(uint256(decimals)), -int256(uint256(decimals))); (uint256 value, bool lossless) = LibDecimalFloat.toFixedDecimalLossy(signedCoefficient, exponent, decimals); uint256 scale = 10 ** uint256(-(exponent + int256(uint256(decimals)))); + // signedCoefficient is bound to the positive int256 range. + // forge-lint: disable-next-line(unsafe-typecast) assertEq(value, uint256(signedCoefficient) / scale, "value"); + // signedCoefficient is bound to the positive int256 range. + // forge-lint: disable-next-line(unsafe-typecast) assertEq(lossless, value * scale == uint256(signedCoefficient), "lossless"); } @@ -270,8 +274,12 @@ contract LibDecimalFloatDecimalTest is Test { exponent = int256(bound(exponent, 1 - int256(uint256(decimals)), 77 - int256(uint256(decimals)))); int256 finalExponent = exponent + int256(uint256(decimals)); + // finalExponent [1, 77] + // forge-lint: disable-next-line(unsafe-typecast) uint256 scale = 10 ** uint256(finalExponent); + // signedCoefficient is bound to the int256 range. + // forge-lint: disable-next-line(unsafe-typecast) uint256 unsignedCoefficient = uint256(signedCoefficient); unchecked { uint256 c = scale * unsignedCoefficient; @@ -289,8 +297,12 @@ contract LibDecimalFloatDecimalTest is Test { exponent = int256(bound(exponent, 1 - int256(uint256(decimals)), 77 - int256(uint256(decimals)))); int256 finalExponent = exponent + int256(uint256(decimals)); + // finalExponent [1, 77] + // forge-lint: disable-next-line(unsafe-typecast) uint256 scale = 10 ** uint256(finalExponent); + // signedCoefficient is bound to the int256 range. + // forge-lint: disable-next-line(unsafe-typecast) uint256 unsignedCoefficient = uint256(signedCoefficient); unchecked { uint256 c = scale * unsignedCoefficient; diff --git a/test/src/lib/LibDecimalFloat.decimalLossless.t.sol b/test/src/lib/LibDecimalFloat.decimalLossless.t.sol index b9710917..08c15209 100644 --- a/test/src/lib/LibDecimalFloat.decimalLossless.t.sol +++ b/test/src/lib/LibDecimalFloat.decimalLossless.t.sol @@ -80,6 +80,8 @@ contract LibDecimalFloatDecimalLosslessTest is Test { function testFromFixedDecimalLosslessPass(uint256 value, uint8 decimals) external pure { value = bound(value, 0, uint256(type(int256).max)); (int256 signedCoefficient, int256 exponent) = LibDecimalFloat.fromFixedDecimalLossless(value, decimals); + assertTrue(signedCoefficient >= 0, "signedCoefficient is negative"); + // forge-lint: disable-next-line(unsafe-typecast) assertEq(uint256(signedCoefficient), value); assertEq(exponent, -int256(uint256(decimals))); } diff --git a/test/src/lib/LibDecimalFloat.floor.t.sol b/test/src/lib/LibDecimalFloat.floor.t.sol index c0b54973..8519818c 100644 --- a/test/src/lib/LibDecimalFloat.floor.t.sol +++ b/test/src/lib/LibDecimalFloat.floor.t.sol @@ -35,7 +35,11 @@ contract LibDecimalFloatFloorTest is Test { /// For exponents [-76,-1] the floor is the / 1. function testFloorInRange(int224 x, int256 exponent) external pure { exponent = bound(exponent, -76, -1); + // exponent [-76, -1] + // forge-lint: disable-next-line(unsafe-typecast) int256 scale = int256(10 ** uint256(-exponent)); + // truncation is intentional here. + // forge-lint: disable-next-line(divide-before-multiply) int256 y = (x / scale) * scale; checkFloor(x, exponent, y, y == 0 ? int256(0) : exponent); } diff --git a/test/src/lib/LibDecimalFloat.frac.t.sol b/test/src/lib/LibDecimalFloat.frac.t.sol index d438d888..35646b3f 100644 --- a/test/src/lib/LibDecimalFloat.frac.t.sol +++ b/test/src/lib/LibDecimalFloat.frac.t.sol @@ -36,6 +36,8 @@ contract LibDecimalFloatFracTest is Test { /// For exponents [-76,-1] the fractional component is the modulo of 1. function testFracInRange(int224 x, int256 exponent) external pure { exponent = bound(exponent, -76, -1); + // exponent [-76, -1] + // forge-lint: disable-next-line(unsafe-typecast) int256 y = x % int256(10 ** uint256(-exponent)); checkFrac(x, exponent, y, y == 0 ? int256(0) : exponent); } @@ -66,7 +68,26 @@ contract LibDecimalFloatFracTest is Test { checkFrac(type(int224).max, -4, 4607, -4); checkFrac(type(int224).max, -77, type(int224).max, -77); checkFrac(type(int224).max, -78, type(int224).max, -78); - checkFrac(type(int224).max, -76, 13479973333575319897333507543509815336818572211270286240551805124607, -76); + checkFrac(type(int224).max, -76, type(int224).max, -76); + + // Negatives. + checkFrac(-123456789, 0, 0, 0); + checkFrac(-123456789, -1, -9, -1); + checkFrac(-123456789, -2, -89, -2); + checkFrac(-123456789, -3, -789, -3); + checkFrac(-123456789, -4, -6789, -4); + checkFrac(-123456789, -5, -56789, -5); + checkFrac(-123456789, -6, -456789, -6); + checkFrac(-123456789, -7, -3456789, -7); + checkFrac(-123456789, -8, -23456789, -8); + checkFrac(-123456789, -9, -123456789, -9); + checkFrac(-123456789, -10, -123456789, -10); + checkFrac(-123456789, -11, -123456789, -11); + checkFrac(-2.5e37, -37, -0.5e37, -37); + + // int224 minimum edge cases. + checkFrac(type(int224).min, -1, -8, -1); + checkFrac(type(int224).min, -76, type(int224).min, -76); } function testFracGasZero() external pure { diff --git a/test/src/lib/LibDecimalFloat.max.t.sol b/test/src/lib/LibDecimalFloat.max.t.sol index 795819b4..3d7ef245 100644 --- a/test/src/lib/LibDecimalFloat.max.t.sol +++ b/test/src/lib/LibDecimalFloat.max.t.sol @@ -16,7 +16,9 @@ contract LibDecimalFloatMaxTest is Test { /// x.max(y) == y.max(x) function testMaxXY(Float x, Float y) external pure { + // forge-lint: disable-next-line(mixed-case-variable) Float maxXY = x.max(y); + // forge-lint: disable-next-line(mixed-case-variable) Float maxYX = y.max(x); assertTrue(maxXY.eq(maxYX), "maxXY != maxYX"); } diff --git a/test/src/lib/LibDecimalFloat.min.t.sol b/test/src/lib/LibDecimalFloat.min.t.sol index fa7f0806..a8897279 100644 --- a/test/src/lib/LibDecimalFloat.min.t.sol +++ b/test/src/lib/LibDecimalFloat.min.t.sol @@ -16,7 +16,9 @@ contract LibDecimalFloatMinTest is Test { /// x.min(y) == y.min(x) function testMinXY(Float x, Float y) external pure { + // forge-lint: disable-next-line(mixed-case-variable) Float minXY = x.min(y); + // forge-lint: disable-next-line(mixed-case-variable) Float minYX = y.min(x); assertTrue(minXY.eq(minYX), "minXY != minYX"); } diff --git a/test/src/lib/LibDecimalFloat.mixed.t.sol b/test/src/lib/LibDecimalFloat.mixed.t.sol index 9b30b4cf..b3105171 100644 --- a/test/src/lib/LibDecimalFloat.mixed.t.sol +++ b/test/src/lib/LibDecimalFloat.mixed.t.sol @@ -3,7 +3,7 @@ pragma solidity =0.8.25; import {LibDecimalFloat, Float} from "src/lib/LibDecimalFloat.sol"; -import {THREES_PACKED, ONES} from "../../lib/LibCommonResults.sol"; +import {THREES_PACKED} from "../../lib/LibCommonResults.sol"; import {Test} from "forge-std/Test.sol"; diff --git a/test/src/lib/LibDecimalFloat.mul.t.sol b/test/src/lib/LibDecimalFloat.mul.t.sol index a345a1e2..dcdeea9b 100644 --- a/test/src/lib/LibDecimalFloat.mul.t.sol +++ b/test/src/lib/LibDecimalFloat.mul.t.sol @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {LibDecimalFloat, Float, EXPONENT_MIN, EXPONENT_MAX} from "src/lib/LibDecimalFloat.sol"; +import {LibDecimalFloat, Float} from "src/lib/LibDecimalFloat.sol"; import {LibDecimalFloatImplementation} from "src/lib/implementation/LibDecimalFloatImplementation.sol"; import {Test} from "forge-std/Test.sol"; diff --git a/test/src/lib/LibDecimalFloat.pack.t.sol b/test/src/lib/LibDecimalFloat.pack.t.sol index ba692428..395506fd 100644 --- a/test/src/lib/LibDecimalFloat.pack.t.sol +++ b/test/src/lib/LibDecimalFloat.pack.t.sol @@ -2,8 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {LibDecimalFloat, ExponentOverflow, Float, EXPONENT_MAX} from "src/lib/LibDecimalFloat.sol"; -import {LibDecimalFloatImplementation} from "src/lib/implementation/LibDecimalFloatImplementation.sol"; +import {LibDecimalFloat, ExponentOverflow, Float} from "src/lib/LibDecimalFloat.sol"; import {Test} from "forge-std/Test.sol"; contract LibDecimalFloatPackTest is Test { diff --git a/test/src/lib/LibDecimalFloat.pow.t.sol b/test/src/lib/LibDecimalFloat.pow.t.sol index 8c5cbea1..059c2399 100644 --- a/test/src/lib/LibDecimalFloat.pow.t.sol +++ b/test/src/lib/LibDecimalFloat.pow.t.sol @@ -5,15 +5,14 @@ pragma solidity =0.8.25; import {LogTest} from "../../abstract/LogTest.sol"; import {LibDecimalFloat, Float} from "src/lib/LibDecimalFloat.sol"; -import {ZeroNegativePower, Log10Negative} from "src/error/ErrDecimalFloat.sol"; -import {LibDecimalFloatImplementation} from "src/lib/implementation/LibDecimalFloatImplementation.sol"; +import {ZeroNegativePower, PowNegativeBase} from "src/error/ErrDecimalFloat.sol"; import {console2} from "forge-std/Test.sol"; contract LibDecimalFloatPowTest is LogTest { using LibDecimalFloat for Float; function diffLimit() internal pure returns (Float) { - return LibDecimalFloat.packLossless(96, -3); + return LibDecimalFloat.packLossless(90, -3); } function checkPow( @@ -37,19 +36,34 @@ contract LibDecimalFloatPowTest is LogTest { } function testPows() external { - // 0.5 ^ 30 = 9.3132257e-10 - checkPow( - 5e37, -38, 3e37, -36, 9.328358208955223880597014925373134328358208955223880597014925373134e66, -66 - 10 - ); + checkPow(5, 0, 13, 0, 1220703125e3, -3); + // 0.5 ^ 30 = 9.3132257462e-10 + checkPow(5e37, -38, 3e37, -36, 9.31322574615478515625e66, -66 - 10); // 0.5 ^ 60 = 8.6736174e-19 - checkPow( - 5e37, -38, 6e37, -36, 8.710801393728222996515679442508710801393728222996515679442508710801e66, -66 - 19 - ); + checkPow(5e37, -38, 6e37, -36, 8.67361737988403547205962240695953369140625e66, -66 - 19); // Issues found in fuzzing from here. - // 99999 ^ 12182 = 8.853071703048649170130397094169464632911643045383977634639832230468640539353...e60910 - // 8.853071703048649170130397094169464632911643045383977634639832230468640539353e75 e60910 - checkPow(99999, 0, 12182, 0, 1000, 60907); - checkPow(1785215562, 0, 18, 0, 3388, 163); + // 8.74538833058575652925523041334332969215722254574942755921268 + // 633458353995901024989835096189737575745161722050119812356738 + // 280497952674131705456780502007277553280469772918551495558754.. e48726 + checkPow(9998, 0, 12182, 0, 8.745388330585756529255230413343329692157222545749427559212686334583e66, 48660); + // 783767830987557747626713214413804946776011874600896376644775 + // 737184122084874429184097039019333746546707574834238563105201 + // 601306157447680045947322051787243602068130996873443425180605.. e60909 + checkPow(99998, 0, 12182, 0, 7.837678309875577476267132144138049467760118746008963766447757371841e66, 60843); + // 99999 ^ 12182 = 8.853071703048649170130397094169464632911643045383977634639832230468640539353...e60909 + // 8.853071703048649170130397094169464632911643045383977634639832230468640539353e75 e60909 + checkPow(99999, 0, 12182, 0, 8.853071703048649170130397094169464632911643045383977634639832230468e66, 60843); + // 339181340264437326833371724490610161292169214732614339791381 + // 077839070153170394796050442886983271326431055976856477078397 + // 05146977035502651573305246467342588868622024704 + checkPow(1785215562, 0, 18, 0, 3.39181340264437326833371724490610161292169214732614339791381077839e66, 100); + + // 1.1295514523570834631500830078383428992881418895780763453451 + // 678937388891303478211805800680150846537485488564609577873121 + // 201465463889111526015508340821749525697772648457658570819388 + // 829891895455052532621e-60910 + // very close, final two digits are different + checkPow(99999, 0, -12182, 0, 1.1295514523570834631500830078383428992881418895780763453451678937375e67, -60977); { (int256 signedCoefficientE, int256 exponentE) = LibDecimalFloat.FLOAT_E.unpack(); @@ -69,7 +83,7 @@ contract LibDecimalFloatPowTest is LogTest { a = a.minus(); } (int256 signedCoefficientA, int256 exponentA) = a.unpack(); - vm.expectRevert(abi.encodeWithSelector(Log10Negative.selector, signedCoefficientA, exponentA)); + vm.expectRevert(abi.encodeWithSelector(PowNegativeBase.selector, signedCoefficientA, exponentA)); this.powExternal(a, b); } @@ -131,7 +145,8 @@ contract LibDecimalFloatPowTest is LogTest { } /// X^Y^(1/Y) = X - /// Can generally round trip whatever within 0.25% of the original value. + /// Can generally round trip whatever within `diffLimit` of the original + /// value. function testRoundTripSimple() external { checkRoundTrip(5, 0, 2, 0); checkRoundTrip(5, 0, 3, 0); diff --git a/test/src/lib/LibDecimalFloat.sqrt.t.sol b/test/src/lib/LibDecimalFloat.sqrt.t.sol index 52703326..4147fbf8 100644 --- a/test/src/lib/LibDecimalFloat.sqrt.t.sol +++ b/test/src/lib/LibDecimalFloat.sqrt.t.sol @@ -5,15 +5,14 @@ pragma solidity =0.8.25; import {LogTest} from "../../abstract/LogTest.sol"; import {LibDecimalFloat, Float} from "src/lib/LibDecimalFloat.sol"; -import {ZeroNegativePower, Log10Negative} from "src/error/ErrDecimalFloat.sol"; -import {LibDecimalFloatImplementation} from "src/lib/implementation/LibDecimalFloatImplementation.sol"; +import {PowNegativeBase} from "src/error/ErrDecimalFloat.sol"; import {console2} from "forge-std/Test.sol"; contract LibDecimalFloatSqrtTest is LogTest { using LibDecimalFloat for Float; function diffLimit() internal pure returns (Float) { - return LibDecimalFloat.packLossless(94, -3); + return LibDecimalFloat.packLossless(19, -4); } function sqrtExternal(Float a, address tables) external view returns (Float) { @@ -68,7 +67,7 @@ contract LibDecimalFloatSqrtTest is LogTest { address tables = logTables(); (int256 signedCoefficient, int256 exponent) = a.unpack(); - vm.expectRevert(abi.encodeWithSelector(Log10Negative.selector, signedCoefficient, exponent)); + vm.expectRevert(abi.encodeWithSelector(PowNegativeBase.selector, signedCoefficient, exponent)); this.sqrtExternal(a, tables); } diff --git a/test/src/lib/LibDecimalFloat.sub.t.sol b/test/src/lib/LibDecimalFloat.sub.t.sol index e2c6e2da..6df35da1 100644 --- a/test/src/lib/LibDecimalFloat.sub.t.sol +++ b/test/src/lib/LibDecimalFloat.sub.t.sol @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {LibDecimalFloat, Float, EXPONENT_MIN, EXPONENT_MAX} from "src/lib/LibDecimalFloat.sol"; +import {LibDecimalFloat, Float} from "src/lib/LibDecimalFloat.sol"; import {LibDecimalFloatImplementation} from "src/lib/implementation/LibDecimalFloatImplementation.sol"; import {Test} from "forge-std/Test.sol"; diff --git a/test/src/lib/format/LibFormatDecimalFloat.countSigFigs.t.sol b/test/src/lib/format/LibFormatDecimalFloat.countSigFigs.t.sol index 4c4b6d27..96183e02 100644 --- a/test/src/lib/format/LibFormatDecimalFloat.countSigFigs.t.sol +++ b/test/src/lib/format/LibFormatDecimalFloat.countSigFigs.t.sol @@ -116,6 +116,8 @@ contract LibFormatDecimalFloatCountSigFigs is Test { function testCountSigFigsOne(int256 exponent) external pure { exponent = bound(exponent, -76, 0); + // exponent [-76, 0] + // forge-lint: disable-next-line(unsafe-typecast) int256 one = int256(10 ** uint256(-exponent)); checkCountSigFigs(one, exponent, 1); checkCountSigFigs(-one, exponent, 1); diff --git a/test/src/lib/format/LibFormatDecimalFloat.toDecimalString.t.sol b/test/src/lib/format/LibFormatDecimalFloat.toDecimalString.t.sol index d56342c7..9b63374d 100644 --- a/test/src/lib/format/LibFormatDecimalFloat.toDecimalString.t.sol +++ b/test/src/lib/format/LibFormatDecimalFloat.toDecimalString.t.sol @@ -86,6 +86,8 @@ contract LibFormatDecimalFloatToDecimalStringTest is Test { /// Negative matches positive. function testFormatDecimalRoundTripNegative(int256 value, uint256 sigFigsLimit) external pure { value = bound(value, 1, int256(type(int128).max)); + // value [1, int256(type(int128).max)] + // forge-lint: disable-next-line(unsafe-typecast) Float float = LibDecimalFloat.fromFixedDecimalLosslessPacked(uint256(value), 18); string memory formatted = float.toDecimalString(sigFigsLimit); float = float.minus(); diff --git a/test/src/lib/implementation/LibDecimalFloatImplementation.add.t.sol b/test/src/lib/implementation/LibDecimalFloatImplementation.add.t.sol index 8c628951..6e8f1e64 100644 --- a/test/src/lib/implementation/LibDecimalFloatImplementation.add.t.sol +++ b/test/src/lib/implementation/LibDecimalFloatImplementation.add.t.sol @@ -174,6 +174,8 @@ contract LibDecimalFloatImplementationAddTest is Test { vm.assume(normalizedSignedCoefficientA != 0); vm.assume(expectedSignedCoefficient != 0); + // ADD_MAX_EXPONENT_DIFF = 76 + // forge-lint: disable-next-line(unsafe-typecast) vm.assume((expectedExponent - normalizedExponentA) > int256(ADD_MAX_EXPONENT_DIFF)); (int256 signedCoefficient, int256 exponent) = diff --git a/test/src/lib/implementation/LibDecimalFloatImplementation.characteristicMantissa.t.sol b/test/src/lib/implementation/LibDecimalFloatImplementation.characteristicMantissa.t.sol index c3d3422a..cce14766 100644 --- a/test/src/lib/implementation/LibDecimalFloatImplementation.characteristicMantissa.t.sol +++ b/test/src/lib/implementation/LibDecimalFloatImplementation.characteristicMantissa.t.sol @@ -60,6 +60,8 @@ contract LibDecimalFloatImplementationCharacteristicMantissaTest is Test { function testCharacteristicMantissaNegExponentSmall(int256 signedCoefficient) public pure { for (int256 exponent = 1; exponent <= 76; exponent++) { + // exponent [1, 76] + // forge-lint: disable-next-line(unsafe-typecast) int256 scale = int256(10 ** uint256(exponent)); int256 expectedMantissa = signedCoefficient % scale; diff --git a/test/src/lib/implementation/LibDecimalFloatImplementation.div.t.sol b/test/src/lib/implementation/LibDecimalFloatImplementation.div.t.sol index bebf82be..e4061815 100644 --- a/test/src/lib/implementation/LibDecimalFloatImplementation.div.t.sol +++ b/test/src/lib/implementation/LibDecimalFloatImplementation.div.t.sol @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {Test, stdError} from "forge-std/Test.sol"; +import {Test} from "forge-std/Test.sol"; import { LibDecimalFloatImplementation, EXPONENT_MIN, diff --git a/test/src/lib/implementation/LibDecimalFloatImplementation.eq.t.sol b/test/src/lib/implementation/LibDecimalFloatImplementation.eq.t.sol index de47cc2c..99c94048 100644 --- a/test/src/lib/implementation/LibDecimalFloatImplementation.eq.t.sol +++ b/test/src/lib/implementation/LibDecimalFloatImplementation.eq.t.sol @@ -37,11 +37,16 @@ contract LibDecimalFloatImplementationEqTest is Test { } else if (y > x) { assertTrue(exponentY < exponentX, "y > x but exponentY >= exponentX"); assertTrue(exponentX - exponentY < 77, "y > x but exponentX - exponentY >= 77"); + // we assert that exponentY < exponentX and the diff is < 77. + // forge-lint: disable-next-line(unsafe-typecast) assertEq(x / y, int256(10 ** uint256(exponentX - exponentY)), "y > x but x / y != 10^(X - Y)"); assertEq(x % y, 0, "y > x but x % y != 0"); } else { assertTrue(exponentX < exponentY, "x < y but exponentX >= exponentY"); assertTrue(exponentY - exponentX < 77, "x < y but exponentY - exponentX >= 77"); + // x < y and they are eq so exponentY - exponentX will always be + // positive. + // forge-lint: disable-next-line(unsafe-typecast) assertEq(y / x, int256(10 ** uint256(exponentY - exponentX)), "x < y but y / x != 10^(Y - X)"); assertEq(y % x, 0, "x < y but y % x != 0"); } diff --git a/test/src/lib/implementation/LibDecimalFloatImplementation.log10.t.sol b/test/src/lib/implementation/LibDecimalFloatImplementation.log10.t.sol index 0dff7edf..baefacf7 100644 --- a/test/src/lib/implementation/LibDecimalFloatImplementation.log10.t.sol +++ b/test/src/lib/implementation/LibDecimalFloatImplementation.log10.t.sol @@ -17,6 +17,9 @@ contract LibDecimalFloatImplementationLog10Test is LogTest { (int256 actualSignedCoefficient, int256 actualExponent) = LibDecimalFloatImplementation.log10(tables, signedCoefficient, exponent); uint256 bGas = gasleft(); + // this is just a log, if the cast causes problems then the dev can + // deal with it. + // forge-lint: disable-next-line(unsafe-typecast) console2.log("%d %d Gas used: %d", uint256(signedCoefficient), uint256(exponent), aGas - bGas); assertEq(actualSignedCoefficient, expectedSignedCoefficient); assertEq(actualExponent, expectedExponent); diff --git a/test/src/lib/implementation/LibDecimalFloatImplementation.lookupLogTableVal.t.sol b/test/src/lib/implementation/LibDecimalFloatImplementation.lookupLogTableVal.t.sol new file mode 100644 index 00000000..38a1750b --- /dev/null +++ b/test/src/lib/implementation/LibDecimalFloatImplementation.lookupLogTableVal.t.sol @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: LicenseRef-DCL-1.0 +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd +pragma solidity =0.8.25; + +import {LogTest} from "../../../abstract/LogTest.sol"; +import {LibDecimalFloatImplementation} from "src/lib/implementation/LibDecimalFloatImplementation.sol"; + +contract LibDecimalFloatImplementationLookupLogTableValTest is LogTest { + function checkLookupLogTableVal(uint256 idx, uint256 expectedResult) internal { + address tables = logTables(); + uint256 result = LibDecimalFloatImplementation.lookupLogTableVal(tables, idx); + assertEq(result, expectedResult); + } + + function testLookupLogTableVal() external { + checkLookupLogTableVal(0, 0); + checkLookupLogTableVal(10, 43); + checkLookupLogTableVal(100, 414); + checkLookupLogTableVal(200, 792); + checkLookupLogTableVal(300, 1139); + checkLookupLogTableVal(400, 1461); + checkLookupLogTableVal(500, 1761); + checkLookupLogTableVal(600, 2041); + checkLookupLogTableVal(700, 2304); + checkLookupLogTableVal(800, 2553); + checkLookupLogTableVal(900, 2788); + checkLookupLogTableVal(1000, 3010); + checkLookupLogTableVal(1100, 3222); + checkLookupLogTableVal(1200, 3424); + checkLookupLogTableVal(1300, 3617); + checkLookupLogTableVal(1400, 3802); + checkLookupLogTableVal(1500, 3979); + checkLookupLogTableVal(1600, 4150); + checkLookupLogTableVal(1700, 4314); + checkLookupLogTableVal(1800, 4472); + checkLookupLogTableVal(1900, 4624); + checkLookupLogTableVal(2000, 4771); + checkLookupLogTableVal(2100, 4914); + checkLookupLogTableVal(2200, 5051); + checkLookupLogTableVal(2300, 5185); + checkLookupLogTableVal(2400, 5315); + checkLookupLogTableVal(2500, 5441); + checkLookupLogTableVal(2600, 5563); + checkLookupLogTableVal(2700, 5682); + checkLookupLogTableVal(2800, 5798); + checkLookupLogTableVal(2900, 5911); + checkLookupLogTableVal(3000, 6021); + checkLookupLogTableVal(3100, 6128); + checkLookupLogTableVal(3200, 6232); + checkLookupLogTableVal(3300, 6335); + checkLookupLogTableVal(3400, 6435); + checkLookupLogTableVal(3500, 6532); + checkLookupLogTableVal(3600, 6628); + checkLookupLogTableVal(3700, 6721); + checkLookupLogTableVal(3800, 6812); + checkLookupLogTableVal(3900, 6902); + checkLookupLogTableVal(4000, 6990); + checkLookupLogTableVal(4100, 7076); + checkLookupLogTableVal(4200, 7160); + checkLookupLogTableVal(4300, 7243); + checkLookupLogTableVal(4400, 7324); + checkLookupLogTableVal(4500, 7404); + checkLookupLogTableVal(4600, 7482); + checkLookupLogTableVal(4700, 7559); + checkLookupLogTableVal(4800, 7634); + checkLookupLogTableVal(4900, 7709); + checkLookupLogTableVal(5000, 7782); + checkLookupLogTableVal(5100, 7853); + checkLookupLogTableVal(5200, 7924); + checkLookupLogTableVal(5300, 7993); + checkLookupLogTableVal(5400, 8062); + checkLookupLogTableVal(5500, 8129); + checkLookupLogTableVal(5600, 8195); + checkLookupLogTableVal(5700, 8261); + checkLookupLogTableVal(5800, 8325); + checkLookupLogTableVal(5900, 8388); + checkLookupLogTableVal(6000, 8451); + checkLookupLogTableVal(6100, 8513); + checkLookupLogTableVal(6200, 8573); + checkLookupLogTableVal(6300, 8633); + checkLookupLogTableVal(6400, 8692); + checkLookupLogTableVal(6500, 8751); + checkLookupLogTableVal(6600, 8808); + checkLookupLogTableVal(6700, 8865); + checkLookupLogTableVal(6800, 8921); + checkLookupLogTableVal(6900, 8976); + checkLookupLogTableVal(7000, 9031); + checkLookupLogTableVal(7100, 9085); + checkLookupLogTableVal(7200, 9138); + checkLookupLogTableVal(7300, 9191); + checkLookupLogTableVal(7400, 9243); + checkLookupLogTableVal(7500, 9294); + checkLookupLogTableVal(7600, 9345); + checkLookupLogTableVal(7700, 9395); + checkLookupLogTableVal(7800, 9445); + checkLookupLogTableVal(7900, 9494); + checkLookupLogTableVal(8000, 9542); + checkLookupLogTableVal(8100, 9590); + checkLookupLogTableVal(8200, 9638); + checkLookupLogTableVal(8300, 9685); + checkLookupLogTableVal(8400, 9731); + checkLookupLogTableVal(8500, 9777); + checkLookupLogTableVal(8600, 9823); + checkLookupLogTableVal(8700, 9868); + checkLookupLogTableVal(8800, 9912); + checkLookupLogTableVal(8900, 9956); + checkLookupLogTableVal(8999, 10000); + } +} diff --git a/test/src/lib/implementation/LibDecimalFloatImplementation.maximize.t.sol b/test/src/lib/implementation/LibDecimalFloatImplementation.maximize.t.sol index 73be8237..056b6c66 100644 --- a/test/src/lib/implementation/LibDecimalFloatImplementation.maximize.t.sol +++ b/test/src/lib/implementation/LibDecimalFloatImplementation.maximize.t.sol @@ -64,6 +64,8 @@ contract LibDecimalFloatImplementationMaximizeTest is Test { checkMaximized(88e74, -74, 8.8e75, -74); for (int256 i = 76; i >= 0; i--) { + // i [0, 76] + // forge-lint: disable-next-line(unsafe-typecast) checkMaximized(int256(10 ** uint256(i)), 0, 1e76, i - 76); } diff --git a/test/src/lib/implementation/LibDecimalFloatImplementation.pow10.t.sol b/test/src/lib/implementation/LibDecimalFloatImplementation.pow10.t.sol index 17b61619..c70cd8cc 100644 --- a/test/src/lib/implementation/LibDecimalFloatImplementation.pow10.t.sol +++ b/test/src/lib/implementation/LibDecimalFloatImplementation.pow10.t.sol @@ -7,8 +7,6 @@ import {LogTest} from "../../../abstract/LogTest.sol"; import {LibDecimalFloatImplementation} from "src/lib/implementation/LibDecimalFloatImplementation.sol"; import {LibDecimalFloat, Float} from "src/lib/LibDecimalFloat.sol"; -import {console2} from "forge-std/Test.sol"; - contract LibDecimalFloatImplementationPow10Test is LogTest { using LibDecimalFloat for Float; diff --git a/test/src/lib/implementation/LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy.t.sol b/test/src/lib/implementation/LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy.t.sol index 6f52e921..8a9a328a 100644 --- a/test/src/lib/implementation/LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy.t.sol +++ b/test/src/lib/implementation/LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy.t.sol @@ -14,8 +14,12 @@ contract LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest is Test { c = bound(c, 0, uint256(type(int256).max)); (int256 actualSignedCoefficient, int256 actualExponent) = - LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy(int256(a), int256(b), c, exponent); + // a and b are both bound to the int256 range. + // forge-lint: disable-next-line(unsafe-typecast) + LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy(int256(a), int256(b), c, exponent); + // c is range bound so won't truncate when cast. + // forge-lint: disable-next-line(unsafe-typecast) int256 expectedSignedCoefficient = int256(c); int256 expectedExponent = exponent; @@ -34,8 +38,12 @@ contract LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest is Test { vm.assume(exponent != type(int256).max); // Prevent overflow in exponent. (int256 actualSignedCoefficient, int256 actualExponent) = - LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy(int256(a), int256(b), c, exponent); + // a and b are both bound to the int256 range. + // forge-lint: disable-next-line(unsafe-typecast) + LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy(int256(a), int256(b), c, exponent); // Expect the result to be positive. + // c is divided by 10 before being cast to int256 so won't truncate. + // forge-lint: disable-next-line(unsafe-typecast) int256 expectedSignedCoefficient = int256(c / 10); int256 expectedExponent = exponent + 1; assertEq(actualSignedCoefficient, expectedSignedCoefficient, "signed coefficient mismatch"); @@ -49,8 +57,12 @@ contract LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest is Test { c = bound(c, 0, uint256(type(int256).max)); (int256 actualSignedCoefficient, int256 actualExponent) = - LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy(-int256(a), -int256(b), c, exponent); + // a and b are both bound to the int256 range. + // forge-lint: disable-next-line(unsafe-typecast) + LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy(-int256(a), -int256(b), c, exponent); + // c is range bound so won't truncate when cast. + // forge-lint: disable-next-line(unsafe-typecast) int256 expectedSignedCoefficient = int256(c); int256 expectedExponent = exponent; @@ -69,9 +81,13 @@ contract LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest is Test { vm.assume(exponent != type(int256).max); // Prevent overflow in exponent. (int256 actualSignedCoefficient, int256 actualExponent) = - LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy(-int256(a), -int256(b), c, exponent); + // a and b are both bound to the int256 range. + // forge-lint: disable-next-line(unsafe-typecast) + LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy(-int256(a), -int256(b), c, exponent); // Expect the result to be positive. + // c is divided by 10 before being cast to int256 so won't truncate. + // forge-lint: disable-next-line(unsafe-typecast) int256 expectedSignedCoefficient = int256(c / 10); int256 expectedExponent = exponent + 1; @@ -86,9 +102,13 @@ contract LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest is Test { c = bound(c, 0, uint256(type(int256).max)); (int256 actualSignedCoefficient, int256 actualExponent) = - LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy(-int256(a), int256(b), c, exponent); + // a and b are both bound to the int256 range. + // forge-lint: disable-next-line(unsafe-typecast) + LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy(-int256(a), int256(b), c, exponent); // Expect the result to be negative. + // c is range bound so won't truncate when cast. + // forge-lint: disable-next-line(unsafe-typecast) int256 expectedSignedCoefficient = -int256(c); int256 expectedExponent = exponent; @@ -104,9 +124,15 @@ contract LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest is Test { vm.assume(exponent != type(int256).max); // Prevent overflow in exponent. (int256 actualSignedCoefficient, int256 actualExponent) = - LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy(int256(a), -int256(b), c, exponent); + // a is in range so won't truncate when cast. + // b is capped at type(int256).max so won't truncate when cast and can + // be negated directly. + // forge-lint: disable-next-line(unsafe-typecast) + LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy(int256(a), -int256(b), c, exponent); // Expect the result to be negative. + // c is divided by 10 before being cast to int256 so won't truncate. + // forge-lint: disable-next-line(unsafe-typecast) int256 expectedSignedCoefficient = -int256(c / 10); int256 expectedExponent = exponent + 1; @@ -125,9 +151,13 @@ contract LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest is Test { vm.assume(exponent != type(int256).max); // Prevent overflow in exponent. (int256 actualSignedCoefficient, int256 actualExponent) = - LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy(-int256(a), int256(b), c, exponent); + // a and b are both bound to the int256 range. + // forge-lint: disable-next-line(unsafe-typecast) + LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy(-int256(a), int256(b), c, exponent); // Expect the result to be negative. + // c is divided by 10 before being cast to int256 so won't truncate. + // forge-lint: disable-next-line(unsafe-typecast) int256 expectedSignedCoefficient = -int256(c / 10); int256 expectedExponent = exponent + 1; @@ -140,8 +170,11 @@ contract LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest is Test { a = bound(a, 1, uint256(type(int256).max)); b = bound(b, 1, uint256(type(int256).max)); uint256 c = uint256(type(int256).max) + 1; + // b is capped at type(int256).max so won't truncate when cast and can + // be negated directly. (int256 actualSignedCoefficient, int256 actualExponent) = - LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy(int256(a), -int256(b), c, exponent); + // forge-lint: disable-next-line(unsafe-typecast) + LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy(int256(a), -int256(b), c, exponent); // Expect the result to be negative. int256 expectedSignedCoefficient = type(int256).min; int256 expectedExponent = exponent; diff --git a/test/src/lib/implementation/LibDecimalFloatImplementation.withTargetExponent.t.sol b/test/src/lib/implementation/LibDecimalFloatImplementation.withTargetExponent.t.sol index ffa2f827..1d8aabde 100644 --- a/test/src/lib/implementation/LibDecimalFloatImplementation.withTargetExponent.t.sol +++ b/test/src/lib/implementation/LibDecimalFloatImplementation.withTargetExponent.t.sol @@ -56,6 +56,8 @@ contract LibDecimalFloatImplementationWithTargetExponentTest is Test { exponent = bound(exponent, targetExponent + 1, targetExponent + 76); unchecked { + // exponent - targetExponent [1, 76] + // forge-lint: disable-next-line(unsafe-typecast) int256 scale = int256(10 ** uint256(exponent - targetExponent)); int256 c = signedCoefficient * scale; vm.assume(c / scale != signedCoefficient); @@ -76,12 +78,16 @@ contract LibDecimalFloatImplementationWithTargetExponentTest is Test { exponent = bound(exponent, targetExponent + 1, targetExponent + 76); unchecked { + // exponent - targetExponent [1, 76] + // forge-lint: disable-next-line(unsafe-typecast) int256 scale = int256(10 ** uint256(exponent - targetExponent)); int256 c = signedCoefficient * scale; vm.assume(c / scale == signedCoefficient); } int256 actualSignedCoefficient = LibDecimalFloatImplementation.withTargetExponent(signedCoefficient, exponent, targetExponent); + // exponent - targetExponent [1, 76] + // forge-lint: disable-next-line(unsafe-typecast) int256 expectedSignedCoefficient = signedCoefficient * int256(10 ** uint256(exponent - targetExponent)); assertEq(actualSignedCoefficient, expectedSignedCoefficient, "signedCoefficient"); } @@ -139,6 +145,8 @@ contract LibDecimalFloatImplementationWithTargetExponentTest is Test { int256 actualSignedCoefficient = LibDecimalFloatImplementation.withTargetExponent(signedCoefficient, exponent, targetExponent); + // targetExponentDiff [1, 76] + // forge-lint: disable-next-line(unsafe-typecast) int256 expectedSignedCoefficient = signedCoefficient / int256(10 ** uint256(targetExponentDiff)); assertEq(actualSignedCoefficient, expectedSignedCoefficient, "signedCoefficient"); } @@ -168,14 +176,17 @@ contract LibDecimalFloatImplementationWithTargetExponentTest is Test { // Assume not overflow. unchecked { - int256 scale = int256(10 ** uint256(exponent - targetExponent)); + // targetExponentDiff fits in uint256 so won't truncate when cast. + // forge-lint: disable-next-line(unsafe-typecast) + int256 scale = int256(10 ** uint256(targetExponentDiff)); int256 c = signedCoefficient * scale; vm.assume(c / scale == signedCoefficient); } int256 actualSignedCoefficient = LibDecimalFloatImplementation.withTargetExponent(signedCoefficient, exponent, targetExponent); - int256 expectedSignedCoefficient = signedCoefficient * int256(10 ** uint256(exponent - targetExponent)); + // forge-lint: disable-next-line(unsafe-typecast) + int256 expectedSignedCoefficient = signedCoefficient * int256(10 ** uint256(targetExponentDiff)); assertEq(actualSignedCoefficient, expectedSignedCoefficient, "signedCoefficient"); } @@ -188,6 +199,8 @@ contract LibDecimalFloatImplementationWithTargetExponentTest is Test { // Assume overflow. unchecked { + // targetExponent > exponent + // forge-lint: disable-next-line(unsafe-typecast) int256 scale = int256(10 ** uint256(exponent - targetExponent)); int256 c = signedCoefficient * scale; vm.assume(c / scale != signedCoefficient); diff --git a/test/src/lib/parse/LibParseDecimalFloat.t.sol b/test/src/lib/parse/LibParseDecimalFloat.t.sol index 612d3ff1..28e1f2d7 100644 --- a/test/src/lib/parse/LibParseDecimalFloat.t.sol +++ b/test/src/lib/parse/LibParseDecimalFloat.t.sol @@ -105,6 +105,8 @@ contract LibParseDecimalFloatTest is Test { checkParseDecimalFloat( input, + // value is bound to the int256 range so won't truncate when cast. + // forge-lint: disable-next-line(unsafe-typecast) isNeg ? (value == (uint256(type(int256).max) + 1) ? type(int256).min : -int256(value)) : int256(value), 0, bytes(input).length