Skip to content

Commit fdf7012

Browse files
authored
Optimize log256's binary search (#5284)
1 parent 4afd599 commit fdf7012

File tree

1 file changed

+11
-23
lines changed

1 file changed

+11
-23
lines changed

contracts/utils/math/Math.sol

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -644,29 +644,17 @@ library Math {
644644
*
645645
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
646646
*/
647-
function log256(uint256 value) internal pure returns (uint256) {
648-
uint256 result = 0;
649-
uint256 isGt;
650-
unchecked {
651-
isGt = SafeCast.toUint(value > (1 << 128) - 1);
652-
value >>= isGt * 128;
653-
result += isGt * 16;
654-
655-
isGt = SafeCast.toUint(value > (1 << 64) - 1);
656-
value >>= isGt * 64;
657-
result += isGt * 8;
658-
659-
isGt = SafeCast.toUint(value > (1 << 32) - 1);
660-
value >>= isGt * 32;
661-
result += isGt * 4;
662-
663-
isGt = SafeCast.toUint(value > (1 << 16) - 1);
664-
value >>= isGt * 16;
665-
result += isGt * 2;
666-
667-
result += SafeCast.toUint(value > (1 << 8) - 1);
668-
}
669-
return result;
647+
function log256(uint256 x) internal pure returns (uint256 r) {
648+
// If value has upper 128 bits set, log2 result is at least 128
649+
r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
650+
// If upper 64 bits of 128-bit half set, add 64 to result
651+
r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
652+
// If upper 32 bits of 64-bit half set, add 32 to result
653+
r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
654+
// If upper 16 bits of 32-bit half set, add 16 to result
655+
r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
656+
// Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8
657+
return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);
670658
}
671659

672660
/**

0 commit comments

Comments
 (0)