module Data.RangeMin.Int.Quadratic (rangeMin) where
import qualified Data.RangeMin.Fusion as F
import Data.RangeMin.Common
rangeMin :: PVector Value -> RM
rangeMin !xs = let
!table = quadTable xs
!m = 2 * n 1
encode !i !d = shiftR' ((i) * (m i)) 1 + d 2
in toRM $ \ i j -> if j == 1 then i else table ! encode i j
where !n = vlength xs
data Q = Q !Int !Int !Int !Value
quadTable :: PVector Value -> PVector Index
quadTable !xs = F.convert $ F.unfoldN (shiftR' (n * (n 1)) 1) suc (Q 0 1 0 (xs ! 0)) where
!n = vlength xs
suc (Q i j x vx)
| j < n = let vj = xs ! j in
if vx <= vj then Just (x, Q i (j+1) x vx) else Just (j, Q i (j+1) j vj)
suc (Q i0 _ _ _) = let i = i0 + 1; i' = i + 1 in
if i' < n then let vi = xs ! i; vi' = xs ! i' in
if vi <= vi' then Just (i, Q i (i'+1) i vi) else
Just (i', Q i (i'+1) i' vi')
else Nothing