on master help sign in
Remove the use of "length" in some impls

length is costly because of an expensive div operation.

commit92738b9dcff3601eeb48f2ad336d46ac5e9f2fba authorHarendra Kumar <harendra@composewell.com> dateWed 6 Oct 2021, 10:30 (5 years ago) parent0abf713
1 file changed+38−11
src/Streamly/Internal/Data/Array/Foreign.hs+38−11
src/Streamly/Internal/Data/Array/Foreign.hs+38−11
@@ -242,19 +242,38 @@ unsafeRead = Unfold step inject
242242
243243 touch r = IO $ \s -> case touch# r s of s' -> (# s', () #)
244244
245−-- | > null arr = length arr == 0
245+-- |
246+--
247+-- >>> import qualified Streamly.Internal.Data.Array.Foreign.Type as Array
248+-- >>> null arr = Array.byteLength arr == 0
246249--
247250-- /Pre-release/
248251{-# INLINE null #-}
249−null :: Storable a => Array a -> Bool
250−null arr = length arr == 0
252+null :: Array a -> Bool
253+null arr = A.byteLength arr == 0
254+
255+-- | Like 'getIndex' but indexes the array in reverse from the end.
256+--
257+-- /Pre-release/
258+{-# INLINE getIndexRev #-}
259+getIndexRev :: forall a. Storable a => Array a -> Int -> Maybe a
260+getIndexRev arr i =
261+ unsafeInlineIO $
262+ unsafeWithForeignPtr (aStart arr) $ \ptr -> do
263+ let elemSize = sizeOf (undefined :: a)
264+ elemPtr = aEnd arr `plusPtr` negate (elemSize * (i + 1))
265+ if i >= 0 && elemPtr >= ptr
266+ then Just <$> peek elemPtr
267+ else return Nothing
251268
252−-- | > last arr = getIndex arr (length arr - 1)
269+-- |
270+--
271+-- >>> last arr = getIndexRev arr 0
253272--
254273-- /Pre-release/
255274{-# INLINE last #-}
256275last :: Storable a => Array a -> Maybe a
257−last arr = getIndex arr (length arr - 1)
276+last arr = getIndexRev arr 0
258277
259278-------------------------------------------------------------------------------
260279-- Folds with Array as the container
@@ -355,16 +374,22 @@ unsafeSlice start len (Array fp _) =
355374-- Random reads and writes
356375-------------------------------------------------------------------------------
357376
358−-- | /O(1)/ Lookup the element at the given index, starting from 0.
377+-- XXX Change this to a partial function instead of a Maybe type? And use
378+-- MA.getIndex instead.
379+--
380+-- | /O(1)/ Lookup the element at the given index. Index starts from 0.
359381--
360382-- @since 0.8.0
361383{-# INLINE getIndex #-}
362−getIndex :: Storable a => Array a -> Int -> Maybe a
384+getIndex :: forall a. Storable a => Array a -> Int -> Maybe a
363385getIndex arr i =
364− if i < 0 || i > length arr - 1
365− then Nothing
366− else unsafeInlineIO $
367− unsafeWithForeignPtr (aStart arr) $ \p -> Just <$> peekElemOff p i
386+ unsafeInlineIO $
387+ unsafeWithForeignPtr (aStart arr) $ \ptr -> do
388+ let elemSize = sizeOf (undefined :: a)
389+ elemPtr = ptr `plusPtr` (elemSize * i)
390+ if i >= 0 && elemPtr `plusPtr` elemSize <= aEnd arr
391+ then Just <$> peek elemPtr
392+ else return Nothing
368393
369394{-
370395-- | @readSlice arr i count@ streams a slice of the array @arr@ starting
@@ -429,6 +454,8 @@ runPipe :: (MonadIO m, Storable a, Storable b)
429454runPipe f arr = P.runPipe (toArrayMinChunk (length arr)) $ f (A.read arr)
430455-}
431456
457+-- XXX Use byteLength instead of length.
458+--
432459-- | Transform an array into another array using a stream transformation
433460-- operation.
434461--