{-|
Module      : Z.Data.Array.Checked
Description : Bounded checked boxed and unboxed arrays
Copyright   : (c) Dong Han, 2017-2019
License     : BSD
Maintainer  : winterland1989@gmail.com
Stability   : experimental
Portability : non-portable

This module provides exactly the same API with "Z.Data.Array", but will throw an 'IndexOutOfBounds'
'ArrayException' on bound check failure, it's useful when debugging array algorithms: just swap this
module with "Z.Data.Array", segmentation faults caused by out bound access will be turned into exceptions
with more informations.

-}
module Z.Data.Array.Checked
  ( -- * Arr typeclass re-export
    Arr, MArr
  , A.emptyArr, A.singletonArr, A.doubletonArr
  , modifyIndexArr, insertIndexArr, deleteIndexArr
  , RealWorld
  -- * Boxed array type
  , A.Array(..)
  , A.MutableArray(..)
  , A.SmallArray(..)
  , A.SmallMutableArray(..)
  , A.uninitialized
  -- * Primitive array type
  , A.PrimArray(..)
  , A.MutablePrimArray(..)
  , Prim(..)
  -- * Bound checked array operations
  , newArr
  , newArrWith
  , readArr
  , writeArr
  , setArr
  , indexArr
  , indexArr'
  , indexArrM
  , freezeArr
  , thawArr
  , copyArr
  , copyMutableArr
  , moveArr
  , cloneArr
  , cloneMutableArr
  , resizeMutableArr
  , shrinkMutableArr
  -- * No bound checked operations
  , A.unsafeFreezeArr
  , A.unsafeThawArr
  , A.sameMutableArr
  , A.sizeofArr
  , A.sizeofMutableArr
  , A.sameArr
  -- * Bound checked primitive array operations
  , newPinnedPrimArray, newAlignedPinnedPrimArray
  , copyPrimArrayToPtr, copyMutablePrimArrayToPtr, copyPtrToMutablePrimArray
  -- * No bound checked primitive array operations
  , A.primArrayContents, A.mutablePrimArrayContents, A.withPrimArrayContents, A.withMutablePrimArrayContents
  , A.isPrimArrayPinned, A.isMutablePrimArrayPinned
  -- * Unlifted array type
  , A.UnliftedArray(..)
  , A.MutableUnliftedArray(..)
  , A.PrimUnlifted(..)
  -- * The 'ArrayException' type
  , ArrayException(..)
  -- * Cast between primitive arrays
  , A.Cast
  , A.castArray
  , A.castMutableArray
  -- * Re-export
  , sizeOf
  ) where

import           Control.Exception       (ArrayException (..), throw)
import           Control.Monad
import           Control.Monad.Primitive
import           Control.Monad.ST
import           Data.Primitive.Types
import           GHC.Stack
import           Z.Data.Array          (Arr, MArr)
import qualified Z.Data.Array          as A

check :: HasCallStack => Bool -> a -> a
{-# INLINE check #-}
check :: Bool -> a -> a
check Bool
True  a
x = a
x
check Bool
False a
_ = ArrayException -> a
forall a e. Exception e => e -> a
throw (String -> ArrayException
IndexOutOfBounds (String -> ArrayException) -> String -> ArrayException
forall a b. (a -> b) -> a -> b
$ CallStack -> String
forall a. Show a => a -> String
show CallStack
HasCallStack => CallStack
callStack)

newArr :: (Arr arr a, PrimMonad m, PrimState m ~ s, HasCallStack)
       => Int -> m (MArr arr s a)
newArr :: Int -> m (MArr arr s a)
newArr Int
n = Bool -> m (MArr arr s a) -> m (MArr arr s a)
forall a. HasCallStack => Bool -> a -> a
check  (Int
nInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0) (Int -> m (MArr arr s a)
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s) =>
Int -> m (MArr arr s a)
A.newArr Int
n)
{-# INLINE newArr #-}

newArrWith :: (Arr arr a, PrimMonad m, PrimState m ~ s, HasCallStack)
           => Int -> a -> m (MArr arr s a)
newArrWith :: Int -> a -> m (MArr arr s a)
newArrWith Int
n a
x = Bool -> m (MArr arr s a) -> m (MArr arr s a)
forall a. HasCallStack => Bool -> a -> a
check  (Int
nInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0) (Int -> a -> m (MArr arr s a)
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s) =>
Int -> a -> m (MArr arr s a)
A.newArrWith Int
n a
x)
{-# INLINE newArrWith #-}

readArr :: (Arr arr a, PrimMonad m, PrimState m ~ s, HasCallStack)
        => MArr arr s a -> Int -> m a
readArr :: MArr arr s a -> Int -> m a
readArr MArr arr s a
marr Int
i = do
    Int
siz <- MArr arr s a -> m Int
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s) =>
MArr arr s a -> m Int
A.sizeofMutableArr MArr arr s a
marr
    Bool -> m a -> m a
