{-# LANGUAGE MagicHash #-}
module Data.RangeMin.Common.Types (SliceMin, runSliceMin, toSliceMin, LEq, RM, MinIx, runMinIx, pickMinIx, toMinIx, minIxOn, toRM, runRM, onRM) where

import GHC.Exts
import Data.RangeMin.Common.Combinators

newtype RM = RM {execRM :: Int# -> Int# -> Int#}
newtype MinIx = MinIx {execMinIx :: Int# -> Int# -> Bool}
newtype SliceMin = SliceMin {execSliceMin :: Int# -> MinIx}
type LEq a = a -> a -> Bool

runSliceMin :: SliceMin -> Int -> MinIx
runSliceMin s (I# i#) = execSliceMin s i#

{-# INLINE toSliceMin #-}
toSliceMin :: (Int -> MinIx) -> SliceMin
toSliceMin f = SliceMin $ \ i# -> f (I# i#)

runMinIx :: MinIx -> Int -> Int -> Bool
runMinIx m (I# i#) (I# j#) = execMinIx m i# j#

{-# INLINE minIxOn #-}
minIxOn :: MinIx -> (Int -> Int) -> MinIx
minIxOn mIx f = toMinIx (runMinIx mIx `on` f)

{-# INLINE pickMinIx #-}
pickMinIx :: MinIx -> Int -> Int -> Int
pickMinIx m i@(I# i#) j@(I# j#) = if execMinIx m i# j# then i else j

{-# INLINE toMinIx #-}
toMinIx :: (Int -> Int -> Bool) -> MinIx
toMinIx f = MinIx $ \ i# j# -> f (I# i#) (I# j#)

{-# INLINE toRM #-}
toRM :: (Int -> Int -> Int) -> RM
toRM f = RM $ \ i# j# -> case f (I# i#) (I# j#) of
	I# k# -> k#

runRM :: RM -> Int -> Int -> Int
runRM f (I# i#) (I# j#) = I# (execRM f i# j#)

{-# INLINE onRM #-}
onRM :: (Int -> Int) -> RM -> RM
onRM f rm = toRM (\ i j -> f (runRM rm i j))