module Data.RangeMin.Internal.HandyNumeric where
import GHC.Exts
import Data.Bits(Bits(..))
import Control.Monad(join)
import Control.Arrow()
intLog :: Int -> Int
intLog 0 = 0
intLog 1 = 0
intLog (I# x) = I# (intLog1 (int2Word# x)) where
intLog1 x# = let ans# = uncheckedShiftRL# x# 16# in if ans# `eqWord#` 0## then intLog2 0# x# else intLog2 16# ans#
intLog2 r# x# = let ans# = uncheckedShiftRL# x# 8# in if ans# `eqWord#` 0## then intLog3 r# x# else intLog3 (r# +# 8#) ans#
intLog3 r# x# = let ans# = uncheckedShiftRL# x# 4# in if ans# `eqWord#` 0## then intLog4 r# x# else intLog4 (r# +# 4#) ans#
intLog4 r# x# = let ans# = uncheckedShiftRL# x# 2# in if ans# `eqWord#` 0## then intLog5 r# x# else intLog5 (r# +# 2#) ans#
intLog5 r# x# = if x# `leWord#` 1## then r# else r# +# 1#
ceilLog :: Int -> Int
ceilLog (I# i#) = intLog (I# (i# +# i# -# 1#))
floor2Pow :: Int -> Int
floor2Pow = pow2 . intLog
double :: Int -> Int
double (I# i#) = I# (i# +# i#)
pow2 :: Int -> Int
pow2 (I# i#) = I# (uncheckedIShiftL# 1# i#)
divCeil :: Int -> Int -> Int
I# a# `divCeil` I# b# = I# ((a# +# b# -# 1#) `quotInt#` b#)
modCeil :: Int -> Int -> Int
I# n# `modCeil` I# m# = let r# = n# `remInt#` m# in I# (if r# ==# 0# then m# else r#)