@@ -48,13 +48,15 @@ module Streamly.Internal.Data.Array.Foreign.Mut.Type
4848 , writeWith
4949 , write
5050
51− -- , writeRevN
51+ , writeRevN
5252 -- , writeRev
5353
5454 -- ** From containers
5555 , fromForeignPtrUnsafe
5656 , fromListN
5757 , fromList
58+ , fromListRevN
59+ , fromListRev
5860 , fromStreamDN
5961 , fromStreamD
6062
@@ -265,6 +267,7 @@ import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
265267#ifdef USE_FOREIGN_PTR
266268import qualified Streamly.Internal.Foreign.Malloc as Malloc
267269#endif
270+import qualified Prelude
268271
269272import Prelude hiding
270273 (length, foldr, read, unlines, splitAt, reverse, truncate)
@@ -1901,6 +1904,43 @@ writeNWith alloc n = FL.take n (writeNWithUnsafe alloc n)
19011904writeN :: forall m a. (MonadIO m, Storable a) => Int -> Fold m a (Array a)
19021905writeN = writeNWith newArray
19031906
1907+-- | Like writeNWithUnsafe but writes the array in reverse order.
1908+--
1909+-- /Internal/
1910+{-# INLINE_NORMAL writeRevNWithUnsafe #-}
1911+writeRevNWithUnsafe :: forall m a. (MonadIO m, Storable a)
1912+ => (Int -> m (Array a)) -> Int -> Fold m a (Array a)
1913+writeRevNWithUnsafe alloc n = Fold step initial (return . fromArrayUnsafe)
1914+
1915+ where
1916+
1917+ toArrayUnsafeRev (Array contents _ _ bound) =
1918+ ArrayUnsafe contents bound bound
1919+
1920+ initial = FL.Partial . toArrayUnsafeRev <$> alloc (max n 0)
1921+
1922+ step (ArrayUnsafe contents start end) x = do
1923+ let ptr = PTR_PREV(start,a)
1924+ liftIO $ poke ptr x >> touch contents
1925+ return
1926+ $ FL.Partial
1927+ $ ArrayUnsafe contents ptr end
1928+
1929+-- | Like writeNWith but writes the array in reverse order.
1930+--
1931+-- /Internal/
1932+{-# INLINE_NORMAL writeRevNWith #-}
1933+writeRevNWith :: forall m a. (MonadIO m, Storable a)
1934+ => (Int -> m (Array a)) -> Int -> Fold m a (Array a)
1935+writeRevNWith alloc n = FL.take n (writeRevNWithUnsafe alloc n)
1936+
1937+-- | Like writeN but writes the array in reverse order.
1938+--
1939+-- /Pre-release/
1940+{-# INLINE_NORMAL writeRevN #-}
1941+writeRevN :: forall m a. (MonadIO m, Storable a) => Int -> Fold m a (Array a)
1942+writeRevN = writeRevNWith newArray
1943+
19041944-- | @writeNAligned align n@ folds a maximum of @n@ elements from the input
19051945-- stream to an 'Array' aligned to the given size.
19061946--
@@ -2052,6 +2092,13 @@ fromStreamDN limit str = do
20522092fromListN :: (MonadIO m, Storable a) => Int -> [a] -> m (Array a)
20532093fromListN n xs = fromStreamDN n $ D.fromList xs
20542094
2095+-- | Like fromListN but writes the array in reverse order.
2096+--
2097+-- /Pre-release/
2098+{-# INLINE fromListRevN #-}
2099+fromListRevN :: (MonadIO m, Storable a) => Int -> [a] -> m (Array a)
2100+fromListRevN n xs = D.fold (writeRevN n) $ D.fromList xs
2101+
20552102-------------------------------------------------------------------------------
20562103-- convert stream to a single array
20572104-------------------------------------------------------------------------------
@@ -2094,6 +2141,14 @@ fromStreamD m = arrayStreamKFromStreamD m >>= fromArrayStreamK
20942141fromList :: (MonadIO m, Storable a) => [a] -> m (Array a)
20952142fromList xs = fromStreamD $ D.fromList xs
20962143
2144+-- XXX We are materializing the whole list first for getting the length. Check
2145+-- if the 'fromList' like chunked implementation would fare better.
2146+
2147+-- | Like 'fromList' but writes the contents of the list in reverse order.
2148+{-# INLINE fromListRev #-}
2149+fromListRev :: (MonadIO m, Storable a) => [a] -> m (Array a)
2150+fromListRev xs = fromListRevN (Prelude.length xs) xs
2151+
20972152-------------------------------------------------------------------------------
20982153-- Combining
20992154-------------------------------------------------------------------------------