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