Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
420 changes: 212 additions & 208 deletions .gas-snapshot

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions src/lib/LibDecimalFloat.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ import {
} from "../error/ErrDecimalFloat.sol";
import {
LibDecimalFloatImplementation,
NORMALIZED_ZERO_SIGNED_COEFFICIENT,
NORMALIZED_ZERO_EXPONENT,
NORMALIZED_MIN,
NORMALIZED_MAX,
EXPONENT_STEP_SIZE,
Expand Down
106 changes: 23 additions & 83 deletions src/lib/implementation/LibDecimalFloatImplementation.sol
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,10 @@ int256 constant SIGNED_NORMALIZED_MAX = 1e38 - 1;
uint256 constant NORMALIZED_MAX_PLUS_ONE = 1e38;
int256 constant SIGNED_NORMALIZED_MAX_PLUS_ONE = 1e38;

/// @dev The signed coefficient of zero when normalized.
int256 constant NORMALIZED_ZERO_SIGNED_COEFFICIENT = 0;
/// @dev The exponent of zero when normalized.
int256 constant NORMALIZED_ZERO_EXPONENT = 0;

/// @dev The signed coefficient of maximized zero.
int256 constant MAXIMIZED_ZERO_SIGNED_COEFFICIENT = NORMALIZED_ZERO_SIGNED_COEFFICIENT;
int256 constant MAXIMIZED_ZERO_SIGNED_COEFFICIENT = 0;
/// @dev The exponent of maximized zero.
int256 constant MAXIMIZED_ZERO_EXPONENT = NORMALIZED_ZERO_EXPONENT;
int256 constant MAXIMIZED_ZERO_EXPONENT = 0;

library LibDecimalFloatImplementation {
/// Negates and normalizes a float.
Expand Down Expand Up @@ -585,24 +580,24 @@ library LibDecimalFloatImplementation {
{
unchecked {
{
(signedCoefficient, exponent) = normalize(signedCoefficient, exponent);

if (signedCoefficient <= 0) {
if (signedCoefficient == 0) {
revert Log10Zero();
} else {
revert Log10Negative(signedCoefficient, exponent);
}
}
(signedCoefficient, exponent) = maximize(signedCoefficient, exponent);
}

// This is a positive log. i.e. log(x) where x >= 1.
if (exponent > -38) {
// This is an exact power of 10.
if (signedCoefficient == 1e37) {
return (exponent + 37, 0);
}
// all powers of 10 look like 1 with a different exponent
if (signedCoefficient == 1e76) {
return (exponent + 76, 0);
}
bool isAtLeastE76 = signedCoefficient >= 1e76;

// This is a positive log. i.e. log(x) where x >= 1.
if (exponent > (isAtLeastE76 ? -77 : -76)) {
int256 y1Coefficient;
Comment thread
thedavidmeister marked this conversation as resolved.
Comment thread
thedavidmeister marked this conversation as resolved.
int256 y2Coefficient;
int256 x1Coefficient;
Expand All @@ -612,7 +607,6 @@ library LibDecimalFloatImplementation {

// Table lookup.
{
uint256 scale = 1e34;
assembly ("memory-safe") {
Comment thread
thedavidmeister marked this conversation as resolved.
//slither-disable-next-line divide-before-multiply
Comment thread
thedavidmeister marked this conversation as resolved.
function lookupTableVal(tables, index) -> result {
Expand All @@ -639,6 +633,10 @@ library LibDecimalFloatImplementation {
result := add(result, mload(0))
}

// let scale := 1e72;
let scale := 1000000000000000000000000000000000000000000000000000000000000000000000000
if isAtLeastE76 { scale := mul(scale, 10) }

Comment thread
thedavidmeister marked this conversation as resolved.
Outdated
// Truncate the signed coefficient to what we can look
// up in the table.
// Slither false positive because the truncation is
Expand All @@ -648,29 +646,31 @@ library LibDecimalFloatImplementation {
let idx := sub(x1Coefficient, 1000)
x1Coefficient := mul(x1Coefficient, scale)
x2Coefficient := add(x1Coefficient, scale)
interpolate := iszero(eq(x1Coefficient, signedCoefficient))

if isAtLeastE76 { scale := div(scale, 10) }

y1Coefficient := mul(scale, lookupTableVal(tablesDataContract, idx))

interpolate := iszero(eq(x1Coefficient, signedCoefficient))

if interpolate { y2Coefficient := mul(scale, lookupTableVal(tablesDataContract, add(idx, 1))) }
}
}

if (interpolate) {
(signedCoefficient, exponent) = unitLinearInterpolation(
x1Coefficient, signedCoefficient, x2Coefficient, exponent, y1Coefficient, y2Coefficient, -38
x1Coefficient, signedCoefficient, x2Coefficient, exponent, y1Coefficient, y2Coefficient, -76
);
} else {
signedCoefficient = y1Coefficient;
exponent = -38;
exponent = -76;
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

return add(signedCoefficient, exponent, x1Exponent + 37, 0);
return add(signedCoefficient, exponent, x1Exponent + (isAtLeastE76 ? int256(76) : int256(75)), 0);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
}
// This is a negative log. i.e. log(x) where 0 < x < 1.
// log(x) = -log(1/x)
else {
(signedCoefficient, exponent) = div(1e37, -37, signedCoefficient, exponent);
(signedCoefficient, exponent) = inv(signedCoefficient, exponent);
(signedCoefficient, exponent) = log10(tablesDataContract, signedCoefficient, exponent);
return minus(signedCoefficient, exponent);
}
Expand Down Expand Up @@ -795,66 +795,6 @@ library LibDecimalFloatImplementation {
return result;
}

function normalize(int256 signedCoefficient, int256 exponent) internal pure returns (int256, int256) {
unchecked {
if (isNormalized(signedCoefficient, exponent)) {
return (signedCoefficient, exponent);
}

if (signedCoefficient == 0) {
return (NORMALIZED_ZERO_SIGNED_COEFFICIENT, NORMALIZED_ZERO_EXPONENT);
}

if (exponent / EXPONENT_MAX_PLUS_ONE != 0) {
revert ExponentOverflow(signedCoefficient, exponent);
}

if (signedCoefficient / SIGNED_NORMALIZED_MAX_PLUS_ONE != 0) {
if (signedCoefficient / 1e56 != 0) {
signedCoefficient /= 1e19;
exponent += 19;
}

if (signedCoefficient / 1e46 != 0) {
signedCoefficient /= 1e9;
exponent += 9;
}

while (signedCoefficient / 1e39 != 0) {
signedCoefficient /= 100;
exponent += 2;
}

if (signedCoefficient / 1e38 != 0) {
signedCoefficient /= 10;
exponent += 1;
}
} else {
if (signedCoefficient / 1e18 == 0) {
signedCoefficient *= 1e19;
exponent -= 19;
}

if (signedCoefficient / 1e28 == 0) {
signedCoefficient *= 1e9;
exponent -= 9;
}

while (signedCoefficient / 1e36 == 0) {
signedCoefficient *= 100;
exponent -= 2;
}

if (signedCoefficient / 1e37 == 0) {
signedCoefficient *= 10;
exponent -= 1;
}
}

return (signedCoefficient, exponent);
}
}

/// Rescale two floats so that they are possible to directly compare using
/// standard operators on the signed coefficient.
///
Expand Down Expand Up @@ -973,7 +913,7 @@ library LibDecimalFloatImplementation {
} else if (targetExponent > exponent) {
int256 exponentDiff = targetExponent - exponent;
if (exponentDiff > 76 || exponentDiff < 0) {
return (NORMALIZED_ZERO_SIGNED_COEFFICIENT);
return (MAXIMIZED_ZERO_SIGNED_COEFFICIENT);
}
Comment thread
thedavidmeister marked this conversation as resolved.
Comment thread
thedavidmeister marked this conversation as resolved.

return signedCoefficient / int256(10 ** uint256(exponentDiff));
Comment thread
thedavidmeister marked this conversation as resolved.
Expand Down
8 changes: 1 addition & 7 deletions test/src/lib/LibDecimalFloat.pow.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ contract LibDecimalFloatPowTest is LogTest {
Float c = a.pow(b, tables);
uint256 afterGas = gasleft();
console2.log("Gas used:", beforeGas - afterGas);
console2.logInt(signedCoefficientA);
console2.logInt(exponentA);
(int256 actualSignedCoefficient, int256 actualExponent) = c.unpack();
assertEq(actualSignedCoefficient, expectedSignedCoefficient, "signedCoefficient");
assertEq(actualExponent, expectedExponent, "exponent");
Expand Down Expand Up @@ -66,11 +64,7 @@ contract LibDecimalFloatPowTest is LogTest {
a = a.minus();
}
(int256 signedCoefficientA, int256 exponentA) = a.unpack();
(int256 signedCoefficientANormalized, int256 exponentANormalized) =
LibDecimalFloatImplementation.normalize(signedCoefficientA, exponentA);
vm.expectRevert(
abi.encodeWithSelector(Log10Negative.selector, signedCoefficientANormalized, exponentANormalized)
);
vm.expectRevert(abi.encodeWithSelector(Log10Negative.selector, signedCoefficientA, exponentA));
this.powExternal(a, b);
}

Expand Down
4 changes: 1 addition & 3 deletions test/src/lib/LibDecimalFloat.sqrt.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,7 @@ contract LibDecimalFloatSqrtTest is LogTest {
address tables = logTables();

(int256 signedCoefficient, int256 exponent) = a.unpack();
(int256 signedCoefficientNormalized, int256 exponentNormalized) =
LibDecimalFloatImplementation.normalize(signedCoefficient, exponent);
vm.expectRevert(abi.encodeWithSelector(Log10Negative.selector, signedCoefficientNormalized, exponentNormalized));
vm.expectRevert(abi.encodeWithSelector(Log10Negative.selector, signedCoefficient, exponent));
this.sqrtExternal(a, tables);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ contract LibDecimalFloatImplementationDivTest is Test {
}

function testDivByNegativeOneFloat(int256 signedCoefficient, int256 exponent) external pure {
exponent = bound(exponent, type(int256).min + 76, type(int256).max);
exponent = bound(exponent, type(int256).min + 76, type(int256).max - 1);
(int256 expectedCoefficient, int256 expectedExponent) =
LibDecimalFloatImplementation.maximize(signedCoefficient, exponent);
(expectedCoefficient, expectedExponent) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,14 @@ contract LibDecimalFloatImplementationLog10Test is LogTest {
checkLog10(1000, 0, 3, 0);
checkLog10(10000, 0, 4, 0);
checkLog10(1e37, -37, 0, 0);
checkLog10(1e76, -76, 0, 0);
}

function testExactLookupsLog10() external {
checkLog10(1001, 0, 3.0004e76, -76);
checkLog10(100.1e1, -1, 2.0004e76, -76);
checkLog10(10.01e2, -2, 1.0004e76, -76);
checkLog10(1.001e3, -3, 0.0004e38, -38);
checkLog10(1.001e3, -3, 0.0004e76, -76);

checkLog10(10.02e2, -2, 1.0009e76, -76);
checkLog10(10.99e2, -2, 1.0411e76, -76);
Expand All @@ -48,6 +49,8 @@ contract LibDecimalFloatImplementationLog10Test is LogTest {
}

function testSub1() external {
checkLog10(0.1001e4, -4, -0.9996e38, -38);
checkLog10(0.1001e4, -4, -0.9996e76, -76);

checkLog10(0.5e1, -1, -0.301e76, -76);
}
Comment thread
thedavidmeister marked this conversation as resolved.
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ pragma solidity =0.8.25;
import {
LibDecimalFloatImplementation,
EXPONENT_MIN,
EXPONENT_MAX,
NORMALIZED_ZERO_SIGNED_COEFFICIENT,
NORMALIZED_ZERO_EXPONENT
EXPONENT_MAX
} from "src/lib/implementation/LibDecimalFloatImplementation.sol";
import {Test} from "forge-std/Test.sol";
import {LibDecimalFloatSlow} from "test/lib/LibDecimalFloatSlow.sol";
Expand Down

This file was deleted.

Loading