{- Split a number into 64-bit blocks -} import Data.Bits ((.&.), (.|.), shiftR, shiftL) -- ! -- Shift operations (.<<) :: Integer -> Int -> Integer (.<<) = shiftL (>>.) :: Integer -> Int -> Integer (>>.) = shiftR split_in_u64s :: Integer -> (Integer, Integer, Integer, Integer) split_in_u64s i = (x3, x2, x1, x0) where mask = (1 .<< 64) - 1 x3 = (i >>. 192) .&. mask x2 = (i >>. 128) .&. mask x1 = (i >>. 64) .&. mask x0 = i .&. mask split_ex = split_in_u64s (x*y) where x = (2 .<< 64) .|. (2 .<< 32) y = (1 .<< 128) - 3 combine_u64s :: (Integer, Integer, Integer, Integer) -> Integer combine_u64s (x3, x2, x1, x0) = (x3 .<< 192) .|. (x2 .<< 128) .|. (x1 .<< 64) .|. x0 div_split :: Integer -> Integer -> ((Integer, Integer, Integer, Integer), (Integer, Integer)) div_split x y = (split_in_u64s q, (r1, r0)) where (_, _, r1, r0) = split_in_u64s r r = x `mod` y q = x `div` y div_tricky :: ((Integer, Integer, Integer, Integer), (Integer, Integer)) div_tricky = div_split x y where x = combine_u64s (2338623232362770208, 2968197749036490859, 9499753957944579205, 10687495549587570827) y = (18446744073709551615 .<< 64) .|. 18446744073709551610