[
  {
    "path": ".gitignore",
    "content": "*~\n*.so\n*.dylib\n*.dSYM\nopencl-test\ntarget/\n.rust\nbin/\ndoc/\nCargo.lock\nbuild/\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: rust\nrust: nightly\n\nenv:\n  global:\n    - secure: TUA5IHO5hwaQvgA1gAvslQ4QWhHEym5bFmmm7nAKHVIxRDchpCmjaLPmu3DirxRJBXi0b5zOZypIH75TMlivfnciQSWr9rj3PaaK+P6LpGScHvYsi/JEawtPJ8V5+xAvOKJ/HsNk5wGS+BBDv4YCPAG5itixMaFxQAVmKw1VMeo=\n    - RUST_THREADS=4\n\ninstall:\n  - sudo apt-get update\n  - sudo apt-get install fglrx opencl-headers\n\nafter_script:\n- curl http://www.rust-ci.org/artifacts/put?t=$RUSTCI_TOKEN | sh"
  },
  {
    "path": "COPYRIGHT",
    "content": "rust-opencl - OpenCL Binding and Higher Level Wrapper for Rust.\nCopyright (C) 2013 - The rust-opencl Developers\n\nLicensed under the Apache License, Version 2.0 <http://www.apache.org/licenses/LICENSE-2.0>\nor the MIT license <http://opensource.org/licenses/MIT>, at your option. All files in the project\nmay not be copied, modified, or distributed except according to those terms.\n\nCopies of both licenses are included: LICENSE-APACHE and LICENSE-MIT\n"
  },
  {
    "path": "Cargo.toml",
    "content": "[package]\nname = \"opencl\"\nversion = \"0.3.0-dev\"\nauthors = [ \"Colin Sherratt <colin.sherratt@gmail.com>\",\n            \"Eric Holk <eholk@cs.indiana.edu>\",\n            \"Ian Daniher <it.daniher@gmail.com>\",\n            \"Luqman Aden <me@luqman.ca>\",\n            \"Milinda Pathirage <milinda.pathirage@gmail.com>\",\n            \"Sébastien Crozet <developer@crozet.re>\",\n            \"Mathijs Henquet <mathijs.henquet@gmail.com>\"\n          ]\nrepository = \"https://github.com/luqmana/rust-opencl\"\nlicense = \"MIT/Apache-2.0\"\ndescription = \"OpenCL bindings for Rust.\"\nkeywords = [\"opencl\", \"bindings\", \"ffi\", \"gpu\", \"compute\"]\n\n[lib]\nname = \"opencl\"\n\n[[example]]\nname = \"demo\"\npath = \"examples/demo/main.rs\"\n\n[[example]]\nname = \"platform\"\npath = \"examples/platform/main.rs\"\n\n[dependencies]\nlog = \"^0.3.1\"\nlibc = \"^0.1.8\""
  },
  {
    "path": "LICENSE-APACHE",
    "content": "                              Apache License\n                        Version 2.0, January 2004\n                     http://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n   \"License\" shall mean the terms and conditions for use, reproduction,\n   and distribution as defined by Sections 1 through 9 of this document.\n\n   \"Licensor\" shall mean the copyright owner or entity authorized by\n   the copyright owner that is granting the License.\n\n   \"Legal Entity\" shall mean the union of the acting entity and all\n   other entities that control, are controlled by, or are under common\n   control with that entity. For the purposes of this definition,\n   \"control\" means (i) the power, direct or indirect, to cause the\n   direction or management of such entity, whether by contract or\n   otherwise, or (ii) ownership of fifty percent (50%) or more of the\n   outstanding shares, or (iii) beneficial ownership of such entity.\n\n   \"You\" (or \"Your\") shall mean an individual or Legal Entity\n   exercising permissions granted by this License.\n\n   \"Source\" form shall mean the preferred form for making modifications,\n   including but not limited to software source code, documentation\n   source, and configuration files.\n\n   \"Object\" form shall mean any form resulting from mechanical\n   transformation or translation of a Source form, including but\n   not limited to compiled object code, generated documentation,\n   and conversions to other media types.\n\n   \"Work\" shall mean the work of authorship, whether in Source or\n   Object form, made available under the License, as indicated by a\n   copyright notice that is included in or attached to the work\n   (an example is provided in the Appendix below).\n\n   \"Derivative Works\" shall mean any work, whether in Source or Object\n   form, that is based on (or derived from) the Work and for which the\n   editorial revisions, annotations, elaborations, or other modifications\n   represent, as a whole, an original work of authorship. For the purposes\n   of this License, Derivative Works shall not include works that remain\n   separable from, or merely link (or bind by name) to the interfaces of,\n   the Work and Derivative Works thereof.\n\n   \"Contribution\" shall mean any work of authorship, including\n   the original version of the Work and any modifications or additions\n   to that Work or Derivative Works thereof, that is intentionally\n   submitted to Licensor for inclusion in the Work by the copyright owner\n   or by an individual or Legal Entity authorized to submit on behalf of\n   the copyright owner. For the purposes of this definition, \"submitted\"\n   means any form of electronic, verbal, or written communication sent\n   to the Licensor or its representatives, including but not limited to\n   communication on electronic mailing lists, source code control systems,\n   and issue tracking systems that are managed by, or on behalf of, the\n   Licensor for the purpose of discussing and improving the Work, but\n   excluding communication that is conspicuously marked or otherwise\n   designated in writing by the copyright owner as \"Not a Contribution.\"\n\n   \"Contributor\" shall mean Licensor and any individual or Legal Entity\n   on behalf of whom a Contribution has been received by Licensor and\n   subsequently incorporated within the Work.\n\n2. Grant of Copyright License. Subject to the terms and conditions of\n   this License, each Contributor hereby grants to You a perpetual,\n   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n   copyright license to reproduce, prepare Derivative Works of,\n   publicly display, publicly perform, sublicense, and distribute the\n   Work and such Derivative Works in Source or Object form.\n\n3. Grant of Patent License. Subject to the terms and conditions of\n   this License, each Contributor hereby grants to You a perpetual,\n   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n   (except as stated in this section) patent license to make, have made,\n   use, offer to sell, sell, import, and otherwise transfer the Work,\n   where such license applies only to those patent claims licensable\n   by such Contributor that are necessarily infringed by their\n   Contribution(s) alone or by combination of their Contribution(s)\n   with the Work to which such Contribution(s) was submitted. If You\n   institute patent litigation against any entity (including a\n   cross-claim or counterclaim in a lawsuit) alleging that the Work\n   or a Contribution incorporated within the Work constitutes direct\n   or contributory patent infringement, then any patent licenses\n   granted to You under this License for that Work shall terminate\n   as of the date such litigation is filed.\n\n4. Redistribution. You may reproduce and distribute copies of the\n   Work or Derivative Works thereof in any medium, with or without\n   modifications, and in Source or Object form, provided that You\n   meet the following conditions:\n\n   (a) You must give any other recipients of the Work or\n       Derivative Works a copy of this License; and\n\n   (b) You must cause any modified files to carry prominent notices\n       stating that You changed the files; and\n\n   (c) You must retain, in the Source form of any Derivative Works\n       that You distribute, all copyright, patent, trademark, and\n       attribution notices from the Source form of the Work,\n       excluding those notices that do not pertain to any part of\n       the Derivative Works; and\n\n   (d) If the Work includes a \"NOTICE\" text file as part of its\n       distribution, then any Derivative Works that You distribute must\n       include a readable copy of the attribution notices contained\n       within such NOTICE file, excluding those notices that do not\n       pertain to any part of the Derivative Works, in at least one\n       of the following places: within a NOTICE text file distributed\n       as part of the Derivative Works; within the Source form or\n       documentation, if provided along with the Derivative Works; or,\n       within a display generated by the Derivative Works, if and\n       wherever such third-party notices normally appear. The contents\n       of the NOTICE file are for informational purposes only and\n       do not modify the License. You may add Your own attribution\n       notices within Derivative Works that You distribute, alongside\n       or as an addendum to the NOTICE text from the Work, provided\n       that such additional attribution notices cannot be construed\n       as modifying the License.\n\n   You may add Your own copyright statement to Your modifications and\n   may provide additional or different license terms and conditions\n   for use, reproduction, or distribution of Your modifications, or\n   for any such Derivative Works as a whole, provided Your use,\n   reproduction, and distribution of the Work otherwise complies with\n   the conditions stated in this License.\n\n5. Submission of Contributions. Unless You explicitly state otherwise,\n   any Contribution intentionally submitted for inclusion in the Work\n   by You to the Licensor shall be under the terms and conditions of\n   this License, without any additional terms or conditions.\n   Notwithstanding the above, nothing herein shall supersede or modify\n   the terms of any separate license agreement you may have executed\n   with Licensor regarding such Contributions.\n\n6. Trademarks. This License does not grant permission to use the trade\n   names, trademarks, service marks, or product names of the Licensor,\n   except as required for reasonable and customary use in describing the\n   origin of the Work and reproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty. Unless required by applicable law or\n   agreed to in writing, Licensor provides the Work (and each\n   Contributor provides its Contributions) on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n   implied, including, without limitation, any warranties or conditions\n   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n   PARTICULAR PURPOSE. You are solely responsible for determining the\n   appropriateness of using or redistributing the Work and assume any\n   risks associated with Your exercise of permissions under this License.\n\n8. Limitation of Liability. In no event and under no legal theory,\n   whether in tort (including negligence), contract, or otherwise,\n   unless required by applicable law (such as deliberate and grossly\n   negligent acts) or agreed to in writing, shall any Contributor be\n   liable to You for damages, including any direct, indirect, special,\n   incidental, or consequential damages of any character arising as a\n   result of this License or out of the use or inability to use the\n   Work (including but not limited to damages for loss of goodwill,\n   work stoppage, computer failure or malfunction, or any and all\n   other commercial damages or losses), even if such Contributor\n   has been advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability. While redistributing\n   the Work or Derivative Works thereof, You may choose to offer,\n   and charge a fee for, acceptance of support, warranty, indemnity,\n   or other liability obligations and/or rights consistent with this\n   License. However, in accepting such obligations, You may act only\n   on Your own behalf and on Your sole responsibility, not on behalf\n   of any other Contributor, and only if You agree to indemnify,\n   defend, and hold each Contributor harmless for any liability\n   incurred by, or claims asserted against, such Contributor by reason\n   of your accepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n\nAPPENDIX: How to apply the Apache License to your work.\n\n   To apply the Apache License to your work, attach the following\n   boilerplate notice, with the fields enclosed by brackets \"[]\"\n   replaced with your own identifying information. (Don't include\n   the brackets!)  The text should be enclosed in the appropriate\n   comment syntax for the file format. We also recommend that a\n   file or class name and description of purpose be included on the\n   same \"printed page\" as the copyright notice for easier\n   identification within third-party archives.\n\nCopyright [yyyy] [name of copyright owner]\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\thttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n"
  },
  {
    "path": "LICENSE-MIT",
    "content": "MIT License\nhttp://opensource.org/licenses/MIT\n\nPermission is hereby granted, free of charge, to any\nperson obtaining a copy of this software and associated\ndocumentation files (the \"Software\"), to deal in the\nSoftware without restriction, including without\nlimitation the rights to use, copy, modify, merge,\npublish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software\nis furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice\nshall be included in all copies or substantial portions\nof the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF\nANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED\nTO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\nPARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT\nSHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR\nIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\nDEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "Makefile",
    "content": "\nifndef RUSTC\n\tRUSTC = rustc\nendif\n\nifndef TARGET_DIR\n\tTARGET_DIR = target/\nendif\n\nRUSTC_OPTS = -g -L $(TARGET_DIR) --out-dir $(TARGET_DIR)\n\nOPENCL_SRC = \\\n\tlib.rs \\\n\tCL.rs \\\n\terror.rs \\\n\thl.rs \\\n\tutil.rs \\\n\tmem.rs \\\n\tarray.rs\n\nOPENCL_ROOT = $(shell pwd)\n\n.PHONY: all\nall: lib\n\n\n.PHONY: debug\ndebug: lib demo\n\tgdb --cd=./ target/demo\n\n\n.PHONY: lib\nlib: target_dir $(TARGET_DIR)libopencl.rlib\n\n$(TARGET_DIR)libopencl.rlib: src/*\n\trustc $(RUSTC_OPTS) src/lib.rs\n\n\n.PHONY: target_dir\ntarget_dir: $(TARGET_DIR)\n\n$(TARGET_DIR):\n\tmkdir -p $(TARGET_DIR)\n\n\n.PHONY: demo\ndemo: target_dir $(TARGET_DIR)demo\n\n$(TARGET_DIR)demo: $(TARGET_DIR)libopencl.rlib test/demo.rs\n\tenv OPENCL_ROOT=$(OPENCL_ROOT) rustc $(RUSTC_OPTS) test/demo.rs\n\n\n.PHONY: check\ncheck: lib\n\trustc $(RUSTC_OPTS) --test test/test.rs\n\t$(TARGET_DIR)test\n\n\n.PHONY: clean\nclean:\n\trm -rf $(TARGET_DIR)\n\n.PHONY: docs\ndocs:\n\trustdoc src/lib.rs\n"
  },
  {
    "path": "examples/demo/demo.ocl",
    "content": "__kernel void vector_add(__global const long *A, __global const long *B, __global long *C) {\n\tint i = get_global_id(0);\n\tC[i] = A[i] + B[i];\n}\n"
  },
  {
    "path": "examples/demo/main.rs",
    "content": "extern crate opencl;\n\nuse opencl::mem::CLBuffer;\nuse std::fmt;\n\nfn main()\n{\n    let ker = include_str!(\"demo.ocl\");\n    println!(\"ker {}\", ker);\n\n    let vec_a = vec![0isize, 1, 2, -3, 4, 5, 6, 7];\n    let vec_b = vec![-7isize, -6, 5, -4, 0, -1, 2, 3];\n\n    let (device, ctx, queue) = opencl::util::create_compute_context().unwrap();\n\n    println!(\"{}\", device.name());\n\n    let a: CLBuffer<isize> = ctx.create_buffer(vec_a.len(), opencl::cl::CL_MEM_READ_ONLY);\n    let b: CLBuffer<isize> = ctx.create_buffer(vec_a.len(), opencl::cl::CL_MEM_READ_ONLY);\n    let c: CLBuffer<isize> = ctx.create_buffer(vec_a.len(), opencl::cl::CL_MEM_WRITE_ONLY);\n\n    queue.write(&a, &&vec_a[..], ());\n    queue.write(&b, &&vec_b[..], ());\n\n    let program = ctx.create_program_from_source(ker);\n    program.build(&device).ok().expect(\"Couldn't build program.\");\n\n\n    let kernel = program.create_kernel(\"vector_add\");\n\n    kernel.set_arg(0, &a);\n    kernel.set_arg(1, &b);\n    kernel.set_arg(2, &c);\n\n    let event = queue.enqueue_async_kernel(&kernel, vec_a.len(), None, ());\n\n    let vec_c: Vec<isize> = queue.get(&c, &event);\n\n    println!(\"  {}\", string_from_slice(&vec_a[..]));\n    println!(\"+ {}\", string_from_slice(&vec_b[..]));\n    println!(\"= {}\", string_from_slice(&vec_c[..]));\n}\n\nfn string_from_slice<T: fmt::Display>(slice: &[T]) -> String {\n    let mut st = String::from(\"[\");\n    let mut first = true;\n\n    for i in slice.iter() {\n        if !first {\n            st.push_str(\", \");\n        }\n        else {\n            first = false;\n        }\n        st.push_str(&*i.to_string())\n    }\n\n    st.push_str(\"]\");\n    return st\n}\n"
  },
  {
    "path": "examples/platform/main.rs",
    "content": "extern crate opencl;\n\nuse opencl::hl;\n\nfn main() {\n    for platform in hl::get_platforms().iter() {\n        println!(\"Platform: {}\", platform.name());\n        println!(\"Platform Version: {}\", platform.version());\n        println!(\"Vendor:   {}\", platform.vendor());\n        println!(\"Profile:  {}\", platform.profile());\n        println!(\"Available extensions: {}\", platform.extensions());\n        println!(\"Available devices:\");\n        for device in platform.get_devices().iter() {\n            println!(\"   Name: {}\", device.name());\n            println!(\"   Type: {}\", device.device_type());\n            println!(\"   Profile: {}\", device.profile());\n            println!(\"   Compute Units: {}\", device.compute_units());\n        }\n    }\n}\n"
  },
  {
    "path": "src/OpenCL/error.rs",
    "content": "//! Error handling utilities.\n\nuse CL::*;\nuse std::fmt::{Show, Formatter, Result};\n\nimpl Show for CLStatus {\n    fn fmt(&self, f: &mut Formatter) -> Result {\n        write!(f.buf, \"{:?}\", *self)\n    }\n}\n\nmacro_rules! convert(\n    ($e: expr, $x: ident) => (if $e == $x as cl_int {\n        Some($x)\n    } else { None });\n\n    ($e: expr, $x: ident, $($xs: ident),+) => (if $e == $x as cl_int {\n        Some($x)\n    } else { convert!($e, $($xs),+) })\n)\n\npub fn try_convert(status: cl_int) -> Option<CLStatus> {\n    convert!(status,\n             CL_SUCCESS,\n             CL_DEVICE_NOT_FOUND,\n             CL_DEVICE_NOT_AVAILABLE,\n             CL_COMPILER_NOT_AVAILABLE,\n             CL_MEM_OBJECT_ALLOCATION_FAILURE,\n             CL_OUT_OF_RESOURCES,\n             CL_OUT_OF_HOST_MEMORY,\n             CL_PROFILING_INFO_NOT_AVAILABLE,\n             CL_MEM_COPY_OVERLAP,\n             CL_IMAGE_FORMAT_MISMATCH,\n             CL_IMAGE_FORMAT_NOT_SUPPORTED,\n             CL_BUILD_PROGRAM_FAILURE,\n             CL_MAP_FAILURE,\n             CL_MISALIGNED_SUB_BUFFER_OFFSET,\n             CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST,\n             CL_INVALID_VALUE,\n             CL_INVALID_DEVICE_TYPE,\n             CL_INVALID_PLATFORM,\n             CL_INVALID_DEVICE,\n             CL_INVALID_CONTEXT,\n             CL_INVALID_QUEUE_PROPERTIES,\n             CL_INVALID_COMMAND_QUEUE,\n             CL_INVALID_HOST_PTR,\n             CL_INVALID_MEM_OBJECT,\n             CL_INVALID_IMAGE_FORMAT_DESCRIPTOR,\n             CL_INVALID_IMAGE_SIZE,\n             CL_INVALID_SAMPLER,\n             CL_INVALID_BINARY,\n             CL_INVALID_BUILD_OPTIONS,\n             CL_INVALID_PROGRAM,\n             CL_INVALID_PROGRAM_EXECUTABLE,\n             CL_INVALID_KERNEL_NAME,\n             CL_INVALID_KERNEL_DEFINITION,\n             CL_INVALID_KERNEL,\n             CL_INVALID_ARG_INDEX,\n             CL_INVALID_ARG_VALUE,\n             CL_INVALID_ARG_SIZE,\n             CL_INVALID_KERNEL_ARGS,\n             CL_INVALID_WORK_DIMENSION,\n             CL_INVALID_WORK_GROUP_SIZE,\n             CL_INVALID_WORK_ITEM_SIZE,\n             CL_INVALID_GLOBAL_OFFSET,\n             CL_INVALID_EVENT_WAIT_LIST,\n             CL_INVALID_EVENT,\n             CL_INVALID_OPERATION,\n             CL_INVALID_GL_OBJECT,\n             CL_INVALID_BUFFER_SIZE,\n             CL_INVALID_MIP_LEVEL,\n             CL_INVALID_GLOBAL_WORK_SIZE,\n             CL_INVALID_PROPERTY)\n}\n\npub fn convert(status: cl_int) -> CLStatus {\n    match try_convert(status) {\n        Some(s) => s,\n        None => fail!(format!(\"Unknown OpenCL Status Code: {:?}\", status))\n    }\n}\n\nfn error_str(status: cl_int) -> ~str {\n    match try_convert(status) {\n        Some(s) => s.to_str(),\n        None => format!(\"Unknown Error: {:?}\", status)\n    }\n}\n\npub fn check(status: cl_int, message: &str) {\n    if status != CL_SUCCESS as cl_int {\n        fail!(format!(\"{:?} ({:?})\", message, error_str(status)))\n    }\n}\n"
  },
  {
    "path": "src/array.rs",
    "content": "//! Two- and three-dimensional array support.\n\nuse cl::*;\nuse cl::ll::*;\nuse mem::*;\nuse std::marker::PhantomData;\nuse std::mem;\nuse std::vec::Vec;\nuse libc::{size_t, c_void};\n\nuse hl::KernelArg;\n\npub struct Array3D<T> {\n    width: usize,\n    height: usize,\n    depth: usize,\n    dat: Vec<T>\n}\n\npub struct Array3DCL<T> {\n    width: usize,\n    height: usize,\n    depth: usize,\n    buf: cl_mem,\n    phantom: PhantomData<T>,\n}\n\nimpl<T: Clone> Array3D<T> {\n    pub fn new<F>(width: usize, height: usize, depth: usize,\n                  val: F)\n               -> Array3D<T>\n        where F: Fn(usize, usize, usize) -> T\n    {\n        let mut dat: Vec<T> = Vec::new();\n        for x in 0 .. width {\n            for y in 0 .. height {\n                for z in 0 .. depth {\n                    dat.push(val(x, y, z));\n                }\n            }\n        }\n\n        Array3D {\n            width: width,\n            height: height,\n            depth: depth,\n            dat: dat\n        }\n    }\n\n    pub fn set(&mut self, x: usize, y: usize, z: usize, val: T)\n    {\n        self.dat[self.width*self.height*z + self.width*y + x] = val;\n    }\n\n    pub fn get(&self, x: usize, y: usize, z: usize) -> T\n    {\n        (&self.dat[..])[self.width*self.height*z + self.width*y + x].clone()\n    }\n}\n\nimpl<T> Drop for Array3DCL<T> {\n    fn drop(&mut self) {\n        unsafe {\n            clReleaseMemObject(self.buf);\n        }\n    }\n}\n\nimpl<'r, T> Put<Array3D<T>, Array3DCL<T>> for &'r Array3D<T>\n{\n    fn put<F>(&self, f: F)\n           -> Array3DCL<T>\n        where F: FnOnce(*const c_void, size_t) -> cl_mem\n    {\n        let p = self.dat.as_ptr();\n        let len = self.dat.len();\n        let out = f(p as *const c_void, (len * mem::size_of::<T>()) as size_t);\n\n        Array3DCL{\n            width: self.width,\n            height: self.height,\n            depth: self.depth,\n            buf: out,\n            phantom: PhantomData,\n        }\n    }\n}\n\n\nimpl<T> Get<Array3DCL<T>, Array3D<T>> for Array3D<T>\n{\n    fn get<F>(arr: &Array3DCL<T>, f: F)\n           -> Array3D<T>\n        where F: FnOnce(size_t, *mut c_void, size_t)\n    {\n        let mut v: Vec<T> = Vec::with_capacity(arr.len());\n        unsafe {\n            v.set_len(arr.len());\n        }\n\n        let p = v.as_mut_ptr();\n        let len = v.len();\n        f(0, p as *mut c_void, (len * mem::size_of::<T>()) as size_t);\n\n        Array3D {\n            width: arr.width,\n            height: arr.height,\n            depth: arr.depth,\n            dat: v,\n        }\n    }\n}\n\nimpl<T> Write for Array3D<T> {\n    fn write<F>(&self, f: F)\n        where F: FnOnce(size_t, *const c_void, size_t)\n    {\n        let p = self.dat.as_ptr();\n        let len = self.dat.len();\n        f(0, p as *const c_void, (len * mem::size_of::<T>()) as size_t)\n    }\n}\n\nimpl<T> Read for Array3D<T> {\n    fn read<F>(&mut self, f: F)\n        where F: FnOnce(size_t, *mut c_void, size_t)\n    {\n        let p = self.dat.as_ptr();\n        let len = self.dat.len();\n        f(0, p as *mut c_void, (len * mem::size_of::<T>()) as size_t)\n    }\n}\n\nimpl<T> Buffer<T> for Array3DCL<T> {\n    unsafe fn id_ptr(&self) -> *const cl_mem {\n        &self.buf as *const cl_mem\n    }\n\n    fn len(&self) -> usize {\n        self.width * self.height * self.depth\n    }\n}\n\nimpl<T> KernelArg for Array3DCL<T> {\n    fn get_value(&self) -> (size_t, *const c_void)\n    {\n        (mem::size_of::<cl_mem>() as size_t,\n         unsafe { self.id_ptr() } as *const c_void)\n    }\n}\n\npub struct Array2D<T> {\n    width: usize,\n    height: usize,\n    dat: Vec<T>,\n}\n\npub struct Array2DCL<T> {\n    width: usize,\n    height: usize,\n    buf: cl_mem,\n    phantom: PhantomData<T>,\n}\n\nimpl<T: Clone> Array2D<T> {\n    pub fn new<F>(width: usize, height: usize, val: F) -> Array2D<T>\n        where F: Fn(usize, usize) -> T\n    {\n        let mut dat: Vec<T> = Vec::new();\n        for x in 0 .. width {\n            for y in 0 .. height {\n                dat.push(val(x, y));\n            }\n        }\n        Array2D {\n            width: width,\n            height: height,\n            dat: dat,\n        }\n    }\n\n    pub fn set(&mut self, x: usize, y: usize, val: T) {\n        self.dat[self.width*y + x] = val;\n    }\n\n    pub fn get(&self, x: usize, y: usize) -> T {\n        (&self.dat[..])[self.width*y + x].clone()\n    }\n}\n\nimpl<T> Drop for Array2DCL<T> {\n    fn drop(&mut self) {\n        unsafe {\n            clReleaseMemObject(self.buf);\n        }\n    }\n}\n\nimpl<'r, T> Put<Array2D<T>, Array2DCL<T>> for &'r Array2D<T>\n{\n    fn put<F>(&self, f: F) -> Array2DCL<T>\n        where F: FnOnce(*const c_void, size_t) -> cl_mem\n    {\n        let p = self.dat.as_ptr();\n        let len = self.dat.len();\n        let out = f(p as *const c_void, (len * mem::size_of::<T>()) as size_t);\n\n        Array2DCL{\n            width: self.width,\n            height: self.height,\n            buf: out,\n            phantom: PhantomData,\n        }\n    }\n}\n\n\nimpl<T> Get<Array2DCL<T>, Array2D<T>> for Array2D<T>\n{\n    fn get<F>(arr: &Array2DCL<T>, f: F)\n           -> Array2D<T>\n        where F: FnOnce(size_t, *mut c_void, size_t)\n    {\n        let mut v: Vec<T> = Vec::with_capacity(arr.len());\n        unsafe {\n            v.set_len(arr.len())\n        }\n\n        let p = v.as_mut_ptr();\n        let len = v.len();\n        f(0, p as *mut c_void, (len * mem::size_of::<T>()) as size_t);\n\n        Array2D {\n            width: arr.width,\n            height: arr.height,\n            dat: v\n        }\n    }\n}\n\nimpl<T> Write for Array2D<T> {\n    fn write<F>(&self, f: F)\n        where F: FnOnce(size_t, *const c_void, size_t)\n    {\n        let p = self.dat.as_ptr();\n        let len = self.dat.len();\n        f(0, p as *const c_void, (len * mem::size_of::<T>()) as size_t)\n    }\n}\n\nimpl<T> Read for Array2D<T> {\n    fn read<F>(&mut self, f: F)\n        where F: FnOnce(size_t, *mut c_void, size_t)\n    {\n        let p = self.dat.as_ptr();\n        let len = self.dat.len();\n        f(0, p as *mut c_void, (len * mem::size_of::<T>()) as size_t)\n    }\n}\n\nimpl<T> Buffer<T> for Array2DCL<T> {\n    unsafe fn id_ptr(&self) -> *const cl_mem {\n        &self.buf as *const cl_mem\n    }\n\n    fn len(&self) -> usize {\n        self.width * self.height\n    }\n}\n\nimpl<T> KernelArg for Array2DCL<T> {\n    fn get_value(&self) -> (size_t, *const c_void)\n    {\n        (mem::size_of::<cl_mem>() as size_t,\n         unsafe { self.id_ptr() } as *const c_void)\n    }\n}\n"
  },
  {
    "path": "src/cl.rs",
    "content": "#![allow(non_camel_case_types, dead_code)]\n\nextern crate std;\n\nuse libc;\nuse std::fmt;\n\n/* Opaque types */\npub type cl_platform_id     = *mut libc::c_void;\npub type cl_device_id       = *mut libc::c_void;\npub type cl_context         = *mut libc::c_void;\npub type cl_command_queue   = *mut libc::c_void;\npub type cl_mem             = *mut libc::c_void;\npub type cl_program         = *mut libc::c_void;\npub type cl_kernel          = *mut libc::c_void;\npub type cl_event           = *mut libc::c_void;\npub type cl_sampler         = *mut libc::c_void;\n\n/* Scalar types */\npub type cl_char    = i8;\npub type cl_uchar   = u8;\npub type cl_short   = i16;\npub type cl_ushort  = u16;\npub type cl_int     = i32;\npub type cl_uint    = u32;\npub type cl_long    = i64;\npub type cl_ulong   = u64;\n\npub type cl_half    = u16;\npub type cl_float   = f32;\npub type cl_double  = f64;\n\npub type cl_bool                        = cl_uint;\npub type cl_bitfield                    = cl_ulong;\npub type cl_device_type                 = cl_bitfield;\npub type cl_platform_info               = cl_uint;\npub type cl_device_info                 = cl_uint;\npub type cl_device_fp_config            = cl_bitfield;\npub type cl_device_mem_cache_type       = cl_uint;\npub type cl_device_local_mem_type       = cl_uint;\npub type cl_device_exec_capabilities    = cl_bitfield;\npub type cl_command_queue_properties    = cl_bitfield;\n\npub type cl_context_properties          = libc::intptr_t;\npub type cl_context_info                = cl_uint;\npub type cl_command_queue_info          = cl_uint;\npub type cl_channel_order               = cl_uint;\npub type cl_channel_type                = cl_uint;\npub type cl_mem_flags                   = cl_bitfield;\npub type cl_mem_object_type             = cl_uint;\npub type cl_mem_info                    = cl_uint;\npub type cl_image_info                  = cl_uint;\npub type cl_buffer_create_type          = cl_uint;\npub type cl_addressing_mode             = cl_uint;\npub type cl_filter_mode                 = cl_uint;\npub type cl_sampler_info                = cl_uint;\npub type cl_map_flags                   = cl_bitfield;\npub type cl_program_info                = cl_uint;\npub type cl_program_build_info          = cl_uint;\npub type cl_build_status                = cl_int;\npub type cl_kernel_info                 = cl_uint;\npub type cl_kernel_work_group_info      = cl_uint;\npub type cl_event_info                  = cl_uint;\npub type cl_command_type                = cl_uint;\npub type cl_profiling_info              = cl_uint;\n\npub struct cl_image_format {\n    image_channel_order:        cl_channel_order,\n    image_channel_data_type:    cl_channel_type\n}\n\npub struct cl_buffer_region {\n    origin:     libc::size_t,\n    size:       libc::size_t\n}\n\n\n/// OpenCL error codes.\n#[derive(PartialEq, Debug)]\n#[repr()]\npub enum CLStatus {\n    CL_SUCCESS = 0,\n    CL_DEVICE_NOT_FOUND = -1,\n    CL_DEVICE_NOT_AVAILABLE = -2,\n    CL_COMPILER_NOT_AVAILABLE = -3,\n    CL_MEM_OBJECT_ALLOCATION_FAILURE = -4,\n    CL_OUT_OF_RESOURCES = -5,\n    CL_OUT_OF_HOST_MEMORY = -6,\n    CL_PROFILING_INFO_NOT_AVAILABLE = -7,\n    CL_MEM_COPY_OVERLAP = -8,\n    CL_IMAGE_FORMAT_MISMATCH = -9,\n    CL_IMAGE_FORMAT_NOT_SUPPORTED = -10,\n    CL_BUILD_PROGRAM_FAILURE = -11,\n    CL_MAP_FAILURE = -12,\n    CL_MISALIGNED_SUB_BUFFER_OFFSET = -13,\n    CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST = -14,\n    CL_INVALID_VALUE = -30,\n    CL_INVALID_DEVICE_TYPE = -31,\n    CL_INVALID_PLATFORM = -32,\n    CL_INVALID_DEVICE = -33,\n    CL_INVALID_CONTEXT = -34,\n    CL_INVALID_QUEUE_PROPERTIES = -35,\n    CL_INVALID_COMMAND_QUEUE = -36,\n    CL_INVALID_HOST_PTR = -37,\n    CL_INVALID_MEM_OBJECT = -38,\n    CL_INVALID_IMAGE_FORMAT_DESCRIPTOR = -39,\n    CL_INVALID_IMAGE_SIZE = -40,\n    CL_INVALID_SAMPLER = -41,\n    CL_INVALID_BINARY = -42,\n    CL_INVALID_BUILD_OPTIONS = -43,\n    CL_INVALID_PROGRAM = -44,\n    CL_INVALID_PROGRAM_EXECUTABLE = -45,\n    CL_INVALID_KERNEL_NAME = -46,\n    CL_INVALID_KERNEL_DEFINITION = -47,\n    CL_INVALID_KERNEL = -48,\n    CL_INVALID_ARG_INDEX = -49,\n    CL_INVALID_ARG_VALUE = -50,\n    CL_INVALID_ARG_SIZE = -51,\n    CL_INVALID_KERNEL_ARGS = -52,\n    CL_INVALID_WORK_DIMENSION = -53,\n    CL_INVALID_WORK_GROUP_SIZE = -54,\n    CL_INVALID_WORK_ITEM_SIZE = -55,\n    CL_INVALID_GLOBAL_OFFSET = -56,\n    CL_INVALID_EVENT_WAIT_LIST = -57,\n    CL_INVALID_EVENT = -58,\n    CL_INVALID_OPERATION = -59,\n    CL_INVALID_GL_OBJECT = -60,\n    CL_INVALID_BUFFER_SIZE = -61,\n    CL_INVALID_MIP_LEVEL = -62,\n    CL_INVALID_GLOBAL_WORK_SIZE = -63,\n    CL_INVALID_PROPERTY = -64,\n    CL_PLATFORM_NOT_FOUND_KHR = -1001,\n}\n\nimpl fmt::Display for CLStatus {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        write!(f, \"{:?}\", self)\n    }\n}\n\n/* OpenCL Version */\npub static CL_VERSION_1_0:                               cl_bool = 1;\npub static CL_VERSION_1_1:                               cl_bool = 1;\n\n/* cl_bool */\npub static CL_FALSE:                                     cl_bool = 0;\npub static CL_TRUE:                                      cl_bool = 1;\n\n/* cl_platform_info */\npub static CL_PLATFORM_PROFILE:                          cl_uint = 0x0900;\npub static CL_PLATFORM_VERSION:                          cl_uint = 0x0901;\npub static CL_PLATFORM_NAME:                             cl_uint = 0x0902;\npub static CL_PLATFORM_VENDOR:                           cl_uint = 0x0903;\npub static CL_PLATFORM_EXTENSIONS:                       cl_uint = 0x0904;\n\n/* cl_device_type - bitfield */\npub static CL_DEVICE_TYPE_DEFAULT:                       cl_bitfield = 1 << 0;\npub static CL_DEVICE_TYPE_CPU:                           cl_bitfield = 1 << 1;\npub static CL_DEVICE_TYPE_GPU:                           cl_bitfield = 1 << 2;\npub static CL_DEVICE_TYPE_ACCELERATOR:                   cl_bitfield = 1 << 3;\npub static CL_DEVICE_TYPE_ALL:                           cl_bitfield = 0xFFFFFFFF;\n\n/* cl_device_info */\npub static CL_DEVICE_TYPE:                               cl_uint = 0x1000;\npub static CL_DEVICE_VENDOR_ID:                          cl_uint = 0x1001;\npub static CL_DEVICE_MAX_COMPUTE_UNITS:                  cl_uint = 0x1002;\npub static CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS:           cl_uint = 0x1003;\npub static CL_DEVICE_MAX_WORK_GROUP_SIZE:                cl_uint = 0x1004;\npub static CL_DEVICE_MAX_WORK_ITEM_SIZES:                cl_uint = 0x1005;\npub static CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR:        cl_uint = 0x1006;\npub static CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT:       cl_uint = 0x1007;\npub static CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT:         cl_uint = 0x1008;\npub static CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG:        cl_uint = 0x1009;\npub static CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT:       cl_uint = 0x100A;\npub static CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE:      cl_uint = 0x100B;\npub static CL_DEVICE_MAX_CLOCK_FREQUENCY:                cl_uint = 0x100C;\npub static CL_DEVICE_ADDRESS_BITS:                       cl_uint = 0x100D;\npub static CL_DEVICE_MAX_READ_IMAGE_ARGS:                cl_uint = 0x100E;\npub static CL_DEVICE_MAX_WRITE_IMAGE_ARGS:               cl_uint = 0x100F;\npub static CL_DEVICE_MAX_MEM_ALLOC_SIZE:                 cl_uint = 0x1010;\npub static CL_DEVICE_IMAGE2D_MAX_WIDTH:                  cl_uint = 0x1011;\npub static CL_DEVICE_IMAGE2D_MAX_HEIGHT:                 cl_uint = 0x1012;\npub static CL_DEVICE_IMAGE3D_MAX_WIDTH:                  cl_uint = 0x1013;\npub static CL_DEVICE_IMAGE3D_MAX_HEIGHT:                 cl_uint = 0x1014;\npub static CL_DEVICE_IMAGE3D_MAX_DEPTH:                  cl_uint = 0x1015;\npub static CL_DEVICE_IMAGE_SUPPORT:                      cl_uint = 0x1016;\npub static CL_DEVICE_MAX_PARAMETER_SIZE:                 cl_uint = 0x1017;\npub static CL_DEVICE_MAX_SAMPLERS:                       cl_uint = 0x1018;\npub static CL_DEVICE_MEM_BASE_ADDR_ALIGN:                cl_uint = 0x1019;\npub static CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE:           cl_uint = 0x101A;\npub static CL_DEVICE_SINGLE_FP_CONFIG:                   cl_uint = 0x101B;\npub static CL_DEVICE_GLOBAL_MEM_CACHE_TYPE:              cl_uint = 0x101C;\npub static CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE:          cl_uint = 0x101D;\npub static CL_DEVICE_GLOBAL_MEM_CACHE_SIZE:              cl_uint = 0x101E;\npub static CL_DEVICE_GLOBAL_MEM_SIZE:                    cl_uint = 0x101F;\npub static CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE:           cl_uint = 0x1020;\npub static CL_DEVICE_MAX_CONSTANT_ARGS:                  cl_uint = 0x1021;\npub static CL_DEVICE_LOCAL_MEM_TYPE:                     cl_uint = 0x1022;\npub static CL_DEVICE_LOCAL_MEM_SIZE:                     cl_uint = 0x1023;\npub static CL_DEVICE_ERROR_CORRECTION_SUPPORT:           cl_uint = 0x1024;\npub static CL_DEVICE_PROFILING_TIMER_RESOLUTION:         cl_uint = 0x1025;\npub static CL_DEVICE_ENDIAN_LITTLE:                      cl_uint = 0x1026;\npub static CL_DEVICE_AVAILABLE:                          cl_uint = 0x1027;\npub static CL_DEVICE_COMPILER_AVAILABLE:                 cl_uint = 0x1028;\npub static CL_DEVICE_EXECUTION_CAPABILITIES:             cl_uint = 0x1029;\npub static CL_DEVICE_QUEUE_PROPERTIES:                   cl_uint = 0x102A;\npub static CL_DEVICE_NAME:                               cl_uint = 0x102B;\npub static CL_DEVICE_VENDOR:                             cl_uint = 0x102C;\npub static CL_DRIVER_VERSION:                            cl_uint = 0x102D;\npub static CL_DEVICE_PROFILE:                            cl_uint = 0x102E;\npub static CL_DEVICE_VERSION:                            cl_uint = 0x102F;\npub static CL_DEVICE_EXTENSIONS:                         cl_uint = 0x1030;\npub static CL_DEVICE_PLATFORM:                           cl_uint = 0x1031;\n/* 0x1032 reserved for CL_DEVICE_DOUBLE_FP_CONFIG */\n/* 0x1033 reserved for CL_DEVICE_HALF_FP_CONFIG */\npub static CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF:        cl_uint = 0x1034;\npub static CL_DEVICE_HOST_UNIFIED_MEMORY:                cl_uint = 0x1035;\npub static CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR:           cl_uint = 0x1036;\npub static CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT:          cl_uint = 0x1037;\npub static CL_DEVICE_NATIVE_VECTOR_WIDTH_INT:            cl_uint = 0x1038;\npub static CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG:           cl_uint = 0x1039;\npub static CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT:          cl_uint = 0x103A;\npub static CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE:         cl_uint = 0x103B;\npub static CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF:           cl_uint = 0x103C;\npub static CL_DEVICE_OPENCL_C_VERSION:                   cl_uint = 0x103D;\n\n/* cl_device_fp_config - bitfield */\npub static CL_FP_DENORM:                                 cl_bitfield = 1 << 0;\npub static CL_FP_INF_NAN:                                cl_bitfield = 1 << 1;\npub static CL_FP_ROUND_TO_NEAREST:                       cl_bitfield = 1 << 2;\npub static CL_FP_ROUND_TO_ZERO:                          cl_bitfield = 1 << 3;\npub static CL_FP_ROUND_TO_INF:                           cl_bitfield = 1 << 4;\npub static CL_FP_FMA:                                    cl_bitfield = 1 << 5;\npub static CL_FP_SOFT_FLOAT:                             cl_bitfield = 1 << 6;\n\n/* cl_device_mem_cache_type */\npub static CL_NONE:                                      cl_uint = 0x0;\npub static CL_READ_ONLY_CACHE:                           cl_uint = 0x1;\npub static CL_READ_WRITE_CACHE:                          cl_uint = 0x2;\n\n/* cl_device_local_mem_type */\npub static CL_LOCAL:                                     cl_uint = 0x1;\npub static CL_GLOBAL:                                    cl_uint = 0x2;\n\n/* cl_device_exec_capabilities - bitfield */\npub static CL_EXEC_KERNEL:                               cl_bitfield = 1 << 0;\npub static CL_EXEC_NATIVE_KERNEL:                        cl_bitfield = 1 << 1;\n\n/* cl_command_queue_properties - bitfield */\npub static CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE:       cl_bitfield = 1 << 0;\npub static CL_QUEUE_PROFILING_ENABLE:                    cl_bitfield = 1 << 1;\n\n/* cl_context_info  */\npub static CL_CONTEXT_REFERENCE_COUNT:                   cl_uint = 0x1080;\npub static CL_CONTEXT_DEVICES:                           cl_uint = 0x1081;\npub static CL_CONTEXT_PROPERTIES:                        cl_uint = 0x1082;\npub static CL_CONTEXT_NUM_DEVICES:                       cl_uint = 0x1083;\n\n/* cl_context_info + cl_context_properties */\npub static CL_CONTEXT_PLATFORM:                          libc::intptr_t = 0x1084;\n\n/* cl_command_queue_info */\npub static CL_QUEUE_CONTEXT:                             cl_uint = 0x1090;\npub static CL_QUEUE_DEVICE:                              cl_uint = 0x1091;\npub static CL_QUEUE_REFERENCE_COUNT:                     cl_uint = 0x1092;\npub static CL_QUEUE_PROPERTIES:                          cl_uint = 0x1093;\n\n/* cl_mem_flags - bitfield */\npub static CL_MEM_READ_WRITE:                            cl_bitfield = 1 << 0;\npub static CL_MEM_WRITE_ONLY:                            cl_bitfield = 1 << 1;\npub static CL_MEM_READ_ONLY:                             cl_bitfield = 1 << 2;\npub static CL_MEM_USE_HOST_PTR:                          cl_bitfield = 1 << 3;\npub static CL_MEM_ALLOC_HOST_PTR:                        cl_bitfield = 1 << 4;\npub static CL_MEM_COPY_HOST_PTR:                         cl_bitfield = 1 << 5;\n\n/* cl_channel_order */\npub static CL_R:                                         cl_uint = 0x10B0;\npub static CL_A:                                         cl_uint = 0x10B1;\npub static CL_RG:                                        cl_uint = 0x10B2;\npub static CL_RA:                                        cl_uint = 0x10B3;\npub static CL_RGB:                                       cl_uint = 0x10B4;\npub static CL_RGBA:                                      cl_uint = 0x10B5;\npub static CL_BGRA:                                      cl_uint = 0x10B6;\npub static CL_ARGB:                                      cl_uint = 0x10B7;\npub static CL_INTENSITY:                                 cl_uint = 0x10B8;\npub static CL_LUMINANCE:                                 cl_uint = 0x10B9;\npub static CL_Rx:                                        cl_uint = 0x10BA;\npub static CL_RGx:                                       cl_uint = 0x10BB;\npub static CL_RGBx:                                      cl_uint = 0x10BC;\n\n/* cl_channel_type */\npub static CL_SNORM_INT8:                                cl_uint = 0x10D0;\npub static CL_SNORM_INT16:                               cl_uint = 0x10D1;\npub static CL_UNORM_INT8:                                cl_uint = 0x10D2;\npub static CL_UNORM_INT16:                               cl_uint = 0x10D3;\npub static CL_UNORM_SHORT_565:                           cl_uint = 0x10D4;\npub static CL_UNORM_SHORT_555:                           cl_uint = 0x10D5;\npub static CL_UNORM_INT_101010:                          cl_uint = 0x10D6;\npub static CL_SIGNED_INT8:                               cl_uint = 0x10D7;\npub static CL_SIGNED_INT16:                              cl_uint = 0x10D8;\npub static CL_SIGNED_INT32:                              cl_uint = 0x10D9;\npub static CL_UNSIGNED_INT8:                             cl_uint = 0x10DA;\npub static CL_UNSIGNED_INT16:                            cl_uint = 0x10DB;\npub static CL_UNSIGNED_INT32:                            cl_uint = 0x10DC;\npub static CL_HALF_FLOAT:                                cl_uint = 0x10DD;\npub static CL_FLOAT:                                     cl_uint = 0x10DE;\n\n/* cl_mem_object_type */\npub static CL_MEM_OBJECT_BUFFER:                         cl_uint = 0x10F0;\npub static CL_MEM_OBJECT_IMAGE2D:                        cl_uint = 0x10F1;\npub static CL_MEM_OBJECT_IMAGE3D:                        cl_uint = 0x10F2;\n\n/* cl_mem_info */\npub static CL_MEM_TYPE:                                  cl_uint = 0x1100;\npub static CL_MEM_FLAGS:                                 cl_uint = 0x1101;\npub static CL_MEM_SIZE:                                  cl_uint = 0x1102;\npub static CL_MEM_HOST_PTR:                              cl_uint = 0x1103;\npub static CL_MEM_MAP_COUNT:                             cl_uint = 0x1104;\npub static CL_MEM_REFERENCE_COUNT:                       cl_uint = 0x1105;\npub static CL_MEM_CONTEXT:                               cl_uint = 0x1106;\npub static CL_MEM_ASSOCIATED_MEMOBJECT:                  cl_uint = 0x1107;\npub static CL_MEM_OFFSET:                                cl_uint = 0x1108;\n\n/* cl_image_info */\npub static CL_IMAGE_FORMAT:                              cl_uint = 0x1110;\npub static CL_IMAGE_ELEMENT_SIZE:                        cl_uint = 0x1111;\npub static CL_IMAGE_ROW_PITCH:                           cl_uint = 0x1112;\npub static CL_IMAGE_SLICE_PITCH:                         cl_uint = 0x1113;\npub static CL_IMAGE_WIDTH:                               cl_uint = 0x1114;\npub static CL_IMAGE_HEIGHT:                              cl_uint = 0x1115;\npub static CL_IMAGE_DEPTH:                               cl_uint = 0x1116;\n\n/* cl_addressing_mode */\npub static CL_ADDRESS_NONE:                              cl_uint = 0x1130;\npub static CL_ADDRESS_CLAMP_TO_EDGE:                     cl_uint = 0x1131;\npub static CL_ADDRESS_CLAMP:                             cl_uint = 0x1132;\npub static CL_ADDRESS_REPEAT:                            cl_uint = 0x1133;\npub static CL_ADDRESS_MIRRORED_REPEAT:                   cl_uint = 0x1134;\n\n/* cl_filter_mode */\npub static CL_FILTER_NEAREST:                            cl_uint = 0x1140;\npub static CL_FILTER_LINEAR:                             cl_uint = 0x1141;\n\n/* cl_sampler_info */\npub static CL_SAMPLER_REFERENCE_COUNT:                   cl_uint = 0x1150;\npub static CL_SAMPLER_CONTEXT:                           cl_uint = 0x1151;\npub static CL_SAMPLER_NORMALIZED_COORDS:                 cl_uint = 0x1152;\npub static CL_SAMPLER_ADDRESSING_MODE:                   cl_uint = 0x1153;\npub static CL_SAMPLER_FILTER_MODE:                       cl_uint = 0x1154;\n\n/* cl_map_flags - bitfield */\npub static CL_MAP_READ:                                  cl_bitfield = 1 << 0;\npub static CL_MAP_WRITE:                                 cl_bitfield = 1 << 1;\n\n/* cl_program_info */\npub static CL_PROGRAM_REFERENCE_COUNT:                   cl_uint = 0x1160;\npub static CL_PROGRAM_CONTEXT:                           cl_uint = 0x1161;\npub static CL_PROGRAM_NUM_DEVICES:                       cl_uint = 0x1162;\npub static CL_PROGRAM_DEVICES:                           cl_uint = 0x1163;\npub static CL_PROGRAM_SOURCE:                            cl_uint = 0x1164;\npub static CL_PROGRAM_BINARY_SIZES:                      cl_uint = 0x1165;\npub static CL_PROGRAM_BINARIES:                          cl_uint = 0x1166;\n\n/* cl_program_build_info */\npub static CL_PROGRAM_BUILD_STATUS:                      cl_uint = 0x1181;\npub static CL_PROGRAM_BUILD_OPTIONS:                     cl_uint = 0x1182;\npub static CL_PROGRAM_BUILD_LOG:                         cl_uint = 0x1183;\n\n/* cl_build_status */\npub static CL_BUILD_SUCCESS:                             cl_uint = 0;\npub static CL_BUILD_NONE:                                cl_uint = (-1isize) as cl_uint;\npub static CL_BUILD_ERROR:                               cl_uint = -2isize as cl_uint;\npub static CL_BUILD_IN_PROGRESS:                         cl_uint = -3isize as cl_uint;\n\n/* cl_kernel_info */\npub static CL_KERNEL_FUNCTION_NAME:                      cl_uint = 0x1190;\npub static CL_KERNEL_NUM_ARGS:                           cl_uint = 0x1191;\npub static CL_KERNEL_REFERENCE_COUNT:                    cl_uint = 0x1192;\npub static CL_KERNEL_CONTEXT:                            cl_uint = 0x1193;\npub static CL_KERNEL_PROGRAM:                            cl_uint = 0x1194;\n\n/* cl_kernel_work_group_info */\npub static CL_KERNEL_WORK_GROUP_SIZE:                    cl_uint = 0x11B0;\npub static CL_KERNEL_COMPILE_WORK_GROUP_SIZE:            cl_uint = 0x11B1;\npub static CL_KERNEL_LOCAL_MEM_SIZE:                     cl_uint = 0x11B2;\npub static CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE: cl_uint = 0x11B3;\npub static CL_KERNEL_PRIVATE_MEM_SIZE:                   cl_uint = 0x11B4;\n\n/* cl_event_info  */\npub static CL_EVENT_COMMAND_QUEUE:                       cl_uint = 0x11D0;\npub static CL_EVENT_COMMAND_TYPE:                        cl_uint = 0x11D1;\npub static CL_EVENT_REFERENCE_COUNT:                     cl_uint = 0x11D2;\npub static CL_EVENT_COMMAND_EXECUTION_STATUS:            cl_uint = 0x11D3;\npub static CL_EVENT_CONTEXT:                             cl_uint = 0x11D4;\n\n/* cl_command_type */\npub static CL_COMMAND_NDRANGE_KERNEL:                    cl_uint = 0x11F0;\npub static CL_COMMAND_TASK:                              cl_uint = 0x11F1;\npub static CL_COMMAND_NATIVE_KERNEL:                     cl_uint = 0x11F2;\npub static CL_COMMAND_READ_BUFFER:                       cl_uint = 0x11F3;\npub static CL_COMMAND_WRITE_BUFFER:                      cl_uint = 0x11F4;\npub static CL_COMMAND_COPY_BUFFER:                       cl_uint = 0x11F5;\npub static CL_COMMAND_READ_IMAGE:                        cl_uint = 0x11F6;\npub static CL_COMMAND_WRITE_IMAGE:                       cl_uint = 0x11F7;\npub static CL_COMMAND_COPY_IMAGE:                        cl_uint = 0x11F8;\npub static CL_COMMAND_COPY_IMAGE_TO_BUFFER:              cl_uint = 0x11F9;\npub static CL_COMMAND_COPY_BUFFER_TO_IMAGE:              cl_uint = 0x11FA;\npub static CL_COMMAND_MAP_BUFFER:                        cl_uint = 0x11FB;\npub static CL_COMMAND_MAP_IMAGE:                         cl_uint = 0x11FC;\npub static CL_COMMAND_UNMAP_MEM_OBJECT:                  cl_uint = 0x11FD;\npub static CL_COMMAND_MARKER:                            cl_uint = 0x11FE;\npub static CL_COMMAND_ACQUIRE_GL_OBJECTS:                cl_uint = 0x11FF;\npub static CL_COMMAND_RELEASE_GL_OBJECTS:                cl_uint = 0x1200;\npub static CL_COMMAND_READ_BUFFER_RECT:                  cl_uint = 0x1201;\npub static CL_COMMAND_WRITE_BUFFER_RECT:                 cl_uint = 0x1202;\npub static CL_COMMAND_COPY_BUFFER_RECT:                  cl_uint = 0x1203;\npub static CL_COMMAND_USER:                              cl_uint = 0x1204;\n\n/* command execution status */\npub static CL_COMPLETE:                                  cl_uint = 0x0;\npub static CL_RUNNING:                                   cl_uint = 0x1;\npub static CL_SUBMITTED:                                 cl_uint = 0x2;\npub static CL_QUEUED:                                    cl_uint = 0x3;\n\n/* cl_buffer_create_type  */\npub static CL_BUFFER_CREATE_TYPE_REGION:                 cl_uint = 0x1220;\n\n/* cl_profiling_info  */\npub static CL_PROFILING_COMMAND_QUEUED:                  cl_uint = 0x1280;\npub static CL_PROFILING_COMMAND_SUBMIT:                  cl_uint = 0x1281;\npub static CL_PROFILING_COMMAND_START:                   cl_uint = 0x1282;\npub static CL_PROFILING_COMMAND_END:                     cl_uint = 0x1283;\n\n\npub mod ll {\n  use cl::*;\n  use libc;\n\n\n  extern\n  {\n    /* Platform APIs */\n    pub fn clGetPlatformIDs(num_entries:   cl_uint,\n                            platforms:     *mut cl_platform_id,\n                            num_platforms: *mut cl_uint) -> cl_int;\n    pub fn clGetPlatformInfo(platform: cl_platform_id,\n                             param_name: cl_platform_info,\n                             param_value_size: libc::size_t,\n                             param_value: *mut libc::c_void,\n                             param_value_size_ret: *mut libc::size_t) -> cl_int;\n\n    /* Device APIs */\n    pub fn clGetDeviceIDs(platform: cl_platform_id,\n                      device_type: cl_device_type,\n                      num_entries: cl_uint,\n                      devices: *mut cl_device_id,\n                      num_devices: *mut cl_uint) -> cl_int;\n    pub fn clGetDeviceInfo(device: cl_device_id,\n                       param_name: cl_device_info,\n                       param_value_size: libc::size_t,\n                       param_value: *mut libc::c_void,\n                       param_value_size_ret: *mut libc::size_t) -> cl_int;\n\n    /* Context APIs */\n    pub fn clCreateContext(properties: *const cl_context_properties,\n                       num_devices: cl_uint,\n                       devices: *const cl_device_id,\n                       pfn_notify: extern fn (*const libc::c_char, *const libc::c_void, libc::size_t, *mut libc::c_void),\n                       user_data: *mut libc::c_void,\n                       errcode_ret: *mut cl_int) -> cl_context;\n    pub fn clCreateContextFromType(properties: *mut cl_context_properties,\n                               device_type: cl_device_type,\n                               pfn_notify: extern fn (*mut libc::c_char, *mut libc::c_void, libc::size_t, *mut libc::c_void),\n                               user_data: *mut libc::c_void,\n                               errcode_ret: *mut cl_int) -> cl_context;\n    pub fn clRetainContext(context: cl_context) -> cl_int;\n    pub fn clReleaseContext(context: cl_context) -> cl_int;\n    pub fn clGetContextInfo(context: cl_context,\n                        param_name: cl_context_info,\n                        param_value_size: libc::size_t,\n                        param_value: *mut libc::c_void,\n                        param_value_size_ret: *mut libc::size_t) -> cl_int;\n\n    /* Command Queue APIs */\n    pub fn clCreateCommandQueue(context: cl_context,\n                            device: cl_device_id,\n                            properties: cl_command_queue_properties,\n                            errcode_ret: *mut cl_int) -> cl_command_queue;\n    pub fn clRetainCommandQueue(command_queue: cl_command_queue) -> cl_int;\n    pub fn clReleaseCommandQueue(command_queue: cl_command_queue) -> cl_int;\n    pub fn clGetCommandQueueInfo(command_queue: cl_command_queue,\n                             param_name: cl_command_queue_info,\n                             param_value_size: libc::size_t,\n                             param_value: *mut libc::c_void,\n                             param_value_size_ret: *mut libc::size_t) -> cl_int;\n\n    /* Memory Object APIs */\n    pub fn clCreateBuffer(context: cl_context,\n                      flags: cl_mem_flags,\n                      size: libc::size_t,\n                      host_ptr: *mut libc::c_void,\n                      errcode_ret: *mut cl_int) -> cl_mem;\n    pub fn clCreateSubBuffer(buffer: cl_mem,\n                        flags: cl_mem_flags,\n                        buffer_create_type: cl_buffer_create_type,\n                        buffer_create_info: *mut libc::c_void,\n                        errcode_ret: *mut cl_int) -> cl_mem;\n    pub fn clCreateImage2D(context: cl_context,\n                       flags: cl_mem_flags,\n                       image_format: *mut cl_image_format,\n                       image_width: libc::size_t,\n                       image_height: libc::size_t,\n                       image_row_pitch: libc::size_t,\n                       host_ptr: *mut libc::c_void,\n                       errcode_ret: *mut cl_int) -> cl_mem;\n    pub fn clCreateImage3D(context: cl_context,\n                       flags: cl_mem_flags,\n                       image_format: *mut cl_image_format,\n                       image_width: libc::size_t,\n                       image_height: libc::size_t,\n                       image_depth: libc::size_t,\n                       image_row_pitch: libc::size_t,\n                       image_depth: libc::size_t,\n                       image_row_pitch: libc::size_t,\n                       image_slice_pitch: libc::size_t,\n                       host_ptr: *mut libc::c_void,\n                       errcode_ret: *mut cl_int) -> cl_mem;\n    pub fn clRetainMemObject(memobj: cl_mem) -> cl_int;\n    pub fn clReleaseMemObject(memobj: cl_mem) -> cl_int;\n    pub fn clGetSupportedImageFormats(context: cl_context,\n                                  flags: cl_mem_flags,\n                                  image_type: cl_mem_object_type,\n                                  num_entries: cl_uint,\n                                  image_formats: *mut cl_image_format,\n                                  num_image_formats: *mut cl_uint) -> cl_int;\n    pub fn clGetMemObjectInfo(memobj: cl_mem,\n                          param_name: cl_mem_info,\n                          param_value_size: libc::size_t,\n                          param_value: *mut libc::c_void,\n                          param_value_size_ret: *mut libc::size_t) -> cl_int;\n    pub fn clGetImageInfo(image: cl_mem,\n                      param_name: cl_image_info,\n                      param_value_size: libc::size_t,\n                      param_value: *mut libc::c_void,\n                      param_value_size_ret: *mut libc::size_t) -> cl_int;\n    pub fn clSetMemObjectDestructorCallback(memobj: cl_mem,\n                                        pfn_notify: extern fn (cl_mem, *mut libc::c_void),\n                                        user_data: *mut libc::c_void) -> cl_int;\n\n    /*mut * Sampler APIs */\n    pub fn clCreateSampler(context: cl_context,\n                       normalize_coords: cl_bool,\n                       addressing_mode: cl_addressing_mode,\n                       filter_mode: cl_filter_mode,\n                       errcode_ret: *mut cl_int) -> cl_sampler;\n    pub fn clRetainSampler(sampler: cl_sampler) -> cl_int;\n    pub fn clReleaseSampler(sampler: cl_sampler) ->cl_int;\n    pub fn clGetSamplerInfo(sampler: cl_sampler,\n                        param_name: cl_sampler_info,\n                        param_value_size: libc::size_t,\n                        param_value: *mut libc::c_void,\n                        param_value_size_ret: *mut libc::size_t) -> cl_int;\n\n    /* Program Object APIs */\n    pub fn clCreateProgramWithSource(context: cl_context,\n                                 count: cl_uint,\n                                 strings: *const *const libc::c_char,\n                                 lengths: *const libc::size_t,\n                                 errcode_ret: *mut cl_int) -> cl_program;\n    pub fn clCreateProgramWithBinary(context: cl_context,\n                                 num_devices: cl_uint,\n                                 device_list: *const cl_device_id,\n                                 lengths: *const libc::size_t,\n                                 binaries: *const *const libc::c_uchar,\n                                 binary_status: *mut cl_int,\n                                 errcode_ret: *mut cl_int) -> cl_program;\n    pub fn clRetainProgram(program: cl_program) -> cl_int;\n    pub fn clReleaseProgram(program: cl_program) -> cl_int;\n    pub fn clBuildProgram(program: cl_program,\n                      num_devices: cl_uint,\n                      device_list: *const cl_device_id,\n                      options: *const libc::c_char,\n                      pfn_notify: extern fn (cl_program, *mut libc::c_void),\n                      user_data: *mut libc::c_void) -> cl_int;\n    pub fn clUnloadCompiler() -> cl_int;\n    pub fn clGetProgramInfo(program: cl_program,\n                        param_name: cl_program_info,\n                        param_value_size: libc::size_t,\n                        param_value: *mut libc::c_void,\n                        param_value_size_ret: *mut libc::size_t) -> cl_int;\n    pub fn clGetProgramBuildInfo(program: cl_program,\n                             device: cl_device_id,\n                             param_name: cl_program_info,\n                             param_value_size: libc::size_t,\n                             param_value: *mut libc::c_void,\n                             param_value_size_ret: *mut libc::size_t) -> cl_int;\n\n    /* Kernel Object APIs */\n    pub fn clCreateKernel(program: cl_program,\n                      kernel_name: *const libc::c_char,\n                      errcode_ret: *mut cl_int) -> cl_kernel;\n    pub fn clCreateKernelsInProgram(program: cl_program,\n                                num_kernels: cl_uint,\n                                kernels: *mut cl_kernel,\n                                num_kernels_ret: *mut cl_uint) -> cl_int;\n    pub fn clRetainKernel(kernel: cl_kernel) -> cl_int;\n    pub fn clReleaseKernel(kernel: cl_kernel) -> cl_int;\n    pub fn clSetKernelArg(kernel: cl_kernel,\n                      arg_index: cl_uint,\n                      arg_size: libc::size_t,\n                      arg_value: *const libc::c_void) -> cl_int;\n    pub fn clGetKernelInfo(kernel: cl_kernel,\n                       param_name: cl_kernel_info,\n                       param_value_size: libc::size_t,\n                       param_value: *mut libc::c_void,\n                       param_value_size_ret: *mut libc::size_t) -> cl_int;\n    pub fn clGetKernelWorkGroupInfo(kernel: cl_kernel,\n                                device: cl_device_id,\n                                param_name: cl_kernel_work_group_info,\n                                param_value_size: libc::size_t,\n                                param_value: *mut libc::c_void,\n                                param_value_size_ret: *mut libc::size_t) -> cl_int;\n\n    /* Event Object APIs */\n    pub fn clWaitForEvents(num_events: cl_uint,\n                       event_list: *const cl_event) -> cl_int;\n    pub fn clGetEventInfo(event: cl_event,\n                      param_name: cl_event_info,\n                      param_value_size: libc::size_t,\n                      param_value: *mut libc::c_void,\n                      param_value_size_ret: *mut libc::size_t) -> cl_int;\n    pub fn clCreateUserEvent(context: cl_context,\n                         errcode_ret: *mut cl_int) -> cl_event;\n    pub fn clRetainEvent(event: cl_event) -> cl_int;\n    pub fn clReleaseEvent(event: cl_event) -> cl_int;\n    pub fn clSetUserEventStatus(event: cl_event,\n                            execution_status: cl_int) -> cl_int;\n    pub fn clSetEventCallback(event: cl_event,\n                          command_exec_callback_type: cl_int,\n                          pfn_notify: extern fn (cl_event, cl_int, *mut libc::c_void),\n                          user_data: *mut libc::c_void) -> cl_int;\n\n    /* Profiling APIs */\n    pub fn clGetEventProfilingInfo(event: cl_event,\n                               param_name: cl_profiling_info,\n                               param_value_size: libc::size_t,\n                               param_value: *mut libc::c_void,\n                               param_value_size_ret: *mut libc::size_t) -> cl_int;\n\n    /* Flush and Finish APIs */\n    pub fn clFlush(command_queue: cl_command_queue) -> cl_int;\n    pub fn clFinish(command_queue: cl_command_queue) -> cl_int;\n\n    /* Enqueued Commands APIs */\n    pub fn clEnqueueReadBuffer(command_queue: cl_command_queue,\n                           buffer: cl_mem,\n                           blocking_read: cl_bool,\n                           offset: libc::size_t,\n                           cb: libc::size_t,\n                           ptr: *mut libc::c_void,\n                           num_events_in_wait_list: cl_uint,\n                           event_wait_list: *const cl_event,\n                           event: *mut cl_event) -> cl_int;\n    pub fn clEnqueueReadBufferRect(command_queue: cl_command_queue,\n                               buffer: cl_mem,\n                               blocking_read: cl_bool,\n                               buffer_origin: *mut libc::size_t,\n                               host_origin: *mut libc::size_t,\n                               region: *mut libc::size_t,\n                               buffer_row_pitch: libc::size_t,\n                               buffer_slice_pitch: libc::size_t,\n                               host_row_pitch: libc::size_t,\n                               host_slice_pitch: libc::size_t,\n                               ptr: *mut libc::c_void,\n                               num_events_in_wait_list: cl_uint,\n                               event_wait_list: *const cl_event,\n                               event: *mut cl_event) -> cl_int;\n    pub fn clEnqueueWriteBuffer(command_queue: cl_command_queue,\n                            buffer: cl_mem,\n                            blocking_write: cl_bool,\n                            offset: libc::size_t,\n                            cb: libc::size_t,\n                            ptr: *const libc::c_void,\n                            num_events_in_wait_list: cl_uint,\n                            event_wait_list: *const cl_event,\n                            event: *mut cl_event) -> cl_int;\n    pub fn clEnqueueWriteBufferRect(command_queue: cl_command_queue,\n                                blocking_write: cl_bool,\n                                buffer_origin: *mut libc::size_t,\n                                host_origin: *mut libc::size_t,\n                                region: *mut libc::size_t,\n                                buffer_row_pitch: libc::size_t,\n                                buffer_slice_pitch: libc::size_t,\n                                host_row_pitch: libc::size_t,\n                                host_slice_pitch: libc::size_t,\n                                ptr: *mut libc::c_void,\n                                num_events_in_wait_list: cl_uint,\n                                event_wait_list: *const cl_event,\n                                event: *mut cl_event) -> cl_int;\n    pub fn clEnqueueCopyBuffer(command_queue: cl_command_queue,\n                           src_buffer: cl_mem,\n                           dst_buffer: cl_mem,\n                           src_offset: libc::size_t,\n                           dst_offset: libc::size_t,\n                           cb: libc::size_t,\n                           num_events_in_wait_list: cl_uint,\n                           event_wait_list: *const cl_event,\n                           event: *mut cl_event) -> cl_int;\n    pub fn clEnqueueCopyBufferRect(command_queue: cl_command_queue,\n                               src_buffer: cl_mem,\n                               dst_buffer: cl_mem,\n                               src_origin: *mut libc::size_t,\n                               dst_origin: *mut libc::size_t,\n                               region: *mut libc::size_t,\n                               src_row_pitch: libc::size_t,\n                               src_slice_pitch: libc::size_t,\n                               dst_row_pitch: libc::size_t,\n                               dst_slice_pitch: libc::size_t,\n                               num_events_in_wait_list: cl_uint,\n                               event_wait_list: *const cl_event,\n                               event: *mut cl_event) -> cl_int;\n    pub fn clEnqueueReadImage(command_queue: cl_command_queue,\n                          image: cl_mem,\n                          blocking_read: cl_bool,\n                          origin: *mut libc::size_t,\n                          region: *mut libc::size_t,\n                          row_pitch: libc::size_t,\n                          slice_pitch: libc::size_t,\n                          ptr: *mut libc::c_void,\n                          num_events_in_wait_list: cl_uint,\n                          event_wait_list: *const cl_event,\n                          event: *mut cl_event) -> cl_int;\n    pub fn clEnqueueWriteImage(command_queue: cl_command_queue,\n                           image: cl_mem,\n                           blocking_write: cl_bool,\n                           origin: *mut libc::size_t,\n                           region: *mut libc::size_t,\n                           input_row_pitch: libc::size_t,\n                           input_slice_pitch: libc::size_t,\n                           ptr: *mut libc::c_void,\n                           num_events_in_wait_list: cl_uint,\n                           event_wait_list: *const cl_event,\n                           event: *mut cl_event) -> cl_int;\n    pub fn clEnqueueCopyImage(command_queue: cl_command_queue,\n                          src_image: cl_mem,\n                          dst_image: cl_mem,\n                          src_origin: *mut libc::size_t,\n                          dst_origin: *mut libc::size_t,\n                          region: *mut libc::size_t,\n                          num_events_in_wait_list: cl_uint,\n                          event_wait_list: *const cl_event,\n                          event: *mut cl_event) -> cl_int;\n    pub fn clEnqueueCopyImageToBuffer(command_queue: cl_command_queue,\n                                  src_image: cl_mem,\n                                  dst_buffer: cl_mem,\n                                  src_origin: *mut libc::size_t,\n                                  region: *mut libc::size_t,\n                                  dst_offset: libc::size_t,\n                                  num_events_in_wait_list: cl_uint,\n                                  event_wait_list: *const cl_event,\n                                  event: *mut cl_event) -> cl_int;\n    pub fn clEnqueueCopyBufferToImage(command_queue: cl_command_queue,\n                                  src_buffer: cl_mem,\n                                  dst_image: cl_mem,\n                                  src_offset: libc::size_t,\n                                  dst_origin: *mut libc::size_t,\n                                  region: *mut libc::size_t,\n                                  num_events_in_wait_list: cl_uint,\n                                  event_wait_list: *const cl_event,\n                                  event: *mut cl_event) -> cl_int;\n    pub fn clEnqueueMapBuffer(command_queue: cl_command_queue,\n                          buffer: cl_mem,\n                          blocking_map: cl_bool,\n                          map_flags: cl_map_flags,\n                          offset: libc::size_t,\n                          cb: libc::size_t,\n                          num_events_in_wait_list: cl_uint,\n                          event_wait_list: *const cl_event,\n                          event: *mut cl_event,\n                          errorcode_ret: *mut cl_int);\n    pub fn clEnqueueMapImage(command_queue: cl_command_queue,\n                         image: cl_mem,\n                         blocking_map: cl_bool,\n                         map_flags: cl_map_flags,\n                         origin: *mut libc::size_t,\n                         region: *mut libc::size_t,\n                         image_row_pitch: libc::size_t,\n                         image_slice_pitch: libc::size_t,\n                         num_events_in_wait_list: cl_uint,\n                         event_wait_list: *const cl_event,\n                         event: *mut cl_event,\n                         errorcode_ret: *mut cl_int);\n    pub fn clEnqueueUnmapMemObject(command_queue: cl_command_queue,\n                               memobj: cl_mem,\n                               mapped_ptr: *mut libc::c_void,\n                               num_events_in_wait_list: cl_uint,\n                               event_wait_list: *const cl_event,\n                               event: *mut cl_event) -> cl_int;\n    pub fn clEnqueueNDRangeKernel(command_queue: cl_command_queue,\n                              kernel: cl_kernel,\n                              work_dim: cl_uint,\n                              global_work_offset: *const libc::size_t,\n                              global_work_size: *const libc::size_t,\n                              local_work_size: *const libc::size_t,\n                              num_events_in_wait_list: cl_uint,\n                              event_wait_list: *const cl_event,\n                              event: *mut cl_event) -> cl_int;\n    pub fn clEnqueueTask(command_queue: cl_command_queue,\n                     kernel: cl_kernel,\n                     num_events_in_wait_list: cl_uint,\n                     event_wait_list: *const cl_event,\n                     event: *mut cl_event) -> cl_int;\n    pub fn clEnqueueNativeKernel(command_queue: cl_command_queue,\n                             user_func: extern fn (*mut libc::c_void),\n                             args: *mut libc::c_void,\n                             cb_args: libc::size_t,\n                             num_mem_objects: cl_uint,\n                             mem_list: *const cl_mem,\n                             args_mem_loc: *const *const libc::c_void,\n                             num_events_in_wait_list: cl_uint,\n                             event_wait_list: *const cl_event,\n                             event: *mut cl_event) -> cl_int;\n    pub fn clEnqueueMarker(command_queue: cl_command_queue,\n                       event: *mut cl_event) -> cl_int;\n    pub fn clEnqueueWaitForEvents(command_queue: cl_command_queue,\n                              num_events: cl_uint,\n                              event_list: *mut cl_event) -> cl_int;\n    pub fn clEnqueueBarrier(command_queue: cl_command_queue) -> cl_int;\n\n    /* Extension function access\n     *\n     * Returns the extension function address for the given function name,\n     * or NULL if a valid function can not be found. The client must\n     * check to make sure the address is not NULL, before using or\n     * or calling the returned function address.\n     */\n    pub fn clGetExtensionFunctionAddress(func_name: *const libc::c_char) -> *mut libc::c_void;\n  }\n}\n"
  },
  {
    "path": "src/error.rs",
    "content": "//! Error handling utilities.\n\nuse cl::{CLStatus, cl_int};\nuse cl::CLStatus::CL_SUCCESS;\n\nfn error_str(status_code: cl_int) -> String {\n    match status_code {\n    0 => CLStatus::CL_SUCCESS.to_string(),\n    -1 => CLStatus::CL_DEVICE_NOT_FOUND.to_string(),\n    -2 => CLStatus::CL_DEVICE_NOT_AVAILABLE.to_string(),\n    -3 => CLStatus::CL_COMPILER_NOT_AVAILABLE.to_string(),\n    -4 => CLStatus::CL_MEM_OBJECT_ALLOCATION_FAILURE.to_string(),\n    -5 => CLStatus::CL_OUT_OF_RESOURCES.to_string(),\n    -6 => CLStatus::CL_OUT_OF_HOST_MEMORY.to_string(),\n    -7 => CLStatus::CL_PROFILING_INFO_NOT_AVAILABLE.to_string(),\n    -8 => CLStatus::CL_MEM_COPY_OVERLAP.to_string(),\n    -9 => CLStatus::CL_IMAGE_FORMAT_MISMATCH.to_string(),\n    -10 => CLStatus::CL_IMAGE_FORMAT_NOT_SUPPORTED.to_string(),\n    -11 => CLStatus::CL_BUILD_PROGRAM_FAILURE.to_string(),\n    -12 => CLStatus::CL_MAP_FAILURE.to_string(),\n    -13 => CLStatus::CL_MISALIGNED_SUB_BUFFER_OFFSET.to_string(),\n    -14 => CLStatus::CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST.to_string(),\n    -30 => CLStatus::CL_INVALID_VALUE.to_string(),\n    -31 => CLStatus::CL_INVALID_DEVICE_TYPE.to_string(),\n    -32 => CLStatus::CL_INVALID_PLATFORM.to_string(),\n    -33 => CLStatus::CL_INVALID_DEVICE.to_string(),\n    -34 => CLStatus::CL_INVALID_CONTEXT.to_string(),\n    -35 => CLStatus::CL_INVALID_QUEUE_PROPERTIES.to_string(),\n    -36 => CLStatus::CL_INVALID_COMMAND_QUEUE.to_string(),\n    -37 => CLStatus::CL_INVALID_HOST_PTR.to_string(),\n    -38 => CLStatus::CL_INVALID_MEM_OBJECT.to_string(),\n    -39 => CLStatus::CL_INVALID_IMAGE_FORMAT_DESCRIPTOR.to_string(),\n    -40 => CLStatus::CL_INVALID_IMAGE_SIZE.to_string(),\n    -41 => CLStatus::CL_INVALID_SAMPLER.to_string(),\n    -42 => CLStatus::CL_INVALID_BINARY.to_string(),\n    -43 => CLStatus::CL_INVALID_BUILD_OPTIONS.to_string(),\n    -44 => CLStatus::CL_INVALID_PROGRAM.to_string(),\n    -45 => CLStatus::CL_INVALID_PROGRAM_EXECUTABLE.to_string(),\n    -46 => CLStatus::CL_INVALID_KERNEL_NAME.to_string(),\n    -47 => CLStatus::CL_INVALID_KERNEL_DEFINITION.to_string(),\n    -48 => CLStatus::CL_INVALID_KERNEL.to_string(),\n    -49 => CLStatus::CL_INVALID_ARG_INDEX.to_string(),\n    -50 => CLStatus::CL_INVALID_ARG_VALUE.to_string(),\n    -51 => CLStatus::CL_INVALID_ARG_SIZE.to_string(),\n    -52 => CLStatus::CL_INVALID_KERNEL_ARGS.to_string(),\n    -53 => CLStatus::CL_INVALID_WORK_DIMENSION.to_string(),\n    -54 => CLStatus::CL_INVALID_WORK_GROUP_SIZE.to_string(),\n    -55 => CLStatus::CL_INVALID_WORK_ITEM_SIZE.to_string(),\n    -56 => CLStatus::CL_INVALID_GLOBAL_OFFSET.to_string(),\n    -57 => CLStatus::CL_INVALID_EVENT_WAIT_LIST.to_string(),\n    -58 => CLStatus::CL_INVALID_EVENT.to_string(),\n    -59 => CLStatus::CL_INVALID_OPERATION.to_string(),\n    -60 => CLStatus::CL_INVALID_GL_OBJECT.to_string(),\n    -61 => CLStatus::CL_INVALID_BUFFER_SIZE.to_string(),\n    -62 => CLStatus::CL_INVALID_MIP_LEVEL.to_string(),\n    -63 => CLStatus::CL_INVALID_GLOBAL_WORK_SIZE.to_string(),\n    -64 => CLStatus::CL_INVALID_PROPERTY.to_string(),\n    -1001 => CLStatus::CL_PLATFORM_NOT_FOUND_KHR.to_string(),\n        _ => format!(\"Unknown Error: {}\", status_code)\n    }\n}\n\npub fn check(status: cl_int, message: &str) {\n    if status != CL_SUCCESS as cl_int {\n        panic!(\"{} ({})\", message, error_str(status))\n    }\n}\n"
  },
  {
    "path": "src/ext.rs",
    "content": "#![allow(unused,\n         unused_attributes,\n         non_camel_case_types,\n         non_snake_case)]\n\n/// All of the extensions defined for OpenCL 1.1, from\n/// [`cl_ext.h`](https://www.khronos.org/registry/cl/api/1.1/cl_ext.h).\n\n// Macro to define a struct-style extension pointer loader.\n// Defines a (`Copy`, `Sync`) `struct Functions` that has extension function pointers as members (and methods,\n// for convenience).\n// Call `$ext::load()` to get an Option<$ext::Functions, String>.  (It's safe to call extension function pointers in other threads, right?)\nmacro_rules! cl_extension_loader {\n    (\n        $ext_name:expr;\n        $(extern fn $function:ident ($($arg:ident : $arg_type:ty),*) -> $ret:ty),*\n    ) => (\n        // Define struct Functions\n        ext_struct_def!{ $($function, ($($arg, $arg_type),*) $ret)* }\n        impl Functions {\n            // Make function pointers available as methods so they don't have to be called as (struct.member)(arg)\n            $( #[inline(always)] unsafe fn $function (&self, $($arg:$arg_type),*) -> $ret { (self.$function)($($arg),*) } )*\n        }\n\n        pub fn load(platform: cl_platform_id) -> Result<Functions, String> {\n            use hl;\n            use std::mem;\n            use std::ptr;\n            use std::ffi::CString;\n            use cl::ll::clGetExtensionFunctionAddress;\n\n            // Read in the available extensions\n            // We have to do this, since loading function pointers for an\n            // unavailable extension can return non-NULL.\n            // TODO read in extensions lazily and store them in a global HashSet?\n            let available = unsafe {\n                let hl_platform = hl::Platform::from_platform_id(platform);\n                let available = hl_platform.extensions().contains($ext_name);\n                mem::forget(hl_platform);\n                available\n            };\n            if !available {\n                let platform_name;\n                unsafe {\n                    let hl_platform = hl::Platform::from_platform_id(platform);\n                    platform_name = hl_platform.name();\n                    mem::forget(hl_platform);\n                }\n                return Err(format!(\"extension {} unavailable for platform {}\", $ext_name, platform_name));\n            }\n            // Return a struct with all functions loaded\n            Ok(ext_struct_literal!($ext_name, platform, $($function),*))\n        }\n    )\n}\n// We only need these helper macros so we can special-case for unit structs\n// (Since writing `struct name {}` is a failing error for some reason)\n// Whatever functions we're calling aren't necessarily thread-safe, but since this is a low-level\n// interface we'll let the callers worry about that\nmacro_rules! ext_struct_def {\n    () => (#[derive(Copy, Clone)] pub struct Functions;);\n    ($($function:ident, ($($arg:ident, $arg_type:ty),+) $ret:ty)+) =>\n    (\n        #[derive(Copy, Clone)]\n        pub struct Functions {\n            $(pub $function: (extern fn ($($arg : $arg_type),+) -> $ret)),+\n        }\n    );\n}\n// (So is writing `name {}` as a literal)\nmacro_rules! ext_struct_literal {\n    ($ext_name:expr, $plat:ident,) => (Functions);\n    ($ext_name:expr, $plat:ident, $($function:ident),+) =>\n    (\n        Functions {\n            $($function: {\n                let mut fn_name\n                        = CString::new(stringify!($function)).unwrap();\n                // TODO use clGetExtensionFunctionAddressForPlatform() when it's available; more\n                // reliable.\n                let fn_ptr = unsafe { clGetExtensionFunctionAddress(fn_name.as_ptr()) };\n                if fn_ptr == ptr::null_mut() {\n                    let platform_name;\n\n                    unsafe {\n                        let hl_platform = hl::Platform::from_platform_id($plat);\n                        platform_name = hl_platform.name();\n                        mem::forget(hl_platform);\n                    }\n\n                    return Err(format!(\"extension {} apparently available for platform with id {}, but couldn't load function {}\",\n                                       $ext_name,\n                                       platform_name,\n                                       stringify!($function)));\n                }\n                unsafe {\n                    // Cast from *mut libc::void to the function pointer type we want\n                    mem::transmute(fn_ptr)\n                }\n            }),+\n        }\n    );\n}\n\npub mod cl_khr_fp64 {\n    use cl::*;\n    static CL_DEVICE_DOUBLE_FP_CONFIG: cl_uint = 0x1032;\n    cl_extension_loader! {\n        \"cl_khr_fp64\";\n    }\n}\n\npub mod cl_khr_fp16 {\n    use cl::*;\n    pub static CL_DEVICE_HALF_FP_CONFIG: cl_uint = 0x1033;\n    cl_extension_loader! {\n        \"cl_khr_pf16\";\n    }\n}\n\npub mod cl_APPLE_SetMemObjectDestructor {\n    use libc;\n    use cl::*;\n    cl_extension_loader! {\n        \"cl_APPLE_SetMemObjectDestructor\";\n        extern fn clSetMemObjectDestructorAPPLE(memobj: cl_mem,\n                                                pfn_notify: (extern fn(memobj: cl_mem,\n                                                                       user_data: *mut libc::c_void)),\n                                                user_data: *mut libc::c_void) -> () // Note: returning () is necessary to satisfy macros\n    }\n}\n\npub mod cl_APPLE_ContextLoggingFunctions {\n    use libc;\n    use cl::*;\n    cl_extension_loader! {\n        \"cl_APPLE_ContextLoggingFunctions\";\n        extern fn clLogMessagesToSystemLogAPPLE(errstr: *const libc::c_char,\n                                                private_info: *const libc::c_void,\n                                                cb: libc::size_t,\n                                                user_data: *mut libc::c_void) -> (),\n        extern fn clLogMessagesToStdoutAPPLE(errstr: *const libc::c_char,\n                                             private_info: *const libc::c_void,\n                                             cb: libc::size_t,\n                                             user_data: *mut libc::c_void) -> (),\n        extern fn clLogMessagesToStderrAPPLE(errstr: *const libc::c_char,\n                                             private_info: *const libc::c_void,\n                                             cb: libc::size_t,\n                                             user_data: *mut libc::c_void) -> ()\n    }\n}\n\npub mod cl_khr_icd {\n    use libc;\n    use cl::*;\n    pub static CL_PLATFORM_ICD_SUFFIX:      cl_uint = 0x0920;\n    // Note: this is an error code, but we can't extend CLStatus with it... hmm.\n    pub static CL_PLATFORM_NOT_FOUND_KHR:   cl_int  = -1001;\n    cl_extension_loader! {\n        \"cl_khr_icd\";\n        extern fn clIcdGetPlatformIDsKHR(num_entries: cl_uint,\n                                         platform: *mut cl_platform_id,\n                                         num_platforms: *mut cl_uint) -> cl_int\n    }\n}\n\npub mod cl_nv_device_attribute_query {\n    use cl::*;\n    pub static CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV:   cl_uint = 0x4000;\n    pub static CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV:   cl_uint = 0x4001;\n    pub static CL_DEVICE_REGISTERS_PER_BLOCK_NV:        cl_uint = 0x4002;\n    pub static CL_DEVICE_WARP_SIZE_NV:                  cl_uint = 0x4003;\n    pub static CL_DEVICE_GPU_OVERLAP_NV:                cl_uint = 0x4004;\n    pub static CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV:        cl_uint = 0x4005;\n    pub static CL_DEVICE_INTEGRATED_MEMORY_NV:          cl_uint = 0x4006;\n    cl_extension_loader! {\n        \"cl_nv_device_attribute_query\";\n    }\n}\n\npub mod cl_amd_device_attribute_query {\n    use cl::*;\n    pub static CL_DEVICE_PROFILING_TIMER_OFFSET_AMD:    cl_uint = 0x4036;\n    cl_extension_loader! {\n        \"cl_amd_device_attribute_query\";\n    }\n}\n\npub mod cl_arm_printf {\n    use cl::*;\n    pub static CL_PRINTF_CALLBACK_ARM:      cl_uint = 0x40B0;\n    pub static CL_PRINTF_BUFFERSIZE_ARM:    cl_uint = 0x40B1;\n    cl_extension_loader! {\n        \"cl_arm_printf\";\n    }\n}\n\npub mod cl_ext_device_fission {\n    use cl::*;\n    pub type cl_device_partition_property_ext = cl_ulong;\n    pub static CL_DEVICE_PARTITION_EQUALLY_EXT: cl_device_partition_property_ext            = 0x4050;\n    pub static CL_DEVICE_PARTITION_BY_COUNTS_EXT: cl_device_partition_property_ext          = 0x4051;\n    pub static CL_DEVICE_PARTITION_BY_NAMES_EXT: cl_device_partition_property_ext           = 0x4052;\n    pub static CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN_EXT: cl_device_partition_property_ext = 0x4053;\n    pub static CL_DEVICE_PARENT_DEVICE_EXT: cl_device_info                                  = 0x4054;\n    pub static CL_DEVICE_PARTITION_TYPES_EXT: cl_device_info                                = 0x4055;\n    pub static CL_DEVICE_AFFINITY_DOMAINS_EXT: cl_device_info                               = 0x4056;\n    pub static CL_DEVICE_REFERENCE_COUNT_EXT: cl_device_info                                = 0x4057;\n    pub static CL_DEVICE_PARTITION_STYLE_EXT: cl_device_info                                = 0x4058;\n    pub static CL_DEVICE_PARTITION_FAILED_EXT: cl_int                                       = -1057;\n    pub static CL_INVALID_PARTITION_COUNT_EXT: cl_int                                       = -1058;\n    pub static CL_INVALID_PARTITION_NAME_EXT: cl_int                                        = -1059;\n    pub static CL_AFFINITY_DOMAIN_L1_CACHE_EXT: cl_uint                                     = 0x1;\n    pub static CL_AFFINITY_DOMAIN_L2_CACHE_EXT: cl_uint                                     = 0x2;\n    pub static CL_AFFINITY_DOMAIN_L3_CACHE_EXT: cl_uint                                     = 0x3;\n    pub static CL_AFFINITY_DOMAIN_L4_CACHE_EXT: cl_uint                                     = 0x4;\n    pub static CL_AFFINITY_DOMAIN_NUMA_EXT: cl_uint                                         = 0x10;\n    pub static CL_AFFINITY_DOMAIN_NEXT_FISSIONABLE_EXT: cl_uint                             = 0x100;\n    pub static CL_PROPERTIES_LIST_END_EXT: cl_device_partition_property_ext                 = 0;\n    pub static CL_PARTITION_BY_COUNTS_LIST_END_EXT: cl_device_partition_property_ext        = 0;\n    pub static CL_PARTITION_BY_NAMES_LIST_END_EXT: cl_device_partition_property_ext         = std::u64::MAX;\n    cl_extension_loader! {\n        \"cl_ext_device_fission\";\n        extern fn clReleaseDeviceEXT(device: cl_device_id) -> cl_int,\n        extern fn clRetainDeviceEXT(device: cl_device_id) -> cl_int,\n        extern fn clCreateSubDevicesExt(in_device: cl_device_id,\n                                        properties: *const cl_device_partition_property_ext,\n                                        num_entries: cl_uint,\n                                        out_devices: *mut cl_device_id,\n                                        num_devices: *mut cl_uint) -> cl_int\n    }\n}\n\npub mod cl_qcom_ext_host_ptr {\n    use libc;\n    use cl::*;\n    pub type cl_image_pitch_info_qcom = cl_uint;\n    pub struct cl_mem_ext_host_ptr {\n        pub allocation_type: cl_uint,\n        pub host_cache_policy: cl_uint\n    }\n    pub static CL_MEM_EXT_HOST_PTR_QCOM:                cl_uint = (1 << 29);\n    pub static CL_DEVICE_EXT_MEM_PADDING_IN_BYTES_QCOM: cl_uint = 0x40A0;\n    pub static CL_DEVICE_PAGE_SIZE_QCOM:                cl_uint = 0x40A1;\n    pub static CL_IMAGE_ROW_ALIGNMENT_QCOM:             cl_uint = 0x40A2;\n    pub static CL_IMAGE_SLICE_ALIGNMENT_QCOM:           cl_uint = 0x40A3;\n    pub static CL_MEM_HOST_UNCACHED_QCOM:               cl_uint = 0x40A4;\n    pub static CL_MEM_HOST_WRITEBACK_QCOM:              cl_uint = 0x40A5;\n    pub static CL_MEM_HOST_WRITETHROUGH_QCOM:           cl_uint = 0x40A6;\n    pub static CL_MEM_HOST_WRITE_COMBINING_QCOM:        cl_uint = 0x40A7;\n    cl_extension_loader! {\n        \"cl_qcom_ext_host_ptr\";\n        extern fn clGetDeviceImageInfoQCOM(device: cl_device_id,\n                                           image_width: libc::size_t,\n                                           image_height: libc::size_t,\n                                           image_format: *const cl_image_format,\n                                           param_name: cl_image_pitch_info_qcom,\n                                           param_value_size: libc::size_t,\n                                           param_value: *mut libc::c_void,\n                                           param_value_size_ret: *mut libc::size_t) -> ()\n    }\n}\n\n// This extension depends on the previous one. Should we try to express that?\npub mod cl_qcom_ion_host_ptr {\n    use libc;\n    use cl::*;\n    use super::cl_qcom_ext_host_ptr;\n    struct cl_mem_ion_host_ptr {\n        pub ext_host_ptr: cl_qcom_ext_host_ptr::cl_mem_ext_host_ptr,\n        pub ion_filedesc: libc::c_int,\n        pub ion_hostptr: *mut libc::c_void\n    }\n    pub static CL_MEM_ION_HOST_PTR_QCOM: cl_uint = 0x40A8;\n\n    cl_extension_loader! {\n        \"cl_qcom_ion_host_ptr\";\n    }\n}\n"
  },
  {
    "path": "src/hl.rs",
    "content": "//! A higher level API.\n\nuse libc;\nuse std::ffi::CString;\nuse std::iter::repeat;\nuse std::marker::PhantomData;\nuse std::mem;\nuse std::ptr;\nuse std::string::String;\nuse std::vec::Vec;\n\nuse cl;\nuse cl::*;\nuse cl::ll::*;\nuse cl::CLStatus::CL_SUCCESS;\nuse error::check;\nuse mem::{Put, Get, Write, Read, Buffer, CLBuffer};\n\n#[derive(Copy, Clone)]\npub enum DeviceType {\n      CPU, GPU\n}\n\nfn convert_device_type(device: DeviceType) -> cl_device_type {\n    match device {\n        DeviceType::CPU => CL_DEVICE_TYPE_CPU,\n        DeviceType::GPU => CL_DEVICE_TYPE_GPU | CL_DEVICE_TYPE_ACCELERATOR\n    }\n}\n\npub struct Platform {\n    id: cl_platform_id\n}\n\nimpl Platform {\n    fn get_devices_internal(&self, dtype: cl_device_type) -> Vec<Device>\n    {\n        unsafe\n        {\n            let mut num_devices = 0;\n\n            info!(\"Looking for devices matching {}\", dtype);\n\n            clGetDeviceIDs(self.id, dtype, 0, ptr::null_mut(),\n                           (&mut num_devices));\n\n            let mut ids: Vec<cl_device_id> = repeat(0 as cl_device_id)\n                .take(num_devices as usize).collect();\n            clGetDeviceIDs(self.id, dtype, ids.len() as cl_uint,\n                           ids.as_mut_ptr(), (&mut num_devices));\n            ids.iter().map(|id| { Device {id: *id }}).collect()\n        }\n    }\n\n    pub fn get_devices(&self) -> Vec<Device>\n    {\n        self.get_devices_internal(CL_DEVICE_TYPE_ALL)\n    }\n\n    pub fn get_devices_by_types(&self, types: &[DeviceType]) -> Vec<Device>\n    {\n        let mut dtype = 0;\n        for &t in types.iter() {\n          dtype |= convert_device_type(t);\n        }\n\n        self.get_devices_internal(dtype)\n    }\n\n    fn profile_info(&self, name: cl_platform_info) -> String\n    {\n        unsafe {\n            let mut size = 0 as libc::size_t;\n\n            let status = clGetPlatformInfo(self.id,\n                              name,\n                              0,\n                              ptr::null_mut(),\n                              &mut size);\n            check(status, \"Could not determine platform info string length\");\n\n            let mut buf : Vec<u8>\n                = repeat(0u8).take(size as usize).collect();\n\n            let status = clGetPlatformInfo(self.id,\n                              name,\n                              size,\n                              buf.as_mut_ptr() as *mut libc::c_void,\n                              ptr::null_mut());\n            check(status, \"Could not get platform info string\");\n\n            String::from_utf8_unchecked(buf)\n        }\n    }\n\n    pub fn get_id(&self) -> cl_platform_id {\n        self.id\n    }\n\n    pub fn name(&self) -> String\n    {\n        self.profile_info(CL_PLATFORM_NAME)\n    }\n\n    pub fn version(&self) -> String\n    {\n        self.profile_info(CL_PLATFORM_VERSION)\n    }\n\n    pub fn profile(&self) -> String\n    {\n        self.profile_info(CL_PLATFORM_PROFILE)\n    }\n\n    pub fn vendor(&self) -> String\n    {\n        self.profile_info(CL_PLATFORM_VENDOR)\n    }\n\n    pub fn extensions(&self) -> String\n    {\n        self.profile_info(CL_PLATFORM_EXTENSIONS)\n    }\n\n    pub unsafe fn from_platform_id(id: cl_platform_id) -> Platform {\n        Platform { id: id }\n    }\n}\n\n// This mutex is used to work around weak OpenCL implementations.\n// On some implementations concurrent calls to clGetPlatformIDs\n// will cause the implantation to return invalid status.\nstatic mut platforms_mutex: std::sync::StaticMutex = std::sync::MUTEX_INIT;\n\npub fn get_platforms() -> Vec<Platform>\n{\n    let mut num_platforms = 0 as cl_uint;\n\n    unsafe\n    {\n        let guard = platforms_mutex.lock();\n        let status = clGetPlatformIDs(0,\n                                          ptr::null_mut(),\n                                          (&mut num_platforms));\n        // unlock this before the check in case the check fails\n        check(status, \"could not get platform count.\");\n\n        let mut ids: Vec<cl_device_id> = repeat(0 as cl_device_id)\n            .take(num_platforms as usize).collect();\n\n        let status = clGetPlatformIDs(num_platforms,\n                                      ids.as_mut_ptr(),\n                                      (&mut num_platforms));\n        check(status, \"could not get platforms.\");\n\n        let _ = guard;\n\n        ids.iter().map(|id| { Platform { id: *id } }).collect()\n    }\n}\n\npub fn create_context_with_properties(dev: &[Device], prop: &[cl_context_properties]) -> Context\n{\n    unsafe\n    {\n        // TODO: Support for multiple devices\n        let mut errcode = 0;\n        let dev: Vec<cl_device_id> = dev.iter().map(|dev| dev.id).collect();\n\n        // TODO: Proper error messages\n        let ctx = clCreateContext(&prop[0],\n                                  dev.len() as u32,\n                                  &dev[0],\n                                  mem::transmute(ptr::null::<fn()>()),\n                                  ptr::null_mut(),\n                                  &mut errcode);\n\n        check(errcode, \"Failed to create opencl context!\");\n\n        Context { ctx: ctx }\n    }\n}\n\n#[derive(Copy, Clone)]\npub struct Device {\n    id: cl_device_id\n}\n\nunsafe impl Sync for Device {}\nunsafe impl Send for Device {}\n\nimpl Device {\n    fn profile_info(&self, name: cl_device_info) -> String\n    {\n        unsafe {\n            let mut size = 0 as libc::size_t;\n\n            let status = clGetDeviceInfo(\n                self.id,\n                name,\n                0,\n                ptr::null_mut(),\n                &mut size);\n            check(status, \"Could not determine device info string length\");\n\n            let mut buf : Vec<u8>\n                = repeat(0u8).take(size as usize).collect();\n\n            let status = clGetDeviceInfo(self.id,\n                                         name,\n                                         size,\n                                         buf.as_mut_ptr() as *mut libc::c_void,\n                                         ptr::null_mut());\n            check(status, \"Could not get device info string\");\n\n            String::from_utf8_unchecked(buf)\n        }\n    }\n\n    pub fn name(&self) -> String\n    {\n        self.profile_info(CL_DEVICE_NAME)\n    }\n    pub fn vendor(&self) -> String\n    {\n        self.profile_info(CL_DEVICE_VENDOR)\n    }\n    pub fn profile(&self) -> String\n    {\n        self.profile_info(CL_DEVICE_PROFILE)\n    }\n    pub fn device_type(&self) -> String\n    {\n        self.profile_info(CL_DEVICE_TYPE)\n    }\n\n    pub fn compute_units(&self) -> usize {\n\t\tunsafe {\n\t\t\tlet mut ct: usize = 0;\n            let status = clGetDeviceInfo(\n                self.id,\n                CL_DEVICE_MAX_COMPUTE_UNITS,\n                8,\n                (&mut ct as *mut usize) as *mut libc::c_void,\n                ptr::null_mut());\n            check(status, \"Could not get number of device compute units.\");\n\t\t\treturn ct;\n\t\t}\n\t}\n\n\n    pub fn create_context(&self) -> Context\n    {\n        unsafe\n        {\n            // TODO: Support for multiple devices\n            let mut errcode = 0;\n\n            // TODO: Proper error messages\n            let ctx = clCreateContext(ptr::null(),\n                                      1,\n                                      &self.id,\n                                      mem::transmute(ptr::null::<fn()>()),\n                                      ptr::null_mut(),\n                                      (&mut errcode));\n\n            check(errcode, \"Failed to create opencl context!\");\n\n            Context { ctx: ctx }\n        }\n    }\n}\n\npub struct Context {\n    pub ctx: cl_context,\n}\n\nunsafe impl Sync for Context {}\nunsafe impl Send for Context {}\n\nimpl Context {\n    pub fn create_buffer<T>(&self, size: usize, flags: cl_mem_flags) -> CLBuffer<T>\n    {\n        unsafe {\n            let mut status = 0;\n            let buf = clCreateBuffer(self.ctx,\n                                     flags,\n                                     (size*mem::size_of::<T>()) as libc::size_t ,\n                                     ptr::null_mut(),\n                                     (&mut status));\n            check(status, \"Could not allocate buffer\");\n            CLBuffer {\n                cl_buffer: buf,\n                phantom: PhantomData,\n            }\n        }\n    }\n\n\n    pub fn create_buffer_from<T, U, IN: Put<T, U>>(&self, create: IN, flags: cl_mem_flags) -> U\n    {\n        create.put(|p, len| {\n            let mut status = 0;\n            let buf = unsafe {\n                clCreateBuffer(self.ctx,\n                               flags | CL_MEM_COPY_HOST_PTR,\n                               len,\n                               mem::transmute(p),\n                               (&mut status))\n            };\n            check(status, \"Could not allocate buffer\");\n            buf\n        })\n    }\n\n    pub fn create_command_queue(&self, device: &Device) -> CommandQueue\n    {\n        unsafe\n        {\n            let mut errcode = 0;\n\n            let cqueue = clCreateCommandQueue(self.ctx,\n                                              device.id,\n                                              CL_QUEUE_PROFILING_ENABLE,\n                                              (&mut errcode));\n\n            check(errcode, \"Failed to create command queue!\");\n\n            CommandQueue {\n                cqueue: cqueue\n            }\n        }\n    }\n\n    pub fn create_program_from_source(&self, src: &str) -> Program\n    {\n        unsafe\n        {\n            let src = CString::new(src).unwrap();\n\n            let mut status = CL_SUCCESS as cl_int;\n            let program = clCreateProgramWithSource(\n                self.ctx,\n                1,\n                &src.as_ptr(),\n                ptr::null(),\n                (&mut status));\n            check(status, \"Could not create program\");\n\n            Program { prg: program }\n        }\n    }\n\n    pub fn create_program_from_binary(&self, bin: &str, device: &Device) -> Program {\n        let src = CString::new(bin).unwrap();\n        let mut status = CL_SUCCESS as cl_int;\n        let len = bin.len() as libc::size_t;\n        let program = unsafe {\n            clCreateProgramWithBinary(\n                self.ctx,\n                1,\n                &device.id,\n                (&len),\n                (src.as_ptr() as *const *const i8) as *const *const libc::c_uchar,\n                ptr::null_mut(),\n                (&mut status))\n        };\n        check(status, \"Could not create program\");\n\n        Program {prg: program}\n    }\n}\n\nimpl Drop for Context\n{\n    fn drop(&mut self) {\n        unsafe {\n            clReleaseContext(self.ctx);\n        }\n    }\n}\n\nimpl<'r, T> KernelArg for &'r (Buffer<T> + 'r) {\n    fn get_value(&self) -> (libc::size_t, *const libc::c_void)\n    {\n        unsafe {\n            (mem::size_of::<cl_mem>() as libc::size_t,\n             self.id_ptr() as *const libc::c_void)\n        }\n    }\n}\n\nimpl<'r, T> KernelArg for Box<Buffer<T> + 'r> {\n    fn get_value(&self) -> (libc::size_t, *const libc::c_void)\n    {\n        unsafe {\n            (mem::size_of::<cl_mem>() as libc::size_t,\n             self.id_ptr() as *const libc::c_void)\n        }\n    }\n}\n\n\npub struct CommandQueue {\n    pub cqueue: cl_command_queue\n}\n\nunsafe impl Sync for CommandQueue {}\nunsafe impl Send for CommandQueue {}\n\nimpl CommandQueue\n{\n    //synchronous\n    pub fn enqueue_kernel<I: KernelIndex, E: EventList>(&self, k: &Kernel, global: I, local: Option<I>, wait_on: E)\n        -> Event\n    {\n        unsafe\n        {\n            wait_on.as_event_list(|event_list, event_list_length| {\n                let mut e: cl_event = ptr::null_mut();\n                let mut status = clEnqueueNDRangeKernel(\n                    self.cqueue,\n                    k.kernel,\n                    KernelIndex::num_dimensions(None::<I>),\n                    ptr::null(),\n                    global.get_ptr(),\n                    match local {\n                        Some(ref l) => l.get_ptr() as *const libc::size_t,\n                        None => ptr::null()\n                    },\n                    event_list_length,\n                    event_list,\n                    (&mut e));\n                check(status, \"Error enqueuing kernel.\");\n                status = clFinish(self.cqueue);\n                check(status, \"Error finishing kernel.\");\n                Event { event: e }\n            })\n        }\n    }\n\n    //asynchronous\n    pub fn enqueue_async_kernel<I: KernelIndex, E: EventList>(&self, k: &Kernel, global: I, local: Option<I>, wait_on: E)\n        -> Event\n    {\n        unsafe\n        {\n            wait_on.as_event_list(|event_list, event_list_length| {\n                let mut e: cl_event = ptr::null_mut();\n                let status = clEnqueueNDRangeKernel(\n                    self.cqueue,\n                    k.kernel,\n                    KernelIndex::num_dimensions(None::<I>),\n                    ptr::null(),\n                    global.get_ptr(),\n                    match local {\n                        Some(ref l) => l.get_ptr() as *const libc::size_t,\n                        None => ptr::null()\n                    },\n                    event_list_length,\n                    event_list,\n                    (&mut e));\n                check(status, \"Error enqueuing kernel.\");\n                Event { event: e }\n            })\n        }\n    }\n\n    pub fn get<T, U, B: Buffer<T>, G: Get<B, U>, E: EventList>(&self, buf: &B, event: E) -> G\n    {\n        event.as_event_list(|event_list, event_list_length| {\n            Get::get(buf, |offset, ptr, len| {\n                unsafe {\n                    let err = clEnqueueReadBuffer(self.cqueue,\n                                                  buf.id(),\n                                                  CL_TRUE,\n                                                  offset as libc::size_t,\n                                                  len,\n                                                  ptr,\n                                                  event_list_length,\n                                                  event_list,\n                                                  ptr::null_mut());\n\n                    check(err, \"Failed to read buffer\");\n                }\n            })\n        })\n    }\n\n    pub fn write<U: Write, T, E: EventList, B: Buffer<T>>(&self, mem: &B, write: &U, event: E)\n    {\n        unsafe {\n            event.as_event_list(|event_list, event_list_length| {\n                write.write(|offset, p, len| {\n                    let err = clEnqueueWriteBuffer(self.cqueue,\n                                                   mem.id(),\n                                                   CL_TRUE,\n                                                   offset as libc::size_t,\n                                                   len as libc::size_t,\n                                                   p as *const libc::c_void,\n                                                   event_list_length,\n                                                   event_list,\n                                                   ptr::null_mut());\n\n                    check(err, \"Failed to write buffer\");\n                })\n            })\n        }\n    }\n\n    pub fn write_async<U: Write, T, E: EventList, B: Buffer<T>>(&self, mem: &B, write: &U, event: E) -> Event\n    {\n        let mut out_event = None;\n        unsafe {\n            event.as_event_list(|evt, evt_len| {\n                write.write(|offset, p, len| {\n                    let mut e: cl_event = ptr::null_mut();\n                    let err = clEnqueueWriteBuffer(self.cqueue,\n                                                   mem.id(),\n                                                   CL_FALSE,\n                                                   offset as libc::size_t,\n                                                   len as libc::size_t,\n                                                   p as *const libc::c_void,\n                                                   evt_len,\n                                                   evt,\n                                                   &mut e);\n                    out_event = Some(e);\n                    check(err, \"Failed to write buffer\");\n                })\n            })\n        }\n        Event { event: out_event.unwrap() }\n    }\n\n    pub fn read<T, U: Read, E: EventList, B: Buffer<T>>(&self, mem: &B, read: &mut U, event: E)\n    {\n        event.as_event_list(|event_list, event_list_length| {\n                read.read(|offset, p, len| {\n                        unsafe {\n                            let err = clEnqueueReadBuffer(self.cqueue,\n                                                          mem.id(),\n                                                          CL_TRUE,\n                                                          offset as libc::size_t,\n                                                          len as libc::size_t,\n                                                          p as *mut libc::c_void,\n                                                          event_list_length,\n                                                          event_list,\n                                                          ptr::null_mut());\n\n                            check(err, \"Failed to read buffer\");\n                        }\n                    })\n            })\n    }\n}\n\nimpl Drop for CommandQueue\n{\n    fn drop(&mut self) {\n        unsafe {\n            clReleaseCommandQueue(self.cqueue);\n        }\n    }\n}\n\n\n/// Represents an OpenCL program, which is a collection of kernels.\n///\n/// Create these using\n/// [`Context::create_program_from_source`](struct.Context.html#method.create_program_from_source)\n/// or\n/// [`Context::create_program_from_binary`](struct.Context.html#method.create_program_from_binary).\npub struct Program\n{\n    prg: cl_program,\n}\n\nimpl Drop for Program\n{\n    fn drop(&mut self) {\n        unsafe {\n            clReleaseProgram(self.prg);\n        }\n    }\n}\n\nimpl Program\n{\n    /// Build the program for a given device.\n    ///\n    /// Both Ok and Err returns include the build log.\n    pub fn build(&self, device: &Device) -> Result<String, String>\n    {\n        unsafe\n        {\n            let ret = clBuildProgram(self.prg, 1, &device.id,\n                                     ptr::null(),\n                                     mem::transmute(ptr::null::<fn()>()),\n                                     ptr::null_mut());\n            // Get the build log.\n            let mut size = 0 as libc::size_t;\n            let status = clGetProgramBuildInfo(\n                self.prg,\n                device.id,\n                CL_PROGRAM_BUILD_LOG,\n                0,\n                ptr::null_mut(),\n                (&mut size));\n            check(status, \"Could not get build log\");\n\n            let mut buf : Vec<u8> = repeat(0u8).take(size as usize).collect();\n            let status = clGetProgramBuildInfo(\n                self.prg,\n                device.id,\n                CL_PROGRAM_BUILD_LOG,\n                buf.len() as libc::size_t,\n                buf.as_mut_ptr() as *mut libc::c_void,\n                ptr::null_mut());\n            check(status, \"Could not get build log\");\n\n            let log = String::from_utf8_lossy(&buf[..]);\n            if ret == CL_SUCCESS as cl_int {\n                Ok(log.into_owned())\n            } else {\n                Err(log.into_owned())\n            }\n        }\n    }\n\n    pub fn create_kernel(&self, name: &str) -> Kernel {\n        create_kernel(self, name)\n    }\n}\n\npub struct Kernel {\n    kernel: cl_kernel,\n}\n\nimpl Drop for Kernel\n{\n    fn drop(&mut self) {\n        unsafe {\n            clReleaseKernel(self.kernel);\n        }\n    }\n}\n\nimpl Kernel {\n    pub fn set_arg<T: KernelArg>(&self, i: usize, x: &T)\n    {\n        set_kernel_arg(self, i as cl::cl_uint, x)\n    }\n}\n\npub fn create_kernel(program: &Program, kernel: & str) -> Kernel\n{\n    unsafe {\n        let mut errcode = 0;\n        let str = CString::new(kernel).unwrap();\n        let kernel = clCreateKernel(program.prg,\n                                    str.as_ptr(),\n                                    (&mut errcode));\n\n        check(errcode, \"Failed to create kernel!\");\n\n        Kernel { kernel: kernel }\n    }\n}\n\npub trait KernelArg {\n  fn get_value(&self) -> (libc::size_t, *const libc::c_void);\n}\n\nmacro_rules! scalar_kernel_arg (\n    ($t:ty) => (impl KernelArg for $t {\n        fn get_value(&self) -> (libc::size_t, *const libc::c_void) {\n            (mem::size_of::<$t>() as libc::size_t,\n             (self as *const $t) as *const libc::c_void)\n        }\n    })\n);\n\nscalar_kernel_arg!(isize);\nscalar_kernel_arg!(usize);\nscalar_kernel_arg!(u32);\nscalar_kernel_arg!(u64);\nscalar_kernel_arg!(i32);\nscalar_kernel_arg!(i64);\nscalar_kernel_arg!(f32);\nscalar_kernel_arg!(f64);\nscalar_kernel_arg!([f32; 2]);\nscalar_kernel_arg!([f64; 2]);\n\nimpl KernelArg for [f32; 3] {\n    fn get_value(&self) -> (libc::size_t, *const libc::c_void) {\n        (4 * mem::size_of::<f32>() as libc::size_t,\n          (self as *const f32) as *const libc::c_void)\n    }\n}\n\nimpl KernelArg for [f64; 3] {\n    fn get_value(&self) -> (libc::size_t, *const libc::c_void) {\n        (4 * mem::size_of::<f64>() as libc::size_t,\n          (self as *const f64) as *const libc::c_void)\n    }\n}\n\npub fn set_kernel_arg<T: KernelArg>(kernel: & Kernel,\n                                    position: cl_uint,\n                                    arg: &T)\n{\n    unsafe\n    {\n        let (size, p) = arg.get_value();\n        let ret = clSetKernelArg(kernel.kernel, position,\n                                 size,\n                                 p);\n\n        check(ret, \"Failed to set kernel arg!\");\n    }\n}\n\n\npub struct Event\n{\n    pub event: cl_event,\n}\n\nimpl Event {\n    fn get_time(&self, param: cl_uint) -> u64\n    {\n        unsafe {\n            let mut time: cl_ulong = 0;\n            let ret = clGetEventProfilingInfo(self.event,\n                                    param,\n                                    mem::size_of::<cl_ulong>() as libc::size_t,\n                                    (&mut time as *mut u64) as *mut libc::c_void,\n                                    ptr::null_mut());\n\n            check(ret, \"Failed to get profiling info\");\n            time as u64\n        }\n    }\n\n    pub fn queue_time(&self) -> u64\n    {\n        self.get_time(CL_PROFILING_COMMAND_QUEUED)\n    }\n\n    pub fn submit_time(&self) -> u64\n    {\n        self.get_time(CL_PROFILING_COMMAND_SUBMIT)\n    }\n\n    pub fn start_time(&self) -> u64\n    {\n        self.get_time(CL_PROFILING_COMMAND_START)\n    }\n\n    pub fn end_time(&self) -> u64\n    {\n        self.get_time(CL_PROFILING_COMMAND_END)\n    }\n}\n\nimpl Drop for Event\n{\n    fn drop(&mut self) {\n        unsafe {\n            clReleaseEvent(self.event);\n        }\n    }\n}\n\npub trait EventList {\n    fn as_event_list<T, F: FnOnce(*const cl_event, cl_uint) -> T>(&self, F) -> T;\n\n    fn wait(&self) {\n        self.as_event_list(|p, len| {\n            unsafe {\n                let status = clWaitForEvents(len, p);\n                check(status, \"Error waiting for event(s)\");\n            }\n        })\n    }\n}\n\nimpl<'r> EventList for &'r Event {\n    fn as_event_list<T, F>(&self, f: F) -> T\n        where F: FnOnce(*const cl_event, cl_uint) -> T\n    {\n        f(&self.event, 1 as cl_uint)\n    }\n}\n\nimpl EventList for Event {\n    fn as_event_list<T, F>(&self, f: F) -> T\n        where F: FnOnce(*const cl_event, cl_uint) -> T\n    {\n        f(&self.event, 1 as cl_uint)\n    }\n}\n\nimpl<T: EventList> EventList for Option<T> {\n    fn as_event_list<T2, F>(&self, f: F) -> T2\n        where F: FnOnce(*const cl_event, cl_uint) -> T2\n    {\n        match *self {\n            None => f(ptr::null(), 0),\n            Some(ref s) => s.as_event_list(f)\n        }\n    }\n}\n\nimpl<'r> EventList for &'r [Event] {\n    fn as_event_list<T, F>(&self, f: F) -> T\n        where F: FnOnce(*const cl_event, cl_uint) -> T\n    {\n        let mut vec: Vec<cl_event> = Vec::with_capacity(self.len());\n        for item in self.iter(){\n            vec.push(item.event);\n        }\n\n        f(vec.as_ptr(), vec.len() as cl_uint)\n    }\n}\n\n/* this seems VERY hackey */\nimpl EventList for () {\n    fn as_event_list<T, F>(&self, f: F) -> T\n        where F: FnOnce(*const cl_event, cl_uint) -> T\n    {\n        f(ptr::null(), 0)\n    }\n}\n\n\npub trait KernelIndex\n{\n    fn num_dimensions(dummy_self: Option<Self>) -> cl_uint where Self: Sized;\n    fn get_ptr(&self) -> *const libc::size_t;\n}\n\nimpl KernelIndex for isize\n{\n    fn num_dimensions(_: Option<isize>) -> cl_uint { 1 }\n\n    fn get_ptr(&self) -> *const libc::size_t\n    {\n        (self as *const isize) as *const libc::size_t\n    }\n}\n\nimpl KernelIndex for (isize, isize) {\n    fn num_dimensions(_: Option<(isize, isize)>) -> cl_uint { 2 }\n\n    fn get_ptr(&self) -> *const libc::size_t {\n        (self as *const (isize, isize)) as *const libc::size_t\n    }\n}\n\nimpl KernelIndex for (isize, isize, isize)\n{\n    fn num_dimensions(_: Option<(isize, isize, isize)>) -> cl_uint { 3 }\n\n    fn get_ptr(&self) -> *const libc::size_t {\n        (self as *const (isize, isize, isize)) as *const libc::size_t\n    }\n}\n\nimpl KernelIndex for usize\n{\n    fn num_dimensions(_: Option<usize>) -> cl_uint { 1 }\n\n    fn get_ptr(&self) -> *const libc::size_t {\n        (self as *const usize) as *const libc::size_t\n    }\n}\n\nimpl KernelIndex for (usize, usize)\n{\n    fn num_dimensions(_: Option<(usize, usize)>) -> cl_uint { 2 }\n\n    fn get_ptr(&self) -> *const libc::size_t {\n        (self as *const (usize, usize)) as *const libc::size_t\n    }\n}\n\nimpl KernelIndex for (usize, usize, usize)\n{\n    fn num_dimensions(_: Option<(usize, usize, usize)>) -> cl_uint { 3 }\n\n    fn get_ptr(&self) -> *const libc::size_t {\n        (self as *const (usize, usize, usize)) as *const libc::size_t\n    }\n}\n"
  },
  {
    "path": "src/lib.rs",
    "content": "#![allow(improper_ctypes)]\n#![allow(missing_copy_implementations)]\n#![allow(non_upper_case_globals)]\n\n#![feature(static_mutex)]\n\n//! OpenCL bindings for Rust.\n\nextern crate libc;\n#[macro_use]\nextern crate log;\n\n#[link(name = \"OpenCL\", kind = \"framework\")]\n#[cfg(target_os = \"macos\")]\nextern { }\n\n#[link(name = \"OpenCL\")]\n#[cfg(target_os = \"linux\")]\nextern { }\n\n/// Low-level OpenCL bindings. These should primarily be used by the\n/// higher level features in this library.\npub mod cl;\n/// OpenCL extensions\npub mod ext;\npub mod error;\npub mod hl;\npub mod util;\npub mod mem;\npub mod array;\n"
  },
  {
    "path": "src/mem.rs",
    "content": "//! High level buffer management.\n\nuse libc::{size_t, c_void};\nuse std::marker::{PhantomData};\nuse std::mem;\nuse std::ptr;\nuse std::vec::Vec;\n\nuse cl::*;\nuse cl::ll::*;\n\nuse hl::KernelArg;\nuse error::check;\n\npub trait Buffer<T> {\n    unsafe fn id_ptr(&self) -> *const cl_mem;\n\n    fn id(&self) -> cl_mem {\n        unsafe {\n            *self.id_ptr()\n        }\n    }\n\n    fn byte_len(&self) -> size_t\n    {\n        unsafe {\n            let mut size : size_t = 0;\n            let err = clGetMemObjectInfo(self.id(),\n                                         CL_MEM_SIZE,\n                                         mem::size_of::<size_t>() as size_t,\n                                         (&mut size as *mut size_t) as *mut c_void,\n                                         ptr::null_mut());\n\n            check(err, \"Failed to read memory size\");\n            size\n        }\n    }\n\n    fn len(&self) -> usize { self.byte_len() as usize / mem::size_of::<T>() }\n}\n\npub struct CLBuffer<T> {\n    pub cl_buffer: cl_mem,\n    pub phantom: PhantomData<T>,\n}\n\nimpl<T> Drop for CLBuffer<T> {\n    fn drop(&mut self) {\n        unsafe {\n            clReleaseMemObject(self.cl_buffer);\n        }\n    }\n}\n\nimpl<T> Buffer<T> for CLBuffer<T> {\n    unsafe fn id_ptr(&self) -> *const cl_mem\n    {\n        &self.cl_buffer as *const cl_mem\n    }\n}\n\nimpl<T> KernelArg for CLBuffer<T> {\n    fn get_value(&self) -> (size_t, *const c_void)\n    {\n        unsafe {\n            (mem::size_of::<cl_mem>() as size_t,\n             self.id_ptr() as *const c_void)\n        }\n    }\n}\n\n/* memory life cycle\n * | Trait  | Exists in rust | Exists in OpenCL | Direction      |\n * | Put    | X              |                  | rust -> opencl |\n * | Get    |                | X                | opencl -> rust |\n * | Write  | X              | X                | rust -> opencl |\n * | Read   | X              | X                | opencl -> rust |\n *mut */\n\npub trait Put<T, B> {\n    fn put<F>(&self, F) -> B\n        where F: FnOnce(*const c_void, size_t) -> cl_mem;\n}\n\npub trait Get<B, T> {\n    fn get<F: FnOnce(size_t, *mut c_void, size_t)>(mem: &B, F) -> Self;\n}\n\npub trait Write {\n    fn write<F: FnOnce(size_t, *const c_void, size_t)>(&self, F);\n}\n\npub trait Read {\n    fn read<F: FnOnce(size_t, *mut c_void, size_t)>(&mut self, F);\n}\n\nimpl<'r, T> Put<T, CLBuffer<T>> for &'r [T]\n{\n    fn put<F>(&self, f: F) -> CLBuffer<T>\n        where F: FnOnce(*const c_void, size_t) -> cl_mem\n    {\n        CLBuffer {\n            cl_buffer: f(self.as_ptr() as *const c_void,\n                         (self.len() * mem::size_of::<T>()) as size_t),\n            phantom: PhantomData,\n        }\n    }\n}\n\nimpl<'r, T> Put<T, CLBuffer<T>> for &'r Vec<T>\n{\n    fn put<F>(&self, f: F) -> CLBuffer<T>\n        where F: FnOnce(*const c_void, size_t) -> cl_mem\n    {\n        CLBuffer {\n            cl_buffer: f(self.as_ptr() as *const c_void, (self.len() * mem::size_of::<T>()) as size_t),\n            phantom: PhantomData,\n        }\n    }\n}\n\nimpl<T> Put<T, CLBuffer<T>> for Vec<T>\n{\n    fn put<F>(&self, f: F) -> CLBuffer<T>\n        where F: FnOnce(*const c_void, size_t) -> cl_mem\n    {\n        CLBuffer {\n            cl_buffer: f(self.as_ptr() as *const c_void, (self.len() * mem::size_of::<T>()) as size_t),\n            phantom: PhantomData,\n        }\n    }\n}\n\nimpl<T> Get<CLBuffer<T>, T> for Vec<T>\n{\n    fn get<F>(mem: &CLBuffer<T>, f: F) -> Vec<T>\n        where F: FnOnce(size_t, *mut c_void, size_t)\n    {\n        let mut v: Vec<T> = Vec::with_capacity(mem.len());\n        unsafe {\n            v.set_len(mem.len());\n        }\n        f(0, v.as_ptr() as *mut c_void, (v.len() * mem::size_of::<T>()) as size_t);\n        v\n    }\n}\n\nimpl<'r, T> Write for &'r [T]\n{\n    fn write<F>(&self, f: F)\n        where F: FnOnce(size_t, *const c_void, size_t)\n    {\n        f(0, self.as_ptr() as *const c_void, (self.len() * mem::size_of::<T>()) as size_t)\n    }\n}\n\nimpl<'r, T> Read for &'r mut [T]\n{\n    fn read<F>(&mut self, f: F)\n        where F: FnOnce(size_t, *mut c_void, size_t)\n    {\n        let p = (*self).as_mut_ptr();\n        let len = self.len();\n        f(0, p as *mut c_void, (len * mem::size_of::<T>()) as size_t)\n    }\n}\n\nmacro_rules! get_arg (\n    ($t:ty) => (impl Get<CLBuffer<$t>, $t> for $t\n        {\n            fn get<F>(_: &CLBuffer<$t>, f: F) -> $t\n                where F: FnOnce(size_t, *mut c_void, size_t)\n            {\n                let mut v: $t = 0 as $t;\n                f(0, (&mut v as *mut $t) as *mut c_void, mem::size_of::<$t>() as size_t);\n                v as $t\n            }\n        })\n);\n\nget_arg!(isize);\nget_arg!(usize);\nget_arg!(u32);\nget_arg!(u64);\nget_arg!(i32);\nget_arg!(i64);\nget_arg!(f32);\nget_arg!(f64);\n\nmacro_rules! put_arg (\n    ($t:ty) => (impl Put<$t, CLBuffer<$t>> for $t\n        {\n            fn put<F>(&self, f: F) -> CLBuffer<$t>\n                where F: FnOnce(*const c_void, size_t) -> cl_mem\n            {\n                CLBuffer {\n                    cl_buffer: f((self as *const $t) as *const c_void, mem::size_of::<$t>() as size_t),\n                    phantom: PhantomData,\n                }\n            }\n        }\n    )\n);\n\nput_arg!(isize);\nput_arg!(usize);\nput_arg!(u32);\nput_arg!(u64);\nput_arg!(i32);\nput_arg!(i64);\nput_arg!(f32);\nput_arg!(f64);\n\nmacro_rules! read_arg (\n    ($t:ty) => (impl Read for $t\n        {\n            fn read<F>(&mut self, f: F)\n                where F: FnOnce(size_t, *mut c_void, size_t)\n            {\n                f(0, (self as *mut $t) as *mut c_void, mem::size_of::<$t>() as size_t)\n            }\n        }\n    )\n);\n\nread_arg!(isize);\nread_arg!(usize);\nread_arg!(u32);\nread_arg!(u64);\nread_arg!(i32);\nread_arg!(i64);\nread_arg!(f32);\nread_arg!(f64);\n\nmacro_rules! write_arg (\n    ($t:ty) => (impl Write for $t\n        {\n            fn write<F>(&self, f: F) \n                where F: FnOnce(size_t, *const c_void, size_t)\n            {\n                f(0, (self as *const $t) as *const c_void, mem::size_of::<$t>() as size_t)\n            }\n        }\n    )\n);\n\nwrite_arg!(isize);\nwrite_arg!(usize);\nwrite_arg!(u32);\nwrite_arg!(u64);\nwrite_arg!(i32);\nwrite_arg!(i64);\nwrite_arg!(f32);\nwrite_arg!(f64);\n"
  },
  {
    "path": "src/util.rs",
    "content": "//! Utility functions\n\nuse hl::*;\n\npub fn create_compute_context() -> Result<(Device, Context, CommandQueue), &'static str>\n{\n    let platforms = get_platforms();\n    if platforms.len() == 0 {\n        return Err(\"No platform found\");\n    }\n\n    let mut devices = platforms[0].get_devices();\n    if devices.len() == 0 {\n        Err(\"No device found\")\n    } else {\n        let device = devices.remove(0);\n        let context = device.create_context();\n        let queue = context.create_command_queue(&device);\n        Ok((device, context, queue))\n    }\n}\n\n#[derive(Copy, Clone)]\npub enum PreferedType {\n    Any,\n\n    CPUPrefered,\n    GPUPrefered,\n\n    CPUOnly,\n    GPUOnly,\n}\n\npub fn create_compute_context_prefer(cltype: PreferedType) -> Result<(Device, Context, CommandQueue), &'static str>\n{\n    let platforms = get_platforms();\n    for platform in platforms.iter() {\n        let types = match cltype {\n            PreferedType::Any => vec![DeviceType::CPU, DeviceType::GPU],\n            PreferedType::CPUPrefered | PreferedType::CPUOnly => vec![DeviceType::CPU],\n            PreferedType::GPUPrefered | PreferedType::GPUOnly => vec![DeviceType::GPU]\n        };\n\n        let mut devices = platform.get_devices_by_types(&types[..]);\n        if devices.len() > 0 {\n            let device = devices.remove(0);\n            let context = device.create_context();\n            let queue = context.create_command_queue(&device);\n            return Ok((device, context, queue))\n        }\n    }\n\n\n    match cltype {\n        PreferedType::Any |\n        PreferedType::CPUPrefered |\n        PreferedType::GPUPrefered => create_compute_context(),\n        _ => Err(\"Could not find valid implementation\")\n    }\n}\n"
  },
  {
    "path": "tests/test.rs",
    "content": "#![feature(slice_bytes)]\n\n#[macro_use]\nextern crate log;\n\nextern crate opencl;\n\nuse opencl::hl::*;\n\nmacro_rules! expect (\n    ($test: expr, $expected: expr) => ({\n            let test     = $test;\n            let expected = $expected;\n            if test != expected {\n                panic!(format!(\"Test failure in {}:\", // \" expected {}, got {}\",\n                              stringify!($test)/*,\n                              expected, test*/))\n            }\n        }\n    )\n);\n\npub fn test_all_platforms_devices<F>(test: &mut F)\n    where F: FnMut(&Device, &Context, &CommandQueue)\n{\n    let platforms = get_platforms();\n    for p in platforms.iter() {\n        let devices = p.get_devices();\n        for d in devices.iter() {\n            let context = d.create_context();\n            let queue = context.create_command_queue(d);\n            test(d, &context, &queue);\n        }\n    }\n}\n\nmod mem {\n    use std::slice;\n    use opencl::mem::{Read, Write};\n\n    fn read_write<W: Write, R: Read>(src: &W, dst: &mut R)\n    {\n        // find the max size of the input buffer\n        let mut max = 0;\n        src.write(|off, _, len| {\n            if max < off + len {\n                max = off + len;\n            }\n        });\n        let max = max as usize;\n\n        let mut buffer: Vec<u8> = Vec::new();\n        unsafe {\n            buffer.reserve(max);\n            buffer.set_len(max);\n        }\n\n        // copy from input into buffer\n        src.write(|off, ptr, len| {\n            let off = off as usize;\n            let len = len as usize;\n            assert!(buffer.len() >= (off + len) as usize);\n            let target = &mut buffer[off .. off + len];\n            unsafe {\n                let ptr = ptr as *const u8;\n                let src = slice::from_raw_parts(ptr, len);\n                slice::bytes::copy_memory(src, target);\n            }\n        });\n\n        // copy from buffer into output\n        dst.read(|off, ptr, len| {\n            let off = off as usize;\n            let len = len as usize;\n            assert!(buffer.len() >= (off + len) as usize);\n            let src = &buffer[off .. off + len];\n            unsafe {\n                let ptr = ptr as *mut u8;\n                let mut dst = slice::from_raw_parts_mut(ptr, len);\n                slice::bytes::copy_memory(src, dst);\n            }\n        })\n    }\n\n    #[test]\n    fn read_write_slice()\n    {\n        let input: &[isize] = &[0, 1, 2, 3, 4, 5, 6, 7];\n        let mut output: &mut [isize] = &mut [0, 0, 0, 0, 0, 0, 0, 0];\n        read_write(&input, &mut output);\n        expect!(input, output);\n    }\n\n    #[test]\n    fn read_write_int()\n    {\n        let input: isize      = 3141;\n        let mut output: isize = 0;\n        read_write(&input, &mut output);\n        expect!(input, output);\n    }\n\n    #[test]\n    fn read_write_uint()\n    {\n        let input : usize = 3141;\n        let mut output : usize = 0;\n        read_write(&input, &mut output);\n        expect!(input, output);\n    }\n\n    #[test]\n    fn read_write_f32()\n    {\n        let input : f32 = 3141.;\n        let mut output : f32 = 0.;\n        read_write(&input, &mut output);\n        expect!(input, output);\n    }\n\n    #[test]\n    fn read_write_f64()\n    {\n        let input : f64 = 3141.;\n        let mut output : f64 = 0.;\n        read_write(&input, &mut output);\n        expect!(input, output);\n    }\n}\n\n#[cfg(test)]\nmod hl {\n    use opencl::cl::*;\n    use opencl::hl::*;\n    use opencl::mem::*;\n    use opencl::util;\n\n    #[test]\n    fn program_build() {\n        let src = \"__kernel void test(__global int *i) { \\\n                   *i += 1; \\\n                   }\";\n        ::test_all_platforms_devices(&mut |device, ctx, _| {\n            let prog = ctx.create_program_from_source(src);\n            prog.build(device).unwrap();\n        })\n    }\n\n    #[test]\n    fn simple_kernel() {\n        let src = \"__kernel void test(__global int *i) { \\\n                   *i += 1; \\\n                   }\";\n        ::test_all_platforms_devices(&mut |device, ctx, queue| {\n            let prog = ctx.create_program_from_source(src);\n            prog.build(device).unwrap();\n\n            let k = prog.create_kernel(\"test\");\n            let v = ctx.create_buffer_from(vec![1isize], CL_MEM_READ_WRITE);\n\n            k.set_arg(0, &v);\n\n            queue.enqueue_async_kernel(&k, 1isize, None, ()).wait();\n\n            let v: Vec<isize> = queue.get(&v, ());\n\n            expect!(v[0], 2);\n        })\n    }\n\n    #[test]\n    fn add_k() {\n        let src = \"__kernel void test(__global int *i, long int k) { \\\n                   *i += k; \\\n                   }\";\n\n        ::test_all_platforms_devices(&mut |device, ctx, queue| {\n            let prog = ctx.create_program_from_source(src);\n            prog.build(device).unwrap();\n\n            let k = prog.create_kernel(\"test\");\n\n            let v = ctx.create_buffer_from(vec![1isize], CL_MEM_READ_WRITE);\n\n            k.set_arg(0, &v);\n            k.set_arg(1, &42isize);\n\n            queue.enqueue_async_kernel(&k, 1isize, None, ()).wait();\n\n            let v: Vec<isize> = queue.get(&v, ());\n\n            expect!(v[0], 43);\n        })\n    }\n\n    #[test]\n    fn simple_kernel_index() {\n        let src = \"__kernel void test(__global int *i) { \\\n                   *i += 1; \\\n                   }\";\n\n        ::test_all_platforms_devices(&mut |device, ctx, queue| {\n            let prog = ctx.create_program_from_source(src);\n            prog.build(device).unwrap();\n\n            let k = prog.create_kernel(\"test\");\n\n            let v = ctx.create_buffer_from(vec![1isize], CL_MEM_READ_WRITE);\n\n            k.set_arg(0, &v);\n\n            queue.enqueue_async_kernel(&k, 1isize, None, ()).wait();\n\n            let v: Vec<isize> = queue.get(&v, ());\n\n            expect!(v[0], 2);\n        })\n    }\n\n    #[test]\n    fn chain_kernel_event() {\n        let src = \"__kernel void test(__global int *i) { \\\n                   *i += 1; \\\n                   }\";\n\n        ::test_all_platforms_devices(&mut |device, ctx, queue| {\n            let prog = ctx.create_program_from_source(src);\n            prog.build(device).unwrap();\n\n            let k = prog.create_kernel(\"test\");\n            let v = ctx.create_buffer_from(vec![1isize], CL_MEM_READ_WRITE);\n\n            k.set_arg(0, &v);\n\n            let mut e : Option<Event> = None;\n            for _ in 0isize .. 8 {\n                e = Some(queue.enqueue_async_kernel(&k, 1isize, None, e));\n            }\n            e.wait();\n\n            let v: Vec<isize> = queue.get(&v, ());\n\n            expect!(v[0], 9);\n        })\n    }\n\n    #[test]\n    fn chain_kernel_event_list() {\n        let src = \"__kernel void inc(__global int *i) { \\\n                   *i += 1; \\\n                   } \\\n                   __kernel void add(__global int *a, __global int *b, __global int *c) { \\\n                   *c = *a + *b; \\\n                   }\";\n\n        ::test_all_platforms_devices(&mut |device, ctx, queue| {\n            let prog = ctx.create_program_from_source(src);\n            prog.build(device).unwrap();\n\n            let k_inc_a = prog.create_kernel(\"inc\");\n            let k_inc_b = prog.create_kernel(\"inc\");\n            let k_add = prog.create_kernel(\"add\");\n\n            let a = ctx.create_buffer_from(vec![1isize], CL_MEM_READ_WRITE);\n            let b = ctx.create_buffer_from(vec![1isize], CL_MEM_READ_WRITE);\n            let c = ctx.create_buffer_from(vec![1isize], CL_MEM_READ_WRITE);\n\n            k_inc_a.set_arg(0, &a);\n            k_inc_b.set_arg(0, &b);\n\n            let event_list = [\n                queue.enqueue_async_kernel(&k_inc_a, 1isize, None, ()),\n                queue.enqueue_async_kernel(&k_inc_b, 1isize, None, ()),\n            ];\n\n            k_add.set_arg(0, &a);\n            k_add.set_arg(1, &b);\n            k_add.set_arg(2, &c);\n\n            let event = queue.enqueue_async_kernel(&k_add, 1isize, None, &event_list[..]);\n\n            let v: Vec<isize> = queue.get(&c, event);\n\n            expect!(v[0], 4);\n        })\n    }\n\n    #[test]\n    fn kernel_2d()\n    {\n        let src = \"__kernel void test(__global long int *N) { \\\n                   int i = get_global_id(0); \\\n                   int j = get_global_id(1); \\\n                   int s = get_global_size(0); \\\n                   N[i * s + j] = i * j;\n}\";\n        ::test_all_platforms_devices(&mut |device, ctx, queue| {\n            let prog = ctx.create_program_from_source(src);\n\n            match prog.build(device) {\n                Ok(_) => (),\n                Err(build_log) => {\n                    println!(\"Error building program:\\n\");\n                    println!(\"{}\", build_log);\n                    panic!(\"\");\n                }\n            }\n\n            let k = prog.create_kernel(\"test\");\n\n            let v = ctx.create_buffer_from(&[1isize, 2, 3, 4, 5, 6, 7, 8, 9][..], CL_MEM_READ_ONLY);\n\n            k.set_arg(0, &v);\n\n            queue.enqueue_async_kernel(&k, (3isize, 3isize), None, ()).wait();\n\n            let v: Vec<isize> = queue.get(&v, ());\n\n            expect!(v, vec!(0, 0, 0, 0, 1, 2, 0, 2, 4));\n        })\n    }\n\n    #[test]\n    fn memory_read_write()\n    {\n        ::test_all_platforms_devices(&mut |_, ctx, queue| {\n            let buffer: CLBuffer<isize> = ctx.create_buffer(8, CL_MEM_READ_ONLY);\n\n            let input = [0isize, 1, 2, 3, 4, 5, 6, 7];\n            let mut output = [0isize, 0, 0, 0, 0, 0, 0, 0];\n\n            queue.write(&buffer, &&input[..], ());\n            queue.read(&buffer, &mut &mut output[..], ());\n\n            expect!(input, output);\n        })\n    }\n\n    #[test]\n    fn memory_read_vec()\n    {\n        ::test_all_platforms_devices(&mut |_, ctx, queue| {\n            let input = [0isize, 1, 2, 3, 4, 5, 6, 7];\n            let buffer = ctx.create_buffer_from(&input[..], CL_MEM_READ_WRITE);\n            let output: Vec<isize> = queue.get(&buffer, ());\n            expect!(&input[..], &output[..]);\n        })\n    }\n\n\n    #[test]\n    fn memory_read_owned()\n    {\n        ::test_all_platforms_devices(&mut |_, ctx, queue| {\n            let input = vec!(0isize, 1, 2, 3, 4, 5, 6, 7);\n            let buffer = ctx.create_buffer_from(&input, CL_MEM_READ_WRITE);\n            let output: Vec<isize> = queue.get(&buffer, ());\n            expect!(input, output);\n        })\n    }\n\n    #[test]\n    fn memory_read_owned_clone()\n    {\n        ::test_all_platforms_devices(&mut |_, ctx, queue| {\n            let input = vec!(0isize, 1, 2, 3, 4, 5, 6, 7);\n            let buffer = ctx.create_buffer_from(input.clone(), CL_MEM_READ_WRITE);\n            let output: Vec<isize> = queue.get(&buffer, ());\n            expect!(input, output);\n        })\n    }\n\n    #[test]\n    fn event_get_times() {\n        let src = \"__kernel void test(__global int *i) { \\\n                   *i += 1; \\\n                   }\";\n\n        let (device, ctx, queue) = util::create_compute_context().unwrap();\n        let prog = ctx.create_program_from_source(src);\n        prog.build(&device).unwrap();\n\n        let k = prog.create_kernel(\"test\");\n        let v = ctx.create_buffer_from(vec![1isize], CL_MEM_READ_WRITE);\n\n        k.set_arg(0, &v);\n\n        let e = queue.enqueue_async_kernel(&k, 1isize, None, ());\n        e.wait();\n\n        // the that are returned are not useful for unit test, this test\n        // is mostly testing that opencl returns no error\n        e.queue_time();\n        e.submit_time();\n        e.start_time();\n        e.end_time();\n    }\n}\n\n\n#[cfg(test)]\nmod array {\n    use opencl::array::*;\n    use opencl::cl::CL_MEM_READ_WRITE;\n\n    #[test]\n    fn put_get_2d()\n    {\n        ::test_all_platforms_devices(&mut |_, ctx, queue| {\n            let arr_in = Array2D::new(8, 8, |x, y| {(x+y) as isize});\n            let arr_cl = ctx.create_buffer_from(&arr_in, CL_MEM_READ_WRITE);\n            let arr_out: Array2D<isize> = queue.get(&arr_cl, ());\n\n            for x in 0usize.. 8usize {\n                for y in 0usize..8usize {\n                    expect!(arr_in.get(x, y), arr_out.get(x, y));\n                }\n            }\n        })\n    }\n\n\n    #[test]\n    fn read_write_2d()\n    {\n        ::test_all_platforms_devices(&mut |_, ctx, queue| {\n            let added = Array2D::new(8, 8, |x, y| {(x+y) as isize});\n            let zero = Array2D::new(8, 8, |_, _| {(0) as isize});\n            let mut out = Array2D::new(8, 8, |_, _| {(0) as isize});\n\n            /* both are zeroed */\n            let a_cl = ctx.create_buffer_from(&zero, CL_MEM_READ_WRITE);\n\n            queue.write(&a_cl, &added, ());\n            queue.read(&a_cl, &mut out, ());\n\n            for x in 0usize .. 8usize {\n                for y in 0usize .. 8usize {\n                    expect!(added.get(x, y), out.get(x, y));\n                }\n            }\n        })\n    }\n\n\n    #[test]\n    fn kernel_2d()\n    {\n        ::test_all_platforms_devices(&mut |device, ctx, queue| {\n            let mut a = Array2D::new(8, 8, |_, _| {(0) as i32});\n            let b = Array2D::new(8, 8, |x, y| {(x*y) as i32});\n            let a_cl = ctx.create_buffer_from(&a, CL_MEM_READ_WRITE);\n\n            let src =  \"__kernel void test(__global int *a) { \\\n                            int x = get_global_id(0); \\\n                            int y = get_global_id(1); \\\n                            int size_x = get_global_size(0); \\\n                            a[size_x*y + x] = x*y; \\\n                        }\";\n            let prog = ctx.create_program_from_source(src);\n            match prog.build(device) {\n                Ok(_) => (),\n                Err(build_log) => {\n                    println!(\"Error building program:\\n\");\n                    println!(\"{}\", build_log);\n                    panic!(\"\");\n                }\n            }\n            let k = prog.create_kernel(\"test\");\n\n            k.set_arg(0, &a_cl);\n            let event = queue.enqueue_async_kernel(&k, (8isize, 8isize), None, ());\n            queue.read(&a_cl, &mut a, &event);\n\n            for x in 0usize .. 8usize {\n                for y in 0usize .. 8usize {\n                    expect!(a.get(x, y), b.get(x, y));\n                }\n            }\n        })\n    }\n\n    #[test]\n    fn put_get_3d()\n    {\n        ::test_all_platforms_devices(&mut |_, ctx, queue| {\n            let arr_in = Array3D::new(8, 8, 8, |x, y, z| {(x+y+z) as isize});\n            let arr_cl = ctx.create_buffer_from(&arr_in, CL_MEM_READ_WRITE);\n            let arr_out: Array3D<isize> = queue.get(&arr_cl, ());\n\n            for x in 0usize .. 8usize {\n                for y in 0usize .. 8usize {\n                    for z in 0usize .. 8usize {\n                        expect!(arr_in.get(x, y, z), arr_out.get(x, y, z));\n                    }\n                }\n            }\n        })\n    }\n\n\n    #[test]\n    fn read_write_3d()\n    {\n        ::test_all_platforms_devices(&mut |_, ctx, queue| {\n            let added = Array3D::new(8, 8, 8, |x, y, z| {(x+y+z) as isize});\n            let zero = Array3D::new(8, 8, 8, |_, _, _| {(0) as isize});\n            let mut out = Array3D::new(8, 8, 8, |_, _, _| {(0) as isize});\n\n            /* both are zeroed */\n            let a_cl = ctx.create_buffer_from(&zero, CL_MEM_READ_WRITE);\n\n            queue.write(&a_cl, &added, ());\n            queue.read(&a_cl, &mut out, ());\n\n            for x in 0usize .. 8usize {\n                for y in 0usize .. 8usize {\n                    for z in 0usize .. 8usize {\n                        expect!(added.get(x, y, z), out.get(x, y, z));\n                    }\n                }\n            }\n        })\n    }\n\n\n    #[test]\n    fn kernel_3d()\n    {\n        ::test_all_platforms_devices(&mut |device, ctx, queue| {\n            let mut a = Array3D::new(8, 8, 8, |_, _, _| {(0) as i32});\n            let b = Array3D::new(8, 8, 8, |x, y, z| {(x*y*z) as i32});\n            let a_cl = ctx.create_buffer_from(&a, CL_MEM_READ_WRITE);\n\n            let src =  \"__kernel void test(__global int *a) { \\\n                            int x = get_global_id(0); \\\n                            int y = get_global_id(1); \\\n                            int z = get_global_id(2); \\\n                            int size_x = get_global_size(0); \\\n                            int size_y = get_global_size(1); \\\n                            a[size_x*size_y*z + size_x*y + x] = x*y*z; \\\n                        }\";\n            let prog = ctx.create_program_from_source(src);\n            match prog.build(device) {\n                Ok(_) => (),\n                Err(build_log) => {\n                    println!(\"Error building program:\\n\");\n                    println!(\"{}\", build_log);\n                    panic!(\"\");\n                }\n            }\n            let k = prog.create_kernel(\"test\");\n\n            k.set_arg(0, &a_cl);\n            let event = queue.enqueue_async_kernel(&k, (8isize, 8isize, 8isize), None, ());\n            queue.read(&a_cl, &mut a, &event);\n\n            for x in 0usize .. 8usize {\n                for y in 0usize .. 8usize {\n                    for z in 0usize .. 8usize {\n                        expect!(a.get(x, y, z), b.get(x, y, z));\n                    }\n                }\n            }\n        })\n    }\n}\n\n#[cfg(test)]\nmod ext {\n    use opencl::ext;\n    use opencl::hl::*;\n\n    #[test]\n    fn try_load_all_extensions() {\n        let platforms = get_platforms();\n\n        for platform in platforms.into_iter() {\n            let platform_id = platform.get_id();\n\n            macro_rules! check_ext {\n                ($ext:ident) => {\n                    match ext::$ext::load(platform_id) {\n                        Ok(_) => {\n                            info!(\"Extension {} loaded successfully.\",\n                                  stringify!($ext))\n                        }\n                        Err(_) => {\n                            info!(\"Error loading extension {}.\",\n                                  stringify!($ext))\n                        }\n                    }\n                }\n            }\n\n            check_ext!(cl_khr_fp64);\n            check_ext!(cl_khr_fp16);\n            check_ext!(cl_APPLE_SetMemObjectDestructor);\n            check_ext!(cl_APPLE_ContextLoggingFunctions);\n            check_ext!(cl_khr_icd);\n            check_ext!(cl_nv_device_attribute_query);\n            check_ext!(cl_amd_device_attribute_query);\n            check_ext!(cl_arm_printf);\n            check_ext!(cl_ext_device_fission);\n            check_ext!(cl_qcom_ext_host_ptr);\n            check_ext!(cl_qcom_ion_host_ptr);\n        }\n    }\n}\n\n#[cfg(test)]\nmod cl {\n    use opencl::cl::CLStatus::*;\n\n    #[test]\n    fn clstatus_str() {\n        let x = CL_SUCCESS;\n        expect!(format!(\"{}\", x), \"CL_SUCCESS\");\n\n        let y = CL_DEVICE_NOT_FOUND;\n        expect!(y.to_string(), \"CL_DEVICE_NOT_FOUND\");\n    }\n}\n"
  }
]