1{-# LANGUAGE CPP, MultiParamTypeClasses, BangPatterns, TypeFamilies #-} 2-- | 3-- Module : Data.Vector.Generic.Mutable.Base 4-- Copyright : (c) Roman Leshchinskiy 2008-2011 5-- License : BSD-style 6-- 7-- Maintainer : Roman Leshchinskiy <rl@cse.unsw.edu.au> 8-- Stability : experimental 9-- Portability : non-portable 10-- 11-- Class of mutable vectors 12-- 13 14module Data.Vector.Generic.Mutable.Base ( 15 MVector(..) 16) where 17 18import Control.Monad.Primitive ( PrimMonad, PrimState ) 19 20-- Data.Vector.Internal.Check is unused 21#define NOT_VECTOR_MODULE 22#include "vector.h" 23 24-- | Class of mutable vectors parametrised with a primitive state token. 25-- 26class MVector v a where 27 -- | Length of the mutable vector. This method should not be 28 -- called directly, use 'length' instead. 29 basicLength :: v s a -> Int 30 31 -- | Yield a part of the mutable vector without copying it. This method 32 -- should not be called directly, use 'unsafeSlice' instead. 33 basicUnsafeSlice :: Int -- ^ starting index 34 -> Int -- ^ length of the slice 35 -> v s a 36 -> v s a 37 38 -- | Check whether two vectors overlap. This method should not be 39 -- called directly, use 'overlaps' instead. 40 basicOverlaps :: v s a -> v s a -> Bool 41 42 -- | Create a mutable vector of the given length. This method should not be 43 -- called directly, use 'unsafeNew' instead. 44 basicUnsafeNew :: PrimMonad m => Int -> m (v (PrimState m) a) 45 46 -- | Initialize a vector to a standard value. This is intended to be called as 47 -- part of the safe new operation (and similar operations), to properly blank 48 -- the newly allocated memory if necessary. 49 -- 50 -- Vectors that are necessarily initialized as part of creation may implement 51 -- this as a no-op. 52 -- 53 -- @since 0.11.0.0 54 basicInitialize :: PrimMonad m => v (PrimState m) a -> m () 55 56 -- | Create a mutable vector of the given length and fill it with an 57 -- initial value. This method should not be called directly, use 58 -- 'replicate' instead. 59 basicUnsafeReplicate :: PrimMonad m => Int -> a -> m (v (PrimState m) a) 60 61 -- | Yield the element at the given position. This method should not be 62 -- called directly, use 'unsafeRead' instead. 63 basicUnsafeRead :: PrimMonad m => v (PrimState m) a -> Int -> m a 64 65 -- | Replace the element at the given position. This method should not be 66 -- called directly, use 'unsafeWrite' instead. 67 basicUnsafeWrite :: PrimMonad m => v (PrimState m) a -> Int -> a -> m () 68 69 -- | Reset all elements of the vector to some undefined value, clearing all 70 -- references to external objects. This is usually a noop for unboxed 71 -- vectors. This method should not be called directly, use 'clear' instead. 72 basicClear :: PrimMonad m => v (PrimState m) a -> m () 73 74 -- | Set all elements of the vector to the given value. This method should 75 -- not be called directly, use 'set' instead. 76 basicSet :: PrimMonad m => v (PrimState m) a -> a -> m () 77 78 -- | Copy a vector. The two vectors may not overlap. This method should not 79 -- be called directly, use 'unsafeCopy' instead. 80 basicUnsafeCopy :: PrimMonad m => v (PrimState m) a -- ^ target 81 -> v (PrimState m) a -- ^ source 82 -> m () 83 84 -- | Move the contents of a vector. The two vectors may overlap. This method 85 -- should not be called directly, use 'unsafeMove' instead. 86 basicUnsafeMove :: PrimMonad m => v (PrimState m) a -- ^ target 87 -> v (PrimState m) a -- ^ source 88 -> m () 89 90 -- | Grow a vector by the given number of elements. Allocates a new vector and 91 -- copies all of the elements over starting at 0 index. This method should not 92 -- be called directly, use 'grow'\/'unsafeGrow' instead. 93 basicUnsafeGrow :: PrimMonad m => v (PrimState m) a 94 -> Int 95 -> m (v (PrimState m) a) 96 97 {-# INLINE basicUnsafeReplicate #-} 98 basicUnsafeReplicate n x 99 = do 100 v <- basicUnsafeNew n 101 basicSet v x 102 return v 103 104 {-# INLINE basicClear #-} 105 basicClear _ = return () 106 107 {-# INLINE basicSet #-} 108 basicSet !v x 109 | n == 0 = return () 110 | otherwise = do 111 basicUnsafeWrite v 0 x 112 do_set 1 113 where 114 !n = basicLength v 115 116 do_set i | 2*i < n = do basicUnsafeCopy (basicUnsafeSlice i i v) 117 (basicUnsafeSlice 0 i v) 118 do_set (2*i) 119 | otherwise = basicUnsafeCopy (basicUnsafeSlice i (n-i) v) 120 (basicUnsafeSlice 0 (n-i) v) 121 122 {-# INLINE basicUnsafeCopy #-} 123 basicUnsafeCopy !dst !src = do_copy 0 124 where 125 !n = basicLength src 126 127 do_copy i | i < n = do 128 x <- basicUnsafeRead src i 129 basicUnsafeWrite dst i x 130 do_copy (i+1) 131 | otherwise = return () 132 133 {-# INLINE basicUnsafeMove #-} 134 basicUnsafeMove !dst !src 135 | basicOverlaps dst src = do 136 srcCopy <- basicUnsafeNew (basicLength src) 137 basicUnsafeCopy srcCopy src 138 basicUnsafeCopy dst srcCopy 139 | otherwise = basicUnsafeCopy dst src 140 141 {-# INLINE basicUnsafeGrow #-} 142 basicUnsafeGrow v by 143 = do 144 v' <- basicUnsafeNew (n+by) 145 basicUnsafeCopy (basicUnsafeSlice 0 n v') v 146 return v' 147 where 148 n = basicLength v 149 150 {-# MINIMAL basicLength, basicUnsafeSlice, basicOverlaps, 151 basicUnsafeNew, basicInitialize, basicUnsafeRead, 152 basicUnsafeWrite #-} 153