packages feed

vector 0.12.3.0 → 0.12.3.1

raw patch · 13 files changed

+265/−191 lines, 13 filesdep ~basedep ~deepseqdep ~doctest

Dependency ranges changed: base, deepseq, doctest, ghc-prim, primitive, semigroups

Files

Data/Vector.hs view
@@ -351,7 +351,7 @@   mempty = empty    {-# INLINE mappend #-}-  mappend = (++)+  mappend = (<>)    {-# INLINE mconcat #-}   mconcat = concat@@ -2002,8 +2002,32 @@ {-# INLINE unsafeFreeze #-} unsafeFreeze = G.unsafeFreeze --- | /O(1)/ Unsafely convert an immutable vector to a mutable one without--- copying. The immutable vector may not be used after this operation.+-- | /O(1)/ Unsafely convert an immutable vector to a mutable one+-- without copying. Note that this is very dangerous function and+-- generally it's only safe to read from resulting vector. In which+-- case immutable vector could be used safely as well.+--+-- Problem with mutation happens because GHC has a lot of freedom to+-- introduce sharing. As a result mutable vectors produced by+-- @unsafeThaw@ may or may not share same underlying buffer. For+-- example:+--+-- > foo = do+-- >   let vec = V.generate 10 id+-- >   mvec <- V.unsafeThaw vec+-- >   do_something mvec+--+-- Here GHC could lift @vec@ outside of foo which means all calls to+-- @do_something@ will use same buffer with possibly disastrous+-- results. Whether such aliasing happens or not depends on program in+-- question, optimization levels, and GHC flags.+--+-- All in all attempts to modify vector after unsafeThaw falls out of+-- domain of software engineering and into realm of black magic, dark+-- rituals, and unspeakable horrors. Only advice that could be given+-- is: "don't attempt to mutate vector after unsafeThaw unless you+-- know how to prevent GHC from aliasing buffers accidentally. We+-- don't" unsafeThaw :: PrimMonad m => Vector a -> m (MVector (PrimState m) a) {-# INLINE unsafeThaw #-} unsafeThaw = G.unsafeThaw
Data/Vector/Generic.hs view
@@ -2164,8 +2164,32 @@ {-# INLINE freeze #-} freeze mv = unsafeFreeze =<< M.clone mv --- | /O(1)/ Unsafely convert an immutable vector to a mutable one without--- copying. The immutable vector may not be used after this operation.+-- | /O(1)/ Unsafely convert an immutable vector to a mutable one+-- without copying. Note that this is very dangerous function and+-- generally it's only safe to read from resulting vector. In which+-- case immutable vector could be used safely as well.+--+-- Problem with mutation happens because GHC has a lot of freedom to+-- introduce sharing. As a result mutable vectors produced by+-- @unsafeThaw@ may or may not share same underlying buffer. For+-- example:+--+-- > foo = do+-- >   let vec = V.generate 10 id+-- >   mvec <- V.unsafeThaw vec+-- >   do_something mvec+--+-- Here GHC could lift @vec@ outside of foo which means all calls to+-- @do_something@ will use same buffer with possibly disastrous+-- results. Whether such aliasing happens or not depends on program in+-- question, optimization levels, and GHC flags.+--+-- All in all attempts to modify vector after unsafeThaw falls out of+-- domain of software engineering and into realm of black magic, dark+-- rituals, and unspeakable horrors. Only advice that could be given+-- is: "don't attempt to mutate vector after unsafeThaw unless you+-- know how to prevent GHC from aliasing buffers accidentally. We+-- don't" unsafeThaw :: (PrimMonad m, Vector v a) => v a -> m (Mutable v (PrimState m) a) {-# INLINE_FUSED unsafeThaw #-} unsafeThaw = basicUnsafeThaw
Data/Vector/Generic/Mutable.hs view
@@ -85,135 +85,7 @@  #include "vector.h" -{--type family Immutable (v :: * -> * -> *) :: * -> * --- | Class of mutable vectors parametrised with a primitive state token.----class MBundle.Pointer u a => MVector v a where-  -- | Length of the mutable vector. This method should not be-  -- called directly, use 'length' instead.-  basicLength       :: v s a -> Int--  -- | Yield a part of the mutable vector without copying it. This method-  -- should not be called directly, use 'unsafeSlice' instead.-  basicUnsafeSlice :: Int  -- ^ starting index-                   -> Int  -- ^ length of the slice-                   -> v s a-                   -> v s a--  -- Check whether two vectors overlap. This method should not be-  -- called directly, use 'overlaps' instead.-  basicOverlaps    :: v s a -> v s a -> Bool--  -- | Create a mutable vector of the given length. This method should not be-  -- called directly, use 'unsafeNew' instead.-  basicUnsafeNew   :: PrimMonad m => Int -> m (v (PrimState m) a)--  -- | Create a mutable vector of the given length and fill it with an-  -- initial value. This method should not be called directly, use-  -- 'replicate' instead.-  basicUnsafeReplicate :: PrimMonad m => Int -> a -> m (v (PrimState m) a)--  -- | Yield the element at the given position. This method should not be-  -- called directly, use 'unsafeRead' instead.-  basicUnsafeRead  :: PrimMonad m => v (PrimState m) a -> Int -> m a--  -- | Replace the element at the given position. This method should not be-  -- called directly, use 'unsafeWrite' instead.-  basicUnsafeWrite :: PrimMonad m => v (PrimState m) a -> Int -> a -> m ()--  -- | Reset all elements of the vector to some undefined value, clearing all-  -- references to external objects. This is usually a noop for unboxed-  -- vectors. This method should not be called directly, use 'clear' instead.-  basicClear       :: PrimMonad m => v (PrimState m) a -> m ()--  -- | Set all elements of the vector to the given value. This method should-  -- not be called directly, use 'set' instead.-  basicSet         :: PrimMonad m => v (PrimState m) a -> a -> m ()--  basicUnsafeCopyPointer :: PrimMonad m => v (PrimState m) a-                                        -> Immutable v a-                                        -> m ()--  -- | Copy a vector. The two vectors may not overlap. This method should not-  -- be called directly, use 'unsafeCopy' instead.-  basicUnsafeCopy  :: PrimMonad m => v (PrimState m) a   -- ^ target-                                  -> v (PrimState m) a   -- ^ source-                                  -> m ()--  -- | Move the contents of a vector. The two vectors may overlap. This method-  -- should not be called directly, use 'unsafeMove' instead.-  basicUnsafeMove  :: PrimMonad m => v (PrimState m) a   -- ^ target-                                  -> v (PrimState m) a   -- ^ source-                                  -> m ()--  -- | Grow a vector by the given number of elements. This method should not be-  -- called directly, use 'unsafeGrow' instead.-  basicUnsafeGrow  :: PrimMonad m => v (PrimState m) a -> Int-                                                       -> m (v (PrimState m) a)--  {-# INLINE basicUnsafeReplicate #-}-  basicUnsafeReplicate n x-    = do-        v <- basicUnsafeNew n-        basicSet v x-        return v--  {-# INLINE basicClear #-}-  basicClear _ = return ()--  {-# INLINE basicSet #-}-  basicSet !v x-    | n == 0    = return ()-    | otherwise = do-                    basicUnsafeWrite v 0 x-                    do_set 1-    where-      !n = basicLength v--      do_set i | 2*i < n = do basicUnsafeCopy (basicUnsafeSlice i i v)-                                              (basicUnsafeSlice 0 i v)-                              do_set (2*i)-               | otherwise = basicUnsafeCopy (basicUnsafeSlice i (n-i) v)-                                             (basicUnsafeSlice 0 (n-i) v)--  {-# INLINE basicUnsafeCopyPointer #-}-  basicUnsafeCopyPointer !dst !src = do_copy 0 src-    where-      do_copy !i p | Just (x,q) <- MBundle.pget p = do-                                                      basicUnsafeWrite dst i x-                                                      do_copy (i+1) q-                   | otherwise = return ()--  {-# INLINE basicUnsafeCopy #-}-  basicUnsafeCopy !dst !src = do_copy 0-    where-      !n = basicLength src--      do_copy i | i < n = do-                            x <- basicUnsafeRead src i-                            basicUnsafeWrite dst i x-                            do_copy (i+1)-                | otherwise = return ()--  {-# INLINE basicUnsafeMove #-}-  basicUnsafeMove !dst !src-    | basicOverlaps dst src = do-        srcCopy <- clone src-        basicUnsafeCopy dst srcCopy-    | otherwise = basicUnsafeCopy dst src--  {-# INLINE basicUnsafeGrow #-}-  basicUnsafeGrow v by-    = do-        v' <- basicUnsafeNew (n+by)-        basicUnsafeCopy (basicUnsafeSlice 0 n v') v-        return v'-    where-      n = basicLength v--}- -- ------------------ -- Internal functions -- ------------------@@ -334,16 +206,6 @@                Just n  -> munstreamMax     s n                Nothing -> munstreamUnknown s --- FIXME: I can't think of how to prevent GHC from floating out--- unstreamUnknown. That is bad because SpecConstr then generates two--- specialisations: one for when it is called from unstream (it doesn't know--- the shape of the vector) and one for when the vector has grown. To see the--- problem simply compile this:------ fromList = Data.Vector.Unboxed.unstream . Bundle.fromList------ I'm not sure this still applies (19/04/2010)- munstreamMax :: (PrimMonad m, MVector v a)              => MBundle m u a -> Int -> m (v (PrimState m) a) {-# INLINE munstreamMax #-}@@ -399,16 +261,6 @@                Just n  -> vmunstreamMax     s n                Nothing -> vmunstreamUnknown s --- FIXME: I can't think of how to prevent GHC from floating out--- unstreamUnknown. That is bad because SpecConstr then generates two--- specialisations: one for when it is called from unstream (it doesn't know--- the shape of the vector) and one for when the vector has grown. To see the--- problem simply compile this:------ fromList = Data.Vector.Unboxed.unstream . Bundle.fromList------ I'm not sure this still applies (19/04/2010)- vmunstreamMax :: (PrimMonad m, V.Vector v a)               => MBundle m v a -> Int -> m (V.Mutable v (PrimState m) a) {-# INLINE vmunstreamMax #-}@@ -526,10 +378,16 @@ slice i n v = BOUNDS_CHECK(checkSlice) "slice" i n (length v)             $ unsafeSlice i n v +-- | Take @n@ first elements of the mutable vector without making a+-- copy. For negative @n@ empty vector is returned. If @n@ is larger+-- than vector's length empty vector is returned, take :: MVector v a => Int -> v s a -> v s a {-# INLINE take #-} take n v = unsafeSlice 0 (min (max n 0) (length v)) v +-- | Drop @n@ first element of the mutable vector without making a+-- copy. For negative @n@ vector is returned unchanged and if @n@ is+-- larger than vector's length empty vector is returned. drop :: MVector v a => Int -> v s a -> v s a {-# INLINE drop #-} drop n v = unsafeSlice (min m n') (max 0 (m - n')) v@@ -547,10 +405,14 @@       n'  = max n 0       len = length v +-- | Drop last element of the mutable vector without making a copy. If+-- vector is empty exception is thrown. init :: MVector v a => v s a -> v s a {-# INLINE init #-} init v = slice 0 (length v - 1) v +-- | Drop first element of the mutable vector without making a copy. If+-- vector is empty exception is thrown. tail :: MVector v a => v s a -> v s a {-# INLINE tail #-} tail v = slice 1 (length v - 1) v@@ -565,18 +427,24 @@ unsafeSlice i n v = UNSAFE_CHECK(checkSlice) "unsafeSlice" i n (length v)                   $ basicUnsafeSlice i n v +-- | Same as 'init' but doesn't do range checks. unsafeInit :: MVector v a => v s a -> v s a {-# INLINE unsafeInit #-} unsafeInit v = unsafeSlice 0 (length v - 1) v +-- | Same as 'tail' but doesn't do range checks. unsafeTail :: MVector v a => v s a -> v s a {-# INLINE unsafeTail #-} unsafeTail v = unsafeSlice 1 (length v - 1) v +-- | Unsafe variant of 'take'. If called with out of range @n@ it will+-- simply create invalid slice that likely violate memory safety unsafeTake :: MVector v a => Int -> v s a -> v s a {-# INLINE unsafeTake #-} unsafeTake n v = unsafeSlice 0 n v +-- | Unsafe variant of 'drop'. If called with out of range @n@ it will+-- simply create invalid slice that likely violate memory safety unsafeDrop :: MVector v a => Int -> v s a -> v s a {-# INLINE unsafeDrop #-} unsafeDrop n v = unsafeSlice n (length v - n) v
Data/Vector/Mutable.hs view
@@ -14,7 +14,7 @@  module Data.Vector.Mutable (   -- * Mutable boxed vectors-  MVector(..), IOVector, STVector,+  MVector(MVector), IOVector, STVector,    -- * Accessors @@ -76,9 +76,13 @@   -- | Mutable boxed vectors keyed on the monad they live in ('IO' or @'ST' s@).-data MVector s a = MVector {-# UNPACK #-} !Int                -- ^ Offset in underlying array-                           {-# UNPACK #-} !Int                -- ^ Size of slice-                           {-# UNPACK #-} !(MutableArray s a) -- ^ Underlying array+data MVector s a = MVector { _offset :: {-# UNPACK #-} !Int+                           -- ^ Offset in underlying array+                           , _size   :: {-# UNPACK #-} !Int+                           -- ^ Size of slice+                           , _array  :: {-# UNPACK #-} !(MutableArray s a)+                           -- ^ Underlying array+                           }         deriving ( Typeable )  type IOVector = MVector RealWorld@@ -225,10 +229,16 @@ {-# INLINE slice #-} slice = G.slice +-- | Take @n@ first elements of the mutable vector without making a+-- copy. For negative @n@ empty vector is returned. If @n@ is larger+-- than vector's length empty vector is returned, take :: Int -> MVector s a -> MVector s a {-# INLINE take #-} take = G.take +-- | Drop @n@ first element of the mutable vector without making a+-- copy. For negative @n@ vector is returned unchanged and if @n@ is+-- larger than vector's length empty vector is returned. drop :: Int -> MVector s a -> MVector s a {-# INLINE drop #-} drop = G.drop@@ -237,10 +247,14 @@ splitAt :: Int -> MVector s a -> (MVector s a, MVector s a) splitAt = G.splitAt +-- | Drop last element of the mutable vector without making a copy. If+-- vector is empty exception is thrown. init :: MVector s a -> MVector s a {-# INLINE init #-} init = G.init +-- | Drop first element of the mutable vector without making a copy. If+-- vector is empty exception is thrown. tail :: MVector s a -> MVector s a {-# INLINE tail #-} tail = G.tail@@ -254,18 +268,24 @@ {-# INLINE unsafeSlice #-} unsafeSlice = G.unsafeSlice +-- | Unsafe variant of 'take'. If called with out of range @n@ it will+-- simply create invalid slice that likely violate memory safety unsafeTake :: Int -> MVector s a -> MVector s a {-# INLINE unsafeTake #-} unsafeTake = G.unsafeTake +-- | Unsafe variant of 'drop'. If called with out of range @n@ it will+-- simply create invalid slice that likely violate memory safety unsafeDrop :: Int -> MVector s a -> MVector s a {-# INLINE unsafeDrop #-} unsafeDrop = G.unsafeDrop +-- | Same as 'init' but doesn't do range checks. unsafeInit :: MVector s a -> MVector s a {-# INLINE unsafeInit #-} unsafeInit = G.unsafeInit +-- | Same as 'tail' but doesn't do range checks. unsafeTail :: MVector s a -> MVector s a {-# INLINE unsafeTail #-} unsafeTail = G.unsafeTail@@ -352,16 +372,16 @@ -- -- >>> MV.write mv' 3 999 -- >>> MV.write mv' 4 777--- >>> V.unsafeFreeze mv'+-- >>> V.freeze mv' -- [10,20,30,999,777] -- -- It is important to note that the source mutable vector is not affected when -- the newly allocated one is mutated. -- -- >>> MV.write mv' 2 888--- >>> V.unsafeFreeze mv'+-- >>> V.freeze mv' -- [10,20,888,999,777]--- >>> V.unsafeFreeze mv+-- >>> V.freeze mv -- [10,20,30] -- -- @since 0.5
Data/Vector/Primitive.hs view
@@ -290,7 +290,7 @@   mempty = empty    {-# INLINE mappend #-}-  mappend = (++)+  mappend = (<>)    {-# INLINE mconcat #-}   mconcat = concat@@ -1685,8 +1685,32 @@ {-# INLINE unsafeFreeze #-} unsafeFreeze = G.unsafeFreeze --- | /O(1)/ Unsafely convert an immutable vector to a mutable one without--- copying. The immutable vector may not be used after this operation.+-- | /O(1)/ Unsafely convert an immutable vector to a mutable one+-- without copying. Note that this is very dangerous function and+-- generally it's only safe to read from resulting vector. In which+-- case immutable vector could be used safely as well.+--+-- Problem with mutation happens because GHC has a lot of freedom to+-- introduce sharing. As a result mutable vectors produced by+-- @unsafeThaw@ may or may not share same underlying buffer. For+-- example:+--+-- > foo = do+-- >   let vec = V.generate 10 id+-- >   mvec <- V.unsafeThaw vec+-- >   do_something mvec+--+-- Here GHC could lift @vec@ outside of foo which means all calls to+-- @do_something@ will use same buffer with possibly disastrous+-- results. Whether such aliasing happens or not depends on program in+-- question, optimization levels, and GHC flags.+--+-- All in all attempts to modify vector after unsafeThaw falls out of+-- domain of software engineering and into realm of black magic, dark+-- rituals, and unspeakable horrors. Only advice that could be given+-- is: "don't attempt to mutate vector after unsafeThaw unless you+-- know how to prevent GHC from aliasing buffers accidentally. We+-- don't" unsafeThaw :: (Prim a, PrimMonad m) => Vector a -> m (MVector (PrimState m) a) {-# INLINE unsafeThaw #-} unsafeThaw = G.unsafeThaw
Data/Vector/Primitive/Mutable.hs view
@@ -111,7 +111,7 @@   {-# INLINE basicUnsafeNew #-}   basicUnsafeNew n     | n < 0 = error $ "Primitive.basicUnsafeNew: negative length: " ++ show n-    | n > mx = error $ "Primitive.basicUnsafeNew: length to large: " ++ show n+    | n > mx = error $ "Primitive.basicUnsafeNew: length too large: " ++ show n     | otherwise = MVector 0 n `liftM` newByteArray (n * size)     where       size = sizeOf (undefined :: a)@@ -171,10 +171,16 @@ {-# INLINE slice #-} slice = G.slice +-- | Take @n@ first elements of the mutable vector without making a+-- copy. For negative @n@ empty vector is returned. If @n@ is larger+-- than vector's length empty vector is returned, take :: Prim a => Int -> MVector s a -> MVector s a {-# INLINE take #-} take = G.take +-- | Drop @n@ first element of the mutable vector without making a+-- copy. For negative @n@ vector is returned unchanged and if @n@ is+-- larger than vector's length empty vector is returned. drop :: Prim a => Int -> MVector s a -> MVector s a {-# INLINE drop #-} drop = G.drop@@ -183,10 +189,14 @@ {-# INLINE splitAt #-} splitAt = G.splitAt +-- | Drop last element of the mutable vector without making a copy. If+-- vector is empty exception is thrown. init :: Prim a => MVector s a -> MVector s a {-# INLINE init #-} init = G.init +-- | Drop first element of the mutable vector without making a copy. If+-- vector is empty exception is thrown. tail :: Prim a => MVector s a -> MVector s a {-# INLINE tail #-} tail = G.tail@@ -201,18 +211,24 @@ {-# INLINE unsafeSlice #-} unsafeSlice = G.unsafeSlice +-- | Unsafe variant of 'take'. If called with out of range @n@ it will+-- simply create invalid slice that likely violate memory safety unsafeTake :: Prim a => Int -> MVector s a -> MVector s a {-# INLINE unsafeTake #-} unsafeTake = G.unsafeTake +-- | Unsafe variant of 'drop'. If called with out of range @n@ it will+-- simply create invalid slice that likely violate memory safety unsafeDrop :: Prim a => Int -> MVector s a -> MVector s a {-# INLINE unsafeDrop #-} unsafeDrop = G.unsafeDrop +-- | Same as 'init' but doesn't do range checks. unsafeInit :: Prim a => MVector s a -> MVector s a {-# INLINE unsafeInit #-} unsafeInit = G.unsafeInit +-- | Same as 'tail' but doesn't do range checks. unsafeTail :: Prim a => MVector s a -> MVector s a {-# INLINE unsafeTail #-} unsafeTail = G.unsafeTail@@ -296,22 +312,22 @@ -- etc. However, if `unsafeGrow` was used instead this would not have been -- guaranteed and some garbage would be there instead: ----- >>> VP.unsafeFreeze mv'+-- >>> VP.freeze mv' -- [10,20,30,0,0] -- -- Having the extra space we can write new values in there: -- -- >>> MVP.write mv' 3 999--- >>> VP.unsafeFreeze mv'+-- >>> VP.freeze mv' -- [10,20,30,999,0] -- -- It is important to note that the source mutable vector is not affected when -- the newly allocated one is mutated. -- -- >>> MVP.write mv' 2 888--- >>> VP.unsafeFreeze mv'+-- >>> VP.freeze mv' -- [10,20,888,999,0]--- >>> VP.unsafeFreeze mv+-- >>> VP.freeze mv -- [10,20,30] -- -- @since 0.5
Data/Vector/Storable.hs view
@@ -305,7 +305,7 @@   mempty = empty    {-# INLINE mappend #-}-  mappend = (++)+  mappend = (<>)    {-# INLINE mconcat #-}   mconcat = concat@@ -1753,8 +1753,32 @@ {-# INLINE unsafeFreeze #-} unsafeFreeze = G.unsafeFreeze --- | /O(1)/ Unsafely convert an immutable vector to a mutable one without--- copying. The immutable vector may not be used after this operation.+-- | /O(1)/ Unsafely convert an immutable vector to a mutable one+-- without copying. Note that this is very dangerous function and+-- generally it's only safe to read from resulting vector. In which+-- case immutable vector could be used safely as well.+--+-- Problem with mutation happens because GHC has a lot of freedom to+-- introduce sharing. As a result mutable vectors produced by+-- @unsafeThaw@ may or may not share same underlying buffer. For+-- example:+--+-- > foo = do+-- >   let vec = V.generate 10 id+-- >   mvec <- V.unsafeThaw vec+-- >   do_something mvec+--+-- Here GHC could lift @vec@ outside of foo which means all calls to+-- @do_something@ will use same buffer with possibly disastrous+-- results. Whether such aliasing happens or not depends on program in+-- question, optimization levels, and GHC flags.+--+-- All in all attempts to modify vector after unsafeThaw falls out of+-- domain of software engineering and into realm of black magic, dark+-- rituals, and unspeakable horrors. Only advice that could be given+-- is: "don't attempt to mutate vector after unsafeThaw unless you+-- know how to prevent GHC from aliasing buffers accidentally. We+-- don't" unsafeThaw         :: (Storable a, PrimMonad m) => Vector a -> m (MVector (PrimState m) a) {-# INLINE unsafeThaw #-}
Data/Vector/Storable/Mutable.hs view
@@ -205,7 +205,9 @@                   1 -> storableSetAsPrim n fp x (undefined :: Word8)                   2 -> storableSetAsPrim n fp x (undefined :: Word16)                   4 -> storableSetAsPrim n fp x (undefined :: Word32)+#if !defined(ghcjs_HOST_OS)                   8 -> storableSetAsPrim n fp x (undefined :: Word64)+#endif                   _ -> unsafeWithForeignPtr fp $ \p -> do                        poke p x @@ -300,10 +302,16 @@ {-# INLINE slice #-} slice = G.slice +-- | Take @n@ first elements of the mutable vector without making a+-- copy. For negative @n@ empty vector is returned. If @n@ is larger+-- than vector's length empty vector is returned, take :: Storable a => Int -> MVector s a -> MVector s a {-# INLINE take #-} take = G.take +-- | Drop @n@ first element of the mutable vector without making a+-- copy. For negative @n@ vector is returned unchanged and if @n@ is+-- larger than vector's length empty vector is returned. drop :: Storable a => Int -> MVector s a -> MVector s a {-# INLINE drop #-} drop = G.drop@@ -312,10 +320,14 @@ {-# INLINE splitAt #-} splitAt = G.splitAt +-- | Drop last element of the mutable vector without making a copy. If+-- vector is empty exception is thrown. init :: Storable a => MVector s a -> MVector s a {-# INLINE init #-} init = G.init +-- | Drop first element of the mutable vector without making a copy. If+-- vector is empty exception is thrown. tail :: Storable a => MVector s a -> MVector s a {-# INLINE tail #-} tail = G.tail@@ -330,18 +342,24 @@ {-# INLINE unsafeSlice #-} unsafeSlice = G.unsafeSlice +-- | Unsafe variant of 'take'. If called with out of range @n@ it will+-- simply create invalid slice that likely violate memory safety unsafeTake :: Storable a => Int -> MVector s a -> MVector s a {-# INLINE unsafeTake #-} unsafeTake = G.unsafeTake +-- | Unsafe variant of 'drop'. If called with out of range @n@ it will+-- simply create invalid slice that likely violate memory safety unsafeDrop :: Storable a => Int -> MVector s a -> MVector s a {-# INLINE unsafeDrop #-} unsafeDrop = G.unsafeDrop +-- | Same as 'init' but doesn't do range checks. unsafeInit :: Storable a => MVector s a -> MVector s a {-# INLINE unsafeInit #-} unsafeInit = G.unsafeInit +-- | Same as 'tail' but doesn't do range checks. unsafeTail :: Storable a => MVector s a -> MVector s a {-# INLINE unsafeTail #-} unsafeTail = G.unsafeTail@@ -425,22 +443,22 @@ -- etc. However, if `unsafeGrow` was used instead this would not have been -- guaranteed and some garbage would be there instead: ----- >>> VS.unsafeFreeze mv'+-- >>> VS.freeze mv' -- [10,20,30,0,0] -- -- Having the extra space we can write new values in there: -- -- >>> MVS.write mv' 3 999--- >>> VS.unsafeFreeze mv'+-- >>> VS.freeze mv' -- [10,20,30,999,0] -- -- It is important to note that the source mutable vector is not affected when -- the newly allocated one is mutated. -- -- >>> MVS.write mv' 2 888--- >>> VS.unsafeFreeze mv'+-- >>> VS.freeze mv' -- [10,20,888,999,0]--- >>> VS.unsafeFreeze mv+-- >>> VS.freeze mv -- [10,20,30] -- -- @since 0.5
Data/Vector/Unboxed.hs view
@@ -249,7 +249,7 @@   mempty = empty    {-# INLINE mappend #-}-  mappend = (++)+  mappend = (<>)    {-# INLINE mconcat #-}   mconcat = concat@@ -1711,8 +1711,32 @@ {-# INLINE unsafeFreeze #-} unsafeFreeze = G.unsafeFreeze --- | /O(1)/ Unsafely convert an immutable vector to a mutable one without--- copying. The immutable vector may not be used after this operation.+-- | /O(1)/ Unsafely convert an immutable vector to a mutable one+-- without copying. Note that this is very dangerous function and+-- generally it's only safe to read from resulting vector. In which+-- case immutable vector could be used safely as well.+--+-- Problem with mutation happens because GHC has a lot of freedom to+-- introduce sharing. As a result mutable vectors produced by+-- @unsafeThaw@ may or may not share same underlying buffer. For+-- example:+--+-- > foo = do+-- >   let vec = V.generate 10 id+-- >   mvec <- V.unsafeThaw vec+-- >   do_something mvec+--+-- Here GHC could lift @vec@ outside of foo which means all calls to+-- @do_something@ will use same buffer with possibly disastrous+-- results. Whether such aliasing happens or not depends on program in+-- question, optimization levels, and GHC flags.+--+-- All in all attempts to modify vector after unsafeThaw falls out of+-- domain of software engineering and into realm of black magic, dark+-- rituals, and unspeakable horrors. Only advice that could be given+-- is: "don't attempt to mutate vector after unsafeThaw unless you+-- know how to prevent GHC from aliasing buffers accidentally. We+-- don't" unsafeThaw :: (Unbox a, PrimMonad m) => Vector a -> m (MVector (PrimState m) a) {-# INLINE unsafeThaw #-} unsafeThaw = G.unsafeThaw
Data/Vector/Unboxed/Mutable.hs view
@@ -100,10 +100,16 @@ {-# INLINE slice #-} slice = G.slice +-- | Take @n@ first elements of the mutable vector without making a+-- copy. For negative @n@ empty vector is returned. If @n@ is larger+-- than vector's length empty vector is returned, take :: Unbox a => Int -> MVector s a -> MVector s a {-# INLINE take #-} take = G.take +-- | Drop @n@ first element of the mutable vector without making a+-- copy. For negative @n@ vector is returned unchanged and if @n@ is+-- larger than vector's length empty vector is returned. drop :: Unbox a => Int -> MVector s a -> MVector s a {-# INLINE drop #-} drop = G.drop@@ -112,10 +118,14 @@ {-# INLINE splitAt #-} splitAt = G.splitAt +-- | Drop last element of the mutable vector without making a copy. If+-- vector is empty exception is thrown. init :: Unbox a => MVector s a -> MVector s a {-# INLINE init #-} init = G.init +-- | Drop first element of the mutable vector without making a copy. If+-- vector is empty exception is thrown. tail :: Unbox a => MVector s a -> MVector s a {-# INLINE tail #-} tail = G.tail@@ -130,18 +140,24 @@ {-# INLINE unsafeSlice #-} unsafeSlice = G.unsafeSlice +-- | Unsafe variant of 'take'. If called with out of range @n@ it will+-- simply create invalid slice that likely violate memory safety unsafeTake :: Unbox a => Int -> MVector s a -> MVector s a {-# INLINE unsafeTake #-} unsafeTake = G.unsafeTake +-- | Unsafe variant of 'drop'. If called with out of range @n@ it will+-- simply create invalid slice that likely violate memory safety unsafeDrop :: Unbox a => Int -> MVector s a -> MVector s a {-# INLINE unsafeDrop #-} unsafeDrop = G.unsafeDrop +-- | Same as 'init' but doesn't do range checks. unsafeInit :: Unbox a => MVector s a -> MVector s a {-# INLINE unsafeInit #-} unsafeInit = G.unsafeInit +-- | Same as 'tail' but doesn't do range checks. unsafeTail :: Unbox a => MVector s a -> MVector s a {-# INLINE unsafeTail #-} unsafeTail = G.unsafeTail@@ -225,22 +241,22 @@ -- etc. However, if `unsafeGrow` was used instead this would not have been -- guaranteed and some garbage would be there instead: ----- >>> VU.unsafeFreeze mv'+-- >>> VU.freeze mv' -- [('a',10),('b',20),('c',30),('\NUL',0),('\NUL',0)] -- -- Having the extra space we can write new values in there: -- -- >>> MVU.write mv' 3 ('d', 999)--- >>> VU.unsafeFreeze mv'+-- >>> VU.freeze mv' -- [('a',10),('b',20),('c',30),('d',999),('\NUL',0)] -- -- It is important to note that the source mutable vector is not affected when -- the newly allocated one is mutated. -- -- >>> MVU.write mv' 2 ('X', 888)--- >>> VU.unsafeFreeze mv'+-- >>> VU.freeze mv' -- [('a',10),('b',20),('X',888),('d',999),('\NUL',0)]--- >>> VU.unsafeFreeze mv+-- >>> VU.freeze mv -- [('a',10),('b',20),('c',30)] -- -- @since 0.5
changelog.md view
@@ -1,3 +1,11 @@+# Changes in version 0.12.3.1++* Bugfix for ghcjs and `Double` memset for `Storable` vector:+  [#410](https://github.com/haskell/vector/issues/410)+* Avoid haddock bug: [#383](https://github.com/haskell/vector/issues/383)+* Improve haddock and doctests+* Disable problematic tests with -boundschecks [#407](https://github.com/haskell/vector/pull/407)+ # Changes in version 0.12.3.0   * Fix performance regression due to introduction of `keepAlive#` primop in ghc-9.0: [#372](https://github.com/haskell/vector/pull/372)
tests/Tests/Vector/UnitTests.hs view
@@ -13,6 +13,7 @@ import qualified Data.List as List import qualified Data.Vector.Generic  as Generic import qualified Data.Vector as Boxed+import qualified Data.Vector.Internal.Check as Check import qualified Data.Vector.Mutable as MBoxed import qualified Data.Vector.Primitive as Primitive import qualified Data.Vector.Storable as Storable@@ -44,6 +45,12 @@     dummy :: a     dummy = undefined +withBoundsChecksOnly :: [TestTree] -> [TestTree]+withBoundsChecksOnly ts =+  if Check.doChecks Check.Bounds+     then ts+     else []+ tests :: [TestTree] tests =   [ testGroup "Data.Vector.Storable.Vector Alignment"@@ -67,14 +74,15 @@       , regression188 ([] :: [Char])       ]     ]-  , testGroup "Negative tests"-    [ testGroup "slice out of bounds #257"+  , testGroup "Negative tests" $+    withBoundsChecksOnly [ testGroup "slice out of bounds #257"       [ testGroup "Boxed" $ testsSliceOutOfBounds Boxed.slice       , testGroup "Primitive" $ testsSliceOutOfBounds Primitive.slice       , testGroup "Storable" $ testsSliceOutOfBounds Storable.slice       , testGroup "Unboxed" $ testsSliceOutOfBounds Unboxed.slice-      ]-    , testGroup "take #282"+      ]]+    +++    [ testGroup "take #282"       [ testCase "Boxed" $ testTakeOutOfMemory Boxed.take       , testCase "Primitive" $ testTakeOutOfMemory Primitive.take       , testCase "Storable" $ testTakeOutOfMemory Storable.take
vector.cabal view
@@ -1,5 +1,5 @@ Name:           vector-Version:        0.12.3.0+Version:        0.12.3.1 -- don't forget to update the changelog file! License:        BSD3 License-File:   LICENSE@@ -152,9 +152,9 @@   Install-Includes:         vector.h -  Build-Depends: base >= 4.5 && < 4.16+  Build-Depends: base >= 4.5 && < 4.17                , primitive >= 0.6.4.0 && < 0.8-               , ghc-prim >= 0.2 && < 0.8+               , ghc-prim >= 0.2 && < 0.9                , deepseq >= 1.1 && < 1.5   if !impl(ghc > 8.0)     Build-Depends: fail == 4.9.*@@ -277,7 +277,7 @@   main-is:          doctests.hs   hs-source-dirs:   tests   default-language: Haskell2010-  -- Older GHC choke on {-# UNPACK #-} pragma for some reason+  -- Older GHC don't support DerivingVia   if impl(ghc < 8.6)     buildable: False   -- GHC 8.10 fails to run doctests for some reason@@ -285,6 +285,6 @@     buildable: False   build-depends:         base      -any-      , doctest   >=0.15 && <0.18+      , doctest   >=0.15 && <0.19       , primitive >= 0.6.4.0 && < 0.8       , vector    -any