From 51a5a7ee879ea2ddc7fe69164bd6f008716bbb33 Mon Sep 17 00:00:00 2001
From: JChoy <jchoyeclipse@gmail.com>
Date: Fri, 17 Jan 2025 08:17:52 +0900
Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20commonPrefix=20(#1306)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/utils/LibBit.sol | 11 +++++++++++
 test/LibBit.t.sol    | 13 +++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/src/utils/LibBit.sol b/src/utils/LibBit.sol
index eb617691a0..b6a8826cd1 100644
--- a/src/utils/LibBit.sol
+++ b/src/utils/LibBit.sol
@@ -117,6 +117,17 @@ 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))
+        }
+    }
+
     /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
     /*                     BOOLEAN OPERATIONS                     */
     /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
diff --git a/test/LibBit.t.sol b/test/LibBit.t.sol
index 2d9694288c..ba641b1b53 100644
--- a/test/LibBit.t.sol
+++ b/test/LibBit.t.sol
@@ -224,4 +224,17 @@ contract LibBitTest is SoladyTest {
             r := mload(0x00)
         }
     }
+
+    function testCommonPrefix() public {
+        assertEq(LibBit.commonPrefix(0x1, 0x2), 0);
+        assertEq(LibBit.commonPrefix(0x1234abc, 0x1234bbb), 0x1234000);
+        assertEq(LibBit.commonPrefix(0x1234abc, 0x1234abc), 0x1234abc);
+    }
+
+    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);
+    }
 }