2{-# LANGUAGE MagicHash #-}
3{-# LANGUAGE UnboxedTuples #-}
8-- Module : Streamly.Internal.Data.Array
9-- Copyright : (c) 2019 Composewell Technologies
11-- License : BSD-3-Clause
12-- Maintainer : streamly@composewell.com
13-- Stability : experimental
16module Streamly.Internal.Data.Array
37import Prelude hiding (foldr, length)
38import Control.DeepSeq (NFData(..))
39import Control.Monad.ST (stToIO, RealWorld)
40import Control.Monad.IO.Class (liftIO, MonadIO)
42import GHC.IO (unsafePerformIO)
43import GHC.Base (Int(..))
44import Data.Functor.Identity (runIdentity)
45import qualified GHC.Exts as Exts
47import Streamly.Internal.Data.Fold.Types (Fold(..))
49import qualified Streamly.Streams.StreamD as D
53 { array# :: Exts.Array# a
56{-# NOINLINE bottomElement #-}
58bottomElement = undefined
60data MutableArray s a =
62 { marray# :: Exts.MutableArray# s a
65{-# INLINE newArray #-}
66newArray :: Int -> a -> ST s (MutableArray s a)
67newArray (I# n#) x = ST
68 (\s# -> case Exts.newArray# n# x s# of
70 let ma = MutableArray marr#
73{-# INLINE writeArray #-}
74writeArray :: MutableArray s a -> Int -> a -> ST s ()
75writeArray marr (I# i#) x =
77 case Exts.writeArray# (marray# marr) i# x s# of
80{-# INLINE freezeArray #-}
81freezeArray :: MutableArray s a -> Int -> Int -> ST s (Array a)
82freezeArray marr (I# start#) (I# len#) =
84 case Exts.freezeArray# (marray# marr) start# len# s# of
85 (# s'#, arr# #) -> (# s'#, Array arr# #))
87{-# INLINE copyMutableArray #-}
88copyMutableArray :: MutableArray s a
91 -- ^ Offset into the source array
93 -- ^ Destination array to copy to
95 -- ^ Offset into the destination array
97 -- ^ Number of elements to copy
99copyMutableArray sourceMarr (I# sourceOffset#) destMarr (I# destOffset#) (I# numElements#) =
101 case Exts.copyMutableArray#
108 s'# -> (# s'#, () #))
110{-# INLINE newArrayIO #-}
111newArrayIO :: Int -> a -> IO (MutableArray RealWorld a)
112newArrayIO i x = stToIO $ newArray i x
114{-# INLINE writeArrayIO #-}
115writeArrayIO :: MutableArray RealWorld a -> Int -> a -> IO ()
116writeArrayIO marr i x = stToIO $ writeArray marr i x
118{-# INLINE freezeArrayIO #-}
119freezeArrayIO :: MutableArray RealWorld a -> Int -> Int -> IO (Array a)
120freezeArrayIO marr i len = stToIO $ freezeArray marr i len
123length :: Array a -> Int
124length arr = I# (Exts.sizeofArray# (array# arr))
126{-# INLINE copyMutableArrayIO #-}
128 MutableArray RealWorld a
130 -> MutableArray RealWorld a
134copyMutableArrayIO sourceMarr sourceOffset destMarr destOffset numElements =
136 copyMutableArray sourceMarr sourceOffset destMarr destOffset numElements
138{-# INLINE_NORMAL toStreamD #-}
139toStreamD :: Monad m => Array a -> D.Stream m a
140toStreamD arr = D.Stream step 0
142 {-# INLINE_LATE step #-}
144 | i == length arr = return D.Stop
147 case Exts.indexArray# (array# arr) i of
148 (# x #) -> D.Yield x ((I# i) + 1)
150{-# INLINE_NORMAL toStreamDRev #-}
151toStreamDRev :: Monad m => Array a -> D.Stream m a
152toStreamDRev arr = D.Stream step (length arr - 1)
154 {-# INLINE_LATE step #-}
156 | i < 0 = return D.Stop
159 case Exts.indexArray# (array# arr) i of
160 (# x #) -> D.Yield x ((I# i) - 1)
162{-# INLINE_NORMAL foldl' #-}
163foldl' :: (b -> a -> b) -> b -> Array a -> b
164foldl' f z arr = runIdentity $ D.foldl' f z $ toStreamD arr
166{-# INLINE_NORMAL foldr #-}
167foldr :: (a -> b -> b) -> b -> Array a -> b
168foldr f z arr = runIdentity $ D.foldr f z $ toStreamD arr
170-- writeN n = S.evertM (fromStreamDN n)
171{-# INLINE_NORMAL writeN #-}
172writeN :: MonadIO m => Int -> Fold m a (Array a)
173writeN limit = Fold step initial extract
176 marr <- liftIO $ newArrayIO limit bottomElement
179 | i == limit = return (marr, i)
181 liftIO $ writeArrayIO marr i x
183 extract (marr, len) = liftIO $ freezeArrayIO marr 0 len
185{-# INLINE_NORMAL write #-}
186write :: MonadIO m => Fold m a (Array a)
187write = 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
204{-# INLINE_NORMAL fromStreamDN #-}
205fromStreamDN :: MonadIO m => Int -> D.Stream m a -> m (Array a)
206fromStreamDN limit str = do
207 marr <- liftIO $ newArrayIO (max limit 0) bottomElement
210 (\i x -> i `seq` (liftIO $ writeArrayIO marr i x) >> return (i + 1))
213 liftIO $ freezeArrayIO marr 0 i
215{-# INLINE fromStreamD #-}
216fromStreamD :: MonadIO m => D.Stream m a -> m (Array a)
217fromStreamD str = D.runFold write str
219{-# INLINABLE fromListN #-}
220fromListN :: Int -> [a] -> Array a
221fromListN n xs = unsafePerformIO $ fromStreamDN n $ D.fromList xs
223{-# INLINABLE fromList #-}
224fromList :: [a] -> Array a
225fromList xs = unsafePerformIO $ fromStreamD $ D.fromList xs
227instance NFData a => NFData (Array a) where
229 rnf = foldl' (\_ x -> rnf x) ()
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list