forall a. HasCallStack => Bool -> a -> a
check
        (Int
iInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& Int
iInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<Int
siz)
        (MArr arr s a -> Int -> m a
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s) =>
MArr arr s a -> Int -> m a
A.readArr MArr arr s a
marr Int
i)
{-# INLINE readArr #-}

writeArr :: (Arr arr a, PrimMonad m, PrimState m ~ s, HasCallStack)
         => MArr arr s a -> Int -> a -> m ()
writeArr :: MArr arr s a -> Int -> a -> m ()
writeArr MArr arr s a
marr Int
i a
x = do
    Int
siz <- MArr arr s a -> m Int
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s) =>
MArr arr s a -> m Int
A.sizeofMutableArr MArr arr s a
marr
    Bool -> m () -> m ()
forall a. HasCallStack => Bool -> a -> a
check
        (Int
iInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& Int
iInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<Int
siz)
        (MArr arr s a -> Int -> a -> m ()
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s) =>
MArr arr s a -> Int -> a -> m ()
A.writeArr MArr arr s a
marr Int
i a
x)
{-# INLINE writeArr #-}

setArr :: (Arr arr a, PrimMonad m, PrimState m ~ s, HasCallStack)
       => MArr arr s a -> Int -> Int -> a -> m ()
setArr :: MArr arr s a -> Int -> Int -> a -> m ()
setArr MArr arr s a
marr Int
s Int
l a
x = do
    Int
siz <- MArr arr s a -> m Int
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s) =>
MArr arr s a -> m Int
A.sizeofMutableArr MArr arr s a
marr
    Bool -> m () -> m ()
