                      `Int'       ,
       cIntConv       `Integer'   } -> `Status' cToEnum #}
 
+
+-- |
+-- Initialise a matrix to a given value
+--
+memset2D :: DevicePtr                   -- ^ The device memory
+         -> (Integer,Integer)           -- ^ The (width,height) of the matrix in bytes
+         -> Integer                     -- ^ The allocation pitch, as returned by 'malloc2D'
+         -> Int                         -- ^ Value to set for each byte
+         -> IO (Maybe String)
+memset2D ptr (width,height) pitch symbol = nothingIfOk `fmap` cudaMemset2D ptr pitch symbol width height
+
+{# fun unsafe cudaMemset2D
+    { withDevicePtr* `DevicePtr' ,
+      cIntConv       `Integer'   ,
+                     `Int'       ,
+      cIntConv       `Integer'   ,
+      cIntConv       `Integer'   } -> `Status' cToEnum #}
+
+
+-- |
+-- Initialise the elements of a 3D array to a given value
+--
+memset3D :: DevicePtr                   -- ^ The device memory
+         -> (Integer,Integer,Integer)   -- ^ The (width,height,depth) of the array in bytes
+         -> Integer                     -- ^ The allocation pitch, as returned by 'malloc3D'
+         -> Int                         -- ^ Value to set for each byte
+         -> IO (Maybe String)
+memset3D = error "not implemented yet"
+
+
+--------------------------------------------------------------------------------
+-- Marshalling
+--------------------------------------------------------------------------------
+
+-- peek
+-- poke
+
+
+--------------------------------------------------------------------------------
+-- Combined allocation and marshalling
+--------------------------------------------------------------------------------
+
+-- newArray
+-- withArray
+
+
+--------------------------------------------------------------------------------
+-- Copying
+--------------------------------------------------------------------------------
+
+-- |
+-- Copy data between host and device
+--
+memcpy :: Ptr a                 -- ^ destination
+       -> Ptr a                 -- ^ source
+       -> Integer               -- ^ number of bytes
+       -> CopyDirection
+       -> IO (Maybe String)
+memcpy dst src bytes dir =  nothingIfOk `fmap` cudaMemcpy dst src bytes dir
+
+{# fun unsafe cudaMemcpy
+    { castPtr   `Ptr a'         ,
+      castPtr   `Ptr a'         ,
+      cIntConv  `Integer'       ,
+      cFromEnum `CopyDirection' } -> `Status' cToEnum #}
+
+-- |
+-- Copy data between host and device asynchronously
+--
+memcpyAsync :: Ptr a            -- ^ destination
+            -> Ptr a            -- ^ source
+            -> Integer          -- ^ number of bytes
+            -> CopyDirection
+            -> Stream
+            -> IO (Maybe String)
+memcpyAsync dst src bytes dir stream =  nothingIfOk `fmap` cudaMemcpyAsync dst src bytes dir stream
+
+{# fun unsafe cudaMemcpyAsync
+    { castPtr    `Ptr a'         ,
+      castPtr    `Ptr a'         ,
+      cIntConv   `Integer'       ,
+      cFromEnum  `CopyDirection' ,
+      cIntConv   `Stream'        } -> `Status' cToEnum #}
+
+



--------------------------------------------------------------------------------
-- Allocation
--------------------------------------------------------------------------------

-- |

-- function may pad the allocation to ensure corresponding pointers in each row
-- meet coalescing requirements. The actual allocation width is returned.
--
malloc2D :: (Integer, Integer)          -- ^ allocation (width,height) in bytes
         -> IO (Either String (DevicePtr,Integer))
malloc2D (width,height) =  do
    (rv,ptr,pitch) <- cudaMallocPitch width height
    case rv of
        Success -> doAutoRelease free_ >>= \fp ->
