Skip to content

Commit 7f5b1b3

Browse files
committed
Make Math.log2 branchless
1 parent 192e873 commit 7f5b1b3

File tree

2 files changed

+46
-26
lines changed

2 files changed

+46
-26
lines changed

.changeset/nervous-pans-grow.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'openzeppelin-solidity': patch
3+
---
4+
5+
Make Math.log2 branchless

contracts/utils/math/Math.sol

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -391,42 +391,57 @@ library Math {
391391
* @dev Return the log in base 2 of a positive value rounded towards zero.
392392
* Returns 0 if given 0.
393393
*/
394-
function log2(uint256 value) internal pure returns (uint256) {
395-
uint256 result = 0;
394+
function log2(uint256 value) internal pure returns (uint256 result) {
396395
unchecked {
397-
if (value >> 128 > 0) {
398-
value >>= 128;
399-
result += 128;
396+
uint256 isGt;
397+
398+
assembly {
399+
isGt := gt(value, 0xffffffffffffffffffffffffffffffff)
400400
}
401-
if (value >> 64 > 0) {
402-
value >>= 64;
403-
result += 64;
401+
value >>= isGt * 128;
402+
result += isGt * 128;
403+
404+
assembly {
405+
isGt := gt(value, 0xffffffffffffffff)
404406
}
405-
if (value >> 32 > 0) {
406-
value >>= 32;
407-
result += 32;
407+
value >>= isGt * 64;
408+
result += isGt * 64;
409+
410+
assembly {
411+
isGt := gt(value, 0xffffffff)
408412
}
409-
if (value >> 16 > 0) {
410-
value >>= 16;
411-
result += 16;
413+
value >>= isGt * 32;
414+
result += isGt * 32;
415+
416+
assembly {
417+
isGt := gt(value, 0xffff)
412418
}
413-
if (value >> 8 > 0) {
414-
value >>= 8;
415-
result += 8;
419+
value >>= isGt * 16;
420+
result += isGt * 16;
421+
422+
assembly {
423+
isGt := gt(value, 0xff)
416424
}
417-
if (value >> 4 > 0) {
418-
value >>= 4;
419-
result += 4;
425+
value >>= isGt * 8;
426+
result += isGt * 8;
427+
428+
assembly {
429+
isGt := gt(value, 0xf)
420430
}
421-
if (value >> 2 > 0) {
422-
value >>= 2;
423-
result += 2;
431+
value >>= isGt * 4;
432+
result += isGt * 4;
433+
434+
assembly {
435+
isGt := gt(value, 0x3)
424436
}
425-
if (value >> 1 > 0) {
426-
result += 1;
437+
value >>= isGt * 2;
438+
result += isGt * 2;
439+
440+
assembly {
441+
isGt := gt(value, 0x1)
427442
}
443+
result += isGt;
428444
}
429-
return result;
430445
}
431446

432447
/**

0 commit comments

Comments
 (0)