primitive-checked-0.7.2.0: src/Data/Primitive/SmallArray.hs
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE PackageImports #-}
{-# LANGUAGE UnboxedTuples #-}
module Data.Primitive.SmallArray
( SmallArray(..)
, SmallMutableArray(..)
, newSmallArray
, readSmallArray
, writeSmallArray
, copySmallArray
, copySmallMutableArray
, indexSmallArray
, indexSmallArrayM
, indexSmallArray##
, cloneSmallArray
, cloneSmallMutableArray
, freezeSmallArray
, unsafeFreezeSmallArray
, thawSmallArray
, A.runSmallArray
, A.unsafeThawSmallArray
, A.sizeofSmallArray
, A.sizeofSmallMutableArray
#if MIN_VERSION_base(4,14,0)
, shrinkSmallMutableArray
#endif
, A.smallArrayFromList
, A.smallArrayFromListN
, A.mapSmallArray'
, A.traverseSmallArrayP
) where
import "primitive" Data.Primitive (sizeOf)
import "primitive" Data.Primitive.SmallArray (SmallArray, SmallMutableArray)
import Control.Exception (throw, ArrayException(..), Exception, toException)
import Control.Monad.Primitive (PrimMonad, PrimState)
import GHC.Exts (raise#)
import GHC.Stack
import qualified "primitive" Data.Primitive.SmallArray as A
import qualified Data.List as L
check :: HasCallStack => String -> Bool -> a -> a
check _ True x = x
check errMsg False _ = throw (IndexOutOfBounds $ "Data.Primitive.SmallArray." ++ errMsg ++ "\n" ++ prettyCallStack callStack)
checkUnary :: HasCallStack => String -> Bool -> (# a #) -> (# a #)
checkUnary _ True x = x
checkUnary errMsg False _ = throwUnary (IndexOutOfBounds $ "Data.Primitive.SmallArray." ++ errMsg ++ "\n" ++ prettyCallStack callStack)
throwUnary :: Exception e => e -> (# a #)
throwUnary e = raise# (toException e)
newSmallArray :: (HasCallStack, PrimMonad m) => Int -> a -> m (SmallMutableArray (PrimState m) a)
newSmallArray n x =
check "newSmallArray: negative size" (n >= 0)
$ check ("newSmallArray: requested " ++ show n ++ " elements") (n * ptrSz < 1024*1024*1024)
$ A.newSmallArray n x
where
ptrSz = sizeOf (undefined :: Int)
readSmallArray :: (HasCallStack, PrimMonad m) => SmallMutableArray (PrimState m) a -> Int -> m a
readSmallArray marr i = do
let siz = A.sizeofSmallMutableArray marr
explain = L.concat
[ "[size: "
, show siz
, ", index: "
, show i
, "]"
]
check ("readSmallArray: index out of bounds " ++ explain) (i >= 0 && i < siz) (A.readSmallArray marr i)
writeSmallArray :: (HasCallStack, PrimMonad m) => SmallMutableArray (PrimState m) a -> Int -> a -> m ()
writeSmallArray marr i x = do
let siz = A.sizeofSmallMutableArray marr
explain = L.concat
[ "[size: "
, show siz
, ", index: "
, show i
, "]"
]
check ("writeSmallArray: index out of bounds " ++ explain) (i >= 0 && i < siz) (A.writeSmallArray marr i x)
indexSmallArray :: HasCallStack => SmallArray a -> Int -> a
indexSmallArray arr i = check ("indexSmallArray: index out of bounds " ++ explain)
(i >= 0 && i < A.sizeofSmallArray arr)
(A.indexSmallArray arr i)
where
explain = L.concat
[ "[size: "
, show (A.sizeofSmallArray arr)
, ", index: "
, show i
, "]"
]
indexSmallArray## :: HasCallStack => SmallArray a -> Int -> (# a #)
indexSmallArray## arr i = checkUnary "indexSmallArray##: index out of bounds"
(i >= 0 && i < A.sizeofSmallArray arr)
(A.indexSmallArray## arr i)
indexSmallArrayM :: (HasCallStack, Monad m) => SmallArray a -> Int -> m a
indexSmallArrayM arr i = check "indexSmallArrayM: index out of bounds"
(i >= 0 && i < A.sizeofSmallArray arr)
(A.indexSmallArrayM arr i)
{-# NOINLINE errorUnsafeFreeze #-}
errorUnsafeFreeze :: a
errorUnsafeFreeze =
error "Data.Primitive.Array.unsafeFreeze:\nAttempted to read from an array after unsafely freezing it."
-- | This installs error thunks in the argument array so that
-- any attempt to use it after an unsafeFreeze will fail.
unsafeFreezeSmallArray :: (HasCallStack, PrimMonad m)
=> SmallMutableArray (PrimState m) a
-> m (SmallArray a)
unsafeFreezeSmallArray marr = do
let sz = A.sizeofSmallMutableArray marr
arr <- A.freezeSmallArray marr 0 sz
let go !ix = if ix < sz
then A.writeSmallArray marr ix errorUnsafeFreeze >> go (ix + 1)
else return ()
go 0
return arr
freezeSmallArray
:: (HasCallStack, PrimMonad m)
=> SmallMutableArray (PrimState m) a -- ^ source
-> Int -- ^ offset
-> Int -- ^ length
-> m (SmallArray a)
freezeSmallArray marr s l = check "freezeSmallArray: index range of out bounds"
(s >= 0 && l >= 0 && s + l <= A.sizeofSmallMutableArray marr)
(A.freezeSmallArray marr s l)
thawSmallArray
:: (HasCallStack, PrimMonad m)
=> SmallArray a -- ^ source
-> Int -- ^ offset
-> Int -- ^ length
-> m (SmallMutableArray (PrimState m) a)
thawSmallArray arr s l = check "thawSmallArray: index range of out bounds"
(s >= 0 && l >= 0 && s + l <= A.sizeofSmallArray arr)
(A.thawSmallArray arr s l)
copySmallArray :: (HasCallStack, PrimMonad m)
=> SmallMutableArray (PrimState m) a -- ^ destination array
-> Int -- ^ offset into destination array
-> SmallArray a -- ^ source array
-> Int -- ^ offset into source array
-> Int -- ^ number of elements to copy
-> m ()
copySmallArray marr s1 arr s2 l = do
let siz = A.sizeofSmallMutableArray marr
check "copySmallArray: index range of out bounds"
(s1 >= 0 && s2 >= 0 && l >= 0 && s1 + l <= siz && s2 + l <= A.sizeofSmallArray arr)
(A.copySmallArray marr s1 arr s2 l)
copySmallMutableArray :: (HasCallStack, PrimMonad m)
=> SmallMutableArray (PrimState m) a -- ^ destination array
-> Int -- ^ offset into destination array
-> SmallMutableArray (PrimState m) a -- ^ source array
-> Int -- ^ offset into source array
-> Int -- ^ number of elements to copy
-> m ()
copySmallMutableArray marr1 s1 marr2 s2 l = do
let siz1 = A.sizeofSmallMutableArray marr1
let siz2 = A.sizeofSmallMutableArray marr2
check "copySmallMutableArray: index range of out bounds"
(s1 >= 0 && s2 >= 0 && l >= 0 && s1 + l <= siz1 && s2 + l <= siz2)
(A.copySmallMutableArray marr1 s1 marr2 s2 l)
cloneSmallArray :: HasCallStack
=> SmallArray a -- ^ source array
-> Int -- ^ offset into source array
-> Int -- ^ number of elements to copy
-> SmallArray a
cloneSmallArray arr s l = check "cloneSmallArray: index range of out bounds"
(s >= 0 && l >= 0 && s + l <= A.sizeofSmallArray arr)
(A.cloneSmallArray arr s l)
cloneSmallMutableArray :: (HasCallStack, PrimMonad m)
=> SmallMutableArray (PrimState m) a -- ^ source array
-> Int -- ^ offset into source array
-> Int -- ^ number of elements to copy
-> m (SmallMutableArray (PrimState m) a)
cloneSmallMutableArray marr s l = check "cloneSmallMutableArray: index range of out bounds"
(s >= 0 && l >= 0 && s + l <= A.sizeofSmallMutableArray marr)
(A.cloneSmallMutableArray marr s l)
#if MIN_VERSION_base(4,14,0)
shrinkSmallMutableArray :: (HasCallStack, PrimMonad m) => SmallMutableArray (PrimState m) a -> Int -> m ()
shrinkSmallMutableArray marr n = do
let old = A.sizeofSmallMutableArray marr
check "shrinkSmallMutableArray: illegal new size" (n >= 0 && n <= old) (A.shrinkSmallMutableArray marr n)
#endif