Skip to content

Commit

Permalink
Improve readability
Browse files Browse the repository at this point in the history
  • Loading branch information
Lohann committed Oct 17, 2024
1 parent 4521ed4 commit 2a50166
Showing 1 changed file with 41 additions and 40 deletions.
81 changes: 41 additions & 40 deletions contracts/utils/math/Math.sol
Original file line number Diff line number Diff line change
Expand Up @@ -537,48 +537,49 @@ library Math {
* @dev Return the log in base 2 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256 result) {
function log2(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;
// If upper 8 bits of 16-bit half set, add 8 to result
r |= SafeCast.toUint((x >> r) > 0xff) << 3;
// If upper 4 bits of 8-bit half set, add 4 to result
r |= SafeCast.toUint((x >> r) > 0xf) << 2;

// Shifts value right by the current result, isolating the last significant bits.
x >>= r;

// Uses the shifted value as an index into this lookup table:
//
// | x (4 bits) | index | table[index] = MSB position |
// |------------|---------|-----------------------------|
// | 0000 | 0 | table[0] = 0 |
// | 0001 | 1 | table[1] = 0 |
// | 0010 | 2 | table[2] = 1 |
// | 0011 | 3 | table[3] = 1 |
// | 0100 | 4 | table[4] = 2 |
// | 0101 | 5 | table[5] = 2 |
// | 0110 | 6 | table[6] = 2 |
// | 0111 | 7 | table[7] = 2 |
// | 1000 | 8 | table[8] = 3 |
// | 1001 | 9 | table[9] = 3 |
// | 1010 | 10 | table[10] = 3 |
// | 1011 | 11 | table[11] = 3 |
// | 1100 | 12 | table[12] = 3 |
// | 1101 | 13 | table[13] = 3 |
// | 1110 | 14 | table[14] = 3 |
// | 1111 | 15 | table[15] = 3 |
//
// The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.
assembly {
// If value has upper 128 bits set, log2 result is at least 128
result := shl(7, lt(0xffffffffffffffffffffffffffffffff, value))
// If upper 64 bits of 128-bit half set, add 64 to result
result := or(result, shl(6, lt(0xffffffffffffffff, shr(result, value))))
// If upper 32 bits of 64-bit half set, add 32 to result
result := or(result, shl(5, lt(0xffffffff, shr(result, value))))
// If upper 16 bits of 32-bit half set, add 16 to result
result := or(result, shl(4, lt(0xffff, shr(result, value))))
// If upper 8 bits of 16-bit half set, add 8 to result
result := or(result, shl(3, lt(0xff, shr(result, value))))
// If upper 4 bits of 8-bit half set, add 4 to result
result := or(result, shl(2, lt(0xf, shr(result, value))))
// shr(result, value) shifts value right by the current result, isolating the last significant bits.
// byte(...) uses the shifted value as an index into this lookup table:
//
// | x (4 bits) | index | table[index] = MSB position |
// |------------|---------|-----------------------------|
// | 0000 | 0 | table[0] = 0 |
// | 0001 | 1 | table[1] = 0 |
// | 0010 | 2 | table[2] = 1 |
// | 0011 | 3 | table[3] = 1 |
// | 0100 | 4 | table[4] = 2 |
// | 0101 | 5 | table[5] = 2 |
// | 0110 | 6 | table[6] = 2 |
// | 0111 | 7 | table[7] = 2 |
// | 1000 | 8 | table[8] = 3 |
// | 1001 | 9 | table[9] = 3 |
// | 1010 | 10 | table[10] = 3 |
// | 1011 | 11 | table[11] = 3 |
// | 1100 | 12 | table[12] = 3 |
// | 1101 | 13 | table[13] = 3 |
// | 1110 | 14 | table[14] = 3 |
// | 1111 | 15 | table[15] = 3 |
//
// The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.
result := or(
result,
byte(shr(result, value), 0x0000010102020202030303030303030300000000000000000000000000000000)
)
x := byte(x, 0x0000010102020202030303030303030300000000000000000000000000000000)
}
r |= x;
}

/**
Expand Down

0 comments on commit 2a50166

Please sign in to comment.