{-# language KindSignatures #-}
{-# language BangPatterns #-}
{-# language RoleAnnotations #-}
{-# language MagicHash #-}
{-# language UnboxedTuples #-}
{-# language RankNTypes #-}
{-# language DeriveTraversable #-}
{-# language Unsafe #-}
module Data.CompactSequence.Internal.Array where
import Data.CompactSequence.Internal.Size
import Data.Primitive.SmallArray
import Control.Monad.ST.Strict
import GHC.Exts (SmallArray#)
newtype Array n a = Array (SmallArray a)
deriving (Functor, Foldable, Traversable)
type role Array nominal representational
singleton :: a -> Array Sz1 a
singleton x = Array (pure x)
unsafeSmallArrayToArray :: SmallArray a -> Array n a
unsafeSmallArrayToArray = Array
arrayToSmallArray :: Array n a -> SmallArray a
arrayToSmallArray (Array sa) = sa
getSingleton# :: Array Sz1 a -> (# a #)
getSingleton# (Array sa) = indexSmallArray## sa 0
getSingletonA :: Applicative f => Array Sz1 a -> f a
getSingletonA (Array sa)
| (# a #) <- indexSmallArray## sa 0
= pure a
splitArray :: Size n -> Array (Twice n) a -> (Array n a, Array n a)
splitArray (Size len) (Array sa)
| (# sa1, sa2 #) <- splitSmallArray# len sa
= (Array (SmallArray sa1), Array (SmallArray sa2))
{-# INLINE splitArray #-}
splitSmallArray# :: Int -> SmallArray a -> (# SmallArray# a, SmallArray# a #)
splitSmallArray# len sa1 = (# sa2, sa3 #)
where
!(SmallArray sa2) = cloneSmallArray sa1 0 len
!(SmallArray sa3) = cloneSmallArray sa1 len len
{-# NOINLINE splitSmallArray# #-}
append :: Size n -> Array n a -> Array n a -> Array (Twice n) a
append (Size n) (Array xs) (Array ys) = Array $
appendSmallArrays n xs ys
appendSmallArrays :: Int -> SmallArray a -> SmallArray a -> SmallArray a
appendSmallArrays n xs ys =
createSmallArray (2*n)
(error "Data.CompactSequence.Internal.Array.append: Internal error")
$ \sma -> copySmallArray sma 0 xs 0 n
*> copySmallArray sma n ys 0 n
{-# NOINLINE appendSmallArrays #-}
createSmallArray
:: Int
-> a
-> (forall s. SmallMutableArray s a -> ST s ())
-> SmallArray a
createSmallArray n x f = runSmallArray $ do
mary <- newSmallArray n x
f mary
pure mary
arraySplitListN :: Size n -> [a] -> (Array n a, [a])
arraySplitListN (Size n) xs
| (sa, xs') <- smallArraySplitListN n xs
= (Array sa, xs')
smallArraySplitListN :: Int -> [a] -> (SmallArray a, [a])
smallArraySplitListN n l = runST $ do
sma <- newSmallArray n (error "smallArraySplitListN: uninitialized")
let go !ix [] = if ix == n
then do
sa <- unsafeFreezeSmallArray sma
pure (sa, [])
else error "smallArraySplitListN: list length less than specified size"
go !ix xss@(x : xs) = if ix < n
then do
writeSmallArray sma ix x
go (ix+1) xs
else do
sa <- unsafeFreezeSmallArray sma
pure (sa, xss)
go 0 l
fromList :: Size n -> [a] -> Array n a
fromList (Size n) xs = Array (smallArrayFromListN n xs)