on master help sign in
Add a basic array slicing combinator
833ad1fAdithya Kumar
src/Streamly/Internal/Data/Array/Foreign.hs+32−2
@@ -121,6 +121,8 @@ module Streamly.Internal.Data.Array.Foreign
121 -- , foldtWith
121 -- , foldtWith
122 -- , foldbWith
122 -- , foldbWith
123
123
124+ , unsafeSlice
125+
124 -- * Immutable Transformations
126 -- * Immutable Transformations
125 , streamTransform
127 , streamTransform
126
128
@@ -149,6 +151,7 @@ import Data.Word (Word8)
149-- import Data.Functor.Identity (Identity)
151-- import Data.Functor.Identity (Identity)
150import Foreign.C.String (CString)
152import Foreign.C.String (CString)
151import Foreign.ForeignPtr (withForeignPtr, castForeignPtr)
153import Foreign.ForeignPtr (withForeignPtr, castForeignPtr)
154+import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
152import Foreign.Ptr (plusPtr, castPtr)
155import Foreign.Ptr (plusPtr, castPtr)
153import Foreign.Storable (Storable(..))
156import Foreign.Storable (Storable(..))
154import Prelude hiding (length, null, last, map, (!!), read, concat)
157import Prelude hiding (length, null, last, map, (!!), read, concat)
@@ -175,6 +178,15 @@ import qualified Streamly.Internal.Data.Unfold as Unfold
175import qualified Streamly.Internal.Data.Producer.Type as Producer
178import qualified Streamly.Internal.Data.Producer.Type as Producer
176import qualified Streamly.Internal.Ring.Foreign as RB
179import qualified Streamly.Internal.Ring.Foreign as RB
177
180
181+#if MIN_VERSION_base(4,10,0)
182+import Foreign.ForeignPtr (plusForeignPtr)
183+#else
184+import GHC.Base (Int(..), plusAddr#)
185+import GHC.ForeignPtr (ForeignPtr(..))
186+plusForeignPtr :: ForeignPtr a -> Int -> ForeignPtr b
187+plusForeignPtr (ForeignPtr addr c) (I# d) = ForeignPtr (plusAddr# addr d) c
188+#endif
189+
178-------------------------------------------------------------------------------
190-------------------------------------------------------------------------------
179-- Construction
191-- Construction
180-------------------------------------------------------------------------------
192-------------------------------------------------------------------------------
@@ -334,9 +346,27 @@ findIndices = undefined
334-- Slice and splice
346-- Slice and splice
335-------------------------------------------------------------------------------
347-------------------------------------------------------------------------------
336
348
349+-- | /O(1)/ Slice an array in constant time.
350+--
351+-- Caution: The bounds of the slice are not checked.
352+--
353+-- /Unsafe/
354+--
355+-- /Pre-release/
356+{-# INLINE unsafeSlice #-}
357+unsafeSlice ::
358+ forall a. Storable a
359+ => Int -- ^ starting index
360+ -> Int -- ^ length of the slice
361+ -> Array a
362+ -> Array a
363+unsafeSlice start len (Array fp _) =
364+ let size = sizeOf (undefined :: a)
365+ fp1 = fp `plusForeignPtr` (start * size)
366+ end = unsafeForeignPtrToPtr fp1 `plusPtr` (len * size)
367+ in Array fp1 end
368+
337{-
369{-
338−slice :: Int -> Int -> Array a
339−slice begin end arr = undefined
340
370
341splitAt :: Int -> Array a -> (Array a, Array a)
371splitAt :: Int -> Array a -> (Array a, Array a)
342splitAt i arr = undefined
372splitAt i arr = undefined
test/Streamly/Test/Common/Array.hs+10
@@ -219,6 +219,12 @@ concatArrayW8 =
219 f2 <- S.toList $ AS.concat $ S.fromList w8ArrList
219 f2 <- S.toList $ AS.concat $ S.fromList w8ArrList
220 w8List `shouldBe` f2
220 w8List `shouldBe` f2
221
221
222+unsafeSlice :: Int -> Int -> [Int] -> Bool
223+unsafeSlice i n list =
224+ let lst = take n $ drop i $ list
225+ arr = A.toList $ A.unsafeSlice i n $ A.fromList list
226+ in arr == lst
227+
222#endif
228#endif
223
229
224main :: IO ()
230main :: IO ()
@@ -252,6 +258,10 @@ main =
252
258
253#ifdef TEST_ARRAY
259#ifdef TEST_ARRAY
254 prop "AS.concat . (A.fromList . (:[]) <$>) === id" $ concatArrayW8
260 prop "AS.concat . (A.fromList . (:[]) <$>) === id" $ concatArrayW8
261+ describe "unsafeSlice" $ do
262+ it "partial" $ unsafeSlice 2 4 [1..10]
263+ it "none" $ unsafeSlice 10 0 [1..10]
264+ it "full" $ unsafeSlice 0 10 [1..10]
255 describe "Fold" $ do
265 describe "Fold" $ do
256 prop "lastN : 0 <= n <= len" $ testLastN
266 prop "lastN : 0 <= n <= len" $ testLastN
257 describe "lastN boundary conditions" $ do
267 describe "lastN boundary conditions" $ do