<commit_before>{-# LANGUAGE Rank2Types, MultiParamTypeClasses, FlexibleContexts,
             TypeFamilies, ScopedTypeVariables #-}
-- |
-- Module      : Data.Vector.Generic
-- Copyright   : (c) <NAME> 2008-2010
-- License     : BSD-style
--
-- Maintainer  : <NAME> <<EMAIL>>
-- Stability   : experimental
-- Portability : non-portable
-- 
-- Generic interface to pure vectors.
--

module Data.Vector.Generic (
  -- * Immutable vectors
  Vector(..), Mutable,

  -- * Accessors

  -- ** Length information
  length, null,

  -- ** Indexing
  (!), head, last,
  unsafeIndex, unsafeHead, unsafeLast,

  -- ** Monadic indexing
  indexM, headM, lastM,
  unsafeIndexM, unsafeHeadM, unsafeLastM,

  -- ** Extracting subvectors (slicing)
  slice, init, tail, take, drop,
  unsafeSlice, unsafeInit, unsafeTail, unsafeTake, unsafeDrop,

  -- * Construction

  -- ** Initialisation
  empty, singleton, replicate, generate,

  -- ** Monadic initialisation
  replicateM, create,

  -- ** Unfolding
  unfoldr, unfoldrN,

  -- ** Enumeration
  enumFromN, enumFromStepN, enumFromTo, enumFromThenTo,

  -- ** Concatenation
  cons, snoc, (++), concat,

  -- ** Restricting memory usage
  force,

  -- * Modifying vectors

  -- ** Bulk updates
  (//), update, update_,
  unsafeUpd, unsafeUpdate, unsafeUpdate_,

  -- ** Accumulations
  accum, accumulate, accumulate_,
  unsafeAccum, unsafeAccumulate, unsafeAccumulate_,

  -- ** Permutations 
  reverse, backpermute, unsafeBackpermute,

  -- ** Safe destructive updates
  modify,

  -- * Elementwise operations

  -- ** Mapping
  map, imap, concatMap,

  -- ** Monadic mapping
  mapM, mapM_, forM, forM_,

  -- ** Zipping
  zipWith, zipWith3, zipWith4, zipWith5, zipWith6,
  izipWith, izipWith3, izipWith4, izipWith5, izipWith6,
  zip, zip3, zip4, zip5, zip6,

  -- ** Monadic zipping
  zipWithM, zipWithM_,

  -- ** Unzipping
  unzip, unzip3, unzip4, unzip5, unzip6,

  -- * Working with predicates

  -- ** Filtering
  filter, ifilter, filterM,
  takeWhile, dropWhile,

  -- ** Partitioning
  partition, unstablePartition, span, break,

  -- ** Searching
  elem, notElem, find, findIndex, findIndices, elemIndex, elemIndices,

  -- * Folding
  foldl, foldl1, foldl', foldl1', foldr, foldr1, foldr', foldr1',
  ifoldl, ifoldl', ifoldr, ifoldr',

  -- ** Specialised folds
  all, any, and, or,
  sum, product,
  maximum, maximumBy, minimum, minimumBy,
  minIndex, minIndexBy, maxIndex, maxIndexBy,

  -- ** Monadic folds
  foldM, foldM', fold1M, fold1M',

  -- * Prefix sums (scans)
  prescanl, prescanl',
  postscanl, postscanl',
  scanl, scanl', scanl1, scanl1',
  prescanr, prescanr',
  postscanr, postscanr',
  scanr, scanr', scanr1, scanr1',

  -- * Conversions

  -- ** Lists
  toList, fromList, fromListN,

  -- ** Different vector types
  convert,

  -- ** Mutable vectors
  thaw, copy, unsafeCopy,

  -- * Fusion support

  -- ** Conversion to/from Streams
  stream, unstream, streamR, unstreamR,

  -- ** Recycling support
  new, clone,

  -- * Utilities

  -- ** Comparisons
  eq, cmp,

  -- ** @Data@ and @Typeable@
  gfoldl, dataCast, mkType
) where

import           Data.Vector.Generic.Base

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 )

import qualified Data.Vector.Fusion.Stream as Stream
import           Data.Vector.Fusion.Stream ( Stream, MStream, inplace, liftStream )
import qualified Data.Vector.Fusion.Stream.Monadic as MStream
import           Data.Vector.Fusion.Stream.Size
import           Data.Vector.Fusion.Util

import Control.Monad.ST ( ST, runST )
import Control.Monad.Primitive
import qualified Control.Monad as Monad
import qualified Data.List as List
import Prelude hiding ( length, null,
                        replicate, (++), concat,
                        head, last,
                        init, tail, take, drop, reverse,
                        map, concat, concatMap,
                        zipWith, zipWith3, zip, zip3, unzip, unzip3,
                        filter, takeWhile, dropWhile, span, break,
                        elem, notElem,
                        foldl, foldl1, foldr, foldr1,
                        all, any, and, or, sum, product, maximum, minimum,
                        scanl, scanl1, scanr, scanr1,
                        enumFromTo, enumFromThenTo,
                        mapM, mapM_ )

import Data.Typeable ( Typeable1, gcast1 )
import Data.Data ( Data, DataType, mkNorepType )

#include "vector.h"

-- Length information
-- ------------------

-- | /O(1)/ Yield the length of the vector.
length :: Vector v a => v a -> Int
{-# INLINE_STREAM length #-}
length v = basicLength v

{-# RULES

"length/unstream [Vector]" forall s.
  length (new (New.unstream s)) = Stream.length s

  #-}

-- | /O(1)/ Test whether a vector if empty
null :: Vector v a => v a -> Bool
{-# INLINE_STREAM null #-}
null v = basicLength v == 0

{-# RULES

"null/unstream [Vector]" forall s.
  null (new (New.unstream s)) = Stream.null s

  #-}

-- Indexing
-- --------

-- | O(1) Indexing
(!) :: Vector v a => v a -> Int -> a
{-# INLINE_STREAM (!) #-}
v ! i = BOUNDS_CHECK(checkIndex) "(!)" i (length v)
      $ unId (basicUnsafeIndexM v i)

-- | /O(1)/ First element
head :: Vector v a => v a -> a
{-# INLINE_STREAM head #-}
head v = v ! 0

-- | /O(1)/ Last element
last :: Vector v a => v a -> a
{-# INLINE_STREAM last #-}
last v = v ! (length v - 1)

-- | /O(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)

-- | /O(1)/ First element without checking if the vector is empty
unsafeHead :: Vector v a => v a -> a
{-# INLINE_STREAM unsafeHead #-}
unsafeHead v = unsafeIndex v 0

-- | /O(1)/ Last element 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 i s.
  new (New.unstream s) ! i = s Stream.!! i

"head/unstream [Vector]" forall s.
  head (new (New.unstream s)) = Stream.head s

"last/unstream [Vector]" forall s.
  last (new (New.unstream s)) = Stream.last s

"unsafeIndex/unstream [Vector]" forall i s.
  unsafeIndex (new (New.unstream s)) i = s Stream.!! i

"unsafeHead/unstream [Vector]" forall s.
  unsafeHead (new (New.unstream s)) = Stream.head s

"unsafeLast/unstream [Vector]" forall s.
  unsafeLast (new (New.unstream s)) = Stream.last s

 #-}

-- Monadic indexing
-- ----------------

-- | /O(1)/ Indexing in a monad.
--
-- The monad allows operations to be strict in the vector when necessary.
-- Suppose vector copying is implemented like this:
--
-- > copy mv v = ... write mv i (v ! i) ...
--
-- For lazy vectors, @v ! i@ would not be evaluated which means that @mv@
-- would unnecessarily retain a reference to @v@ in each element written.
--
-- With 'indexM', copying can be implemented like this instead:
--
-- > copy mv v = ... do
-- >                   x <- indexM v i
-- >                   write mv i x
--
-- Here, no references to @v@ are retained because indexing (but /not/ the
-- elements) is evaluated eagerly.
--
indexM :: (Vector v a, Monad m) => v a -> Int -> m a
{-# INLINE_STREAM indexM #-}
indexM v i = BOUNDS_CHECK(checkIndex) "indexM" i (length v)
           $ basicUnsafeIndexM v i

-- | /O(1)/ First element of a vector in a monad. See 'indexM' for an
-- explanation of why this is useful.
headM :: (Vector v a, Monad m) => v a -> m a
{-# INLINE_STREAM headM #-}
headM v = indexM v 0

-- | /O(1)/ Last element of a vector in a monad. See 'indexM' for an
-- explanation of why this is useful.
lastM :: (Vector v a, Monad m) => v a -> m a
{-# INLINE_STREAM lastM #-}
lastM v = indexM v (length v - 1)

-- | /O(1)/ Indexing in a monad without bounds checks. See 'indexM' for an
-- explanation of why this is useful.
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

-- | /O(1)/ First element in a monad without checking for empty vectors.
-- See 'indexM' for an explanation of why this is useful.
unsafeHeadM :: (Vector v a, Monad m) => v a -> m a
{-# INLINE_STREAM unsafeHeadM #-}
unsafeHeadM v = unsafeIndexM v 0

-- | /O(1)/ Last element in a monad without checking for empty vectors.
-- See 'indexM' for an explanation of why this is useful.
unsafeLastM :: (Vector v a, Monad m) => v a -> m a
{-# INLINE_STREAM unsafeLastM #-}
unsafeLastM v = unsafeIndexM v (length v - 1)

{-# RULES

"indexM/unstream [Vector]" forall s i.
  indexM (new (New.unstream s)) i = liftStream s MStream.!! i

"headM/unstream [Vector]" forall s.
  headM (new (New.unstream s)) = MStream.head (liftStream s)

"lastM/unstream [Vector]" forall s.
  lastM (new (New.unstream s)) = MStream.last (liftStream s)

"unsafeIndexM/unstream [Vector]" forall s i.
  unsafeIndexM (new (New.unstream s)) i = liftStream s MStream.!! i

"unsafeHeadM/unstream [Vector]" forall s.
  unsafeHeadM (new (New.unstream s)) = MStream.head (liftStream s)

"unsafeLastM/unstream [Vector]" forall s.
  unsafeLastM (new (New.unstream s)) = MStream.last (liftStream s)

  #-}

-- Extracting subvectors (slicing)
-- -------------------------------

-- | /O(1)/ Yield a slice of the vector without copying it. The vector must
-- contain at least @i+n@ elements.
slice :: Vector v a => Int   -- ^ @i@ starting index
                    -> Int   -- ^ @n@ length
                    -> v a
                    -> v a
{-# INLINE_STREAM slice #-}
slice i n v = BOUNDS_CHECK(checkSlice) "slice" i n (length v)
            $ basicUnsafeSlice i n v

-- | /O(1)/ Yield all but the last element without copying. The vector may not
-- be empty.
init :: Vector v a => v a -> v a
{-# INLINE_STREAM init #-}
init v = slice 0 (length v - 1) v

-- | /O(1)/ Yield all but the first element without copying. The vector may not
-- be empty.
tail :: Vector v a => v a -> v a
{-# INLINE_STREAM tail #-}
tail v = slice 1 (length v - 1) v

-- | /O(1)/ Yield at the first @n@ elements without copying. The vector may
-- contain less than @n@ elements in which case it is returned unchanged.
take :: Vector v a => Int -> v a -> v a
{-# INLINE_STREAM take #-}
take n v = unsafeSlice 0 (delay_inline min n' (length v)) v
  where n' = max n 0

-- | /O(1)/ Yield all but the first @n@ elements without copying. The vector may
-- contain less than @n@ elements in which case an empty vector is returned.
drop :: Vector v a => Int -> v a -> v a
{-# INLINE_STREAM drop #-}
drop n v = unsafeSlice (delay_inline min n' len)
                       (delay_inline max 0 (len - n')) v
  where n' = max n 0
        len = length v

-- | /O(1)/ Yield a slice of the vector without copying. The vector must
-- contain at least @i+n@ elements but this is not checked.
unsafeSlice :: Vector v a => Int   -- ^ @i@ starting index
                          -> Int   -- ^ @n@ length
                          -> v a
                          -> v a
{-# INLINE_STREAM unsafeSlice #-}
unsafeSlice i n v = UNSAFE_CHECK(checkSlice) "unsafeSlice" i n (length v)
                  $ basicUnsafeSlice i n v

-- | /O(1)/ Yield all but the last element without copying. The vector may not
-- be empty but this is not checked.
unsafeInit :: Vector v a => v a -> v a
{-# INLINE_STREAM unsafeInit #-}
unsafeInit v = unsafeSlice 0 (length v - 1) v

-- | /O(1)/ Yield all but the first element without copying. The vector may not
-- be empty but this is not checked.
unsafeTail :: Vector v a => v a -> v a
{-# INLINE_STREAM unsafeTail #-}
unsafeTail v = unsafeSlice 1 (length v - 1) v

-- | /O(1)/ Yield the first @n@ elements without copying. The vector must
-- contain at least @n@ elements but this is not checked.
unsafeTake :: Vector v a => Int -> v a -> v a
{-# INLINE unsafeTake #-}
unsafeTake n v = unsafeSlice 0 n v

-- | /O(1)/ Yield all but the first @n@ elements without copying. The vector
-- must contain at least @n@ elements but this is not checked.
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 p.
  slice i n (new p) = new (New.slice i n p)

"init/new [Vector]" forall p.
  init (new p) = new (New.init p)

"tail/new [Vector]" forall p.
  tail (new p) = new (New.tail p)

"take/new [Vector]" forall n p.
  take n (new p) = new (New.take n p)

"drop/new [Vector]" forall n p.
  drop n (new p) = new (New.drop n p)

"unsafeSlice/new [Vector]" forall i n p.
  unsafeSlice i n (new p) = new (New.unsafeSlice i n p)

"unsafeInit/new [Vector]" forall p.
  unsafeInit (new p) = new (New.unsafeInit p)

"unsafeTail/new [Vector]" forall p.
  unsafeTail (new p) = new (New.unsafeTail p)

  #-}

-- Initialisation
-- --------------

-- | /O(1)/ Empty vector
empty :: Vector v a => v a
{-# INLINE empty #-}
empty = unstream Stream.empty

-- | /O(1)/ Vector with exactly one element
singleton :: forall v a. Vector v a => a -> v a
{-# INLINE singleton #-}
singleton x = elemseq (undefined :: v a) x
            $ unstream (Stream.singleton x)

-- | /O(n)/ Vector of the given length with the same value in each position
replicate :: forall v a. Vector v a => Int -> a -> v a
{-# INLINE replicate #-}
replicate n x = elemseq (undefined :: v a) x
              $ unstream
              $ Stream.replicate n x

-- | /O(n)/ Construct 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)

-- Unfolding
-- ---------

-- | /O(n)/ Construct a vector by repeatedly applying the generator function
-- to a seed. The generator function yields 'Just' the next element and the
-- new seed or 'Nothing' if there are no more elements.
--
-- > unfoldr (\n -> if n == 0 then Nothing else Just (n,n-1)) 10
-- >  = <10,9,8,7,6,5,4,3,2,1>
unfoldr :: Vector v a => (b -> Maybe (a, b)) -> b -> v a
{-# INLINE unfoldr #-}
unfoldr f = unstream . Stream.unfoldr f

-- | /O(n)/ Construct a vector with at most @n@ by repeatedly applying the
-- generator function to the a seed. The generator function yields 'Just' the
-- next element and the new seed or 'Nothing' if there are no more elements.
--
-- > unfoldrN 3 (\n -> Just (n,n-1)) 10 = <10,9,8>
unfoldrN  :: Vector v a => Int -> (b -> Maybe (a, b)) -> b -> v a
{-# INLINE unfoldrN #-}
unfoldrN n f = unstream . Stream.unfoldrN n f

-- Enumeration
-- -----------

-- | /O(n)/ Yield a vector of the given length containing the values @x@, @x+1@
-- etc. This operation is usually more efficient than 'enumFromTo'.
--
-- > enumFromN 5 3 = <5,6,7>
enumFromN :: (Vector v a, Num a) => a -> Int -> v a
{-# INLINE enumFromN #-}
enumFromN x n = enumFromStepN x 1 n

-- | /O(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 1 0.1 5 = <1,1.1,1.2,1.3,1.4>
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

-- | /O(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)

-- | /O(n)/ 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)

-- Concatenation
-- -------------

-- | /O(n)/ Prepend an element
cons :: forall v a. Vector v a => a -> v a -> v a
{-# INLINE cons #-}
cons x v = elemseq (undefined :: v a) x
         $ unstream
         $ Stream.cons x
         $ stream v

-- | /O(n)/ Append an element
snoc :: forall v a. Vector v a => v a -> a -> v a
{-# INLINE snoc #-}
snoc v x = elemseq (undefined :: v a) x
         $ unstream
         $ Stream.snoc (stream v) x

infixr 5 ++
-- | /O(m+n)/ Concatenate two vectors
(++) :: Vector v a => v a -> v a -> v a
{-# INLINE (++) #-}
v ++ w = unstream (stream v Stream.++ stream w)

-- | /O(n)/ Concatenate all vectors in the list
concat :: Vector v a => [v a] -> v a
{-# INLINE concat #-}
-- concat vs = create (thawMany vs)
concat vs = unstream (Stream.flatten mk step (Exact n) (Stream.fromList vs))
  where
    n = List.foldl' (\k v -> k + length v) 0 vs

    {-# INLINE_INNER step #-}
    step (v,i,k)
      | i < k = case unsafeIndexM v i of
                  Box x -> Stream.Yield x (v,i+1,k)
      | otherwise = Stream.Done

    {-# INLINE mk #-}
    mk v = let k = length v
           in
           k `seq` (v,0,k)

-- Monadic initialisation
-- ----------------------

-- | /O(n)/ Execute the monadic action the given number of times and store the
-- results in a vector.
replicateM :: (Monad m, Vector v a) => Int -> m a -> m (v a)
-- FIXME: specialise for ST and IO?
{-# INLINE replicateM #-}
replicateM n m = fromListN n `Monad.liftM` Monad.replicateM n m

-- | Execute the monadic action and freeze the resulting vector.
--
-- @
-- create (do { v \<- 'M.new' 2; 'M.write' v 0 \'a\'; 'M.write' v 1 \'b\' }) = \<'a','b'\>
-- @
create :: Vector v a => (forall s. ST s (Mutable v s a)) -> v a
{-# INLINE create #-}
create p = new (New.create p)

-- Restricting memory usage
-- ------------------------

-- | /O(n)/ Yield the argument but force it not to retain any extra memory,
-- possibly by copying it.
--
-- This is especially useful when dealing with slices. For example:
--
-- > force (slice 0 2 <huge vector>)
--
-- Here, the slice retains a reference to the huge vector. Forcing it creates
-- a copy of just the elements that belong to the slice and allows the huge
-- vector to be garbage collected.
force :: Vector v a => v a -> v a
-- FIXME: we probably ought to inline this later as the rules still might fire
-- otherwise
{-# INLINE_STREAM force #-}
force v = new (clone v)

-- Bulk updates
-- ------------

-- | /O(m+n)/ For each pair @(i,a)@ from the list, replace the vector
-- element at position @i@ by @a@.
--
-- > <5,9,2,7> // [(2,1),(0,3),(2,8)] = <3,9,8,7>
--
(//) :: Vector v a => v a        -- ^ initial vector (of length @m@)
                   -> [(Int, a)] -- ^ list of index/value pairs (of length @n@)
                   -> v a
{-# INLINE (//) #-}
v // us = update_stream v (Stream.fromList us)

-- | /O(m+n)/ For each pair @(i,a)@ from the vector of index/value pairs,
-- replace the vector element at position @i@ by @a@.
--
-- > update <5,9,2,7> <(2,1),(0,3),(2,8)> = <3,9,8,7>
--
update :: (Vector v a, Vector v (Int, a))
        => v a        -- ^ initial vector (of length @m@)
        -> v (Int, a) -- ^ vector of index/value pairs (of length @n@)
        -> v a
{-# INLINE update #-}
update v w = update_stream v (stream w)

-- | /O(m+min(n1,n2))/ For each index @i@ from the index vector and the
-- corresponding value @a@ from the value vector, replace the element of the
-- initial vector at position @i@ by @a@.
--
-- > update_ <5,9,2,7>  <2,0,2> <1,3,8> = <3,9,8,7>
--
-- This function is useful for instances of 'Vector' that cannot store pairs.
-- Otherwise, 'update' is probably more convenient.
--
-- @
-- update_ xs is ys = 'update' xs ('zip' is ys)
-- @
update_ :: (Vector v a, Vector v Int)
        => v a   -- ^ initial vector (of length @m@)
        -> v Int -- ^ index vector (of length @n1@)
        -> v a   -- ^ value vector (of length @n2@)
        -> v a
{-# INLINE update_ #-}
update_ v is w = update_stream v (Stream.zipWith (,) (stream is) (stream w))

update_stream :: Vector v a => v a -> Stream (Int,a) -> v a
{-# INLINE update_stream #-}
update_stream = modifyWithStream M.update

-- | Same as ('//') but without bounds checking.
unsafeUpd :: Vector v a => v a -> [(Int, a)] -> v a
{-# INLINE unsafeUpd #-}
unsafeUpd v us = unsafeUpdate_stream v (Stream.fromList us)

-- | Same as 'update' but without bounds checking.
unsafeUpdate :: (Vector v a, Vector v (Int, a)) => v a -> v (Int, a) -> v a
{-# INLINE unsafeUpdate #-}
unsafeUpdate v w = unsafeUpdate_stream v (stream w)

-- | Same as 'update_' but without bounds checking.
unsafeUpdate_ :: (Vector v a, Vector v Int) => v a -> v Int -> v a -> v a
{-# INLINE unsafeUpdate_ #-}
unsafeUpdate_ v is w
  = unsafeUpdate_stream v (Stream.zipWith (,) (stream is) (stream w))

unsafeUpdate_stream :: Vector v a => v a -> Stream (Int,a) -> v a
{-# INLINE unsafeUpdate_stream #-}
unsafeUpdate_stream = modifyWithStream M.unsafeUpdate

-- Accumulations
-- -------------

-- | /O(m+n)/ For each pair @(i,b)@ from the list, replace the vector element
-- @a@ at position @i@ by @f a b@.
--
-- > accum (+) <5,9,2> [(2,4),(1,6),(0,3),(1,7)] = <5+3, 9+6+7, 2+4>
accum :: Vector v a
      => (a -> b -> a) -- ^ accumulating function @f@
      -> v a           -- ^ initial vector (of length @m@)
      -> [(Int,b)]     -- ^ list of index/value pairs (of length @n@)
      -> v a
{-# INLINE accum #-}
accum f v us = accum_stream f v (Stream.fromList us)

-- | /O(m+n)/ For each pair @(i,b)@ from the vector of pairs, replace the vector
-- element @a@ at position @i@ by @f a b@.
--
-- > accumulate (+) <5,9,2> <(2,4),(1,6),(0,3),(1,7)> = <5+3, 9+6+7, 2+4>
accumulate :: (Vector v a, Vector v (Int, b))
           => (a -> b -> a) -- ^ accumulating function @f@
           -> v a           -- ^ initial vector (of length @m@)
           -> v (Int,b)     -- ^ vector of index/value pairs (of length @n@)
           -> v a
{-# INLINE accumulate #-}
accumulate f v us = accum_stream f v (stream us)

-- | /O(m+min(n1,n2))/ For each index @i@ from the index vector and the
-- corresponding value @b@ from the the value vector,
-- replace the element of the initial vector at
-- position @i@ by @f a b@.
--
-- > accumulate_ (+) <5,9,2> <2,1,0,1> <4,6,3,7> = <5+3, 9+6+7, 2+4>
--
-- This function is useful for instances of 'Vector' that cannot store pairs.
-- Otherwise, 'accumulate' is probably more convenient:
--
-- @
-- accumulate_ f as is bs = 'accumulate' f as ('zip' is bs)
-- @
accumulate_ :: (Vector v a, Vector v Int, Vector v b)
                => (a -> b -> a) -- ^ accumulating function @f@
                -> v a           -- ^ initial vector (of length @m@)
                -> v Int         -- ^ index vector (of length @n1@)
                -> v b           -- ^ value vector (of length @n2@)
                -> v a
{-# INLINE accumulate_ #-}
accumulate_ f v is xs = accum_stream f v (Stream.zipWith (,) (stream is)
                                                             (stream xs))
                                        

accum_stream :: Vector v a => (a -> b -> a) -> v a -> Stream (Int,b) -> v a
{-# INLINE accum_stream #-}
accum_stream f = modifyWithStream (M.accum f)

-- | Same as 'accum' but without bounds checking.
unsafeAccum :: Vector v a => (a -> b -> a) -> v a -> [(Int,b)] -> v a
{-# INLINE unsafeAccum #-}
unsafeAccum f v us = unsafeAccum_stream f v (Stream.fromList us)

-- | Same as 'accumulate' but without bounds checking.
unsafeAccumulate :: (Vector v a, Vector v (Int, b))
                => (a -> b -> a) -> v a -> v (Int,b) -> v a
{-# INLINE unsafeAccumulate #-}
unsafeAccumulate f v us = unsafeAccum_stream f v (stream us)

-- | Same as 'accumulate_' but without bounds checking.
unsafeAccumulate_ :: (Vector v a, Vector v Int, Vector v b)
                => (a -> b -> a) -> v a -> v Int -> v b -> v a
{-# INLINE unsafeAccumulate_ #-}
unsafeAccumulate_ f v is xs
  = unsafeAccum_stream f v (Stream.zipWith (,) (stream is) (stream xs))

unsafeAccum_stream
  :: Vector v a => (a -> b -> a) -> v a -> Stream (Int,b) -> v a
{-# INLINE unsafeAccum_stream #-}
unsafeAccum_stream f = modifyWithStream (M.unsafeAccum f)

-- Permutations
-- ------------

-- | /O(n)/ Reverse a vector
reverse :: (Vector v a) => v a -> v a
{-# INLINE reverse #-}
-- FIXME: make this fuse better, add support for recycling
reverse = unstream . streamR

-- | /O(n)/ Yield the vector obtained by replacing each element @i@ of the
-- index vector by @xs'!'i@. This is equivalent to @'map' (xs'!') is@ but is
-- often much more efficient.
--
-- > backpermute <a,b,c,d> <0,3,2,3,1,0> = <a,d,c,d,b,a>
backpermute :: (Vector v a, Vector v Int)
            => v a   -- ^ @xs@ value vector
            -> v Int -- ^ @is@ index vector (of length @n@)
            -> v a
{-# INLINE backpermute #-}
-- This somewhat non-intuitive definition ensures that the resulting vector
-- does not retain references to the original one even if it is lazy in its
-- elements. This would not be the case if we simply used map (v!)
backpermute v is = seq v
                 $ unstream
                 $ Stream.unbox
                 $ Stream.map (indexM v)
                 $ stream is

-- | Same as 'backpermute' but without bounds checking.
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

-- Safe destructive updates
-- ------------------------

-- | Apply a destructive operation to a vector. The operation will be
-- performed in place if it is safe to do so and will modify a copy of the
-- vector otherwise.
--
-- @
-- modify (\\v -> 'M.write' v 0 \'x\') ('replicate' 3 \'a\') = \<\'x\',\'a\',\'a\'\>
-- @
modify :: Vector v a => (forall s. Mutable v s a -> ST s ()) -> v a -> v a
{-# INLINE modify #-}
modify p = new . New.modify p . clone
<commit_msg>Avoid last LiberateCase in D.V.Generic<commit_after>{-# LANGUAGE Rank2Types, MultiParamTypeClasses, FlexibleContexts,
             TypeFamilies, ScopedTypeVariables #-}
-- |
-- Module      : Data.Vector.Generic
-- Copyright   : (c) <NAME> 2008-2010
-- License     : BSD-style
--
-- Maintainer  : <NAME> <<EMAIL>>
-- Stability   : experimental
-- Portability : non-portable
-- 
-- Generic interface to pure vectors.
--

module Data.Vector.Generic (
  -- * Immutable vectors
  Vector(..), Mutable,

  -- * Accessors

  -- ** Length information
  length, null,

  -- ** Indexing
  (!), head, last,
  unsafeIndex, unsafeHead, unsafeLast,

  -- ** Monadic indexing
  indexM, headM, lastM,
  unsafeIndexM, unsafeHeadM, unsafeLastM,

  -- ** Extracting subvectors (slicing)
  slice, init, tail, take, drop,
  unsafeSlice, unsafeInit, unsafeTail, unsafeTake, unsafeDrop,

  -- * Construction

  -- ** Initialisation
  empty, singleton, replicate, generate,

  -- ** Monadic initialisation
  replicateM, create,

  -- ** Unfolding
  unfoldr, unfoldrN,

  -- ** Enumeration
  enumFromN, enumFromStepN, enumFromTo, enumFromThenTo,

  -- ** Concatenation
  cons, snoc, (++), concat,

  -- ** Restricting memory usage
  force,

  -- * Modifying vectors

  -- ** Bulk updates
  (//), update, update_,
  unsafeUpd, unsafeUpdate, unsafeUpdate_,

  -- ** Accumulations
  accum, accumulate, accumulate_,
  unsafeAccum, unsafeAccumulate, unsafeAccumulate_,

  -- ** Permutations 
  reverse, backpermute, unsafeBackpermute,

  -- ** Safe destructive updates
  modify,

  -- * Elementwise operations

  -- ** Mapping
  map, imap, concatMap,

  -- ** Monadic mapping
  mapM, mapM_, forM, forM_,

  -- ** Zipping
  zipWith, zipWith3, zipWith4, zipWith5, zipWith6,
  izipWith, izipWith3, izipWith4, izipWith5, izipWith6,
  zip, zip3, zip4, zip5, zip6,

  -- ** Monadic zipping
  zipWithM, zipWithM_,

  -- ** Unzipping
  unzip, unzip3, unzip4, unzip5, unzip6,

  -- * Working with predicates

  -- ** Filtering
  filter, ifilter, filterM,
  takeWhile, dropWhile,

  -- ** Partitioning
  partition, unstablePartition, span, break,

  -- ** Searching
  elem, notElem, find, findIndex, findIndices, elemIndex, elemIndices,

  -- * Folding
  foldl, foldl1, foldl', foldl1', foldr, foldr1, foldr', foldr1',
  ifoldl, ifoldl', ifoldr, ifoldr',

  -- ** Specialised folds
  all, any, and, or,
  sum, product,
  maximum, maximumBy, minimum, minimumBy,
  minIndex, minIndexBy, maxIndex, maxIndexBy,

  -- ** Monadic folds
  foldM, foldM', fold1M, fold1M',

  -- * Prefix sums (scans)
  prescanl, prescanl',
  postscanl, postscanl',
  scanl, scanl', scanl1, scanl1',
  prescanr, prescanr',
  postscanr, postscanr',
  scanr, scanr', scanr1, scanr1',

  -- * Conversions

  -- ** Lists
  toList, fromList, fromListN,

  -- ** Different vector types
  convert,

  -- ** Mutable vectors
  thaw, copy, unsafeCopy,

  -- * Fusion support

  -- ** Conversion to/from Streams
  stream, unstream, streamR, unstreamR,

  -- ** Recycling support
  new, clone,

  -- * Utilities

  -- ** Comparisons
  eq, cmp,

  -- ** @Data@ and @Typeable@
  gfoldl, dataCast, mkType
) where

import           Data.Vector.Generic.Base

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 )

import qualified Data.Vector.Fusion.Stream as Stream
import           Data.Vector.Fusion.Stream ( Stream, MStream, inplace, liftStream )
import qualified Data.Vector.Fusion.Stream.Monadic as MStream
import           Data.Vector.Fusion.Stream.Size
import           Data.Vector.Fusion.Util

import Control.Monad.ST ( ST, runST )
import Control.Monad.Primitive
import qualified Control.Monad as Monad
import qualified Data.List as List
import Prelude hiding ( length, null,
                        replicate, (++), concat,
                        head, last,
                        init, tail, take, drop, reverse,
                        map, concat, concatMap,
                        zipWith, zipWith3, zip, zip3, unzip, unzip3,
                        filter, takeWhile, dropWhile, span, break,
                        elem, notElem,
                        foldl, foldl1, foldr, foldr1,
                        all, any, and, or, sum, product, maximum, minimum,
                        scanl, scanl1, scanr, scanr1,
                        enumFromTo, enumFromThenTo,
                        mapM, mapM_ )

import Data.Typeable ( Typeable1, gcast1 )
import Data.Data ( Data, DataType, mkNorepType )

#include "vector.h"

-- Length information
-- ------------------

-- | /O(1)/ Yield the length of the vector.
length :: Vector v a => v a -> Int
{-# INLINE_STREAM length #-}
length v = basicLength v

{-# RULES

"length/unstream [Vector]" forall s.
  length (new (New.unstream s)) = Stream.length s

  #-}

-- | /O(1)/ Test whether a vector if empty
null :: Vector v a => v a -> Bool
{-# INLINE_STREAM null #-}
null v = basicLength v == 0

{-# RULES

"null/unstream [Vector]" forall s.
  null (new (New.unstream s)) = Stream.null s

  #-}

-- Indexing
-- --------

-- | O(1) Indexing
(!) :: Vector v a => v a -> Int -> a
{-# INLINE_STREAM (!) #-}
v ! i = BOUNDS_CHECK(checkIndex) "(!)" i (length v)
      $ unId (basicUnsafeIndexM v i)

-- | /O(1)/ First element
head :: Vector v a => v a -> a
{-# INLINE_STREAM head #-}
head v = v ! 0

-- | /O(1)/ Last element
last :: Vector v a => v a -> a
{-# INLINE_STREAM last #-}
last v = v ! (length v - 1)

-- | /O(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)

-- | /O(1)/ First element without checking if the vector is empty
unsafeHead :: Vector v a => v a -> a
{-# INLINE_STREAM unsafeHead #-}
unsafeHead v = unsafeIndex v 0

-- | /O(1)/ Last element 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 i s.
  new (New.unstream s) ! i = s Stream.!! i

"head/unstream [Vector]" forall s.
  head (new (New.unstream s)) = Stream.head s

"last/unstream [Vector]" forall s.
  last (new (New.unstream s)) = Stream.last s

"unsafeIndex/unstream [Vector]" forall i s.
  unsafeIndex (new (New.unstream s)) i = s Stream.!! i

"unsafeHead/unstream [Vector]" forall s.
  unsafeHead (new (New.unstream s)) = Stream.head s

"unsafeLast/unstream [Vector]" forall s.
  unsafeLast (new (New.unstream s)) = Stream.last s

 #-}

-- Monadic indexing
-- ----------------

-- | /O(1)/ Indexing in a monad.
--
-- The monad allows operations to be strict in the vector when necessary.
-- Suppose vector copying is implemented like this:
--
-- > copy mv v = ... write mv i (v ! i) ...
--
-- For lazy vectors, @v ! i@ would not be evaluated which means that @mv@
-- would unnecessarily retain a reference to @v@ in each element written.
--
-- With 'indexM', copying can be implemented like this instead:
--
-- > copy mv v = ... do
-- >                   x <- indexM v i
-- >                   write mv i x
--
-- Here, no references to @v@ are retained because indexing (but /not/ the
-- elements) is evaluated eagerly.
--
indexM :: (Vector v a, Monad m) => v a -> Int -> m a
{-# INLINE_STREAM indexM #-}
indexM v i = BOUNDS_CHECK(checkIndex) "indexM" i (length v)
           $ basicUnsafeIndexM v i

-- | /O(1)/ First element of a vector in a monad. See 'indexM' for an
-- explanation of why this is useful.
headM :: (Vector v a, Monad m) => v a -> m a
{-# INLINE_STREAM headM #-}
headM v = indexM v 0

-- | /O(1)/ Last element of a vector in a monad. See 'indexM' for an
-- explanation of why this is useful.
lastM :: (Vector v a, Monad m) => v a -> m a
{-# INLINE_STREAM lastM #-}
lastM v = indexM v (length v - 1)

-- | /O(1)/ Indexing in a monad without bounds checks. See 'indexM' for an
-- explanation of why this is useful.
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

-- | /O(1)/ First element in a monad without checking for empty vectors.
-- See 'indexM' for an explanation of why this is useful.
unsafeHeadM :: (Vector v a, Monad m) => v a -> m a
{-# INLINE_STREAM unsafeHeadM #-}
unsafeHeadM v = unsafeIndexM v 0

-- | /O(1)/ Last element in a monad without checking for empty vectors.
-- See 'indexM' for an explanation of why this is useful.
unsafeLastM :: (Vector v a, Monad m) => v a -> m a
{-# INLINE_STREAM unsafeLastM #-}
unsafeLastM v = unsafeIndexM v (length v - 1)

{-# RULES

"indexM/unstream [Vector]" forall s i.
  indexM (new (New.unstream s)) i = liftStream s MStream.!! i

"headM/unstream [Vector]" forall s.
  headM (new (New.unstream s)) = MStream.head (liftStream s)

"lastM/unstream [Vector]" forall s.
  lastM (new (New.unstream s)) = MStream.last (liftStream s)

"unsafeIndexM/unstream [Vector]" forall s i.
  unsafeIndexM (new (New.unstream s)) i = liftStream s MStream.!! i

"unsafeHeadM/unstream [Vector]" forall s.
  unsafeHeadM (new (New.unstream s)) = MStream.head (liftStream s)

"unsafeLastM/unstream [Vector]" forall s.
  unsafeLastM (new (New.unstream s)) = MStream.last (liftStream s)

  #-}

-- Extracting subvectors (slicing)
-- -------------------------------

-- | /O(1)/ Yield a slice of the vector without copying it. The vector must
-- contain at least @i+n@ elements.
slice :: Vector v a => Int   -- ^ @i@ starting index
                    -> Int   -- ^ @n@ length
                    -> v a
                    -> v a
{-# INLINE_STREAM slice #-}
slice i n v = BOUNDS_CHECK(checkSlice) "slice" i n (length v)
            $ basicUnsafeSlice i n v

-- | /O(1)/ Yield all but the last element without copying. The vector may not
-- be empty.
init :: Vector v a => v a -> v a
{-# INLINE_STREAM init #-}
init v = slice 0 (length v - 1) v

-- | /O(1)/ Yield all but the first element without copying. The vector may not
-- be empty.
tail :: Vector v a => v a -> v a
{-# INLINE_STREAM tail #-}
tail v = slice 1 (length v - 1) v

-- | /O(1)/ Yield at the first @n@ elements without copying. The vector may
-- contain less than @n@ elements in which case it is returned unchanged.
take :: Vector v a => Int -> v a -> v a
{-# INLINE_STREAM take #-}
take n v = unsafeSlice 0 (delay_inline min n' (length v)) v
  where n' = max n 0

-- | /O(1)/ Yield all but the first @n@ elements without copying. The vector may
-- contain less than @n@ elements in which case an empty vector is returned.
drop :: Vector v a => Int -> v a -> v a
{-# INLINE_STREAM drop #-}
drop n v = unsafeSlice (delay_inline min n' len)
                       (delay_inline max 0 (len - n')) v
  where n' = max n 0
        len = length v

-- | /O(1)/ Yield a slice of the vector without copying. The vector must
-- contain at least @i+n@ elements but this is not checked.
unsafeSlice :: Vector v a => Int   -- ^ @i@ starting index
                          -> Int   -- ^ @n@ length
                          -> v a
                          -> v a
{-# INLINE_STREAM unsafeSlice #-}
unsafeSlice i n v = UNSAFE_CHECK(checkSlice) "unsafeSlice" i n (length v)
                  $ basicUnsafeSlice i n v

-- | /O(1)/ Yield all but the last element without copying. The vector may not
-- be empty but this is not checked.
unsafeInit :: Vector v a => v a -> v a
{-# INLINE_STREAM unsafeInit #-}
unsafeInit v = unsafeSlice 0 (length v - 1) v

-- | /O(1)/ Yield all but the first element without copying. The vector may not
-- be empty but this is not checked.
unsafeTail :: Vector v a => v a -> v a
{-# INLINE_STREAM unsafeTail #-}
unsafeTail v = unsafeSlice 1 (length v - 1) v

-- | /O(1)/ Yield the first @n@ elements without copying. The vector must
-- contain at least @n@ elements but this is not checked.
unsafeTake :: Vector v a => Int -> v a -> v a
{-# INLINE unsafeTake #-}
unsafeTake n v = unsafeSlice 0 n v

-- | /O(1)/ Yield all but the first @n@ elements without copying. The vector
-- must contain at least @n@ elements but this is not checked.
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 p.
  slice i n (new p) = new (New.slice i n p)

"init/new [Vector]" forall p.
  init (new p) = new (New.init p)

"tail/new [Vector]" forall p.
  tail (new p) = new (New.tail p)

"take/new [Vector]" forall n p.
  take n (new p) = new (New.take n p)

"drop/new [Vector]" forall n p.
  drop n (new p) = new (New.drop n p)

"unsafeSlice/new [Vector]" forall i n p.
  unsafeSlice i n (new p) = new (New.unsafeSlice i n p)

"unsafeInit/new [Vector]" forall p.
  unsafeInit (new p) = new (New.unsafeInit p)

"unsafeTail/new [Vector]" forall p.
  unsafeTail (new p) = new (New.unsafeTail p)

  #-}

-- Initialisation
-- --------------

-- | /O(1)/ Empty vector
empty :: Vector v a => v a
{-# INLINE empty #-}
empty = unstream Stream.empty

-- | /O(1)/ Vector with exactly one element
singleton :: forall v a. Vector v a => a -> v a
{-# INLINE singleton #-}
singleton x = elemseq (undefined :: v a) x
            $ unstream (Stream.singleton x)

-- | /O(n)/ Vector of the given length with the same value in each position
replicate :: forall v a. Vector v a => Int -> a -> v a
{-# INLINE replicate #-}
replicate n x = elemseq (undefined :: v a) x
              $ unstream
              $ Stream.replicate n x

-- | /O(n)/ Construct 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)

-- Unfolding
-- ---------

-- | /O(n)/ Construct a vector by repeatedly applying the generator function
-- to a seed. The generator function yields 'Just' the next element and the
-- new seed or 'Nothing' if there are no more elements.
--
-- > unfoldr (\n -> if n == 0 then Nothing else Just (n,n-1)) 10
-- >  = <10,9,8,7,6,5,4,3,2,1>
unfoldr :: Vector v a => (b -> Maybe (a, b)) -> b -> v a
{-# INLINE unfoldr #-}
unfoldr f = unstream . Stream.unfoldr f

-- | /O(n)/ Construct a vector with at most @n@ by repeatedly applying the
-- generator function to the a seed. The generator function yields 'Just' the
-- next element and the new seed or 'Nothing' if there are no more elements.
--
-- > unfoldrN 3 (\n -> Just (n,n-1)) 10 = <10,9,8>
unfoldrN  :: Vector v a => Int -> (b -> Maybe (a, b)) -> b -> v a
{-# INLINE unfoldrN #-}
unfoldrN n f = unstream . Stream.unfoldrN n f

-- Enumeration
-- -----------

-- | /O(n)/ Yield a vector of the given length containing the values @x@, @x+1@
-- etc. This operation is usually more efficient than 'enumFromTo'.
--
-- > enumFromN 5 3 = <5,6,7>
enumFromN :: (Vector v a, Num a) => a -> Int -> v a
{-# INLINE enumFromN #-}
enumFromN x n = enumFromStepN x 1 n

-- | /O(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 1 0.1 5 = <1,1.1,1.2,1.3,1.4>
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

-- | /O(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)

-- | /O(n)/ 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)

-- Concatenation
-- -------------

-- | /O(n)/ Prepend an element
cons :: forall v a. Vector v a => a -> v a -> v a
{-# INLINE cons #-}
cons x v = elemseq (undefined :: v a) x
         $ unstream
         $ Stream.cons x
         $ stream v

-- | /O(n)/ Append an element
snoc :: forall v a. Vector v a => v a -> a -> v a
{-# INLINE snoc #-}
snoc v x = elemseq (undefined :: v a) x
         $ unstream
         $ Stream.snoc (stream v) x

infixr 5 ++
-- | /O(m+n)/ Concatenate two vectors
(++) :: Vector v a => v a -> v a -> v a
{-# INLINE (++) #-}
v ++ w = unstream (stream v Stream.++ stream w)

-- | /O(n)/ Concatenate all vectors in the list
concat :: Vector v a => [v a] -> v a
{-# INLINE concat #-}
-- concat vs = create (thawMany vs)
concat vs = unstream (Stream.flatten mk step (Exact n) (Stream.fromList vs))
  where
    n = List.foldl' (\k v -> k + length v) 0 vs

    {-# INLINE_INNER step #-}
    step (v,i,k)
      | i < k = case unsafeIndexM v i of
                  Box x -> Stream.Yield x (v,i+1,k)
      | otherwise = Stream.Done

    {-# INLINE mk #-}
    mk v = let k = length v
           in
           k `seq` (v,0,k)

-- Monadic initialisation
-- ----------------------

-- | /O(n)/ Execute the monadic action the given number of times and store the
-- results in a vector.
replicateM :: (Monad m, Vector v a) => Int -> m a -> m (v a)
-- FIXME: specialise for ST and IO?
{-# INLINE replicateM #-}
replicateM n m = fromListN n `Monad.liftM` Monad.replicateM n m

-- | Execute the monadic action and freeze the resulting vector.
--
-- @
-- create (do { v \<- 'M.new' 2; 'M.write' v 0 \'a\'; 'M.write' v 1 \'b\' }) = \<'a','b'\>
-- @
create :: Vector v a => (forall s. ST s (Mutable v s a)) -> v a
{-# INLINE create #-}
create p = new (New.create p)

-- Restricting memory usage
-- ------------------------

-- | /O(n)/ Yield the argument but force it not to retain any extra memory,
-- possibly by copying it.
--
-- This is especially useful when dealing with slices. For example:
--
-- > force (slice 0 2 <huge vector>)
--
-- Here, the slice retains a reference to the huge vector. Forcing it creates
-- a copy of just the elements that belong to the slice and allows the huge
-- vector to be garbage collected.
force :: Vector v a => v a -> v a
-- FIXME: we probably ought to inline this later as the rules still might fire
-- otherwise
{-# INLINE_STREAM force #-}
force v = new (clone v)

-- Bulk updates
-- ------------

-- | /O(m+n)/ For each pair @(i,a)@ from the list, replace the vector
-- element at position @i@ by @a@.
--
-- > <5,9,2,7> // [(2,1),(0,3),(2,8)] = <3,9,8,7>
--
(//) :: Vector v a => v a        -- ^ initial vector (of length @m@)
                   -> [(Int, a)] -- ^ list of index/value pairs (of length @n@)
                   -> v a
{-# INLINE (//) #-}
v // us = update_stream v (Stream.fromList us)

-- | /O(m+n)/ For each pair @(i,a)@ from the vector of index/value pairs,
-- replace the vector element at position @i@ by @a@.
--
-- > update <5,9,2,7> <(2,1),(0,3),(2,8)> = <3,9,8,7>
--
update :: (Vector v a, Vector v (Int, a))
        => v a        -- ^ initial vector (of length @m@)
        -> v (Int, a) -- ^ vector of index/value pairs (of length @n@)
        -> v a
{-# INLINE update #-}
update v w = update_stream v (stream w)

-- | /O(m+min(n1,n2))/ For each index @i@ from the index vector and the
-- corresponding value @a@ from the value vector, replace the element of the
-- initial vector at position @i@ by @a@.
--
-- > update_ <5,9,2,7>  <2,0,2> <1,3,8> = <3,9,8,7>
--
-- This function is useful for instances of 'Vector' that cannot store pairs.
-- Otherwise, 'update' is probably more convenient.
--
-- @
-- update_ xs is ys = 'update' xs ('zip' is ys)
-- @
update_ :: (Vector v a, Vector v Int)
        => v a   -- ^ initial vector (of length @m@)
        -> v Int -- ^ index vector (of length @n1@)
        -> v a   -- ^ value vector (of length @n2@)
        -> v a
{-# INLINE update_ #-}
update_ v is w = update_stream v (Stream.zipWith (,) (stream is) (stream w))

update_stream :: Vector v a => v a -> Stream (Int,a) -> v a
{-# INLINE update_stream #-}
update_stream = modifyWithStream M.update

-- | Same as ('//') but without bounds checking.
unsafeUpd :: Vector v a => v a -> [(Int, a)] -> v a
{-# INLINE unsafeUpd #-}
unsafeUpd v us = unsafeUpdate_stream v (Stream.fromList us)

-- | Same as 'update' but without bounds checking.
unsafeUpdate :: (Vector v a, Vector v (Int, a)) => v a -> v (Int, a) -> v a
{-# INLINE unsafeUpdate #-}
unsafeUpdate v w = unsafeUpdate_stream v (stream w)

-- | Same as 'update_' but without bounds checking.
unsafeUpdate_ :: (Vector v a, Vector v Int) => v a -> v Int -> v a -> v a
{-# INLINE unsafeUpdate_ #-}
unsafeUpdate_ v is w
  = unsafeUpdate_stream v (Stream.zipWith (,) (stream is) (stream w))

unsafeUpdate_stream :: Vector v a => v a -> Stream (Int,a) -> v a
{-# INLINE unsafeUpdate_stream #-}
unsafeUpdate_stream = modifyWithStream M.unsafeUpdate

-- Accumulations
-- -------------

-- | /O(m+n)/ For each pair @(i,b)@ from the list, replace the vector element
-- @a@ at position @i@ by @f a b@.
--
-- > accum (+) <5,9,2> [(2,4),(1,6),(0,3),(1,7)] = <5+3, 9+6+7, 2+4>
accum :: Vector v a
      => (a -> b -> a) -- ^ accumulating function @f@
      -> v a           -- ^ initial vector (of length @m@)
      -> [(Int,b)]     -- ^ list of index/value pairs (of length @n@)
      -> v a
{-# INLINE accum #-}
accum f v us = accum_stream f v (Stream.fromList us)

-- | /O(m+n)/ For each pair @(i,b)@ from the vector of pairs, replace the vector
-- element @a@ at position @i@ by @f a b@.
--
-- > accumulate (+) <5,9,2> <(2,4),(1,6),(0,3),(1,7)> = <5+3, 9+6+7, 2+4>
accumulate :: (Vector v a, Vector v (Int, b))
           => (a -> b -> a) -- ^ accumulating function @f@
           -> v a           -- ^ initial vector (of length @m@)
           -> v (Int,b)     -- ^ vector of index/value pairs (of length @n@)
           -> v a
{-# INLINE accumulate #-}
accumulate f v us = accum_stream f v (stream us)

-- | /O(m+min(n1,n2))/ For each index @i@ from the index vector and the
-- corresponding value @b@ from the the value vector,
-- replace the element of the initial vector at
-- position @i@ by @f a b@.
--
-- > accumulate_ (+) <5,9,2> <2,1,0,1> <4,6,3,7> = <5+3, 9+6+7, 2+4>
--
-- This function is useful for instances of 'Vector' that cannot store pairs.
-- Otherwise, 'accumulate' is probably more convenient:
--
-- @
-- accumulate_ f as is bs = 'accumulate' f as ('zip' is bs)
-- @
accumulate_ :: (Vector v a, Vector v Int, Vector v b)
                => (a -> b -> a) -- ^ accumulating function @f@
                -> v a           -- ^ initial vector (of length @m@)
                -> v Int         -- ^ index vector (of length @n1@)
                -> v b           -- ^ value vector (of length @n2@)
                -> v a
{-# INLINE accumulate_ #-}
accumulate_ f v is xs = accum_stream f v (Stream.zipWith (,) (stream is)
                                                             (stream xs))
                                        

accum_stream :: Vector v a => (a -> b -> a) -> v a -> Stream (Int,b) -> v a
{-# INLINE accum_stream #-}
accum_stream f = modifyWithStream (M.accum f)

-- | Same as 'accum' but without bounds checking.
unsafeAccum :: Vector v a => (a -> b -> a) -> v a -> [(Int,b)] -> v a
{-# INLINE unsafeAccum #-}
unsafeAccum f v us = unsafeAccum_stream f v (Stream.fromList us)

-- | Same as 'accumulate' but without bounds checking.
unsafeAccumulate :: (Vector v a, Vector v (Int, b))
                => (a -> b -> a) -> v a -> v (Int,b) -> v a
{-# INLINE unsafeAccumulate #-}
unsafeAccumulate f v us = unsafeAccum_stream f v (stream us)

-- | Same as 'accumulate_' but without bounds checking.
unsafeAccumulate_ :: (Vector v a, Vector v Int, Vector v b)
                => (a -> b -> a) -> v a -> v Int -> v b -> v a
{-# INLINE unsafeAccumulate_ #-}
unsafeAccumulate_ f v is xs
  = unsafeAccum_stream f v (Stream.zipWith (,) (stream is) (stream xs))

unsafeAccum_stream
  :: Vector v a => (a -> b -> a) -> v a -> Stream (Int,b) -> v a
{-# INLINE unsafeAccum_stream #-}
unsafeAccum_stream f = modifyWithStream (M.unsafeAccum f)

-- Permutations
-- ------------

-- | /O(n)/ Reverse a vector
reverse :: (Vector v a) => v a -> v a
{-# INLINE reverse #-}
-- FIXME: make this fuse better, add support for recycling
reverse = unstream . streamR

-- | /O(n)/ Yield the vector obtained by replacing each element @i@ of the
-- index vector by @xs'!'i@. This is equivalent to @'map' (xs'!') is@ but is
-- often much more efficient.
--
-- > backpermute <a,b,c,d> <0,3,2,3,1,0> = <a,d,c,d,b,a>
backpermute :: (Vector v a, Vector v Int)
            => v a   -- ^ @xs@ value vector
            -> v Int -- ^ @is@ index vector (of length @n@)
            -> v a
{-# INLINE backpermute #-}
-- This somewhat non-intuitive definition ensures that the resulting vector
-- does not retain references to the original one even if it is lazy in its
-- elements. This would not be the case if we simply used map (v!)
backpermute v is = seq v
                 $ seq n
                 $ unstream
                 $ Stream.unbox
                 $ Stream.map index
                 $ stream is
  where
    n = length v

    {-# INLINE index #-}
    -- NOTE: we do it this way to avoid triggering LiberateCase on n in
    -- polymorphic code
    index i = BOUNDS_CHECK(checkIndex) "backpermute" i n
            $ basicUnsafeIndexM v i

-- | Same as 'backpermute' but without bounds checking.
unsafeBackpermute :: (Vector v a, Vector v Int) => v a -> v Int -> v a
{-# INLINE unsafeBackpermute #-}
unsafeBackpermute v is = seq v
                       $ seq n
                       $ unstream
                       $ Stream.unbox
                       $ Stream.map index
                       $ stream is
  where
    n = length v

    {-# INLINE index #-}
    -- NOTE: we do it this way to avoid triggering LiberateCase on n in
    -- polymorphic code
    index i = UNSAFE_CHECK(checkIndex) "unsafeBackpermute" i n
            $ basicUnsafeIndexM v i

-- Safe destructive updates
-- ------------------------

-- | Apply a destructive operation to a vector. The operation will be
-- performed in place if it is safe to do so and will modify a copy of the
-- vector otherwise.
--
-- @
-- modify (\\v -> 'M.write' v 0 \'x\') ('replicate' 3 \'a\') = \<\'x\',\'a\',\'a\'\>
-- @
modify :: Vector v a => (forall s. Mutable v s a -> ST s ()) -> v a -> v a
{-# INLINE modify #-}
modify p = new . New.modify p . clone

{'fraction_non_alphanumeric': 0.15433231782314985, 'fraction_numerical': 0.009688345601453251, 'mean_word_length': 2.3164731722623157, 'pattern_counts': {'":': 0, '<': 73, '<?xml version=': 0, '>': 509, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3672341', 'n_tokens_mistral': 18413, 'n_tokens_neox': 17661, 'n_words': 6746}