on 734d2cf help sign in
103 lines 3.7 kB history raw
1#include "inline.hs"
3-- |
4-- Module : Streamly.Internal.Data.Array.Mut
5-- Copyright : (c) 2020 Composewell Technologies
6-- License : BSD-3-Clause
7-- Maintainer : streamly@composewell.com
8-- Stability : experimental
9-- Portability : GHC
10--
11-- Unboxed pinned mutable array type for 'Unboxed' types with an option to use
12-- foreign (non-GHC) memory allocators. Fulfils the following goals:
13--
14-- * Random access (array)
15-- * Efficient storage (unboxed)
16-- * Performance (unboxed access)
17-- * Performance - in-place operations (mutable)
18-- * Performance - GC (pinned, mutable)
19-- * interfacing with OS (pinned)
20-- * Fragmentation control (foreign allocators)
21--
22-- Stream and Fold APIs allow easy, efficient and convenient operations on
23-- arrays.
25module Streamly.Internal.Data.Array.Mut
26 (
27 module Streamly.Internal.Data.Array.Mut.Type
28 , splitOn
29 , genSlicesFromLen
30 , getSlicesFromLen
31 , fromStream
32 )
33where
35import Control.Monad.IO.Class (MonadIO(..))
36import Streamly.Internal.Data.Unboxed (Unbox)
37import Streamly.Internal.Data.Stream (Stream)
38import Streamly.Internal.Data.Unfold.Type (Unfold(..))
40import qualified Streamly.Internal.Data.Stream.StreamD as D
41import qualified Streamly.Internal.Data.Stream.Type as Stream
42import qualified Streamly.Internal.Data.Unfold as Unfold
43-- import qualified Streamly.Internal.Data.Stream.Common as P
45import Prelude hiding (foldr, length, read, splitAt)
46import Streamly.Internal.Data.Array.Mut.Type
48-- | Split the array into a stream of slices using a predicate. The element
49-- matching the predicate is dropped.
50--
51-- /Pre-release/
52{-# INLINE splitOn #-}
53splitOn :: (MonadIO m, Unbox a) =>
54 (a -> Bool) -> Array a -> Stream m (Array a)
55splitOn predicate arr =
56 Stream.fromStreamD
57 $ fmap (\(i, len) -> getSliceUnsafe i len arr)
58 $ D.sliceOnSuffix predicate (toStreamD arr)
60-- | Generate a stream of array slice descriptors ((index, len)) of specified
61-- length from an array, starting from the supplied array index. The last slice
62-- may be shorter than the requested length depending on the array length.
63--
64-- /Pre-release/
65{-# INLINE genSlicesFromLen #-}
66genSlicesFromLen :: forall m a. (Monad m, Unbox a)
67 => Int -- ^ from index
68 -> Int -- ^ length of the slice
69 -> Unfold m (Array a) (Int, Int)
70genSlicesFromLen from len =
71 let fromThenTo n = (from, from + len, n - 1)
72 mkSlice n i = return (i, min len (n - i))
73 in Unfold.lmap length
74 $ Unfold.mapM2 mkSlice
75 $ Unfold.lmap fromThenTo Unfold.enumerateFromThenTo
77-- | Generate a stream of slices of specified length from an array, starting
78-- from the supplied array index. The last slice may be shorter than the
79-- requested length depending on the array length.
80--
81-- /Pre-release/
82{-# INLINE getSlicesFromLen #-}
83getSlicesFromLen :: forall m a. (Monad m, Unbox a)
84 => Int -- ^ from index
85 -> Int -- ^ length of the slice
86 -> Unfold m (Array a) (Array a)
87getSlicesFromLen from len =
88 let mkSlice arr (i, n) = return $ getSliceUnsafe i n arr
89 in Unfold.mapM2 mkSlice (genSlicesFromLen from len)
91-- | Create an 'Array' from a stream. This is useful when we want to create a
92-- single array from a stream of unknown size. 'writeN' is at least twice
93-- as efficient when the size is already known.
94--
95-- Note that if the input stream is too large memory allocation for the array
96-- may fail. When the stream size is not known, `arraysOf` followed by
97-- processing of indvidual arrays in the resulting stream should be preferred.
98--
99-- /Pre-release/
100{-# INLINE fromStream #-}
101fromStream :: (MonadIO m, Unbox a) => Stream m a -> m (Array a)
102fromStream = fromStreamD . Stream.toStreamD
103-- fromStream (Stream m) = P.fold write m