{-# LANGUAGE CPP #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE ScopedTypeVariables #-} #ifndef MIN_VERSION_base #define MIN_VERSION_base(x,y,z) 1 #endif module Data.Vector.Mixed.Mutable ( MVector , IOVector , STVector -- * Accessors -- ** Length information , length, null -- ** Extracting subvectors , slice, init, tail, take, drop, splitAt , unsafeSlice, unsafeInit, unsafeTail, unsafeTake, unsafeDrop -- ** Overlapping , overlaps -- * Construction , replicateM, move, unsafeMove -- ** Initialisation , new, unsafeNew, replicate, clone -- ** Growing , grow, unsafeGrow -- ** Restricting memory usage , clear -- * Accessing individual elements , read, write, swap , unsafeRead, unsafeWrite, unsafeSwap -- * Modifying vectors -- ** Filling and copying , set, copy, unsafeCopy ) where import Control.Monad (liftM) import Control.Monad.Primitive import qualified Data.Vector.Generic.Mutable as G import Data.Vector.Mixed.Internal import Prelude hiding (length, null, replicate, reverse, map, read, take, drop, init, tail, splitAt) type IOVector = MVector RealWorld type STVector = MVector -- Length information -- ------------------ -- | Length of the mutable vector. length :: G.MVector u a => u s a -> Int length = G.length {-# INLINE length #-} -- | Check whether the vector is empty null :: G.MVector u a => u s a -> Bool null = G.null {-# INLINE null #-} -- Extracting subvectors -- --------------------- -- | Yield a part of the mutable vector without copying it. slice :: Mixed u v a => Int -> Int -> u s a -> MVector s a slice i j m = mmix (G.slice i j m) {-# INLINE slice #-} take :: Mixed u v a => Int -> u s a -> MVector s a take i m = mmix (G.take i m) {-# INLINE take #-} drop :: Mixed u v a => Int -> u s a -> MVector s a drop i m = mmix (G.drop i m) {-# INLINE drop #-} splitAt :: Mixed u v a => Int -> u s a -> (MVector s a, MVector s a) splitAt i m = case G.splitAt i m of (l,r) -> (mmix l, mmix r) {-# INLINE splitAt #-} init :: Mixed u v a => u s a -> MVector s a init m = mmix (G.init m) {-# INLINE init #-} tail :: Mixed u v a => u s a -> MVector s a tail m = mmix (G.tail m) {-# INLINE tail #-} -- | Yield a part of the mutable vector without copying it. No bounds checks -- are performed. unsafeSlice :: Mixed u v a => Int -- ^ starting index -> Int -- ^ length of the slice -> u s a -> MVector s a unsafeSlice i j m = mmix (G.unsafeSlice i j m) {-# INLINE unsafeSlice #-} unsafeTake :: Mixed u v a => Int -> u s a -> MVector s a unsafeTake i m = mmix (G.unsafeTake i m) {-# INLINE unsafeTake #-} unsafeDrop :: Mixed u v a => Int -> u s a -> MVector s a unsafeDrop i m = mmix (G.unsafeDrop i m) {-# INLINE unsafeDrop #-} unsafeInit :: Mixed u v a => u s a -> MVector s a unsafeInit m = mmix (G.unsafeInit m) {-# INLINE unsafeInit #-} unsafeTail :: Mixed u v a => u s a -> MVector s a unsafeTail m = mmix (G.unsafeTail m) {-# INLINE unsafeTail #-} -- Overlapping -- ----------- -- Check whether two vectors overlap. overlaps :: (Mixed u v a, Mixed u' v' a) => u s a -> u' s a -> Bool overlaps m n = G.overlaps (mmix m) (mmix n) {-# INLINE overlaps #-} -- Initialisation -- -------------- -- | Create a mutable vector of the given length. new :: PrimMonad m => Int -> m (MVector (PrimState m) a) new = G.new {-# INLINE new #-} -- | Create a mutable vector of the given length. The length is not checked. unsafeNew :: PrimMonad m => Int -> m (MVector (PrimState m) a) unsafeNew n = liftM mboxed (G.unsafeNew n) {-# INLINE unsafeNew #-} -- | Create a mutable vector of the given length (0 if the length is negative) -- and fill it with an initial value. replicate :: PrimMonad m => Int -> a -> m (MVector (PrimState m) a) replicate n a = liftM mboxed (G.replicate n a) {-# INLINE replicate #-} -- | Create a mutable vector of the given length (0 if the length is negative) -- and fill it with values produced by repeatedly executing the monadic action. replicateM :: PrimMonad m => Int -> m a -> m (MVector (PrimState m) a) replicateM n m = liftM mboxed (G.replicateM n m) {-# INLINE replicateM #-} -- | Create a copy of a mutable vector. clone :: (PrimMonad m, Mixed u v a) => u (PrimState m) a -> m (MVector (PrimState m) a) clone m = liftM mmix (G.clone m) {-# INLINE clone #-} -- Growing -- ------- -- | Grow a vector by the given number of elements. The number must be -- positive. grow :: (PrimMonad m, Mixed u v a) => u (PrimState m) a -> Int -> m (MVector (PrimState m) a) grow m n = liftM mmix (G.grow m n) {-# INLINE grow #-} -- | Grow a vector by the given number of elements. The number must be -- positive but this is not checked. unsafeGrow :: (PrimMonad m, Mixed u v a) => u (PrimState m) a -> Int -> m (MVector (PrimState m) a) unsafeGrow m n = liftM mmix (G.unsafeGrow m n) {-# INLINE unsafeGrow #-} -- Restricting memory usage -- ------------------------ -- | Reset all elements of the vector to some undefined value, clearing all -- references to external objects. This is usually a noop for unboxed vectors. clear :: (PrimMonad m, G.MVector u a) => u (PrimState m) a -> m () clear = G.clear {-# INLINE clear #-} -- Accessing individual elements -- ----------------------------- -- | Yield the element at the given position. read :: (PrimMonad m, G.MVector u a) => u (PrimState m) a -> Int -> m a read = G.read {-# INLINE read #-} -- | Replace the element at the given position. write :: (PrimMonad m, G.MVector u a) => u (PrimState m) a -> Int -> a -> m () write = G.write {-# INLINE write #-} -- | Swap the elements at the given positions. swap :: (PrimMonad m, G.MVector u a) => u (PrimState m) a -> Int -> Int -> m () swap = G.swap {-# INLINE swap #-} -- | Yield the element at the given position. No bounds checks are performed. unsafeRead :: (PrimMonad m, G.MVector u a) => u (PrimState m) a -> Int -> m a unsafeRead = G.unsafeRead {-# INLINE unsafeRead #-} -- | Replace the element at the given position. No bounds checks are performed. unsafeWrite :: (PrimMonad m, G.MVector u a) => u (PrimState m) a -> Int -> a -> m () unsafeWrite = G.unsafeWrite {-# INLINE unsafeWrite #-} -- | Swap the elements at the given positions. No bounds checks are performed. unsafeSwap :: (PrimMonad m, G.MVector u a) => u (PrimState m) a -> Int -> Int -> m () unsafeSwap = G.unsafeSwap {-# INLINE unsafeSwap #-} -- Filling and copying -- ------------------- -- | Set all elements of the vector to the given value. set :: (PrimMonad m, G.MVector u a) => u (PrimState m) a -> a -> m () set = G.set {-# INLINE set #-} -- | Copy a vector. The two vectors must have the same length and may not -- overlap. copy :: (PrimMonad m, Mixed u v a, Mixed u' v' a) => u (PrimState m) a -> u' (PrimState m) a -> m () copy dst src = G.copy (mmix dst) (mmix src) {-# INLINE copy #-} -- | Copy a vector. The two vectors must have the same length and may not -- overlap. This is not checked. unsafeCopy :: (PrimMonad m, Mixed u v a, Mixed u' v' a) => u (PrimState m) a -- ^ target -> u' (PrimState m) a -- ^ source -> m () unsafeCopy dst src = G.unsafeCopy (mmix dst) (mmix src) {-# INLINE unsafeCopy #-} -- | Move the contents of a vector. The two vectors must have the same -- length. -- -- If the vectors do not overlap, then this is equivalent to 'copy'. -- Otherwise, the copying is performed as if the source vector were -- copied to a temporary vector and then the temporary vector was copied -- to the target vector. move :: (PrimMonad m, Mixed u v a, Mixed u' v' a) => u (PrimState m) a -> u' (PrimState m) a -> m () move dst src = G.move (mmix dst) (mmix src) {-# INLINE move #-} -- | Move the contents of a vector. The two vectors must have the same -- length, but this is not checked. -- -- If the vectors do not overlap, then this is equivalent to 'unsafeCopy'. -- Otherwise, the copying is performed as if the source vector were -- copied to a temporary vector and then the temporary vector was copied -- to the target vector. unsafeMove :: (PrimMonad m, Mixed u v a, Mixed u' v' a) => u (PrimState m) a -- ^ target -> u' (PrimState m) a -- ^ source -> m () unsafeMove dst src = G.unsafeMove (mmix dst) (mmix src) {-# INLINE unsafeMove #-}