{-# language MagicHash #-}
{-# language UnboxedTuples #-}
{-# language TypeFamilies #-}
{-# language TypeApplications #-}
{-# language ScopedTypeVariables #-}

-- GHC contains three general classes of value types:
--
--   1. Unboxed types: values are machine values made up of fixed numbers of bytes
--   2. Unlifted types: values are pointers, but strictly evaluated
--   3. Lifted types: values are pointers, lazily evaluated
--
-- The first category can be stored in a 'ByteArray', and this allows types in
-- category 3 that are simple wrappers around category 1 types to be stored
-- more efficiently using a 'ByteArray'. This module provides the same facility
-- for category 2 types.
--
-- GHC has two primitive types, 'ArrayArray#' and 'MutableArrayArray#'. These
-- are arrays of pointers, but of category 2 values, so they are known to not
-- be bottom. This allows types that are wrappers around such types to be stored
-- in an array without an extra level of indirection.
--
-- The way that the 'ArrayArray#' API works is that one can read and write
-- 'ArrayArray#' values to the positions. This works because all category 2
-- types share a uniform representation, unlike unboxed values which are
-- represented by varying (by type) numbers of bytes. However, using the
-- this makes the internal API very unsafe to use, as one has to coerce values
-- to and from 'ArrayArray#'.
--
-- The API presented by this module is more type safe. 'UnliftedArray' and
-- 'MutableUnliftedArray' are parameterized by the type of arrays they contain, and
-- the coercions necessary are abstracted into a class, 'PrimUnlifted', of things
-- that are eligible to be stored.
--
module Z.Data.Array.UnliftedArray where

import Control.Monad.Primitive
import Data.Primitive.PrimArray (PrimArray(..),MutablePrimArray(..))
import Data.Primitive.ByteArray (ByteArray(..),MutableByteArray(..))
import GHC.MVar (MVar(..))
import GHC.IORef (IORef(..))
import GHC.STRef (STRef(..))
import GHC.Exts
import GHC.IO.Unsafe

class PrimUnlifted a where
    writeUnliftedArray# :: MutableArrayArray# s -> Int# -> a -> State# s -> State# s
    readUnliftedArray# :: MutableArrayArray# s -> Int# -> State# s -> (# State# s, a #)
    indexUnliftedArray# :: ArrayArray# -> Int# -> a

instance PrimUnlifted (PrimArray a) where
    {-# inline writeUnliftedArray# #-}
    {-# inline readUnliftedArray# #-}
    {-# inline indexUnliftedArray# #-}
    writeUnliftedArray# :: MutableArrayArray# s -> Int# -> PrimArray a -> State# s -> State# s
writeUnliftedArray# MutableArrayArray# s
a Int#
i (PrimArray ByteArray#
x) = MutableArrayArray# s -> Int# -> ByteArray# -> State# s -> State# s
forall d.
MutableArrayArray# d -> Int# -> ByteArray# -> State# d -> State# d
writeByteArrayArray# MutableArrayArray# s
a Int#
i ByteArray#
x
    readUnliftedArray# :: MutableArrayArray# s
-> Int# -> State# s -> (# State# s, PrimArray a #)
readUnliftedArray# MutableArrayArray# s
a Int#
i State# s
s0 = case MutableArrayArray# s
-> Int# -> State# s -> (# State# s, ByteArray# #)
forall d.
MutableArrayArray# d
-> Int# -> State# d -> (# State# d, ByteArray# #)
readByteArrayArray# MutableArrayArray# s
a Int#
i State# s
s0 of
        (# State# s
s1, ByteArray#
x #) -> (# State# s
s1, ByteArray# -> PrimArray a
forall a. ByteArray# -> PrimArray a
PrimArray ByteArray#
x #)
    indexUnliftedArray# :: ArrayArray# -> Int# -> PrimArray a
indexUnliftedArray# ArrayArray#
a Int#
i = ByteArray# -> PrimArray a
forall a. ByteArray# -> PrimArray a
PrimArray (ArrayArray# -> Int# -> ByteArray#
indexByteArrayArray# ArrayArray#
a Int#
i)

instance PrimUnlifted ByteArray where
    {-# inline writeUnliftedArray# #-}
    {-# inline readUnliftedArray# #-}
    {-# inline indexUnliftedArray# #-}
    writeUnliftedArray# :: MutableArrayArray# s -> Int# -> ByteArray -> State# s -> State# s
writeUnliftedArray# MutableArrayArray# s
a Int#
i (ByteArray ByteArray#
x) = MutableArrayArray# s -> Int# -> ByteArray# -> State# s -> State# s
forall d.
MutableArrayArray# d -> Int# -> ByteArray# -> State# d -> State# d
writeByteArrayArray# MutableArrayArray# s
a Int#
i ByteArray#
x
    readUnliftedArray# :: MutableArrayArray# s
-> Int# -> State# s -> (# State# s, ByteArray #)
readUnliftedArray# MutableArrayArray# s
a Int#
i State# s
s0 = case MutableArrayArray# s
-> Int# -> State# s -> (# State# s, ByteArray# #)
forall d.
MutableArrayArray# d
-> Int# -> State# d -> (# State# d, ByteArray# #)
readByteArrayArray# MutableArrayArray# s
a Int#
i State# s
s0 of
        (# State# s
s1, ByteArray#
x #) -> (# State# s
s1, ByteArray# -> ByteArray
ByteArray ByteArray#
x #)
    indexUnliftedArray# :: ArrayArray# -> Int# -> ByteArray
indexUnliftedArray# ArrayArray#
a Int#
i = ByteArray# -> ByteArray
ByteArray (ArrayArray# -> Int# -> ByteArray#
indexByteArrayArray# ArrayArray#
a Int#
i)

-- This uses unsafeCoerce# in the implementation of
-- indexUnliftedArray#. This does not lead to corruption FFI codegen
-- since ByteArray# and MutableByteArray# have the same FFI offset
-- applied by add_shim.
-- This also uses unsafeCoerce# to relax the constraints on the
-- state token. The primitives in GHC.Prim are too restrictive.
instance PrimUnlifted (MutableByteArray s) where
    {-# inline writeUnliftedArray# #-}
    {-# inline readUnliftedArray# #-}
    {-# inline indexUnliftedArray# #-}
    writeUnliftedArray# :: MutableArrayArray# s
-> Int# -> MutableByteArray s -> State# s -> State# s
writeUnliftedArray# MutableArrayArray# s
a Int#
i (MutableByteArray MutableByteArray# s
x) =
        MutableArrayArray# s
-> Int# -> MutableByteArray# s -> State# s -> State# s
forall d.
MutableArrayArray# d
-> Int# -> MutableByteArray# d -> State# d -> State# d
writeMutableByteArrayArray# MutableArrayArray# s
a Int#
i (MutableByteArray# s -> MutableByteArray# s
unsafeCoerce# MutableByteArray# s
x)
    readUnliftedArray# :: MutableArrayArray# s
-> Int# -> State# s -> (# State# s, MutableByteArray s #)
readUnliftedArray# MutableArrayArray# s
a Int#
i State# s
s0 = case MutableArrayArray# s
-> Int# -> State# s -> (# State# s, MutableByteArray# s #)
forall d.
MutableArrayArray# d
-> Int# -> State# d -> (# State# d, MutableByteArray# d #)
readMutableByteArrayArray# MutableArrayArray# s
a Int#
i State# s
s0 of
        (# State# s
s1, MutableByteArray# s
x #) -> (# State# s
s1, MutableByteArray# s -> MutableByteArray s
forall s. MutableByteArray# s -> MutableByteArray s
MutableByteArray (MutableByteArray# s -> MutableByteArray# s
unsafeCoerce# MutableByteArray# s
x) #)
    indexUnliftedArray# :: ArrayArray# -> Int# -> MutableByteArray s
indexUnliftedArray# ArrayArray#
a Int#
i = MutableByteArray# s -> MutableByteArray s
forall s. MutableByteArray# s -> MutableByteArray s
MutableByteArray (ByteArray# -> MutableByteArray# s
unsafeCoerce# (ArrayArray# -> Int# -> ByteArray#
indexByteArrayArray# ArrayArray#
a Int#
i))

-- See the note on the PrimUnlifted instance for MutableByteArray.
-- The same uses of unsafeCoerce# happen here.
instance PrimUnlifted (MutablePrimArray s a) where
    {-# inline writeUnliftedArray# #-}
    {-# inline readUnliftedArray# #-}
    {-# inline indexUnliftedArray# #-}
    writeUnliftedArray# :: MutableArrayArray# s
-> Int# -> MutablePrimArray s a -> State# s -> State# s
writeUnliftedArray# MutableArrayArray# s
a Int#
i (MutablePrimArray MutableByteArray# s
x) =
        MutableArrayArray# s
-> Int# -> MutableByteArray# s -> State# s -> State# s
forall d.
MutableArrayArray# d
-> Int# -> MutableByteArray# d -> State# d -> State# d
writeMutableByteArrayArray# MutableArrayArray# s
a Int#
i (MutableByteArray# s -> MutableByteArray# s
unsafeCoerce# MutableByteArray# s
x)
    readUnliftedArray# :: MutableArrayArray# s
-> Int# -> State# s -> (# State# s, MutablePrimArray s a #)
readUnliftedArray# MutableArrayArray# s
a Int#
i State# s
s0 = case MutableArrayArray# s
-> Int# -> State# s -> (# State# s, MutableByteArray# s #)
forall d.
MutableArrayArray# d
-> Int# -> State# d -> (# State# d, MutableByteArray# d #)
readMutableByteArrayArray# MutableArrayArray# s
a Int#
i State# s
s0 of
        (# State# s
s1, MutableByteArray# s
x #) -> (# State# s
s1, MutableByteArray# s -> MutablePrimArray s a
forall s a. MutableByteArray# s -> MutablePrimArray s a
MutablePrimArray (MutableByteArray# s -> MutableByteArray# s
unsafeCoerce# MutableByteArray# s
x) #)
    indexUnliftedArray# :: ArrayArray# -> Int# -> MutablePrimArray s a
indexUnliftedArray# ArrayArray#
a Int#
i = MutableByteArray# s -> MutablePrimArray s a
forall s a. MutableByteArray# s -> MutablePrimArray s a
MutablePrimArray (ByteArray# -> MutableByteArray# s
unsafeCoerce# (ArrayArray# -> Int# -> ByteArray#
indexByteArrayArray# ArrayArray#
a Int#
i))

-- This uses unsafeCoerce# in the implementation of all of its
-- methods. See the note for the PrimUnlifted instance of
-- Data.Primitive.MVar.MVar.
instance PrimUnlifted (MVar a) where
    {-# inline writeUnliftedArray# #-}
    {-# inline readUnliftedArray# #-}
    {-# inline indexUnliftedArray# #-}
    writeUnliftedArray# :: MutableArrayArray# s -> Int# -> MVar a -> State# s -> State# s
writeUnliftedArray# MutableArrayArray# s
a Int#
i (MVar MVar# RealWorld a
x) =
        MutableArrayArray# s -> Int# -> ArrayArray# -> State# s -> State# s
forall d.
MutableArrayArray# d -> Int# -> ArrayArray# -> State# d -> State# d
writeArrayArrayArray# MutableArrayArray# s
a Int#
i (MVar# RealWorld a -> ArrayArray#
unsafeCoerce# MVar# RealWorld a
x)
    readUnliftedArray# :: MutableArrayArray# s -> Int# -> State# s -> (# State# s, MVar a #)
readUnliftedArray# MutableArrayArray# s
a Int#
i State# s
s0 = case MutableArrayArray# s
-> Int# -> State# s -> (# State# s, ArrayArray# #)
forall d.
MutableArrayArray# d
-> Int# -> State# d -> (# State# d, ArrayArray# #)
readArrayArrayArray# MutableArrayArray# s
a Int#
i State# s
s0 of
        (# State# s
s1, ArrayArray#
x #) -> (# State# s
s1, MVar# RealWorld a -> MVar a
forall a. MVar# RealWorld a -> MVar a
MVar (ArrayArray# -> MVar# RealWorld a
unsafeCoerce# ArrayArray#
x) #)
    indexUnliftedArray# :: ArrayArray# -> Int# -> MVar a
indexUnliftedArray# ArrayArray#
a Int#
i = MVar# RealWorld a -> MVar a
forall a. MVar# RealWorld a -> MVar a
MVar (ArrayArray# -> MVar# RealWorld a
unsafeCoerce# (ArrayArray# -> Int# -> ArrayArray#
indexArrayArrayArray# ArrayArray#
a Int#
i))

-- This uses unsafeCoerce# in the implementation of all of its
-- methods. This does not lead to corruption FFI codegen since ArrayArray#
-- and MutVar# have the same FFI offset applied by add_shim.
instance PrimUnlifted (STRef s a) where
    {-# inline writeUnliftedArray# #-}
    {-# inline readUnliftedArray# #-}
    {-# inline indexUnliftedArray# #-}
    writeUnliftedArray# :: MutableArrayArray# s -> Int# -> STRef s a -> State# s -> State# s
writeUnliftedArray# MutableArrayArray# s
a Int#
i (STRef MutVar# s a
x) =
        MutableArrayArray# s -> Int# -> ArrayArray# -> State# s -> State# s
forall d.
MutableArrayArray# d -> Int# -> ArrayArray# -> State# d -> State# d
writeArrayArrayArray# MutableArrayArray# s
a Int#
i (MutVar# s a -> ArrayArray#
unsafeCoerce# MutVar# s a
x)
    readUnliftedArray# :: MutableArrayArray# s
-> Int# -> State# s -> (# State# s, STRef s a #)
readUnliftedArray# MutableArrayArray# s
a Int#
i State# s
s0 = case MutableArrayArray# s
-> Int# -> State# s -> (# State# s, ArrayArray# #)
forall d.
MutableArrayArray# d
-> Int# -> State# d -> (# State# d, ArrayArray# #)
readArrayArrayArray# MutableArrayArray# s
a Int#
i State# s
s0 of
        (# State# s
s1, ArrayArray#
x #) -> (# State# s
s1, MutVar# s a -> STRef s a
forall s a. MutVar# s a -> STRef s a
STRef (ArrayArray# -> MutVar# s a
unsafeCoerce# ArrayArray#
x) #)
    indexUnliftedArray# :: ArrayArray# -> Int# -> STRef s a
indexUnliftedArray# ArrayArray#
a Int#
i =
        MutVar# s a -> STRef s a
forall s a. MutVar# s a -> STRef s a
STRef (ArrayArray# -> MutVar# s a
unsafeCoerce# (ArrayArray# -> Int# -> ArrayArray#
indexArrayArrayArray# ArrayArray#
a Int#
i))

instance PrimUnlifted (IORef a) where
    {-# inline writeUnliftedArray# #-}
    {-# inline readUnliftedArray# #-}
    {-# inline indexUnliftedArray# #-}
    writeUnliftedArray# :: MutableArrayArray# s -> Int# -> IORef a -> State# s -> State# s
writeUnliftedArray# MutableArrayArray# s
a Int#
i (IORef STRef RealWorld a
v) = MutableArrayArray# s
-> Int# -> STRef RealWorld a -> State# s -> State# s
forall a s.
PrimUnlifted a =>
MutableArrayArray# s -> Int# -> a -> State# s -> State# s
writeUnliftedArray# MutableArrayArray# s
a Int#
i STRef RealWorld a
v
    readUnliftedArray# :: MutableArrayArray# s -> Int# -> State# s -> (# State# s, IORef a #)
readUnliftedArray# MutableArrayArray# s
a Int#
i State# s
s0 = case MutableArrayArray# s
-> Int# -> State# s -> (# State# s, STRef RealWorld a #)
forall a s.
PrimUnlifted a =>
MutableArrayArray# s -> Int# -> State# s -> (# State# s, a #)
readUnliftedArray# MutableArrayArray# s
a Int#
i State# s
s0 of
        (# State# s
s1, STRef RealWorld a
v #) -> (# State# s
s1, STRef RealWorld a -> IORef a
forall a. STRef RealWorld a -> IORef a
IORef STRef RealWorld a
v #)
    indexUnliftedArray# :: ArrayArray# -> Int# -> IORef a
indexUnliftedArray# ArrayArray#
a Int#
i = STRef RealWorld a -> IORef a
forall a. STRef RealWorld a -> IORef a
IORef (ArrayArray# -> Int# -> STRef RealWorld a
forall a. PrimUnlifted a => ArrayArray# -> Int# -> a
indexUnliftedArray# ArrayArray#
a Int#
i)

--------------------------------------------------------------------------------

data MutableUnliftedArray s a
    = MutableUnliftedArray (MutableArrayArray# s)

data UnliftedArray a
    = UnliftedArray ArrayArray#

-- | Creates a new 'MutableUnliftedArray'. This function is unsafe because it
-- initializes all elements of the array as pointers to the array itself. Attempting
-- to read one of these elements before writing to it is in effect an unsafe
-- coercion from the @'MutableUnliftedArray' s a@ to the element type.
unsafeNewUnliftedArray
    :: (PrimMonad m)
    => Int -- ^ size
    -> m (MutableUnliftedArray (PrimState m) a)
{-# inline unsafeNewUnliftedArray #-}
unsafeNewUnliftedArray :: Int -> m (MutableUnliftedArray (PrimState m) a)
unsafeNewUnliftedArray (I# Int#
i#) = (State# (PrimState m)
 -> (# State# (PrimState m),
       MutableUnliftedArray (PrimState m) a #))
-> m (MutableUnliftedArray (PrimState m) a)
forall (m :: * -> *) a.
PrimMonad m =>
(State# (PrimState m) -> (# State# (PrimState m), a #)) -> m a
primitive ((State# (PrimState m)
  -> (# State# (PrimState m),
        MutableUnliftedArray (PrimState m) a #))
 -> m (MutableUnliftedArray (PrimState m) a))
-> (State# (PrimState m)
    -> (# State# (PrimState m),
          MutableUnliftedArray (PrimState m) a #))
-> m (MutableUnliftedArray (PrimState m) a)
forall a b. (a -> b) -> a -> b
$ \State# (PrimState m)
s -> case Int#
-> State# (PrimState m)
-> (# State# (PrimState m), MutableArrayArray# (PrimState m) #)
forall d. Int# -> State# d -> (# State# d, MutableArrayArray# d #)
newArrayArray# Int#
i# State# (PrimState m)
s of
    (# State# (PrimState m)
s', MutableArrayArray# (PrimState m)
maa# #) -> (# State# (PrimState m)
s', MutableArrayArray# (PrimState m)
-> MutableUnliftedArray (PrimState m) a
forall s a. MutableArrayArray# s -> MutableUnliftedArray s a
MutableUnliftedArray MutableArrayArray# (PrimState m)
maa# #)

-- | Creates a new 'MutableUnliftedArray' with the specified value as initial
-- contents. This is slower than 'unsafeNewUnliftedArray', but safer.
newUnliftedArray
    :: (PrimMonad m, PrimUnlifted a)
    => Int -- ^ size
    -> a -- ^ initial value
    -> m (MutableUnliftedArray (PrimState m) a)
newUnliftedArray :: Int -> a -> m (MutableUnliftedArray (PrimState m) a)
newUnliftedArray Int
len a
v = do
    MutableUnliftedArray (PrimState m) a
mua <- Int -> m (MutableUnliftedArray (PrimState m) a)
forall (m :: * -> *) a.
PrimMonad m =>
Int -> m (MutableUnliftedArray (PrimState m) a)
unsafeNewUnliftedArray Int
len
    MutableUnliftedArray (PrimState m) a -> Int -> Int -> a -> m ()
forall (m :: * -> *) a.
(PrimMonad m, PrimUnlifted a) =>
MutableUnliftedArray (PrimState m) a -> Int -> Int -> a -> m ()
setUnliftedArray MutableUnliftedArray (PrimState m) a
mua Int
0 Int
len a
v
    MutableUnliftedArray (PrimState m) a
-> m (MutableUnliftedArray (PrimState m) a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure MutableUnliftedArray (PrimState m) a
mua
{-# inline newUnliftedArray #-}

setUnliftedArray
    :: (PrimMonad m, PrimUnlifted a)
    => MutableUnliftedArray (PrimState m) a -- ^ destination
    -> Int -- ^ offset
    -> Int -- ^ length
    -> a -- ^ value to fill with
    -> m ()
{-# inline setUnliftedArray #-}
setUnliftedArray :: MutableUnliftedArray (PrimState m) a -> Int -> Int -> a -> m ()
setUnliftedArray MutableUnliftedArray (PrimState m) a
mua Int
off Int
len a
v = Int -> m ()
loop (Int
len Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
off Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
  where
    loop :: Int -> m ()
loop Int
i
        | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
off = () -> m ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
        | Bool
otherwise = MutableUnliftedArray (PrimState m) a -> Int -> a -> m ()
forall (m :: * -> *) a.
(PrimMonad m, PrimUnlifted a) =>
MutableUnliftedArray (PrimState m) a -> Int -> a -> m ()
writeUnliftedArray MutableUnliftedArray (PrimState m) a
mua Int
i a
v m () -> m () -> m ()
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Int -> m ()
loop (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)

-- | Yields the length of an 'UnliftedArray'.
sizeofUnliftedArray :: UnliftedArray e -> Int
{-# inline sizeofUnliftedArray #-}
sizeofUnliftedArray :: UnliftedArray e -> Int
sizeofUnliftedArray (UnliftedArray ArrayArray#
aa#) = Int# -> Int
I# (ArrayArray# -> Int#
sizeofArrayArray# ArrayArray#
aa#)

-- | Yields the length of a 'MutableUnliftedArray'.
sizeofMutableUnliftedArray :: MutableUnliftedArray s e -> Int
{-# inline sizeofMutableUnliftedArray #-}
sizeofMutableUnliftedArray :: MutableUnliftedArray s e -> Int
sizeofMutableUnliftedArray (MutableUnliftedArray MutableArrayArray# s
maa#)
    = Int# -> Int
I# (MutableArrayArray# s -> Int#
forall d. MutableArrayArray# d -> Int#
sizeofMutableArrayArray# MutableArrayArray# s
maa#)

writeUnliftedArray :: (PrimMonad m, PrimUnlifted a)
    => MutableUnliftedArray (PrimState m) a
    -> Int
    -> a
    -> m ()
{-# inline writeUnliftedArray #-}
writeUnliftedArray :: MutableUnliftedArray (PrimState m) a -> Int -> a -> m ()
writeUnliftedArray (MutableUnliftedArray MutableArrayArray# (PrimState m)
arr) (I# Int#
ix) a
a =
    (State# (PrimState m) -> State# (PrimState m)) -> m ()
forall (m :: * -> *).
PrimMonad m =>
(State# (PrimState m) -> State# (PrimState m)) -> m ()
primitive_ (MutableArrayArray# (PrimState m)
-> Int# -> a -> State# (PrimState m) -> State# (PrimState m)
forall a s.
PrimUnlifted a =>
MutableArrayArray# s -> Int# -> a -> State# s -> State# s
writeUnliftedArray# MutableArrayArray# (PrimState m)
arr Int#
ix a
a)

readUnliftedArray :: (PrimMonad m, PrimUnlifted a)
    => MutableUnliftedArray (PrimState m) a
    -> Int
    -> m a
{-# inline readUnliftedArray #-}
readUnliftedArray :: MutableUnliftedArray (PrimState m) a -> Int -> m a
readUnliftedArray (MutableUnliftedArray MutableArrayArray# (PrimState m)
arr) (I# Int#
ix) =
    (State# (PrimState m) -> (# State# (PrimState m), a #)) -> m a
forall (m :: * -> *) a.
PrimMonad m =>
(State# (PrimState m) -> (# State# (PrimState m), a #)) -> m a
primitive (MutableArrayArray# (PrimState m)
-> Int# -> State# (PrimState m) -> (# State# (PrimState m), a #)
forall a s.
PrimUnlifted a =>
MutableArrayArray# s -> Int# -> State# s -> (# State# s, a #)
readUnliftedArray# MutableArrayArray# (PrimState m)
arr Int#
ix)

indexUnliftedArray :: PrimUnlifted a
    => UnliftedArray a
    -> Int
    -> a
{-# inline indexUnliftedArray #-}
indexUnliftedArray :: UnliftedArray a -> Int -> a
indexUnliftedArray (UnliftedArray ArrayArray#
arr) (I# Int#
ix) =
    ArrayArray# -> Int# -> a
forall a. PrimUnlifted a => ArrayArray# -> Int# -> a
indexUnliftedArray# ArrayArray#
arr Int#
ix

-- | Freezes a 'MutableUnliftedArray', yielding an 'UnliftedArray'. This simply
-- marks the array as frozen in place, so it should only be used when no further
-- modifications to the mutable array will be performed.
unsafeFreezeUnliftedArray
    :: (PrimMonad m)
    => MutableUnliftedArray (PrimState m) a
    -> m (UnliftedArray a)
unsafeFreezeUnliftedArray :: MutableUnliftedArray (PrimState m) a -> m (UnliftedArray a)
unsafeFreezeUnliftedArray (MutableUnliftedArray MutableArrayArray# (PrimState m)
maa#)
    = (State# (PrimState m)
 -> (# State# (PrimState m), UnliftedArray a #))
-> m (UnliftedArray a)
forall (m :: * -> *) a.
PrimMonad m =>
(State# (PrimState m) -> (# State# (PrimState m), a #)) -> m a
primitive ((State# (PrimState m)
  -> (# State# (PrimState m), UnliftedArray a #))
 -> m (UnliftedArray a))
-> (State# (PrimState m)
    -> (# State# (PrimState m), UnliftedArray a #))
-> m (UnliftedArray a)
forall a b. (a -> b) -> a -> b
$ \State# (PrimState m)
s -> case MutableArrayArray# (PrimState m)
-> State# (PrimState m) -> (# State# (PrimState m), ArrayArray# #)
forall d.
MutableArrayArray# d -> State# d -> (# State# d, ArrayArray# #)
unsafeFreezeArrayArray# MutableArrayArray# (PrimState m)
maa# State# (PrimState m)
s of
        (# State# (PrimState m)
s', ArrayArray#
aa# #) -> (# State# (PrimState m)
s', ArrayArray# -> UnliftedArray a
forall a. ArrayArray# -> UnliftedArray a
UnliftedArray ArrayArray#
aa# #)
{-# inline unsafeFreezeUnliftedArray #-}

-- | Determines whether two 'MutableUnliftedArray' values are the same. This is
-- object/pointer identity, not based on the contents.
sameMutableUnliftedArray
    :: MutableUnliftedArray s a
    -> MutableUnliftedArray s a
    -> Bool
sameMutableUnliftedArray :: MutableUnliftedArray s a -> MutableUnliftedArray s a -> Bool
sameMutableUnliftedArray (MutableUnliftedArray MutableArrayArray# s
maa1#) (MutableUnliftedArray MutableArrayArray# s
maa2#)
    = Int# -> Bool
isTrue# (MutableArrayArray# s -> MutableArrayArray# s -> Int#
forall d. MutableArrayArray# d -> MutableArrayArray# d -> Int#
sameMutableArrayArray# MutableArrayArray# s
maa1# MutableArrayArray# s
maa2#)
{-# inline sameMutableUnliftedArray #-}

-- | Copies the contents of an immutable array into a mutable array.
copyUnliftedArray
    :: (PrimMonad m)
    => MutableUnliftedArray (PrimState m) a -- ^ destination
    -> Int -- ^ offset into destination
    -> UnliftedArray a -- ^ source
    -> Int -- ^ offset into source
    -> Int -- ^ number of elements to copy
    -> m ()
{-# inline copyUnliftedArray #-}
copyUnliftedArray :: MutableUnliftedArray (PrimState m) a
-> Int -> UnliftedArray a -> Int -> Int -> m ()
copyUnliftedArray
    (MutableUnliftedArray MutableArrayArray# (PrimState m)
dst) (I# Int#
doff)
    (UnliftedArray ArrayArray#
src) (I# Int#
soff) (I# Int#
ln) =
      (State# (PrimState m) -> State# (PrimState m)) -> m ()
forall (m :: * -> *).
PrimMonad m =>
(State# (PrimState m) -> State# (PrimState m)) -> m ()
primitive_ ((State# (PrimState m) -> State# (PrimState m)) -> m ())
-> (State# (PrimState m) -> State# (PrimState m)) -> m ()
forall a b. (a -> b) -> a -> b
$ ArrayArray#
-> Int#
-> MutableArrayArray# (PrimState m)
-> Int#
-> Int#
-> State# (PrimState m)
-> State# (PrimState m)
forall d.
ArrayArray#
-> Int#
-> MutableArrayArray# d
-> Int#
-> Int#
-> State# d
-> State# d
copyArrayArray# ArrayArray#
src Int#
soff MutableArrayArray# (PrimState m)
dst Int#
doff Int#
ln


-- | Copies the contents of one mutable array into another.
copyMutableUnliftedArray
    :: (PrimMonad m)
    => MutableUnliftedArray (PrimState m) a -- ^ destination
    -> Int -- ^ offset into destination
    -> MutableUnliftedArray (PrimState m) a -- ^ source
    -> Int -- ^ offset into source
    -> Int -- ^ number of elements to copy
    -> m ()
{-# inline copyMutableUnliftedArray #-}
copyMutableUnliftedArray :: MutableUnliftedArray (PrimState m) a
-> Int
-> MutableUnliftedArray (PrimState m) a
-> Int
-> Int
-> m ()
copyMutableUnliftedArray
    (MutableUnliftedArray MutableArrayArray# (PrimState m)
dst) (I# Int#
doff)
    (MutableUnliftedArray MutableArrayArray# (PrimState m)
src) (I# Int#
soff) (I# Int#
ln) =
      (State# (PrimState m) -> State# (PrimState m)) -> m ()
forall (m :: * -> *).
PrimMonad m =>
(State# (PrimState m) -> State# (PrimState m)) -> m ()
primitive_ ((State# (PrimState m) -> State# (PrimState m)) -> m ())
-> (State# (PrimState m) -> State# (PrimState m)) -> m ()
forall a b. (a -> b) -> a -> b
$ MutableArrayArray# (PrimState m)
-> Int#
-> MutableArrayArray# (PrimState m)
-> Int#
-> Int#
-> State# (PrimState m)
-> State# (PrimState m)
forall d.
MutableArrayArray# d
-> Int#
-> MutableArrayArray# d
-> Int#
-> Int#
-> State# d
-> State# d
copyMutableArrayArray# MutableArrayArray# (PrimState m)
src Int#
soff MutableArrayArray# (PrimState m)
dst Int#
doff Int#
ln


-- | Freezes a portion of a 'MutableUnliftedArray', yielding an 'UnliftedArray'.
-- This operation is safe, in that it copies the frozen portion, and the
-- existing mutable array may still be used afterward.
freezeUnliftedArray
    :: (PrimMonad m)
    => MutableUnliftedArray (PrimState m) a -- ^ source
    -> Int -- ^ offset
    -> Int -- ^ length
    -> m (UnliftedArray a)
freezeUnliftedArray :: MutableUnliftedArray (PrimState m) a
-> Int -> Int -> m (UnliftedArray a)
freezeUnliftedArray MutableUnliftedArray (PrimState m) a
src Int
off Int
len = do
    MutableUnliftedArray (PrimState m) a
dst <- Int -> m (MutableUnliftedArray (PrimState m) a)
forall (m :: * -> *) a.
PrimMonad m =>
Int -> m (MutableUnliftedArray (PrimState m) a)
unsafeNewUnliftedArray Int
len
    MutableUnliftedArray (PrimState m) a
-> Int
-> MutableUnliftedArray (PrimState m) a
-> Int
-> Int
-> m ()
forall (m :: * -> *) a.
PrimMonad m =>
MutableUnliftedArray (PrimState m) a
-> Int
-> MutableUnliftedArray (PrimState m) a
-> Int
-> Int
-> m ()
copyMutableUnliftedArray MutableUnliftedArray (PrimState m) a
dst Int
0 MutableUnliftedArray (PrimState m) a
src Int
off Int
len
    MutableUnliftedArray (PrimState m) a -> m (UnliftedArray a)
forall (m :: * -> *) a.
PrimMonad m =>
MutableUnliftedArray (PrimState m) a -> m (UnliftedArray a)
unsafeFreezeUnliftedArray MutableUnliftedArray (PrimState m) a
dst
{-# inline freezeUnliftedArray #-}


-- | Thaws a portion of an 'UnliftedArray', yielding a 'MutableUnliftedArray'.
-- This copies the thawed portion, so mutations will not affect the original
-- array.
thawUnliftedArray
    :: (PrimMonad m)
    => UnliftedArray a -- ^ source
    -> Int -- ^ offset
    -> Int -- ^ length
    -> m (MutableUnliftedArray (PrimState m) a)
{-# inline thawUnliftedArray #-}
thawUnliftedArray :: UnliftedArray a
-> Int -> Int -> m (MutableUnliftedArray (PrimState m) a)
thawUnliftedArray UnliftedArray a
src Int
off Int
len = do
    MutableUnliftedArray (PrimState m) a
dst <- Int -> m (MutableUnliftedArray (PrimState m) a)
forall (m :: * -> *) a.
PrimMonad m =>
Int -> m (MutableUnliftedArray (PrimState m) a)
unsafeNewUnliftedArray Int
len
    MutableUnliftedArray (PrimState m) a
-> Int -> UnliftedArray a -> Int -> Int -> m ()
forall (m :: * -> *) a.
PrimMonad m =>
MutableUnliftedArray (PrimState m) a
-> Int -> UnliftedArray a -> Int -> Int -> m ()
copyUnliftedArray MutableUnliftedArray (PrimState m) a
dst Int
0 UnliftedArray a
src Int
off Int
len
    MutableUnliftedArray (PrimState m) a
-> m (MutableUnliftedArray (PrimState m) a)
forall (m :: * -> *) a. Monad m => a -> m a
return MutableUnliftedArray (PrimState m) a
dst

-- | Creates a copy of a portion of an 'UnliftedArray'
cloneUnliftedArray
    :: UnliftedArray a -- ^ source
    -> Int -- ^ offset
    -> Int -- ^ length
    -> UnliftedArray a
{-# inline cloneUnliftedArray #-}
cloneUnliftedArray :: UnliftedArray a -> Int -> Int -> UnliftedArray a
cloneUnliftedArray UnliftedArray a
src Int
off Int
len = IO (UnliftedArray a) -> UnliftedArray a
forall a. IO a -> a
unsafeDupablePerformIO (IO (UnliftedArray a) -> UnliftedArray a)
-> IO (UnliftedArray a) -> UnliftedArray a
forall a b. (a -> b) -> a -> b
$ do
    MutableUnliftedArray RealWorld a
dst <- Int -> IO (MutableUnliftedArray (PrimState IO) a)
forall (m :: * -> *) a.
PrimMonad m =>
Int -> m (MutableUnliftedArray (PrimState m) a)
unsafeNewUnliftedArray Int
len
    MutableUnliftedArray (PrimState IO) a
-> Int -> UnliftedArray a -> Int -> Int -> IO ()
forall (m :: * -> *) a.
PrimMonad m =>
MutableUnliftedArray (PrimState m) a
-> Int -> UnliftedArray a -> Int -> Int -> m ()
copyUnliftedArray MutableUnliftedArray RealWorld a
MutableUnliftedArray (PrimState IO) a
dst Int
0 UnliftedArray a
src Int
off Int
len
    MutableUnliftedArray (PrimState IO) a -> IO (UnliftedArray a)
forall (m :: * -> *) a.
PrimMonad m =>
MutableUnliftedArray (PrimState m) a -> m (UnliftedArray a)
unsafeFreezeUnliftedArray MutableUnliftedArray RealWorld a
MutableUnliftedArray (PrimState IO) a
dst

-- | Creates a new 'MutableUnliftedArray' containing a copy of a portion of
-- another mutable array.
cloneMutableUnliftedArray
    :: (PrimMonad m)
    => MutableUnliftedArray (PrimState m) a -- ^ source
    -> Int -- ^ offset
    -> Int -- ^ length
    -> m (MutableUnliftedArray (PrimState m) a)
{-# inline cloneMutableUnliftedArray #-}
cloneMutableUnliftedArray :: MutableUnliftedArray (PrimState m) a
-> Int -> Int -> m (MutableUnliftedArray (PrimState m) a)
cloneMutableUnliftedArray MutableUnliftedArray (PrimState m) a
src Int
off Int
len = do
    MutableUnliftedArray (PrimState m) a
dst <- Int -> m (MutableUnliftedArray (PrimState m) a)
forall (m :: * -> *) a.
PrimMonad m =>
Int -> m (MutableUnliftedArray (PrimState m) a)
unsafeNewUnliftedArray Int
len
    MutableUnliftedArray (PrimState m) a
-> Int
-> MutableUnliftedArray (PrimState m) a
-> Int
-> Int
-> m ()
forall (m :: * -> *) a.
PrimMonad m =>
MutableUnliftedArray (PrimState m) a
-> Int
-> MutableUnliftedArray (PrimState m) a
-> Int
-> Int
-> m ()
copyMutableUnliftedArray MutableUnliftedArray (PrimState m) a
dst Int
0 MutableUnliftedArray (PrimState m) a
src Int
off Int
len
    MutableUnliftedArray (PrimState m) a
-> m (MutableUnliftedArray (PrimState m) a)
forall (m :: * -> *) a. Monad m => a -> m a
return MutableUnliftedArray (PrimState m) a
dst