module Data.RangeMin.Common.Math (bit', div', mod', ceilLog, intLog) where
import Data.Bits (Bits(..))
import GHC.Exts
div' :: Int -> Int -> Int
I# i# `div'` I# j# = I# (quotInt# i# j#)
mod' :: Int -> Int -> Int
I# i# `mod'` I# j# = I# (remInt# i# j#)
bit' :: Int -> Int
bit' (I# i#) = I# (uncheckedIShiftL# 1# i#)
ceilLog :: Int -> Int
ceilLog n = intLog (2 * n 1)
intLog :: Int -> Int
intLog = wordLog . fromIntegral
wordLog :: Word -> Int
wordLog v = intLog4 v 0 where
intLog4 !v !r
| v .&. 0xFFFF0000 == 0 = intLog3 v r
| otherwise = intLog3 (v `shiftR` 16) (r .|. 16)
intLog3 !v !r
| v .&. 0xFF00 == 0 = intLog2 v r
| otherwise = intLog2 (v `shiftR` 8) (r .|. 8)
intLog2 !v !r
| v .&. 0xF0 == 0 = intLog1 v r
| otherwise = intLog1 (v `shiftR` 4) (r .|. 4)
intLog1 !v !r
| v .&. 0xC == 0 = intLog0 v r
| otherwise = intLog0 (v `shiftR` 2) (r .|. 2)
intLog0 :: Word -> Word -> Int
intLog0 !v !r
| v .&. 0x2 == 0 = fromIntegral r
| otherwise = fromIntegral (r .|. 1)