{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE TypeFamilies #-}
module Data.Vector.Algorithms.Search
       ( binarySearch
       , binarySearchBy
       , binarySearchByBounds
       , binarySearchL
       , binarySearchLBy
       , binarySearchLByBounds
       , binarySearchR
       , binarySearchRBy
       , binarySearchRByBounds
       , binarySearchP
       , binarySearchPBounds
       , gallopingSearchLeftP
       , gallopingSearchLeftPBounds
       , gallopingSearchRightP
       , gallopingSearchRightPBounds
       , Comparison
       ) where
import Prelude hiding (read, length)
import Control.Monad.Primitive
import Data.Bits
import Data.Vector.Generic.Mutable
import Data.Vector.Algorithms.Common (Comparison, midPoint)
binarySearch :: (PrimMonad m, MVector v e, Ord e)
             => v (PrimState m) e -> e -> m Int
binarySearch :: v (PrimState m) e -> e -> m Int
binarySearch = Comparison e -> v (PrimState m) e -> e -> m Int
forall (m :: * -> *) (v :: * -> * -> *) e.
(PrimMonad m, MVector v e) =>
Comparison e -> v (PrimState m) e -> e -> m Int
binarySearchBy Comparison e
forall a. Ord a => a -> a -> Ordering
compare
{-# INLINE binarySearch #-}
binarySearchBy :: (PrimMonad m, MVector v e)
               => Comparison e -> v (PrimState m) e -> e -> m Int
binarySearchBy :: Comparison e -> v (PrimState m) e -> e -> m Int
binarySearchBy Comparison e
cmp v (PrimState m) e
vec e
e = Comparison e -> v (PrimState m) e -> e -> Int -> Int -> m Int
forall (m :: * -> *) (v :: * -> * -> *) e.
(PrimMonad m, MVector v e) =>
Comparison e -> v (PrimState m) e -> e -> Int -> Int -> m Int
binarySearchByBounds Comparison e
cmp v (PrimState m) e
vec e
e Int
0 (v (PrimState m) e -> Int
forall (v :: * -> * -> *) a s. MVector v a => v s a -> Int
length v (PrimState m) e
vec)
{-# INLINE binarySearchBy #-}
binarySearchByBounds :: (PrimMonad m, MVector v e)
                     => Comparison e -> v (PrimState m) e -> e -> Int -> Int -> m Int
binarySearchByBounds :: Comparison e -> v (PrimState m) e -> e -> Int -> Int -> m Int
binarySearchByBounds Comparison e
cmp v (PrimState m) e
vec e
e = Int -> Int -> m Int
loop
 where
 loop :: Int -> Int -> m Int
loop !Int
l !Int
u
   | Int
u Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
l    = Int -> m Int
forall (m :: * -> *) a. Monad m => a -> m a
return Int
l
   | Bool
otherwise = do e
e' <- v (PrimState m) e -> Int -> m e
forall (m :: * -> *) (v :: * -> * -> *) a.
(PrimMonad m, MVector v a) =>
v (PrimState m) a -> Int -> m a
unsafeRead v (PrimState m) e
vec Int
k
                    case Comparison e
cmp e
e' e
e of
                      Ordering
LT -> Int -> Int -> m Int
loop (Int
kInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) Int
u
                      Ordering
EQ -> Int -> m Int
forall (m :: * -> *) a. Monad m => a -> m a
return Int
k
                      Ordering
GT -> Int -> Int -> m Int
loop Int
l     Int
k
  where k :: Int
k = Int -> Int -> Int
midPoint Int
u Int
l
{-# INLINE binarySearchByBounds #-}
binarySearchL :: (PrimMonad m, MVector v e, Ord e) => v (PrimState m) e -> e -> m Int
binarySearchL :: v (PrimState m) e -> e -> m Int
binarySearchL = Comparison e -> v (PrimState m) e -> e -> m Int
forall (m :: * -> *) (v :: * -> * -> *) e.
(PrimMonad m, MVector v e) =>
Comparison e -> v (PrimState m) e -> e -> m Int
binarySearchLBy Comparison e
forall a. Ord a => a -> a -> Ordering
compare
{-# INLINE binarySearchL #-}
binarySearchLBy :: (PrimMonad m, MVector v e)
                => Comparison e -> v (PrimState m) e -> e -> m Int
binarySearchLBy :: Comparison e -> v (PrimState m) e -> e -> m Int
binarySearchLBy Comparison e
cmp v (PrimState m) e
vec e
e = Comparison e -> v (PrimState m) e -> e -> Int -> Int -> m Int
forall (m :: * -> *) (v :: * -> * -> *) e.
(PrimMonad m, MVector v e) =>
Comparison e -> v (PrimState m) e -> e -> Int -> Int -> m Int
binarySearchLByBounds Comparison e
cmp v (PrimState m) e
vec e
e Int
0 (v (PrimState m) e -> Int
forall (v :: * -> * -> *) a s. MVector v a => v s a -> Int
length v (PrimState m) e
vec)
{-# INLINE binarySearchLBy #-}
binarySearchLByBounds :: (PrimMonad m, MVector v e)
                      => Comparison e -> v (PrimState m) e -> e -> Int -> Int -> m Int
binarySearchLByBounds :: Comparison e -> v (PrimState m) e -> e -> Int -> Int -> m Int
binarySearchLByBounds Comparison e
cmp v (PrimState m) e
vec e
e = (e -> Bool) -> v (PrimState m) e -> Int -> Int -> m Int
forall (m :: * -> *) (v :: * -> * -> *) e.
(PrimMonad m, MVector v e) =>
(e -> Bool) -> v (PrimState m) e -> Int -> Int -> m Int
binarySearchPBounds e -> Bool
p v (PrimState m) e
vec
 where p :: e -> Bool
p e
e' = case Comparison e
cmp e
e' e
e of Ordering
LT -> Bool
False ; Ordering
_ -> Bool
True
{-# INLINE binarySearchLByBounds #-}
binarySearchR :: (PrimMonad m, MVector v e, Ord e) => v (PrimState m) e -> e -> m Int
binarySearchR :: v (PrimState m) e -> e -> m Int
binarySearchR = Comparison e -> v (PrimState m) e -> e -> m Int
forall (m :: * -> *) (v :: * -> * -> *) e.
(PrimMonad m, MVector v e) =>
Comparison e -> v (PrimState m) e -> e -> m Int
binarySearchRBy Comparison e
forall a. Ord a => a -> a -> Ordering
compare
{-# INLINE binarySearchR #-}
binarySearchRBy :: (PrimMonad m, MVector v e)
                => Comparison e -> v (PrimState m) e -> e -> m Int
binarySearchRBy :: Comparison e -> v (PrimState m) e -> e -> m Int
binarySearchRBy Comparison e
cmp v (PrimState m) e
vec e
e = Comparison e -> v (PrimState m) e -> e -> Int -> Int -> m Int
forall (m :: * -> *) (v :: * -> * -> *) e.
(PrimMonad m, MVector v e) =>
Comparison e -> v (PrimState m) e -> e -> Int -> Int -> m Int
binarySearchRByBounds Comparison e
cmp v (PrimState m) e
vec e
e Int
0 (v (PrimState m) e -> Int
forall (v :: * -> * -> *) a s. MVector v a => v s a -> Int
length v (PrimState m) e
vec)
{-# INLINE binarySearchRBy #-}
binarySearchRByBounds :: (PrimMonad m, MVector v e)
                      => Comparison e -> v (PrimState m) e -> e -> Int -> Int -> m Int
binarySearchRByBounds :: Comparison e -> v (PrimState m) e -> e -> Int -> Int -> m Int
binarySearchRByBounds Comparison e
cmp v (PrimState m) e
vec e
e = (e -> Bool) -> v (PrimState m) e -> Int -> Int -> m Int
forall (m :: * -> *) (v :: * -> * -> *) e.
(PrimMonad m, MVector v e) =>
(e -> Bool) -> v (PrimState m) e -> Int -> Int -> m Int
binarySearchPBounds e -> Bool
p v (PrimState m) e
vec
 where p :: e -> Bool
p e
e' = case Comparison e
cmp e
e' e
e of Ordering
GT -> Bool
True ; Ordering
_ -> Bool
False
{-# INLINE binarySearchRByBounds #-}
binarySearchP :: (PrimMonad m, MVector v e) => (e -> Bool) -> v (PrimState m) e -> m Int
binarySearchP :: (e -> Bool) -> v (PrimState m) e -> m Int
binarySearchP e -> Bool
p v (PrimState m) e
vec = (e -> Bool) -> v (PrimState m) e -> Int -> Int -> m Int
forall (m :: * -> *) (v :: * -> * -> *) e.
(PrimMonad m, MVector v e) =>
(e -> Bool) -> v (PrimState m) e -> Int -> Int -> m Int
binarySearchPBounds e -> Bool
p v (PrimState m) e
vec Int
0 (v (PrimState m) e -> Int
forall (v :: * -> * -> *) a s. MVector v a => v s a -> Int
length v (PrimState m) e
vec)
{-# INLINE binarySearchP #-}
binarySearchPBounds :: (PrimMonad m, MVector v e)
                    => (e -> Bool) -> v (PrimState m) e -> Int -> Int -> m Int
binarySearchPBounds :: (e -> Bool) -> v (PrimState m) e -> Int -> Int -> m Int
binarySearchPBounds e -> Bool
p v (PrimState m) e
vec = Int -> Int -> m Int
loop
 where
 loop :: Int -> Int -> m Int
loop !Int
l !Int
u
   | Int
u Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
l    = Int -> m Int
forall (m :: * -> *) a. Monad m => a -> m a
return Int
l
   | Bool
otherwise = v (PrimState m) e -> Int -> m e
forall (m :: * -> *) (v :: * -> * -> *) a.
(PrimMonad m, MVector v a) =>
v (PrimState m) a -> Int -> m a
unsafeRead v (PrimState m) e
vec Int
k m e -> (e -> m Int) -> m Int
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \e
e -> if e -> Bool
p e
e then Int -> Int -> m Int
loop Int
l Int
k else Int -> Int -> m Int
loop (Int
kInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) Int
u
  where k :: Int
k = Int -> Int -> Int
midPoint Int
u Int
l
{-# INLINE binarySearchPBounds #-}
gallopingSearchLeftP
  :: (PrimMonad m, MVector v e) => (e -> Bool) -> v (PrimState m) e -> m Int
gallopingSearchLeftP :: (e -> Bool) -> v (PrimState m) e -> m Int
gallopingSearchLeftP e -> Bool
p v (PrimState m) e
vec = (e -> Bool) -> v (PrimState m) e -> Int -> Int -> m Int
forall (m :: * -> *) (v :: * -> * -> *) e.
(PrimMonad m, MVector v e) =>
(e -> Bool) -> v (PrimState m) e -> Int -> Int -> m Int
gallopingSearchLeftPBounds e -> Bool
p v (PrimState m) e
vec Int
0 (v (PrimState m) e -> Int
forall (v :: * -> * -> *) a s. MVector v a => v s a -> Int
length v (PrimState m) e
vec)
{-# INLINE gallopingSearchLeftP #-}
gallopingSearchRightP
  :: (PrimMonad m, MVector v e) => (e -> Bool) -> v (PrimState m) e -> m Int
gallopingSearchRightP :: (e -> Bool) -> v (PrimState m) e -> m Int
gallopingSearchRightP e -> Bool
p v (PrimState m) e
vec = (e -> Bool) -> v (PrimState m) e -> Int -> Int -> m Int
forall (m :: * -> *) (v :: * -> * -> *) e.
(PrimMonad m, MVector v e) =>
(e -> Bool) -> v (PrimState m) e -> Int -> Int -> m Int
gallopingSearchRightPBounds e -> Bool
p v (PrimState m) e
vec Int
0 (v (PrimState m) e -> Int
forall (v :: * -> * -> *) a s. MVector v a => v s a -> Int
length v (PrimState m) e
vec)
{-# INLINE gallopingSearchRightP #-}
gallopingSearchLeftPBounds :: (PrimMonad m, MVector v e)
                           => (e -> Bool)
                           -> v (PrimState m) e
                           -> Int 
                           -> Int 
                           -> m Int
gallopingSearchLeftPBounds :: (e -> Bool) -> v (PrimState m) e -> Int -> Int -> m Int
gallopingSearchLeftPBounds e -> Bool
p v (PrimState m) e
vec Int
l Int
u
  | Int
u Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
l    = Int -> m Int
forall (m :: * -> *) a. Monad m => a -> m a
return Int
l
  | Bool
otherwise = do e
x <- v (PrimState m) e -> Int -> m e
forall (m :: * -> *) (v :: * -> * -> *) a.
(PrimMonad m, MVector v a) =>
v (PrimState m) a -> Int -> m a
unsafeRead v (PrimState m) e
vec Int
l
                   if e -> Bool
p e
x then Int -> m Int
forall (m :: * -> *) a. Monad m => a -> m a
return Int
l else Int -> Int -> Int -> m Int
iter (Int
lInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) Int
l Int
2
 where
 binSearch :: Int -> Int -> m Int
binSearch = (e -> Bool) -> v (PrimState m) e -> Int -> Int -> m Int
forall (m :: * -> *) (v :: * -> * -> *) e.
(PrimMonad m, MVector v e) =>
(e -> Bool) -> v (PrimState m) e -> Int -> Int -> m Int
binarySearchPBounds e -> Bool
p v (PrimState m) e
vec
 iter :: Int -> Int -> Int -> m Int
iter !Int
i !Int
j !Int
_stepSize | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
u Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1 = do
   e
x <- v (PrimState m) e -> Int -> m e
forall (m :: * -> *) (v :: * -> * -> *) a.
(PrimMonad m, MVector v a) =>
v (PrimState m) a -> Int -> m a
unsafeRead v (PrimState m) e
vec (Int
uInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)
   if e -> Bool
p e
x then Int -> Int -> m Int
binSearch (Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) (Int
uInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) else Int -> m Int
forall (m :: * -> *) a. Monad m => a -> m a
return Int
u
 iter !Int
i !Int
j !Int
stepSize = do
   e
x <- v (PrimState m) e -> Int -> m e
forall (m :: * -> *) (v :: * -> * -> *) a.
(PrimMonad m, MVector v a) =>
v (PrimState m) a -> Int -> m a
unsafeRead v (PrimState m) e
vec Int
i
   if e -> Bool
p e
x then Int -> Int -> m Int
binSearch (Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) Int
i else Int -> Int -> Int -> m Int
iter (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
stepSize) Int
i (Int
2Int -> Int -> Int
forall a. Num a => a -> a -> a
*Int
stepSize)
{-# INLINE gallopingSearchLeftPBounds #-}
gallopingSearchRightPBounds :: (PrimMonad m, MVector v e)
                            => (e -> Bool)
                            -> v (PrimState m) e
                            -> Int 
                            -> Int 
                            -> m Int
gallopingSearchRightPBounds :: (e -> Bool) -> v (PrimState m) e -> Int -> Int -> m Int
gallopingSearchRightPBounds e -> Bool
p v (PrimState m) e
vec Int
l Int
u
  | Int
u Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
l    = Int -> m Int
forall (m :: * -> *) a. Monad m => a -> m a
return Int
l
  | Bool
otherwise = Int -> Int -> Int -> m Int
iter (Int
uInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) (Int
uInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) (-Int
1)
 where
 binSearch :: Int -> Int -> m Int
binSearch = (e -> Bool) -> v (PrimState m) e -> Int -> Int -> m Int
forall (m :: * -> *) (v :: * -> * -> *) e.
(PrimMonad m, MVector v e) =>
(e -> Bool) -> v (PrimState m) e -> Int -> Int -> m Int
binarySearchPBounds e -> Bool
p v (PrimState m) e
vec
 iter :: Int -> Int -> Int -> m Int
iter !Int
i !Int
j !Int
_stepSize | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
l = do
   e
x <- v (PrimState m) e -> Int -> m e
forall (m :: * -> *) (v :: * -> * -> *) a.
(PrimMonad m, MVector v a) =>
v (PrimState m) a -> Int -> m a
unsafeRead v (PrimState m) e
vec Int
l
   if e -> Bool
p e
x then Int -> m Int
forall (m :: * -> *) a. Monad m => a -> m a
return Int
l else Int -> Int -> m Int
binSearch (Int
lInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) Int
j
 iter !Int
i !Int
j !Int
stepSize = do
   e
x <- v (PrimState m) e -> Int -> m e
forall (m :: * -> *) (v :: * -> * -> *) a.
(PrimMonad m, MVector v a) =>
v (PrimState m) a -> Int -> m a
unsafeRead v (PrimState m) e
vec Int
i
   if e -> Bool
p e
x then Int -> Int -> Int -> m Int
iter (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
stepSize) Int
i (Int
2Int -> Int -> Int
forall a. Num a => a -> a -> a
*Int
stepSize) else Int -> Int -> m Int
binSearch (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) Int
j
{-# INLINE gallopingSearchRightPBounds #-}