{-# LANGUAGE TypeFamilies #-}
module Data.Vector.Algorithms.Insertion
( sort
, sortBy
, sortByBounds
, sortByBounds'
, Comparison
) where
import Prelude hiding (read, length)
import Control.Monad.Primitive
import Data.Vector.Generic.Mutable
import Data.Vector.Algorithms.Common (Comparison)
import qualified Data.Vector.Algorithms.Optimal as O
sort :: (PrimMonad m, MVector v e, Ord e) => v (PrimState m) e -> m ()
sort = sortBy compare
{-# INLINABLE sort #-}
sortBy :: (PrimMonad m, MVector v e) => Comparison e -> v (PrimState m) e -> m ()
sortBy cmp a = sortByBounds cmp a 0 (length a)
{-# INLINE sortBy #-}
sortByBounds :: (PrimMonad m, MVector v e)
=> Comparison e -> v (PrimState m) e -> Int -> Int -> m ()
sortByBounds cmp a l u
| len < 2 = return ()
| len == 2 = O.sort2ByOffset cmp a l
| len == 3 = O.sort3ByOffset cmp a l
| len == 4 = O.sort4ByOffset cmp a l
| otherwise = O.sort4ByOffset cmp a l >> sortByBounds' cmp a l (l + 4) u
where
len = u - l
{-# INLINE sortByBounds #-}
sortByBounds' :: (PrimMonad m, MVector v e)
=> Comparison e -> v (PrimState m) e -> Int -> Int -> Int -> m ()
sortByBounds' cmp a l m u = sort m
where
sort i
| i < u = do v <- unsafeRead a i
insert cmp a l v i
sort (i+1)
| otherwise = return ()
{-# INLINE sortByBounds' #-}
insert :: (PrimMonad m, MVector v e)
=> Comparison e -> v (PrimState m) e -> Int -> e -> Int -> m ()
insert cmp a l = loop
where
loop val j
| j <= l = unsafeWrite a l val
| otherwise = do e <- unsafeRead a (j - 1)
case cmp val e of
LT -> unsafeWrite a j e >> loop val (j - 1)
_ -> unsafeWrite a j val
{-# INLINE insert #-}