{-# 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 #-}