on master help sign in
Add a basic array slicing combinator
commit833ad1f591b305cda89f467053c5843378a4e59c authorAdithya Kumar <adithya@composewell.com> dateSat 3 Apr 2021, 04:46 (6 years ago) parent9b98f41
2 files changed+42−2
src/Streamly/Internal/Data/Array/Foreign.hs+32−2 test/Streamly/Test/Common/Array.hs+10
src/Streamly/Internal/Data/Array/Foreign.hs+32−2
@@ -121,6 +121,8 @@ module Streamly.Internal.Data.Array.Foreign
121121 -- , foldtWith
122122 -- , foldbWith
123123
124+ , unsafeSlice
125+
124126 -- * Immutable Transformations
125127 , streamTransform
126128
@@ -149,6 +151,7 @@ import Data.Word (Word8)
149151-- import Data.Functor.Identity (Identity)
150152import Foreign.C.String (CString)
151153import Foreign.ForeignPtr (withForeignPtr, castForeignPtr)
154+import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
152155import Foreign.Ptr (plusPtr, castPtr)
153156import Foreign.Storable (Storable(..))
154157import Prelude hiding (length, null, last, map, (!!), read, concat)
@@ -175,6 +178,15 @@ import qualified Streamly.Internal.Data.Unfold as Unfold
175178import qualified Streamly.Internal.Data.Producer.Type as Producer
176179import qualified Streamly.Internal.Ring.Foreign as RB
177180
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+
178190-------------------------------------------------------------------------------
179191-- Construction
180192-------------------------------------------------------------------------------
@@ -334,9 +346,27 @@ findIndices = undefined
334346-- Slice and splice
335347-------------------------------------------------------------------------------
336348
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+
337369{-
338−slice :: Int -> Int -> Array a
339−slice begin end arr = undefined
340370
341371splitAt :: Int -> Array a -> (Array a, Array a)
342372splitAt i arr = undefined
test/Streamly/Test/Common/Array.hs+10
@@ -219,6 +219,12 @@ concatArrayW8 =
219219 f2 <- S.toList $ AS.concat $ S.fromList w8ArrList
220220 w8List `shouldBe` f2
221221
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+
222228#endif
223229
224230main :: IO ()
@@ -252,6 +258,10 @@ main =
252258
253259#ifdef TEST_ARRAY
254260 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]
255265 describe "Fold" $ do
256266 prop "lastN : 0 <= n <= len" $ testLastN
257267 describe "lastN boundary conditions" $ do