{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UnboxedTuples #-}
{-# OPTIONS_GHC -Wall #-}
module Data.Primitive.PrimArray
(
PrimArray(..)
, MutablePrimArray(..)
, newPrimArray
, resizeMutablePrimArray
#if __GLASGOW_HASKELL__ >= 710
, shrinkMutablePrimArray
#endif
, readPrimArray
, writePrimArray
, indexPrimArray
, unsafeFreezePrimArray
, unsafeThawPrimArray
, copyPrimArray
, copyMutablePrimArray
#if __GLASGOW_HASKELL__ >= 708
, copyPrimArrayToPtr
, copyMutablePrimArrayToPtr
#endif
, setPrimArray
, sameMutablePrimArray
, getSizeofMutablePrimArray
, sizeofMutablePrimArray
, sizeofPrimArray
, primArrayToList
, primArrayFromList
, primArrayFromListN
, foldrPrimArray
, foldrPrimArray'
, foldlPrimArray
, foldlPrimArray'
, foldlPrimArrayM'
, traversePrimArray_
, itraversePrimArray_
, mapPrimArray
, imapPrimArray
, generatePrimArray
, replicatePrimArray
, filterPrimArray
, mapMaybePrimArray
, traversePrimArray
, itraversePrimArray
, generatePrimArrayA
, replicatePrimArrayA
, filterPrimArrayA
, mapMaybePrimArrayA
, traversePrimArrayP
, itraversePrimArrayP
, generatePrimArrayP
, replicatePrimArrayP
, filterPrimArrayP
, mapMaybePrimArrayP
) where
import GHC.Prim
import GHC.Base ( Int(..) )
import GHC.Exts (build)
import GHC.Ptr
import Data.Primitive.Internal.Compat (isTrue#)
import Data.Primitive.Types
import Data.Primitive.ByteArray (ByteArray(..))
import Data.Monoid (Monoid(..),(<>))
import Control.Applicative
import Control.Monad.Primitive
import Control.Monad.ST
import qualified Data.List as L
import qualified Data.Primitive.ByteArray as PB
import qualified Data.Primitive.Types as PT
#if MIN_VERSION_base(4,7,0)
import GHC.Exts (IsList(..))
#endif
#if MIN_VERSION_base(4,9,0)
import Data.Semigroup (Semigroup)
import qualified Data.Semigroup as SG
#endif
data PrimArray a = PrimArray ByteArray#
data MutablePrimArray s a = MutablePrimArray (MutableByteArray# s)
sameByteArray :: ByteArray# -> ByteArray# -> Bool
sameByteArray ba1 ba2 =
case reallyUnsafePtrEquality# (unsafeCoerce# ba1 :: ()) (unsafeCoerce# ba2 :: ()) of
#if __GLASGOW_HASKELL__ >= 708
r -> isTrue# r
#else
1# -> True
_ -> False
#endif
instance (Eq a, Prim a) => Eq (PrimArray a) where
a1@(PrimArray ba1#) == a2@(PrimArray ba2#)
| sameByteArray ba1# ba2# = True
| sz1 /= sz2 = False
| otherwise = loop (quot sz1 (sizeOf (undefined :: a)) - 1)
where
sz1 = PB.sizeofByteArray (ByteArray ba1#)
sz2 = PB.sizeofByteArray (ByteArray ba2#)
loop !i
| i < 0 = True
| otherwise = indexPrimArray a1 i == indexPrimArray a2 i && loop (i-1)
instance (Ord a, Prim a) => Ord (PrimArray a) where
compare a1@(PrimArray ba1#) a2@(PrimArray ba2#)
| sameByteArray ba1# ba2# = EQ
| otherwise = loop 0
where
sz1 = PB.sizeofByteArray (ByteArray ba1#)
sz2 = PB.sizeofByteArray (ByteArray ba2#)
sz = quot (min sz1 sz2) (sizeOf (undefined :: a))
loop !i
| i < sz = compare (indexPrimArray a1 i) (indexPrimArray a2 i) <> loop (i+1)
| otherwise = compare sz1 sz2
#if MIN_VERSION_base(4,7,0)
instance Prim a => IsList (PrimArray a) where
type Item (PrimArray a) = a
fromList = primArrayFromList
fromListN = primArrayFromListN
toList = primArrayToList
#endif
instance (Show a, Prim a) => Show (PrimArray a) where
showsPrec p a = showParen (p > 10) $
showString "fromListN " . shows (sizeofPrimArray a) . showString " "
. shows (primArrayToList a)
die :: String -> String -> a
die fun problem = error $ "Data.Primitive.PrimArray." ++ fun ++ ": " ++ problem
primArrayFromList :: Prim a => [a] -> PrimArray a
primArrayFromList vs = primArrayFromListN (L.length vs) vs
primArrayFromListN :: forall a. Prim a => Int -> [a] -> PrimArray a
primArrayFromListN len vs = runST run where
run :: forall s. ST s (PrimArray a)
run = do
arr <- newPrimArray len
let go :: [a] -> Int -> ST s ()
go [] !ix = if ix == len
then return ()
else die "fromListN" "list length less than specified size"
go (a : as) !ix = if ix < len
then do
writePrimArray arr ix a
go as (ix + 1)
else die "fromListN" "list length greater than specified size"
go vs 0
unsafeFreezePrimArray arr
{-# INLINE primArrayToList #-}
primArrayToList :: forall a. Prim a => PrimArray a -> [a]
primArrayToList xs = build (\c n -> foldrPrimArray c n xs)
primArrayToByteArray :: PrimArray a -> PB.ByteArray
primArrayToByteArray (PrimArray x) = PB.ByteArray x
byteArrayToPrimArray :: ByteArray -> PrimArray a
byteArrayToPrimArray (PB.ByteArray x) = PrimArray x
#if MIN_VERSION_base(4,9,0)
instance Semigroup (PrimArray a) where
x <> y = byteArrayToPrimArray (primArrayToByteArray x SG.<> primArrayToByteArray y)
sconcat = byteArrayToPrimArray . SG.sconcat . fmap primArrayToByteArray
stimes i arr = byteArrayToPrimArray (SG.stimes i (primArrayToByteArray arr))
#endif
instance Monoid (PrimArray a) where
mempty = emptyPrimArray
#if !(MIN_VERSION_base(4,11,0))
mappend x y = byteArrayToPrimArray (mappend (primArrayToByteArray x) (primArrayToByteArray y))
#endif
mconcat = byteArrayToPrimArray . mconcat . map primArrayToByteArray
emptyPrimArray :: PrimArray a
{-# NOINLINE emptyPrimArray #-}
emptyPrimArray = runST $ primitive $ \s0# -> case newByteArray# 0# s0# of
(# s1#, arr# #) -> case unsafeFreezeByteArray# arr# s1# of
(# s2#, arr'# #) -> (# s2#, PrimArray arr'# #)
newPrimArray :: forall m a. (PrimMonad m, Prim a) => Int -> m (MutablePrimArray (PrimState m) a)
{-# INLINE newPrimArray #-}
newPrimArray (I# n#)
= primitive (\s# ->
case newByteArray# (n# *# sizeOf# (undefined :: a)) s# of
(# s'#, arr# #) -> (# s'#, MutablePrimArray arr# #)
)
resizeMutablePrimArray :: forall m a. (PrimMonad m, Prim a)
=> MutablePrimArray (PrimState m) a
-> Int
-> m (MutablePrimArray (PrimState m) a)
{-# INLINE resizeMutablePrimArray #-}
#if __GLASGOW_HASKELL__ >= 710
resizeMutablePrimArray (MutablePrimArray arr#) (I# n#)
= primitive (\s# -> case resizeMutableByteArray# arr# (n# *# sizeOf# (undefined :: a)) s# of
(# s'#, arr'# #) -> (# s'#, MutablePrimArray arr'# #))
#else
resizeMutablePrimArray arr n
= do arr' <- newPrimArray n
copyMutablePrimArray arr' 0 arr 0 (min (sizeofMutablePrimArray arr) n)
return arr'
#endif
#if __GLASGOW_HASKELL__ >= 710
shrinkMutablePrimArray :: forall m a. (PrimMonad m, Prim a)
=> MutablePrimArray (PrimState m) a
-> Int
-> m ()
{-# INLINE shrinkMutablePrimArray #-}
shrinkMutablePrimArray (MutablePrimArray arr#) (I# n#)
= primitive_ (shrinkMutableByteArray# arr# (n# *# sizeOf# (undefined :: a)))
#endif
readPrimArray :: (Prim a, PrimMonad m) => MutablePrimArray (PrimState m) a -> Int -> m a
{-# INLINE readPrimArray #-}
readPrimArray (MutablePrimArray arr#) (I# i#)
= primitive (readByteArray# arr# i#)
writePrimArray ::
(Prim a, PrimMonad m)
=> MutablePrimArray (PrimState m) a
-> Int
-> a
-> m ()
{-# INLINE writePrimArray #-}
writePrimArray (MutablePrimArray arr#) (I# i#) x
= primitive_ (writeByteArray# arr# i# x)
copyMutablePrimArray :: forall m a.
(PrimMonad m, Prim a)
=> MutablePrimArray (PrimState m) a
-> Int
-> MutablePrimArray (PrimState m) a
-> Int
-> Int
-> m ()
{-# INLINE copyMutablePrimArray #-}
copyMutablePrimArray (MutablePrimArray dst#) (I# doff#) (MutablePrimArray src#) (I# soff#) (I# n#)
= primitive_ (copyMutableByteArray#
src#
(soff# *# (sizeOf# (undefined :: a)))
dst#
(doff# *# (sizeOf# (undefined :: a)))
(n# *# (sizeOf# (undefined :: a)))
)
copyPrimArray :: forall m a.
(PrimMonad m, Prim a)
=> MutablePrimArray (PrimState m) a
-> Int
-> PrimArray a
-> Int
-> Int
-> m ()
{-# INLINE copyPrimArray #-}
copyPrimArray (MutablePrimArray dst#) (I# doff#) (PrimArray src#) (I# soff#) (I# n#)
= primitive_ (copyByteArray#
src#
(soff# *# (sizeOf# (undefined :: a)))
dst#
(doff# *# (sizeOf# (undefined :: a)))
(n# *# (sizeOf# (undefined :: a)))
)
#if __GLASGOW_HASKELL__ >= 708
copyPrimArrayToPtr :: forall m a. (PrimMonad m, Prim a)
=> Ptr a
-> PrimArray a
-> Int
-> Int
-> m ()
{-# INLINE copyPrimArrayToPtr #-}
copyPrimArrayToPtr (Ptr addr#) (PrimArray ba#) (I# soff#) (I# n#) =
primitive (\ s# ->
let s'# = copyByteArrayToAddr# ba# (soff# *# siz#) addr# (n# *# siz#) s#
in (# s'#, () #))
where siz# = sizeOf# (undefined :: a)
copyMutablePrimArrayToPtr :: forall m a. (PrimMonad m, Prim a)
=> Ptr a
-> MutablePrimArray (PrimState m) a
-> Int
-> Int
-> m ()
{-# INLINE copyMutablePrimArrayToPtr #-}
copyMutablePrimArrayToPtr (Ptr addr#) (MutablePrimArray mba#) (I# soff#) (I# n#) =
primitive (\ s# ->
let s'# = copyMutableByteArrayToAddr# mba# (soff# *# siz#) addr# (n# *# siz#) s#
in (# s'#, () #))
where siz# = sizeOf# (undefined :: a)
#endif
setPrimArray
:: (Prim a, PrimMonad m)
=> MutablePrimArray (PrimState m) a
-> Int
-> Int
-> a
-> m ()
{-# INLINE setPrimArray #-}
setPrimArray (MutablePrimArray dst#) (I# doff#) (I# sz#) x
= primitive_ (PT.setByteArray# dst# doff# sz# x)
getSizeofMutablePrimArray :: forall m a. (PrimMonad m, Prim a)
=> MutablePrimArray (PrimState m) a
-> m Int
{-# INLINE getSizeofMutablePrimArray #-}
#if __GLASGOW_HASKELL__ >= 801
getSizeofMutablePrimArray (MutablePrimArray arr#)
= primitive (\s# ->
case getSizeofMutableByteArray# arr# s# of
(# s'#, sz# #) -> (# s'#, I# (quotInt# sz# (sizeOf# (undefined :: a))) #)
)
#else
getSizeofMutablePrimArray arr
= return (sizeofMutablePrimArray arr)
#endif
sizeofMutablePrimArray :: forall s a. Prim a => MutablePrimArray s a -> Int
{-# INLINE sizeofMutablePrimArray #-}
sizeofMutablePrimArray (MutablePrimArray arr#) =
I# (quotInt# (sizeofMutableByteArray# arr#) (sizeOf# (undefined :: a)))
sameMutablePrimArray :: MutablePrimArray s a -> MutablePrimArray s a -> Bool
{-# INLINE sameMutablePrimArray #-}
sameMutablePrimArray (MutablePrimArray arr#) (MutablePrimArray brr#)
= isTrue# (sameMutableByteArray# arr# brr#)
unsafeFreezePrimArray
:: PrimMonad m => MutablePrimArray (PrimState m) a -> m (PrimArray a)
{-# INLINE unsafeFreezePrimArray #-}
unsafeFreezePrimArray (MutablePrimArray arr#)
= primitive (\s# -> case unsafeFreezeByteArray# arr# s# of
(# s'#, arr'# #) -> (# s'#, PrimArray arr'# #))
unsafeThawPrimArray
:: PrimMonad m => PrimArray a -> m (MutablePrimArray (PrimState m) a)
{-# INLINE unsafeThawPrimArray #-}
unsafeThawPrimArray (PrimArray arr#)
= primitive (\s# -> (# s#, MutablePrimArray (unsafeCoerce# arr#) #))
indexPrimArray :: forall a. Prim a => PrimArray a -> Int -> a
{-# INLINE indexPrimArray #-}
indexPrimArray (PrimArray arr#) (I# i#) = indexByteArray# arr# i#
sizeofPrimArray :: forall a. Prim a => PrimArray a -> Int
{-# INLINE sizeofPrimArray #-}
sizeofPrimArray (PrimArray arr#) = I# (quotInt# (sizeofByteArray# arr#) (sizeOf# (undefined :: a)))
{-# INLINE foldrPrimArray #-}
foldrPrimArray :: forall a b. Prim a => (a -> b -> b) -> b -> PrimArray a -> b
foldrPrimArray f z arr = go 0
where
!sz = sizeofPrimArray arr
go !i
| sz > i = f (indexPrimArray arr i) (go (i+1))
| otherwise = z
{-# INLINE foldrPrimArray' #-}
foldrPrimArray' :: forall a b. Prim a => (a -> b -> b) -> b -> PrimArray a -> b
foldrPrimArray' f z0 arr = go (sizeofPrimArray arr - 1) z0
where
go !i !acc
| i < 0 = acc
| otherwise = go (i - 1) (f (indexPrimArray arr i) acc)
{-# INLINE foldlPrimArray #-}
foldlPrimArray :: forall a b. Prim a => (b -> a -> b) -> b -> PrimArray a -> b
foldlPrimArray f z arr = go (sizeofPrimArray arr - 1)
where
go !i
| i < 0 = z
| otherwise = f (go (i - 1)) (indexPrimArray arr i)
{-# INLINE foldlPrimArray' #-}
foldlPrimArray' :: forall a b. Prim a => (b -> a -> b) -> b -> PrimArray a -> b
foldlPrimArray' f z0 arr = go 0 z0
where
!sz = sizeofPrimArray arr
go !i !acc
| i < sz = go (i + 1) (f acc (indexPrimArray arr i))
| otherwise = acc
{-# INLINE foldlPrimArrayM' #-}
foldlPrimArrayM' :: (Prim a, Monad m) => (b -> a -> m b) -> b -> PrimArray a -> m b
foldlPrimArrayM' f z0 arr = go 0 z0
where
!sz = sizeofPrimArray arr
go !i !acc1
| i < sz = do
acc2 <- f acc1 (indexPrimArray arr i)
go (i + 1) acc2
| otherwise = return acc1
{-# INLINE traversePrimArrayP #-}
traversePrimArrayP :: (PrimMonad m, Prim a, Prim b)
=> (a -> m b)
-> PrimArray a
-> m (PrimArray b)
traversePrimArrayP f arr = do
let !sz = sizeofPrimArray arr
marr <- newPrimArray sz
let go !ix = if ix < sz
then do
b <- f (indexPrimArray arr ix)
writePrimArray marr ix b
go (ix + 1)
else return ()
go 0
unsafeFreezePrimArray marr
{-# INLINE filterPrimArrayP #-}
filterPrimArrayP :: (PrimMonad m, Prim a)
=> (a -> m Bool)
-> PrimArray a
-> m (PrimArray a)
filterPrimArrayP f arr = do
let !sz = sizeofPrimArray arr
marr <- newPrimArray sz
let go !ixSrc !ixDst = if ixSrc < sz
then do
let a = indexPrimArray arr ixSrc
b <- f a
if b
then do
writePrimArray marr ixDst a
go (ixSrc + 1) (ixDst + 1)
else go (ixSrc + 1) ixDst
else return ixDst
lenDst <- go 0 0
marr' <- resizeMutablePrimArray marr lenDst
unsafeFreezePrimArray marr'
{-# INLINE mapMaybePrimArrayP #-}
mapMaybePrimArrayP :: (PrimMonad m, Prim a, Prim b)
=> (a -> m (Maybe b))
-> PrimArray a
-> m (PrimArray b)
mapMaybePrimArrayP f arr = do
let !sz = sizeofPrimArray arr
marr <- newPrimArray sz
let go !ixSrc !ixDst = if ixSrc < sz
then do
let a = indexPrimArray arr ixSrc
mb <- f a
case mb of
Just b -> do
writePrimArray marr ixDst b
go (ixSrc + 1) (ixDst + 1)
Nothing -> go (ixSrc + 1) ixDst
else return ixDst
lenDst <- go 0 0
marr' <- resizeMutablePrimArray marr lenDst
unsafeFreezePrimArray marr'
{-# INLINE generatePrimArrayP #-}
generatePrimArrayP :: (PrimMonad m, Prim a)
=> Int
-> (Int -> m a)
-> m (PrimArray a)
generatePrimArrayP sz f = do
marr <- newPrimArray sz
let go !ix = if ix < sz
then do
b <- f ix
writePrimArray marr ix b
go (ix + 1)
else return ()
go 0
unsafeFreezePrimArray marr
{-# INLINE replicatePrimArrayP #-}
replicatePrimArrayP :: (PrimMonad m, Prim a)
=> Int
-> m a
-> m (PrimArray a)
replicatePrimArrayP sz f = do
marr <- newPrimArray sz
let go !ix = if ix < sz
then do
b <- f
writePrimArray marr ix b
go (ix + 1)
else return ()
go 0
unsafeFreezePrimArray marr
{-# INLINE mapPrimArray #-}
mapPrimArray :: (Prim a, Prim b)
=> (a -> b)
-> PrimArray a
-> PrimArray b
mapPrimArray f arr = runST $ do
let !sz = sizeofPrimArray arr
marr <- newPrimArray sz
let go !ix = if ix < sz
then do
let b = f (indexPrimArray arr ix)
writePrimArray marr ix b
go (ix + 1)
else return ()
go 0
unsafeFreezePrimArray marr
{-# INLINE imapPrimArray #-}
imapPrimArray :: (Prim a, Prim b)
=> (Int -> a -> b)
-> PrimArray a
-> PrimArray b
imapPrimArray f arr = runST $ do
let !sz = sizeofPrimArray arr
marr <- newPrimArray sz
let go !ix = if ix < sz
then do
let b = f ix (indexPrimArray arr ix)
writePrimArray marr ix b
go (ix + 1)
else return ()
go 0
unsafeFreezePrimArray marr
{-# INLINE filterPrimArray #-}
filterPrimArray :: Prim a
=> (a -> Bool)
-> PrimArray a
-> PrimArray a
filterPrimArray p arr = runST $ do
let !sz = sizeofPrimArray arr
marr <- newPrimArray sz
let go !ixSrc !ixDst = if ixSrc < sz
then do
let !a = indexPrimArray arr ixSrc
if p a
then do
writePrimArray marr ixDst a
go (ixSrc + 1) (ixDst + 1)
else go (ixSrc + 1) ixDst
else return ixDst
dstLen <- go 0 0
marr' <- resizeMutablePrimArray marr dstLen
unsafeFreezePrimArray marr'
filterPrimArrayA ::
(Applicative f, Prim a)
=> (a -> f Bool)
-> PrimArray a
-> f (PrimArray a)
filterPrimArrayA f = \ !ary ->
let
!len = sizeofPrimArray ary
go !ixSrc
| ixSrc == len = pure $ IxSTA $ \ixDst _ -> return ixDst
| otherwise = let x = indexPrimArray ary ixSrc in
liftA2
(\keep (IxSTA m) -> IxSTA $ \ixDst mary -> if keep
then writePrimArray (MutablePrimArray mary) ixDst x >> m (ixDst + 1) mary
else m ixDst mary
)
(f x)
(go (ixSrc + 1))
in if len == 0
then pure emptyPrimArray
else runIxSTA len <$> go 0
mapMaybePrimArrayA ::
(Applicative f, Prim a, Prim b)
=> (a -> f (Maybe b))
-> PrimArray a
-> f (PrimArray b)
mapMaybePrimArrayA f = \ !ary ->
let
!len = sizeofPrimArray ary
go !ixSrc
| ixSrc == len = pure $ IxSTA $ \ixDst _ -> return ixDst
| otherwise = let x = indexPrimArray ary ixSrc in
liftA2
(\mb (IxSTA m) -> IxSTA $ \ixDst mary -> case mb of
Just b -> writePrimArray (MutablePrimArray mary) ixDst b >> m (ixDst + 1) mary
Nothing -> m ixDst mary
)
(f x)
(go (ixSrc + 1))
in if len == 0
then pure emptyPrimArray
else runIxSTA len <$> go 0
{-# INLINE mapMaybePrimArray #-}
mapMaybePrimArray :: (Prim a, Prim b)
=> (a -> Maybe b)
-> PrimArray a
-> PrimArray b
mapMaybePrimArray p arr = runST $ do
let !sz = sizeofPrimArray arr
marr <- newPrimArray sz
let go !ixSrc !ixDst = if ixSrc < sz
then do
let !a = indexPrimArray arr ixSrc
case p a of
Just b -> do
writePrimArray marr ixDst b
go (ixSrc + 1) (ixDst + 1)
Nothing -> go (ixSrc + 1) ixDst
else return ixDst
dstLen <- go 0 0
marr' <- resizeMutablePrimArray marr dstLen
unsafeFreezePrimArray marr'
traversePrimArray ::
(Applicative f, Prim a, Prim b)
=> (a -> f b)
-> PrimArray a
-> f (PrimArray b)
traversePrimArray f = \ !ary ->
let
!len = sizeofPrimArray ary
go !i
| i == len = pure $ STA $ \mary -> unsafeFreezePrimArray (MutablePrimArray mary)
| x <- indexPrimArray ary i
= liftA2 (\b (STA m) -> STA $ \mary ->
writePrimArray (MutablePrimArray mary) i b >> m mary)
(f x) (go (i + 1))
in if len == 0
then pure emptyPrimArray
else runSTA len <$> go 0
itraversePrimArray ::
(Applicative f, Prim a, Prim b)
=> (Int -> a -> f b)
-> PrimArray a
-> f (PrimArray b)
itraversePrimArray f = \ !ary ->
let
!len = sizeofPrimArray ary
go !i
| i == len = pure $ STA $ \mary -> unsafeFreezePrimArray (MutablePrimArray mary)
| x <- indexPrimArray ary i
= liftA2 (\b (STA m) -> STA $ \mary ->
writePrimArray (MutablePrimArray mary) i b >> m mary)
(f i x) (go (i + 1))
in if len == 0
then pure emptyPrimArray
else runSTA len <$> go 0
{-# INLINE itraversePrimArrayP #-}
itraversePrimArrayP :: (Prim a, Prim b, PrimMonad m)
=> (Int -> a -> m b)
-> PrimArray a
-> m (PrimArray b)
itraversePrimArrayP f arr = do
let !sz = sizeofPrimArray arr
marr <- newPrimArray sz
let go !ix
| ix < sz = do
writePrimArray marr ix =<< f ix (indexPrimArray arr ix)
go (ix + 1)
| otherwise = return ()
go 0
unsafeFreezePrimArray marr
{-# INLINE generatePrimArray #-}
generatePrimArray :: Prim a
=> Int
-> (Int -> a)
-> PrimArray a
generatePrimArray len f = runST $ do
marr <- newPrimArray len
let go !ix = if ix < len
then do
writePrimArray marr ix (f ix)
go (ix + 1)
else return ()
go 0
unsafeFreezePrimArray marr
{-# INLINE replicatePrimArray #-}
replicatePrimArray :: Prim a
=> Int
-> a
-> PrimArray a
replicatePrimArray len a = runST $ do
marr <- newPrimArray len
setPrimArray marr 0 len a
unsafeFreezePrimArray marr
{-# INLINE generatePrimArrayA #-}
generatePrimArrayA ::
(Applicative f, Prim a)
=> Int
-> (Int -> f a)
-> f (PrimArray a)
generatePrimArrayA len f =
let
go !i
| i == len = pure $ STA $ \mary -> unsafeFreezePrimArray (MutablePrimArray mary)
| otherwise
= liftA2 (\b (STA m) -> STA $ \mary ->
writePrimArray (MutablePrimArray mary) i b >> m mary)
(f i) (go (i + 1))
in if len == 0
then pure emptyPrimArray
else runSTA len <$> go 0
{-# INLINE replicatePrimArrayA #-}
replicatePrimArrayA ::
(Applicative f, Prim a)
=> Int
-> f a
-> f (PrimArray a)
replicatePrimArrayA len f =
let
go !i
| i == len = pure $ STA $ \mary -> unsafeFreezePrimArray (MutablePrimArray mary)
| otherwise
= liftA2 (\b (STA m) -> STA $ \mary ->
writePrimArray (MutablePrimArray mary) i b >> m mary)
f (go (i + 1))
in if len == 0
then pure emptyPrimArray
else runSTA len <$> go 0
traversePrimArray_ ::
(Applicative f, Prim a)
=> (a -> f b)
-> PrimArray a
-> f ()
traversePrimArray_ f a = go 0 where
!sz = sizeofPrimArray a
go !ix = if ix < sz
then f (indexPrimArray a ix) *> go (ix + 1)
else pure ()
itraversePrimArray_ ::
(Applicative f, Prim a)
=> (Int -> a -> f b)
-> PrimArray a
-> f ()
itraversePrimArray_ f a = go 0 where
!sz = sizeofPrimArray a
go !ix = if ix < sz
then f ix (indexPrimArray a ix) *> go (ix + 1)
else pure ()
newtype IxSTA a = IxSTA {_runIxSTA :: forall s. Int -> MutableByteArray# s -> ST s Int}
runIxSTA :: forall a. Prim a
=> Int
-> IxSTA a
-> PrimArray a
runIxSTA !szUpper = \ (IxSTA m) -> runST $ do
ar :: MutablePrimArray s a <- newPrimArray szUpper
sz <- m 0 (unMutablePrimArray ar)
ar' <- resizeMutablePrimArray ar sz
unsafeFreezePrimArray ar'
{-# INLINE runIxSTA #-}
newtype STA a = STA {_runSTA :: forall s. MutableByteArray# s -> ST s (PrimArray a)}
runSTA :: forall a. Prim a => Int -> STA a -> PrimArray a
runSTA !sz = \ (STA m) -> runST $ newPrimArray sz >>= \ (ar :: MutablePrimArray s a) -> m (unMutablePrimArray ar)
{-# INLINE runSTA #-}
unMutablePrimArray :: MutablePrimArray s a -> MutableByteArray# s
unMutablePrimArray (MutablePrimArray m) = m