{-# LANGUAGE CPP #-} module Data.RangeMin.Inject ( Injective, unsafeInjectRangeMin, unsafeInjectRangeMax, injectRangeMin, injectRangeMax) where import Data.RangeMin.Common import Data.RangeMin.Int import Data.RangeMin.Vector import Data.RangeMin.Cartesian.Spec import qualified Data.Vector.Primitive as PV import qualified Data.Vector.Generic as G #define injection An order-preserving function into 'Int'. (The ordering on the elements is \ equivalent to @\\ x y -> f x '<=' f y@.) #define injectDoc(inj,other,cmp) /O(n)/. @'inj' f xs@ is equivalent to \ @'other' (\\ x y -> f x 'cmp' f y) xs@, but is frequently much faster, \ fusing with the input vector and converting it directly to a @'PV.Vector' 'Int'@. {-# INLINE unsafeInjectRangeMin #-} -- | injectDoc(unsafeInjectRangeMin,unsafeVecRangeMinBy,<=) The returned function /does not/ do bounds checks; -- see 'unsafeIntRangeMin' for details. unsafeInjectRangeMin :: G.Vector v a => (a -> Int) -- ^ injection -> v a -- ^ The input vector. -> RangeMin -- ^ A range-min function on the elements (under the above ordering) -- which runs in /O(1)/. {-# INLINE unsafeInjectRangeMax #-} -- | injectDoc(unsafeInjectRangeMax,unsafeVecRangeMinBy,>=) The returned function /does not/ do bounds checks; -- see 'unsafeIntRangeMin' for details. unsafeInjectRangeMax :: G.Vector v a => (a -> Int) -- ^ injection -> v a -- ^ The input vector. -> RangeMin -- ^ A range-max function on the elements (under the above ordering) -- which runs in /O(1)/. {-# INLINE injectRangeMin #-} -- | injectDoc(injectRangeMin,vecRangeMinBy,<=) The returned function /does/ do bounds checks; see 'intRangeMin' for details. injectRangeMin :: G.Vector v a => (a -> Int) -- ^ injection -> v a -- ^ The input vector. -> RangeMin -- ^ A range-min function on the elements (under the above ordering) -- which runs in /O(1)/. {-# INLINE injectRangeMax #-} -- | injectDoc(injectRangeMax,vecRangeMinBy,>=) The returned function /does/ do bounds checks; see 'intRangeMin' for details. injectRangeMax :: G.Vector v a => (a -> Int) -- ^ injection -> v a -- ^ The input vector. -> RangeMin -- ^ A range-max function on the elements (under the above ordering) -- which runs in /O(1)/. unsafeInjectRangeMin inject xs = unsafeIntRangeMin (G.unstream (fmap inject (G.stream xs))) unsafeInjectRangeMax inject = unsafeInjectRangeMin (invertValue . inject) injectRangeMin inject xs = intRangeMin (G.unstream (fmap inject (G.stream xs))) injectRangeMax inject = injectRangeMin (invertValue . inject)