Skip to content

Commit

Permalink
T
Browse files Browse the repository at this point in the history
  • Loading branch information
Vectorized committed Jan 17, 2025
1 parent 51a5a7e commit 1a49dc3
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 12 deletions.
27 changes: 19 additions & 8 deletions src/utils/LibBit.sol
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,25 @@ library LibBit {
}
}

/// @dev Returns the common prefix of `x` and `y` in hex format.
function commonPrefix(uint256 x, uint256 y) internal pure returns (uint256 r) {
uint256 lz = clz(x ^ y);
assembly {
let nibbles := div(lz, 4)
// Since nibbles is always <= 64, there's no risk of underflow.
let bits := mul(sub(64, nibbles), 4)
r := shl(bits, shr(bits, x))
/// @dev Returns the common prefix of `x` and `y` at the bit level.
function commonBitPrefix(uint256 x, uint256 y) internal pure returns (uint256 r) {
r = clz(x ^ y);
r = (x >> r) << r;
}

/// @dev Returns the common prefix of `x` and `y` at the nibble level.
function commonNibblePrefix(uint256 x, uint256 y) internal pure returns (uint256 r) {
unchecked {
uint256 s = (64 - (clz(x ^ y) >> 2)) << 2;
r = (x >> s) << s;
}
}

/// @dev Returns the common prefix of `x` and `y` at the byte level.
function commonBytePrefix(uint256 x, uint256 y) internal pure returns (uint256 r) {
unchecked {
uint256 s = (32 - (clz(x ^ y) >> 3)) << 3;
r = (x >> s) << s;
}
}

Expand Down
13 changes: 9 additions & 4 deletions test/LibBit.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -226,15 +226,20 @@ contract LibBitTest is SoladyTest {
}

function testCommonPrefix() public {
assertEq(LibBit.commonPrefix(0x1, 0x2), 0);
assertEq(LibBit.commonPrefix(0x1234abc, 0x1234bbb), 0x1234000);
assertEq(LibBit.commonPrefix(0x1234abc, 0x1234abc), 0x1234abc);
assertEq(LibBit.commonNibblePrefix(0x1, 0x2), 0);
assertEq(LibBit.commonNibblePrefix(0x1234abc, 0x1234bbb), 0x1234000);
assertEq(LibBit.commonNibblePrefix(0x1234abc, 0x1234abc), 0x1234abc);

assertEq(LibBit.commonBytePrefix(0xaabbcc, 0xaabbcc), 0xaabbcc);
assertEq(LibBit.commonBytePrefix(0xaabbcc, 0xaabbc0), 0xaabb00);
assertEq(LibBit.commonBytePrefix(0xaabbcc, 0xaab0c0), 0xaa0000);
assertEq(LibBit.commonBytePrefix(0xaabbcc, 0xa0b0c0), 0x000000);
}

function testCommonPrefix(uint256 x, uint8 p) public {
uint256 y = x ^ (1 << p);
uint256 l = 63 - p / 4;
uint256 r = l == 0 ? 0 : x & ~((1 << ((64 - l) * 4)) - 1);
assertEq(LibBit.commonPrefix(x, y), r);
assertEq(LibBit.commonNibblePrefix(x, y), r);
}
}

0 comments on commit 1a49dc3

Please sign in to comment.