forall a. HasCallStack => Bool -> a -> a
check
        (Int
sInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& Int
lInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& (Int
sInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
l)Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<=Int
siz)
        (MArr arr s a -> Int -> Int -> a -> m ()
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s) =>
MArr arr s a -> Int -> Int -> a -> m ()
A.setArr MArr arr s a
marr Int
s Int
l a
x)
{-# INLINE setArr #-}

indexArr :: (Arr arr a, HasCallStack)
         => arr a -> Int -> a
indexArr :: arr a -> Int -> a
indexArr arr a
arr Int
i = Bool -> a -> a
forall a. HasCallStack => Bool -> a -> a
check
    (Int
iInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& Int
iInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<arr a -> Int
forall (arr :: * -> *) a. Arr arr a => arr a -> Int
A.sizeofArr arr a
arr)
    (arr a -> Int -> a
forall (arr :: * -> *) a. Arr arr a => arr a -> Int -> a
A.indexArr arr a
arr Int
i)
{-# INLINE indexArr #-}

indexArr' :: (Arr arr a, HasCallStack)
          => arr a -> Int -> (# a #)
indexArr' :: arr a -> Int -> (# a #)
indexArr' arr a
arr Int
i =
    if (Int
iInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& Int
iInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<arr a -> Int
forall (arr :: * -> *) a. Arr arr a => arr a -> Int
A.sizeofArr arr a
arr)
    then arr a -> Int -> (# a #)
forall (arr :: * -> *) a. Arr arr a => arr a -> Int -> (# a #)
A.indexArr' arr a
arr Int
i
    else ArrayException -> (# a #)
forall a e. Exception e => e -> a
throw (String -> ArrayException
IndexOutOfBounds (String -> ArrayException) -> String -> ArrayException
forall a b. (a -> b) -> a -> b
$ CallStack -> String
forall a. Show a => a -> String
show CallStack
HasCallStack => CallStack
callStack)
{-# INLINE indexArr' #-}

indexArrM :: (Arr arr a, Monad m, HasCallStack)
          => arr a -> Int -> m a
indexArrM :: arr a -> Int -> m a
indexArrM arr a
arr Int
i = Bool -> m a -> m a
forall a. HasCallStack => Bool -> a -> a
check
    (Int
iInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& Int
iInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<arr a -> Int
forall (arr :: * -> *) a. Arr arr a => arr a -> Int
A.sizeofArr arr a
arr)
    (arr a -> Int -> m a
forall (arr :: * -> *) a (m :: * -> *).
(Arr arr a, Monad m) =>
arr a -> Int -> m a
A.indexArrM arr a
arr Int
i)
{-# INLINE indexArrM #-}

freezeArr :: (Arr arr a, PrimMonad m, PrimState m ~ s, HasCallStack)
          => MArr arr s a -> Int -> Int -> m (arr a)
freezeArr :: MArr arr s a -> Int -> Int -> m (arr a)
freezeArr MArr arr s a
marr Int
s Int
l = do
    Int
siz <- MArr arr s a -> m Int
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s) =>
MArr arr s a -> m Int
A.sizeofMutableArr MArr arr s a
marr
    Bool -> m (arr a) -> m (arr a)
forall a. HasCallStack => Bool -> a -> a
check
        (Int
sInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& Int
lInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& (Int
sInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
l)Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<=Int
siz)
        (MArr arr s a -> Int -> Int -> m (arr a)
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s) =>
MArr arr s a -> Int -> Int -> m (arr a)
A.freezeArr MArr arr s a
marr Int
s Int
l)
{-# INLINE freezeArr #-}

thawArr :: (Arr arr a, PrimMonad m, PrimState m ~ s, HasCallStack)
        => arr a -> Int -> Int -> m (MArr arr s a)
thawArr :: arr a -> Int -> Int -> m (MArr arr s a)
thawArr arr a
arr Int
s Int
l = Bool -> m (MArr arr s a) -> m (MArr arr s a)
forall a. HasCallStack => Bool -> a -> a
check
    (Int
sInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& Int
lInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& (Int
sInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
l)Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<=arr a -> Int
forall (arr :: * -> *) a. Arr arr a => arr a -> Int
A.sizeofArr arr a
arr)
    (arr a -> Int -> Int -> m (MArr arr s a)
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s) =>
arr a -> Int -> Int -> m (MArr arr s a)
A.thawArr arr a
arr Int
s Int
l)
{-# INLINE thawArr #-}

copyArr :: (Arr arr a, PrimMonad m, PrimState m ~ s, HasCallStack)
        => MArr arr s a -> Int -> arr a -> Int -> Int -> m ()
copyArr :: MArr arr s a -> Int -> arr a -> Int -> Int -> m ()
copyArr MArr arr s a
marr Int
s1 arr a
arr Int
s2 Int
l = do
    Int
siz <- MArr arr s a -> m Int
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s) =>
MArr arr s a -> m Int
A.sizeofMutableArr MArr arr s a
marr
    Bool -> m () -> m ()
forall a. HasCallStack => Bool -> a -> a
check
        (Int
s1Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& Int
s2Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& Int
lInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& (Int
s2Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
l)Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<=arr a -> Int
forall (arr :: * -> *) a. Arr arr a => arr a -> Int
A.sizeofArr arr a
arr Bool -> Bool -> Bool
&& (Int
s1Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
l)Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<=Int
siz)
        (MArr arr s a -> Int -> arr a -> Int -> Int -> m ()
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s) =>
MArr arr s a -> Int -> arr a -> Int -> Int -> m ()
A.copyArr MArr arr s a
marr Int
s1 arr a
arr Int
s2 Int
l)
{-# INLINE copyArr #-}

copyMutableArr :: (Arr arr a, PrimMonad m, PrimState m ~ s, HasCallStack)
               => MArr arr s a -> Int -> MArr arr s a -> Int -> Int -> m ()
copyMutableArr :: MArr arr s a -> Int -> MArr arr s a -> Int -> Int -> m ()
copyMutableArr MArr arr s a
marr1 Int
s1 MArr arr s a
marr2 Int
s2 Int
l = do
    Int
siz1 <- MArr arr s a -> m Int
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s) =>
MArr arr s a -> m Int
A.sizeofMutableArr MArr arr s a
marr1
    Int
siz2 <- MArr arr s a -> m Int
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s) =>
MArr arr s a -> m Int
A.sizeofMutableArr MArr arr s a
marr2
    Bool -> m () -> m ()
forall a. HasCallStack => Bool -> a -> a
check
        (Int
s1Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& Int
s2Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& Int
lInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& (Int
s2Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
l)Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<=Int
siz2 Bool -> Bool -> Bool
&& (Int
s1Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
l)Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<=Int
siz1)
        (MArr arr s a -> Int -> MArr arr s a -> Int -> Int -> m ()
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s) =>
MArr arr s a -> Int -> MArr arr s a -> Int -> Int -> m ()
A.copyMutableArr MArr arr s a
marr1 Int
s1 MArr arr s a
marr2 Int
s2 Int
l)
{-# INLINE copyMutableArr #-}

moveArr :: (Arr arr a, PrimMonad m, PrimState m ~ s, HasCallStack)
        => MArr arr s a -> Int -> MArr arr s a -> Int -> Int -> m ()
moveArr :: MArr arr s a -> Int -> MArr arr s a -> Int -> Int -> m ()
moveArr MArr arr s a
marr1 Int
s1 MArr arr s a
marr2 Int
s2 Int
l = do
    Int
siz1 <- MArr arr s a -> m Int
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s) =>
MArr arr s a -> m Int
A.sizeofMutableArr MArr arr s a
marr1
    Int
siz2 <- MArr arr s a -> m Int
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s) =>
MArr arr s a -> m Int
A.sizeofMutableArr MArr arr s a
marr2
    Bool -> m () -> m ()
forall a. HasCallStack => Bool -> a -> a
check
        (Int
s1Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& Int
s2Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& Int
lInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& (Int
s2Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
l)Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<=Int
siz2 Bool -> Bool -> Bool
&& (Int
s1Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
l)Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<=Int
siz1)
        (MArr arr s a -> Int -> MArr arr s a -> Int -> Int -> m ()
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s) =>
MArr arr s a -> Int -> MArr arr s a -> Int -> Int -> m ()
A.copyMutableArr MArr arr s a
marr1 Int
s1 MArr arr s a
marr2 Int
s2 Int
l)
{-# INLINE moveArr #-}

cloneArr :: (Arr arr a, HasCallStack)
         => arr a -> Int -> Int -> arr a
cloneArr :: arr a -> Int -> Int -> arr a
cloneArr arr a
arr Int
s Int
l = Bool -> arr a -> arr a
forall a. HasCallStack => Bool -> a -> a
check
    (Int
sInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& Int
lInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& (Int
sInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
l)Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<=arr a -> Int
forall (arr :: * -> *) a. Arr arr a => arr a -> Int
A.sizeofArr arr a
arr)
    (arr a -> Int -> Int -> arr a
forall (arr :: * -> *) a. Arr arr a => arr a -> Int -> Int -> arr a
A.cloneArr arr a
arr Int
s Int
l)
{-# INLINE cloneArr #-}

cloneMutableArr :: (Arr arr a, PrimMonad m, PrimState m ~ s, HasCallStack)
                => MArr arr s a -> Int -> Int -> m (MArr arr s a)
cloneMutableArr :: MArr arr s a -> Int -> Int -> m (MArr arr s a)
cloneMutableArr MArr arr s a
marr Int
s Int
l = do
    Int
siz <- MArr arr s a -> m Int
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s) =>
MArr arr s a -> m Int
A.sizeofMutableArr MArr arr s a
marr
    Bool -> m (MArr arr s a) -> m (MArr arr s a)
forall a. HasCallStack => Bool -> a -> a
check
        (Int
sInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& Int
lInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& (Int
sInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
l)Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<=Int
siz)
        (MArr arr s a -> Int -> Int -> m (MArr arr s a)
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s) =>
MArr arr s a -> Int -> Int -> m (MArr arr s a)
A.cloneMutableArr MArr arr s a
marr Int
s Int
l)
{-# INLINE cloneMutableArr #-}

resizeMutableArr :: (Arr arr a, PrimMonad m, PrimState m ~ s, HasCallStack)
                 => MArr arr s a -> Int -> m (MArr arr s a)
resizeMutableArr :: MArr arr s a -> Int -> m (MArr arr s a)
resizeMutableArr MArr arr s a
marr Int
n = Bool -> m (MArr arr s a) -> m (MArr arr s a)
forall a. HasCallStack => Bool -> a -> a
check
    (Int
nInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0)
    (MArr arr s a -> Int -> m (MArr arr s a)
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s) =>
MArr arr s a -> Int -> m (MArr arr s a)
A.resizeMutableArr MArr arr s a
marr Int
n)
{-# INLINE resizeMutableArr #-}

-- | New size should be >= 0, and <= original size.
--
shrinkMutableArr :: (Arr arr a, PrimMonad m, PrimState m ~ s, HasCallStack)
                 => MArr arr s a -> Int -> m ()
shrinkMutableArr :: MArr arr s a -> Int -> m ()
shrinkMutableArr MArr arr s a
marr Int
n = do
    Int
siz <- MArr arr s a -> m Int
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s) =>
MArr arr s a -> m Int
A.sizeofMutableArr MArr arr s a
marr
    Bool -> m () -> m ()
forall a. HasCallStack => Bool -> a -> a
check
        (Int
nInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& Int
nInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<=Int
siz)
        (MArr arr s a -> Int -> m ()
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s) =>
MArr arr s a -> Int -> m ()
A.shrinkMutableArr MArr arr s a
marr Int
n)
{-# INLINE shrinkMutableArr #-}

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

-- | Create a /pinned/ byte array of the specified size,
-- The garbage collector is guaranteed not to move it.
newPinnedPrimArray :: (PrimMonad m, Prim a, HasCallStack)
                   => Int -> m (A.MutablePrimArray (PrimState m) a)
{-# INLINE newPinnedPrimArray #-}
newPinnedPrimArray :: Int -> m (MutablePrimArray (PrimState m) a)
newPinnedPrimArray Int
n =
    Bool
-> m (MutablePrimArray (PrimState m) a)
-> m (MutablePrimArray (PrimState m) a)
forall a. HasCallStack => Bool -> a -> a
check  (Int
nInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0) (Int -> m (MutablePrimArray (PrimState m) a)
forall (m :: * -> *) a.
(PrimMonad m, Prim a) =>
Int -> m (MutablePrimArray (PrimState m) a)
A.newPinnedPrimArray Int
n)

-- | Create a /pinned/ primitive array of the specified size and respect given primitive type's
-- alignment. The garbage collector is guaranteed not to move it.
--
newAlignedPinnedPrimArray :: (PrimMonad m, Prim a, HasCallStack)
                          => Int -> m (A.MutablePrimArray (PrimState m) a)
{-# INLINE newAlignedPinnedPrimArray #-}
newAlignedPinnedPrimArray :: Int -> m (MutablePrimArray (PrimState m) a)
newAlignedPinnedPrimArray Int
n =
    Bool
-> m (MutablePrimArray (PrimState m) a)
-> m (MutablePrimArray (PrimState m) a)
forall a. HasCallStack => Bool -> a -> a
check  (Int
nInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0) (Int -> m (MutablePrimArray (PrimState m) a)
forall (m :: * -> *) a.
(PrimMonad m, Prim a) =>
Int -> m (MutablePrimArray (PrimState m) a)
A.newAlignedPinnedPrimArray Int
n)

copyPrimArrayToPtr :: (PrimMonad m, Prim a, HasCallStack)
                   => Ptr a
                   -> A.PrimArray a
                   -> Int
                   -> Int
                   -> m ()
{-# INLINE copyPrimArrayToPtr #-}
copyPrimArrayToPtr :: Ptr a -> PrimArray a -> Int -> Int -> m ()
copyPrimArrayToPtr Ptr a
ptr PrimArray a
arr Int
s Int
l = Bool -> m () -> m ()
forall a. HasCallStack => Bool -> a -> a
check
    (Int
sInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& Int
lInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& (Int
sInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
l)Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<=PrimArray a -> Int
forall (arr :: * -> *) a. Arr arr a => arr a -> Int
A.sizeofArr PrimArray a
arr)
    (Ptr a -> PrimArray a -> Int -> Int -> m ()
forall (m :: * -> *) a.
(PrimMonad m, Prim a) =>
Ptr a -> PrimArray a -> Int -> Int -> m ()
A.copyPrimArrayToPtr Ptr a
ptr PrimArray a
arr Int
s Int
l)

copyMutablePrimArrayToPtr :: (PrimMonad m, Prim a, HasCallStack)
                          => Ptr a
                          -> A.MutablePrimArray (PrimState m) a
                          -> Int
                          -> Int
                          -> m ()
{-# INLINE copyMutablePrimArrayToPtr #-}
copyMutablePrimArrayToPtr :: Ptr a -> MutablePrimArray (PrimState m) a -> Int -> Int -> m ()
copyMutablePrimArrayToPtr Ptr a
ptr MutablePrimArray (PrimState m) a
marr Int
s Int
l = do
    Int
siz <- MArr PrimArray (PrimState m) a -> m Int
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s) =>
MArr arr s a -> m Int
A.sizeofMutableArr MutablePrimArray (PrimState m) a
MArr PrimArray (PrimState m) a
marr
    Bool -> m () -> m ()
forall a. HasCallStack => Bool -> a -> a
check
        (Int
sInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& Int
lInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& (Int
sInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
l)Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<=Int
siz)
        (Ptr a -> MutablePrimArray (PrimState m) a -> Int -> Int -> m ()
forall (m :: * -> *) a.
(PrimMonad m, Prim a) =>
Ptr a -> MutablePrimArray (PrimState m) a -> Int -> Int -> m ()
A.copyMutablePrimArrayToPtr Ptr a
ptr MutablePrimArray (PrimState m) a
marr Int
s Int
l)

copyPtrToMutablePrimArray :: (PrimMonad m, Prim a, HasCallStack)
                            => A.MutablePrimArray (PrimState m) a
                            -> Int
                            -> Ptr a
                            -> Int
                            -> m ()
{-# INLINE copyPtrToMutablePrimArray #-}
copyPtrToMutablePrimArray :: MutablePrimArray (PrimState m) a -> Int -> Ptr a -> Int -> m ()
copyPtrToMutablePrimArray MutablePrimArray (PrimState m) a
marr Int
s Ptr a
ptr Int
l = do
    Int
siz <- MArr PrimArray (PrimState m) a -> m Int
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s) =>
MArr arr s a -> m Int
A.sizeofMutableArr MutablePrimArray (PrimState m) a
MArr PrimArray (PrimState m) a
marr
    Bool -> m () -> m ()
forall a. HasCallStack => Bool -> a -> a
check
        (Int
sInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& Int
lInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=Int
0 Bool -> Bool -> Bool
&& (Int
sInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
l)Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<=Int
siz)
        (MutablePrimArray (PrimState m) a -> Int -> Ptr a -> Int -> m ()
forall (m :: * -> *) a.
(PrimMonad m, Prim a) =>
MutablePrimArray (PrimState m) a -> Int -> Ptr a -> Int -> m ()
A.copyPtrToMutablePrimArray MutablePrimArray (PrimState m) a
marr Int
s Ptr a
ptr Int
l)

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

modifyIndexArr :: (Arr arr a, HasCallStack) => arr a
               -> Int    -- ^ offset
               -> Int    -- ^ length
               -> Int    -- ^ index in new array
               -> (a -> a)   -- ^ modify function
               -> arr a
{-# INLINE modifyIndexArr #-}
modifyIndexArr :: arr a -> Int -> Int -> Int -> (a -> a) -> arr a
modifyIndexArr arr a
arr Int
off Int
len Int
ix a -> a
f = (forall s. ST s (arr a)) -> arr a
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s (arr a)) -> arr a)
-> (forall s. ST s (arr a)) -> arr a
forall a b. (a -> b) -> a -> b
$ do
    MArr arr s a
marr <- arr a -> ST s (MArr arr s a)
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s) =>
arr a -> m (MArr arr s a)
A.unsafeThawArr (arr a -> Int -> Int -> arr a
forall (arr :: * -> *) a.
(Arr arr a, HasCallStack) =>
arr a -> Int -> Int -> arr a
cloneArr arr a
arr Int
off Int
len)
    !a
v <- a -> a
f (a -> a) -> ST s a -> ST s a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MArr arr s a -> Int -> ST s a
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s, HasCallStack) =>
MArr arr s a -> Int -> m a
readArr MArr arr s a
marr Int
ix
    MArr arr s a -> Int -> a -> ST s ()
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s, HasCallStack) =>
MArr arr s a -> Int -> a -> m ()
writeArr MArr arr s a
marr Int
ix a
v
    MArr arr s a -> ST s (arr a)
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s) =>
MArr arr s a -> m (arr a)
A.unsafeFreezeArr MArr arr s a
marr

