{-# LANGUAGE CPP #-}
module Data.Vector.Algorithms.Optimal
       ( sort2ByIndex
       , sort2ByOffset
       , sort3ByIndex
       , sort3ByOffset
       , sort4ByIndex
       , sort4ByOffset
       , Comparison
       ) where
import Prelude hiding (read, length)
import Control.Monad.Primitive
import Data.Vector.Generic.Mutable
import Data.Vector.Algorithms.Common (Comparison)
#include "vector.h"
sort2ByOffset :: (PrimMonad m, MVector v e)
              => Comparison e -> v (PrimState m) e -> Int -> m ()
sort2ByOffset :: Comparison e -> v (PrimState m) e -> Int -> m ()
sort2ByOffset Comparison e
cmp v (PrimState m) e
a Int
off = Comparison e -> v (PrimState m) e -> Int -> Int -> m ()
forall (m :: * -> *) (v :: * -> * -> *) e.
(PrimMonad m, MVector v e) =>
Comparison e -> v (PrimState m) e -> Int -> Int -> m ()
sort2ByIndex Comparison e
cmp v (PrimState m) e
a Int
off (Int
off Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
{-# INLINABLE sort2ByOffset #-}
sort2ByIndex :: (PrimMonad m, MVector v e)
             => Comparison e -> v (PrimState m) e -> Int -> Int -> m ()
sort2ByIndex :: Comparison e -> v (PrimState m) e -> Int -> Int -> m ()
sort2ByIndex Comparison e
cmp v (PrimState m) e
a Int
i Int
j = UNSAFE_CHECK(checkIndex) "sort2ByIndex" i (length a)
                       (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ UNSAFE_CHECK(checkIndex) "sort2ByIndex" j (length a) $  do
  a0 <- unsafeRead a i
  a1 <- unsafeRead a j
  case cmp a0 a1 of
    GT -> unsafeWrite a i a1 >> unsafeWrite a j a0
    _  -> return ()
{-# INLINABLE sort2ByIndex #-}
sort3ByOffset :: (PrimMonad m, MVector v e)
              => Comparison e -> v (PrimState m) e -> Int -> m ()
sort3ByOffset :: Comparison e -> v (PrimState m) e -> Int -> m ()
sort3ByOffset Comparison e
cmp v (PrimState m) e
a Int
off = Comparison e -> v (PrimState m) e -> Int -> Int -> Int -> m ()
forall (m :: * -> *) (v :: * -> * -> *) e.
(PrimMonad m, MVector v e) =>
Comparison e -> v (PrimState m) e -> Int -> Int -> Int -> m ()
sort3ByIndex Comparison e
cmp v (PrimState m) e
a Int
off (Int
off Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) (Int
off Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
2)
{-# INLINABLE sort3ByOffset #-}
sort3ByIndex :: (PrimMonad m, MVector v e)
             => Comparison e -> v (PrimState m) e -> Int -> Int -> Int -> m ()
sort3ByIndex :: Comparison e -> v (PrimState m) e -> Int -> Int -> Int -> m ()
sort3ByIndex Comparison e
cmp v (PrimState m) e
a Int
i Int
j Int
k = UNSAFE_CHECK(checkIndex) "sort3ByIndex" i (length a)
                         (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ UNSAFE_CHECK(checkIndex) "sort3ByIndex" j (length a)
                         (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ UNSAFE_CHECK(checkIndex) "sort3ByIndex" k (length a) $ do
  a0 <- unsafeRead a i
  a1 <- unsafeRead a j
  a2 <- unsafeRead a k
  case cmp a0 a1 of
    GT -> case cmp a0 a2 of
            GT -> case cmp a2 a1 of
                    LT -> do unsafeWrite a i a2
                             unsafeWrite a k a0
                    _  -> do unsafeWrite a i a1
                             unsafeWrite a j a2
                             unsafeWrite a k a0
            _  -> do unsafeWrite a i a1
                     unsafeWrite a j a0
    _  -> case cmp a1 a2 of
            GT -> case cmp a0 a2 of
                    GT -> do unsafeWrite a i a2
                             unsafeWrite a j a0
                             unsafeWrite a k a1
                    _  -> do unsafeWrite a j a2
                             unsafeWrite a k a1
            _  -> return ()
{-# INLINABLE sort3ByIndex #-}
sort4ByOffset :: (PrimMonad m, MVector v e)
              => Comparison e -> v (PrimState m) e -> Int -> m ()
sort4ByOffset :: Comparison e -> v (PrimState m) e -> Int -> m ()
sort4ByOffset Comparison e
cmp v (PrimState m) e
a Int
off = Comparison e
-> v (PrimState m) e -> Int -> Int -> Int -> Int -> m ()
forall (m :: * -> *) (v :: * -> * -> *) e.
(PrimMonad m, MVector v e) =>
Comparison e
-> v (PrimState m) e -> Int -> Int -> Int -> Int -> m ()
sort4ByIndex Comparison e
cmp v (PrimState m) e
a Int
off (Int
off Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) (Int
off Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
2) (Int
off Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
3)
{-# INLINABLE sort4ByOffset #-}
sort4ByIndex :: (PrimMonad m, MVector v e)
             => Comparison e -> v (PrimState m) e -> Int -> Int -> Int -> Int -> m ()
sort4ByIndex :: Comparison e
-> v (PrimState m) e -> Int -> Int -> Int -> Int -> m ()
sort4ByIndex Comparison e
cmp v (PrimState m) e
a Int
i Int
j Int
k Int
l = UNSAFE_CHECK(checkIndex) "sort4ByIndex" i (length a)
                           (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ UNSAFE_CHECK(checkIndex) "sort4ByIndex" j (length a)
                           (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ UNSAFE_CHECK(checkIndex) "sort4ByIndex" k (length a)
                           (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ UNSAFE_CHECK(checkIndex) "sort4ByIndex" l (length a) $ do
  a0 <- unsafeRead a i
  a1 <- unsafeRead a j
  a2 <- unsafeRead a k
  a3 <- unsafeRead a l
  case cmp a0 a1 of
    GT -> case cmp a0 a2 of
            GT -> case cmp a1 a2 of
                    GT -> case cmp a1 a3 of
                            GT -> case cmp a2 a3 of
                                    GT -> do unsafeWrite a i a3
                                             unsafeWrite a j a2
                                             unsafeWrite a k a1
                                             unsafeWrite a l a0
                                    _  -> do unsafeWrite a i a2
                                             unsafeWrite a j a3
                                             unsafeWrite a k a1
                                             unsafeWrite a l a0
                            _  -> case cmp a0 a3 of
                                    GT -> do unsafeWrite a i a2
                                             unsafeWrite a j a1
                                             unsafeWrite a k a3
                                             unsafeWrite a l a0
                                    _  -> do unsafeWrite a i a2
                                             unsafeWrite a j a1
                                             unsafeWrite a k a0
                                             unsafeWrite a l a3
                    _ -> case cmp a2 a3 of
                           GT -> case cmp a1 a3 of
                                   GT -> do unsafeWrite a i a3
                                            unsafeWrite a j a1
                                            unsafeWrite a k a2
                                            unsafeWrite a l a0
                                   _  -> do unsafeWrite a i a1
                                            unsafeWrite a j a3
                                            unsafeWrite a k a2
                                            unsafeWrite a l a0
                           _  -> case cmp a0 a3 of
                                   GT -> do unsafeWrite a i a1
                                            unsafeWrite a j a2
                                            unsafeWrite a k a3
                                            unsafeWrite a l a0
                                   _  -> do unsafeWrite a i a1
                                            unsafeWrite a j a2
                                            unsafeWrite a k a0
                                            
            _  -> case cmp a0 a3 of
                    GT -> case cmp a1 a3 of
                            GT -> do unsafeWrite a i a3
                                     
                                     unsafeWrite a k a0
                                     unsafeWrite a l a2
                            _  -> do unsafeWrite a i a1
                                     unsafeWrite a j a3
                                     unsafeWrite a k a0
                                     unsafeWrite a l a2
                    _  -> case cmp a2 a3 of
                            GT -> do unsafeWrite a i a1
                                     unsafeWrite a j a0
                                     unsafeWrite a k a3
                                     unsafeWrite a l a2
                            _  -> do unsafeWrite a i a1
                                     unsafeWrite a j a0
                                     
                                     
    _  -> case cmp a1 a2 of
            GT -> case cmp a0 a2 of
                    GT -> case cmp a0 a3 of
                            GT -> case cmp a2 a3 of
                                    GT -> do unsafeWrite a i a3
                                             unsafeWrite a j a2
                                             unsafeWrite a k a0
                                             unsafeWrite a l a1
                                    _  -> do unsafeWrite a i a2
                                             unsafeWrite a j a3
                                             unsafeWrite a k a0
                                             unsafeWrite a l a1
                            _  -> case cmp a1 a3 of
                                    GT -> do unsafeWrite a i a2
                                             unsafeWrite a j a0
                                             unsafeWrite a k a3
                                             unsafeWrite a l a1
                                    _  -> do unsafeWrite a i a2
                                             unsafeWrite a j a0
                                             unsafeWrite a k a1
                                             
                    _  -> case cmp a2 a3 of
                            GT -> case cmp a0 a3 of
                                    GT -> do unsafeWrite a i a3
                                             unsafeWrite a j a0
                                             
                                             unsafeWrite a l a1
                                    _  -> do 
                                             unsafeWrite a j a3
                                             
                                             unsafeWrite a l a1
                            _  -> case cmp a1 a3 of
                                    GT -> do 
                                             unsafeWrite a j a2
                                             unsafeWrite a k a3
                                             unsafeWrite a l a1
                                    _  -> do 
                                             unsafeWrite a j a2
                                             unsafeWrite a k a1
                                             
            _  -> case cmp a1 a3 of
                    GT -> case cmp a0 a3 of
                            GT -> do unsafeWrite a i a3
                                     unsafeWrite a j a0
                                     unsafeWrite a k a1
                                     unsafeWrite a l a2
                            _  -> do 
                                     unsafeWrite a j a3
                                     unsafeWrite a k a1
                                     unsafeWrite a l a2
                    _  -> case cmp a2 a3 of
                            GT -> do 
                                     
                                     unsafeWrite a k a3
                                     unsafeWrite a l a2
                            _  -> do 
                                     
                                     
                                     
                                     return ()
{-# INLINABLE sort4ByIndex #-}