Add enumFromN, enumFromStepN
[darcs-mirrors/vector.git] / Data / Vector / Generic.hs
index 2ae65a6..e077204 100644 (file)
@@ -20,19 +20,24 @@ module Data.Vector.Generic (
   length, null,
 
   -- * Construction
-  empty, singleton, cons, snoc, replicate, (++), copy,
+  empty, singleton, cons, snoc, replicate, generate, (++), copy,
 
   -- * Accessing individual elements
   (!), head, last, indexM, headM, lastM,
+  unsafeIndex, unsafeHead, unsafeLast,
+  unsafeIndexM, unsafeHeadM, unsafeLastM,
 
   -- * Subvectors
   slice, init, tail, take, drop,
-  unsafeSlice,
+  unsafeSlice, unsafeInit, unsafeTail, unsafeTake, unsafeDrop,
 
   -- * Permutations
   accum, accumulate, accumulate_,
   (//), update, update_,
   backpermute, reverse,
+  unsafeAccum, unsafeAccumulate, unsafeAccumulate_,
+  unsafeUpd, unsafeUpdate, unsafeUpdate_,
+  unsafeBackpermute,
 
   -- * Mapping
   map, imap, concatMap,
@@ -48,16 +53,20 @@ module Data.Vector.Generic (
 
   -- * Filtering
   filter, ifilter, takeWhile, dropWhile,
+  partition, unstablePartition, span, break,
 
   -- * Searching
-  elem, notElem, find, findIndex,
+  elem, notElem, find, findIndex, findIndices, elemIndex, elemIndices,
 
   -- * Folding
-  foldl, foldl1, foldl', foldl1', foldr, foldr1,
-  ifoldl, ifoldl', ifoldr,
+  foldl, foldl1, foldl', foldl1', foldr, foldr1, foldr', foldr1',
+  ifoldl, ifoldl', ifoldr, ifoldr',
  
   -- * Specialised folds
-  and, or, sum, product, maximum, minimum, minIndex, maxIndex,
+  all, any, and, or,
+  sum, product,
+  maximum, maximumBy, minimum, minimumBy,
+  minIndex, minIndexBy, maxIndex, maxIndexBy,
 
   -- * Unfolding
   unfoldr,
@@ -66,26 +75,25 @@ module Data.Vector.Generic (
   prescanl, prescanl',
   postscanl, postscanl',
   scanl, scanl', scanl1, scanl1',
+  prescanr, prescanr',
+  postscanr, postscanr',
+  scanr, scanr', scanr1, scanr1',
 
   -- * Enumeration
-  enumFromTo, enumFromThenTo,
+  enumFromN, enumFromStepN, enumFromTo, enumFromThenTo,
 
   -- * Conversion to/from lists
   toList, fromList,
 
   -- * Conversion to/from Streams
-  stream, unstream,
+  stream, unstream, streamR, unstreamR,
 
   -- * MVector-based initialisation
-  new,
-
-  -- * Unsafe operations
-  unsafeIndex, unsafeIndexM,
-  unsafeAccum, unsafeAccumulate, unsafeAccumulate_,
-  unsafeUpd, unsafeUpdate, unsafeUpdate_
+  new
 ) where
 
 import           Data.Vector.Generic.Mutable ( MVector )
+import qualified Data.Vector.Generic.Mutable as M
 
 import qualified Data.Vector.Generic.New as New
 import           Data.Vector.Generic.New ( New )
@@ -104,11 +112,11 @@ import Prelude hiding ( length, null,
                         init, tail, take, drop, reverse,
                         map, concatMap,
                         zipWith, zipWith3, zip, zip3, unzip, unzip3,
-                        filter, takeWhile, dropWhile,
+                        filter, takeWhile, dropWhile, span, break,
                         elem, notElem,
                         foldl, foldl1, foldr, foldr1,
-                        and, or, sum, product, maximum, minimum,
-                        scanl, scanl1,
+                        all, any, and, or, sum, product, maximum, minimum,
+                        scanl, scanl1, scanr, scanr1,
                         enumFromTo, enumFromThenTo )
 
 #include "vector.h"
@@ -127,7 +135,7 @@ class MVector (Mutable v) a => Vector v a where
   basicLength      :: v a -> Int
 
   -- | Yield a part of the vector without copying it. No range checks!
-  basicUnsafeSlice  :: v a -> Int -> Int -> v a
+  basicUnsafeSlice  :: Int -> Int -> v a -> v a
 
   -- | Yield the element at the given position in a monad. The monad allows us
   -- to be strict in the vector if we want. Suppose we had
@@ -215,6 +223,48 @@ unstream s = new (New.unstream s)
 
  #-}
 
+-- | Convert a vector to a 'Stream'
+streamR :: Vector v a => v a -> Stream a
+{-# INLINE_STREAM streamR #-}
+streamR v = v `seq` (Stream.unfoldr get n `Stream.sized` Exact n)
+  where
+    n = length v
+
+    -- NOTE: the False case comes first in Core so making it the recursive one
+    -- makes the code easier to read
+    {-# INLINE get #-}
+    get 0 = Nothing
+    get i = let i' = i-1
+            in
+            case basicUnsafeIndexM v i' of Box x -> Just (x, i')
+
+-- | Create a vector from a 'Stream'
+unstreamR :: Vector v a => Stream a -> v a
+{-# INLINE unstreamR #-}
+unstreamR s = new (New.unstreamR s)
+
+{-# RULES
+
+"streamR/unstreamR [Vector]" forall v s.
+  streamR (new' v (New.unstreamR s)) = s
+
+"New.unstreamR/streamR/new [Vector]" forall v p.
+  New.unstreamR (streamR (new' v p)) = p
+
+ #-}
+
+{-# RULES
+
+"inplace [Vector]"
+  forall (f :: forall m. Monad m => MStream m a -> MStream m a) v m.
+  New.unstreamR (inplace f (streamR (new' v m))) = New.transformR f m
+
+"uninplace [Vector]"
+  forall (f :: forall m. Monad m => MStream m a -> MStream m a) v m.
+  streamR (new' v (New.transformR f m)) = inplace f (streamR (new' v m))
+
+ #-}
+
 -- Length
 -- ------
 
@@ -254,6 +304,12 @@ replicate n x = elemseq (undefined :: v a) x
               $ unstream
               $ Stream.replicate n x
 
+-- | Generate a vector of the given length by applying the function to each
+-- index
+generate :: Vector v a => Int -> (Int -> a) -> v a
+{-# INLINE generate #-}
+generate n f = unstream (Stream.generate n f)
+
 -- | Prepend an element
 cons :: forall v a. Vector v a => a -> v a -> v a
 {-# INLINE cons #-}
@@ -296,12 +352,6 @@ copy = unstream . stream
 v ! i = BOUNDS_CHECK(checkIndex) "(!)" i (length v)
       $ unId (basicUnsafeIndexM v i)
 
--- | Unsafe indexing without bounds checking
-unsafeIndex :: Vector v a => v a -> Int -> a
-{-# INLINE_STREAM unsafeIndex #-}
-unsafeIndex v i = UNSAFE_CHECK(checkIndex) "unsafeIndex" i (length v)
-                $ unId (basicUnsafeIndexM v i)
-
 -- | First element
 head :: Vector v a => v a -> a
 {-# INLINE_STREAM head #-}
@@ -312,20 +362,44 @@ last :: Vector v a => v a -> a
 {-# INLINE_STREAM last #-}
 last v = v ! (length v - 1)
 
+-- | Unsafe indexing without bounds checking
+unsafeIndex :: Vector v a => v a -> Int -> a
+{-# INLINE_STREAM unsafeIndex #-}
+unsafeIndex v i = UNSAFE_CHECK(checkIndex) "unsafeIndex" i (length v)
+                $ unId (basicUnsafeIndexM v i)
+
+-- | Yield the first element of a vector without checking if the vector is
+-- empty
+unsafeHead :: Vector v a => v a -> a
+{-# INLINE_STREAM unsafeHead #-}
+unsafeHead v = unsafeIndex v 0
+
+-- | Yield the last element of a vector without checking if the vector is
+-- empty
+unsafeLast :: Vector v a => v a -> a
+{-# INLINE_STREAM unsafeLast #-}
+unsafeLast v = unsafeIndex v (length v - 1)
+
 {-# RULES
 
 "(!)/unstream [Vector]" forall v i s.
   new' v (New.unstream s) ! i = s Stream.!! i
 
-"unsafeIndex/unstream [Vector]" forall v i s.
-  unsafeIndex (new' v (New.unstream s)) i = s Stream.!! i
-
 "head/unstream [Vector]" forall v s.
   head (new' v (New.unstream s)) = Stream.head s
 
 "last/unstream [Vector]" forall v s.
   last (new' v (New.unstream s)) = Stream.last s
 
+"unsafeIndex/unstream [Vector]" forall v i s.
+  unsafeIndex (new' v (New.unstream s)) i = s Stream.!! i
+
+"unsafeHead/unstream [Vector]" forall v s.
+  unsafeHead (new' v (New.unstream s)) = Stream.head s
+
+"unsafeLast/unstream [Vector]" forall v s.
+  unsafeLast (new' v (New.unstream s)) = Stream.last s
+
  #-}
 
 -- | Monadic indexing which can be strict in the vector while remaining lazy in
@@ -335,12 +409,6 @@ indexM :: (Vector v a, Monad m) => v a -> Int -> m a
 indexM v i = BOUNDS_CHECK(checkIndex) "indexM" i (length v)
            $ basicUnsafeIndexM v i
 
--- | Unsafe monadic indexing without bounds checks
-unsafeIndexM :: (Vector v a, Monad m) => v a -> Int -> m a
-{-# INLINE_STREAM unsafeIndexM #-}
-unsafeIndexM v i = UNSAFE_CHECK(checkIndex) "unsafeIndexM" i (length v)
-                 $ basicUnsafeIndexM v i
-
 headM :: (Vector v a, Monad m) => v a -> m a
 {-# INLINE_STREAM headM #-}
 headM v = indexM v 0
@@ -349,6 +417,20 @@ lastM :: (Vector v a, Monad m) => v a -> m a
 {-# INLINE_STREAM lastM #-}
 lastM v = indexM v (length v - 1)
 
+-- | Unsafe monadic indexing without bounds checks
+unsafeIndexM :: (Vector v a, Monad m) => v a -> Int -> m a
+{-# INLINE_STREAM unsafeIndexM #-}
+unsafeIndexM v i = UNSAFE_CHECK(checkIndex) "unsafeIndexM" i (length v)
+                 $ basicUnsafeIndexM v i
+
+unsafeHeadM :: (Vector v a, Monad m) => v a -> m a
+{-# INLINE_STREAM unsafeHeadM #-}
+unsafeHeadM v = unsafeIndexM v 0
+
+unsafeLastM :: (Vector v a, Monad m) => v a -> m a
+{-# INLINE_STREAM unsafeLastM #-}
+unsafeLastM v = unsafeIndexM v (length v - 1)
+
 -- FIXME: the rhs of these rules are lazy in the stream which is WRONG
 {- RULES
 
@@ -369,52 +451,67 @@ lastM v = indexM v (length v - 1)
 -- FIXME: slicing doesn't work with the inplace stuff at the moment
 
 -- | Yield a part of the vector without copying it.
-slice :: Vector v a => v a -> Int   -- ^ starting index
-                           -> Int   -- ^ length
-                           -> v a
+slice :: Vector v a => Int   -- ^ starting index
+                    -> Int   -- ^ length
+                    -> v a
+                    -> v a
 {-# INLINE_STREAM slice #-}
-slice v i n = BOUNDS_CHECK(checkSlice) "slice" i n (length v)
-            $ basicUnsafeSlice v i n
-
--- | Unsafely yield a part of the vector without copying it and without
--- performing bounds checks.
-unsafeSlice :: Vector v a => v a -> Int   -- ^ starting index
-                                 -> Int   -- ^ length
-                                 -> v a
-{-# INLINE_STREAM unsafeSlice #-}
-unsafeSlice v i n = UNSAFE_CHECK(checkSlice) "unsafeSlice" i n (length v)
-                  $ basicUnsafeSlice v i n
+slice i n v = BOUNDS_CHECK(checkSlice) "slice" i n (length v)
+            $ basicUnsafeSlice i n v
 
 -- | Yield all but the last element without copying.
 init :: Vector v a => v a -> v a
 {-# INLINE_STREAM init #-}
-init v = slice v 0 (length v - 1)
+init v = slice 0 (length v - 1) v
 
 -- | All but the first element (without copying).
 tail :: Vector v a => v a -> v a
 {-# INLINE_STREAM tail #-}
-tail v = slice v 1 (length v - 1)
+tail v = slice 1 (length v - 1) v
 
 -- | Yield the first @n@ elements without copying.
 take :: Vector v a => Int -> v a -> v a
 {-# INLINE_STREAM take #-}
-take n v = slice v 0 (min n' (length v))
+take n v = unsafeSlice 0 (min n' (length v)) v
   where n' = max n 0
 
 -- | Yield all but the first @n@ elements without copying.
 drop :: Vector v a => Int -> v a -> v a
 {-# INLINE_STREAM drop #-}
-drop n v = slice v (min n' len) (max 0 (len - n'))
+drop n v = unsafeSlice (min n' len) (max 0 (len - n')) v
   where n' = max n 0
         len = length v
 
-{-# RULES
+-- | Unsafely yield a part of the vector without copying it and without
+-- performing bounds checks.
+unsafeSlice :: Vector v a => Int   -- ^ starting index
+                          -> Int   -- ^ length
+                          -> v a
+                          -> v a
+{-# INLINE_STREAM unsafeSlice #-}
+unsafeSlice i n v = UNSAFE_CHECK(checkSlice) "unsafeSlice" i n (length v)
+                  $ basicUnsafeSlice i n v
+
+unsafeInit :: Vector v a => v a -> v a
+{-# INLINE_STREAM unsafeInit #-}
+unsafeInit v = unsafeSlice 0 (length v - 1) v
+
+unsafeTail :: Vector v a => v a -> v a
+{-# INLINE_STREAM unsafeTail #-}
+unsafeTail v = unsafeSlice 1 (length v - 1) v
 
-"slice/new [Vector]" forall v p i n.
-  slice (new' v p) i n = new' v (New.slice p i n)
+unsafeTake :: Vector v a => Int -> v a -> v a
+{-# INLINE unsafeTake #-}
+unsafeTake n v = unsafeSlice 0 n v
 
-"unsafeSlice/new [Vector]" forall v p i n.
-  unsafeSlice (new' v p) i n = new' v (New.unsafeSlice p i n)
+unsafeDrop :: Vector v a => Int -> v a -> v a
+{-# INLINE unsafeDrop #-}
+unsafeDrop n v = unsafeSlice n (length v - n) v
+
+{-# RULES
+
+"slice/new [Vector]" forall i n v p.
+  slice i n (new' v p) = new' v (New.slice i n p)
 
 "init/new [Vector]" forall v p.
   init (new' v p) = new' v (New.init p)
@@ -428,6 +525,15 @@ drop n v = slice v (min n' len) (max 0 (len - n'))
 "drop/new [Vector]" forall n v p.
   drop n (new' v p) = new' v (New.drop n p)
 
+"unsafeSlice/new [Vector]" forall i n v p.
+  unsafeSlice i n (new' v p) = new' v (New.unsafeSlice i n p)
+
+"unsafeInit/new [Vector]" forall v p.
+  unsafeInit (new' v p) = new' v (New.unsafeInit p)
+
+"unsafeTail/new [Vector]" forall v p.
+  unsafeTail (new' v p) = new' v (New.unsafeTail p)
+
   #-}
 
 -- Permutations
@@ -519,6 +625,14 @@ backpermute v is = seq v
                  $ Stream.map (indexM v)
                  $ stream is
 
+unsafeBackpermute :: (Vector v a, Vector v Int) => v a -> v Int -> v a
+{-# INLINE unsafeBackpermute #-}
+unsafeBackpermute v is = seq v
+                       $ unstream
+                       $ Stream.unbox
+                       $ Stream.map (unsafeIndexM v)
+                       $ stream is
+
 reverse :: (Vector v a) => v a -> v a
 {-# INLINE reverse #-}
 reverse = new . New.reverse . New.unstream . stream
@@ -748,6 +862,79 @@ dropWhile :: Vector v a => (a -> Bool) -> v a -> v a
 {-# INLINE dropWhile #-}
 dropWhile f = unstream . Stream.dropWhile f . stream
 
+-- | Split the vector in two parts, the first one containing those elements
+-- that satisfy the predicate and the second one those that don't. The
+-- relative order of the elements is preserved at the cost of a (sometimes)
+-- reduced performance compared to 'unstablePartition'.
+partition :: Vector v a => (a -> Bool) -> v a -> (v a, v a)
+{-# INLINE partition #-}
+partition f = partition_stream f . stream
+
+-- FIXME: Make this inplace-fusible (look at how stable_partition is
+-- implemented in C++)
+
+partition_stream :: Vector v a => (a -> Bool) -> Stream a -> (v a, v a)
+{-# INLINE_STREAM partition_stream #-}
+partition_stream f s = s `seq` runST (
+  do
+    (mv1,mv2) <- M.partitionStream f s
+    v1 <- unsafeFreeze mv1
+    v2 <- unsafeFreeze mv2
+    return (v1,v2))
+
+-- | Split the vector in two parts, the first one containing those elements
+-- that satisfy the predicate and the second one those that don't. The order
+-- of the elements is not preserved but the operation is often faster than
+-- 'partition'.
+unstablePartition :: Vector v a => (a -> Bool) -> v a -> (v a, v a)
+{-# INLINE unstablePartition #-}
+unstablePartition f = unstablePartition_stream f . stream
+
+unstablePartition_stream
+  :: Vector v a => (a -> Bool) -> Stream a -> (v a, v a)
+{-# INLINE_STREAM unstablePartition_stream #-}
+unstablePartition_stream f s = s `seq` runST (
+  do
+    (mv1,mv2) <- M.unstablePartitionStream f s
+    v1 <- unsafeFreeze mv1
+    v2 <- unsafeFreeze mv2
+    return (v1,v2))
+
+unstablePartition_new :: Vector v a => (a -> Bool) -> New a -> (v a, v a)
+{-# INLINE_STREAM unstablePartition_new #-}
+unstablePartition_new f (New.New p) = runST (
+  do
+    mv <- p
+    i <- M.unstablePartition f mv
+    v <- unsafeFreeze mv
+    return (unsafeTake i v, unsafeDrop i v))
+
+{-# RULES
+
+"unstablePartition" forall f v p.
+  unstablePartition_stream f (stream (new' v p))
+    = unstablePartition_new f p
+
+  #-}
+
+
+-- FIXME: make span and break fusible
+
+-- | Split the vector into the longest prefix of elements that satisfy the
+-- predicate and the rest.
+span :: Vector v a => (a -> Bool) -> v a -> (v a, v a)
+{-# INLINE span #-}
+span f = break (not . f)
+
+-- | Split the vector into the longest prefix of elements that do not satisfy
+-- the predicate and the rest.
+break :: Vector v a => (a -> Bool) -> v a -> (v a, v a)
+{-# INLINE break #-}
+break f xs = case findIndex f xs of
+               Just i  -> (unsafeSlice 0 i xs, unsafeSlice i (length xs - i) xs)
+               Nothing -> (xs, empty)
+    
+
 -- Searching
 -- ---------
 
@@ -775,6 +962,25 @@ findIndex :: Vector v a => (a -> Bool) -> v a -> Maybe Int
 {-# INLINE findIndex #-}
 findIndex f = Stream.findIndex f . stream
 
+-- | Yield the indices of elements satisfying the predicate
+findIndices :: (Vector v a, Vector v Int) => (a -> Bool) -> v a -> v Int
+{-# INLINE findIndices #-}
+findIndices f = unstream
+              . inplace (MStream.map fst . MStream.filter (f . snd)
+                                         . MStream.indexed)
+              . stream
+
+-- | Yield 'Just' the index of the first occurence of the given element or
+-- 'Nothing' if the vector does not contain the element
+elemIndex :: (Vector v a, Eq a) => a -> v a -> Maybe Int
+{-# INLINE elemIndex #-}
+elemIndex x = findIndex (x==)
+
+-- | Yield the indices of all occurences of the given element
+elemIndices :: (Vector v a, Vector v Int, Eq a) => a -> v a -> v Int
+{-# INLINE elemIndices #-}
+elemIndices x = findIndices (x==)
+
 -- Folding
 -- -------
 
@@ -808,6 +1014,16 @@ foldr1 :: Vector v a => (a -> a -> a) -> v a -> a
 {-# INLINE foldr1 #-}
 foldr1 f = Stream.foldr1 f . stream
 
+-- | Right fold with a strict accumulator
+foldr' :: Vector v a => (a -> b -> b) -> b -> v a -> b
+{-# INLINE foldr' #-}
+foldr' f z = Stream.foldl' (flip f) z . streamR
+
+-- | Right fold on non-empty vectors with strict accumulator
+foldr1' :: Vector v a => (a -> a -> a) -> v a -> a
+{-# INLINE foldr1' #-}
+foldr1' f = Stream.foldl1' (flip f) . streamR
+
 -- | Left fold (function applied to each element and its index)
 ifoldl :: Vector v b => (a -> Int -> b -> a) -> a -> v b -> a
 {-# INLINE ifoldl #-}
@@ -824,9 +1040,24 @@ ifoldr :: Vector v a => (Int -> a -> b -> b) -> b -> v a -> b
 {-# INLINE ifoldr #-}
 ifoldr f z = Stream.foldr (uncurry f) z . Stream.indexed . stream
 
+-- | Right fold with strict accumulator (function applied to each element and
+-- its index)
+ifoldr' :: Vector v a => (Int -> a -> b -> b) -> b -> v a -> b
+{-# INLINE ifoldr' #-}
+ifoldr' f z xs = Stream.foldl' (flip (uncurry f)) z
+               $ Stream.indexedR (length xs) $ streamR xs
+
 -- Specialised folds
 -- -----------------
 
+all :: Vector v a => (a -> Bool) -> v a -> Bool
+{-# INLINE all #-}
+all f = Stream.and . Stream.map f . stream
+
+any :: Vector v a => (a -> Bool) -> v a -> Bool
+{-# INLINE any #-}
+any f = Stream.or . Stream.map f . stream
+
 and :: Vector v Bool => v Bool -> Bool
 {-# INLINE and #-}
 and = Stream.and . stream
@@ -847,23 +1078,51 @@ maximum :: (Vector v a, Ord a) => v a -> a
 {-# INLINE maximum #-}
 maximum = Stream.foldl1' max . stream
 
+maximumBy :: Vector v a => (a -> a -> Ordering) -> v a -> a
+{-# INLINE maximumBy #-}
+maximumBy cmp = Stream.foldl1' maxBy . stream
+  where
+    {-# INLINE maxBy #-}
+    maxBy x y = case cmp x y of
+                  LT -> y
+                  _  -> x
+
 minimum :: (Vector v a, Ord a) => v a -> a
 {-# INLINE minimum #-}
 minimum = Stream.foldl1' min . stream
 
-minIndex :: (Vector v a, Ord a) => v a -> Int
-{-# INLINE minIndex #-}
-minIndex = fst . Stream.foldl1' imin . Stream.indexed . stream
+minimumBy :: Vector v a => (a -> a -> Ordering) -> v a -> a
+{-# INLINE minimumBy #-}
+minimumBy cmp = Stream.foldl1' minBy . stream
   where
-    imin (i,x) (j,y) | x <= y    = (i,x)
-                     | otherwise = (j,y)
+    {-# INLINE minBy #-}
+    minBy x y = case cmp x y of
+                  GT -> y
+                  _  -> x
 
 maxIndex :: (Vector v a, Ord a) => v a -> Int
 {-# INLINE maxIndex #-}
-maxIndex = fst . Stream.foldl1' imax . Stream.indexed . stream
+maxIndex = maxIndexBy compare
+
+maxIndexBy :: Vector v a => (a -> a -> Ordering) -> v a -> Int
+{-# INLINE maxIndexBy #-}
+maxIndexBy cmp = fst . Stream.foldl1' imax . Stream.indexed . stream
+  where
+    imax (i,x) (j,y) = case cmp x y of
+                         LT -> (j,y)
+                         _  -> (i,x)
+
+minIndex :: (Vector v a, Ord a) => v a -> Int
+{-# INLINE minIndex #-}
+minIndex = minIndexBy compare
+
+minIndexBy :: Vector v a => (a -> a -> Ordering) -> v a -> Int
+{-# INLINE minIndexBy #-}
+minIndexBy cmp = fst . Stream.foldl1' imin . Stream.indexed . stream
   where
-    imax (i,x) (j,y) | x >= y    = (i,x)
-                     | otherwise = (j,y)
+    imin (i,x) (j,y) = case cmp x y of
+                         GT -> (j,y)
+                         _  -> (i,x)
 
 
 -- Unfolding
@@ -916,13 +1175,78 @@ scanl1' :: Vector v a => (a -> a -> a) -> v a -> v a
 {-# INLINE scanl1' #-}
 scanl1' f = unstream . inplace (MStream.scanl1' f) . stream
 
+
+-- | Prefix right-to-left scan
+prescanr :: (Vector v a, Vector v b) => (a -> b -> b) -> b -> v a -> v b
+{-# INLINE prescanr #-}
+prescanr f z = unstreamR . inplace (MStream.prescanl (flip f) z) . streamR
+
+-- | Prefix right-to-left scan with strict accumulator
+prescanr' :: (Vector v a, Vector v b) => (a -> b -> b) -> b -> v a -> v b
+{-# INLINE prescanr' #-}
+prescanr' f z = unstreamR . inplace (MStream.prescanl' (flip f) z) . streamR
+
+-- | Suffix right-to-left scan
+postscanr :: (Vector v a, Vector v b) => (a -> b -> b) -> b -> v a -> v b
+{-# INLINE postscanr #-}
+postscanr f z = unstreamR . inplace (MStream.postscanl (flip f) z) . streamR
+
+-- | Suffix right-to-left scan with strict accumulator
+postscanr' :: (Vector v a, Vector v b) => (a -> b -> b) -> b -> v a -> v b
+{-# INLINE postscanr' #-}
+postscanr' f z = unstreamR . inplace (MStream.postscanl' (flip f) z) . streamR
+
+-- | Haskell-style right-to-left scan
+scanr :: (Vector v a, Vector v b) => (a -> b -> b) -> b -> v a -> v b
+{-# INLINE scanr #-}
+scanr f z = unstreamR . Stream.scanl (flip f) z . streamR
+
+-- | Haskell-style right-to-left scan with strict accumulator
+scanr' :: (Vector v a, Vector v b) => (a -> b -> b) -> b -> v a -> v b
+{-# INLINE scanr' #-}
+scanr' f z = unstreamR . Stream.scanl' (flip f) z . streamR
+
+-- | Right-to-left scan over a non-empty vector
+scanr1 :: Vector v a => (a -> a -> a) -> v a -> v a
+{-# INLINE scanr1 #-}
+scanr1 f = unstreamR . inplace (MStream.scanl1 (flip f)) . streamR
+
+-- | Right-to-left scan over a non-empty vector with a strict accumulator
+scanr1' :: Vector v a => (a -> a -> a) -> v a -> v a
+{-# INLINE scanr1' #-}
+scanr1' f = unstreamR . inplace (MStream.scanl1' (flip f)) . streamR
+
 -- Enumeration
 -- -----------
 
+-- | Yield a vector of the given length containing the values @x@, @x+1@ etc.
+-- This operation is usually more efficient than 'enumFromTo'.
+enumFromN :: (Vector v a, Num a) => a -> Int -> v a
+{-# INLINE enumFromN #-}
+enumFromN x n = enumFromStepN x 1 n
+
+-- | Yield a vector of the given length containing the values @x@, @x+y@,
+-- @x+y+y@ etc. This operations is usually more efficient than
+-- 'enumFromThenTo'.
+enumFromStepN :: forall v a. (Vector v a, Num a) => a -> a -> Int -> v a
+{-# INLINE enumFromStepN #-}
+enumFromStepN x y n = elemseq (undefined :: v a) x
+                    $ elemseq (undefined :: v a) y
+                    $ unstream
+                    $ Stream.enumFromStepN  x y n
+
+-- | Enumerate values from @x@ to @y@.
+--
+-- /WARNING:/ This operation can be very inefficient. If at all possible, use
+-- 'enumFromN' instead.
 enumFromTo :: (Vector v a, Enum a) => a -> a -> v a
 {-# INLINE enumFromTo #-}
 enumFromTo x y = unstream (Stream.enumFromTo x y)
 
+-- | Enumerate values from @x@ to @y@ with a specific step @z@.
+--
+-- /WARNING:/ This operation can be very inefficient. If at all possible, use
+-- 'enumFromStepN' instead.
 enumFromThenTo :: (Vector v a, Enum a) => a -> a -> a -> v a
 {-# INLINE enumFromThenTo #-}
 enumFromThenTo x y z = unstream (Stream.enumFromThenTo x y z)