{-# LANGUAGE BangPatterns, MagicHash #-}
module Data.RangeMin.Common.Math (bit', div', mod',  ceilLog, intLog) where

-- import Data.Word (Word)
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)