primdata-0.1.2.3: Data/Array/FM.hs
{-# language
UnboxedTuples, TypeOperators, MagicHash, RankNTypes, PolyKinds,
TypeApplications, ScopedTypeVariables, BangPatterns, BlockArguments,
RoleAnnotations, TypeFamilies, AllowAmbiguousTypes #-}
{-# options_ghc -Wno-deprecations #-}
{-|
Flat mutable arrays.
-}
module Data.Array.FM where
import GHC.Exts
import Data.Kind
import Data.Flat
import IO
import qualified Data.Array.FI as FI
import Data.Unlifted
type role Array representational
data Array (a :: Type) = Array (MutableByteArray# RealWorld)
elemType :: Array a -> Proxy# a
elemType _ = proxy#
{-# inline elemType #-}
instance Unlifted (Array a) where
type Rep (Array a) = MutableByteArray# RealWorld
to# (Array arr) = arr
from# = Array
{-# inline to# #-}
{-# inline from# #-}
defaultElem = empty
{-# inline defaultElem #-}
new :: forall a. Flat a => Int -> IO (Array a)
new (I# n) = IO \s -> case newByteArray# (toByteOffset# @a proxy# n) s of
(# s, marr #) -> (# s, Array marr #)
{-# inline new #-}
pinnedNew :: forall a. Flat a => Int -> IO (Array a)
pinnedNew (I# n) = IO \s -> case newPinnedByteArray# (toByteOffset# @a proxy# n) s of
(# s, marr #) -> (# s, Array marr #)
{-# inline pinnedNew #-}
isPinned :: Array a -> Bool
isPinned (Array arr) = isTrue# (isMutableByteArrayPinned# arr)
{-# inline isPinned #-}
empty :: Array a
empty = Array (runRW# \s -> case newByteArray# 0# s of
(# s, arr #) -> arr)
{-# noinline empty #-}
copy :: forall a. Flat a => Array a -> Int -> Array a -> Int -> Int -> IO ()
copy (Array arr) (I# i) (Array arr') (I# i') (I# len) = IO \s ->
case copyMutableByteArray#
arr (toByteOffset# @a proxy# i)
arr' (toByteOffset# @a proxy# i')
(toByteOffset# @a proxy# len) s of
s -> (# s, () #)
{-# inline copy #-}
read :: forall a. Flat a => Array a -> Int -> IO a
read (Array arr) (I# i) = IO (readByteArray# arr i)
{-# inline read #-}
write :: forall a. Flat a => Array a -> Int -> a -> IO ()
write (Array arr) (I# i) a = IO \s ->
case writeByteArray# arr i a s of
s -> (# s, () #)
{-# inline write #-}
modify :: forall a. Flat a => Array a -> Int -> (a -> a) -> IO ()
modify (Array arr) (I# i) f = IO \s -> case readByteArray# arr i s of
(# s, a #) -> let !v = f a in case writeByteArray# arr i v s of
s -> (# s, () #)
{-# inline modify #-}
map' :: forall a. Flat a => (a -> a) -> Array a -> IO ()
map' f (Array arr) = IO \s ->
let go arr i n s = case i ==# n of
1# -> (# s, () #)
_ -> case readWord8ArrayAs# arr i s of
(# s, a #) -> case a of
!a -> case f a of
!a -> case writeWord8ArrayAs# arr i a s of
s -> go arr (i +# size# @a proxy#) n s
in go arr 0# (sizeofMutableByteArray# arr) s
{-# inline map' #-}
for :: forall a. Flat a => Array a -> (a -> IO ()) -> IO ()
for (Array arr) f = IO \s ->
let go arr i n s = case i ==# n of
1# -> (# s, () #)
_ -> case readWord8ArrayAs# arr i s of
(# s, a #) -> case a of
!a -> case f a of
IO f -> case f s of
(# s, _ #) -> go arr (i +# size# @a proxy#) n s
in go arr 0# (sizeofMutableByteArray# arr) s
{-# inline for #-}
forIx :: forall a. Flat a => Array a -> (Int -> a -> IO ()) -> IO ()
forIx (Array arr) f = IO \s ->
let go arr i n !ix s = case i ==# n of
1# -> (# s, () #)
_ -> case readWord8ArrayAs# arr i s of
(# s, a #) -> case a of
!a -> case f ix a of
IO f -> case f s of
(# s, _ #) -> go arr (i +# size# @a proxy#) n (ix + 1) s
in go arr 0# (sizeofMutableByteArray# arr) 0 s
{-# inline forIx #-}
set :: forall a. Flat a => Array a -> a -> IO ()
set (Array arr) a = IO \s ->
let go arr i n s = case i ==# n of
1# -> (# s, () #)
_ -> case writeWord8ArrayAs# arr i a s of
s -> go arr (i +# size# @a proxy#) n s
in go arr 0# (sizeofMutableByteArray# arr) s
{-# inline set #-}
size :: forall a. Flat a => Array a -> Int
size (Array arr) = I# (fromByteOffset# @a proxy# (sizeofMutableByteArray# arr))
{-# inline size #-}
thawSlice :: forall a. Flat a => FI.Array a -> Int -> Int -> IO (Array a)
thawSlice (FI.Array arr) (I# start) (I# len) =
let len' = toByteOffset# (proxy# :: Proxy# a) len
start' = toByteOffset# (proxy# :: Proxy# a) start
in IO \s -> case newByteArray# len' s of
(# s, marr #) -> case copyByteArray# arr start' marr 0# len' s of
s -> (# s, Array marr #)
{-# inline thawSlice #-}
thaw :: forall a. FI.Array a -> IO (Array a)
thaw (FI.Array arr) =
let n = sizeofByteArray# arr
in IO \s -> case newByteArray# n s of
(# s, marr #) -> case copyByteArray# arr 0# marr 0# n s of
s -> (# s, Array marr #)
{-# inline thaw #-}
copySlice :: forall a. Flat a => Array a -> Int -> Array a -> Int -> Int -> IO ()
copySlice (Array src) (I# i) (Array dst) (I# j) (I# len) = IO \s ->
let i' = toByteOffset# (proxy# :: Proxy# a) i
j' = toByteOffset# (proxy# :: Proxy# a) j
len' = toByteOffset# (proxy# :: Proxy# a) len
in case copyMutableByteArray# src i' dst j' len' s of
s -> (# s, () #)
{-# inline copySlice #-}
sizedThaw :: forall a. Flat a => Int -> FI.Array a -> IO (Array a)
sizedThaw size arr = thawSlice arr 0 size
{-# inline sizedThaw #-}
unsafeFreeze :: Array a -> IO (FI.Array a)
unsafeFreeze (Array marr) = IO \s -> case unsafeFreezeByteArray# marr s of
(# s, arr #) -> (# s, FI.Array arr #)
{-# inline unsafeFreeze #-}
freezeSlice :: forall a. Flat a => Array a -> Int -> Int -> IO (FI.Array a)
freezeSlice src start len = do
dst <- new @a len
copySlice @a src start dst 0 len
unsafeFreeze dst
{-# inline freezeSlice #-}
freeze :: Array a -> IO (FI.Array a)
freeze (Array arr) = IO \s ->
let len = sizeofMutableByteArray# arr
in case newByteArray# len s of
(# s, marr #) -> case copyMutableByteArrayNonOverlapping# arr 0# marr 0# len s of
s -> case unsafeFreezeByteArray# marr s of
(# s, arr #) -> (# s, FI.Array arr #)
{-# inline freeze #-}