From 2c531361747afd3b417d91a4160c50fc2058efec Mon Sep 17 00:00:00 2001 From: Shuhui Luo <107524008+shuhuiluo@users.noreply.github.com> Date: Sun, 31 Dec 2023 03:12:29 -0800 Subject: [PATCH] Import optimized bit math from Solady --- .gas-snapshot | 22 +++++++++++----------- src/BitMath.sol | 20 ++++++-------------- src/TickMath.sol | 15 ++++----------- 3 files changed, 21 insertions(+), 36 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index 2008702..eead584 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,8 +1,8 @@ BitMathTest:testFuzz_LSB(uint256) (runs: 65536, μ: 14911, ~: 14909) -BitMathTest:testFuzz_MSB(uint256) (runs: 65536, μ: 14791, ~: 14816) +BitMathTest:testFuzz_MSB(uint256) (runs: 65536, μ: 14771, ~: 14796) BitMathTest:testGas_LSB() (gas: 193393) BitMathTest:testGas_LSB_Og() (gas: 291088) -BitMathTest:testGas_MSB() (gas: 213472) +BitMathTest:testGas_MSB() (gas: 208372) BitMathTest:testGas_MSB_Og() (gas: 274437) FullMathTest:testFuzz_MulDiv96(uint256,uint256) (runs: 65536, μ: 3601, ~: 3585) FullMathTest:testFuzz_MulDivUp_OZ(uint256,uint256,uint256) (runs: 65536, μ: 4391, ~: 4237) @@ -107,21 +107,21 @@ SwapMathTest:testGas_ComputeSwapStepExactIn_Og() (gas: 515722) SwapMathTest:testGas_ComputeSwapStepExactOut() (gas: 370755) SwapMathTest:testGas_ComputeSwapStepExactOut_Og() (gas: 510266) SwapMathTest:testGas_ComputeSwapStep_Og() (gas: 526558) -TickBitmapTest:testFuzz_Compress(int24,int24) (runs: 65536, μ: 8348, ~: 8393) -TickBitmapTest:testFuzz_FlipTick(int24) (runs: 65536, μ: 61584, ~: 61590) -TickBitmapTest:testFuzz_NextInitializedTickWithinOneWord(int24,uint8,bool) (runs: 65536, μ: 67891, ~: 67871) +TickBitmapTest:testFuzz_Compress(int24,int24) (runs: 65536, μ: 8348, ~: 8382) +TickBitmapTest:testFuzz_FlipTick(int24) (runs: 65536, μ: 61570, ~: 61576) +TickBitmapTest:testFuzz_NextInitializedTickWithinOneWord(int24,uint8,bool) (runs: 65536, μ: 67880, ~: 67868) TickBitmapTest:testFuzz_Position(int24) (runs: 65536, μ: 498, ~: 498) -TickBitmapTest:testGas_NextInitializedTickWithinOneWord() (gas: 6776007) +TickBitmapTest:testGas_NextInitializedTickWithinOneWord() (gas: 6769095) TickBitmapTest:testGas_NextInitializedTickWithinOneWord_Og() (gas: 7050256) TickBitmapTest:test_NextInitializedTickWithinOneWord_GT() (gas: 203148) -TickBitmapTest:test_NextInitializedTickWithinOneWord_LTE() (gas: 212522) +TickBitmapTest:test_NextInitializedTickWithinOneWord_LTE() (gas: 204586) TickBitmapTest:test_NextInitializedTick_GT() (gas: 342054) -TickBitmapTest:test_NextInitializedTick_LTE() (gas: 399975) -TickMathTest:testFuzz_GetSqrtRatioAtTick(int24) (runs: 65536, μ: 16536, ~: 16831) -TickMathTest:testFuzz_GetTickAtSqrtRatio(uint160) (runs: 65536, μ: 13140, ~: 13159) +TickBitmapTest:test_NextInitializedTick_LTE() (gas: 388455) +TickMathTest:testFuzz_GetSqrtRatioAtTick(int24) (runs: 65536, μ: 16522, ~: 16817) +TickMathTest:testFuzz_GetTickAtSqrtRatio(uint160) (runs: 65536, μ: 13125, ~: 13145) TickMathTest:testGas_GetSqrtRatioAtTick() (gas: 146478) TickMathTest:testGas_GetSqrtRatioAtTick_Og() (gas: 168547) -TickMathTest:testGas_GetTickAtSqrtRatio() (gas: 252577) +TickMathTest:testGas_GetTickAtSqrtRatio() (gas: 251177) TickMathTest:testGas_GetTickAtSqrtRatio_Og() (gas: 307790) TickMathTest:testRevert_GetSqrtRatioAtTick() (gas: 10445) TickMathTest:testRevert_GetTickAtSqrtRatio() (gas: 10522) \ No newline at end of file diff --git a/src/BitMath.sol b/src/BitMath.sol index 25fef87..74c7573 100644 --- a/src/BitMath.sol +++ b/src/BitMath.sol @@ -21,21 +21,13 @@ library BitMath { r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x)))) // r += (x >> r) >= 2**32 ? 32 : 0 r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) - - // For the remaining 32 bits, use a De Bruijn lookup. - // https://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn - x := shr(r, x) - x := or(x, shr(1, x)) - x := or(x, shr(2, x)) - x := or(x, shr(4, x)) - x := or(x, shr(8, x)) - x := or(x, shr(16, x)) - + r := or(r, shl(4, lt(0xffff, shr(r, x)))) + r := or(r, shl(3, lt(0xff, shr(r, x)))) r := or( r, byte( - shr(251, mul(x, shl(224, 0x07c4acdd))), - 0x0009010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f + and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)), + 0x0706060506020504060203020504030106050205030304010505030400000000 ) ) } @@ -65,8 +57,8 @@ library BitMath { r := or( r, byte( - shr(251, mul(shr(r, x), shl(224, 0x077cb531))), - 0x00011c021d0e18031e16140f191104081f1b0d17151310071a0c12060b050a09 + and(div(0xd76453e0, shr(r, x)), 0x1f), + 0x001f0d1e100c1d070f090b19131c1706010e11080a1a141802121b1503160405 ) ) } diff --git a/src/TickMath.sol b/src/TickMath.sol index 72b682a..f0ccade 100644 --- a/src/TickMath.sol +++ b/src/TickMath.sol @@ -135,20 +135,13 @@ library TickMath { msb := shl(7, lt(0xffffffffffffffffffffffffffffffff, x)) msb := or(msb, shl(6, lt(0xffffffffffffffff, shr(msb, x)))) msb := or(msb, shl(5, lt(0xffffffff, shr(msb, x)))) - - // For the remaining 32 bits, use a De Bruijn lookup. - x := shr(msb, x) - x := or(x, shr(1, x)) - x := or(x, shr(2, x)) - x := or(x, shr(4, x)) - x := or(x, shr(8, x)) - x := or(x, shr(16, x)) - + msb := or(msb, shl(4, lt(0xffff, shr(msb, x)))) + msb := or(msb, shl(3, lt(0xff, shr(msb, x)))) msb := or( msb, byte( - shr(251, mul(x, shl(224, 0x07c4acdd))), - 0x0009010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f + and(0x1f, shr(shr(msb, x), 0x8421084210842108cc6318c6db6d54be)), + 0x0706060506020504060203020504030106050205030304010505030400000000 ) ) }