I am not sure if this is appropriate. I am afraid that I am reprogramming countLeadingZeros in some form ...
Anyway, the idea is that the snoc bit on the left is shifted to the right. Then we can βcountβ the trailing zeros of x using x-1 and XOR. The result of "counting" is the mask "00..01..11", which, roughly speaking, is a unary representation of trailing zeros. We do not convert this unary to binary, because we do not need: with some work at the bit level, we can uncons.
What follows is an unverified and unproven code.
import Data.Word import Data.Bits import Text.Printf type T = Word64 -- can be adapted to any WordN -- for pretty printing pr :: T -> String pr x = printf "%064b\n" x empty :: T empty = shiftL 1 63 snoc :: T -> T -> T snoc x xs = shiftR xs 1 .|. (shiftL x 63) -- returns (head, tail) -- head is not normalized (0 or 1), only (0 or /=0) uncons :: T -> (T, T) uncons xs = let -- example -- 0101001100000000000 xs y = (xs `xor` (xs - 1)) -- 0000000111111111111 y z = shiftR y 1 + 1 -- 0000000100000000000 z z' = shiftL z 1 -- 0000001000000000000 z' in (xs .&. z' , (xs .&. complement z) .|. z' )
source share