Skip to content

Commit

Permalink
Optimize
Browse files Browse the repository at this point in the history
  • Loading branch information
Vectorized committed Dec 13, 2023
1 parent 9817cd5 commit b85c610
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 93 deletions.
82 changes: 41 additions & 41 deletions .gas-snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -247,15 +247,15 @@ ERC4337Test:testValidateUserOp() (gas: 491533)
ERC4337Test:test__codesize() (gas: 54065)
ERC4626Test:testDepositWithNoApprovalReverts() (gas: 16371)
ERC4626Test:testDepositWithNotEnoughApprovalReverts() (gas: 89884)
ERC4626Test:testDifferentialFullMulDiv(uint256,uint256,uint256) (runs: 256, μ: 3343, ~: 3201)
ERC4626Test:testDifferentialFullMulDiv(uint256,uint256,uint256) (runs: 256, μ: 3342, ~: 3201)
ERC4626Test:testMetadata() (gas: 15439)
ERC4626Test:testMintWithNoApprovalReverts() (gas: 16345)
ERC4626Test:testMintZero() (gas: 54317)
ERC4626Test:testMultipleMintDepositRedeemWithdraw() (gas: 425667)
ERC4626Test:testRedeemWithNoShareAmountReverts() (gas: 10918)
ERC4626Test:testRedeemWithNotEnoughShareAmountReverts() (gas: 142915)
ERC4626Test:testSingleDepositWithdraw(uint128) (runs: 256, μ: 202684, ~: 202694)
ERC4626Test:testSingleMintRedeem(uint128) (runs: 256, μ: 201605, ~: 201615)
ERC4626Test:testSingleDepositWithdraw(uint128) (runs: 256, μ: 202683, ~: 202694)
ERC4626Test:testSingleMintRedeem(uint128) (runs: 256, μ: 201604, ~: 201615)
ERC4626Test:testTryGetAssetDecimals() (gas: 30490416)
ERC4626Test:testUseVirtualShares() (gas: 2442168)
ERC4626Test:testVaultInteractionsForSomeoneElse() (gas: 296189)
Expand Down Expand Up @@ -373,20 +373,20 @@ FixedPointMathLibTest:testAvgEdgeCase() (gas: 492)
FixedPointMathLibTest:testAvgSigned() (gas: 897)
FixedPointMathLibTest:testCbrt() (gas: 10261)
FixedPointMathLibTest:testCbrt(uint256) (runs: 256, μ: 1424, ~: 1513)
FixedPointMathLibTest:testCbrtBack(uint256) (runs: 256, μ: 30495, ~: 29427)
FixedPointMathLibTest:testCbrtBack(uint256) (runs: 256, μ: 31752, ~: 42267)
FixedPointMathLibTest:testCbrtWad() (gas: 12006)
FixedPointMathLibTest:testCbrtWad(uint256) (runs: 256, μ: 1997, ~: 2005)
FixedPointMathLibTest:testClamp(uint256,uint256,uint256) (runs: 256, μ: 546, ~: 546)
FixedPointMathLibTest:testClampSigned(int256,int256,int256) (runs: 256, μ: 611, ~: 611)
FixedPointMathLibTest:testDist() (gas: 634)
FixedPointMathLibTest:testDist(int256,int256) (runs: 256, μ: 519, ~: 524)
FixedPointMathLibTest:testDist(int256,int256) (runs: 256, μ: 518, ~: 514)
FixedPointMathLibTest:testDistEdgeCases() (gas: 570)
FixedPointMathLibTest:testDivWad() (gas: 702)
FixedPointMathLibTest:testDivWad(uint256,uint256) (runs: 256, μ: 791, ~: 913)
FixedPointMathLibTest:testDivWad(uint256,uint256) (runs: 256, μ: 798, ~: 913)
FixedPointMathLibTest:testDivWadEdgeCases() (gas: 458)
FixedPointMathLibTest:testDivWadOverflowReverts(uint256,uint256) (runs: 256, μ: 3749, ~: 3749)
FixedPointMathLibTest:testDivWadUp() (gas: 3062)
FixedPointMathLibTest:testDivWadUp(uint256,uint256) (runs: 256, μ: 785, ~: 942)
FixedPointMathLibTest:testDivWadUp(uint256,uint256) (runs: 256, μ: 793, ~: 942)
FixedPointMathLibTest:testDivWadUpEdgeCases() (gas: 483)
FixedPointMathLibTest:testDivWadUpOverflowReverts(uint256,uint256) (runs: 256, μ: 3748, ~: 3748)
FixedPointMathLibTest:testDivWadUpZeroDenominatorReverts() (gas: 3239)
Expand All @@ -397,44 +397,44 @@ FixedPointMathLibTest:testExpWad() (gas: 7544)
FixedPointMathLibTest:testFactorial() (gas: 98825)
FixedPointMathLibTest:testFactorialOriginal() (gas: 94187)
FixedPointMathLibTest:testFullMulDiv() (gas: 1189)
FixedPointMathLibTest:testFullMulDiv(uint256,uint256,uint256) (runs: 256, μ: 1394, ~: 996)
FixedPointMathLibTest:testFullMulDivUp(uint256,uint256,uint256) (runs: 256, μ: 1769, ~: 1539)
FixedPointMathLibTest:testFullMulDiv(uint256,uint256,uint256) (runs: 256, μ: 1376, ~: 996)
FixedPointMathLibTest:testFullMulDivUp(uint256,uint256,uint256) (runs: 256, μ: 1746, ~: 1539)
FixedPointMathLibTest:testFullMulDivUpRevertsIfRoundedUpResultOverflowsCase1() (gas: 3688)
FixedPointMathLibTest:testFullMulDivUpRevertsIfRoundedUpResultOverflowsCase2() (gas: 3699)
FixedPointMathLibTest:testGcd() (gas: 4206)
FixedPointMathLibTest:testGcd(uint256,uint256) (runs: 256, μ: 5119, ~: 2408)
FixedPointMathLibTest:testLambertW0WadAccuracy() (gas: 7194)
FixedPointMathLibTest:testLambertW0WadAccuracy(uint184) (runs: 256, μ: 1691, ~: 386)
FixedPointMathLibTest:testLambertW0WadKnownValues() (gas: 1699205)
FixedPointMathLibTest:testLambertW0WadMonoDebug() (gas: 783283)
FixedPointMathLibTest:testLambertW0WadMonotonicallyIncreasing() (gas: 18639147)
FixedPointMathLibTest:testLambertW0WadMonotonicallyIncreasing(int256,int256) (runs: 256, μ: 7155, ~: 7040)
FixedPointMathLibTest:testLambertW0WadMonotonicallyIncreasing2() (gas: 4090726)
FixedPointMathLibTest:testLambertW0WadMonotonicallyIncreasingAround(int256) (runs: 256, μ: 26964, ~: 23672)
FixedPointMathLibTest:testLambertW0WadMonotonicallyIncreasingAround2(uint96) (runs: 256, μ: 41148, ~: 17702)
FixedPointMathLibTest:testLambertW0WadRevertsForOutOfDomain() (gas: 16546)
FixedPointMathLibTest:testLambertW0WadWithinBounds() (gas: 124171)
FixedPointMathLibTest:testLambertW0WadWithinBounds(int256) (runs: 256, μ: 3163, ~: 2322)
FixedPointMathLibTest:testGcd(uint256,uint256) (runs: 256, μ: 5049, ~: 2223)
FixedPointMathLibTest:testLambertW0WadAccuracy() (gas: 7193)
FixedPointMathLibTest:testLambertW0WadAccuracy(uint184) (runs: 256, μ: 1706, ~: 386)
FixedPointMathLibTest:testLambertW0WadKnownValues() (gas: 1700404)
FixedPointMathLibTest:testLambertW0WadMonoDebug() (gas: 783131)
FixedPointMathLibTest:testLambertW0WadMonotonicallyIncreasing() (gas: 18657507)
FixedPointMathLibTest:testLambertW0WadMonotonicallyIncreasing(int256,int256) (runs: 256, μ: 7089, ~: 6888)
FixedPointMathLibTest:testLambertW0WadMonotonicallyIncreasing2() (gas: 4089974)
FixedPointMathLibTest:testLambertW0WadMonotonicallyIncreasingAround(int256) (runs: 256, μ: 26664, ~: 17568)
FixedPointMathLibTest:testLambertW0WadMonotonicallyIncreasingAround2(uint96) (runs: 256, μ: 57160, ~: 17694)
FixedPointMathLibTest:testLambertW0WadRevertsForOutOfDomain() (gas: 16545)
FixedPointMathLibTest:testLambertW0WadWithinBounds() (gas: 124153)
FixedPointMathLibTest:testLambertW0WadWithinBounds(int256) (runs: 256, μ: 3072, ~: 1273)
FixedPointMathLibTest:testLnWad() (gas: 2145)
FixedPointMathLibTest:testLnWadBig() (gas: 2178)
FixedPointMathLibTest:testLnWadNegativeReverts() (gas: 3198)
FixedPointMathLibTest:testLnWadOverflowReverts() (gas: 3173)
FixedPointMathLibTest:testLnWadSmall() (gas: 2758)
FixedPointMathLibTest:testLog10() (gas: 76167)
FixedPointMathLibTest:testLog10(uint256,uint256) (runs: 256, μ: 2153, ~: 2215)
FixedPointMathLibTest:testLog10(uint256,uint256) (runs: 256, μ: 2161, ~: 2222)
FixedPointMathLibTest:testLog10Up() (gas: 4413)
FixedPointMathLibTest:testLog2() (gas: 243209)
FixedPointMathLibTest:testLog256() (gas: 22853)
FixedPointMathLibTest:testLog256(uint256,uint256) (runs: 256, μ: 2030, ~: 2129)
FixedPointMathLibTest:testLog256(uint256,uint256) (runs: 256, μ: 2023, ~: 2091)
FixedPointMathLibTest:testLog256Up() (gas: 1249)
FixedPointMathLibTest:testLog2Differential(uint256) (runs: 256, μ: 870, ~: 864)
FixedPointMathLibTest:testLog2Differential(uint256) (runs: 256, μ: 869, ~: 858)
FixedPointMathLibTest:testLog2Up() (gas: 297368)
FixedPointMathLibTest:testMax(uint256,uint256) (runs: 256, μ: 518, ~: 523)
FixedPointMathLibTest:testMaxCasted(uint32,uint32,uint256) (runs: 256, μ: 887, ~: 892)
FixedPointMathLibTest:testMaxSigned(int256,int256) (runs: 256, μ: 541, ~: 537)
FixedPointMathLibTest:testMin(uint256,uint256) (runs: 256, μ: 498, ~: 494)
FixedPointMathLibTest:testMinBrutalized(uint256,uint256) (runs: 256, μ: 829, ~: 839)
FixedPointMathLibTest:testMinSigned(int256,int256) (runs: 256, μ: 475, ~: 480)
FixedPointMathLibTest:testMax(uint256,uint256) (runs: 256, μ: 517, ~: 513)
FixedPointMathLibTest:testMaxCasted(uint32,uint32,uint256) (runs: 256, μ: 886, ~: 882)
FixedPointMathLibTest:testMaxSigned(int256,int256) (runs: 256, μ: 542, ~: 547)
FixedPointMathLibTest:testMin(uint256,uint256) (runs: 256, μ: 499, ~: 504)
FixedPointMathLibTest:testMinBrutalized(uint256,uint256) (runs: 256, μ: 830, ~: 839)
FixedPointMathLibTest:testMinSigned(int256,int256) (runs: 256, μ: 474, ~: 470)
FixedPointMathLibTest:testMulDiv() (gas: 1890)
FixedPointMathLibTest:testMulDiv(uint256,uint256,uint256) (runs: 256, μ: 691, ~: 794)
FixedPointMathLibTest:testMulDivEdgeCases() (gas: 718)
Expand All @@ -448,15 +448,15 @@ FixedPointMathLibTest:testMulDivUpZeroDenominatorReverts(uint256,uint256) (runs:
FixedPointMathLibTest:testMulDivZeroDenominatorReverts() (gas: 3252)
FixedPointMathLibTest:testMulDivZeroDenominatorReverts(uint256,uint256) (runs: 256, μ: 3377, ~: 3377)
FixedPointMathLibTest:testMulWad() (gas: 714)
FixedPointMathLibTest:testMulWad(uint256,uint256) (runs: 256, μ: 719, ~: 854)
FixedPointMathLibTest:testMulWad(uint256,uint256) (runs: 256, μ: 720, ~: 854)
FixedPointMathLibTest:testMulWadEdgeCases() (gas: 692)
FixedPointMathLibTest:testMulWadOverflowReverts(uint256,uint256) (runs: 256, μ: 3832, ~: 3832)
FixedPointMathLibTest:testMulWadUp() (gas: 815)
FixedPointMathLibTest:testMulWadUp(uint256,uint256) (runs: 256, μ: 848, ~: 1065)
FixedPointMathLibTest:testMulWadUp(uint256,uint256) (runs: 256, μ: 851, ~: 1065)
FixedPointMathLibTest:testMulWadUpEdgeCases() (gas: 793)
FixedPointMathLibTest:testMulWadUpOverflowReverts(uint256,uint256) (runs: 256, μ: 3769, ~: 3769)
FixedPointMathLibTest:testPackUnpackSci() (gas: 129349)
FixedPointMathLibTest:testPackUnpackSci(uint256) (runs: 256, μ: 30153, ~: 30109)
FixedPointMathLibTest:testPackUnpackSci(uint256) (runs: 256, μ: 30151, ~: 30088)
FixedPointMathLibTest:testRPow() (gas: 3276)
FixedPointMathLibTest:testRPowOverflowReverts() (gas: 4973)
FixedPointMathLibTest:testRawAdd(int256,int256) (runs: 256, μ: 484, ~: 484)
Expand All @@ -472,19 +472,19 @@ FixedPointMathLibTest:testRawSMod(int256,int256) (runs: 256, μ: 422, ~: 422)
FixedPointMathLibTest:testRawSub(int256,int256) (runs: 256, μ: 463, ~: 463)
FixedPointMathLibTest:testRawSub(uint256,uint256) (runs: 256, μ: 440, ~: 440)
FixedPointMathLibTest:testSci() (gas: 1838613)
FixedPointMathLibTest:testSci(uint256) (runs: 256, μ: 32082, ~: 37538)
FixedPointMathLibTest:testSci2(uint256) (runs: 256, μ: 900, ~: 911)
FixedPointMathLibTest:testSci(uint256) (runs: 256, μ: 31365, ~: 33716)
FixedPointMathLibTest:testSci2(uint256) (runs: 256, μ: 901, ~: 911)
FixedPointMathLibTest:testSqrt() (gas: 42576)
FixedPointMathLibTest:testSqrt(uint256) (runs: 256, μ: 1037, ~: 1086)
FixedPointMathLibTest:testSqrtBack(uint256) (runs: 256, μ: 13876, ~: 363)
FixedPointMathLibTest:testSqrtHashed(uint256) (runs: 256, μ: 53141, ~: 53549)
FixedPointMathLibTest:testSqrtBack(uint256) (runs: 256, μ: 13866, ~: 363)
FixedPointMathLibTest:testSqrtHashed(uint256) (runs: 256, μ: 53130, ~: 53342)
FixedPointMathLibTest:testSqrtHashedSingle() (gas: 53041)
FixedPointMathLibTest:testSqrtWad() (gas: 7470)
FixedPointMathLibTest:testSqrtWad(uint256) (runs: 256, μ: 1493, ~: 1498)
FixedPointMathLibTest:testZZZ() (gas: 2731)
FixedPointMathLibTest:testZeroFloorSub(uint256,uint256) (runs: 256, μ: 501, ~: 473)
FixedPointMathLibTest:testZeroFloorSubCasted(uint32,uint32,uint256) (runs: 256, μ: 924, ~: 886)
FixedPointMathLibTest:test__codesize() (gas: 39879)
FixedPointMathLibTest:testZeroFloorSub(uint256,uint256) (runs: 256, μ: 505, ~: 534)
FixedPointMathLibTest:testZeroFloorSubCasted(uint32,uint32,uint256) (runs: 256, μ: 928, ~: 967)
FixedPointMathLibTest:test__codesize() (gas: 39870)
GasBurnerLibTest:testBurnGas() (gas: 1700805)
GasBurnerLibTest:test__codesize() (gas: 1435)
JSONParserLibTest:testDecodeEncodedStringDoesNotRevert(string) (runs: 256, μ: 58291, ~: 57099)
Expand Down
99 changes: 47 additions & 52 deletions src/utils/FixedPointMathLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -291,63 +291,58 @@ library FixedPointMathLib {
/// See: https://en.wikipedia.org/wiki/Lambert_W_function
/// a.k.a. Product log function. This is an approximation of the principal branch.
function lambertW0Wad(int256 x) internal pure returns (int256 w) {
if ((w = x) <= -367879441171442322) revert OutOfDomain(); // `x` less than `-1/e`.
uint256 c; // Whether we need to avoid catastrophic cancellation.
uint256 i = 4; // Number of iterations.
if (w <= 0x1ffffffffffff) {
if (-0x4000000000000 <= w) {
i = 1; // Inputs near zero only take one step to converge.
} else if (w <= -0x3ffffffffffffff) {
i = 32; // Inputs near `-1/e` take very long to converge.
}
} else if (w >> 63 == 0) {
/// @solidity memory-safe-assembly
assembly {
// Inline log2 for more performance, since the range is small.
let v := shr(49, w)
let l := shl(3, lt(0xff, v))
// forgefmt: disable-next-item
l := add(or(l, byte(and(0x1f, shr(shr(l, v), 0x8421084210842108cc6318c6db6d54be)),
0x0706060506020504060203020504030106050205030304010505030400000000)), 49)
w := sdiv(shl(l, 7), byte(sub(l, 31), 0x0303030303030303040506080c13))
c := gt(l, 60)
i := add(2, add(gt(l, 53), c))
}
} else {
// `ln(x) - ln(ln(x)) + b * ln(ln(x)) / ln(x)`.
int256 ll = lnWad(w = lnWad(w));
/// @solidity memory-safe-assembly
assembly {
w := add(sdiv(mul(ll, 1023715080943847266), w), sub(w, ll))
i := add(3, iszero(shr(68, x)))
c := iszero(shr(143, x))
}
if (c == 0) {
int256 wad = int256(WAD);
int256 p = x;
// If `x` is big, use Newton's so that intermediate values won't overflow.
do {
int256 e = expWad(w);
// forgefmt: disable-next-item
unchecked {
if ((w = x) <= -367879441171442322) revert OutOfDomain(); // `x` less than `-1/e`.
int256 wad = int256(WAD);
int256 p = x;
uint256 c; // Whether we need to avoid catastrophic cancellation.
uint256 i = 4; // Number of iterations.
if (w <= 0x1ffffffffffff) {
if (-0x4000000000000 <= w) {
i = 1; // Inputs near zero only take one step to converge.
} else if (w <= -0x3ffffffffffffff) {
i = 32; // Inputs near `-1/e` take very long to converge.
}
} else if (w >> 63 == 0) {
/// @solidity memory-safe-assembly
assembly {
// Inline log2 for more performance, since the range is small.
let v := shr(49, w)
let l := shl(3, lt(0xff, v))
l := add(or(l, byte(and(0x1f, shr(shr(l, v), 0x8421084210842108cc6318c6db6d54be)),
0x0706060506020504060203020504030106050205030304010505030400000000)), 49)
w := sdiv(shl(l, 7), byte(sub(l, 31), 0x0303030303030303040506080c13))
c := gt(l, 60)
i := add(2, add(gt(l, 53), c))
}
} else {
// `ln(x) - ln(ln(x)) + b * ln(ln(x)) / ln(x)`.
int256 ll = lnWad(w = lnWad(w));
/// @solidity memory-safe-assembly
assembly {
w := add(sdiv(mul(ll, 1023715080943847266), w), sub(w, ll))
i := add(3, iszero(shr(68, x)))
c := iszero(shr(143, x))
}
if (c == 0) {
do { // If `x` is big, use Newton's so that intermediate values won't overflow.
int256 e = expWad(w);
/// @solidity memory-safe-assembly
assembly {
let t := mul(w, div(e, wad))
w := sub(w, sdiv(sub(t, x), div(add(e, t), wad)))
}
if (p <= w) break;
p = w;
} while (--i != 0);
/// @solidity memory-safe-assembly
assembly {
let t := mul(w, div(e, wad))
w := sub(w, sdiv(sub(t, x), div(add(e, t), wad)))
i := sub(i, 1)
w := sub(w, sgt(w, 2))
}
if (p <= w) break;
p = w;
} while (i != 0);
/// @solidity memory-safe-assembly
assembly {
w := sub(w, sgt(w, 2))
return w;
}
return w;
}
}
// forgefmt: disable-next-item
unchecked {
int256 wad = int256(WAD);
int256 p = x;
do { // Otherwise, use Halley's for faster convergence.
int256 e = expWad(w);
/// @solidity memory-safe-assembly
Expand Down

0 comments on commit b85c610

Please sign in to comment.