1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
|
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE MagicHash #-}
module Basement.Alg.PrimArray
( Indexable, index
, findIndexElem
, revFindIndexElem
, findIndexPredicate
, revFindIndexPredicate
, foldl
, foldr
, foldl1
, all
, any
, filter
) where
import GHC.Types
import GHC.Prim
import Basement.Alg.Class
import Basement.Compat.Base
import Basement.Numerical.Additive
import Basement.Numerical.Multiplicative
import Basement.Types.OffsetSize
import Basement.PrimType
import Basement.Monad
findIndexElem :: (Indexable container ty, Eq ty) => ty -> container -> Offset ty -> Offset ty -> Offset ty
findIndexElem ty ba startIndex endIndex = loop startIndex
where
loop !i
| i >= endIndex = sentinel
| index ba i == ty = i
| otherwise = loop (i+1)
{-# INLINE findIndexElem #-}
revFindIndexElem :: (Indexable container ty, Eq ty) => ty -> container -> Offset ty -> Offset ty -> Offset ty
revFindIndexElem ty ba startIndex endIndex = loop endIndex
where
loop !iplus1
| iplus1 <= startIndex = sentinel
| index ba i == ty = i
| otherwise = loop i
where !i = iplus1 `offsetMinusE` 1
{-# INLINE revFindIndexElem #-}
findIndexPredicate :: Indexable container ty => (ty -> Bool) -> container -> Offset ty -> Offset ty -> Offset ty
findIndexPredicate predicate ba startIndex endIndex = loop startIndex
where
loop !i
| i >= endIndex = sentinel
| predicate (index ba i) = i
| otherwise = loop (i+1)
{-# INLINE findIndexPredicate #-}
revFindIndexPredicate :: Indexable container ty => (ty -> Bool) -> container -> Offset ty -> Offset ty -> Offset ty
revFindIndexPredicate predicate ba startIndex endIndex = loop endIndex
where
loop !iplus1
| iplus1 <= startIndex = sentinel
| predicate (index ba i) = i
| otherwise = loop i
where !i = iplus1 `offsetMinusE` 1
{-# INLINE revFindIndexPredicate #-}
foldl :: Indexable container ty => (a -> ty -> a) -> a -> container -> Offset ty -> Offset ty -> a
foldl f !initialAcc ba !startIndex !endIndex = loop startIndex initialAcc
where
loop !i !acc
| i == endIndex = acc
| otherwise = loop (i+1) (f acc (index ba i))
{-# INLINE foldl #-}
foldr :: Indexable container ty => (ty -> a -> a) -> a -> container -> Offset ty -> Offset ty -> a
foldr f !initialAcc ba startIndex endIndex = loop startIndex
where
loop !i
| i == endIndex = initialAcc
| otherwise = index ba i `f` loop (i+1)
{-# INLINE foldr #-}
foldl1 :: Indexable container ty => (ty -> ty -> ty) -> container -> Offset ty -> Offset ty -> ty
foldl1 f ba startIndex endIndex = loop (startIndex+1) (index ba startIndex)
where
loop !i !acc
| i == endIndex = acc
| otherwise = loop (i+1) (f acc (index ba i))
{-# INLINE foldl1 #-}
filter :: (PrimMonad prim, PrimType ty, Indexable container ty)
=> (ty -> Bool) -> MutableByteArray# (PrimState prim)
-> container -> Offset ty -> Offset ty -> prim (CountOf ty)
filter predicate dst src start end = loop azero start
where
loop !d !s
| s == end = pure (offsetAsSize d)
| predicate v = primMbaWrite dst d v >> loop (d+Offset 1) (s+Offset 1)
| otherwise = loop d (s+Offset 1)
where
v = index src s
{-# INLINE filter #-}
all :: Indexable container ty => (ty -> Bool) -> container -> Offset ty -> Offset ty -> Bool
all predicate ba start end = loop start
where
loop !i
| i == end = True
| predicate (index ba i) = loop (i+1)
| otherwise = False
{-# INLINE all #-}
any :: Indexable container ty => (ty -> Bool) -> container -> Offset ty -> Offset ty -> Bool
any predicate ba start end = loop start
where
loop !i
| i == end = False
| predicate (index ba i) = True
| otherwise = loop (i+1)
{-# INLINE any #-}
|