@@ -1,6 +1,5 @@
1{-# LANGUAGE CPP #-}
1{-# LANGUAGE CPP #-}
2{-# LANGUAGE MagicHash #-}
2{-# LANGUAGE MagicHash #-}
3−{-# LANGUAGE RecordWildCards #-}
4{-# LANGUAGE UnboxedTuples #-}
3{-# LANGUAGE UnboxedTuples #-}
6#include "inline.hs"
5#include "inline.hs"
@@ -20,18 +19,27 @@ module Streamly.Internal.Data.Array
25 , toStreamD
27 , toStreamD
26 , toStreamDRev
28 , toStreamDRev
27 , fromStreamDN
32 , fromStreamDN
31−import Prelude hiding (foldr)
37+import Prelude hiding (foldr, length)
38+import Control.DeepSeq (NFData(..))
32import Control.Monad.ST (stToIO, RealWorld)
39import Control.Monad.ST (stToIO, RealWorld)
33import Control.Monad.IO.Class (liftIO, MonadIO)
40import Control.Monad.IO.Class (liftIO, MonadIO)
34import GHC.ST (ST(..))
41import GHC.ST (ST(..))
42+import GHC.IO (unsafePerformIO)
35import GHC.Base (Int(..))
43import GHC.Base (Int(..))
36import Data.Functor.Identity (runIdentity)
44import Data.Functor.Identity (runIdentity)
37import qualified GHC.Exts as Exts
45import qualified GHC.Exts as Exts
@@ -42,8 +50,7 @@ import qualified Streamly.Streams.StreamD as D
43data Array a =
51data Array a =
45− { aLen :: {-# UNPACK #-} !Int -- Length of the array
46− , aA :: Exts.Array# a
53+ { array# :: Exts.Array# a
49{-# NOINLINE bottomElement #-}
56{-# NOINLINE bottomElement #-}
@@ -75,7 +82,30 @@ freezeArray :: MutableArray s a -> Int -> Int -> ST s (Array a)
75freezeArray marr (I# start#) (I# len#) =
82freezeArray marr (I# start#) (I# len#) =
76 ST (\s# ->
83 ST (\s# ->
77 case Exts.freezeArray# (marray# marr) start# len# s# of
84 case Exts.freezeArray# (marray# marr) start# len# s# of
78− (# s'#, arr# #) -> (# s'#, Array (I# len#) arr# #))
85+ (# s'#, arr# #) -> (# s'#, Array arr# #))
87+{-# INLINE copyMutableArray #-}
88+copyMutableArray :: MutableArray s a
89+ -- ^ The source array
91+ -- ^ Offset into the source array
93+ -- ^ Destination array to copy to
95+ -- ^ Offset into the destination array
97+ -- ^ Number of elements to copy
99+copyMutableArray sourceMarr (I# sourceOffset#) destMarr (I# destOffset#) (I# numElements#) =
101+ case Exts.copyMutableArray#
102+ (marray# sourceMarr)
108+ s'# -> (# s'#, () #))
80{-# INLINE newArrayIO #-}
110{-# INLINE newArrayIO #-}
81newArrayIO :: Int -> a -> IO (MutableArray RealWorld a)
111newArrayIO :: Int -> a -> IO (MutableArray RealWorld a)
@@ -89,28 +119,44 @@ writeArrayIO marr i x = stToIO $ writeArray marr i x
89freezeArrayIO :: MutableArray RealWorld a -> Int -> Int -> IO (Array a)
119freezeArrayIO :: MutableArray RealWorld a -> Int -> Int -> IO (Array a)
90freezeArrayIO marr i len = stToIO $ freezeArray marr i len
120freezeArrayIO marr i len = stToIO $ freezeArray marr i len
122+{-# INLINE length #-}
123+length :: Array a -> Int
124+length arr = I# (Exts.sizeofArray# (array# arr))
126+{-# INLINE copyMutableArrayIO #-}
127+copyMutableArrayIO ::
128+ MutableArray RealWorld a
130+ -> MutableArray RealWorld a
134+copyMutableArrayIO sourceMarr sourceOffset destMarr destOffset numElements =
136+ copyMutableArray sourceMarr sourceOffset destMarr destOffset numElements
92{-# INLINE_NORMAL toStreamD #-}
138{-# INLINE_NORMAL toStreamD #-}
93toStreamD :: Monad m => Array a -> D.Stream m a
139toStreamD :: Monad m => Array a -> D.Stream m a
94−toStreamD Array {..} = D.Stream step 0
140+toStreamD arr = D.Stream step 0
96 {-# INLINE_LATE step #-}
142 {-# INLINE_LATE step #-}
98− | i == aLen = return D.Stop
144+ | i == length arr = return D.Stop
99 step _ (I# i) =
145 step _ (I# i) =
101− case Exts.indexArray# aA i of
147+ case Exts.indexArray# (array# arr) i of
102 (# x #) -> D.Yield x ((I# i) + 1)
148 (# x #) -> D.Yield x ((I# i) + 1)
104{-# INLINE_NORMAL toStreamDRev #-}
150{-# INLINE_NORMAL toStreamDRev #-}
105toStreamDRev :: Monad m => Array a -> D.Stream m a
151toStreamDRev :: Monad m => Array a -> D.Stream m a
106−toStreamDRev Array {..} = D.Stream step (aLen - 1)
152+toStreamDRev arr = D.Stream step (length arr - 1)
108 {-# INLINE_LATE step #-}
154 {-# INLINE_LATE step #-}
110 | i < 0 = return D.Stop
156 | i < 0 = return D.Stop
111 step _ (I# i) =
157 step _ (I# i) =
113− case Exts.indexArray# aA i of
159+ case Exts.indexArray# (array# arr) i of
114 (# x #) -> D.Yield x ((I# i) - 1)
160 (# x #) -> D.Yield x ((I# i) - 1)
116{-# INLINE_NORMAL foldl' #-}
162{-# INLINE_NORMAL foldl' #-}
@@ -127,13 +173,33 @@ writeN :: MonadIO m => Int -> Fold m a (Array a)
127writeN limit = Fold step initial extract
173writeN limit = Fold step initial extract
129 initial = do
175 initial = do
130− marr <- liftIO $ newArrayIO limit bottomElement
176+ marr <- liftIO $ newArrayIO limit bottomElement
131− return (marr, 0)
177+ return (marr, 0)
132− step (marr,i) x | i == limit = return (marr, i)
179+ | i == limit = return (marr, i)
133− | otherwise = do
180+ | otherwise = do
134− liftIO $ writeArrayIO marr i x
181+ liftIO $ writeArrayIO marr i x
135− return (marr, i+1)
182+ return (marr, i + 1)
136− extract (marr,len) = liftIO $ freezeArrayIO marr 0 len
183+ extract (marr, len) = liftIO $ freezeArrayIO marr 0 len
185+{-# INLINE_NORMAL write #-}
186+write :: MonadIO m => Fold m a (Array a)
187+write = Fold step initial extract
190+ marr <- liftIO $ newArrayIO 0 bottomElement
192+ step (marr, i, capacity) x
194+ let newCapacity = max (capacity * 2) 1
195+ in do newMarr <- liftIO $ newArrayIO newCapacity bottomElement
196+ liftIO $ copyMutableArrayIO marr 0 newMarr 0 i
197+ liftIO $ writeArrayIO newMarr i x
198+ return (newMarr, i + 1, newCapacity)
200+ liftIO $ writeArrayIO marr i x
201+ return (marr, i + 1, capacity)
202+ extract (marr, len, _) = liftIO $ freezeArrayIO marr 0 len
138{-# INLINE_NORMAL fromStreamDN #-}
204{-# INLINE_NORMAL fromStreamDN #-}
139fromStreamDN :: MonadIO m => Int -> D.Stream m a -> m (Array a)
205fromStreamDN :: MonadIO m => Int -> D.Stream m a -> m (Array a)
@@ -145,3 +211,19 @@ fromStreamDN limit str = do
146 D.take limit str
212 D.take limit str
147 liftIO $ freezeArrayIO marr 0 i
213 liftIO $ freezeArrayIO marr 0 i
215+{-# INLINE fromStreamD #-}
216+fromStreamD :: MonadIO m => D.Stream m a -> m (Array a)
217+fromStreamD str = D.runFold write str
219+{-# INLINABLE fromListN #-}
220+fromListN :: Int -> [a] -> Array a
221+fromListN n xs = unsafePerformIO $ fromStreamDN n $ D.fromList xs
223+{-# INLINABLE fromList #-}
224+fromList :: [a] -> Array a
225+fromList xs = unsafePerformIO $ fromStreamD $ D.fromList xs
227+instance NFData a => NFData (Array a) where
229+ rnf = foldl' (\_ x -> rnf x) ()