-- | Insert an immutable array's element at given index to produce a new array.
insertIndexArr :: Arr arr a
               => arr a
               -> Int        -- ^ offset
               -> Int        -- ^ length
               -> Int        -- ^ insert index in new array
               -> a          -- ^ element to be inserted
               -> arr a
{-# INLINE insertIndexArr #-}
insertIndexArr :: arr a -> Int -> Int -> Int -> a -> arr a
insertIndexArr arr a
arr Int
s Int
l Int
i a
x = (forall s. ST s (arr a)) -> arr a
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s (arr a)) -> arr a)
-> (forall s. ST s (arr a)) -> arr a
forall a b. (a -> b) -> a -> b
$ do
    MArr arr s a
marr <- Int -> a -> ST s (MArr arr s a)
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s, HasCallStack) =>
Int -> a -> m (MArr arr s a)
newArrWith (Int
lInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) a
x
    Bool -> ST s () -> ST s ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
iInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>Int
0) (ST s () -> ST s ()) -> ST s () -> ST s ()
forall a b. (a -> b) -> a -> b
$ MArr arr s a -> Int -> arr a -> Int -> Int -> ST s ()
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s, HasCallStack) =>
MArr arr s a -> Int -> arr a -> Int -> Int -> m ()
copyArr MArr arr s a
marr Int
0 arr a
arr Int
s Int
i
    Bool -> ST s () -> ST s ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
iInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<Int
l) (ST s () -> ST s ()) -> ST s () -> ST s ()
forall a b. (a -> b) -> a -> b
$ MArr arr s a -> Int -> arr a -> Int -> Int -> ST s ()
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s, HasCallStack) =>
MArr arr s a -> Int -> arr a -> Int -> Int -> m ()
copyArr MArr arr s a
marr (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) arr a
arr (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
s) (Int
lInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
i)
    MArr arr s a -> ST s (arr a)
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s) =>
MArr arr s a -> m (arr a)
A.unsafeFreezeArr MArr arr s a
marr

-- | Drop an immutable array's element at given index to produce a new array.
deleteIndexArr :: Arr arr a
               => arr a
               -> Int        -- ^ offset
               -> Int        -- ^ length
               -> Int        -- ^ drop index in new array
               -> arr a
{-# INLINE deleteIndexArr #-}
deleteIndexArr :: arr a -> Int -> Int -> Int -> arr a
deleteIndexArr arr a
arr Int
s Int
l Int
i = (forall s. ST s (arr a)) -> arr a
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s (arr a)) -> arr a)
-> (forall s. ST s (arr a)) -> arr a
forall a b. (a -> b) -> a -> b
$ do
    MArr arr s a
marr <- Int -> ST s (MArr arr s a)
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s, HasCallStack) =>
Int -> m (MArr arr s a)
newArr (Int
lInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)
    Bool -> ST s () -> ST s ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
iInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>Int
0) (ST s () -> ST s ()) -> ST s () -> ST s ()
forall a b. (a -> b) -> a -> b
$ MArr arr s a -> Int -> arr a -> Int -> Int -> ST s ()
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s, HasCallStack) =>
MArr arr s a -> Int -> arr a -> Int -> Int -> m ()
copyArr MArr arr s a
marr Int
0 arr a
arr Int
s Int
i
    let i' :: Int
i' = Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1
    Bool -> ST s () -> ST s ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
i'Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<Int
l) (ST s () -> ST s ()) -> ST s () -> ST s ()
forall a b. (a -> b) -> a -> b
$ MArr arr s a -> Int -> arr a -> Int -> Int -> ST s ()
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s, HasCallStack) =>
MArr arr s a -> Int -> arr a -> Int -> Int -> m ()
copyArr MArr arr s a
marr Int
i arr a
arr (Int
i'Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
s) (Int
lInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
i')
    MArr arr s a -> ST s (arr a)
forall (arr :: * -> *) a (m :: * -> *) s.
(Arr arr a, PrimMonad m, PrimState m ~ s) =>
MArr arr s a -> m (arr a)
A.unsafeFreezeArr MArr arr s a
marr