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

import GHC.Exts
import Data.RangeMin.Common.Types.IPVector

on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
(f `on` g) x y = f (g x) (g y)

type RM = (Int# -> Int# -> Int#)
newtype MinIx = MinIx {execMinIx :: Int# -> Int# -> Bool}
newtype SliceMin = SliceMin {execSliceMin :: Int# -> MinIx}
-- newtype ReIx = ReIx {execReIx :: Int# -> Int#}

-- | A function of type @'LEq' a@ is used as if it were @('<=')@ for comparison purposes.
type LEq a = a -> a -> Bool

-- reIx :: ReIx -> Int -> Int
-- reIx f (I# i#) = I# (execReIx f i#)
-- 
-- minReIx :: ReIx -> MinIx -> MinIx
-- minReIx rIx mIx = mIx `minIxOn` reIx rIx
-- 
-- {-# INLINE toReIx #-}
-- toReIx :: (Int -> Int) -> ReIx
-- toReIx f = ReIx $ \ i# -> case f (I# i#) of
-- 	I# j# -> j#

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

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

{-# INLINE runMinIx #-}
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 = \ i# j# -> case f (I# i#) (I# j#) of
	I# k# -> k#

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

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