From 953ddbeecd5ac27001e054c96b76a1c7bdd5e6c9 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Sun, 17 Aug 2025 15:11:09 +0400 Subject: [PATCH 01/15] wip on normal mul --- .../LibDecimalFloatImplementation.sol | 89 ++++++++++++++----- 1 file changed, 65 insertions(+), 24 deletions(-) diff --git a/src/lib/implementation/LibDecimalFloatImplementation.sol b/src/lib/implementation/LibDecimalFloatImplementation.sol index 83e26c32..b888f9f1 100644 --- a/src/lib/implementation/LibDecimalFloatImplementation.sol +++ b/src/lib/implementation/LibDecimalFloatImplementation.sol @@ -106,35 +106,76 @@ library LibDecimalFloatImplementation { 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); + // mulDiv only works with unsigned integers, so get the aboslute + // values of the coefficients. + uint256 signedCoefficientAAbs; + if (signedCoefficientA < 0) { + if (signedCoefficientA == type(int256).min) { + signedCoefficientAAbs = uint256(type(int256).max) + 1; + } else { + signedCoefficientAAbs = uint256(-signedCoefficientA); + } + } else { + signedCoefficientAAbs = uint256(signedCoefficientA); + } + uint256 signedCoefficientBAbs; + if (signedCoefficientB < 0) { + if (signedCoefficientB == type(int256).min) { + signedCoefficientBAbs = uint256(type(int256).max) + 1; + } else { + signedCoefficientBAbs = uint256(-signedCoefficientB); + } + } else { + signedCoefficientBAbs = uint256(signedCoefficientB); } - int256 exponent = exponentA + exponentB; - - // No jumps to see if we overflowed. - bool didOverflow; + // 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") { - didOverflow := - or( - iszero(eq(sdiv(signedCoefficient, signedCoefficientA), signedCoefficientB)), - iszero(eq(sub(exponent, exponentA), exponentB)) - ) + let mm := mulmod(signedCoefficientA, signedCoefficientB, not(0)) + prod0 := mul(signedCoefficientA, signedCoefficientB) + prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } - // 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); + + // Handle non-overflow cases, 256 by 256 division. + if (prod1 == 0) { + unchecked { + return (prod0 * denominator, 0); + } } - return (signedCoefficient, exponent); + + // // 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); + // } + + // int256 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); + // } + // return (signedCoefficient, exponent); } } From 32cfc12fdd98cdec88df67cab8056960d30c432d Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Tue, 19 Aug 2025 20:20:34 +0400 Subject: [PATCH 02/15] wip on mul precision --- .../LibDecimalFloatImplementation.sol | 132 +++++++++++------- .../LibDecimalFloatImplementation.mul.t.sol | 18 ++- 2 files changed, 95 insertions(+), 55 deletions(-) diff --git a/src/lib/implementation/LibDecimalFloatImplementation.sol b/src/lib/implementation/LibDecimalFloatImplementation.sol index 9a73299f..00551a13 100644 --- a/src/lib/implementation/LibDecimalFloatImplementation.sol +++ b/src/lib/implementation/LibDecimalFloatImplementation.sol @@ -11,6 +11,8 @@ import { } from "../../generated/LogTables.pointers.sol"; import {LibDecimalFloat} from "../LibDecimalFloat.sol"; +import {console2} from "forge-std/console2.sol"; + error WithTargetExponentOverflow(int256 signedCoefficient, int256 exponent, int256 targetExponent); uint256 constant ADD_MAX_EXPONENT_DIFF = 76; @@ -100,78 +102,106 @@ library LibDecimalFloatImplementation { pure returns (int256, int256) { + // mulDiv only works with unsigned integers, so get the aboslute + // values of the coefficients. + uint256 signedCoefficientAAbs; + uint256 signedCoefficientBAbs; + unchecked { - // mulDiv only works with unsigned integers, so get the aboslute - // values of the coefficients. - uint256 signedCoefficientAAbs; if (signedCoefficientA < 0) { if (signedCoefficientA == type(int256).min) { signedCoefficientAAbs = uint256(type(int256).max) + 1; } else { signedCoefficientAAbs = uint256(-signedCoefficientA); } - } else { + } else if (signedCoefficientA > 0) { 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 { + } else if (signedCoefficientB > 0) { signedCoefficientBAbs = uint256(signedCoefficientB); + } else { + return (MAXIMIZED_ZERO_SIGNED_COEFFICIENT, MAXIMIZED_ZERO_EXPONENT); } + } - // 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(signedCoefficientA, signedCoefficientB, not(0)) - prod0 := mul(signedCoefficientA, signedCoefficientB) - prod1 := sub(sub(mm, prod0), lt(mm, prod0)) - } + // 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(signedCoefficientAAbs, signedCoefficientBAbs, not(0)) + prod0 := mul(signedCoefficientAAbs, signedCoefficientBAbs) + prod1 := sub(sub(mm, prod0), lt(mm, prod0)) + } - // Handle non-overflow cases, 256 by 256 division. - if (prod1 == 0) { - unchecked { - return (prod0 * denominator, 0); - } + int256 exponent = exponentA + exponentB; + + // // Handle non-overflow cases, 256 by 256 division. + // if (prod1 == 0) { + // int256 signedCoefficient = (signedCoefficientA ^ signedCoefficientB) < 0 ? -int256(prod0) : int256(prod0); + // unchecked { + // return (signedCoefficient, exponent); + // } + // } + console2.logInt(type(int256).max); + console2.logUint(prod0); + console2.logUint(prod1); + unchecked { + uint256 adjustExponent = 0; + while (prod1 != 0) { + prod1 /= 10; + adjustExponent++; } - - // // 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); - // } - - // int256 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); - // } - // return (signedCoefficient, exponent); + console2.logUint(adjustExponent); + uint256 signedCoefficientAbs = mulDiv(signedCoefficientAAbs, signedCoefficientBAbs, 10 ** adjustExponent); + console2.logUint(signedCoefficientAbs); + int256 signedCoefficient = (signedCoefficientA ^ signedCoefficientB) < 0 + ? -int256(signedCoefficientAbs) + : int256(signedCoefficientAbs); + exponent += int256(adjustExponent); + return (signedCoefficient, exponent); } + + // // 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); + // } + + // int256 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); + // } + // return (signedCoefficient, exponent); + // } } /// https://speleotrove.com/decimal/daops.html#refdivide diff --git a/test/src/lib/implementation/LibDecimalFloatImplementation.mul.t.sol b/test/src/lib/implementation/LibDecimalFloatImplementation.mul.t.sol index d3461511..2f970238 100644 --- a/test/src/lib/implementation/LibDecimalFloatImplementation.mul.t.sol +++ b/test/src/lib/implementation/LibDecimalFloatImplementation.mul.t.sol @@ -60,6 +60,16 @@ contract LibDecimalFloatImplementationMulTest is Test { assertEq(exponent, 0); } + function testMulMaxSignedCoefficient() external pure { + (int256 signedCoefficient, int256 exponent) = + LibDecimalFloatImplementation.mul(type(int256).max, 0, type(int256).max, 0); + // Numbers checked on desmos. + assertEq( + signedCoefficient, int256(3.3519519824856492748935062495514615318698414551480983444308903609304410075182e76) + ); + assertEq(exponent, 77); + } + /// 123456789 multiply 987654321 with exponents /// 123456789 * 987654321 = 121932631112635269 function testMul123456789987654321WithExponents(int128 exponentA, int128 exponentB) external pure { @@ -99,10 +109,10 @@ contract LibDecimalFloatImplementationMulTest is Test { exponentB = bound(exponentB, EXPONENT_MIN, EXPONENT_MAX); (int256 signedCoefficient, int256 exponent) = LibDecimalFloatImplementation.mul(signedCoefficientA, exponentA, signedCoefficientB, exponentB); - (int256 expectedSignedCoefficient, int256 expectedExponent) = - LibDecimalFloatSlow.mulSlow(signedCoefficientA, exponentA, signedCoefficientB, exponentB); + // (int256 expectedSignedCoefficient, int256 expectedExponent) = + // LibDecimalFloatSlow.mulSlow(signedCoefficientA, exponentA, signedCoefficientB, exponentB); - assertEq(signedCoefficient, expectedSignedCoefficient); - assertEq(exponent, expectedExponent); + // assertEq(signedCoefficient, expectedSignedCoefficient); + // assertEq(exponent, expectedExponent); } } From 8252c9333bb68c6de95b79b0434ebb3d78d10957 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Tue, 19 Aug 2025 20:22:35 +0400 Subject: [PATCH 03/15] lint --- .../LibDecimalFloatImplementation.sol | 45 ------------------- 1 file changed, 45 deletions(-) diff --git a/src/lib/implementation/LibDecimalFloatImplementation.sol b/src/lib/implementation/LibDecimalFloatImplementation.sol index 00551a13..ffc1beb5 100644 --- a/src/lib/implementation/LibDecimalFloatImplementation.sol +++ b/src/lib/implementation/LibDecimalFloatImplementation.sol @@ -11,8 +11,6 @@ import { } from "../../generated/LogTables.pointers.sol"; import {LibDecimalFloat} from "../LibDecimalFloat.sol"; -import {console2} from "forge-std/console2.sol"; - error WithTargetExponentOverflow(int256 signedCoefficient, int256 exponent, int256 targetExponent); uint256 constant ADD_MAX_EXPONENT_DIFF = 76; @@ -146,62 +144,19 @@ library LibDecimalFloatImplementation { int256 exponent = exponentA + exponentB; - // // Handle non-overflow cases, 256 by 256 division. - // if (prod1 == 0) { - // int256 signedCoefficient = (signedCoefficientA ^ signedCoefficientB) < 0 ? -int256(prod0) : int256(prod0); - // unchecked { - // return (signedCoefficient, exponent); - // } - // } - console2.logInt(type(int256).max); - console2.logUint(prod0); - console2.logUint(prod1); unchecked { uint256 adjustExponent = 0; while (prod1 != 0) { prod1 /= 10; adjustExponent++; } - console2.logUint(adjustExponent); uint256 signedCoefficientAbs = mulDiv(signedCoefficientAAbs, signedCoefficientBAbs, 10 ** adjustExponent); - console2.logUint(signedCoefficientAbs); int256 signedCoefficient = (signedCoefficientA ^ signedCoefficientB) < 0 ? -int256(signedCoefficientAbs) : int256(signedCoefficientAbs); exponent += int256(adjustExponent); return (signedCoefficient, exponent); } - - // // 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); - // } - - // int256 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); - // } - // return (signedCoefficient, exponent); - // } } /// https://speleotrove.com/decimal/daops.html#refdivide From 18f7d73e3b28be7d81af235285eea2d129aafd98 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Wed, 20 Aug 2025 18:06:40 +0400 Subject: [PATCH 04/15] mul cleanup --- .../LibDecimalFloatImplementation.sol | 186 +++++++++--------- test/lib/LibDecimalFloatSlow.sol | 34 ++-- .../LibDecimalFloatImplementation.mul.t.sol | 8 +- 3 files changed, 115 insertions(+), 113 deletions(-) diff --git a/src/lib/implementation/LibDecimalFloatImplementation.sol b/src/lib/implementation/LibDecimalFloatImplementation.sol index ffc1beb5..63001f2b 100644 --- a/src/lib/implementation/LibDecimalFloatImplementation.sol +++ b/src/lib/implementation/LibDecimalFloatImplementation.sol @@ -94,68 +94,85 @@ library LibDecimalFloatImplementation { } } - /// Stack only implementation of `mul`. - function mul(int256 signedCoefficientA, int256 exponentA, int256 signedCoefficientB, int256 exponentB) - internal - pure - returns (int256, int256) - { - // mulDiv only works with unsigned integers, so get the aboslute - // values of the coefficients. - uint256 signedCoefficientAAbs; - uint256 signedCoefficientBAbs; - + function absUnsignedSignedCoefficient(int256 signedCoefficient) internal pure returns (uint256) { unchecked { - if (signedCoefficientA < 0) { - if (signedCoefficientA == type(int256).min) { - signedCoefficientAAbs = uint256(type(int256).max) + 1; + if (signedCoefficient < 0) { + if (signedCoefficient == type(int256).min) { + return uint256(type(int256).max) + 1; } else { - signedCoefficientAAbs = uint256(-signedCoefficientA); + return uint256(-signedCoefficient); } - } else if (signedCoefficientA > 0) { - signedCoefficientAAbs = uint256(signedCoefficientA); } else { - return (MAXIMIZED_ZERO_SIGNED_COEFFICIENT, MAXIMIZED_ZERO_EXPONENT); + return uint256(signedCoefficient); } + } + } - if (signedCoefficientB < 0) { - if (signedCoefficientB == type(int256).min) { - signedCoefficientBAbs = uint256(type(int256).max) + 1; - } else { - signedCoefficientBAbs = uint256(-signedCoefficientB); - } - } else if (signedCoefficientB > 0) { - signedCoefficientBAbs = uint256(signedCoefficientB); - } else { - return (MAXIMIZED_ZERO_SIGNED_COEFFICIENT, MAXIMIZED_ZERO_EXPONENT); - } + function unabsUnsignedSignedCoefficientMulOrDiv(int256 a, int256 b, uint256 signedCoefficientAbs) + internal + pure + returns (int256) + { + unchecked { + return (a ^ b) < 0 ? -int256(signedCoefficientAbs) : int256(signedCoefficientAbs); } + } - // 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 + /// 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") { - let mm := mulmod(signedCoefficientAAbs, signedCoefficientBAbs, not(0)) - prod0 := mul(signedCoefficientAAbs, signedCoefficientBAbs) - prod1 := sub(sub(mm, prod0), lt(mm, prod0)) + 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 { + // mulDiv only works with unsigned integers, so get the aboslute + // values of the coefficients. + uint256 signedCoefficientAAbs = absUnsignedSignedCoefficient(signedCoefficientA); + uint256 signedCoefficientBAbs = absUnsignedSignedCoefficient(signedCoefficientB); - int256 exponent = exponentA + exponentB; + (uint256 prod1, uint256 prod0) = mul512(signedCoefficientAAbs, signedCoefficientBAbs); + + exponent = exponentA + exponentB; - unchecked { uint256 adjustExponent = 0; - while (prod1 != 0) { - prod1 /= 10; - adjustExponent++; + 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++; + } } - uint256 signedCoefficientAbs = mulDiv(signedCoefficientAAbs, signedCoefficientBAbs, 10 ** adjustExponent); - int256 signedCoefficient = (signedCoefficientA ^ signedCoefficientB) < 0 - ? -int256(signedCoefficientAbs) - : int256(signedCoefficientAbs); + + signedCoefficient = unabsUnsignedSignedCoefficientMulOrDiv( + signedCoefficientA, + signedCoefficientB, + mulDiv(signedCoefficientAAbs, signedCoefficientBAbs, uint256(10) ** adjustExponent) + ); exponent += int256(adjustExponent); - return (signedCoefficient, exponent); } } @@ -212,13 +229,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); @@ -226,28 +242,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 @@ -259,31 +258,32 @@ library LibDecimalFloatImplementation { scale = 1e75; adjustExponent = 75; } - uint256 signedCoefficientAbs = mulDiv(signedCoefficientAAbs, scale, signedCoefficientBAbs); - signedCoefficient = (signedCoefficientA ^ signedCoefficientB) < 0 - ? -int256(signedCoefficientAbs) - : int256(signedCoefficientAbs); + + signedCoefficient = unabsUnsignedSignedCoefficientMulOrDiv( + signedCoefficientA, signedCoefficientB, mulDiv(signedCoefficientAAbs, scale, signedCoefficientBAbs) + ); + exponent = exponentA - exponentB - adjustExponent; } + } - // 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..1cba3254 100644 --- a/test/lib/LibDecimalFloatSlow.sol +++ b/test/lib/LibDecimalFloatSlow.sol @@ -13,29 +13,31 @@ 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; + uint256 signedCoefficientAAbs = + LibDecimalFloatImplementation.absUnsignedSignedCoefficient(signedCoefficientA); + uint256 signedCoefficientBAbs = + LibDecimalFloatImplementation.absUnsignedSignedCoefficient(signedCoefficientB); + + (uint256 prod1, uint256 prod0) = + LibDecimalFloatImplementation.mul512(signedCoefficientAAbs, signedCoefficientBAbs); - return (signedCoefficient, exponent); + int256 exponent = exponentA + exponentB; + + uint256 adjustExponent = 0; + while (prod1 > 0) { + prod1 /= 10; + adjustExponent++; } + + uint256 signedCoefficientAbs = LibDecimalFloatImplementation.mulDiv( + signedCoefficientAAbs, signedCoefficientBAbs, uint256(10) ** adjustExponent + ); } } diff --git a/test/src/lib/implementation/LibDecimalFloatImplementation.mul.t.sol b/test/src/lib/implementation/LibDecimalFloatImplementation.mul.t.sol index 2f970238..1749ff84 100644 --- a/test/src/lib/implementation/LibDecimalFloatImplementation.mul.t.sol +++ b/test/src/lib/implementation/LibDecimalFloatImplementation.mul.t.sol @@ -109,10 +109,10 @@ contract LibDecimalFloatImplementationMulTest is Test { exponentB = bound(exponentB, EXPONENT_MIN, EXPONENT_MAX); (int256 signedCoefficient, int256 exponent) = LibDecimalFloatImplementation.mul(signedCoefficientA, exponentA, signedCoefficientB, exponentB); - // (int256 expectedSignedCoefficient, int256 expectedExponent) = - // LibDecimalFloatSlow.mulSlow(signedCoefficientA, exponentA, signedCoefficientB, exponentB); + (int256 expectedSignedCoefficient, int256 expectedExponent) = + LibDecimalFloatSlow.mulSlow(signedCoefficientA, exponentA, signedCoefficientB, exponentB); - // assertEq(signedCoefficient, expectedSignedCoefficient); - // assertEq(exponent, expectedExponent); + assertEq(signedCoefficient, expectedSignedCoefficient); + assertEq(exponent, expectedExponent); } } From b844ef2d8ec9d03007f3d3ae163e0b79091992b4 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Wed, 20 Aug 2025 20:10:58 +0400 Subject: [PATCH 05/15] lint --- src/lib/LibDecimalFloat.sol | 10 +++++ .../LibDecimalFloatImplementation.sol | 42 +++++++++++++------ test/lib/LibDecimalFloatSlow.sol | 14 +++++-- test/src/lib/LibDecimalFloat.pow.t.sol | 18 ++++---- .../LibDecimalFloatImplementation.mul.t.sol | 25 ++++++++++- .../LibDecimalFloatImplementation.pow10.t.sol | 3 +- 6 files changed, 85 insertions(+), 27 deletions(-) diff --git a/src/lib/LibDecimalFloat.sol b/src/lib/LibDecimalFloat.sol index fbfe1893..3e354af0 100644 --- a/src/lib/LibDecimalFloat.sol +++ b/src/lib/LibDecimalFloat.sol @@ -29,6 +29,8 @@ import { EXPONENT_MIN } from "./implementation/LibDecimalFloatImplementation.sol"; +import {console2} from "forge-std/console2.sol"; + type Float is bytes32; /// @dev When normalizing a number, how far we "leap" when very far from @@ -719,9 +721,17 @@ library LibDecimalFloat { (int256 signedCoefficientB, int256 exponentB) = b.unpack(); + console2.logInt(signedCoefficientC); + console2.logInt(exponentC); + console2.logInt(signedCoefficientB); + console2.logInt(exponentB); + (signedCoefficientC, exponentC) = LibDecimalFloatImplementation.mul(signedCoefficientC, exponentC, signedCoefficientB, exponentB); + console2.logInt(signedCoefficientC); + console2.logInt(exponentC); + (signedCoefficientC, exponentC) = LibDecimalFloatImplementation.pow10(tablesDataContract, signedCoefficientC, exponentC); diff --git a/src/lib/implementation/LibDecimalFloatImplementation.sol b/src/lib/implementation/LibDecimalFloatImplementation.sol index 63001f2b..bf0b1aaa 100644 --- a/src/lib/implementation/LibDecimalFloatImplementation.sol +++ b/src/lib/implementation/LibDecimalFloatImplementation.sol @@ -108,13 +108,26 @@ library LibDecimalFloatImplementation { } } - function unabsUnsignedSignedCoefficientMulOrDiv(int256 a, int256 b, uint256 signedCoefficientAbs) + function unabsUnsignedMulOrDivLossy(int256 a, int256 b, uint256 signedCoefficientAbs, int256 exponent) internal pure - returns (int256) + returns (int256, int256) { unchecked { - return (a ^ b) < 0 ? -int256(signedCoefficientAbs) : int256(signedCoefficientAbs); + // Need to minus the coefficient because a and b had different signs. + if (a ^ b < 0) { + if (signedCoefficientAbs > uint256(type(int256).max) + 1) { + 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); + } + } } } @@ -134,14 +147,14 @@ library LibDecimalFloatImplementation { signedCoefficient = MAXIMIZED_ZERO_SIGNED_COEFFICIENT; exponent = MAXIMIZED_ZERO_EXPONENT; } else { + exponent = exponentA + exponentB; + // mulDiv only works with unsigned integers, so get the aboslute // values of the coefficients. uint256 signedCoefficientAAbs = absUnsignedSignedCoefficient(signedCoefficientA); uint256 signedCoefficientBAbs = absUnsignedSignedCoefficient(signedCoefficientB); - (uint256 prod1, uint256 prod0) = mul512(signedCoefficientAAbs, signedCoefficientBAbs); - - exponent = exponentA + exponentB; + (uint256 prod1,) = mul512(signedCoefficientAAbs, signedCoefficientBAbs); uint256 adjustExponent = 0; unchecked { @@ -167,12 +180,14 @@ library LibDecimalFloatImplementation { } } - signedCoefficient = unabsUnsignedSignedCoefficientMulOrDiv( + exponent += int256(adjustExponent); + + (signedCoefficient, exponent) = unabsUnsignedMulOrDivLossy( signedCoefficientA, signedCoefficientB, - mulDiv(signedCoefficientAAbs, signedCoefficientBAbs, uint256(10) ** adjustExponent) + mulDiv(signedCoefficientAAbs, signedCoefficientBAbs, uint256(10) ** adjustExponent), + exponent ); - exponent += int256(adjustExponent); } } @@ -258,11 +273,14 @@ library LibDecimalFloatImplementation { scale = 1e75; adjustExponent = 75; } + exponent = exponentA - exponentB - adjustExponent; - signedCoefficient = unabsUnsignedSignedCoefficientMulOrDiv( - signedCoefficientA, signedCoefficientB, mulDiv(signedCoefficientAAbs, scale, signedCoefficientBAbs) + (signedCoefficient, exponent) = unabsUnsignedMulOrDivLossy( + signedCoefficientA, + signedCoefficientB, + mulDiv(signedCoefficientAAbs, scale, signedCoefficientBAbs), + exponent ); - exponent = exponentA - exponentB - adjustExponent; } } diff --git a/test/lib/LibDecimalFloatSlow.sol b/test/lib/LibDecimalFloatSlow.sol index 1cba3254..86927203 100644 --- a/test/lib/LibDecimalFloatSlow.sol +++ b/test/lib/LibDecimalFloatSlow.sol @@ -19,15 +19,14 @@ library LibDecimalFloatSlow { return (0, 0); } + int256 exponent = exponentA + exponentB; + uint256 signedCoefficientAAbs = LibDecimalFloatImplementation.absUnsignedSignedCoefficient(signedCoefficientA); uint256 signedCoefficientBAbs = LibDecimalFloatImplementation.absUnsignedSignedCoefficient(signedCoefficientB); - (uint256 prod1, uint256 prod0) = - LibDecimalFloatImplementation.mul512(signedCoefficientAAbs, signedCoefficientBAbs); - - int256 exponent = exponentA + exponentB; + (uint256 prod1,) = LibDecimalFloatImplementation.mul512(signedCoefficientAAbs, signedCoefficientBAbs); uint256 adjustExponent = 0; while (prod1 > 0) { @@ -38,6 +37,13 @@ library LibDecimalFloatSlow { 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); } } diff --git a/test/src/lib/LibDecimalFloat.pow.t.sol b/test/src/lib/LibDecimalFloat.pow.t.sol index 4f356254..740f7bd0 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); } @@ -117,14 +119,14 @@ contract LibDecimalFloatPowTest is LogTest { /// Can generally round trip whatever within 0.25% of the original value. function testRoundTripSimple() external { checkRoundTrip(5, 0, 2, 0); - checkRoundTrip(5, 0, 3, 0); - checkRoundTrip(50, 0, 40, 0); - checkRoundTrip(5, -1, 3, -1); - checkRoundTrip(5, -1, 2, -1); - checkRoundTrip(5, 10, 3, 5); - checkRoundTrip(5, -1, 100, 0); - checkRoundTrip(7721, 0, -1, -2); - checkRoundTrip(4157, 0, -1, -2); + // checkRoundTrip(5, 0, 3, 0); + // checkRoundTrip(50, 0, 40, 0); + // checkRoundTrip(5, -1, 3, -1); + // checkRoundTrip(5, -1, 2, -1); + // checkRoundTrip(5, 10, 3, 5); + // checkRoundTrip(5, -1, 100, 0); + // checkRoundTrip(7721, 0, -1, -2); + // checkRoundTrip(4157, 0, -1, -2); } function powExternal(Float a, Float b) external returns (Float) { diff --git a/test/src/lib/implementation/LibDecimalFloatImplementation.mul.t.sol b/test/src/lib/implementation/LibDecimalFloatImplementation.mul.t.sol index 1749ff84..5eea5011 100644 --- a/test/src/lib/implementation/LibDecimalFloatImplementation.mul.t.sol +++ b/test/src/lib/implementation/LibDecimalFloatImplementation.mul.t.sol @@ -12,6 +12,27 @@ 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"); + } + + /// found during testing + /// 1.3979 * 0.5 = 0.69895 + /// represented as e76 and + 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 { @@ -105,8 +126,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..ef077959 100644 --- a/test/src/lib/implementation/LibDecimalFloatImplementation.pow10.t.sol +++ b/test/src/lib/implementation/LibDecimalFloatImplementation.pow10.t.sol @@ -63,7 +63,8 @@ contract LibDecimalFloatImplementationPow10Test is LogTest { function testInterpolatedLookupsPower() external { // 10^1.55555 = 35.9376769153 checkPow10(1.55555e37, -37, 35.935e75, -75); - // 10^1234.56789 + // calculated on wolfram + // 10^1234.56789 = 3.69734519948141829344363446069899674413404079870780463377448004811497051583459624644095897334743494067266231680935688534678044962972813724... × 10^1234 checkPow10(123456789, -5, 3.6979e76, 1158); // ~= 10 (fuzzing found this edge case). checkPow10( From 368563a905b65e5fff8af00b3cc051a746892ce1 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Wed, 20 Aug 2025 20:15:35 +0400 Subject: [PATCH 06/15] lint --- src/lib/LibDecimalFloat.sol | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/lib/LibDecimalFloat.sol b/src/lib/LibDecimalFloat.sol index 3e354af0..fbfe1893 100644 --- a/src/lib/LibDecimalFloat.sol +++ b/src/lib/LibDecimalFloat.sol @@ -29,8 +29,6 @@ import { EXPONENT_MIN } from "./implementation/LibDecimalFloatImplementation.sol"; -import {console2} from "forge-std/console2.sol"; - type Float is bytes32; /// @dev When normalizing a number, how far we "leap" when very far from @@ -721,17 +719,9 @@ library LibDecimalFloat { (int256 signedCoefficientB, int256 exponentB) = b.unpack(); - console2.logInt(signedCoefficientC); - console2.logInt(exponentC); - console2.logInt(signedCoefficientB); - console2.logInt(exponentB); - (signedCoefficientC, exponentC) = LibDecimalFloatImplementation.mul(signedCoefficientC, exponentC, signedCoefficientB, exponentB); - console2.logInt(signedCoefficientC); - console2.logInt(exponentC); - (signedCoefficientC, exponentC) = LibDecimalFloatImplementation.pow10(tablesDataContract, signedCoefficientC, exponentC); From 79765b657364148f27bf5cce32efb0d0c0f55831 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Wed, 20 Aug 2025 20:17:59 +0400 Subject: [PATCH 07/15] lint --- test/src/lib/LibDecimalFloat.pow.t.sol | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/src/lib/LibDecimalFloat.pow.t.sol b/test/src/lib/LibDecimalFloat.pow.t.sol index 740f7bd0..501a1bd0 100644 --- a/test/src/lib/LibDecimalFloat.pow.t.sol +++ b/test/src/lib/LibDecimalFloat.pow.t.sol @@ -119,14 +119,14 @@ contract LibDecimalFloatPowTest is LogTest { /// Can generally round trip whatever within 0.25% of the original value. function testRoundTripSimple() external { checkRoundTrip(5, 0, 2, 0); - // checkRoundTrip(5, 0, 3, 0); - // checkRoundTrip(50, 0, 40, 0); - // checkRoundTrip(5, -1, 3, -1); - // checkRoundTrip(5, -1, 2, -1); - // checkRoundTrip(5, 10, 3, 5); - // checkRoundTrip(5, -1, 100, 0); - // checkRoundTrip(7721, 0, -1, -2); - // checkRoundTrip(4157, 0, -1, -2); + checkRoundTrip(5, 0, 3, 0); + checkRoundTrip(50, 0, 40, 0); + checkRoundTrip(5, -1, 3, -1); + checkRoundTrip(5, -1, 2, -1); + checkRoundTrip(5, 10, 3, 5); + checkRoundTrip(5, -1, 100, 0); + checkRoundTrip(7721, 0, -1, -2); + checkRoundTrip(4157, 0, -1, -2); } function powExternal(Float a, Float b) external returns (Float) { From ef163f5db7dfd6130622c4b3f518dea6d2920ea9 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Thu, 21 Aug 2025 11:39:16 +0400 Subject: [PATCH 08/15] maximized reference test --- test/lib/LibDecimalFloatSlow.sol | 15 +++++++++++++++ .../LibDecimalFloatImplementation.maximize.t.sol | 12 ++++++++++++ 2 files changed, 27 insertions(+) diff --git a/test/lib/LibDecimalFloatSlow.sol b/test/lib/LibDecimalFloatSlow.sol index 86927203..03fcdb63 100644 --- a/test/lib/LibDecimalFloatSlow.sol +++ b/test/lib/LibDecimalFloatSlow.sol @@ -191,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/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); + } } From 41982bb7aea095c54eae23400c4c5d214c9bc2da Mon Sep 17 00:00:00 2001 From: David Meister Date: Thu, 21 Aug 2025 11:42:16 +0400 Subject: [PATCH 09/15] Update test/src/lib/implementation/LibDecimalFloatImplementation.pow10.t.sol Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .../implementation/LibDecimalFloatImplementation.pow10.t.sol | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/src/lib/implementation/LibDecimalFloatImplementation.pow10.t.sol b/test/src/lib/implementation/LibDecimalFloatImplementation.pow10.t.sol index ef077959..f0e2639b 100644 --- a/test/src/lib/implementation/LibDecimalFloatImplementation.pow10.t.sol +++ b/test/src/lib/implementation/LibDecimalFloatImplementation.pow10.t.sol @@ -63,8 +63,9 @@ contract LibDecimalFloatImplementationPow10Test is LogTest { function testInterpolatedLookupsPower() external { // 10^1.55555 = 35.9376769153 checkPow10(1.55555e37, -37, 35.935e75, -75); - // calculated on wolfram - // 10^1234.56789 = 3.69734519948141829344363446069899674413404079870780463377448004811497051583459624644095897334743494067266231680935688534678044962972813724... × 10^1234 + // 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( From 294b04a2cd7709c968bc7e0e38a801032bae2b3e Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Thu, 21 Aug 2025 21:55:39 +0400 Subject: [PATCH 10/15] test unabsUnsignedMulOrDivLossy --- .../LibDecimalFloatImplementation.mul.t.sol | 61 ++++---- ...mentation.unabsUnsignedMulOrDivLossy.t.sol | 136 ++++++++++++++++++ 2 files changed, 166 insertions(+), 31 deletions(-) create mode 100644 test/src/lib/implementation/LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy.t.sol diff --git a/test/src/lib/implementation/LibDecimalFloatImplementation.mul.t.sol b/test/src/lib/implementation/LibDecimalFloatImplementation.mul.t.sol index 5eea5011..98896a90 100644 --- a/test/src/lib/implementation/LibDecimalFloatImplementation.mul.t.sol +++ b/test/src/lib/implementation/LibDecimalFloatImplementation.mul.t.sol @@ -26,6 +26,21 @@ contract LibDecimalFloatImplementationMulTest is Test { 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 /// represented as e76 and @@ -36,59 +51,48 @@ contract LibDecimalFloatImplementationMulTest is Test { /// 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 { - (int256 signedCoefficient, int256 exponent) = - LibDecimalFloatImplementation.mul(type(int256).max, 0, type(int256).max, 0); - // Numbers checked on desmos. - assertEq( - signedCoefficient, int256(3.3519519824856492748935062495514615318698414551480983444308903609304410075182e76) + checkMul( + type(int256).max, + 0, + type(int256).max, + 0, + int256(3.3519519824856492748935062495514615318698414551480983444308903609304410075182e76), + 77 ); - assertEq(exponent, 77); } /// 123456789 multiply 987654321 with exponents @@ -97,17 +101,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 { 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..5c5c6357 --- /dev/null +++ b/test/src/lib/implementation/LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy.t.sol @@ -0,0 +1,136 @@ +// 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 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. + 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"); + } +} From 37e60df0ec550c42f6d283199a3b4308d1a7c61c Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Thu, 21 Aug 2025 22:04:17 +0400 Subject: [PATCH 11/15] typo --- src/lib/implementation/LibDecimalFloatImplementation.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/implementation/LibDecimalFloatImplementation.sol b/src/lib/implementation/LibDecimalFloatImplementation.sol index bf0b1aaa..bc06384e 100644 --- a/src/lib/implementation/LibDecimalFloatImplementation.sol +++ b/src/lib/implementation/LibDecimalFloatImplementation.sol @@ -149,7 +149,7 @@ library LibDecimalFloatImplementation { } else { exponent = exponentA + exponentB; - // mulDiv only works with unsigned integers, so get the aboslute + // mulDiv only works with unsigned integers, so get the absolute // values of the coefficients. uint256 signedCoefficientAAbs = absUnsignedSignedCoefficient(signedCoefficientA); uint256 signedCoefficientBAbs = absUnsignedSignedCoefficient(signedCoefficientB); From be053b9c4073b41e7920392a31ee180c297c3d0b Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Fri, 22 Aug 2025 16:50:12 +0400 Subject: [PATCH 12/15] handle edge case in unabs --- .../LibDecimalFloatImplementation.sol | 10 ++++++++-- ...mplementation.unabsUnsignedMulOrDivLossy.t.sol | 15 +++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/lib/implementation/LibDecimalFloatImplementation.sol b/src/lib/implementation/LibDecimalFloatImplementation.sol index bc06384e..904e7593 100644 --- a/src/lib/implementation/LibDecimalFloatImplementation.sol +++ b/src/lib/implementation/LibDecimalFloatImplementation.sol @@ -116,8 +116,14 @@ library LibDecimalFloatImplementation { unchecked { // Need to minus the coefficient because a and b had different signs. if (a ^ b < 0) { - if (signedCoefficientAbs > uint256(type(int256).max) + 1) { - return (-int256(signedCoefficientAbs / 10), exponent + 1); + 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); } diff --git a/test/src/lib/implementation/LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy.t.sol b/test/src/lib/implementation/LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy.t.sol index 5c5c6357..a7fc1d5a 100644 --- a/test/src/lib/implementation/LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy.t.sol +++ b/test/src/lib/implementation/LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy.t.sol @@ -133,4 +133,19 @@ contract LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest is Test { 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"); + } } From 424ad866e0c8a946347b4511b33c06df14176fa0 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Fri, 22 Aug 2025 16:52:50 +0400 Subject: [PATCH 13/15] lint --- .../lib/implementation/LibDecimalFloatImplementation.mul.t.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/test/src/lib/implementation/LibDecimalFloatImplementation.mul.t.sol b/test/src/lib/implementation/LibDecimalFloatImplementation.mul.t.sol index 98896a90..4a90624f 100644 --- a/test/src/lib/implementation/LibDecimalFloatImplementation.mul.t.sol +++ b/test/src/lib/implementation/LibDecimalFloatImplementation.mul.t.sol @@ -43,7 +43,6 @@ contract LibDecimalFloatImplementationMulTest is Test { /// found during testing /// 1.3979 * 0.5 = 0.69895 - /// represented as e76 and function testMul1_3979_0_5() external pure { checkMul(1.3979e76, -76, 0.5e66, -66, 0.69895e76, -76); } From 77170c8993842e85a727b615bc7c926dcbc6b61c Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Fri, 22 Aug 2025 16:54:31 +0400 Subject: [PATCH 14/15] lint --- ...bDecimalFloatImplementation.unabsUnsignedMulOrDivLossy.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/src/lib/implementation/LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy.t.sol b/test/src/lib/implementation/LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy.t.sol index a7fc1d5a..e6d8d4c4 100644 --- a/test/src/lib/implementation/LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy.t.sol +++ b/test/src/lib/implementation/LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy.t.sol @@ -70,7 +70,7 @@ contract LibDecimalFloatImplementationUnabsUnsignedMulOrDivLossyTest is Test { (int256 actualSignedCoefficient, int256 actualExponent) = LibDecimalFloatImplementation.unabsUnsignedMulOrDivLossy(-int256(a), -int256(b), c, exponent); - // Expect the result to be negative. + // Expect the result to be positive. int256 expectedSignedCoefficient = int256(c / 10); int256 expectedExponent = exponent + 1; From 0281a393fd3d719015ee6a8481449124d47ce3b7 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Fri, 22 Aug 2025 16:58:49 +0400 Subject: [PATCH 15/15] snapshot --- .gas-snapshot | 423 +++++++++--------- .../LibDecimalFloatImplementation.sol | 2 +- 2 files changed, 220 insertions(+), 205 deletions(-) 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 904e7593..b385f97e 100644 --- a/src/lib/implementation/LibDecimalFloatImplementation.sol +++ b/src/lib/implementation/LibDecimalFloatImplementation.sol @@ -115,7 +115,7 @@ library LibDecimalFloatImplementation { { unchecked { // Need to minus the coefficient because a and b had different signs. - if (a ^ b < 0) { + 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