contiguous-0.6.1.1: src/Data/Primitive/Contiguous/Class.hs
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeFamilyDependencies #-}
{-# LANGUAGE UnboxedTuples #-}
{-# LANGUAGE UnliftedNewtypes #-}
-- | The 'Contiguous' typeclass parameterises over a contiguous array type.
-- It provides the core primitives necessary to implement the common API in "Data.Primitive.Contiguous".
-- This allows us to have a common API to a number of contiguous
-- array types and their mutable counterparts.
module Data.Primitive.Contiguous.Class
( Contiguous(..)
, Slice(..)
, MutableSlice(..)
, ContiguousU(..)
, Always
) where
import Data.Primitive.Contiguous.Shim
import Data.Primitive hiding (fromList,fromListN)
import Data.Primitive.Unlifted.Array
import Prelude hiding (length,map,all,any,foldr,foldMap,traverse,read,filter,replicate,null,reverse,foldl,foldr,zip,zipWith,scanl,(<$),elem,maximum,minimum,mapM,mapM_,sequence,sequence_)
import Control.DeepSeq (NFData)
import Control.Monad.Primitive (PrimState, PrimMonad(..))
import Control.Monad.ST (runST,ST)
import Control.Monad.ST.Run (runPrimArrayST,runSmallArrayST,runUnliftedArrayST,runArrayST)
import Data.Kind (Type)
import Data.Primitive.Unlifted.Class (PrimUnlifted)
import GHC.Exts (ArrayArray#,Constraint,sizeofByteArray#,sizeofArray#,sizeofArrayArray#)
import GHC.Exts (SmallMutableArray#,MutableArray#,MutableArrayArray#)
import GHC.Exts (SmallArray#,Array#)
import GHC.Exts (TYPE)
import qualified Control.DeepSeq as DS
-- In GHC 9.2 the UnliftedRep constructor of RuntimeRep was removed
-- and replaced with a type synonym
#if __GLASGOW_HASKELL__ >= 902
import GHC.Exts (UnliftedRep)
#else
import GHC.Exts (RuntimeRep(UnliftedRep))
type UnliftedRep = 'UnliftedRep
#endif
-- | Slices of immutable arrays: packages an offset and length with a backing array.
--
-- @since 0.6.0
data Slice arr a = Slice
{ offset :: {-# UNPACK #-} !Int
, length :: {-# UNPACK #-} !Int
, base :: !(Unlifted arr a)
}
-- | Slices of mutable arrays: packages an offset and length with a mutable backing array.
--
-- @since 0.6.0
data MutableSlice arr s a = MutableSlice
{ offsetMut :: {-# UNPACK #-} !Int
, lengthMut :: {-# UNPACK #-} !Int
, baseMut :: !(UnliftedMut arr s a)
}
-- | The 'Contiguous' typeclass as an interface to a multitude of
-- contiguous structures.
--
-- Some functions do not make sense on slices; for those, see 'ContiguousU'.
class Contiguous (arr :: Type -> Type) where
-- | The Mutable counterpart to the array.
type family Mutable arr = (r :: Type -> Type -> Type) | r -> arr
-- | The constraint needed to store elements in the array.
type family Element arr :: Type -> Constraint
-- | The slice type of this array.
-- The slice of a raw array type @t@ should be 'Slice t',
-- whereas the slice of a slice should be the same slice type.
--
-- @since 0.6.0
type family Sliced arr :: Type -> Type
-- | The mutable slice type of this array.
-- The mutable slice of a raw array type @t@ should be 'MutableSlice t',
-- whereas the mutable slice of a mutable slice should be the same slice type.
--
-- @since 0.6.0
type family MutableSliced arr :: Type -> Type -> Type
------ Construction ------
-- | Allocate a new mutable array of the given size.
new :: (PrimMonad m, Element arr b) => Int -> m (Mutable arr (PrimState m) b)
-- | @'replicateMut' n x@ is a mutable array of length @n@ with @x@ the
-- value of every element.
replicateMut :: (PrimMonad m, Element arr b)
=> Int -- length
-> b -- fill element
-> m (Mutable arr (PrimState m) b)
-- | Resize an array without growing it.
--
-- @since 0.6.0
shrink :: (PrimMonad m, Element arr a)
=> Mutable arr (PrimState m) a
-> Int -- ^ new length
-> m (Mutable arr (PrimState m) a)
default shrink ::
( ContiguousU arr
, PrimMonad m, Element arr a)
=> Mutable arr (PrimState m) a -> Int -> m (Mutable arr (PrimState m) a)
{-# INLINE shrink #-}
shrink = resize
-- | The empty array.
empty :: arr a
-- | Create a singleton array.
singleton :: Element arr a => a -> arr a
-- | Create a doubleton array.
doubleton :: Element arr a => a -> a -> arr a
-- | Create a tripleton array.
tripleton :: Element arr a => a -> a -> a -> arr a
-- | Create a quadrupleton array.
quadrupleton :: Element arr a => a -> a -> a -> a -> arr a
------ Access and Update ------
-- | Index into an array at the given index.
index :: Element arr b => arr b -> Int -> b
-- | Index into an array at the given index, yielding an unboxed one-tuple of the element.
index# :: Element arr b => arr b -> Int -> (# b #)
-- | Indexing in a monad.
--
-- The monad allows operations to be strict in the array
-- when necessary. Suppose array copying is implemented like this:
--
-- > copy mv v = ... write mv i (v ! i) ...
--
-- For lazy arrays, @v ! i@ would not be not be evaluated,
-- which means that @mv@ would unnecessarily retain a reference
-- to @v@ in each element written.
--
-- With 'indexM', copying can be implemented like this instead:
--
-- > copy mv v = ... do
-- > x <- indexM v i
-- > write mv i x
--
-- Here, no references to @v@ are retained because indexing
-- (but /not/ the elements) is evaluated eagerly.
indexM :: (Element arr b, Monad m) => arr b -> Int -> m b
-- | Read a mutable array at the given index.
read :: (PrimMonad m, Element arr b)
=> Mutable arr (PrimState m) b -> Int -> m b
-- | Write to a mutable array at the given index.
write :: (PrimMonad m, Element arr b)
=> Mutable arr (PrimState m) b -> Int -> b -> m ()
------ Properties ------
-- | Test whether the array is empty.
null :: arr b -> Bool
-- | The size of the array
size :: Element arr b => arr b -> Int
-- | The size of the mutable array
sizeMut :: (PrimMonad m, Element arr b)
=> Mutable arr (PrimState m) b -> m Int
-- | Test the two arrays for equality.
equals :: (Element arr b, Eq b) => arr b -> arr b -> Bool
-- | Test the two mutable arrays for pointer equality.
-- Does not check equality of elements.
equalsMut :: Mutable arr s a -> Mutable arr s a -> Bool
------ Conversion ------
-- | Create a 'Slice' of an array.
--
-- @O(1)@.
--
-- @since 0.6.0
slice :: (Element arr a)
=> arr a -- base array
-> Int -- offset
-> Int -- length
-> Sliced arr a
-- | Create a 'MutableSlice' of a mutable array.
--
-- @O(1)@.
--
-- @since 0.6.0
sliceMut :: (Element arr a)
=> Mutable arr s a -- base array
-> Int -- offset
-> Int -- length
-> MutableSliced arr s a
-- | Create a 'Slice' that covers the entire array.
--
-- @since 0.6.0
toSlice :: (Element arr a) => arr a -> Sliced arr a
-- | Create a 'MutableSlice' that covers the entire array.
--
-- @since 0.6.0
toSliceMut :: (PrimMonad m, Element arr a)
=> Mutable arr (PrimState m) a
-> m (MutableSliced arr (PrimState m) a)
-- | Clone a slice of an array.
clone :: Element arr b
=> Sliced arr b -- ^ slice to copy
-> arr b
default clone ::
( Sliced arr ~ Slice arr, ContiguousU arr
, Element arr b)
=> Sliced arr b -> arr b
{-# INLINE clone #-}
clone Slice{offset,length,base} = clone_ (lift base) offset length
-- | Clone a slice of an array without using the 'Slice' type.
-- These methods are required to implement 'Contiguous (Slice arr)' for any `Contiguous arr`;
-- they are not really meant for direct use.
--
-- @since 0.6.0
clone_ :: Element arr a => arr a -> Int -> Int -> arr a
-- | Clone a slice of a mutable array.
cloneMut :: (PrimMonad m, Element arr b)
=> MutableSliced arr (PrimState m) b -- ^ Array to copy a slice of
-> m (Mutable arr (PrimState m) b)
default cloneMut ::
( MutableSliced arr ~ MutableSlice arr, ContiguousU arr
, PrimMonad m, Element arr b)
=> MutableSliced arr (PrimState m) b -> m (Mutable arr (PrimState m) b)
{-# INLINE cloneMut #-}
cloneMut MutableSlice{offsetMut,lengthMut,baseMut}
= cloneMut_ (liftMut baseMut) offsetMut lengthMut
-- | Clone a slice of a mutable array without using the 'MutableSlice' type.
-- These methods are required to implement 'Contiguous (Slice arr)' for any `Contiguous arr`;
-- they are not really meant for direct use.
--
-- @since 0.6.0
cloneMut_ :: (PrimMonad m, Element arr b)
=> Mutable arr (PrimState m) b -- ^ Array to copy a slice of
-> Int -- ^ offset
-> Int -- ^ length
-> m (Mutable arr (PrimState m) b)
-- | Turn a mutable array slice an immutable array by copying.
--
-- @since 0.6.0
freeze :: (PrimMonad m, Element arr a)
=> MutableSliced arr (PrimState m) a
-> m (arr a)
default freeze ::
( MutableSliced arr ~ MutableSlice arr, ContiguousU arr
, PrimMonad m, Element arr a)
=> MutableSliced arr (PrimState m) a -> m (arr a)
{-# INLINE freeze #-}
freeze MutableSlice{offsetMut,lengthMut,baseMut}
= freeze_ (liftMut baseMut) offsetMut lengthMut
-- | Turn a slice of a mutable array into an immutable one with copying,
-- without using the 'MutableSlice' type.
-- These methods are required to implement 'Contiguous (Slice arr)' for any `Contiguous arr`;
-- they are not really meant for direct use.
--
-- @since 0.6.0
freeze_ :: (PrimMonad m, Element arr b)
=> Mutable arr (PrimState m) b
-> Int -- ^ offset
-> Int -- ^ length
-> m (arr b)
-- | Turn a mutable array into an immutable one without copying.
-- The mutable array should not be used after this conversion.
unsafeFreeze :: (PrimMonad m, Element arr b)
=> Mutable arr (PrimState m) b
-> m (arr b)
unsafeFreeze xs = unsafeShrinkAndFreeze xs =<< sizeMut xs
{-# INLINE unsafeFreeze #-}
unsafeShrinkAndFreeze :: (PrimMonad m, Element arr a)
=> Mutable arr (PrimState m) a
-> Int -- ^ final size
-> m (arr a)
default unsafeShrinkAndFreeze ::
( ContiguousU arr
, PrimMonad m, Element arr a)
=> Mutable arr (PrimState m) a -> Int -> m (arr a)
{-# INLINE unsafeShrinkAndFreeze #-}
unsafeShrinkAndFreeze arr0 len' =
resize arr0 len' >>= unsafeFreeze
-- | Copy a slice of an immutable array into a new mutable array.
thaw :: (PrimMonad m, Element arr b)
=> Sliced arr b
-> m (Mutable arr (PrimState m) b)
default thaw ::
( Sliced arr ~ Slice arr, ContiguousU arr
, PrimMonad m, Element arr b)
=> Sliced arr b
-> m (Mutable arr (PrimState m) b)
{-# INLINE thaw #-}
thaw Slice{offset,length,base} = thaw_ (lift base) offset length
-- | Copy a slice of an immutable array into a new mutable array without using the 'Slice' type.
-- These methods are required to implement 'Contiguous (Slice arr)' for any `Contiguous arr`;
-- they are not really meant for direct use.
--
-- @since 0.6.0
thaw_ :: (PrimMonad m, Element arr b)
=> arr b
-> Int -- ^ offset into the array
-> Int -- ^ length of the slice
-> m (Mutable arr (PrimState m) b)
------ Copy Operations ------
-- | Copy a slice of an array into a mutable array.
copy :: (PrimMonad m, Element arr b)
=> Mutable arr (PrimState m) b -- ^ destination array
-> Int -- ^ offset into destination array
-> Sliced arr b -- ^ source slice
-> m ()
default copy ::
( Sliced arr ~ Slice arr, ContiguousU arr
, PrimMonad m, Element arr b)
=> Mutable arr (PrimState m) b -> Int -> Sliced arr b -> m ()
{-# INLINE copy #-}
copy dst dstOff Slice{offset,length,base} = copy_ dst dstOff (lift base) offset length
-- | Copy a slice of an array into a mutable array without using the 'Slice' type.
-- These methods are required to implement 'Contiguous (Slice arr)' for any `Contiguous arr`;
-- they are not really meant for direct use.
--
-- @since 0.6.0
copy_ :: (PrimMonad m, Element arr b)
=> Mutable arr (PrimState m) b -- ^ destination array
-> Int -- ^ offset into destination array
-> arr b -- ^ source array
-> Int -- ^ offset into source array
-> Int -- ^ number of elements to copy
-> m ()
-- | Copy a slice of a mutable array into another mutable array.
-- In the case that the destination and source arrays are the
-- same, the regions may overlap.
copyMut :: (PrimMonad m, Element arr b)
=> Mutable arr (PrimState m) b -- ^ destination array
-> Int -- ^ offset into destination array
-> MutableSliced arr (PrimState m) b -- ^ source slice
-> m ()
default copyMut ::
( MutableSliced arr ~ MutableSlice arr, ContiguousU arr
, PrimMonad m, Element arr b)
=> Mutable arr (PrimState m) b -> Int -> MutableSliced arr (PrimState m) b -> m ()
{-# INLINE copyMut #-}
copyMut dst dstOff MutableSlice{offsetMut,lengthMut,baseMut}
= copyMut_ dst dstOff (liftMut baseMut) offsetMut lengthMut
-- | Copy a slice of a mutable array into another mutable array without using the 'Slice' type.
-- These methods are required to implement 'Contiguous (Slice arr)' for any `Contiguous arr`;
-- they are not really meant for direct use.
--
-- @since 0.6.0
copyMut_ :: (PrimMonad m, Element arr b)
=> Mutable arr (PrimState m) b -- ^ destination array
-> Int -- ^ offset into destination array
-> Mutable arr (PrimState m) b -- ^ source array
-> Int -- ^ offset into source array
-> Int -- ^ number of elements to copy
-> m ()
-- | Copy a slice of an array and then insert an element into that array.
--
-- The default implementation performs a memset which would be unnecessary
-- except that the garbage collector might trace the uninitialized array.
--
-- Was previously @insertSlicing@
-- @since 0.6.0
insertAt :: (Element arr b)
=> arr b -- ^ slice to copy from
-> Int -- ^ index in the output array to insert at
-> b -- ^ element to insert
-> arr b
default insertAt ::
(Element arr b, ContiguousU arr)
=> arr b -> Int -> b -> arr b
insertAt src i x = run $ do
dst <- replicateMut (size src + 1) x
copy dst 0 (slice src 0 i)
copy dst (i + 1) (slice src i (size src - i))
unsafeFreeze dst
{-# inline insertAt #-}
------ Reduction ------
-- | Reduce the array and all of its elements to WHNF.
rnf :: (NFData a, Element arr a) => arr a -> ()
-- | Run an effectful computation that produces an array.
run :: (forall s. ST s (arr a)) -> arr a
-- | The 'ContiguousU' typeclass is an extension of the 'Contiguous' typeclass,
-- but includes operations that make sense only on uncliced contiguous structures.
--
-- @since 0.6.0
class (Contiguous arr) => ContiguousU arr where
-- | The unifted version of the immutable array type (i.e. eliminates an indirection through a thunk).
type Unlifted arr = (r :: Type -> TYPE UnliftedRep) | r -> arr
-- | The unifted version of the mutable array type (i.e. eliminates an indirection through a thunk).
type UnliftedMut arr = (r :: Type -> Type -> TYPE UnliftedRep) | r -> arr
-- | Resize an array into one with the given size.
resize :: (PrimMonad m, Element arr b)
=> Mutable arr (PrimState m) b
-> Int
-> m (Mutable arr (PrimState m) b)
-- | Unlift an array (i.e. point to the data without an intervening thunk).
--
-- @since 0.6.0
unlift :: arr b -> Unlifted arr b
-- | Unlift a mutable array (i.e. point to the data without an intervening thunk).
--
-- @since 0.6.0
unliftMut :: Mutable arr s b -> UnliftedMut arr s b
-- | Lift an array (i.e. point to the data through an intervening thunk).
--
-- @since 0.6.0
lift :: Unlifted arr b -> arr b
-- | Lift a mutable array (i.e. point to the data through an intervening thunk).
--
-- @since 0.6.0
liftMut :: UnliftedMut arr s b -> Mutable arr s b
-- | A typeclass that is satisfied by all types. This is used
-- used to provide a fake constraint for 'Array' and 'SmallArray'.
class Always a where {}
instance Always a where {}
instance (ContiguousU arr) => Contiguous (Slice arr) where
type Mutable (Slice arr) = MutableSlice arr
type Element (Slice arr) = Element arr
type Sliced (Slice arr) = Slice arr
type MutableSliced (Slice arr) = MutableSlice arr
------ Construction ------
{-# INLINE new #-}
new len = do
baseMut <- new len
pure MutableSlice{offsetMut=0,lengthMut=len,baseMut=unliftMut baseMut}
{-# INLINE replicateMut #-}
replicateMut len x = do
baseMut <- replicateMut len x
pure MutableSlice{offsetMut=0,lengthMut=len,baseMut=unliftMut baseMut}
{-# INLINE shrink #-}
shrink xs len' = pure $ case compare len' (lengthMut xs) of
LT -> xs{lengthMut=len'}
EQ -> xs
GT -> errorWithoutStackTrace "Data.Primitive.Contiguous.Class.shrink: passed a larger than existing size"
{-# INLINE empty #-}
empty = Slice{offset=0,length=0,base=unlift empty}
{-# INLINE singleton #-}
singleton a = Slice{offset=0,length=1,base=unlift $ singleton a}
{-# INLINE doubleton #-}
doubleton a b = Slice{offset=0,length=2,base=unlift $ doubleton a b}
{-# INLINE tripleton #-}
tripleton a b c = Slice{offset=0,length=3,base=unlift $ tripleton a b c}
{-# INLINE quadrupleton #-}
quadrupleton a b c d = Slice{offset=0,length=4,base=unlift $ quadrupleton a b c d}
------ Access and Update ------
{-# INLINE index #-}
index Slice{offset,base} i = index (lift base) (offset + i)
{-# INLINE index# #-}
index# Slice{offset,base} i = index# (lift base) (offset + i)
{-# INLINE indexM #-}
indexM Slice{offset,base} i = indexM (lift base) (offset + i)
{-# INLINE read #-}
read MutableSlice{offsetMut,baseMut} i = read (liftMut baseMut) (offsetMut + i)
{-# INLINE write #-}
write MutableSlice{offsetMut,baseMut} i = write (liftMut baseMut) (offsetMut + i)
------ Properties ------
{-# INLINE null #-}
null Slice{length} = length == 0
{-# INLINE size #-}
size Slice{length} = length
{-# INLINE sizeMut #-}
sizeMut MutableSlice{lengthMut} = pure lengthMut
{-# INLINE equals #-}
equals Slice{offset=oA,length=lenA,base=a}
Slice{offset=oB,length=lenB,base=b}
= lenA == lenB && loop 0 oA oB
where
loop !i !iA !iB =
if i == lenA then True
else index (lift a) iA == index (lift b) iB && loop (i+1) (iA+1) (iB+1)
{-# INLINE equalsMut #-}
equalsMut MutableSlice{offsetMut=offA,lengthMut=lenA,baseMut=a}
MutableSlice{offsetMut=offB,lengthMut=lenB,baseMut=b}
= liftMut a `equalsMut` liftMut b
&& offA == offB
&& lenA == lenB
------ Conversion ------
{-# INLINE slice #-}
slice Slice{offset,base} off' len' = Slice
{ offset = offset + off'
, length = len'
, base
}
{-# INLINE sliceMut #-}
sliceMut MutableSlice{offsetMut,baseMut} off' len' = MutableSlice
{ offsetMut = offsetMut + off'
, lengthMut = len'
, baseMut
}
{-# INLINE clone #-}
clone = id
{-# INLINE clone_ #-}
clone_ Slice{offset,base} off' len' =
Slice{offset=offset+off',length=len',base}
{-# INLINE cloneMut #-}
cloneMut xs@MutableSlice{lengthMut} = cloneMut_ xs 0 lengthMut
{-# INLINE cloneMut_ #-}
cloneMut_ MutableSlice{offsetMut,baseMut} off' len' = do
baseMut' <- cloneMut_ (liftMut baseMut) (offsetMut + off') len'
pure MutableSlice{offsetMut=0,lengthMut=len',baseMut=unliftMut baseMut'}
{-# INLINE freeze #-}
freeze xs@MutableSlice{lengthMut}
= freeze_ xs 0 lengthMut
{-# INLINE freeze_ #-}
freeze_ MutableSlice{offsetMut,baseMut} off' len' = do
base <- freeze_ (liftMut baseMut) (offsetMut + off') len'
pure Slice{offset=0,length=len',base=unlift base}
{-# INLINE unsafeShrinkAndFreeze #-}
unsafeShrinkAndFreeze MutableSlice{offsetMut=0,lengthMut,baseMut} len' = do
shrunk <- if lengthMut /= len'
then resize (liftMut baseMut) len'
else pure (liftMut baseMut)
base <- unsafeFreeze shrunk
pure Slice{offset=0,length=len',base=unlift base}
unsafeShrinkAndFreeze MutableSlice{offsetMut,baseMut} len' = do
base <- freeze_ (liftMut baseMut) offsetMut len'
pure Slice{offset=0,length=len',base=unlift base}
{-# INLINE thaw #-}
thaw xs@Slice{length} = thaw_ xs 0 length
{-# INLINE thaw_ #-}
thaw_ Slice{offset,base} off' len' = do
baseMut <- thaw_ (lift base) (offset + off') len'
pure MutableSlice{offsetMut=0,lengthMut=len',baseMut=unliftMut baseMut}
{-# INLINE toSlice #-}
toSlice = id
{-# INLINE toSliceMut #-}
toSliceMut = pure
------ Copy Operations ------
{-# INLINE copy #-}
copy dst dstOff src@Slice{length} = copy_ dst dstOff src 0 length
{-# INLINE copy_ #-}
copy_ MutableSlice{offsetMut,baseMut} dstOff Slice{offset,base} off' len =
copy_ (liftMut baseMut) (offsetMut + dstOff) (lift base) (offset + off') len
{-# INLINE copyMut #-}
copyMut dst dstOff src@MutableSlice{lengthMut} = copyMut_ dst dstOff src 0 lengthMut
{-# INLINE copyMut_ #-}
copyMut_ MutableSlice{offsetMut=dstOff,baseMut=dst} dstOff'
MutableSlice{offsetMut=srcOff,baseMut=src} srcOff' len =
copyMut_ (liftMut dst) (dstOff + dstOff') (liftMut src) (srcOff + srcOff') len
{-# INLINE insertAt #-}
insertAt Slice{offset,length,base} i x = run $ do
dst <- replicateMut (length + 1) x
copy_ dst 0 (lift base) offset i
copy_ dst (i + 1) (lift base) (offset + i) (length - i)
base' <- unsafeFreeze dst
pure Slice{offset=0,length=length+1,base=unlift base'}
------ Reduction ------
{-# INLINE rnf #-}
rnf !arr@Slice{length} =
let go !ix = if ix < length
then
let !(# x #) = index# arr ix
in DS.rnf x `seq` go (ix + 1)
else ()
in go 0
{-# INLINE run #-}
run = runST
instance Contiguous SmallArray where
type Mutable SmallArray = SmallMutableArray
type Element SmallArray = Always
type Sliced SmallArray = Slice SmallArray
type MutableSliced SmallArray = MutableSlice SmallArray
{-# INLINE new #-}
new n = newSmallArray n errorThunk
{-# INLINE empty #-}
empty = mempty
{-# INLINE index #-}
index = indexSmallArray
{-# INLINE indexM #-}
indexM = indexSmallArrayM
{-# INLINE index# #-}
index# = indexSmallArray##
{-# INLINE read #-}
read = readSmallArray
{-# INLINE write #-}
write = writeSmallArray
{-# INLINE null #-}
null a = case sizeofSmallArray a of
0 -> True
_ -> False
{-# INLINE slice #-}
slice base offset length = Slice{offset,length,base=unlift base}
{-# INLINE sliceMut #-}
sliceMut baseMut offsetMut lengthMut = MutableSlice{offsetMut,lengthMut,baseMut=unliftMut baseMut}
{-# INLINE toSlice #-}
toSlice base = Slice{offset=0,length=size base,base=unlift base}
{-# INLINE toSliceMut #-}
toSliceMut baseMut = do
lengthMut <- sizeMut baseMut
pure MutableSlice{offsetMut=0,lengthMut,baseMut=unliftMut baseMut}
{-# INLINE freeze_ #-}
freeze_ = freezeSmallArray
{-# INLINE unsafeFreeze #-}
unsafeFreeze = unsafeFreezeSmallArray
{-# INLINE size #-}
size = sizeofSmallArray
{-# INLINE sizeMut #-}
sizeMut = (\x -> pure $! sizeofSmallMutableArray x)
{-# INLINE thaw_ #-}
thaw_ = thawSmallArray
{-# INLINE equals #-}
equals = (==)
{-# INLINE equalsMut #-}
equalsMut = (==)
{-# INLINE singleton #-}
singleton a = runST $ do
marr <- newSmallArray 1 errorThunk
writeSmallArray marr 0 a
unsafeFreezeSmallArray marr
{-# INLINE doubleton #-}
doubleton a b = runST $ do
m <- newSmallArray 2 errorThunk
writeSmallArray m 0 a
writeSmallArray m 1 b
unsafeFreezeSmallArray m
{-# INLINE tripleton #-}
tripleton a b c = runST $ do
m <- newSmallArray 3 errorThunk
writeSmallArray m 0 a
writeSmallArray m 1 b
writeSmallArray m 2 c
unsafeFreezeSmallArray m
{-# INLINE quadrupleton #-}
quadrupleton a b c d = runST $ do
m <- newSmallArray 4 errorThunk
writeSmallArray m 0 a
writeSmallArray m 1 b
writeSmallArray m 2 c
writeSmallArray m 3 d
unsafeFreezeSmallArray m
{-# INLINE rnf #-}
rnf !ary =
let !sz = sizeofSmallArray ary
go !ix = if ix < sz
then
let !(# x #) = indexSmallArray## ary ix
in DS.rnf x `seq` go (ix + 1)
else ()
in go 0
{-# INLINE clone_ #-}
clone_ = cloneSmallArray
{-# INLINE cloneMut_ #-}
cloneMut_ = cloneSmallMutableArray
{-# INLINE copy_ #-}
copy_ = copySmallArray
{-# INLINE copyMut_ #-}
copyMut_ = copySmallMutableArray
{-# INLINE replicateMut #-}
replicateMut = replicateSmallMutableArray
{-# INLINE run #-}
run = runSmallArrayST
instance ContiguousU SmallArray where
type Unlifted SmallArray = SmallArray#
type UnliftedMut SmallArray = SmallMutableArray#
{-# INLINE resize #-}
resize = resizeSmallArray
{-# INLINE unlift #-}
unlift (SmallArray x) = x
{-# INLINE unliftMut #-}
unliftMut (SmallMutableArray x) = x
{-# INLINE lift #-}
lift x = SmallArray x
{-# INLINE liftMut #-}
liftMut x = SmallMutableArray x
instance Contiguous PrimArray where
type Mutable PrimArray = MutablePrimArray
type Element PrimArray = Prim
type Sliced PrimArray = Slice PrimArray
type MutableSliced PrimArray = MutableSlice PrimArray
{-# INLINE empty #-}
empty = mempty
{-# INLINE new #-}
new = newPrimArray
{-# INLINE replicateMut #-}
replicateMut = replicateMutablePrimArray
{-# INLINE index #-}
index = indexPrimArray
{-# INLINE index# #-}
index# arr ix = (# indexPrimArray arr ix #)
{-# INLINE indexM #-}
indexM arr ix = pure (indexPrimArray arr ix)
{-# INLINE read #-}
read = readPrimArray
{-# INLINE write #-}
write = writePrimArray
{-# INLINE size #-}
size = sizeofPrimArray
{-# INLINE sizeMut #-}
sizeMut = getSizeofMutablePrimArray
{-# INLINE slice #-}
slice base offset length = Slice{offset,length,base=unlift base}
{-# INLINE sliceMut #-}
sliceMut baseMut offsetMut lengthMut = MutableSlice{offsetMut,lengthMut,baseMut=unliftMut baseMut}
{-# INLINE toSlice #-}
toSlice base = Slice{offset=0,length=size base,base=unlift base}
{-# INLINE toSliceMut #-}
toSliceMut baseMut = do
lengthMut <- sizeMut baseMut
pure MutableSlice{offsetMut=0,lengthMut,baseMut=unliftMut baseMut}
{-# INLINE freeze_ #-}
freeze_ = freezePrimArrayShim
{-# INLINE unsafeFreeze #-}
unsafeFreeze = unsafeFreezePrimArray
{-# INLINE thaw_ #-}
thaw_ = thawPrimArray
{-# INLINE copy_ #-}
copy_ = copyPrimArray
{-# INLINE copyMut_ #-}
copyMut_ = copyMutablePrimArray
{-# INLINE clone_ #-}
clone_ = clonePrimArrayShim
{-# INLINE cloneMut_ #-}
cloneMut_ = cloneMutablePrimArrayShim
{-# INLINE equals #-}
equals = (==)
{-# INLINE null #-}
null (PrimArray a) = case sizeofByteArray# a of
0# -> True
_ -> False
{-# INLINE equalsMut #-}
equalsMut = sameMutablePrimArray
{-# INLINE rnf #-}
rnf (PrimArray !_) = ()
{-# INLINE singleton #-}
singleton a = runPrimArrayST $ do
marr <- newPrimArray 1
writePrimArray marr 0 a
unsafeFreezePrimArray marr
{-# INLINE doubleton #-}
doubleton a b = runPrimArrayST $ do
m <- newPrimArray 2
writePrimArray m 0 a
writePrimArray m 1 b
unsafeFreezePrimArray m
{-# INLINE tripleton #-}
tripleton a b c = runPrimArrayST $ do
m <- newPrimArray 3
writePrimArray m 0 a
writePrimArray m 1 b
writePrimArray m 2 c
unsafeFreezePrimArray m
{-# INLINE quadrupleton #-}
quadrupleton a b c d = runPrimArrayST $ do
m <- newPrimArray 4
writePrimArray m 0 a
writePrimArray m 1 b
writePrimArray m 2 c
writePrimArray m 3 d
unsafeFreezePrimArray m
{-# INLINE insertAt #-}
insertAt src i x = runPrimArrayST $ do
dst <- new (size src + 1)
copy dst 0 (slice src 0 i)
write dst i x
copy dst (i + 1) (slice src i (size src - i))
unsafeFreeze dst
{-# INLINE run #-}
run = runPrimArrayST
newtype PrimArray# a = PrimArray# ByteArray#
newtype MutablePrimArray# s a = MutablePrimArray# (MutableByteArray# s)
instance ContiguousU PrimArray where
type Unlifted PrimArray = PrimArray#
type UnliftedMut PrimArray = MutablePrimArray#
{-# INLINE resize #-}
resize = resizeMutablePrimArray
{-# INLINE unlift #-}
unlift (PrimArray x) = PrimArray# x
{-# INLINE unliftMut #-}
unliftMut (MutablePrimArray x) = MutablePrimArray# x
{-# INLINE lift #-}
lift (PrimArray# x) = PrimArray x
{-# INLINE liftMut #-}
liftMut (MutablePrimArray# x) = MutablePrimArray x
instance Contiguous Array where
type Mutable Array = MutableArray
type Element Array = Always
type Sliced Array = Slice Array
type MutableSliced Array = MutableSlice Array
{-# INLINE empty #-}
empty = mempty
{-# INLINE new #-}
new n = newArray n errorThunk
{-# INLINE replicateMut #-}
replicateMut = newArray
{-# INLINE index #-}
index = indexArray
{-# INLINE index# #-}
index# = indexArray##
{-# INLINE indexM #-}
indexM = indexArrayM
{-# INLINE read #-}
read = readArray
{-# INLINE write #-}
write = writeArray
{-# INLINE size #-}
size = sizeofArray
{-# INLINE sizeMut #-}
sizeMut = (\x -> pure $! sizeofMutableArray x)
{-# INLINE slice #-}
slice base offset length = Slice{offset,length,base=unlift base}
{-# INLINE sliceMut #-}
sliceMut baseMut offsetMut lengthMut = MutableSlice{offsetMut,lengthMut,baseMut=unliftMut baseMut}
{-# INLINE toSlice #-}
toSlice base = Slice{offset=0,length=size base,base=unlift base}
{-# INLINE toSliceMut #-}
toSliceMut baseMut = do
lengthMut <- sizeMut baseMut
pure MutableSlice{offsetMut=0,lengthMut,baseMut=unliftMut baseMut}
{-# INLINE freeze_ #-}
freeze_ = freezeArray
{-# INLINE unsafeFreeze #-}
unsafeFreeze = unsafeFreezeArray
{-# INLINE thaw_ #-}
thaw_ = thawArray
{-# INLINE copy_ #-}
copy_ = copyArray
{-# INLINE copyMut_ #-}
copyMut_ = copyMutableArray
{-# INLINE clone #-}
clone Slice{offset,length,base} = clone_ (lift base) offset length
{-# INLINE clone_ #-}
clone_ = cloneArray
{-# INLINE cloneMut_ #-}
cloneMut_ = cloneMutableArray
{-# INLINE equals #-}
equals = (==)
{-# INLINE null #-}
null (Array a) = case sizeofArray# a of
0# -> True
_ -> False
{-# INLINE equalsMut #-}
equalsMut = sameMutableArray
{-# INLINE rnf #-}
rnf !ary =
let !sz = sizeofArray ary
go !i
| i == sz = ()
| otherwise =
let !(# x #) = indexArray## ary i
in DS.rnf x `seq` go (i+1)
in go 0
{-# INLINE singleton #-}
singleton a = runArrayST (newArray 1 a >>= unsafeFreezeArray)
{-# INLINE doubleton #-}
doubleton a b = runArrayST $ do
m <- newArray 2 a
writeArray m 1 b
unsafeFreezeArray m
{-# INLINE tripleton #-}
tripleton a b c = runArrayST $ do
m <- newArray 3 a
writeArray m 1 b
writeArray m 2 c
unsafeFreezeArray m
{-# INLINE quadrupleton #-}
quadrupleton a b c d = runArrayST $ do
m <- newArray 4 a
writeArray m 1 b
writeArray m 2 c
writeArray m 3 d
unsafeFreezeArray m
{-# INLINE run #-}
run = runArrayST
instance ContiguousU Array where
type Unlifted Array = Array#
type UnliftedMut Array = MutableArray#
{-# INLINE resize #-}
resize = resizeArray
{-# INLINE unlift #-}
unlift (Array x) = x
{-# INLINE unliftMut #-}
unliftMut (MutableArray x) = x
{-# INLINE lift #-}
lift x = Array x
{-# INLINE liftMut #-}
liftMut x = MutableArray x
instance Contiguous UnliftedArray where
type Mutable UnliftedArray = MutableUnliftedArray
type Element UnliftedArray = PrimUnlifted
type Sliced UnliftedArray = Slice UnliftedArray
type MutableSliced UnliftedArray = MutableSlice UnliftedArray
{-# INLINE empty #-}
empty = emptyUnliftedArray
{-# INLINE new #-}
new = unsafeNewUnliftedArray
{-# INLINE replicateMut #-}
replicateMut = newUnliftedArray
{-# INLINE index #-}
index = indexUnliftedArray
{-# INLINE index# #-}
index# arr ix = (# indexUnliftedArray arr ix #)
{-# INLINE indexM #-}
indexM arr ix = pure (indexUnliftedArray arr ix)
{-# INLINE read #-}
read = readUnliftedArray
{-# INLINE write #-}
write = writeUnliftedArray
{-# INLINE size #-}
size = sizeofUnliftedArray
{-# INLINE sizeMut #-}
sizeMut = pure . sizeofMutableUnliftedArray
{-# INLINE slice #-}
slice base offset length = Slice{offset,length,base=unlift base}
{-# INLINE sliceMut #-}
sliceMut baseMut offsetMut lengthMut = MutableSlice{offsetMut,lengthMut,baseMut=unliftMut baseMut}
{-# INLINE freeze_ #-}
freeze_ = freezeUnliftedArray
{-# INLINE unsafeFreeze #-}
unsafeFreeze = unsafeFreezeUnliftedArray
{-# INLINE toSlice #-}
toSlice base = Slice{offset=0,length=size base,base=unlift base}
{-# INLINE toSliceMut #-}
toSliceMut baseMut = do
lengthMut <- sizeMut baseMut
pure MutableSlice{offsetMut=0,lengthMut,baseMut=unliftMut baseMut}
{-# INLINE thaw_ #-}
thaw_ = thawUnliftedArray
{-# INLINE copy_ #-}
copy_ = copyUnliftedArray
{-# INLINE copyMut_ #-}
copyMut_ = copyMutableUnliftedArray
{-# INLINE clone_ #-}
clone_ = cloneUnliftedArray
{-# INLINE cloneMut_ #-}
cloneMut_ = cloneMutableUnliftedArray
{-# INLINE equals #-}
equals = (==)
{-# INLINE null #-}
null (UnliftedArray a) = case sizeofArrayArray# a of
0# -> True
_ -> False
{-# INLINE equalsMut #-}
equalsMut = sameMutableUnliftedArray
{-# INLINE rnf #-}
rnf !ary =
let !sz = sizeofUnliftedArray ary
go !i
| i == sz = ()
| otherwise =
let x = indexUnliftedArray ary i
in DS.rnf x `seq` go (i+1)
in go 0
{-# INLINE singleton #-}
singleton a = runUnliftedArrayST (newUnliftedArray 1 a >>= unsafeFreezeUnliftedArray)
{-# INLINE doubleton #-}
doubleton a b = runUnliftedArrayST $ do
m <- newUnliftedArray 2 a
writeUnliftedArray m 1 b
unsafeFreezeUnliftedArray m
{-# INLINE tripleton #-}
tripleton a b c = runUnliftedArrayST $ do
m <- newUnliftedArray 3 a
writeUnliftedArray m 1 b
writeUnliftedArray m 2 c
unsafeFreezeUnliftedArray m
{-# INLINE quadrupleton #-}
quadrupleton a b c d = runUnliftedArrayST $ do
m <- newUnliftedArray 4 a
writeUnliftedArray m 1 b
writeUnliftedArray m 2 c
writeUnliftedArray m 3 d
unsafeFreezeUnliftedArray m
{-# INLINE run #-}
run = runUnliftedArrayST
newtype UnliftedArray# a = UnliftedArray# ArrayArray#
newtype MutableUnliftedArray# s a = MutableUnliftedArray# (MutableArrayArray# s)
instance ContiguousU UnliftedArray where
type Unlifted UnliftedArray = UnliftedArray#
type UnliftedMut UnliftedArray = MutableUnliftedArray#
{-# INLINE resize #-}
resize = resizeUnliftedArray
{-# INLINE unlift #-}
unlift (UnliftedArray x) = (UnliftedArray# x)
{-# INLINE unliftMut #-}
unliftMut (MutableUnliftedArray x) = (MutableUnliftedArray# x)
{-# INLINE lift #-}
lift (UnliftedArray# x) = UnliftedArray x
{-# INLINE liftMut #-}
liftMut (MutableUnliftedArray# x) = MutableUnliftedArray x