Skip to content

Commit

Permalink
Optimize log256's binary search (OpenZeppelin#5284)
Browse files Browse the repository at this point in the history
  • Loading branch information
cairoeth authored Nov 26, 2024
1 parent 4afd599 commit fdf7012
Showing 1 changed file with 11 additions and 23 deletions.
34 changes: 11 additions & 23 deletions contracts/utils/math/Math.sol
Original file line number Diff line number Diff line change
Expand Up @@ -644,29 +644,17 @@ library Math {
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
uint256 isGt;
unchecked {
isGt = SafeCast.toUint(value > (1 << 128) - 1);
value >>= isGt * 128;
result += isGt * 16;

isGt = SafeCast.toUint(value > (1 << 64) - 1);
value >>= isGt * 64;
result += isGt * 8;

isGt = SafeCast.toUint(value > (1 << 32) - 1);
value >>= isGt * 32;
result += isGt * 4;

isGt = SafeCast.toUint(value > (1 << 16) - 1);
value >>= isGt * 16;
result += isGt * 2;

result += SafeCast.toUint(value > (1 << 8) - 1);
}
return result;
function log256(uint256 x) internal pure returns (uint256 r) {
// If value has upper 128 bits set, log2 result is at least 128
r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
// If upper 64 bits of 128-bit half set, add 64 to result
r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
// If upper 32 bits of 64-bit half set, add 32 to result
r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
// If upper 16 bits of 32-bit half set, add 16 to result
r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
// Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8
return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);
}

/**
Expand Down

0 comments on commit fdf7012

Please sign in to comment.