on master help sign in
Add exact files for change comparision for SmallArray and PrimArray
commite14ad7b3d0d312fe5e746ef6c91350af191b7451 authoradithyaov <adi.obilisetty@gmail.com> dateFri 7 Feb 2020, 17:41 (7 years ago) parentf6fd95a
2 files changed+1939
src/Streamly/Internal/Data/Prim/Array/Types.hs+966 src/Streamly/Internal/Data/SmallArray/Types.hs+973
src/Streamly/Internal/Data/Prim/Array/Types.hsnew file+966
@@ -0,0 +1,966 @@
1+{-# LANGUAGE BangPatterns #-}
2+{-# LANGUAGE CPP #-}
3+{-# LANGUAGE MagicHash #-}
4+{-# LANGUAGE RankNTypes #-}
5+{-# LANGUAGE ScopedTypeVariables #-}
6+{-# LANGUAGE TypeFamilies #-}
7+{-# LANGUAGE UnboxedTuples #-}
8+
9+
10+-- |
11+-- Module : Data.Primitive.PrimArray
12+-- Copyright : (c) Roman Leshchinskiy 2009-2012
13+-- License : BSD-style
14+--
15+-- Maintainer : Roman Leshchinskiy <rl@cse.unsw.edu.au>
16+-- Portability : non-portable
17+--
18+-- Arrays of unboxed primitive types. The function provided by this module
19+-- match the behavior of those provided by @Data.Primitive.ByteArray@, and
20+-- the underlying types and primops that back them are the same.
21+-- However, the type constructors 'PrimArray' and 'MutablePrimArray' take one additional
22+-- argument than their respective counterparts 'ByteArray' and 'MutableByteArray'.
23+-- This argument is used to designate the type of element in the array.
24+-- Consequently, all function this modules accepts length and incides in
25+-- terms of elements, not bytes.
26+--
27+-- @since 0.6.4.0
28+module Data.Primitive.PrimArray
29+ ( -- * Types
30+ PrimArray(..)
31+ , MutablePrimArray(..)
32+ -- * Allocation
33+ , newPrimArray
34+ , resizeMutablePrimArray
35+#if __GLASGOW_HASKELL__ >= 710
36+ , shrinkMutablePrimArray
37+#endif
38+ -- * Element Access
39+ , readPrimArray
40+ , writePrimArray
41+ , indexPrimArray
42+ -- * Freezing and Thawing
43+ , unsafeFreezePrimArray
44+ , unsafeThawPrimArray
45+ -- * Block Operations
46+ , copyPrimArray
47+ , copyMutablePrimArray
48+#if __GLASGOW_HASKELL__ >= 708
49+ , copyPrimArrayToPtr
50+ , copyMutablePrimArrayToPtr
51+#endif
52+ , setPrimArray
53+ -- * Information
54+ , sameMutablePrimArray
55+ , getSizeofMutablePrimArray
56+ , sizeofMutablePrimArray
57+ , sizeofPrimArray
58+ -- * List Conversion
59+ , primArrayToList
60+ , primArrayFromList
61+ , primArrayFromListN
62+ -- * Folding
63+ , foldrPrimArray
64+ , foldrPrimArray'
65+ , foldlPrimArray
66+ , foldlPrimArray'
67+ , foldlPrimArrayM'
68+ -- * Effectful Folding
69+ , traversePrimArray_
70+ , itraversePrimArray_
71+ -- * Map/Create
72+ , mapPrimArray
73+ , imapPrimArray
74+ , generatePrimArray
75+ , replicatePrimArray
76+ , filterPrimArray
77+ , mapMaybePrimArray
78+ -- * Effectful Map/Create
79+ -- $effectfulMapCreate
80+ -- ** Lazy Applicative
81+ , traversePrimArray
82+ , itraversePrimArray
83+ , generatePrimArrayA
84+ , replicatePrimArrayA
85+ , filterPrimArrayA
86+ , mapMaybePrimArrayA
87+ -- ** Strict Primitive Monadic
88+ , traversePrimArrayP
89+ , itraversePrimArrayP
90+ , generatePrimArrayP
91+ , replicatePrimArrayP
92+ , filterPrimArrayP
93+ , mapMaybePrimArrayP
94+ ) where
95+
96+import GHC.Exts
97+import GHC.Base ( Int(..) )
98+import Data.Primitive.Internal.Compat (isTrue#)
99+import Data.Primitive.Types
100+import Data.Primitive.ByteArray (ByteArray(..))
101+import Data.Monoid (Monoid(..),(<>))
102+import Control.Applicative
103+import Control.Monad.Primitive
104+import Control.Monad.ST
105+import qualified Data.List as L
106+import qualified Data.Primitive.ByteArray as PB
107+import qualified Data.Primitive.Types as PT
108+
109+#if MIN_VERSION_base(4,7,0)
110+import GHC.Exts (IsList(..))
111+#endif
112+
113+#if MIN_VERSION_base(4,9,0)
114+import Data.Semigroup (Semigroup)
115+import qualified Data.Semigroup as SG
116+#endif
117+
118+-- | Arrays of unboxed elements. This accepts types like 'Double', 'Char',
119+-- 'Int', and 'Word', as well as their fixed-length variants ('Word8',
120+-- 'Word16', etc.). Since the elements are unboxed, a 'PrimArray' is strict
121+-- in its elements. This differs from the behavior of 'Array', which is lazy
122+-- in its elements.
123+data PrimArray a = PrimArray ByteArray#
124+
125+-- | Mutable primitive arrays associated with a primitive state token.
126+-- These can be written to and read from in a monadic context that supports
127+-- sequencing such as 'IO' or 'ST'. Typically, a mutable primitive array will
128+-- be built and then convert to an immutable primitive array using
129+-- 'unsafeFreezePrimArray'. However, it is also acceptable to simply discard
130+-- a mutable primitive array since it lives in managed memory and will be
131+-- garbage collected when no longer referenced.
132+data MutablePrimArray s a = MutablePrimArray (MutableByteArray# s)
133+
134+sameByteArray :: ByteArray# -> ByteArray# -> Bool
135+sameByteArray ba1 ba2 =
136+ case reallyUnsafePtrEquality# (unsafeCoerce# ba1 :: ()) (unsafeCoerce# ba2 :: ()) of
137+#if __GLASGOW_HASKELL__ >= 708
138+ r -> isTrue# r
139+#else
140+ 1# -> True
141+ _ -> False
142+#endif
143+
144+-- | @since 0.6.4.0
145+instance (Eq a, Prim a) => Eq (PrimArray a) where
146+ a1@(PrimArray ba1#) == a2@(PrimArray ba2#)
147+ | sameByteArray ba1# ba2# = True
148+ | sz1 /= sz2 = False
149+ | otherwise = loop (quot sz1 (sizeOf (undefined :: a)) - 1)
150+ where
151+ -- Here, we take the size in bytes, not in elements. We do this
152+ -- since it allows us to defer performing the division to
153+ -- calculate the size in elements.
154+ sz1 = PB.sizeofByteArray (ByteArray ba1#)
155+ sz2 = PB.sizeofByteArray (ByteArray ba2#)
156+ loop !i
157+ | i < 0 = True
158+ | otherwise = indexPrimArray a1 i == indexPrimArray a2 i && loop (i-1)
159+ {-# INLINE (==) #-}
160+
161+-- | Lexicographic ordering. Subject to change between major versions.
162+--
163+-- @since 0.6.4.0
164+instance (Ord a, Prim a) => Ord (PrimArray a) where
165+ compare a1@(PrimArray ba1#) a2@(PrimArray ba2#)
166+ | sameByteArray ba1# ba2# = EQ
167+ | otherwise = loop 0
168+ where
169+ sz1 = PB.sizeofByteArray (ByteArray ba1#)
170+ sz2 = PB.sizeofByteArray (ByteArray ba2#)
171+ sz = quot (min sz1 sz2) (sizeOf (undefined :: a))
172+ loop !i
173+ | i < sz = compare (indexPrimArray a1 i) (indexPrimArray a2 i) <> loop (i+1)
174+ | otherwise = compare sz1 sz2
175+ {-# INLINE compare #-}
176+
177+#if MIN_VERSION_base(4,7,0)
178+-- | @since 0.6.4.0
179+instance Prim a => IsList (PrimArray a) where
180+ type Item (PrimArray a) = a
181+ fromList = primArrayFromList
182+ fromListN = primArrayFromListN
183+ toList = primArrayToList
184+#endif
185+
186+-- | @since 0.6.4.0
187+instance (Show a, Prim a) => Show (PrimArray a) where
188+ showsPrec p a = showParen (p > 10) $
189+ showString "fromListN " . shows (sizeofPrimArray a) . showString " "
190+ . shows (primArrayToList a)
191+
192+die :: String -> String -> a
193+die fun problem = error $ "Data.Primitive.PrimArray." ++ fun ++ ": " ++ problem
194+
195+primArrayFromList :: Prim a => [a] -> PrimArray a
196+primArrayFromList vs = primArrayFromListN (L.length vs) vs
197+
198+primArrayFromListN :: forall a. Prim a => Int -> [a] -> PrimArray a
199+primArrayFromListN len vs = runST run where
200+ run :: forall s. ST s (PrimArray a)
201+ run = do
202+ arr <- newPrimArray len
203+ let go :: [a] -> Int -> ST s ()
204+ go [] !ix = if ix == len
205+ then return ()
206+ else die "fromListN" "list length less than specified size"
207+ go (a : as) !ix = if ix < len
208+ then do
209+ writePrimArray arr ix a
210+ go as (ix + 1)
211+ else die "fromListN" "list length greater than specified size"
212+ go vs 0
213+ unsafeFreezePrimArray arr
214+
215+-- | Convert the primitive array to a list.
216+{-# INLINE primArrayToList #-}
217+primArrayToList :: forall a. Prim a => PrimArray a -> [a]
218+primArrayToList xs = build (\c n -> foldrPrimArray c n xs)
219+
220+primArrayToByteArray :: PrimArray a -> PB.ByteArray
221+primArrayToByteArray (PrimArray x) = PB.ByteArray x
222+
223+byteArrayToPrimArray :: ByteArray -> PrimArray a
224+byteArrayToPrimArray (PB.ByteArray x) = PrimArray x
225+
226+#if MIN_VERSION_base(4,9,0)
227+-- | @since 0.6.4.0
228+instance Semigroup (PrimArray a) where
229+ x <> y = byteArrayToPrimArray (primArrayToByteArray x SG.<> primArrayToByteArray y)
230+ sconcat = byteArrayToPrimArray . SG.sconcat . fmap primArrayToByteArray
231+ stimes i arr = byteArrayToPrimArray (SG.stimes i (primArrayToByteArray arr))
232+#endif
233+
234+-- | @since 0.6.4.0
235+instance Monoid (PrimArray a) where
236+ mempty = emptyPrimArray
237+#if !(MIN_VERSION_base(4,11,0))
238+ mappend x y = byteArrayToPrimArray (mappend (primArrayToByteArray x) (primArrayToByteArray y))
239+#endif
240+ mconcat = byteArrayToPrimArray . mconcat . map primArrayToByteArray
241+
242+-- | The empty primitive array.
243+emptyPrimArray :: PrimArray a
244+{-# NOINLINE emptyPrimArray #-}
245+emptyPrimArray = runST $ primitive $ \s0# -> case newByteArray# 0# s0# of
246+ (# s1#, arr# #) -> case unsafeFreezeByteArray# arr# s1# of
247+ (# s2#, arr'# #) -> (# s2#, PrimArray arr'# #)
248+
249+-- | Create a new mutable primitive array of the given length. The
250+-- underlying memory is left uninitialized.
251+newPrimArray :: forall m a. (PrimMonad m, Prim a) => Int -> m (MutablePrimArray (PrimState m) a)
252+{-# INLINE newPrimArray #-}
253+newPrimArray (I# n#)
254+ = primitive (\s# ->
255+ case newByteArray# (n# *# sizeOf# (undefined :: a)) s# of
256+ (# s'#, arr# #) -> (# s'#, MutablePrimArray arr# #)
257+ )
258+
259+-- | Resize a mutable primitive array. The new size is given in elements.
260+--
261+-- This will either resize the array in-place or, if not possible, allocate the
262+-- contents into a new, unpinned array and copy the original array\'s contents.
263+--
264+-- To avoid undefined behaviour, the original 'MutablePrimArray' shall not be
265+-- accessed anymore after a 'resizeMutablePrimArray' has been performed.
266+-- Moreover, no reference to the old one should be kept in order to allow
267+-- garbage collection of the original 'MutablePrimArray' in case a new
268+-- 'MutablePrimArray' had to be allocated.
269+resizeMutablePrimArray :: forall m a. (PrimMonad m, Prim a)
270+ => MutablePrimArray (PrimState m) a
271+ -> Int -- ^ new size
272+ -> m (MutablePrimArray (PrimState m) a)
273+{-# INLINE resizeMutablePrimArray #-}
274+#if __GLASGOW_HASKELL__ >= 710
275+resizeMutablePrimArray (MutablePrimArray arr#) (I# n#)
276+ = primitive (\s# -> case resizeMutableByteArray# arr# (n# *# sizeOf# (undefined :: a)) s# of
277+ (# s'#, arr'# #) -> (# s'#, MutablePrimArray arr'# #))
278+#else
279+resizeMutablePrimArray arr n
280+ = do arr' <- newPrimArray n
281+ copyMutablePrimArray arr' 0 arr 0 (min (sizeofMutablePrimArray arr) n)
282+ return arr'
283+#endif
284+
285+-- Although it is possible to shim resizeMutableByteArray for old GHCs, this
286+-- is not the case with shrinkMutablePrimArray.
287+#if __GLASGOW_HASKELL__ >= 710
288+-- | Shrink a mutable primitive array. The new size is given in elements.
289+-- It must be smaller than the old size. The array will be resized in place.
290+-- This function is only available when compiling with GHC 7.10 or newer.
291+shrinkMutablePrimArray :: forall m a. (PrimMonad m, Prim a)
292+ => MutablePrimArray (PrimState m) a
293+ -> Int -- ^ new size
294+ -> m ()
295+{-# INLINE shrinkMutablePrimArray #-}
296+shrinkMutablePrimArray (MutablePrimArray arr#) (I# n#)
297+ = primitive_ (shrinkMutableByteArray# arr# (n# *# sizeOf# (undefined :: a)))
298+#endif
299+
300+readPrimArray :: (Prim a, PrimMonad m) => MutablePrimArray (PrimState m) a -> Int -> m a
301+{-# INLINE readPrimArray #-}
302+readPrimArray (MutablePrimArray arr#) (I# i#)
303+ = primitive (readByteArray# arr# i#)
304+
305+-- | Write an element to the given index.
306+writePrimArray ::
307+ (Prim a, PrimMonad m)
308+ => MutablePrimArray (PrimState m) a -- ^ array
309+ -> Int -- ^ index
310+ -> a -- ^ element
311+ -> m ()
312+{-# INLINE writePrimArray #-}
313+writePrimArray (MutablePrimArray arr#) (I# i#) x
314+ = primitive_ (writeByteArray# arr# i# x)
315+
316+-- | Copy part of a mutable array into another mutable array.
317+-- In the case that the destination and
318+-- source arrays are the same, the regions may overlap.
319+copyMutablePrimArray :: forall m a.
320+ (PrimMonad m, Prim a)
321+ => MutablePrimArray (PrimState m) a -- ^ destination array
322+ -> Int -- ^ offset into destination array
323+ -> MutablePrimArray (PrimState m) a -- ^ source array
324+ -> Int -- ^ offset into source array
325+ -> Int -- ^ number of elements to copy
326+ -> m ()
327+{-# INLINE copyMutablePrimArray #-}
328+copyMutablePrimArray (MutablePrimArray dst#) (I# doff#) (MutablePrimArray src#) (I# soff#) (I# n#)
329+ = primitive_ (copyMutableByteArray#
330+ src#
331+ (soff# *# (sizeOf# (undefined :: a)))
332+ dst#
333+ (doff# *# (sizeOf# (undefined :: a)))
334+ (n# *# (sizeOf# (undefined :: a)))
335+ )
336+
337+-- | Copy part of an array into another mutable array.
338+copyPrimArray :: forall m a.
339+ (PrimMonad m, Prim a)
340+ => MutablePrimArray (PrimState m) a -- ^ destination array
341+ -> Int -- ^ offset into destination array
342+ -> PrimArray a -- ^ source array
343+ -> Int -- ^ offset into source array
344+ -> Int -- ^ number of elements to copy
345+ -> m ()
346+{-# INLINE copyPrimArray #-}
347+copyPrimArray (MutablePrimArray dst#) (I# doff#) (PrimArray src#) (I# soff#) (I# n#)
348+ = primitive_ (copyByteArray#
349+ src#
350+ (soff# *# (sizeOf# (undefined :: a)))
351+ dst#
352+ (doff# *# (sizeOf# (undefined :: a)))
353+ (n# *# (sizeOf# (undefined :: a)))
354+ )
355+
356+#if __GLASGOW_HASKELL__ >= 708
357+-- | Copy a slice of an immutable primitive array to an address.
358+-- The offset and length are given in elements of type @a@.
359+-- This function assumes that the 'Prim' instance of @a@
360+-- agrees with the 'Storable' instance. This function is only
361+-- available when building with GHC 7.8 or newer.
362+copyPrimArrayToPtr :: forall m a. (PrimMonad m, Prim a)
363+ => Ptr a -- ^ destination pointer
364+ -> PrimArray a -- ^ source array
365+ -> Int -- ^ offset into source array
366+ -> Int -- ^ number of prims to copy
367+ -> m ()
368+{-# INLINE copyPrimArrayToPtr #-}
369+copyPrimArrayToPtr (Ptr addr#) (PrimArray ba#) (I# soff#) (I# n#) =
370+ primitive (\ s# ->
371+ let s'# = copyByteArrayToAddr# ba# (soff# *# siz#) addr# (n# *# siz#) s#
372+ in (# s'#, () #))
373+ where siz# = sizeOf# (undefined :: a)
374+
375+-- | Copy a slice of an immutable primitive array to an address.
376+-- The offset and length are given in elements of type @a@.
377+-- This function assumes that the 'Prim' instance of @a@
378+-- agrees with the 'Storable' instance. This function is only
379+-- available when building with GHC 7.8 or newer.
380+copyMutablePrimArrayToPtr :: forall m a. (PrimMonad m, Prim a)
381+ => Ptr a -- ^ destination pointer
382+ -> MutablePrimArray (PrimState m) a -- ^ source array
383+ -> Int -- ^ offset into source array
384+ -> Int -- ^ number of prims to copy
385+ -> m ()
386+{-# INLINE copyMutablePrimArrayToPtr #-}
387+copyMutablePrimArrayToPtr (Ptr addr#) (MutablePrimArray mba#) (I# soff#) (I# n#) =
388+ primitive (\ s# ->
389+ let s'# = copyMutableByteArrayToAddr# mba# (soff# *# siz#) addr# (n# *# siz#) s#
390+ in (# s'#, () #))
391+ where siz# = sizeOf# (undefined :: a)
392+#endif
393+
394+-- | Fill a slice of a mutable primitive array with a value.
395+setPrimArray
396+ :: (Prim a, PrimMonad m)
397+ => MutablePrimArray (PrimState m) a -- ^ array to fill
398+ -> Int -- ^ offset into array
399+ -> Int -- ^ number of values to fill
400+ -> a -- ^ value to fill with
401+ -> m ()
402+{-# INLINE setPrimArray #-}
403+setPrimArray (MutablePrimArray dst#) (I# doff#) (I# sz#) x
404+ = primitive_ (PT.setByteArray# dst# doff# sz# x)
405+
406+-- | Get the size of a mutable primitive array in elements. Unlike 'sizeofMutablePrimArray',
407+-- this function ensures sequencing in the presence of resizing.
408+getSizeofMutablePrimArray :: forall m a. (PrimMonad m, Prim a)
409+ => MutablePrimArray (PrimState m) a -- ^ array
410+ -> m Int
411+{-# INLINE getSizeofMutablePrimArray #-}
412+#if __GLASGOW_HASKELL__ >= 801
413+getSizeofMutablePrimArray (MutablePrimArray arr#)
414+ = primitive (\s# ->
415+ case getSizeofMutableByteArray# arr# s# of
416+ (# s'#, sz# #) -> (# s'#, I# (quotInt# sz# (sizeOf# (undefined :: a))) #)
417+ )
418+#else
419+-- On older GHCs, it is not possible to resize a byte array, so
420+-- this provides behavior consistent with the implementation for
421+-- newer GHCs.
422+getSizeofMutablePrimArray arr
423+ = return (sizeofMutablePrimArray arr)
424+#endif
425+
426+-- | Size of the mutable primitive array in elements. This function shall not
427+-- be used on primitive arrays that are an argument to or a result of
428+-- 'resizeMutablePrimArray' or 'shrinkMutablePrimArray'.
429+sizeofMutablePrimArray :: forall s a. Prim a => MutablePrimArray s a -> Int
430+{-# INLINE sizeofMutablePrimArray #-}
431+sizeofMutablePrimArray (MutablePrimArray arr#) =
432+ I# (quotInt# (sizeofMutableByteArray# arr#) (sizeOf# (undefined :: a)))
433+
434+-- | Check if the two arrays refer to the same memory block.
435+sameMutablePrimArray :: MutablePrimArray s a -> MutablePrimArray s a -> Bool
436+{-# INLINE sameMutablePrimArray #-}
437+sameMutablePrimArray (MutablePrimArray arr#) (MutablePrimArray brr#)
438+ = isTrue# (sameMutableByteArray# arr# brr#)
439+
440+-- | Convert a mutable byte array to an immutable one without copying. The
441+-- array should not be modified after the conversion.
442+unsafeFreezePrimArray
443+ :: PrimMonad m => MutablePrimArray (PrimState m) a -> m (PrimArray a)
444+{-# INLINE unsafeFreezePrimArray #-}
445+unsafeFreezePrimArray (MutablePrimArray arr#)
446+ = primitive (\s# -> case unsafeFreezeByteArray# arr# s# of
447+ (# s'#, arr'# #) -> (# s'#, PrimArray arr'# #))
448+
449+-- | Convert an immutable array to a mutable one without copying. The
450+-- original array should not be used after the conversion.
451+unsafeThawPrimArray
452+ :: PrimMonad m => PrimArray a -> m (MutablePrimArray (PrimState m) a)
453+{-# INLINE unsafeThawPrimArray #-}
454+unsafeThawPrimArray (PrimArray arr#)
455+ = primitive (\s# -> (# s#, MutablePrimArray (unsafeCoerce# arr#) #))
456+
457+-- | Read a primitive value from the primitive array.
458+indexPrimArray :: forall a. Prim a => PrimArray a -> Int -> a
459+{-# INLINE indexPrimArray #-}
460+indexPrimArray (PrimArray arr#) (I# i#) = indexByteArray# arr# i#
461+
462+-- | Get the size, in elements, of the primitive array.
463+sizeofPrimArray :: forall a. Prim a => PrimArray a -> Int
464+{-# INLINE sizeofPrimArray #-}
465+sizeofPrimArray (PrimArray arr#) = I# (quotInt# (sizeofByteArray# arr#) (sizeOf# (undefined :: a)))
466+
467+-- | Lazy right-associated fold over the elements of a 'PrimArray'.
468+{-# INLINE foldrPrimArray #-}
469+foldrPrimArray :: forall a b. Prim a => (a -> b -> b) -> b -> PrimArray a -> b
470+foldrPrimArray f z arr = go 0
471+ where
472+ !sz = sizeofPrimArray arr
473+ go !i
474+ | sz > i = f (indexPrimArray arr i) (go (i+1))
475+ | otherwise = z
476+
477+-- | Strict right-associated fold over the elements of a 'PrimArray'.
478+{-# INLINE foldrPrimArray' #-}
479+foldrPrimArray' :: forall a b. Prim a => (a -> b -> b) -> b -> PrimArray a -> b
480+foldrPrimArray' f z0 arr = go (sizeofPrimArray arr - 1) z0
481+ where
482+ go !i !acc
483+ | i < 0 = acc
484+ | otherwise = go (i - 1) (f (indexPrimArray arr i) acc)
485+
486+-- | Lazy left-associated fold over the elements of a 'PrimArray'.
487+{-# INLINE foldlPrimArray #-}
488+foldlPrimArray :: forall a b. Prim a => (b -> a -> b) -> b -> PrimArray a -> b
489+foldlPrimArray f z arr = go (sizeofPrimArray arr - 1)
490+ where
491+ go !i
492+ | i < 0 = z
493+ | otherwise = f (go (i - 1)) (indexPrimArray arr i)
494+
495+-- | Strict left-associated fold over the elements of a 'PrimArray'.
496+{-# INLINE foldlPrimArray' #-}
497+foldlPrimArray' :: forall a b. Prim a => (b -> a -> b) -> b -> PrimArray a -> b
498+foldlPrimArray' f z0 arr = go 0 z0
499+ where
500+ !sz = sizeofPrimArray arr
501+ go !i !acc
502+ | i < sz = go (i + 1) (f acc (indexPrimArray arr i))
503+ | otherwise = acc
504+
505+-- | Strict left-associated fold over the elements of a 'PrimArray'.
506+{-# INLINE foldlPrimArrayM' #-}
507+foldlPrimArrayM' :: (Prim a, Monad m) => (b -> a -> m b) -> b -> PrimArray a -> m b
508+foldlPrimArrayM' f z0 arr = go 0 z0
509+ where
510+ !sz = sizeofPrimArray arr
511+ go !i !acc1
512+ | i < sz = do
513+ acc2 <- f acc1 (indexPrimArray arr i)
514+ go (i + 1) acc2
515+ | otherwise = return acc1
516+
517+-- | Traverse a primitive array. The traversal forces the resulting values and
518+-- writes them to the new primitive array as it performs the monadic effects.
519+-- Consequently:
520+--
521+-- >>> traversePrimArrayP (\x -> print x $> bool x undefined (x == 2)) (fromList [1, 2, 3 :: Int])
522+-- 1
523+-- 2
524+-- *** Exception: Prelude.undefined
525+--
526+-- In many situations, 'traversePrimArrayP' can replace 'traversePrimArray',
527+-- changing the strictness characteristics of the traversal but typically improving
528+-- the performance. Consider the following short-circuiting traversal:
529+--
530+-- > incrPositiveA :: PrimArray Int -> Maybe (PrimArray Int)
531+-- > incrPositiveA xs = traversePrimArray (\x -> bool Nothing (Just (x + 1)) (x > 0)) xs
532+--
533+-- This can be rewritten using 'traversePrimArrayP'. To do this, we must
534+-- change the traversal context to @MaybeT (ST s)@, which has a 'PrimMonad'
535+-- instance:
536+--
537+-- > incrPositiveB :: PrimArray Int -> Maybe (PrimArray Int)
538+-- > incrPositiveB xs = runST $ runMaybeT $ traversePrimArrayP
539+-- > (\x -> bool (MaybeT (return Nothing)) (MaybeT (return (Just (x + 1)))) (x > 0))
540+-- > xs
541+--
542+-- Benchmarks demonstrate that the second implementation runs 150 times
543+-- faster than the first. It also results in fewer allocations.
544+{-# INLINE traversePrimArrayP #-}
545+traversePrimArrayP :: (PrimMonad m, Prim a, Prim b)
546+ => (a -> m b)
547+ -> PrimArray a
548+ -> m (PrimArray b)
549+traversePrimArrayP f arr = do
550+ let !sz = sizeofPrimArray arr
551+ marr <- newPrimArray sz
552+ let go !ix = if ix < sz
553+ then do
554+ b <- f (indexPrimArray arr ix)
555+ writePrimArray marr ix b
556+ go (ix + 1)
557+ else return ()
558+ go 0
559+ unsafeFreezePrimArray marr
560+
561+-- | Filter the primitive array, keeping the elements for which the monadic
562+-- predicate evaluates true.
563+{-# INLINE filterPrimArrayP #-}
564+filterPrimArrayP :: (PrimMonad m, Prim a)
565+ => (a -> m Bool)
566+ -> PrimArray a
567+ -> m (PrimArray a)
568+filterPrimArrayP f arr = do
569+ let !sz = sizeofPrimArray arr
570+ marr <- newPrimArray sz
571+ let go !ixSrc !ixDst = if ixSrc < sz
572+ then do
573+ let a = indexPrimArray arr ixSrc
574+ b <- f a
575+ if b
576+ then do
577+ writePrimArray marr ixDst a
578+ go (ixSrc + 1) (ixDst + 1)
579+ else go (ixSrc + 1) ixDst
580+ else return ixDst
581+ lenDst <- go 0 0
582+ marr' <- resizeMutablePrimArray marr lenDst
583+ unsafeFreezePrimArray marr'
584+
585+-- | Map over the primitive array, keeping the elements for which the monadic
586+-- predicate provides a 'Just'.
587+{-# INLINE mapMaybePrimArrayP #-}
588+mapMaybePrimArrayP :: (PrimMonad m, Prim a, Prim b)
589+ => (a -> m (Maybe b))
590+ -> PrimArray a
591+ -> m (PrimArray b)
592+mapMaybePrimArrayP f arr = do
593+ let !sz = sizeofPrimArray arr
594+ marr <- newPrimArray sz
595+ let go !ixSrc !ixDst = if ixSrc < sz
596+ then do
597+ let a = indexPrimArray arr ixSrc
598+ mb <- f a
599+ case mb of
600+ Just b -> do
601+ writePrimArray marr ixDst b
602+ go (ixSrc + 1) (ixDst + 1)
603+ Nothing -> go (ixSrc + 1) ixDst
604+ else return ixDst
605+ lenDst <- go 0 0
606+ marr' <- resizeMutablePrimArray marr lenDst
607+ unsafeFreezePrimArray marr'
608+
609+-- | Generate a primitive array by evaluating the monadic generator function
610+-- at each index.
611+{-# INLINE generatePrimArrayP #-}
612+generatePrimArrayP :: (PrimMonad m, Prim a)
613+ => Int -- ^ length
614+ -> (Int -> m a) -- ^ generator
615+ -> m (PrimArray a)
616+generatePrimArrayP sz f = do
617+ marr <- newPrimArray sz
618+ let go !ix = if ix < sz
619+ then do
620+ b <- f ix
621+ writePrimArray marr ix b
622+ go (ix + 1)
623+ else return ()
624+ go 0
625+ unsafeFreezePrimArray marr
626+
627+-- | Execute the monadic action the given number of times and store the
628+-- results in a primitive array.
629+{-# INLINE replicatePrimArrayP #-}
630+replicatePrimArrayP :: (PrimMonad m, Prim a)
631+ => Int
632+ -> m a
633+ -> m (PrimArray a)
634+replicatePrimArrayP sz f = do
635+ marr <- newPrimArray sz
636+ let go !ix = if ix < sz
637+ then do
638+ b <- f
639+ writePrimArray marr ix b
640+ go (ix + 1)
641+ else return ()
642+ go 0
643+ unsafeFreezePrimArray marr
644+
645+
646+-- | Map over the elements of a primitive array.
647+{-# INLINE mapPrimArray #-}
648+mapPrimArray :: (Prim a, Prim b)
649+ => (a -> b)
650+ -> PrimArray a
651+ -> PrimArray b
652+mapPrimArray f arr = runST $ do
653+ let !sz = sizeofPrimArray arr
654+ marr <- newPrimArray sz
655+ let go !ix = if ix < sz
656+ then do
657+ let b = f (indexPrimArray arr ix)
658+ writePrimArray marr ix b
659+ go (ix + 1)
660+ else return ()
661+ go 0
662+ unsafeFreezePrimArray marr
663+
664+-- | Indexed map over the elements of a primitive array.
665+{-# INLINE imapPrimArray #-}
666+imapPrimArray :: (Prim a, Prim b)
667+ => (Int -> a -> b)
668+ -> PrimArray a
669+ -> PrimArray b
670+imapPrimArray f arr = runST $ do
671+ let !sz = sizeofPrimArray arr
672+ marr <- newPrimArray sz
673+ let go !ix = if ix < sz
674+ then do
675+ let b = f ix (indexPrimArray arr ix)
676+ writePrimArray marr ix b
677+ go (ix + 1)
678+ else return ()
679+ go 0
680+ unsafeFreezePrimArray marr
681+
682+-- | Filter elements of a primitive array according to a predicate.
683+{-# INLINE filterPrimArray #-}
684+filterPrimArray :: Prim a
685+ => (a -> Bool)
686+ -> PrimArray a
687+ -> PrimArray a
688+filterPrimArray p arr = runST $ do
689+ let !sz = sizeofPrimArray arr
690+ marr <- newPrimArray sz
691+ let go !ixSrc !ixDst = if ixSrc < sz
692+ then do
693+ let !a = indexPrimArray arr ixSrc
694+ if p a
695+ then do
696+ writePrimArray marr ixDst a
697+ go (ixSrc + 1) (ixDst + 1)
698+ else go (ixSrc + 1) ixDst
699+ else return ixDst
700+ dstLen <- go 0 0
701+ marr' <- resizeMutablePrimArray marr dstLen
702+ unsafeFreezePrimArray marr'
703+
704+-- | Filter the primitive array, keeping the elements for which the monadic
705+-- predicate evaluates true.
706+filterPrimArrayA ::
707+ (Applicative f, Prim a)
708+ => (a -> f Bool) -- ^ mapping function
709+ -> PrimArray a -- ^ primitive array
710+ -> f (PrimArray a)
711+filterPrimArrayA f = \ !ary ->
712+ let
713+ !len = sizeofPrimArray ary
714+ go !ixSrc
715+ | ixSrc == len = pure $ IxSTA $ \ixDst _ -> return ixDst
716+ | otherwise = let x = indexPrimArray ary ixSrc in
717+ liftA2
718+ (\keep (IxSTA m) -> IxSTA $ \ixDst mary -> if keep
719+ then writePrimArray (MutablePrimArray mary) ixDst x >> m (ixDst + 1) mary
720+ else m ixDst mary
721+ )
722+ (f x)
723+ (go (ixSrc + 1))
724+ in if len == 0
725+ then pure emptyPrimArray
726+ else runIxSTA len <$> go 0
727+
728+-- | Map over the primitive array, keeping the elements for which the applicative
729+-- predicate provides a 'Just'.
730+mapMaybePrimArrayA ::
731+ (Applicative f, Prim a, Prim b)
732+ => (a -> f (Maybe b)) -- ^ mapping function
733+ -> PrimArray a -- ^ primitive array
734+ -> f (PrimArray b)
735+mapMaybePrimArrayA f = \ !ary ->
736+ let
737+ !len = sizeofPrimArray ary
738+ go !ixSrc
739+ | ixSrc == len = pure $ IxSTA $ \ixDst _ -> return ixDst
740+ | otherwise = let x = indexPrimArray ary ixSrc in
741+ liftA2
742+ (\mb (IxSTA m) -> IxSTA $ \ixDst mary -> case mb of
743+ Just b -> writePrimArray (MutablePrimArray mary) ixDst b >> m (ixDst + 1) mary
744+ Nothing -> m ixDst mary
745+ )
746+ (f x)
747+ (go (ixSrc + 1))
748+ in if len == 0
749+ then pure emptyPrimArray
750+ else runIxSTA len <$> go 0
751+
752+-- | Map over a primitive array, optionally discarding some elements. This
753+-- has the same behavior as @Data.Maybe.mapMaybe@.
754+{-# INLINE mapMaybePrimArray #-}
755+mapMaybePrimArray :: (Prim a, Prim b)
756+ => (a -> Maybe b)
757+ -> PrimArray a
758+ -> PrimArray b
759+mapMaybePrimArray p arr = runST $ do
760+ let !sz = sizeofPrimArray arr
761+ marr <- newPrimArray sz
762+ let go !ixSrc !ixDst = if ixSrc < sz
763+ then do
764+ let !a = indexPrimArray arr ixSrc
765+ case p a of
766+ Just b -> do
767+ writePrimArray marr ixDst b
768+ go (ixSrc + 1) (ixDst + 1)
769+ Nothing -> go (ixSrc + 1) ixDst
770+ else return ixDst
771+ dstLen <- go 0 0
772+ marr' <- resizeMutablePrimArray marr dstLen
773+ unsafeFreezePrimArray marr'
774+
775+
776+-- | Traverse a primitive array. The traversal performs all of the applicative
777+-- effects /before/ forcing the resulting values and writing them to the new
778+-- primitive array. Consequently:
779+--
780+-- >>> traversePrimArray (\x -> print x $> bool x undefined (x == 2)) (fromList [1, 2, 3 :: Int])
781+-- 1
782+-- 2
783+-- 3
784+-- *** Exception: Prelude.undefined
785+--
786+-- The function 'traversePrimArrayP' always outperforms this function, but it
787+-- requires a 'PrimMonad' constraint, and it forces the values as
788+-- it performs the effects.
789+traversePrimArray ::
790+ (Applicative f, Prim a, Prim b)
791+ => (a -> f b) -- ^ mapping function
792+ -> PrimArray a -- ^ primitive array
793+ -> f (PrimArray b)
794+traversePrimArray f = \ !ary ->
795+ let
796+ !len = sizeofPrimArray ary
797+ go !i
798+ | i == len = pure $ STA $ \mary -> unsafeFreezePrimArray (MutablePrimArray mary)
799+ | x <- indexPrimArray ary i
800+ = liftA2 (\b (STA m) -> STA $ \mary ->
801+ writePrimArray (MutablePrimArray mary) i b >> m mary)
802+ (f x) (go (i + 1))
803+ in if len == 0
804+ then pure emptyPrimArray
805+ else runSTA len <$> go 0
806+
807+-- | Traverse a primitive array with the index of each element.
808+itraversePrimArray ::
809+ (Applicative f, Prim a, Prim b)
810+ => (Int -> a -> f b)
811+ -> PrimArray a
812+ -> f (PrimArray b)
813+itraversePrimArray f = \ !ary ->
814+ let
815+ !len = sizeofPrimArray ary
816+ go !i
817+ | i == len = pure $ STA $ \mary -> unsafeFreezePrimArray (MutablePrimArray mary)
818+ | x <- indexPrimArray ary i
819+ = liftA2 (\b (STA m) -> STA $ \mary ->
820+ writePrimArray (MutablePrimArray mary) i b >> m mary)
821+ (f i x) (go (i + 1))
822+ in if len == 0
823+ then pure emptyPrimArray
824+ else runSTA len <$> go 0
825+
826+-- | Traverse a primitive array with the indices. The traversal forces the
827+-- resulting values and writes them to the new primitive array as it performs
828+-- the monadic effects.
829+{-# INLINE itraversePrimArrayP #-}
830+itraversePrimArrayP :: (Prim a, Prim b, PrimMonad m)
831+ => (Int -> a -> m b)
832+ -> PrimArray a
833+ -> m (PrimArray b)
834+itraversePrimArrayP f arr = do
835+ let !sz = sizeofPrimArray arr
836+ marr <- newPrimArray sz
837+ let go !ix
838+ | ix < sz = do
839+ writePrimArray marr ix =<< f ix (indexPrimArray arr ix)
840+ go (ix + 1)
841+ | otherwise = return ()
842+ go 0
843+ unsafeFreezePrimArray marr
844+
845+-- | Generate a primitive array.
846+{-# INLINE generatePrimArray #-}
847+generatePrimArray :: Prim a
848+ => Int -- ^ length
849+ -> (Int -> a) -- ^ element from index
850+ -> PrimArray a
851+generatePrimArray len f = runST $ do
852+ marr <- newPrimArray len
853+ let go !ix = if ix < len
854+ then do
855+ writePrimArray marr ix (f ix)
856+ go (ix + 1)
857+ else return ()
858+ go 0
859+ unsafeFreezePrimArray marr
860+
861+-- | Create a primitive array by copying the element the given
862+-- number of times.
863+{-# INLINE replicatePrimArray #-}
864+replicatePrimArray :: Prim a
865+ => Int -- ^ length
866+ -> a -- ^ element
867+ -> PrimArray a
868+replicatePrimArray len a = runST $ do
869+ marr <- newPrimArray len
870+ setPrimArray marr 0 len a
871+ unsafeFreezePrimArray marr
872+
873+-- | Generate a primitive array by evaluating the applicative generator
874+-- function at each index.
875+{-# INLINE generatePrimArrayA #-}
876+generatePrimArrayA ::
877+ (Applicative f, Prim a)
878+ => Int -- ^ length
879+ -> (Int -> f a) -- ^ element from index
880+ -> f (PrimArray a)
881+generatePrimArrayA len f =
882+ let
883+ go !i
884+ | i == len = pure $ STA $ \mary -> unsafeFreezePrimArray (MutablePrimArray mary)
885+ | otherwise
886+ = liftA2 (\b (STA m) -> STA $ \mary ->
887+ writePrimArray (MutablePrimArray mary) i b >> m mary)
888+ (f i) (go (i + 1))
889+ in if len == 0
890+ then pure emptyPrimArray
891+ else runSTA len <$> go 0
892+
893+-- | Execute the applicative action the given number of times and store the
894+-- results in a vector.
895+{-# INLINE replicatePrimArrayA #-}
896+replicatePrimArrayA ::
897+ (Applicative f, Prim a)
898+ => Int -- ^ length
899+ -> f a -- ^ applicative element producer
900+ -> f (PrimArray a)
901+replicatePrimArrayA len f =
902+ let
903+ go !i
904+ | i == len = pure $ STA $ \mary -> unsafeFreezePrimArray (MutablePrimArray mary)
905+ | otherwise
906+ = liftA2 (\b (STA m) -> STA $ \mary ->
907+ writePrimArray (MutablePrimArray mary) i b >> m mary)
908+ f (go (i + 1))
909+ in if len == 0
910+ then pure emptyPrimArray
911+ else runSTA len <$> go 0
912+
913+-- | Traverse the primitive array, discarding the results. There
914+-- is no 'PrimMonad' variant of this function since it would not provide
915+-- any performance benefit.
916+traversePrimArray_ ::
917+ (Applicative f, Prim a)
918+ => (a -> f b)
919+ -> PrimArray a
920+ -> f ()
921+traversePrimArray_ f a = go 0 where
922+ !sz = sizeofPrimArray a
923+ go !ix = if ix < sz
924+ then f (indexPrimArray a ix) *> go (ix + 1)
925+ else pure ()
926+
927+-- | Traverse the primitive array with the indices, discarding the results.
928+-- There is no 'PrimMonad' variant of this function since it would not
929+-- provide any performance benefit.
930+itraversePrimArray_ ::
931+ (Applicative f, Prim a)
932+ => (Int -> a -> f b)
933+ -> PrimArray a
934+ -> f ()
935+itraversePrimArray_ f a = go 0 where
936+ !sz = sizeofPrimArray a
937+ go !ix = if ix < sz
938+ then f ix (indexPrimArray a ix) *> go (ix + 1)
939+ else pure ()
940+
941+newtype IxSTA a = IxSTA {_runIxSTA :: forall s. Int -> MutableByteArray# s -> ST s Int}
942+
943+runIxSTA :: forall a. Prim a
944+ => Int -- maximum possible size
945+ -> IxSTA a
946+ -> PrimArray a
947+runIxSTA !szUpper = \ (IxSTA m) -> runST $ do
948+ ar :: MutablePrimArray s a <- newPrimArray szUpper
949+ sz <- m 0 (unMutablePrimArray ar)
950+ ar' <- resizeMutablePrimArray ar sz
951+ unsafeFreezePrimArray ar'
952+{-# INLINE runIxSTA #-}
953+
954+newtype STA a = STA {_runSTA :: forall s. MutableByteArray# s -> ST s (PrimArray a)}
955+
956+runSTA :: forall a. Prim a => Int -> STA a -> PrimArray a
957+runSTA !sz = \ (STA m) -> runST $ newPrimArray sz >>= \ (ar :: MutablePrimArray s a) -> m (unMutablePrimArray ar)
958+{-# INLINE runSTA #-}
959+
960+unMutablePrimArray :: MutablePrimArray s a -> MutableByteArray# s
961+unMutablePrimArray (MutablePrimArray m) = m
962+
963+{- $effectfulMapCreate
964+The naming conventions adopted in this section are explained in the
965+documentation of the @Data.Primitive@ module.
966+-}
src/Streamly/Internal/Data/SmallArray/Types.hsnew file+973
@@ -0,0 +1,973 @@
1+{-# LANGUAGE CPP #-}
2+{-# LANGUAGE MagicHash #-}
3+{-# LANGUAGE RankNTypes #-}
4+{-# LANGUAGE TypeFamilies #-}
5+{-# LANGUAGE UnboxedTuples #-}
6+{-# LANGUAGE DeriveTraversable #-}
7+{-# LANGUAGE DeriveDataTypeable #-}
8+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
9+{-# LANGUAGE BangPatterns #-}
10+
11+-- |
12+-- Module : Data.Primitive.SmallArray
13+-- Copyright: (c) 2015 Dan Doel
14+-- License: BSD3
15+--
16+-- Maintainer: libraries@haskell.org
17+-- Portability: non-portable
18+--
19+-- Small arrays are boxed (im)mutable arrays.
20+--
21+-- The underlying structure of the 'Array' type contains a card table, allowing
22+-- segments of the array to be marked as having been mutated. This allows the
23+-- garbage collector to only re-traverse segments of the array that have been
24+-- marked during certain phases, rather than having to traverse the entire
25+-- array.
26+--
27+-- 'SmallArray' lacks this table. This means that it takes up less memory and
28+-- has slightly faster writes. It is also more efficient during garbage
29+-- collection so long as the card table would have a single entry covering the
30+-- entire array. These advantages make them suitable for use as arrays that are
31+-- known to be small.
32+--
33+-- The card size is 128, so for uses much larger than that, 'Array' would likely
34+-- be superior.
35+--
36+-- The underlying type, 'SmallArray#', was introduced in GHC 7.10, so prior to
37+-- that version, this module simply implements small arrays as 'Array'.
38+
39+module Data.Primitive.SmallArray
40+ ( SmallArray(..)
41+ , SmallMutableArray(..)
42+ , newSmallArray
43+ , readSmallArray
44+ , writeSmallArray
45+ , copySmallArray
46+ , copySmallMutableArray
47+ , indexSmallArray
48+ , indexSmallArrayM
49+ , indexSmallArray##
50+ , cloneSmallArray
51+ , cloneSmallMutableArray
52+ , freezeSmallArray
53+ , unsafeFreezeSmallArray
54+ , thawSmallArray
55+ , runSmallArray
56+ , unsafeThawSmallArray
57+ , sizeofSmallArray
58+ , sizeofSmallMutableArray
59+ , smallArrayFromList
60+ , smallArrayFromListN
61+ , mapSmallArray'
62+ , traverseSmallArrayP
63+ ) where
64+
65+
66+#if (__GLASGOW_HASKELL__ >= 710)
67+#define HAVE_SMALL_ARRAY 1
68+#endif
69+
70+#if MIN_VERSION_base(4,7,0)
71+import GHC.Exts hiding (toList)
72+import qualified GHC.Exts
73+#endif
74+
75+import Control.Applicative
76+import Control.Monad
77+import qualified Control.Monad.Fail as Fail
78+import Control.Monad.Fix
79+import Control.Monad.Primitive
80+import Control.Monad.ST
81+import Control.Monad.Zip
82+import Data.Data
83+import Data.Foldable as Foldable
84+import Data.Functor.Identity
85+#if !(MIN_VERSION_base(4,10,0))
86+import Data.Monoid
87+#endif
88+#if MIN_VERSION_base(4,9,0)
89+import qualified GHC.ST as GHCST
90+import qualified Data.Semigroup as Sem
91+#endif
92+import Text.ParserCombinators.ReadP
93+#if MIN_VERSION_base(4,10,0)
94+import GHC.Exts (runRW#)
95+#elif MIN_VERSION_base(4,9,0)
96+import GHC.Base (runRW#)
97+#endif
98+
99+#if !(HAVE_SMALL_ARRAY)
100+import Data.Primitive.Array
101+import Data.Traversable
102+import qualified Data.Primitive.Array as Array
103+#endif
104+
105+#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,4,0)
106+import Data.Functor.Classes (Eq1(..),Ord1(..),Show1(..),Read1(..))
107+#endif
108+
109+#if HAVE_SMALL_ARRAY
110+data SmallArray a = SmallArray (SmallArray# a)
111+ deriving Typeable
112+#else
113+newtype SmallArray a = SmallArray (Array a) deriving
114+ ( Eq
115+ , Ord
116+ , Show
117+ , Read
118+ , Foldable
119+ , Traversable
120+ , Functor
121+ , Applicative
122+ , Alternative
123+ , Monad
124+ , MonadPlus
125+ , MonadZip
126+ , MonadFix
127+ , Monoid
128+ , Typeable
129+#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,4,0)
130+ , Eq1
131+ , Ord1
132+ , Show1
133+ , Read1
134+#endif
135+ )
136+
137+#if MIN_VERSION_base(4,7,0)
138+instance IsList (SmallArray a) where
139+ type Item (SmallArray a) = a
140+ fromListN n l = SmallArray (fromListN n l)
141+ fromList l = SmallArray (fromList l)
142+ toList a = Foldable.toList a
143+#endif
144+#endif
145+
146+#if HAVE_SMALL_ARRAY
147+data SmallMutableArray s a = SmallMutableArray (SmallMutableArray# s a)
148+ deriving Typeable
149+#else
150+newtype SmallMutableArray s a = SmallMutableArray (MutableArray s a)
151+ deriving (Eq, Typeable)
152+#endif
153+
154+-- | Create a new small mutable array.
155+newSmallArray
156+ :: PrimMonad m
157+ => Int -- ^ size
158+ -> a -- ^ initial contents
159+ -> m (SmallMutableArray (PrimState m) a)
160+#if HAVE_SMALL_ARRAY
161+newSmallArray (I# i#) x = primitive $ \s ->
162+ case newSmallArray# i# x s of
163+ (# s', sma# #) -> (# s', SmallMutableArray sma# #)
164+#else
165+newSmallArray n e = SmallMutableArray `liftM` newArray n e
166+#endif
167+{-# INLINE newSmallArray #-}
168+
169+-- | Read the element at a given index in a mutable array.
170+readSmallArray
171+ :: PrimMonad m
172+ => SmallMutableArray (PrimState m) a -- ^ array
173+ -> Int -- ^ index
174+ -> m a
175+#if HAVE_SMALL_ARRAY
176+readSmallArray (SmallMutableArray sma#) (I# i#) =
177+ primitive $ readSmallArray# sma# i#
178+#else
179+readSmallArray (SmallMutableArray a) = readArray a
180+#endif
181+{-# INLINE readSmallArray #-}
182+
183+-- | Write an element at the given idex in a mutable array.
184+writeSmallArray
185+ :: PrimMonad m
186+ => SmallMutableArray (PrimState m) a -- ^ array
187+ -> Int -- ^ index
188+ -> a -- ^ new element
189+ -> m ()
190+#if HAVE_SMALL_ARRAY
191+writeSmallArray (SmallMutableArray sma#) (I# i#) x =
192+ primitive_ $ writeSmallArray# sma# i# x
193+#else
194+writeSmallArray (SmallMutableArray a) = writeArray a
195+#endif
196+{-# INLINE writeSmallArray #-}
197+
198+-- | Look up an element in an immutable array.
199+--
200+-- The purpose of returning a result using a monad is to allow the caller to
201+-- avoid retaining references to the array. Evaluating the return value will
202+-- cause the array lookup to be performed, even though it may not require the
203+-- element of the array to be evaluated (which could throw an exception). For
204+-- instance:
205+--
206+-- > data Box a = Box a
207+-- > ...
208+-- >
209+-- > f sa = case indexSmallArrayM sa 0 of
210+-- > Box x -> ...
211+--
212+-- 'x' is not a closure that references 'sa' as it would be if we instead
213+-- wrote:
214+--
215+-- > let x = indexSmallArray sa 0
216+--
217+-- And does not prevent 'sa' from being garbage collected.
218+--
219+-- Note that 'Identity' is not adequate for this use, as it is a newtype, and
220+-- cannot be evaluated without evaluating the element.
221+indexSmallArrayM
222+ :: Monad m
223+ => SmallArray a -- ^ array
224+ -> Int -- ^ index
225+ -> m a
226+#if HAVE_SMALL_ARRAY
227+indexSmallArrayM (SmallArray sa#) (I# i#) =
228+ case indexSmallArray# sa# i# of
229+ (# x #) -> pure x
230+#else
231+indexSmallArrayM (SmallArray a) = indexArrayM a
232+#endif
233+{-# INLINE indexSmallArrayM #-}
234+
235+-- | Look up an element in an immutable array.
236+indexSmallArray
237+ :: SmallArray a -- ^ array
238+ -> Int -- ^ index
239+ -> a
240+#if HAVE_SMALL_ARRAY
241+indexSmallArray sa i = runIdentity $ indexSmallArrayM sa i
242+#else
243+indexSmallArray (SmallArray a) = indexArray a
244+#endif
245+{-# INLINE indexSmallArray #-}
246+
247+-- | Read a value from the immutable array at the given index, returning
248+-- the result in an unboxed unary tuple. This is currently used to implement
249+-- folds.
250+indexSmallArray## :: SmallArray a -> Int -> (# a #)
251+#if HAVE_SMALL_ARRAY
252+indexSmallArray## (SmallArray ary) (I# i) = indexSmallArray# ary i
253+#else
254+indexSmallArray## (SmallArray a) = indexArray## a
255+#endif
256+{-# INLINE indexSmallArray## #-}
257+
258+-- | Create a copy of a slice of an immutable array.
259+cloneSmallArray
260+ :: SmallArray a -- ^ source
261+ -> Int -- ^ offset
262+ -> Int -- ^ length
263+ -> SmallArray a
264+#if HAVE_SMALL_ARRAY
265+cloneSmallArray (SmallArray sa#) (I# i#) (I# j#) =
266+ SmallArray (cloneSmallArray# sa# i# j#)
267+#else
268+cloneSmallArray (SmallArray a) i j = SmallArray $ cloneArray a i j
269+#endif
270+{-# INLINE cloneSmallArray #-}
271+
272+-- | Create a copy of a slice of a mutable array.
273+cloneSmallMutableArray
274+ :: PrimMonad m
275+ => SmallMutableArray (PrimState m) a -- ^ source
276+ -> Int -- ^ offset
277+ -> Int -- ^ length
278+ -> m (SmallMutableArray (PrimState m) a)
279+#if HAVE_SMALL_ARRAY
280+cloneSmallMutableArray (SmallMutableArray sma#) (I# o#) (I# l#) =
281+ primitive $ \s -> case cloneSmallMutableArray# sma# o# l# s of
282+ (# s', smb# #) -> (# s', SmallMutableArray smb# #)
283+#else
284+cloneSmallMutableArray (SmallMutableArray ma) i j =
285+ SmallMutableArray `liftM` cloneMutableArray ma i j
286+#endif
287+{-# INLINE cloneSmallMutableArray #-}
288+
289+-- | Create an immutable array corresponding to a slice of a mutable array.
290+--
291+-- This operation copies the portion of the array to be frozen.
292+freezeSmallArray
293+ :: PrimMonad m
294+ => SmallMutableArray (PrimState m) a -- ^ source
295+ -> Int -- ^ offset
296+ -> Int -- ^ length
297+ -> m (SmallArray a)
298+#if HAVE_SMALL_ARRAY
299+freezeSmallArray (SmallMutableArray sma#) (I# i#) (I# j#) =
300+ primitive $ \s -> case freezeSmallArray# sma# i# j# s of
301+ (# s', sa# #) -> (# s', SmallArray sa# #)
302+#else
303+freezeSmallArray (SmallMutableArray ma) i j =
304+ SmallArray `liftM` freezeArray ma i j
305+#endif
306+{-# INLINE freezeSmallArray #-}
307+
308+-- | Render a mutable array immutable.
309+--
310+-- This operation performs no copying, so care must be taken not to modify the
311+-- input array after freezing.
312+unsafeFreezeSmallArray
313+ :: PrimMonad m => SmallMutableArray (PrimState m) a -> m (SmallArray a)
314+#if HAVE_SMALL_ARRAY
315+unsafeFreezeSmallArray (SmallMutableArray sma#) =
316+ primitive $ \s -> case unsafeFreezeSmallArray# sma# s of
317+ (# s', sa# #) -> (# s', SmallArray sa# #)
318+#else
319+unsafeFreezeSmallArray (SmallMutableArray ma) =
320+ SmallArray `liftM` unsafeFreezeArray ma
321+#endif
322+{-# INLINE unsafeFreezeSmallArray #-}
323+
324+-- | Create a mutable array corresponding to a slice of an immutable array.
325+--
326+-- This operation copies the portion of the array to be thawed.
327+thawSmallArray
328+ :: PrimMonad m
329+ => SmallArray a -- ^ source
330+ -> Int -- ^ offset
331+ -> Int -- ^ length
332+ -> m (SmallMutableArray (PrimState m) a)
333+#if HAVE_SMALL_ARRAY
334+thawSmallArray (SmallArray sa#) (I# o#) (I# l#) =
335+ primitive $ \s -> case thawSmallArray# sa# o# l# s of
336+ (# s', sma# #) -> (# s', SmallMutableArray sma# #)
337+#else
338+thawSmallArray (SmallArray a) off len =
339+ SmallMutableArray `liftM` thawArray a off len
340+#endif
341+{-# INLINE thawSmallArray #-}
342+
343+-- | Render an immutable array mutable.
344+--
345+-- This operation performs no copying, so care must be taken with its use.
346+unsafeThawSmallArray
347+ :: PrimMonad m => SmallArray a -> m (SmallMutableArray (PrimState m) a)
348+#if HAVE_SMALL_ARRAY
349+unsafeThawSmallArray (SmallArray sa#) =
350+ primitive $ \s -> case unsafeThawSmallArray# sa# s of
351+ (# s', sma# #) -> (# s', SmallMutableArray sma# #)
352+#else
353+unsafeThawSmallArray (SmallArray a) = SmallMutableArray `liftM` unsafeThawArray a
354+#endif
355+{-# INLINE unsafeThawSmallArray #-}
356+
357+-- | Copy a slice of an immutable array into a mutable array.
358+copySmallArray
359+ :: PrimMonad m
360+ => SmallMutableArray (PrimState m) a -- ^ destination
361+ -> Int -- ^ destination offset
362+ -> SmallArray a -- ^ source
363+ -> Int -- ^ source offset
364+ -> Int -- ^ length
365+ -> m ()
366+#if HAVE_SMALL_ARRAY
367+copySmallArray
368+ (SmallMutableArray dst#) (I# do#) (SmallArray src#) (I# so#) (I# l#) =
369+ primitive_ $ copySmallArray# src# so# dst# do# l#
370+#else
371+copySmallArray (SmallMutableArray dst) i (SmallArray src) = copyArray dst i src
372+#endif
373+{-# INLINE copySmallArray #-}
374+
375+-- | Copy a slice of one mutable array into another.
376+copySmallMutableArray
377+ :: PrimMonad m
378+ => SmallMutableArray (PrimState m) a -- ^ destination
379+ -> Int -- ^ destination offset
380+ -> SmallMutableArray (PrimState m) a -- ^ source
381+ -> Int -- ^ source offset
382+ -> Int -- ^ length
383+ -> m ()
384+#if HAVE_SMALL_ARRAY
385+copySmallMutableArray
386+ (SmallMutableArray dst#) (I# do#)
387+ (SmallMutableArray src#) (I# so#)
388+ (I# l#) =
389+ primitive_ $ copySmallMutableArray# src# so# dst# do# l#
390+#else
391+copySmallMutableArray (SmallMutableArray dst) i (SmallMutableArray src) =
392+ copyMutableArray dst i src
393+#endif
394+{-# INLINE copySmallMutableArray #-}
395+
396+sizeofSmallArray :: SmallArray a -> Int
397+#if HAVE_SMALL_ARRAY
398+sizeofSmallArray (SmallArray sa#) = I# (sizeofSmallArray# sa#)
399+#else
400+sizeofSmallArray (SmallArray a) = sizeofArray a
401+#endif
402+{-# INLINE sizeofSmallArray #-}
403+
404+sizeofSmallMutableArray :: SmallMutableArray s a -> Int
405+#if HAVE_SMALL_ARRAY
406+sizeofSmallMutableArray (SmallMutableArray sa#) =
407+ I# (sizeofSmallMutableArray# sa#)
408+#else
409+sizeofSmallMutableArray (SmallMutableArray ma) = sizeofMutableArray ma
410+#endif
411+{-# INLINE sizeofSmallMutableArray #-}
412+
413+-- | This is the fastest, most straightforward way to traverse
414+-- an array, but it only works correctly with a sufficiently
415+-- "affine" 'PrimMonad' instance. In particular, it must only produce
416+-- *one* result array. 'Control.Monad.Trans.List.ListT'-transformed
417+-- monads, for example, will not work right at all.
418+traverseSmallArrayP
419+ :: PrimMonad m
420+ => (a -> m b)
421+ -> SmallArray a
422+ -> m (SmallArray b)
423+#if HAVE_SMALL_ARRAY
424+traverseSmallArrayP f = \ !ary ->
425+ let
426+ !sz = sizeofSmallArray ary
427+ go !i !mary
428+ | i == sz
429+ = unsafeFreezeSmallArray mary
430+ | otherwise
431+ = do
432+ a <- indexSmallArrayM ary i
433+ b <- f a
434+ writeSmallArray mary i b
435+ go (i + 1) mary
436+ in do
437+ mary <- newSmallArray sz badTraverseValue
438+ go 0 mary
439+#else
440+traverseSmallArrayP f (SmallArray ar) = SmallArray `liftM` traverseArrayP f ar
441+#endif
442+{-# INLINE traverseSmallArrayP #-}
443+
444+-- | Strict map over the elements of the array.
445+mapSmallArray' :: (a -> b) -> SmallArray a -> SmallArray b
446+#if HAVE_SMALL_ARRAY
447+mapSmallArray' f sa = createSmallArray (length sa) (die "mapSmallArray'" "impossible") $ \smb ->
448+ fix ? 0 $ \go i ->
449+ when (i < length sa) $ do
450+ x <- indexSmallArrayM sa i
451+ let !y = f x
452+ writeSmallArray smb i y *> go (i+1)
453+#else
454+mapSmallArray' f (SmallArray ar) = SmallArray (mapArray' f ar)
455+#endif
456+{-# INLINE mapSmallArray' #-}
457+
458+#ifndef HAVE_SMALL_ARRAY
459+runSmallArray
460+ :: (forall s. ST s (SmallMutableArray s a))
461+ -> SmallArray a
462+runSmallArray m = SmallArray $ runArray $
463+ m >>= \(SmallMutableArray mary) -> return mary
464+
465+#elif !MIN_VERSION_base(4,9,0)
466+runSmallArray
467+ :: (forall s. ST s (SmallMutableArray s a))
468+ -> SmallArray a
469+runSmallArray m = runST $ m >>= unsafeFreezeSmallArray
470+
471+#else
472+-- This low-level business is designed to work with GHC's worker-wrapper
473+-- transformation. A lot of the time, we don't actually need an Array
474+-- constructor. By putting it on the outside, and being careful about
475+-- how we special-case the empty array, we can make GHC smarter about this.
476+-- The only downside is that separately created 0-length arrays won't share
477+-- their Array constructors, although they'll share their underlying
478+-- Array#s.
479+runSmallArray
480+ :: (forall s. ST s (SmallMutableArray s a))
481+ -> SmallArray a
482+runSmallArray m = SmallArray (runSmallArray# m)
483+
484+runSmallArray#
485+ :: (forall s. ST s (SmallMutableArray s a))
486+ -> SmallArray# a
487+runSmallArray# m = case runRW# $ \s ->
488+ case unST m s of { (# s', SmallMutableArray mary# #) ->
489+ unsafeFreezeSmallArray# mary# s'} of (# _, ary# #) -> ary#
490+
491+unST :: ST s a -> State# s -> (# State# s, a #)
492+unST (GHCST.ST f) = f
493+
494+#endif
495+
496+#if HAVE_SMALL_ARRAY
497+-- See the comment on runSmallArray for why we use emptySmallArray#.
498+createSmallArray
499+ :: Int
500+ -> a
501+ -> (forall s. SmallMutableArray s a -> ST s ())
502+ -> SmallArray a
503+createSmallArray 0 _ _ = SmallArray (emptySmallArray# (# #))
504+createSmallArray n x f = runSmallArray $ do
505+ mary <- newSmallArray n x
506+ f mary
507+ pure mary
508+
509+emptySmallArray# :: (# #) -> SmallArray# a
510+emptySmallArray# _ = case emptySmallArray of SmallArray ar -> ar
511+{-# NOINLINE emptySmallArray# #-}
512+
513+die :: String -> String -> a
514+die fun problem = error $ "Data.Primitive.SmallArray." ++ fun ++ ": " ++ problem
515+
516+emptySmallArray :: SmallArray a
517+emptySmallArray =
518+ runST $ newSmallArray 0 (die "emptySmallArray" "impossible")
519+ >>= unsafeFreezeSmallArray
520+{-# NOINLINE emptySmallArray #-}
521+
522+
523+infixl 1 ?
524+(?) :: (a -> b -> c) -> (b -> a -> c)
525+(?) = flip
526+{-# INLINE (?) #-}
527+
528+noOp :: a -> ST s ()
529+noOp = const $ pure ()
530+
531+smallArrayLiftEq :: (a -> b -> Bool) -> SmallArray a -> SmallArray b -> Bool
532+smallArrayLiftEq p sa1 sa2 = length sa1 == length sa2 && loop (length sa1 - 1)
533+ where
534+ loop i
535+ | i < 0
536+ = True
537+ | (# x #) <- indexSmallArray## sa1 i
538+ , (# y #) <- indexSmallArray## sa2 i
539+ = p x y && loop (i-1)
540+
541+#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,4,0)
542+-- | @since 0.6.4.0
543+instance Eq1 SmallArray where
544+#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,5,0)
545+ liftEq = smallArrayLiftEq
546+#else
547+ eq1 = smallArrayLiftEq (==)
548+#endif
549+#endif
550+
551+instance Eq a => Eq (SmallArray a) where
552+ sa1 == sa2 = smallArrayLiftEq (==) sa1 sa2
553+
554+instance Eq (SmallMutableArray s a) where
555+ SmallMutableArray sma1# == SmallMutableArray sma2# =
556+ isTrue# (sameSmallMutableArray# sma1# sma2#)
557+
558+smallArrayLiftCompare :: (a -> b -> Ordering) -> SmallArray a -> SmallArray b -> Ordering
559+smallArrayLiftCompare elemCompare a1 a2 = loop 0
560+ where
561+ mn = length a1 `min` length a2
562+ loop i
563+ | i < mn
564+ , (# x1 #) <- indexSmallArray## a1 i
565+ , (# x2 #) <- indexSmallArray## a2 i
566+ = elemCompare x1 x2 `mappend` loop (i+1)
567+ | otherwise = compare (length a1) (length a2)
568+
569+#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,4,0)
570+-- | @since 0.6.4.0
571+instance Ord1 SmallArray where
572+#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,5,0)
573+ liftCompare = smallArrayLiftCompare
574+#else
575+ compare1 = smallArrayLiftCompare compare
576+#endif
577+#endif
578+
579+-- | Lexicographic ordering. Subject to change between major versions.
580+instance Ord a => Ord (SmallArray a) where
581+ compare sa1 sa2 = smallArrayLiftCompare compare sa1 sa2
582+
583+instance Foldable SmallArray where
584+ -- Note: we perform the array lookups eagerly so we won't
585+ -- create thunks to perform lookups even if GHC can't see
586+ -- that the folding function is strict.
587+ foldr f = \z !ary ->
588+ let
589+ !sz = sizeofSmallArray ary
590+ go i
591+ | i == sz = z
592+ | (# x #) <- indexSmallArray## ary i
593+ = f x (go (i+1))
594+ in go 0
595+ {-# INLINE foldr #-}
596+ foldl f = \z !ary ->
597+ let
598+ go i
599+ | i < 0 = z
600+ | (# x #) <- indexSmallArray## ary i
601+ = f (go (i-1)) x
602+ in go (sizeofSmallArray ary - 1)
603+ {-# INLINE foldl #-}
604+ foldr1 f = \ !ary ->
605+ let
606+ !sz = sizeofSmallArray ary - 1
607+ go i =
608+ case indexSmallArray## ary i of
609+ (# x #) | i == sz -> x
610+ | otherwise -> f x (go (i+1))
611+ in if sz < 0
612+ then die "foldr1" "Empty SmallArray"
613+ else go 0
614+ {-# INLINE foldr1 #-}
615+ foldl1 f = \ !ary ->
616+ let
617+ !sz = sizeofSmallArray ary - 1
618+ go i =
619+ case indexSmallArray## ary i of
620+ (# x #) | i == 0 -> x
621+ | otherwise -> f (go (i - 1)) x
622+ in if sz < 0
623+ then die "foldl1" "Empty SmallArray"
624+ else go sz
625+ {-# INLINE foldl1 #-}
626+ foldr' f = \z !ary ->
627+ let
628+ go i !acc
629+ | i == -1 = acc
630+ | (# x #) <- indexSmallArray## ary i
631+ = go (i-1) (f x acc)
632+ in go (sizeofSmallArray ary - 1) z
633+ {-# INLINE foldr' #-}
634+ foldl' f = \z !ary ->
635+ let
636+ !sz = sizeofSmallArray ary
637+ go i !acc
638+ | i == sz = acc
639+ | (# x #) <- indexSmallArray## ary i
640+ = go (i+1) (f acc x)
641+ in go 0 z
642+ {-# INLINE foldl' #-}
643+ null a = sizeofSmallArray a == 0
644+ {-# INLINE null #-}
645+ length = sizeofSmallArray
646+ {-# INLINE length #-}
647+ maximum ary | sz == 0 = die "maximum" "Empty SmallArray"
648+ | (# frst #) <- indexSmallArray## ary 0
649+ = go 1 frst
650+ where
651+ sz = sizeofSmallArray ary
652+ go i !e
653+ | i == sz = e
654+ | (# x #) <- indexSmallArray## ary i
655+ = go (i+1) (max e x)
656+ {-# INLINE maximum #-}
657+ minimum ary | sz == 0 = die "minimum" "Empty SmallArray"
658+ | (# frst #) <- indexSmallArray## ary 0
659+ = go 1 frst
660+ where sz = sizeofSmallArray ary
661+ go i !e
662+ | i == sz = e
663+ | (# x #) <- indexSmallArray## ary i
664+ = go (i+1) (min e x)
665+ {-# INLINE minimum #-}
666+ sum = foldl' (+) 0
667+ {-# INLINE sum #-}
668+ product = foldl' (*) 1
669+ {-# INLINE product #-}
670+
671+newtype STA a = STA {_runSTA :: forall s. SmallMutableArray# s a -> ST s (SmallArray a)}
672+
673+runSTA :: Int -> STA a -> SmallArray a
674+runSTA !sz = \ (STA m) -> runST $ newSmallArray_ sz >>=
675+ \ (SmallMutableArray ar#) -> m ar#
676+{-# INLINE runSTA #-}
677+
678+newSmallArray_ :: Int -> ST s (SmallMutableArray s a)
679+newSmallArray_ !n = newSmallArray n badTraverseValue
680+
681+badTraverseValue :: a
682+badTraverseValue = die "traverse" "bad indexing"
683+{-# NOINLINE badTraverseValue #-}
684+
685+instance Traversable SmallArray where
686+ traverse f = traverseSmallArray f
687+ {-# INLINE traverse #-}
688+
689+traverseSmallArray
690+ :: Applicative f
691+ => (a -> f b) -> SmallArray a -> f (SmallArray b)
692+traverseSmallArray f = \ !ary ->
693+ let
694+ !len = sizeofSmallArray ary
695+ go !i
696+ | i == len
697+ = pure $ STA $ \mary -> unsafeFreezeSmallArray (SmallMutableArray mary)
698+ | (# x #) <- indexSmallArray## ary i
699+ = liftA2 (\b (STA m) -> STA $ \mary ->
700+ writeSmallArray (SmallMutableArray mary) i b >> m mary)
701+ (f x) (go (i + 1))
702+ in if len == 0
703+ then pure emptySmallArray
704+ else runSTA len <$> go 0
705+{-# INLINE [1] traverseSmallArray #-}
706+
707+{-# RULES
708+"traverse/ST" forall (f :: a -> ST s b). traverseSmallArray f = traverseSmallArrayP f
709+"traverse/IO" forall (f :: a -> IO b). traverseSmallArray f = traverseSmallArrayP f
710+"traverse/Id" forall (f :: a -> Identity b). traverseSmallArray f =
711+ (coerce :: (SmallArray a -> SmallArray (Identity b))
712+ -> SmallArray a -> Identity (SmallArray b)) (fmap f)
713+ #-}
714+
715+
716+instance Functor SmallArray where
717+ fmap f sa = createSmallArray (length sa) (die "fmap" "impossible") $ \smb ->
718+ fix ? 0 $ \go i ->
719+ when (i < length sa) $ do
720+ x <- indexSmallArrayM sa i
721+ writeSmallArray smb i (f x) *> go (i+1)
722+ {-# INLINE fmap #-}
723+
724+ x <$ sa = createSmallArray (length sa) x noOp
725+
726+instance Applicative SmallArray where
727+ pure x = createSmallArray 1 x noOp
728+
729+ sa *> sb = createSmallArray (la*lb) (die "*>" "impossible") $ \smb ->
730+ fix ? 0 $ \go i ->
731+ when (i < la) $
732+ copySmallArray smb 0 sb 0 lb *> go (i+1)
733+ where
734+ la = length sa ; lb = length sb
735+
736+ a <* b = createSmallArray (sza*szb) (die "<*" "impossible") $ \ma ->
737+ let fill off i e = when (i < szb) $
738+ writeSmallArray ma (off+i) e >> fill off (i+1) e
739+ go i = when (i < sza) $ do
740+ x <- indexSmallArrayM a i
741+ fill (i*szb) 0 x
742+ go (i+1)
743+ in go 0
744+ where sza = sizeofSmallArray a ; szb = sizeofSmallArray b
745+
746+ ab <*> a = createSmallArray (szab*sza) (die "<*>" "impossible") $ \mb ->
747+ let go1 i = when (i < szab) $
748+ do
749+ f <- indexSmallArrayM ab i
750+ go2 (i*sza) f 0
751+ go1 (i+1)
752+ go2 off f j = when (j < sza) $
753+ do
754+ x <- indexSmallArrayM a j
755+ writeSmallArray mb (off + j) (f x)
756+ go2 off f (j + 1)
757+ in go1 0
758+ where szab = sizeofSmallArray ab ; sza = sizeofSmallArray a
759+
760+instance Alternative SmallArray where
761+ empty = emptySmallArray
762+
763+ sl <|> sr =
764+ createSmallArray (length sl + length sr) (die "<|>" "impossible") $ \sma ->
765+ copySmallArray sma 0 sl 0 (length sl)
766+ *> copySmallArray sma (length sl) sr 0 (length sr)
767+
768+ many sa | null sa = pure []
769+ | otherwise = die "many" "infinite arrays are not well defined"
770+
771+ some sa | null sa = emptySmallArray
772+ | otherwise = die "some" "infinite arrays are not well defined"
773+
774+data ArrayStack a
775+ = PushArray !(SmallArray a) !(ArrayStack a)
776+ | EmptyStack
777+-- TODO: This isn't terribly efficient. It would be better to wrap
778+-- ArrayStack with a type like
779+--
780+-- data NES s a = NES !Int !(SmallMutableArray s a) !(ArrayStack a)
781+--
782+-- We'd copy incoming arrays into the mutable array until we would
783+-- overflow it. Then we'd freeze it, push it on the stack, and continue.
784+-- Any sufficiently large incoming arrays would go straight on the stack.
785+-- Such a scheme would make the stack much more compact in the case
786+-- of many small arrays.
787+
788+instance Monad SmallArray where
789+ return = pure
790+ (>>) = (*>)
791+
792+ sa >>= f = collect 0 EmptyStack (la-1)
793+ where
794+ la = length sa
795+ collect sz stk i
796+ | i < 0 = createSmallArray sz (die ">>=" "impossible") $ fill 0 stk
797+ | (# x #) <- indexSmallArray## sa i
798+ , let sb = f x
799+ lsb = length sb
800+ -- If we don't perform this check, we could end up allocating
801+ -- a stack full of empty arrays if someone is filtering most
802+ -- things out. So we refrain from pushing empty arrays.
803+ = if lsb == 0
804+ then collect sz stk (i-1)
805+ else collect (sz + lsb) (PushArray sb stk) (i-1)
806+
807+ fill _ EmptyStack _ = return ()
808+ fill off (PushArray sb sbs) smb =
809+ copySmallArray smb off sb 0 (length sb)
810+ *> fill (off + length sb) sbs smb
811+
812+#if !(MIN_VERSION_base(4,13,0))
813+ fail = Fail.fail
814+#endif
815+
816+instance Fail.MonadFail SmallArray where
817+ fail _ = emptySmallArray
818+
819+instance MonadPlus SmallArray where
820+ mzero = empty
821+ mplus = (<|>)
822+
823+zipW :: String -> (a -> b -> c) -> SmallArray a -> SmallArray b -> SmallArray c
824+zipW nm = \f sa sb -> let mn = length sa `min` length sb in
825+ createSmallArray mn (die nm "impossible") $ \mc ->
826+ fix ? 0 $ \go i -> when (i < mn) $ do
827+ x <- indexSmallArrayM sa i
828+ y <- indexSmallArrayM sb i
829+ writeSmallArray mc i (f x y)
830+ go (i+1)
831+{-# INLINE zipW #-}
832+
833+instance MonadZip SmallArray where
834+ mzip = zipW "mzip" (,)
835+ mzipWith = zipW "mzipWith"
836+ {-# INLINE mzipWith #-}
837+ munzip sab = runST $ do
838+ let sz = length sab
839+ sma <- newSmallArray sz $ die "munzip" "impossible"
840+ smb <- newSmallArray sz $ die "munzip" "impossible"
841+ fix ? 0 $ \go i ->
842+ when (i < sz) $ case indexSmallArray sab i of
843+ (x, y) -> do writeSmallArray sma i x
844+ writeSmallArray smb i y
845+ go $ i+1
846+ (,) <$> unsafeFreezeSmallArray sma
847+ <*> unsafeFreezeSmallArray smb
848+
849+instance MonadFix SmallArray where
850+ mfix f = createSmallArray (sizeofSmallArray (f err))
851+ (die "mfix" "impossible") $ flip fix 0 $
852+ \r !i !mary -> when (i < sz) $ do
853+ writeSmallArray mary i (fix (\xi -> f xi `indexSmallArray` i))
854+ r (i + 1) mary
855+ where
856+ sz = sizeofSmallArray (f err)
857+ err = error "mfix for Data.Primitive.SmallArray applied to strict function."
858+
859+#if MIN_VERSION_base(4,9,0)
860+-- | @since 0.6.3.0
861+instance Sem.Semigroup (SmallArray a) where
862+ (<>) = (<|>)
863+ sconcat = mconcat . toList
864+#endif
865+
866+instance Monoid (SmallArray a) where
867+ mempty = empty
868+#if !(MIN_VERSION_base(4,11,0))
869+ mappend = (<|>)
870+#endif
871+ mconcat l = createSmallArray n (die "mconcat" "impossible") $ \ma ->
872+ let go !_ [ ] = return ()
873+ go off (a:as) =
874+ copySmallArray ma off a 0 (sizeofSmallArray a) >> go (off + sizeofSmallArray a) as
875+ in go 0 l
876+ where n = sum . fmap length $ l
877+
878+instance IsList (SmallArray a) where
879+ type Item (SmallArray a) = a
880+ fromListN = smallArrayFromListN
881+ fromList = smallArrayFromList
882+ toList = Foldable.toList
883+
884+smallArrayLiftShowsPrec :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> Int -> SmallArray a -> ShowS
885+smallArrayLiftShowsPrec elemShowsPrec elemListShowsPrec p sa = showParen (p > 10) $
886+ showString "fromListN " . shows (length sa) . showString " "
887+ . listLiftShowsPrec elemShowsPrec elemListShowsPrec 11 (toList sa)
888+
889+-- this need to be included for older ghcs
890+listLiftShowsPrec :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> Int -> [a] -> ShowS
891+listLiftShowsPrec _ sl _ = sl
892+
893+instance Show a => Show (SmallArray a) where
894+ showsPrec p sa = smallArrayLiftShowsPrec showsPrec showList p sa
895+
896+#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,4,0)
897+-- | @since 0.6.4.0
898+instance Show1 SmallArray where
899+#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,5,0)
900+ liftShowsPrec = smallArrayLiftShowsPrec
901+#else
902+ showsPrec1 = smallArrayLiftShowsPrec showsPrec showList
903+#endif
904+#endif
905+
906+smallArrayLiftReadsPrec :: (Int -> ReadS a) -> ReadS [a] -> Int -> ReadS (SmallArray a)
907+smallArrayLiftReadsPrec _ listReadsPrec p = readParen (p > 10) . readP_to_S $ do
908+ () <$ string "fromListN"
909+ skipSpaces
910+ n <- readS_to_P reads
911+ skipSpaces
912+ l <- readS_to_P listReadsPrec
913+ return $ smallArrayFromListN n l
914+
915+instance Read a => Read (SmallArray a) where
916+ readsPrec = smallArrayLiftReadsPrec readsPrec readList
917+
918+#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,4,0)
919+-- | @since 0.6.4.0
920+instance Read1 SmallArray where
921+#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,5,0)
922+ liftReadsPrec = smallArrayLiftReadsPrec
923+#else
924+ readsPrec1 = smallArrayLiftReadsPrec readsPrec readList
925+#endif
926+#endif
927+
928+
929+
930+smallArrayDataType :: DataType
931+smallArrayDataType =
932+ mkDataType "Data.Primitive.SmallArray.SmallArray" [fromListConstr]
933+
934+fromListConstr :: Constr
935+fromListConstr = mkConstr smallArrayDataType "fromList" [] Prefix
936+
937+instance Data a => Data (SmallArray a) where
938+ toConstr _ = fromListConstr
939+ dataTypeOf _ = smallArrayDataType
940+ gunfold k z c = case constrIndex c of
941+ 1 -> k (z fromList)
942+ _ -> die "gunfold" "SmallArray"
943+ gfoldl f z m = z fromList `f` toList m
944+
945+instance (Typeable s, Typeable a) => Data (SmallMutableArray s a) where
946+ toConstr _ = die "toConstr" "SmallMutableArray"
947+ gunfold _ _ = die "gunfold" "SmallMutableArray"
948+ dataTypeOf _ = mkNoRepType "Data.Primitive.SmallArray.SmallMutableArray"
949+#endif
950+
951+-- | Create a 'SmallArray' from a list of a known length. If the length
952+-- of the list does not match the given length, this throws an exception.
953+smallArrayFromListN :: Int -> [a] -> SmallArray a
954+#if HAVE_SMALL_ARRAY
955+smallArrayFromListN n l =
956+ createSmallArray n
957+ (die "smallArrayFromListN" "uninitialized element") $ \sma ->
958+ let go !ix [] = if ix == n
959+ then return ()
960+ else die "smallArrayFromListN" "list length less than specified size"
961+ go !ix (x : xs) = if ix < n
962+ then do
963+ writeSmallArray sma ix x
964+ go (ix+1) xs
965+ else die "smallArrayFromListN" "list length greater than specified size"
966+ in go 0 l
967+#else
968+smallArrayFromListN n l = SmallArray (Array.fromListN n l)
969+#endif
970+
971+-- | Create a 'SmallArray' from a list.
972+smallArrayFromList :: [a] -> SmallArray a
973+smallArrayFromList l = smallArrayFromListN (length l) l