diff --git a/.gas-snapshot b/.gas-snapshot index 086fc50b..7f6ecb84 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,277 +1,292 @@ -DecimalFloatAbsTest:testAbsDeployed(bytes32) (runs: 5096, μ: 2657875, ~: 2657817) -DecimalFloatAddTest:testAddDeployed(bytes32,bytes32) (runs: 5096, μ: 2661931, ~: 2662013) -DecimalFloatCeilTest:testCeilDeployed(bytes32) (runs: 5096, μ: 2657902, ~: 2657530) -DecimalFloatConstantsTest:testEDeployed() (gas: 2657060) -DecimalFloatConstantsTest:testMaxNegativeValueDeployed() (gas: 2657092) -DecimalFloatConstantsTest:testMaxPositiveValueDeployed() (gas: 2657050) -DecimalFloatConstantsTest:testMinNegativeValueDeployed() (gas: 2657025) -DecimalFloatConstantsTest:testMinPositiveValueDeployed() (gas: 2657004) -DecimalFloatDivTest:testDivDeployed(bytes32,bytes32) (runs: 5096, μ: 2662969, ~: 2663034) -DecimalFloatEqTest:testEqDeployed(bytes32,bytes32) (runs: 5096, μ: 2658260, ~: 2658185) -DecimalFloatFloorTest:testFloorDeployed(bytes32) (runs: 5096, μ: 2657712, ~: 2657528) -DecimalFloatFormatTest:testFormatDeployed(bytes32) (runs: 5096, μ: 2661880, ~: 2661721) -DecimalFloatFracTest:testFracDeployed(bytes32) (runs: 5096, μ: 2658104, ~: 2658088) -DecimalFloatFromFixedDecimalLosslessTest:testFromFixedDecimalLosslessDeployed(uint256,uint8) (runs: 5096, μ: 2658659, ~: 2658592) -DecimalFloatFromFixedDecimalLossyTest:testFromFixedDecimalLossyDeployed(uint256,uint8) (runs: 5096, μ: 2659145, ~: 2659062) -DecimalFloatGtTest:testGtDeployed(bytes32,bytes32) (runs: 5096, μ: 2658201, ~: 2658127) -DecimalFloatGteTest:testGteDeployed(bytes32,bytes32) (runs: 5096, μ: 2658187, ~: 2658113) -DecimalFloatInvTest:testInvDeployed(bytes32) (runs: 5096, μ: 2661791, ~: 2661828) -DecimalFloatIsZeroTest:testIsZeroDeployed(bytes32) (runs: 5096, μ: 2657370, ~: 2657370) -DecimalFloatLtTest:testLtDeployed(bytes32,bytes32) (runs: 5096, μ: 2658178, ~: 2658104) -DecimalFloatLteTest:testLteDeployed(bytes32,bytes32) (runs: 5096, μ: 2658231, ~: 2658157) -DecimalFloatMaxTest:testMaxDeployed(bytes32,bytes32) (runs: 5096, μ: 2658240, ~: 2658179) -DecimalFloatMinTest:testMinDeployed(bytes32,bytes32) (runs: 5096, μ: 2658261, ~: 2658199) -DecimalFloatMinusTest:testMinusDeployed(bytes32) (runs: 5096, μ: 2657975, ~: 2657975) -DecimalFloatMulTest:testMulDeployed(bytes32,bytes32) (runs: 5096, μ: 2660075, ~: 2661135) -DecimalFloatPackLosslessTest:testPackDeployed(int224,int32) (runs: 5096, μ: 158769, ~: 158769) -DecimalFloatParseTest:testParseDeployed(string) (runs: 5096, μ: 2660608, ~: 2660477) -DecimalFloatPowTest:testPowDeployed(bytes32,bytes32) (runs: 5096, μ: 2669675, ~: 2666208) -DecimalFloatSqrtTest:testSqrtDeployed(bytes32) (runs: 5096, μ: 2669032, ~: 2666922) -DecimalFloatSubTest:testSubDeployed(bytes32,bytes32) (runs: 5096, μ: 2662292, ~: 2662313) -DecimalFloatToFixedDecimalLosslessTest:testToFixedDecimalLosslessDeployed(bytes32,uint8) (runs: 5096, μ: 2659274, ~: 2659175) -DecimalFloatToFixedDecimalLossyTest:testToFixedDecimalLossyDeployed(bytes32,uint8) (runs: 5096, μ: 2659415, ~: 2659704) -LibDecimalFloatAbsTest:testAbsMinValue(int32) (runs: 5096, μ: 5121, ~: 5121) -LibDecimalFloatAbsTest:testAbsNegative(int256,int32) (runs: 5096, μ: 10475, ~: 10702) -LibDecimalFloatAbsTest:testAbsNonNegative(int256,int32) (runs: 5096, μ: 9641, ~: 9392) +DecimalFloatAbsTest:testAbsDeployed(bytes32) (runs: 5104, μ: 2743074, ~: 2743016) +DecimalFloatAddTest:testAddDeployed(bytes32,bytes32) (runs: 5104, μ: 2747129, ~: 2747212) +DecimalFloatCeilTest:testCeilDeployed(bytes32) (runs: 5104, μ: 2743105, ~: 2742729) +DecimalFloatConstantsTest:testEDeployed() (gas: 2742259) +DecimalFloatConstantsTest:testMaxNegativeValueDeployed() (gas: 2742291) +DecimalFloatConstantsTest:testMaxPositiveValueDeployed() (gas: 2742249) +DecimalFloatConstantsTest:testMinNegativeValueDeployed() (gas: 2742224) +DecimalFloatConstantsTest:testMinPositiveValueDeployed() (gas: 2742203) +DecimalFloatDivTest:testDivDeployed(bytes32,bytes32) (runs: 5104, μ: 2749019, ~: 2749102) +DecimalFloatEqTest:testEqDeployed(bytes32,bytes32) (runs: 5104, μ: 2743459, ~: 2743384) +DecimalFloatFloorTest:testFloorDeployed(bytes32) (runs: 5104, μ: 2742912, ~: 2742727) +DecimalFloatFormatTest:testFormatDeployed(bytes32) (runs: 5104, μ: 2747070, ~: 2746892) +DecimalFloatFracTest:testFracDeployed(bytes32) (runs: 5104, μ: 2743303, ~: 2743287) +DecimalFloatFromFixedDecimalLosslessTest:testFromFixedDecimalLosslessDeployed(uint256,uint8) (runs: 5104, μ: 2743854, ~: 2743791) +DecimalFloatFromFixedDecimalLossyTest:testFromFixedDecimalLossyDeployed(uint256,uint8) (runs: 5104, μ: 2744344, ~: 2744261) +DecimalFloatGtTest:testGtDeployed(bytes32,bytes32) (runs: 5104, μ: 2743401, ~: 2743326) +DecimalFloatGteTest:testGteDeployed(bytes32,bytes32) (runs: 5104, μ: 2743387, ~: 2743312) +DecimalFloatInvTest:testInvDeployed(bytes32) (runs: 5104, μ: 2747886, ~: 2747923) +DecimalFloatIsZeroTest:testIsZeroDeployed(bytes32) (runs: 5104, μ: 2742569, ~: 2742569) +DecimalFloatLtTest:testLtDeployed(bytes32,bytes32) (runs: 5104, μ: 2743378, ~: 2743303) +DecimalFloatLteTest:testLteDeployed(bytes32,bytes32) (runs: 5104, μ: 2743431, ~: 2743356) +DecimalFloatMaxTest:testMaxDeployed(bytes32,bytes32) (runs: 5104, μ: 2743439, ~: 2743378) +DecimalFloatMinTest:testMinDeployed(bytes32,bytes32) (runs: 5104, μ: 2743460, ~: 2743398) +DecimalFloatMinusTest:testMinusDeployed(bytes32) (runs: 5104, μ: 2743174, ~: 2743174) +DecimalFloatMulTest:testMulDeployed(bytes32,bytes32) (runs: 5104, μ: 2747034, ~: 2747843) +DecimalFloatPackLosslessTest:testPackDeployed(int224,int32) (runs: 5104, μ: 158769, ~: 158769) +DecimalFloatParseTest:testParseDeployed(string) (runs: 5104, μ: 2745806, ~: 2745675) +DecimalFloatPowTest:testPowDeployed(bytes32,bytes32) (runs: 5104, μ: 2755926, ~: 2753551) +DecimalFloatSqrtTest:testSqrtDeployed(bytes32) (runs: 5104, μ: 2755575, ~: 2754253) +DecimalFloatSubTest:testSubDeployed(bytes32,bytes32) (runs: 5104, μ: 2747478, ~: 2747512) +DecimalFloatToFixedDecimalLosslessTest:testToFixedDecimalLosslessDeployed(bytes32,uint8) (runs: 5104, μ: 2744480, ~: 2744374) +DecimalFloatToFixedDecimalLossyTest:testToFixedDecimalLossyDeployed(bytes32,uint8) (runs: 5104, μ: 2744618, ~: 2744903) +LibDecimalFloatAbsTest:testAbsMinValue(int32) (runs: 5104, μ: 5121, ~: 5121) +LibDecimalFloatAbsTest:testAbsNegative(int256,int32) (runs: 5104, μ: 10475, ~: 10702) +LibDecimalFloatAbsTest:testAbsNonNegative(int256,int32) (runs: 5104, μ: 9641, ~: 9392) LibDecimalFloatCeilTest:testCeilExamples() (gas: 30794) -LibDecimalFloatCeilTest:testCeilInRange(int224,int256) (runs: 5096, μ: 11040, ~: 10713) -LibDecimalFloatCeilTest:testCeilLessThanMin(int224,int256) (runs: 5096, μ: 10059, ~: 9820) -LibDecimalFloatCeilTest:testCeilNonNegative(int224,int256) (runs: 5096, μ: 8961, ~: 9212) -LibDecimalFloatCeilTest:testCeilNotReverts(bytes32) (runs: 5096, μ: 598, ~: 411) -LibDecimalFloatCeilTest:testCeilZero(int32) (runs: 5096, μ: 5438, ~: 5438) +LibDecimalFloatCeilTest:testCeilInRange(int224,int256) (runs: 5104, μ: 11040, ~: 10713) +LibDecimalFloatCeilTest:testCeilLessThanMin(int224,int256) (runs: 5104, μ: 10059, ~: 9820) +LibDecimalFloatCeilTest:testCeilNonNegative(int224,int256) (runs: 5104, μ: 8961, ~: 9212) +LibDecimalFloatCeilTest:testCeilNotReverts(bytes32) (runs: 5104, μ: 598, ~: 411) +LibDecimalFloatCeilTest:testCeilZero(int32) (runs: 5104, μ: 5438, ~: 5438) LibDecimalFloatConstantsTest:testFloatE() (gas: 3357) LibDecimalFloatConstantsTest:testFloatHalf() (gas: 3336) LibDecimalFloatConstantsTest:testFloatMaxNegativeValue() (gas: 3379) -LibDecimalFloatConstantsTest:testFloatMaxNegativeValueIsMax(bytes32) (runs: 5096, μ: 4488, ~: 4594) +LibDecimalFloatConstantsTest:testFloatMaxNegativeValueIsMax(bytes32) (runs: 5104, μ: 4488, ~: 4594) LibDecimalFloatConstantsTest:testFloatMaxPositiveValue() (gas: 3335) -LibDecimalFloatConstantsTest:testFloatMaxPositiveValueIsMax(bytes32) (runs: 5096, μ: 3545, ~: 3586) +LibDecimalFloatConstantsTest:testFloatMaxPositiveValueIsMax(bytes32) (runs: 5104, μ: 3545, ~: 3586) LibDecimalFloatConstantsTest:testFloatMinNegativeValue() (gas: 3335) -LibDecimalFloatConstantsTest:testFloatMinNegativeValueIsMin(bytes32) (runs: 5096, μ: 3496, ~: 3457) +LibDecimalFloatConstantsTest:testFloatMinNegativeValueIsMin(bytes32) (runs: 5104, μ: 3496, ~: 3457) LibDecimalFloatConstantsTest:testFloatMinPositiveValue() (gas: 3357) -LibDecimalFloatConstantsTest:testFloatMinPositiveValueIsMin(bytes32) (runs: 5096, μ: 4938, ~: 4870) +LibDecimalFloatConstantsTest:testFloatMinPositiveValueIsMin(bytes32) (runs: 5104, μ: 4939, ~: 4870) LibDecimalFloatConstantsTest:testFloatOne() (gas: 3358) LibDecimalFloatConstantsTest:testFloatTwo() (gas: 3380) LibDecimalFloatConstantsTest:testFloatZero() (gas: 3337) -LibDecimalFloatDecimalAddTest:testAddPacked(bytes32,bytes32) (runs: 5096, μ: 9762, ~: 9832) -LibDecimalFloatDecimalLosslessTest:testFromFixedDecimalLosslessFail(uint256,uint8) (runs: 5096, μ: 9615, ~: 9663) -LibDecimalFloatDecimalLosslessTest:testFromFixedDecimalLosslessMem(uint256,uint8) (runs: 5096, μ: 8130, ~: 8048) -LibDecimalFloatDecimalLosslessTest:testFromFixedDecimalLosslessPass(uint256,uint8) (runs: 5096, μ: 7452, ~: 7424) +LibDecimalFloatDecimalAddTest:testAddPacked(bytes32,bytes32) (runs: 5104, μ: 9762, ~: 9832) +LibDecimalFloatDecimalLosslessTest:testFromFixedDecimalLosslessFail(uint256,uint8) (runs: 5102, μ: 9615, ~: 9663) +LibDecimalFloatDecimalLosslessTest:testFromFixedDecimalLosslessMem(uint256,uint8) (runs: 5104, μ: 8130, ~: 8048) +LibDecimalFloatDecimalLosslessTest:testFromFixedDecimalLosslessPass(uint256,uint8) (runs: 5104, μ: 7452, ~: 7424) LibDecimalFloatDecimalLosslessTest:testToFixedDecimalLosslessFail() (gas: 4894) -LibDecimalFloatDecimalLosslessTest:testToFixedDecimalLosslessPacked(bytes32,uint8) (runs: 5096, μ: 6718, ~: 6161) -LibDecimalFloatDecimalLosslessTest:testToFixedDecimalLosslessPass(int256,int256,uint8) (runs: 5096, μ: 15805, ~: 15768) -LibDecimalFloatDecimalTest:testFixedDecimalRoundTripLossless(uint256,uint8) (runs: 5096, μ: 9274, ~: 9053) +LibDecimalFloatDecimalLosslessTest:testToFixedDecimalLosslessPacked(bytes32,uint8) (runs: 5104, μ: 6717, ~: 6161) +LibDecimalFloatDecimalLosslessTest:testToFixedDecimalLosslessPass(int256,int256,uint8) (runs: 5104, μ: 15805, ~: 15768) +LibDecimalFloatDecimalTest:testFixedDecimalRoundTripLossless(uint256,uint8) (runs: 5104, μ: 9274, ~: 9053) LibDecimalFloatDecimalTest:testFromFixedDecimalLossyComplicated() (gas: 685958) LibDecimalFloatDecimalTest:testFromFixedDecimalLossyNormalizedMax() (gas: 673506) LibDecimalFloatDecimalTest:testFromFixedDecimalLossyNormalizedMaxPlusOne() (gas: 704362) LibDecimalFloatDecimalTest:testFromFixedDecimalLossyOne() (gas: 685936) LibDecimalFloatDecimalTest:testFromFixedDecimalLossyOneMillion() (gas: 685937) LibDecimalFloatDecimalTest:testFromFixedDecimalLossyOverflow() (gas: 715261) -LibDecimalFloatDecimalTest:testFromFixedDecimalLossyPacked(uint256,uint8) (runs: 5096, μ: 9460, ~: 9374) -LibDecimalFloatDecimalTest:testFromFixedDecimalLossyTruncateOne(uint256,uint8) (runs: 5096, μ: 5978, ~: 5937) -LibDecimalFloatDecimalTest:testFromFixedDecimalLossyTruncateZero(uint256,uint8) (runs: 5096, μ: 7305, ~: 5860) -LibDecimalFloatDecimalTest:testToFixedDecimalLosslessScaleUp(int256,int256,uint8) (runs: 5096, μ: 16005, ~: 15996) -LibDecimalFloatDecimalTest:testToFixedDecimalLossyExponentOverflow(int256,int256,uint8) (runs: 5096, μ: 14964, ~: 14729) -LibDecimalFloatDecimalTest:testToFixedDecimalLossyIdentity(int256,uint8) (runs: 5096, μ: 10152, ~: 9811) -LibDecimalFloatDecimalTest:testToFixedDecimalLossyNegative(int256,int256,uint8) (runs: 5096, μ: 10825, ~: 11076) -LibDecimalFloatDecimalTest:testToFixedDecimalLossyPacked(bytes32,uint8) (runs: 5096, μ: 6804, ~: 6905) -LibDecimalFloatDecimalTest:testToFixedDecimalLossyScaleUpOverflow(int256,int256,uint8) (runs: 5096, μ: 15348, ~: 15612) -LibDecimalFloatDecimalTest:testToFixedDecimalLossyTruncate(int256,int256,uint8) (runs: 5096, μ: 14493, ~: 14212) +LibDecimalFloatDecimalTest:testFromFixedDecimalLossyPacked(uint256,uint8) (runs: 5104, μ: 9460, ~: 9374) +LibDecimalFloatDecimalTest:testFromFixedDecimalLossyTruncateOne(uint256,uint8) (runs: 5104, μ: 5978, ~: 5937) +LibDecimalFloatDecimalTest:testFromFixedDecimalLossyTruncateZero(uint256,uint8) (runs: 5104, μ: 7306, ~: 5860) +LibDecimalFloatDecimalTest:testToFixedDecimalLosslessScaleUp(int256,int256,uint8) (runs: 5099, μ: 16005, ~: 15996) +LibDecimalFloatDecimalTest:testToFixedDecimalLossyExponentOverflow(int256,int256,uint8) (runs: 5104, μ: 14964, ~: 14729) +LibDecimalFloatDecimalTest:testToFixedDecimalLossyIdentity(int256,uint8) (runs: 5104, μ: 10152, ~: 9811) +LibDecimalFloatDecimalTest:testToFixedDecimalLossyNegative(int256,int256,uint8) (runs: 5104, μ: 10825, ~: 11076) +LibDecimalFloatDecimalTest:testToFixedDecimalLossyPacked(bytes32,uint8) (runs: 5104, μ: 6803, ~: 6905) +LibDecimalFloatDecimalTest:testToFixedDecimalLossyScaleUpOverflow(int256,int256,uint8) (runs: 5101, μ: 15348, ~: 15612) +LibDecimalFloatDecimalTest:testToFixedDecimalLossyTruncate(int256,int256,uint8) (runs: 5104, μ: 14493, ~: 14212) LibDecimalFloatDecimalTest:testToFixedDecimalLossyTruncateLossless() (gas: 14523) -LibDecimalFloatDecimalTest:testToFixedDecimalLossyUnderflow(int256,int256,uint8) (runs: 5096, μ: 13738, ~: 13602) -LibDecimalFloatDecimalTest:testToFixedDecimalLossyZero(int256,uint8) (runs: 5096, μ: 4598, ~: 4598) -LibDecimalFloatDivTest:testDivPacked(bytes32,bytes32) (runs: 5096, μ: 10691, ~: 10757) -LibDecimalFloatEqTest:testEqPacked(bytes32,bytes32) (runs: 5096, μ: 5524, ~: 5450) -LibDecimalFloatEqTest:testEqXNotYExponents(bytes32,bytes32) (runs: 5096, μ: 4341, ~: 4234) -LibDecimalFloatEqTest:testEqZero(int32) (runs: 5096, μ: 5133, ~: 5133) +LibDecimalFloatDecimalTest:testToFixedDecimalLossyUnderflow(int256,int256,uint8) (runs: 5104, μ: 13739, ~: 13602) +LibDecimalFloatDecimalTest:testToFixedDecimalLossyZero(int256,uint8) (runs: 5104, μ: 4598, ~: 4598) +LibDecimalFloatDivTest:testDivPacked(bytes32,bytes32) (runs: 5104, μ: 11524, ~: 11603) +LibDecimalFloatEqTest:testEqPacked(bytes32,bytes32) (runs: 5104, μ: 5524, ~: 5450) +LibDecimalFloatEqTest:testEqXNotYExponents(bytes32,bytes32) (runs: 5104, μ: 4341, ~: 4234) +LibDecimalFloatEqTest:testEqZero(int32) (runs: 5104, μ: 5133, ~: 5133) LibDecimalFloatFloorTest:testFloorExamples() (gas: 38387) LibDecimalFloatFloorTest:testFloorGas0() (gas: 960) LibDecimalFloatFloorTest:testFloorGasTiny() (gas: 881) LibDecimalFloatFloorTest:testFloorGasZero() (gas: 553) -LibDecimalFloatFloorTest:testFloorInRange(int224,int256) (runs: 5096, μ: 11032, ~: 11044) -LibDecimalFloatFloorTest:testFloorLessThanMin(int224,int256) (runs: 5096, μ: 10284, ~: 10293) -LibDecimalFloatFloorTest:testFloorNonNegative(int224,int256) (runs: 5096, μ: 9547, ~: 9806) -LibDecimalFloatFloorTest:testFloorNotReverts(bytes32) (runs: 5096, μ: 461, ~: 365) +LibDecimalFloatFloorTest:testFloorInRange(int224,int256) (runs: 5104, μ: 11032, ~: 11044) +LibDecimalFloatFloorTest:testFloorLessThanMin(int224,int256) (runs: 5104, μ: 10284, ~: 10293) +LibDecimalFloatFloorTest:testFloorNonNegative(int224,int256) (runs: 5104, μ: 9547, ~: 9806) +LibDecimalFloatFloorTest:testFloorNotReverts(bytes32) (runs: 5104, μ: 461, ~: 365) LibDecimalFloatFracTest:testFracExamples() (gas: 39135) LibDecimalFloatFracTest:testFracGas0() (gas: 960) LibDecimalFloatFracTest:testFracGasTiny() (gas: 836) LibDecimalFloatFracTest:testFracGasZero() (gas: 820) -LibDecimalFloatFracTest:testFracInRange(int224,int256) (runs: 5096, μ: 10847, ~: 10859) -LibDecimalFloatFracTest:testFracLessThanMin(int224,int256) (runs: 5096, μ: 10273, ~: 10280) -LibDecimalFloatFracTest:testFracNonNegative(int224,int256) (runs: 5096, μ: 9806, ~: 10066) -LibDecimalFloatFracTest:testFracNotReverts(bytes32) (runs: 5096, μ: 630, ~: 621) +LibDecimalFloatFracTest:testFracInRange(int224,int256) (runs: 5104, μ: 10847, ~: 10859) +LibDecimalFloatFracTest:testFracLessThanMin(int224,int256) (runs: 5104, μ: 10273, ~: 10280) +LibDecimalFloatFracTest:testFracNonNegative(int224,int256) (runs: 5104, μ: 9806, ~: 10066) +LibDecimalFloatFracTest:testFracNotReverts(bytes32) (runs: 5104, μ: 630, ~: 621) LibDecimalFloatGtTest:testGtGasAZero() (gas: 973) LibDecimalFloatGtTest:testGtGasBZero() (gas: 973) LibDecimalFloatGtTest:testGtGasBothZero() (gas: 751) LibDecimalFloatGtTest:testGtGasDifferentSigns() (gas: 974) LibDecimalFloatGtTest:testGtGasExponentDiffOverflow() (gas: 1143) -LibDecimalFloatGtTest:testGtOneEAny(bytes32) (runs: 5096, μ: 3494, ~: 3494) -LibDecimalFloatGtTest:testGtReference(int224,int32,int224,int32) (runs: 5096, μ: 8067, ~: 6285) -LibDecimalFloatGtTest:testGtX(int224,int32) (runs: 5096, μ: 3882, ~: 3882) -LibDecimalFloatGtTest:testGtXEAnyVsXEAny(int256,int32,int32) (runs: 5096, μ: 10592, ~: 10332) -LibDecimalFloatGtTest:testGtXEAnyVsXEAnyNegative(int256,int32,int32) (runs: 5096, μ: 11144, ~: 11349) -LibDecimalFloatGtTest:testGtXNotY(bytes32,bytes32) (runs: 5096, μ: 4341, ~: 4232) -LibDecimalFloatGtTest:testGtXPositiveYNegative(int256,int32,int256,int32) (runs: 5096, μ: 13764, ~: 13595) -LibDecimalFloatGtTest:testGtXPositiveYZero(int256,int32,int32) (runs: 5096, μ: 10273, ~: 10026) -LibDecimalFloatGtTest:testGtZero(int32,int32) (runs: 5096, μ: 4793, ~: 4793) +LibDecimalFloatGtTest:testGtOneEAny(bytes32) (runs: 5104, μ: 3494, ~: 3494) +LibDecimalFloatGtTest:testGtReference(int224,int32,int224,int32) (runs: 5104, μ: 8066, ~: 6272) +LibDecimalFloatGtTest:testGtX(int224,int32) (runs: 5104, μ: 3882, ~: 3882) +LibDecimalFloatGtTest:testGtXEAnyVsXEAny(int256,int32,int32) (runs: 5104, μ: 10593, ~: 10332) +LibDecimalFloatGtTest:testGtXEAnyVsXEAnyNegative(int256,int32,int32) (runs: 5104, μ: 11144, ~: 11349) +LibDecimalFloatGtTest:testGtXNotY(bytes32,bytes32) (runs: 5104, μ: 4341, ~: 4232) +LibDecimalFloatGtTest:testGtXPositiveYNegative(int256,int32,int256,int32) (runs: 5104, μ: 13764, ~: 13595) +LibDecimalFloatGtTest:testGtXPositiveYZero(int256,int32,int32) (runs: 5104, μ: 10274, ~: 10026) +LibDecimalFloatGtTest:testGtZero(int32,int32) (runs: 5104, μ: 4793, ~: 4793) LibDecimalFloatGteTest:testGteGasAZero() (gas: 976) LibDecimalFloatGteTest:testGteGasBZero() (gas: 1020) LibDecimalFloatGteTest:testGteGasBothZero() (gas: 753) LibDecimalFloatGteTest:testGteGasDifferentSigns() (gas: 996) LibDecimalFloatGteTest:testGteGasExponentDiffOverflow() (gas: 1102) -LibDecimalFloatGteTest:testGteOneEAny(bytes32) (runs: 5096, μ: 3494, ~: 3494) -LibDecimalFloatGteTest:testGteReference(int224,int32,int224,int32) (runs: 5096, μ: 8117, ~: 6344) -LibDecimalFloatGteTest:testGteX(int224,int32) (runs: 5096, μ: 3925, ~: 3925) -LibDecimalFloatGteTest:testGteXEAnyVsXEAny(int256,int32,int32) (runs: 5096, μ: 10622, ~: 10364) -LibDecimalFloatGteTest:testGteXEAnyVsXEAnyNegative(int256,int32,int32) (runs: 5096, μ: 11156, ~: 11361) -LibDecimalFloatGteTest:testGteXNotLtY(bytes32,bytes32) (runs: 5096, μ: 3947, ~: 3873) -LibDecimalFloatGteTest:testGteXPositiveYNegative(int256,int32,int256,int32) (runs: 5096, μ: 13794, ~: 13623) -LibDecimalFloatGteTest:testGteXPositiveYZero(int256,int32,int32) (runs: 5096, μ: 9551, ~: 9170) -LibDecimalFloatGteTest:testGteZero(int32,int32) (runs: 5096, μ: 4838, ~: 4838) +LibDecimalFloatGteTest:testGteOneEAny(bytes32) (runs: 5104, μ: 3494, ~: 3494) +LibDecimalFloatGteTest:testGteReference(int224,int32,int224,int32) (runs: 5104, μ: 8116, ~: 6344) +LibDecimalFloatGteTest:testGteX(int224,int32) (runs: 5104, μ: 3925, ~: 3925) +LibDecimalFloatGteTest:testGteXEAnyVsXEAny(int256,int32,int32) (runs: 5104, μ: 10622, ~: 10364) +LibDecimalFloatGteTest:testGteXEAnyVsXEAnyNegative(int256,int32,int32) (runs: 5104, μ: 11156, ~: 11361) +LibDecimalFloatGteTest:testGteXNotLtY(bytes32,bytes32) (runs: 5104, μ: 3947, ~: 3873) +LibDecimalFloatGteTest:testGteXPositiveYNegative(int256,int32,int256,int32) (runs: 5104, μ: 13794, ~: 13623) +LibDecimalFloatGteTest:testGteXPositiveYZero(int256,int32,int32) (runs: 5104, μ: 9551, ~: 9170) +LibDecimalFloatGteTest:testGteZero(int32,int32) (runs: 5104, μ: 4838, ~: 4838) LibDecimalFloatImplementationAddTest:testAdd123456789987654321() (gas: 4811) LibDecimalFloatImplementationAddTest:testAdd123456789e9987654321() (gas: 4861) -LibDecimalFloatImplementationAddTest:testAddNeverRevert(int256,int256,int256,int256) (runs: 5096, μ: 13101, ~: 13034) +LibDecimalFloatImplementationAddTest:testAddNeverRevert(int256,int256,int256,int256) (runs: 5104, μ: 13101, ~: 13035) LibDecimalFloatImplementationAddTest:testAddOneOneNotMaximized() (gas: 6148) LibDecimalFloatImplementationAddTest:testAddOneOnePreMaximized() (gas: 4300) LibDecimalFloatImplementationAddTest:testAddOneZero() (gas: 3666) -LibDecimalFloatImplementationAddTest:testAddSameExponent(int256,int256) (runs: 5096, μ: 6865, ~: 6935) +LibDecimalFloatImplementationAddTest:testAddSameExponent(int256,int256) (runs: 5104, μ: 6864, ~: 6935) LibDecimalFloatImplementationAddTest:testAddZero() (gas: 3665) -LibDecimalFloatImplementationAddTest:testAddZeroAnyExponent(int128) (runs: 5096, μ: 9293, ~: 9271) +LibDecimalFloatImplementationAddTest:testAddZeroAnyExponent(int128) (runs: 5104, μ: 9293, ~: 9271) LibDecimalFloatImplementationAddTest:testAddZeroOne() (gas: 3664) -LibDecimalFloatImplementationAddTest:testAddZeroToAnyNonZero(int256,int256,int256) (runs: 5096, μ: 13974, ~: 13948) +LibDecimalFloatImplementationAddTest:testAddZeroToAnyNonZero(int256,int256,int256) (runs: 5102, μ: 13974, ~: 13948) LibDecimalFloatImplementationAddTest:testAddingSmallToLargeReturnsLargeExamples() (gas: 92086) -LibDecimalFloatImplementationAddTest:testAddingSmallToLargeReturnsLargeFuzz(int256,int256,int256,int256) (runs: 5096, μ: 16980, ~: 16963) +LibDecimalFloatImplementationAddTest:testAddingSmallToLargeReturnsLargeFuzz(int256,int256,int256,int256) (runs: 5098, μ: 16980, ~: 16963) LibDecimalFloatImplementationAddTest:testGasAddOne() (gas: 1342) LibDecimalFloatImplementationAddTest:testGasAddZero() (gas: 360) -LibDecimalFloatImplementationAddTest:testOverflowChecks(int256,int256) (runs: 5096, μ: 3857, ~: 3843) +LibDecimalFloatImplementationAddTest:testOverflowChecks(int256,int256) (runs: 5104, μ: 3857, ~: 3843) LibDecimalFloatImplementationCharacteristicMantissaTest:testCharacteristicMantissaExamples() (gas: 30611) -LibDecimalFloatImplementationDivTest:testDiv1Over3() (gas: 6627) -LibDecimalFloatImplementationDivTest:testDiv1Over3Gas0() (gas: 1775) -LibDecimalFloatImplementationDivTest:testDiv1Over3Gas10() (gas: 14642) -LibDecimalFloatImplementationDivTest:testDiv1Over9Over1Over3() (gas: 12815) -LibDecimalFloatImplementationDivTest:testDiv1e18Over3() (gas: 6286) -LibDecimalFloatImplementationDivTest:testDivNegative1Over3() (gas: 6741) -LibDecimalFloatImplementationDivTest:testDivOOMs5and2() (gas: 5907) -LibDecimalFloatImplementationDivTest:testDivOOMsOverTen() (gas: 6597) -LibDecimalFloatImplementationDivTest:testDivTenOverOOMs() (gas: 6510) -LibDecimalFloatImplementationDivTest:testUnnormalizedThreesDiv0(int256,int256) (runs: 100, μ: 24587009, ~: 24586663) +LibDecimalFloatImplementationDivTest:testDiv1Over3() (gas: 7083) +LibDecimalFloatImplementationDivTest:testDiv1Over3Gas0() (gas: 2231) +LibDecimalFloatImplementationDivTest:testDiv1Over3Gas10() (gas: 19202) +LibDecimalFloatImplementationDivTest:testDiv1Over9Over1Over3() (gas: 14639) +LibDecimalFloatImplementationDivTest:testDiv1e18Over3() (gas: 6742) +LibDecimalFloatImplementationDivTest:testDivNegative1Over3() (gas: 7176) +LibDecimalFloatImplementationDivTest:testDivOOMs5and2() (gas: 6363) +LibDecimalFloatImplementationDivTest:testDivOOMsOverTen() (gas: 7053) +LibDecimalFloatImplementationDivTest:testDivTenOverOOMs() (gas: 6966) +LibDecimalFloatImplementationDivTest:testUnnormalizedThreesDiv0(int256,int256) (runs: 108, μ: 27290587, ~: 27290219) 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: 5096, μ: 654, ~: 679) -LibDecimalFloatImplementationEqTest:testEqOneEAny(int256,int256) (runs: 5096, μ: 3416, ~: 3416) -LibDecimalFloatImplementationEqTest:testEqReference(int256,int256,int256,int256) (runs: 5096, μ: 9904, ~: 11446) -LibDecimalFloatImplementationEqTest:testEqX(int256) (runs: 5096, μ: 3392, ~: 3392) -LibDecimalFloatImplementationEqTest:testEqXEAnyVsXEAny(int256,int256,int256) (runs: 5096, μ: 4718, ~: 4714) -LibDecimalFloatImplementationEqTest:testEqXEqY(int256,int256,int256,int256) (runs: 5096, μ: 732, ~: 753) -LibDecimalFloatImplementationEqTest:testEqXNotY(int256,int256,int256,int256) (runs: 5096, μ: 3928, ~: 3953) -LibDecimalFloatImplementationEqTest:testEqZero(int256,int256) (runs: 5096, μ: 3440, ~: 3440) -LibDecimalFloatImplementationInvTest:testInvGas0() (gas: 1602) -LibDecimalFloatImplementationInvTest:testInvReference(int256,int256) (runs: 5096, μ: 13646, ~: 13607) -LibDecimalFloatImplementationInvTest:testInvSlowGas0() (gas: 1786) +LibDecimalFloatImplementationEqTest:testEqNotReverts(int256,int256,int256,int256) (runs: 5104, μ: 654, ~: 679) +LibDecimalFloatImplementationEqTest:testEqOneEAny(int256,int256) (runs: 5104, μ: 3416, ~: 3416) +LibDecimalFloatImplementationEqTest:testEqReference(int256,int256,int256,int256) (runs: 5104, μ: 9900, ~: 11437) +LibDecimalFloatImplementationEqTest:testEqX(int256) (runs: 5104, μ: 3392, ~: 3392) +LibDecimalFloatImplementationEqTest:testEqXEAnyVsXEAny(int256,int256,int256) (runs: 5103, μ: 4718, ~: 4714) +LibDecimalFloatImplementationEqTest:testEqXEqY(int256,int256,int256,int256) (runs: 5104, μ: 732, ~: 753) +LibDecimalFloatImplementationEqTest:testEqXNotY(int256,int256,int256,int256) (runs: 5104, μ: 3928, ~: 3953) +LibDecimalFloatImplementationEqTest:testEqZero(int256,int256) (runs: 5104, μ: 3440, ~: 3440) +LibDecimalFloatImplementationInvTest:testInv0() (gas: 5503) +LibDecimalFloatImplementationInvTest:testInvGas0() (gas: 2057) +LibDecimalFloatImplementationInvTest:testInvReference(int256,int256) (runs: 5103, μ: 14535, ~: 14484) +LibDecimalFloatImplementationInvTest:testInvSlowGas0() (gas: 2241) LibDecimalFloatImplementationLog10Test:testExactLogs() (gas: 1263178) LibDecimalFloatImplementationLog10Test:testExactLookupsLog10() (gas: 1280250) -LibDecimalFloatImplementationLog10Test:testInterpolatedLookups() (gas: 1260157) -LibDecimalFloatImplementationLog10Test:testSub1() (gas: 1257848) -LibDecimalFloatImplementationMaximizeTest:testMaximizedEverything(int256,int256) (runs: 5096, μ: 9478, ~: 9455) +LibDecimalFloatImplementationLog10Test:testInterpolatedLookups() (gas: 1260776) +LibDecimalFloatImplementationLog10Test:testSub1() (gas: 1257663) +LibDecimalFloatImplementationMaximizeTest:testMaximizedEverything(int256,int256) (runs: 5104, μ: 9478, ~: 9455) LibDecimalFloatImplementationMaximizeTest:testMaximizedExamples() (gas: 165819) -LibDecimalFloatImplementationMaximizeTest:testMaximizedIdempotent(int256,int256) (runs: 5096, μ: 9904, ~: 9868) -LibDecimalFloatImplementationMinusTest:testMinusIsSubZero(int256,int256,int256) (runs: 5096, μ: 12949, ~: 12929) -LibDecimalFloatImplementationMulTest:testMul123456789987654321() (gas: 3676) -LibDecimalFloatImplementationMulTest:testMul123456789987654321WithExponents(int128,int128) (runs: 5096, μ: 13186, ~: 13270) -LibDecimalFloatImplementationMulTest:testMul1e181e19() (gas: 3720) -LibDecimalFloatImplementationMulTest:testMulGasOne() (gas: 382) -LibDecimalFloatImplementationMulTest:testMulGasZero() (gas: 324) -LibDecimalFloatImplementationMulTest:testMulNotRevertAnyExpectation(int256,int256,int256,int256) (runs: 5096, μ: 13394, ~: 12563) -LibDecimalFloatImplementationMulTest:testMulOneOne() (gas: 3721) -LibDecimalFloatImplementationMulTest:testMulOneZero() (gas: 3663) -LibDecimalFloatImplementationMulTest:testMulZero0Exponent() (gas: 3620) -LibDecimalFloatImplementationMulTest:testMulZeroAnyExponent(int64,int64) (runs: 5096, μ: 3908, ~: 3908) -LibDecimalFloatImplementationMulTest:testMulZeroOne() (gas: 3642) +LibDecimalFloatImplementationMaximizeTest:testMaximizedIdempotent(int256,int256) (runs: 5104, μ: 9903, ~: 9868) +LibDecimalFloatImplementationMaximizeTest:testMaximizedReference(int256,int256) (runs: 5104, μ: 13375, ~: 14263) +LibDecimalFloatImplementationMinusTest:testMinusIsSubZero(int256,int256,int256) (runs: 5104, μ: 12949, ~: 12929) +LibDecimalFloatImplementationMulTest:testMul123456789987654321() (gas: 5559) +LibDecimalFloatImplementationMulTest:testMul123456789987654321WithExponents(int128,int128) (runs: 5104, μ: 15077, ~: 15160) +LibDecimalFloatImplementationMulTest:testMul1_3979_0_5() (gas: 6193) +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: 5104, μ: 15244, ~: 14593) +LibDecimalFloatImplementationMulTest:testMulOneNegativeOne() (gas: 5635) +LibDecimalFloatImplementationMulTest:testMulOneOne() (gas: 5582) +LibDecimalFloatImplementationMulTest:testMulOneZero() (gas: 4481) +LibDecimalFloatImplementationMulTest:testMulZero0Exponent() (gas: 4503) +LibDecimalFloatImplementationMulTest:testMulZeroAnyExponent(int64,int64) (runs: 5104, μ: 4704, ~: 4704) +LibDecimalFloatImplementationMulTest:testMulZeroOne() (gas: 4438) LibDecimalFloatImplementationNormalizeTest:testExamples() (gas: 160899) -LibDecimalFloatImplementationNormalizeTest:testIdempotent(int256,int256) (runs: 5096, μ: 9875, ~: 9808) -LibDecimalFloatImplementationNormalizeTest:testIsNormalizedReference(int256,int256) (runs: 5096, μ: 3533, ~: 3539) -LibDecimalFloatImplementationNormalizeTest:testNormalized(int256,int256) (runs: 5096, μ: 9415, ~: 9348) -LibDecimalFloatImplementationPow10Test:testExactLookupsPow10() (gas: 1282687) +LibDecimalFloatImplementationNormalizeTest:testIdempotent(int256,int256) (runs: 5104, μ: 9875, ~: 9808) +LibDecimalFloatImplementationNormalizeTest:testIsNormalizedReference(int256,int256) (runs: 5104, μ: 3533, ~: 3539) +LibDecimalFloatImplementationNormalizeTest:testNormalized(int256,int256) (runs: 5104, μ: 9415, ~: 9348) +LibDecimalFloatImplementationPow10Test:testExactLookupsPow10() (gas: 1283140) LibDecimalFloatImplementationPow10Test:testExactPows() (gas: 1260107) -LibDecimalFloatImplementationPow10Test:testInterpolatedLookupsPower() (gas: 1283540) -LibDecimalFloatImplementationPow10Test:testNoRevert(int224,int32) (runs: 5096, μ: 1259162, ~: 1259873) -LibDecimalFloatImplementationSubTest:testSubIsAdd(int256,int256,int256,int256) (runs: 5096, μ: 15801, ~: 15834) -LibDecimalFloatImplementationSubTest:testSubMinSignedValue(int256,int256,int256) (runs: 5096, μ: 14990, ~: 14932) +LibDecimalFloatImplementationPow10Test:testInterpolatedLookupsPower() (gas: 1285366) +LibDecimalFloatImplementationPow10Test:testNoRevert(int224,int32) (runs: 5102, μ: 1259276, ~: 1259675) +LibDecimalFloatImplementationSubTest:testSubIsAdd(int256,int256,int256,int256) (runs: 5104, μ: 15802, ~: 15834) +LibDecimalFloatImplementationSubTest:testSubMinSignedValue(int256,int256,int256) (runs: 5104, μ: 14990, ~: 14932) LibDecimalFloatImplementationSubTest:testSubOneFromMax() (gas: 6517) -LibDecimalFloatImplementationSubTest:testSubSelf(int224,int32) (runs: 5096, μ: 5509, ~: 5620) +LibDecimalFloatImplementationSubTest:testSubSelf(int224,int32) (runs: 5104, μ: 5509, ~: 5620) +LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest:testUnabsUnsignedMulOrDivLossyMixedAB(uint256,uint256,uint256,int256) (runs: 5104, μ: 9961, ~: 9888) +LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest:testUnabsUnsignedMulOrDivLossyMixedABOverflow(uint256,uint256,uint256,int256) (runs: 5104, μ: 11207, ~: 11200) +LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest:testUnabsUnsignedMulOrDivLossyMixedBA(uint256,uint256,uint256,int256) (runs: 5104, μ: 11205, ~: 11198) +LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest:testUnabsUnsignedMulOrDivLossyMixedBAOverflow(uint256,uint256,int256) (runs: 5104, μ: 9070, ~: 9018) +LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest:testUnabsUnsignedMulOrDivLossyNegative(uint256,uint256,uint256,int256) (runs: 5104, μ: 9968, ~: 9892) +LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest:testUnabsUnsignedMulOrDivLossyNegativeOverflow(uint256,uint256,uint256,int256) (runs: 5104, μ: 11200, ~: 11190) +LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest:testUnabsUnsignedMulOrDivLossyPositive(uint256,uint256,uint256,int256) (runs: 5104, μ: 9102, ~: 9033) +LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest:testUnabsUnsignedMulOrDivLossyPositiveOverflow(uint256,uint256,uint256,int256) (runs: 5104, μ: 11089, ~: 11086) LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentExamples() (gas: 13429) -LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentLargerExponentOverflowRescaleRevert(int256,int256,int256) (runs: 5096, μ: 14426, ~: 14395) -LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentLargerExponentVeryLargeDiffRevert(int256,int256,int256) (runs: 5096, μ: 13307, ~: 13527) -LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentLargerTargetExponentNoRevert(int256,int256,int256) (runs: 5096, μ: 11669, ~: 11718) -LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentSameExponentNoop(int256,int256) (runs: 5096, μ: 3676, ~: 3676) -LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentSmallerExponentNoRevert(int256,int256,int256) (runs: 5096, μ: 13874, ~: 13665) -LibDecimalFloatInvTest:testInvMem(bytes32) (runs: 5096, μ: 9679, ~: 9738) -LibDecimalFloatIsZeroTest:testIsZeroDeployed(bytes32) (runs: 5096, μ: 3899, ~: 3899) -LibDecimalFloatIsZeroTest:testIsZeroEqZero(bytes32) (runs: 5096, μ: 3527, ~: 3527) -LibDecimalFloatIsZeroTest:testIsZeroExamples(int32) (runs: 5096, μ: 4477, ~: 4477) -LibDecimalFloatIsZeroTest:testNotIsZero(int224,int32) (runs: 5096, μ: 3896, ~: 3896) -LibDecimalFloatLog10Test:testLog10Packed(bytes32) (runs: 5096, μ: 1650742, ~: 1270777) +LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentLargerExponentOverflowRescaleRevert(int256,int256,int256) (runs: 5099, μ: 14426, ~: 14395) +LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentLargerExponentVeryLargeDiffRevert(int256,int256,int256) (runs: 5104, μ: 13307, ~: 13527) +LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentLargerTargetExponentNoRevert(int256,int256,int256) (runs: 5104, μ: 11669, ~: 11718) +LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentSameExponentNoop(int256,int256) (runs: 5104, μ: 3676, ~: 3676) +LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentSmallerExponentNoRevert(int256,int256,int256) (runs: 5101, μ: 13874, ~: 13665) +LibDecimalFloatInvTest:testInvMem(bytes32) (runs: 5104, μ: 10557, ~: 10616) +LibDecimalFloatIsZeroTest:testIsZeroDeployed(bytes32) (runs: 5104, μ: 3899, ~: 3899) +LibDecimalFloatIsZeroTest:testIsZeroEqZero(bytes32) (runs: 5104, μ: 3527, ~: 3527) +LibDecimalFloatIsZeroTest:testIsZeroExamples(int32) (runs: 5104, μ: 4477, ~: 4477) +LibDecimalFloatIsZeroTest:testNotIsZero(int224,int32) (runs: 5103, μ: 3896, ~: 3896) +LibDecimalFloatLog10Test:testLog10Packed(bytes32) (runs: 5104, μ: 1651924, ~: 1271911) LibDecimalFloatLtTest:testLtExamples() (gas: 3994) LibDecimalFloatLtTest:testLtGasAZero() (gas: 946) LibDecimalFloatLtTest:testLtGasBZero() (gas: 1012) LibDecimalFloatLtTest:testLtGasBothZero() (gas: 969) LibDecimalFloatLtTest:testLtGasDifferentSigns() (gas: 969) LibDecimalFloatLtTest:testLtGasExponentDiffOverflow() (gas: 1053) -LibDecimalFloatLtTest:testLtNegativeVsPositive(int256,int32,int256,int32) (runs: 5096, μ: 13750, ~: 13593) -LibDecimalFloatLtTest:testLtNegativeVsZero(int256,int32,int32) (runs: 5096, μ: 10790, ~: 11008) -LibDecimalFloatLtTest:testLtOneEAny(int224,int32) (runs: 5096, μ: 3905, ~: 3905) -LibDecimalFloatLtTest:testLtReference(bytes32,bytes32) (runs: 5096, μ: 4697, ~: 4998) -LibDecimalFloatLtTest:testLtVsEqualVsGt(bytes32,bytes32) (runs: 5096, μ: 4323, ~: 4210) -LibDecimalFloatLtTest:testLtX(int224) (runs: 5096, μ: 3798, ~: 3798) -LibDecimalFloatLtTest:testLtXEAnyVsXEAny(int256,int32,int32) (runs: 5096, μ: 10557, ~: 10297) -LibDecimalFloatLtTest:testLtXEAnyVsXEAnyNegative(int256,int32,int32) (runs: 5096, μ: 11153, ~: 11359) -LibDecimalFloatLtTest:testLtZero(int32,int32) (runs: 5096, μ: 4171, ~: 4171) +LibDecimalFloatLtTest:testLtNegativeVsPositive(int256,int32,int256,int32) (runs: 5104, μ: 13750, ~: 13593) +LibDecimalFloatLtTest:testLtNegativeVsZero(int256,int32,int32) (runs: 5104, μ: 10790, ~: 11008) +LibDecimalFloatLtTest:testLtOneEAny(int224,int32) (runs: 5104, μ: 3905, ~: 3905) +LibDecimalFloatLtTest:testLtReference(bytes32,bytes32) (runs: 5104, μ: 4697, ~: 4998) +LibDecimalFloatLtTest:testLtVsEqualVsGt(bytes32,bytes32) (runs: 5104, μ: 4323, ~: 4210) +LibDecimalFloatLtTest:testLtX(int224) (runs: 5104, μ: 3798, ~: 3798) +LibDecimalFloatLtTest:testLtXEAnyVsXEAny(int256,int32,int32) (runs: 5104, μ: 10558, ~: 10297) +LibDecimalFloatLtTest:testLtXEAnyVsXEAnyNegative(int256,int32,int32) (runs: 5104, μ: 11154, ~: 11359) +LibDecimalFloatLtTest:testLtZero(int32,int32) (runs: 5104, μ: 4171, ~: 4171) LibDecimalFloatLteTest:testLteGasAZero() (gas: 997) LibDecimalFloatLteTest:testLteGasBZero() (gas: 999) LibDecimalFloatLteTest:testLteGasBothZero() (gas: 753) LibDecimalFloatLteTest:testLteGasDifferentSigns() (gas: 976) LibDecimalFloatLteTest:testLteGasExponentDiffOverflow() (gas: 1082) -LibDecimalFloatLteTest:testLteOneEAny(bytes32) (runs: 5096, μ: 3493, ~: 3493) -LibDecimalFloatLteTest:testLteReference(int224,int32,int224,int32) (runs: 5096, μ: 8112, ~: 6341) -LibDecimalFloatLteTest:testLteX(int224,int32) (runs: 5096, μ: 3904, ~: 3904) -LibDecimalFloatLteTest:testLteXEAnyVsXEAny(int256,int32,int32) (runs: 5096, μ: 10582, ~: 10321) -LibDecimalFloatLteTest:testLteXEAnyVsXEAnyNegative(int256,int32,int32) (runs: 5096, μ: 11177, ~: 11383) -LibDecimalFloatLteTest:testLteXNotLtY(bytes32,bytes32) (runs: 5096, μ: 3882, ~: 3807) -LibDecimalFloatLteTest:testLteXPositiveYNegative(int256,int32,int256,int32) (runs: 5096, μ: 13103, ~: 12931) -LibDecimalFloatLteTest:testLteXPositiveYZero(int256,int32,int32) (runs: 5096, μ: 9575, ~: 9191) -LibDecimalFloatLteTest:testLteZero(int32,int32) (runs: 5096, μ: 4816, ~: 4816) -LibDecimalFloatMaxTest:testMaxX(bytes32) (runs: 5096, μ: 4246, ~: 4246) -LibDecimalFloatMaxTest:testMaxXY(bytes32,bytes32) (runs: 5096, μ: 4689, ~: 4613) -LibDecimalFloatMaxTest:testMaxXYEqual(bytes32) (runs: 5096, μ: 5272, ~: 5272) +LibDecimalFloatLteTest:testLteOneEAny(bytes32) (runs: 5104, μ: 3493, ~: 3493) +LibDecimalFloatLteTest:testLteReference(int224,int32,int224,int32) (runs: 5104, μ: 8112, ~: 6328) +LibDecimalFloatLteTest:testLteX(int224,int32) (runs: 5104, μ: 3904, ~: 3904) +LibDecimalFloatLteTest:testLteXEAnyVsXEAny(int256,int32,int32) (runs: 5104, μ: 10582, ~: 10321) +LibDecimalFloatLteTest:testLteXEAnyVsXEAnyNegative(int256,int32,int32) (runs: 5104, μ: 11177, ~: 11383) +LibDecimalFloatLteTest:testLteXNotLtY(bytes32,bytes32) (runs: 5104, μ: 3882, ~: 3807) +LibDecimalFloatLteTest:testLteXPositiveYNegative(int256,int32,int256,int32) (runs: 5104, μ: 13102, ~: 12931) +LibDecimalFloatLteTest:testLteXPositiveYZero(int256,int32,int32) (runs: 5104, μ: 9575, ~: 9191) +LibDecimalFloatLteTest:testLteZero(int32,int32) (runs: 5104, μ: 4816, ~: 4816) +LibDecimalFloatMaxTest:testMaxX(bytes32) (runs: 5104, μ: 4246, ~: 4246) +LibDecimalFloatMaxTest:testMaxXY(bytes32,bytes32) (runs: 5104, μ: 4689, ~: 4613) +LibDecimalFloatMaxTest:testMaxXYEqual(bytes32) (runs: 5104, μ: 5272, ~: 5272) LibDecimalFloatMaxTest:testMaxXYGreater(bytes32,bytes32) (runs: 5096, μ: 6129, ~: 6016) -LibDecimalFloatMaxTest:testMaxXYLess(bytes32,bytes32) (runs: 5096, μ: 6141, ~: 6027) -LibDecimalFloatMinTest:testMinX(bytes32) (runs: 5096, μ: 4268, ~: 4268) -LibDecimalFloatMinTest:testMinXY(bytes32,bytes32) (runs: 5096, μ: 4689, ~: 4613) -LibDecimalFloatMinTest:testMinXYEqual(bytes32) (runs: 5096, μ: 5292, ~: 5292) +LibDecimalFloatMaxTest:testMaxXYLess(bytes32,bytes32) (runs: 5104, μ: 6141, ~: 6027) +LibDecimalFloatMinTest:testMinX(bytes32) (runs: 5104, μ: 4268, ~: 4268) +LibDecimalFloatMinTest:testMinXY(bytes32,bytes32) (runs: 5104, μ: 4689, ~: 4613) +LibDecimalFloatMinTest:testMinXYEqual(bytes32) (runs: 5104, μ: 5292, ~: 5292) LibDecimalFloatMinTest:testMinXYGreater(bytes32,bytes32) (runs: 5096, μ: 6074, ~: 5961) -LibDecimalFloatMinTest:testMinXYLess(bytes32,bytes32) (runs: 5096, μ: 6087, ~: 5972) -LibDecimalFloatMinusTest:testMinusPacked(bytes32) (runs: 5096, μ: 5550, ~: 5550) -LibDecimalFloatMixedTest:testDiv1Over3Mixed() (gas: 9518) -LibDecimalFloatMulTest:testMulPacked(bytes32,bytes32) (runs: 5096, μ: 7890, ~: 8837) -LibDecimalFloatPackTest:testPartsRoundTrip(int224,int32) (runs: 5096, μ: 5352, ~: 5352) -LibDecimalFloatPow10Test:testPow10Packed(bytes32) (runs: 5096, μ: 1644472, ~: 1258201) -LibDecimalFloatPowTest:testNegativePowError(bytes32,bytes32) (runs: 5096, μ: 1248480, ~: 1248447) -LibDecimalFloatPowTest:testPowAZero(int32,bytes32) (runs: 5096, μ: 1246471, ~: 1246471) -LibDecimalFloatPowTest:testPowAZeroNegative(bytes32) (runs: 5096, μ: 1246870, ~: 1246870) -LibDecimalFloatPowTest:testPowBZero(bytes32,int32) (runs: 5096, μ: 1246058, ~: 1246058) -LibDecimalFloatPowTest:testPows() (gas: 1312147) -LibDecimalFloatPowTest:testRoundTripFuzzPow(bytes32,bytes32) (runs: 5096, μ: 1261462, ~: 1258766) -LibDecimalFloatPowTest:testRoundTripSimple() (gas: 1508171) -LibDecimalFloatSqrtTest:testRoundTripFuzzSqrt(int224,int32) (runs: 5096, μ: 1293364, ~: 1293233) -LibDecimalFloatSqrtTest:testSqrt() (gas: 1292895) -LibDecimalFloatSqrtTest:testSqrtNegative(bytes32) (runs: 5096, μ: 1248099, ~: 1248059) -LibDecimalFloatSqrtTest:testSqrtRoundTrip() (gas: 1400101) -LibDecimalFloatSubTest:testSubPacked(bytes32,bytes32) (runs: 5096, μ: 9974, ~: 9995) +LibDecimalFloatMinTest:testMinXYLess(bytes32,bytes32) (runs: 5104, μ: 6087, ~: 5972) +LibDecimalFloatMinusTest:testMinusPacked(bytes32) (runs: 5104, μ: 5550, ~: 5550) +LibDecimalFloatMixedTest:testDiv1Over3Mixed() (gas: 11039) +LibDecimalFloatMulTest:testMulPacked(bytes32,bytes32) (runs: 5104, μ: 9630, ~: 10369) +LibDecimalFloatPackTest:testPartsRoundTrip(int224,int32) (runs: 5104, μ: 5352, ~: 5352) +LibDecimalFloatPow10Test:testPow10Packed(bytes32) (runs: 5104, μ: 1645674, ~: 1256407) +LibDecimalFloatPowTest:testNegativePowError(bytes32,bytes32) (runs: 5104, μ: 1248482, ~: 1248447) +LibDecimalFloatPowTest:testPowAZero(int32,bytes32) (runs: 5099, μ: 1246471, ~: 1246471) +LibDecimalFloatPowTest:testPowAZeroNegative(bytes32) (runs: 5101, μ: 1246870, ~: 1246870) +LibDecimalFloatPowTest:testPowBZero(bytes32,int32) (runs: 5104, μ: 1246058, ~: 1246058) +LibDecimalFloatPowTest:testPows() (gas: 1315564) +LibDecimalFloatPowTest:testRoundTripFuzzPow(bytes32,bytes32) (runs: 5104, μ: 1262566, ~: 1260242) +LibDecimalFloatPowTest:testRoundTripSimple() (gas: 1535140) +LibDecimalFloatSqrtTest:testRoundTripFuzzSqrt(int224,int32) (runs: 5104, μ: 1295391, ~: 1294787) +LibDecimalFloatSqrtTest:testSqrt() (gas: 1293719) +LibDecimalFloatSqrtTest:testSqrtNegative(bytes32) (runs: 5104, μ: 1248098, ~: 1248059) +LibDecimalFloatSqrtTest:testSqrtRoundTrip() (gas: 1417956) +LibDecimalFloatSubTest:testSubPacked(bytes32,bytes32) (runs: 5104, μ: 9974, ~: 9995) LibFormatDecimalFloatTest:testFormatDecimalExamples() (gas: 133439) -LibFormatDecimalFloatTest:testFormatDecimalRoundTrip(uint256) (runs: 5096, μ: 25219, ~: 20105) -LibFormatDecimalFloatTest:testFormatDecimalRoundTripNegative(int256) (runs: 5096, μ: 19679, ~: 21006) +LibFormatDecimalFloatTest:testFormatDecimalRoundTrip(uint256) (runs: 5104, μ: 25221, ~: 20105) +LibFormatDecimalFloatTest:testFormatDecimalRoundTripNegative(int256) (runs: 5104, μ: 19680, ~: 21006) LibLogTableBytesTest:testToBytesAntiLogTableDec() (gas: 159794) LibLogTableBytesTest:testToBytesAntiLogTableDecSmall() (gas: 162322) LibLogTableBytesTest:testToBytesLogTableDec() (gas: 143165) @@ -293,7 +308,7 @@ LibParseDecimalFloatTest:testParseLiteralDecimalFloatEDot() (gas: 4190) LibParseDecimalFloatTest:testParseLiteralDecimalFloatExponentRevert5() (gas: 4176) LibParseDecimalFloatTest:testParseLiteralDecimalFloatExponentRevert6() (gas: 4188) LibParseDecimalFloatTest:testParseLiteralDecimalFloatExponents() (gas: 402635) -LibParseDecimalFloatTest:testParseLiteralDecimalFloatFuzz(uint256,uint8,bool) (runs: 5096, μ: 45910, ~: 37386) +LibParseDecimalFloatTest:testParseLiteralDecimalFloatFuzz(uint256,uint8,bool) (runs: 5104, μ: 45895, ~: 37386) LibParseDecimalFloatTest:testParseLiteralDecimalFloatLeadingZeros() (gas: 59779) LibParseDecimalFloatTest:testParseLiteralDecimalFloatNegativeE() (gas: 6100) LibParseDecimalFloatTest:testParseLiteralDecimalFloatNegativeFrac() (gas: 5137) @@ -301,5 +316,5 @@ LibParseDecimalFloatTest:testParseLiteralDecimalFloatPrecisionRevert0() (gas: 27 LibParseDecimalFloatTest:testParseLiteralDecimalFloatPrecisionRevert1() (gas: 24801) LibParseDecimalFloatTest:testParseLiteralDecimalFloatSpecific() (gas: 22959) LibParseDecimalFloatTest:testParseLiteralDecimalFloatUnrelated() (gas: 50856) -LibParseDecimalFloatTest:testParsePacked(string) (runs: 5096, μ: 9787, ~: 9668) -TestDecimalFloatUnpackTest:testUnpackDeployed(bytes32) (runs: 5096, μ: 158422, ~: 158422) \ No newline at end of file +LibParseDecimalFloatTest:testParsePacked(string) (runs: 5104, μ: 9786, ~: 9668) +TestDecimalFloatUnpackTest:testUnpackDeployed(bytes32) (runs: 5104, μ: 158422, ~: 158422) \ No newline at end of file diff --git a/src/lib/implementation/LibDecimalFloatImplementation.sol b/src/lib/implementation/LibDecimalFloatImplementation.sol index b0cd5c74..b385f97e 100644 --- a/src/lib/implementation/LibDecimalFloatImplementation.sol +++ b/src/lib/implementation/LibDecimalFloatImplementation.sol @@ -94,42 +94,106 @@ library LibDecimalFloatImplementation { } } - /// Stack only implementation of `mul`. - function mul(int256 signedCoefficientA, int256 exponentA, int256 signedCoefficientB, int256 exponentB) + function absUnsignedSignedCoefficient(int256 signedCoefficient) internal pure returns (uint256) { + unchecked { + if (signedCoefficient < 0) { + if (signedCoefficient == type(int256).min) { + return uint256(type(int256).max) + 1; + } else { + return uint256(-signedCoefficient); + } + } else { + return uint256(signedCoefficient); + } + } + } + + function unabsUnsignedMulOrDivLossy(int256 a, int256 b, uint256 signedCoefficientAbs, int256 exponent) internal pure returns (int256, int256) { unchecked { - // Unchecked mul the coefficients and add the exponents. - int256 signedCoefficient = signedCoefficientA * signedCoefficientB; - - // Need to return early if the result is zero to avoid divide by - // zero in the overflow check. - if (signedCoefficient == 0) { - return (NORMALIZED_ZERO_SIGNED_COEFFICIENT, NORMALIZED_ZERO_EXPONENT); + // 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); + } + } else { + return (-int256(signedCoefficientAbs), exponent); + } + } else { + if (signedCoefficientAbs > uint256(type(int256).max)) { + return (int256(signedCoefficientAbs / 10), exponent + 1); + } else { + return (int256(signedCoefficientAbs), exponent); + } } + } + } - int256 exponent = exponentA + exponentB; + /// Stack only implementation of `mul`. + function mul(int256 signedCoefficientA, int256 exponentA, int256 signedCoefficientB, int256 exponentB) + internal + pure + returns (int256 signedCoefficient, int256 exponent) + { + bool isZero; + assembly ("memory-safe") { + isZero := or(iszero(signedCoefficientA), iszero(signedCoefficientB)) + } + if (isZero) { + // These sets are redundant as both are zero but this makes it + // clearer and more explicit. + signedCoefficient = MAXIMIZED_ZERO_SIGNED_COEFFICIENT; + exponent = MAXIMIZED_ZERO_EXPONENT; + } else { + exponent = exponentA + exponentB; - // No jumps to see if we overflowed. - bool didOverflow; - assembly ("memory-safe") { - didOverflow := - or( - iszero(eq(sdiv(signedCoefficient, signedCoefficientA), signedCoefficientB)), - iszero(eq(sub(exponent, exponentA), exponentB)) - ) - } - // If we did overflow, normalize and try again. Normalized values - // cannot overflow, so this will always succeed, provided the - // exponents are not out of bounds. - if (didOverflow) { - (signedCoefficientA, exponentA) = normalize(signedCoefficientA, exponentA); - (signedCoefficientB, exponentB) = normalize(signedCoefficientB, exponentB); - return mul(signedCoefficientA, exponentA, signedCoefficientB, exponentB); + // mulDiv only works with unsigned integers, so get the absolute + // values of the coefficients. + uint256 signedCoefficientAAbs = absUnsignedSignedCoefficient(signedCoefficientA); + uint256 signedCoefficientBAbs = absUnsignedSignedCoefficient(signedCoefficientB); + + (uint256 prod1,) = mul512(signedCoefficientAAbs, signedCoefficientBAbs); + + uint256 adjustExponent = 0; + unchecked { + if (prod1 > 1e37) { + prod1 /= 1e37; + adjustExponent += 37; + } + if (prod1 > 1e18) { + prod1 /= 1e18; + adjustExponent += 18; + } + if (prod1 > 1e9) { + prod1 /= 1e9; + adjustExponent += 9; + } + if (prod1 > 1e4) { + prod1 /= 1e4; + adjustExponent += 4; + } + while (prod1 > 0) { + prod1 /= 10; + adjustExponent++; + } } - return (signedCoefficient, exponent); + + exponent += int256(adjustExponent); + + (signedCoefficient, exponent) = unabsUnsignedMulOrDivLossy( + signedCoefficientA, + signedCoefficientB, + mulDiv(signedCoefficientAAbs, signedCoefficientBAbs, uint256(10) ** adjustExponent), + exponent + ); } } @@ -186,13 +250,12 @@ library LibDecimalFloatImplementation { function div(int256 signedCoefficientA, int256 exponentA, int256 signedCoefficientB, int256 exponentB) internal pure - returns (int256, int256) + returns (int256 signedCoefficient, int256 exponent) { - uint256 scale = 1e76; - int256 adjustExponent = 76; - int256 signedCoefficient; - - unchecked { + if (signedCoefficientA == 0) { + signedCoefficient = MAXIMIZED_ZERO_SIGNED_COEFFICIENT; + exponent = MAXIMIZED_ZERO_EXPONENT; + } else { // Move both coefficients into the e75/e76 range, so that the result // of division will not cause a mulDiv overflow. (signedCoefficientA, exponentA) = maximize(signedCoefficientA, exponentA); @@ -200,28 +263,11 @@ library LibDecimalFloatImplementation { // mulDiv only works with unsigned integers, so get the absolute // values of the coefficients. - uint256 signedCoefficientAAbs; - if (signedCoefficientA > 0) { - signedCoefficientAAbs = uint256(signedCoefficientA); - } else if (signedCoefficientA < 0) { - if (signedCoefficientA == type(int256).min) { - signedCoefficientAAbs = uint256(type(int256).max) + 1; - } else { - signedCoefficientAAbs = uint256(-signedCoefficientA); - } - } else { - return (MAXIMIZED_ZERO_SIGNED_COEFFICIENT, MAXIMIZED_ZERO_EXPONENT); - } - uint256 signedCoefficientBAbs; - if (signedCoefficientB < 0) { - if (signedCoefficientB == type(int256).min) { - signedCoefficientBAbs = uint256(type(int256).max) + 1; - } else { - signedCoefficientBAbs = uint256(-signedCoefficientB); - } - } else { - signedCoefficientBAbs = uint256(signedCoefficientB); - } + uint256 signedCoefficientAAbs = absUnsignedSignedCoefficient(signedCoefficientA); + uint256 signedCoefficientBAbs = absUnsignedSignedCoefficient(signedCoefficientB); + + uint256 scale = 1e76; + int256 adjustExponent = 76; // We are going to scale the numerator up by the largest power of ten // that is smaller than the denominator. This will always overflow @@ -233,31 +279,35 @@ library LibDecimalFloatImplementation { scale = 1e75; adjustExponent = 75; } - uint256 signedCoefficientAbs = mulDiv(signedCoefficientAAbs, scale, signedCoefficientBAbs); - signedCoefficient = (signedCoefficientA ^ signedCoefficientB) < 0 - ? -int256(signedCoefficientAbs) - : int256(signedCoefficientAbs); + exponent = exponentA - exponentB - adjustExponent; + + (signedCoefficient, exponent) = unabsUnsignedMulOrDivLossy( + signedCoefficientA, + signedCoefficientB, + mulDiv(signedCoefficientAAbs, scale, signedCoefficientBAbs), + exponent + ); } + } - // Keep the exponent calculation outside the unchecked block so that we - // don't silently under/overflow. - int256 exponent = exponentA - exponentB - adjustExponent; - return (signedCoefficient, exponent); + /// mul512 from Open Zeppelin. + /// Simply part of the original mulDiv function abstracted out for reuse + /// elsewhere. + function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) { + // 512-bit multiply [high low] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use + // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 + // variables such that product = high * 2²⁵⁶ + low. + assembly ("memory-safe") { + let mm := mulmod(a, b, not(0)) + low := mul(a, b) + high := sub(sub(mm, low), lt(mm, low)) + } } /// mulDiv as seen in Open Zeppelin, PRB Math, Solady, and other libraries. /// Credit to Remco Bloemen under MIT license: https://2π.com/21/muldiv function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { - // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use - // use the Chinese Remainder Theorem to reconstruct the 512-bit result. The result is stored in two 256 - // variables such that product = prod1 * 2^256 + prod0. - uint256 prod0; // Least significant 256 bits of the product - uint256 prod1; // Most significant 256 bits of the product - assembly ("memory-safe") { - let mm := mulmod(x, y, not(0)) - prod0 := mul(x, y) - prod1 := sub(sub(mm, prod0), lt(mm, prod0)) - } + (uint256 prod1, uint256 prod0) = mul512(x, y); // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { diff --git a/test/lib/LibDecimalFloatSlow.sol b/test/lib/LibDecimalFloatSlow.sol index 987eb223..03fcdb63 100644 --- a/test/lib/LibDecimalFloatSlow.sol +++ b/test/lib/LibDecimalFloatSlow.sol @@ -13,29 +13,37 @@ library LibDecimalFloatSlow { returns (int256, int256) { unchecked { - int256 signedCoefficient = signedCoefficientA * signedCoefficientB; - int256 exponent = exponentA + exponentB; - // If the expected signed coefficient is 0 then everything is just // normalized 0. - if (signedCoefficient == 0) { + if (signedCoefficientA == 0 || signedCoefficientB == 0) { return (0, 0); } - // If nothing overflowed then our expected outcome is correct. - else if (signedCoefficient / signedCoefficientA == signedCoefficientB && exponent - exponentA == exponentB) - { - return (signedCoefficient, exponent); - } - // If something overflowed then we have to normalize and try again. - else { - (signedCoefficientA, exponentA) = LibDecimalFloatImplementation.normalize(signedCoefficientA, exponentA); - (signedCoefficientB, exponentB) = LibDecimalFloatImplementation.normalize(signedCoefficientB, exponentB); - signedCoefficient = signedCoefficientA * signedCoefficientB; - exponent = exponentA + exponentB; + int256 exponent = exponentA + exponentB; - return (signedCoefficient, exponent); + uint256 signedCoefficientAAbs = + LibDecimalFloatImplementation.absUnsignedSignedCoefficient(signedCoefficientA); + uint256 signedCoefficientBAbs = + LibDecimalFloatImplementation.absUnsignedSignedCoefficient(signedCoefficientB); + + (uint256 prod1,) = LibDecimalFloatImplementation.mul512(signedCoefficientAAbs, signedCoefficientBAbs); + + uint256 adjustExponent = 0; + while (prod1 > 0) { + prod1 /= 10; + adjustExponent++; } + + uint256 signedCoefficientAbs = LibDecimalFloatImplementation.mulDiv( + signedCoefficientAAbs, signedCoefficientBAbs, uint256(10) ** adjustExponent + ); + + exponent += int256(adjustExponent); + int256 signedCoefficient; + (signedCoefficient, exponent) = LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy( + signedCoefficientA, signedCoefficientB, signedCoefficientAbs, exponent + ); + return (signedCoefficient, exponent); } } @@ -183,4 +191,19 @@ library LibDecimalFloatSlow { return ltSlow(signedCoefficientA, exponentA, signedCoefficientB, exponentB); } + + function maximizeSlow(int256 signedCoefficient, int256 exponent) internal pure returns (int256, int256) { + unchecked { + if (signedCoefficient == 0) { + return (0, 0); + } + int256 trySignedCoefficient = signedCoefficient * 10; + while (trySignedCoefficient / 10 == signedCoefficient) { + signedCoefficient = trySignedCoefficient; + exponent--; + trySignedCoefficient *= 10; + } + return (signedCoefficient, exponent); + } + } } diff --git a/test/src/lib/LibDecimalFloat.pow.t.sol b/test/src/lib/LibDecimalFloat.pow.t.sol index 4f356254..501a1bd0 100644 --- a/test/src/lib/LibDecimalFloat.pow.t.sol +++ b/test/src/lib/LibDecimalFloat.pow.t.sol @@ -47,6 +47,8 @@ contract LibDecimalFloatPowTest is LogTest { 5e37, -38, 6e37, -36, 8.710801393728222996515679442508710801393728222996515679442508710801e66, -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); } diff --git a/test/src/lib/implementation/LibDecimalFloatImplementation.maximize.t.sol b/test/src/lib/implementation/LibDecimalFloatImplementation.maximize.t.sol index 624d3a7f..2c3fc6c9 100644 --- a/test/src/lib/implementation/LibDecimalFloatImplementation.maximize.t.sol +++ b/test/src/lib/implementation/LibDecimalFloatImplementation.maximize.t.sol @@ -10,6 +10,7 @@ import { MAXIMIZED_ZERO_EXPONENT, MAXIMIZED_ZERO_SIGNED_COEFFICIENT } from "src/lib/implementation/LibDecimalFloatImplementation.sol"; +import {LibDecimalFloatSlow} from "test/lib/LibDecimalFloatSlow.sol"; contract LibDecimalFloatImplementationMaximizeTest is Test { function isMaximized(int256 signedCoefficient, int256 exponent) internal pure returns (bool) { @@ -79,4 +80,15 @@ contract LibDecimalFloatImplementationMaximizeTest is Test { assertEq(actualSignedCoefficient, maximizedSignedCoefficient); assertEq(actualExponent, maximizedExponent); } + + /// Maximization against reference. + function testMaximizedReference(int256 signedCoefficient, int256 exponent) external pure { + exponent = bound(exponent, EXPONENT_MIN, EXPONENT_MAX); + (int256 actualSignedCoefficient, int256 actualExponent) = + LibDecimalFloatImplementation.maximize(signedCoefficient, exponent); + (int256 expectedSignedCoefficient, int256 expectedExponent) = + LibDecimalFloatSlow.maximizeSlow(signedCoefficient, exponent); + assertEq(actualSignedCoefficient, expectedSignedCoefficient); + assertEq(actualExponent, expectedExponent); + } } diff --git a/test/src/lib/implementation/LibDecimalFloatImplementation.mul.t.sol b/test/src/lib/implementation/LibDecimalFloatImplementation.mul.t.sol index d3461511..4a90624f 100644 --- a/test/src/lib/implementation/LibDecimalFloatImplementation.mul.t.sol +++ b/test/src/lib/implementation/LibDecimalFloatImplementation.mul.t.sol @@ -12,52 +12,86 @@ import {Test} from "forge-std/Test.sol"; import {LibDecimalFloatSlow} from "test/lib/LibDecimalFloatSlow.sol"; contract LibDecimalFloatImplementationMulTest is Test { + function checkMul( + int256 signedCoefficientA, + int256 exponentA, + int256 signedCoefficientB, + int256 exponentB, + int256 expectedSignedCoefficient, + int256 expectedExponent + ) internal pure { + (int256 actualSignedCoefficient, int256 actualExponent) = + LibDecimalFloatImplementation.mul(signedCoefficientA, exponentA, signedCoefficientB, exponentB); + assertEq(actualSignedCoefficient, expectedSignedCoefficient, "signedCoefficient"); + assertEq(actualExponent, expectedExponent, "exponent"); + } + + /// -1 * -1 = 1 + function testMulNegativeOne() external pure { + checkMul(-1, 0, -1, 0, 1, 0); + } + + /// -1 * 1 = -1 + function testMulNegativeOneOne() external pure { + checkMul(-1, 0, 1, 0, -1, 0); + } + + /// 1 * -1 = -1 + function testMulOneNegativeOne() external pure { + checkMul(1, 0, -1, 0, -1, 0); + } + + /// found during testing + /// 1.3979 * 0.5 = 0.69895 + function testMul1_3979_0_5() external pure { + checkMul(1.3979e76, -76, 0.5e66, -66, 0.69895e76, -76); + } + /// Simple 0 multiply 0 /// 0 * 0 = 0 function testMulZero0Exponent() external pure { - (int256 signedCoefficient, int256 exponent) = LibDecimalFloatImplementation.mul(0, 0, 0, 0); - assertEq(signedCoefficient, NORMALIZED_ZERO_SIGNED_COEFFICIENT); - assertEq(exponent, NORMALIZED_ZERO_EXPONENT); + checkMul(0, 0, 0, 0, 0, 0); } /// 0 multiply 0 any exponent /// 0 * 0 = 0 function testMulZeroAnyExponent(int64 exponentA, int64 exponentB) external pure { - (int256 signedCoefficient, int256 exponent) = LibDecimalFloatImplementation.mul(0, exponentA, 0, exponentB); - assertEq(signedCoefficient, NORMALIZED_ZERO_SIGNED_COEFFICIENT); - assertEq(exponent, NORMALIZED_ZERO_EXPONENT); + checkMul(0, exponentA, 0, exponentB, 0, 0); } /// 0 multiply 1 /// 0 * 1 = 0 function testMulZeroOne() external pure { - (int256 signedCoefficient, int256 exponent) = LibDecimalFloatImplementation.mul(0, 0, 1, 0); - assertEq(signedCoefficient, NORMALIZED_ZERO_SIGNED_COEFFICIENT); - assertEq(exponent, NORMALIZED_ZERO_EXPONENT); + checkMul(0, 0, 1, 0, 0, 0); } /// 1 multiply 0 /// 1 * 0 = 0 function testMulOneZero() external pure { - (int256 signedCoefficient, int256 exponent) = LibDecimalFloatImplementation.mul(1, 0, 0, 0); - assertEq(signedCoefficient, NORMALIZED_ZERO_SIGNED_COEFFICIENT); - assertEq(exponent, NORMALIZED_ZERO_EXPONENT); + checkMul(1, 0, 0, 0, 0, 0); } /// 1 multiply 1 /// 1 * 1 = 1 function testMulOneOne() external pure { - (int256 signedCoefficient, int256 exponent) = LibDecimalFloatImplementation.mul(1, 0, 1, 0); - assertEq(signedCoefficient, 1); - assertEq(exponent, 0); + checkMul(1, 0, 1, 0, 1, 0); } /// 123456789 multiply 987654321 /// 123456789 * 987654321 = 121932631112635269 function testMul123456789987654321() external pure { - (int256 signedCoefficient, int256 exponent) = LibDecimalFloatImplementation.mul(123456789, 0, 987654321, 0); - assertEq(signedCoefficient, 121932631112635269); - assertEq(exponent, 0); + checkMul(123456789, 0, 987654321, 0, 121932631112635269, 0); + } + + function testMulMaxSignedCoefficient() external pure { + checkMul( + type(int256).max, + 0, + type(int256).max, + 0, + int256(3.3519519824856492748935062495514615318698414551480983444308903609304410075182e76), + 77 + ); } /// 123456789 multiply 987654321 with exponents @@ -66,17 +100,12 @@ contract LibDecimalFloatImplementationMulTest is Test { exponentA = int128(bound(exponentA, -127, 127)); exponentB = int128(bound(exponentB, -127, 127)); - (int256 signedCoefficient, int256 exponent) = - LibDecimalFloatImplementation.mul(123456789, exponentA, 987654321, exponentB); - assertEq(signedCoefficient, 121932631112635269); - assertEq(exponent, exponentA + exponentB); + checkMul(123456789, exponentA, 987654321, exponentB, 121932631112635269, exponentA + exponentB); } /// 1e18 * 1e-19 = 1e-1 function testMul1e181e19() external pure { - (int256 signedCoefficient, int256 exponent) = LibDecimalFloatImplementation.mul(1, 18, 1, -19); - assertEq(signedCoefficient, 1); - assertEq(exponent, -1); + checkMul(1, 18, 1, -19, 1, -1); } function testMulGasZero() external pure { @@ -95,8 +124,8 @@ contract LibDecimalFloatImplementationMulTest is Test { int256 signedCoefficientB, int256 exponentB ) external pure { - exponentA = bound(exponentA, EXPONENT_MIN, EXPONENT_MAX); - exponentB = bound(exponentB, EXPONENT_MIN, EXPONENT_MAX); + exponentA = bound(exponentA, EXPONENT_MIN, EXPONENT_MAX / 2); + exponentB = bound(exponentB, EXPONENT_MIN, EXPONENT_MAX / 2); (int256 signedCoefficient, int256 exponent) = LibDecimalFloatImplementation.mul(signedCoefficientA, exponentA, signedCoefficientB, exponentB); (int256 expectedSignedCoefficient, int256 expectedExponent) = diff --git a/test/src/lib/implementation/LibDecimalFloatImplementation.pow10.t.sol b/test/src/lib/implementation/LibDecimalFloatImplementation.pow10.t.sol index 5324d6ec..f0e2639b 100644 --- a/test/src/lib/implementation/LibDecimalFloatImplementation.pow10.t.sol +++ b/test/src/lib/implementation/LibDecimalFloatImplementation.pow10.t.sol @@ -63,7 +63,9 @@ contract LibDecimalFloatImplementationPow10Test is LogTest { function testInterpolatedLookupsPower() external { // 10^1.55555 = 35.9376769153 checkPow10(1.55555e37, -37, 35.935e75, -75); - // 10^1234.56789 + // Source: WolframAlpha (10^1234.56789). Full-precision mantissa below is reference only. + // 10^1234.56789 ≈ 3.69734519948141829344363446069899674413404079870780463377448004811497051583459624644095897334743494067266231680935688534678044962972813724… × 10^1234 + // Test expectation uses a truncated mantissa (3.6979e76) consistent with library rounding. checkPow10(123456789, -5, 3.6979e76, 1158); // ~= 10 (fuzzing found this edge case). checkPow10( diff --git a/test/src/lib/implementation/LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy.t.sol b/test/src/lib/implementation/LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy.t.sol new file mode 100644 index 00000000..e6d8d4c4 --- /dev/null +++ b/test/src/lib/implementation/LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy.t.sol @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: CAL +pragma solidity =0.8.25; + +import {Test} from "forge-std/Test.sol"; + +import {LibDecimalFloatImplementation} from "src/lib/implementation/LibDecimalFloatImplementation.sol"; + +contract LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest is Test { + /// a and b are both not negative. + function testUnabsUnsignedMulOrDivLossyPositive(uint256 a, uint256 b, uint256 c, int256 exponent) external pure { + a = bound(a, 0, uint256(type(int256).max)); + b = bound(b, 0, uint256(type(int256).max)); + c = bound(c, 0, uint256(type(int256).max)); + + (int256 actualSignedCoefficient, int256 actualExponent) = + LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy(int256(a), int256(b), c, exponent); + + int256 expectedSignedCoefficient = int256(c); + int256 expectedExponent = exponent; + + assertEq(actualSignedCoefficient, expectedSignedCoefficient); + assertEq(actualExponent, expectedExponent); + } + + /// a and b are both not negative, c overflows int256. + function testUnabsUnsignedMulOrDivLossyPositiveOverflow(uint256 a, uint256 b, uint256 c, int256 exponent) + external + pure + { + a = bound(a, 0, uint256(type(int256).max)); + b = bound(b, 0, uint256(type(int256).max)); + c = bound(c, uint256(type(int256).max) + 1, type(uint256).max); + vm.assume(exponent != type(int256).max); // Prevent overflow in exponent. + + (int256 actualSignedCoefficient, int256 actualExponent) = + LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy(int256(a), int256(b), c, exponent); + // Expect the result to be positive. + int256 expectedSignedCoefficient = int256(c / 10); + int256 expectedExponent = exponent + 1; + assertEq(actualSignedCoefficient, expectedSignedCoefficient, "signed coefficient mismatch"); + assertEq(actualExponent, expectedExponent, "exponent mismatch"); + } + + /// a and b are both negative. + function testUnabsUnsignedMulOrDivLossyNegative(uint256 a, uint256 b, uint256 c, int256 exponent) external pure { + a = bound(a, 1, uint256(type(int256).max)); + b = bound(b, 1, uint256(type(int256).max)); + c = bound(c, 0, uint256(type(int256).max)); + + (int256 actualSignedCoefficient, int256 actualExponent) = + LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy(-int256(a), -int256(b), c, exponent); + + int256 expectedSignedCoefficient = int256(c); + int256 expectedExponent = exponent; + + assertEq(actualSignedCoefficient, expectedSignedCoefficient, "signed coefficient mismatch"); + assertEq(actualExponent, expectedExponent, "exponent mismatch"); + } + + /// a and b are both negative, c overflows int256. + function testUnabsUnsignedMulOrDivLossyNegativeOverflow(uint256 a, uint256 b, uint256 c, int256 exponent) + external + pure + { + a = bound(a, 1, uint256(type(int256).max)); + b = bound(b, 1, uint256(type(int256).max)); + c = bound(c, uint256(type(int256).max) + 1, type(uint256).max); + vm.assume(exponent != type(int256).max); // Prevent overflow in exponent. + + (int256 actualSignedCoefficient, int256 actualExponent) = + LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy(-int256(a), -int256(b), c, exponent); + + // Expect the result to be positive. + int256 expectedSignedCoefficient = int256(c / 10); + int256 expectedExponent = exponent + 1; + + assertEq(actualSignedCoefficient, expectedSignedCoefficient, "signed coefficient mismatch"); + assertEq(actualExponent, expectedExponent, "exponent mismatch"); + } + + /// a is negative, b is positive. + function testUnabsUnsignedMulOrDivLossyMixedAB(uint256 a, uint256 b, uint256 c, int256 exponent) external pure { + a = bound(a, 1, uint256(type(int256).max)); + b = bound(b, 0, uint256(type(int256).max)); + c = bound(c, 0, uint256(type(int256).max)); + + (int256 actualSignedCoefficient, int256 actualExponent) = + LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy(-int256(a), int256(b), c, exponent); + + // Expect the result to be negative. + int256 expectedSignedCoefficient = -int256(c); + int256 expectedExponent = exponent; + + assertEq(actualSignedCoefficient, expectedSignedCoefficient, "signed coefficient mismatch"); + assertEq(actualExponent, expectedExponent, "exponent mismatch"); + } + + /// a is positive, b is negative. c overflows int256. + function testUnabsUnsignedMulOrDivLossyMixedBA(uint256 a, uint256 b, uint256 c, int256 exponent) external pure { + a = bound(a, 0, uint256(type(int256).max)); + b = bound(b, 1, uint256(type(int256).max)); + c = bound(c, uint256(type(int256).max) + 2, type(uint256).max); + vm.assume(exponent != type(int256).max); // Prevent overflow in exponent. + + (int256 actualSignedCoefficient, int256 actualExponent) = + LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy(int256(a), -int256(b), c, exponent); + + // Expect the result to be negative. + int256 expectedSignedCoefficient = -int256(c / 10); + int256 expectedExponent = exponent + 1; + + assertEq(actualSignedCoefficient, expectedSignedCoefficient, "signed coefficient mismatch"); + assertEq(actualExponent, expectedExponent, "exponent mismatch"); + } + + /// a is negative, b is positive, c overflows int256. + function testUnabsUnsignedMulOrDivLossyMixedABOverflow(uint256 a, uint256 b, uint256 c, int256 exponent) + external + pure + { + a = bound(a, 1, uint256(type(int256).max)); + b = bound(b, 0, uint256(type(int256).max)); + c = bound(c, uint256(type(int256).max) + 2, type(uint256).max); + vm.assume(exponent != type(int256).max); // Prevent overflow in exponent. + + (int256 actualSignedCoefficient, int256 actualExponent) = + LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy(-int256(a), int256(b), c, exponent); + + // Expect the result to be negative. + int256 expectedSignedCoefficient = -int256(c / 10); + int256 expectedExponent = exponent + 1; + + assertEq(actualSignedCoefficient, expectedSignedCoefficient, "signed coefficient mismatch"); + assertEq(actualExponent, expectedExponent, "exponent mismatch"); + } + + // c is type(int256).max + 1, a is positive and b is negative. + function testUnabsUnsignedMulOrDivLossyMixedBAOverflow(uint256 a, uint256 b, int256 exponent) external pure { + a = bound(a, 1, uint256(type(int256).max)); + b = bound(b, 1, uint256(type(int256).max)); + uint256 c = uint256(type(int256).max) + 1; + (int256 actualSignedCoefficient, int256 actualExponent) = + LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy(int256(a), -int256(b), c, exponent); + // Expect the result to be negative. + int256 expectedSignedCoefficient = type(int256).min; + int256 expectedExponent = exponent; + + assertEq(actualSignedCoefficient, expectedSignedCoefficient, "signed coefficient mismatch"); + assertEq(actualExponent, expectedExponent, "exponent mismatch"); + } +}