 foreign import ccall "wrapper"
     doAutoRelease   :: (Ptr () -> IO ()) -> IO (FunPtr (Ptr () -> IO ()))
 
+--
+-- Copy data between host and device
+--
+memcpy :: DevicePtr -> DevicePtr -> Integer -> CopyDirection -> IO (Maybe String)
+memcpy dst src bytes dir =  nothingIfOk `fmap` cudaMemcpy dst src bytes dir
+
+{# fun unsafe cudaMemcpy
+    { withDevicePtr* `DevicePtr'     ,
+      withDevicePtr* `DevicePtr'     ,
+      cIntConv       `Integer'       ,
+      cFromEnum      `CopyDirection' } -> `Result' cToEnum #}
+
+--
+-- Copy data between host and device asynchronously
+--
+memcpyAsync :: DevicePtr -> DevicePtr -> Integer -> CopyDirection -> Stream -> IO (Maybe String)
+memcpyAsync dst src bytes dir stream =  nothingIfOk `fmap` cudaMemcpyAsync dst src bytes dir stream
+
+{# fun unsafe cudaMemcpyAsync
+    { withDevicePtr* `DevicePtr'     ,
+      withDevicePtr* `DevicePtr'     ,
+      cIntConv       `Integer'       ,
+      cFromEnum      `CopyDirection' ,
+      cIntConv       `Stream'        } -> `Result' cToEnum #}
+
+--
+-- Initialize device memory to a given value
+--
+memset                  :: DevicePtr -> Integer -> Int -> IO (Maybe String)
+memset ptr symbol bytes =  nothingIfOk `fmap` cudaMemset ptr bytes symbol
+
+{# fun unsafe cudaMemset
+    { withDevicePtr* `DevicePtr' ,
+                     `Int'       ,
+      cIntConv       `Integer'   } -> `Result' cToEnum #}
 
 --------------------------------------------------------------------------------
 -- Stream Management

        _       -> return.Left $ getErrorString rv

{# fun unsafe cudaMalloc
    { alloca-  `Ptr ()'  peek*,
      cIntConv `Integer'      } -> `Result' cToEnum #}


--
-- Free previously allocated memory on the device

    --
    -- Memory management
    --
    malloc, mallocPitch,
    memcpy, memcpyAsync,
    memset,


    --
    -- Stream management
    --
    streamCreate,
    streamDestroy,
    streamQuery,
    streamSynchronize
  ) where

import Foreign.CUDA.Types
