diff --git a/OpenCL.cabal b/OpenCL.cabal
--- a/OpenCL.cabal
+++ b/OpenCL.cabal
@@ -1,5 +1,5 @@
 Name: OpenCL
-Version: 1.0.2.6
+Version: 1.0.3.0
 License: BSD3
 License-File: LICENSE
 Author: Luis Cabellos
@@ -36,39 +36,41 @@
   ghc-options: -Wall
   Build-Depends: base >=4.0 && < 5, bytestring -any, mtl==2.0.*
   Exposed-Modules: 
-    System.GPU.OpenCL
-    System.GPU.OpenCL.Query
-    System.GPU.OpenCL.Context
-    System.GPU.OpenCL.CommandQueue
-    System.GPU.OpenCL.Memory
-    System.GPU.OpenCL.Event
-    System.GPU.OpenCL.Program
+    Control.Parallel.OpenCL
+    Control.Parallel.OpenCL.Query
+    Control.Parallel.OpenCL.Context
+    Control.Parallel.OpenCL.CommandQueue
+    Control.Parallel.OpenCL.Memory
+    Control.Parallel.OpenCL.Event
+    Control.Parallel.OpenCL.Program
   Other-Modules: 
-    System.GPU.OpenCL.Types
+    Control.Parallel.OpenCL.Types
 
-  
+  if os(linux)
+    cpp-options: -DCALLCONV=ccall -Iinclude
+    Frameworks:  OpenCL
+
   if os(darwin)
-    cpp-options: "-U__BLOCKS__"
-  
-  if os(windows)
-      cpp-options: "-DCALLCONV=stdcall"
-  else
-      cpp-options: "-DCALLCONV=ccall"
+    cpp-options: -DCALLCONV=ccall
+    cc-options: "-U__BLOCKS__"
+    Frameworks:  OpenCL
 
-  cpp-options: -Iinclude
+  if os(windows)
+    cpp-options: -DCALLCONV=stdcall
 
 Test-suite tests
   type:         exitcode-stdio-1.0
   main-is:      test-opencl.hs
   hs-Source-Dirs: src/test
   ghc-options:    -Wall
-  extra-libraries: OpenCL
-  build-depends: base >=4.0 && < 5, QuickCheck==2.4.0.*, OpenCL
+  -- Uncomment the following line to build tests on Linux or Windows:
+  -- extra-libraries: OpenCL
+  build-depends: base >=4.0 && < 5, QuickCheck==2.4.*, OpenCL
 
 source-repository this
   type: git
   location: https://zhensydow@github.com/zhensydow/opencl.git
-  tag: 1.0.2.6
+  tag: 1.0.3.0
   branch: master
 
 source-repository head
diff --git a/README.org b/README.org
--- a/README.org
+++ b/README.org
@@ -4,6 +4,8 @@
 
   Based on the [[http://hackage.haskell.org/package/OpenCLRaw][OpenCLRaw]] package by J.R. Heard.
 
+  By Luis Cabellos at [[http://www.ifca.es/en/home2][IFCA]]
+
 ** Installation
    *Requirements:* [[http://hackage.haskell.org/package/c2hs][c2hs]] must be installed. (Try ~cabal install c2hs~.)
 
@@ -13,6 +15,16 @@
 
   Programs using the library must link against OpenCL; for example, by
   passing ~-lOpenCL~ to GHC.
+
+*** About versioning
+
+    OpenCL module uses Package Version Policy:
+
+    http://www.haskell.org/haskellwiki/Package_versioning_policy
+
+    But It differs in the A version number. It use OpenCL API version as A
+    number, so 1.0.3.0 correspond to A=1.0=OpenCL API version 1.0, B=3 and
+    C=0. The major version number is 1.0.3
 
 ** Optional Requisites
    Some OpenCL libraries require additional NUMA libraries. For instance,
diff --git a/examples/example01.hs b/examples/example01.hs
--- a/examples/example01.hs
+++ b/examples/example01.hs
@@ -29,7 +29,7 @@
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 -}
-import System.GPU.OpenCL
+import Control.Parallel.OpenCL
 import Foreign( castPtr, nullPtr, sizeOf )
 import Foreign.C.Types( CFloat )
 import Foreign.Marshal.Array( newArray, peekArray )
@@ -42,7 +42,7 @@
   -- Initialize OpenCL
   (platform:_) <- clGetPlatformIDs
   (dev:_) <- clGetDeviceIDs platform CL_DEVICE_TYPE_ALL
-  context <- clCreateContext [dev] print
+  context <- clCreateContext [CL_CONTEXT_PLATFORM platform] [dev] print
   q <- clCreateCommandQueue context dev []
   
   -- Initialize Kernel
@@ -60,8 +60,8 @@
   mem_in <- clCreateBuffer context [CL_MEM_READ_ONLY, CL_MEM_COPY_HOST_PTR] (vecSize, castPtr input)  
   mem_out <- clCreateBuffer context [CL_MEM_WRITE_ONLY] (vecSize, nullPtr)
 
-  clSetKernelArg kernel 0 mem_in
-  clSetKernelArg kernel 1 mem_out
+  clSetKernelArgSto kernel 0 mem_in
+  clSetKernelArgSto kernel 1 mem_out
   
   -- Execute Kernel
   eventExec <- clEnqueueNDRangeKernel q kernel [length original] [1] []
diff --git a/examples/example02.hs b/examples/example02.hs
--- a/examples/example02.hs
+++ b/examples/example02.hs
@@ -29,7 +29,7 @@
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 -}
-import System.GPU.OpenCL  
+import Control.Parallel.OpenCL  
 import Foreign( castPtr, nullPtr, sizeOf )
 import Foreign.C.Types( CFloat )
 import Foreign.Marshal.Array( peekArray, withArray )
@@ -47,7 +47,7 @@
   -- Initialize OpenCL
   (platform:_) <- clGetPlatformIDs
   (dev:_) <- clGetDeviceIDs platform CL_DEVICE_TYPE_ALL
-  context <- clCreateContext [dev] print
+  context <- clCreateContext [] [dev] print
   q <- clCreateCommandQueue context dev [CL_QUEUE_PROFILING_ENABLE]
   
   -- Initialize Kernel
@@ -74,8 +74,8 @@
   mem_in <- clCreateBuffer ctx [CL_MEM_READ_ONLY] (vecSize, nullPtr)  
   mem_out <- clCreateBuffer ctx [CL_MEM_WRITE_ONLY] (vecSize, nullPtr)
 
-  clSetKernelArg krn 0 mem_in
-  clSetKernelArg krn 1 mem_out
+  clSetKernelArgSto krn 0 mem_in
+  clSetKernelArgSto krn 1 mem_out
   
   -- Put Input
   eventWrite <- clEnqueueWriteBuffer q mem_in True 0 vecSize (castPtr input) []
diff --git a/examples/example03.hs b/examples/example03.hs
--- a/examples/example03.hs
+++ b/examples/example03.hs
@@ -29,7 +29,7 @@
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 -}
-import System.GPU.OpenCL  
+import Control.Parallel.OpenCL  
 import Foreign( castPtr, nullPtr, sizeOf )
 import Foreign.C.Types( CFloat )
 import Foreign.Marshal.Array( newArray, peekArray )
@@ -45,7 +45,7 @@
   -- Initialize OpenCL
   (platform:_) <- clGetPlatformIDs
   (dev:_) <- clGetDeviceIDs platform CL_DEVICE_TYPE_ALL
-  context <- clCreateContext [dev] print
+  context <- clCreateContext [] [dev] print
   q <- clCreateCommandQueue context dev []
   
   -- Initialize Kernels
@@ -70,14 +70,14 @@
   mem_out1 <- clCreateBuffer context [CL_MEM_WRITE_ONLY] (vecSize, nullPtr)
   mem_out2 <- clCreateBuffer context [CL_MEM_WRITE_ONLY] (vecSize, nullPtr)
 
-  clSetKernelArg kernel1 0 mem_in
-  clSetKernelArg kernel1 1 mem_mid
+  clSetKernelArgSto kernel1 0 mem_in
+  clSetKernelArgSto kernel1 1 mem_mid
   
-  clSetKernelArg kernel2 0 mem_mid
-  clSetKernelArg kernel2 1 mem_out1
+  clSetKernelArgSto kernel2 0 mem_mid
+  clSetKernelArgSto kernel2 1 mem_out1
   
-  clSetKernelArg kernel3 0 mem_mid
-  clSetKernelArg kernel3 1 mem_out2
+  clSetKernelArgSto kernel3 0 mem_mid
+  clSetKernelArgSto kernel3 1 mem_out2
   
   -- Execute Kernels
   eventExec1 <- clEnqueueNDRangeKernel q kernel1 [length original] [1] []
diff --git a/examples/example04.hs b/examples/example04.hs
--- a/examples/example04.hs
+++ b/examples/example04.hs
@@ -29,7 +29,7 @@
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 -}
-import System.GPU.OpenCL
+import Control.Parallel.OpenCL
 import Foreign( castPtr, nullPtr, sizeOf )
 import Foreign.C.Types( CFloat )
 import Foreign.Marshal.Array( newArray, peekArray )
@@ -42,7 +42,7 @@
   -- Initialize OpenCL
   (platform:_) <- clGetPlatformIDs
   (dev:_) <- clGetDeviceIDs platform CL_DEVICE_TYPE_ALL
-  context <- clCreateContext [dev] print
+  context <- clCreateContext [] [dev] print
   q <- clCreateCommandQueue context dev []
   
   -- Compile and get binaries
@@ -65,8 +65,8 @@
   mem_in <- clCreateBuffer context [CL_MEM_READ_ONLY, CL_MEM_COPY_HOST_PTR] (vecSize, castPtr input)  
   mem_out <- clCreateBuffer context [CL_MEM_WRITE_ONLY] (vecSize, nullPtr)
 
-  clSetKernelArg kernel 0 mem_in
-  clSetKernelArg kernel 1 mem_out
+  clSetKernelArgSto kernel 0 mem_in
+  clSetKernelArgSto kernel 1 mem_out
   
   -- Execute Kernel
   eventExec <- clEnqueueNDRangeKernel q kernel [length original] [1] []
diff --git a/src/Control/Parallel/OpenCL.hs b/src/Control/Parallel/OpenCL.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Parallel/OpenCL.hs
@@ -0,0 +1,55 @@
+{- Copyright (c) 2011 Luis Cabellos,
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of  nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-}
+module Control.Parallel.OpenCL( 
+  -- * Basic Types
+  CLError(..), CLint, CLuint, CLulong,
+  -- * Modules
+  module Control.Parallel.OpenCL.Query,
+  module Control.Parallel.OpenCL.Context,
+  module Control.Parallel.OpenCL.CommandQueue, 
+  module Control.Parallel.OpenCL.Memory,
+  module Control.Parallel.OpenCL.Event,
+  module Control.Parallel.OpenCL.Program
+  )
+       where
+
+-- -----------------------------------------------------------------------------
+import Control.Parallel.OpenCL.Query
+import Control.Parallel.OpenCL.Context
+import Control.Parallel.OpenCL.CommandQueue
+import Control.Parallel.OpenCL.Memory
+import Control.Parallel.OpenCL.Event
+import Control.Parallel.OpenCL.Program
+import Control.Parallel.OpenCL.Types( 
+  CLError(..), CLint, CLuint, CLulong )
+
+-- -----------------------------------------------------------------------------
diff --git a/src/Control/Parallel/OpenCL/CommandQueue.chs b/src/Control/Parallel/OpenCL/CommandQueue.chs
new file mode 100644
--- /dev/null
+++ b/src/Control/Parallel/OpenCL/CommandQueue.chs
@@ -0,0 +1,1457 @@
+{- Copyright (c) 2011 Luis Cabellos,
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of  nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-}
+{-# LANGUAGE ForeignFunctionInterface, ScopedTypeVariables, CPP #-}
+module Control.Parallel.OpenCL.CommandQueue(
+  -- * Types
+  CLCommandQueue, CLCommandQueueProperty(..), CLMapFlag(..),
+  -- * Command Queue Functions
+  clCreateCommandQueue, clRetainCommandQueue, clReleaseCommandQueue,
+  clGetCommandQueueContext, clGetCommandQueueDevice, 
+  clGetCommandQueueReferenceCount, clGetCommandQueueProperties,
+  clSetCommandQueueProperty,
+  -- * Memory Commands
+  clEnqueueReadBuffer, clEnqueueWriteBuffer, clEnqueueReadImage, 
+  clEnqueueWriteImage, clEnqueueCopyImage, clEnqueueCopyImageToBuffer,
+  clEnqueueCopyBufferToImage, clEnqueueMapBuffer, clEnqueueMapImage,
+  clEnqueueUnmapMemObject,
+  -- * Executing Kernels
+  clEnqueueNDRangeKernel, clEnqueueTask, clEnqueueNativeKernel, 
+  clEnqueueMarker, clEnqueueWaitForEvents, clEnqueueBarrier,
+  -- * Flush and Finish
+  clFlush, clFinish
+  ) where
+
+-- -----------------------------------------------------------------------------
+import Foreign
+import Foreign.C.Types
+import Control.Parallel.OpenCL.Types( 
+  CLint, CLbool, CLuint, CLCommandQueueProperty_, CLCommandQueueInfo_, 
+  CLMapFlags_, CLMapFlag(..), CLCommandQueue, CLDeviceID, CLContext, 
+  CLCommandQueueProperty(..), CLEvent, CLMem, CLKernel,
+  whenSuccess, wrapCheckSuccess, wrapPError, wrapGetInfo, getCLValue, 
+  bitmaskToCommandQueueProperties, bitmaskFromFlags )
+
+#ifdef __APPLE__
+#include <OpenCL/opencl.h>
+#else
+#include <CL/cl.h>
+#endif
+
+-- -----------------------------------------------------------------------------
+type NativeKernelCallback = Ptr () -> IO ()
+foreign import CALLCONV "wrapper" wrapNativeKernelCallback :: 
+  NativeKernelCallback -> IO (FunPtr NativeKernelCallback)
+foreign import CALLCONV "clCreateCommandQueue" raw_clCreateCommandQueue :: 
+  CLContext -> CLDeviceID -> CLCommandQueueProperty_ -> Ptr CLint -> IO CLCommandQueue
+foreign import CALLCONV "clRetainCommandQueue" raw_clRetainCommandQueue :: 
+  CLCommandQueue -> IO CLint
+foreign import CALLCONV "clReleaseCommandQueue" raw_clReleaseCommandQueue :: 
+  CLCommandQueue -> IO CLint
+foreign import CALLCONV "clGetCommandQueueInfo" raw_clGetCommandQueueInfo :: 
+  CLCommandQueue -> CLCommandQueueInfo_ -> CSize -> Ptr () -> Ptr CSize -> IO CLint
+foreign import CALLCONV "clSetCommandQueueProperty" raw_clSetCommandQueueProperty :: 
+  CLCommandQueue -> CLCommandQueueProperty_ -> CLbool -> Ptr CLCommandQueueProperty_ -> IO CLint
+foreign import CALLCONV "clEnqueueReadBuffer" raw_clEnqueueReadBuffer ::
+  CLCommandQueue -> CLMem -> CLbool -> CSize -> CSize -> Ptr () -> CLuint -> Ptr CLEvent -> Ptr CLEvent -> IO CLint
+foreign import CALLCONV "clEnqueueWriteBuffer" raw_clEnqueueWriteBuffer ::
+  CLCommandQueue -> CLMem -> CLbool -> CSize -> CSize -> Ptr () -> CLuint -> Ptr CLEvent -> Ptr CLEvent -> IO CLint
+foreign import CALLCONV "clEnqueueReadImage" raw_clEnqueueReadImage ::
+  CLCommandQueue -> CLMem -> CLbool -> Ptr CSize -> Ptr CSize -> CSize -> CSize -> Ptr () -> CLuint -> Ptr CLEvent -> Ptr CLEvent -> IO CLint
+foreign import CALLCONV "clEnqueueWriteImage" raw_clEnqueueWriteImage ::
+  CLCommandQueue -> CLMem -> CLbool -> Ptr CSize -> Ptr CSize -> CSize -> CSize -> Ptr () -> CLuint -> Ptr CLEvent -> Ptr CLEvent -> IO CLint
+foreign import CALLCONV "clEnqueueCopyImage" raw_clEnqueueCopyImage ::
+  CLCommandQueue -> CLMem -> CLMem -> Ptr CSize -> Ptr CSize -> Ptr CSize -> CLuint -> Ptr CLEvent -> Ptr CLEvent -> IO CLint
+foreign import CALLCONV "clEnqueueCopyImageToBuffer" raw_clEnqueueCopyImageToBuffer ::
+  CLCommandQueue -> CLMem -> CLMem -> Ptr CSize -> Ptr CSize -> CSize -> CLuint -> Ptr CLEvent -> Ptr CLEvent -> IO CLint
+foreign import CALLCONV "clEnqueueCopyBufferToImage" raw_clEnqueueCopyBufferToImage ::
+  CLCommandQueue -> CLMem -> CLMem -> CSize -> Ptr CSize -> Ptr CSize -> CLuint -> Ptr CLEvent -> Ptr CLEvent -> IO CLint
+foreign import CALLCONV "clEnqueueMapBuffer" raw_clEnqueueMapBuffer ::
+  CLCommandQueue -> CLMem -> CLbool -> CLMapFlags_ -> CSize -> CSize -> CLuint -> Ptr CLEvent -> Ptr CLEvent -> Ptr CLint -> IO (Ptr ())
+foreign import CALLCONV "clEnqueueMapImage" raw_clEnqueueMapImage ::
+  CLCommandQueue -> CLMem -> CLbool -> CLMapFlags_ -> Ptr CSize -> Ptr CSize -> Ptr CSize -> Ptr CSize -> CLuint -> Ptr CLEvent -> Ptr CLEvent -> Ptr CLint -> IO (Ptr ())
+foreign import CALLCONV "clEnqueueUnmapMemObject" raw_clEnqueueUnmapMemObject ::
+  CLCommandQueue -> CLMem -> Ptr () -> CLuint -> Ptr CLEvent -> Ptr CLEvent -> IO CLint
+foreign import CALLCONV "clEnqueueNDRangeKernel" raw_clEnqueueNDRangeKernel :: 
+  CLCommandQueue -> CLKernel -> CLuint -> Ptr CSize -> Ptr CSize -> Ptr CSize -> CLuint -> Ptr CLEvent -> Ptr CLEvent -> IO CLint
+foreign import CALLCONV "clEnqueueNativeKernel" raw_clEnqueueNativeKernel ::
+  CLCommandQueue ->  FunPtr NativeKernelCallback -> Ptr () -> CSize -> CLuint -> Ptr CLMem -> Ptr (Ptr ()) -> CLuint -> Ptr CLEvent -> Ptr CLEvent -> IO CLint
+foreign import CALLCONV "clEnqueueTask" raw_clEnqueueTask :: 
+  CLCommandQueue -> CLKernel -> CLuint -> Ptr CLEvent -> Ptr CLEvent -> IO CLint
+foreign import CALLCONV "clEnqueueMarker" raw_clEnqueueMarker :: 
+  CLCommandQueue -> Ptr CLEvent -> IO CLint 
+foreign import CALLCONV "clEnqueueWaitForEvents" raw_clEnqueueWaitForEvents :: 
+  CLCommandQueue -> CLuint -> Ptr CLEvent -> IO CLint
+foreign import CALLCONV "clEnqueueBarrier" raw_clEnqueueBarrier :: 
+  CLCommandQueue -> IO CLint 
+foreign import CALLCONV "clFlush" raw_clFlush ::
+  CLCommandQueue -> IO CLint
+foreign import CALLCONV "clFinish" raw_clFinish ::
+  CLCommandQueue -> IO CLint
+
+-- -----------------------------------------------------------------------------
+withMaybeArray :: Storable a => [a] -> (Ptr a -> IO b) -> IO b
+withMaybeArray [] = ($ nullPtr)
+withMaybeArray xs = withArray xs
+
+-- -----------------------------------------------------------------------------
+{-| Create a command-queue on a specific device.
+
+The OpenCL functions that are submitted to a command-queue are enqueued in the 
+order the calls are made but can be configured to execute in-order or 
+out-of-order. The properties argument in clCreateCommandQueue can be used to 
+specify the execution order.
+
+If the 'CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE' property of a command-queue is 
+not set, the commands enqueued to a command-queue execute in order. For example, 
+if an application calls 'clEnqueueNDRangeKernel' to execute kernel A followed by 
+a 'clEnqueueNDRangeKernel' to execute kernel B, the application can assume that 
+kernel A finishes first and then kernel B is executed. If the memory objects 
+output by kernel A are inputs to kernel B then kernel B will see the correct 
+data in memory objects produced by execution of kernel A. If the 
+'CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE' property of a commandqueue is set, then 
+there is no guarantee that kernel A will finish before kernel B starts execution.
+
+Applications can configure the commands enqueued to a command-queue to execute 
+out-of-order by setting the 'CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE' property of 
+the command-queue. This can be specified when the command-queue is created or 
+can be changed dynamically using 'clCreateCommandQueue'. In out-of-order 
+execution mode there is no guarantee that the enqueued commands will finish 
+execution in the order they were queued. As there is no guarantee that kernels 
+will be executed in order, i.e. based on when the 'clEnqueueNDRangeKernel' calls 
+are made within a command-queue, it is therefore possible that an earlier 
+'clEnqueueNDRangeKernel' call to execute kernel A identified by event A may 
+execute and/or finish later than a 'clEnqueueNDRangeKernel' call to execute 
+kernel B which was called by the application at a later point in time. To 
+guarantee a specific order of execution of kernels, a wait on a particular event 
+(in this case event A) can be used. The wait for event A can be specified in the 
+event_wait_list argument to 'clEnqueueNDRangeKernel' for kernel B.
+
+In addition, a wait for events or a barrier command can be enqueued to the 
+command-queue. The wait for events command ensures that previously enqueued 
+commands identified by the list of events to wait for have finished before the 
+next batch of commands is executed. The barrier command ensures that all 
+previously enqueued commands in a command-queue have finished execution before 
+the next batch of commands is executed.
+
+Similarly, commands to read, write, copy or map memory objects that are enqueued 
+after 'clEnqueueNDRangeKernel', 'clEnqueueTask' or 'clEnqueueNativeKernel' 
+commands are not guaranteed to wait for kernels scheduled for execution to have 
+completed (if the 'CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE' property is set). To 
+ensure correct ordering of commands, the event object returned by 
+'clEnqueueNDRangeKernel', 'clEnqueueTask' or 'clEnqueueNativeKernel' can be 
+used to enqueue a wait for event or a barrier command can be enqueued that must 
+complete before reads or writes to the memory object(s) occur.
+-}
+clCreateCommandQueue :: CLContext -> CLDeviceID -> [CLCommandQueueProperty] 
+                     -> IO CLCommandQueue
+clCreateCommandQueue ctx did xs = wrapPError $ \perr -> do
+  raw_clCreateCommandQueue ctx did props perr
+    where
+      props = bitmaskFromFlags xs
+
+{-| Increments the command_queue reference count. 'clCreateCommandQueue'
+performs an implicit retain. This is very helpful for 3rd party libraries, which
+typically get a command-queue passed to them by the application. However, it is
+possible that the application may delete the command-queue without informing the
+library. Allowing functions to attach to (i.e. retain) and release a
+command-queue solves the problem of a command-queue being used by a library no
+longer being valid.  Returns 'True' if the function is executed successfully. It
+returns 'False' if command_queue is not a valid command-queue.  
+-}
+clRetainCommandQueue :: CLCommandQueue -> IO Bool
+clRetainCommandQueue = wrapCheckSuccess . raw_clRetainCommandQueue
+
+-- | Decrements the command_queue reference count.
+-- After the command_queue reference count becomes zero and all commands queued 
+-- to command_queue have finished (e.g., kernel executions, memory object 
+-- updates, etc.), the command-queue is deleted.
+-- Returns 'True' if the function is executed successfully. It returns 'False'
+-- if command_queue is not a valid command-queue.
+clReleaseCommandQueue :: CLCommandQueue -> IO Bool
+clReleaseCommandQueue = wrapCheckSuccess . raw_clReleaseCommandQueue
+
+#c
+enum CLCommandQueueInfo {
+  cL_QUEUE_CONTEXT=CL_QUEUE_CONTEXT,
+  cL_QUEUE_DEVICE=CL_QUEUE_DEVICE,
+  cL_QUEUE_REFERENCE_COUNT=CL_QUEUE_REFERENCE_COUNT,
+  cL_QUEUE_PROPERTIES=CL_QUEUE_PROPERTIES,
+  };
+#endc
+{#enum CLCommandQueueInfo {upcaseFirstLetter} #}
+
+-- | Return the context specified when the command-queue is created.
+--
+-- This function execute OpenCL clGetCommandQueueInfo with 'CL_QUEUE_CONTEXT'.
+clGetCommandQueueContext :: CLCommandQueue -> IO CLContext
+clGetCommandQueueContext cq =
+    wrapGetInfo (\(dat :: Ptr CLContext) ->
+        raw_clGetCommandQueueInfo cq infoid size (castPtr dat)) id
+    where 
+      infoid = getCLValue CL_QUEUE_CONTEXT
+      size = fromIntegral $ sizeOf (nullPtr::CLContext)
+
+-- | Return the device specified when the command-queue is created.
+--
+-- This function execute OpenCL clGetCommandQueueInfo with 'CL_QUEUE_DEVICE'.
+clGetCommandQueueDevice :: CLCommandQueue -> IO CLDeviceID
+clGetCommandQueueDevice cq =
+    wrapGetInfo (\(dat :: Ptr CLDeviceID) ->
+        raw_clGetCommandQueueInfo cq infoid size (castPtr dat)) id
+    where 
+      infoid = getCLValue CL_QUEUE_DEVICE
+      size = fromIntegral $ sizeOf (nullPtr::CLDeviceID)
+
+-- | Return the command-queue reference count.
+-- The reference count returned should be considered immediately stale. It is 
+-- unsuitable for general use in applications. This feature is provided for 
+-- identifying memory leaks.
+--
+-- This function execute OpenCL clGetCommandQueueInfo with
+-- 'CL_QUEUE_REFERENCE_COUNT'.
+clGetCommandQueueReferenceCount :: CLCommandQueue -> IO CLuint
+clGetCommandQueueReferenceCount cq =
+    wrapGetInfo (\(dat :: Ptr CLuint) ->
+        raw_clGetCommandQueueInfo cq infoid size (castPtr dat)) id
+    where 
+      infoid = getCLValue CL_QUEUE_REFERENCE_COUNT
+      size = fromIntegral $ sizeOf (0::CLuint)
+
+
+-- | Return the currently specified properties for the command-queue. These 
+-- properties are specified by the properties argument in 'clCreateCommandQueue'
+-- , and can be changed by 'clSetCommandQueueProperty'.
+--
+-- This function execute OpenCL clGetCommandQueueInfo with
+-- 'CL_QUEUE_PROPERTIES'.
+clGetCommandQueueProperties :: CLCommandQueue -> IO [CLCommandQueueProperty]
+clGetCommandQueueProperties cq =
+    wrapGetInfo (\(dat :: Ptr CLCommandQueueProperty_) ->
+        raw_clGetCommandQueueInfo cq infoid size (castPtr dat)) bitmaskToCommandQueueProperties
+    where 
+      infoid = getCLValue CL_QUEUE_PROPERTIES
+      size = fromIntegral $ sizeOf (0::CLCommandQueueProperty_)
+
+{-| Enable or disable the properties of a command-queue.  Returns the
+command-queue properties before they were changed by
+'clSetCommandQueueProperty'.  As specified for 'clCreateCommandQueue', the
+'CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE' command-queue property determines
+whether the commands in a command-queue are executed in-order or
+out-of-order. Changing this command-queue property will cause the OpenCL
+implementation to block until all previously queued commands in command_queue
+have completed. This can be an expensive operation and therefore changes to the
+'CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE' property should be only done when
+absolutely necessary.
+
+ It is possible that a device(s) becomes unavailable after a context and
+command-queues that use this device(s) have been created and commands have been
+queued to command-queues. In this case the behavior of OpenCL API calls that use
+this context (and command-queues) are considered to be
+implementation-defined. The user callback function, if specified when the
+context is created, can be used to record appropriate information when the
+device becomes unavailable.
+-}
+clSetCommandQueueProperty :: CLCommandQueue -> [CLCommandQueueProperty] -> Bool 
+                          -> IO [CLCommandQueueProperty]
+clSetCommandQueueProperty cq xs val = alloca 
+                                      $ \(dat :: Ptr CLCommandQueueProperty_) 
+                                        -> whenSuccess (f dat)
+                                           $ fmap bitmaskToCommandQueueProperties $ peek dat
+    where
+      f = raw_clSetCommandQueueProperty cq props (fromBool val)
+      props = bitmaskFromFlags xs
+
+-- -----------------------------------------------------------------------------
+clEnqueue :: (CLuint -> Ptr CLEvent -> Ptr CLEvent -> IO CLint) -> [CLEvent] 
+             -> IO CLEvent
+clEnqueue f [] = alloca $ \event -> whenSuccess (f 0 nullPtr event)
+                                    $ peek event
+clEnqueue f events = allocaArray nevents $ \pevents -> do
+  pokeArray pevents events
+  alloca $ \event -> whenSuccess (f cnevents pevents event)
+                     $ peek event
+    where
+      nevents = length events
+      cnevents = fromIntegral nevents
+
+-- -----------------------------------------------------------------------------
+{-| Enqueue commands to read from a buffer object to host memory. Calling
+clEnqueueReadBuffer to read a region of the buffer object with the ptr argument
+value set to host_ptr + offset, where host_ptr is a pointer to the memory region
+specified when the buffer object being read is created with
+'CL_MEM_USE_HOST_PTR', must meet the following requirements in order to avoid
+undefined behavior:
+
+ * All commands that use this buffer object have finished execution before the
+read command begins execution
+
+ * The buffer object is not mapped
+
+ * The buffer object is not used by any command-queue until the read command has
+finished execution Errors
+
+'clEnqueueReadBuffer' returns the event if the function is executed
+successfully. It can throw the following 'CLError' exceptions:
+
+ * 'CL_INVALID_COMMAND_QUEUE' if command_queue is not a valid command-queue.
+
+ * 'CL_INVALID_CONTEXT' if the context associated with command_queue and buffer
+are not the same or if the context associated with command_queue and events in
+event_wait_list are not the same.
+
+ * 'CL_INVALID_MEM_OBJECT' if buffer is not a valid buffer object.
+
+ * 'CL_INVALID_VALUE' if the region being read specified by (offset, cb) is out
+of bounds or if ptr is a NULL value.
+
+ * 'CL_INVALID_EVENT_WAIT_LIST' if event_wait_list is NULL and
+num_events_in_wait_list greater than 0, or event_wait_list is not NULL and
+num_events_in_wait_list is 0, or if event objects in event_wait_list are not
+valid events.
+
+ * 'CL_MEM_OBJECT_ALLOCATION_FAILURE' if there is a failure to allocate memory
+for data store associated with buffer.
+
+ * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
+by the OpenCL implementation on the host.
+-}
+clEnqueueReadBuffer :: Integral a => CLCommandQueue -> CLMem -> Bool -> a -> a
+                       -> Ptr () -> [CLEvent] -> IO CLEvent
+clEnqueueReadBuffer cq mem check off size dat = clEnqueue (raw_clEnqueueReadBuffer cq mem (fromBool check) (fromIntegral off) (fromIntegral size) dat)
+
+{-| Enqueue commands to write to a buffer object from host memory.Calling
+clEnqueueWriteBuffer to update the latest bits in a region of the buffer object
+with the ptr argument value set to host_ptr + offset, where host_ptr is a
+pointer to the memory region specified when the buffer object being written is
+created with 'CL_MEM_USE_HOST_PTR', must meet the following requirements in
+order to avoid undefined behavior:
+
+ * The host memory region given by (host_ptr + offset, cb) contains the latest
+bits when the enqueued write command begins execution.
+
+ * The buffer object is not mapped.
+
+ * The buffer object is not used by any command-queue until the write command
+has finished execution.
+
+'clEnqueueWriteBuffer' returns the Event if the function is executed
+successfully. It can throw the following 'CLError' exceptions:
+
+ * 'CL_INVALID_COMMAND_QUEUE' if command_queue is not a valid command-queue.
+
+ * 'CL_INVALID_CONTEXT' if the context associated with command_queue and buffer
+are not the same or if the context associated with command_queue and events in
+event_wait_list are not the same.
+
+ * 'CL_INVALID_MEM_OBJECT' if buffer is not a valid buffer object.
+
+ * 'CL_INVALID_VALUE' if the region being written specified by (offset, cb) is
+out of bounds or if ptr is a NULL value.
+
+ * 'CL_INVALID_EVENT_WAIT_LIST' if event_wait_list is NULL and
+num_events_in_wait_list greater than 0, or event_wait_list is not NULL and
+num_events_in_wait_list is 0, or if event objects in event_wait_list are not
+valid events.
+
+ * 'CL_MEM_OBJECT_ALLOCATION_FAILURE' if there is a failure to allocate memory
+for data store associated with buffer.
+
+ * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
+by the OpenCL implementation on the host.
+-}
+clEnqueueWriteBuffer :: Integral a => CLCommandQueue -> CLMem -> Bool -> a -> a
+                       -> Ptr () -> [CLEvent] -> IO CLEvent
+clEnqueueWriteBuffer cq mem check off size dat = clEnqueue (raw_clEnqueueWriteBuffer cq mem (fromBool check) (fromIntegral off) (fromIntegral size) dat)
+
+{-| Enqueues a command to read from a 2D or 3D image object to host memory.
+
+Returns an event object that identifies this particular read command and can be
+used to query or queue a wait for this particular command to complete. event can
+be NULL in which case it will not be possible for the application to query the
+status of this command or queue a wait for this command to complete.
+
+Notes
+
+If blocking is 'True' i.e. the read command is blocking, 'clEnqueueReadImage'
+does not return until the buffer data has been read and copied into memory
+pointed to by ptr.
+
+If blocking_read is 'False' i.e. map operation is non-blocking,
+'clEnqueueReadImage' queues a non-blocking read command and returns. The
+contents of the buffer that ptr points to cannot be used until the read command
+has completed. The event argument returns an event object which can be used to
+query the execution status of the read command. When the read command has
+completed, the contents of the buffer that ptr points to can be used by the
+application.
+
+Calling 'clEnqueueReadImage' to read a region of the image object with the ptr
+argument value set to host_ptr + (origin.z * image slice pitch + origin.y *
+image row pitch + origin.x * bytes per pixel), where host_ptr is a pointer to
+the memory region specified when the image object being read is created with
+'CL_MEM_USE_HOST_PTR', must meet the following requirements in order to avoid
+undefined behavior:
+
+ * All commands that use this image object have finished execution before the
+read command begins execution.
+
+ * The row_pitch and slice_pitch argument values in clEnqueueReadImage must be
+set to the image row pitch and slice pitch.
+
+ * The image object is not mapped.
+
+ * The image object is not used by any command-queue until the read command has
+finished execution.
+
+'clEnqueueReadImage' returns the 'CLEvent' if the function is executed
+successfully. It can throw the following 'CLError' exceptions:
+
+ * 'CL_INVALID_COMMAND_QUEUE' if command_queue is not a valid command-queue.
+
+ * 'CL_INVALID_CONTEXT' if the context associated with command_queue and image
+are not the same or if the context associated with command_queue and events in
+event_wait_list are not the same.
+
+ * 'CL_INVALID_MEM_OBJECT' if image is not a valid image object.
+
+ * 'CL_INVALID_VALUE' if the region being read specified by origin and region is
+out of bounds or if ptr is a nullPtr value.
+
+ * 'CL_INVALID_VALUE' if image is a 2D image object and z is not equal to 0 or
+depth is not equal to 1 or slice_pitch is not equal to 0.
+
+ * 'CL_INVALID_EVENT_WAIT_LIST' if event objects in event_wait_list are not
+valid events.
+
+ * 'CL_MEM_OBJECT_ALLOCATION_FAILURE' if there is a failure to allocate memory
+for data store associated with image.
+
+ * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
+by the OpenCL implementation on the host.
+
+-}
+clEnqueueReadImage :: Integral a 
+                      => CLCommandQueue -- ^ Refers to the command-queue in
+                                        -- which the read command will be
+                                        -- queued. command_queue and image must
+                                        -- be created with the same OpenCL
+                                        -- contex
+                      -> CLMem -- ^ Refers to a valid 2D or 3D image object.
+                      -> Bool -- ^ Indicates if the read operations are blocking
+                              -- or non-blocking.
+                      -> (a,a,a) -- ^ Defines the (x, y, z) offset in pixels in
+                                 -- the image from where to read. If image is a
+                                 -- 2D image object, the z value given must be
+                                 -- 0.
+                      -> (a,a,a) -- ^ Defines the (width, height, depth) in
+                                 -- pixels of the 2D or 3D rectangle being
+                                 -- read. If image is a 2D image object, the
+                                 -- depth value given must be 1.
+                      -> a -- ^ The length of each row in bytes. This value must
+                           -- be greater than or equal to the element size in
+                           -- bytes * width. If row_pitch is set to 0, the
+                           -- appropriate row pitch is calculated based on the
+                           -- size of each element in bytes multiplied by width.
+                      -> a -- ^ Size in bytes of the 2D slice of the 3D region
+                           -- of a 3D image being read. This must be 0 if image
+                           -- is a 2D image. This value must be greater than or
+                           -- equal to row_pitch * height. If slice_pitch is set
+                           -- to 0, the appropriate slice pitch is calculated
+                           -- based on the row_pitch * height.
+                      -> Ptr () -- ^ The pointer to a buffer in host memory
+                                -- where image data is to be read from.
+                      -> [CLEvent] -- ^ Specify events that need to complete
+                                   -- before this particular command can be
+                                   -- executed. If event_wait_list is empty,
+                                   -- then this particular command does not wait
+                                   -- on any event to complete. The events
+                                   -- specified in the list act as
+                                   -- synchronization points. The context
+                                   -- associated with events in event_wait_list
+                                   -- and command_queue must be the same.
+                      -> IO CLEvent
+clEnqueueReadImage cq mem check (orix,oriy,oriz) (regx,regy,regz) rp sp dat xs = 
+  withArray (fmap fromIntegral [orix,oriy,oriz]) $ \pori -> 
+  withArray (fmap fromIntegral [regx,regy,regz]) $ \preg -> 
+  clEnqueue (raw_clEnqueueReadImage cq mem (fromBool check) pori preg (fromIntegral rp) (fromIntegral sp) dat) xs
+                       
+{-| Enqueues a command to write from a 2D or 3D image object to host memory.
+
+Returns an event object that identifies this particular write command and can be
+used to query or queue a wait for this particular command to complete. event can
+be NULL in which case it will not be possible for the application to query the
+status of this command or queue a wait for this command to complete.
+
+Notes
+
+If blocking_write is 'True' the OpenCL implementation copies the data referred
+to by ptr and enqueues the write command in the command-queue. The memory
+pointed to by ptr can be reused by the application after the
+'clEnqueueWriteImage' call returns.
+
+If blocking_write is 'False' the OpenCL implementation will use ptr to perform a
+nonblocking write. As the write is non-blocking the implementation can return
+immediately. The memory pointed to by ptr cannot be reused by the application
+after the call returns. The event argument returns an event object which can be
+used to query the execution status of the write command. When the write command
+has completed, the memory pointed to by ptr can then be reused by the
+application.
+
+Calling 'clEnqueueWriteImage' to update the latest bits in a region of the image
+object with the ptr argument value set to host_ptr + (origin.z * image slice
+pitch + origin.y * image row pitch + origin.x * bytes per pixel), where host_ptr
+is a pointer to the memory region specified when the image object being written
+is created with 'CL_MEM_USE_HOST_PTR', must meet the following requirements in
+order to avoid undefined behavior:
+
+ * The host memory region being written contains the latest bits when the
+enqueued write command begins execution.
+
+ * The input_row_pitch and input_slice_pitch argument values in
+clEnqueueWriteImage must be set to the image row pitch and slice pitch.
+
+ * The image object is not mapped.
+
+ * The image object is not used by any command-queue until the write command has
+finished execution.
+
+'clEnqueueWriteImage' returns the 'CLEvent' if the function is executed
+successfully. It can throw the following 'CLError' exceptions:
+
+ * 'CL_INVALID_COMMAND_QUEUE' if command_queue is not a valid command-queue.
+
+ * 'CL_INVALID_CONTEXT' if the context associated with command_queue and image
+are not the same or if the context associated with command_queue and events in
+event_wait_list are not the same.
+
+ * 'CL_INVALID_MEM_OBJECT' if image is not a valid image object.
+
+ * 'CL_INVALID_VALUE' if the region being write or written specified by origin
+and region is out of bounds or if ptr is a NULL value.
+
+ * 'CL_INVALID_VALUE' if image is a 2D image object and z is not equal to 0 or
+depth is not equal to 1 or slice_pitch is not equal to 0.
+
+ * 'CL_INVALID_EVENT_WAIT_LIST' if event objects in event_wait_list are not
+valid events.
+
+ * 'CL_MEM_OBJECT_ALLOCATION_FAILURE' if there is a failure to allocate memory
+for data store associated with image.
+
+ * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
+by the OpenCL implementation on the host.
+
+-}
+clEnqueueWriteImage :: Integral a 
+                       => CLCommandQueue -- ^ Refers to the command-queue in
+                                         -- which the write command will be
+                                         -- queued. command_queue and image must
+                                         -- be created with the same OpenCL
+                                         -- contex
+                       -> CLMem -- ^ Refers to a valid 2D or 3D image object.
+                       -> Bool -- ^ Indicates if the write operation is blocking
+                               -- or non-blocking.
+                       -> (a,a,a) -- ^ Defines the (x, y, z) offset in pixels in
+                                  -- the image from where to write or write. If
+                                  -- image is a 2D image object, the z value
+                                  -- given must be 0.
+                       -> (a,a,a) -- ^ Defines the (width, height, depth) in
+                                  -- pixels of the 2D or 3D rectangle being
+                                  -- write or written. If image is a 2D image
+                                  -- object, the depth value given must be 1.
+                       -> a -- ^ The length of each row in bytes. This value
+                            -- must be greater than or equal to the element size
+                            -- in bytes * width. If input_row_pitch is set to 0,
+                            -- the appropriate row pitch is calculated based on
+                            -- the size of each element in bytes multiplied by
+                            -- width.
+                       -> a -- ^ Size in bytes of the 2D slice of the 3D region
+                            -- of a 3D image being written. This must be 0 if
+                            -- image is a 2D image. This value must be greater
+                            -- than or equal to row_pitch * height. If
+                            -- input_slice_pitch is set to 0, the appropriate
+                            -- slice pitch is calculated based on the row_pitch
+                            -- * height.
+                       -> Ptr () -- ^ The pointer to a buffer in host memory
+                                 -- where image data is to be written to.
+                       -> [CLEvent] -- ^ Specify events that need to complete
+                                    -- before this particular command can be
+                                    -- executed. If event_wait_list is empty,
+                                    -- then this particular command does not
+                                    -- wait on any event to complete. The events
+                                    -- specified in event_wait_list act as
+                                    -- synchronization points. The context
+                                    -- associated with events in event_wait_list
+                                    -- and command_queue must be the same.
+                       -> IO CLEvent
+clEnqueueWriteImage cq mem check (orix,oriy,oriz) (regx,regy,regz) rp sp dat xs = 
+  withArray (fmap fromIntegral [orix,oriy,oriz]) $ \pori -> 
+  withArray (fmap fromIntegral [regx,regy,regz]) $ \preg -> 
+  clEnqueue (raw_clEnqueueWriteImage cq mem (fromBool check) pori preg (fromIntegral rp) (fromIntegral sp) dat) xs
+                       
+{-| Enqueues a command to copy image objects.
+
+Notes 
+
+It is currently a requirement that the src_image and dst_image image memory
+objects for 'clEnqueueCopyImage' must have the exact same image format (i.e. the
+'CLImageFormat' descriptor specified when src_image and dst_image are created
+must match).
+
+src_image and dst_image can be 2D or 3D image objects allowing us to perform the
+following actions:
+
+ * Copy a 2D image object to a 2D image object.
+
+ * Copy a 2D image object to a 2D slice of a 3D image object.
+
+ * Copy a 2D slice of a 3D image object to a 2D image object.
+
+ * Copy a 3D image object to a 3D image object.
+
+'clEnqueueCopyImage' returns the 'CLEvent' if the function is executed
+successfully. It can throw the following 'CLError' exceptions:
+
+ * 'CL_INVALID_COMMAND_QUEUE if command_queue is not a valid command-queue.
+
+ * 'CL_INVALID_CONTEXT if the context associated with command_queue, src_image
+and dst_image are not the same or if the context associated with command_queue
+and events in event_wait_list are not the same.
+
+ * 'CL_INVALID_MEM_OBJECT if src_image and dst_image are not valid image
+objects.
+
+ * 'CL_IMAGE_FORMAT_MISMATCH if src_image and dst_image do not use the same
+image format.
+
+ * 'CL_INVALID_VALUE if the 2D or 3D rectangular region specified by src_origin
+and src_origin + region refers to a region outside src_image, or if the 2D or 3D
+rectangular region specified by dst_origin and dst_origin + region refers to a
+region outside dst_image.
+
+ * 'CL_INVALID_VALUE if src_image is a 2D image object and src_origin.z is not
+equal to 0 or region.depth is not equal to 1.
+
+ * 'CL_INVALID_VALUE if dst_image is a 2D image object and dst_origen.z is not
+equal to 0 or region.depth is not equal to 1.
+
+ * 'CL_INVALID_EVENT_WAIT_LIST if event objects in event_wait_list are not valid
+events.
+
+ * 'CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate memory
+for data store associated with src_image or dst_image.
+
+ * 'CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources required
+by the OpenCL implementation on the host.
+
+ * 'CL_MEM_COPY_OVERLAP if src_image and dst_image are the same image object and
+the source and destination regions overlap.
+
+-}
+clEnqueueCopyImage :: Integral a 
+                      => CLCommandQueue -- ^ Refers to the command-queue in
+                                        -- which the copy command will be
+                                        -- queued. The OpenCL context associated
+                                        -- with command_queue, src_image and
+                                        -- dst_image must be the same.
+                      -> CLMem -- ^ src
+                      -> CLMem -- ^ dst
+                      -> (a,a,a) -- ^ Defines the starting (x, y, z) location in
+                                 -- pixels in src_image from where to start the
+                                 -- data copy. If src_image is a 2D image
+                                 -- object, the z value given must be 0.
+                      -> (a,a,a) -- ^ Defines the starting (x, y, z) location in
+                                 -- pixels in dst_image from where to start the
+                                 -- data copy. If dst_image is a 2D image
+                                 -- object, the z value given must be 0.
+                      -> (a,a,a) -- ^ Defines the (width, height, depth) in
+                                 -- pixels of the 2D or 3D rectangle to copy. If
+                                 -- src_image or dst_image is a 2D image object,
+                                 -- the depth value given must be 1.
+                      -> [CLEvent] -- ^ Specify events that need to complete
+                                   -- before this particular command can be
+                                   -- executed. If event_wait_list is empty, then
+                                   -- this particular command does not wait on
+                                   -- any event to complete. 
+                      -> IO CLEvent
+clEnqueueCopyImage cq src dst (src_orix,src_oriy,src_oriz) (dst_orix,dst_oriy,dst_oriz) (regx,regy,regz) xs =
+  withArray (fmap fromIntegral [src_orix,src_oriy,src_oriz]) $ \psrc_ori -> 
+  withArray (fmap fromIntegral [dst_orix,dst_oriy,dst_oriz]) $ \pdst_ori -> 
+  withArray (fmap fromIntegral [regx,regy,regz]) $ \preg -> 
+  clEnqueue (raw_clEnqueueCopyImage cq src dst psrc_ori pdst_ori preg) xs
+
+
+{-| Enqueues a command to copy an image object to a buffer object.
+
+Returns an event object that identifies this particular copy command and can be
+used to query or queue a wait for this particular command to complete. event can
+be NULL in which case it will not be possible for the application to query the
+status of this command or queue a wait for this command to
+complete. 'clEnqueueBarrier' can be used instead.
+
+'clEnqueueCopyImageToBuffer' returns the 'CLEvent' if the function is executed
+successfully. It can throw the following 'CLError' exceptions:
+
+ * CL_INVALID_COMMAND_QUEUE if command_queue is not a valid command-queue.
+
+ * CL_INVALID_CONTEXT if the context associated with command_queue, src_image
+and dst_buffer are not the same or if the context associated with command_queue
+and events in event_wait_list are not the same.
+
+ * CL_INVALID_MEM_OBJECT if src_image is not a valid image object and dst_buffer
+is not a valid buffer object.
+
+ * CL_INVALID_VALUE if the 2D or 3D rectangular region specified by src_origin
+and src_origin + region refers to a region outside src_image, or if the region
+specified by dst_offset and dst_offset + dst_cb refers to a region outside
+dst_buffer.
+
+ * CL_INVALID_VALUE if src_image is a 2D image object and src_origin.z is not
+equal to 0 or region.depth is not equal to 1.
+
+ * CL_INVALID_EVENT_WAIT_LIST if event objects in event_wait_list are not valid
+events.
+
+ * CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate memory for
+data store associated with src_image or dst_buffer.
+
+ * CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources required by
+the OpenCL implementation on the host.
+
+-}
+clEnqueueCopyImageToBuffer :: Integral a 
+                              => CLCommandQueue -- ^ The OpenCL context
+                                                -- associated with
+                                                -- command_queue, src_image, and
+                                                -- dst_buffer must be the same.
+                              -> CLMem -- ^ src. A valid image object.
+                              -> CLMem -- ^ dst. A valid buffer object.
+                              -> (a,a,a) -- ^ Defines the (x, y, z) offset in
+                                         -- pixels in the image from where to
+                                         -- copy. If src_image is a 2D image
+                                         -- object, the z value given must be 0.
+                              -> (a,a,a) -- ^ Defines the (width, height, depth)
+                                         -- in pixels of the 2D or 3D rectangle
+                                         -- to copy. If src_image is a 2D image
+                                         -- object, the depth value given must
+                                         -- be 1.
+                              -> a -- ^ The offset where to begin copying data
+                                   -- into dst_buffer. The size in bytes of the
+                                   -- region to be copied referred to as dst_cb
+                                   -- is computed as width * height * depth *
+                                   -- bytes/image element if src_image is a 3D
+                                   -- image object and is computed as width *
+                                   -- height * bytes/image element if src_image
+                                   -- is a 2D image object.
+                              -> [CLEvent] -- ^ Specify events that need to
+                                           -- complete before this particular
+                                           -- command can be executed. If
+                                           -- event_wait_list is empty, then
+                                           -- this particular command does not
+                                           -- wait on any event to complete. The
+                                           -- events specified in
+                                           -- event_wait_list act as
+                                           -- synchronization points. The
+                                           -- context associated with events in
+                                           -- event_wait_list and command_queue
+                                           -- must be the same.
+                              -> IO CLEvent
+clEnqueueCopyImageToBuffer cq src dst (src_orix,src_oriy,src_oriz) (regx,regy,regz) offset xs =
+  withArray (fmap fromIntegral [src_orix,src_oriy,src_oriz]) $ \psrc_ori -> 
+  withArray (fmap fromIntegral [regx,regy,regz]) $ \preg -> 
+  clEnqueue (raw_clEnqueueCopyImageToBuffer cq src dst psrc_ori preg (fromIntegral offset)) xs
+
+{-| Enqueues a command to copy a buffer object to an image object.
+
+The size in bytes of the region to be copied from src_buffer referred to as
+src_cb is computed as width * height * depth * bytes/image element if dst_image
+is a 3D image object and is computed as width * height * bytes/image element if
+dst_image is a 2D image object.
+
+Returns an event object that identifies this particular copy command and can be
+used to query or queue a wait for this particular command to complete. event can
+be NULL in which case it will not be possible for the application to query the
+status of this command or queue a wait for this command to
+complete. 'clEnqueueBarrier' can be used instead.
+
+'clEnqueueCopyBufferToImage' returns the 'CLEvent' if the function is executed
+successfully. It can throw the following 'CLError' exceptions:
+
+ * 'CL_INVALID_COMMAND_QUEUE' if command_queue is not a valid command-queue.
+
+ * 'CL_INVALID_CONTEXT' if the context associated with command_queue, src_buffer
+and dst_image are not the same or if the context associated with command_queue
+and events in event_wait_list are not the same.
+
+ * 'CL_INVALID_MEM_OBJECT' if src_buffer is not a valid buffer object and
+dst_image is not a valid image object.
+
+ * 'CL_INVALID_VALUE' if the 2D or 3D rectangular region specified by dst_origin
+and dst_origin + region refers to a region outside dst_origin, or if the region
+specified by src_offset and src_offset + src_cb refers to a region outside
+src_buffer.
+
+ * 'CL_INVALID_VALUE' if dst_image is a 2D image object and dst_origin.z is not
+equal to 0 or region.depth is not equal to 1.
+
+ * 'CL_INVALID_EVENT_WAIT_LIST' if event objects in event_wait_list are not
+valid events.
+
+ * 'CL_MEM_OBJECT_ALLOCATION_FAILURE' if there is a failure to allocate memory
+for data store associated with src_buffer or dst_image.
+
+ * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
+by the OpenCL implementation on the host.
+
+-}
+clEnqueueCopyBufferToImage :: Integral a 
+                              => CLCommandQueue -- ^ The OpenCL context
+                                                -- associated with
+                                                -- command_queue, src_image, and
+                                                -- dst_buffer must be the same.
+                              -> CLMem -- ^ src. A valid buffer object.
+                              -> CLMem -- ^ dst. A valid image object.
+                              -> a -- ^ The offset where to begin copying data
+                                   -- from src_buffer.
+                              -> (a,a,a) -- ^ The (x, y, z) offset in pixels
+                                         -- where to begin copying data to
+                                         -- dst_image. If dst_image is a 2D
+                                         -- image object, the z value given by
+                                         -- must be 0.
+                              -> (a,a,a) -- ^ Defines the (width, height, depth)
+                                         -- in pixels of the 2D or 3D rectangle
+                                         -- to copy. If dst_image is a 2D image
+                                         -- object, the depth value given by
+                                         -- must be 1.
+                              -> [CLEvent] -- ^ Specify events that need to
+                                           -- complete before this particular
+                                           -- command can be executed. If
+                                           -- event_wait_list is empty, then
+                                           -- this particular command does not
+                                           -- wait on any event to complete. The
+                                           -- events specified in
+                                           -- event_wait_list act as
+                                           -- synchronization points. The
+                                           -- context associated with events in
+                                           -- event_wait_list and command_queue
+                                           -- must be the same.
+                              -> IO CLEvent
+clEnqueueCopyBufferToImage cq src dst offset (dst_orix,dst_oriy,dst_oriz) (regx,regy,regz) xs =
+  withArray (fmap fromIntegral [dst_orix,dst_oriy,dst_oriz]) $ \pdst_ori -> 
+  withArray (fmap fromIntegral [regx,regy,regz]) $ \preg -> 
+  clEnqueue (raw_clEnqueueCopyBufferToImage cq src dst (fromIntegral offset) pdst_ori preg) xs
+
+{-| Enqueues a command to map a region of the buffer object given by buffer into
+the host address space and returns a pointer to this mapped region.
+
+If blocking_map is 'True', 'clEnqueueMapBuffer' does not return until the
+specified region in buffer can be mapped.
+
+If blocking_map is 'False' i.e. map operation is non-blocking, the pointer to
+the mapped region returned by 'clEnqueueMapBuffer' cannot be used until the map
+command has completed. The event argument returns an event object which can be
+used to query the execution status of the map command. When the map command is
+completed, the application can access the contents of the mapped region using
+the pointer returned by 'clEnqueueMapBuffer'.
+
+Returns an event object that identifies this particular copy command and can be
+used toquery or queue a wait for this particular command to complete. event can
+be NULL in which case it will not be possible for the application to query the
+status of this command or queue a wait for this command to complete.
+
+The contents of the regions of a memory object mapped for writing
+(i.e. 'CL_MAP_WRITE' is set in map_flags argument to 'clEnqueueMapBuffer' or
+'clEnqueueMapImage') are considered to be undefined until this region is
+unmapped. Reads and writes by a kernel executing on a device to a memory
+region(s) mapped for writing are undefined.
+
+Multiple command-queues can map a region or overlapping regions of a memory
+object for reading (i.e. map_flags = 'CL_MAP_READ'). The contents of the regions
+of a memory object mapped for reading can also be read by kernels executing on a
+device(s). The behavior of writes by a kernel executing on a device to a mapped
+region of a memory object is undefined. Mapping (and unmapping) overlapped
+regions of a buffer or image memory object for writing is undefined.
+
+The behavior of OpenCL function calls that enqueue commands that write or copy
+to regions of a memory object that are mapped is undefined.
+
+'clEnqueueMapBuffer' will return a pointer to the mapped region if the function
+is executed successfully. A nullPtr pointer is returned otherwise with one of
+the following exception:
+
+ * 'CL_INVALID_COMMAND_QUEUE' if command_queue is not a valid command-queue.
+
+ * 'CL_INVALID_CONTEXT' if the context associated with command_queue, src_image
+and dst_buffer are not the same or if the context associated with command_queue
+and events in event_wait_list are not the same.
+
+ * 'CL_INVALID_MEM_OBJECT' if buffer is not a valid buffer object.
+
+ * 'CL_INVALID_VALUE' if region being mapped given by (offset, cb) is out of
+bounds or if values specified in map_flags are not valid
+
+ * 'CL_INVALID_EVENT_WAIT_LIST' if event objects in event_wait_list are not
+valid events.
+
+ * 'CL_MAP_FAILURE' if there is a failure to map the requested region into the
+host address space. This error cannot occur for buffer objects created with
+'CL_MEM_USE_HOST_PTR' or 'CL_MEM_ALLOC_HOST_PTR'.
+
+ * 'CL_MEM_OBJECT_ALLOCATION_FAILURE' if there is a failure to allocate memory
+for data store associated with buffer.
+
+ * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
+by the OpenCL implementation on the host.
+
+The pointer returned maps a region starting at offset and is atleast cb bytes in
+size. The result of a memory access outside this region is undefined.
+
+-}
+clEnqueueMapBuffer :: Integral a => CLCommandQueue 
+                      -> CLMem -- ^ A valid buffer object. The OpenCL context
+                               -- associated with command_queue and buffer must
+                               -- be the same.
+                      -> Bool -- ^ Indicates if the map operation is blocking or
+                              -- non-blocking.
+                      -> [CLMapFlag] -- ^ Is a list and can be set to
+                                     -- 'CL_MAP_READ' to indicate that the
+                                     -- region specified by (offset, cb) in the
+                                     -- buffer object is being mapped for
+                                     -- reading, and/or 'CL_MAP_WRITE' to
+                                     -- indicate that the region specified by
+                                     -- (offset, cb) in the buffer object is
+                                     -- being mapped for writing.
+                      -> a -- ^ The offset in bytes of the region in the buffer
+                           -- object that is being mapped.
+                      -> a -- ^ The size in bytes of the region in the buffer
+                           -- object that is being mapped.
+                      -> [CLEvent] -- ^ Specify events that need to complete
+                                   -- before this particular command can be
+                                   -- executed. If event_wait_list is empty,
+                                   -- then this particular command does not wait
+                                   -- on any event to complete. The events
+                                   -- specified in event_wait_list act as
+                                   -- synchronization points. The context
+                                   -- associated with events in event_wait_list
+                                   -- and command_queue must be the same.
+
+                      -> IO (CLEvent, Ptr ())
+clEnqueueMapBuffer cq mem check xs offset cb [] = 
+  alloca $ \pevent -> do
+    val <- wrapPError $ \perr -> raw_clEnqueueMapBuffer cq mem (fromBool check) flags (fromIntegral offset) (fromIntegral cb) 0 nullPtr pevent perr
+    event <- peek pevent
+    return (event, val)
+    
+      where
+        flags = bitmaskFromFlags xs
+clEnqueueMapBuffer cq mem check xs offset cb events = 
+  allocaArray nevents $ \pevents -> do
+    pokeArray pevents events
+    alloca $ \pevent -> do
+      val <- wrapPError $ \perr -> raw_clEnqueueMapBuffer cq mem (fromBool check) flags (fromIntegral offset) (fromIntegral cb) cnevents pevents pevent perr
+      event <- peek pevent
+      return (event, val)
+    where
+      flags = bitmaskFromFlags xs
+      nevents = length events
+      cnevents = fromIntegral nevents
+
+{-| Enqueues a command to map a region of an image object into the host address
+space and returns a pointer to this mapped region.
+
+If blocking_map is 'False' i.e. map operation is non-blocking, the pointer to
+the mapped region returned by 'clEnqueueMapImage' cannot be used until the map
+command has completed. The event argument returns an event object which can be
+used to query the execution status of the map command. When the map command is
+completed, the application can access the contents of the mapped region using
+the pointer returned by 'clEnqueueMapImage'.
+
+Returns an event object that identifies this particular copy command and can be
+used to query or queue a wait for this particular command to complete. event can
+be NULL in which case it will not be possible for the application to query the
+status of this command or queue a wait for this command to complete.
+
+If the buffer or image object is created with 'CL_MEM_USE_HOST_PTR' set in
+mem_flags, the following will be true:
+
+* The host_ptr specified in 'clCreateBuffer', 'clCreateImage2D', or
+'clCreateImage3D' is guaranteed to contain the latest bits in the region being
+mapped when the 'clEnqueueMapBuffer' or 'clEnqueueMapImage' command has
+completed.
+
+ * The pointer value returned by 'clEnqueueMapBuffer' or 'clEnqueueMapImage'
+will be derived from the host_ptr specified when the buffer or image object is
+created.  
+
+The contents of the regions of a memory object mapped for writing
+(i.e. 'CL_MAP_WRITE' is set in map_flags argument to 'clEnqueueMapBuffer' or
+'clEnqueueMapImage') are considered to be undefined until this region is
+unmapped. Reads and writes by a kernel executing on a device to a memory
+region(s) mapped for writing are undefined.
+
+Multiple command-queues can map a region or overlapping regions of a memory
+object for reading (i.e. map_flags = 'CL_MAP_READ'). The contents of the regions
+of a memory object mapped for reading can also be read by kernels executing on a
+device(s). The behavior of writes by a kernel executing on a device to a mapped
+region of a memory object is undefined. Mapping (and unmapping) overlapped
+regions of a buffer or image memory object for writing is undefined.
+
+The behavior of OpenCL function calls that enqueue commands that write or copy
+to regions of a memory object that are mapped is undefined.
+
+'clEnqueueMapImage' will return a pointer to the mapped region if the
+function is executed successfully also the scan-line (row) pitch in bytes for
+the mapped region and the size in bytes of each 2D slice for the mapped
+region. For a 2D image, zero is returned as slice pitch. A nullPtr pointer is
+returned otherwise with one of the following exception:
+
+ * 'CL_INVALID_COMMAND_QUEUE' if command_queue is not a valid command-queue.
+
+ * 'CL_INVALID_CONTEXT' if the context associated with command_queue and image
+are not the same or if the context associated with command_queue and events in
+event_wait_list are not the same.
+
+ * 'CL_INVALID_MEM_OBJECT' if image is not a valid image object.
+
+ * 'CL_INVALID_VALUE' if region being mapped given by (origin, origin+region) is
+out of bounds or if values specified in map_flags are not valid.
+
+ * 'CL_INVALID_VALUE' if image is a 2D image object and z is not equal to 0 or
+depth is not equal to 1.
+
+ * 'CL_INVALID_EVENT_WAIT_LIST' if event objects in event_wait_list are not
+valid events.
+
+ * 'CL_MAP_FAILURE' if there is a failure to map the requested region into the
+host address space. This error cannot occur for image objects created with
+'CL_MEM_USE_HOST_PTR' or 'CL_MEM_ALLOC_HOST_PTR'.
+
+ * 'CL_MEM_OBJECT_ALLOCATION_FAILURE' if there is a failure to allocate memory
+for data store associated with image.
+
+ * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
+by the OpenCL implementation on the host.
+
+The pointer returned maps a 2D or 3D region starting at origin and is atleast
+(image_row_pitch * y + x) pixels in size for a 2D image, and is atleast
+(image_slice_pitch * z] + image_row_pitch * y + x) pixels in size for a 3D
+image. The result of a memory access outside this region is undefined.
+
+-}
+clEnqueueMapImage :: Integral a => CLCommandQueue 
+                     -> CLMem -- ^ A valid image object. The OpenCL context
+                              -- associated with command_queue and image must be
+                              -- the same.
+                     -> Bool -- ^ Indicates if the map operation is blocking or
+                             -- non-blocking. If blocking_map is 'True',
+                             -- 'clEnqueueMapImage' does not return until the
+                             -- specified region in image can be mapped.
+                     -> [CLMapFlag] -- ^ Is a bit-field and can be set to
+                                    -- 'CL_MAP_READ' to indicate that the region
+                                    -- specified by (origin, region) in the
+                                    -- image object is being mapped for reading,
+                                    -- and/or 'CL_MAP_WRITE' to indicate that the
+                                    -- region specified by (origin, region) in
+                                    -- the image object is being mapped for
+                                    -- writing.
+                     -> (a,a,a) -- ^ Define the (x, y, z) offset in pixels of
+                                -- the 2D or 3D rectangle region that is to be
+                                -- mapped. If image is a 2D image object, the z
+                                -- value given must be 0.
+                     -> (a,a,a) -- ^ Define the (width, height, depth) in pixels
+                                -- of the 2D or 3D rectangle region that is to
+                                -- be mapped. If image is a 2D image object, the
+                                -- depth value given must be 1.
+                     -> [CLEvent] -- ^ Specify events that need to complete
+                                  -- before 'clEnqueueMapImage' can be
+                                  -- executed. If event_wait_list is empty, then
+                                  -- 'clEnqueueMapImage' does not wait on any
+                                  -- event to complete. The events specified in
+                                  -- event_wait_list act as synchronization
+                                  -- points. The context associated with events
+                                  -- in event_wait_list and command_queue must
+                                  -- be the same.
+                     -> IO (CLEvent, (Ptr (), CSize, CSize))
+clEnqueueMapImage cq mem check xs (orix,oriy,oriz) (regx,regy,regz) [] = 
+  alloca $ \ppitch -> 
+  alloca $ \pslice ->
+  withArray (fmap fromIntegral [orix,oriy,oriz]) $ \pori -> 
+  withArray (fmap fromIntegral [regx,regy,regz]) $ \preg -> 
+  alloca $ \pevent -> do
+    val <- wrapPError $ \perr -> raw_clEnqueueMapImage cq mem (fromBool check) flags pori preg ppitch pslice 0 nullPtr pevent perr
+    event <- peek pevent
+    pitch <- peek ppitch
+    slice <- peek pslice
+    return (event, (val, pitch, slice))
+    
+      where
+        flags = bitmaskFromFlags xs
+clEnqueueMapImage cq mem check xs (orix,oriy,oriz) (regx,regy,regz) events = 
+  alloca $ \ppitch -> 
+  alloca $ \pslice ->
+  withArray (fmap fromIntegral [orix,oriy,oriz]) $ \pori -> 
+  withArray (fmap fromIntegral [regx,regy,regz]) $ \preg -> 
+  allocaArray nevents $ \pevents -> do
+    pokeArray pevents events
+    alloca $ \pevent -> do
+      val <- wrapPError $ \perr -> raw_clEnqueueMapImage cq mem (fromBool check) flags pori preg ppitch pslice cnevents pevents pevent perr
+      event <- peek pevent
+      pitch <- peek ppitch
+      slice <- peek pslice
+      return (event, (val, pitch, slice))
+
+    where
+      flags = bitmaskFromFlags xs
+      nevents = length events
+      cnevents = fromIntegral nevents
+      
+{-| Enqueues a command to unmap a previously mapped region of a memory object.
+
+Returns an event object that identifies this particular copy command and can be
+used to query or queue a wait for this particular command to complete. event can
+be NULL in which case it will not be possible for the application to query the
+status of this command or queue a wait for this command to
+complete. 'clEnqueueBarrier' can be used instead.
+
+Reads or writes from the host using the pointer returned by 'clEnqueueMapBuffer'
+or 'clEnqueueMapImage' are considered to be complete.
+
+'clEnqueueMapBuffer' and 'clEnqueueMapImage' increments the mapped count of the
+memory object. The initial mapped count value of a memory object is
+zero. Multiple calls to 'clEnqueueMapBuffer' or 'clEnqueueMapImage' on the same
+memory object will increment this mapped count by appropriate number of
+calls. 'clEnqueueUnmapMemObject' decrements the mapped count of the memory
+object.
+
+'clEnqueueMapBuffer' and 'clEnqueueMapImage' act as synchronization points for a
+region of the memory object being mapped.
+
+'clEnqueueUnmapMemObject' returns the 'CLEvent' if the function is executed
+successfully. It can throw the following 'CLError' exceptions:
+
+ * CL_INVALID_COMMAND_QUEUE if command_queue is not a valid command-queue.
+
+ * CL_INVALID_MEM_OBJECT if memobj is not a valid memory object.
+
+ * CL_INVALID_VALUE if mapped_ptr is not a valid pointer returned by
+'clEnqueueMapBuffer' or 'clEnqueueMapImage' for memobj.
+
+ * CL_INVALID_EVENT_WAIT_LIST if event objects in event_wait_list are not valid
+events.
+
+ * CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources required by
+the OpenCL implementation on the host.
+
+ * CL_INVALID_CONTEXT if the context associated with command_queue and memobj
+are not the same or if the context associated with command_queue and events in
+event_wait_list are not the same.
+-}
+clEnqueueUnmapMemObject :: CLCommandQueue 
+                           -> CLMem -- ^ A valid memory object. The OpenCL
+                                    -- context associated with command_queue and
+                                    -- memobj must be the same.
+                           -> Ptr () -- ^ The host address returned by a
+                                     -- previous call to 'clEnqueueMapBuffer' or
+                                     -- 'clEnqueueMapImage' for memobj.
+                           -> [CLEvent] -- ^ Specify events that need to
+                                        -- complete before
+                                        -- 'clEnqueueUnmapMemObject' can be
+                                        -- executed. If event_wait_list is
+                                        -- empty, then 'clEnqueueUnmapMemObject'
+                                        -- does not wait on any event to
+                                        -- complete. The events specified in
+                                        -- event_wait_list act as
+                                        -- synchronization points. The context
+                                        -- associated with events in
+                                        -- event_wait_list and command_queue
+                                        -- must be the same.
+
+                           -> IO CLEvent
+clEnqueueUnmapMemObject cq mem pp = clEnqueue (raw_clEnqueueUnmapMemObject cq mem pp)
+
+-- -----------------------------------------------------------------------------
+{-| Enqueues a command to execute a kernel on a device. Each work-item is
+uniquely identified by a global identifier. The global ID, which can be read
+inside the kernel, is computed using the value given by global_work_size and
+global_work_offset. In OpenCL 1.0, the starting global ID is always (0, 0,
+... 0). In addition, a work-item is also identified within a work-group by a
+unique local ID. The local ID, which can also be read by the kernel, is computed
+using the value given by local_work_size. The starting local ID is always (0, 0,
+... 0).
+
+Returns the event if the kernel execution was successfully queued. It can throw
+the following 'CLError' exceptions:
+
+ * 'CL_INVALID_PROGRAM_EXECUTABLE' if there is no successfully built program
+executable available for device associated with command_queue.
+
+ * 'CL_INVALID_COMMAND_QUEUE' if command_queue is not a valid command-queue.
+
+ * 'CL_INVALID_KERNEL' if kernel is not a valid kernel object.
+
+ * 'CL_INVALID_CONTEXT' if context associated with command_queue and kernel is
+not the same or if the context associated with command_queue and events in
+event_wait_list are not the same.
+
+ * 'CL_INVALID_KERNEL_ARGS' if the kernel argument values have not been
+specified.
+
+ * 'CL_INVALID_WORK_DIMENSION' if work_dim is not a valid value (i.e. a value
+between 1 and 3).
+
+ * 'CL_INVALID_WORK_GROUP_SIZE' if local_work_size is specified and number of
+work-items specified by global_work_size is not evenly divisable by size of
+work-group given by local_work_size or does not match the work-group size
+specified for kernel using the __attribute__((reqd_work_group_size(X, Y, Z)))
+qualifier in program source.
+
+ * 'CL_INVALID_WORK_GROUP_SIZE' if local_work_size is specified and the total
+number of work-items in the work-group computed as local_work_size[0]
+*... local_work_size[work_dim - 1] is greater than the value specified by
+'CL_DEVICE_MAX_WORK_GROUP_SIZE' in the table of OpenCL Device Queries for
+clGetDeviceInfo.
+
+ * 'CL_INVALID_WORK_GROUP_SIZE' if local_work_size is NULL and the
+__attribute__((reqd_work_group_size(X, Y, Z))) qualifier is used to declare the
+work-group size for kernel in the program source.
+
+ * 'CL_INVALID_WORK_ITEM_SIZE' if the number of work-items specified in any of
+local_work_size[0], ... local_work_size[work_dim - 1] is greater than the
+corresponding values specified by 'CL_DEVICE_MAX_WORK_ITEM_SIZES'[0],
+.... 'CL_DEVICE_MAX_WORK_ITEM_SIZES'[work_dim - 1].
+
+ * 'CL_OUT_OF_RESOURCES' if there is a failure to queue the execution instance
+of kernel on the command-queue because of insufficient resources needed to
+execute the kernel. For example, the explicitly specified local_work_size causes
+a failure to execute the kernel because of insufficient resources such as
+registers or local memory. Another example would be the number of read-only
+image args used in kernel exceed the 'CL_DEVICE_MAX_READ_IMAGE_ARGS' value for
+device or the number of write-only image args used in kernel exceed the
+'CL_DEVICE_MAX_WRITE_IMAGE_ARGS' value for device or the number of samplers used
+in kernel exceed 'CL_DEVICE_MAX_SAMPLERS' for device.
+
+ * 'CL_MEM_OBJECT_ALLOCATION_FAILURE' if there is a failure to allocate memory for data store associated with image or buffer objects specified as arguments to kernel.
+
+ * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required by
+the OpenCL implementation on the host.
+-}
+clEnqueueNDRangeKernel :: Integral a => CLCommandQueue -> CLKernel -> [a] -> [a] 
+                          -> [CLEvent] -> IO CLEvent
+clEnqueueNDRangeKernel cq krn gws lws events = withArray (map fromIntegral gws) $ \pgws -> withMaybeArray (map fromIntegral lws) $ \plws -> do
+  clEnqueue (raw_clEnqueueNDRangeKernel cq krn num nullPtr pgws plws) events
+    where
+      num = fromIntegral $ length gws
+
+{-| Enqueues a command to execute a kernel on a device. The kernel is executed
+using a single work-item.
+
+'clEnqueueTask' is equivalent to calling 'clEnqueueNDRangeKernel' with work_dim
+= 1, global_work_offset = [], global_work_size[0] set to 1, and
+local_work_size[0] set to 1.
+
+Returns the evens if the kernel execution was successfully queued. It can throw
+the following 'CLError' exceptions:
+
+ * 'CL_INVALID_PROGRAM_EXECUTABLE' if there is no successfully built program
+executable available for device associated with command_queue.
+
+ * 'CL_INVALID_COMMAND_QUEUE if' command_queue is not a valid command-queue.
+
+ * 'CL_INVALID_KERNEL' if kernel is not a valid kernel object.
+
+ * 'CL_INVALID_CONTEXT' if context associated with command_queue and kernel is
+not the same or if the context associated with command_queue and events in
+event_wait_list are not the same.
+
+ * 'CL_INVALID_KERNEL_ARGS' if the kernel argument values have not been specified.
+
+ * 'CL_INVALID_WORK_GROUP_SIZE' if a work-group size is specified for kernel
+using the __attribute__((reqd_work_group_size(X, Y, Z))) qualifier in program
+source and is not (1, 1, 1).
+
+ * 'CL_OUT_OF_RESOURCES' if there is a failure to queue the execution instance
+of kernel on the command-queue because of insufficient resources needed to
+execute the kernel.
+
+ * 'CL_MEM_OBJECT_ALLOCATION_FAILURE' if there is a failure to allocate memory
+for data store associated with image or buffer objects specified as arguments to
+kernel.
+
+ * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
+by the OpenCL implementation on the host.
+-}
+clEnqueueTask :: CLCommandQueue -> CLKernel -> [CLEvent] -> IO CLEvent
+clEnqueueTask cq krn = clEnqueue (raw_clEnqueueTask cq krn)
+  
+{-| Enqueues a command to execute a native C/C++ function not compiled using the
+OpenCL compiler. A native user function can only be executed on a command-queue
+created on a device that has 'CL_EXEC_NATIVE_KERNEL' capability set in
+'clGetDeviceExecutionCapabilities'.
+
+The data pointed to by args and cb_args bytes in size will be copied and a
+pointer to this copied region will be passed to user_func. The copy needs to be
+done because the memory objects ('CLMem' values) that args may contain need to
+be modified and replaced by appropriate pointers to global memory. When
+'clEnqueueNativeKernel' returns, the memory region pointed to by args can be
+reused by the application.
+
+Returns the evens if the kernel execution was successfully queued. It can throw
+the following 'CLError' exceptions:
+
+ * 'CL_INVALID_COMMAND_QUEUE' if command_queue is not a valid command-queue.
+
+ * 'CL_INVALID_CONTEXT' if context associated with command_queue and events in
+event-wait_list are not the same.
+
+ * 'CL_INVALID_VALUE' if args is a NULL value and cb_args is greater than 0, or
+if args is a NULL value and num_mem_objects is greater than 0.
+
+ * 'CL_INVALID_VALUE' if args is not NULL and cb_args is 0.
+
+ * 'CL_INVALID_OPERATION' if device cannot execute the native kernel.
+
+ * 'CL_INVALID_MEM_OBJECT' if one or more memory objects specified in mem_list
+are not valid or are not buffer objects.
+
+ * 'CL_OUT_OF_RESOURCES' if there is a failure to queue the execution instance
+of kernel on the command-queue because of insufficient resources needed to
+execute the kernel.
+
+ * 'CL_MEM_OBJECT_ALLOCATION_FAILURE' if there is a failure to allocate memory
+for data store associated with buffer objects specified as arguments to kernel.
+
+ * 'CL_INVALID_EVENT_WAIT_LIST' if event objects in event_wait_list are not
+valid events.
+
+ * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
+by the OpenCL implementation on the host.
+
+-}
+clEnqueueNativeKernel :: CLCommandQueue -> (Ptr () -> IO ()) -> Ptr () -> CSize 
+                         -> [CLMem] -> [Ptr ()] -> [CLEvent] -> IO CLEvent
+clEnqueueNativeKernel cq f dat sz xs ys evs = 
+  withMaybeArray xs $ \pmem -> 
+  withMaybeArray ys $ \pbuff -> do
+    fptr <- wrapNativeKernelCallback f
+    clEnqueue (raw_clEnqueueNativeKernel cq fptr dat sz 
+               (fromIntegral . length $ xs) pmem pbuff) evs
+                          
+-- -----------------------------------------------------------------------------
+-- | Enqueues a marker command to command_queue. The marker command returns an
+-- event which can be used to queue a wait on this marker event i.e. wait for
+-- all commands queued before the marker command to complete. Returns the event
+-- if the function is successfully executed. It throw the 'CLError' exception
+-- 'CL_INVALID_COMMAND_QUEUE' if command_queue is not a valid command-queue and
+-- throw 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources
+-- required by the OpenCL implementation on the host.
+clEnqueueMarker :: CLCommandQueue -> IO CLEvent
+clEnqueueMarker cq = alloca $ \event 
+                              -> whenSuccess (raw_clEnqueueMarker cq event)
+                                 $ peek event
+         
+{-| Enqueues a wait for a specific event or a list of events to complete before
+any future commands queued in the command-queue are executed. The context
+associated with events in event_list and command_queue must be the same.
+
+It can throw the following 'CLError' exceptions:
+
+ * 'CL_INVALID_COMMAND_QUEUE' if command_queue is not a valid command-queue.
+
+ * 'CL_INVALID_CONTEXT' if the context associated with command_queue and events
+in event_list are not the same.
+
+ * 'CL_INVALID_VALUE' if num_events is zero.
+
+ * 'CL_INVALID_EVENT' if event objects specified in event_list are not valid
+events.
+
+ * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
+by the OpenCL implementation on the host.
+-}
+clEnqueueWaitForEvents :: CLCommandQueue -> [CLEvent] -> IO ()
+clEnqueueWaitForEvents cq [] = whenSuccess 
+                               (raw_clEnqueueWaitForEvents cq 0 nullPtr)
+                               $ return ()
+clEnqueueWaitForEvents cq events = allocaArray nevents $ \pevents -> do
+  pokeArray pevents events
+  whenSuccess (raw_clEnqueueWaitForEvents cq cnevents pevents)
+    $ return ()
+    where
+      nevents = length events
+      cnevents = fromIntegral nevents
+
+-- | 'clEnqueueBarrier' is a synchronization point that ensures that all queued
+-- commands in command_queue have finished execution before the next batch of
+-- commands can begin execution. It throws 'CL_INVALID_COMMAND_QUEUE' if
+-- command_queue is not a valid command-queue and throws
+-- 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
+-- by the OpenCL implementation on the host.
+clEnqueueBarrier :: CLCommandQueue -> IO ()
+clEnqueueBarrier cq = whenSuccess (raw_clEnqueueBarrier cq) $ return ()
+  
+-- -----------------------------------------------------------------------------
+{-| Issues all previously queued OpenCL commands in a command-queue to the
+device associated with the command-queue.  'clFlush' only guarantees that all
+queued commands to command_queue get issued to the appropriate device. There is
+no guarantee that they will be complete after 'clFlush' returns.
+
+ 'clFlush' returns 'True' if the function call was executed successfully. It
+returns 'False' if command_queue is not a valid command-queue or if there is a
+failure to allocate resources required by the OpenCL implementation on the host.
+
+ Any blocking commands queued in a command-queue such as 'clEnqueueReadImage' or
+'clEnqueueReadBuffer' with blocking_read set to 'True', 'clEnqueueWriteImage' or
+'clEnqueueWriteBuffer' with blocking_write set to 'True', 'clEnqueueMapImage' or
+'clEnqueueMapBuffer' with blocking_map set to 'True' or 'clWaitForEvents'
+perform an implicit flush of the command-queue.
+
+ To use event objects that refer to commands enqueued in a command-queue as
+event objects to wait on by commands enqueued in a different command-queue, the
+application must call a 'clFlush' or any blocking commands that perform an
+implicit flush of the command-queue where the commands that refer to these event
+objects are enqueued.
+-}
+clFlush :: CLCommandQueue -> IO Bool
+clFlush = wrapCheckSuccess . raw_clFlush
+             
+-- | Blocks until all previously queued OpenCL commands in a command-queue are 
+-- issued to the associated device and have completed.
+-- 'clFinish' does not return until all queued commands in command_queue have 
+-- been processed and completed. 'clFinish' is also a synchronization point.
+--
+-- 'clFinish' returns 'True' if the function call was executed successfully. It 
+-- returns 'False' if command_queue is not a valid command-queue or if there is 
+-- a failure to allocate resources required by the OpenCL implementation on the 
+-- host.
+clFinish :: CLCommandQueue -> IO Bool
+clFinish = wrapCheckSuccess . raw_clFinish
+             
+-- -----------------------------------------------------------------------------
diff --git a/src/Control/Parallel/OpenCL/Context.chs b/src/Control/Parallel/OpenCL/Context.chs
new file mode 100644
--- /dev/null
+++ b/src/Control/Parallel/OpenCL/Context.chs
@@ -0,0 +1,224 @@
+{- Copyright (c) 2011 Luis Cabellos,
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of  nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-}
+{-# LANGUAGE ForeignFunctionInterface, ScopedTypeVariables, CPP #-}
+module Control.Parallel.OpenCL.Context(
+  -- * Types
+  CLContext, CLContextProperty(..),
+  -- * Context Functions
+  clCreateContext, clCreateContextFromType, clRetainContext, clReleaseContext,
+  clGetContextReferenceCount, clGetContextDevices, clGetContextProperties )
+    where
+
+-- -----------------------------------------------------------------------------
+import Foreign( 
+  Ptr, FunPtr, nullPtr, castPtr, alloca, allocaArray, peek, peekArray, 
+  ptrToIntPtr, intPtrToPtr, withArray )
+import Foreign.C.Types( CSize )
+import Foreign.C.String( CString, peekCString )
+import Foreign.Storable( sizeOf )
+import Control.Parallel.OpenCL.Types( 
+  CLuint, CLint, CLDeviceType_, CLContextInfo_, CLContextProperty_, CLDeviceID, 
+  CLContext, CLDeviceType, CLPlatformID, bitmaskFromFlags, getCLValue, getEnumCL,
+  whenSuccess, wrapCheckSuccess, wrapPError, wrapGetInfo )
+
+#ifdef __APPLE__
+#include <OpenCL/opencl.h>
+#else
+#include <CL/cl.h>
+#endif
+
+-- -----------------------------------------------------------------------------
+type ContextCallback = CString -> Ptr () -> CSize -> Ptr () -> IO ()
+foreign import CALLCONV "wrapper" wrapContextCallback :: 
+  ContextCallback -> IO (FunPtr ContextCallback)
+foreign import CALLCONV "clCreateContext" raw_clCreateContext ::
+  Ptr CLContextProperty_ -> CLuint -> Ptr CLDeviceID -> FunPtr ContextCallback -> 
+  Ptr () -> Ptr CLint -> IO CLContext
+foreign import CALLCONV "clCreateContextFromType" raw_clCreateContextFromType :: 
+  Ptr CLContextProperty_ -> CLDeviceType_ -> FunPtr ContextCallback -> 
+  Ptr () -> Ptr CLint -> IO CLContext
+foreign import CALLCONV "clRetainContext" raw_clRetainContext :: 
+  CLContext -> IO CLint
+foreign import CALLCONV "clReleaseContext" raw_clReleaseContext :: 
+  CLContext -> IO CLint
+foreign import CALLCONV "clGetContextInfo" raw_clGetContextInfo :: 
+  CLContext -> CLContextInfo_ -> CSize -> Ptr () -> Ptr CSize -> IO CLint
+
+-- -----------------------------------------------------------------------------
+#c
+enum CLContextProperties {
+  cL_CONTEXT_PLATFORM_=CL_CONTEXT_PLATFORM,
+  };
+#endc
+{#enum CLContextProperties {upcaseFirstLetter} #}
+
+-- | Specifies a context property name and its corresponding value.
+data CLContextProperty = CL_CONTEXT_PLATFORM CLPlatformID 
+                         -- ^ Specifies the platform to use.
+                       deriving( Show )
+
+packContextProperties :: [CLContextProperty] -> [CLContextProperty_]
+packContextProperties [] = [0]
+packContextProperties (CL_CONTEXT_PLATFORM pid : xs) = getCLValue CL_CONTEXT_PLATFORM_ 
+                                                       : (fromIntegral . ptrToIntPtr $ pid) 
+                                                       : packContextProperties xs
+
+unpackContextProperties :: [CLContextProperty_] -> [CLContextProperty]
+unpackContextProperties [] = error "non-exhaustive Context Property list"
+unpackContextProperties [x] 
+  | x == 0 = []
+  | otherwise = error "non-exhaustive Context Property list"
+unpackContextProperties (x:y:xs) = let ys = unpackContextProperties xs 
+                                   in case getEnumCL x of
+                                     CL_CONTEXT_PLATFORM_ 
+                                       -> CL_CONTEXT_PLATFORM 
+                                          (intPtrToPtr . fromIntegral $ y) : ys
+  
+-- -----------------------------------------------------------------------------
+mkContextCallback :: (String -> IO ()) -> ContextCallback
+mkContextCallback f msg _ _ _ = peekCString msg >>= f
+
+-- | Creates an OpenCL context.
+-- An OpenCL context is created with one or more devices. Contexts are used by 
+-- the OpenCL runtime for managing objects such as command-queues, memory, 
+-- program and kernel objects and for executing kernels on one or more devices 
+-- specified in the context.
+clCreateContext :: [CLContextProperty] -> [CLDeviceID] -> (String -> IO ()) 
+                   -> IO CLContext
+clCreateContext [] devs f = withArray devs $ \pdevs ->
+  wrapPError $ \perr -> do
+    fptr <- wrapContextCallback $ mkContextCallback f
+    raw_clCreateContext nullPtr cndevs pdevs fptr nullPtr perr
+    where
+      cndevs = fromIntegral . length $ devs
+clCreateContext props devs f = withArray devs $ \pdevs ->
+  wrapPError $ \perr -> do
+    fptr <- wrapContextCallback $ mkContextCallback f
+    withArray (packContextProperties props) $ \pprops ->
+      raw_clCreateContext pprops cndevs pdevs fptr nullPtr perr    
+    where
+      cndevs = fromIntegral . length $ devs
+
+-- | Create an OpenCL context from a device type that identifies the specific 
+-- device(s) to use.
+clCreateContextFromType :: [CLContextProperty] -> [CLDeviceType] 
+                           -> (String -> IO ()) -> IO CLContext
+clCreateContextFromType [] xs f = wrapPError $ \perr -> do
+  fptr <- wrapContextCallback $ mkContextCallback f
+  raw_clCreateContextFromType nullPtr types fptr nullPtr perr
+    where
+      types = bitmaskFromFlags xs
+clCreateContextFromType props xs f = wrapPError $ \perr -> do
+  fptr <- wrapContextCallback $ mkContextCallback f
+  withArray (packContextProperties props) $ \pprops -> 
+    raw_clCreateContextFromType pprops types fptr nullPtr perr
+    where
+      types = bitmaskFromFlags xs
+
+-- | Increment the context reference count.
+-- 'clCreateContext' and 'clCreateContextFromType' perform an implicit retain. 
+-- This is very helpful for 3rd party libraries, which typically get a context 
+-- passed to them by the application. However, it is possible that the 
+-- application may delete the context without informing the library. Allowing 
+-- functions to attach to (i.e. retain) and release a context solves the 
+-- problem of a context being used by a library no longer being valid.
+-- Returns 'True' if the function is executed successfully, or 'False' if 
+-- context is not a valid OpenCL context.
+clRetainContext :: CLContext -> IO Bool
+clRetainContext ctx = wrapCheckSuccess $ raw_clRetainContext ctx 
+
+-- | Decrement the context reference count.
+-- After the context reference count becomes zero and all the objects attached 
+-- to context (such as memory objects, command-queues) are released, the 
+-- context is deleted.
+-- Returns 'True' if the function is executed successfully, or 'False' if 
+-- context is not a valid OpenCL context.
+clReleaseContext :: CLContext -> IO Bool
+clReleaseContext ctx = wrapCheckSuccess $ raw_clReleaseContext ctx 
+
+getContextInfoSize :: CLContext -> CLContextInfo_ -> IO CSize
+getContextInfoSize ctx infoid = alloca $ \(value_size :: Ptr CSize) -> do
+  whenSuccess (raw_clGetContextInfo ctx infoid 0 nullPtr value_size)
+    $ peek value_size
+
+#c
+enum CLContextInfo {
+  cL_CONTEXT_REFERENCE_COUNT=CL_CONTEXT_REFERENCE_COUNT,
+  cL_CONTEXT_DEVICES=CL_CONTEXT_DEVICES,
+  cL_CONTEXT_PROPERTIES=CL_CONTEXT_PROPERTIES
+  };
+#endc
+{#enum CLContextInfo {upcaseFirstLetter} #}
+
+-- | Return the context reference count. The reference count returned should be 
+-- considered immediately stale. It is unsuitable for general use in 
+-- applications. This feature is provided for identifying memory leaks.
+--
+-- This function execute OpenCL clGetContextInfo with 'CL_CONTEXT_REFERENCE_COUNT'.
+clGetContextReferenceCount :: CLContext -> IO CLuint
+clGetContextReferenceCount ctx =
+    wrapGetInfo (\(dat :: Ptr CLuint) ->
+        raw_clGetContextInfo ctx infoid size (castPtr dat)) id
+    where 
+      infoid = getCLValue CL_CONTEXT_REFERENCE_COUNT
+      size = fromIntegral $ sizeOf (0::CLuint)
+
+-- | Return the list of devices in context.
+--
+-- This function execute OpenCL clGetContextInfo with 'CL_CONTEXT_DEVICES'.
+clGetContextDevices :: CLContext -> IO [CLDeviceID]
+clGetContextDevices ctx = do
+  size <- getContextInfoSize ctx infoid
+  let n = (fromIntegral size) `div` elemSize 
+    
+  allocaArray n $ \(buff :: Ptr CLDeviceID) -> do
+    whenSuccess (raw_clGetContextInfo ctx infoid size (castPtr buff) nullPtr)
+      $ peekArray n buff
+    where
+      infoid = getCLValue CL_CONTEXT_DEVICES
+      elemSize = sizeOf (nullPtr :: CLDeviceID)
+
+clGetContextProperties :: CLContext -> IO [CLContextProperty]
+clGetContextProperties ctx = do
+  size <- getContextInfoSize ctx infoid
+  let n = (fromIntegral size) `div` elemSize 
+    
+  if n == 0 
+    then return []
+    else allocaArray n $ \(buff :: Ptr CLContextProperty_) ->
+      whenSuccess (raw_clGetContextInfo ctx infoid size (castPtr buff) nullPtr)
+        $ fmap unpackContextProperties $ peekArray n buff
+    where
+      infoid = getCLValue CL_CONTEXT_PROPERTIES
+      elemSize = sizeOf (nullPtr :: CLDeviceID)
+  
+-- -----------------------------------------------------------------------------
diff --git a/src/Control/Parallel/OpenCL/Event.chs b/src/Control/Parallel/OpenCL/Event.chs
new file mode 100644
--- /dev/null
+++ b/src/Control/Parallel/OpenCL/Event.chs
@@ -0,0 +1,191 @@
+{- Copyright (c) 2011 Luis Cabellos,
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of  nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-}
+{-# LANGUAGE ForeignFunctionInterface, ScopedTypeVariables, CPP #-}
+module Control.Parallel.OpenCL.Event(  
+  -- * Types
+  CLEvent, CLCommandType(..), CLProfilingInfo(..), CLCommandExecutionStatus(..),
+  -- * Functions
+  clWaitForEvents, clRetainEvent, clReleaseEvent, clGetEventCommandQueue, 
+  clGetEventCommandType, clGetEventReferenceCount, 
+  clGetEventCommandExecutionStatus, clGetEventProfilingInfo
+  ) where
+
+-- -----------------------------------------------------------------------------
+import Foreign
+import Foreign.C.Types
+import Control.Parallel.OpenCL.Types( 
+  CLEvent, CLint, CLuint, CLulong, CLEventInfo_, CLProfilingInfo_,
+  CLCommandQueue, CLCommandType(..), CLCommandType_, 
+  CLCommandExecutionStatus(..), CLProfilingInfo(..), getCommandExecutionStatus, 
+  getCLValue, getEnumCL, wrapCheckSuccess, wrapGetInfo )
+
+#ifdef __APPLE__
+#include <OpenCL/opencl.h>
+#else
+#include <CL/cl.h>
+#endif
+
+-- -----------------------------------------------------------------------------
+foreign import CALLCONV "clWaitForEvents" raw_clWaitForEvents :: 
+  CLuint -> Ptr CLEvent -> IO CLint
+foreign import CALLCONV "clGetEventInfo" raw_clGetEventInfo :: 
+  CLEvent -> CLEventInfo_ -> CSize -> Ptr () -> Ptr CSize -> IO CLint
+foreign import CALLCONV "clRetainEvent" raw_clRetainEvent :: 
+  CLEvent -> IO CLint 
+foreign import CALLCONV "clReleaseEvent" raw_clReleaseEvent :: 
+  CLEvent -> IO CLint 
+foreign import CALLCONV "clGetEventProfilingInfo" raw_clGetEventProfilingInfo :: 
+  CLEvent -> CLProfilingInfo_ -> CSize -> Ptr () -> Ptr CSize -> IO CLint
+
+-- -----------------------------------------------------------------------------
+-- | Waits on the host thread for commands identified by event objects in 
+-- event_list to complete. A command is considered complete if its execution 
+-- status is 'CL_COMPLETE' or a negative value.
+-- Returns 'True' if the function was executed successfully. It returns 'False'
+-- if the list of events is empty, or if events specified in event_list do not 
+-- belong to the same context, or if event objects specified in event_list are 
+-- not valid event objects.
+clWaitForEvents :: [CLEvent] -> IO Bool
+clWaitForEvents [] = return False
+clWaitForEvents xs = allocaArray nevents $ \pevents -> do
+  pokeArray pevents xs
+  wrapCheckSuccess $ raw_clWaitForEvents (fromIntegral nevents) pevents
+    where
+      nevents = length xs
+  
+-- | Increments the event reference count.
+-- The OpenCL commands that return an event perform an implicit retain.
+-- Returns 'True' if the function is executed successfully. It returns 'False' 
+-- if event is not a valid event object.
+clRetainEvent :: CLEvent -> IO Bool
+clRetainEvent ev = wrapCheckSuccess $ raw_clRetainEvent ev
+
+-- | Decrements the event reference count.
+-- Decrements the event reference count. The event object is deleted once the 
+-- reference count becomes zero, the specific command identified by this event 
+-- has completed (or terminated) and there are no commands in the command-queues 
+-- of a context that require a wait for this event to complete.
+-- Returns 'True' if the function is executed successfully. It returns 'False' 
+-- if event is not a valid event object.
+clReleaseEvent :: CLEvent -> IO Bool
+clReleaseEvent ev = wrapCheckSuccess $ raw_clReleaseEvent ev
+
+#c
+enum CLEventInfo {
+  cL_EVENT_COMMAND_QUEUE=CL_EVENT_COMMAND_QUEUE,
+  cL_EVENT_COMMAND_TYPE=CL_EVENT_COMMAND_TYPE,
+  cL_EVENT_COMMAND_EXECUTION_STATUS=CL_EVENT_COMMAND_EXECUTION_STATUS,
+  cL_EVENT_REFERENCE_COUNT=CL_EVENT_REFERENCE_COUNT
+  };
+#endc
+{#enum CLEventInfo {upcaseFirstLetter} #}
+
+
+-- | Return the command-queue associated with event.
+--
+-- This function execute OpenCL clGetEventInfo with 'CL_EVENT_COMMAND_QUEUE'.
+clGetEventCommandQueue :: CLEvent -> IO CLCommandQueue
+clGetEventCommandQueue ev =
+    wrapGetInfo (\(dat :: Ptr CLCommandQueue) ->
+        raw_clGetEventInfo ev infoid size (castPtr dat)) id
+    where 
+      infoid = getCLValue CL_EVENT_COMMAND_QUEUE
+      size = fromIntegral $ sizeOf (nullPtr::CLCommandQueue)
+      
+-- | Return the command associated with event.
+--
+-- This function execute OpenCL clGetEventInfo with 'CL_EVENT_COMMAND_TYPE'.
+clGetEventCommandType :: CLEvent -> IO CLCommandType
+clGetEventCommandType ev =
+    wrapGetInfo (\(dat :: Ptr CLCommandType_) ->
+        raw_clGetEventInfo ev infoid size (castPtr dat)) getEnumCL
+    where 
+      infoid = getCLValue CL_EVENT_COMMAND_TYPE
+      size = fromIntegral $ sizeOf (0::CLCommandType_)
+      
+-- | Return the event reference count. The reference count returned should be 
+-- considered immediately stale. It is unsuitable for general use in applications. 
+-- This feature is provided for identifying memory leaks.
+--
+-- This function execute OpenCL clGetEventInfo with 'CL_EVENT_REFERENCE_COUNT'.
+clGetEventReferenceCount :: CLEvent -> IO CLint
+clGetEventReferenceCount ev =
+    wrapGetInfo (\(dat :: Ptr CLint) ->
+        raw_clGetEventInfo ev infoid size (castPtr dat)) id
+    where 
+      infoid = getCLValue CL_EVENT_REFERENCE_COUNT
+      size = fromIntegral $ sizeOf (0::CLint)
+
+-- | Return the execution status of the command identified by event.
+--
+-- This function execute OpenCL clGetEventInfo with
+-- 'CL_EVENT_COMMAND_EXECUTION_STATUS'.
+clGetEventCommandExecutionStatus :: CLEvent -> IO CLCommandExecutionStatus
+clGetEventCommandExecutionStatus ev =
+    wrapGetInfo (\(dat :: Ptr CLint) ->
+        raw_clGetEventInfo ev infoid size (castPtr dat)) getCommandExecutionStatus
+    where 
+      infoid = getCLValue CL_EVENT_COMMAND_EXECUTION_STATUS
+      size = fromIntegral $ sizeOf (0::CLint)
+      
+{-| Returns profiling information for the command associated with event if 
+profiling is enabled. The unsigned 64-bit values returned can be used to measure 
+the time in nano-seconds consumed by OpenCL commands.
+
+OpenCL devices are required to correctly track time across changes in device 
+frequency and power states. The 'CL_DEVICE_PROFILING_TIMER_RESOLUTION' specifies 
+the resolution of the timer i.e. the number of nanoseconds elapsed before the 
+timer is incremented.
+
+Event objects can be used to capture profiling information that measure 
+execution time of a command. Profiling of OpenCL commands can be enabled either 
+by using a command-queue created with 'CL_QUEUE_PROFILING_ENABLE' flag set in 
+properties argument to clCreateCommandQueue or by setting the 
+'CL_QUEUE_PROFILING_ENABLE' flag in properties argument to 
+'clSetCommandQueueProperty'.
+
+'clGetEventProfilingInfo' returns the valueif the function is executed 
+successfully and the profiling information has been recorded, and returns 
+'Nothing'  if the 'CL_QUEUE_PROFILING_ENABLE' flag is not set for the 
+command-queue and if the profiling information is currently not available 
+(because the command identified by event has not completed), or if event is a 
+not a valid event object.
+-} 
+clGetEventProfilingInfo :: CLEvent -> CLProfilingInfo -> IO CLulong
+clGetEventProfilingInfo ev prof =
+    wrapGetInfo (\(dat :: Ptr CLulong) ->
+        raw_clGetEventProfilingInfo ev infoid size (castPtr dat)) id
+    where 
+      infoid = getCLValue prof
+      size = fromIntegral $ sizeOf (0::CLulong)
+
+-- -----------------------------------------------------------------------------
diff --git a/src/Control/Parallel/OpenCL/Memory.chs b/src/Control/Parallel/OpenCL/Memory.chs
new file mode 100644
--- /dev/null
+++ b/src/Control/Parallel/OpenCL/Memory.chs
@@ -0,0 +1,776 @@
+{- Copyright (c) 2011 Luis Cabellos,
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of  nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-}
+{-# LANGUAGE ForeignFunctionInterface, ScopedTypeVariables, CPP #-}
+module Control.Parallel.OpenCL.Memory(
+  -- * Types
+  CLMem, CLSampler, CLMemFlag(..), CLMemObjectType(..), CLAddressingMode(..), 
+  CLFilterMode(..), CLImageFormat(..),
+  -- * Memory Functions
+  clCreateBuffer, clRetainMemObject, clReleaseMemObject, clGetMemType, 
+  clGetMemFlags, clGetMemSize, clGetMemHostPtr, clGetMemMapCount, 
+  clGetMemReferenceCount, clGetMemContext,
+  -- * Image Functions
+  clCreateImage2D, clCreateImage3D, clGetSupportedImageFormats,
+  clGetImageFormat, clGetImageElementSize, clGetImageRowPitch,
+  clGetImageSlicePitch, clGetImageWidth, clGetImageHeight, clGetImageDepth,
+  -- * Sampler Functions
+  clCreateSampler, clRetainSampler, clReleaseSampler, clGetSamplerReferenceCount, 
+  clGetSamplerContext, clGetSamplerAddressingMode, clGetSamplerFilterMode, 
+  clGetSamplerNormalizedCoords
+  ) where
+
+-- -----------------------------------------------------------------------------
+import Foreign
+import Foreign.C.Types
+import Control.Applicative( (<$>), (<*>) )
+import Control.Parallel.OpenCL.Types( 
+  CLMem, CLContext, CLSampler, CLint, CLuint, CLbool, CLMemFlags_,
+  CLMemInfo_, CLAddressingMode_, CLFilterMode_, CLSamplerInfo_, CLImageInfo_,
+  CLAddressingMode(..), CLFilterMode(..), CLMemFlag(..), CLMemObjectType_, 
+  CLMemObjectType(..), 
+  wrapPError, wrapCheckSuccess, wrapGetInfo, whenSuccess, getEnumCL, 
+  bitmaskFromFlags, bitmaskToMemFlags, getCLValue )
+
+#ifdef __APPLE__
+#include <OpenCL/opencl.h>
+#else
+#include <CL/cl.h>
+#endif
+
+-- -----------------------------------------------------------------------------
+foreign import CALLCONV "clCreateBuffer" raw_clCreateBuffer :: 
+  CLContext -> CLMemFlags_ -> CSize -> Ptr () -> Ptr CLint -> IO CLMem
+foreign import CALLCONV "clCreateImage2D" raw_clCreateImage2D :: 
+  CLContext -> CLMemFlags_ -> CLImageFormat_p -> CSize -> CSize -> CSize 
+  -> Ptr () -> Ptr CLint -> IO CLMem
+foreign import CALLCONV "clCreateImage3D" raw_clCreateImage3D :: 
+  CLContext -> CLMemFlags_-> CLImageFormat_p -> CSize -> CSize -> CSize -> CSize 
+  -> CSize -> Ptr () -> Ptr CLint -> IO CLMem
+foreign import CALLCONV "clRetainMemObject" raw_clRetainMemObject :: 
+  CLMem -> IO CLint
+foreign import CALLCONV "clReleaseMemObject" raw_clReleaseMemObject :: 
+  CLMem -> IO CLint
+foreign import CALLCONV "clGetSupportedImageFormats" raw_clGetSupportedImageFormats :: 
+  CLContext -> CLMemFlags_ -> CLMemObjectType_ -> CLuint -> CLImageFormat_p 
+  -> Ptr CLuint -> IO CLint
+foreign import CALLCONV "clGetMemObjectInfo" raw_clGetMemObjectInfo :: 
+  CLMem -> CLMemInfo_ -> CSize -> Ptr () -> Ptr CSize -> IO CLint
+foreign import CALLCONV "clGetImageInfo" raw_clGetImageInfo ::
+  CLMem -> CLImageInfo_ -> CSize -> Ptr () -> Ptr CSize -> IO CLint
+foreign import CALLCONV "clCreateSampler" raw_clCreateSampler :: 
+  CLContext -> CLbool -> CLAddressingMode_ -> CLFilterMode_ -> Ptr CLint -> IO CLSampler
+foreign import CALLCONV "clRetainSampler" raw_clRetainSampler :: 
+  CLSampler -> IO CLint
+foreign import CALLCONV "clReleaseSampler" raw_clReleaseSampler :: 
+  CLSampler -> IO CLint
+foreign import CALLCONV "clGetSamplerInfo" raw_clGetSamplerInfo :: 
+  CLSampler -> CLSamplerInfo_ -> CSize -> Ptr () -> Ptr CSize -> IO CLint
+
+-- -----------------------------------------------------------------------------
+{-| Creates a buffer object. Returns a valid non-zero buffer object if the
+buffer object is created successfully. Otherwise, it throws the 'CLError': 
+
+ * 'CL_INVALID_CONTEXT' if context is not a valid context.
+
+ * 'CL_INVALID_VALUE' if values specified in flags are not valid.
+
+ * 'CL_INVALID_BUFFER_SIZE' if size is 0 or is greater than
+'clDeviceMaxMemAllocSize' value for all devices in context.
+
+ * 'CL_INVALID_HOST_PTR' if host_ptr is NULL and 'CL_MEM_USE_HOST_PTR' or
+'CL_MEM_COPY_HOST_PTR' are set in flags or if host_ptr is not NULL but
+'CL_MEM_COPY_HOST_PTR' or 'CL_MEM_USE_HOST_PTR' are not set in flags.
+
+ * 'CL_MEM_OBJECT_ALLOCATION_FAILURE' if there is a failure to allocate memory
+for buffer object.
+
+ * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
+by the OpenCL implementation on the host.
+-}
+clCreateBuffer :: Integral a => CLContext -> [CLMemFlag] -> (a, Ptr ()) -> IO CLMem
+clCreateBuffer ctx xs (sbuff,buff) = wrapPError $ \perr -> do
+  raw_clCreateBuffer ctx flags (fromIntegral sbuff) buff perr
+    where
+      flags = bitmaskFromFlags xs
+    
+-- | Increments the memory object reference count. returns 'True' if the
+-- function is executed successfully. After the memobj reference count becomes
+-- zero and commands queued for execution on a command-queue(s) that use memobj
+-- have finished, the memory object is deleted. It returns 'False' if memobj is
+-- not a valid memory object.
+clRetainMemObject :: CLMem -> IO Bool
+clRetainMemObject mem = wrapCheckSuccess $ raw_clRetainMemObject mem
+
+-- | Decrements the memory object reference count. After the memobj reference
+-- count becomes zero and commands queued for execution on a command-queue(s)
+-- that use memobj have finished, the memory object is deleted. Returns 'True'
+-- if the function is executed successfully. It returns 'False' if memobj is not
+-- a valid memory object.
+clReleaseMemObject :: CLMem -> IO Bool
+clReleaseMemObject mem = wrapCheckSuccess $ raw_clReleaseMemObject mem
+
+-- -----------------------------------------------------------------------------
+#c
+enum CLChannelOrder {
+  cL_R=CL_R,
+  cL_A=CL_A,
+  cL_INTENSITY=CL_INTENSITY,
+  cL_LUMINANCE=CL_LUMINANCE,
+  cL_RG=CL_RG,
+  cL_RA=CL_RA,
+  cL_RGB=CL_RGB,
+  cL_RGBA=CL_RGBA,
+  cL_ARGB=CL_ARGB,
+  cL_BGRA=CL_BGRA,
+  };
+#endc
+{-| Specifies the number of channels and the channel layout i.e. the memory
+layout in which channels are stored in the image. Valid values are described in
+the table below.
+ 
+ * 'CL_R', 'CL_A'.
+
+ * 'CL_INTENSITY', This format can only be used if channel data type =
+'CL_UNORM_INT8', 'CL_UNORM_INT16', 'CL_SNORM_INT8', 'CL_SNORM_INT16',
+'CL_HALF_FLOAT', or 'CL_FLOAT'.
+
+ * 'CL_LUMINANCE', This format can only be used if channel data type =
+'CL_UNORM_INT8', 'CL_UNORM_INT16', 'CL_SNORM_INT8', 'CL_SNORM_INT16',
+'CL_HALF_FLOAT', or 'CL_FLOAT'.
+
+ * 'CL_RG', 'CL_RA'.
+
+ * 'CL_RGB', This format can only be used if channel data type =
+'CL_UNORM_SHORT_565', 'CL_UNORM_SHORT_555' or 'CL_UNORM_INT101010'.
+
+ * 'CL_RGBA'.
+
+ * 'CL_ARGB', 'CL_BGRA'. This format can only be used if channel data type =
+'CL_UNORM_INT8', 'CL_SNORM_INT8', 'CL_SIGNED_INT8' or 'CL_UNSIGNED_INT8'.  
+-}
+{#enum CLChannelOrder {upcaseFirstLetter} deriving(Show)#}
+
+#c
+enum CLChannelType {
+  cL_SNORM_INT8=CL_SNORM_INT8,
+  cL_SNORM_INT16=CL_SNORM_INT16,
+  cL_UNORM_INT8=CL_UNORM_INT8,
+  cL_UNORM_INT16=CL_UNORM_INT16,
+  cL_UNORM_SHORT_565=CL_UNORM_SHORT_565,
+  cL_UNORM_SHORT_555=CL_UNORM_SHORT_555,
+  cL_UNORM_INT_101010=CL_UNORM_INT_101010,
+  cL_SIGNED_INT8=CL_SIGNED_INT8,
+  cL_SIGNED_INT16=CL_SIGNED_INT16,
+  cL_SIGNED_INT32=CL_SIGNED_INT32,
+  cL_UNSIGNED_INT8=CL_UNSIGNED_INT8,
+  cL_UNSIGNED_INT16=CL_UNSIGNED_INT16,
+  cL_UNSIGNED_INT32=CL_UNSIGNED_INT32,
+  cL_HALF_FLOAT=CL_HALF_FLOAT,
+  cL_FLOAT=CL_FLOAT,
+  };
+#endc
+{-| Describes the size of the channel data type. The number of bits per element
+determined by the image_channel_data_type and image_channel_order must be a
+power of two. The list of supported values is described in the table below.
+
+ * 'CL_SNORM_INT8', Each channel component is a normalized signed 8-bit integer
+value.
+
+ * 'CL_SNORM_INT16', Each channel component is a normalized signed 16-bit
+integer value.
+
+ * 'CL_UNORM_INT8', Each channel component is a normalized unsigned 8-bit
+integer value.
+
+ * 'CL_UNORM_INT16', Each channel component is a normalized unsigned 16-bit
+integer value.
+
+ * 'CL_UNORM_SHORT_565', Represents a normalized 5-6-5 3-channel RGB image. The
+channel order must be 'CL_RGB'.
+
+ * 'CL_UNORM_SHORT_555', Represents a normalized x-5-5-5 4-channel xRGB
+image. The channel order must be 'CL_RGB'.
+
+ * 'CL_UNORM_INT_101010', Represents a normalized x-10-10-10 4-channel xRGB
+image. The channel order must be 'CL_RGB'.
+
+ * 'CL_SIGNED_INT8', Each channel component is an unnormalized signed 8-bit
+integer value.
+
+ * 'CL_SIGNED_INT16', Each channel component is an unnormalized signed 16-bit
+integer value.
+
+ * 'CL_SIGNED_INT32', Each channel component is an unnormalized signed 32-bit
+integer value.
+
+ * 'CL_UNSIGNED_INT8', Each channel component is an unnormalized unsigned 8-bit
+integer value.
+
+ * 'CL_UNSIGNED_INT16', Each channel component is an unnormalized unsigned
+16-bit integer value.
+
+ * 'CL_UNSIGNED_INT32', Each channel component is an unnormalized unsigned
+32-bit integer value.
+
+ * 'CL_HALF_FLOAT', Each channel component is a 16-bit half-float value.
+
+ * 'CL_FLOAT', Each channel component is a single precision floating-point
+value.
+-}
+{#enum CLChannelType {upcaseFirstLetter} deriving(Show)#}
+
+data CLImageFormat = CLImageFormat
+                     { image_channel_order :: ! CLChannelOrder
+                     , image_channel_data_type :: ! CLChannelType }
+                     deriving( Show )
+{#pointer *cl_image_format as CLImageFormat_p -> CLImageFormat#}
+instance Storable CLImageFormat where
+  alignment _ = alignment (undefined :: CDouble)
+  sizeOf _ = {#sizeof cl_image_format #}
+  peek p =
+    CLImageFormat <$> fmap getEnumCL ({#get cl_image_format.image_channel_order #} p)
+           <*> fmap getEnumCL ({#get cl_image_format.image_channel_data_type #} p)
+  poke p (CLImageFormat a b) = do
+    {#set cl_image_format.image_channel_order #} p (getCLValue a)
+    {#set cl_image_format.image_channel_data_type #} p (getCLValue b)
+
+-- -----------------------------------------------------------------------------
+{-| Creates a 2D image object.
+
+'clCreateImage2D' returns a valid non-zero image object created if the image
+object is created successfully. Otherwise, it throws one of the following
+'CLError' exceptions:
+
+ * 'CL_INVALID_CONTEXT' if context is not a valid context.
+
+ * 'CL_INVALID_VALUE' if values specified in flags are not valid.
+
+ * 'CL_INVALID_IMAGE_FORMAT_DESCRIPTOR' if values specified in image_format are
+not valid.
+
+ * 'CL_INVALID_IMAGE_SIZE' if image_width or image_height are 0 or if they
+exceed values specified in 'CL_DEVICE_IMAGE2D_MAX_WIDTH' or
+'CL_DEVICE_IMAGE2D_MAX_HEIGHT' respectively for all devices in context or if
+values specified by image_row_pitch do not follow rules described in the
+argument description above.
+
+ * 'CL_INVALID_HOST_PTR' if host_ptr is 'nullPtr' and 'CL_MEM_USE_HOST_PTR' or
+'CL_MEM_COPY_HOST_PTR' are set in flags or if host_ptr is not 'nullPtr' but
+'CL_MEM_COPY_HOST_PTR' or 'CL_MEM_USE_HOST_PTR' are not set in flags.
+
+ * 'CL_IMAGE_FORMAT_NOT_SUPPORTED' if the image_format is not supported.
+
+ * 'CL_MEM_OBJECT_ALLOCATION_FAILURE' if there is a failure to allocate memory
+for image object.
+
+ * 'CL_INVALID_OPERATION' if there are no devices in context that support images
+(i.e. 'CL_DEVICE_IMAGE_SUPPORT' (specified in the table of OpenCL Device Queries
+for 'clGetDeviceInfo') is 'False').
+
+ * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
+by the OpenCL implementation on the host.
+
+-}
+
+clCreateImage2D :: Integral a => CLContext -- ^ A valid OpenCL context on which
+                                           -- the image object is to be created.
+                   -> [CLMemFlag] -- ^ A list of flags that is used to specify
+                                  -- allocation and usage information about the
+                                  -- image memory object being created.
+                   -> CLImageFormat -- ^ Structure that describes format
+                                    -- properties of the image to be allocated.
+                   -> a -- ^ The width of the image in pixels. It must be values
+                        -- greater than or equal to 1.
+                   -> a -- ^ The height of the image in pixels. It must be
+                        -- values greater than or equal to 1.
+                   -> a -- ^ The scan-line pitch in bytes. This must be 0 if
+                        -- host_ptr is 'nullPtr' and can be either 0 or greater
+                        -- than or equal to image_width * size of element in
+                        -- bytes if host_ptr is not 'nullPtr'. If host_ptr is
+                        -- not 'nullPtr' and image_row_pitch is equal to 0,
+                        -- image_row_pitch is calculated as image_width * size
+                        -- of element in bytes. If image_row_pitch is not 0, it
+                        -- must be a multiple of the image element size in
+                        -- bytes.
+                   -> Ptr () -- ^ A pointer to the image data that may already
+                             -- be allocated by the application. The size of the
+                             -- buffer that host_ptr points to must be greater
+                             -- than or equal to image_row_pitch *
+                             -- image_height. The size of each element in bytes
+                             -- must be a power of 2. The image data specified
+                             -- by host_ptr is stored as a linear sequence of
+                             -- adjacent scanlines. Each scanline is stored as a
+                             -- linear sequence of image elements.
+                   -> IO CLMem
+clCreateImage2D ctx xs fmt iw ih irp ptr = wrapPError $ \perr -> with fmt $ \pfmt -> do
+  raw_clCreateImage2D ctx flags pfmt ciw cih cirp ptr perr
+    where
+      flags = bitmaskFromFlags xs
+      ciw = fromIntegral iw
+      cih = fromIntegral ih
+      cirp = fromIntegral irp
+
+{-| Creates a 3D image object.
+
+'clCreateImage3D' returns a valid non-zero image object created if the image
+object is created successfully. Otherwise, it throws one of the following
+'CLError' exceptions:
+
+ * 'CL_INVALID_CONTEXT' if context is not a valid context.
+
+ * 'CL_INVALID_VALUE' if values specified in flags are not valid.
+
+ * 'CL_INVALID_IMAGE_FORMAT_DESCRIPTOR' if values specified in image_format are
+not valid.
+
+ * 'CL_INVALID_IMAGE_SIZE' if image_width, image_height are 0 or if image_depth
+less than or equal to 1 or if they exceed values specified in
+'CL_DEVICE_IMAGE3D_MAX_WIDTH', CL_DEVICE_IMAGE3D_MAX_HEIGHT' or
+'CL_DEVICE_IMAGE3D_MAX_DEPTH' respectively for all devices in context or if
+values specified by image_row_pitch and image_slice_pitch do not follow rules
+described in the argument description above.
+
+ * 'CL_INVALID_HOST_PTR' if host_ptr is 'nullPtr' and 'CL_MEM_USE_HOST_PTR' or
+'CL_MEM_COPY_HOST_PTR' are set in flags or if host_ptr is not 'nullPtr' but
+'CL_MEM_COPY_HOST_PTR' or 'CL_MEM_USE_HOST_PTR' are not set in flags.
+
+ * 'CL_IMAGE_FORMAT_NOT_SUPPORTED' if the image_format is not supported.
+
+ * 'CL_MEM_OBJECT_ALLOCATION_FAILURE' if there is a failure to allocate memory
+for image object.
+
+ * 'CL_INVALID_OPERATION' if there are no devices in context that support images
+(i.e. 'CL_DEVICE_IMAGE_SUPPORT' (specified in the table of OpenCL Device Queries
+for clGetDeviceInfo) is 'False').
+
+ * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
+by the OpenCL implementation on the host.
+
+-}
+clCreateImage3D :: Integral a => CLContext -- ^ A valid OpenCL context on which
+                                           -- the image object is to be created.
+                   -> [CLMemFlag] -- ^ A list of flags that is used to specify
+                                  -- allocation and usage information about the
+                                  -- image memory object being created.
+                   -> CLImageFormat -- ^ Structure that describes format
+                                    -- properties of the image to be allocated.
+                   -> a -- ^ The width of the image in pixels. It must be values
+                        -- greater than or equal to 1.
+                   -> a -- ^ The height of the image in pixels. It must be
+                        -- values greater than or equal to 1.
+                   -> a -- ^ The depth of the image in pixels. This must be a
+                        -- value greater than 1.
+                   -> a -- ^ The scan-line pitch in bytes. This must be 0 if
+                        -- host_ptr is 'nullPtr' and can be either 0 or greater
+                        -- than or equal to image_width * size of element in
+                        -- bytes if host_ptr is not 'nullPtr'. If host_ptr is
+                        -- not 'nullPtr' and image_row_pitch is equal to 0,
+                        -- image_row_pitch is calculated as image_width * size
+                        -- of element in bytes. If image_row_pitch is not 0, it
+                        -- must be a multiple of the image element size in
+                        -- bytes.
+                   -> a -- ^ The size in bytes of each 2D slice in the 3D
+                        -- image. This must be 0 if host_ptr is 'nullPtr' and
+                        -- can be either 0 or greater than or equal to
+                        -- image_row_pitch * image_height if host_ptr is not
+                        -- 'nullPtr'. If host_ptr is not 'nullPtr' and
+                        -- image_slice_pitch equal to 0, image_slice_pitch is
+                        -- calculated as image_row_pitch * image_height. If
+                        -- image_slice_pitch is not 0, it must be a multiple of
+                        -- the image_row_pitch.
+                   -> Ptr () -- ^ A pointer to the image data that may already
+                             -- be allocated by the application. The size of the
+                             -- buffer that host_ptr points to must be greater
+                             -- than or equal to image_slice_pitch *
+                             -- image_depth. The size of each element in bytes
+                             -- must be a power of 2. The image data specified
+                             -- by host_ptr is stored as a linear sequence of
+                             -- adjacent 2D slices. Each 2D slice is a linear
+                             -- sequence of adjacent scanlines. Each scanline is
+                             -- a linear sequence of image elements.
+                   -> IO CLMem
+clCreateImage3D ctx xs fmt iw ih idepth irp isp ptr = wrapPError $ \perr -> with fmt $ \pfmt -> do
+  raw_clCreateImage3D ctx flags pfmt ciw cih cid cirp cisp ptr perr
+    where
+      flags = bitmaskFromFlags xs
+      ciw = fromIntegral iw
+      cih = fromIntegral ih
+      cid = fromIntegral idepth
+      cirp = fromIntegral irp
+      cisp = fromIntegral isp  
+      
+getNumSupportedImageFormats :: CLContext -> [CLMemFlag] -> CLMemObjectType -> IO CLuint
+getNumSupportedImageFormats ctx xs mtype = alloca $ \(value_size :: Ptr CLuint) -> do
+  whenSuccess (raw_clGetSupportedImageFormats ctx flags (getCLValue mtype) 0 nullPtr value_size)
+    $ peek value_size
+    where
+      flags = bitmaskFromFlags xs
+  
+{-| Get the list of image formats supported by an OpenCL
+implementation. 'clGetSupportedImageFormats' can be used to get the list of
+image formats supported by an OpenCL implementation when the following
+information about an image memory object is specified:
+
+ * Context
+ * Image type - 2D or 3D image
+ * Image object allocation information
+
+Throws 'CL_INVALID_CONTEXT' if context is not a valid context, throws
+'CL_INVALID_VALUE' if flags or image_type are not valid.
+
+-}
+clGetSupportedImageFormats :: CLContext -- ^ A valid OpenCL context on which the
+                                        -- image object(s) will be created.
+                              -> [CLMemFlag] -- ^ A bit-field that is used to
+                                             -- specify allocation and usage
+                                             -- information about the image
+                                             -- memory object.
+                              -> CLMemObjectType -- ^ Describes the image type
+                                                 -- and must be either
+                                                 -- 'CL_MEM_OBJECT_IMAGE2D' or
+                                                 -- 'CL_MEM_OBJECT_IMAGE3D'.
+                              -> IO [CLImageFormat]
+clGetSupportedImageFormats ctx xs mtype = do
+  num <- getNumSupportedImageFormats ctx xs mtype
+  allocaArray (fromIntegral num) $ \(buff :: Ptr CLImageFormat) -> do
+    whenSuccess (raw_clGetSupportedImageFormats ctx flags (getCLValue mtype) num (castPtr buff) nullPtr)
+      $ peekArray (fromIntegral num) buff
+    where
+      flags = bitmaskFromFlags xs
+
+-- -----------------------------------------------------------------------------
+#c
+enum CLImageInfo {
+  cL_IMAGE_FORMAT=CL_IMAGE_FORMAT,
+  cL_IMAGE_ELEMENT_SIZE=CL_IMAGE_ELEMENT_SIZE,
+  cL_IMAGE_ROW_PITCH=CL_IMAGE_ROW_PITCH,
+  cL_IMAGE_SLICE_PITCH=CL_IMAGE_SLICE_PITCH,
+  cL_IMAGE_WIDTH=CL_IMAGE_WIDTH,
+  cL_IMAGE_HEIGHT=CL_IMAGE_HEIGHT,
+  cL_IMAGE_DEPTH=CL_IMAGE_DEPTH,
+  };
+#endc
+{#enum CLImageInfo {upcaseFirstLetter} #}
+
+-- | Return image format descriptor specified when image is created with
+-- clCreateImage2D or clCreateImage3D.
+--
+-- This function execute OpenCL clGetImageInfo with 'CL_IMAGE_FORMAT'.
+clGetImageFormat :: CLMem -> IO CLImageFormat
+clGetImageFormat mem =
+  wrapGetInfo (\(dat :: Ptr CLImageFormat) ->
+                raw_clGetImageInfo mem infoid size (castPtr dat)) id
+    where 
+      infoid = getCLValue CL_IMAGE_FORMAT
+      size = fromIntegral $ sizeOf (undefined :: CLImageFormat)
+  
+-- | Return size of each element of the image memory object given by image. An
+-- element is made up of n channels. The value of n is given in 'CLImageFormat'
+-- descriptor.
+--
+-- This function execute OpenCL clGetImageInfo with 'CL_IMAGE_ELEMENT_SIZE'.
+clGetImageElementSize :: CLMem -> IO CSize      
+clGetImageElementSize mem =
+  wrapGetInfo (\(dat :: Ptr CSize) ->
+                raw_clGetImageInfo mem infoid size (castPtr dat)) id
+    where 
+      infoid = getCLValue CL_IMAGE_ELEMENT_SIZE
+      size = fromIntegral $ sizeOf (undefined :: CSize)
+      
+-- | Return size in bytes of a row of elements of the image object given by
+-- image.
+--
+-- This function execute OpenCL clGetImageInfo with 'CL_IMAGE_ROW_PITCH'.
+clGetImageRowPitch :: CLMem -> IO CSize      
+clGetImageRowPitch mem = 
+  wrapGetInfo (\(dat :: Ptr CSize) ->
+                raw_clGetImageInfo mem infoid size (castPtr dat)) id
+    where 
+      infoid = getCLValue CL_IMAGE_ROW_PITCH
+      size = fromIntegral $ sizeOf (undefined :: CSize)
+      
+-- | Return size in bytes of a 2D slice for the 3D image object given by
+-- image. For a 2D image object this value will be 0.
+--
+-- This function execute OpenCL clGetImageInfo with 'CL_IMAGE_SLICE_PITCH'.
+clGetImageSlicePitch :: CLMem -> IO CSize      
+clGetImageSlicePitch mem = 
+  wrapGetInfo (\(dat :: Ptr CSize) ->
+                raw_clGetImageInfo mem infoid size (castPtr dat)) id
+    where 
+      infoid = getCLValue CL_IMAGE_SLICE_PITCH
+      size = fromIntegral $ sizeOf (undefined :: CSize)      
+      
+-- | Return width of image in pixels.
+--
+-- This function execute OpenCL clGetImageInfo with 'CL_IMAGE_WIDTH'.
+clGetImageWidth :: CLMem -> IO CSize      
+clGetImageWidth mem = 
+  wrapGetInfo (\(dat :: Ptr CSize) ->
+                raw_clGetImageInfo mem infoid size (castPtr dat)) id
+    where 
+      infoid = getCLValue CL_IMAGE_WIDTH
+      size = fromIntegral $ sizeOf (undefined :: CSize)
+      
+-- | Return height of image in pixels.
+--
+-- This function execute OpenCL clGetImageInfo with 'CL_IMAGE_HEIGHT'.
+clGetImageHeight :: CLMem -> IO CSize      
+clGetImageHeight mem = 
+  wrapGetInfo (\(dat :: Ptr CSize) ->
+                raw_clGetImageInfo mem infoid size (castPtr dat)) id
+    where 
+      infoid = getCLValue CL_IMAGE_HEIGHT
+      size = fromIntegral $ sizeOf (undefined :: CSize)
+
+-- | Return depth of the image in pixels. For a 2D image, depth equals 0.
+--
+-- This function execute OpenCL clGetImageInfo with 'CL_IMAGE_DEPTH'.
+clGetImageDepth :: CLMem -> IO CSize      
+clGetImageDepth mem = 
+  wrapGetInfo (\(dat :: Ptr CSize) ->
+                raw_clGetImageInfo mem infoid size (castPtr dat)) id
+    where 
+      infoid = getCLValue CL_IMAGE_DEPTH
+      size = fromIntegral $ sizeOf (undefined :: CSize)
+
+-- -----------------------------------------------------------------------------
+#c
+enum CLMemInfo {
+  cL_MEM_TYPE=CL_MEM_TYPE,
+  cL_MEM_FLAGS=CL_MEM_FLAGS,
+  cL_MEM_SIZE=CL_MEM_SIZE,
+  cL_MEM_HOST_PTR=CL_MEM_HOST_PTR,
+  cL_MEM_MAP_COUNT=CL_MEM_MAP_COUNT,
+  cL_MEM_REFERENCE_COUNT=CL_MEM_REFERENCE_COUNT,
+  cL_MEM_CONTEXT=CL_MEM_CONTEXT,
+  };
+#endc
+{#enum CLMemInfo {upcaseFirstLetter} #}
+
+-- | Returns the mem object type.
+--
+-- This function execute OpenCL clGetMemObjectInfo with 'CL_MEM_TYPE'.
+clGetMemType :: CLMem -> IO CLMemObjectType
+clGetMemType mem =
+    wrapGetInfo (\(dat :: Ptr CLMemObjectType_) ->
+        raw_clGetMemObjectInfo mem infoid size (castPtr dat)) getEnumCL
+    where 
+      infoid = getCLValue CL_MEM_TYPE
+      size = fromIntegral $ sizeOf (0::CLMemObjectType_)
+
+-- | Return the flags argument value specified when memobj was created.
+--
+-- This function execute OpenCL clGetMemObjectInfo with 'CL_MEM_FLAGS'.
+clGetMemFlags :: CLMem -> IO [CLMemFlag]
+clGetMemFlags mem =
+    wrapGetInfo (\(dat :: Ptr CLMemFlags_)->
+        raw_clGetMemObjectInfo mem infoid size (castPtr dat)) bitmaskToMemFlags
+    where 
+      infoid = getCLValue CL_MEM_FLAGS
+      size = fromIntegral $ sizeOf (0::CLMemFlags_)
+
+-- | Return actual size of memobj in bytes.
+--
+-- This function execute OpenCL clGetMemObjectInfo with 'CL_MEM_SIZE'.
+clGetMemSize :: CLMem -> IO CSize
+clGetMemSize mem =
+    wrapGetInfo (\(dat :: Ptr CSize)->
+        raw_clGetMemObjectInfo mem infoid size (castPtr dat)) id
+    where 
+      infoid = getCLValue CL_MEM_SIZE
+      size = fromIntegral $ sizeOf (0::CSize)
+
+-- | Return the host_ptr argument value specified when memobj is created.
+--
+-- This function execute OpenCL clGetMemObjectInfo with 'CL_MEM_HOST_PTR'.
+clGetMemHostPtr :: CLMem -> IO (Ptr ())
+clGetMemHostPtr mem =
+    wrapGetInfo (\(dat :: Ptr (Ptr ()))->
+        raw_clGetMemObjectInfo mem infoid size (castPtr dat)) id
+    where 
+      infoid = getCLValue CL_MEM_HOST_PTR
+      size = fromIntegral $ sizeOf (nullPtr::Ptr ())
+
+-- | Map count. The map count returned should be considered immediately
+-- stale. It is unsuitable for general use in applications. This feature is
+-- provided for debugging.
+--
+-- This function execute OpenCL clGetMemObjectInfo with 'CL_MEM_MAP_COUNT'.
+clGetMemMapCount :: CLMem -> IO CLuint
+clGetMemMapCount mem =
+    wrapGetInfo (\(dat :: Ptr CLuint)->
+        raw_clGetMemObjectInfo mem infoid size (castPtr dat)) id
+    where 
+      infoid = getCLValue CL_MEM_MAP_COUNT
+      size = fromIntegral $ sizeOf (0 :: CLuint)
+
+-- | Return memobj reference count. The reference count returned should be
+-- considered immediately stale. It is unsuitable for general use in
+-- applications. This feature is provided for identifying memory leaks.
+--
+-- This function execute OpenCL clGetMemObjectInfo with 'CL_MEM_REFERENCE_COUNT'.
+clGetMemReferenceCount :: CLMem -> IO CLuint
+clGetMemReferenceCount mem =
+    wrapGetInfo (\(dat :: Ptr CLuint)->
+        raw_clGetMemObjectInfo mem infoid size (castPtr dat)) id
+    where 
+      infoid = getCLValue CL_MEM_REFERENCE_COUNT
+      size = fromIntegral $ sizeOf (0 :: CLuint)
+
+-- | Return context specified when memory object is created.
+--
+-- This function execute OpenCL clGetMemObjectInfo with 'CL_MEM_CONTEXT'.
+clGetMemContext :: CLMem -> IO CLContext
+clGetMemContext mem =
+    wrapGetInfo (\(dat :: Ptr CLContext)->
+        raw_clGetMemObjectInfo mem infoid size (castPtr dat)) id
+    where 
+      infoid = getCLValue CL_MEM_CONTEXT
+      size = fromIntegral $ sizeOf (0 :: CLuint)
+
+-- -----------------------------------------------------------------------------
+{-| Creates a sampler object. A sampler object describes how to sample an image
+when the image is read in the kernel. The built-in functions to read from an
+image in a kernel take a sampler as an argument. The sampler arguments to the
+image read function can be sampler objects created using OpenCL functions and
+passed as argument values to the kernel or can be samplers declared inside a
+kernel. In this section we discuss how sampler objects are created using OpenCL
+functions.
+
+Returns a valid non-zero sampler object if the sampler object is created
+successfully. Otherwise, it throws one of the following 'CLError' exceptions:
+
+ * 'CL_INVALID_CONTEXT' if context is not a valid context.
+
+ * 'CL_INVALID_VALUE' if addressing_mode, filter_mode, or normalized_coords or a
+combination of these argument values are not valid.
+
+ * 'CL_INVALID_OPERATION' if images are not supported by any device associated
+with context (i.e. 'CL_DEVICE_IMAGE_SUPPORT' specified in the table of OpenCL
+Device Queries for clGetDeviceInfo is 'False').
+
+ * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
+by the OpenCL implementation on the host.
+-}
+clCreateSampler :: CLContext -> Bool -> CLAddressingMode -> CLFilterMode 
+                   -> IO CLSampler
+clCreateSampler ctx norm am fm = wrapPError $ \perr -> do
+  raw_clCreateSampler ctx (fromBool norm) (getCLValue am) (getCLValue fm) perr
+
+-- | Increments the sampler reference count. 'clCreateSampler' does an implicit
+-- retain. Returns 'True' if the function is executed successfully. It returns
+-- 'False' if sampler is not a valid sampler object.
+clRetainSampler :: CLSampler -> IO Bool
+clRetainSampler mem = wrapCheckSuccess $ raw_clRetainSampler mem
+
+-- | Decrements the sampler reference count. The sampler object is deleted after
+-- the reference count becomes zero and commands queued for execution on a
+-- command-queue(s) that use sampler have finished. 'clReleaseSampler' returns
+-- 'True' if the function is executed successfully. It returns 'False' if
+-- sampler is not a valid sampler object.
+clReleaseSampler :: CLSampler -> IO Bool
+clReleaseSampler mem = wrapCheckSuccess $ raw_clReleaseSampler mem
+
+#c
+enum CLSamplerInfo {
+  cL_SAMPLER_REFERENCE_COUNT=CL_SAMPLER_REFERENCE_COUNT,
+  cL_SAMPLER_CONTEXT=CL_SAMPLER_CONTEXT,
+  cL_SAMPLER_ADDRESSING_MODE=CL_SAMPLER_ADDRESSING_MODE,
+  cL_SAMPLER_FILTER_MODE=CL_SAMPLER_FILTER_MODE,
+  cL_SAMPLER_NORMALIZED_COORDS=CL_SAMPLER_NORMALIZED_COORDS
+  };
+#endc
+{#enum CLSamplerInfo {upcaseFirstLetter} #}
+
+-- | Return the sampler reference count. The reference count returned should be
+-- considered immediately stale. It is unsuitable for general use in
+-- applications. This feature is provided for identifying memory leaks.
+--
+-- This function execute OpenCL clGetSamplerInfo with
+-- 'CL_SAMPLER_REFERENCE_COUNT'.
+clGetSamplerReferenceCount :: CLSampler -> IO CLuint
+clGetSamplerReferenceCount sam =
+    wrapGetInfo (\(dat :: Ptr CLuint)->
+        raw_clGetSamplerInfo sam infoid size (castPtr dat)) id
+    where 
+      infoid = getCLValue CL_SAMPLER_REFERENCE_COUNT
+      size = fromIntegral $ sizeOf (0 :: CLuint)
+
+-- | Return the context specified when the sampler is created.
+--
+-- This function execute OpenCL clGetSamplerInfo with 'CL_SAMPLER_CONTEXT'.
+clGetSamplerContext :: CLSampler -> IO CLContext
+clGetSamplerContext sam =
+    wrapGetInfo (\(dat :: Ptr CLContext)->
+        raw_clGetSamplerInfo sam infoid size (castPtr dat)) id
+    where 
+      infoid = getCLValue CL_SAMPLER_CONTEXT
+      size = fromIntegral $ sizeOf (nullPtr :: CLContext)
+
+-- | Return the value specified by addressing_mode argument to clCreateSampler.
+--
+-- This function execute OpenCL clGetSamplerInfo with
+-- 'CL_SAMPLER_ADDRESSING_MODE'.
+clGetSamplerAddressingMode :: CLSampler -> IO CLAddressingMode
+clGetSamplerAddressingMode sam =
+    wrapGetInfo (\(dat :: Ptr CLAddressingMode_)->
+        raw_clGetSamplerInfo sam infoid size (castPtr dat)) getEnumCL
+    where 
+      infoid = getCLValue CL_SAMPLER_ADDRESSING_MODE
+      size = fromIntegral $ sizeOf (0 :: CLAddressingMode_)
+
+-- | Return the value specified by filter_mode argument to clCreateSampler.
+--
+-- This function execute OpenCL clGetSamplerInfo with 'CL_SAMPLER_FILTER_MODE'.
+clGetSamplerFilterMode :: CLSampler -> IO CLFilterMode
+clGetSamplerFilterMode sam =
+    wrapGetInfo (\(dat :: Ptr CLFilterMode_)->
+        raw_clGetSamplerInfo sam infoid size (castPtr dat)) getEnumCL
+    where 
+      infoid = getCLValue CL_SAMPLER_FILTER_MODE
+      size = fromIntegral $ sizeOf (0 :: CLFilterMode_)
+
+-- | Return the value specified by normalized_coords argument to
+-- clCreateSampler.
+--
+-- This function execute OpenCL clGetSamplerInfo with
+-- 'CL_SAMPLER_NORMALIZED_COORDS'.
+clGetSamplerNormalizedCoords :: CLSampler -> IO Bool
+clGetSamplerNormalizedCoords sam =
+    wrapGetInfo (\(dat :: Ptr CLbool)->
+        raw_clGetSamplerInfo sam infoid size (castPtr dat)) (/=0)
+    where 
+      infoid = getCLValue CL_SAMPLER_NORMALIZED_COORDS
+      size = fromIntegral $ sizeOf (0 :: CLbool)
+
+-- -----------------------------------------------------------------------------
diff --git a/src/Control/Parallel/OpenCL/Program.chs b/src/Control/Parallel/OpenCL/Program.chs
new file mode 100644
--- /dev/null
+++ b/src/Control/Parallel/OpenCL/Program.chs
@@ -0,0 +1,840 @@
+{- Copyright (c) 2011 Luis Cabellos,
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of  nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-}
+{-# LANGUAGE ForeignFunctionInterface, ScopedTypeVariables, CPP #-}
+module Control.Parallel.OpenCL.Program(  
+  -- * Types
+  CLProgram, CLBuildStatus(..), CLKernel,
+  -- * Program Functions
+  clCreateProgramWithSource, clCreateProgramWithBinary, clRetainProgram, 
+  clReleaseProgram, clUnloadCompiler, clBuildProgram, 
+  clGetProgramReferenceCount, clGetProgramContext, clGetProgramNumDevices, 
+  clGetProgramDevices, clGetProgramSource, clGetProgramBinarySizes, 
+  clGetProgramBinaries, clGetProgramBuildStatus, clGetProgramBuildOptions, 
+  clGetProgramBuildLog,
+  -- * Kernel Functions
+  clCreateKernel, clCreateKernelsInProgram, clRetainKernel, clReleaseKernel, 
+  clSetKernelArg, clSetKernelArgSto, clGetKernelFunctionName, clGetKernelNumArgs, 
+  clGetKernelReferenceCount, clGetKernelContext, clGetKernelProgram, 
+  clGetKernelWorkGroupSize, clGetKernelCompileWorkGroupSize, 
+  clGetKernelLocalMemSize
+  ) where
+
+-- -----------------------------------------------------------------------------
+import Control.Monad( zipWithM, forM )
+import Foreign
+import Foreign.C.Types
+import Foreign.C.String( CString, withCString, peekCString )
+import Control.Parallel.OpenCL.Types( 
+  CLint, CLuint, CLulong, CLProgram, CLContext, CLKernel, CLDeviceID, CLError,
+  CLProgramInfo_, CLBuildStatus(..), CLBuildStatus_, CLProgramBuildInfo_, 
+  CLKernelInfo_, CLKernelWorkGroupInfo_, wrapCheckSuccess, 
+  whenSuccess, wrapPError, wrapGetInfo, getCLValue, getEnumCL )
+
+#ifdef __APPLE__
+#include <OpenCL/opencl.h>
+#else
+#include <CL/cl.h>
+#endif
+
+-- -----------------------------------------------------------------------------
+type BuildCallback = CLProgram -> Ptr () -> IO ()
+foreign import CALLCONV "clCreateProgramWithSource" raw_clCreateProgramWithSource :: 
+  CLContext -> CLuint -> Ptr CString -> Ptr CSize -> Ptr CLint -> IO CLProgram
+foreign import CALLCONV "clCreateProgramWithBinary" raw_clCreateProgramWithBinary :: 
+  CLContext -> CLuint -> Ptr CLDeviceID -> Ptr CSize -> Ptr (Ptr Word8) -> Ptr CLint -> Ptr CLint -> IO CLProgram
+foreign import CALLCONV "clRetainProgram" raw_clRetainProgram :: 
+  CLProgram -> IO CLint
+foreign import CALLCONV "clReleaseProgram" raw_clReleaseProgram :: 
+  CLProgram -> IO CLint
+foreign import CALLCONV "clBuildProgram" raw_clBuildProgram :: 
+  CLProgram -> CLuint -> Ptr CLDeviceID -> CString -> FunPtr BuildCallback -> Ptr () -> IO CLint
+foreign import CALLCONV "clUnloadCompiler" raw_clUnloadCompiler :: 
+  IO CLint
+foreign import CALLCONV "clGetProgramInfo" raw_clGetProgramInfo :: 
+  CLProgram -> CLProgramInfo_ -> CSize -> Ptr () -> Ptr CSize -> IO CLint
+foreign import CALLCONV "clGetProgramBuildInfo"  raw_clGetProgramBuildInfo :: 
+  CLProgram -> CLDeviceID -> CLProgramBuildInfo_ -> CSize -> Ptr () -> Ptr CSize -> IO CLint
+foreign import CALLCONV "clCreateKernel" raw_clCreateKernel :: 
+  CLProgram -> CString -> Ptr CLint -> IO CLKernel 
+foreign import CALLCONV "clCreateKernelsInProgram" raw_clCreateKernelsInProgram :: 
+  CLProgram -> CLuint -> Ptr CLKernel -> Ptr CLuint -> IO CLint 
+foreign import CALLCONV "clRetainKernel" raw_clRetainKernel :: 
+  CLKernel -> IO CLint 
+foreign import CALLCONV "clReleaseKernel" raw_clReleaseKernel :: 
+  CLKernel -> IO CLint 
+foreign import CALLCONV "clSetKernelArg" raw_clSetKernelArg :: 
+  CLKernel -> CLuint -> CSize -> Ptr () -> IO CLint
+foreign import CALLCONV "clGetKernelInfo" raw_clGetKernelInfo :: 
+  CLKernel -> CLKernelInfo_ -> CSize -> Ptr () -> Ptr CSize -> IO CLint
+foreign import CALLCONV "clGetKernelWorkGroupInfo" raw_clGetKernelWorkGroupInfo :: 
+  CLKernel -> CLDeviceID -> CLKernelWorkGroupInfo_ -> CSize -> Ptr () -> Ptr CSize -> IO CLint
+
+-- -----------------------------------------------------------------------------
+{-| Creates a program object for a context, and loads the source code specified
+by the text strings in the strings array into the program object. The devices
+associated with the program object are the devices associated with context.
+
+OpenCL allows applications to create a program object using the program source
+or binary and build appropriate program executables. This allows applications to
+determine whether they want to use the pre-built offline binary or load and
+compile the program source and use the executable compiled/linked online as the
+program executable. This can be very useful as it allows applications to load
+and build program executables online on its first instance for appropriate
+OpenCL devices in the system. These executables can now be queried and cached by
+the application. Future instances of the application launching will no longer
+need to compile and build the program executables. The cached executables can be
+read and loaded by the application, which can help significantly reduce the
+application initialization time.
+
+An OpenCL program consists of a set of kernels that are identified as functions
+declared with the __kernel qualifier in the program source. OpenCL programs may
+also contain auxiliary functions and constant data that can be used by __kernel
+functions. The program executable can be generated online or offline by the
+OpenCL compiler for the appropriate target device(s).
+
+'clCreateProgramWithSource' returns a valid non-zero program object if the
+program object is created successfully. Otherwise, it throws one of the
+following 'CLError' exceptions:
+
+ * 'CL_INVALID_CONTEXT' if context is not a valid context.
+
+ * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
+by the OpenCL implementation on the host.  
+-}
+clCreateProgramWithSource :: CLContext -> String -> IO CLProgram
+clCreateProgramWithSource ctx source =
+  withCString source $ \cSource ->
+  withArray [cSource] $ \sourcesP ->
+  wrapPError (raw_clCreateProgramWithSource ctx 1 sourcesP nullPtr)
+
+{-| Creates a program object for a context, and loads specified binary data into
+the program object.
+
+The program binaries specified by binaries contain the bits that describe the
+program executable that will be run on the device(s) associated with
+context. The program binary can consist of either or both of device-specific
+executable(s), and/or implementation-specific intermediate representation (IR)
+which will be converted to the device-specific executable.
+
+OpenCL allows applications to create a program object using the program
+source or binary and build appropriate program executables. This allows
+applications to determine whether they want to use the pre-built offline binary
+or load and compile the program source and use the executable compiled/linked
+online as the program executable. This can be very useful as it allows
+applications to load and build program executables online on its first instance
+for appropriate OpenCL devices in the system. These executables can now be
+queried and cached by the application. Future instances of the application
+launching will no longer need to compile and build the program executables. The
+cached executables can be read and loaded by the application, which can help
+significantly reduce the application initialization time.
+
+Returns a valid non-zero program object and a list of 'CLError' values whether
+the program binary for each device specified in device_list was loaded
+successfully or not. It is list of the same length the list of devices with
+'CL_SUCCESS' if binary was successfully loaded for device specified by same
+position; otherwise returns 'CL_INVALID_VALUE' if length of binary is zero or
+'CL_INVALID_BINARY' if program binary is not a valid binary
+for the specified device.
+
+The function can throw on of the following 'CLError' exceptions:
+
+ * 'CL_INVALID_CONTEXT' if context is not a valid context.  
+
+ * 'CL_INVALID_VALUE' if the device list is empty; or if lengths or binaries are
+empty.
+
+ * 'CL_INVALID_DEVICE' if OpenCL devices listed in the device list are not in
+the list of devices associated with context.
+
+ * 'CL_INVALID_BINARY' if an invalid program binary was encountered for any
+device.
+
+ * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
+by the OpenCL implementation on the host.  
+-} 
+clCreateProgramWithBinary :: CLContext -> [CLDeviceID] -> [[Word8]] 
+                             -> IO (CLProgram, [CLError])
+clCreateProgramWithBinary ctx devs bins = wrapPError $ \perr ->
+  withArray devs $ \pdevs ->
+    withArray lbins $ \plbins -> do
+      buffs <- forM bins $ \bs -> do
+        buff <- mallocArray (length bs) :: IO (Ptr Word8)
+        pokeArray buff bs
+        return buff
+
+      ret <- withArray buffs $ \(pbuffs :: Ptr (Ptr Word8)) -> do
+        allocaArray ndevs $ \(perrs :: Ptr CLint) -> do
+          prog <- raw_clCreateProgramWithBinary ctx (fromIntegral ndevs) pdevs plbins pbuffs perrs perr
+          errs <- peekArray ndevs perrs
+          return (prog, map getEnumCL errs)
+
+      mapM_ free buffs
+      return ret
+    
+    where
+      lbins = map (fromIntegral . length) bins :: [CSize]
+      ndevs = length devs
+
+-- | Increments the program reference count. 'clRetainProgram' returns 'True' if 
+-- the function is executed successfully. It returns 'False' if program is not a 
+-- valid program object.
+clRetainProgram :: CLProgram -> IO Bool
+clRetainProgram prg = wrapCheckSuccess $ raw_clRetainProgram prg
+
+-- | Decrements the program reference count. The program object is deleted after 
+-- all kernel objects associated with program have been deleted and the program 
+-- reference count becomes zero. 'clReleseProgram' returns 'True' if 
+-- the function is executed successfully. It returns 'False' if program is not a 
+-- valid program object.
+clReleaseProgram :: CLProgram -> IO Bool
+clReleaseProgram prg = wrapCheckSuccess $ raw_clReleaseProgram prg
+
+-- | Allows the implementation to release the resources allocated by the OpenCL
+-- compiler. This is a hint from the application and does not guarantee that the
+-- compiler will not be used in the future or that the compiler will actually be
+-- unloaded by the implementation. Calls to 'clBuildProgram' after
+-- 'clUnloadCompiler' will reload the compiler, if necessary, to build the
+-- appropriate program executable.
+clUnloadCompiler :: IO ()
+clUnloadCompiler = raw_clUnloadCompiler >> return ()
+
+{-| Builds (compiles and links) a program executable from the program source or
+binary. OpenCL allows program executables to be built using the source or the
+binary. The build options are categorized as pre-processor options, options for
+math intrinsics, options that control optimization and miscellaneous
+options. This specification defines a standard set of options that must be
+supported by an OpenCL compiler when building program executables online or
+offline. These may be extended by a set of vendor- or platform-specific options.
+
+ * Preprocessor Options
+
+These options control the OpenCL preprocessor which is run on each program
+source before actual compilation. -D options are processed in the order they are
+given in the options argument to clBuildProgram.
+
+ [-D name] Predefine name as a macro, with definition 1.
+
+ [-D name=definition] The contents of definition are tokenized and processed as
+if they appeared during translation phase three in a `#define' directive. In
+particular, the definition will be truncated by embedded newline characters.
+
+ [-I dir] Add the directory dir to the list of directories to be searched for
+header files.
+
+ * Math Intrinsics Options
+
+These options control compiler behavior regarding floating-point
+arithmetic. These options trade off between speed and correctness.
+
+ [-cl-single-precision-constant] Treat double precision floating-point constant
+as single precision constant.
+
+ [-cl-denorms-are-zero] This option controls how single precision and double
+precision denormalized numbers are handled. If specified as a build option, the
+single precision denormalized numbers may be flushed to zero and if the optional
+extension for double precision is supported, double precision denormalized
+numbers may also be flushed to zero. This is intended to be a performance hint
+and the OpenCL compiler can choose not to flush denorms to zero if the device
+supports single precision (or double precision) denormalized numbers.
+
+This option is ignored for single precision numbers if the device does not
+support single precision denormalized numbers i.e. 'CL_FP_DENORM' bit is not set
+in 'clGetDeviceSingleFPConfig'.
+
+This option is ignored for double precision numbers if the device does not
+support double precision or if it does support double precison but
+'CL_FP_DENORM' bit is not set in 'clGetDeviceDoubleFPConfig'.
+
+This flag only applies for scalar and vector single precision floating-point
+variables and computations on these floating-point variables inside a
+program. It does not apply to reading from or writing to image objects.
+
+ * Optimization Options
+
+These options control various sorts of optimizations. Turning on optimization
+flags makes the compiler attempt to improve the performance and/or code size at
+the expense of compilation time and possibly the ability to debug the program.
+
+ [-cl-opt-disable] This option disables all optimizations. The default is
+optimizations are enabled.
+
+ [-cl-strict-aliasing] This option allows the compiler to assume the strictest
+aliasing rules.
+
+The following options control compiler behavior regarding floating-point
+arithmetic. These options trade off between performance and correctness and must
+be specifically enabled. These options are not turned on by default since it can
+result in incorrect output for programs which depend on an exact implementation
+of IEEE 754 rules/specifications for math functions.
+
+ [-cl-mad-enable] Allow a * b + c to be replaced by a mad. The mad computes a *
+b + c with reduced accuracy. For example, some OpenCL devices implement mad as
+truncate the result of a * b before adding it to c.
+
+ [-cl-no-signed-zeros] Allow optimizations for floating-point arithmetic that
+ignore the signedness of zero. IEEE 754 arithmetic specifies the behavior of
+distinct +0.0 and -0.0 values, which then prohibits simplification of
+expressions such as x+0.0 or 0.0*x (even with -clfinite-math only). This option
+implies that the sign of a zero result isn't significant.
+
+ [-cl-unsafe-math-optimizations] Allow optimizations for floating-point
+arithmetic that (a) assume that arguments and results are valid, (b) may violate
+IEEE 754 standard and (c) may violate the OpenCL numerical compliance
+requirements as defined in section 7.4 for single-precision floating-point,
+section 9.3.9 for double-precision floating-point, and edge case behavior in
+section 7.5. This option includes the -cl-no-signed-zeros and -cl-mad-enable
+options.
+
+ [-cl-finite-math-only] Allow optimizations for floating-point arithmetic that
+assume that arguments and results are not NaNs or ±∞. This option may violate
+the OpenCL numerical compliance requirements defined in in section 7.4 for
+single-precision floating-point, section 9.3.9 for double-precision
+floating-point, and edge case behavior in section 7.5.
+
+ [-cl-fast-relaxed-math] Sets the optimization options -cl-finite-math-only and
+-cl-unsafe-math-optimizations. This allows optimizations for floating-point
+arithmetic that may violate the IEEE 754 standard and the OpenCL numerical
+compliance requirements defined in the specification in section 7.4 for
+single-precision floating-point, section 9.3.9 for double-precision
+floating-point, and edge case behavior in section 7.5. This option causes the
+preprocessor macro __FAST_RELAXED_MATH__ to be defined in the OpenCL program.
+
+ * Options to Request or Suppress Warnings
+
+Warnings are diagnostic messages that report constructions which are not
+inherently erroneous but which are risky or suggest there may have been an
+error. The following languageindependent options do not enable specific warnings
+but control the kinds of diagnostics produced by the OpenCL compiler.
+
+ [-w] Inhibit all warning messages.
+ 
+ [-Werror] Make all warnings into errors.
+
+clBuildProgram can throw the following 'CLError' exceptions when fails:
+
+ * 'CL_INVALID_PROGRAM' if program is not a valid program object.
+
+ * 'CL_INVALID_DEVICE' if OpenCL devices listed in device_list are not in the
+list of devices associated with program.
+
+ * 'CL_INVALID_BINARY' if program is created with
+'clCreateWithProgramWithBinary' and devices listed in device_list do not have a
+valid program binary loaded.
+
+ * 'CL_INVALID_BUILD_OPTIONS' if the build options specified by options are
+invalid.
+
+ * 'CL_INVALID_OPERATION' if the build of a program executable for any of the
+devices listed in device_list by a previous call to 'clBuildProgram' for program
+has not completed.
+
+ * 'CL_COMPILER_NOT_AVAILABLE' if program is created with
+'clCreateProgramWithSource' and a compiler is not available
+i.e. 'clGetDeviceCompilerAvailable' is set to 'False'.
+
+ * 'CL_BUILD_PROGRAM_FAILURE' if there is a failure to build the program
+executable. This error will be returned if 'clBuildProgram' does not return
+until the build has completed.
+
+ * 'CL_INVALID_OPERATION' if there are kernel objects attached to program.
+
+ * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
+by the OpenCL implementation on the host.  
+-}
+clBuildProgram :: CLProgram -> [CLDeviceID] -> String -> IO ()
+clBuildProgram prg devs opts = allocaArray ndevs $ \pdevs -> do
+  pokeArray pdevs devs
+  withCString opts $ \copts -> do
+    whenSuccess (raw_clBuildProgram prg cndevs pdevs copts nullFunPtr nullPtr)
+      $ return ()
+    where
+      ndevs = length devs
+      cndevs = fromIntegral ndevs
+
+#c
+enum CLProgramInfo {
+  cL_PROGRAM_REFERENCE_COUNT=CL_PROGRAM_REFERENCE_COUNT,
+  cL_PROGRAM_CONTEXT=CL_PROGRAM_CONTEXT,
+  cL_PROGRAM_NUM_DEVICES=CL_PROGRAM_NUM_DEVICES,
+  cL_PROGRAM_DEVICES=CL_PROGRAM_DEVICES,
+  cL_PROGRAM_SOURCE=CL_PROGRAM_SOURCE,
+  cL_PROGRAM_BINARY_SIZES=CL_PROGRAM_BINARY_SIZES,
+  cL_PROGRAM_BINARIES=CL_PROGRAM_BINARIES,
+  };
+#endc
+{#enum CLProgramInfo {upcaseFirstLetter} #}
+
+getProgramInfoSize :: CLProgram -> CLProgramInfo_ -> IO CSize
+getProgramInfoSize prg infoid = alloca $ \(value_size :: Ptr CSize) -> do
+  whenSuccess (raw_clGetProgramInfo prg infoid 0 nullPtr value_size)
+    $ peek value_size
+  
+-- | Return the program reference count. The reference count returned should be
+-- considered immediately stale. It is unsuitable for general use in
+-- applications. This feature is provided for identifying memory leaks.
+--
+-- This function execute OpenCL clGetProgramInfo with
+-- 'CL_PROGRAM_REFERENCE_COUNT'.
+clGetProgramReferenceCount :: CLProgram -> IO CLuint
+clGetProgramReferenceCount prg =
+    wrapGetInfo (\(dat :: Ptr CLuint) ->
+        raw_clGetProgramInfo prg infoid size (castPtr dat)) id
+    where 
+      infoid = getCLValue CL_PROGRAM_REFERENCE_COUNT
+      size = fromIntegral $ sizeOf (0::CLuint)
+
+-- | Return the context specified when the program object is created.
+--
+-- This function execute OpenCL clGetProgramInfo with 'CL_PROGRAM_CONTEXT'.
+clGetProgramContext :: CLProgram -> IO CLContext
+clGetProgramContext prg =
+    wrapGetInfo (\(dat :: Ptr CLContext) ->
+        raw_clGetProgramInfo prg infoid size (castPtr dat)) id
+    where 
+      infoid = getCLValue CL_PROGRAM_CONTEXT
+      size = fromIntegral $ sizeOf (nullPtr::CLContext)
+
+-- | Return the number of devices associated with program.
+--
+-- This function execute OpenCL clGetProgramInfo with 'CL_PROGRAM_NUM_DEVICES'.
+clGetProgramNumDevices :: CLProgram -> IO CLuint
+clGetProgramNumDevices prg =
+    wrapGetInfo (\(dat :: Ptr CLuint) ->
+        raw_clGetProgramInfo prg infoid size (castPtr dat)) id
+    where 
+      infoid = getCLValue CL_PROGRAM_NUM_DEVICES
+      size = fromIntegral $ sizeOf (0::CLuint)
+
+-- | Return the list of devices associated with the program object. This can be
+-- the devices associated with context on which the program object has been
+-- created or can be a subset of devices that are specified when a progam object
+-- is created using 'clCreateProgramWithBinary'.
+--
+-- This function execute OpenCL clGetProgramInfo with 'CL_PROGRAM_DEVICES'.
+clGetProgramDevices :: CLProgram -> IO [CLDeviceID]
+clGetProgramDevices prg = do
+  size <- getProgramInfoSize prg infoid
+  allocaArray (numElems size) $ \(buff :: Ptr CLDeviceID) -> do
+    whenSuccess (raw_clGetProgramInfo prg infoid size (castPtr buff) nullPtr)
+      $ peekArray (numElems size) buff
+    where 
+      infoid = getCLValue CL_PROGRAM_DEVICES
+      numElems s = (fromIntegral s) `div` elemSize
+      elemSize = sizeOf (nullPtr::CLDeviceID)
+
+-- | Return the program source code specified by
+-- 'clCreateProgramWithSource'. The source string returned is a concatenation of
+-- all source strings specified to 'clCreateProgramWithSource' with a null
+-- terminator. The concatenation strips any nulls in the original source
+-- strings. The actual number of characters that represents the program source
+-- code including the null terminator is returned in param_value_size_ret.
+--
+-- This function execute OpenCL clGetProgramInfo with 'CL_PROGRAM_SOURCE'.
+clGetProgramSource :: CLProgram -> IO String
+clGetProgramSource prg = do
+  n <- getProgramInfoSize prg infoid
+  allocaArray (fromIntegral n) $ \(buff :: CString) -> do
+    whenSuccess (raw_clGetProgramInfo prg infoid n (castPtr buff) nullPtr)
+      $ peekCString buff
+    where 
+      infoid = getCLValue CL_PROGRAM_SOURCE
+  
+-- | Returns an array that contains the size in bytes of the program binary for
+-- each device associated with program. The size of the array is the number of
+-- devices associated with program. If a binary is not available for a
+-- device(s), a size of zero is returned.
+--
+-- This function execute OpenCL clGetProgramInfo with 'CL_PROGRAM_BINARY_SIZES'.
+clGetProgramBinarySizes :: CLProgram -> IO [CSize]
+clGetProgramBinarySizes prg = do
+  size <- getProgramInfoSize prg infoid
+  allocaArray (numElems size) $ \(buff :: Ptr CSize) -> do
+    whenSuccess (raw_clGetProgramInfo prg infoid size (castPtr buff) nullPtr)
+      $ peekArray (numElems size) buff
+    where 
+      infoid = getCLValue CL_PROGRAM_BINARY_SIZES
+      numElems s = (fromIntegral s) `div` elemSize
+      elemSize = sizeOf (0::CSize)
+
+{-| Return the program binaries for all devices associated with program. For
+each device in program, the binary returned can be the binary specified for the
+device when program is created with 'clCreateProgramWithBinary' or it can be the
+executable binary generated by 'clBuildProgram'. If program is created with
+'clCreateProgramWithSource', the binary returned is the binary generated by
+'clBuildProgram'. The bits returned can be an implementation-specific
+intermediate representation (a.k.a. IR) or device specific executable bits or
+both. The decision on which information is returned in the binary is up to the
+OpenCL implementation.
+
+To find out which device the program binary in the array refers to, use the
+'clGetProgramDevices' query to get the list of devices. There is a one-to-one
+correspondence between the array of data returned by 'clGetProgramBinaries' and
+array of devices returned by 'clGetProgramDevices'.  
+
+This function execute OpenCL clGetProgramInfo with 'CL_PROGRAM_BINARIES'.
+-}
+clGetProgramBinaries :: CLProgram -> IO [[Word8]]
+clGetProgramBinaries prg = do
+  sizes <- clGetProgramBinarySizes prg
+  let numElems = length sizes
+      size = fromIntegral $ numElems * elemSize
+  buffers <- (mapM (mallocArray.fromIntegral) sizes) :: IO [Ptr Word8]
+  ret <- withArray buffers $ \(parray :: Ptr (Ptr Word8)) -> do
+    whenSuccess (raw_clGetProgramInfo prg infoid size (castPtr parray) nullPtr)
+      $ zipWithM peekArray (map fromIntegral sizes) buffers
+  mapM_ free buffers
+  return ret
+    where 
+      infoid = getCLValue CL_PROGRAM_BINARIES
+      elemSize = sizeOf (nullPtr::Ptr Word8)
+
+-- -----------------------------------------------------------------------------
+#c
+enum CLProgramBuildInfo {
+  cL_PROGRAM_BUILD_STATUS=CL_PROGRAM_BUILD_STATUS,
+  cL_PROGRAM_BUILD_OPTIONS=CL_PROGRAM_BUILD_OPTIONS,
+  cL_PROGRAM_BUILD_LOG=CL_PROGRAM_BUILD_LOG,
+  };
+#endc
+{#enum CLProgramBuildInfo {upcaseFirstLetter} #}
+
+getProgramBuildInfoSize :: CLProgram -> CLDeviceID -> CLProgramInfo_ -> IO CSize
+getProgramBuildInfoSize prg device infoid = alloca $ \(val :: Ptr CSize) -> do
+  whenSuccess (raw_clGetProgramBuildInfo prg device infoid 0 nullPtr val)
+    $ peek val
+  
+-- | Returns the build status of program for a specific device as given by
+-- device.
+--
+-- This function execute OpenCL clGetProgramBuildInfo with
+-- 'CL_PROGRAM_BUILD_STATUS'.
+clGetProgramBuildStatus :: CLProgram -> CLDeviceID -> IO CLBuildStatus
+clGetProgramBuildStatus prg device =
+    wrapGetInfo (\(dat :: Ptr CLBuildStatus_) ->
+        raw_clGetProgramBuildInfo prg device infoid size (castPtr dat)) getEnumCL
+    where 
+      infoid = getCLValue CL_PROGRAM_BUILD_STATUS
+      size = fromIntegral $ sizeOf (0::CLBuildStatus_)
+
+-- | Return the build options specified by the options argument in
+-- clBuildProgram for device. If build status of program for device is
+-- 'CL_BUILD_NONE', an empty string is returned.
+--
+-- This function execute OpenCL clGetProgramBuildInfo with
+-- 'CL_PROGRAM_BUILD_OPTIONS'.
+clGetProgramBuildOptions :: CLProgram -> CLDeviceID -> IO String
+clGetProgramBuildOptions prg device = do
+  n <- getProgramBuildInfoSize prg device infoid
+  allocaArray (fromIntegral n) $ \(buff :: CString) -> do
+    whenSuccess (raw_clGetProgramBuildInfo prg device infoid n (castPtr buff) nullPtr)
+      $ peekCString buff
+    where 
+      infoid = getCLValue CL_PROGRAM_BUILD_OPTIONS
+  
+-- | Return the build log when 'clBuildProgram' was called for device. If build
+-- status of program for device is 'CL_BUILD_NONE', an empty string is returned.
+--
+-- This function execute OpenCL clGetProgramBuildInfo with
+-- 'CL_PROGRAM_BUILD_LOG'.
+clGetProgramBuildLog :: CLProgram -> CLDeviceID -> IO String
+clGetProgramBuildLog prg device = do
+  n <- getProgramBuildInfoSize prg device infoid
+  allocaArray (fromIntegral n) $ \(buff :: CString) -> do
+    whenSuccess (raw_clGetProgramBuildInfo prg device infoid n (castPtr buff) nullPtr)
+      $ peekCString buff
+    where 
+      infoid = getCLValue CL_PROGRAM_BUILD_LOG
+  
+-- -----------------------------------------------------------------------------
+{-| Creates a kernal object. A kernel is a function declared in a program. A
+kernel is identified by the __kernel qualifier applied to any function in a
+program. A kernel object encapsulates the specific __kernel function declared in
+a program and the argument values to be used when executing this __kernel
+function.
+
+'clCreateKernel' returns a valid non-zero kernel object if the kernel object is
+created successfully. Otherwise, it throws one of the following 'CLError'
+exceptions:
+
+ * 'CL_INVALID_PROGRAM' if program is not a valid program object.
+
+ * 'CL_INVALID_PROGRAM_EXECUTABLE' if there is no successfully built executable
+ for program.
+
+ * 'CL_INVALID_KERNEL_NAME' if kernel_name is not found in program.
+
+ * 'CL_INVALID_KERNEL_DEFINITION' if the function definition for __kernel
+function given by kernel_name such as the number of arguments, the argument
+types are not the same for all devices for which the program executable has been
+built.
+
+ * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
+by the OpenCL implementation on the host.  
+-}
+clCreateKernel :: CLProgram -> String -> IO CLKernel
+clCreateKernel prg name = withCString name $ \cname -> wrapPError $ \perr -> do
+  raw_clCreateKernel prg cname perr
+
+{-| Creates kernel objects for all kernel functions in a program object. Kernel
+objects are not created for any __kernel functions in program that do not have
+the same function definition across all devices for which a program executable
+has been successfully built.
+
+Kernel objects can only be created once you have a program object with a valid
+program source or binary loaded into the program object and the program
+executable has been successfully built for one or more devices associated with
+program. No changes to the program executable are allowed while there are kernel
+objects associated with a program object. This means that calls to
+'clBuildProgram' return 'CL_INVALID_OPERATION' if there are kernel objects
+attached to a program object. The OpenCL context associated with program will be
+the context associated with kernel. The list of devices associated with program
+are the devices associated with kernel. Devices associated with a program object
+for which a valid program executable has been built can be used to execute
+kernels declared in the program object.
+
+'clCreateKernelsInProgram' will return the kernel objects if the kernel objects
+were successfully allocated, throws 'CL_INVALID_PROGRAM' if program is not a
+valid program object, throws 'CL_INVALID_PROGRAM_EXECUTABLE' if there is no
+successfully built executable for any device in program and throws
+'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required by
+the OpenCL implementation on the host.
+-}
+clCreateKernelsInProgram :: CLProgram -> IO [CLKernel]
+clCreateKernelsInProgram prg = do
+  n <- alloca $ \pn -> do
+    whenSuccess (raw_clCreateKernelsInProgram prg 0 nullPtr pn)
+      $ peek pn  
+  allocaArray (fromIntegral n) $ \pks -> do
+    whenSuccess (raw_clCreateKernelsInProgram prg n pks nullPtr)
+      $ peekArray (fromIntegral n) pks
+
+-- | Increments the program program reference count. 'clRetainKernel' returns
+-- 'True' if the function is executed successfully. 'clCreateKernel' or
+-- 'clCreateKernelsInProgram' do an implicit retain.
+clRetainKernel :: CLKernel -> IO Bool
+clRetainKernel krn = wrapCheckSuccess $ raw_clRetainKernel krn
+
+-- | Decrements the kernel reference count. The kernel object is deleted once
+-- the number of instances that are retained to kernel become zero and the
+-- kernel object is no longer needed by any enqueued commands that use
+-- kernel. 'clReleaseKernel' returns 'True' if the function is executed
+-- successfully.
+clReleaseKernel :: CLKernel -> IO Bool
+clReleaseKernel krn = wrapCheckSuccess $ raw_clReleaseKernel krn
+
+{-| Used to set the argument value for a specific argument of a kernel.
+
+A kernel object does not update the reference count for objects such as memory,
+sampler objects specified as argument values by 'clSetKernelArg', Users may not
+rely on a kernel object to retain objects specified as argument values to the
+kernel.
+
+Implementations shall not allow 'CLKernel' objects to hold reference counts to
+'CLKernel' arguments, because no mechanism is provided for the user to tell the
+kernel to release that ownership right. If the kernel holds ownership rights on
+kernel args, that would make it impossible for the user to tell with certainty
+when he may safely release user allocated resources associated with OpenCL
+objects such as the CLMem backing store used with 'CL_MEM_USE_HOST_PTR'.
+
+'clSetKernelArg' throws one of the following 'CLError' exceptions when fails:
+
+ * 'CL_INVALID_KERNEL' if kernel is not a valid kernel object.
+ 
+ * 'CL_INVALID_ARG_INDEX' if arg_index is not a valid argument index.
+
+ * 'CL_INVALID_ARG_VALUE' if arg_value specified is NULL for an argument that is
+not declared with the __local qualifier or vice-versa.
+
+ * 'CL_INVALID_MEM_OBJECT' for an argument declared to be a memory object when
+the specified arg_value is not a valid memory object.
+
+ * 'CL_INVALID_SAMPLER' for an argument declared to be of type sampler_t when
+the specified arg_value is not a valid sampler object.
+
+ * 'CL_INVALID_ARG_SIZE' if arg_size does not match the size of the data type
+for an argument that is not a memory object or if the argument is a memory
+object and arg_size != sizeof(cl_mem) or if arg_size is zero and the argument is
+declared with the __local qualifier or if the argument is a sampler and arg_size
+!= sizeof(cl_sampler).  
+-}
+clSetKernelArg :: Integral a => CLKernel -> CLuint -> a -> Ptr b -> IO ()
+clSetKernelArg krn idx sz pval = do
+  whenSuccess (raw_clSetKernelArg krn idx (fromIntegral sz) (castPtr pval))
+    $ return ()
+
+-- | Wrap function of `clSetKernelArg` with Storable data.
+clSetKernelArgSto :: Storable a => CLKernel -> CLuint -> a -> IO ()
+clSetKernelArgSto krn idx val = with val $ \pval -> do
+  whenSuccess (raw_clSetKernelArg krn idx (fromIntegral . sizeOf $ val) (castPtr pval))
+    $ return ()
+
+#c
+enum CLKernelInfo {
+  cL_KERNEL_FUNCTION_NAME=CL_KERNEL_FUNCTION_NAME,
+  cL_KERNEL_NUM_ARGS=CL_KERNEL_NUM_ARGS,
+  cL_KERNEL_REFERENCE_COUNT=CL_KERNEL_REFERENCE_COUNT,
+  cL_KERNEL_CONTEXT=CL_KERNEL_CONTEXT,
+  cL_KERNEL_PROGRAM=CL_KERNEL_PROGRAM
+  };
+#endc
+{#enum CLKernelInfo {upcaseFirstLetter} #}
+
+getKernelInfoSize :: CLKernel -> CLKernelInfo_ -> IO CSize
+getKernelInfoSize krn infoid = alloca $ \(val :: Ptr CSize) -> do
+  whenSuccess (raw_clGetKernelInfo krn infoid 0 nullPtr val)
+    $ peek val
+  
+-- | Return the kernel function name.
+--
+-- This function execute OpenCL clGetKernelInfo with 'CL_KERNEL_FUNCTION_NAME'.
+clGetKernelFunctionName :: CLKernel -> IO String
+clGetKernelFunctionName krn = do
+  n <- getKernelInfoSize krn infoid
+  allocaArray (fromIntegral n) $ \(buff :: CString) -> do
+    whenSuccess (raw_clGetKernelInfo krn infoid n (castPtr buff) nullPtr)
+      $ peekCString buff
+    where 
+      infoid = getCLValue CL_KERNEL_FUNCTION_NAME
+
+-- | Return the number of arguments to kernel.
+--
+-- This function execute OpenCL clGetKernelInfo with 'CL_KERNEL_NUM_ARGS'.
+clGetKernelNumArgs :: CLKernel -> IO CLuint
+clGetKernelNumArgs krn =
+    wrapGetInfo (\(dat :: Ptr CLuint) ->
+        raw_clGetKernelInfo krn infoid size (castPtr dat)) id
+    where 
+      infoid = getCLValue CL_KERNEL_NUM_ARGS
+      size = fromIntegral $ sizeOf (0::CLuint)
+
+-- | Return the kernel reference count. The reference count returned should be
+-- considered immediately stale. It is unsuitable for general use in
+-- applications. This feature is provided for identifying memory leaks.
+--
+-- This function execute OpenCL clGetKernelInfo with
+-- 'CL_KERNEL_REFERENCE_COUNT'.
+clGetKernelReferenceCount :: CLKernel -> IO CLuint
+clGetKernelReferenceCount krn =
+    wrapGetInfo (\(dat :: Ptr CLuint) ->
+        raw_clGetKernelInfo krn infoid size (castPtr dat)) id
+    where 
+      infoid = getCLValue CL_KERNEL_REFERENCE_COUNT
+      size = fromIntegral $ sizeOf (0::CLuint)
+
+-- | Return the context associated with kernel.
+--
+-- This function execute OpenCL clGetKernelInfo with 'CL_KERNEL_CONTEXT'.
+clGetKernelContext :: CLKernel -> IO CLContext
+clGetKernelContext krn =
+    wrapGetInfo (\(dat :: Ptr CLContext) ->
+        raw_clGetKernelInfo krn infoid size (castPtr dat)) id
+    where 
+      infoid = getCLValue CL_KERNEL_CONTEXT
+      size = fromIntegral $ sizeOf (nullPtr::CLContext)
+
+-- | Return the program object associated with kernel.
+--
+-- This function execute OpenCL clGetKernelInfo with 'CL_KERNEL_PROGRAM'.
+clGetKernelProgram :: CLKernel -> IO CLProgram
+clGetKernelProgram krn =
+    wrapGetInfo (\(dat :: Ptr CLProgram) ->
+        raw_clGetKernelInfo krn infoid size (castPtr dat)) id
+    where 
+      infoid = getCLValue CL_KERNEL_PROGRAM
+      size = fromIntegral $ sizeOf (nullPtr::CLProgram)
+
+
+#c
+enum CLKernelGroupInfo {
+  cL_KERNEL_WORK_GROUP_SIZE=CL_KERNEL_WORK_GROUP_SIZE,
+  cL_KERNEL_COMPILE_WORK_GROUP_SIZE=CL_KERNEL_COMPILE_WORK_GROUP_SIZE,
+  cL_KERNEL_LOCAL_MEM_SIZE=CL_KERNEL_LOCAL_MEM_SIZE,
+  };
+#endc
+{#enum CLKernelGroupInfo {upcaseFirstLetter} #}
+
+-- | This provides a mechanism for the application to query the work-group size
+-- that can be used to execute a kernel on a specific device given by
+-- device. The OpenCL implementation uses the resource requirements of the
+-- kernel (register usage etc.) to determine what this work-group size should
+-- be.
+--
+-- This function execute OpenCL clGetKernelWorkGroupInfo with
+-- 'CL_KERNEL_WORK_GROUP_SIZE'.
+clGetKernelWorkGroupSize :: CLKernel -> CLDeviceID -> IO CSize
+clGetKernelWorkGroupSize krn device =
+    wrapGetInfo (\(dat :: Ptr CSize) ->
+        raw_clGetKernelWorkGroupInfo krn device infoid size (castPtr dat)) id
+    where
+      infoid = getCLValue CL_KERNEL_WORK_GROUP_SIZE
+      size = fromIntegral $ sizeOf (0::CSize)
+
+-- | Returns the work-group size specified by the __attribute__((reqd_work_gr
+-- oup_size(X, Y, Z))) qualifier. See Function Qualifiers. If the work-group
+-- size is not specified using the above attribute qualifier (0, 0, 0) is
+-- returned.
+--
+-- This function execute OpenCL clGetKernelWorkGroupInfo with
+-- 'CL_KERNEL_COMPILE_WORK_GROUP_SIZE'.
+clGetKernelCompileWorkGroupSize :: CLKernel -> CLDeviceID -> IO [CSize]
+clGetKernelCompileWorkGroupSize krn device = do
+  allocaArray num $ \(buff :: Ptr CSize) -> do
+    whenSuccess (raw_clGetKernelWorkGroupInfo krn device infoid size (castPtr buff) nullPtr)
+      $ peekArray num buff
+    where 
+      infoid = getCLValue CL_KERNEL_COMPILE_WORK_GROUP_SIZE
+      num = 3
+      elemSize = fromIntegral $ sizeOf (0::CSize)
+      size = fromIntegral $ num * elemSize
+
+
+-- | Returns the amount of local memory in bytes being used by a kernel. This
+-- includes local memory that may be needed by an implementation to execute the
+-- kernel, variables declared inside the kernel with the __local address
+-- qualifier and local memory to be allocated for arguments to the kernel
+-- declared as pointers with the __local address qualifier and whose size is
+-- specified with 'clSetKernelArg'.
+--
+-- If the local memory size, for any pointer argument to the kernel declared
+-- with the __local address qualifier, is not specified, its size is assumed to
+-- be 0.
+--
+-- This function execute OpenCL clGetKernelWorkGroupInfo with
+-- 'CL_KERNEL_LOCAL_MEM_SIZE'.
+clGetKernelLocalMemSize :: CLKernel -> CLDeviceID -> IO CLulong
+clGetKernelLocalMemSize krn device =
+    wrapGetInfo (\(dat :: Ptr CLulong) ->
+        raw_clGetKernelWorkGroupInfo krn device infoid size (castPtr dat)) id
+    where
+      infoid = getCLValue CL_KERNEL_LOCAL_MEM_SIZE
+      size = fromIntegral $ sizeOf (0::CLulong)
+-- -----------------------------------------------------------------------------
diff --git a/src/Control/Parallel/OpenCL/Query.chs b/src/Control/Parallel/OpenCL/Query.chs
new file mode 100644
--- /dev/null
+++ b/src/Control/Parallel/OpenCL/Query.chs
@@ -0,0 +1,725 @@
+{- Copyright (c) 2011 Luis Cabellos,
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of  nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-}
+{-# LANGUAGE ForeignFunctionInterface, ScopedTypeVariables, CPP #-}
+module Control.Parallel.OpenCL.Query( 
+  -- * Types
+  CLPlatformInfo(..), CLPlatformID, CLDeviceID, CLDeviceType(..),
+  CLDeviceFPConfig(..), CLDeviceExecCapability(..), CLDeviceLocalMemType(..),
+  CLDeviceMemCacheType(..),
+  -- * Platform Query Functions
+  clGetPlatformIDs, clGetPlatformInfo, 
+  -- * Device Query Functions
+  clGetDeviceIDs, clGetDeviceExecutionCapabilities,
+  clGetDeviceAddressBits, clGetDeviceAvailable, clGetDeviceCompilerAvailable, 
+  clGetDeviceEndianLittle, clGetDeviceErrorCorrectionSupport, 
+  clGetDeviceExtensions, clGetDeviceGlobalMemCacheSize, 
+  clGetDeviceGlobalMemCachelineSize, clGetDeviceGlobalMemSize, 
+  clGetDeviceImageSupport, clGetDeviceImage2DMaxHeight, 
+  clGetDeviceImage2DMaxWidth, clGetDeviceImage3DMaxDepth, 
+  clGetDeviceImage3DMaxHeight, clGetDeviceImage3DMaxWidth, 
+  clGetDeviceLocalMemSize, clGetDeviceMaxClockFrequency, 
+  clGetDeviceMaxComputeUnits, clGetDeviceMaxConstantArgs, 
+  clGetDeviceMaxConstantBufferSize, clGetDeviceMaxMemAllocSize, 
+  clGetDeviceMaxParameterSize, clGetDeviceMaxReadImageArgs, 
+  clGetDeviceMaxSamplers, clGetDeviceMaxWorkGroupSize, 
+  clGetDeviceMaxWorkItemDimensions, clGetDeviceMaxWorkItemSizes, 
+  clGetDeviceMaxWriteImageArgs, clGetDeviceMemBaseAddrAlign, 
+  clGetDeviceMinDataTypeAlignSize, clGetDeviceName, clGetDevicePlatform, 
+  clGetDevicePreferredVectorWidthChar, clGetDevicePreferredVectorWidthShort, 
+  clGetDevicePreferredVectorWidthInt, clGetDevicePreferredVectorWidthLong, 
+  clGetDevicePreferredVectorWidthFloat, clGetDevicePreferredVectorWidthDouble, 
+  clGetDeviceProfile, clGetDeviceProfilingTimerResolution, clGetDeviceVendor, 
+  clGetDeviceVendorID, clGetDeviceVersion, clGetDeviceDriverVersion, 
+  clGetDeviceSingleFPConfig, clGetDeviceDoubleFPConfig, 
+  clGetDeviceHalfFPConfig, clGetDeviceLocalMemType, 
+  clGetDeviceGlobalMemCacheType, clGetDeviceQueueProperties, clGetDeviceType )
+       where
+
+-- -----------------------------------------------------------------------------
+import Foreign( Ptr, nullPtr, castPtr, alloca, allocaArray, peek, peekArray )
+import Foreign.C.String( CString, peekCString )
+import Foreign.C.Types( CSize )
+import Foreign.Storable( sizeOf )
+import Control.Parallel.OpenCL.Types( 
+  CLbool, CLint, CLuint, CLulong, CLPlatformInfo_, CLDeviceType_,
+  CLDeviceInfo_, CLDeviceFPConfig(..), CLDeviceExecCapability(..),
+  CLDeviceLocalMemType(..), CLDeviceMemCacheType(..), CLPlatformInfo(..),
+  CLPlatformID, CLDeviceID, CLDeviceType(..), CLCommandQueueProperty, 
+  getCLValue, getEnumCL, bitmaskToDeviceTypes, bitmaskToCommandQueueProperties, 
+  whenSuccess, bitmaskToFPConfig, bitmaskToExecCapability )
+
+-- -----------------------------------------------------------------------------
+foreign import CALLCONV "clGetPlatformIDs" raw_clGetPlatformIDs :: 
+  CLuint -> Ptr CLPlatformID -> Ptr CLuint -> IO CLint
+foreign import CALLCONV "clGetPlatformInfo" raw_clGetPlatformInfo :: 
+  CLPlatformID -> CLPlatformInfo_ -> CSize -> Ptr () -> Ptr CSize -> IO CLint 
+foreign import CALLCONV "clGetDeviceIDs" raw_clGetDeviceIDs :: 
+  CLPlatformID -> CLDeviceType_ -> CLuint -> Ptr CLDeviceID -> Ptr CLuint -> IO CLint
+foreign import CALLCONV "clGetDeviceInfo" raw_clGetDeviceInfo :: 
+  CLDeviceID -> CLDeviceInfo_ -> CSize -> Ptr () -> Ptr CSize -> IO CLint
+
+#ifdef __APPLE__
+#include <OpenCL/opencl.h>
+#else
+#include <CL/cl.h>
+#endif
+
+-- -----------------------------------------------------------------------------
+getNumPlatforms :: IO CLuint
+getNumPlatforms = alloca $ \(num_platforms :: Ptr CLuint) -> do 
+  whenSuccess (raw_clGetPlatformIDs 0 nullPtr num_platforms) 
+    $ peek num_platforms
+
+-- | Obtain the list of platforms available. Returns the list if the function 
+-- is executed successfully. Otherwise it returns the empty list.
+clGetPlatformIDs :: IO [CLPlatformID]
+clGetPlatformIDs = do
+  nplats <- getNumPlatforms
+  allocaArray (fromIntegral nplats) $ \(plats :: Ptr CLPlatformID) -> do
+    whenSuccess (raw_clGetPlatformIDs nplats plats nullPtr) 
+      $ peekArray (fromIntegral nplats) plats
+  
+getPlatformInfoSize :: CLPlatformID -> CLuint -> IO CSize
+getPlatformInfoSize platform infoid = alloca $ \(value_size :: Ptr CSize) -> do
+  whenSuccess (raw_clGetPlatformInfo platform infoid 0 nullPtr value_size) 
+    $ peek value_size
+  
+-- | Get specific information about the OpenCL platform. It returns Nothing if
+-- platform is not a valid platform.
+clGetPlatformInfo :: CLPlatformID -> CLPlatformInfo -> IO String
+clGetPlatformInfo platform infoid = do
+  sval <- getPlatformInfoSize platform infocl
+  allocaArray (fromIntegral sval) $ \(buff :: CString) -> do
+    whenSuccess (raw_clGetPlatformInfo platform infocl sval (castPtr buff) nullPtr)
+      $ peekCString buff
+    where
+      infocl = getCLValue infoid
+
+-- -----------------------------------------------------------------------------
+getNumDevices :: CLPlatformID -> CLDeviceType_ -> IO CLuint
+getNumDevices platform dtype = alloca $ \(num_devices :: Ptr CLuint) -> do
+  whenSuccess (raw_clGetDeviceIDs platform dtype 0 nullPtr num_devices)
+    $ peek num_devices
+
+-- | Obtain the list of devices available on a platform. Returns the list if 
+-- the function is executed successfully. Otherwise it returns the empty list 
+-- if platform is not a valid platform or no OpenCL devices that matched 
+-- device_type were found.
+clGetDeviceIDs :: CLPlatformID -> CLDeviceType -> IO [CLDeviceID]
+clGetDeviceIDs platform dtype = do
+  ndevs <- getNumDevices platform dval
+  allocaArray (fromIntegral ndevs) $ \(devs :: Ptr CLDeviceID) -> do
+    whenSuccess (raw_clGetDeviceIDs platform dval ndevs devs nullPtr)
+      $ peekArray (fromIntegral ndevs) devs
+    where
+      dval = getCLValue dtype
+
+getDeviceInfoSize :: CLDeviceID -> CLDeviceInfo_ -> IO CSize
+getDeviceInfoSize device infoid = alloca $ \(value_size :: Ptr CSize) -> do
+  whenSuccess (raw_clGetDeviceInfo device infoid 0 nullPtr value_size)
+    $ peek value_size
+  
+getDeviceInfoString :: CLDeviceInfo_ -> CLDeviceID -> IO String
+getDeviceInfoString infoid device = do
+  n <- getDeviceInfoSize device infoid
+  allocaArray (fromIntegral n) $ \(buff :: CString) -> do
+    whenSuccess (raw_clGetDeviceInfo device infoid n (castPtr buff) nullPtr)
+      $ peekCString buff
+  
+getDeviceInfoUint :: CLDeviceInfo_ -> CLDeviceID -> IO CLuint
+getDeviceInfoUint infoid device = alloca $ \(dat :: Ptr CLuint) -> do
+  whenSuccess (raw_clGetDeviceInfo device infoid size (castPtr dat) nullPtr)
+    $ peek dat
+    where 
+      size = fromIntegral $ sizeOf (0::CLuint)
+
+getDeviceInfoUlong :: CLDeviceInfo_ -> CLDeviceID -> IO CLulong
+getDeviceInfoUlong infoid device = alloca $ \(dat :: Ptr CLulong) -> do
+  whenSuccess (raw_clGetDeviceInfo device infoid size (castPtr dat) nullPtr)
+    $ peek dat
+    where 
+      size = fromIntegral $ sizeOf (0::CLulong)
+
+getDeviceInfoSizet :: CLDeviceInfo_ -> CLDeviceID -> IO CSize
+getDeviceInfoSizet infoid device = alloca $ \(dat :: Ptr CSize) -> do
+  whenSuccess (raw_clGetDeviceInfo device infoid size (castPtr dat) nullPtr)
+    $ peek dat
+    where 
+      size = fromIntegral $ sizeOf (0::CSize)
+  
+getDeviceInfoBool :: CLDeviceInfo_ -> CLDeviceID -> IO Bool
+getDeviceInfoBool infoid device = alloca $ \(dat :: Ptr CLbool) -> do
+  whenSuccess (raw_clGetDeviceInfo device infoid size (castPtr dat) nullPtr)
+    $ peek dat >>= return . (/=0)
+    where 
+      size = fromIntegral $ sizeOf (0::CLbool)
+  
+getDeviceInfoFP :: CLDeviceInfo_ -> CLDeviceID -> IO [CLDeviceFPConfig]
+getDeviceInfoFP infoid device = do
+  flags <- getDeviceInfoUlong infoid device
+  return . bitmaskToFPConfig $ flags
+
+#c
+enum CLDeviceInfo {
+  cL_DEVICE_ADDRESS_BITS=CL_DEVICE_ADDRESS_BITS,
+  cL_DEVICE_AVAILABLE=CL_DEVICE_AVAILABLE,
+  cL_DEVICE_COMPILER_AVAILABLE=CL_DEVICE_COMPILER_AVAILABLE,
+#ifdef CL_DEVICE_DOUBLE_FP_CONFIG  
+  cL_DEVICE_DOUBLE_FP_CONFIG=CL_DEVICE_DOUBLE_FP_CONFIG,
+#else
+  cL_DEVICE_DOUBLE_FP_CONFIG=0x1032,
+#endif
+  cL_DEVICE_ENDIAN_LITTLE=CL_DEVICE_ENDIAN_LITTLE,
+  cL_DEVICE_ERROR_CORRECTION_SUPPORT=CL_DEVICE_ERROR_CORRECTION_SUPPORT,
+  cL_DEVICE_EXECUTION_CAPABILITIES=CL_DEVICE_EXECUTION_CAPABILITIES,
+  cL_DEVICE_EXTENSIONS=CL_DEVICE_EXTENSIONS,
+  cL_DEVICE_GLOBAL_MEM_CACHE_SIZE=CL_DEVICE_GLOBAL_MEM_CACHE_SIZE,
+  cL_DEVICE_GLOBAL_MEM_CACHE_TYPE=CL_DEVICE_GLOBAL_MEM_CACHE_TYPE,
+  cL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE=CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE,
+  cL_DEVICE_GLOBAL_MEM_SIZE=CL_DEVICE_GLOBAL_MEM_SIZE,
+#ifdef CL_DEVICE_HALF_FP_CONFIG
+  cL_DEVICE_HALF_FP_CONFIG=CL_DEVICE_HALF_FP_CONFIG,
+#else
+  cL_DEVICE_HALF_FP_CONFIG=0x1033,
+#endif
+  cL_DEVICE_IMAGE_SUPPORT=CL_DEVICE_IMAGE_SUPPORT,
+  cL_DEVICE_IMAGE2D_MAX_HEIGHT=CL_DEVICE_IMAGE2D_MAX_HEIGHT,
+  cL_DEVICE_IMAGE2D_MAX_WIDTH=CL_DEVICE_IMAGE2D_MAX_WIDTH,
+  cL_DEVICE_IMAGE3D_MAX_DEPTH=CL_DEVICE_IMAGE3D_MAX_DEPTH,
+  cL_DEVICE_IMAGE3D_MAX_HEIGHT=CL_DEVICE_IMAGE3D_MAX_HEIGHT,
+  cL_DEVICE_IMAGE3D_MAX_WIDTH=CL_DEVICE_IMAGE3D_MAX_WIDTH,
+  cL_DEVICE_LOCAL_MEM_SIZE=CL_DEVICE_LOCAL_MEM_SIZE,
+  cL_DEVICE_LOCAL_MEM_TYPE=CL_DEVICE_LOCAL_MEM_TYPE,
+  cL_DEVICE_MAX_CLOCK_FREQUENCY=CL_DEVICE_MAX_CLOCK_FREQUENCY,
+  cL_DEVICE_MAX_COMPUTE_UNITS=CL_DEVICE_MAX_COMPUTE_UNITS,
+  cL_DEVICE_MAX_CONSTANT_ARGS=CL_DEVICE_MAX_CONSTANT_ARGS,
+  cL_DEVICE_MAX_CONSTANT_BUFFER_SIZE=CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE,
+  cL_DEVICE_MAX_MEM_ALLOC_SIZE=CL_DEVICE_MAX_MEM_ALLOC_SIZE,
+  cL_DEVICE_MAX_PARAMETER_SIZE=CL_DEVICE_MAX_PARAMETER_SIZE,
+  cL_DEVICE_MAX_READ_IMAGE_ARGS=CL_DEVICE_MAX_READ_IMAGE_ARGS,
+  cL_DEVICE_MAX_SAMPLERS=CL_DEVICE_MAX_SAMPLERS,
+  cL_DEVICE_MAX_WORK_GROUP_SIZE=CL_DEVICE_MAX_WORK_GROUP_SIZE,
+  cL_DEVICE_MAX_WORK_ITEM_DIMENSIONS=CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS,
+  cL_DEVICE_MAX_WORK_ITEM_SIZES=CL_DEVICE_MAX_WORK_ITEM_SIZES,
+  cL_DEVICE_MAX_WRITE_IMAGE_ARGS=CL_DEVICE_MAX_WRITE_IMAGE_ARGS,
+  cL_DEVICE_MEM_BASE_ADDR_ALIGN=CL_DEVICE_MEM_BASE_ADDR_ALIGN,
+  cL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE=CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE,
+  cL_DEVICE_NAME=CL_DEVICE_NAME,
+  cL_DEVICE_PLATFORM=CL_DEVICE_PLATFORM,
+  cL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR=CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR,
+  cL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT=CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT,
+  cL_DEVICE_PREFERRED_VECTOR_WIDTH_INT=CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT,
+  cL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG=CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG,
+  cL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT=CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT,
+  cL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE=CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE,
+  cL_DEVICE_PROFILE=CL_DEVICE_PROFILE,
+  cL_DEVICE_PROFILING_TIMER_RESOLUTION=CL_DEVICE_PROFILING_TIMER_RESOLUTION,
+  cL_DEVICE_QUEUE_PROPERTIES=CL_DEVICE_QUEUE_PROPERTIES,
+  cL_DEVICE_SINGLE_FP_CONFIG=CL_DEVICE_SINGLE_FP_CONFIG,
+  cL_DEVICE_TYPE=CL_DEVICE_TYPE,
+  cL_DEVICE_VENDOR=CL_DEVICE_VENDOR,
+  cL_DEVICE_VENDOR_ID=CL_DEVICE_VENDOR_ID,
+  cL_DEVICE_VERSION=CL_DEVICE_VERSION,
+  cL_DRIVER_VERSION=CL_DRIVER_VERSION,
+  };
+#endc
+{#enum CLDeviceInfo {upcaseFirstLetter} #}
+
+-- | The default compute device address space size specified as an unsigned 
+-- integer value in bits. Currently supported values are 32 or 64 bits.
+--
+-- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_ADDRESS_BITS'.
+clGetDeviceAddressBits :: CLDeviceID -> IO CLuint
+clGetDeviceAddressBits = getDeviceInfoUint . getCLValue $ CL_DEVICE_ADDRESS_BITS
+
+-- | Is 'True' if the device is available and 'False' if the device is not 
+-- available.
+--
+-- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_AVAILABLE'.
+clGetDeviceAvailable :: CLDeviceID -> IO Bool
+clGetDeviceAvailable = getDeviceInfoBool . getCLValue $ CL_DEVICE_AVAILABLE
+
+-- | Is 'False' if the implementation does not have a compiler available to 
+-- compile the program source. Is 'True' if the compiler is available. This can 
+-- be 'False' for the embededed platform profile only.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_COMPILER_AVAILABLE'.
+clGetDeviceCompilerAvailable :: CLDeviceID -> IO Bool
+clGetDeviceCompilerAvailable = getDeviceInfoBool . getCLValue $ CL_DEVICE_COMPILER_AVAILABLE
+
+-- | Describes the OPTIONAL double precision floating-point capability of the 
+-- OpenCL device. This is a bit-field that describes one or more of the 
+-- 'CLDeviceFPConfig' values.
+-- The mandated minimum double precision floating-point capability is 
+-- 'CL_FP_FMA' | 'CL_FP_ROUND_TO_NEAREST' | 'CL_FP_ROUND_TO_ZERO' | 
+-- 'CL_FP_ROUND_TO_INF' | 'CL_FP_INF_NAN' | 'CL_FP_DENORM'.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_DOUBLE_FP_CONFIG'.
+clGetDeviceDoubleFPConfig :: CLDeviceID -> IO [CLDeviceFPConfig]
+clGetDeviceDoubleFPConfig = getDeviceInfoFP . getCLValue $ CL_DEVICE_DOUBLE_FP_CONFIG
+
+-- | Is 'True' if the OpenCL device is a little endian device and 'False' 
+-- otherwise.
+--
+-- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_ENDIAN_LITTLE'.
+clGetDeviceEndianLittle :: CLDeviceID -> IO Bool
+clGetDeviceEndianLittle = getDeviceInfoBool . getCLValue $ CL_DEVICE_ENDIAN_LITTLE
+
+-- | Is 'True' if the device implements error correction for the memories, 
+-- caches, registers etc. in the device. Is 'False' if the device does not 
+-- implement error correction. This can be a requirement for certain clients of 
+-- OpenCL.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_ERROR_CORRECTION_SUPPORT'.
+clGetDeviceErrorCorrectionSupport :: CLDeviceID -> IO Bool
+clGetDeviceErrorCorrectionSupport = getDeviceInfoBool . getCLValue $ CL_DEVICE_ERROR_CORRECTION_SUPPORT
+
+-- | Describes the execution capabilities of the device. This is a list that 
+-- describes one or more of the 'CLDeviceExecCapability' values.
+-- The mandated minimum capability is 'CL_EXEC_KERNEL'.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_EXECUTION_CAPABILITIES'.
+clGetDeviceExecutionCapabilities :: CLDeviceID -> IO [CLDeviceExecCapability]
+clGetDeviceExecutionCapabilities device = do
+  flags <- getDeviceInfoUlong (getCLValue CL_DEVICE_EXECUTION_CAPABILITIES) device
+  return . bitmaskToExecCapability $ flags
+
+-- | Returns a space separated list of extension names (the extension names 
+-- themselves do not contain any spaces). The list of extension names returned 
+-- currently can include one or more of the following approved extension names:
+--
+-- * cl_khr_fp64
+--
+-- * cl_khr_select_fprounding_mode
+--
+-- * cl_khr_global_int32_base_atomics
+--
+-- * cl_khr_global_int32_extended_atomics
+--
+-- * cl_khr_local_int32_base_atomics
+--
+-- * cl_khr_local_int32_extended_atomics
+--
+-- * cl_khr_int64_base_atomics
+--
+-- * cl_khr_int64_extended_atomics
+--
+-- * cl_khr_3d_image_writes
+--
+-- * cl_khr_byte_addressable_store
+--
+-- * cl_khr_fp16
+--
+-- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_EXTENSIONS'.
+clGetDeviceExtensions :: CLDeviceID -> IO String
+clGetDeviceExtensions = getDeviceInfoString . getCLValue $ CL_DEVICE_EXTENSIONS
+
+-- | Size of global memory cache in bytes.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_GLOBAL_MEM_CACHE_SIZE'.
+clGetDeviceGlobalMemCacheSize :: CLDeviceID -> IO CLulong
+clGetDeviceGlobalMemCacheSize = getDeviceInfoUlong . getCLValue $ CL_DEVICE_GLOBAL_MEM_CACHE_SIZE
+
+-- | Type of global memory cache supported. Valid values are: 'CL_NONE', 
+-- 'CL_READ_ONLY_CACHE', and 'CL_READ_WRITE_CACHE'.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_GLOBAL_MEM_CACHE_TYPE'.
+clGetDeviceGlobalMemCacheType :: CLDeviceID -> IO CLDeviceMemCacheType
+clGetDeviceGlobalMemCacheType device = do
+  typ <- getDeviceInfoUint (getCLValue CL_DEVICE_GLOBAL_MEM_CACHE_TYPE) device 
+  return . getEnumCL $ typ
+
+-- | Size of global memory cache line in bytes.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE'.
+clGetDeviceGlobalMemCachelineSize :: CLDeviceID -> IO CLuint
+clGetDeviceGlobalMemCachelineSize = getDeviceInfoUint . getCLValue $ CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE
+
+-- | Size of global device memory in bytes.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_GLOBAL_MEM_SIZE'.
+clGetDeviceGlobalMemSize :: CLDeviceID -> IO CLulong
+clGetDeviceGlobalMemSize = getDeviceInfoUlong . getCLValue $ CL_DEVICE_GLOBAL_MEM_SIZE
+
+-- | Describes the OPTIONAL half precision floating-point capability of the 
+-- OpenCL device. This is a bit-field that describes one or more of the 
+-- 'CLDeviceFPConfig' values.
+-- The required minimum half precision floating-point capability as implemented 
+-- by this extension is 'CL_FP_ROUND_TO_ZERO' | 'CL_FP_ROUND_TO_INF' | 
+-- 'CL_FP_INF_NAN'.
+--
+-- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_HALF_FP_CONFIG'.
+clGetDeviceHalfFPConfig :: CLDeviceID -> IO [CLDeviceFPConfig]
+clGetDeviceHalfFPConfig = getDeviceInfoFP . getCLValue $ CL_DEVICE_HALF_FP_CONFIG
+
+-- | Is 'True' if images are supported by the OpenCL device and 'False' otherwise.
+--
+-- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_IMAGE_SUPPORT'.
+clGetDeviceImageSupport :: CLDeviceID -> IO Bool
+clGetDeviceImageSupport = getDeviceInfoBool . getCLValue $ CL_DEVICE_IMAGE_SUPPORT
+
+-- | Max height of 2D image in pixels. The minimum value is 8192 if
+-- 'clGetDeviceImageSupport' is 'True'.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_IMAGE2D_MAX_HEIGHT'.
+clGetDeviceImage2DMaxHeight :: CLDeviceID -> IO CSize
+clGetDeviceImage2DMaxHeight = getDeviceInfoSizet . getCLValue $ CL_DEVICE_IMAGE2D_MAX_HEIGHT
+
+-- | Max width of 2D image in pixels. The minimum value is 8192 if
+-- 'clGetDeviceImageSupport' is 'True'.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_IMAGE2D_MAX_WIDTH'.
+clGetDeviceImage2DMaxWidth :: CLDeviceID -> IO CSize
+clGetDeviceImage2DMaxWidth = getDeviceInfoSizet . getCLValue $ CL_DEVICE_IMAGE2D_MAX_WIDTH
+
+-- | Max depth of 3D image in pixels. The minimum value is 2048 if 
+-- 'clGetDeviceImageSupport' is 'True'.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_IMAGE3D_MAX_DEPTH'.
+clGetDeviceImage3DMaxDepth :: CLDeviceID -> IO CSize
+clGetDeviceImage3DMaxDepth = getDeviceInfoSizet . getCLValue $ CL_DEVICE_IMAGE3D_MAX_DEPTH
+
+-- | Max height of 3D image in pixels. The minimum value is 2048 if 
+-- 'clGetDeviceImageSupport' is 'True'.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_IMAGE3D_MAX_HEIGHT'.
+clGetDeviceImage3DMaxHeight :: CLDeviceID -> IO CSize
+clGetDeviceImage3DMaxHeight = getDeviceInfoSizet . getCLValue $ CL_DEVICE_IMAGE3D_MAX_HEIGHT
+
+-- | Max width of 3D image in pixels. The minimum value is 2048 if 
+-- 'clGetDeviceImageSupport' is 'True'.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_IMAGE3D_MAX_WIDTH'.
+clGetDeviceImage3DMaxWidth :: CLDeviceID -> IO CSize
+clGetDeviceImage3DMaxWidth = getDeviceInfoSizet . getCLValue $ CL_DEVICE_IMAGE3D_MAX_WIDTH
+
+-- | Size of local memory arena in bytes. The minimum value is 16 KB.
+--
+-- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_LOCAL_MEM_SIZE'.
+clGetDeviceLocalMemSize :: CLDeviceID -> IO CLulong
+clGetDeviceLocalMemSize = getDeviceInfoUlong . getCLValue $ CL_DEVICE_LOCAL_MEM_SIZE
+
+-- | Type of local memory supported. This can be set to 'CL_LOCAL' implying 
+-- dedicated local memory storage such as SRAM, or 'CL_GLOBAL'.
+--
+-- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_LOCAL_MEM_TYPE'.
+clGetDeviceLocalMemType :: CLDeviceID -> IO CLDeviceLocalMemType
+clGetDeviceLocalMemType device = do
+  typ <- getDeviceInfoUint (getCLValue CL_DEVICE_LOCAL_MEM_TYPE) device 
+  return . getEnumCL $ typ
+
+-- | Maximum configured clock frequency of the device in MHz.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_MAX_CLOCK_FREQUENCY'.
+clGetDeviceMaxClockFrequency :: CLDeviceID -> IO CLuint
+clGetDeviceMaxClockFrequency = getDeviceInfoUint . getCLValue $ CL_DEVICE_MAX_CLOCK_FREQUENCY
+
+-- | The number of parallel compute cores on the OpenCL device. The minimum 
+-- value is 1.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_MAX_COMPUTE_UNITS'.
+clGetDeviceMaxComputeUnits :: CLDeviceID -> IO CLuint
+clGetDeviceMaxComputeUnits = getDeviceInfoUint . getCLValue $ CL_DEVICE_MAX_COMPUTE_UNITS
+
+-- | Max number of arguments declared with the __constant qualifier in a kernel. 
+-- The minimum value is 8.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_MAX_CONSTANT_ARGS'.
+clGetDeviceMaxConstantArgs :: CLDeviceID -> IO CLuint
+clGetDeviceMaxConstantArgs = getDeviceInfoUint . getCLValue $ CL_DEVICE_MAX_CONSTANT_ARGS
+
+-- | Max size in bytes of a constant buffer allocation. The minimum value is 
+-- 64 KB.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE'.
+clGetDeviceMaxConstantBufferSize :: CLDeviceID -> IO CLulong
+clGetDeviceMaxConstantBufferSize = getDeviceInfoUlong . getCLValue $ CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE
+
+-- | Max size of memory object allocation in bytes. The minimum value is max 
+-- (1/4th of 'clGetDeviceGlobalMemSize', 128*1024*1024)
+--
+-- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_MAX_MEM_ALLOC_SIZE'.
+clGetDeviceMaxMemAllocSize :: CLDeviceID -> IO CLulong
+clGetDeviceMaxMemAllocSize = getDeviceInfoUlong . getCLValue $ CL_DEVICE_MAX_MEM_ALLOC_SIZE
+
+-- | Max size in bytes of the arguments that can be passed to a kernel. The 
+-- minimum value is 256.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_MAX_PARAMETER_SIZE'.
+clGetDeviceMaxParameterSize :: CLDeviceID -> IO CSize
+clGetDeviceMaxParameterSize = getDeviceInfoSizet . getCLValue $ CL_DEVICE_MAX_PARAMETER_SIZE
+
+-- | Max number of simultaneous image objects that can be read by a kernel. The 
+-- minimum value is 128 if 'clGetDeviceImageSupport' is 'True'.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_MAX_READ_IMAGE_ARGS'.
+clGetDeviceMaxReadImageArgs :: CLDeviceID -> IO CLuint
+clGetDeviceMaxReadImageArgs = getDeviceInfoUint . getCLValue $ CL_DEVICE_MAX_READ_IMAGE_ARGS
+
+-- | Maximum number of samplers that can be used in a kernel. The minimum value 
+-- is 16 if 'clGetDeviceImageSupport' is 'True'. (Also see sampler type.)
+--
+-- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_MAX_SAMPLERS'.
+clGetDeviceMaxSamplers :: CLDeviceID -> IO CLuint
+clGetDeviceMaxSamplers = getDeviceInfoUint . getCLValue $ CL_DEVICE_MAX_SAMPLERS
+
+-- | Maximum number of work-items in a work-group executing a kernel using the 
+-- data parallel execution model. (Refer to 'clEnqueueNDRangeKernel'). The 
+-- minimum value is 1.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_MAX_WORK_GROUP_SIZE'.
+clGetDeviceMaxWorkGroupSize :: CLDeviceID -> IO CSize
+clGetDeviceMaxWorkGroupSize = getDeviceInfoSizet . getCLValue $ CL_DEVICE_MAX_WORK_GROUP_SIZE
+
+-- | Maximum dimensions that specify the global and local work-item IDs used by 
+-- the data parallel execution model. (Refer to 'clEnqueueNDRangeKernel'). 
+-- The minimum value is 3.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS'.
+clGetDeviceMaxWorkItemDimensions :: CLDeviceID -> IO CLuint
+clGetDeviceMaxWorkItemDimensions = getDeviceInfoUint . getCLValue $ CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS
+
+-- | Maximum number of work-items that can be specified in each dimension of the 
+-- work-group to 'clEnqueueNDRangeKernel'.
+-- Returns n entries, where n is the value returned by the query for 
+-- clDeviceMaxWorkItemDimensions. The minimum value is (1, 1, 1).
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_MAX_WORK_ITEM_SIZES'.
+clGetDeviceMaxWorkItemSizes :: CLDeviceID -> IO [CSize]
+clGetDeviceMaxWorkItemSizes device = do
+  n <- clGetDeviceMaxWorkItemDimensions device
+  allocaArray (fromIntegral n) $ \(buff :: Ptr CSize) -> do
+    whenSuccess (raw_clGetDeviceInfo device infoid (size n) (castPtr buff) nullPtr)
+      $ peekArray (fromIntegral n) buff
+    where
+      infoid = getCLValue CL_DEVICE_MAX_WORK_ITEM_SIZES
+      size n = fromIntegral $ (fromIntegral n) * (sizeOf (0::CSize))
+
+-- | Max number of simultaneous image objects that can be written to by a 
+-- kernel. The minimum value is 8 if 'clGetDeviceImageSupport' is 'True'.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_MAX_WRITE_IMAGE_ARGS'.
+clGetDeviceMaxWriteImageArgs :: CLDeviceID -> IO CLuint
+clGetDeviceMaxWriteImageArgs = getDeviceInfoUint . getCLValue $ CL_DEVICE_MAX_WRITE_IMAGE_ARGS
+
+-- | Describes the alignment in bits of the base address of any allocated 
+-- memory object.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_MEM_BASE_ADDR_ALIGN'.
+clGetDeviceMemBaseAddrAlign :: CLDeviceID -> IO CLuint
+clGetDeviceMemBaseAddrAlign = getDeviceInfoUint . getCLValue $ CL_DEVICE_MEM_BASE_ADDR_ALIGN
+
+-- | The smallest alignment in bytes which can be used for any data type.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE'.
+clGetDeviceMinDataTypeAlignSize :: CLDeviceID -> IO CLuint
+clGetDeviceMinDataTypeAlignSize = getDeviceInfoUint . getCLValue $ CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE
+
+-- | Device name string.
+--
+-- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_NAME'.
+clGetDeviceName :: CLDeviceID -> IO String
+clGetDeviceName = getDeviceInfoString . getCLValue $ CL_DEVICE_NAME
+
+-- | The platform associated with this device.
+--
+-- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_PLATFORM'.
+clGetDevicePlatform :: CLDeviceID -> IO CLPlatformID
+clGetDevicePlatform device = alloca $ \(dat :: Ptr CLPlatformID) -> do
+  whenSuccess (raw_clGetDeviceInfo device infoid size (castPtr dat) nullPtr)
+    $ peek dat
+    where 
+      infoid = getCLValue CL_DEVICE_PLATFORM
+      size = fromIntegral $ sizeOf (nullPtr :: CLPlatformID)
+
+-- | Preferred native vector width size for built-in char types that can be put 
+-- into vectors. The vector width is defined as the number of scalar elements 
+-- that can be stored in the vector.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR'.
+clGetDevicePreferredVectorWidthChar :: CLDeviceID -> IO CLuint
+clGetDevicePreferredVectorWidthChar = getDeviceInfoUint . getCLValue $ CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR
+
+-- | Preferred native vector width size for built-in short types that can be put 
+-- into vectors. The vector width is defined as the number of scalar elements 
+-- that can be stored in the vector.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT'.
+clGetDevicePreferredVectorWidthShort :: CLDeviceID -> IO CLuint
+clGetDevicePreferredVectorWidthShort = getDeviceInfoUint . getCLValue $ CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT
+
+-- | Preferred native vector width size for built-in int types that can be put 
+-- into vectors. The vector width is defined as the number of scalar elements 
+-- that can be stored in the vector.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT'.
+clGetDevicePreferredVectorWidthInt :: CLDeviceID -> IO CLuint
+clGetDevicePreferredVectorWidthInt = getDeviceInfoUint . getCLValue $ CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT
+
+-- | Preferred native vector width size for built-in long types that can be put 
+-- into vectors. The vector width is defined as the number of scalar elements 
+-- that can be stored in the vector.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG'.
+clGetDevicePreferredVectorWidthLong :: CLDeviceID -> IO CLuint
+clGetDevicePreferredVectorWidthLong = getDeviceInfoUint . getCLValue $ CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG
+
+-- | Preferred native vector width size for built-in float types that can be put 
+-- into vectors. The vector width is defined as the number of scalar elements 
+-- that can be stored in the vector.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT'.
+clGetDevicePreferredVectorWidthFloat :: CLDeviceID -> IO CLuint
+clGetDevicePreferredVectorWidthFloat = getDeviceInfoUint . getCLValue $ CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT
+
+-- | Preferred native vector width size for built-in double types that can be put 
+-- into vectors. The vector width is defined as the number of scalar elements 
+-- that can be stored in the vector.
+-- | If the cl_khr_fp64 extension is not supported, 
+-- 'clGetDevicePreferredVectorWidthDouble' must return 0.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE'.
+clGetDevicePreferredVectorWidthDouble :: CLDeviceID -> IO CLuint
+clGetDevicePreferredVectorWidthDouble = getDeviceInfoUint . getCLValue $ CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE
+
+-- | OpenCL profile string. Returns the profile name supported by the device 
+-- (see note). The profile name returned can be one of the following strings:
+-- 
+-- * FULL_PROFILE - if the device supports the OpenCL specification 
+-- (functionality defined as part of the core specification and does not require 
+-- any extensions to be supported).
+-- 
+-- * EMBEDDED_PROFILE - if the device supports the OpenCL embedded profile.
+--
+-- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_PROFILE'.
+clGetDeviceProfile :: CLDeviceID -> IO String
+clGetDeviceProfile = getDeviceInfoString . getCLValue $ CL_DEVICE_PROFILE
+
+-- | Describes the resolution of device timer. This is measured in nanoseconds.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_PROFILING_TIMER_RESOLUTION'.
+clGetDeviceProfilingTimerResolution :: CLDeviceID -> IO CSize
+clGetDeviceProfilingTimerResolution = getDeviceInfoSizet . getCLValue $ CL_DEVICE_PROFILING_TIMER_RESOLUTION
+
+-- | Describes the command-queue properties supported by the device. This is a 
+-- list that describes one or more of the CLCommandQueueProperty values.
+-- These properties are described in the table for 'clCreateCommandQueue'. 
+-- The mandated minimum capability is 'CL_QUEUE_PROFILING_ENABLE'.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_QUEUE_PROPERTIES'.
+clGetDeviceQueueProperties :: CLDeviceID -> IO [CLCommandQueueProperty]
+clGetDeviceQueueProperties device = do
+  flags <- getDeviceInfoUlong (getCLValue CL_DEVICE_QUEUE_PROPERTIES) device
+  return . bitmaskToCommandQueueProperties $ flags
+    
+-- | Describes single precision floating-point capability of the device. This is 
+-- a bit-field that describes one or more of the 'CLDeviceFPConfig' values.
+-- The mandated minimum floating-point capability is 'CL_FP_ROUND_TO_NEAREST' | 
+-- 'CL_FP_INF_NAN'.
+--
+-- This function execute OpenCL clGetDeviceInfo with
+-- 'CL_DEVICE_SINGLE_FP_CONFIG'.
+clGetDeviceSingleFPConfig :: CLDeviceID -> IO [CLDeviceFPConfig]
+clGetDeviceSingleFPConfig = getDeviceInfoFP . getCLValue $ CL_DEVICE_SINGLE_FP_CONFIG
+
+-- | The OpenCL device type. Currently supported values are one of or a 
+-- combination of: 'CL_DEVICE_TYPE_CPU', 'CL_DEVICE_TYPE_GPU', 
+-- 'CL_DEVICE_TYPE_ACCELERATOR', or 'CL_DEVICE_TYPE_DEFAULT'.
+--
+-- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_TYPE'.
+clGetDeviceType :: CLDeviceID -> IO [CLDeviceType]
+clGetDeviceType device = do
+  flags <- getDeviceInfoUlong (getCLValue CL_DEVICE_TYPE) device
+  return . bitmaskToDeviceTypes $ flags
+
+-- | Vendor name string.
+--
+-- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_VENDOR'.
+clGetDeviceVendor :: CLDeviceID -> IO String
+clGetDeviceVendor = getDeviceInfoString . getCLValue $ CL_DEVICE_VENDOR
+
+-- | A unique device vendor identifier. An example of a unique device identifier 
+-- could be the PCIe ID.
+--
+-- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_VENDOR_ID'.
+clGetDeviceVendorID :: CLDeviceID -> IO CLuint
+clGetDeviceVendorID = getDeviceInfoUint . getCLValue $ CL_DEVICE_VENDOR_ID
+
+-- | OpenCL version string. Returns the OpenCL version supported by the device. 
+-- This version string has the following format:
+-- /OpenCL major_version.minor_version vendor-specific information/
+-- The major_version.minor_version value returned will be 1.0.
+--
+-- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_VERSION'.
+clGetDeviceVersion :: CLDeviceID -> IO String
+clGetDeviceVersion = getDeviceInfoString . getCLValue $ CL_DEVICE_VERSION
+
+-- | OpenCL software driver version string in the form major_number.minor_number.
+--
+-- This function execute OpenCL clGetDeviceInfo with 'CL_DRIVER_VERSION'.
+clGetDeviceDriverVersion :: CLDeviceID -> IO String
+clGetDeviceDriverVersion = getDeviceInfoString . getCLValue $ CL_DRIVER_VERSION
+
+-- -----------------------------------------------------------------------------
diff --git a/src/Control/Parallel/OpenCL/Types.chs b/src/Control/Parallel/OpenCL/Types.chs
new file mode 100644
--- /dev/null
+++ b/src/Control/Parallel/OpenCL/Types.chs
@@ -0,0 +1,731 @@
+{- Copyright (c) 2011 Luis Cabellos,
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of  nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-}
+{-# LANGUAGE DeriveDataTypeable #-}
+module Control.Parallel.OpenCL.Types( 
+  -- * Symple CL Types
+  CLbool, CLint, CLuint, CLulong, CLProgram, CLEvent, CLMem, CLPlatformID, 
+  CLDeviceID, CLContext, CLCommandQueue, CLPlatformInfo_, CLDeviceType_, 
+  CLDeviceInfo_, CLContextInfo_, CLContextProperty_, CLCommandQueueInfo_, 
+  CLEventInfo_, CLProfilingInfo_, CLCommandType_, CLCommandQueueProperty_, 
+  CLMemFlags_, CLMemObjectType_, CLMemInfo_, CLImageInfo_, CLMapFlags_,
+  CLProgramInfo_, CLBuildStatus_,CLKernel, CLProgramBuildInfo_, CLKernelInfo_,
+  CLKernelWorkGroupInfo_, CLDeviceLocalMemType_, CLDeviceMemCacheType_,
+  CLSampler, CLFilterMode_, CLSamplerInfo_, CLAddressingMode_,
+  -- * High Level Types
+  CLError(..), CLDeviceFPConfig(..), CLDeviceMemCacheType(..), 
+  CLDeviceExecCapability(..), CLDeviceLocalMemType(..), CLDeviceType(..), 
+  CLCommandQueueProperty(..), CLCommandType(..),  CLCommandExecutionStatus(..), 
+  CLProfilingInfo(..), CLPlatformInfo(..), CLMemFlag(..), CLMemObjectType(..),
+  CLBuildStatus(..), CLAddressingMode(..), CLFilterMode(..), CLMapFlag(..),
+  -- * Functions
+  wrapPError, wrapCheckSuccess, wrapGetInfo, whenSuccess, getCLValue, 
+  throwCLError, getEnumCL, bitmaskToFlags, getCommandExecutionStatus, 
+  bitmaskToDeviceTypes, bitmaskFromFlags, bitmaskToCommandQueueProperties, 
+  bitmaskToFPConfig, bitmaskToExecCapability, bitmaskToMemFlags )
+       where
+
+-- -----------------------------------------------------------------------------
+import Foreign
+import Foreign.C.Types
+import Data.List( foldl' )
+import Data.Typeable( Typeable(..) )
+import Control.Applicative( (<$>) )
+import Control.Exception( Exception(..), throwIO )
+
+#ifdef __APPLE__
+#include <OpenCL/opencl.h>
+#else
+#include <CL/cl.h>
+#endif
+
+-- -----------------------------------------------------------------------------
+
+type CLPlatformID = {#type cl_platform_id#}
+type CLDeviceID = {#type cl_device_id#}
+type CLContext = {#type cl_context#}
+type CLCommandQueue = {#type cl_command_queue#}
+type CLMem = {#type cl_mem#}
+type CLEvent = {#type cl_event#}
+type CLProgram = {#type cl_program#}
+type CLKernel = {#type cl_kernel#}
+type CLSampler = {#type cl_sampler#}
+
+type CLint = {#type cl_int#}
+type CLuint = {#type cl_uint#}
+type CLulong = {#type cl_ulong#}
+type CLbool = {#type cl_bool#}
+
+type CLPlatformInfo_ = {#type cl_platform_info#}
+type CLDeviceType_ = {#type cl_device_type#}
+type CLDeviceInfo_ = {#type cl_device_info#}
+type CLDeviceFPConfig_ = {#type cl_device_fp_config#}
+type CLDeviceMemCacheType_ = {#type cl_device_mem_cache_type#}
+type CLDeviceLocalMemType_ = {#type cl_device_local_mem_type#}
+type CLDeviceExecCapability_ = {#type cl_device_exec_capabilities#}
+type CLContextInfo_ = {#type cl_context_info#}
+type CLContextProperty_ = {#type cl_context_properties#}
+type CLCommandQueueInfo_ = {#type cl_command_queue_info#}
+type CLCommandQueueProperty_ = {#type cl_command_queue_properties#}
+type CLEventInfo_ = {#type cl_event_info#}
+type CLProfilingInfo_ = {#type cl_profiling_info#}
+type CLCommandType_ = {#type cl_command_type#}
+type CLMemFlags_ = {#type cl_mem_flags#}
+type CLMemObjectType_ = {#type cl_mem_object_type#}
+type CLMemInfo_ = {#type cl_mem_info#}
+type CLImageInfo_ = {#type cl_image_info#}
+type CLMapFlags_ = {#type cl_map_flags#}
+type CLProgramInfo_ = {#type cl_program_info#}
+type CLProgramBuildInfo_ = {#type cl_program_build_info#}
+type CLBuildStatus_ = {#type cl_build_status#}
+type CLKernelInfo_ = {#type cl_kernel_info#}
+type CLKernelWorkGroupInfo_ = {#type cl_kernel_work_group_info#}
+type CLFilterMode_ = {#type cl_filter_mode#}
+type CLSamplerInfo_ = {#type cl_sampler_info#}
+type CLAddressingMode_ = {#type cl_addressing_mode#}
+
+-- -----------------------------------------------------------------------------
+#c
+enum CLError {
+  cL_BUILD_PROGRAM_FAILURE=CL_BUILD_PROGRAM_FAILURE,
+  cL_COMPILER_NOT_AVAILABLE=CL_COMPILER_NOT_AVAILABLE,
+  cL_DEVICE_NOT_AVAILABLE=CL_DEVICE_NOT_AVAILABLE,
+  cL_DEVICE_NOT_FOUND=CL_DEVICE_NOT_FOUND,
+  cL_IMAGE_FORMAT_MISMATCH=CL_IMAGE_FORMAT_MISMATCH,
+  cL_IMAGE_FORMAT_NOT_SUPPORTED=CL_IMAGE_FORMAT_NOT_SUPPORTED,
+  cL_INVALID_ARG_INDEX=CL_INVALID_ARG_INDEX,
+  cL_INVALID_ARG_SIZE=CL_INVALID_ARG_SIZE,
+  cL_INVALID_ARG_VALUE=CL_INVALID_ARG_VALUE,
+  cL_INVALID_BINARY=CL_INVALID_BINARY,
+  cL_INVALID_BUFFER_SIZE=CL_INVALID_BUFFER_SIZE,
+  cL_INVALID_BUILD_OPTIONS=CL_INVALID_BUILD_OPTIONS,
+  cL_INVALID_COMMAND_QUEUE=CL_INVALID_COMMAND_QUEUE,
+  cL_INVALID_CONTEXT=CL_INVALID_CONTEXT,
+  cL_INVALID_DEVICE=CL_INVALID_DEVICE,
+  cL_INVALID_DEVICE_TYPE=CL_INVALID_DEVICE_TYPE,
+  cL_INVALID_EVENT=CL_INVALID_EVENT,
+  cL_INVALID_EVENT_WAIT_LIST=CL_INVALID_EVENT_WAIT_LIST,
+  cL_INVALID_GL_OBJECT=CL_INVALID_GL_OBJECT,
+  cL_INVALID_GLOBAL_OFFSET=CL_INVALID_GLOBAL_OFFSET,
+  cL_INVALID_HOST_PTR=CL_INVALID_HOST_PTR,
+  cL_INVALID_IMAGE_FORMAT_DESCRIPTOR=CL_INVALID_IMAGE_FORMAT_DESCRIPTOR,
+  cL_INVALID_IMAGE_SIZE=CL_INVALID_IMAGE_SIZE,
+  cL_INVALID_KERNEL_NAME=CL_INVALID_KERNEL_NAME,
+  cL_INVALID_KERNEL=CL_INVALID_KERNEL,
+  cL_INVALID_KERNEL_ARGS=CL_INVALID_KERNEL_ARGS,
+  cL_INVALID_KERNEL_DEFINITION=CL_INVALID_KERNEL_DEFINITION,
+  cL_INVALID_MEM_OBJECT=CL_INVALID_MEM_OBJECT,
+  cL_INVALID_OPERATION=CL_INVALID_OPERATION,
+  cL_INVALID_PLATFORM=CL_INVALID_PLATFORM,
+  cL_INVALID_PROGRAM=CL_INVALID_PROGRAM,
+  cL_INVALID_PROGRAM_EXECUTABLE=CL_INVALID_PROGRAM_EXECUTABLE,
+  cL_INVALID_QUEUE_PROPERTIES=CL_INVALID_QUEUE_PROPERTIES,
+  cL_INVALID_SAMPLER=CL_INVALID_SAMPLER,
+  cL_INVALID_VALUE=CL_INVALID_VALUE,
+  cL_INVALID_WORK_DIMENSION=CL_INVALID_WORK_DIMENSION,
+  cL_INVALID_WORK_GROUP_SIZE=CL_INVALID_WORK_GROUP_SIZE,
+  cL_INVALID_WORK_ITEM_SIZE=CL_INVALID_WORK_ITEM_SIZE,
+  cL_MAP_FAILURE=CL_MAP_FAILURE,
+  cL_MEM_OBJECT_ALLOCATION_FAILURE=CL_MEM_OBJECT_ALLOCATION_FAILURE,
+  cL_MEM_COPY_OVERLAP=CL_MEM_COPY_OVERLAP,
+  cL_OUT_OF_HOST_MEMORY=CL_OUT_OF_HOST_MEMORY,
+  cL_OUT_OF_RESOURCES=CL_OUT_OF_RESOURCES,
+  cL_PROFILING_INFO_NOT_AVAILABLE=CL_PROFILING_INFO_NOT_AVAILABLE,
+  cL_SUCCESS=CL_SUCCESS
+  };
+#endc
+
+{-| 
+ * 'CL_BUILD_PROGRAM_FAILURE', Returned if there is a failure to build the
+program executable.
+
+ * 'CL_COMPILER_NOT_AVAILABLE', Returned if the parameter program is created with
+'clCreateProgramWithSource' and a compiler is not available. For example
+'clDeviceCompilerAvalaible' is set to 'False'.
+
+ * 'CL_DEVICE_NOT_AVAILABLE', Returned if the specified device is not currently
+available.
+
+ * 'CL_DEVICE_NOT_FOUND', Returned if no OpenCL devices that match the specified
+devices were found.
+
+ * 'CL_IMAGE_FORMAT_MISMATCH', Returned if the specified source and destination
+images are not valid image objects.
+
+ * 'CL_IMAGE_FORMAT_NOT_SUPPORTED', Returned if the specified image format is not
+supported.
+
+ * 'CL_INVALID_ARG_INDEX', Returned if an invalid argument index is specified.
+
+ * 'CL_INVALID_ARG_SIZE', Returned if argument size specified (arg_size) does not
+match the size of the data type for an argument that is not a memory object, or
+if the argument is a memory object and arg_size != sizeof(cl_mem) or if arg_size
+is zero and the argument is declared with the __local qualifier or if the
+argument is a sampler and arg_size != sizeof(cl_sampler).
+
+ * 'CL_INVALID_ARG_VALUE', Returned if the argument value specified is NULL for
+an argument that is not declared with the __local qualifier or vice-versa.
+
+ * 'CL_INVALID_BINARY', Returned if the program binary is not a valid binary for
+the specified device.
+
+ * 'CL_INVALID_BUFFER_SIZE', Returned if the value of the parameter size is 0 or
+is greater than 'clDeviceMaxMemAllocSize' for all devices specified in the
+parameter context.
+
+ * 'CL_INVALID_BUILD_OPTIONS', Returned if the specified build options are
+invalid.
+
+ * 'CL_INVALID_COMMAND_QUEUE', Returned if the specified command-queue is not a
+valid command-queue.
+
+ * 'CL_INVALID_CONTEXT', Returned if the specified context is not a valid OpenCL
+context, or the context associated with certain parameters are not the same.
+
+ * 'CL_INVALID_DEVICE', Returned if the device or devices specified are not
+valid.
+
+ * 'CL_INVALID_DEVICE_TYPE', Returned if device type specified is not valid.
+
+ * 'CL_INVALID_EVENT', Returned if the event objects specified are not valid.
+
+ * 'CL_INVALID_EVENT_WAIT_LIST', Returned if event_wait_list is NULL and
+num_events_in_wait_list > 0, or event_wait_list_list is not NULL and
+num_events_in_wait_list is 0, or specified event objects are not valid events.
+
+ * 'CL_INVALID_GL_OBJECT', Returned if obj is not a vaild GL object or is a GL
+object but does not have an existing data store.
+
+ * 'CL_INVALID_GLOBAL_OFFSET', Returned if global_work_offset is not NULL.
+
+ * 'CL_INVALID_HOST_PTR', Returned if host_ptr is NULL and 'CL_MEM_USE_HOST_PTR'
+or 'CL_MEM_COPY_HOST_PTR' are set in flags or if host_ptr is not NULL but
+'CL_MEM_COPY_HOST_PTR' or 'CL_MEM_USE_HOST_PTR' are not set in flags.
+
+ * 'CL_INVALID_IMAGE_FORMAT_DESCRIPTOR', Returned if the image format specified
+is not valid or is NULL or does not map to a supported OpenCL image format.
+
+ * 'CL_INVALID_IMAGE_SIZE', Returned if the specified image width or height are
+invalid or if the image row pitch and image slice pitch do not follow the rules.
+
+ * 'CL_INVALID_KERNEL_NAME', Returned if the specified kernel name is not found
+in program.
+
+ * 'CL_INVALID_KERNEL', Returned if the specified kernel is not a valid kernel
+object.
+
+ * 'CL_INVALID_KERNEL_ARGS', Returned if the kernel argument values have not been
+specified.
+
+ * 'CL_INVALID_KERNEL_DEFINITION', Returned if the function definition for
+__kernel function given by kernel_name such as the number of arguments, the
+argument types are not the same for all devices for which the program executable
+has been built.
+
+ * 'CL_INVALID_MEM_OBJECT', Returned if a parameter is not a valid memory, image,
+or buffer object.
+
+ * 'CL_INVALID_OPERATION', Returned if there are no devices in context that
+support images. Returned if the build of a program executable for any of the
+devices specified by a previous call to 'clBuildProgram' for program has not
+completed, or if there are kernel objects attached to program. Returned by
+'clEnqueueNativeKernel' if the specified device cannot execute the native
+kernel.
+
+ * 'CL_INVALID_PLATFORM', Returned if the specified platform is not a valid
+platform, or no platform could be selected, or if platform value specified in
+properties is not a valid platform.
+
+ * 'CL_INVALID_PROGRAM', Returned if the specified program is not a valid program
+object.
+
+ * 'CL_INVALID_PROGRAM_EXECUTABLE', Returned if there is no successfully built
+executable for program, or if there is no device in program. Returned if there
+is no successfully built program executable available for device associated with
+command_queue.
+
+ * 'CL_INVALID_QUEUE_PROPERTIES', Returned if specified properties are valid but
+are not supported by the device.
+
+ * 'CL_INVALID_SAMPLER', Returned if the specified sampler is not a valid sampler
+object, or for an argument declared to be of type sampler_t when the specified
+arg_value is not a valid sampler object.
+
+ * 'CL_INVALID_VALUE', Returned if a parameter is not an expected value.
+
+ * 'CL_INVALID_WORK_DIMENSION', Returned if work_dim is not a valid value.
+
+ * 'CL_INVALID_WORK_GROUP_SIZE', Returned if local_work_size is specified and
+number of workitems specified by global_work_size is not evenly divisible by
+size of work-group given by local_work_size or does not match the work-group
+size specified for kernel using the __attribute__((reqd_work_group_size(X, Y,
+Z))) qualifier in program source.
+
+ * 'CL_INVALID_WORK_ITEM_SIZE', Returned if the number of work-items specified in
+any of local_work_size... [0]... local_work_size[work_dim - 1] is greater than
+the corresponding values specified by 'clDeviceMaxWorkItemSizes'.
+
+ * 'CL_MAP_FAILURE', Returned by if there is a failure to map the requested
+region into the host address space. This error cannot occur for buffer objects
+created with 'CLMEM_USE_HOST_PTR' or 'CLMEM_ALLOC_HOST_PTR'.
+
+ * 'CL_MEM_OBJECT_ALLOCATION_FAILURE', Returned if there is a failure to allocate
+memory for data store associated with image or buffer objects specified as
+arguments to kernel.
+
+ * 'CL_MEM_COPY_OVERLAP', Returned if the source and destination images are the
+same image (or the source and destination buffers are the same buffer), and the
+source and destination regions overlap.
+
+ * 'CL_OUT_OF_HOST_MEMORY', Returned in the event of a failure to allocate
+resources required by the OpenCL implementation on the host.
+
+ * 'CL_OUT_OF_RESOURCES', Returned in the event of a failure to queue the
+execution instance of kernel on the command-queue because of insufficient
+resources needed to execute the kernel.
+
+ * 'CL_PROFILING_INFO_NOT_AVAILABLE', Returned if the 'CL_QUEUE_PROFILING_ENABLE'
+flag is not set for the command-queue and the profiling information is currently
+not available (because the command identified by event has not completed).
+
+ * 'CL_SUCCESS', Indicates that the function executed successfully.
+-}
+{#enum CLError {upcaseFirstLetter} deriving( Show, Eq, Typeable ) #}
+
+instance Exception CLError
+
+throwCLError :: CLint -> IO a
+throwCLError = throwIO . (getEnumCL :: CLint -> CLError)
+
+wrapPError :: (Ptr CLint -> IO a) -> IO a
+wrapPError f = alloca $ \perr -> do
+  v <- f perr
+  errcode <- getEnumCL <$> peek perr
+  if errcode == CL_SUCCESS
+    then return v
+    else throwIO errcode
+  
+wrapCheckSuccess :: IO CLint -> IO Bool
+wrapCheckSuccess f = f >>= return . (==CL_SUCCESS) . getEnumCL
+
+wrapGetInfo :: Storable a 
+               => (Ptr a -> Ptr CSize -> IO CLint) -> (a -> b) -> IO b
+wrapGetInfo fget fconvert= alloca $ \dat -> do
+  errcode <- fget dat nullPtr
+  if errcode == getCLValue CL_SUCCESS
+    then fmap fconvert $ peek dat
+    else throwCLError errcode
+
+whenSuccess :: IO CLint -> IO a -> IO a
+whenSuccess fcheck fval = do
+  errcode <- fcheck
+  if errcode == getCLValue CL_SUCCESS
+    then fval
+    else throwCLError errcode
+         
+-- -----------------------------------------------------------------------------
+#c
+enum CLPlatformInfo {
+  cL_PLATFORM_PROFILE=CL_PLATFORM_PROFILE,
+  cL_PLATFORM_VERSION=CL_PLATFORM_VERSION,
+  cL_PLATFORM_NAME=CL_PLATFORM_NAME,
+  cL_PLATFORM_VENDOR=CL_PLATFORM_VENDOR,
+  cL_PLATFORM_EXTENSIONS=CL_PLATFORM_EXTENSIONS
+  };
+#endc
+
+{-|
+ * 'CL_PLATFORM_PROFILE', OpenCL profile string. Returns the profile name 
+supported by the implementation. The profile name returned can be one of the 
+following strings:
+
+ [@FULL_PROFILE@] If the implementation supports the OpenCL specification
+(functionality defined as part of the core specification and does not require
+any extensions to be supported).
+
+ [@EMBEDDED_PROFILE@] If the implementation supports the OpenCL embedded 
+profile. The embedded profile is  defined to be a subset for each version of 
+OpenCL.
+
+ * 'CL_PLATFORM_VERSION', OpenCL version string. Returns the OpenCL version 
+supported by the implementation. This version string has the following format: 
+/OpenCL major_version.minor_version platform-specific information/ The 
+/major_version.minor_version/ value returned will be 1.0.
+                    
+ * 'CL_PLATFORM_NAME', Platform name string.
+ 
+ * 'CL_PLATFORM_VENDOR', Platform vendor string.
+                   
+ * 'CL_PLATFORM_EXTENSIONS', Returns a space-separated list of extension names 
+(the extension names themselves do not contain any spaces) supported by the 
+platform. Extensions defined here must be supported by all devices associated 
+with this platform.
+-}
+{#enum CLPlatformInfo {upcaseFirstLetter} deriving( Show ) #}
+
+-- -----------------------------------------------------------------------------
+#c
+enum CLDeviceType {
+  cL_DEVICE_TYPE_CPU=CL_DEVICE_TYPE_CPU,
+  cL_DEVICE_TYPE_GPU=CL_DEVICE_TYPE_GPU,
+  cL_DEVICE_TYPE_ACCELERATOR=CL_DEVICE_TYPE_ACCELERATOR,
+  cL_DEVICE_TYPE_DEFAULT=CL_DEVICE_TYPE_DEFAULT,
+  cL_DEVICE_TYPE_ALL=CL_DEVICE_TYPE_ALL
+  };
+#endc
+
+{-|
+ * 'CL_DEVICE_TYPE_CPU', An OpenCL device that is the host processor. The host 
+processor runs the OpenCL implementations and is a single or multi-core CPU.
+                  
+ * 'CL_DEVICE_TYPE_GPU', An OpenCL device that is a GPU. By this we mean that the 
+device can also be used to accelerate a 3D API such as OpenGL or DirectX.
+                  
+ * 'CL_DEVICE_TYPE_ACCELERATOR', Dedicated OpenCL accelerators (for example the 
+IBM CELL Blade). These devices communicate with the host processor using a 
+peripheral interconnect such as PCIe.
+                
+ * 'CL_DEVICE_TYPE_DEFAULT', The default OpenCL device in the system.
+           
+ * 'CL_DEVICE_TYPE_ALL', All OpenCL devices available in the system.
+-}
+{#enum CLDeviceType {upcaseFirstLetter} deriving( Show ) #}
+
+#c
+enum CLCommandQueueProperty { 
+  cL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE=CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE,
+  cL_QUEUE_PROFILING_ENABLE=CL_QUEUE_PROFILING_ENABLE
+  };
+#endc
+
+{-|
+ * 'CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE', Determines whether the commands 
+queued in the command-queue are executed in-order or out-of-order. If set, the 
+commands in the command-queue are executed out-of-order. Otherwise, commands are 
+executed in-order.
+                            
+ * 'CL_QUEUE_PROFILING_ENABLE', Enable or disable profiling of commands in the 
+command-queue. If set, the profiling of commands is enabled. Otherwise profiling 
+of commands is disabled. See 'clGetEventProfilingInfo' for more information.
+-}
+{#enum CLCommandQueueProperty {upcaseFirstLetter} deriving( Show, Bounded, Eq, Ord ) #}
+
+#c
+enum CLDeviceFPConfig {
+  cL_FP_DENORM=CL_FP_DENORM, cL_FP_INF_NAN=CL_FP_INF_NAN,
+  cL_FP_ROUND_TO_NEAREST=CL_FP_ROUND_TO_NEAREST,
+  cL_FP_ROUND_TO_ZERO=CL_FP_ROUND_TO_ZERO,
+  cL_FP_ROUND_TO_INF=CL_FP_ROUND_TO_INF, cL_FP_FMA=CL_FP_FMA,
+  };
+#endc
+
+{-|
+ * 'CL_FP_DENORM', denorms are supported.
+                      
+ * 'CL_FP_INF_NAN', INF and NaNs are supported.
+                      
+ * 'CL_FP_ROUND_TO_NEAREST', round to nearest even rounding mode supported.
+                      
+ * 'CL_FP_ROUND_TO_ZERO', round to zero rounding mode supported.
+                      
+ * 'CL_FP_ROUND_TO_INF', round to +ve and -ve infinity rounding modes supported.
+                      
+ * 'CL_FP_FMA', IEEE754-2008 fused multiply-add is supported.
+-}
+{#enum CLDeviceFPConfig {upcaseFirstLetter} deriving( Show, Bounded, Eq, Ord ) #}
+
+#c
+enum CLDeviceExecCapability {
+  cL_EXEC_KERNEL=CL_EXEC_KERNEL,
+  cL_EXEC_NATIVE_KERNEL=CL_EXEC_NATIVE_KERNEL
+  };
+#endc
+
+{-|
+ * 'CL_EXEC_KERNEL', The OpenCL device can execute OpenCL kernels.
+                            
+ * 'CL_EXEC_NATIVE_KERNEL', The OpenCL device can execute native kernels.
+-}
+{#enum CLDeviceExecCapability {upcaseFirstLetter} deriving( Show, Bounded, Eq, Ord ) #}
+
+#c
+enum CLDeviceMemCacheType {
+  cL_NONE=CL_NONE, cL_READ_ONLY_CACHE=CL_READ_ONLY_CACHE,
+  cL_READ_WRITE_CACHE=CL_READ_WRITE_CACHE
+  };
+#endc
+
+{#enum CLDeviceMemCacheType {upcaseFirstLetter} deriving( Show ) #}
+
+#c
+enum CLDeviceLocalMemType {
+  cL_LOCAL=CL_LOCAL, cL_GLOBAL=CL_GLOBAL
+  };
+#endc
+
+{#enum CLDeviceLocalMemType {upcaseFirstLetter} deriving( Show ) #}
+
+-- -----------------------------------------------------------------------------
+#c
+enum CLCommandType {
+  cL_COMMAND_NDRANGE_KERNEL=CL_COMMAND_NDRANGE_KERNEL,
+  cL_COMMAND_TASK=CL_COMMAND_TASK ,
+  cL_COMMAND_NATIVE_KERNEL=CL_COMMAND_NATIVE_KERNEL,
+  cL_COMMAND_READ_BUFFER=CL_COMMAND_READ_BUFFER,
+  cL_COMMAND_WRITE_BUFFER=CL_COMMAND_WRITE_BUFFER,
+  cL_COMMAND_COPY_BUFFER=CL_COMMAND_COPY_BUFFER,
+  cL_COMMAND_READ_IMAGE=CL_COMMAND_READ_IMAGE,
+  cL_COMMAND_WRITE_IMAGE=CL_COMMAND_WRITE_IMAGE,
+  cL_COMMAND_COPY_IMAGE=CL_COMMAND_COPY_IMAGE,
+  cL_COMMAND_COPY_BUFFER_TO_IMAGE=CL_COMMAND_COPY_BUFFER_TO_IMAGE,
+  cL_COMMAND_COPY_IMAGE_TO_BUFFER=CL_COMMAND_COPY_IMAGE_TO_BUFFER,
+  cL_COMMAND_MAP_BUFFER=CL_COMMAND_MAP_BUFFER,
+  cL_COMMAND_MAP_IMAGE=CL_COMMAND_MAP_IMAGE,
+  cL_COMMAND_UNMAP_MEM_OBJECT=CL_COMMAND_UNMAP_MEM_OBJECT,
+  cL_COMMAND_MARKER=CL_COMMAND_MARKER,
+  cL_COMMAND_ACQUIRE_GL_OBJECTS=CL_COMMAND_ACQUIRE_GL_OBJECTS,
+  cL_COMMAND_RELEASE_GL_OBJECTS=CL_COMMAND_RELEASE_GL_OBJECTS
+  };
+#endc
+
+-- | Command associated with an event.
+{#enum CLCommandType {upcaseFirstLetter} deriving( Show ) #}
+
+#c
+enum CLCommandExecutionStatus {
+  cL_QUEUED=CL_QUEUED, cL_SUBMITTED=CL_SUBMITTED, cL_RUNNING=CL_RUNNING,
+  cL_COMPLETE=CL_COMPLETE, cL_EXEC_ERROR= -1
+  };
+#endc
+
+{-|
+ * 'CL_QUEUED', command has been enqueued in the command-queue.
+
+ * 'CL_SUBMITTED', enqueued command has been submitted by the host to the 
+device associated with the command-queue.
+
+ * 'CL_RUNNING', device is currently executing this command.
+                            
+ * 'CL_COMPLETE', the command has completed.
+                              
+ * 'CL_EXEC_ERROR', command was abnormally terminated.
+-}
+{#enum CLCommandExecutionStatus {upcaseFirstLetter} deriving( Show ) #}
+
+#c
+enum CLProfilingInfo {
+  cL_PROFILING_COMMAND_QUEUED=CL_PROFILING_COMMAND_QUEUED,
+  cL_PROFILING_COMMAND_SUBMIT=CL_PROFILING_COMMAND_SUBMIT,
+  cL_PROFILING_COMMAND_START=CL_PROFILING_COMMAND_START,
+  cL_PROFILING_COMMAND_END=CL_PROFILING_COMMAND_END
+  };
+#endc
+
+{-| Specifies the profiling data.
+
+ * 'CL_PROFILING_COMMAND_QUEUED', A 64-bit value that describes the current 
+device time counter in nanoseconds when the command identified by event is 
+enqueued in a command-queue by the host.
+ 
+ * 'CL_PROFILING_COMMAND_SUBMIT', A 64-bit value that describes the current 
+device time counter in nanoseconds when the command identified by event that has 
+been enqueued is submitted by the host to the device associated with the 
+commandqueue.
+ 
+ * 'CL_PROFILING_COMMAND_START', A 64-bit value that describes the current 
+device time counter in nanoseconds when the command identified by event starts 
+execution on the device.
+ 
+ * 'CL_PROFILING_COMMAND_END', A 64-bit value that describes the current device 
+time counter in nanoseconds when the command identified by event has finished 
+execution on the device.
+-}
+{#enum CLProfilingInfo {upcaseFirstLetter} deriving( Show ) #}
+
+-- -----------------------------------------------------------------------------
+#c
+enum CLMemFlag {
+  cL_MEM_READ_WRITE=CL_MEM_READ_WRITE,
+  cL_MEM_WRITE_ONLY=CL_MEM_WRITE_ONLY,
+  cL_MEM_READ_ONLY=CL_MEM_READ_ONLY,
+  cL_MEM_USE_HOST_PTR=CL_MEM_USE_HOST_PTR,
+  cL_MEM_ALLOC_HOST_PTR=CL_MEM_ALLOC_HOST_PTR,
+  cL_MEM_COPY_HOST_PTR=CL_MEM_COPY_HOST_PTR
+  };
+#endc
+{-| 
+ * 'CL_MEM_READ_WRITE', This flag specifies that the memory object will be
+read and written by a kernel. This is the default.
+
+ * 'CL_MEM_WRITE_ONLY', This flags specifies that the memory object will be
+written but not read by a kernel. Reading from a buffer or image object created
+with 'CLMEM_WRITE_ONLY' inside a kernel is undefined.
+
+ * 'CL_MEM_READ_ONLY', This flag specifies that the memory object is a read-only
+memory object when used inside a kernel. Writing to a buffer or image object
+created with 'CLMEM_READ_ONLY' inside a kernel is undefined.
+
+ * 'CL_MEM_USE_HOST_PTR', This flag is valid only if host_ptr is not NULL. If
+specified, it indicates that the application wants the OpenCL implementation to
+use memory referenced by host_ptr as the storage bits for the memory
+object. OpenCL implementations are allowed to cache the buffer contents pointed
+to by host_ptr in device memory. This cached copy can be used when kernels are
+executed on a device. The result of OpenCL commands that operate on multiple
+buffer objects created with the same host_ptr or overlapping host regions is
+considered to be undefined.
+
+ * 'CL_MEM_ALLOC_HOST_PTR', This flag specifies that the application wants the
+OpenCL implementation to allocate memory from host accessible
+memory. 'CL_MEM_ALLOC_HOST_PTR' and 'CL_MEM_USE_HOST_PTR' are mutually exclusive.
+
+ * 'CL_MEM_COPY_HOST_PTR', This flag is valid only if host_ptr is not NULL. If
+specified, it indicates that the application wants the OpenCL implementation to
+allocate memory for the memory object and copy the data from memory referenced
+by host_ptr. 'CL_MEM_COPY_HOST_PTR' and 'CL_MEM_USE_HOST_PTR' are mutually
+exclusive. 'CL_MEM_COPY_HOST_PTR' can be used with 'CL_MEM_ALLOC_HOST_PTR' to
+initialize the contents of the cl_mem object allocated using host-accessible
+(e.g. PCIe) memory.  
+-} 
+{#enum CLMemFlag {upcaseFirstLetter} deriving( Show, Bounded, Eq, Ord ) #}
+
+#c
+enum CLMapFlag {
+  cL_MAP_READ=CL_MAP_READ,
+  cL_MAP_WRITE=CL_MAP_WRITE
+  };
+#endc
+{#enum CLMapFlag {upcaseFirstLetter} deriving( Show, Bounded, Eq, Ord ) #}
+
+#c
+enum CLMemObjectType {
+  cL_MEM_OBJECT_BUFFER=CL_MEM_OBJECT_BUFFER,
+  cL_MEM_OBJECT_IMAGE2D=CL_MEM_OBJECT_IMAGE2D,
+  cL_MEM_OBJECT_IMAGE3D=CL_MEM_OBJECT_IMAGE3D
+  };
+#endc
+
+{-| * 'CL_MEM_OBJECT_BUFFER' if memobj is created with 'clCreateBuffer'. 
+ 
+ * 'CL_MEM_OBJECT_IMAGE2D' if memobj is created with 'clCreateImage2D' 
+
+ * 'CL_MEM_OBJECT_IMAGE3D' if memobj is created with 'clCreateImage3D'.
+-}
+{#enum CLMemObjectType {upcaseFirstLetter} deriving( Show ) #}
+
+#c
+enum CLBuildStatus {
+  cL_BUILD_NONE=CL_BUILD_NONE,
+  cL_BUILD_ERROR=CL_BUILD_ERROR,
+  cL_BUILD_SUCCESS=CL_BUILD_SUCCESS,
+  cL_BUILD_IN_PROGRESS=CL_BUILD_IN_PROGRESS,
+  };
+#endc
+
+{-| * 'CL_BUILD_NONE'. The build status returned if no build has been performed
+on the specified program object for device.
+
+ * 'CL_BUILD_ERROR'. The build status returned if the last call to
+'clBuildProgram' on the specified program object for device generated an error.
+
+ * 'CL_BUILD_SUCCESS'. The build status retrned if the last call to
+'clBuildProgram' on the specified program object for device was successful.
+
+ * 'CL_BUILD_IN_PROGRESS'. The build status returned if the last call to 
+'clBuildProgram' on the specified program object for device has not finished.
+-}
+{#enum CLBuildStatus {upcaseFirstLetter} deriving( Show ) #}
+
+#c
+enum CLAddressingMode {
+  cL_ADDRESS_REPEAT=CL_ADDRESS_REPEAT,
+  cL_ADDRESS_CLAMP_TO_EDGE =CL_ADDRESS_CLAMP_TO_EDGE ,
+  cL_ADDRESS_CLAMP=CL_ADDRESS_CLAMP,
+  cL_ADDRESS_NONE=CL_ADDRESS_NONE
+  };
+#endc
+{#enum CLAddressingMode {upcaseFirstLetter} deriving( Show ) #}
+
+#c
+enum CLFilterMode {
+  cL_FILTER_NEAREST=CL_FILTER_NEAREST,
+  cL_FILTER_LINEAR=CL_FILTER_LINEAR,
+  };
+#endc
+{#enum CLFilterMode {upcaseFirstLetter} deriving( Show ) #}
+
+-- -----------------------------------------------------------------------------
+getCLValue :: (Enum a, Integral b) => a -> b
+getCLValue = fromIntegral . fromEnum
+
+getEnumCL :: (Integral a, Enum b) => a -> b
+getEnumCL = toEnum . fromIntegral 
+
+getCommandExecutionStatus :: CLint -> CLCommandExecutionStatus
+getCommandExecutionStatus n 
+  | n < 0 = CL_EXEC_ERROR
+  | otherwise = getEnumCL $ n
+                
+-- -----------------------------------------------------------------------------
+binaryFlags :: (Ord b, Enum b, Bounded b) => b -> [b]
+binaryFlags m = map toEnum . takeWhile (<= (fromEnum m)) $ [1 `shiftL` n | n <- [0..]]
+  
+testMask :: Bits b => b -> b -> Bool
+testMask mask v = (v .&. mask) == v
+
+bitmaskFromFlags :: (Enum a, Bits b) => [a] -> b
+bitmaskFromFlags = foldl' (.|.) 0 . map (fromIntegral . fromEnum)
+
+bitmaskToFlags :: (Enum a, Bits b) => [a] -> b -> [a]
+bitmaskToFlags xs mask = filter (testMask mask . fromIntegral . fromEnum) xs
+
+bitmaskToDeviceTypes :: CLDeviceType_ -> [CLDeviceType]
+bitmaskToDeviceTypes =
+	bitmaskToFlags 
+		[CL_DEVICE_TYPE_CPU
+		,CL_DEVICE_TYPE_GPU
+		,CL_DEVICE_TYPE_ACCELERATOR
+		,CL_DEVICE_TYPE_DEFAULT
+		,CL_DEVICE_TYPE_ALL
+		]
+
+bitmaskToCommandQueueProperties :: CLCommandQueueProperty_ -> [CLCommandQueueProperty]
+bitmaskToCommandQueueProperties = bitmaskToFlags (binaryFlags maxBound)
+      
+bitmaskToFPConfig :: CLDeviceFPConfig_ -> [CLDeviceFPConfig]
+bitmaskToFPConfig = bitmaskToFlags (binaryFlags maxBound)
+
+bitmaskToExecCapability :: CLDeviceExecCapability_ -> [CLDeviceExecCapability]
+bitmaskToExecCapability = bitmaskToFlags (binaryFlags maxBound)
+
+bitmaskToMemFlags :: CLMemFlags_ -> [CLMemFlag]
+bitmaskToMemFlags = bitmaskToFlags (binaryFlags maxBound)
+
+-- -----------------------------------------------------------------------------
diff --git a/src/System/GPU/OpenCL.hs b/src/System/GPU/OpenCL.hs
deleted file mode 100644
--- a/src/System/GPU/OpenCL.hs
+++ /dev/null
@@ -1,55 +0,0 @@
-{- Copyright (c) 2011 Luis Cabellos,
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above
-      copyright notice, this list of conditions and the following
-      disclaimer in the documentation and/or other materials provided
-      with the distribution.
-
-    * Neither the name of  nor the names of other
-      contributors may be used to endorse or promote products derived
-      from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--}
-module System.GPU.OpenCL( 
-  -- * Basic Types
-  CLError(..), CLint, CLuint, CLulong,
-  -- * Modules
-  module System.GPU.OpenCL.Query,
-  module System.GPU.OpenCL.Context,
-  module System.GPU.OpenCL.CommandQueue, 
-  module System.GPU.OpenCL.Memory,
-  module System.GPU.OpenCL.Event,
-  module System.GPU.OpenCL.Program
-  )
-       where
-
--- -----------------------------------------------------------------------------
-import System.GPU.OpenCL.Query
-import System.GPU.OpenCL.Context
-import System.GPU.OpenCL.CommandQueue
-import System.GPU.OpenCL.Memory
-import System.GPU.OpenCL.Event
-import System.GPU.OpenCL.Program
-import System.GPU.OpenCL.Types( 
-  CLError(..), CLint, CLuint, CLulong )
-
--- -----------------------------------------------------------------------------
diff --git a/src/System/GPU/OpenCL/CommandQueue.chs b/src/System/GPU/OpenCL/CommandQueue.chs
deleted file mode 100644
--- a/src/System/GPU/OpenCL/CommandQueue.chs
+++ /dev/null
@@ -1,566 +0,0 @@
-{- Copyright (c) 2011 Luis Cabellos,
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above
-      copyright notice, this list of conditions and the following
-      disclaimer in the documentation and/or other materials provided
-      with the distribution.
-
-    * Neither the name of  nor the names of other
-      contributors may be used to endorse or promote products derived
-      from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--}
-{-# LANGUAGE ForeignFunctionInterface, ScopedTypeVariables, CPP #-}
-module System.GPU.OpenCL.CommandQueue(
-  -- * Types
-  CLCommandQueue, CLCommandQueueProperty(..), 
-  -- * Command Queue Functions
-  clCreateCommandQueue, clRetainCommandQueue, clReleaseCommandQueue,
-  clGetCommandQueueContext, clGetCommandQueueDevice, 
-  clGetCommandQueueReferenceCount, clGetCommandQueueProperties,
-  clSetCommandQueueProperty,
-  -- * Memory Commands
-  clEnqueueReadBuffer, clEnqueueWriteBuffer,
-  -- * Executing Kernels
-  clEnqueueNDRangeKernel, clEnqueueTask, clEnqueueMarker, 
-  clEnqueueWaitForEvents, clEnqueueBarrier,
-  -- * Flush and Finish
-  clFlush, clFinish
-  ) where
-
--- -----------------------------------------------------------------------------
-import Foreign
-import Foreign.C.Types
-import System.GPU.OpenCL.Types( 
-  CLint, CLbool, CLuint, CLCommandQueueProperty_, CLCommandQueueInfo_, 
-  CLCommandQueue, CLDeviceID, CLContext, CLCommandQueueProperty(..), 
-  CLEvent, CLMem, CLKernel,
-  whenSuccess, wrapCheckSuccess, wrapPError, wrapGetInfo, getCLValue, 
-  bitmaskToCommandQueueProperties, bitmaskFromFlags )
-
-#include <CL/cl.h>
-
--- -----------------------------------------------------------------------------
-foreign import CALLCONV "clCreateCommandQueue" raw_clCreateCommandQueue :: 
-  CLContext -> CLDeviceID -> CLCommandQueueProperty_ -> Ptr CLint -> IO CLCommandQueue
-foreign import CALLCONV "clRetainCommandQueue" raw_clRetainCommandQueue :: 
-  CLCommandQueue -> IO CLint
-foreign import CALLCONV "clReleaseCommandQueue" raw_clReleaseCommandQueue :: 
-  CLCommandQueue -> IO CLint
-foreign import CALLCONV "clGetCommandQueueInfo" raw_clGetCommandQueueInfo :: 
-  CLCommandQueue -> CLCommandQueueInfo_ -> CSize -> Ptr () -> Ptr CSize -> IO CLint
-foreign import CALLCONV "clSetCommandQueueProperty" raw_clSetCommandQueueProperty :: 
-  CLCommandQueue -> CLCommandQueueProperty_ -> CLbool -> Ptr CLCommandQueueProperty_ -> IO CLint
-foreign import CALLCONV "clEnqueueReadBuffer" raw_clEnqueueReadBuffer ::
-  CLCommandQueue -> CLMem -> CLbool -> CSize -> CSize -> Ptr () -> CLuint -> Ptr CLEvent -> Ptr CLEvent -> IO CLint
-foreign import CALLCONV "clEnqueueWriteBuffer" raw_clEnqueueWriteBuffer ::
-  CLCommandQueue -> CLMem -> CLbool -> CSize -> CSize -> Ptr () -> CLuint -> Ptr CLEvent -> Ptr CLEvent -> IO CLint
-foreign import CALLCONV "clEnqueueNDRangeKernel" raw_clEnqueueNDRangeKernel :: 
-  CLCommandQueue -> CLKernel -> CLuint -> Ptr CSize -> Ptr CSize -> Ptr CSize -> CLuint -> Ptr CLEvent -> Ptr CLEvent -> IO CLint
-foreign import CALLCONV "clEnqueueTask" raw_clEnqueueTask :: 
-  CLCommandQueue -> CLKernel -> CLuint -> Ptr CLEvent -> Ptr CLEvent -> IO CLint
-foreign import CALLCONV "clEnqueueMarker" raw_clEnqueueMarker :: 
-  CLCommandQueue -> Ptr CLEvent -> IO CLint 
-foreign import CALLCONV "clEnqueueWaitForEvents" raw_clEnqueueWaitForEvents :: 
-  CLCommandQueue -> CLuint -> Ptr CLEvent -> IO CLint
-foreign import CALLCONV "clEnqueueBarrier" raw_clEnqueueBarrier :: 
-  CLCommandQueue -> IO CLint 
-foreign import CALLCONV "clFlush" raw_clFlush ::
-  CLCommandQueue -> IO CLint
-foreign import CALLCONV "clFinish" raw_clFinish ::
-  CLCommandQueue -> IO CLint
-
--- -----------------------------------------------------------------------------
-{-| Create a command-queue on a specific device.
-
-The OpenCL functions that are submitted to a command-queue are enqueued in the 
-order the calls are made but can be configured to execute in-order or 
-out-of-order. The properties argument in clCreateCommandQueue can be used to 
-specify the execution order.
-
-If the 'CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE' property of a command-queue is 
-not set, the commands enqueued to a command-queue execute in order. For example, 
-if an application calls 'clEnqueueNDRangeKernel' to execute kernel A followed by 
-a 'clEnqueueNDRangeKernel' to execute kernel B, the application can assume that 
-kernel A finishes first and then kernel B is executed. If the memory objects 
-output by kernel A are inputs to kernel B then kernel B will see the correct 
-data in memory objects produced by execution of kernel A. If the 
-'CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE' property of a commandqueue is set, then 
-there is no guarantee that kernel A will finish before kernel B starts execution.
-
-Applications can configure the commands enqueued to a command-queue to execute 
-out-of-order by setting the 'CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE' property of 
-the command-queue. This can be specified when the command-queue is created or 
-can be changed dynamically using 'clCreateCommandQueue'. In out-of-order 
-execution mode there is no guarantee that the enqueued commands will finish 
-execution in the order they were queued. As there is no guarantee that kernels 
-will be executed in order, i.e. based on when the 'clEnqueueNDRangeKernel' calls 
-are made within a command-queue, it is therefore possible that an earlier 
-'clEnqueueNDRangeKernel' call to execute kernel A identified by event A may 
-execute and/or finish later than a 'clEnqueueNDRangeKernel' call to execute 
-kernel B which was called by the application at a later point in time. To 
-guarantee a specific order of execution of kernels, a wait on a particular event 
-(in this case event A) can be used. The wait for event A can be specified in the 
-event_wait_list argument to 'clEnqueueNDRangeKernel' for kernel B.
-
-In addition, a wait for events or a barrier command can be enqueued to the 
-command-queue. The wait for events command ensures that previously enqueued 
-commands identified by the list of events to wait for have finished before the 
-next batch of commands is executed. The barrier command ensures that all 
-previously enqueued commands in a command-queue have finished execution before 
-the next batch of commands is executed.
-
-Similarly, commands to read, write, copy or map memory objects that are enqueued 
-after 'clEnqueueNDRangeKernel', 'clEnqueueTask' or 'clEnqueueNativeKernel' 
-commands are not guaranteed to wait for kernels scheduled for execution to have 
-completed (if the 'CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE' property is set). To 
-ensure correct ordering of commands, the event object returned by 
-'clEnqueueNDRangeKernel', 'clEnqueueTask' or 'clEnqueueNativeKernel' can be 
-used to enqueue a wait for event or a barrier command can be enqueued that must 
-complete before reads or writes to the memory object(s) occur.
--}
-clCreateCommandQueue :: CLContext -> CLDeviceID -> [CLCommandQueueProperty] 
-                     -> IO CLCommandQueue
-clCreateCommandQueue ctx did xs = wrapPError $ \perr -> do
-  raw_clCreateCommandQueue ctx did props perr
-    where
-      props = bitmaskFromFlags xs
-
-{-| Increments the command_queue reference count. 'clCreateCommandQueue'
-performs an implicit retain. This is very helpful for 3rd party libraries, which
-typically get a command-queue passed to them by the application. However, it is
-possible that the application may delete the command-queue without informing the
-library. Allowing functions to attach to (i.e. retain) and release a
-command-queue solves the problem of a command-queue being used by a library no
-longer being valid.  Returns 'True' if the function is executed successfully. It
-returns 'False' if command_queue is not a valid command-queue.  
--}
-clRetainCommandQueue :: CLCommandQueue -> IO Bool
-clRetainCommandQueue = wrapCheckSuccess . raw_clRetainCommandQueue
-
--- | Decrements the command_queue reference count.
--- After the command_queue reference count becomes zero and all commands queued 
--- to command_queue have finished (e.g., kernel executions, memory object 
--- updates, etc.), the command-queue is deleted.
--- Returns 'True' if the function is executed successfully. It returns 'False'
--- if command_queue is not a valid command-queue.
-clReleaseCommandQueue :: CLCommandQueue -> IO Bool
-clReleaseCommandQueue = wrapCheckSuccess . raw_clReleaseCommandQueue
-
-#c
-enum CLCommandQueueInfo {
-  cL_QUEUE_CONTEXT=CL_QUEUE_CONTEXT,
-  cL_QUEUE_DEVICE=CL_QUEUE_DEVICE,
-  cL_QUEUE_REFERENCE_COUNT=CL_QUEUE_REFERENCE_COUNT,
-  cL_QUEUE_PROPERTIES=CL_QUEUE_PROPERTIES,
-  };
-#endc
-{#enum CLCommandQueueInfo {upcaseFirstLetter} #}
-
--- | Return the context specified when the command-queue is created.
---
--- This function execute OpenCL clGetCommandQueueInfo with 'CL_QUEUE_CONTEXT'.
-clGetCommandQueueContext :: CLCommandQueue -> IO CLContext
-clGetCommandQueueContext cq =
-    wrapGetInfo (\(dat :: Ptr CLContext) ->
-        raw_clGetCommandQueueInfo cq infoid size (castPtr dat)) id
-    where 
-      infoid = getCLValue CL_QUEUE_CONTEXT
-      size = fromIntegral $ sizeOf (nullPtr::CLContext)
-
--- | Return the device specified when the command-queue is created.
---
--- This function execute OpenCL clGetCommandQueueInfo with 'CL_QUEUE_DEVICE'.
-clGetCommandQueueDevice :: CLCommandQueue -> IO CLDeviceID
-clGetCommandQueueDevice cq =
-    wrapGetInfo (\(dat :: Ptr CLDeviceID) ->
-        raw_clGetCommandQueueInfo cq infoid size (castPtr dat)) id
-    where 
-      infoid = getCLValue CL_QUEUE_DEVICE
-      size = fromIntegral $ sizeOf (nullPtr::CLDeviceID)
-
--- | Return the command-queue reference count.
--- The reference count returned should be considered immediately stale. It is 
--- unsuitable for general use in applications. This feature is provided for 
--- identifying memory leaks.
---
--- This function execute OpenCL clGetCommandQueueInfo with
--- 'CL_QUEUE_REFERENCE_COUNT'.
-clGetCommandQueueReferenceCount :: CLCommandQueue -> IO CLuint
-clGetCommandQueueReferenceCount cq =
-    wrapGetInfo (\(dat :: Ptr CLuint) ->
-        raw_clGetCommandQueueInfo cq infoid size (castPtr dat)) id
-    where 
-      infoid = getCLValue CL_QUEUE_REFERENCE_COUNT
-      size = fromIntegral $ sizeOf (0::CLuint)
-
-
--- | Return the currently specified properties for the command-queue. These 
--- properties are specified by the properties argument in 'clCreateCommandQueue'
--- , and can be changed by 'clSetCommandQueueProperty'.
---
--- This function execute OpenCL clGetCommandQueueInfo with
--- 'CL_QUEUE_PROPERTIES'.
-clGetCommandQueueProperties :: CLCommandQueue -> IO [CLCommandQueueProperty]
-clGetCommandQueueProperties cq =
-    wrapGetInfo (\(dat :: Ptr CLCommandQueueProperty_) ->
-        raw_clGetCommandQueueInfo cq infoid size (castPtr dat)) bitmaskToCommandQueueProperties
-    where 
-      infoid = getCLValue CL_QUEUE_PROPERTIES
-      size = fromIntegral $ sizeOf (0::CLCommandQueueProperty_)
-
-{-| Enable or disable the properties of a command-queue.  Returns the
-command-queue properties before they were changed by
-'clSetCommandQueueProperty'.  As specified for 'clCreateCommandQueue', the
-'CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE' command-queue property determines
-whether the commands in a command-queue are executed in-order or
-out-of-order. Changing this command-queue property will cause the OpenCL
-implementation to block until all previously queued commands in command_queue
-have completed. This can be an expensive operation and therefore changes to the
-'CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE' property should be only done when
-absolutely necessary.
-
- It is possible that a device(s) becomes unavailable after a context and
-command-queues that use this device(s) have been created and commands have been
-queued to command-queues. In this case the behavior of OpenCL API calls that use
-this context (and command-queues) are considered to be
-implementation-defined. The user callback function, if specified when the
-context is created, can be used to record appropriate information when the
-device becomes unavailable.
--}
-clSetCommandQueueProperty :: CLCommandQueue -> [CLCommandQueueProperty] -> Bool 
-                          -> IO [CLCommandQueueProperty]
-clSetCommandQueueProperty cq xs val = alloca 
-                                      $ \(dat :: Ptr CLCommandQueueProperty_) 
-                                        -> whenSuccess (f dat)
-                                           $ fmap bitmaskToCommandQueueProperties $ peek dat
-    where
-      f = raw_clSetCommandQueueProperty cq props (fromBool val)
-      props = bitmaskFromFlags xs
-
--- -----------------------------------------------------------------------------
-clEnqueue :: (CLuint -> Ptr CLEvent -> Ptr CLEvent -> IO CLint) -> [CLEvent] 
-             -> IO CLEvent
-clEnqueue f [] = alloca $ \event -> whenSuccess (f 0 nullPtr event)
-                                    $ peek event
-clEnqueue f events = allocaArray nevents $ \pevents -> do
-  pokeArray pevents events
-  alloca $ \event -> whenSuccess (f cnevents pevents event)
-                     $ peek event
-    where
-      nevents = length events
-      cnevents = fromIntegral nevents
-
--- -----------------------------------------------------------------------------
-{-| Enqueue commands to read from a buffer object to host memory. Calling
-clEnqueueReadBuffer to read a region of the buffer object with the ptr argument
-value set to host_ptr + offset, where host_ptr is a pointer to the memory region
-specified when the buffer object being read is created with
-'CL_MEM_USE_HOST_PTR', must meet the following requirements in order to avoid
-undefined behavior:
-
- * All commands that use this buffer object have finished execution before the
-read command begins execution
-
- * The buffer object is not mapped
-
- * The buffer object is not used by any command-queue until the read command has
-finished execution Errors
-
-'clEnqueueReadBuffer' returns the event if the function is executed
-successfully. It can throw the following 'CLError' exceptions:
-
- * 'CL_INVALID_COMMAND_QUEUE' if command_queue is not a valid command-queue.
-
- * 'CL_INVALID_CONTEXT' if the context associated with command_queue and buffer
-are not the same or if the context associated with command_queue and events in
-event_wait_list are not the same.
-
- * 'CL_INVALID_MEM_OBJECT' if buffer is not a valid buffer object.
-
- * 'CL_INVALID_VALUE' if the region being read specified by (offset, cb) is out
-of bounds or if ptr is a NULL value.
-
- * 'CL_INVALID_EVENT_WAIT_LIST' if event_wait_list is NULL and
-num_events_in_wait_list greater than 0, or event_wait_list is not NULL and
-num_events_in_wait_list is 0, or if event objects in event_wait_list are not
-valid events.
-
- * 'CL_MEM_OBJECT_ALLOCATION_FAILURE' if there is a failure to allocate memory
-for data store associated with buffer.
-
- * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
-by the OpenCL implementation on the host.
--}
-clEnqueueReadBuffer :: Integral a => CLCommandQueue -> CLMem -> Bool -> a -> a
-                       -> Ptr () -> [CLEvent] -> IO CLEvent
-clEnqueueReadBuffer cq mem check off size dat = clEnqueue (raw_clEnqueueReadBuffer cq mem (fromBool check) (fromIntegral off) (fromIntegral size) dat)
-
-{-| Enqueue commands to write to a buffer object from host memory.Calling
-clEnqueueWriteBuffer to update the latest bits in a region of the buffer object
-with the ptr argument value set to host_ptr + offset, where host_ptr is a
-pointer to the memory region specified when the buffer object being written is
-created with 'CL_MEM_USE_HOST_PTR', must meet the following requirements in
-order to avoid undefined behavior:
-
- * The host memory region given by (host_ptr + offset, cb) contains the latest
-bits when the enqueued write command begins execution.
-
- * The buffer object is not mapped.
-
- * The buffer object is not used by any command-queue until the write command
-has finished execution.
-
-'clEnqueueWriteBuffer' returns the Event if the function is executed
-successfully. It can throw the following 'CLError' exceptions:
-
- * 'CL_INVALID_COMMAND_QUEUE' if command_queue is not a valid command-queue.
-
- * 'CL_INVALID_CONTEXT' if the context associated with command_queue and buffer
-are not the same or if the context associated with command_queue and events in
-event_wait_list are not the same.
-
- * 'CL_INVALID_MEM_OBJECT' if buffer is not a valid buffer object.
-
- * 'CL_INVALID_VALUE' if the region being written specified by (offset, cb) is
-out of bounds or if ptr is a NULL value.
-
- * 'CL_INVALID_EVENT_WAIT_LIST' if event_wait_list is NULL and
-num_events_in_wait_list greater than 0, or event_wait_list is not NULL and
-num_events_in_wait_list is 0, or if event objects in event_wait_list are not
-valid events.
-
- * 'CL_MEM_OBJECT_ALLOCATION_FAILURE' if there is a failure to allocate memory
-for data store associated with buffer.
-
- * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
-by the OpenCL implementation on the host.
--}
-clEnqueueWriteBuffer :: Integral a => CLCommandQueue -> CLMem -> Bool -> a -> a
-                       -> Ptr () -> [CLEvent] -> IO CLEvent
-clEnqueueWriteBuffer cq mem check off size dat = clEnqueue (raw_clEnqueueWriteBuffer cq mem (fromBool check) (fromIntegral off) (fromIntegral size) dat)
-
--- -----------------------------------------------------------------------------
-{-| Enqueues a command to execute a kernel on a device. Each work-item is
-uniquely identified by a global identifier. The global ID, which can be read
-inside the kernel, is computed using the value given by global_work_size and
-global_work_offset. In OpenCL 1.0, the starting global ID is always (0, 0,
-... 0). In addition, a work-item is also identified within a work-group by a
-unique local ID. The local ID, which can also be read by the kernel, is computed
-using the value given by local_work_size. The starting local ID is always (0, 0,
-... 0).
-
-Returns the event if the kernel execution was successfully queued. It can throw
-the following 'CLError' exceptions:
-
- * 'CL_INVALID_PROGRAM_EXECUTABLE' if there is no successfully built program
-executable available for device associated with command_queue.
-
- * 'CL_INVALID_COMMAND_QUEUE' if command_queue is not a valid command-queue.
-
- * 'CL_INVALID_KERNEL' if kernel is not a valid kernel object.
-
- * 'CL_INVALID_CONTEXT' if context associated with command_queue and kernel is
-not the same or if the context associated with command_queue and events in
-event_wait_list are not the same.
-
- * 'CL_INVALID_KERNEL_ARGS' if the kernel argument values have not been
-specified.
-
- * 'CL_INVALID_WORK_DIMENSION' if work_dim is not a valid value (i.e. a value
-between 1 and 3).
-
- * 'CL_INVALID_WORK_GROUP_SIZE' if local_work_size is specified and number of
-work-items specified by global_work_size is not evenly divisable by size of
-work-group given by local_work_size or does not match the work-group size
-specified for kernel using the __attribute__((reqd_work_group_size(X, Y, Z)))
-qualifier in program source.
-
- * 'CL_INVALID_WORK_GROUP_SIZE' if local_work_size is specified and the total
-number of work-items in the work-group computed as local_work_size[0]
-*... local_work_size[work_dim - 1] is greater than the value specified by
-'CL_DEVICE_MAX_WORK_GROUP_SIZE' in the table of OpenCL Device Queries for
-clGetDeviceInfo.
-
- * 'CL_INVALID_WORK_GROUP_SIZE' if local_work_size is NULL and the
-__attribute__((reqd_work_group_size(X, Y, Z))) qualifier is used to declare the
-work-group size for kernel in the program source.
-
- * 'CL_INVALID_WORK_ITEM_SIZE' if the number of work-items specified in any of
-local_work_size[0], ... local_work_size[work_dim - 1] is greater than the
-corresponding values specified by 'CL_DEVICE_MAX_WORK_ITEM_SIZES'[0],
-.... 'CL_DEVICE_MAX_WORK_ITEM_SIZES'[work_dim - 1].
-
- * 'CL_OUT_OF_RESOURCES' if there is a failure to queue the execution instance
-of kernel on the command-queue because of insufficient resources needed to
-execute the kernel. For example, the explicitly specified local_work_size causes
-a failure to execute the kernel because of insufficient resources such as
-registers or local memory. Another example would be the number of read-only
-image args used in kernel exceed the 'CL_DEVICE_MAX_READ_IMAGE_ARGS' value for
-device or the number of write-only image args used in kernel exceed the
-'CL_DEVICE_MAX_WRITE_IMAGE_ARGS' value for device or the number of samplers used
-in kernel exceed 'CL_DEVICE_MAX_SAMPLERS' for device.
-
- * 'CL_MEM_OBJECT_ALLOCATION_FAILURE' if there is a failure to allocate memory for data store associated with image or buffer objects specified as arguments to kernel.
-
- * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required by
-the OpenCL implementation on the host.
--}
-clEnqueueNDRangeKernel :: Integral a => CLCommandQueue -> CLKernel -> [a] -> [a] 
-                          -> [CLEvent] -> IO CLEvent
-clEnqueueNDRangeKernel cq krn gws lws events = withArray (map fromIntegral gws) $ \pgws -> withArray (map fromIntegral lws) $ \plws -> do
-  clEnqueue (raw_clEnqueueNDRangeKernel cq krn num nullPtr pgws plws) events
-    where
-      num = fromIntegral $ length gws
-      
-{-| Enqueues a command to execute a kernel on a device. The kernel is executed
-using a single work-item.
-
-'clEnqueueTask' is equivalent to calling 'clEnqueueNDRangeKernel' with work_dim
-= 1, global_work_offset = [], global_work_size[0] set to 1, and
-local_work_size[0] set to 1.
-
-Returns the evens if the kernel execution was successfully queued. It can throw
-the following 'CLError' exceptions:
-
- * 'CL_INVALID_PROGRAM_EXECUTABLE' if there is no successfully built program
-executable available for device associated with command_queue.
-
- * 'CL_INVALID_COMMAND_QUEUE if' command_queue is not a valid command-queue.
-
- * 'CL_INVALID_KERNEL' if kernel is not a valid kernel object.
-
- * 'CL_INVALID_CONTEXT' if context associated with command_queue and kernel is
-not the same or if the context associated with command_queue and events in
-event_wait_list are not the same.
-
- * 'CL_INVALID_KERNEL_ARGS' if the kernel argument values have not been specified.
-
- * 'CL_INVALID_WORK_GROUP_SIZE' if a work-group size is specified for kernel
-using the __attribute__((reqd_work_group_size(X, Y, Z))) qualifier in program
-source and is not (1, 1, 1).
-
- * 'CL_OUT_OF_RESOURCES' if there is a failure to queue the execution instance
-of kernel on the command-queue because of insufficient resources needed to
-execute the kernel.
-
- * 'CL_MEM_OBJECT_ALLOCATION_FAILURE' if there is a failure to allocate memory
-for data store associated with image or buffer objects specified as arguments to
-kernel.
-
- * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
-by the OpenCL implementation on the host.
--}
-clEnqueueTask :: CLCommandQueue -> CLKernel -> [CLEvent] -> IO CLEvent
-clEnqueueTask cq krn = clEnqueue (raw_clEnqueueTask cq krn)
-  
--- -----------------------------------------------------------------------------
--- | Enqueues a marker command to command_queue. The marker command returns an
--- event which can be used to queue a wait on this marker event i.e. wait for
--- all commands queued before the marker command to complete. Returns the event
--- if the function is successfully executed. It throw the 'CLError' exception
--- 'CL_INVALID_COMMAND_QUEUE' if command_queue is not a valid command-queue and
--- throw 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources
--- required by the OpenCL implementation on the host.
-clEnqueueMarker :: CLCommandQueue -> IO CLEvent
-clEnqueueMarker cq = alloca $ \event 
-                              -> whenSuccess (raw_clEnqueueMarker cq event)
-                                 $ peek event
-         
-{-| Enqueues a wait for a specific event or a list of events to complete before
-any future commands queued in the command-queue are executed. The context
-associated with events in event_list and command_queue must be the same.
-
-It can throw the following 'CLError' exceptions:
-
- * 'CL_INVALID_COMMAND_QUEUE' if command_queue is not a valid command-queue.
-
- * 'CL_INVALID_CONTEXT' if the context associated with command_queue and events
-in event_list are not the same.
-
- * 'CL_INVALID_VALUE' if num_events is zero.
-
- * 'CL_INVALID_EVENT' if event objects specified in event_list are not valid
-events.
-
- * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
-by the OpenCL implementation on the host.
--}
-clEnqueueWaitForEvents :: CLCommandQueue -> [CLEvent] -> IO ()
-clEnqueueWaitForEvents cq [] = whenSuccess 
-                               (raw_clEnqueueWaitForEvents cq 0 nullPtr)
-                               $ return ()
-clEnqueueWaitForEvents cq events = allocaArray nevents $ \pevents -> do
-  pokeArray pevents events
-  whenSuccess (raw_clEnqueueWaitForEvents cq cnevents pevents)
-    $ return ()
-    where
-      nevents = length events
-      cnevents = fromIntegral nevents
-
--- | 'clEnqueueBarrier' is a synchronization point that ensures that all queued
--- commands in command_queue have finished execution before the next batch of
--- commands can begin execution. It throws 'CL_INVALID_COMMAND_QUEUE' if
--- command_queue is not a valid command-queue and throws
--- 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
--- by the OpenCL implementation on the host.
-clEnqueueBarrier :: CLCommandQueue -> IO ()
-clEnqueueBarrier cq = whenSuccess (raw_clEnqueueBarrier cq) $ return ()
-  
--- -----------------------------------------------------------------------------
-{-| Issues all previously queued OpenCL commands in a command-queue to the
-device associated with the command-queue.  'clFlush' only guarantees that all
-queued commands to command_queue get issued to the appropriate device. There is
-no guarantee that they will be complete after 'clFlush' returns.
-
- 'clFlush' returns 'True' if the function call was executed successfully. It
-returns 'False' if command_queue is not a valid command-queue or if there is a
-failure to allocate resources required by the OpenCL implementation on the host.
-
- Any blocking commands queued in a command-queue such as 'clEnqueueReadImage' or
-'clEnqueueReadBuffer' with blocking_read set to 'True', 'clEnqueueWriteImage' or
-'clEnqueueWriteBuffer' with blocking_write set to 'True', 'clEnqueueMapImage' or
-'clEnqueueMapBuffer' with blocking_map set to 'True' or 'clWaitForEvents'
-perform an implicit flush of the command-queue.
-
- To use event objects that refer to commands enqueued in a command-queue as
-event objects to wait on by commands enqueued in a different command-queue, the
-application must call a 'clFlush' or any blocking commands that perform an
-implicit flush of the command-queue where the commands that refer to these event
-objects are enqueued.
--}
-clFlush :: CLCommandQueue -> IO Bool
-clFlush = wrapCheckSuccess . raw_clFlush
-             
--- | Blocks until all previously queued OpenCL commands in a command-queue are 
--- issued to the associated device and have completed.
--- 'clFinish' does not return until all queued commands in command_queue have 
--- been processed and completed. 'clFinish' is also a synchronization point.
---
--- 'clFinish' returns 'True' if the function call was executed successfully. It 
--- returns 'False' if command_queue is not a valid command-queue or if there is 
--- a failure to allocate resources required by the OpenCL implementation on the 
--- host.
-clFinish :: CLCommandQueue -> IO Bool
-clFinish = wrapCheckSuccess . raw_clFinish
-             
--- -----------------------------------------------------------------------------
diff --git a/src/System/GPU/OpenCL/Context.chs b/src/System/GPU/OpenCL/Context.chs
deleted file mode 100644
--- a/src/System/GPU/OpenCL/Context.chs
+++ /dev/null
@@ -1,164 +0,0 @@
-{- Copyright (c) 2011 Luis Cabellos,
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above
-      copyright notice, this list of conditions and the following
-      disclaimer in the documentation and/or other materials provided
-      with the distribution.
-
-    * Neither the name of  nor the names of other
-      contributors may be used to endorse or promote products derived
-      from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--}
-{-# LANGUAGE ForeignFunctionInterface, ScopedTypeVariables, CPP #-}
-module System.GPU.OpenCL.Context(
-  -- * Types
-  CLContext,
-  -- * Context Functions
-  clCreateContext, clCreateContextFromType, clRetainContext, clReleaseContext,
-  clGetContextReferenceCount, clGetContextDevices )
-    where
-
--- -----------------------------------------------------------------------------
-import Foreign( 
-  Ptr, FunPtr, nullPtr, castPtr, alloca, allocaArray, peek, peekArray, 
-  pokeArray )
-import Foreign.C.Types( CSize )
-import Foreign.C.String( CString, peekCString )
-import Foreign.Storable( sizeOf )
-import System.GPU.OpenCL.Types( 
-  CLuint, CLint, CLDeviceType_, CLContextInfo_, CLContextProperty_, CLDeviceID, 
-  CLContext, CLDeviceType, bitmaskFromFlags, getCLValue,
-  whenSuccess, wrapCheckSuccess, wrapPError, wrapGetInfo )
-
-#include <CL/cl.h>
-
--- -----------------------------------------------------------------------------
-type ContextCallback = CString -> Ptr () -> CSize -> Ptr () -> IO ()
-foreign import CALLCONV "wrapper" wrapContextCallback :: 
-  ContextCallback -> IO (FunPtr ContextCallback)
-foreign import CALLCONV "clCreateContext" raw_clCreateContext ::
-  Ptr CLContextProperty_ -> CLuint -> Ptr CLDeviceID -> FunPtr ContextCallback -> 
-  Ptr () -> Ptr CLint -> IO CLContext
-foreign import CALLCONV "clCreateContextFromType" raw_clCreateContextFromType :: 
-  Ptr CLContextProperty_ -> CLDeviceType_ -> FunPtr ContextCallback -> 
-  Ptr () -> Ptr CLint -> IO CLContext
-foreign import CALLCONV "clRetainContext" raw_clRetainContext :: 
-  CLContext -> IO CLint
-foreign import CALLCONV "clReleaseContext" raw_clReleaseContext :: 
-  CLContext -> IO CLint
-foreign import CALLCONV "clGetContextInfo" raw_clGetContextInfo :: 
-  CLContext -> CLContextInfo_ -> CSize -> Ptr () -> Ptr CSize -> IO CLint
-
--- -----------------------------------------------------------------------------
-mkContextCallback :: (String -> IO ()) -> ContextCallback
-mkContextCallback f msg _ _ _ = peekCString msg >>= f
-
--- | Creates an OpenCL context.
--- An OpenCL context is created with one or more devices. Contexts are used by 
--- the OpenCL runtime for managing objects such as command-queues, memory, 
--- program and kernel objects and for executing kernels on one or more devices 
--- specified in the context.
-clCreateContext :: [CLDeviceID] -> (String -> IO ()) -> IO CLContext
-clCreateContext devs f = allocaArray ndevs $ \pdevs -> do
-  pokeArray pdevs devs
-  wrapPError $ \perr -> do
-    fptr <- wrapContextCallback $ mkContextCallback f
-    raw_clCreateContext nullPtr cndevs pdevs fptr nullPtr perr
-    where
-      ndevs = length devs
-      cndevs = fromIntegral ndevs
-
--- | Create an OpenCL context from a device type that identifies the specific 
--- device(s) to use.
-clCreateContextFromType :: [CLDeviceType] -> (String -> IO ()) 
-                           -> IO CLContext
-clCreateContextFromType xs f = wrapPError $ \perr -> do
-  fptr <- wrapContextCallback $ mkContextCallback f
-  raw_clCreateContextFromType nullPtr types fptr nullPtr perr
-    where
-      types = bitmaskFromFlags xs
-
--- | Increment the context reference count.
--- 'clCreateContext' and 'clCreateContextFromType' perform an implicit retain. 
--- This is very helpful for 3rd party libraries, which typically get a context 
--- passed to them by the application. However, it is possible that the 
--- application may delete the context without informing the library. Allowing 
--- functions to attach to (i.e. retain) and release a context solves the 
--- problem of a context being used by a library no longer being valid.
--- Returns 'True' if the function is executed successfully, or 'False' if 
--- context is not a valid OpenCL context.
-clRetainContext :: CLContext -> IO Bool
-clRetainContext ctx = wrapCheckSuccess $ raw_clRetainContext ctx 
-
--- | Decrement the context reference count.
--- After the context reference count becomes zero and all the objects attached 
--- to context (such as memory objects, command-queues) are released, the 
--- context is deleted.
--- Returns 'True' if the function is executed successfully, or 'False' if 
--- context is not a valid OpenCL context.
-clReleaseContext :: CLContext -> IO Bool
-clReleaseContext ctx = wrapCheckSuccess $ raw_clReleaseContext ctx 
-
-getContextInfoSize :: CLContext -> CLContextInfo_ -> IO CSize
-getContextInfoSize ctx infoid = alloca $ \(value_size :: Ptr CSize) -> do
-  whenSuccess (raw_clGetContextInfo ctx infoid 0 nullPtr value_size)
-    $ peek value_size
-
-#c
-enum CLContextInfo {
-  cL_CONTEXT_REFERENCE_COUNT=CL_CONTEXT_REFERENCE_COUNT,
-  cL_CONTEXT_DEVICES=CL_CONTEXT_DEVICES,
-  cL_CONTEXT_PROPERTIES=CL_CONTEXT_PROPERTIES
-  };
-#endc
-{#enum CLContextInfo {upcaseFirstLetter} #}
-
--- | Return the context reference count. The reference count returned should be 
--- considered immediately stale. It is unsuitable for general use in 
--- applications. This feature is provided for identifying memory leaks.
---
--- This function execute OpenCL clGetContextInfo with 'CL_CONTEXT_REFERENCE_COUNT'.
-clGetContextReferenceCount :: CLContext -> IO CLuint
-clGetContextReferenceCount ctx =
-    wrapGetInfo (\(dat :: Ptr CLuint) ->
-        raw_clGetContextInfo ctx infoid size (castPtr dat)) id
-    where 
-      infoid = getCLValue CL_CONTEXT_REFERENCE_COUNT
-      size = fromIntegral $ sizeOf (0::CLuint)
-
--- | Return the list of devices in context.
---
--- This function execute OpenCL clGetContextInfo with 'CL_CONTEXT_DEVICES'.
-clGetContextDevices :: CLContext -> IO [CLDeviceID]
-clGetContextDevices ctx = do
-  size <- getContextInfoSize ctx infoid
-  let n = (fromIntegral size) `div` elemSize 
-    
-  allocaArray n $ \(buff :: Ptr CLDeviceID) -> do
-    whenSuccess (raw_clGetContextInfo ctx infoid size (castPtr buff) nullPtr)
-      $ peekArray n buff
-    where
-      infoid = getCLValue CL_CONTEXT_DEVICES
-      elemSize = sizeOf (nullPtr :: CLDeviceID)
-
--- -----------------------------------------------------------------------------
diff --git a/src/System/GPU/OpenCL/Event.chs b/src/System/GPU/OpenCL/Event.chs
deleted file mode 100644
--- a/src/System/GPU/OpenCL/Event.chs
+++ /dev/null
@@ -1,187 +0,0 @@
-{- Copyright (c) 2011 Luis Cabellos,
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above
-      copyright notice, this list of conditions and the following
-      disclaimer in the documentation and/or other materials provided
-      with the distribution.
-
-    * Neither the name of  nor the names of other
-      contributors may be used to endorse or promote products derived
-      from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--}
-{-# LANGUAGE ForeignFunctionInterface, ScopedTypeVariables, CPP #-}
-module System.GPU.OpenCL.Event(  
-  -- * Types
-  CLEvent, CLCommandType(..), CLProfilingInfo(..), CLCommandExecutionStatus(..),
-  -- * Functions
-  clWaitForEvents, clRetainEvent, clReleaseEvent, clGetEventCommandQueue, 
-  clGetEventCommandType, clGetEventReferenceCount, 
-  clGetEventCommandExecutionStatus, clGetEventProfilingInfo
-  ) where
-
--- -----------------------------------------------------------------------------
-import Foreign
-import Foreign.C.Types
-import System.GPU.OpenCL.Types( 
-  CLEvent, CLint, CLuint, CLulong, CLEventInfo_, CLProfilingInfo_,
-  CLCommandQueue, CLCommandType(..), CLCommandType_, 
-  CLCommandExecutionStatus(..), CLProfilingInfo(..), getCommandExecutionStatus, 
-  getCLValue, getEnumCL, wrapCheckSuccess, wrapGetInfo )
-
-#include <CL/cl.h>
-
--- -----------------------------------------------------------------------------
-foreign import CALLCONV "clWaitForEvents" raw_clWaitForEvents :: 
-  CLuint -> Ptr CLEvent -> IO CLint
-foreign import CALLCONV "clGetEventInfo" raw_clGetEventInfo :: 
-  CLEvent -> CLEventInfo_ -> CSize -> Ptr () -> Ptr CSize -> IO CLint
-foreign import CALLCONV "clRetainEvent" raw_clRetainEvent :: 
-  CLEvent -> IO CLint 
-foreign import CALLCONV "clReleaseEvent" raw_clReleaseEvent :: 
-  CLEvent -> IO CLint 
-foreign import CALLCONV "clGetEventProfilingInfo" raw_clGetEventProfilingInfo :: 
-  CLEvent -> CLProfilingInfo_ -> CSize -> Ptr () -> Ptr CSize -> IO CLint
-
--- -----------------------------------------------------------------------------
--- | Waits on the host thread for commands identified by event objects in 
--- event_list to complete. A command is considered complete if its execution 
--- status is 'CL_COMPLETE' or a negative value.
--- Returns 'True' if the function was executed successfully. It returns 'False'
--- if the list of events is empty, or if events specified in event_list do not 
--- belong to the same context, or if event objects specified in event_list are 
--- not valid event objects.
-clWaitForEvents :: [CLEvent] -> IO Bool
-clWaitForEvents [] = return False
-clWaitForEvents xs = allocaArray nevents $ \pevents -> do
-  pokeArray pevents xs
-  wrapCheckSuccess $ raw_clWaitForEvents (fromIntegral nevents) pevents
-    where
-      nevents = length xs
-  
--- | Increments the event reference count.
--- The OpenCL commands that return an event perform an implicit retain.
--- Returns 'True' if the function is executed successfully. It returns 'False' 
--- if event is not a valid event object.
-clRetainEvent :: CLEvent -> IO Bool
-clRetainEvent ev = wrapCheckSuccess $ raw_clRetainEvent ev
-
--- | Decrements the event reference count.
--- Decrements the event reference count. The event object is deleted once the 
--- reference count becomes zero, the specific command identified by this event 
--- has completed (or terminated) and there are no commands in the command-queues 
--- of a context that require a wait for this event to complete.
--- Returns 'True' if the function is executed successfully. It returns 'False' 
--- if event is not a valid event object.
-clReleaseEvent :: CLEvent -> IO Bool
-clReleaseEvent ev = wrapCheckSuccess $ raw_clReleaseEvent ev
-
-#c
-enum CLEventInfo {
-  cL_EVENT_COMMAND_QUEUE=CL_EVENT_COMMAND_QUEUE,
-  cL_EVENT_COMMAND_TYPE=CL_EVENT_COMMAND_TYPE,
-  cL_EVENT_COMMAND_EXECUTION_STATUS=CL_EVENT_COMMAND_EXECUTION_STATUS,
-  cL_EVENT_REFERENCE_COUNT=CL_EVENT_REFERENCE_COUNT
-  };
-#endc
-{#enum CLEventInfo {upcaseFirstLetter} #}
-
-
--- | Return the command-queue associated with event.
---
--- This function execute OpenCL clGetEventInfo with 'CL_EVENT_COMMAND_QUEUE'.
-clGetEventCommandQueue :: CLEvent -> IO CLCommandQueue
-clGetEventCommandQueue ev =
-    wrapGetInfo (\(dat :: Ptr CLCommandQueue) ->
-        raw_clGetEventInfo ev infoid size (castPtr dat)) id
-    where 
-      infoid = getCLValue CL_EVENT_COMMAND_QUEUE
-      size = fromIntegral $ sizeOf (nullPtr::CLCommandQueue)
-      
--- | Return the command associated with event.
---
--- This function execute OpenCL clGetEventInfo with 'CL_EVENT_COMMAND_TYPE'.
-clGetEventCommandType :: CLEvent -> IO CLCommandType
-clGetEventCommandType ev =
-    wrapGetInfo (\(dat :: Ptr CLCommandType_) ->
-        raw_clGetEventInfo ev infoid size (castPtr dat)) getEnumCL
-    where 
-      infoid = getCLValue CL_EVENT_COMMAND_TYPE
-      size = fromIntegral $ sizeOf (0::CLCommandType_)
-      
--- | Return the event reference count. The reference count returned should be 
--- considered immediately stale. It is unsuitable for general use in applications. 
--- This feature is provided for identifying memory leaks.
---
--- This function execute OpenCL clGetEventInfo with 'CL_EVENT_REFERENCE_COUNT'.
-clGetEventReferenceCount :: CLEvent -> IO CLint
-clGetEventReferenceCount ev =
-    wrapGetInfo (\(dat :: Ptr CLint) ->
-        raw_clGetEventInfo ev infoid size (castPtr dat)) id
-    where 
-      infoid = getCLValue CL_EVENT_REFERENCE_COUNT
-      size = fromIntegral $ sizeOf (0::CLint)
-
--- | Return the execution status of the command identified by event.
---
--- This function execute OpenCL clGetEventInfo with
--- 'CL_EVENT_COMMAND_EXECUTION_STATUS'.
-clGetEventCommandExecutionStatus :: CLEvent -> IO CLCommandExecutionStatus
-clGetEventCommandExecutionStatus ev =
-    wrapGetInfo (\(dat :: Ptr CLint) ->
-        raw_clGetEventInfo ev infoid size (castPtr dat)) getCommandExecutionStatus
-    where 
-      infoid = getCLValue CL_EVENT_COMMAND_EXECUTION_STATUS
-      size = fromIntegral $ sizeOf (0::CLint)
-      
-{-| Returns profiling information for the command associated with event if 
-profiling is enabled. The unsigned 64-bit values returned can be used to measure 
-the time in nano-seconds consumed by OpenCL commands.
-
-OpenCL devices are required to correctly track time across changes in device 
-frequency and power states. The 'CL_DEVICE_PROFILING_TIMER_RESOLUTION' specifies 
-the resolution of the timer i.e. the number of nanoseconds elapsed before the 
-timer is incremented.
-
-Event objects can be used to capture profiling information that measure 
-execution time of a command. Profiling of OpenCL commands can be enabled either 
-by using a command-queue created with 'CL_QUEUE_PROFILING_ENABLE' flag set in 
-properties argument to clCreateCommandQueue or by setting the 
-'CL_QUEUE_PROFILING_ENABLE' flag in properties argument to 
-'clSetCommandQueueProperty'.
-
-'clGetEventProfilingInfo' returns the valueif the function is executed 
-successfully and the profiling information has been recorded, and returns 
-'Nothing'  if the 'CL_QUEUE_PROFILING_ENABLE' flag is not set for the 
-command-queue and if the profiling information is currently not available 
-(because the command identified by event has not completed), or if event is a 
-not a valid event object.
--} 
-clGetEventProfilingInfo :: CLEvent -> CLProfilingInfo -> IO CLulong
-clGetEventProfilingInfo ev prof =
-    wrapGetInfo (\(dat :: Ptr CLulong) ->
-        raw_clGetEventProfilingInfo ev infoid size (castPtr dat)) id
-    where 
-      infoid = getCLValue prof
-      size = fromIntegral $ sizeOf (0::CLulong)
-
--- -----------------------------------------------------------------------------
diff --git a/src/System/GPU/OpenCL/Memory.chs b/src/System/GPU/OpenCL/Memory.chs
deleted file mode 100644
--- a/src/System/GPU/OpenCL/Memory.chs
+++ /dev/null
@@ -1,341 +0,0 @@
-{- Copyright (c) 2011 Luis Cabellos,
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above
-      copyright notice, this list of conditions and the following
-      disclaimer in the documentation and/or other materials provided
-      with the distribution.
-
-    * Neither the name of  nor the names of other
-      contributors may be used to endorse or promote products derived
-      from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--}
-{-# LANGUAGE ForeignFunctionInterface, ScopedTypeVariables, CPP #-}
-module System.GPU.OpenCL.Memory(
-  -- * Types
-  CLMem, CLSampler, CLMemFlag(..), CLMemObjectType(..), CLAddressingMode(..), 
-  CLFilterMode(..),
-  -- * Memory Functions
-  clCreateBuffer, clRetainMemObject, clReleaseMemObject, clGetMemType, 
-  clGetMemFlags, clGetMemSize, clGetMemHostPtr, clGetMemMapCount, 
-  clGetMemReferenceCount, clGetMemContext,
-  -- * Sampler Functions
-  clCreateSampler, clRetainSampler, clReleaseSampler, clGetSamplerReferenceCount, 
-  clGetSamplerContext, clGetSamplerAddressingMode, clGetSamplerFilterMode, 
-  clGetSamplerNormalizedCoords
-  ) where
-
--- -----------------------------------------------------------------------------
-import Foreign
-import Foreign.C.Types
-import System.GPU.OpenCL.Types( 
-  CLMem, CLContext, CLSampler, CLint, CLuint, CLbool, CLMemFlags_,
-  CLMemInfo_, CLAddressingMode_, CLFilterMode_, CLSamplerInfo_, 
-  CLAddressingMode(..), CLFilterMode(..), CLMemFlag(..), CLMemObjectType_, 
-  CLMemObjectType(..), 
-  wrapPError, wrapCheckSuccess, wrapGetInfo, getEnumCL, bitmaskFromFlags, 
-  bitmaskToMemFlags, getCLValue )
-
-#include <CL/cl.h>
-
--- -----------------------------------------------------------------------------
-foreign import CALLCONV "clCreateBuffer" raw_clCreateBuffer :: 
-  CLContext -> CLMemFlags_ -> CSize -> Ptr () -> Ptr CLint -> IO CLMem
---foreign import CALLCONV "clCreateImage2D" raw_clCreateImage2D :: 
---  CLContext -> CLMemFlags_ -> CLImageFormat_p -> CSize -> CSize -> CSize 
---  -> Ptr () -> Ptr CLint -> IO CLMem
---foreign import CALLCONV "clCreateImage3D" raw_clCreateImage3D :: 
---  CLContext -> CLMemFlags_-> CLImageFormat_p -> CSize -> CSize -> CSize -> CSize 
---  -> CSize -> Ptr () -> Ptr CLint -> IO CLMem
-foreign import CALLCONV "clRetainMemObject" raw_clRetainMemObject :: 
-  CLMem -> IO CLint
-foreign import CALLCONV "clReleaseMemObject" raw_clReleaseMemObject :: 
-  CLMem -> IO CLint
---foreign import CALLCONV "clGetSupportedImageFormats" raw_clGetSupportedImageFormats :: 
---  CLContext -> CLMemFlags_ -> CLMemObjectType_ -> CLuint -> CLImageFormat_p 
---  -> Ptr CLuint -> IO CLint
-foreign import CALLCONV "clGetMemObjectInfo" raw_clGetMemObjectInfo :: 
-  CLMem -> CLMemInfo_ -> CSize -> Ptr () -> Ptr CSize -> IO CLint
---foreign import CALLCONV "clGetImageInfo" raw_clGetImageInfo :: 
---  CLMem -> CLImageInfo_ -> CSize -> Ptr () -> Ptr CSize -> IO CLint
-foreign import CALLCONV "clCreateSampler" raw_clCreateSampler :: 
-  CLContext -> CLbool -> CLAddressingMode_ -> CLFilterMode_ -> Ptr CLint -> IO CLSampler
-foreign import CALLCONV "clRetainSampler" raw_clRetainSampler :: 
-  CLSampler -> IO CLint
-foreign import CALLCONV "clReleaseSampler" raw_clReleaseSampler :: 
-  CLSampler -> IO CLint
-foreign import CALLCONV "clGetSamplerInfo" raw_clGetSamplerInfo :: 
-  CLSampler -> CLSamplerInfo_ -> CSize -> Ptr () -> Ptr CSize -> IO CLint
-
--- -----------------------------------------------------------------------------
-{-| Creates a buffer object. Returns a valid non-zero buffer object if the
-buffer object is created successfully. Otherwise, it throws the 'CLError': 
-
- * 'CL_INVALID_CONTEXT' if context is not a valid context.
-
- * 'CL_INVALID_VALUE' if values specified in flags are not valid.
-
- * 'CL_INVALID_BUFFER_SIZE' if size is 0 or is greater than
-'clDeviceMaxMemAllocSize' value for all devices in context.
-
- * 'CL_INVALID_HOST_PTR' if host_ptr is NULL and 'CL_MEM_USE_HOST_PTR' or
-'CL_MEM_COPY_HOST_PTR' are set in flags or if host_ptr is not NULL but
-'CL_MEM_COPY_HOST_PTR' or 'CL_MEM_USE_HOST_PTR' are not set in flags.
-
- * 'CL_MEM_OBJECT_ALLOCATION_FAILURE' if there is a failure to allocate memory
-for buffer object.
-
- * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
-by the OpenCL implementation on the host.
--}
-clCreateBuffer :: Integral a => CLContext -> [CLMemFlag] -> (a, Ptr ()) -> IO CLMem
-clCreateBuffer ctx xs (sbuff,buff) = wrapPError $ \perr -> do
-  raw_clCreateBuffer ctx flags (fromIntegral sbuff) buff perr
-    where
-      flags = bitmaskFromFlags xs
-    
--- | Increments the memory object reference count. returns 'True' if the
--- function is executed successfully. After the memobj reference count becomes
--- zero and commands queued for execution on a command-queue(s) that use memobj
--- have finished, the memory object is deleted. It returns 'False' if memobj is
--- not a valid memory object.
-clRetainMemObject :: CLMem -> IO Bool
-clRetainMemObject mem = wrapCheckSuccess $ raw_clRetainMemObject mem
-
--- | Decrements the memory object reference count. After the memobj reference
--- count becomes zero and commands queued for execution on a command-queue(s)
--- that use memobj have finished, the memory object is deleted. Returns 'True'
--- if the function is executed successfully. It returns 'False' if memobj is not
--- a valid memory object.
-clReleaseMemObject :: CLMem -> IO Bool
-clReleaseMemObject mem = wrapCheckSuccess $ raw_clReleaseMemObject mem
-
-#c
-enum CLMemInfo {
-  cL_MEM_TYPE=CL_MEM_TYPE,
-  cL_MEM_FLAGS=CL_MEM_FLAGS,
-  cL_MEM_SIZE=CL_MEM_SIZE,
-  cL_MEM_HOST_PTR=CL_MEM_HOST_PTR,
-  cL_MEM_MAP_COUNT=CL_MEM_MAP_COUNT,
-  cL_MEM_REFERENCE_COUNT=CL_MEM_REFERENCE_COUNT,
-  cL_MEM_CONTEXT=CL_MEM_CONTEXT,
-  };
-#endc
-{#enum CLMemInfo {upcaseFirstLetter} #}
-
--- | Returns the mem object type.
---
--- This function execute OpenCL clGetMemObjectInfo with 'CL_MEM_TYPE'.
-clGetMemType :: CLMem -> IO CLMemObjectType
-clGetMemType mem =
-    wrapGetInfo (\(dat :: Ptr CLMemObjectType_) ->
-        raw_clGetMemObjectInfo mem infoid size (castPtr dat)) getEnumCL
-    where 
-      infoid = getCLValue CL_MEM_TYPE
-      size = fromIntegral $ sizeOf (0::CLMemObjectType_)
-
--- | Return the flags argument value specified when memobj was created.
---
--- This function execute OpenCL clGetMemObjectInfo with 'CL_MEM_FLAGS'.
-clGetMemFlags :: CLMem -> IO [CLMemFlag]
-clGetMemFlags mem =
-    wrapGetInfo (\(dat :: Ptr CLMemFlags_)->
-        raw_clGetMemObjectInfo mem infoid size (castPtr dat)) bitmaskToMemFlags
-    where 
-      infoid = getCLValue CL_MEM_FLAGS
-      size = fromIntegral $ sizeOf (0::CLMemFlags_)
-
--- | Return actual size of memobj in bytes.
---
--- This function execute OpenCL clGetMemObjectInfo with 'CL_MEM_SIZE'.
-clGetMemSize :: CLMem -> IO CSize
-clGetMemSize mem =
-    wrapGetInfo (\(dat :: Ptr CSize)->
-        raw_clGetMemObjectInfo mem infoid size (castPtr dat)) id
-    where 
-      infoid = getCLValue CL_MEM_SIZE
-      size = fromIntegral $ sizeOf (0::CSize)
-
--- | Return the host_ptr argument value specified when memobj is created.
---
--- This function execute OpenCL clGetMemObjectInfo with 'CL_MEM_HOST_PTR'.
-clGetMemHostPtr :: CLMem -> IO (Ptr ())
-clGetMemHostPtr mem =
-    wrapGetInfo (\(dat :: Ptr (Ptr ()))->
-        raw_clGetMemObjectInfo mem infoid size (castPtr dat)) id
-    where 
-      infoid = getCLValue CL_MEM_HOST_PTR
-      size = fromIntegral $ sizeOf (nullPtr::Ptr ())
-
--- | Map count. The map count returned should be considered immediately
--- stale. It is unsuitable for general use in applications. This feature is
--- provided for debugging.
---
--- This function execute OpenCL clGetMemObjectInfo with 'CL_MEM_MAP_COUNT'.
-clGetMemMapCount :: CLMem -> IO CLuint
-clGetMemMapCount mem =
-    wrapGetInfo (\(dat :: Ptr CLuint)->
-        raw_clGetMemObjectInfo mem infoid size (castPtr dat)) id
-    where 
-      infoid = getCLValue CL_MEM_MAP_COUNT
-      size = fromIntegral $ sizeOf (0 :: CLuint)
-
--- | Return memobj reference count. The reference count returned should be
--- considered immediately stale. It is unsuitable for general use in
--- applications. This feature is provided for identifying memory leaks.
---
--- This function execute OpenCL clGetMemObjectInfo with 'CL_MEM_REFERENCE_COUNT'.
-clGetMemReferenceCount :: CLMem -> IO CLuint
-clGetMemReferenceCount mem =
-    wrapGetInfo (\(dat :: Ptr CLuint)->
-        raw_clGetMemObjectInfo mem infoid size (castPtr dat)) id
-    where 
-      infoid = getCLValue CL_MEM_REFERENCE_COUNT
-      size = fromIntegral $ sizeOf (0 :: CLuint)
-
--- | Return context specified when memory object is created.
---
--- This function execute OpenCL clGetMemObjectInfo with 'CL_MEM_CONTEXT'.
-clGetMemContext :: CLMem -> IO CLContext
-clGetMemContext mem =
-    wrapGetInfo (\(dat :: Ptr CLContext)->
-        raw_clGetMemObjectInfo mem infoid size (castPtr dat)) id
-    where 
-      infoid = getCLValue CL_MEM_CONTEXT
-      size = fromIntegral $ sizeOf (0 :: CLuint)
-
--- -----------------------------------------------------------------------------
-{-| Creates a sampler object. A sampler object describes how to sample an image
-when the image is read in the kernel. The built-in functions to read from an
-image in a kernel take a sampler as an argument. The sampler arguments to the
-image read function can be sampler objects created using OpenCL functions and
-passed as argument values to the kernel or can be samplers declared inside a
-kernel. In this section we discuss how sampler objects are created using OpenCL
-functions.
-
-Returns a valid non-zero sampler object if the sampler object is created
-successfully. Otherwise, it throws one of the following 'CLError' exceptions:
-
- * 'CL_INVALID_CONTEXT' if context is not a valid context.
-
- * 'CL_INVALID_VALUE' if addressing_mode, filter_mode, or normalized_coords or a
-combination of these argument values are not valid.
-
- * 'CL_INVALID_OPERATION' if images are not supported by any device associated
-with context (i.e. 'CL_DEVICE_IMAGE_SUPPORT' specified in the table of OpenCL
-Device Queries for clGetDeviceInfo is 'False').
-
- * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
-by the OpenCL implementation on the host.
--}
-clCreateSampler :: CLContext -> Bool -> CLAddressingMode -> CLFilterMode 
-                   -> IO CLSampler
-clCreateSampler ctx norm am fm = wrapPError $ \perr -> do
-  raw_clCreateSampler ctx (fromBool norm) (getCLValue am) (getCLValue fm) perr
-
--- | Increments the sampler reference count. 'clCreateSampler' does an implicit
--- retain. Returns 'True' if the function is executed successfully. It returns
--- 'False' if sampler is not a valid sampler object.
-clRetainSampler :: CLSampler -> IO Bool
-clRetainSampler mem = wrapCheckSuccess $ raw_clRetainSampler mem
-
--- | Decrements the sampler reference count. The sampler object is deleted after
--- the reference count becomes zero and commands queued for execution on a
--- command-queue(s) that use sampler have finished. 'clReleaseSampler' returns
--- 'True' if the function is executed successfully. It returns 'False' if
--- sampler is not a valid sampler object.
-clReleaseSampler :: CLSampler -> IO Bool
-clReleaseSampler mem = wrapCheckSuccess $ raw_clReleaseSampler mem
-
-#c
-enum CLSamplerInfo {
-  cL_SAMPLER_REFERENCE_COUNT=CL_SAMPLER_REFERENCE_COUNT,
-  cL_SAMPLER_CONTEXT=CL_SAMPLER_CONTEXT,
-  cL_SAMPLER_ADDRESSING_MODE=CL_SAMPLER_ADDRESSING_MODE,
-  cL_SAMPLER_FILTER_MODE=CL_SAMPLER_FILTER_MODE,
-  cL_SAMPLER_NORMALIZED_COORDS=CL_SAMPLER_NORMALIZED_COORDS
-  };
-#endc
-{#enum CLSamplerInfo {upcaseFirstLetter} #}
-
--- | Return the sampler reference count. The reference count returned should be
--- considered immediately stale. It is unsuitable for general use in
--- applications. This feature is provided for identifying memory leaks.
---
--- This function execute OpenCL clGetSamplerInfo with
--- 'CL_SAMPLER_REFERENCE_COUNT'.
-clGetSamplerReferenceCount :: CLSampler -> IO CLuint
-clGetSamplerReferenceCount sam =
-    wrapGetInfo (\(dat :: Ptr CLuint)->
-        raw_clGetSamplerInfo sam infoid size (castPtr dat)) id
-    where 
-      infoid = getCLValue CL_SAMPLER_REFERENCE_COUNT
-      size = fromIntegral $ sizeOf (0 :: CLuint)
-
--- | Return the context specified when the sampler is created.
---
--- This function execute OpenCL clGetSamplerInfo with 'CL_SAMPLER_CONTEXT'.
-clGetSamplerContext :: CLSampler -> IO CLContext
-clGetSamplerContext sam =
-    wrapGetInfo (\(dat :: Ptr CLContext)->
-        raw_clGetSamplerInfo sam infoid size (castPtr dat)) id
-    where 
-      infoid = getCLValue CL_SAMPLER_CONTEXT
-      size = fromIntegral $ sizeOf (nullPtr :: CLContext)
-
--- | Return the value specified by addressing_mode argument to clCreateSampler.
---
--- This function execute OpenCL clGetSamplerInfo with
--- 'CL_SAMPLER_ADDRESSING_MODE'.
-clGetSamplerAddressingMode :: CLSampler -> IO CLAddressingMode
-clGetSamplerAddressingMode sam =
-    wrapGetInfo (\(dat :: Ptr CLAddressingMode_)->
-        raw_clGetSamplerInfo sam infoid size (castPtr dat)) getEnumCL
-    where 
-      infoid = getCLValue CL_SAMPLER_ADDRESSING_MODE
-      size = fromIntegral $ sizeOf (0 :: CLAddressingMode_)
-
--- | Return the value specified by filter_mode argument to clCreateSampler.
---
--- This function execute OpenCL clGetSamplerInfo with 'CL_SAMPLER_FILTER_MODE'.
-clGetSamplerFilterMode :: CLSampler -> IO CLFilterMode
-clGetSamplerFilterMode sam =
-    wrapGetInfo (\(dat :: Ptr CLFilterMode_)->
-        raw_clGetSamplerInfo sam infoid size (castPtr dat)) getEnumCL
-    where 
-      infoid = getCLValue CL_SAMPLER_FILTER_MODE
-      size = fromIntegral $ sizeOf (0 :: CLFilterMode_)
-
--- | Return the value specified by normalized_coords argument to
--- clCreateSampler.
---
--- This function execute OpenCL clGetSamplerInfo with
--- 'CL_SAMPLER_NORMALIZED_COORDS'.
-clGetSamplerNormalizedCoords :: CLSampler -> IO Bool
-clGetSamplerNormalizedCoords sam =
-    wrapGetInfo (\(dat :: Ptr CLbool)->
-        raw_clGetSamplerInfo sam infoid size (castPtr dat)) (/=0)
-    where 
-      infoid = getCLValue CL_SAMPLER_NORMALIZED_COORDS
-      size = fromIntegral $ sizeOf (0 :: CLbool)
-
--- -----------------------------------------------------------------------------
diff --git a/src/System/GPU/OpenCL/Program.chs b/src/System/GPU/OpenCL/Program.chs
deleted file mode 100644
--- a/src/System/GPU/OpenCL/Program.chs
+++ /dev/null
@@ -1,830 +0,0 @@
-{- Copyright (c) 2011 Luis Cabellos,
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above
-      copyright notice, this list of conditions and the following
-      disclaimer in the documentation and/or other materials provided
-      with the distribution.
-
-    * Neither the name of  nor the names of other
-      contributors may be used to endorse or promote products derived
-      from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--}
-{-# LANGUAGE ForeignFunctionInterface, ScopedTypeVariables, CPP #-}
-module System.GPU.OpenCL.Program(  
-  -- * Types
-  CLProgram, CLBuildStatus(..), CLKernel,
-  -- * Program Functions
-  clCreateProgramWithSource, clCreateProgramWithBinary, clRetainProgram, 
-  clReleaseProgram, clUnloadCompiler, clBuildProgram, 
-  clGetProgramReferenceCount, clGetProgramContext, clGetProgramNumDevices, 
-  clGetProgramDevices, clGetProgramSource, clGetProgramBinarySizes, 
-  clGetProgramBinaries, clGetProgramBuildStatus, clGetProgramBuildOptions, 
-  clGetProgramBuildLog,
-  -- * Kernel Functions
-  clCreateKernel, clCreateKernelsInProgram, clRetainKernel, clReleaseKernel, 
-  clSetKernelArg, clGetKernelFunctionName, clGetKernelNumArgs, 
-  clGetKernelReferenceCount, clGetKernelContext, clGetKernelProgram, 
-  clGetKernelWorkGroupSize, clGetKernelCompileWorkGroupSize, 
-  clGetKernelLocalMemSize
-  ) where
-
--- -----------------------------------------------------------------------------
-import Control.Monad( zipWithM, forM )
-import Foreign
-import Foreign.C.Types
-import Foreign.C.String( CString, withCString, peekCString )
-import System.GPU.OpenCL.Types( 
-  CLint, CLuint, CLulong, CLProgram, CLContext, CLKernel, CLDeviceID, CLError,
-  CLProgramInfo_, CLBuildStatus(..), CLBuildStatus_, CLProgramBuildInfo_, 
-  CLKernelInfo_, CLKernelWorkGroupInfo_, wrapCheckSuccess, 
-  whenSuccess, wrapPError, wrapGetInfo, getCLValue, getEnumCL )
-
-#include <CL/cl.h>
-
--- -----------------------------------------------------------------------------
-type BuildCallback = CLProgram -> Ptr () -> IO ()
-foreign import CALLCONV "clCreateProgramWithSource" raw_clCreateProgramWithSource :: 
-  CLContext -> CLuint -> Ptr CString -> Ptr CSize -> Ptr CLint -> IO CLProgram
-foreign import CALLCONV "clCreateProgramWithBinary" raw_clCreateProgramWithBinary :: 
-  CLContext -> CLuint -> Ptr CLDeviceID -> Ptr CSize -> Ptr (Ptr Word8) -> Ptr CLint -> Ptr CLint -> IO CLProgram
-foreign import CALLCONV "clRetainProgram" raw_clRetainProgram :: 
-  CLProgram -> IO CLint
-foreign import CALLCONV "clReleaseProgram" raw_clReleaseProgram :: 
-  CLProgram -> IO CLint
-foreign import CALLCONV "clBuildProgram" raw_clBuildProgram :: 
-  CLProgram -> CLuint -> Ptr CLDeviceID -> CString -> FunPtr BuildCallback -> Ptr () -> IO CLint
-foreign import CALLCONV "clUnloadCompiler" raw_clUnloadCompiler :: 
-  IO CLint
-foreign import CALLCONV "clGetProgramInfo" raw_clGetProgramInfo :: 
-  CLProgram -> CLProgramInfo_ -> CSize -> Ptr () -> Ptr CSize -> IO CLint
-foreign import CALLCONV "clGetProgramBuildInfo"  raw_clGetProgramBuildInfo :: 
-  CLProgram -> CLDeviceID -> CLProgramBuildInfo_ -> CSize -> Ptr () -> Ptr CSize -> IO CLint
-foreign import CALLCONV "clCreateKernel" raw_clCreateKernel :: 
-  CLProgram -> CString -> Ptr CLint -> IO CLKernel 
-foreign import CALLCONV "clCreateKernelsInProgram" raw_clCreateKernelsInProgram :: 
-  CLProgram -> CLuint -> Ptr CLKernel -> Ptr CLuint -> IO CLint 
-foreign import CALLCONV "clRetainKernel" raw_clRetainKernel :: 
-  CLKernel -> IO CLint 
-foreign import CALLCONV "clReleaseKernel" raw_clReleaseKernel :: 
-  CLKernel -> IO CLint 
-foreign import CALLCONV "clSetKernelArg" raw_clSetKernelArg :: 
-  CLKernel -> CLuint -> CSize -> Ptr () -> IO CLint
-foreign import CALLCONV "clGetKernelInfo" raw_clGetKernelInfo :: 
-  CLKernel -> CLKernelInfo_ -> CSize -> Ptr () -> Ptr CSize -> IO CLint
-foreign import CALLCONV "clGetKernelWorkGroupInfo" raw_clGetKernelWorkGroupInfo :: 
-  CLKernel -> CLDeviceID -> CLKernelWorkGroupInfo_ -> CSize -> Ptr () -> Ptr CSize -> IO CLint
-
--- -----------------------------------------------------------------------------
-{-| Creates a program object for a context, and loads the source code specified
-by the text strings in the strings array into the program object. The devices
-associated with the program object are the devices associated with context.
-
-OpenCL allows applications to create a program object using the program source
-or binary and build appropriate program executables. This allows applications to
-determine whether they want to use the pre-built offline binary or load and
-compile the program source and use the executable compiled/linked online as the
-program executable. This can be very useful as it allows applications to load
-and build program executables online on its first instance for appropriate
-OpenCL devices in the system. These executables can now be queried and cached by
-the application. Future instances of the application launching will no longer
-need to compile and build the program executables. The cached executables can be
-read and loaded by the application, which can help significantly reduce the
-application initialization time.
-
-An OpenCL program consists of a set of kernels that are identified as functions
-declared with the __kernel qualifier in the program source. OpenCL programs may
-also contain auxiliary functions and constant data that can be used by __kernel
-functions. The program executable can be generated online or offline by the
-OpenCL compiler for the appropriate target device(s).
-
-'clCreateProgramWithSource' returns a valid non-zero program object if the
-program object is created successfully. Otherwise, it throws one of the
-following 'CLError' exceptions:
-
- * 'CL_INVALID_CONTEXT' if context is not a valid context.
-
- * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
-by the OpenCL implementation on the host.  
--}
-clCreateProgramWithSource :: CLContext -> String -> IO CLProgram
-clCreateProgramWithSource ctx source =
-  withCString source $ \cSource ->
-  withArray [cSource] $ \sourcesP ->
-  wrapPError (raw_clCreateProgramWithSource ctx 1 sourcesP nullPtr)
-
-{-| Creates a program object for a context, and loads specified binary data into
-the program object.
-
-The program binaries specified by binaries contain the bits that describe the
-program executable that will be run on the device(s) associated with
-context. The program binary can consist of either or both of device-specific
-executable(s), and/or implementation-specific intermediate representation (IR)
-which will be converted to the device-specific executable.
-
-OpenCL allows applications to create a program object using the program
-source or binary and build appropriate program executables. This allows
-applications to determine whether they want to use the pre-built offline binary
-or load and compile the program source and use the executable compiled/linked
-online as the program executable. This can be very useful as it allows
-applications to load and build program executables online on its first instance
-for appropriate OpenCL devices in the system. These executables can now be
-queried and cached by the application. Future instances of the application
-launching will no longer need to compile and build the program executables. The
-cached executables can be read and loaded by the application, which can help
-significantly reduce the application initialization time.
-
-Returns a valid non-zero program object and a list of 'CLError' values whether
-the program binary for each device specified in device_list was loaded
-successfully or not. It is list of the same length the list of devices with
-'CL_SUCCESS' if binary was successfully loaded for device specified by same
-position; otherwise returns 'CL_INVALID_VALUE' if length of binary is zero or
-'CL_INVALID_BINARY' if program binary is not a valid binary
-for the specified device.
-
-The function can throw on of the following 'CLError' exceptions:
-
- * 'CL_INVALID_CONTEXT' if context is not a valid context.  
-
- * 'CL_INVALID_VALUE' if the device list is empty; or if lengths or binaries are
-empty.
-
- * 'CL_INVALID_DEVICE' if OpenCL devices listed in the device list are not in
-the list of devices associated with context.
-
- * 'CL_INVALID_BINARY' if an invalid program binary was encountered for any
-device.
-
- * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
-by the OpenCL implementation on the host.  
--} 
-clCreateProgramWithBinary :: CLContext -> [CLDeviceID] -> [[Word8]] 
-                             -> IO (CLProgram, [CLError])
-clCreateProgramWithBinary ctx devs bins = wrapPError $ \perr ->
-  withArray devs $ \pdevs ->
-    withArray lbins $ \plbins -> do
-      buffs <- forM bins $ \bs -> do
-        buff <- mallocArray (length bs) :: IO (Ptr Word8)
-        pokeArray buff bs
-        return buff
-
-      ret <- withArray buffs $ \(pbuffs :: Ptr (Ptr Word8)) -> do
-        allocaArray ndevs $ \(perrs :: Ptr CLint) -> do
-          prog <- raw_clCreateProgramWithBinary ctx (fromIntegral ndevs) pdevs plbins pbuffs perrs perr
-          errs <- peekArray ndevs perrs
-          return (prog, map getEnumCL errs)
-
-      mapM_ free buffs
-      return ret
-    
-    where
-      lbins = map (fromIntegral . length) bins :: [CSize]
-      ndevs = length devs
-
--- | Increments the program reference count. 'clRetainProgram' returns 'True' if 
--- the function is executed successfully. It returns 'False' if program is not a 
--- valid program object.
-clRetainProgram :: CLProgram -> IO Bool
-clRetainProgram prg = wrapCheckSuccess $ raw_clRetainProgram prg
-
--- | Decrements the program reference count. The program object is deleted after 
--- all kernel objects associated with program have been deleted and the program 
--- reference count becomes zero. 'clReleseProgram' returns 'True' if 
--- the function is executed successfully. It returns 'False' if program is not a 
--- valid program object.
-clReleaseProgram :: CLProgram -> IO Bool
-clReleaseProgram prg = wrapCheckSuccess $ raw_clReleaseProgram prg
-
--- | Allows the implementation to release the resources allocated by the OpenCL
--- compiler. This is a hint from the application and does not guarantee that the
--- compiler will not be used in the future or that the compiler will actually be
--- unloaded by the implementation. Calls to 'clBuildProgram' after
--- 'clUnloadCompiler' will reload the compiler, if necessary, to build the
--- appropriate program executable.
-clUnloadCompiler :: IO ()
-clUnloadCompiler = raw_clUnloadCompiler >> return ()
-
-{-| Builds (compiles and links) a program executable from the program source or
-binary. OpenCL allows program executables to be built using the source or the
-binary. The build options are categorized as pre-processor options, options for
-math intrinsics, options that control optimization and miscellaneous
-options. This specification defines a standard set of options that must be
-supported by an OpenCL compiler when building program executables online or
-offline. These may be extended by a set of vendor- or platform-specific options.
-
- * Preprocessor Options
-
-These options control the OpenCL preprocessor which is run on each program
-source before actual compilation. -D options are processed in the order they are
-given in the options argument to clBuildProgram.
-
- [-D name] Predefine name as a macro, with definition 1.
-
- [-D name=definition] The contents of definition are tokenized and processed as
-if they appeared during translation phase three in a `#define' directive. In
-particular, the definition will be truncated by embedded newline characters.
-
- [-I dir] Add the directory dir to the list of directories to be searched for
-header files.
-
- * Math Intrinsics Options
-
-These options control compiler behavior regarding floating-point
-arithmetic. These options trade off between speed and correctness.
-
- [-cl-single-precision-constant] Treat double precision floating-point constant
-as single precision constant.
-
- [-cl-denorms-are-zero] This option controls how single precision and double
-precision denormalized numbers are handled. If specified as a build option, the
-single precision denormalized numbers may be flushed to zero and if the optional
-extension for double precision is supported, double precision denormalized
-numbers may also be flushed to zero. This is intended to be a performance hint
-and the OpenCL compiler can choose not to flush denorms to zero if the device
-supports single precision (or double precision) denormalized numbers.
-
-This option is ignored for single precision numbers if the device does not
-support single precision denormalized numbers i.e. 'CL_FP_DENORM' bit is not set
-in 'clGetDeviceSingleFPConfig'.
-
-This option is ignored for double precision numbers if the device does not
-support double precision or if it does support double precison but
-'CL_FP_DENORM' bit is not set in 'clGetDeviceDoubleFPConfig'.
-
-This flag only applies for scalar and vector single precision floating-point
-variables and computations on these floating-point variables inside a
-program. It does not apply to reading from or writing to image objects.
-
- * Optimization Options
-
-These options control various sorts of optimizations. Turning on optimization
-flags makes the compiler attempt to improve the performance and/or code size at
-the expense of compilation time and possibly the ability to debug the program.
-
- [-cl-opt-disable] This option disables all optimizations. The default is
-optimizations are enabled.
-
- [-cl-strict-aliasing] This option allows the compiler to assume the strictest
-aliasing rules.
-
-The following options control compiler behavior regarding floating-point
-arithmetic. These options trade off between performance and correctness and must
-be specifically enabled. These options are not turned on by default since it can
-result in incorrect output for programs which depend on an exact implementation
-of IEEE 754 rules/specifications for math functions.
-
- [-cl-mad-enable] Allow a * b + c to be replaced by a mad. The mad computes a *
-b + c with reduced accuracy. For example, some OpenCL devices implement mad as
-truncate the result of a * b before adding it to c.
-
- [-cl-no-signed-zeros] Allow optimizations for floating-point arithmetic that
-ignore the signedness of zero. IEEE 754 arithmetic specifies the behavior of
-distinct +0.0 and -0.0 values, which then prohibits simplification of
-expressions such as x+0.0 or 0.0*x (even with -clfinite-math only). This option
-implies that the sign of a zero result isn't significant.
-
- [-cl-unsafe-math-optimizations] Allow optimizations for floating-point
-arithmetic that (a) assume that arguments and results are valid, (b) may violate
-IEEE 754 standard and (c) may violate the OpenCL numerical compliance
-requirements as defined in section 7.4 for single-precision floating-point,
-section 9.3.9 for double-precision floating-point, and edge case behavior in
-section 7.5. This option includes the -cl-no-signed-zeros and -cl-mad-enable
-options.
-
- [-cl-finite-math-only] Allow optimizations for floating-point arithmetic that
-assume that arguments and results are not NaNs or ±∞. This option may violate
-the OpenCL numerical compliance requirements defined in in section 7.4 for
-single-precision floating-point, section 9.3.9 for double-precision
-floating-point, and edge case behavior in section 7.5.
-
- [-cl-fast-relaxed-math] Sets the optimization options -cl-finite-math-only and
--cl-unsafe-math-optimizations. This allows optimizations for floating-point
-arithmetic that may violate the IEEE 754 standard and the OpenCL numerical
-compliance requirements defined in the specification in section 7.4 for
-single-precision floating-point, section 9.3.9 for double-precision
-floating-point, and edge case behavior in section 7.5. This option causes the
-preprocessor macro __FAST_RELAXED_MATH__ to be defined in the OpenCL program.
-
- * Options to Request or Suppress Warnings
-
-Warnings are diagnostic messages that report constructions which are not
-inherently erroneous but which are risky or suggest there may have been an
-error. The following languageindependent options do not enable specific warnings
-but control the kinds of diagnostics produced by the OpenCL compiler.
-
- [-w] Inhibit all warning messages.
- 
- [-Werror] Make all warnings into errors.
-
-clBuildProgram can throw the following 'CLError' exceptions when fails:
-
- * 'CL_INVALID_PROGRAM' if program is not a valid program object.
-
- * 'CL_INVALID_DEVICE' if OpenCL devices listed in device_list are not in the
-list of devices associated with program.
-
- * 'CL_INVALID_BINARY' if program is created with
-'clCreateWithProgramWithBinary' and devices listed in device_list do not have a
-valid program binary loaded.
-
- * 'CL_INVALID_BUILD_OPTIONS' if the build options specified by options are
-invalid.
-
- * 'CL_INVALID_OPERATION' if the build of a program executable for any of the
-devices listed in device_list by a previous call to 'clBuildProgram' for program
-has not completed.
-
- * 'CL_COMPILER_NOT_AVAILABLE' if program is created with
-'clCreateProgramWithSource' and a compiler is not available
-i.e. 'clGetDeviceCompilerAvailable' is set to 'False'.
-
- * 'CL_BUILD_PROGRAM_FAILURE' if there is a failure to build the program
-executable. This error will be returned if 'clBuildProgram' does not return
-until the build has completed.
-
- * 'CL_INVALID_OPERATION' if there are kernel objects attached to program.
-
- * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
-by the OpenCL implementation on the host.  
--}
-clBuildProgram :: CLProgram -> [CLDeviceID] -> String -> IO ()
-clBuildProgram prg devs opts = allocaArray ndevs $ \pdevs -> do
-  pokeArray pdevs devs
-  withCString opts $ \copts -> do
-    whenSuccess (raw_clBuildProgram prg cndevs pdevs copts nullFunPtr nullPtr)
-      $ return ()
-    where
-      ndevs = length devs
-      cndevs = fromIntegral ndevs
-
-#c
-enum CLProgramInfo {
-  cL_PROGRAM_REFERENCE_COUNT=CL_PROGRAM_REFERENCE_COUNT,
-  cL_PROGRAM_CONTEXT=CL_PROGRAM_CONTEXT,
-  cL_PROGRAM_NUM_DEVICES=CL_PROGRAM_NUM_DEVICES,
-  cL_PROGRAM_DEVICES=CL_PROGRAM_DEVICES,
-  cL_PROGRAM_SOURCE=CL_PROGRAM_SOURCE,
-  cL_PROGRAM_BINARY_SIZES=CL_PROGRAM_BINARY_SIZES,
-  cL_PROGRAM_BINARIES=CL_PROGRAM_BINARIES,
-  };
-#endc
-{#enum CLProgramInfo {upcaseFirstLetter} #}
-
-getProgramInfoSize :: CLProgram -> CLProgramInfo_ -> IO CSize
-getProgramInfoSize prg infoid = alloca $ \(value_size :: Ptr CSize) -> do
-  whenSuccess (raw_clGetProgramInfo prg infoid 0 nullPtr value_size)
-    $ peek value_size
-  
--- | Return the program reference count. The reference count returned should be
--- considered immediately stale. It is unsuitable for general use in
--- applications. This feature is provided for identifying memory leaks.
---
--- This function execute OpenCL clGetProgramInfo with
--- 'CL_PROGRAM_REFERENCE_COUNT'.
-clGetProgramReferenceCount :: CLProgram -> IO CLuint
-clGetProgramReferenceCount prg =
-    wrapGetInfo (\(dat :: Ptr CLuint) ->
-        raw_clGetProgramInfo prg infoid size (castPtr dat)) id
-    where 
-      infoid = getCLValue CL_PROGRAM_REFERENCE_COUNT
-      size = fromIntegral $ sizeOf (0::CLuint)
-
--- | Return the context specified when the program object is created.
---
--- This function execute OpenCL clGetProgramInfo with 'CL_PROGRAM_CONTEXT'.
-clGetProgramContext :: CLProgram -> IO CLContext
-clGetProgramContext prg =
-    wrapGetInfo (\(dat :: Ptr CLContext) ->
-        raw_clGetProgramInfo prg infoid size (castPtr dat)) id
-    where 
-      infoid = getCLValue CL_PROGRAM_CONTEXT
-      size = fromIntegral $ sizeOf (nullPtr::CLContext)
-
--- | Return the number of devices associated with program.
---
--- This function execute OpenCL clGetProgramInfo with 'CL_PROGRAM_NUM_DEVICES'.
-clGetProgramNumDevices :: CLProgram -> IO CLuint
-clGetProgramNumDevices prg =
-    wrapGetInfo (\(dat :: Ptr CLuint) ->
-        raw_clGetProgramInfo prg infoid size (castPtr dat)) id
-    where 
-      infoid = getCLValue CL_PROGRAM_NUM_DEVICES
-      size = fromIntegral $ sizeOf (0::CLuint)
-
--- | Return the list of devices associated with the program object. This can be
--- the devices associated with context on which the program object has been
--- created or can be a subset of devices that are specified when a progam object
--- is created using 'clCreateProgramWithBinary'.
---
--- This function execute OpenCL clGetProgramInfo with 'CL_PROGRAM_DEVICES'.
-clGetProgramDevices :: CLProgram -> IO [CLDeviceID]
-clGetProgramDevices prg = do
-  size <- getProgramInfoSize prg infoid
-  allocaArray (numElems size) $ \(buff :: Ptr CLDeviceID) -> do
-    whenSuccess (raw_clGetProgramInfo prg infoid size (castPtr buff) nullPtr)
-      $ peekArray (numElems size) buff
-    where 
-      infoid = getCLValue CL_PROGRAM_DEVICES
-      numElems s = (fromIntegral s) `div` elemSize
-      elemSize = sizeOf (nullPtr::CLDeviceID)
-
--- | Return the program source code specified by
--- 'clCreateProgramWithSource'. The source string returned is a concatenation of
--- all source strings specified to 'clCreateProgramWithSource' with a null
--- terminator. The concatenation strips any nulls in the original source
--- strings. The actual number of characters that represents the program source
--- code including the null terminator is returned in param_value_size_ret.
---
--- This function execute OpenCL clGetProgramInfo with 'CL_PROGRAM_SOURCE'.
-clGetProgramSource :: CLProgram -> IO String
-clGetProgramSource prg = do
-  n <- getProgramInfoSize prg infoid
-  allocaArray (fromIntegral n) $ \(buff :: CString) -> do
-    whenSuccess (raw_clGetProgramInfo prg infoid n (castPtr buff) nullPtr)
-      $ peekCString buff
-    where 
-      infoid = getCLValue CL_PROGRAM_SOURCE
-  
--- | Returns an array that contains the size in bytes of the program binary for
--- each device associated with program. The size of the array is the number of
--- devices associated with program. If a binary is not available for a
--- device(s), a size of zero is returned.
---
--- This function execute OpenCL clGetProgramInfo with 'CL_PROGRAM_BINARY_SIZES'.
-clGetProgramBinarySizes :: CLProgram -> IO [CSize]
-clGetProgramBinarySizes prg = do
-  size <- getProgramInfoSize prg infoid
-  allocaArray (numElems size) $ \(buff :: Ptr CSize) -> do
-    whenSuccess (raw_clGetProgramInfo prg infoid size (castPtr buff) nullPtr)
-      $ peekArray (numElems size) buff
-    where 
-      infoid = getCLValue CL_PROGRAM_BINARY_SIZES
-      numElems s = (fromIntegral s) `div` elemSize
-      elemSize = sizeOf (0::CSize)
-
-{-| Return the program binaries for all devices associated with program. For
-each device in program, the binary returned can be the binary specified for the
-device when program is created with 'clCreateProgramWithBinary' or it can be the
-executable binary generated by 'clBuildProgram'. If program is created with
-'clCreateProgramWithSource', the binary returned is the binary generated by
-'clBuildProgram'. The bits returned can be an implementation-specific
-intermediate representation (a.k.a. IR) or device specific executable bits or
-both. The decision on which information is returned in the binary is up to the
-OpenCL implementation.
-
-To find out which device the program binary in the array refers to, use the
-'clGetProgramDevices' query to get the list of devices. There is a one-to-one
-correspondence between the array of data returned by 'clGetProgramBinaries' and
-array of devices returned by 'clGetProgramDevices'.  
-
-This function execute OpenCL clGetProgramInfo with 'CL_PROGRAM_BINARIES'.
--}
-clGetProgramBinaries :: CLProgram -> IO [[Word8]]
-clGetProgramBinaries prg = do
-  sizes <- clGetProgramBinarySizes prg
-  let numElems = length sizes
-      size = fromIntegral $ numElems * elemSize
-  buffers <- (mapM (mallocArray.fromIntegral) sizes) :: IO [Ptr Word8]
-  ret <- withArray buffers $ \(parray :: Ptr (Ptr Word8)) -> do
-    whenSuccess (raw_clGetProgramInfo prg infoid size (castPtr parray) nullPtr)
-      $ zipWithM peekArray (map fromIntegral sizes) buffers
-  mapM_ free buffers
-  return ret
-    where 
-      infoid = getCLValue CL_PROGRAM_BINARIES
-      elemSize = sizeOf (nullPtr::Ptr Word8)
-
--- -----------------------------------------------------------------------------
-#c
-enum CLProgramBuildInfo {
-  cL_PROGRAM_BUILD_STATUS=CL_PROGRAM_BUILD_STATUS,
-  cL_PROGRAM_BUILD_OPTIONS=CL_PROGRAM_BUILD_OPTIONS,
-  cL_PROGRAM_BUILD_LOG=CL_PROGRAM_BUILD_LOG,
-  };
-#endc
-{#enum CLProgramBuildInfo {upcaseFirstLetter} #}
-
-getProgramBuildInfoSize :: CLProgram -> CLDeviceID -> CLProgramInfo_ -> IO CSize
-getProgramBuildInfoSize prg device infoid = alloca $ \(val :: Ptr CSize) -> do
-  whenSuccess (raw_clGetProgramBuildInfo prg device infoid 0 nullPtr val)
-    $ peek val
-  
--- | Returns the build status of program for a specific device as given by
--- device.
---
--- This function execute OpenCL clGetProgramBuildInfo with
--- 'CL_PROGRAM_BUILD_STATUS'.
-clGetProgramBuildStatus :: CLProgram -> CLDeviceID -> IO CLBuildStatus
-clGetProgramBuildStatus prg device =
-    wrapGetInfo (\(dat :: Ptr CLBuildStatus_) ->
-        raw_clGetProgramBuildInfo prg device infoid size (castPtr dat)) getEnumCL
-    where 
-      infoid = getCLValue CL_PROGRAM_BUILD_STATUS
-      size = fromIntegral $ sizeOf (0::CLBuildStatus_)
-
--- | Return the build options specified by the options argument in
--- clBuildProgram for device. If build status of program for device is
--- 'CL_BUILD_NONE', an empty string is returned.
---
--- This function execute OpenCL clGetProgramBuildInfo with
--- 'CL_PROGRAM_BUILD_OPTIONS'.
-clGetProgramBuildOptions :: CLProgram -> CLDeviceID -> IO String
-clGetProgramBuildOptions prg device = do
-  n <- getProgramBuildInfoSize prg device infoid
-  allocaArray (fromIntegral n) $ \(buff :: CString) -> do
-    whenSuccess (raw_clGetProgramBuildInfo prg device infoid n (castPtr buff) nullPtr)
-      $ peekCString buff
-    where 
-      infoid = getCLValue CL_PROGRAM_BUILD_OPTIONS
-  
--- | Return the build log when 'clBuildProgram' was called for device. If build
--- status of program for device is 'CL_BUILD_NONE', an empty string is returned.
---
--- This function execute OpenCL clGetProgramBuildInfo with
--- 'CL_PROGRAM_BUILD_LOG'.
-clGetProgramBuildLog :: CLProgram -> CLDeviceID -> IO String
-clGetProgramBuildLog prg device = do
-  n <- getProgramBuildInfoSize prg device infoid
-  allocaArray (fromIntegral n) $ \(buff :: CString) -> do
-    whenSuccess (raw_clGetProgramBuildInfo prg device infoid n (castPtr buff) nullPtr)
-      $ peekCString buff
-    where 
-      infoid = getCLValue CL_PROGRAM_BUILD_LOG
-  
--- -----------------------------------------------------------------------------
-{-| Creates a kernal object. A kernel is a function declared in a program. A
-kernel is identified by the __kernel qualifier applied to any function in a
-program. A kernel object encapsulates the specific __kernel function declared in
-a program and the argument values to be used when executing this __kernel
-function.
-
-'clCreateKernel' returns a valid non-zero kernel object if the kernel object is
-created successfully. Otherwise, it throws one of the following 'CLError'
-exceptions:
-
- * 'CL_INVALID_PROGRAM' if program is not a valid program object.
-
- * 'CL_INVALID_PROGRAM_EXECUTABLE' if there is no successfully built executable
- for program.
-
- * 'CL_INVALID_KERNEL_NAME' if kernel_name is not found in program.
-
- * 'CL_INVALID_KERNEL_DEFINITION' if the function definition for __kernel
-function given by kernel_name such as the number of arguments, the argument
-types are not the same for all devices for which the program executable has been
-built.
-
- * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
-by the OpenCL implementation on the host.  
--}
-clCreateKernel :: CLProgram -> String -> IO CLKernel
-clCreateKernel prg name = withCString name $ \cname -> wrapPError $ \perr -> do
-  raw_clCreateKernel prg cname perr
-
-{-| Creates kernel objects for all kernel functions in a program object. Kernel
-objects are not created for any __kernel functions in program that do not have
-the same function definition across all devices for which a program executable
-has been successfully built.
-
-Kernel objects can only be created once you have a program object with a valid
-program source or binary loaded into the program object and the program
-executable has been successfully built for one or more devices associated with
-program. No changes to the program executable are allowed while there are kernel
-objects associated with a program object. This means that calls to
-'clBuildProgram' return 'CL_INVALID_OPERATION' if there are kernel objects
-attached to a program object. The OpenCL context associated with program will be
-the context associated with kernel. The list of devices associated with program
-are the devices associated with kernel. Devices associated with a program object
-for which a valid program executable has been built can be used to execute
-kernels declared in the program object.
-
-'clCreateKernelsInProgram' will return the kernel objects if the kernel objects
-were successfully allocated, throws 'CL_INVALID_PROGRAM' if program is not a
-valid program object, throws 'CL_INVALID_PROGRAM_EXECUTABLE' if there is no
-successfully built executable for any device in program and throws
-'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required by
-the OpenCL implementation on the host.
--}
-clCreateKernelsInProgram :: CLProgram -> IO [CLKernel]
-clCreateKernelsInProgram prg = do
-  n <- alloca $ \pn -> do
-    whenSuccess (raw_clCreateKernelsInProgram prg 0 nullPtr pn)
-      $ peek pn  
-  allocaArray (fromIntegral n) $ \pks -> do
-    whenSuccess (raw_clCreateKernelsInProgram prg n pks nullPtr)
-      $ peekArray (fromIntegral n) pks
-
--- | Increments the program program reference count. 'clRetainKernel' returns
--- 'True' if the function is executed successfully. 'clCreateKernel' or
--- 'clCreateKernelsInProgram' do an implicit retain.
-clRetainKernel :: CLKernel -> IO Bool
-clRetainKernel krn = wrapCheckSuccess $ raw_clRetainKernel krn
-
--- | Decrements the kernel reference count. The kernel object is deleted once
--- the number of instances that are retained to kernel become zero and the
--- kernel object is no longer needed by any enqueued commands that use
--- kernel. 'clReleaseKernel' returns 'True' if the function is executed
--- successfully.
-clReleaseKernel :: CLKernel -> IO Bool
-clReleaseKernel krn = wrapCheckSuccess $ raw_clReleaseKernel krn
-
-{-| Used to set the argument value for a specific argument of a kernel.
-
-A kernel object does not update the reference count for objects such as memory,
-sampler objects specified as argument values by 'clSetKernelArg', Users may not
-rely on a kernel object to retain objects specified as argument values to the
-kernel.
-
-Implementations shall not allow 'CLKernel' objects to hold reference counts to
-'CLKernel' arguments, because no mechanism is provided for the user to tell the
-kernel to release that ownership right. If the kernel holds ownership rights on
-kernel args, that would make it impossible for the user to tell with certainty
-when he may safely release user allocated resources associated with OpenCL
-objects such as the CLMem backing store used with 'CL_MEM_USE_HOST_PTR'.
-
-'clSetKernelArg' throws one of the following 'CLError' exceptions when fails:
-
- * 'CL_INVALID_KERNEL' if kernel is not a valid kernel object.
- 
- * 'CL_INVALID_ARG_INDEX' if arg_index is not a valid argument index.
-
- * 'CL_INVALID_ARG_VALUE' if arg_value specified is NULL for an argument that is
-not declared with the __local qualifier or vice-versa.
-
- * 'CL_INVALID_MEM_OBJECT' for an argument declared to be a memory object when
-the specified arg_value is not a valid memory object.
-
- * 'CL_INVALID_SAMPLER' for an argument declared to be of type sampler_t when
-the specified arg_value is not a valid sampler object.
-
- * 'CL_INVALID_ARG_SIZE' if arg_size does not match the size of the data type
-for an argument that is not a memory object or if the argument is a memory
-object and arg_size != sizeof(cl_mem) or if arg_size is zero and the argument is
-declared with the __local qualifier or if the argument is a sampler and arg_size
-!= sizeof(cl_sampler).  
--}
-clSetKernelArg :: Storable a => CLKernel -> CLuint -> a -> IO ()
-clSetKernelArg krn idx val = with val $ \pval -> do
-  whenSuccess (raw_clSetKernelArg krn idx (fromIntegral . sizeOf $ val) (castPtr pval))
-    $ return ()
-
-#c
-enum CLKernelInfo {
-  cL_KERNEL_FUNCTION_NAME=CL_KERNEL_FUNCTION_NAME,
-  cL_KERNEL_NUM_ARGS=CL_KERNEL_NUM_ARGS,
-  cL_KERNEL_REFERENCE_COUNT=CL_KERNEL_REFERENCE_COUNT,
-  cL_KERNEL_CONTEXT=CL_KERNEL_CONTEXT,
-  cL_KERNEL_PROGRAM=CL_KERNEL_PROGRAM
-  };
-#endc
-{#enum CLKernelInfo {upcaseFirstLetter} #}
-
-getKernelInfoSize :: CLKernel -> CLKernelInfo_ -> IO CSize
-getKernelInfoSize krn infoid = alloca $ \(val :: Ptr CSize) -> do
-  whenSuccess (raw_clGetKernelInfo krn infoid 0 nullPtr val)
-    $ peek val
-  
--- | Return the kernel function name.
---
--- This function execute OpenCL clGetKernelInfo with 'CL_KERNEL_FUNCTION_NAME'.
-clGetKernelFunctionName :: CLKernel -> IO String
-clGetKernelFunctionName krn = do
-  n <- getKernelInfoSize krn infoid
-  allocaArray (fromIntegral n) $ \(buff :: CString) -> do
-    whenSuccess (raw_clGetKernelInfo krn infoid n (castPtr buff) nullPtr)
-      $ peekCString buff
-    where 
-      infoid = getCLValue CL_KERNEL_FUNCTION_NAME
-
--- | Return the number of arguments to kernel.
---
--- This function execute OpenCL clGetKernelInfo with 'CL_KERNEL_NUM_ARGS'.
-clGetKernelNumArgs :: CLKernel -> IO CLuint
-clGetKernelNumArgs krn =
-    wrapGetInfo (\(dat :: Ptr CLuint) ->
-        raw_clGetKernelInfo krn infoid size (castPtr dat)) id
-    where 
-      infoid = getCLValue CL_KERNEL_NUM_ARGS
-      size = fromIntegral $ sizeOf (0::CLuint)
-
--- | Return the kernel reference count. The reference count returned should be
--- considered immediately stale. It is unsuitable for general use in
--- applications. This feature is provided for identifying memory leaks.
---
--- This function execute OpenCL clGetKernelInfo with
--- 'CL_KERNEL_REFERENCE_COUNT'.
-clGetKernelReferenceCount :: CLKernel -> IO CLuint
-clGetKernelReferenceCount krn =
-    wrapGetInfo (\(dat :: Ptr CLuint) ->
-        raw_clGetKernelInfo krn infoid size (castPtr dat)) id
-    where 
-      infoid = getCLValue CL_KERNEL_REFERENCE_COUNT
-      size = fromIntegral $ sizeOf (0::CLuint)
-
--- | Return the context associated with kernel.
---
--- This function execute OpenCL clGetKernelInfo with 'CL_KERNEL_CONTEXT'.
-clGetKernelContext :: CLKernel -> IO CLContext
-clGetKernelContext krn =
-    wrapGetInfo (\(dat :: Ptr CLContext) ->
-        raw_clGetKernelInfo krn infoid size (castPtr dat)) id
-    where 
-      infoid = getCLValue CL_KERNEL_CONTEXT
-      size = fromIntegral $ sizeOf (nullPtr::CLContext)
-
--- | Return the program object associated with kernel.
---
--- This function execute OpenCL clGetKernelInfo with 'CL_KERNEL_PROGRAM'.
-clGetKernelProgram :: CLKernel -> IO CLProgram
-clGetKernelProgram krn =
-    wrapGetInfo (\(dat :: Ptr CLProgram) ->
-        raw_clGetKernelInfo krn infoid size (castPtr dat)) id
-    where 
-      infoid = getCLValue CL_KERNEL_PROGRAM
-      size = fromIntegral $ sizeOf (nullPtr::CLProgram)
-
-
-#c
-enum CLKernelGroupInfo {
-  cL_KERNEL_WORK_GROUP_SIZE=CL_KERNEL_WORK_GROUP_SIZE,
-  cL_KERNEL_COMPILE_WORK_GROUP_SIZE=CL_KERNEL_COMPILE_WORK_GROUP_SIZE,
-  cL_KERNEL_LOCAL_MEM_SIZE=CL_KERNEL_LOCAL_MEM_SIZE,
-  };
-#endc
-{#enum CLKernelGroupInfo {upcaseFirstLetter} #}
-
--- | This provides a mechanism for the application to query the work-group size
--- that can be used to execute a kernel on a specific device given by
--- device. The OpenCL implementation uses the resource requirements of the
--- kernel (register usage etc.) to determine what this work-group size should
--- be.
---
--- This function execute OpenCL clGetKernelWorkGroupInfo with
--- 'CL_KERNEL_WORK_GROUP_SIZE'.
-clGetKernelWorkGroupSize :: CLKernel -> CLDeviceID -> IO CSize
-clGetKernelWorkGroupSize krn device =
-    wrapGetInfo (\(dat :: Ptr CSize) ->
-        raw_clGetKernelWorkGroupInfo krn device infoid size (castPtr dat)) id
-    where
-      infoid = getCLValue CL_KERNEL_WORK_GROUP_SIZE
-      size = fromIntegral $ sizeOf (0::CSize)
-
--- | Returns the work-group size specified by the __attribute__((reqd_work_gr
--- oup_size(X, Y, Z))) qualifier. See Function Qualifiers. If the work-group
--- size is not specified using the above attribute qualifier (0, 0, 0) is
--- returned.
---
--- This function execute OpenCL clGetKernelWorkGroupInfo with
--- 'CL_KERNEL_COMPILE_WORK_GROUP_SIZE'.
-clGetKernelCompileWorkGroupSize :: CLKernel -> CLDeviceID -> IO [CSize]
-clGetKernelCompileWorkGroupSize krn device = do
-  allocaArray num $ \(buff :: Ptr CSize) -> do
-    whenSuccess (raw_clGetKernelWorkGroupInfo krn device infoid size (castPtr buff) nullPtr)
-      $ peekArray num buff
-    where 
-      infoid = getCLValue CL_KERNEL_COMPILE_WORK_GROUP_SIZE
-      num = 3
-      elemSize = fromIntegral $ sizeOf (0::CSize)
-      size = fromIntegral $ num * elemSize
-
-
--- | Returns the amount of local memory in bytes being used by a kernel. This
--- includes local memory that may be needed by an implementation to execute the
--- kernel, variables declared inside the kernel with the __local address
--- qualifier and local memory to be allocated for arguments to the kernel
--- declared as pointers with the __local address qualifier and whose size is
--- specified with 'clSetKernelArg'.
---
--- If the local memory size, for any pointer argument to the kernel declared
--- with the __local address qualifier, is not specified, its size is assumed to
--- be 0.
---
--- This function execute OpenCL clGetKernelWorkGroupInfo with
--- 'CL_KERNEL_LOCAL_MEM_SIZE'.
-clGetKernelLocalMemSize :: CLKernel -> CLDeviceID -> IO CLulong
-clGetKernelLocalMemSize krn device =
-    wrapGetInfo (\(dat :: Ptr CLulong) ->
-        raw_clGetKernelWorkGroupInfo krn device infoid size (castPtr dat)) id
-    where
-      infoid = getCLValue CL_KERNEL_LOCAL_MEM_SIZE
-      size = fromIntegral $ sizeOf (0::CLulong)
--- -----------------------------------------------------------------------------
diff --git a/src/System/GPU/OpenCL/Query.chs b/src/System/GPU/OpenCL/Query.chs
deleted file mode 100644
--- a/src/System/GPU/OpenCL/Query.chs
+++ /dev/null
@@ -1,721 +0,0 @@
-{- Copyright (c) 2011 Luis Cabellos,
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above
-      copyright notice, this list of conditions and the following
-      disclaimer in the documentation and/or other materials provided
-      with the distribution.
-
-    * Neither the name of  nor the names of other
-      contributors may be used to endorse or promote products derived
-      from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--}
-{-# LANGUAGE ForeignFunctionInterface, ScopedTypeVariables, CPP #-}
-module System.GPU.OpenCL.Query( 
-  -- * Types
-  CLPlatformInfo(..), CLPlatformID, CLDeviceID, CLDeviceType(..),
-  CLDeviceFPConfig(..), CLDeviceExecCapability(..), CLDeviceLocalMemType(..),
-  CLDeviceMemCacheType(..),
-  -- * Platform Query Functions
-  clGetPlatformIDs, clGetPlatformInfo, 
-  -- * Device Query Functions
-  clGetDeviceIDs, clGetDeviceExecutionCapabilities,
-  clGetDeviceAddressBits, clGetDeviceAvailable, clGetDeviceCompilerAvailable, 
-  clGetDeviceEndianLittle, clGetDeviceErrorCorrectionSupport, 
-  clGetDeviceExtensions, clGetDeviceGlobalMemCacheSize, 
-  clGetDeviceGlobalMemCachelineSize, clGetDeviceGlobalMemSize, 
-  clGetDeviceImageSupport, clGetDeviceImage2DMaxHeight, 
-  clGetDeviceImage2DMaxWidth, clGetDeviceImage3DMaxDepth, 
-  clGetDeviceImage3DMaxHeight, clGetDeviceImage3DMaxWidth, 
-  clGetDeviceLocalMemSize, clGetDeviceMaxClockFrequency, 
-  clGetDeviceMaxComputeUnits, clGetDeviceMaxConstantArgs, 
-  clGetDeviceMaxConstantBufferSize, clGetDeviceMaxMemAllocSize, 
-  clGetDeviceMaxParameterSize, clGetDeviceMaxReadImageArgs, 
-  clGetDeviceMaxSamplers, clGetDeviceMaxWorkGroupSize, 
-  clGetDeviceMaxWorkItemDimensions, clGetDeviceMaxWorkItemSizes, 
-  clGetDeviceMaxWriteImageArgs, clGetDeviceMemBaseAddrAlign, 
-  clGetDeviceMinDataTypeAlignSize, clGetDeviceName, clGetDevicePlatform, 
-  clGetDevicePreferredVectorWidthChar, clGetDevicePreferredVectorWidthShort, 
-  clGetDevicePreferredVectorWidthInt, clGetDevicePreferredVectorWidthLong, 
-  clGetDevicePreferredVectorWidthFloat, clGetDevicePreferredVectorWidthDouble, 
-  clGetDeviceProfile, clGetDeviceProfilingTimerResolution, clGetDeviceVendor, 
-  clGetDeviceVendorID, clGetDeviceVersion, clGetDeviceDriverVersion, 
-  clGetDeviceSingleFPConfig, clGetDeviceDoubleFPConfig, 
-  clGetDeviceHalfFPConfig, clGetDeviceLocalMemType, 
-  clGetDeviceGlobalMemCacheType, clGetDeviceQueueProperties, clGetDeviceType )
-       where
-
--- -----------------------------------------------------------------------------
-import Foreign( Ptr, nullPtr, castPtr, alloca, allocaArray, peek, peekArray )
-import Foreign.C.String( CString, peekCString )
-import Foreign.C.Types( CSize )
-import Foreign.Storable( sizeOf )
-import System.GPU.OpenCL.Types( 
-  CLbool, CLint, CLuint, CLulong, CLPlatformInfo_, CLDeviceType_,
-  CLDeviceInfo_, CLDeviceFPConfig(..), CLDeviceExecCapability(..),
-  CLDeviceLocalMemType(..), CLDeviceMemCacheType(..), CLPlatformInfo(..),
-  CLPlatformID, CLDeviceID, CLDeviceType(..), CLCommandQueueProperty, 
-  getCLValue, getEnumCL, bitmaskToDeviceTypes, bitmaskToCommandQueueProperties, 
-  whenSuccess, bitmaskToFPConfig, bitmaskToExecCapability )
-
--- -----------------------------------------------------------------------------
-foreign import CALLCONV "clGetPlatformIDs" raw_clGetPlatformIDs :: 
-  CLuint -> Ptr CLPlatformID -> Ptr CLuint -> IO CLint
-foreign import CALLCONV "clGetPlatformInfo" raw_clGetPlatformInfo :: 
-  CLPlatformID -> CLPlatformInfo_ -> CSize -> Ptr () -> Ptr CSize -> IO CLint 
-foreign import CALLCONV "clGetDeviceIDs" raw_clGetDeviceIDs :: 
-  CLPlatformID -> CLDeviceType_ -> CLuint -> Ptr CLDeviceID -> Ptr CLuint -> IO CLint
-foreign import CALLCONV "clGetDeviceInfo" raw_clGetDeviceInfo :: 
-  CLDeviceID -> CLDeviceInfo_ -> CSize -> Ptr () -> Ptr CSize -> IO CLint
-
-#include <CL/cl.h>
-
--- -----------------------------------------------------------------------------
-getNumPlatforms :: IO CLuint
-getNumPlatforms = alloca $ \(num_platforms :: Ptr CLuint) -> do 
-  whenSuccess (raw_clGetPlatformIDs 0 nullPtr num_platforms) 
-    $ peek num_platforms
-
--- | Obtain the list of platforms available. Returns the list if the function 
--- is executed successfully. Otherwise it returns the empty list.
-clGetPlatformIDs :: IO [CLPlatformID]
-clGetPlatformIDs = do
-  nplats <- getNumPlatforms
-  allocaArray (fromIntegral nplats) $ \(plats :: Ptr CLPlatformID) -> do
-    whenSuccess (raw_clGetPlatformIDs nplats plats nullPtr) 
-      $ peekArray (fromIntegral nplats) plats
-  
-getPlatformInfoSize :: CLPlatformID -> CLuint -> IO CSize
-getPlatformInfoSize platform infoid = alloca $ \(value_size :: Ptr CSize) -> do
-  whenSuccess (raw_clGetPlatformInfo platform infoid 0 nullPtr value_size) 
-    $ peek value_size
-  
--- | Get specific information about the OpenCL platform. It returns Nothing if
--- platform is not a valid platform.
-clGetPlatformInfo :: CLPlatformID -> CLPlatformInfo -> IO String
-clGetPlatformInfo platform infoid = do
-  sval <- getPlatformInfoSize platform infocl
-  allocaArray (fromIntegral sval) $ \(buff :: CString) -> do
-    whenSuccess (raw_clGetPlatformInfo platform infocl sval (castPtr buff) nullPtr)
-      $ peekCString buff
-    where
-      infocl = getCLValue infoid
-
--- -----------------------------------------------------------------------------
-getNumDevices :: CLPlatformID -> CLDeviceType_ -> IO CLuint
-getNumDevices platform dtype = alloca $ \(num_devices :: Ptr CLuint) -> do
-  whenSuccess (raw_clGetDeviceIDs platform dtype 0 nullPtr num_devices)
-    $ peek num_devices
-
--- | Obtain the list of devices available on a platform. Returns the list if 
--- the function is executed successfully. Otherwise it returns the empty list 
--- if platform is not a valid platform or no OpenCL devices that matched 
--- device_type were found.
-clGetDeviceIDs :: CLPlatformID -> CLDeviceType -> IO [CLDeviceID]
-clGetDeviceIDs platform dtype = do
-  ndevs <- getNumDevices platform dval
-  allocaArray (fromIntegral ndevs) $ \(devs :: Ptr CLDeviceID) -> do
-    whenSuccess (raw_clGetDeviceIDs platform dval ndevs devs nullPtr)
-      $ peekArray (fromIntegral ndevs) devs
-    where
-      dval = getCLValue dtype
-
-getDeviceInfoSize :: CLDeviceID -> CLDeviceInfo_ -> IO CSize
-getDeviceInfoSize device infoid = alloca $ \(value_size :: Ptr CSize) -> do
-  whenSuccess (raw_clGetDeviceInfo device infoid 0 nullPtr value_size)
-    $ peek value_size
-  
-getDeviceInfoString :: CLDeviceInfo_ -> CLDeviceID -> IO String
-getDeviceInfoString infoid device = do
-  n <- getDeviceInfoSize device infoid
-  allocaArray (fromIntegral n) $ \(buff :: CString) -> do
-    whenSuccess (raw_clGetDeviceInfo device infoid n (castPtr buff) nullPtr)
-      $ peekCString buff
-  
-getDeviceInfoUint :: CLDeviceInfo_ -> CLDeviceID -> IO CLuint
-getDeviceInfoUint infoid device = alloca $ \(dat :: Ptr CLuint) -> do
-  whenSuccess (raw_clGetDeviceInfo device infoid size (castPtr dat) nullPtr)
-    $ peek dat
-    where 
-      size = fromIntegral $ sizeOf (0::CLuint)
-
-getDeviceInfoUlong :: CLDeviceInfo_ -> CLDeviceID -> IO CLulong
-getDeviceInfoUlong infoid device = alloca $ \(dat :: Ptr CLulong) -> do
-  whenSuccess (raw_clGetDeviceInfo device infoid size (castPtr dat) nullPtr)
-    $ peek dat
-    where 
-      size = fromIntegral $ sizeOf (0::CLulong)
-
-getDeviceInfoSizet :: CLDeviceInfo_ -> CLDeviceID -> IO CSize
-getDeviceInfoSizet infoid device = alloca $ \(dat :: Ptr CSize) -> do
-  whenSuccess (raw_clGetDeviceInfo device infoid size (castPtr dat) nullPtr)
-    $ peek dat
-    where 
-      size = fromIntegral $ sizeOf (0::CSize)
-  
-getDeviceInfoBool :: CLDeviceInfo_ -> CLDeviceID -> IO Bool
-getDeviceInfoBool infoid device = alloca $ \(dat :: Ptr CLbool) -> do
-  whenSuccess (raw_clGetDeviceInfo device infoid size (castPtr dat) nullPtr)
-    $ peek dat >>= return . (/=0)
-    where 
-      size = fromIntegral $ sizeOf (0::CLbool)
-  
-getDeviceInfoFP :: CLDeviceInfo_ -> CLDeviceID -> IO [CLDeviceFPConfig]
-getDeviceInfoFP infoid device = do
-  flags <- getDeviceInfoUlong infoid device
-  return . bitmaskToFPConfig $ flags
-
-#c
-enum CLDeviceInfo {
-  cL_DEVICE_ADDRESS_BITS=CL_DEVICE_ADDRESS_BITS,
-  cL_DEVICE_AVAILABLE=CL_DEVICE_AVAILABLE,
-  cL_DEVICE_COMPILER_AVAILABLE=CL_DEVICE_COMPILER_AVAILABLE,
-#ifdef CL_DEVICE_DOUBLE_FP_CONFIG  
-  cL_DEVICE_DOUBLE_FP_CONFIG=CL_DEVICE_DOUBLE_FP_CONFIG,
-#else
-  cL_DEVICE_DOUBLE_FP_CONFIG=0x1032,
-#endif
-  cL_DEVICE_ENDIAN_LITTLE=CL_DEVICE_ENDIAN_LITTLE,
-  cL_DEVICE_ERROR_CORRECTION_SUPPORT=CL_DEVICE_ERROR_CORRECTION_SUPPORT,
-  cL_DEVICE_EXECUTION_CAPABILITIES=CL_DEVICE_EXECUTION_CAPABILITIES,
-  cL_DEVICE_EXTENSIONS=CL_DEVICE_EXTENSIONS,
-  cL_DEVICE_GLOBAL_MEM_CACHE_SIZE=CL_DEVICE_GLOBAL_MEM_CACHE_SIZE,
-  cL_DEVICE_GLOBAL_MEM_CACHE_TYPE=CL_DEVICE_GLOBAL_MEM_CACHE_TYPE,
-  cL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE=CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE,
-  cL_DEVICE_GLOBAL_MEM_SIZE=CL_DEVICE_GLOBAL_MEM_SIZE,
-#ifdef CL_DEVICE_HALF_FP_CONFIG
-  cL_DEVICE_HALF_FP_CONFIG=CL_DEVICE_HALF_FP_CONFIG,
-#else
-  cL_DEVICE_HALF_FP_CONFIG=0x1033,
-#endif
-  cL_DEVICE_IMAGE_SUPPORT=CL_DEVICE_IMAGE_SUPPORT,
-  cL_DEVICE_IMAGE2D_MAX_HEIGHT=CL_DEVICE_IMAGE2D_MAX_HEIGHT,
-  cL_DEVICE_IMAGE2D_MAX_WIDTH=CL_DEVICE_IMAGE2D_MAX_WIDTH,
-  cL_DEVICE_IMAGE3D_MAX_DEPTH=CL_DEVICE_IMAGE3D_MAX_DEPTH,
-  cL_DEVICE_IMAGE3D_MAX_HEIGHT=CL_DEVICE_IMAGE3D_MAX_HEIGHT,
-  cL_DEVICE_IMAGE3D_MAX_WIDTH=CL_DEVICE_IMAGE3D_MAX_WIDTH,
-  cL_DEVICE_LOCAL_MEM_SIZE=CL_DEVICE_LOCAL_MEM_SIZE,
-  cL_DEVICE_LOCAL_MEM_TYPE=CL_DEVICE_LOCAL_MEM_TYPE,
-  cL_DEVICE_MAX_CLOCK_FREQUENCY=CL_DEVICE_MAX_CLOCK_FREQUENCY,
-  cL_DEVICE_MAX_COMPUTE_UNITS=CL_DEVICE_MAX_COMPUTE_UNITS,
-  cL_DEVICE_MAX_CONSTANT_ARGS=CL_DEVICE_MAX_CONSTANT_ARGS,
-  cL_DEVICE_MAX_CONSTANT_BUFFER_SIZE=CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE,
-  cL_DEVICE_MAX_MEM_ALLOC_SIZE=CL_DEVICE_MAX_MEM_ALLOC_SIZE,
-  cL_DEVICE_MAX_PARAMETER_SIZE=CL_DEVICE_MAX_PARAMETER_SIZE,
-  cL_DEVICE_MAX_READ_IMAGE_ARGS=CL_DEVICE_MAX_READ_IMAGE_ARGS,
-  cL_DEVICE_MAX_SAMPLERS=CL_DEVICE_MAX_SAMPLERS,
-  cL_DEVICE_MAX_WORK_GROUP_SIZE=CL_DEVICE_MAX_WORK_GROUP_SIZE,
-  cL_DEVICE_MAX_WORK_ITEM_DIMENSIONS=CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS,
-  cL_DEVICE_MAX_WORK_ITEM_SIZES=CL_DEVICE_MAX_WORK_ITEM_SIZES,
-  cL_DEVICE_MAX_WRITE_IMAGE_ARGS=CL_DEVICE_MAX_WRITE_IMAGE_ARGS,
-  cL_DEVICE_MEM_BASE_ADDR_ALIGN=CL_DEVICE_MEM_BASE_ADDR_ALIGN,
-  cL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE=CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE,
-  cL_DEVICE_NAME=CL_DEVICE_NAME,
-  cL_DEVICE_PLATFORM=CL_DEVICE_PLATFORM,
-  cL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR=CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR,
-  cL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT=CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT,
-  cL_DEVICE_PREFERRED_VECTOR_WIDTH_INT=CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT,
-  cL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG=CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG,
-  cL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT=CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT,
-  cL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE=CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE,
-  cL_DEVICE_PROFILE=CL_DEVICE_PROFILE,
-  cL_DEVICE_PROFILING_TIMER_RESOLUTION=CL_DEVICE_PROFILING_TIMER_RESOLUTION,
-  cL_DEVICE_QUEUE_PROPERTIES=CL_DEVICE_QUEUE_PROPERTIES,
-  cL_DEVICE_SINGLE_FP_CONFIG=CL_DEVICE_SINGLE_FP_CONFIG,
-  cL_DEVICE_TYPE=CL_DEVICE_TYPE,
-  cL_DEVICE_VENDOR=CL_DEVICE_VENDOR,
-  cL_DEVICE_VENDOR_ID=CL_DEVICE_VENDOR_ID,
-  cL_DEVICE_VERSION=CL_DEVICE_VERSION,
-  cL_DRIVER_VERSION=CL_DRIVER_VERSION,
-  };
-#endc
-{#enum CLDeviceInfo {upcaseFirstLetter} #}
-
--- | The default compute device address space size specified as an unsigned 
--- integer value in bits. Currently supported values are 32 or 64 bits.
---
--- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_ADDRESS_BITS'.
-clGetDeviceAddressBits :: CLDeviceID -> IO CLuint
-clGetDeviceAddressBits = getDeviceInfoUint . getCLValue $ CL_DEVICE_ADDRESS_BITS
-
--- | Is 'True' if the device is available and 'False' if the device is not 
--- available.
---
--- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_AVAILABLE'.
-clGetDeviceAvailable :: CLDeviceID -> IO Bool
-clGetDeviceAvailable = getDeviceInfoBool . getCLValue $ CL_DEVICE_AVAILABLE
-
--- | Is 'False' if the implementation does not have a compiler available to 
--- compile the program source. Is 'True' if the compiler is available. This can 
--- be 'False' for the embededed platform profile only.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_COMPILER_AVAILABLE'.
-clGetDeviceCompilerAvailable :: CLDeviceID -> IO Bool
-clGetDeviceCompilerAvailable = getDeviceInfoBool . getCLValue $ CL_DEVICE_COMPILER_AVAILABLE
-
--- | Describes the OPTIONAL double precision floating-point capability of the 
--- OpenCL device. This is a bit-field that describes one or more of the 
--- 'CLDeviceFPConfig' values.
--- The mandated minimum double precision floating-point capability is 
--- 'CL_FP_FMA' | 'CL_FP_ROUND_TO_NEAREST' | 'CL_FP_ROUND_TO_ZERO' | 
--- 'CL_FP_ROUND_TO_INF' | 'CL_FP_INF_NAN' | 'CL_FP_DENORM'.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_DOUBLE_FP_CONFIG'.
-clGetDeviceDoubleFPConfig :: CLDeviceID -> IO [CLDeviceFPConfig]
-clGetDeviceDoubleFPConfig = getDeviceInfoFP . getCLValue $ CL_DEVICE_DOUBLE_FP_CONFIG
-
--- | Is 'True' if the OpenCL device is a little endian device and 'False' 
--- otherwise.
---
--- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_ENDIAN_LITTLE'.
-clGetDeviceEndianLittle :: CLDeviceID -> IO Bool
-clGetDeviceEndianLittle = getDeviceInfoBool . getCLValue $ CL_DEVICE_ENDIAN_LITTLE
-
--- | Is 'True' if the device implements error correction for the memories, 
--- caches, registers etc. in the device. Is 'False' if the device does not 
--- implement error correction. This can be a requirement for certain clients of 
--- OpenCL.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_ERROR_CORRECTION_SUPPORT'.
-clGetDeviceErrorCorrectionSupport :: CLDeviceID -> IO Bool
-clGetDeviceErrorCorrectionSupport = getDeviceInfoBool . getCLValue $ CL_DEVICE_ERROR_CORRECTION_SUPPORT
-
--- | Describes the execution capabilities of the device. This is a list that 
--- describes one or more of the 'CLDeviceExecCapability' values.
--- The mandated minimum capability is 'CL_EXEC_KERNEL'.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_EXECUTION_CAPABILITIES'.
-clGetDeviceExecutionCapabilities :: CLDeviceID -> IO [CLDeviceExecCapability]
-clGetDeviceExecutionCapabilities device = do
-  flags <- getDeviceInfoUlong (getCLValue CL_DEVICE_EXECUTION_CAPABILITIES) device
-  return . bitmaskToExecCapability $ flags
-
--- | Returns a space separated list of extension names (the extension names 
--- themselves do not contain any spaces). The list of extension names returned 
--- currently can include one or more of the following approved extension names:
---
--- * cl_khr_fp64
---
--- * cl_khr_select_fprounding_mode
---
--- * cl_khr_global_int32_base_atomics
---
--- * cl_khr_global_int32_extended_atomics
---
--- * cl_khr_local_int32_base_atomics
---
--- * cl_khr_local_int32_extended_atomics
---
--- * cl_khr_int64_base_atomics
---
--- * cl_khr_int64_extended_atomics
---
--- * cl_khr_3d_image_writes
---
--- * cl_khr_byte_addressable_store
---
--- * cl_khr_fp16
---
--- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_EXTENSIONS'.
-clGetDeviceExtensions :: CLDeviceID -> IO String
-clGetDeviceExtensions = getDeviceInfoString . getCLValue $ CL_DEVICE_EXTENSIONS
-
--- | Size of global memory cache in bytes.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_GLOBAL_MEM_CACHE_SIZE'.
-clGetDeviceGlobalMemCacheSize :: CLDeviceID -> IO CLulong
-clGetDeviceGlobalMemCacheSize = getDeviceInfoUlong . getCLValue $ CL_DEVICE_GLOBAL_MEM_CACHE_SIZE
-
--- | Type of global memory cache supported. Valid values are: 'CL_NONE', 
--- 'CL_READ_ONLY_CACHE', and 'CL_READ_WRITE_CACHE'.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_GLOBAL_MEM_CACHE_TYPE'.
-clGetDeviceGlobalMemCacheType :: CLDeviceID -> IO CLDeviceMemCacheType
-clGetDeviceGlobalMemCacheType device = do
-  typ <- getDeviceInfoUint (getCLValue CL_DEVICE_GLOBAL_MEM_CACHE_TYPE) device 
-  return . getEnumCL $ typ
-
--- | Size of global memory cache line in bytes.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE'.
-clGetDeviceGlobalMemCachelineSize :: CLDeviceID -> IO CLuint
-clGetDeviceGlobalMemCachelineSize = getDeviceInfoUint . getCLValue $ CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE
-
--- | Size of global device memory in bytes.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_GLOBAL_MEM_SIZE'.
-clGetDeviceGlobalMemSize :: CLDeviceID -> IO CLulong
-clGetDeviceGlobalMemSize = getDeviceInfoUlong . getCLValue $ CL_DEVICE_GLOBAL_MEM_SIZE
-
--- | Describes the OPTIONAL half precision floating-point capability of the 
--- OpenCL device. This is a bit-field that describes one or more of the 
--- 'CLDeviceFPConfig' values.
--- The required minimum half precision floating-point capability as implemented 
--- by this extension is 'CL_FP_ROUND_TO_ZERO' | 'CL_FP_ROUND_TO_INF' | 
--- 'CL_FP_INF_NAN'.
---
--- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_HALF_FP_CONFIG'.
-clGetDeviceHalfFPConfig :: CLDeviceID -> IO [CLDeviceFPConfig]
-clGetDeviceHalfFPConfig = getDeviceInfoFP . getCLValue $ CL_DEVICE_HALF_FP_CONFIG
-
--- | Is 'True' if images are supported by the OpenCL device and 'False' otherwise.
---
--- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_IMAGE_SUPPORT'.
-clGetDeviceImageSupport :: CLDeviceID -> IO Bool
-clGetDeviceImageSupport = getDeviceInfoBool . getCLValue $ CL_DEVICE_IMAGE_SUPPORT
-
--- | Max height of 2D image in pixels. The minimum value is 8192 if
--- 'clGetDeviceImageSupport' is 'True'.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_IMAGE2D_MAX_HEIGHT'.
-clGetDeviceImage2DMaxHeight :: CLDeviceID -> IO CSize
-clGetDeviceImage2DMaxHeight = getDeviceInfoSizet . getCLValue $ CL_DEVICE_IMAGE2D_MAX_HEIGHT
-
--- | Max width of 2D image in pixels. The minimum value is 8192 if
--- 'clGetDeviceImageSupport' is 'True'.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_IMAGE2D_MAX_WIDTH'.
-clGetDeviceImage2DMaxWidth :: CLDeviceID -> IO CSize
-clGetDeviceImage2DMaxWidth = getDeviceInfoSizet . getCLValue $ CL_DEVICE_IMAGE2D_MAX_WIDTH
-
--- | Max depth of 3D image in pixels. The minimum value is 2048 if 
--- 'clGetDeviceImageSupport' is 'True'.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_IMAGE3D_MAX_DEPTH'.
-clGetDeviceImage3DMaxDepth :: CLDeviceID -> IO CSize
-clGetDeviceImage3DMaxDepth = getDeviceInfoSizet . getCLValue $ CL_DEVICE_IMAGE3D_MAX_DEPTH
-
--- | Max height of 3D image in pixels. The minimum value is 2048 if 
--- 'clGetDeviceImageSupport' is 'True'.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_IMAGE3D_MAX_HEIGHT'.
-clGetDeviceImage3DMaxHeight :: CLDeviceID -> IO CSize
-clGetDeviceImage3DMaxHeight = getDeviceInfoSizet . getCLValue $ CL_DEVICE_IMAGE3D_MAX_HEIGHT
-
--- | Max width of 3D image in pixels. The minimum value is 2048 if 
--- 'clGetDeviceImageSupport' is 'True'.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_IMAGE3D_MAX_WIDTH'.
-clGetDeviceImage3DMaxWidth :: CLDeviceID -> IO CSize
-clGetDeviceImage3DMaxWidth = getDeviceInfoSizet . getCLValue $ CL_DEVICE_IMAGE3D_MAX_WIDTH
-
--- | Size of local memory arena in bytes. The minimum value is 16 KB.
---
--- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_LOCAL_MEM_SIZE'.
-clGetDeviceLocalMemSize :: CLDeviceID -> IO CLulong
-clGetDeviceLocalMemSize = getDeviceInfoUlong . getCLValue $ CL_DEVICE_LOCAL_MEM_SIZE
-
--- | Type of local memory supported. This can be set to 'CL_LOCAL' implying 
--- dedicated local memory storage such as SRAM, or 'CL_GLOBAL'.
---
--- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_LOCAL_MEM_TYPE'.
-clGetDeviceLocalMemType :: CLDeviceID -> IO CLDeviceLocalMemType
-clGetDeviceLocalMemType device = do
-  typ <- getDeviceInfoUint (getCLValue CL_DEVICE_LOCAL_MEM_TYPE) device 
-  return . getEnumCL $ typ
-
--- | Maximum configured clock frequency of the device in MHz.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_MAX_CLOCK_FREQUENCY'.
-clGetDeviceMaxClockFrequency :: CLDeviceID -> IO CLuint
-clGetDeviceMaxClockFrequency = getDeviceInfoUint . getCLValue $ CL_DEVICE_MAX_CLOCK_FREQUENCY
-
--- | The number of parallel compute cores on the OpenCL device. The minimum 
--- value is 1.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_MAX_COMPUTE_UNITS'.
-clGetDeviceMaxComputeUnits :: CLDeviceID -> IO CLuint
-clGetDeviceMaxComputeUnits = getDeviceInfoUint . getCLValue $ CL_DEVICE_MAX_COMPUTE_UNITS
-
--- | Max number of arguments declared with the __constant qualifier in a kernel. 
--- The minimum value is 8.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_MAX_CONSTANT_ARGS'.
-clGetDeviceMaxConstantArgs :: CLDeviceID -> IO CLuint
-clGetDeviceMaxConstantArgs = getDeviceInfoUint . getCLValue $ CL_DEVICE_MAX_CONSTANT_ARGS
-
--- | Max size in bytes of a constant buffer allocation. The minimum value is 
--- 64 KB.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE'.
-clGetDeviceMaxConstantBufferSize :: CLDeviceID -> IO CLulong
-clGetDeviceMaxConstantBufferSize = getDeviceInfoUlong . getCLValue $ CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE
-
--- | Max size of memory object allocation in bytes. The minimum value is max 
--- (1/4th of 'clGetDeviceGlobalMemSize', 128*1024*1024)
---
--- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_MAX_MEM_ALLOC_SIZE'.
-clGetDeviceMaxMemAllocSize :: CLDeviceID -> IO CLulong
-clGetDeviceMaxMemAllocSize = getDeviceInfoUlong . getCLValue $ CL_DEVICE_MAX_MEM_ALLOC_SIZE
-
--- | Max size in bytes of the arguments that can be passed to a kernel. The 
--- minimum value is 256.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_MAX_PARAMETER_SIZE'.
-clGetDeviceMaxParameterSize :: CLDeviceID -> IO CSize
-clGetDeviceMaxParameterSize = getDeviceInfoSizet . getCLValue $ CL_DEVICE_MAX_PARAMETER_SIZE
-
--- | Max number of simultaneous image objects that can be read by a kernel. The 
--- minimum value is 128 if 'clGetDeviceImageSupport' is 'True'.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_MAX_READ_IMAGE_ARGS'.
-clGetDeviceMaxReadImageArgs :: CLDeviceID -> IO CLuint
-clGetDeviceMaxReadImageArgs = getDeviceInfoUint . getCLValue $ CL_DEVICE_MAX_READ_IMAGE_ARGS
-
--- | Maximum number of samplers that can be used in a kernel. The minimum value 
--- is 16 if 'clGetDeviceImageSupport' is 'True'. (Also see sampler type.)
---
--- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_MAX_SAMPLERS'.
-clGetDeviceMaxSamplers :: CLDeviceID -> IO CLuint
-clGetDeviceMaxSamplers = getDeviceInfoUint . getCLValue $ CL_DEVICE_MAX_SAMPLERS
-
--- | Maximum number of work-items in a work-group executing a kernel using the 
--- data parallel execution model. (Refer to 'clEnqueueNDRangeKernel'). The 
--- minimum value is 1.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_MAX_WORK_GROUP_SIZE'.
-clGetDeviceMaxWorkGroupSize :: CLDeviceID -> IO CSize
-clGetDeviceMaxWorkGroupSize = getDeviceInfoSizet . getCLValue $ CL_DEVICE_MAX_WORK_GROUP_SIZE
-
--- | Maximum dimensions that specify the global and local work-item IDs used by 
--- the data parallel execution model. (Refer to 'clEnqueueNDRangeKernel'). 
--- The minimum value is 3.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS'.
-clGetDeviceMaxWorkItemDimensions :: CLDeviceID -> IO CLuint
-clGetDeviceMaxWorkItemDimensions = getDeviceInfoUint . getCLValue $ CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS
-
--- | Maximum number of work-items that can be specified in each dimension of the 
--- work-group to 'clEnqueueNDRangeKernel'.
--- Returns n entries, where n is the value returned by the query for 
--- clDeviceMaxWorkItemDimensions. The minimum value is (1, 1, 1).
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_MAX_WORK_ITEM_SIZES'.
-clGetDeviceMaxWorkItemSizes :: CLDeviceID -> IO [CSize]
-clGetDeviceMaxWorkItemSizes device = do
-  n <- clGetDeviceMaxWorkItemDimensions device
-  allocaArray (fromIntegral n) $ \(buff :: Ptr CSize) -> do
-    whenSuccess (raw_clGetDeviceInfo device infoid (size n) (castPtr buff) nullPtr)
-      $ peekArray (fromIntegral n) buff
-    where
-      infoid = getCLValue CL_DEVICE_MAX_WORK_ITEM_SIZES
-      size n = fromIntegral $ (fromIntegral n) * (sizeOf (0::CSize))
-
--- | Max number of simultaneous image objects that can be written to by a 
--- kernel. The minimum value is 8 if 'clGetDeviceImageSupport' is 'True'.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_MAX_WRITE_IMAGE_ARGS'.
-clGetDeviceMaxWriteImageArgs :: CLDeviceID -> IO CLuint
-clGetDeviceMaxWriteImageArgs = getDeviceInfoUint . getCLValue $ CL_DEVICE_MAX_WRITE_IMAGE_ARGS
-
--- | Describes the alignment in bits of the base address of any allocated 
--- memory object.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_MEM_BASE_ADDR_ALIGN'.
-clGetDeviceMemBaseAddrAlign :: CLDeviceID -> IO CLuint
-clGetDeviceMemBaseAddrAlign = getDeviceInfoUint . getCLValue $ CL_DEVICE_MEM_BASE_ADDR_ALIGN
-
--- | The smallest alignment in bytes which can be used for any data type.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE'.
-clGetDeviceMinDataTypeAlignSize :: CLDeviceID -> IO CLuint
-clGetDeviceMinDataTypeAlignSize = getDeviceInfoUint . getCLValue $ CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE
-
--- | Device name string.
---
--- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_NAME'.
-clGetDeviceName :: CLDeviceID -> IO String
-clGetDeviceName = getDeviceInfoString . getCLValue $ CL_DEVICE_NAME
-
--- | The platform associated with this device.
---
--- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_PLATFORM'.
-clGetDevicePlatform :: CLDeviceID -> IO CLPlatformID
-clGetDevicePlatform device = alloca $ \(dat :: Ptr CLPlatformID) -> do
-  whenSuccess (raw_clGetDeviceInfo device infoid size (castPtr dat) nullPtr)
-    $ peek dat
-    where 
-      infoid = getCLValue CL_DEVICE_PLATFORM
-      size = fromIntegral $ sizeOf (nullPtr :: CLPlatformID)
-
--- | Preferred native vector width size for built-in char types that can be put 
--- into vectors. The vector width is defined as the number of scalar elements 
--- that can be stored in the vector.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR'.
-clGetDevicePreferredVectorWidthChar :: CLDeviceID -> IO CLuint
-clGetDevicePreferredVectorWidthChar = getDeviceInfoUint . getCLValue $ CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR
-
--- | Preferred native vector width size for built-in short types that can be put 
--- into vectors. The vector width is defined as the number of scalar elements 
--- that can be stored in the vector.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT'.
-clGetDevicePreferredVectorWidthShort :: CLDeviceID -> IO CLuint
-clGetDevicePreferredVectorWidthShort = getDeviceInfoUint . getCLValue $ CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT
-
--- | Preferred native vector width size for built-in int types that can be put 
--- into vectors. The vector width is defined as the number of scalar elements 
--- that can be stored in the vector.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT'.
-clGetDevicePreferredVectorWidthInt :: CLDeviceID -> IO CLuint
-clGetDevicePreferredVectorWidthInt = getDeviceInfoUint . getCLValue $ CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT
-
--- | Preferred native vector width size for built-in long types that can be put 
--- into vectors. The vector width is defined as the number of scalar elements 
--- that can be stored in the vector.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG'.
-clGetDevicePreferredVectorWidthLong :: CLDeviceID -> IO CLuint
-clGetDevicePreferredVectorWidthLong = getDeviceInfoUint . getCLValue $ CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG
-
--- | Preferred native vector width size for built-in float types that can be put 
--- into vectors. The vector width is defined as the number of scalar elements 
--- that can be stored in the vector.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT'.
-clGetDevicePreferredVectorWidthFloat :: CLDeviceID -> IO CLuint
-clGetDevicePreferredVectorWidthFloat = getDeviceInfoUint . getCLValue $ CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT
-
--- | Preferred native vector width size for built-in double types that can be put 
--- into vectors. The vector width is defined as the number of scalar elements 
--- that can be stored in the vector.
--- | If the cl_khr_fp64 extension is not supported, 
--- 'clGetDevicePreferredVectorWidthDouble' must return 0.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE'.
-clGetDevicePreferredVectorWidthDouble :: CLDeviceID -> IO CLuint
-clGetDevicePreferredVectorWidthDouble = getDeviceInfoUint . getCLValue $ CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE
-
--- | OpenCL profile string. Returns the profile name supported by the device 
--- (see note). The profile name returned can be one of the following strings:
--- 
--- * FULL_PROFILE - if the device supports the OpenCL specification 
--- (functionality defined as part of the core specification and does not require 
--- any extensions to be supported).
--- 
--- * EMBEDDED_PROFILE - if the device supports the OpenCL embedded profile.
---
--- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_PROFILE'.
-clGetDeviceProfile :: CLDeviceID -> IO String
-clGetDeviceProfile = getDeviceInfoString . getCLValue $ CL_DEVICE_PROFILE
-
--- | Describes the resolution of device timer. This is measured in nanoseconds.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_PROFILING_TIMER_RESOLUTION'.
-clGetDeviceProfilingTimerResolution :: CLDeviceID -> IO CSize
-clGetDeviceProfilingTimerResolution = getDeviceInfoSizet . getCLValue $ CL_DEVICE_PROFILING_TIMER_RESOLUTION
-
--- | Describes the command-queue properties supported by the device. This is a 
--- list that describes one or more of the CLCommandQueueProperty values.
--- These properties are described in the table for 'clCreateCommandQueue'. 
--- The mandated minimum capability is 'CL_QUEUE_PROFILING_ENABLE'.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_QUEUE_PROPERTIES'.
-clGetDeviceQueueProperties :: CLDeviceID -> IO [CLCommandQueueProperty]
-clGetDeviceQueueProperties device = do
-  flags <- getDeviceInfoUlong (getCLValue CL_DEVICE_QUEUE_PROPERTIES) device
-  return . bitmaskToCommandQueueProperties $ flags
-    
--- | Describes single precision floating-point capability of the device. This is 
--- a bit-field that describes one or more of the 'CLDeviceFPConfig' values.
--- The mandated minimum floating-point capability is 'CL_FP_ROUND_TO_NEAREST' | 
--- 'CL_FP_INF_NAN'.
---
--- This function execute OpenCL clGetDeviceInfo with
--- 'CL_DEVICE_SINGLE_FP_CONFIG'.
-clGetDeviceSingleFPConfig :: CLDeviceID -> IO [CLDeviceFPConfig]
-clGetDeviceSingleFPConfig = getDeviceInfoFP . getCLValue $ CL_DEVICE_SINGLE_FP_CONFIG
-
--- | The OpenCL device type. Currently supported values are one of or a 
--- combination of: 'CL_DEVICE_TYPE_CPU', 'CL_DEVICE_TYPE_GPU', 
--- 'CL_DEVICE_TYPE_ACCELERATOR', or 'CL_DEVICE_TYPE_DEFAULT'.
---
--- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_TYPE'.
-clGetDeviceType :: CLDeviceID -> IO [CLDeviceType]
-clGetDeviceType device = do
-  flags <- getDeviceInfoUlong (getCLValue CL_DEVICE_TYPE) device
-  return . bitmaskToDeviceTypes $ flags
-
--- | Vendor name string.
---
--- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_VENDOR'.
-clGetDeviceVendor :: CLDeviceID -> IO String
-clGetDeviceVendor = getDeviceInfoString . getCLValue $ CL_DEVICE_VENDOR
-
--- | A unique device vendor identifier. An example of a unique device identifier 
--- could be the PCIe ID.
---
--- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_VENDOR_ID'.
-clGetDeviceVendorID :: CLDeviceID -> IO CLuint
-clGetDeviceVendorID = getDeviceInfoUint . getCLValue $ CL_DEVICE_VENDOR_ID
-
--- | OpenCL version string. Returns the OpenCL version supported by the device. 
--- This version string has the following format:
--- /OpenCL major_version.minor_version vendor-specific information/
--- The major_version.minor_version value returned will be 1.0.
---
--- This function execute OpenCL clGetDeviceInfo with 'CL_DEVICE_VERSION'.
-clGetDeviceVersion :: CLDeviceID -> IO String
-clGetDeviceVersion = getDeviceInfoString . getCLValue $ CL_DEVICE_VERSION
-
--- | OpenCL software driver version string in the form major_number.minor_number.
---
--- This function execute OpenCL clGetDeviceInfo with 'CL_DRIVER_VERSION'.
-clGetDeviceDriverVersion :: CLDeviceID -> IO String
-clGetDeviceDriverVersion = getDeviceInfoString . getCLValue $ CL_DRIVER_VERSION
-
--- -----------------------------------------------------------------------------
diff --git a/src/System/GPU/OpenCL/Types.chs b/src/System/GPU/OpenCL/Types.chs
deleted file mode 100644
--- a/src/System/GPU/OpenCL/Types.chs
+++ /dev/null
@@ -1,723 +0,0 @@
-{- Copyright (c) 2011 Luis Cabellos,
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above
-      copyright notice, this list of conditions and the following
-      disclaimer in the documentation and/or other materials provided
-      with the distribution.
-
-    * Neither the name of  nor the names of other
-      contributors may be used to endorse or promote products derived
-      from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--}
-{-# LANGUAGE DeriveDataTypeable #-}
-module System.GPU.OpenCL.Types( 
-  -- * Symple CL Types
-  CLbool, CLint, CLuint, CLulong, CLProgram, CLEvent, CLMem, CLPlatformID, 
-  CLDeviceID, CLContext, CLCommandQueue, CLPlatformInfo_, CLDeviceType_, 
-  CLDeviceInfo_, CLContextInfo_, CLContextProperty_, CLCommandQueueInfo_, 
-  CLEventInfo_, CLProfilingInfo_, CLCommandType_, CLCommandQueueProperty_, 
-  CLMemFlags_, CLImageFormat_p, CLMemObjectType_, CLMemInfo_, CLImageInfo_,
-  CLProgramInfo_, CLBuildStatus_,CLKernel, CLProgramBuildInfo_, CLKernelInfo_,
-  CLKernelWorkGroupInfo_, CLDeviceLocalMemType_, CLDeviceMemCacheType_,
-  CLSampler, CLFilterMode_, CLSamplerInfo_, CLAddressingMode_,
-  -- * High Level Types
-  CLError(..), CLDeviceFPConfig(..), CLDeviceMemCacheType(..), 
-  CLDeviceExecCapability(..), CLDeviceLocalMemType(..), CLDeviceType(..), 
-  CLCommandQueueProperty(..), CLCommandType(..),  CLCommandExecutionStatus(..), 
-  CLProfilingInfo(..), CLPlatformInfo(..), CLMemFlag(..), CLMemObjectType(..),
-  CLBuildStatus(..), CLAddressingMode(..), CLFilterMode(..),
-  -- * Functions
-  wrapPError, wrapCheckSuccess, wrapGetInfo, whenSuccess, getCLValue, 
-  throwCLError, getEnumCL, bitmaskToFlags, getCommandExecutionStatus, 
-  bitmaskToDeviceTypes, bitmaskFromFlags, bitmaskToCommandQueueProperties, 
-  bitmaskToFPConfig, bitmaskToExecCapability, bitmaskToMemFlags )
-       where
-
--- -----------------------------------------------------------------------------
-import Foreign
-import Foreign.C.Types
-import Data.List( foldl' )
-import Data.Typeable( Typeable(..) )
-import Control.Applicative( (<$>) )
-import Control.Exception( Exception(..), throwIO )
-
-#include <CL/cl.h>
-
--- -----------------------------------------------------------------------------
-
-type CLPlatformID = {#type cl_platform_id#}
-type CLDeviceID = {#type cl_device_id#}
-type CLContext = {#type cl_context#}
-type CLCommandQueue = {#type cl_command_queue#}
-type CLMem = {#type cl_mem#}
-type CLEvent = {#type cl_event#}
-type CLProgram = {#type cl_program#}
-type CLKernel = {#type cl_kernel#}
-type CLSampler = {#type cl_sampler#}
-
-type CLint = {#type cl_int#}
-type CLuint = {#type cl_uint#}
-type CLulong = {#type cl_ulong#}
-type CLbool = {#type cl_bool#}
-
-type CLPlatformInfo_ = {#type cl_platform_info#}
-type CLDeviceType_ = {#type cl_device_type#}
-type CLDeviceInfo_ = {#type cl_device_info#}
-type CLDeviceFPConfig_ = {#type cl_device_fp_config#}
-type CLDeviceMemCacheType_ = {#type cl_device_mem_cache_type#}
-type CLDeviceLocalMemType_ = {#type cl_device_local_mem_type#}
-type CLDeviceExecCapability_ = {#type cl_device_exec_capabilities#}
-type CLContextInfo_ = {#type cl_context_info#}
-type CLContextProperty_ = {#type cl_context_properties#}
-type CLCommandQueueInfo_ = {#type cl_command_queue_info#}
-type CLCommandQueueProperty_ = {#type cl_command_queue_properties#}
-type CLEventInfo_ = {#type cl_event_info#}
-type CLProfilingInfo_ = {#type cl_profiling_info#}
-type CLCommandType_ = {#type cl_command_type#}
-type CLMemFlags_ = {#type cl_mem_flags#}
-type CLMemObjectType_ = {#type cl_mem_object_type#}
-type CLMemInfo_ = {#type cl_mem_info#}
-type CLImageInfo_ = {#type cl_image_info#}
-type CLProgramInfo_ = {#type cl_program_info#}
-type CLProgramBuildInfo_ = {#type cl_program_build_info#}
-type CLBuildStatus_ = {#type cl_build_status#}
-type CLKernelInfo_ = {#type cl_kernel_info#}
-type CLKernelWorkGroupInfo_ = {#type cl_kernel_work_group_info#}
-type CLFilterMode_ = {#type cl_filter_mode#}
-type CLSamplerInfo_ = {#type cl_sampler_info#}
-type CLAddressingMode_ = {#type cl_addressing_mode#}
-
-{#pointer *cl_image_format as CLImageFormat_p#}
-
---type CLImageChannelOrder_ = {#type cl_channel_order#}
---type CLImageChannelDataType_ = {#type cl_channel_type#}
-
--- -----------------------------------------------------------------------------
-#c
-enum CLError {
-  cL_BUILD_PROGRAM_FAILURE=CL_BUILD_PROGRAM_FAILURE,
-  cL_COMPILER_NOT_AVAILABLE=CL_COMPILER_NOT_AVAILABLE,
-  cL_DEVICE_NOT_AVAILABLE=CL_DEVICE_NOT_AVAILABLE,
-  cL_DEVICE_NOT_FOUND=CL_DEVICE_NOT_FOUND,
-  cL_IMAGE_FORMAT_MISMATCH=CL_IMAGE_FORMAT_MISMATCH,
-  cL_IMAGE_FORMAT_NOT_SUPPORTED=CL_IMAGE_FORMAT_NOT_SUPPORTED,
-  cL_INVALID_ARG_INDEX=CL_INVALID_ARG_INDEX,
-  cL_INVALID_ARG_SIZE=CL_INVALID_ARG_SIZE,
-  cL_INVALID_ARG_VALUE=CL_INVALID_ARG_VALUE,
-  cL_INVALID_BINARY=CL_INVALID_BINARY,
-  cL_INVALID_BUFFER_SIZE=CL_INVALID_BUFFER_SIZE,
-  cL_INVALID_BUILD_OPTIONS=CL_INVALID_BUILD_OPTIONS,
-  cL_INVALID_COMMAND_QUEUE=CL_INVALID_COMMAND_QUEUE,
-  cL_INVALID_CONTEXT=CL_INVALID_CONTEXT,
-  cL_INVALID_DEVICE=CL_INVALID_DEVICE,
-  cL_INVALID_DEVICE_TYPE=CL_INVALID_DEVICE_TYPE,
-  cL_INVALID_EVENT=CL_INVALID_EVENT,
-  cL_INVALID_EVENT_WAIT_LIST=CL_INVALID_EVENT_WAIT_LIST,
-  cL_INVALID_GL_OBJECT=CL_INVALID_GL_OBJECT,
-  cL_INVALID_GLOBAL_OFFSET=CL_INVALID_GLOBAL_OFFSET,
-  cL_INVALID_HOST_PTR=CL_INVALID_HOST_PTR,
-  cL_INVALID_IMAGE_FORMAT_DESCRIPTOR=CL_INVALID_IMAGE_FORMAT_DESCRIPTOR,
-  cL_INVALID_IMAGE_SIZE=CL_INVALID_IMAGE_SIZE,
-  cL_INVALID_KERNEL_NAME=CL_INVALID_KERNEL_NAME,
-  cL_INVALID_KERNEL=CL_INVALID_KERNEL,
-  cL_INVALID_KERNEL_ARGS=CL_INVALID_KERNEL_ARGS,
-  cL_INVALID_KERNEL_DEFINITION=CL_INVALID_KERNEL_DEFINITION,
-  cL_INVALID_MEM_OBJECT=CL_INVALID_MEM_OBJECT,
-  cL_INVALID_OPERATION=CL_INVALID_OPERATION,
-  cL_INVALID_PLATFORM=CL_INVALID_PLATFORM,
-  cL_INVALID_PROGRAM=CL_INVALID_PROGRAM,
-  cL_INVALID_PROGRAM_EXECUTABLE=CL_INVALID_PROGRAM_EXECUTABLE,
-  cL_INVALID_QUEUE_PROPERTIES=CL_INVALID_QUEUE_PROPERTIES,
-  cL_INVALID_SAMPLER=CL_INVALID_SAMPLER,
-  cL_INVALID_VALUE=CL_INVALID_VALUE,
-  cL_INVALID_WORK_DIMENSION=CL_INVALID_WORK_DIMENSION,
-  cL_INVALID_WORK_GROUP_SIZE=CL_INVALID_WORK_GROUP_SIZE,
-  cL_INVALID_WORK_ITEM_SIZE=CL_INVALID_WORK_ITEM_SIZE,
-  cL_MAP_FAILURE=CL_MAP_FAILURE,
-  cL_MEM_OBJECT_ALLOCATION_FAILURE=CL_MEM_OBJECT_ALLOCATION_FAILURE,
-  cL_MEM_COPY_OVERLAP=CL_MEM_COPY_OVERLAP,
-  cL_OUT_OF_HOST_MEMORY=CL_OUT_OF_HOST_MEMORY,
-  cL_OUT_OF_RESOURCES=CL_OUT_OF_RESOURCES,
-  cL_PROFILING_INFO_NOT_AVAILABLE=CL_PROFILING_INFO_NOT_AVAILABLE,
-  cL_SUCCESS=CL_SUCCESS
-  };
-#endc
-
-{-| 
- * 'CL_BUILD_PROGRAM_FAILURE', Returned if there is a failure to build the
-program executable.
-
- * 'CL_COMPILER_NOT_AVAILABLE', Returned if the parameter program is created with
-'clCreateProgramWithSource' and a compiler is not available. For example
-'clDeviceCompilerAvalaible' is set to 'False'.
-
- * 'CL_DEVICE_NOT_AVAILABLE', Returned if the specified device is not currently
-available.
-
- * 'CL_DEVICE_NOT_FOUND', Returned if no OpenCL devices that match the specified
-devices were found.
-
- * 'CL_IMAGE_FORMAT_MISMATCH', Returned if the specified source and destination
-images are not valid image objects.
-
- * 'CL_IMAGE_FORMAT_NOT_SUPPORTED', Returned if the specified image format is not
-supported.
-
- * 'CL_INVALID_ARG_INDEX', Returned if an invalid argument index is specified.
-
- * 'CL_INVALID_ARG_SIZE', Returned if argument size specified (arg_size) does not
-match the size of the data type for an argument that is not a memory object, or
-if the argument is a memory object and arg_size != sizeof(cl_mem) or if arg_size
-is zero and the argument is declared with the __local qualifier or if the
-argument is a sampler and arg_size != sizeof(cl_sampler).
-
- * 'CL_INVALID_ARG_VALUE', Returned if the argument value specified is NULL for
-an argument that is not declared with the __local qualifier or vice-versa.
-
- * 'CL_INVALID_BINARY', Returned if the program binary is not a valid binary for
-the specified device.
-
- * 'CL_INVALID_BUFFER_SIZE', Returned if the value of the parameter size is 0 or
-is greater than 'clDeviceMaxMemAllocSize' for all devices specified in the
-parameter context.
-
- * 'CL_INVALID_BUILD_OPTIONS', Returned if the specified build options are
-invalid.
-
- * 'CL_INVALID_COMMAND_QUEUE', Returned if the specified command-queue is not a
-valid command-queue.
-
- * 'CL_INVALID_CONTEXT', Returned if the specified context is not a valid OpenCL
-context, or the context associated with certain parameters are not the same.
-
- * 'CL_INVALID_DEVICE', Returned if the device or devices specified are not
-valid.
-
- * 'CL_INVALID_DEVICE_TYPE', Returned if device type specified is not valid.
-
- * 'CL_INVALID_EVENT', Returned if the event objects specified are not valid.
-
- * 'CL_INVALID_EVENT_WAIT_LIST', Returned if event_wait_list is NULL and
-num_events_in_wait_list > 0, or event_wait_list_list is not NULL and
-num_events_in_wait_list is 0, or specified event objects are not valid events.
-
- * 'CL_INVALID_GL_OBJECT', Returned if obj is not a vaild GL object or is a GL
-object but does not have an existing data store.
-
- * 'CL_INVALID_GLOBAL_OFFSET', Returned if global_work_offset is not NULL.
-
- * 'CL_INVALID_HOST_PTR', Returned if host_ptr is NULL and 'CL_MEM_USE_HOST_PTR'
-or 'CL_MEM_COPY_HOST_PTR' are set in flags or if host_ptr is not NULL but
-'CL_MEM_COPY_HOST_PTR' or 'CL_MEM_USE_HOST_PTR' are not set in flags.
-
- * 'CL_INVALID_IMAGE_FORMAT_DESCRIPTOR', Returned if the image format specified
-is not valid or is NULL or does not map to a supported OpenCL image format.
-
- * 'CL_INVALID_IMAGE_SIZE', Returned if the specified image width or height are
-invalid or if the image row pitch and image slice pitch do not follow the rules.
-
- * 'CL_INVALID_KERNEL_NAME', Returned if the specified kernel name is not found
-in program.
-
- * 'CL_INVALID_KERNEL', Returned if the specified kernel is not a valid kernel
-object.
-
- * 'CL_INVALID_KERNEL_ARGS', Returned if the kernel argument values have not been
-specified.
-
- * 'CL_INVALID_KERNEL_DEFINITION', Returned if the function definition for
-__kernel function given by kernel_name such as the number of arguments, the
-argument types are not the same for all devices for which the program executable
-has been built.
-
- * 'CL_INVALID_MEM_OBJECT', Returned if a parameter is not a valid memory, image,
-or buffer object.
-
- * 'CL_INVALID_OPERATION', Returned if there are no devices in context that
-support images. Returned if the build of a program executable for any of the
-devices specified by a previous call to 'clBuildProgram' for program has not
-completed, or if there are kernel objects attached to program. Returned by
-'clEnqueueNativeKernel' if the specified device cannot execute the native
-kernel.
-
- * 'CL_INVALID_PLATFORM', Returned if the specified platform is not a valid
-platform, or no platform could be selected, or if platform value specified in
-properties is not a valid platform.
-
- * 'CL_INVALID_PROGRAM', Returned if the specified program is not a valid program
-object.
-
- * 'CL_INVALID_PROGRAM_EXECUTABLE', Returned if there is no successfully built
-executable for program, or if there is no device in program. Returned if there
-is no successfully built program executable available for device associated with
-command_queue.
-
- * 'CL_INVALID_QUEUE_PROPERTIES', Returned if specified properties are valid but
-are not supported by the device.
-
- * 'CL_INVALID_SAMPLER', Returned if the specified sampler is not a valid sampler
-object, or for an argument declared to be of type sampler_t when the specified
-arg_value is not a valid sampler object.
-
- * 'CL_INVALID_VALUE', Returned if a parameter is not an expected value.
-
- * 'CL_INVALID_WORK_DIMENSION', Returned if work_dim is not a valid value.
-
- * 'CL_INVALID_WORK_GROUP_SIZE', Returned if local_work_size is specified and
-number of workitems specified by global_work_size is not evenly divisible by
-size of work-group given by local_work_size or does not match the work-group
-size specified for kernel using the __attribute__((reqd_work_group_size(X, Y,
-Z))) qualifier in program source.
-
- * 'CL_INVALID_WORK_ITEM_SIZE', Returned if the number of work-items specified in
-any of local_work_size... [0]... local_work_size[work_dim - 1] is greater than
-the corresponding values specified by 'clDeviceMaxWorkItemSizes'.
-
- * 'CL_MAP_FAILURE', Returned by if there is a failure to map the requested
-region into the host address space. This error cannot occur for buffer objects
-created with 'CLMEM_USE_HOST_PTR' or 'CLMEM_ALLOC_HOST_PTR'.
-
- * 'CL_MEM_OBJECT_ALLOCATION_FAILURE', Returned if there is a failure to allocate
-memory for data store associated with image or buffer objects specified as
-arguments to kernel.
-
- * 'CL_MEM_COPY_OVERLAP', Returned if the source and destination images are the
-same image (or the source and destination buffers are the same buffer), and the
-source and destination regions overlap.
-
- * 'CL_OUT_OF_HOST_MEMORY', Returned in the event of a failure to allocate
-resources required by the OpenCL implementation on the host.
-
- * 'CL_OUT_OF_RESOURCES', Returned in the event of a failure to queue the
-execution instance of kernel on the command-queue because of insufficient
-resources needed to execute the kernel.
-
- * 'CL_PROFILING_INFO_NOT_AVAILABLE', Returned if the 'CL_QUEUE_PROFILING_ENABLE'
-flag is not set for the command-queue and the profiling information is currently
-not available (because the command identified by event has not completed).
-
- * 'CL_SUCCESS', Indicates that the function executed successfully.
--}
-{#enum CLError {upcaseFirstLetter} deriving( Show, Eq, Typeable ) #}
-
-instance Exception CLError
-
-throwCLError :: CLint -> IO a
-throwCLError = throwIO . (getEnumCL :: CLint -> CLError)
-
-wrapPError :: (Ptr CLint -> IO a) -> IO a
-wrapPError f = alloca $ \perr -> do
-  v <- f perr
-  errcode <- getEnumCL <$> peek perr
-  if errcode == CL_SUCCESS
-    then return v
-    else throwIO errcode
-  
-wrapCheckSuccess :: IO CLint -> IO Bool
-wrapCheckSuccess f = f >>= return . (==CL_SUCCESS) . getEnumCL
-
-wrapGetInfo :: Storable a 
-               => (Ptr a -> Ptr CSize -> IO CLint) -> (a -> b) -> IO b
-wrapGetInfo fget fconvert= alloca $ \dat -> do
-  errcode <- fget dat nullPtr
-  if errcode == getCLValue CL_SUCCESS
-    then fmap fconvert $ peek dat
-    else throwCLError errcode
-
-whenSuccess :: IO CLint -> IO a -> IO a
-whenSuccess fcheck fval = do
-  errcode <- fcheck
-  if errcode == getCLValue CL_SUCCESS
-    then fval
-    else throwCLError errcode
-         
--- -----------------------------------------------------------------------------
-#c
-enum CLPlatformInfo {
-  cL_PLATFORM_PROFILE=CL_PLATFORM_PROFILE,
-  cL_PLATFORM_VERSION=CL_PLATFORM_VERSION,
-  cL_PLATFORM_NAME=CL_PLATFORM_NAME,
-  cL_PLATFORM_VENDOR=CL_PLATFORM_VENDOR,
-  cL_PLATFORM_EXTENSIONS=CL_PLATFORM_EXTENSIONS
-  };
-#endc
-
-{-|
- * 'CL_PLATFORM_PROFILE', OpenCL profile string. Returns the profile name 
-supported by the implementation. The profile name returned can be one of the 
-following strings:
-
- [@FULL_PROFILE@] If the implementation supports the OpenCL specification
-(functionality defined as part of the core specification and does not require
-any extensions to be supported).
-
- [@EMBEDDED_PROFILE@] If the implementation supports the OpenCL embedded 
-profile. The embedded profile is  defined to be a subset for each version of 
-OpenCL.
-
- * 'CL_PLATFORM_VERSION', OpenCL version string. Returns the OpenCL version 
-supported by the implementation. This version string has the following format: 
-/OpenCL major_version.minor_version platform-specific information/ The 
-/major_version.minor_version/ value returned will be 1.0.
-                    
- * 'CL_PLATFORM_NAME', Platform name string.
- 
- * 'CL_PLATFORM_VENDOR', Platform vendor string.
-                   
- * 'CL_PLATFORM_EXTENSIONS', Returns a space-separated list of extension names 
-(the extension names themselves do not contain any spaces) supported by the 
-platform. Extensions defined here must be supported by all devices associated 
-with this platform.
--}
-{#enum CLPlatformInfo {upcaseFirstLetter} deriving( Show ) #}
-
--- -----------------------------------------------------------------------------
-#c
-enum CLDeviceType {
-  cL_DEVICE_TYPE_CPU=CL_DEVICE_TYPE_CPU,
-  cL_DEVICE_TYPE_GPU=CL_DEVICE_TYPE_GPU,
-  cL_DEVICE_TYPE_ACCELERATOR=CL_DEVICE_TYPE_ACCELERATOR,
-  cL_DEVICE_TYPE_DEFAULT=CL_DEVICE_TYPE_DEFAULT,
-  cL_DEVICE_TYPE_ALL=CL_DEVICE_TYPE_ALL
-  };
-#endc
-
-{-|
- * 'CL_DEVICE_TYPE_CPU', An OpenCL device that is the host processor. The host 
-processor runs the OpenCL implementations and is a single or multi-core CPU.
-                  
- * 'CL_DEVICE_TYPE_GPU', An OpenCL device that is a GPU. By this we mean that the 
-device can also be used to accelerate a 3D API such as OpenGL or DirectX.
-                  
- * 'CL_DEVICE_TYPE_ACCELERATOR', Dedicated OpenCL accelerators (for example the 
-IBM CELL Blade). These devices communicate with the host processor using a 
-peripheral interconnect such as PCIe.
-                
- * 'CL_DEVICE_TYPE_DEFAULT', The default OpenCL device in the system.
-           
- * 'CL_DEVICE_TYPE_ALL', All OpenCL devices available in the system.
--}
-{#enum CLDeviceType {upcaseFirstLetter} deriving( Show ) #}
-
-#c
-enum CLCommandQueueProperty { 
-  cL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE=CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE,
-  cL_QUEUE_PROFILING_ENABLE=CL_QUEUE_PROFILING_ENABLE
-  };
-#endc
-
-{-|
- * 'CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE', Determines whether the commands 
-queued in the command-queue are executed in-order or out-of-order. If set, the 
-commands in the command-queue are executed out-of-order. Otherwise, commands are 
-executed in-order.
-                            
- * 'CL_QUEUE_PROFILING_ENABLE', Enable or disable profiling of commands in the 
-command-queue. If set, the profiling of commands is enabled. Otherwise profiling 
-of commands is disabled. See 'clGetEventProfilingInfo' for more information.
--}
-{#enum CLCommandQueueProperty {upcaseFirstLetter} deriving( Show, Bounded, Eq, Ord ) #}
-
-#c
-enum CLDeviceFPConfig {
-  cL_FP_DENORM=CL_FP_DENORM, cL_FP_INF_NAN=CL_FP_INF_NAN,
-  cL_FP_ROUND_TO_NEAREST=CL_FP_ROUND_TO_NEAREST,
-  cL_FP_ROUND_TO_ZERO=CL_FP_ROUND_TO_ZERO,
-  cL_FP_ROUND_TO_INF=CL_FP_ROUND_TO_INF, cL_FP_FMA=CL_FP_FMA,
-  };
-#endc
-
-{-|
- * 'CL_FP_DENORM', denorms are supported.
-                      
- * 'CL_FP_INF_NAN', INF and NaNs are supported.
-                      
- * 'CL_FP_ROUND_TO_NEAREST', round to nearest even rounding mode supported.
-                      
- * 'CL_FP_ROUND_TO_ZERO', round to zero rounding mode supported.
-                      
- * 'CL_FP_ROUND_TO_INF', round to +ve and -ve infinity rounding modes supported.
-                      
- * 'CL_FP_FMA', IEEE754-2008 fused multiply-add is supported.
--}
-{#enum CLDeviceFPConfig {upcaseFirstLetter} deriving( Show, Bounded, Eq, Ord ) #}
-
-#c
-enum CLDeviceExecCapability {
-  cL_EXEC_KERNEL=CL_EXEC_KERNEL,
-  cL_EXEC_NATIVE_KERNEL=CL_EXEC_NATIVE_KERNEL
-  };
-#endc
-
-{-|
- * 'CL_EXEC_KERNEL', The OpenCL device can execute OpenCL kernels.
-                            
- * 'CL_EXEC_NATIVE_KERNEL', The OpenCL device can execute native kernels.
--}
-{#enum CLDeviceExecCapability {upcaseFirstLetter} deriving( Show, Bounded, Eq, Ord ) #}
-
-#c
-enum CLDeviceMemCacheType {
-  cL_NONE=CL_NONE, cL_READ_ONLY_CACHE=CL_READ_ONLY_CACHE,
-  cL_READ_WRITE_CACHE=CL_READ_WRITE_CACHE
-  };
-#endc
-
-{#enum CLDeviceMemCacheType {upcaseFirstLetter} deriving( Show ) #}
-
-#c
-enum CLDeviceLocalMemType {
-  cL_LOCAL=CL_LOCAL, cL_GLOBAL=CL_GLOBAL
-  };
-#endc
-
-{#enum CLDeviceLocalMemType {upcaseFirstLetter} deriving( Show ) #}
-
--- -----------------------------------------------------------------------------
-#c
-enum CLCommandType {
-  cL_COMMAND_NDRANGE_KERNEL=CL_COMMAND_NDRANGE_KERNEL,
-  cL_COMMAND_TASK=CL_COMMAND_TASK ,
-  cL_COMMAND_NATIVE_KERNEL=CL_COMMAND_NATIVE_KERNEL,
-  cL_COMMAND_READ_BUFFER=CL_COMMAND_READ_BUFFER,
-  cL_COMMAND_WRITE_BUFFER=CL_COMMAND_WRITE_BUFFER,
-  cL_COMMAND_COPY_BUFFER=CL_COMMAND_COPY_BUFFER,
-  cL_COMMAND_READ_IMAGE=CL_COMMAND_READ_IMAGE,
-  cL_COMMAND_WRITE_IMAGE=CL_COMMAND_WRITE_IMAGE,
-  cL_COMMAND_COPY_IMAGE=CL_COMMAND_COPY_IMAGE,
-  cL_COMMAND_COPY_BUFFER_TO_IMAGE=CL_COMMAND_COPY_BUFFER_TO_IMAGE,
-  cL_COMMAND_COPY_IMAGE_TO_BUFFER=CL_COMMAND_COPY_IMAGE_TO_BUFFER,
-  cL_COMMAND_MAP_BUFFER=CL_COMMAND_MAP_BUFFER,
-  cL_COMMAND_MAP_IMAGE=CL_COMMAND_MAP_IMAGE,
-  cL_COMMAND_UNMAP_MEM_OBJECT=CL_COMMAND_UNMAP_MEM_OBJECT,
-  cL_COMMAND_MARKER=CL_COMMAND_MARKER,
-  cL_COMMAND_ACQUIRE_GL_OBJECTS=CL_COMMAND_ACQUIRE_GL_OBJECTS,
-  cL_COMMAND_RELEASE_GL_OBJECTS=CL_COMMAND_RELEASE_GL_OBJECTS
-  };
-#endc
-
--- | Command associated with an event.
-{#enum CLCommandType {upcaseFirstLetter} deriving( Show ) #}
-
-#c
-enum CLCommandExecutionStatus {
-  cL_QUEUED=CL_QUEUED, cL_SUBMITTED=CL_SUBMITTED, cL_RUNNING=CL_RUNNING,
-  cL_COMPLETE=CL_COMPLETE, cL_EXEC_ERROR= -1
-  };
-#endc
-
-{-|
- * 'CL_QUEUED', command has been enqueued in the command-queue.
-
- * 'CL_SUBMITTED', enqueued command has been submitted by the host to the 
-device associated with the command-queue.
-
- * 'CL_RUNNING', device is currently executing this command.
-                            
- * 'CL_COMPLETE', the command has completed.
-                              
- * 'CL_EXEC_ERROR', command was abnormally terminated.
--}
-{#enum CLCommandExecutionStatus {upcaseFirstLetter} deriving( Show ) #}
-
-#c
-enum CLProfilingInfo {
-  cL_PROFILING_COMMAND_QUEUED=CL_PROFILING_COMMAND_QUEUED,
-  cL_PROFILING_COMMAND_SUBMIT=CL_PROFILING_COMMAND_SUBMIT,
-  cL_PROFILING_COMMAND_START=CL_PROFILING_COMMAND_START,
-  cL_PROFILING_COMMAND_END=CL_PROFILING_COMMAND_END
-  };
-#endc
-
-{-| Specifies the profiling data.
-
- * 'CL_PROFILING_COMMAND_QUEUED', A 64-bit value that describes the current 
-device time counter in nanoseconds when the command identified by event is 
-enqueued in a command-queue by the host.
- 
- * 'CL_PROFILING_COMMAND_SUBMIT', A 64-bit value that describes the current 
-device time counter in nanoseconds when the command identified by event that has 
-been enqueued is submitted by the host to the device associated with the 
-commandqueue.
- 
- * 'CL_PROFILING_COMMAND_START', A 64-bit value that describes the current 
-device time counter in nanoseconds when the command identified by event starts 
-execution on the device.
- 
- * 'CL_PROFILING_COMMAND_END', A 64-bit value that describes the current device 
-time counter in nanoseconds when the command identified by event has finished 
-execution on the device.
--}
-{#enum CLProfilingInfo {upcaseFirstLetter} deriving( Show ) #}
-
--- -----------------------------------------------------------------------------
-#c
-enum CLMemFlag {
-  cL_MEM_READ_WRITE=CL_MEM_READ_WRITE,
-  cL_MEM_WRITE_ONLY=CL_MEM_WRITE_ONLY,
-  cL_MEM_READ_ONLY=CL_MEM_READ_ONLY,
-  cL_MEM_USE_HOST_PTR=CL_MEM_USE_HOST_PTR,
-  cL_MEM_ALLOC_HOST_PTR=CL_MEM_ALLOC_HOST_PTR,
-  cL_MEM_COPY_HOST_PTR=CL_MEM_COPY_HOST_PTR
-  };
-#endc
-{-| 
- * 'CL_MEM_READ_WRITE', This flag specifies that the memory object will be
-read and written by a kernel. This is the default.
-
- * 'CL_MEM_WRITE_ONLY', This flags specifies that the memory object will be
-written but not read by a kernel. Reading from a buffer or image object created
-with 'CLMEM_WRITE_ONLY' inside a kernel is undefined.
-
- * 'CL_MEM_READ_ONLY', This flag specifies that the memory object is a read-only
-memory object when used inside a kernel. Writing to a buffer or image object
-created with 'CLMEM_READ_ONLY' inside a kernel is undefined.
-
- * 'CL_MEM_USE_HOST_PTR', This flag is valid only if host_ptr is not NULL. If
-specified, it indicates that the application wants the OpenCL implementation to
-use memory referenced by host_ptr as the storage bits for the memory
-object. OpenCL implementations are allowed to cache the buffer contents pointed
-to by host_ptr in device memory. This cached copy can be used when kernels are
-executed on a device. The result of OpenCL commands that operate on multiple
-buffer objects created with the same host_ptr or overlapping host regions is
-considered to be undefined.
-
- * 'CL_MEM_ALLOC_HOST_PTR', This flag specifies that the application wants the
-OpenCL implementation to allocate memory from host accessible
-memory. 'CL_MEM_ALLOC_HOST_PTR' and 'CL_MEM_USE_HOST_PTR' are mutually exclusive.
-
- * 'CL_MEM_COPY_HOST_PTR', This flag is valid only if host_ptr is not NULL. If
-specified, it indicates that the application wants the OpenCL implementation to
-allocate memory for the memory object and copy the data from memory referenced
-by host_ptr. 'CL_MEM_COPY_HOST_PTR' and 'CL_MEM_USE_HOST_PTR' are mutually
-exclusive. 'CL_MEM_COPY_HOST_PTR' can be used with 'CL_MEM_ALLOC_HOST_PTR' to
-initialize the contents of the cl_mem object allocated using host-accessible
-(e.g. PCIe) memory.  
--} 
-{#enum CLMemFlag {upcaseFirstLetter} deriving( Show, Bounded, Eq, Ord ) #}
-
-#c
-enum CLMemObjectType {
-  cL_MEM_OBJECT_BUFFER=CL_MEM_OBJECT_BUFFER,
-  cL_MEM_OBJECT_IMAGE2D=CL_MEM_OBJECT_IMAGE2D,
-  cL_MEM_OBJECT_IMAGE3D=CL_MEM_OBJECT_IMAGE3D
-  };
-#endc
-
-{-| * 'CL_MEM_OBJECT_BUFFER' if memobj is created with 'clCreateBuffer'. 
- 
- * 'CL_MEM_OBJECT_IMAGE2D' if memobj is created with 'clCreateImage2D' 
-
- * 'CL_MEM_OBJECT_IMAGE3D' if memobj is created with 'clCreateImage3D'.
--}
-{#enum CLMemObjectType {upcaseFirstLetter} deriving( Show ) #}
-
-#c
-enum CLBuildStatus {
-  cL_BUILD_NONE=CL_BUILD_NONE,
-  cL_BUILD_ERROR=CL_BUILD_ERROR,
-  cL_BUILD_SUCCESS=CL_BUILD_SUCCESS,
-  cL_BUILD_IN_PROGRESS=CL_BUILD_IN_PROGRESS,
-  };
-#endc
-
-{-| * 'CL_BUILD_NONE'. The build status returned if no build has been performed
-on the specified program object for device.
-
- * 'CL_BUILD_ERROR'. The build status returned if the last call to
-'clBuildProgram' on the specified program object for device generated an error.
-
- * 'CL_BUILD_SUCCESS'. The build status retrned if the last call to
-'clBuildProgram' on the specified program object for device was successful.
-
- * 'CL_BUILD_IN_PROGRESS'. The build status returned if the last call to 
-'clBuildProgram' on the specified program object for device has not finished.
--}
-{#enum CLBuildStatus {upcaseFirstLetter} deriving( Show ) #}
-
-#c
-enum CLAddressingMode {
-  cL_ADDRESS_REPEAT=CL_ADDRESS_REPEAT,
-  cL_ADDRESS_CLAMP_TO_EDGE =CL_ADDRESS_CLAMP_TO_EDGE ,
-  cL_ADDRESS_CLAMP=CL_ADDRESS_CLAMP,
-  cL_ADDRESS_NONE=CL_ADDRESS_NONE
-  };
-#endc
-{#enum CLAddressingMode {upcaseFirstLetter} deriving( Show ) #}
-
-#c
-enum CLFilterMode {
-  cL_FILTER_NEAREST=CL_FILTER_NEAREST,
-  cL_FILTER_LINEAR=CL_FILTER_LINEAR,
-  };
-#endc
-{#enum CLFilterMode {upcaseFirstLetter} deriving( Show ) #}
-
--- -----------------------------------------------------------------------------
-getCLValue :: (Enum a, Integral b) => a -> b
-getCLValue = fromIntegral . fromEnum
-
-getEnumCL :: (Integral a, Enum b) => a -> b
-getEnumCL = toEnum . fromIntegral 
-
-getCommandExecutionStatus :: CLint -> CLCommandExecutionStatus
-getCommandExecutionStatus n 
-  | n < 0 = CL_EXEC_ERROR
-  | otherwise = getEnumCL $ n
-                
--- -----------------------------------------------------------------------------
-binaryFlags :: (Ord b, Enum b, Bounded b) => b -> [b]
-binaryFlags m = map toEnum . takeWhile (<= (fromEnum m)) $ [1 `shiftL` n | n <- [0..]]
-  
-testMask :: Bits b => b -> b -> Bool
-testMask mask v = (v .&. mask) == v
-
-bitmaskFromFlags :: (Enum a, Bits b) => [a] -> b
-bitmaskFromFlags = foldl' (.|.) 0 . map (fromIntegral . fromEnum)
-
-bitmaskToFlags :: (Enum a, Bits b) => [a] -> b -> [a]
-bitmaskToFlags xs mask = filter (testMask mask . fromIntegral . fromEnum) xs
-
-bitmaskToDeviceTypes :: CLDeviceType_ -> [CLDeviceType]
-bitmaskToDeviceTypes =
-	bitmaskToFlags 
-		[CL_DEVICE_TYPE_CPU
-		,CL_DEVICE_TYPE_GPU
-		,CL_DEVICE_TYPE_ACCELERATOR
-		,CL_DEVICE_TYPE_DEFAULT
-		,CL_DEVICE_TYPE_ALL
-		]
-
-bitmaskToCommandQueueProperties :: CLCommandQueueProperty_ -> [CLCommandQueueProperty]
-bitmaskToCommandQueueProperties = bitmaskToFlags (binaryFlags maxBound)
-      
-bitmaskToFPConfig :: CLDeviceFPConfig_ -> [CLDeviceFPConfig]
-bitmaskToFPConfig = bitmaskToFlags (binaryFlags maxBound)
-
-bitmaskToExecCapability :: CLDeviceExecCapability_ -> [CLDeviceExecCapability]
-bitmaskToExecCapability = bitmaskToFlags (binaryFlags maxBound)
-
-bitmaskToMemFlags :: CLMemFlags_ -> [CLMemFlag]
-bitmaskToMemFlags = bitmaskToFlags (binaryFlags maxBound)
-
--- -----------------------------------------------------------------------------
diff --git a/src/test/test-opencl.hs b/src/test/test-opencl.hs
--- a/src/test/test-opencl.hs
+++ b/src/test/test-opencl.hs
@@ -39,7 +39,7 @@
 import Test.QuickCheck.Test( Result, Args(..), isSuccess, stdArgs )
 import Text.Printf( printf )
 import System.Exit( exitSuccess, exitFailure )
-import System.GPU.OpenCL
+import Control.Parallel.OpenCL
 
 -- -----------------------------------------------------------------------------
 clDupSource :: String
@@ -50,7 +50,7 @@
   -- Initialize OpenCL
   (platform:_) <- clGetPlatformIDs
   (dev:_) <- clGetDeviceIDs platform CL_DEVICE_TYPE_ALL
-  context <- clCreateContext [dev] print
+  context <- clCreateContext [] [dev] print
   q <- clCreateCommandQueue context dev []
   
   -- Initialize Kernel
@@ -68,8 +68,8 @@
   mem_in <- clCreateBuffer context [CL_MEM_READ_ONLY, CL_MEM_COPY_HOST_PTR] (vecSize, castPtr input)  
   mem_out <- clCreateBuffer context [CL_MEM_WRITE_ONLY] (vecSize, nullPtr)
 
-  clSetKernelArg kernel 0 mem_in
-  clSetKernelArg kernel 1 mem_out
+  clSetKernelArgSto kernel 0 mem_in
+  clSetKernelArgSto kernel 1 mem_out
   
   -- Execute Kernel
   eventExec <- clEnqueueNDRangeKernel q kernel [length original] [1] []
