module Data.RangeMin.Int (
unsafeIntRangeMin,
intRangeMin) where
import Control.Exception
import Data.RangeMin.Common
import qualified Data.Vector.Generic as G
import qualified Data.Vector.Primitive as PV
import qualified Data.RangeMin.Int.Quadratic as N2
import qualified Data.RangeMin.Int.Linearithmic as Nlogn
import qualified Data.RangeMin.Int.NearLinear as NearN
import qualified Data.RangeMin.Int.Linear as N
negativeStart :: Int -> String
negativeStart i = "Data.RangeMin: starting index " ++ shows i " must be nonnegative"
nonPositiveWidth :: Int -> String
nonPositiveWidth m = "Data.RangeMin: query width " ++ shows m " must be positive"
outOfBoundsQuery :: Int -> Int -> Int -> String
outOfBoundsQuery n i m = "Data.RangeMin: query " ++ shows (i, m)
(" is too big for a vector of size " ++ show n)
checkBounds :: Int -> (Int -> Int -> a) -> Int -> Int -> a
checkBounds !n f !i !m
| i < 0 = throw (IndexOutOfBounds (negativeStart i))
| m < 1 = throw (IndexOutOfBounds (nonPositiveWidth m))
| i + m > n
= throw (IndexOutOfBounds (outOfBoundsQuery n i m))
| otherwise
= f i m
internalIntRangeMin :: PV.Vector Int -> RM
internalIntRangeMin !xs
| n <= n2Cross = N2.rangeMin xs
| n <= nlognCross = Nlogn.rangeMin xs
| n <= nearNCross = NearN.rangeMin xs
| otherwise = N.rangeMin xs
where !n = PV.length xs
#define vec ('PV.fromList' [0,7,-10,4,5,4])
unsafeIntRangeMin ::
PV.Vector Int
-> RangeMin
unsafeIntRangeMin xs = runRM (internalIntRangeMin xs)
intRangeMin ::
PV.Vector Int
-> RangeMin
intRangeMin !xs =
let !rM = internalIntRangeMin xs in checkBounds (PV.length xs) (runRM rM)