From 0160ad9a48907665663a955aef9227f2744e97b1 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Sat, 19 Jul 2025 16:59:32 +0400 Subject: [PATCH] gte and lte --- .gas-snapshot | 284 +++++++++++++---------- src/concrete/DecimalFloat.sol | 18 ++ src/lib/LibDecimalFloat.sol | 24 ++ test/lib/LibDecimalFloatSlow.sol | 16 ++ test/src/concrete/DecimalFloat.gte.t.sol | 27 +++ test/src/concrete/DecimalFloat.lte.t.sol | 27 +++ test/src/lib/LibDecimalFloat.gt.t.sol | 4 +- test/src/lib/LibDecimalFloat.gte.t.sol | 136 +++++++++++ test/src/lib/LibDecimalFloat.lte.t.sol | 133 +++++++++++ 9 files changed, 540 insertions(+), 129 deletions(-) create mode 100644 test/src/concrete/DecimalFloat.gte.t.sol create mode 100644 test/src/concrete/DecimalFloat.lte.t.sol create mode 100644 test/src/lib/LibDecimalFloat.gte.t.sol create mode 100644 test/src/lib/LibDecimalFloat.lte.t.sol diff --git a/.gas-snapshot b/.gas-snapshot index caec17aa..e27b1386 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,95 +1,111 @@ -DecimalFloatAbsTest:testAbsDeployed(bytes32) (runs: 5098, μ: 2165104, ~: 2165047) -DecimalFloatAddTest:testAddDeployed(bytes32,bytes32) (runs: 5098, μ: 2167802, ~: 2167484) -DecimalFloatDivTest:testDivDeployed(bytes32,bytes32) (runs: 5098, μ: 2167634, ~: 2167471) -DecimalFloatEqTest:testEqDeployed(bytes32,bytes32) (runs: 5098, μ: 2165488, ~: 2165414) -DecimalFloatFloorTest:testFloorDeployed(bytes32) (runs: 5098, μ: 2165330, ~: 2165314) -DecimalFloatFormatTest:testFormatDeployed(bytes32) (runs: 5098, μ: 2169147, ~: 2168973) -DecimalFloatFracTest:testFracDeployed(bytes32) (runs: 5098, μ: 2165356, ~: 2165340) -DecimalFloatGtTest:testGtDeployed(bytes32,bytes32) (runs: 5098, μ: 2165409, ~: 2165335) -DecimalFloatInvTest:testInvDeployed(bytes32) (runs: 5098, μ: 2166716, ~: 2166640) -DecimalFloatIsZeroTest:testIsZeroDeployed(bytes32) (runs: 5098, μ: 2164644, ~: 2164644) -DecimalFloatLtTest:testLtDeployed(bytes32,bytes32) (runs: 5098, μ: 2165386, ~: 2165312) -DecimalFloatMaxTest:testMaxDeployed(bytes32,bytes32) (runs: 5098, μ: 2165492, ~: 2165431) -DecimalFloatMinTest:testMinDeployed(bytes32,bytes32) (runs: 5098, μ: 2165490, ~: 2165429) -DecimalFloatMinusTest:testMinusDeployed(bytes32) (runs: 5098, μ: 2165204, ~: 2165204) -DecimalFloatMulTest:testMulDeployed(bytes32,bytes32) (runs: 5098, μ: 2167322, ~: 2168387) -DecimalFloatParseTest:testParseDeployed(string) (runs: 5098, μ: 2168368, ~: 2168250) -DecimalFloatSubTest:testSubDeployed(bytes32,bytes32) (runs: 5098, μ: 2168162, ~: 2167844) -LibDecimalFloatAbsTest:testAbsMinValue(int32) (runs: 5098, μ: 5121, ~: 5121) -LibDecimalFloatAbsTest:testAbsNegative(int256,int32) (runs: 5098, μ: 10475, ~: 10702) -LibDecimalFloatAbsTest:testAbsNonNegative(int256,int32) (runs: 5098, μ: 9641, ~: 9392) -LibDecimalFloatDecimalAddTest:testAddPacked(bytes32,bytes32) (runs: 5098, μ: 8361, ~: 8036) -LibDecimalFloatDecimalLosslessTest:testFromFixedDecimalLosslessFail(uint256,uint8) (runs: 5097, μ: 9615, ~: 9663) -LibDecimalFloatDecimalLosslessTest:testFromFixedDecimalLosslessMem(uint256,uint8) (runs: 5098, μ: 8130, ~: 8048) -LibDecimalFloatDecimalLosslessTest:testFromFixedDecimalLosslessPass(uint256,uint8) (runs: 5098, μ: 7452, ~: 7424) +DecimalFloatAbsTest:testAbsDeployed(bytes32) (runs: 5103, μ: 2349731, ~: 2349674) +DecimalFloatAddTest:testAddDeployed(bytes32,bytes32) (runs: 5103, μ: 2352443, ~: 2352133) +DecimalFloatDivTest:testDivDeployed(bytes32,bytes32) (runs: 5103, μ: 2352235, ~: 2352087) +DecimalFloatEqTest:testEqDeployed(bytes32,bytes32) (runs: 5103, μ: 2350137, ~: 2350064) +DecimalFloatFloorTest:testFloorDeployed(bytes32) (runs: 5103, μ: 2349935, ~: 2349919) +DecimalFloatFormatTest:testFormatDeployed(bytes32) (runs: 5103, μ: 2353754, ~: 2353600) +DecimalFloatFracTest:testFracDeployed(bytes32) (runs: 5103, μ: 2349961, ~: 2349945) +DecimalFloatGtTest:testGtDeployed(bytes32,bytes32) (runs: 5103, μ: 2350057, ~: 2349984) +DecimalFloatGteTest:testGteDeployed(bytes32,bytes32) (runs: 5103, μ: 2350130, ~: 2350057) +DecimalFloatInvTest:testInvDeployed(bytes32) (runs: 5103, μ: 2351346, ~: 2351267) +DecimalFloatIsZeroTest:testIsZeroDeployed(bytes32) (runs: 5103, μ: 2349293, ~: 2349293) +DecimalFloatLtTest:testLtDeployed(bytes32,bytes32) (runs: 5103, μ: 2349989, ~: 2349916) +DecimalFloatLteTest:testLteDeployed(bytes32,bytes32) (runs: 5103, μ: 2350087, ~: 2350014) +DecimalFloatMaxTest:testMaxDeployed(bytes32,bytes32) (runs: 5103, μ: 2350118, ~: 2350058) +DecimalFloatMinTest:testMinDeployed(bytes32,bytes32) (runs: 5103, μ: 2350116, ~: 2350056) +DecimalFloatMinusTest:testMinusDeployed(bytes32) (runs: 5103, μ: 2349853, ~: 2349853) +DecimalFloatMulTest:testMulDeployed(bytes32,bytes32) (runs: 5103, μ: 2351949, ~: 2353014) +DecimalFloatParseTest:testParseDeployed(string) (runs: 5103, μ: 2352530, ~: 2352399) +DecimalFloatSubTest:testSubDeployed(bytes32,bytes32) (runs: 5103, μ: 2352810, ~: 2352494) +LibDecimalFloatAbsTest:testAbsMinValue(int32) (runs: 5103, μ: 5121, ~: 5121) +LibDecimalFloatAbsTest:testAbsNegative(int256,int32) (runs: 5103, μ: 10475, ~: 10702) +LibDecimalFloatAbsTest:testAbsNonNegative(int256,int32) (runs: 5103, μ: 9641, ~: 9392) +LibDecimalFloatDecimalAddTest:testAddPacked(bytes32,bytes32) (runs: 5103, μ: 8361, ~: 8036) +LibDecimalFloatDecimalLosslessTest:testFromFixedDecimalLosslessFail(uint256,uint8) (runs: 5099, μ: 9615, ~: 9663) +LibDecimalFloatDecimalLosslessTest:testFromFixedDecimalLosslessMem(uint256,uint8) (runs: 5103, μ: 8130, ~: 8048) +LibDecimalFloatDecimalLosslessTest:testFromFixedDecimalLosslessPass(uint256,uint8) (runs: 5103, μ: 7452, ~: 7424) LibDecimalFloatDecimalLosslessTest:testToFixedDecimalLosslessFail() (gas: 4894) -LibDecimalFloatDecimalLosslessTest:testToFixedDecimalLosslessPacked(bytes32,uint8) (runs: 5098, μ: 6718, ~: 6161) -LibDecimalFloatDecimalLosslessTest:testToFixedDecimalLosslessPass(int256,int256,uint8) (runs: 5098, μ: 15805, ~: 15768) -LibDecimalFloatDecimalTest:testFixedDecimalRoundTripLossless(uint256,uint8) (runs: 5098, μ: 9274, ~: 9053) +LibDecimalFloatDecimalLosslessTest:testToFixedDecimalLosslessPacked(bytes32,uint8) (runs: 5103, μ: 6719, ~: 6161) +LibDecimalFloatDecimalLosslessTest:testToFixedDecimalLosslessPass(int256,int256,uint8) (runs: 5103, μ: 15805, ~: 15768) +LibDecimalFloatDecimalTest:testFixedDecimalRoundTripLossless(uint256,uint8) (runs: 5103, μ: 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: 5098, μ: 9460, ~: 9374) -LibDecimalFloatDecimalTest:testFromFixedDecimalLossyTruncateOne(uint256,uint8) (runs: 5098, μ: 5978, ~: 5937) -LibDecimalFloatDecimalTest:testFromFixedDecimalLossyTruncateZero(uint256,uint8) (runs: 5098, μ: 7306, ~: 5860) -LibDecimalFloatDecimalTest:testToFixedDecimalLosslessScaleUp(int256,int256,uint8) (runs: 5096, μ: 16005, ~: 15996) -LibDecimalFloatDecimalTest:testToFixedDecimalLossyExponentOverflow(int256,int256,uint8) (runs: 5098, μ: 14964, ~: 14729) -LibDecimalFloatDecimalTest:testToFixedDecimalLossyIdentity(int256,uint8) (runs: 5098, μ: 10152, ~: 9811) -LibDecimalFloatDecimalTest:testToFixedDecimalLossyNegative(int256,int256,uint8) (runs: 5098, μ: 10825, ~: 11076) -LibDecimalFloatDecimalTest:testToFixedDecimalLossyPacked(bytes32,uint8) (runs: 5098, μ: 6805, ~: 6905) -LibDecimalFloatDecimalTest:testToFixedDecimalLossyScaleUpOverflow(int256,int256,uint8) (runs: 5098, μ: 15348, ~: 15612) -LibDecimalFloatDecimalTest:testToFixedDecimalLossyTruncate(int256,int256,uint8) (runs: 5098, μ: 14494, ~: 14212) +LibDecimalFloatDecimalTest:testFromFixedDecimalLossyPacked(uint256,uint8) (runs: 5103, μ: 9460, ~: 9374) +LibDecimalFloatDecimalTest:testFromFixedDecimalLossyTruncateOne(uint256,uint8) (runs: 5103, μ: 5978, ~: 5937) +LibDecimalFloatDecimalTest:testFromFixedDecimalLossyTruncateZero(uint256,uint8) (runs: 5103, μ: 7305, ~: 5860) +LibDecimalFloatDecimalTest:testToFixedDecimalLosslessScaleUp(int256,int256,uint8) (runs: 5098, μ: 16005, ~: 15996) +LibDecimalFloatDecimalTest:testToFixedDecimalLossyExponentOverflow(int256,int256,uint8) (runs: 5103, μ: 14964, ~: 14729) +LibDecimalFloatDecimalTest:testToFixedDecimalLossyIdentity(int256,uint8) (runs: 5103, μ: 10152, ~: 9811) +LibDecimalFloatDecimalTest:testToFixedDecimalLossyNegative(int256,int256,uint8) (runs: 5103, μ: 10825, ~: 11076) +LibDecimalFloatDecimalTest:testToFixedDecimalLossyPacked(bytes32,uint8) (runs: 5103, μ: 6805, ~: 6905) +LibDecimalFloatDecimalTest:testToFixedDecimalLossyScaleUpOverflow(int256,int256,uint8) (runs: 5101, μ: 15348, ~: 15612) +LibDecimalFloatDecimalTest:testToFixedDecimalLossyTruncate(int256,int256,uint8) (runs: 5103, μ: 14494, ~: 14212) LibDecimalFloatDecimalTest:testToFixedDecimalLossyTruncateLossless() (gas: 14523) -LibDecimalFloatDecimalTest:testToFixedDecimalLossyUnderflow(int256,int256,uint8) (runs: 5098, μ: 13739, ~: 13602) -LibDecimalFloatDecimalTest:testToFixedDecimalLossyZero(int256,uint8) (runs: 5098, μ: 4598, ~: 4598) -LibDecimalFloatDivTest:testDivPacked(bytes32,bytes32) (runs: 5098, μ: 8052, ~: 7855) -LibDecimalFloatEqTest:testEqPacked(bytes32,bytes32) (runs: 5098, μ: 5524, ~: 5450) -LibDecimalFloatEqTest:testEqXNotYExponents(bytes32,bytes32) (runs: 5098, μ: 4341, ~: 4234) -LibDecimalFloatEqTest:testEqZero(int32) (runs: 5098, μ: 5133, ~: 5133) +LibDecimalFloatDecimalTest:testToFixedDecimalLossyUnderflow(int256,int256,uint8) (runs: 5103, μ: 13739, ~: 13602) +LibDecimalFloatDecimalTest:testToFixedDecimalLossyZero(int256,uint8) (runs: 5103, μ: 4598, ~: 4598) +LibDecimalFloatDivTest:testDivPacked(bytes32,bytes32) (runs: 5103, μ: 8052, ~: 7855) +LibDecimalFloatEqTest:testEqPacked(bytes32,bytes32) (runs: 5103, μ: 5524, ~: 5450) +LibDecimalFloatEqTest:testEqXNotYExponents(bytes32,bytes32) (runs: 5103, μ: 4341, ~: 4234) +LibDecimalFloatEqTest:testEqZero(int32) (runs: 5103, μ: 5133, ~: 5133) LibDecimalFloatFloorTest:testFloorExamples() (gas: 38974) LibDecimalFloatFloorTest:testFloorGas0() (gas: 937) LibDecimalFloatFloorTest:testFloorGasTiny() (gas: 858) LibDecimalFloatFloorTest:testFloorGasZero() (gas: 809) -LibDecimalFloatFloorTest:testFloorInRange(int224,int256) (runs: 5098, μ: 11009, ~: 11021) -LibDecimalFloatFloorTest:testFloorLessThanMin(int224,int256) (runs: 5098, μ: 10261, ~: 10270) -LibDecimalFloatFloorTest:testFloorNonNegative(int224,int256) (runs: 5098, μ: 9803, ~: 10062) -LibDecimalFloatFloorTest:testFloorNotReverts(bytes32) (runs: 5098, μ: 630, ~: 621) +LibDecimalFloatFloorTest:testFloorInRange(int224,int256) (runs: 5103, μ: 11009, ~: 11021) +LibDecimalFloatFloorTest:testFloorLessThanMin(int224,int256) (runs: 5103, μ: 10261, ~: 10270) +LibDecimalFloatFloorTest:testFloorNonNegative(int224,int256) (runs: 5103, μ: 9803, ~: 10062) +LibDecimalFloatFloorTest:testFloorNotReverts(bytes32) (runs: 5103, μ: 630, ~: 621) LibDecimalFloatFracTest:testFracExamples() (gas: 39135) LibDecimalFloatFracTest:testFracGas0() (gas: 960) LibDecimalFloatFracTest:testFracGasTiny() (gas: 836) LibDecimalFloatFracTest:testFracGasZero() (gas: 820) -LibDecimalFloatFracTest:testFracInRange(int224,int256) (runs: 5098, μ: 10847, ~: 10859) -LibDecimalFloatFracTest:testFracLessThanMin(int224,int256) (runs: 5098, μ: 10273, ~: 10280) -LibDecimalFloatFracTest:testFracNonNegative(int224,int256) (runs: 5098, μ: 9805, ~: 10066) -LibDecimalFloatFracTest:testFracNotReverts(bytes32) (runs: 5098, μ: 630, ~: 621) -LibDecimalFloatGtTest:testGtGasAZero() (gas: 1017) -LibDecimalFloatGtTest:testGtGasBZero() (gas: 1038) +LibDecimalFloatFracTest:testFracInRange(int224,int256) (runs: 5103, μ: 10847, ~: 10859) +LibDecimalFloatFracTest:testFracLessThanMin(int224,int256) (runs: 5103, μ: 10273, ~: 10280) +LibDecimalFloatFracTest:testFracNonNegative(int224,int256) (runs: 5103, μ: 9805, ~: 10066) +LibDecimalFloatFracTest:testFracNotReverts(bytes32) (runs: 5103, μ: 630, ~: 621) +LibDecimalFloatGtTest:testGtGasAZero() (gas: 973) +LibDecimalFloatGtTest:testGtGasBZero() (gas: 973) LibDecimalFloatGtTest:testGtGasBothZero() (gas: 751) LibDecimalFloatGtTest:testGtGasDifferentSigns() (gas: 974) -LibDecimalFloatGtTest:testGtGasExponentDiffOverflow() (gas: 1121) -LibDecimalFloatGtTest:testGtOneEAny(bytes32) (runs: 5098, μ: 3472, ~: 3472) -LibDecimalFloatGtTest:testGtReference(int224,int32,int224,int32) (runs: 5098, μ: 8077, ~: 6298) -LibDecimalFloatGtTest:testGtX(int224) (runs: 5098, μ: 3820, ~: 3820) -LibDecimalFloatGtTest:testGtXEAnyVsXEAny(int256,int32,int32) (runs: 5098, μ: 10568, ~: 10310) -LibDecimalFloatGtTest:testGtXEAnyVsXEAnyNegative(int256,int32,int32) (runs: 5098, μ: 11144, ~: 11349) -LibDecimalFloatGtTest:testGtXNotY(bytes32,bytes32) (runs: 5098, μ: 4319, ~: 4210) -LibDecimalFloatGtTest:testGtXPositiveYNegative(int256,int32,int256,int32) (runs: 5098, μ: 13742, ~: 13573) -LibDecimalFloatGtTest:testGtXPositiveYZero(int256,int32,int32) (runs: 5098, μ: 10249, ~: 9857) -LibDecimalFloatGtTest:testGtZero(int32,int32) (runs: 5098, μ: 4838, ~: 4838) +LibDecimalFloatGtTest:testGtGasExponentDiffOverflow() (gas: 1143) +LibDecimalFloatGtTest:testGtOneEAny(bytes32) (runs: 5103, μ: 3494, ~: 3494) +LibDecimalFloatGtTest:testGtReference(int224,int32,int224,int32) (runs: 5103, μ: 8066, ~: 6272) +LibDecimalFloatGtTest:testGtX(int224,int32) (runs: 5103, μ: 3882, ~: 3882) +LibDecimalFloatGtTest:testGtXEAnyVsXEAny(int256,int32,int32) (runs: 5103, μ: 10593, ~: 10332) +LibDecimalFloatGtTest:testGtXEAnyVsXEAnyNegative(int256,int32,int32) (runs: 5103, μ: 11144, ~: 11349) +LibDecimalFloatGtTest:testGtXNotY(bytes32,bytes32) (runs: 5103, μ: 4341, ~: 4232) +LibDecimalFloatGtTest:testGtXPositiveYNegative(int256,int32,int256,int32) (runs: 5103, μ: 13764, ~: 13595) +LibDecimalFloatGtTest:testGtXPositiveYZero(int256,int32,int32) (runs: 5103, μ: 10274, ~: 10026) +LibDecimalFloatGtTest:testGtZero(int32,int32) (runs: 5103, μ: 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: 5103, μ: 3494, ~: 3494) +LibDecimalFloatGteTest:testGteReference(int224,int32,int224,int32) (runs: 5103, μ: 8116, ~: 6344) +LibDecimalFloatGteTest:testGteX(int224,int32) (runs: 5103, μ: 3925, ~: 3925) +LibDecimalFloatGteTest:testGteXEAnyVsXEAny(int256,int32,int32) (runs: 5103, μ: 10622, ~: 10364) +LibDecimalFloatGteTest:testGteXEAnyVsXEAnyNegative(int256,int32,int32) (runs: 5103, μ: 11156, ~: 11361) +LibDecimalFloatGteTest:testGteXNotLtY(bytes32,bytes32) (runs: 5103, μ: 3947, ~: 3873) +LibDecimalFloatGteTest:testGteXPositiveYNegative(int256,int32,int256,int32) (runs: 5103, μ: 13794, ~: 13623) +LibDecimalFloatGteTest:testGteXPositiveYZero(int256,int32,int32) (runs: 5103, μ: 9551, ~: 9170) +LibDecimalFloatGteTest:testGteZero(int32,int32) (runs: 5103, μ: 4838, ~: 4838) LibDecimalFloatImplementationAddTest:testAdd123456789987654321() (gas: 4813) LibDecimalFloatImplementationAddTest:testAdd123456789e9987654321() (gas: 4865) -LibDecimalFloatImplementationAddTest:testAddNeverRevert(int256,int256,int256,int256) (runs: 5098, μ: 13213, ~: 13134) +LibDecimalFloatImplementationAddTest:testAddNeverRevert(int256,int256,int256,int256) (runs: 5103, μ: 13213, ~: 13134) LibDecimalFloatImplementationAddTest:testAddOneOneNotNormalized() (gas: 5368) LibDecimalFloatImplementationAddTest:testAddOneOnePreNormalized() (gas: 4250) LibDecimalFloatImplementationAddTest:testAddOneZero() (gas: 3688) -LibDecimalFloatImplementationAddTest:testAddSameExponentSameCoefficient(int256,int256) (runs: 5098, μ: 5764, ~: 5813) +LibDecimalFloatImplementationAddTest:testAddSameExponentSameCoefficient(int256,int256) (runs: 5103, μ: 5763, ~: 5813) LibDecimalFloatImplementationAddTest:testAddZero() (gas: 3664) -LibDecimalFloatImplementationAddTest:testAddZeroAnyExponent(int128) (runs: 5098, μ: 9294, ~: 9271) +LibDecimalFloatImplementationAddTest:testAddZeroAnyExponent(int128) (runs: 5103, μ: 9294, ~: 9271) LibDecimalFloatImplementationAddTest:testAddZeroOne() (gas: 3686) -LibDecimalFloatImplementationAddTest:testAddZeroToAnyNonZero(int256,int256,int256) (runs: 5097, μ: 14015, ~: 14005) +LibDecimalFloatImplementationAddTest:testAddZeroToAnyNonZero(int256,int256,int256) (runs: 5102, μ: 14015, ~: 14005) LibDecimalFloatImplementationAddTest:testAddingSmallToLargeReturnsLargeExamples() (gas: 19289) LibDecimalFloatImplementationAddTest:testAddingSmallToLargeReturnsLargeFuzz(int256,int256,int256,int256) (runs: 5098, μ: 17092, ~: 17016) LibDecimalFloatImplementationAddTest:testGasAddOne() (gas: 944) @@ -103,98 +119,112 @@ LibDecimalFloatImplementationDivTest:testDivNegative1Over3() (gas: 6074) LibDecimalFloatImplementationDivTest:testDivOOMs5and2() (gas: 4848) LibDecimalFloatImplementationDivTest:testDivOOMsOverTen() (gas: 5665) LibDecimalFloatImplementationDivTest:testDivTenOverOOMs() (gas: 5590) -LibDecimalFloatImplementationDivTest:testUnnormalizedThreesDiv0(int256,int256) (runs: 102, μ: 21050743, ~: 21050370) +LibDecimalFloatImplementationDivTest:testUnnormalizedThreesDiv0(int256,int256) (runs: 107, μ: 21050756, ~: 21050370) 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: 5098, μ: 654, ~: 679) -LibDecimalFloatImplementationEqTest:testEqOneEAny(int256,int256) (runs: 5098, μ: 3416, ~: 3416) -LibDecimalFloatImplementationEqTest:testEqReference(int256,int256,int256,int256) (runs: 5098, μ: 9904, ~: 11437) -LibDecimalFloatImplementationEqTest:testEqX(int256) (runs: 5098, μ: 3392, ~: 3392) -LibDecimalFloatImplementationEqTest:testEqXEAnyVsXEAny(int256,int256,int256) (runs: 5098, μ: 4718, ~: 4714) -LibDecimalFloatImplementationEqTest:testEqXEqY(int256,int256,int256,int256) (runs: 5098, μ: 732, ~: 753) -LibDecimalFloatImplementationEqTest:testEqXNotY(int256,int256,int256,int256) (runs: 5098, μ: 3928, ~: 3953) -LibDecimalFloatImplementationEqTest:testEqZero(int256,int256) (runs: 5098, μ: 3440, ~: 3440) +LibDecimalFloatImplementationEqTest:testEqNotReverts(int256,int256,int256,int256) (runs: 5103, μ: 654, ~: 679) +LibDecimalFloatImplementationEqTest:testEqOneEAny(int256,int256) (runs: 5103, μ: 3416, ~: 3416) +LibDecimalFloatImplementationEqTest:testEqReference(int256,int256,int256,int256) (runs: 5103, μ: 9902, ~: 11437) +LibDecimalFloatImplementationEqTest:testEqX(int256) (runs: 5103, μ: 3392, ~: 3392) +LibDecimalFloatImplementationEqTest:testEqXEAnyVsXEAny(int256,int256,int256) (runs: 5101, μ: 4718, ~: 4714) +LibDecimalFloatImplementationEqTest:testEqXEqY(int256,int256,int256,int256) (runs: 5103, μ: 732, ~: 753) +LibDecimalFloatImplementationEqTest:testEqXNotY(int256,int256,int256,int256) (runs: 5103, μ: 3928, ~: 3953) +LibDecimalFloatImplementationEqTest:testEqZero(int256,int256) (runs: 5103, μ: 3440, ~: 3440) LibDecimalFloatImplementationInvTest:testInvGas0() (gas: 734) -LibDecimalFloatImplementationInvTest:testInvReference(int256,int256) (runs: 5098, μ: 12224, ~: 12163) +LibDecimalFloatImplementationInvTest:testInvReference(int256,int256) (runs: 5101, μ: 12224, ~: 12163) LibDecimalFloatImplementationInvTest:testInvSlowGas0() (gas: 755) LibDecimalFloatImplementationLog10Test:testExactLogs() (gas: 1263200) LibDecimalFloatImplementationLog10Test:testExactLookups() (gas: 1280292) LibDecimalFloatImplementationLog10Test:testInterpolatedLookups() (gas: 1257728) LibDecimalFloatImplementationLog10Test:testSub1() (gas: 1255242) -LibDecimalFloatImplementationMinusTest:testMinusIsSubZero(int256,int256,int256) (runs: 5098, μ: 12951, ~: 12929) +LibDecimalFloatImplementationMinusTest:testMinusIsSubZero(int256,int256,int256) (runs: 5103, μ: 12951, ~: 12929) LibDecimalFloatImplementationMulTest:testMul123456789987654321() (gas: 3676) -LibDecimalFloatImplementationMulTest:testMul123456789987654321WithExponents(int128,int128) (runs: 5098, μ: 13185, ~: 13270) +LibDecimalFloatImplementationMulTest:testMul123456789987654321WithExponents(int128,int128) (runs: 5103, μ: 13185, ~: 13270) LibDecimalFloatImplementationMulTest:testMul1e181e19() (gas: 3720) LibDecimalFloatImplementationMulTest:testMulGasOne() (gas: 382) LibDecimalFloatImplementationMulTest:testMulGasZero() (gas: 324) -LibDecimalFloatImplementationMulTest:testMulNotRevertAnyExpectation(int256,int256,int256,int256) (runs: 5098, μ: 13394, ~: 12563) +LibDecimalFloatImplementationMulTest:testMulNotRevertAnyExpectation(int256,int256,int256,int256) (runs: 5103, μ: 13395, ~: 12563) LibDecimalFloatImplementationMulTest:testMulOneOne() (gas: 3721) LibDecimalFloatImplementationMulTest:testMulOneZero() (gas: 3663) LibDecimalFloatImplementationMulTest:testMulZero0Exponent() (gas: 3620) -LibDecimalFloatImplementationMulTest:testMulZeroAnyExponent(int64,int64) (runs: 5098, μ: 3908, ~: 3908) +LibDecimalFloatImplementationMulTest:testMulZeroAnyExponent(int64,int64) (runs: 5103, μ: 3908, ~: 3908) LibDecimalFloatImplementationMulTest:testMulZeroOne() (gas: 3642) LibDecimalFloatImplementationNormalizeTest:testExamples() (gas: 160899) -LibDecimalFloatImplementationNormalizeTest:testIdempotent(int256,int256) (runs: 5098, μ: 9875, ~: 9808) -LibDecimalFloatImplementationNormalizeTest:testIsNormalizedReference(int256,int256) (runs: 5098, μ: 3533, ~: 3539) -LibDecimalFloatImplementationNormalizeTest:testNormalized(int256,int256) (runs: 5098, μ: 9415, ~: 9348) +LibDecimalFloatImplementationNormalizeTest:testIdempotent(int256,int256) (runs: 5103, μ: 9875, ~: 9808) +LibDecimalFloatImplementationNormalizeTest:testIsNormalizedReference(int256,int256) (runs: 5103, μ: 3533, ~: 3539) +LibDecimalFloatImplementationNormalizeTest:testNormalized(int256,int256) (runs: 5103, μ: 9415, ~: 9348) LibDecimalFloatImplementationPow10Test:testExactLookups() (gas: 1281984) LibDecimalFloatImplementationPow10Test:testExactPows() (gas: 1260129) LibDecimalFloatImplementationPow10Test:testInterpolatedLookupsPower() (gas: 1277254) -LibDecimalFloatImplementationPow10Test:testNoRevert(int224,int32) (runs: 5097, μ: 1258251, ~: 1259171) -LibDecimalFloatImplementationSubTest:testSubIsAdd(int256,int256,int256,int256) (runs: 5098, μ: 16004, ~: 15966) -LibDecimalFloatImplementationSubTest:testSubMinSignedValue(int256,int256,int256) (runs: 5098, μ: 16216, ~: 16148) +LibDecimalFloatImplementationPow10Test:testNoRevert(int224,int32) (runs: 5100, μ: 1258250, ~: 1259171) +LibDecimalFloatImplementationSubTest:testSubIsAdd(int256,int256,int256,int256) (runs: 5103, μ: 16003, ~: 15964) +LibDecimalFloatImplementationSubTest:testSubMinSignedValue(int256,int256,int256) (runs: 5103, μ: 16215, ~: 16148) LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentExamples() (gas: 13429) -LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentLargerExponentOverflowRescaleRevert(int256,int256,int256) (runs: 5096, μ: 14426, ~: 14395) -LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentLargerExponentVeryLargeDiffRevert(int256,int256,int256) (runs: 5098, μ: 13307, ~: 13527) -LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentLargerTargetExponentNoRevert(int256,int256,int256) (runs: 5098, μ: 11669, ~: 11718) -LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentSameExponentNoop(int256,int256) (runs: 5098, μ: 3676, ~: 3676) -LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentSmallerExponentNoRevert(int256,int256,int256) (runs: 5098, μ: 13874, ~: 13665) -LibDecimalFloatInvTest:testInvMem(bytes32) (runs: 5098, μ: 7321, ~: 7246) -LibDecimalFloatIsZeroTest:testIsZeroDeployed(bytes32) (runs: 5098, μ: 3899, ~: 3899) -LibDecimalFloatIsZeroTest:testIsZeroEqZero(bytes32) (runs: 5098, μ: 3527, ~: 3527) -LibDecimalFloatIsZeroTest:testIsZeroExamples(int32) (runs: 5098, μ: 4477, ~: 4477) -LibDecimalFloatIsZeroTest:testNotIsZero(int224,int32) (runs: 5098, μ: 3896, ~: 3896) -LibDecimalFloatLog10Test:testLog10Packed(bytes32) (runs: 5098, μ: 1645677, ~: 1263823) +LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentLargerExponentOverflowRescaleRevert(int256,int256,int256) (runs: 5097, μ: 14426, ~: 14395) +LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentLargerExponentVeryLargeDiffRevert(int256,int256,int256) (runs: 5103, μ: 13307, ~: 13527) +LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentLargerTargetExponentNoRevert(int256,int256,int256) (runs: 5103, μ: 11669, ~: 11718) +LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentSameExponentNoop(int256,int256) (runs: 5103, μ: 3676, ~: 3676) +LibDecimalFloatImplementationWithTargetExponentTest:testWithTargetExponentSmallerExponentNoRevert(int256,int256,int256) (runs: 5102, μ: 13874, ~: 13665) +LibDecimalFloatInvTest:testInvMem(bytes32) (runs: 5103, μ: 7321, ~: 7246) +LibDecimalFloatIsZeroTest:testIsZeroDeployed(bytes32) (runs: 5103, μ: 3899, ~: 3899) +LibDecimalFloatIsZeroTest:testIsZeroEqZero(bytes32) (runs: 5103, μ: 3527, ~: 3527) +LibDecimalFloatIsZeroTest:testIsZeroExamples(int32) (runs: 5103, μ: 4477, ~: 4477) +LibDecimalFloatIsZeroTest:testNotIsZero(int224,int32) (runs: 5101, μ: 3896, ~: 3896) +LibDecimalFloatLog10Test:testLog10Packed(bytes32) (runs: 5103, μ: 1645540, ~: 1263823) 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: 5098, μ: 13750, ~: 13593) -LibDecimalFloatLtTest:testLtNegativeVsZero(int256,int32,int32) (runs: 5098, μ: 10789, ~: 11008) -LibDecimalFloatLtTest:testLtOneEAny(int224,int32) (runs: 5098, μ: 3905, ~: 3905) -LibDecimalFloatLtTest:testLtReference(bytes32,bytes32) (runs: 5098, μ: 4697, ~: 4998) -LibDecimalFloatLtTest:testLtVsEqualVsGt(bytes32,bytes32) (runs: 5098, μ: 4323, ~: 4210) -LibDecimalFloatLtTest:testLtX(int224) (runs: 5098, μ: 3798, ~: 3798) -LibDecimalFloatLtTest:testLtXEAnyVsXEAny(int256,int32,int32) (runs: 5098, μ: 10557, ~: 10297) -LibDecimalFloatLtTest:testLtXEAnyVsXEAnyNegative(int256,int32,int32) (runs: 5098, μ: 11153, ~: 11359) -LibDecimalFloatLtTest:testLtZero(int32,int32) (runs: 5098, μ: 4171, ~: 4171) -LibDecimalFloatMaxTest:testMaxX(bytes32) (runs: 5098, μ: 4246, ~: 4246) -LibDecimalFloatMaxTest:testMaxXY(bytes32,bytes32) (runs: 5098, μ: 4689, ~: 4613) -LibDecimalFloatMaxTest:testMaxXYEqual(bytes32) (runs: 5098, μ: 5272, ~: 5272) -LibDecimalFloatMaxTest:testMaxXYGreater(bytes32,bytes32) (runs: 5098, μ: 6129, ~: 6016) -LibDecimalFloatMaxTest:testMaxXYLess(bytes32,bytes32) (runs: 5096, μ: 6141, ~: 6027) -LibDecimalFloatMinTest:testMinX(bytes32) (runs: 5098, μ: 4268, ~: 4268) -LibDecimalFloatMinTest:testMinXY(bytes32,bytes32) (runs: 5098, μ: 4689, ~: 4613) -LibDecimalFloatMinTest:testMinXYEqual(bytes32) (runs: 5098, μ: 5292, ~: 5292) -LibDecimalFloatMinTest:testMinXYGreater(bytes32,bytes32) (runs: 5098, μ: 6074, ~: 5961) -LibDecimalFloatMinTest:testMinXYLess(bytes32,bytes32) (runs: 5096, μ: 6087, ~: 5972) -LibDecimalFloatMinusTest:testMinusPacked(bytes32) (runs: 5098, μ: 5550, ~: 5550) +LibDecimalFloatLtTest:testLtNegativeVsPositive(int256,int32,int256,int32) (runs: 5103, μ: 13750, ~: 13593) +LibDecimalFloatLtTest:testLtNegativeVsZero(int256,int32,int32) (runs: 5103, μ: 10790, ~: 11008) +LibDecimalFloatLtTest:testLtOneEAny(int224,int32) (runs: 5103, μ: 3905, ~: 3905) +LibDecimalFloatLtTest:testLtReference(bytes32,bytes32) (runs: 5103, μ: 4697, ~: 4998) +LibDecimalFloatLtTest:testLtVsEqualVsGt(bytes32,bytes32) (runs: 5103, μ: 4323, ~: 4210) +LibDecimalFloatLtTest:testLtX(int224) (runs: 5103, μ: 3798, ~: 3798) +LibDecimalFloatLtTest:testLtXEAnyVsXEAny(int256,int32,int32) (runs: 5103, μ: 10558, ~: 10297) +LibDecimalFloatLtTest:testLtXEAnyVsXEAnyNegative(int256,int32,int32) (runs: 5103, μ: 11153, ~: 11359) +LibDecimalFloatLtTest:testLtZero(int32,int32) (runs: 5103, μ: 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: 5103, μ: 3493, ~: 3493) +LibDecimalFloatLteTest:testLteReference(int224,int32,int224,int32) (runs: 5103, μ: 8111, ~: 6341) +LibDecimalFloatLteTest:testLteX(int224,int32) (runs: 5103, μ: 3904, ~: 3904) +LibDecimalFloatLteTest:testLteXEAnyVsXEAny(int256,int32,int32) (runs: 5103, μ: 10582, ~: 10321) +LibDecimalFloatLteTest:testLteXEAnyVsXEAnyNegative(int256,int32,int32) (runs: 5103, μ: 11177, ~: 11383) +LibDecimalFloatLteTest:testLteXNotLtY(bytes32,bytes32) (runs: 5103, μ: 3882, ~: 3807) +LibDecimalFloatLteTest:testLteXPositiveYNegative(int256,int32,int256,int32) (runs: 5103, μ: 13102, ~: 12931) +LibDecimalFloatLteTest:testLteXPositiveYZero(int256,int32,int32) (runs: 5103, μ: 9575, ~: 9191) +LibDecimalFloatLteTest:testLteZero(int32,int32) (runs: 5103, μ: 4816, ~: 4816) +LibDecimalFloatMaxTest:testMaxX(bytes32) (runs: 5103, μ: 4246, ~: 4246) +LibDecimalFloatMaxTest:testMaxXY(bytes32,bytes32) (runs: 5103, μ: 4689, ~: 4613) +LibDecimalFloatMaxTest:testMaxXYEqual(bytes32) (runs: 5103, μ: 5272, ~: 5272) +LibDecimalFloatMaxTest:testMaxXYGreater(bytes32,bytes32) (runs: 5101, μ: 6129, ~: 6016) +LibDecimalFloatMaxTest:testMaxXYLess(bytes32,bytes32) (runs: 5097, μ: 6141, ~: 6027) +LibDecimalFloatMinTest:testMinX(bytes32) (runs: 5103, μ: 4268, ~: 4268) +LibDecimalFloatMinTest:testMinXY(bytes32,bytes32) (runs: 5103, μ: 4689, ~: 4613) +LibDecimalFloatMinTest:testMinXYEqual(bytes32) (runs: 5103, μ: 5292, ~: 5292) +LibDecimalFloatMinTest:testMinXYGreater(bytes32,bytes32) (runs: 5101, μ: 6074, ~: 5961) +LibDecimalFloatMinTest:testMinXYLess(bytes32,bytes32) (runs: 5097, μ: 6087, ~: 5972) +LibDecimalFloatMinusTest:testMinusPacked(bytes32) (runs: 5103, μ: 5550, ~: 5550) LibDecimalFloatMixedTest:testDiv1Over3() (gas: 8161) -LibDecimalFloatMulTest:testMulPacked(bytes32,bytes32) (runs: 5098, μ: 7891, ~: 8837) -LibDecimalFloatPackTest:testPartsRoundTrip(int224,int32) (runs: 5098, μ: 5352, ~: 5352) -LibDecimalFloatPow10Test:testPow10Packed(bytes32) (runs: 5098, μ: 1644841, ~: 1257918) +LibDecimalFloatMulTest:testMulPacked(bytes32,bytes32) (runs: 5103, μ: 7891, ~: 8837) +LibDecimalFloatPackTest:testPartsRoundTrip(int224,int32) (runs: 5103, μ: 5352, ~: 5352) +LibDecimalFloatPow10Test:testPow10Packed(bytes32) (runs: 5103, μ: 1644701, ~: 1257918) LibDecimalFloatPowTest:testPows() (gas: 1296748) -LibDecimalFloatPowTest:testRoundTripFuzz(bytes32,bytes32) (runs: 5098, μ: 1256889, ~: 1253536) +LibDecimalFloatPowTest:testRoundTripFuzz(bytes32,bytes32) (runs: 5103, μ: 1256891, ~: 1253536) LibDecimalFloatPowTest:testRoundTripSimple() (gas: 1450883) -LibDecimalFloatSubTest:testSubPacked(bytes32,bytes32) (runs: 5098, μ: 8614, ~: 8297) +LibDecimalFloatSubTest:testSubPacked(bytes32,bytes32) (runs: 5103, μ: 8614, ~: 8297) LibFormatDecimalFloatTest:testFormatDecimalExamples() (gas: 133439) -LibFormatDecimalFloatTest:testFormatDecimalRoundTrip(uint256) (runs: 5098, μ: 25171, ~: 20084) -LibFormatDecimalFloatTest:testFormatDecimalRoundTripNegative(int256) (runs: 5098, μ: 19691, ~: 21140) +LibFormatDecimalFloatTest:testFormatDecimalRoundTrip(uint256) (runs: 5103, μ: 25217, ~: 20105) +LibFormatDecimalFloatTest:testFormatDecimalRoundTripNegative(int256) (runs: 5103, μ: 19680, ~: 21006) LibLogTableBytesTest:testToBytesAntiLogTableDec() (gas: 159794) LibLogTableBytesTest:testToBytesAntiLogTableDecSmall() (gas: 162322) LibLogTableBytesTest:testToBytesLogTableDec() (gas: 143165) @@ -216,7 +246,7 @@ LibParseDecimalFloatTest:testParseLiteralDecimalFloatEDot() (gas: 4190) LibParseDecimalFloatTest:testParseLiteralDecimalFloatExponentRevert5() (gas: 4176) LibParseDecimalFloatTest:testParseLiteralDecimalFloatExponentRevert6() (gas: 4188) LibParseDecimalFloatTest:testParseLiteralDecimalFloatExponents() (gas: 402635) -LibParseDecimalFloatTest:testParseLiteralDecimalFloatFuzz(uint256,uint8,bool) (runs: 5098, μ: 46138, ~: 37507) +LibParseDecimalFloatTest:testParseLiteralDecimalFloatFuzz(uint256,uint8,bool) (runs: 5103, μ: 45914, ~: 37379) LibParseDecimalFloatTest:testParseLiteralDecimalFloatLeadingZeros() (gas: 59779) LibParseDecimalFloatTest:testParseLiteralDecimalFloatNegativeE() (gas: 6100) LibParseDecimalFloatTest:testParseLiteralDecimalFloatNegativeFrac() (gas: 5137) @@ -224,4 +254,4 @@ LibParseDecimalFloatTest:testParseLiteralDecimalFloatPrecisionRevert0() (gas: 27 LibParseDecimalFloatTest:testParseLiteralDecimalFloatPrecisionRevert1() (gas: 24801) LibParseDecimalFloatTest:testParseLiteralDecimalFloatSpecific() (gas: 22959) LibParseDecimalFloatTest:testParseLiteralDecimalFloatUnrelated() (gas: 50856) -LibParseDecimalFloatTest:testParsePacked(string) (runs: 5098, μ: 10041, ~: 9929) \ No newline at end of file +LibParseDecimalFloatTest:testParsePacked(string) (runs: 5103, μ: 9787, ~: 9668) \ No newline at end of file diff --git a/src/concrete/DecimalFloat.sol b/src/concrete/DecimalFloat.sol index d43e31b8..ca8ccd53 100644 --- a/src/concrete/DecimalFloat.sol +++ b/src/concrete/DecimalFloat.sol @@ -105,6 +105,24 @@ contract DecimalFloat { return a.gt(b); } + /// Exposes `LibDecimalFloat.lte` for offchain use. + /// @param a The first float to compare. + /// @param b The second float to compare. + /// @return True if the first float is less than or equal to the second, + /// false otherwise. + function lte(Float a, Float b) external pure returns (bool) { + return a.lte(b); + } + + /// Exposes `LibDecimalFloat.gte` for offchain use. + /// @param a The first float to compare. + /// @param b The second float to compare. + /// @return True if the first float is greater than or equal to the second, + /// false otherwise. + function gte(Float a, Float b) external pure returns (bool) { + return a.gte(b); + } + /// Exposes `LibDecimalFloat.frac` for offchain use. /// @param a The float to get the fractional part of. /// @return The fractional part of the float. diff --git a/src/lib/LibDecimalFloat.sol b/src/lib/LibDecimalFloat.sol index c3cdb7b5..c88ab717 100644 --- a/src/lib/LibDecimalFloat.sol +++ b/src/lib/LibDecimalFloat.sol @@ -525,6 +525,30 @@ library LibDecimalFloat { return signedCoefficientA > signedCoefficientB; } + /// Numeric less than or equal to for floats. + /// A float is less than or equal to another if its numeric value is less + /// than or equal to the other. For example, 1e2 is less than or equal to 1e3 + /// and 1e2 is less than or equal to 1e2. + function lte(Float a, Float b) internal pure returns (bool) { + (int256 signedCoefficientA, int256 exponentA) = a.unpack(); + (int256 signedCoefficientB, int256 exponentB) = b.unpack(); + (signedCoefficientA, signedCoefficientB) = + LibDecimalFloatImplementation.compareRescale(signedCoefficientA, exponentA, signedCoefficientB, exponentB); + return signedCoefficientA <= signedCoefficientB; + } + + /// Numeric greater than or equal to for floats. + /// A float is greater than or equal to another if its numeric value is + /// greater than or equal to the other. For example, 1e3 is greater than or + /// equal to 1e2 and 1e2 is greater than or equal to 1e2. + function gte(Float a, Float b) internal pure returns (bool) { + (int256 signedCoefficientA, int256 exponentA) = a.unpack(); + (int256 signedCoefficientB, int256 exponentB) = b.unpack(); + (signedCoefficientA, signedCoefficientB) = + LibDecimalFloatImplementation.compareRescale(signedCoefficientA, exponentA, signedCoefficientB, exponentB); + return signedCoefficientA >= signedCoefficientB; + } + /// Fractional component of a float. /// @param float The float to frac. function frac(Float float) internal pure returns (Float) { diff --git a/test/lib/LibDecimalFloatSlow.sol b/test/lib/LibDecimalFloatSlow.sol index 4e3c69d4..987eb223 100644 --- a/test/lib/LibDecimalFloatSlow.sol +++ b/test/lib/LibDecimalFloatSlow.sol @@ -82,6 +82,22 @@ library LibDecimalFloatSlow { return eqSlow(signedCoefficientA, exponentA, signedCoefficientB, exponentB); } + function gteSlow(int256 signedCoefficientA, int256 exponentA, int256 signedCoefficientB, int256 exponentB) + internal + pure + returns (bool) + { + return !ltSlow(signedCoefficientA, exponentA, signedCoefficientB, exponentB); + } + + function lteSlow(int256 signedCoefficientA, int256 exponentA, int256 signedCoefficientB, int256 exponentB) + internal + pure + returns (bool) + { + return !gtSlow(signedCoefficientA, exponentA, signedCoefficientB, exponentB); + } + function gtSlow(int256 signedCoefficientA, int256 exponentA, int256 signedCoefficientB, int256 exponentB) internal pure diff --git a/test/src/concrete/DecimalFloat.gte.t.sol b/test/src/concrete/DecimalFloat.gte.t.sol new file mode 100644 index 00000000..44d4a48e --- /dev/null +++ b/test/src/concrete/DecimalFloat.gte.t.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: CAL +pragma solidity =0.8.25; + +import {LibDecimalFloat, Float} from "src/lib/LibDecimalFloat.sol"; +import {Test} from "forge-std/Test.sol"; +import {DecimalFloat} from "src/concrete/DecimalFloat.sol"; + +contract DecimalFloatGteTest is Test { + using LibDecimalFloat for Float; + + function gteExternal(Float a, Float b) external pure returns (bool) { + return a.gte(b); + } + + function testGteDeployed(Float a, Float b) external { + DecimalFloat deployed = new DecimalFloat(); + + try this.gteExternal(a, b) returns (bool c) { + bool deployedC = deployed.gte(a, b); + + assertEq(c, deployedC); + } catch (bytes memory err) { + vm.expectRevert(err); + deployed.gte(a, b); + } + } +} diff --git a/test/src/concrete/DecimalFloat.lte.t.sol b/test/src/concrete/DecimalFloat.lte.t.sol new file mode 100644 index 00000000..0599de97 --- /dev/null +++ b/test/src/concrete/DecimalFloat.lte.t.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: CAL +pragma solidity =0.8.25; + +import {LibDecimalFloat, Float} from "src/lib/LibDecimalFloat.sol"; +import {Test} from "forge-std/Test.sol"; +import {DecimalFloat} from "src/concrete/DecimalFloat.sol"; + +contract DecimalFloatLteTest is Test { + using LibDecimalFloat for Float; + + function lteExternal(Float a, Float b) external pure returns (bool) { + return a.lte(b); + } + + function testLteDeployed(Float a, Float b) external { + DecimalFloat deployed = new DecimalFloat(); + + try this.lteExternal(a, b) returns (bool c) { + bool deployedC = deployed.lte(a, b); + + assertEq(c, deployedC); + } catch (bytes memory err) { + vm.expectRevert(err); + deployed.lte(a, b); + } + } +} diff --git a/test/src/lib/LibDecimalFloat.gt.t.sol b/test/src/lib/LibDecimalFloat.gt.t.sol index d6ff44d5..814fe126 100644 --- a/test/src/lib/LibDecimalFloat.gt.t.sol +++ b/test/src/lib/LibDecimalFloat.gt.t.sol @@ -23,8 +23,8 @@ contract LibDecimalFloatGtTest is Test { } /// x !> x - function testGtX(int224 x) external pure { - Float a = LibDecimalFloat.packLossless(x, 0); + function testGtX(int224 x, int32 exponent) external pure { + Float a = LibDecimalFloat.packLossless(x, exponent); bool gt = a.gt(a); assertTrue(!gt); } diff --git a/test/src/lib/LibDecimalFloat.gte.t.sol b/test/src/lib/LibDecimalFloat.gte.t.sol new file mode 100644 index 00000000..cec99edd --- /dev/null +++ b/test/src/lib/LibDecimalFloat.gte.t.sol @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: CAL +pragma solidity =0.8.25; + +import {LibDecimalFloat, Float} from "src/lib/LibDecimalFloat.sol"; + +import {LibDecimalFloatSlow} from "test/lib/LibDecimalFloatSlow.sol"; + +import {Test} from "forge-std/Test.sol"; + +contract LibDecimalFloatGteTest is Test { + using LibDecimalFloat for Float; + + function testGteReference(int224 signedCoefficientA, int32 exponentA, int224 signedCoefficientB, int32 exponentB) + external + pure + { + Float a = LibDecimalFloat.packLossless(signedCoefficientA, exponentA); + Float b = LibDecimalFloat.packLossless(signedCoefficientB, exponentB); + bool actual = a.gte(b); + bool expected = LibDecimalFloatSlow.gteSlow(signedCoefficientA, exponentA, signedCoefficientB, exponentB); + + assertEq(actual, expected); + } + + /// x >= x + function testGteX(int224 x, int32 exponent) external pure { + Float a = LibDecimalFloat.packLossless(x, exponent); + bool gte = a.gte(a); + assertTrue(gte); + } + + /// xeX >= xeX + function testGteOneEAny(Float a) external pure { + bool gte = a.gte(a); + assertTrue(gte); + } + + /// xeX >= xeY if X >= Y && x > 0 + function testGteXEAnyVsXEAny(int256 x, int32 exponentA, int32 exponentB) external pure { + x = bound(x, 1, type(int224).max); + Float a = LibDecimalFloat.packLossless(x, exponentA); + Float b = LibDecimalFloat.packLossless(x, exponentB); + bool gte = a.gte(b); + + assertEq(gte, exponentA >= exponentB); + + // Reverse the order. + gte = b.gte(a); + assertEq(gte, exponentB >= exponentA); + } + + /// xeX >= xeY if X <= Y && x < 0 + function testGteXEAnyVsXEAnyNegative(int256 x, int32 exponentA, int32 exponentB) external pure { + x = bound(x, type(int224).min, -1); + Float a = LibDecimalFloat.packLossless(x, exponentA); + Float b = LibDecimalFloat.packLossless(x, exponentB); + bool gte = a.gte(b); + + assertEq(gte, exponentA <= exponentB); + + // Reverse the order. + gte = b.gte(a); + assertEq(gte, exponentB <= exponentA); + } + + /// xeX >= xeY if x == 0 + function testGteZero(int32 exponentA, int32 exponentB) external pure { + Float a = LibDecimalFloat.packLossless(0, exponentA); + Float b = LibDecimalFloat.packLossless(0, exponentB); + bool gte = a.gte(b); + assertTrue(gte); + // Reverse the order. + gte = b.gte(a); + assertTrue(gte); + } + + /// xeX >= yeY if x >= 0 && y < 0 + function testGteXPositiveYNegative(int256 x, int32 exponentX, int256 y, int32 exponentY) external pure { + x = bound(x, 0, type(int224).max); + y = bound(y, type(int224).min, -1); + Float a = LibDecimalFloat.packLossless(x, exponentX); + Float b = LibDecimalFloat.packLossless(y, exponentY); + bool gte = a.gte(b); + assertTrue(gte); + + // Reverse the order. + gte = b.gte(a); + assertTrue(!gte); + } + + /// xeX >= yeY if xeX !< yeY + function testGteXNotLtY(Float a, Float b) external pure { + bool gte = a.gte(b); + bool lt = a.lt(b); + + assertEq(gte, !lt); + } + + /// xeX >= yeY if xeX >= 0 && yeY == 0 + function testGteXPositiveYZero(int256 x, int32 exponentX, int32 exponentZero) external pure { + x = bound(x, 0, type(int224).max); + Float a = LibDecimalFloat.packLossless(x, exponentX); + Float b = LibDecimalFloat.packLossless(0, exponentZero); + bool gte = a.gte(b); + assertTrue(gte); + } + + function testGteGasDifferentSigns() external pure { + Float a = LibDecimalFloat.packLossless(1, 0); + Float b = LibDecimalFloat.packLossless(-1, 0); + a.gte(b); + } + + function testGteGasAZero() external pure { + Float a = LibDecimalFloat.packLossless(0, 0); + Float b = LibDecimalFloat.packLossless(1, 0); + a.gte(b); + } + + function testGteGasBZero() external pure { + Float a = LibDecimalFloat.packLossless(1, 0); + Float b = LibDecimalFloat.packLossless(0, 0); + a.gte(b); + } + + function testGteGasBothZero() external pure { + Float a = LibDecimalFloat.packLossless(0, 0); + a.gte(a); + } + + function testGteGasExponentDiffOverflow() external pure { + Float a = LibDecimalFloat.packLossless(1, type(int32).max); + Float b = LibDecimalFloat.packLossless(1, type(int32).min); + a.gte(b); + } +} diff --git a/test/src/lib/LibDecimalFloat.lte.t.sol b/test/src/lib/LibDecimalFloat.lte.t.sol new file mode 100644 index 00000000..3c62d1e3 --- /dev/null +++ b/test/src/lib/LibDecimalFloat.lte.t.sol @@ -0,0 +1,133 @@ +// SPDX-License-Identifier: CAL +pragma solidity =0.8.25; + +import {LibDecimalFloat, Float} from "src/lib/LibDecimalFloat.sol"; + +import {LibDecimalFloatSlow} from "test/lib/LibDecimalFloatSlow.sol"; + +import {Test} from "forge-std/Test.sol"; + +contract LibDecimalFloatLteTest is Test { + using LibDecimalFloat for Float; + + function testLteReference(int224 signedCoefficientA, int32 exponentA, int224 signedCoefficientB, int32 exponentB) + external + pure + { + Float a = LibDecimalFloat.packLossless(signedCoefficientA, exponentA); + Float b = LibDecimalFloat.packLossless(signedCoefficientB, exponentB); + bool actual = a.lte(b); + bool expected = LibDecimalFloatSlow.lteSlow(signedCoefficientA, exponentA, signedCoefficientB, exponentB); + + assertEq(actual, expected); + } + + /// x <= x + function testLteX(int224 x, int32 exponent) external pure { + Float a = LibDecimalFloat.packLossless(x, exponent); + bool lte = a.lte(a); + assertTrue(lte); + } + + /// xeX <= xeX + function testLteOneEAny(Float a) external pure { + bool lte = a.lte(a); + assertTrue(lte); + } + + /// xeX <= xeY if X >= Y && x > 0 + function testLteXEAnyVsXEAny(int256 x, int32 exponentA, int32 exponentB) external pure { + x = bound(x, 1, type(int224).max); + Float a = LibDecimalFloat.packLossless(x, exponentA); + Float b = LibDecimalFloat.packLossless(x, exponentB); + bool lte = a.lte(b); + + assertEq(lte, exponentA <= exponentB); + + // Reverse the order. + lte = b.lte(a); + assertEq(lte, exponentB <= exponentA); + } + + /// xeX <= xeY if X >= Y && x < 0 + function testLteXEAnyVsXEAnyNegative(int256 x, int32 exponentA, int32 exponentB) external pure { + x = bound(x, type(int224).min, -1); + Float a = LibDecimalFloat.packLossless(x, exponentA); + Float b = LibDecimalFloat.packLossless(x, exponentB); + bool lte = a.lte(b); + + assertEq(lte, exponentA >= exponentB); + + // Reverse the order. + lte = b.lte(a); + assertEq(lte, exponentB >= exponentA); + } + + /// xeX <= xeY if x == 0 + function testLteZero(int32 exponentA, int32 exponentB) external pure { + Float a = LibDecimalFloat.packLossless(0, exponentA); + Float b = LibDecimalFloat.packLossless(0, exponentB); + bool lte = a.lte(b); + assertTrue(lte); + // Reverse the order. + lte = b.lte(a); + assertTrue(lte); + } + + /// yeY <= xeX if x >= 0 && y < 0 + function testLteXPositiveYNegative(int256 x, int32 exponentX, int256 y, int32 exponentY) external pure { + x = bound(x, 0, type(int224).max); + y = bound(y, type(int224).min, -1); + Float a = LibDecimalFloat.packLossless(x, exponentX); + Float b = LibDecimalFloat.packLossless(y, exponentY); + + bool lte = b.lte(a); + assertTrue(lte); + } + + /// xeX <= yeY if xeX !> yeY + function testLteXNotLtY(Float a, Float b) external pure { + bool lte = a.lte(b); + bool gt = a.gt(b); + + assertEq(lte, !gt); + } + + /// yeY >= xeX if xeX >= 0 && yeY == 0 + function testLteXPositiveYZero(int256 x, int32 exponentX, int32 exponentZero) external pure { + x = bound(x, 0, type(int224).max); + Float a = LibDecimalFloat.packLossless(x, exponentX); + Float b = LibDecimalFloat.packLossless(0, exponentZero); + bool lte = b.lte(a); + assertTrue(lte); + } + + function testLteGasDifferentSigns() external pure { + Float a = LibDecimalFloat.packLossless(1, 0); + Float b = LibDecimalFloat.packLossless(-1, 0); + a.lte(b); + } + + function testLteGasAZero() external pure { + Float a = LibDecimalFloat.packLossless(0, 0); + Float b = LibDecimalFloat.packLossless(1, 0); + a.lte(b); + } + + function testLteGasBZero() external pure { + Float a = LibDecimalFloat.packLossless(1, 0); + Float b = LibDecimalFloat.packLossless(0, 0); + a.lte(b); + } + + function testLteGasBothZero() external pure { + Float a = LibDecimalFloat.packLossless(0, 0); + a.lte(a); + } + + function testLteGasExponentDiffOverflow() external pure { + Float a = LibDecimalFloat.packLossless(1, type(int32).max); + Float b = LibDecimalFloat.packLossless(1, type(int32).min); + a.lte(b); + } +}