contiguous-0.6.4.1: src/Data/Primitive/Contiguous/Class.hs
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeFamilyDependencies #-}
{-# LANGUAGE TypeOperators #-}
{-# 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 hiding (fromList, fromListN)
import Data.Primitive.Contiguous.Shim
import Data.Primitive.Unlifted.Array
import Prelude hiding
( all
, any
, elem
, filter
, foldMap
, foldl
, foldr
, length
, map
, mapM
, mapM_
, maximum
, minimum
, null
, read
, replicate
, reverse
, scanl
, sequence
, sequence_
, traverse
, zip
, zipWith
, (<$)
)
import Control.DeepSeq (NFData)
import Control.Monad.Primitive (PrimMonad (..), PrimState)
import Control.Monad.ST (ST, runST)
import Control.Monad.ST.Run (runArrayST, runPrimArrayST, runSmallArrayST, runUnliftedArrayST)
import Data.Kind (Type)
import Data.Primitive.Unlifted.Array ()
import Data.Primitive.Unlifted.Array.Primops (MutableUnliftedArray# (MutableUnliftedArray#), UnliftedArray# (UnliftedArray#))
import Data.Primitive.Unlifted.Class (PrimUnlifted)
import GHC.Exts (Array#, Constraint, MutableArray#, SmallArray#, SmallMutableArray#, TYPE, sizeofArray#, sizeofByteArray#)
import qualified Control.DeepSeq as DS
import qualified Data.Primitive.Unlifted.Class as Class
import qualified GHC.Exts as Exts
-- 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 Mutable arr = (r :: Type -> Type -> Type) | r -> arr
-- | The constraint needed to store elements in the array.
type 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 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 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 ->
-- | new length
Int ->
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
-- | Create a quintupleton array.
quintupleton :: (Element arr a) => a -> a -> a -> a -> a -> arr a
-- | Create a sextupleton array.
sextupleton :: (Element arr a) => a -> 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) =>
-- | slice to copy
Sliced arr b ->
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) =>
-- | Array to copy a slice of
MutableSliced arr (PrimState m) b ->
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) =>
-- | Array to copy a slice of
Mutable arr (PrimState m) b ->
-- | offset
Int ->
-- | length
Int ->
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 ->
-- | offset
Int ->
-- | length
Int ->
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 ->
-- | final size
Int ->
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 ->
-- | offset into the array
Int ->
-- | length of the slice
Int ->
m (Mutable arr (PrimState m) b)
------ Copy Operations ------
-- | Copy a slice of an array into a mutable array.
copy ::
(PrimMonad m, Element arr b) =>
-- | destination array
Mutable arr (PrimState m) b ->
-- | offset into destination array
Int ->
-- | source slice
Sliced arr b ->
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) =>
-- | destination array
Mutable arr (PrimState m) b ->
-- | offset into destination array
Int ->
-- | source array
arr b ->
-- | offset into source array
Int ->
-- | number of elements to copy
Int ->
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) =>
-- | destination array
Mutable arr (PrimState m) b ->
-- | offset into destination array
Int ->
-- | source slice
MutableSliced arr (PrimState m) b ->
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) =>
-- | destination array
Mutable arr (PrimState m) b ->
-- | offset into destination array
Int ->
-- | source array
Mutable arr (PrimState m) b ->
-- | offset into source array
Int ->
-- | number of elements to copy
Int ->
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) =>
-- | slice to copy from
arr b ->
-- | index in the output array to insert at
Int ->
-- | element to insert
b ->
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 unsliced 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
instance Always a
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}
{-# INLINE quintupleton #-}
quintupleton a b c d e = Slice {offset = 0, length = 5, base = unlift $ quintupleton a b c d e}
{-# INLINE sextupleton #-}
sextupleton a b c d e f = Slice {offset = 0, length = 6, base = unlift $ sextupleton a b c d e f}
------ 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 a
unsafeFreezeSmallArray marr
{-# INLINE doubleton #-}
doubleton a b = runST $ do
m <- newSmallArray 2 a
writeSmallArray m 1 b
unsafeFreezeSmallArray m
{-# INLINE tripleton #-}
tripleton a b c = runST $ do
m <- newSmallArray 3 a
writeSmallArray m 1 b
writeSmallArray m 2 c
unsafeFreezeSmallArray m
{-# INLINE quadrupleton #-}
quadrupleton a b c d = runST $ do
m <- newSmallArray 4 a
writeSmallArray m 1 b
writeSmallArray m 2 c
writeSmallArray m 3 d
unsafeFreezeSmallArray m
{-# INLINE quintupleton #-}
quintupleton a b c d e = runST $ do
m <- newSmallArray 5 a
writeSmallArray m 1 b
writeSmallArray m 2 c
writeSmallArray m 3 d
writeSmallArray m 4 e
unsafeFreezeSmallArray m
{-# INLINE sextupleton #-}
sextupleton a b c d e f = runST $ do
m <- newSmallArray 6 a
writeSmallArray m 1 b
writeSmallArray m 2 c
writeSmallArray m 3 d
writeSmallArray m 4 e
writeSmallArray m 5 f
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 quintupleton #-}
quintupleton a b c d e = runPrimArrayST $ do
m <- newPrimArray 5
writePrimArray m 0 a
writePrimArray m 1 b
writePrimArray m 2 c
writePrimArray m 3 d
writePrimArray m 4 e
unsafeFreezePrimArray m
{-# INLINE sextupleton #-}
sextupleton a b c d e f = runPrimArrayST $ do
m <- newPrimArray 6
writePrimArray m 0 a
writePrimArray m 1 b
writePrimArray m 2 c
writePrimArray m 3 d
writePrimArray m 4 e
writePrimArray m 5 f
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 quintupleton #-}
quintupleton a b c d e = runArrayST $ do
m <- newArray 5 a
writeArray m 1 b
writeArray m 2 c
writeArray m 3 d
writeArray m 4 e
unsafeFreezeArray m
{-# INLINE sextupleton #-}
sextupleton a b c d e f = runArrayST $ do
m <- newArray 6 a
writeArray m 1 b
writeArray m 2 c
writeArray m 3 d
writeArray m 4 e
writeArray m 5 f
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
class (Class.Unlifted a ~ u, PrimUnlifted a) => PrimUnliftsInto (u :: TYPE ('Exts.BoxedRep 'Exts.Unlifted)) (a :: Type)
instance (Class.Unlifted a ~ u, PrimUnlifted a) => PrimUnliftsInto u a
instance Contiguous (UnliftedArray_ unlifted_a) where
type Mutable (UnliftedArray_ unlifted_a) = MutableUnliftedArray_ unlifted_a
type Element (UnliftedArray_ unlifted_a) = PrimUnliftsInto unlifted_a
type Sliced (UnliftedArray_ unlifted_a) = Slice (UnliftedArray_ unlifted_a)
type MutableSliced (UnliftedArray_ unlifted_a) = MutableSlice (UnliftedArray_ unlifted_a)
{-# 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 (UnliftedArray# a)) = case Exts.sizeofArray# 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 quintupleton #-}
quintupleton a b c d e = runUnliftedArrayST $ do
m <- newUnliftedArray 5 a
writeUnliftedArray m 1 b
writeUnliftedArray m 2 c
writeUnliftedArray m 3 d
writeUnliftedArray m 4 e
unsafeFreezeUnliftedArray m
{-# INLINE sextupleton #-}
sextupleton a b c d e f = runUnliftedArrayST $ do
m <- newUnliftedArray 6 a
writeUnliftedArray m 1 b
writeUnliftedArray m 2 c
writeUnliftedArray m 3 d
writeUnliftedArray m 4 e
writeUnliftedArray m 5 f
unsafeFreezeUnliftedArray m
{-# INLINE run #-}
run = runUnliftedArrayST
newtype UnliftedArray## (u :: TYPE UnliftedRep) (a :: Type)
= UnliftedArray## (Exts.Array# u)
newtype MutableUnliftedArray## (u :: TYPE UnliftedRep) s (a :: Type)
= MutableUnliftedArray## (Exts.MutableArray# s u)
instance ContiguousU (UnliftedArray_ unlifted_a) where
type Unlifted (UnliftedArray_ unlifted_a) = UnliftedArray## unlifted_a
type UnliftedMut (UnliftedArray_ unlifted_a) = MutableUnliftedArray## unlifted_a
{-# INLINE resize #-}
resize = resizeUnliftedArray
{-# INLINE unlift #-}
unlift (UnliftedArray (UnliftedArray# x)) = UnliftedArray## x
{-# INLINE unliftMut #-}
unliftMut (MutableUnliftedArray (MutableUnliftedArray# x)) = MutableUnliftedArray## x
{-# INLINE lift #-}
lift (UnliftedArray## x) = UnliftedArray (UnliftedArray# x)
{-# INLINE liftMut #-}
liftMut (MutableUnliftedArray## x) = MutableUnliftedArray (MutableUnliftedArray# x)