Export create, modify and copy/unsafeCopy
[darcs-mirrors/vector.git] / Data / Vector / Primitive.hs
index e7cbf04..741e575 100644 (file)
@@ -1,8 +1,8 @@
-{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, TypeFamilies #-}
+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, TypeFamilies, ScopedTypeVariables, Rank2Types #-}
 
 -- |
 -- Module      : Data.Vector.Primitive
--- Copyright   : (c) Roman Leshchinskiy 2008-2009
+-- Copyright   : (c) Roman Leshchinskiy 2008-2010
 -- License     : BSD-style
 --
 -- Maintainer  : Roman Leshchinskiy <rl@cse.unsw.edu.au>
@@ -19,7 +19,7 @@ module Data.Vector.Primitive (
   length, null,
 
   -- * Construction
-  empty, singleton, cons, snoc, replicate, generate, (++), copy,
+  empty, singleton, cons, snoc, replicate, generate, (++), force,
 
   -- * Accessing individual elements
   (!), head, last, indexM, headM, lastM,
@@ -75,16 +75,21 @@ module Data.Vector.Primitive (
   enumFromN, enumFromStepN, enumFromTo, enumFromThenTo,
 
   -- * Conversion to/from lists
-  toList, fromList
+  toList, fromList, fromListN,
+
+  -- * Destructive operations
+  create, modify, copy, unsafeCopy
 ) where
 
 import qualified Data.Vector.Generic           as G
 import           Data.Vector.Primitive.Mutable ( MVector(..) )
 import qualified Data.Vector.Fusion.Stream as Stream
 import           Data.Primitive.ByteArray
-import           Data.Primitive ( Prim )
+import           Data.Primitive ( Prim, sizeOf )
 
 import Control.Monad ( liftM )
+import Control.Monad.ST ( ST )
+import Control.Monad.Primitive
 
 import Prelude hiding ( length, null,
                         replicate, (++),
@@ -101,14 +106,26 @@ import Prelude hiding ( length, null,
 
 import qualified Prelude
 
+import Data.Typeable ( Typeable )
+import Data.Data     ( Data(..) )
+
 -- | Unboxed vectors of primitive types
 data Vector a = Vector {-# UNPACK #-} !Int
                        {-# UNPACK #-} !Int
                        {-# UNPACK #-} !ByteArray
+  deriving ( Typeable )
 
 instance (Show a, Prim a) => Show (Vector a) where
     show = (Prelude.++ " :: Data.Vector.Primitive.Vector") . ("fromList " Prelude.++) . show . toList
 
+instance (Data a, Prim a) => Data (Vector a) where
+  gfoldl       = G.gfoldl
+  toConstr _   = error "toConstr"
+  gunfold _ _  = error "gunfold"
+  dataTypeOf _ = G.mkType "Data.Vector.Primitive.Vector"
+  dataCast1    = G.dataCast
+
+
 type instance G.Mutable Vector = MVector
 
 instance Prim a => G.Vector Vector a where
@@ -125,6 +142,12 @@ instance Prim a => G.Vector Vector a where
   {-# INLINE basicUnsafeIndexM #-}
   basicUnsafeIndexM (Vector i _ arr) j = return (indexByteArray arr (i+j))
 
+  {-# INLINE basicUnsafeCopy #-}
+  basicUnsafeCopy (MVector i n dst) (Vector j _ src)
+    = memcpyByteArray' dst (i * sz) src (j * sz) (n * sz)
+    where
+      sz = sizeOf (undefined :: a)
+
   {-# INLINE elemseq #-}
   elemseq _ = seq
 
@@ -205,9 +228,9 @@ infixr 5 ++
 (++) = (G.++)
 
 -- | Create a copy of a vector. Useful when dealing with slices.
-copy :: Prim a => Vector a -> Vector a
-{-# INLINE copy #-}
-copy = G.copy
+force :: Prim a => Vector a -> Vector a
+{-# INLINE force #-}
+force = G.force
 
 -- Accessing individual elements
 -- -----------------------------
@@ -825,3 +848,37 @@ fromList :: Prim a => [a] -> Vector a
 {-# INLINE fromList #-}
 fromList = G.fromList
 
+-- | Convert the first @n@ elements of a list to a vector
+--
+-- > fromListN n xs = fromList (take n xs)
+fromListN :: Prim a => Int -> [a] -> Vector a
+{-# INLINE fromListN #-}
+fromListN = G.fromListN
+
+-- Destructive operations
+-- ----------------------
+
+-- | Destructively initialise a vector.
+create :: Prim a => (forall s. ST s (MVector s a)) -> Vector a
+{-# INLINE create #-}
+create = G.create
+
+-- | Apply a destructive operation to a vector. The operation is applied to a
+-- copy of the vector unless it can be safely performed in place.
+modify :: Prim a => (forall s. MVector s a -> ST s ()) -> Vector a -> Vector a
+{-# INLINE modify #-}
+modify = G.modify
+
+-- | Copy an immutable vector into a mutable one. The two vectors must have
+-- the same length. This is not checked.
+unsafeCopy
+  :: (Prim a, PrimMonad m) => MVector (PrimState m) a -> Vector a -> m ()
+{-# INLINE unsafeCopy #-}
+unsafeCopy = G.unsafeCopy
+           
+-- | Copy an immutable vector into a mutable one. The two vectors must have the
+-- same length.
+copy :: (Prim a, PrimMonad m) => MVector (PrimState m) a -> Vector a -> m ()
+{-# INLINE copy #-}
+copy = G.copy
+