Merge pull request #44 from b-sumner/master

Add cl_amd_planar_yuv extension
diff --git a/index.php b/index.php
index 4a7eefe..ea6419d 100644
--- a/index.php
+++ b/index.php
@@ -4,16 +4,16 @@
 include_once("../../assets/static_pages/khr_page_top.php");
 ?>
 
-<p> The OpenCL registry contains specifications of the core API and the
-    OpenCL C language; a portable intermediate representation of OpenCL
-    programs; specifications of Khronos- and vendor-approved OpenCL
-    extensions; reference pages for different OpenCL versions; and links to
-    header files corresponding to the specifications, which are now hosted
-    in the <a href="https://www.github.com/KhronosGroup/OpenCL-Headers/">
-    OpenCL-Headers </a> Github repository. </p>
+<p> The OpenCL registry contains specifications for the core API; Khronos-
+    and vendor-approved extensions to the core API; the OpenCL C and C++
+    languages; and the OpenCL SPIR-V Environment.
 
-<p> The OpenCL Standard Portable Intermediate Representation (SPIR) is
-    found in the <a href="../spir/">SPIR Registry</a>. </p>
+<p> In addition, it contains reference pages for different OpenCL versions,
+    and links to the github repository containing unified header files
+    corresponding to the Specifications. </p>
+
+<p> The OpenCL Standard Portable Intermediate Representation (SPIR)
+    specification is found in the <a href="../spir/">SPIR Registry</a>. </p>
 
 <p> The SYCL specification is found in the <a href="../sycl/">SYCL
     Registry</a>. </p>
@@ -23,31 +23,42 @@
     href="https://github.com/KhronosGroup/OpenCL-Registry/"> OpenCL-Registry
     </a> Github repository. </li>
 
-<h6> OpenCL Core API and C Language Specification, Headers, and Documentation </h6>
+<h6> OpenCL Specifications and Related Documentation </h6>
 
 <p> The current version of OpenCL is OpenCL 2.2. </p>
 
-<p> The asciidoc source for the OpenCL 2.2 Specifications is available in
+<p> The asciidoctor source for the OpenCL 2.2 Specifications is available in
     the <a href="https://github.com/KhronosGroup/OpenCL-Docs">
     KhronosGroup/OpenCL-Docs </a> Github repository. </p>
 
 <ul>
 <li> OpenCL 2.2 API Specification
-     (<a href="specs/opencl-2.2.pdf">PDF</a>)
-     (<a href="specs/opencl-2.2.html">HTML</a>)
-     (May 12, 2017). </li>
+     (<a href="specs/2.2/html/OpenCL_API.html">HTML</a>)
+     (<a href="specs/2.2/pdf/OpenCL_API.pdf">PDF</a>)
+     (May 12, 2018). </li>
 <li> OpenCL 2.2 Extension Specification
-     (<a href="specs/opencl-2.2-extension.pdf">PDF</a>)
-     (<a href="specs/opencl-2.2-extension.html">HTML</a>)
-     (May 12, 2017). </li>
+     (<a href="specs/2.2/html/OpenCL_Ext.html">HTML</a>)
+     (<a href="specs/2.2/pdf/OpenCL_Ext.pdf">PDF</a>)
+     (May 12, 2018). </li>
 <li> OpenCL 2.2 SPIR-V Environment Specification
-     (<a href="specs/opencl-2.2-environment.pdf">PDF</a>)
-     (<a href="specs/opencl-2.2-environment.html">HTML</a>)
-     (May 12, 2017). </li>
+     (<a href="specs/2.2/html/OpenCL_Env.html">HTML</a>)
+     (<a href="specs/2.2/pdf/OpenCL_Env.pdf">PDF</a>)
+     (May 12, 2018). </li>
+<li> OpenCL C Language Specification
+     (<a href="specs/2.2/html/OpenCL_C.html">HTML</a>)
+     (<a href="specs/2.2/pdf/OpenCL_C.pdf">PDF</a>)
+     (May 12, 2018). </li>
 <li> OpenCL C++ Language Specification
-     (<a href="specs/opencl-2.2-cplusplus.pdf">PDF</a>)
-     (<a href="specs/opencl-2.2-cplusplus.html">HTML</a>)
-     (May 12, 2017). </li>
+     (<a href="specs/2.2/html/OpenCL_Cxx.html">HTML</a>)
+     (<a href="specs/2.2/pdf/OpenCL_Cxx.pdf">PDF</a>)
+     (May 12, 2018). </li>
+<li> OpenCL ICD Installation Guide Specification
+     (<a href="specs/2.2/html/OpenCL_ICD_Installation.html">HTML</a>)
+     (<a href="specs/2.2/pdf/OpenCL_ICD_Installation.pdf">PDF</a>)
+     (May 12, 2018). </li>
+<li> The <a href="https://www.khronos.org/registry/spir-v/"> OpenCL Extended
+     Instruction Set for SPIR-V</a> is included as part of the SPIR-V
+     registry.
 <li> The OpenCL 2.2 Reference Pages are not posted yet. </li>
      <!--
      <a href="http://www.khronos.org/registry/cl/sdk/2.2/docs/man/xhtml/">
@@ -58,6 +69,21 @@
      -->
 <li> <a href="https://www.khronos.org/files/opencl22-reference-guide.pdf">
      OpenCL 2.2 Reference Guide.</a> </li>
+</ul>
+
+<h6> OpenCL Header Files </h6>
+
+<p> C language header files for the OpenCL API are found in the <a
+    href="https://github.com/KhronosGroup/OpenCL-Headers">
+    KhronosGroup/OpenCL-Headers</a> Github repository. In the past, there
+    were different header files for each OpenCL version. The header files
+    have now been unified - a single set of headers supports all OpenCL API
+    versions - and the API version defined by the headers at compilation
+    time is determined as described in the README.md in that repository.
+    </a>
+
+    <!--
+<ul>
 <li> All of the following headers should be present in a directory
      <tt> CL/ </tt> (or <tt> OpenCL/ </tt> on MacOS X). The single
      header file <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl22/CL/opencl.h"> opencl.h </a> includes
@@ -88,10 +114,8 @@
      <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl22/CL/cl_gl_ext.h"> cl_gl_ext.h </a> -
           OpenCL 2.2 Vendor OpenCL/OpenGL Extensions Header File. </li>
      </li>
-<li> The <a href="https://www.khronos.org/registry/spir-v/"> OpenCL Extended
-     Instruction Set for SPIR-V</a> is included as part of the SPIR-V
-     registry.
 </ul>
+    -->
 
 
 <h6> OpenCL ICD and C++ Bindings Headers </h6>
@@ -137,36 +161,6 @@
      OpenCL 2.1 Reference Pages.</a>
 <li> <a href="http://www.khronos.org/registry/cl/sdk/2.1/docs/OpenCL-2.1-refcard.pdf">
      OpenCL 2.1 Quick Reference Card.</a> </li>
-<li> All of the following headers should be present in a directory
-     <tt> CL/ </tt> (or <tt> OpenCL/ </tt> on MacOS X). The single
-     header file <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl21/CL/opencl.h"> opencl.h </a> includes
-     other headers as appropriate for the target platform, and simply
-     including <tt> opencl.h </tt> should be all that most applications
-     need to do.
-
-     <ul>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl21/CL/opencl.h"> opencl.h </a> -
-          OpenCL 2.1 Single Header File for Applications. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl21/CL/cl_platform.h"> cl_platform.h </a> -
-          OpenCL 2.1 Platform-Dependent Macros. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl21/CL/cl.h"> cl.h </a> -
-          OpenCL 2.1 Core API Header File. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl21/CL/cl_ext.h"> cl_ext.h </a> -
-          OpenCL 2.1 Extensions Header File. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl21/CL/cl_egl.h"> cl_egl.h </a> -
-          OpenCL 2.1 Khronos EGL Extensions Header File. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl21/CL/cl_dx9_media_sharing.h"> cl_dx9_media_sharing.h </a> -
-          OpenCL 2.1 Khronos OpenCL/Direct3D 9 Media Sharing Extensions
-          Header File. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl21/CL/cl_d3d10.h"> cl_d3d10.h </a> -
-          OpenCL 2.1 Khronos OpenCL/Direct3D 10 Extensions Header File. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl21/CL/cl_d3d11.h"> cl_d3d11.h </a> -
-          OpenCL 2.1 Khronos OpenCL/Direct3D 11 Extensions Header File. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl21/CL/cl_gl.h"> cl_gl.h </a> -
-          OpenCL 2.1 Khronos OpenCL/OpenGL Extensions Header File. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl21/CL/cl_gl_ext.h"> cl_gl_ext.h </a> -
-          OpenCL 2.1 Vendor OpenCL/OpenGL Extensions Header File. </li>
-     </ul> </li>
 </ul>
 
 <h6> OpenCL 2.0 </h6>
@@ -185,32 +179,6 @@
      OpenCL 2.0 Reference Pages.</a>
 <li> <a href="http://www.khronos.org/registry/cl/sdk/2.0/docs/OpenCL-2.0-refcard.pdf">
      OpenCL 2.0 Quick Reference Card.</a> </li>
-<li> OpenCL 2.0 headers are structured in exactly the same fashion as
-     OpenCL 2.0 headers described above.
-
-     <ul>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl20/CL/opencl.h"> opencl.h </a> -
-          OpenCL 2.0 Single Header File for Applications. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl20/CL/cl_platform.h"> cl_platform.h </a> -
-          OpenCL 2.0 Platform-Dependent Macros. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl20/CL/cl.h"> cl.h </a> -
-          OpenCL 2.0 Core API Header File. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl20/CL/cl_ext.h"> cl_ext.h </a> -
-          OpenCL 2.0 Extensions Header File. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl20/CL/cl_egl.h"> cl_egl.h </a> -
-          OpenCL 2.0 Khronos EGL Extensions Header File. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl20/CL/cl_dx9_media_sharing.h"> cl_dx9_media_sharing.h </a> -
-          OpenCL 2.0 Khronos OpenCL/Direct3D 9 Media Sharing Extensions
-          Header File. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl20/CL/cl_d3d10.h"> cl_d3d10.h </a> -
-          OpenCL 2.0 Khronos OpenCL/Direct3D 10 Extensions Header File. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl20/CL/cl_d3d11.h"> cl_d3d11.h </a> -
-          OpenCL 2.0 Khronos OpenCL/Direct3D 11 Extensions Header File. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl20/CL/cl_gl.h"> cl_gl.h </a> -
-          OpenCL 2.0 Khronos OpenCL/OpenGL Extensions Header File. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl20/CL/cl_gl_ext.h"> cl_gl_ext.h </a> -
-          OpenCL 2.0 Vendor OpenCL/OpenGL Extensions Header File. </li>
-     </ul> </li>
 </ul>
 
 <h6> OpenCL 1.2 </h6>
@@ -226,32 +194,6 @@
      OpenCL 1.2 Reference Pages.</a>
 <li> <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/OpenCL-1.2-refcard.pdf">
      OpenCL 1.2 Quick Reference Card.</a> </li>
-<li> OpenCL 1.2 headers are structured in exactly the same fashion as
-     OpenCL 2.1 headers described above.
-
-     <ul>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl12/CL/opencl.h"> opencl.h </a> -
-          OpenCL 1.2 Single Header File for Applications. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl12/CL/cl_platform.h"> cl_platform.h </a> -
-          OpenCL 1.2 Platform-Dependent Macros. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl12/CL/cl.h"> cl.h </a> -
-          OpenCL 1.2 Core API Header File. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl12/CL/cl_ext.h"> cl_ext.h </a> -
-          OpenCL 1.2 Extensions Header File. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl12/CL/cl_egl.h"> cl_egl.h </a> -
-          OpenCL 1.2 Khronos EGL Extensions Header File. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl12/CL/cl_dx9_media_sharing.h"> cl_dx9_media_sharing.h </a> -
-          OpenCL 1.2 Khronos OpenCL/Direct3D 9 Media Sharing Extensions
-          Header File. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl12/CL/cl_d3d10.h"> cl_d3d10.h </a> -
-          OpenCL 1.2 Khronos OpenCL/Direct3D 10 Extensions Header File. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl12/CL/cl_d3d11.h"> cl_d3d11.h </a> -
-          OpenCL 1.2 Khronos OpenCL/Direct3D 11 Extensions Header File. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl12/CL/cl_gl.h"> cl_gl.h </a> -
-          OpenCL 1.2 Khronos OpenCL/OpenGL Extensions Header File. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl12/CL/cl_gl_ext.h"> cl_gl_ext.h </a> -
-          OpenCL 1.2 Vendor OpenCL/OpenGL Extensions Header File. </li>
-     </ul> </li>
 </ul>
 
 <h6> OpenCL 1.1 </h6>
@@ -268,25 +210,6 @@
      OpenCL 1.1 Reference Pages.</a> </li>
 <li> <a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/OpenCL-1.1-refcard.pdf">
      OpenCL 1.1 Reference Card.</a> </li>
-<li> OpenCL 1.1 headers are structured in exactly the same fashion as
-     OpenCL 2.1 headers described above.
-
-     <ul>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl11/CL/opencl.h"> opencl.h </a> -
-          OpenCL 1.1 Single Header File for Applications. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl11/CL/cl_platform.h"> cl_platform.h </a> -
-          OpenCL 1.1 Platform-Dependent Macros. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl11/CL/cl.h"> cl.h </a> -
-          OpenCL 1.1 Core API Header File. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl11/CL/cl_ext.h"> cl_ext.h </a> -
-          OpenCL 1.1 Extensions Header File. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl11/CL/cl_d3d10.h"> cl_d3d10.h </a> -
-          OpenCL 1.1 Khronos OpenCL/Direct3D 10 Extensions Header File. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl11/CL/cl_gl.h"> cl_gl.h </a> -
-          OpenCL 1.1 Khronos OpenCL/OpenGL Extensions Header File. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl11/CL/cl_gl_ext.h"> cl_gl_ext.h </a> -
-          OpenCL 1.1 Vendor OpenCL/OpenGL Extensions Header File. </li>
-     </ul> </li>
 </ul>
 
 <h6> OpenCL 1.0 </h6>
@@ -299,25 +222,6 @@
      OpenCL 1.0 Reference Pages.</a> </li>
 <li> <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/OpenCL-1.0-refcard.pdf">
      OpenCL 1.0 Reference Card.</a> </li>
-<li> OpenCL 1.0 headers are structured in exactly the same fashion as
-     OpenCL 2.1 headers described above.
-
-     <ul>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl10/CL/opencl.h"> opencl.h </a> -
-          OpenCL 1.0 Single Header File for Applications. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl10/CL/cl_platform.h"> cl_platform.h </a> -
-          OpenCL 1.0 Platform-Dependent Macros. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl10/CL/cl.h"> cl.h </a> -
-          OpenCL 1.0 Core API Header File. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl10/CL/cl_ext.h"> cl_ext.h </a> -
-          OpenCL 1.0 Extensions Header File. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl10/CL/cl_d3d10.h"> cl_d3d10.h </a> -
-          OpenCL 1.0 Khronos OpenCL/Direct3D 10 Extensions Header File. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl10/CL/cl_gl.h"> cl_gl.h </a> -
-          OpenCL 1.0 Khronos OpenCL/OpenGL Extensions Header File. </li>
-     <li> <a href="https://raw.githubusercontent.com/KhronosGroup/OpenCL-Headers/master/opencl10/CL/cl_gl_ext.h"> cl_gl_ext.h </a> -
-          OpenCL 1.0 Vendor OpenCL/OpenGL Extensions Header File. </li>
-     </ul> </li>
 </ul>
 
 <h6> Providing Feedback on the Registry </h6>
diff --git a/specs/2.2/html/OpenCL_API.html b/specs/2.2/html/OpenCL_API.html
new file mode 100644
index 0000000..afc7d01
--- /dev/null
+++ b/specs/2.2/html/OpenCL_API.html
@@ -0,0 +1,21451 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<meta name="generator" content="Asciidoctor 1.5.6.1">
+<meta name="author" content="Khronos OpenCL Working Group">
+<title>The OpenCL&#8482; Specification</title>
+<style>
+/*! normalize.css v2.1.2 | MIT License | git.io/normalize */
+/* ========================================================================== HTML5 display definitions ========================================================================== */
+/** Correct `block` display not defined in IE 8/9. */
+article, aside, details, figcaption, figure, footer, header, hgroup, main, nav, section, summary { display: block; }
+
+/** Correct `inline-block` display not defined in IE 8/9. */
+audio, canvas, video { display: inline-block; }
+
+/** Prevent modern browsers from displaying `audio` without controls. Remove excess height in iOS 5 devices. */
+audio:not([controls]) { display: none; height: 0; }
+
+/** Address `[hidden]` styling not present in IE 8/9. Hide the `template` element in IE, Safari, and Firefox < 22. */
+[hidden], template { display: none; }
+
+script { display: none !important; }
+
+/* ========================================================================== Base ========================================================================== */
+/** 1. Set default font family to sans-serif. 2. Prevent iOS text size adjust after orientation change, without disabling user zoom. */
+html { font-family: sans-serif; /* 1 */ -ms-text-size-adjust: 100%; /* 2 */ -webkit-text-size-adjust: 100%; /* 2 */ }
+
+/** Remove default margin. */
+body { margin: 0; }
+
+/* ========================================================================== Links ========================================================================== */
+/** Remove the gray background color from active links in IE 10. */
+a { background: transparent; }
+
+/** Address `outline` inconsistency between Chrome and other browsers. */
+a:focus { outline: thin dotted; }
+
+/** Improve readability when focused and also mouse hovered in all browsers. */
+a:active, a:hover { outline: 0; }
+
+/* ========================================================================== Typography ========================================================================== */
+/** Address variable `h1` font-size and margin within `section` and `article` contexts in Firefox 4+, Safari 5, and Chrome. */
+h1 { font-size: 2em; margin: 0.67em 0; }
+
+/** Address styling not present in IE 8/9, Safari 5, and Chrome. */
+abbr[title] { border-bottom: 1px dotted; }
+
+/** Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome. */
+b, strong { font-weight: bold; }
+
+/** Address styling not present in Safari 5 and Chrome. */
+dfn { font-style: italic; }
+
+/** Address differences between Firefox and other browsers. */
+hr { -moz-box-sizing: content-box; box-sizing: content-box; height: 0; }
+
+/** Address styling not present in IE 8/9. */
+mark { background: #ff0; color: #000; }
+
+/** Correct font family set oddly in Safari 5 and Chrome. */
+code, kbd, pre, samp { font-family: monospace, serif; font-size: 1em; }
+
+/** Improve readability of pre-formatted text in all browsers. */
+pre { white-space: pre-wrap; }
+
+/** Set consistent quote types. */
+q { quotes: "\201C" "\201D" "\2018" "\2019"; }
+
+/** Address inconsistent and variable font size in all browsers. */
+small { font-size: 80%; }
+
+/** Prevent `sub` and `sup` affecting `line-height` in all browsers. */
+sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }
+
+sup { top: -0.5em; }
+
+sub { bottom: -0.25em; }
+
+/* ========================================================================== Embedded content ========================================================================== */
+/** Remove border when inside `a` element in IE 8/9. */
+img { border: 0; }
+
+/** Correct overflow displayed oddly in IE 9. */
+svg:not(:root) { overflow: hidden; }
+
+/* ========================================================================== Figures ========================================================================== */
+/** Address margin not present in IE 8/9 and Safari 5. */
+figure { margin: 0; }
+
+/* ========================================================================== Forms ========================================================================== */
+/** Define consistent border, margin, and padding. */
+fieldset { border: 1px solid #c0c0c0; margin: 0 2px; padding: 0.35em 0.625em 0.75em; }
+
+/** 1. Correct `color` not being inherited in IE 8/9. 2. Remove padding so people aren't caught out if they zero out fieldsets. */
+legend { border: 0; /* 1 */ padding: 0; /* 2 */ }
+
+/** 1. Correct font family not being inherited in all browsers. 2. Correct font size not being inherited in all browsers. 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome. */
+button, input, select, textarea { font-family: inherit; /* 1 */ font-size: 100%; /* 2 */ margin: 0; /* 3 */ }
+
+/** Address Firefox 4+ setting `line-height` on `input` using `!important` in the UA stylesheet. */
+button, input { line-height: normal; }
+
+/** Address inconsistent `text-transform` inheritance for `button` and `select`. All other form control elements do not inherit `text-transform` values. Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+. Correct `select` style inheritance in Firefox 4+ and Opera. */
+button, select { text-transform: none; }
+
+/** 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` and `video` controls. 2. Correct inability to style clickable `input` types in iOS. 3. Improve usability and consistency of cursor style between image-type `input` and others. */
+button, html input[type="button"], input[type="reset"], input[type="submit"] { -webkit-appearance: button; /* 2 */ cursor: pointer; /* 3 */ }
+
+/** Re-set default cursor for disabled elements. */
+button[disabled], html input[disabled] { cursor: default; }
+
+/** 1. Address box sizing set to `content-box` in IE 8/9. 2. Remove excess padding in IE 8/9. */
+input[type="checkbox"], input[type="radio"] { box-sizing: border-box; /* 1 */ padding: 0; /* 2 */ }
+
+/** 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome (include `-moz` to future-proof). */
+input[type="search"] { -webkit-appearance: textfield; /* 1 */ -moz-box-sizing: content-box; -webkit-box-sizing: content-box; /* 2 */ box-sizing: content-box; }
+
+/** Remove inner padding and search cancel button in Safari 5 and Chrome on OS X. */
+input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; }
+
+/** Remove inner padding and border in Firefox 4+. */
+button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; }
+
+/** 1. Remove default vertical scrollbar in IE 8/9. 2. Improve readability and alignment in all browsers. */
+textarea { overflow: auto; /* 1 */ vertical-align: top; /* 2 */ }
+
+/* ========================================================================== Tables ========================================================================== */
+/** Remove most spacing between table cells. */
+table { border-collapse: collapse; border-spacing: 0; }
+
+meta.foundation-mq-small { font-family: "only screen and (min-width: 768px)"; width: 768px; }
+
+meta.foundation-mq-medium { font-family: "only screen and (min-width:1280px)"; width: 1280px; }
+
+meta.foundation-mq-large { font-family: "only screen and (min-width:1440px)"; width: 1440px; }
+
+*, *:before, *:after { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; }
+
+html, body { font-size: 100%; }
+
+body { background: white; color: #222222; padding: 0; margin: 0; font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; font-weight: normal; font-style: normal; line-height: 1; position: relative; cursor: auto; }
+
+a:hover { cursor: pointer; }
+
+img, object, embed { max-width: 100%; height: auto; }
+
+object, embed { height: 100%; }
+
+img { -ms-interpolation-mode: bicubic; }
+
+#map_canvas img, #map_canvas embed, #map_canvas object, .map_canvas img, .map_canvas embed, .map_canvas object { max-width: none !important; }
+
+.left { float: left !important; }
+
+.right { float: right !important; }
+
+.text-left { text-align: left !important; }
+
+.text-right { text-align: right !important; }
+
+.text-center { text-align: center !important; }
+
+.text-justify { text-align: justify !important; }
+
+.hide { display: none; }
+
+.antialiased { -webkit-font-smoothing: antialiased; }
+
+img { display: inline-block; vertical-align: middle; }
+
+textarea { height: auto; min-height: 50px; }
+
+select { width: 100%; }
+
+object, svg { display: inline-block; vertical-align: middle; }
+
+.center { margin-left: auto; margin-right: auto; }
+
+.spread { width: 100%; }
+
+p.lead, .paragraph.lead > p, #preamble > .sectionbody > .paragraph:first-of-type p { font-size: 1.21875em; line-height: 1.6; }
+
+.subheader, .admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { line-height: 1.4; color: black; font-weight: 300; margin-top: 0.2em; margin-bottom: 0.5em; }
+
+/* Typography resets */
+div, dl, dt, dd, ul, ol, li, h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6, pre, form, p, blockquote, th, td { margin: 0; padding: 0; direction: ltr; }
+
+/* Default Link Styles */
+a { color: #0068b0; text-decoration: none; line-height: inherit; }
+a:hover, a:focus { color: #333333; }
+a img { border: none; }
+
+/* Default paragraph styles */
+p { font-family: Noto, sans-serif; font-weight: normal; font-size: 1em; line-height: 1.6; margin-bottom: 0.75em; text-rendering: optimizeLegibility; }
+p aside { font-size: 0.875em; line-height: 1.35; font-style: italic; }
+
+/* Default header styles */
+h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { font-family: Noto, sans-serif; font-weight: normal; font-style: normal; color: black; text-rendering: optimizeLegibility; margin-top: 0.5em; margin-bottom: 0.5em; line-height: 1.2125em; }
+h1 small, h2 small, h3 small, #toctitle small, .sidebarblock > .content > .title small, h4 small, h5 small, h6 small { font-size: 60%; color: #4d4d4d; line-height: 0; }
+
+h1 { font-size: 2.125em; }
+
+h2 { font-size: 1.6875em; }
+
+h3, #toctitle, .sidebarblock > .content > .title { font-size: 1.375em; }
+
+h4 { font-size: 1.125em; }
+
+h5 { font-size: 1.125em; }
+
+h6 { font-size: 1em; }
+
+hr { border: solid #dddddd; border-width: 1px 0 0; clear: both; margin: 1.25em 0 1.1875em; height: 0; }
+
+/* Helpful Typography Defaults */
+em, i { font-style: italic; line-height: inherit; }
+
+strong, b { font-weight: bold; line-height: inherit; }
+
+small { font-size: 60%; line-height: inherit; }
+
+code { font-family: Consolas, "Liberation Mono", Courier, monospace; font-weight: normal; color: #264357; }
+
+/* Lists */
+ul, ol, dl { font-size: 1em; line-height: 1.6; margin-bottom: 0.75em; list-style-position: outside; font-family: Noto, sans-serif; }
+
+ul, ol { margin-left: 1.5em; }
+ul.no-bullet, ol.no-bullet { margin-left: 1.5em; }
+
+/* Unordered Lists */
+ul li ul, ul li ol { margin-left: 1.25em; margin-bottom: 0; font-size: 1em; /* Override nested font-size change */ }
+ul.square li ul, ul.circle li ul, ul.disc li ul { list-style: inherit; }
+ul.square { list-style-type: square; }
+ul.circle { list-style-type: circle; }
+ul.disc { list-style-type: disc; }
+ul.no-bullet { list-style: none; }
+
+/* Ordered Lists */
+ol li ul, ol li ol { margin-left: 1.25em; margin-bottom: 0; }
+
+/* Definition Lists */
+dl dt { margin-bottom: 0.3em; font-weight: bold; }
+dl dd { margin-bottom: 0.75em; }
+
+/* Abbreviations */
+abbr, acronym { text-transform: uppercase; font-size: 90%; color: black; border-bottom: 1px dotted #dddddd; cursor: help; }
+
+abbr { text-transform: none; }
+
+/* Blockquotes */
+blockquote { margin: 0 0 0.75em; padding: 0.5625em 1.25em 0 1.1875em; border-left: 1px solid #dddddd; }
+blockquote cite { display: block; font-size: 0.8125em; color: #5e93b8; }
+blockquote cite:before { content: "\2014 \0020"; }
+blockquote cite a, blockquote cite a:visited { color: #5e93b8; }
+
+blockquote, blockquote p { line-height: 1.6; color: #333333; }
+
+/* Microformats */
+.vcard { display: inline-block; margin: 0 0 1.25em 0; border: 1px solid #dddddd; padding: 0.625em 0.75em; }
+.vcard li { margin: 0; display: block; }
+.vcard .fn { font-weight: bold; font-size: 0.9375em; }
+
+.vevent .summary { font-weight: bold; }
+.vevent abbr { cursor: auto; text-decoration: none; font-weight: bold; border: none; padding: 0 0.0625em; }
+
+@media only screen and (min-width: 768px) { h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { line-height: 1.4; }
+  h1 { font-size: 2.75em; }
+  h2 { font-size: 2.3125em; }
+  h3, #toctitle, .sidebarblock > .content > .title { font-size: 1.6875em; }
+  h4 { font-size: 1.4375em; } }
+/* Tables */
+table { background: white; margin-bottom: 1.25em; border: solid 1px #d8d8ce; }
+table thead, table tfoot { background: -webkit-linear-gradient(top, #add386, #90b66a); font-weight: bold; }
+table thead tr th, table thead tr td, table tfoot tr th, table tfoot tr td { padding: 0.5em 0.625em 0.625em; font-size: inherit; color: white; text-align: left; }
+table tr th, table tr td { padding: 0.5625em 0.625em; font-size: inherit; color: #6d6e71; }
+table tr.even, table tr.alt, table tr:nth-of-type(even) { background: #edf2f2; }
+table thead tr th, table tfoot tr th, table tbody tr td, table tr td, table tfoot tr td { display: table-cell; line-height: 1.4; }
+
+body { -moz-osx-font-smoothing: grayscale; -webkit-font-smoothing: antialiased; tab-size: 4; }
+
+h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { line-height: 1.4; }
+
+a:hover, a:focus { text-decoration: underline; }
+
+.clearfix:before, .clearfix:after, .float-group:before, .float-group:after { content: " "; display: table; }
+.clearfix:after, .float-group:after { clear: both; }
+
+*:not(pre) > code { font-size: inherit; font-style: normal !important; letter-spacing: 0; padding: 0; background-color: white; -webkit-border-radius: 0; border-radius: 0; line-height: inherit; word-wrap: break-word; }
+*:not(pre) > code.nobreak { word-wrap: normal; }
+*:not(pre) > code.nowrap { white-space: nowrap; }
+
+pre, pre > code { line-height: 1.6; color: #264357; font-family: Consolas, "Liberation Mono", Courier, monospace; font-weight: normal; }
+
+em em { font-style: normal; }
+
+strong strong { font-weight: normal; }
+
+.keyseq { color: #333333; }
+
+kbd { font-family: Consolas, "Liberation Mono", Courier, monospace; display: inline-block; color: black; font-size: 0.65em; line-height: 1.45; background-color: #f7f7f7; border: 1px solid #ccc; -webkit-border-radius: 3px; border-radius: 3px; -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 0.1em white inset; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 0.1em white inset; margin: 0 0.15em; padding: 0.2em 0.5em; vertical-align: middle; position: relative; top: -0.1em; white-space: nowrap; }
+
+.keyseq kbd:first-child { margin-left: 0; }
+
+.keyseq kbd:last-child { margin-right: 0; }
+
+.menuseq, .menuref { color: #000; }
+
+.menuseq b:not(.caret), .menuref { font-weight: inherit; }
+
+.menuseq { word-spacing: -0.02em; }
+.menuseq b.caret { font-size: 1.25em; line-height: 0.8; }
+.menuseq i.caret { font-weight: bold; text-align: center; width: 0.45em; }
+
+b.button:before, b.button:after { position: relative; top: -1px; font-weight: normal; }
+
+b.button:before { content: "["; padding: 0 3px 0 2px; }
+
+b.button:after { content: "]"; padding: 0 2px 0 3px; }
+
+#header, #content, #footnotes, #footer { width: 100%; margin-left: auto; margin-right: auto; margin-top: 0; margin-bottom: 0; max-width: 62.5em; *zoom: 1; position: relative; padding-left: 1.5em; padding-right: 1.5em; }
+#header:before, #header:after, #content:before, #content:after, #footnotes:before, #footnotes:after, #footer:before, #footer:after { content: " "; display: table; }
+#header:after, #content:after, #footnotes:after, #footer:after { clear: both; }
+
+#content { margin-top: 1.25em; }
+
+#content:before { content: none; }
+
+#header > h1:first-child { color: black; margin-top: 2.25rem; margin-bottom: 0; }
+#header > h1:first-child + #toc { margin-top: 8px; border-top: 1px solid #dddddd; }
+#header > h1:only-child, body.toc2 #header > h1:nth-last-child(2) { border-bottom: 1px solid #dddddd; padding-bottom: 8px; }
+#header .details { border-bottom: 1px solid #dddddd; line-height: 1.45; padding-top: 0.25em; padding-bottom: 0.25em; padding-left: 0.25em; color: #5e93b8; display: -ms-flexbox; display: -webkit-flex; display: flex; -ms-flex-flow: row wrap; -webkit-flex-flow: row wrap; flex-flow: row wrap; }
+#header .details span:first-child { margin-left: -0.125em; }
+#header .details span.email a { color: #333333; }
+#header .details br { display: none; }
+#header .details br + span:before { content: "\00a0\2013\00a0"; }
+#header .details br + span.author:before { content: "\00a0\22c5\00a0"; color: #333333; }
+#header .details br + span#revremark:before { content: "\00a0|\00a0"; }
+#header #revnumber { text-transform: capitalize; }
+#header #revnumber:after { content: "\00a0"; }
+
+#content > h1:first-child:not([class]) { color: black; border-bottom: 1px solid #dddddd; padding-bottom: 8px; margin-top: 0; padding-top: 1rem; margin-bottom: 1.25rem; }
+
+#toc { border-bottom: 0 solid #dddddd; padding-bottom: 0.5em; }
+#toc > ul { margin-left: 0.125em; }
+#toc ul.sectlevel0 > li > a { font-style: italic; }
+#toc ul.sectlevel0 ul.sectlevel1 { margin: 0.5em 0; }
+#toc ul { font-family: Noto, sans-serif; list-style-type: none; }
+#toc li { line-height: 1.3334; margin-top: 0.3334em; }
+#toc a { text-decoration: none; }
+#toc a:active { text-decoration: underline; }
+
+#toctitle { color: black; font-size: 1.2em; }
+
+@media only screen and (min-width: 768px) { #toctitle { font-size: 1.375em; }
+  body.toc2 { padding-left: 15em; padding-right: 0; }
+  #toc.toc2 { margin-top: 0 !important; background-color: white; position: fixed; width: 15em; left: 0; top: 0; border-right: 1px solid #dddddd; border-top-width: 0 !important; border-bottom-width: 0 !important; z-index: 1000; padding: 1.25em 1em; height: 100%; overflow: auto; }
+  #toc.toc2 #toctitle { margin-top: 0; margin-bottom: 0.8rem; font-size: 1.2em; }
+  #toc.toc2 > ul { font-size: 0.9em; margin-bottom: 0; }
+  #toc.toc2 ul ul { margin-left: 0; padding-left: 1em; }
+  #toc.toc2 ul.sectlevel0 ul.sectlevel1 { padding-left: 0; margin-top: 0.5em; margin-bottom: 0.5em; }
+  body.toc2.toc-right { padding-left: 0; padding-right: 15em; }
+  body.toc2.toc-right #toc.toc2 { border-right-width: 0; border-left: 1px solid #dddddd; left: auto; right: 0; } }
+@media only screen and (min-width: 1280px) { body.toc2 { padding-left: 20em; padding-right: 0; }
+  #toc.toc2 { width: 20em; }
+  #toc.toc2 #toctitle { font-size: 1.375em; }
+  #toc.toc2 > ul { font-size: 0.95em; }
+  #toc.toc2 ul ul { padding-left: 1.25em; }
+  body.toc2.toc-right { padding-left: 0; padding-right: 20em; } }
+#content #toc { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 0; border-radius: 0; }
+#content #toc > :first-child { margin-top: 0; }
+#content #toc > :last-child { margin-bottom: 0; }
+
+#footer { max-width: 100%; background-color: none; padding: 1.25em; }
+
+#footer-text { color: black; line-height: 1.44; }
+
+#content { margin-bottom: 0.625em; }
+
+.sect1 { padding-bottom: 0.625em; }
+
+@media only screen and (min-width: 768px) { #content { margin-bottom: 1.25em; }
+  .sect1 { padding-bottom: 1.25em; } }
+.sect1:last-child { padding-bottom: 0; }
+
+.sect1 + .sect1 { border-top: 0 solid #dddddd; }
+
+#content h1 > a.anchor, h2 > a.anchor, h3 > a.anchor, #toctitle > a.anchor, .sidebarblock > .content > .title > a.anchor, h4 > a.anchor, h5 > a.anchor, h6 > a.anchor { position: absolute; z-index: 1001; width: 1.5ex; margin-left: -1.5ex; display: block; text-decoration: none !important; visibility: hidden; text-align: center; font-weight: normal; }
+#content h1 > a.anchor:before, h2 > a.anchor:before, h3 > a.anchor:before, #toctitle > a.anchor:before, .sidebarblock > .content > .title > a.anchor:before, h4 > a.anchor:before, h5 > a.anchor:before, h6 > a.anchor:before { content: "\00A7"; font-size: 0.85em; display: block; padding-top: 0.1em; }
+#content h1:hover > a.anchor, #content h1 > a.anchor:hover, h2:hover > a.anchor, h2 > a.anchor:hover, h3:hover > a.anchor, #toctitle:hover > a.anchor, .sidebarblock > .content > .title:hover > a.anchor, h3 > a.anchor:hover, #toctitle > a.anchor:hover, .sidebarblock > .content > .title > a.anchor:hover, h4:hover > a.anchor, h4 > a.anchor:hover, h5:hover > a.anchor, h5 > a.anchor:hover, h6:hover > a.anchor, h6 > a.anchor:hover { visibility: visible; }
+#content h1 > a.link, h2 > a.link, h3 > a.link, #toctitle > a.link, .sidebarblock > .content > .title > a.link, h4 > a.link, h5 > a.link, h6 > a.link { color: black; text-decoration: none; }
+#content h1 > a.link:hover, h2 > a.link:hover, h3 > a.link:hover, #toctitle > a.link:hover, .sidebarblock > .content > .title > a.link:hover, h4 > a.link:hover, h5 > a.link:hover, h6 > a.link:hover { color: black; }
+
+.audioblock, .imageblock, .literalblock, .listingblock, .stemblock, .videoblock { margin-bottom: 1.25em; }
+
+.admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { text-rendering: optimizeLegibility; text-align: left; }
+
+table.tableblock > caption.title { white-space: nowrap; overflow: visible; max-width: 0; }
+
+.paragraph.lead > p, #preamble > .sectionbody > .paragraph:first-of-type p { color: black; }
+
+table.tableblock #preamble > .sectionbody > .paragraph:first-of-type p { font-size: inherit; }
+
+.admonitionblock > table { border-collapse: separate; border: 0; background: none; width: 100%; }
+.admonitionblock > table td.icon { text-align: center; width: 80px; }
+.admonitionblock > table td.icon img { max-width: initial; }
+.admonitionblock > table td.icon .title { font-weight: bold; font-family: Noto, sans-serif; text-transform: uppercase; }
+.admonitionblock > table td.content { padding-left: 1.125em; padding-right: 1.25em; border-left: 1px solid #dddddd; color: #5e93b8; }
+.admonitionblock > table td.content > :last-child > :last-child { margin-bottom: 0; }
+
+.exampleblock > .content { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 0; border-radius: 0; }
+.exampleblock > .content > :first-child { margin-top: 0; }
+.exampleblock > .content > :last-child { margin-bottom: 0; }
+
+.sidebarblock { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 0; border-radius: 0; }
+.sidebarblock > :first-child { margin-top: 0; }
+.sidebarblock > :last-child { margin-bottom: 0; }
+.sidebarblock > .content > .title { color: black; margin-top: 0; }
+
+.exampleblock > .content > :last-child > :last-child, .exampleblock > .content .olist > ol > li:last-child > :last-child, .exampleblock > .content .ulist > ul > li:last-child > :last-child, .exampleblock > .content .qlist > ol > li:last-child > :last-child, .sidebarblock > .content > :last-child > :last-child, .sidebarblock > .content .olist > ol > li:last-child > :last-child, .sidebarblock > .content .ulist > ul > li:last-child > :last-child, .sidebarblock > .content .qlist > ol > li:last-child > :last-child { margin-bottom: 0; }
+
+.literalblock pre, .listingblock pre:not(.highlight), .listingblock pre[class="highlight"], .listingblock pre[class^="highlight "], .listingblock pre.CodeRay, .listingblock pre.prettyprint { background: #eeeeee; }
+.sidebarblock .literalblock pre, .sidebarblock .listingblock pre:not(.highlight), .sidebarblock .listingblock pre[class="highlight"], .sidebarblock .listingblock pre[class^="highlight "], .sidebarblock .listingblock pre.CodeRay, .sidebarblock .listingblock pre.prettyprint { background: #f2f1f1; }
+
+.literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { border: 1px hidden #666666; -webkit-border-radius: 0; border-radius: 0; word-wrap: break-word; padding: 1.25em 1.5625em 1.125em 1.5625em; font-size: 0.8125em; }
+.literalblock pre.nowrap, .literalblock pre[class].nowrap, .listingblock pre.nowrap, .listingblock pre[class].nowrap { overflow-x: auto; white-space: pre; word-wrap: normal; }
+@media only screen and (min-width: 768px) { .literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { font-size: 0.90625em; } }
+@media only screen and (min-width: 1280px) { .literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { font-size: 1em; } }
+
+.literalblock.output pre { color: #eeeeee; background-color: #264357; }
+
+.listingblock pre.highlightjs { padding: 0; }
+.listingblock pre.highlightjs > code { padding: 1.25em 1.5625em 1.125em 1.5625em; -webkit-border-radius: 0; border-radius: 0; }
+
+.listingblock > .content { position: relative; }
+
+.listingblock code[data-lang]:before { display: none; content: attr(data-lang); position: absolute; font-size: 0.75em; top: 0.425rem; right: 0.5rem; line-height: 1; text-transform: uppercase; color: #999; }
+
+.listingblock:hover code[data-lang]:before { display: block; }
+
+.listingblock.terminal pre .command:before { content: attr(data-prompt); padding-right: 0.5em; color: #999; }
+
+.listingblock.terminal pre .command:not([data-prompt]):before { content: "$"; }
+
+table.pyhltable { border-collapse: separate; border: 0; margin-bottom: 0; background: none; }
+
+table.pyhltable td { vertical-align: top; padding-top: 0; padding-bottom: 0; line-height: 1.6; }
+
+table.pyhltable td.code { padding-left: .75em; padding-right: 0; }
+
+pre.pygments .lineno, table.pyhltable td:not(.code) { color: #999; padding-left: 0; padding-right: .5em; border-right: 1px solid #dddddd; }
+
+pre.pygments .lineno { display: inline-block; margin-right: .25em; }
+
+table.pyhltable .linenodiv { background: none !important; padding-right: 0 !important; }
+
+.quoteblock { margin: 0 1em 0.75em 1.5em; display: table; }
+.quoteblock > .title { margin-left: -1.5em; margin-bottom: 0.75em; }
+.quoteblock blockquote, .quoteblock blockquote p { color: #333333; font-size: 1.15rem; line-height: 1.75; word-spacing: 0.1em; letter-spacing: 0; font-style: italic; text-align: justify; }
+.quoteblock blockquote { margin: 0; padding: 0; border: 0; }
+.quoteblock blockquote:before { content: "\201c"; float: left; font-size: 2.75em; font-weight: bold; line-height: 0.6em; margin-left: -0.6em; color: black; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); }
+.quoteblock blockquote > .paragraph:last-child p { margin-bottom: 0; }
+.quoteblock .attribution { margin-top: 0.5em; margin-right: 0.5ex; text-align: right; }
+.quoteblock .quoteblock { margin-left: 0; margin-right: 0; padding: 0.5em 0; border-left: 3px solid #5e93b8; }
+.quoteblock .quoteblock blockquote { padding: 0 0 0 0.75em; }
+.quoteblock .quoteblock blockquote:before { display: none; }
+
+.verseblock { margin: 0 1em 0.75em 1em; }
+.verseblock pre { font-family: "Open Sans", "DejaVu Sans", sans; font-size: 1.15rem; color: #333333; font-weight: 300; text-rendering: optimizeLegibility; }
+.verseblock pre strong { font-weight: 400; }
+.verseblock .attribution { margin-top: 1.25rem; margin-left: 0.5ex; }
+
+.quoteblock .attribution, .verseblock .attribution { font-size: 0.8125em; line-height: 1.45; font-style: italic; }
+.quoteblock .attribution br, .verseblock .attribution br { display: none; }
+.quoteblock .attribution cite, .verseblock .attribution cite { display: block; letter-spacing: -0.025em; color: #5e93b8; }
+
+.quoteblock.abstract { margin: 0 0 0.75em 0; display: block; }
+.quoteblock.abstract blockquote, .quoteblock.abstract blockquote p { text-align: left; word-spacing: 0; }
+.quoteblock.abstract blockquote:before, .quoteblock.abstract blockquote p:first-of-type:before { display: none; }
+
+table.tableblock { max-width: 100%; border-collapse: separate; }
+table.tableblock td > .paragraph:last-child p > p:last-child, table.tableblock th > p:last-child, table.tableblock td > p:last-child { margin-bottom: 0; }
+
+table.tableblock, th.tableblock, td.tableblock { border: 0 solid #d8d8ce; }
+
+table.grid-all > thead > tr > .tableblock, table.grid-all > tbody > tr > .tableblock { border-width: 0 1px 1px 0; }
+
+table.grid-all > tfoot > tr > .tableblock { border-width: 1px 1px 0 0; }
+
+table.grid-cols > * > tr > .tableblock { border-width: 0 1px 0 0; }
+
+table.grid-rows > thead > tr > .tableblock, table.grid-rows > tbody > tr > .tableblock { border-width: 0 0 1px 0; }
+
+table.grid-rows > tfoot > tr > .tableblock { border-width: 1px 0 0 0; }
+
+table.grid-all > * > tr > .tableblock:last-child, table.grid-cols > * > tr > .tableblock:last-child { border-right-width: 0; }
+
+table.grid-all > tbody > tr:last-child > .tableblock, table.grid-all > thead:last-child > tr > .tableblock, table.grid-rows > tbody > tr:last-child > .tableblock, table.grid-rows > thead:last-child > tr > .tableblock { border-bottom-width: 0; }
+
+table.frame-all { border-width: 1px; }
+
+table.frame-sides { border-width: 0 1px; }
+
+table.frame-topbot { border-width: 1px 0; }
+
+th.halign-left, td.halign-left { text-align: left; }
+
+th.halign-right, td.halign-right { text-align: right; }
+
+th.halign-center, td.halign-center { text-align: center; }
+
+th.valign-top, td.valign-top { vertical-align: top; }
+
+th.valign-bottom, td.valign-bottom { vertical-align: bottom; }
+
+th.valign-middle, td.valign-middle { vertical-align: middle; }
+
+table thead th, table tfoot th { font-weight: bold; }
+
+tbody tr th { display: table-cell; line-height: 1.4; background: -webkit-linear-gradient(top, #add386, #90b66a); }
+
+tbody tr th, tbody tr th p, tfoot tr th, tfoot tr th p { color: white; font-weight: bold; }
+
+p.tableblock > code:only-child { background: none; padding: 0; }
+
+p.tableblock { font-size: 1em; }
+
+td > div.verse { white-space: pre; }
+
+ol { margin-left: 1.75em; }
+
+ul li ol { margin-left: 1.5em; }
+
+dl dd { margin-left: 1.125em; }
+
+dl dd:last-child, dl dd:last-child > :last-child { margin-bottom: 0; }
+
+ol > li p, ul > li p, ul dd, ol dd, .olist .olist, .ulist .ulist, .ulist .olist, .olist .ulist { margin-bottom: 0.375em; }
+
+ul.checklist, ul.none, ol.none, ul.no-bullet, ol.no-bullet, ol.unnumbered, ul.unstyled, ol.unstyled { list-style-type: none; }
+
+ul.no-bullet, ol.no-bullet, ol.unnumbered { margin-left: 0.625em; }
+
+ul.unstyled, ol.unstyled { margin-left: 0; }
+
+ul.checklist { margin-left: 0.625em; }
+
+ul.checklist li > p:first-child > .fa-square-o:first-child, ul.checklist li > p:first-child > .fa-check-square-o:first-child { width: 1.25em; font-size: 0.8em; position: relative; bottom: 0.125em; }
+
+ul.checklist li > p:first-child > input[type="checkbox"]:first-child { margin-right: 0.25em; }
+
+ul.inline { display: -ms-flexbox; display: -webkit-box; display: flex; -ms-flex-flow: row wrap; -webkit-flex-flow: row wrap; flex-flow: row wrap; list-style: none; margin: 0 0 0.375em -0.75em; }
+
+ul.inline > li { margin-left: 0.75em; }
+
+.unstyled dl dt { font-weight: normal; font-style: normal; }
+
+ol.arabic { list-style-type: decimal; }
+
+ol.decimal { list-style-type: decimal-leading-zero; }
+
+ol.loweralpha { list-style-type: lower-alpha; }
+
+ol.upperalpha { list-style-type: upper-alpha; }
+
+ol.lowerroman { list-style-type: lower-roman; }
+
+ol.upperroman { list-style-type: upper-roman; }
+
+ol.lowergreek { list-style-type: lower-greek; }
+
+.hdlist > table, .colist > table { border: 0; background: none; }
+.hdlist > table > tbody > tr, .colist > table > tbody > tr { background: none; }
+
+td.hdlist1, td.hdlist2 { vertical-align: top; padding: 0 0.625em; }
+
+td.hdlist1 { font-weight: bold; padding-bottom: 0.75em; }
+
+.literalblock + .colist, .listingblock + .colist { margin-top: -0.5em; }
+
+.colist > table tr > td:first-of-type { padding: 0.4em 0.75em 0 0.75em; line-height: 1; vertical-align: top; }
+.colist > table tr > td:first-of-type img { max-width: initial; }
+.colist > table tr > td:last-of-type { padding: 0.25em 0; }
+
+.thumb, .th { line-height: 0; display: inline-block; border: solid 4px white; -webkit-box-shadow: 0 0 0 1px #dddddd; box-shadow: 0 0 0 1px #dddddd; }
+
+.imageblock.left, .imageblock[style*="float: left"] { margin: 0.25em 0.625em 1.25em 0; }
+.imageblock.right, .imageblock[style*="float: right"] { margin: 0.25em 0 1.25em 0.625em; }
+.imageblock > .title { margin-bottom: 0; }
+.imageblock.thumb, .imageblock.th { border-width: 6px; }
+.imageblock.thumb > .title, .imageblock.th > .title { padding: 0 0.125em; }
+
+.image.left, .image.right { margin-top: 0.25em; margin-bottom: 0.25em; display: inline-block; line-height: 0; }
+.image.left { margin-right: 0.625em; }
+.image.right { margin-left: 0.625em; }
+
+a.image { text-decoration: none; display: inline-block; }
+a.image object { pointer-events: none; }
+
+sup.footnote, sup.footnoteref { font-size: 0.875em; position: static; vertical-align: super; }
+sup.footnote a, sup.footnoteref a { text-decoration: none; }
+sup.footnote a:active, sup.footnoteref a:active { text-decoration: underline; }
+
+#footnotes { padding-top: 0.75em; padding-bottom: 0.75em; margin-bottom: 0.625em; }
+#footnotes hr { width: 20%; min-width: 6.25em; margin: -0.25em 0 0.75em 0; border-width: 1px 0 0 0; }
+#footnotes .footnote { padding: 0 0.375em 0 0.225em; line-height: 1.3334; font-size: 0.875em; margin-left: 1.2em; margin-bottom: 0.2em; }
+#footnotes .footnote a:first-of-type { font-weight: bold; text-decoration: none; margin-left: -1.05em; }
+#footnotes .footnote:last-of-type { margin-bottom: 0; }
+#content #footnotes { margin-top: -0.625em; margin-bottom: 0; padding: 0.75em 0; }
+
+.gist .file-data > table { border: 0; background: #fff; width: 100%; margin-bottom: 0; }
+.gist .file-data > table td.line-data { width: 99%; }
+
+div.unbreakable { page-break-inside: avoid; }
+
+.big { font-size: larger; }
+
+.small { font-size: smaller; }
+
+.underline { text-decoration: underline; }
+
+.overline { text-decoration: overline; }
+
+.line-through { text-decoration: line-through; }
+
+.aqua { color: #00bfbf; }
+
+.aqua-background { background-color: #00fafa; }
+
+.black { color: black; }
+
+.black-background { background-color: black; }
+
+.blue { color: #0000bf; }
+
+.blue-background { background-color: #0000fa; }
+
+.fuchsia { color: #bf00bf; }
+
+.fuchsia-background { background-color: #fa00fa; }
+
+.gray { color: #606060; }
+
+.gray-background { background-color: #7d7d7d; }
+
+.green { color: #006000; }
+
+.green-background { background-color: #007d00; }
+
+.lime { color: #00bf00; }
+
+.lime-background { background-color: #00fa00; }
+
+.maroon { color: #600000; }
+
+.maroon-background { background-color: #7d0000; }
+
+.navy { color: #000060; }
+
+.navy-background { background-color: #00007d; }
+
+.olive { color: #606000; }
+
+.olive-background { background-color: #7d7d00; }
+
+.purple { color: #600060; }
+
+.purple-background { background-color: #7d007d; }
+
+.red { color: #bf0000; }
+
+.red-background { background-color: #fa0000; }
+
+.silver { color: #909090; }
+
+.silver-background { background-color: #bcbcbc; }
+
+.teal { color: #006060; }
+
+.teal-background { background-color: #007d7d; }
+
+.white { color: #bfbfbf; }
+
+.white-background { background-color: #fafafa; }
+
+.yellow { color: #bfbf00; }
+
+.yellow-background { background-color: #fafa00; }
+
+span.icon > .fa { cursor: default; }
+a span.icon > .fa { cursor: inherit; }
+
+.admonitionblock td.icon [class^="fa icon-"] { font-size: 2.5em; text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5); cursor: default; }
+.admonitionblock td.icon .icon-note:before { content: "\f05a"; color: #29475c; }
+.admonitionblock td.icon .icon-tip:before { content: "\f0eb"; text-shadow: 1px 1px 2px rgba(155, 155, 0, 0.8); color: #111; }
+.admonitionblock td.icon .icon-warning:before { content: "\f071"; color: #bf6900; }
+.admonitionblock td.icon .icon-caution:before { content: "\f06d"; color: #bf3400; }
+.admonitionblock td.icon .icon-important:before { content: "\f06a"; color: #bf0000; }
+
+.conum[data-value] { display: inline-block; color: #fff !important; background-color: black; -webkit-border-radius: 100px; border-radius: 100px; text-align: center; font-size: 0.75em; width: 1.67em; height: 1.67em; line-height: 1.67em; font-family: "Open Sans", "DejaVu Sans", sans-serif; font-style: normal; font-weight: bold; }
+.conum[data-value] * { color: #fff !important; }
+.conum[data-value] + b { display: none; }
+.conum[data-value]:after { content: attr(data-value); }
+pre .conum[data-value] { position: relative; top: -0.125em; }
+
+b.conum * { color: inherit !important; }
+
+.conum:not([data-value]):empty { display: none; }
+
+h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { border-bottom: 1px solid #dddddd; }
+
+.sect1 { padding-bottom: 0; }
+
+#toctitle { color: #00406F; font-weight: normal; margin-top: 1.5em; }
+
+.sidebarblock { border-color: #aaa; }
+
+code { -webkit-border-radius: 4px; border-radius: 4px; }
+
+p.tableblock.header { color: #6d6e71; }
+
+.literalblock pre, .listingblock pre { background: #eeeeee; }
+
+</style>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css">
+<style>
+/* Stylesheet for CodeRay to match GitHub theme | MIT License | http://foundation.zurb.com */
+/*pre.CodeRay {background-color:#f7f7f8;}*/
+.CodeRay .line-numbers{border-right:1px solid #d8d8d8;padding:0 0.5em 0 .25em}
+.CodeRay span.line-numbers{display:inline-block;margin-right:.5em;color:rgba(0,0,0,.3)}
+.CodeRay .line-numbers strong{color:rgba(0,0,0,.4)}
+table.CodeRay{border-collapse:separate;border-spacing:0;margin-bottom:0;border:0;background:none}
+table.CodeRay td{vertical-align: top;line-height:1.45}
+table.CodeRay td.line-numbers{text-align:right}
+table.CodeRay td.line-numbers>pre{padding:0;color:rgba(0,0,0,.3)}
+table.CodeRay td.code{padding:0 0 0 .5em}
+table.CodeRay td.code>pre{padding:0}
+.CodeRay .debug{color:#fff !important;background:#000080 !important}
+.CodeRay .annotation{color:#007}
+.CodeRay .attribute-name{color:#000080}
+.CodeRay .attribute-value{color:#700}
+.CodeRay .binary{color:#509}
+.CodeRay .comment{color:#998;font-style:italic}
+.CodeRay .char{color:#04d}
+.CodeRay .char .content{color:#04d}
+.CodeRay .char .delimiter{color:#039}
+.CodeRay .class{color:#458;font-weight:bold}
+.CodeRay .complex{color:#a08}
+.CodeRay .constant,.CodeRay .predefined-constant{color:#008080}
+.CodeRay .color{color:#099}
+.CodeRay .class-variable{color:#369}
+.CodeRay .decorator{color:#b0b}
+.CodeRay .definition{color:#099}
+.CodeRay .delimiter{color:#000}
+.CodeRay .doc{color:#970}
+.CodeRay .doctype{color:#34b}
+.CodeRay .doc-string{color:#d42}
+.CodeRay .escape{color:#666}
+.CodeRay .entity{color:#800}
+.CodeRay .error{color:#808}
+.CodeRay .exception{color:inherit}
+.CodeRay .filename{color:#099}
+.CodeRay .function{color:#900;font-weight:bold}
+.CodeRay .global-variable{color:#008080}
+.CodeRay .hex{color:#058}
+.CodeRay .integer,.CodeRay .float{color:#099}
+.CodeRay .include{color:#555}
+.CodeRay .inline{color:#000}
+.CodeRay .inline .inline{background:#ccc}
+.CodeRay .inline .inline .inline{background:#bbb}
+.CodeRay .inline .inline-delimiter{color:#d14}
+.CodeRay .inline-delimiter{color:#d14}
+.CodeRay .important{color:#555;font-weight:bold}
+.CodeRay .interpreted{color:#b2b}
+.CodeRay .instance-variable{color:#008080}
+.CodeRay .label{color:#970}
+.CodeRay .local-variable{color:#963}
+.CodeRay .octal{color:#40e}
+.CodeRay .predefined{color:#369}
+.CodeRay .preprocessor{color:#579}
+.CodeRay .pseudo-class{color:#555}
+.CodeRay .directive{font-weight:bold}
+.CodeRay .type{font-weight:bold}
+.CodeRay .predefined-type{color:inherit}
+.CodeRay .reserved,.CodeRay .keyword {color:#000;font-weight:bold}
+.CodeRay .key{color:#808}
+.CodeRay .key .delimiter{color:#606}
+.CodeRay .key .char{color:#80f}
+.CodeRay .value{color:#088}
+.CodeRay .regexp .delimiter{color:#808}
+.CodeRay .regexp .content{color:#808}
+.CodeRay .regexp .modifier{color:#808}
+.CodeRay .regexp .char{color:#d14}
+.CodeRay .regexp .function{color:#404;font-weight:bold}
+.CodeRay .string{color:#d20}
+.CodeRay .string .string .string{background:#ffd0d0}
+.CodeRay .string .content{color:#d14}
+.CodeRay .string .char{color:#d14}
+.CodeRay .string .delimiter{color:#d14}
+.CodeRay .shell{color:#d14}
+.CodeRay .shell .delimiter{color:#d14}
+.CodeRay .symbol{color:#990073}
+.CodeRay .symbol .content{color:#a60}
+.CodeRay .symbol .delimiter{color:#630}
+.CodeRay .tag{color:#008080}
+.CodeRay .tag-special{color:#d70}
+.CodeRay .variable{color:#036}
+.CodeRay .insert{background:#afa}
+.CodeRay .delete{background:#faa}
+.CodeRay .change{color:#aaf;background:#007}
+.CodeRay .head{color:#f8f;background:#505}
+.CodeRay .insert .insert{color:#080}
+.CodeRay .delete .delete{color:#800}
+.CodeRay .change .change{color:#66f}
+.CodeRay .head .head{color:#f4f}
+</style>
+<link rel="stylesheet" href="../katex/katex.min.css">
+<script src="../katex/katex.min.js"></script>
+<script src="../katex/contrib/auto-render.min.js"></script>
+    <!-- Use KaTeX to render math once document is loaded, see
+         https://github.com/Khan/KaTeX/tree/master/contrib/auto-render -->
+<script>
+    document.addEventListener("DOMContentLoaded", function () {
+        renderMathInElement(
+            document.body,
+            {
+                delimiters: [
+                    { left: "$$", right: "$$", display: true},
+                    { left: "\\[", right: "\\]", display: true},
+                    { left: "$", right: "$", display: false},
+                    { left: "\\(", right: "\\)", display: false}
+                ]
+            }
+        );
+    });
+</script></head>
+<body class="book toc2 toc-left" style="max-width: 100;">
+<div id="header">
+<h1>The OpenCL<sup>&#8482;</sup> Specification</h1>
+<div class="details">
+<span id="author" class="author">Khronos OpenCL Working Group</span><br>
+<span id="revnumber">version 2.2-7,</span>
+<span id="revdate">Sat, 12 May 2018 13:21:27 +0000</span>
+<br><span id="revremark">from git branch: master commit: ab6da3001e9eeafaa36c18888ca7eb4ebb9768af</span>
+</div>
+<div id="toc" class="toc2">
+<div id="toctitle">Table of Contents</div>
+<ul class="sectlevel1">
+<li><a href="#_introduction">1. Introduction</a>
+<ul class="sectlevel2">
+<li><a href="#_normative_references">1.1. Normative References</a></li>
+<li><a href="#_version_numbers">1.2. Version Numbers</a></li>
+</ul>
+</li>
+<li><a href="#_glossary">2. Glossary</a></li>
+<li><a href="#_the_opencl_architecture">3. The OpenCL Architecture</a>
+<ul class="sectlevel2">
+<li><a href="#_platform_model">3.1. Platform Model</a></li>
+<li><a href="#_execution_model">3.2. Execution Model</a></li>
+<li><a href="#_memory_model">3.3. Memory Model</a></li>
+<li><a href="#opencl-framework">3.4. The OpenCL Framework</a></li>
+</ul>
+</li>
+<li><a href="#opencl-platform-layer">4. The OpenCL Platform Layer</a>
+<ul class="sectlevel2">
+<li><a href="#_querying_platform_info">4.1. Querying Platform Info</a></li>
+<li><a href="#platform-querying-devices">4.2. Querying Devices</a></li>
+<li><a href="#_partitioning_a_device">4.3. Partitioning a Device</a></li>
+<li><a href="#_contexts">4.4. Contexts</a></li>
+</ul>
+</li>
+<li><a href="#opencl-runtime">5. The OpenCL Runtime</a>
+<ul class="sectlevel2">
+<li><a href="#_command_queues">5.1. Command Queues</a></li>
+<li><a href="#_buffer_objects">5.2. Buffer Objects</a></li>
+<li><a href="#_image_objects">5.3. Image Objects</a></li>
+<li><a href="#_pipes">5.4. Pipes</a></li>
+<li><a href="#_querying_unmapping_migrating_retaining_and_releasing_memory_objects">5.5. Querying, Unmapping, Migrating, Retaining and Releasing Memory Objects</a></li>
+<li><a href="#_shared_virtual_memory">5.6. Shared Virtual Memory</a></li>
+<li><a href="#_sampler_objects">5.7. Sampler Objects</a></li>
+<li><a href="#_program_objects">5.8. Program Objects</a></li>
+<li><a href="#_kernel_objects">5.9. Kernel Objects</a></li>
+<li><a href="#_executing_kernels">5.10. Executing Kernels</a></li>
+<li><a href="#event-objects">5.11. Event Objects</a></li>
+<li><a href="#markers-barriers-waiting-for-events">5.12. Markers, Barriers and Waiting for Events</a></li>
+<li><a href="#_out_of_order_execution_of_kernels_and_memory_object_commands">5.13. Out-of-order Execution of Kernels and Memory Object Commands</a></li>
+<li><a href="#profiling-operations">5.14. Profiling Operations on Memory Objects and Kernels</a></li>
+<li><a href="#_flush_and_finish">5.15. Flush and Finish</a></li>
+</ul>
+</li>
+<li><a href="#_associated_opencl_specification">6. Associated OpenCL specification</a>
+<ul class="sectlevel2">
+<li><a href="#spirv-il">6.1. SPIR-V Intermediate language</a></li>
+<li><a href="#opencl-extensions">6.2. Extensions to OpenCL</a></li>
+<li><a href="#_support_for_earlier_opencl_c_kernel_languages">6.3. Support for earlier OpenCL C kernel languages</a></li>
+</ul>
+</li>
+<li><a href="#opencl-embedded-profile">7. OpenCL Embedded Profile</a></li>
+<li><a href="#_shared_objects_thread_safety">Appendix A: Shared Objects, Thread Safety</a>
+<ul class="sectlevel2">
+<li><a href="#shared-opencl-objects">Shared OpenCL Objects</a></li>
+<li><a href="#_multiple_host_threads">Multiple Host Threads</a></li>
+</ul>
+</li>
+<li><a href="#_portability">Appendix B: Portability</a></li>
+<li><a href="#data-types">Appendix C: Application Data Types</a>
+<ul class="sectlevel2">
+<li><a href="#scalar-data-types">Shared Application Scalar Data Types</a></li>
+<li><a href="#vector-data-types">Supported Application Vector Data Types</a></li>
+<li><a href="#alignment-app-data-types">Alignment of Application Data Types</a></li>
+<li><a href="#_vector_literals">Vector Literals</a></li>
+<li><a href="#vector-components">Vector Components</a></li>
+<li><a href="#_implicit_conversions">Implicit Conversions</a></li>
+<li><a href="#_explicit_casts">Explicit Casts</a></li>
+<li><a href="#_other_operators_and_functions">Other operators and functions</a></li>
+<li><a href="#_application_constant_definitions">Application constant definitions</a></li>
+</ul>
+</li>
+<li><a href="#check-copy-overlap">Appendix D: CL_MEM_COPY_OVERLAP</a></li>
+<li><a href="#_changes">Appendix E: Changes</a>
+<ul class="sectlevel2">
+<li><a href="#_summary_of_changes_from_opencl_1_0">Summary of changes from OpenCL 1.0</a></li>
+<li><a href="#_summary_of_changes_from_opencl_1_1">Summary of changes from OpenCL 1.1</a></li>
+<li><a href="#_summary_of_changes_from_opencl_1_2">Summary of changes from OpenCL 1.2</a></li>
+<li><a href="#_summary_of_changes_from_opencl_2_0">Summary of changes from OpenCL 2.0</a></li>
+<li><a href="#_summary_of_changes_from_opencl_2_1">Summary of changes from OpenCL 2.1</a></li>
+</ul>
+</li>
+</ul>
+</div>
+</div>
+<div id="content">
+<div id="preamble">
+<div class="sectionbody">
+<div style="page-break-after: always;"></div>
+<div class="paragraph">
+<p>Copyright 2008-2018 The Khronos Group.</p>
+</div>
+<div class="paragraph">
+<p>This specification is protected by copyright laws and contains material proprietary
+to the Khronos Group, Inc. Except as described by these terms, it or any components
+may not be reproduced, republished, distributed, transmitted, displayed, broadcast
+or otherwise exploited in any manner without the express prior written permission
+of Khronos Group.</p>
+</div>
+<div class="paragraph">
+<p>Khronos Group grants a conditional copyright license to use and reproduce the
+unmodified specification for any purpose, without fee or royalty, EXCEPT no licenses
+to any patent, trademark or other intellectual property rights are granted under
+these terms. Parties desiring to implement the specification and make use of
+Khronos trademarks in relation to that implementation, and receive reciprocal patent
+license protection under the Khronos IP Policy must become Adopters and confirm the
+implementation as conformant under the process defined by Khronos for this
+specification; see <a href="https://www.khronos.org/adopters" class="bare">https://www.khronos.org/adopters</a>.</p>
+</div>
+<div class="paragraph">
+<p>Khronos Group makes no, and expressly disclaims any, representations or warranties,
+express or implied, regarding this specification, including, without limitation:
+merchantability, fitness for a particular purpose, non-infringement of any
+intellectual property, correctness, accuracy, completeness, timeliness, and
+reliability. Under no circumstances will the Khronos Group, or any of its Promoters,
+Contributors or Members, or their respective partners, officers, directors,
+employees, agents or representatives be liable for any damages, whether direct,
+indirect, special or consequential damages for lost revenues, lost profits, or
+otherwise, arising from or in connection with these materials.</p>
+</div>
+<div class="paragraph">
+<p>Vulkan is a registered trademark and Khronos, OpenXR, SPIR, SPIR-V, SYCL, WebGL,
+WebCL, OpenVX, OpenVG, EGL, COLLADA, glTF, NNEF, OpenKODE, OpenKCAM, StreamInput,
+OpenWF, OpenSL ES, OpenMAX, OpenMAX AL, OpenMAX IL, OpenMAX DL, OpenML and DevU are
+trademarks of the Khronos Group Inc. ASTC is a trademark of ARM Holdings PLC,
+OpenCL is a trademark of Apple Inc. and OpenGL and OpenML are registered trademarks
+and the OpenGL ES and OpenGL SC logos are trademarks of Silicon Graphics
+International used under license by Khronos. All other product names, trademarks,
+and/or company names are used solely for identification and belong to their
+respective owners.</p>
+</div>
+<div style="page-break-after: always;"></div>
+<div class="paragraph">
+<p><strong>Acknowledgements</strong></p>
+</div>
+<div class="paragraph">
+<p>The OpenCL specification is the result of the contributions of many people,
+representing a cross section of the desktop, hand-held, and embedded
+computer industry.
+Following is a partial list of the contributors, including the company that
+they represented at the time of their contribution:</p>
+</div>
+<div class="paragraph">
+<p>Chuck Rose, Adobe<br>
+Eric Berdahl, Adobe<br>
+Shivani Gupta, Adobe<br>
+Bill Licea Kane, AMD<br>
+Ed Buckingham, AMD<br>
+Jan Civlin, AMD<br>
+Laurent Morichetti, AMD<br>
+Mark Fowler, AMD<br>
+Marty Johnson, AMD<br>
+Michael Mantor, AMD<br>
+Norm Rubin, AMD<br>
+Ofer Rosenberg, AMD<br>
+Brian Sumner, AMD<br>
+Victor Odintsov, AMD<br>
+Aaftab Munshi, Apple<br>
+Abe Stephens, Apple<br>
+Alexandre Namaan, Apple<br>
+Anna Tikhonova, Apple<br>
+Chendi Zhang, Apple<br>
+Eric Bainville, Apple<br>
+David Hayward, Apple<br>
+Giridhar Murthy, Apple<br>
+Ian Ollmann, Apple<br>
+Inam Rahman, Apple<br>
+James Shearer, Apple<br>
+MonPing Wang, Apple<br>
+Tanya Lattner, Apple<br>
+Mikael Bourges-Sevenier, Aptina<br>
+Anton Lokhmotov, ARM<br>
+Dave Shreiner, ARM<br>
+Hedley Francis, ARM<br>
+Robert Elliott, ARM<br>
+Scott Moyers, ARM<br>
+Tom Olson, ARM<br>
+Anastasia Stulova, ARM<br>
+Christopher Thompson-Walsh, Broadcom<br>
+Holger Waechtler, Broadcom<br>
+Norman Rink, Broadcom<br>
+Andrew Richards, Codeplay<br>
+Maria Rovatsou, Codeplay<br>
+Alistair Donaldson, Codeplay<br>
+Alastair Murray, Codeplay<br>
+Stephen Frye, Electronic Arts<br>
+Eric Schenk, Electronic Arts<br>
+Daniel Laroche, Freescale<br>
+David Neto, Google<br>
+Robin Grosman, Huawei<br>
+Craig Davies, Huawei<br>
+Brian Horton, IBM<br>
+Brian Watt, IBM<br>
+Gordon Fossum, IBM<br>
+Greg Bellows, IBM<br>
+Joaquin Madruga, IBM<br>
+Mark Nutter, IBM<br>
+Mike Perks, IBM<br>
+Sean Wagner, IBM<br>
+Jon Parr, Imagination Technologies<br>
+Robert Quill, Imagination Technologies<br>
+James McCarthy, Imagination Technologie<br>
+Jon Leech, Independent<br>
+Aaron Kunze, Intel<br>
+Aaron Lefohn, Intel<br>
+Adam Lake, Intel<br>
+Alexey Bader, Intel<br>
+Allen Hux, Intel<br>
+Andrew Brownsword, Intel<br>
+Andrew Lauritzen, Intel<br>
+Bartosz Sochacki, Intel<br>
+Ben Ashbaugh, Intel<br>
+Brian Lewis, Intel<br>
+Geoff Berry, Intel<br>
+Hong Jiang, Intel<br>
+Jayanth Rao, Intel<br>
+Josh Fryman, Intel<br>
+Larry Seiler, Intel<br>
+Mike MacPherson, Intel<br>
+Murali Sundaresan, Intel<br>
+Paul Lalonde, Intel<br>
+Raun Krisch, Intel<br>
+Stephen Junkins, Intel<br>
+Tim Foley, Intel<br>
+Timothy Mattson, Intel<br>
+Yariv Aridor, Intel<br>
+Michael Kinsner, Intel<br>
+Kevin Stevens, Intel<br>
+Jon Leech, Khronos<br>
+Benjamin Bergen, Los Alamos National Laboratory<br>
+Roy Ju, Mediatek<br>
+Bor-Sung Liang, Mediatek<br>
+Rahul Agarwal, Mediatek<br>
+Michal Witaszek, Mobica<br>
+JenqKuen Lee, NTHU<br>
+Amit Rao, NVIDIA<br>
+Ashish Srivastava, NVIDIA<br>
+Bastiaan Aarts, NVIDIA<br>
+Chris Cameron, NVIDIA<br>
+Christopher Lamb, NVIDIA<br>
+Dibyapran Sanyal, NVIDIA<br>
+Guatam Chakrabarti, NVIDIA<br>
+Ian Buck, NVIDIA<br>
+Jaydeep Marathe, NVIDIA<br>
+Jian-Zhong Wang, NVIDIA<br>
+Karthik Raghavan Ravi, NVIDIA<br>
+Kedar Patil, NVIDIA<br>
+Manjunath Kudlur, NVIDIA<br>
+Mark Harris, NVIDIA<br>
+Michael Gold, NVIDIA<br>
+Neil Trevett, NVIDIA<br>
+Richard Johnson, NVIDIA<br>
+Sean Lee, NVIDIA<br>
+Tushar Kashalikar, NVIDIA<br>
+Vinod Grover, NVIDIA<br>
+Xiangyun Kong, NVIDIA<br>
+Yogesh Kini, NVIDIA<br>
+Yuan Lin, NVIDIA<br>
+Mayuresh Pise, NVIDIA<br>
+Allan Tzeng, QUALCOMM<br>
+Alex Bourd, QUALCOMM<br>
+Anirudh Acharya, QUALCOMM<br>
+Andrew Gruber, QUALCOMM<br>
+Andrzej Mamona, QUALCOMM<br>
+Benedict Gaster, QUALCOMM<br>
+Bill Torzewski, QUALCOMM<br>
+Bob Rychlik, QUALCOMM<br>
+Chihong Zhang, QUALCOMM<br>
+Chris Mei, QUALCOMM<br>
+Colin Sharp, QUALCOMM<br>
+David Garcia, QUALCOMM<br>
+David Ligon, QUALCOMM<br>
+Jay Yun, QUALCOMM<br>
+Lee Howes, QUALCOMM<br>
+Richard Ruigrok, QUALCOMM<br>
+Robert J. Simpson, QUALCOMM<br>
+Sumesh Udayakumaran, QUALCOMM<br>
+Vineet Goel, QUALCOMM<br>
+Lihan Bin, QUALCOMM<br>
+Vlad Shimanskiy, QUALCOMM<br>
+Jian Liu, QUALCOMM<br>
+Tasneem Brutch, Samsung<br>
+Yoonseo Choi, Samsung<br>
+Dennis Adams, Sony<br>
+Pr-Anders Aronsson, Sony<br>
+Jim Rasmusson, Sony<br>
+Thierry Lepley, STMicroelectronics<br>
+Anton Gorenko, StreamHPC<br>
+Jakub Szuppe, StreamHPC<br>
+Vincent Hindriksen, StreamHPC<br>
+Alan Ward, Texas Instruments<br>
+Yuan Zhao, Texas Instruments<br>
+Pete Curry, Texas Instruments<br>
+Simon McIntosh-Smith, University of Bristol<br>
+James Price, University of Bristol<br>
+Paul Preney, University of Windsor<br>
+Shane Peelar, University of Windsor<br>
+Brian Hutsell, Vivante<br>
+Mike Cai, Vivante<br>
+Sumeet Kumar, Vivante<br>
+Wei-Lun Kao, Vivante<br>
+Xing Wang, Vivante<br>
+Jeff Fifield, Xilinx<br>
+Hem C. Neema, Xilinx<br>
+Henry Styles, Xilinx<br>
+Ralph Wittig, Xilinx<br>
+Ronan Keryell, Xilinx<br>
+AJ Guillon, YetiWare Inc<br></p>
+</div>
+<div style="page-break-after: always;"></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_introduction">1. Introduction</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>Modern processor architectures have embraced parallelism as an important
+pathway to increased performance.
+Facing technical challenges with higher clock speeds in a fixed power
+envelope, Central Processing Units (CPUs) now improve performance by adding
+multiple cores.
+Graphics Processing Units (GPUs) have also evolved from fixed function
+rendering devices into programmable parallel processors.
+As todays computer systems often include highly parallel CPUs, GPUs and
+other types of processors, it is important to enable software developers to
+take full advantage of these heterogeneous processing platforms.</p>
+</div>
+<div class="paragraph">
+<p>Creating applications for heterogeneous parallel processing platforms is
+challenging as traditional programming approaches for multi-core CPUs and
+GPUs are very different.
+CPU-based parallel programming models are typically based on standards but
+usually assume a shared address space and do not encompass vector
+operations.
+General purpose GPU programming models address complex memory hierarchies
+and vector operations but are traditionally platform-, vendor- or
+hardware-specific.
+These limitations make it difficult for a developer to access the compute
+power of heterogeneous CPUs, GPUs and other types of processors from a
+single, multi-platform source code base.
+More than ever, there is a need to enable software developers to effectively
+take full advantage of heterogeneous processing platforms from high
+performance compute servers, through desktop computer systems to handheld
+devices - that include a diverse mix of parallel CPUs, GPUs and other
+processors such as DSPs and the Cell/B.E.
+processor.</p>
+</div>
+<div class="paragraph">
+<p><strong>OpenCL</strong> (Open Computing Language) is an open royalty-free standard for
+general purpose parallel programming across CPUs, GPUs and other processors,
+giving software developers portable and efficient access to the power of
+these heterogeneous processing platforms.</p>
+</div>
+<div class="paragraph">
+<p>OpenCL supports a wide range of applications, ranging from embedded and
+consumer software to HPC solutions, through a low-level, high-performance,
+portable abstraction.
+By creating an efficient, close-to-the-metal programming interface, OpenCL
+will form the foundation layer of a parallel computing ecosystem of
+platform-independent tools, middleware and applications.
+OpenCL is particularly suited to play an increasingly significant role in
+emerging interactive graphics applications that combine general parallel
+compute algorithms with graphics rendering pipelines.</p>
+</div>
+<div class="paragraph">
+<p>OpenCL consists of an API for coordinating parallel computation across
+heterogeneous processors; and a cross-platform intermediate language with a
+well-specified computation environment.
+The OpenCL standard:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Supports both data- and task-based parallel programming models</p>
+</li>
+<li>
+<p>Utilizes a portable and self-contained intermediate representation with
+support for parallel execution</p>
+</li>
+<li>
+<p>Defines consistent numerical requirements based on IEEE 754</p>
+</li>
+<li>
+<p>Defines a configuration profile for handheld and embedded devices</p>
+</li>
+<li>
+<p>Efficiently interoperates with OpenGL, OpenGL ES and other graphics APIs</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>This document begins with an overview of basic concepts and the architecture
+of OpenCL, followed by a detailed description of its execution model, memory
+model and synchronization support.
+It then discusses the OpenCL platform and runtime API.
+Some examples are given that describe sample compute use-cases and how they
+would be written in OpenCL.
+The specification is divided into a core specification that any OpenCL
+compliant implementation must support; a handheld/embedded profile which
+relaxes the OpenCL compliance requirements for handheld and embedded
+devices; and a set of optional extensions that are likely to move into the
+core specification in later revisions of the OpenCL specification.</p>
+</div>
+<div class="sect2">
+<h3 id="_normative_references">1.1. Normative References</h3>
+<div class="paragraph">
+<p>Normative references are references to external documents or resources to
+which implementers of OpenCL must comply with all, or specified portions of,
+as described in this specification.</p>
+</div>
+<div id="iso-c11" class="paragraph">
+<p><em>ISO/IEC 9899:2011 - Information technology - Programming languages - C</em>,
+<a href="https://www.iso.org/standard/57853.html" class="bare">https://www.iso.org/standard/57853.html</a> (final specification),
+<a href="http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1570.pdf" class="bare">http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1570.pdf</a> (last public
+draft).</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_version_numbers">1.2. Version Numbers</h3>
+<div class="paragraph">
+<p>The OpenCL version number follows a <em>major.minor-revision</em> scheme.  When this
+version number is used within the API it generally only includes the
+<em>major.minor</em> components of the version number.</p>
+</div>
+<div class="paragraph">
+<p>A difference in the <em>major</em> or <em>minor</em> version number indicates that some
+amount of new functionality has been added to the specification, and may also
+include behavior changes and bug fixes.
+Functionality may also be deprecated or removed when the <em>major</em> or <em>minor</em>
+version changes.</p>
+</div>
+<div class="paragraph">
+<p>A difference in the <em>revision</em> number indicates small changes to the
+specification, typically to fix a bug or to clarify language.
+When the <em>revision</em> number changes there may be an impact on the behavior of
+existing functionality, but this should not affect backwards compatibility.
+Functionality should not be added or removed when the <em>revision</em> number
+changes.</p>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_glossary">2. Glossary</h2>
+<div class="sectionbody">
+<div class="dlist">
+<dl>
+<dt class="hdlist1">Application </dt>
+<dd>
+<p>The combination of the program running on the host and OpenCL devices.</p>
+</dd>
+<dt class="hdlist1">Acquire semantics </dt>
+<dd>
+<p>One of the memory order semantics defined for synchronization
+operations.
+Acquire semantics apply to atomic operations that load from memory.
+Given two units of execution, <strong>A</strong> and <strong>B</strong>, acting on a shared atomic
+object <strong>M</strong>, if <strong>A</strong> uses an atomic load of <strong>M</strong> with acquire semantics to
+synchronize-with an atomic store to <strong>M</strong> by <strong>B</strong> that used release
+semantics, then <strong>A</strong>'s atomic load will occur before any subsequent
+operations by <strong>A</strong>.
+Note that the memory orders <em>release</em>, <em>sequentially consistent</em>, and
+<em>acquire_release</em> all include <em>release semantics</em> and effectively pair
+with a load using acquire semantics.</p>
+</dd>
+<dt class="hdlist1">Acquire release semantics </dt>
+<dd>
+<p>A memory order semantics for synchronization operations (such as atomic
+operations) that has the properties of both acquire and release memory
+orders.
+It is used with read-modify-write operations.</p>
+</dd>
+<dt class="hdlist1">Atomic operations </dt>
+<dd>
+<p>Operations that at any point, and from any perspective, have either
+occurred completely, or not at all.
+Memory orders associated with atomic operations may constrain the
+visibility of loads and stores with respect to the atomic operations
+(see <em>relaxed semantics</em>, <em>acquire semantics</em>, <em>release semantics</em> or
+<em>acquire release semantics</em>).</p>
+</dd>
+<dt class="hdlist1">Blocking and Non-Blocking Enqueue API calls </dt>
+<dd>
+<p>A <em>non-blocking enqueue API call</em> places a <em>command</em> on a
+<em>command-queue</em> and returns immediately to the host.
+The <em>blocking-mode enqueue API calls</em> do not return to the host until
+the command has completed.</p>
+</dd>
+<dt class="hdlist1">Barrier </dt>
+<dd>
+<p>There are three types of <em>barriers</em> a command-queue barrier, a
+work-group barrier and a sub-group barrier.</p>
+<div class="openblock">
+<div class="content">
+<div class="ulist">
+<ul>
+<li>
+<p>The OpenCL API provides a function to enqueue a <em>command-queue</em>
+<em>barrier</em> command.
+This <em>barrier</em> command ensures that all previously enqueued commands to
+a command-queue have finished execution before any following <em>commands</em>
+enqueued in the <em>command-queue</em> can begin execution.</p>
+</li>
+<li>
+<p>The OpenCL kernel execution model provides built-in <em>work-group barrier</em>
+functionality.
+This <em>barrier</em> built-in function can be used by a <em>kernel</em> executing on
+a <em>device</em> to perform synchronization between <em>work-items</em> in a
+<em>work-group</em> executing the <em>kernel</em>.
+All the <em>work-items</em> of a <em>work-group</em> must execute the <em>barrier</em>
+construct before any are allowed to continue execution beyond the
+<em>barrier</em>.</p>
+</li>
+<li>
+<p>The OpenCL kernel execution model provides built-in <em>sub-group barrier</em>
+functionality.
+This <em>barrier</em> built-in function can be used by a <em>kernel</em> executing on
+a <em>device</em> to perform synchronization between <em>work-items</em> in a
+<em>sub-group</em> executing the <em>kernel</em>.
+All the <em>work-items</em> of a <em>sub-group</em> must execute the <em>barrier</em>
+construct before any are allowed to continue execution beyond the
+<em>barrier</em>.</p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+</dd>
+<dt class="hdlist1">Buffer Object </dt>
+<dd>
+<p>A memory object that stores a linear collection of bytes.
+Buffer objects are accessible using a pointer in a <em>kernel</em> executing on
+a <em>device</em>.
+Buffer objects can be manipulated by the host using OpenCL API calls.
+A <em>buffer object</em> encapsulates the following information:</p>
+<div class="openblock">
+<div class="content">
+<div class="ulist">
+<ul>
+<li>
+<p>Size in bytes.</p>
+</li>
+<li>
+<p>Properties that describe usage information and which region to allocate
+from.</p>
+</li>
+<li>
+<p>Buffer data.</p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+</dd>
+<dt class="hdlist1">Built-in Kernel </dt>
+<dd>
+<p>A <em>built-in kernel</em> is a <em>kernel</em> that is executed on an OpenCL <em>device</em>
+or <em>custom device</em> by fixed-function hardware or in firmware.
+<em>Applications</em> can query the <em>built-in kernels</em> supported by a <em>device</em>
+or <em>custom device</em>.
+A <em>program object</em> can only contain <em>kernels</em> written in OpenCL C or
+<em>built-in kernels</em> but not both.
+See also <em>Kernel</em> and <em>Program</em>.</p>
+</dd>
+<dt class="hdlist1">Child kernel </dt>
+<dd>
+<p>See <em>Device-side enqueue</em>.</p>
+</dd>
+<dt class="hdlist1">Command </dt>
+<dd>
+<p>The OpenCL operations that are submitted to a <em>command-queue</em> for
+execution.
+For example, OpenCL commands issue kernels for execution on a compute
+device, manipulate memory objects, etc.</p>
+</dd>
+<dt class="hdlist1">Command-queue </dt>
+<dd>
+<p>An object that holds <em>commands</em> that will be executed on a specific
+<em>device</em>.
+The <em>command-queue</em> is created on a specific <em>device</em> in a <em>context</em>.
+<em>Commands</em> to a <em>command-queue</em> are queued in-order but may be executed
+in-order or out-of-order.
+<em>Refer to In-order Execution_and_Out-of-order Execution</em>.</p>
+</dd>
+<dt class="hdlist1">Command-queue Barrier </dt>
+<dd>
+<p>See <em>Barrier</em>.</p>
+</dd>
+<dt class="hdlist1">Command synchronization </dt>
+<dd>
+<p>Constraints on the order that commands are launched for execution on a
+device defined in terms of the synchronization points that occur between
+commands in host command-queues and between commands in device-side
+command-queues.
+See <em>synchronization points</em>.</p>
+</dd>
+<dt class="hdlist1">Complete </dt>
+<dd>
+<p>The final state in the six state model for the execution of a command.
+The transition into this state occurs is signaled through event objects
+or callback functions associated with a command.</p>
+</dd>
+<dt class="hdlist1">Compute Device Memory </dt>
+<dd>
+<p>This refers to one or more memories attached to the compute device.</p>
+</dd>
+<dt class="hdlist1">Compute Unit </dt>
+<dd>
+<p>An OpenCL <em>device</em> has one or more <em>compute units</em>.
+A <em>work-group</em> executes on a single <em>compute unit</em>.
+A <em>compute unit</em> is composed of one or more <em>processing elements</em> and
+<em>local memory</em>.
+A <em>compute unit</em> may also include dedicated texture filter units that
+can be accessed by its processing elements.</p>
+</dd>
+<dt class="hdlist1">Concurrency </dt>
+<dd>
+<p>A property of a system in which a set of tasks in a system can remain
+active and make progress at the same time.
+To utilize concurrent execution when running a program, a programmer
+must identify the concurrency in their problem, expose it within the
+source code, and then exploit it using a notation that supports
+concurrency.</p>
+</dd>
+<dt class="hdlist1">Constant Memory </dt>
+<dd>
+<p>A region of <em>global memory</em> that remains constant during the execution
+of a <em>kernel</em>.
+The <em>host</em> allocates and initializes memory objects placed into
+<em>constant memory</em>.</p>
+</dd>
+<dt class="hdlist1">Context </dt>
+<dd>
+<p>The environment within which the kernels execute and the domain in which
+synchronization and memory management is defined.
+The <em>context</em> includes a set of <em>devices</em>, the memory accessible to
+those <em>devices</em>, the corresponding memory properties and one or more
+<em>command-queues</em> used to schedule execution of a <em>kernel(s)</em> or
+operations on <em>memory objects</em>.</p>
+</dd>
+<dt class="hdlist1">Control flow </dt>
+<dd>
+<p>The flow of instructions executed by a work-item.
+Multiple logically related work items may or may not execute the same
+control flow.
+The control flow is said to be <em>converged</em> if all the work-items in the
+set execution the same stream of instructions.
+In a <em>diverged</em> control flow, the work-items in the set execute
+different instructions.
+At a later point, if a diverged control flow becomes converged, it is
+said to be a re-converged control flow.</p>
+</dd>
+<dt class="hdlist1">Converged control flow </dt>
+<dd>
+<p>See <em>Control flow</em>.</p>
+</dd>
+<dt class="hdlist1">Custom Device </dt>
+<dd>
+<p>An OpenCL <em>device</em> that fully implements the OpenCL Runtime but does not
+support <em>programs</em> written in OpenCL C.
+A custom device may be specialized non-programmable hardware that is
+very power efficient and performant for directed tasks or hardware with
+limited programmable capabilities such as specialized DSPs.
+Custom devices are not OpenCL conformant.
+Custom devices may support an online compiler.
+Programs for custom devices can be created using the OpenCL runtime APIs
+that allow OpenCL programs to be created from source (if an online
+compiler is supported) and/or binary, or from <em>built-in kernels</em>
+supported by the <em>device</em>.
+See also <em>Device</em>.</p>
+</dd>
+<dt class="hdlist1">Data Parallel Programming Model </dt>
+<dd>
+<p>Traditionally, this term refers to a programming model where concurrency
+is expressed as instructions from a single program applied to multiple
+elements within a set of data structures.
+The term has been generalized in OpenCL to refer to a model wherein a
+set of instructions from a single program are applied concurrently to
+each point within an abstract domain of indices.</p>
+</dd>
+<dt class="hdlist1">Data race </dt>
+<dd>
+<p>The execution of a program contains a data race if it contains two
+actions in different work items or host threads where (1) one action
+modifies a memory location and the other action reads or modifies the
+same memory location, and (2) at least one of these actions is not
+atomic, or the corresponding memory scopes are not inclusive, and (3)
+the actions are global actions unordered by the global-happens-before
+relation or are local actions unordered by the local-happens before
+relation.</p>
+</dd>
+<dt class="hdlist1">Deprecation </dt>
+<dd>
+<p>Existing features are marked as deprecated if their usage is not
+recommended as that feature is being de-emphasized, superseded and may
+be removed from a future version of the specification.</p>
+</dd>
+<dt class="hdlist1">Device </dt>
+<dd>
+<p>A <em>device</em> is a collection of <em>compute units</em>.
+A <em>command-queue</em> is used to queue <em>commands</em> to a <em>device</em>.
+Examples of <em>commands</em> include executing <em>kernels</em>, or reading and
+writing <em>memory objects</em>.
+OpenCL devices typically correspond to a GPU, a multi-core CPU, and
+other processors such as DSPs and the Cell/B.E.
+processor.</p>
+</dd>
+<dt class="hdlist1">Device-side enqueue </dt>
+<dd>
+<p>A mechanism whereby a kernel-instance is enqueued by a kernel-instance
+running on a device without direct involvement by the host program.
+This produces <em>nested parallelism</em>; i.e. additional levels of
+concurrency are nested inside a running kernel-instance.
+The kernel-instance executing on a device (the <em>parent kernel</em>) enqueues
+a kernel-instance (the <em>child kernel</em>) to a device-side command queue.
+Child and parent kernels execute asynchronously though a parent kernel
+does not complete until all of its child-kernels have completed.</p>
+</dd>
+<dt class="hdlist1">Diverged control flow </dt>
+<dd>
+<p>See <em>Control flow</em>.</p>
+</dd>
+<dt class="hdlist1">Ended </dt>
+<dd>
+<p>The fifth state in the six state model for the execution of a command.
+The transition into this state occurs when execution of a command has
+ended.
+When a Kernel-enqueue command ends, all of the work-groups associated
+with that command have finished their execution.</p>
+</dd>
+<dt class="hdlist1">Event Object </dt>
+<dd>
+<p>An <em>event object</em> encapsulates the status of an operation such as a
+<em>command</em>.
+It can be used to synchronize operations in a context.</p>
+</dd>
+<dt class="hdlist1">Event Wait List </dt>
+<dd>
+<p>An <em>event wait list</em> is a list of <em>event objects</em> that can be used to
+control when a particular <em>command</em> begins execution.</p>
+</dd>
+<dt class="hdlist1">Fence </dt>
+<dd>
+<p>A memory ordering operation without an associated atomic object.
+A fence can use the <em>acquire semantics, release semantics</em>, or <em>acquire
+release semantics</em>.</p>
+</dd>
+<dt class="hdlist1">Framework </dt>
+<dd>
+<p>A software system that contains the set of components to support
+software development and execution.
+A <em>framework</em> typically includes libraries, APIs, runtime systems,
+compilers, etc.</p>
+</dd>
+<dt class="hdlist1">Generic address space </dt>
+<dd>
+<p>An address space that include the <em>private</em>, <em>local</em>, and <em>global</em>
+address spaces available to a device.
+The generic address space supports conversion of pointers to and from
+private, local and global address spaces, and hence lets a programmer
+write a single function that at compile time can take arguments from any
+of the three named address spaces.</p>
+</dd>
+<dt class="hdlist1">Global Happens before </dt>
+<dd>
+<p>See <em>Happens before</em>.</p>
+</dd>
+<dt class="hdlist1">Global ID </dt>
+<dd>
+<p>A <em>global ID</em> is used to uniquely identify a <em>work-item</em> and is derived
+from the number of <em>global work-items</em> specified when executing a
+<em>kernel</em>.
+The <em>global ID</em> is a N-dimensional value that starts at (0, 0, &#8230;&#8203; 0).
+See also <em>Local ID</em>.</p>
+</dd>
+<dt class="hdlist1">Global Memory </dt>
+<dd>
+<p>A memory region accessible to all <em>work-items</em> executing in a <em>context</em>.
+It is accessible to the <em>host</em> using <em>commands</em> such as read, write and
+map.
+<em>Global memory</em> is included within the <em>generic address space</em> that
+includes the private and local address spaces.</p>
+</dd>
+<dt class="hdlist1">GL share group </dt>
+<dd>
+<p>A <em>GL share group</em> object manages shared OpenGL or OpenGL ES resources
+such as textures, buffers, framebuffers, and renderbuffers and is
+associated with one or more GL context objects.
+The <em>GL share group</em> is typically an opaque object and not directly
+accessible.</p>
+</dd>
+<dt class="hdlist1">Handle </dt>
+<dd>
+<p>An opaque type that references an <em>object</em> allocated by OpenCL.
+Any operation on an <em>object</em> occurs by reference to that objects handle.</p>
+</dd>
+<dt class="hdlist1">Happens before </dt>
+<dd>
+<p>An ordering relationship between operations that execute on multiple
+units of execution.
+If an operation A happens-before operation B then A must occur before B;
+in particular, any value written by A will be visible to B.
+We define two separate happens before relations: <em>global-happens-before</em>
+and <em>local-happens-before</em>.
+These are defined in <a href="#memory-ordering-rules">Memory Model: Memory
+Ordering Rules</a>.</p>
+</dd>
+<dt class="hdlist1">Host </dt>
+<dd>
+<p>The <em>host</em> interacts with the <em>context</em> using the OpenCL API.</p>
+</dd>
+<dt class="hdlist1">Host-thread </dt>
+<dd>
+<p>The unit of execution that executes the statements in the host program.</p>
+</dd>
+<dt class="hdlist1">Host pointer </dt>
+<dd>
+<p>A pointer to memory that is in the virtual address space on the <em>host</em>.</p>
+</dd>
+<dt class="hdlist1">Illegal </dt>
+<dd>
+<p>Behavior of a system that is explicitly not allowed and will be reported
+as an error when encountered by OpenCL.</p>
+</dd>
+<dt class="hdlist1">Image Object </dt>
+<dd>
+<p>A <em>memory object</em> that stores a two- or three-dimensional structured
+array.
+Image data can only be accessed with read and write functions.
+The read functions use a <em>sampler</em>.</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>The <em>image object</em> encapsulates the following information:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Dimensions of the image.</p>
+</li>
+<li>
+<p>Description of each element in the image.</p>
+</li>
+<li>
+<p>Properties that describe usage information and which region to allocate
+from.</p>
+</li>
+<li>
+<p>Image data.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The elements of an image are selected from a list of predefined image
+formats.</p>
+</div>
+</div>
+</div>
+</dd>
+<dt class="hdlist1">Implementation Defined </dt>
+<dd>
+<p>Behavior that is explicitly allowed to vary between conforming
+implementations of OpenCL.
+An OpenCL implementor is required to document the implementation-defined
+behavior.</p>
+</dd>
+<dt class="hdlist1">Independent Forward Progress </dt>
+<dd>
+<p>If an entity supports independent forward progress, then if it is
+otherwise not dependent on any actions due to be performed by any other
+entity (for example it does not wait on a lock held by, and thus that
+must be released by, any other entity), then its execution cannot be
+blocked by the execution of any other entity in the system (it will not
+be starved).
+Work items in a subgroup, for example, typically do not support
+independent forward progress, so one work item in a subgroup may be
+completely blocked (starved) if a different work item in the same
+subgroup enters a spin loop.</p>
+</dd>
+<dt class="hdlist1">In-order Execution </dt>
+<dd>
+<p>A model of execution in OpenCL where the <em>commands</em> in a <em>command-queue</em>
+are executed in order of submission with each <em>command</em> running to
+completion before the next one begins.
+See Out-of-order Execution.</p>
+</dd>
+<dt class="hdlist1">Intermediate Language </dt>
+<dd>
+<p>A lower-level language that may be used to create programs.
+SPIR-V is a required IL for OpenCL 2.2 runtimes.
+Additional ILs may be accepted on an implementation-defined basis.</p>
+</dd>
+<dt class="hdlist1">Kernel </dt>
+<dd>
+<p>A <em>kernel</em> is a function declared in a <em>program</em> and executed on an
+OpenCL <em>device</em>.
+A <em>kernel</em> is identified by the kernel or kernel qualifier applied to
+any function defined in a <em>program</em>.</p>
+</dd>
+<dt class="hdlist1">Kernel-instance </dt>
+<dd>
+<p>The work carried out by an OpenCL program occurs through the execution
+of kernel-instances on devices.
+The kernel instance is the <em>kernel object</em>, the values associated with
+the arguments to the kernel, and the parameters that define the
+<em>NDRange</em> index space.</p>
+</dd>
+<dt class="hdlist1">Kernel Object </dt>
+<dd>
+<p>A <em>kernel object</em> encapsulates a specific <code>__kernel</code> function declared
+in a <em>program</em> and the argument values to be used when executing this
+<code>__kernel</code> function.</p>
+</dd>
+<dt class="hdlist1">Kernel Language </dt>
+<dd>
+<p>A language that is used to create source code for kernel.
+Supported kernel languages include OpenCL C, OpenCL C++, and OpenCL
+dialect of SPIR-V.</p>
+</dd>
+<dt class="hdlist1">Launch </dt>
+<dd>
+<p>The transition of a command from the <em>submitted</em> state to the <em>ready</em>
+state.
+See <em>Ready</em>.</p>
+</dd>
+<dt class="hdlist1">Local ID </dt>
+<dd>
+<p>A <em>local ID</em> specifies a unique <em>work-item ID</em> within a given
+<em>work-group</em> that is executing a <em>kernel</em>.
+The <em>local ID</em> is a N-dimensional value that starts at (0, 0, &#8230;&#8203; 0).
+See also <em>Global ID</em>.</p>
+</dd>
+<dt class="hdlist1">Local Memory </dt>
+<dd>
+<p>A memory region associated with a <em>work-group</em> and accessible only by
+<em>work-items</em> in that <em>work-group</em>.
+<em>Local memory</em> is included within the <em>generic address space</em> that
+includes the private and global address spaces.</p>
+</dd>
+<dt class="hdlist1">Marker </dt>
+<dd>
+<p>A <em>command</em> queued in a <em>command-queue</em> that can be used to tag all
+<em>commands</em> queued before the <em>marker</em> in the <em>command-queue</em>.
+The <em>marker</em> command returns an <em>event</em> which can be used by the
+<em>application</em> to queue a wait on the marker event i.e. wait for all
+commands queued before the <em>marker</em> command to complete.</p>
+</dd>
+<dt class="hdlist1">Memory Consistency Model </dt>
+<dd>
+<p>Rules that define which values are observed when multiple units of
+execution load data from any shared memory plus the synchronization
+operations that constrain the order of memory operations and define
+synchronization relationships.
+The memory consistency model in OpenCL is based on the memory model from
+the ISO C11 programming language.</p>
+</dd>
+<dt class="hdlist1">Memory Objects </dt>
+<dd>
+<p>A <em>memory object</em> is a handle to a reference counted region of <em>Global
+Memory</em>.
+Also see <em>Buffer Object</em> and <em>Image Object</em>.</p>
+</dd>
+<dt class="hdlist1">Memory Regions (or Pools) </dt>
+<dd>
+<p>A distinct address space in OpenCL.
+<em>Memory regions</em> may overlap in physical memory though OpenCL will treat
+them as logically distinct.
+The <em>memory regions</em> are denoted as <em>private</em>, <em>local</em>, <em>constant,</em> and
+<em>global</em>.</p>
+</dd>
+<dt class="hdlist1">Memory Scopes </dt>
+<dd>
+<p>These memory scopes define a hierarchy of visibilities when analyzing
+the ordering constraints of memory operations.
+They are defined by the values of the <strong>memory_scope</strong> enumeration
+constant.
+Current values are <strong>memory_scope_work_item</strong> (memory constraints only
+apply to a single work-item and in practice apply only to image
+operations), <strong>memory_scope_sub_group</strong> (memory-ordering constraints only
+apply to work-items executing in a sub-group), <strong>memory_scope_work_group</strong>
+(memory-ordering constraints only apply to work-items executing in a
+work-group), <strong>memory_scope_device</strong> (memory-ordering constraints only
+apply to work-items executing on a single device) and
+<strong>memory_scope_all_svm_devices</strong> (memory-ordering constraints only apply
+to work-items executing across multiple devices and when using shared
+virtual memory).</p>
+</dd>
+<dt class="hdlist1">Modification Order </dt>
+<dd>
+<p>All modifications to a particular atomic object M occur in some
+particular <em>total order</em>, called the <em>modification order</em> of M.
+If A and B are modifications of an atomic object M, and A happens-before
+B, then A shall precede B in the modification order of M.
+Note that the modification order of an atomic object M is independent of
+whether M is in local or global memory.</p>
+</dd>
+<dt class="hdlist1">Nested Parallelism </dt>
+<dd>
+<p>See <em>device-side enqueue</em>.</p>
+</dd>
+<dt class="hdlist1">Object </dt>
+<dd>
+<p>Objects are abstract representation of the resources that can be
+manipulated by the OpenCL API.
+Examples include <em>program objects</em>, <em>kernel objects</em>, and <em>memory
+objects</em>.</p>
+</dd>
+<dt class="hdlist1">Out-of-Order Execution </dt>
+<dd>
+<p>A model of execution in which <em>commands</em> placed in the <em>work queue</em> may
+begin and complete execution in any order consistent with constraints
+imposed by <em>event wait lists_and_command-queue barrier</em>.
+See <em>In-order Execution</em>.</p>
+</dd>
+<dt class="hdlist1">Parent device </dt>
+<dd>
+<p>The OpenCL <em>device</em> which is partitioned to create <em>sub-devices</em>.
+Not all <em>parent devices</em> are <em>root devices</em>.
+A <em>root device</em> might be partitioned and the <em>sub-devices</em> partitioned
+again.
+In this case, the first set of <em>sub-devices</em> would be <em>parent devices</em>
+of the second set, but not the <em>root devices</em>.
+Also see <em>Device</em>, <em>parent device</em> and <em>root device</em>.</p>
+</dd>
+<dt class="hdlist1">Parent kernel </dt>
+<dd>
+<p>see <em>Device-side enqueue</em>.</p>
+</dd>
+<dt class="hdlist1">Pipe </dt>
+<dd>
+<p>The <em>pipe</em> memory object conceptually is an ordered sequence of data
+items.
+A pipe has two endpoints: a write endpoint into which data items are
+inserted, and a read endpoint from which data items are removed.
+At any one time, only one kernel instance may write into a pipe, and
+only one kernel instance may read from a pipe.
+To support the producer consumer design pattern, one kernel instance
+connects to the write endpoint (the producer) while another kernel
+instance connects to the reading endpoint (the consumer).</p>
+</dd>
+<dt class="hdlist1">Platform </dt>
+<dd>
+<p>The <em>host</em> plus a collection of <em>devices</em> managed by the OpenCL
+<em>framework</em> that allow an application to share <em>resources</em> and execute
+<em>kernels</em> on <em>devices</em> in the <em>platform</em>.</p>
+</dd>
+<dt class="hdlist1">Private Memory </dt>
+<dd>
+<p>A region of memory private to a <em>work-item</em>.
+Variables defined in one <em>work-items</em> <em>private memory</em> are not visible
+to another <em>work-item</em>.</p>
+</dd>
+<dt class="hdlist1">Processing Element </dt>
+<dd>
+<p>A virtual scalar processor.
+A work-item may execute on one or more processing elements.</p>
+</dd>
+<dt class="hdlist1">Program </dt>
+<dd>
+<p>An OpenCL <em>program</em> consists of a set of <em>kernels</em>.
+<em>Programs</em> may also contain auxiliary functions called by the
+<code>__kernel</code> functions and constant data.</p>
+</dd>
+<dt class="hdlist1">Program Object </dt>
+<dd>
+<p>A <em>program object</em> encapsulates the following information:</p>
+<div class="openblock">
+<div class="content">
+<div class="ulist">
+<ul>
+<li>
+<p>A reference to an associated <em>context</em>.</p>
+</li>
+<li>
+<p>A <em>program</em> source or binary.</p>
+</li>
+<li>
+<p>The latest successfully built program executable, the list of <em>devices</em>
+for which the program executable is built, the build options used and a
+build log.</p>
+</li>
+<li>
+<p>The number of <em>kernel objects</em> currently attached.</p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+</dd>
+<dt class="hdlist1">Queued </dt>
+<dd>
+<p>The first state in the six state model for the execution of a command.
+The transition into this state occurs when the command is enqueued into
+a command-queue.</p>
+</dd>
+<dt class="hdlist1">Ready </dt>
+<dd>
+<p>The third state in the six state model for the execution of a command.
+The transition into this state occurs when pre-requisites constraining
+execution of a command have been met; i.e. the command has been
+launched.
+When a kernel-enqueue command is launched, work-groups associated with
+the command are placed in a devices work-pool from which they are
+scheduled for execution.</p>
+</dd>
+<dt class="hdlist1">Re-converged Control Flow </dt>
+<dd>
+<p>see <em>Control flow</em>.</p>
+</dd>
+<dt class="hdlist1">Reference Count </dt>
+<dd>
+<p>The life span of an OpenCL object is determined by its <em>reference
+count</em>, an internal count of the number of references to the object.
+When you create an object in OpenCL, its <em>reference count</em> is set to
+one.
+Subsequent calls to the appropriate <em>retain</em> API (such as
+<strong>clRetainContext</strong>, <strong>clRetainCommandQueue</strong>) increment the <em>reference
+count</em>.
+Calls to the appropriate <em>release</em> API (such as <strong>clReleaseContext</strong>,
+<strong>clReleaseCommandQueue</strong>) decrement the <em>reference count</em>.
+Implementations may also modify the <em>reference count</em>, e.g. to track
+attached objects or to ensure correct operation of in-progress or
+scheduled activities.
+The object becomes inaccessible to host code when the number of
+<em>release</em> operations performed matches the number of <em>retain</em> operations
+plus the allocation of the object.
+At this point the reference count may be zero but this is not
+guaranteed.</p>
+</dd>
+<dt class="hdlist1">Relaxed Consistency </dt>
+<dd>
+<p>A memory consistency model in which the contents of memory visible to
+different <em>work-items</em> or <em>commands</em> may be different except at a
+<em>barrier</em> or other explicit synchronization points.</p>
+</dd>
+<dt class="hdlist1">Relaxed Semantics </dt>
+<dd>
+<p>A memory order semantics for atomic operations that implies no order
+constraints.
+The operation is <em>atomic</em> but it has no impact on the order of memory
+operations.</p>
+</dd>
+<dt class="hdlist1">Release Semantics </dt>
+<dd>
+<p>One of the memory order semantics defined for synchronization
+operations.
+Release semantics apply to atomic operations that store to memory.
+Given two units of execution, <strong>A</strong> and <strong>B</strong>, acting on a shared atomic
+object <strong>M</strong>, if <strong>A</strong> uses an atomic store of <strong>M</strong> with release semantics to
+synchronize-with an atomic load to <strong>M</strong> by <strong>B</strong> that used acquire
+semantics, then <strong>A</strong>'s atomic store will occur <em>after</em> any prior
+operations by <strong>A</strong>.
+Note that the memory orders <em>acquire</em>, <em>sequentialy consistent</em>, and
+<em>acquire_release</em> all include <em>acquire semantics</em> and effectively pair
+with a store using release semantics.</p>
+</dd>
+<dt class="hdlist1">Remainder work-groups </dt>
+<dd>
+<p>When the work-groups associated with a kernel-instance are defined, the
+sizes of a work-group in each dimension may not evenly divide the size
+of the NDRange in the corresponding dimensions.
+The result is a collection of work-groups on the boundaries of the
+NDRange that are smaller than the base work-group size.
+These are known as <em>remainder work-groups</em>.</p>
+</dd>
+<dt class="hdlist1">Running </dt>
+<dd>
+<p>The fourth state in the six state model for the execution of a command.
+The transition into this state occurs when the execution of the command
+starts.
+When a Kernel-enqueue command starts, one or more work-groups associated
+with the command start to execute.</p>
+</dd>
+<dt class="hdlist1">Root device </dt>
+<dd>
+<p>A <em>root device</em> is an OpenCL <em>device</em> that has not been partitioned.
+Also see <em>Device</em>, <em>Parent device</em> and <em>Root device</em>.</p>
+</dd>
+<dt class="hdlist1">Resource </dt>
+<dd>
+<p>A class of <em>objects</em> defined by OpenCL.
+An instance of a <em>resource</em> is an <em>object</em>.
+The most common <em>resources</em> are the <em>context</em>, <em>command-queue</em>, <em>program
+objects</em>, <em>kernel objects</em>, and <em>memory objects</em>.
+Computational resources are hardware elements that participate in the
+action of advancing a program counter.
+Examples include the <em>host</em>, <em>devices</em>, <em>compute units</em> and <em>processing
+elements</em>.</p>
+</dd>
+<dt class="hdlist1">Retain, Release </dt>
+<dd>
+<p>The action of incrementing (retain) and decrementing (release) the
+reference count using an OpenCL <em>object</em>.
+This is a book keeping functionality to make sure the system doesnt
+remove an <em>object</em> before all instances that use this <em>object</em> have
+finished.
+Refer to <em>Reference Count</em>.</p>
+</dd>
+<dt class="hdlist1">Sampler </dt>
+<dd>
+<p>An <em>object</em> that describes how to sample an image when the image is read
+in the <em>kernel</em>.
+The image read functions take a <em>sampler</em> as an argument.
+The <em>sampler</em> specifies the image addressing-mode i.e. how out-of-range
+image coordinates are handled, the filter mode, and whether the input
+image coordinate is a normalized or unnormalized value.</p>
+</dd>
+<dt class="hdlist1">Scope inclusion </dt>
+<dd>
+<p>Two actions <strong>A</strong> and <strong>B</strong> are defined to have an inclusive scope if they
+have the same scope <strong>P</strong> such that: (1) if <strong>P</strong> is
+<strong>memory_scope_sub_group</strong>, and <strong>A</strong> and <strong>B</strong> are executed by work-items
+within the same sub-group, or (2) if <strong>P</strong> is <strong>memory_scope_work_group</strong>,
+and <strong>A</strong> and <strong>B</strong> are executed by work-items within the same work-group,
+or (3) if <strong>P</strong> is <strong>memory_scope_device</strong>, and <strong>A</strong> and <strong>B</strong> are executed by
+work-items on the same device, or (4) if <strong>P</strong> is
+<strong>memory_scope_all_svm_devices</strong>, if <strong>A</strong> and <strong>B</strong> are executed by host
+threads or by work-items on one or more devices that can share SVM
+memory with each other and the host process.</p>
+</dd>
+<dt class="hdlist1">Sequenced before </dt>
+<dd>
+<p>A relation between evaluations executed by a single unit of execution.
+Sequenced-before is an asymmetric, transitive, pair-wise relation that
+induces a partial order between evaluations.
+Given any two evaluations A and B, if A is sequenced-before B, then the
+execution of A shall precede the execution of B.</p>
+</dd>
+<dt class="hdlist1">Sequential consistency </dt>
+<dd>
+<p>Sequential consistency interleaves the steps executed by each unit of
+execution.
+Each access to a memory location sees the last assignment to that
+location in that interleaving.</p>
+</dd>
+<dt class="hdlist1">Sequentially consistent semantics </dt>
+<dd>
+<p>One of the memory order semantics defined for synchronization
+operations.
+When using sequentially-consistent synchronization operations, the loads
+and stores within one unit of execution appear to execute in program
+order (i.e., the sequenced-before order), and loads and stores from
+different units of execution appear to be simply interleaved.</p>
+</dd>
+<dt class="hdlist1">Shared Virtual Memory (SVM) </dt>
+<dd>
+<p>An address space exposed to both the host and the devices within a
+context.
+SVM causes addresses to be meaningful between the host and all of the
+devices within a context and therefore supports the use of pointer based
+data structures in OpenCL kernels.
+It logically extends a portion of the global memory into the host
+address space therefore giving work-items access to the host address
+space.
+There are three types of SVM in OpenCL:</p>
+<div class="openblock">
+<div class="content">
+<div class="dlist">
+<dl>
+<dt class="hdlist1"><em>Coarse-Grained buffer SVM</em> </dt>
+<dd>
+<p>Sharing occurs at the granularity of regions of OpenCL buffer memory
+objects.</p>
+</dd>
+<dt class="hdlist1"><em>Fine-Grained buffer SVM</em> </dt>
+<dd>
+<p>Sharing occurs at the granularity of individual loads/stores into bytes
+within OpenCL buffer memory objects.</p>
+</dd>
+<dt class="hdlist1"><em>Fine-Grained system SVM</em> </dt>
+<dd>
+<p>Sharing occurs at the granularity of individual loads/stores into bytes
+occurring anywhere within the host memory.</p>
+</dd>
+</dl>
+</div>
+</div>
+</div>
+</dd>
+<dt class="hdlist1">SIMD </dt>
+<dd>
+<p>Single Instruction Multiple Data.
+A programming model where a <em>kernel</em> is executed concurrently on
+multiple <em>processing elements</em> each with its own data and a shared
+program counter.
+All <em>processing elements</em> execute a strictly identical set of
+instructions.</p>
+</dd>
+<dt class="hdlist1">Specialization constants </dt>
+<dd>
+<p>Specialization is intended for constant objects that will not have known
+constant values until after initial generation of a SPIR-V module.
+Such objects are called specialization constants.
+Application might provide values for the specialization constants that
+will be used when SPIR-V program is built.
+Specialization constants that do not receive a value from an application
+shall use default value as defined in SPIR-V specification.</p>
+</dd>
+<dt class="hdlist1">SPMD </dt>
+<dd>
+<p>Single Program Multiple Data.
+A programming model where a <em>kernel</em> is executed concurrently on
+multiple <em>processing elements</em> each with its own data and its own
+program counter.
+Hence, while all computational resources run the same <em>kernel</em> they
+maintain their own instruction counter and due to branches in a
+<em>kernel</em>, the actual sequence of instructions can be quite different
+across the set of <em>processing elements</em>.</p>
+</dd>
+<dt class="hdlist1">Sub-device </dt>
+<dd>
+<p>An OpenCL <em>device</em> can be partitioned into multiple <em>sub-devices</em>.
+The new <em>sub-devices</em> alias specific collections of compute units within
+the parent <em>device</em>, according to a partition scheme.
+The <em>sub-devices</em> may be used in any situation that their parent
+<em>device</em> may be used.
+Partitioning a <em>device</em> does not destroy the parent <em>device</em>, which may
+continue to be used along side and intermingled with its child
+<em>sub-devices</em>.
+Also see <em>Device</em>, <em>Parent device</em> and <em>Root device</em>.</p>
+</dd>
+<dt class="hdlist1">Sub-group </dt>
+<dd>
+<p>Sub-groups are an implementation-dependent grouping of work-items within
+a work-group.
+The size and number of sub-groups is implementation-defined.</p>
+</dd>
+<dt class="hdlist1">Sub-group Barrier </dt>
+<dd>
+<p>See <em>Barrier</em>.</p>
+</dd>
+<dt class="hdlist1">Submitted </dt>
+<dd>
+<p>The second state in the six state model for the execution of a command.
+The transition into this state occurs when the command is flushed from
+the command-queue and submitted for execution on the device.
+Once submitted, a programmer can assume a command will execute once its
+prerequisites have been met.</p>
+</dd>
+<dt class="hdlist1">SVM Buffer </dt>
+<dd>
+<p>A memory allocation enabled to work with <em>Shared Virtual Memory (SVM)</em>.
+Depending on how the SVM buffer is created, it can be a coarse-grained
+or fine-grained SVM buffer.
+Optionally it may be wrapped by a <em>Buffer Object</em>.
+See <em>Shared Virtual Memory (SVM)</em>.</p>
+</dd>
+<dt class="hdlist1">Synchronization </dt>
+<dd>
+<p>Synchronization refers to mechanisms that constrain the order of
+execution and the visibility of memory operations between two or more
+units of execution.</p>
+</dd>
+<dt class="hdlist1">Synchronization operations </dt>
+<dd>
+<p>Operations that define memory order constraints in a program.
+They play a special role in controlling how memory operations in one
+unit of execution (such as work-items or, when using SVM a host thread)
+are made visible to another.
+Synchronization operations in OpenCL include <em>atomic operations</em> and
+<em>fences</em>.</p>
+</dd>
+<dt class="hdlist1">Synchronization point </dt>
+<dd>
+<p>A synchronization point between a pair of commands (A and B) assures
+that results of command A happens-before command B is launched (i.e.
+enters the ready state) .</p>
+</dd>
+<dt class="hdlist1">Synchronizes with </dt>
+<dd>
+<p>A relation between operations in two different units of execution that
+defines a memory order constraint in global memory
+(<em>global-synchronizes-with</em>) or local memory
+(<em>local-synchronizes-with</em>).</p>
+</dd>
+<dt class="hdlist1">Task Parallel Programming Model </dt>
+<dd>
+<p>A programming model in which computations are expressed in terms of
+multiple concurrent tasks executing in one or more <em>command-queues</em>.
+The concurrent tasks can be running different <em>kernels</em>.</p>
+</dd>
+<dt class="hdlist1">Thread-safe </dt>
+<dd>
+<p>An OpenCL API call is considered to be <em>thread-safe</em> if the internal
+state as managed by OpenCL remains consistent when called simultaneously
+by multiple <em>host</em> threads.
+OpenCL API calls that are <em>thread-safe</em> allow an application to call
+these functions in multiple <em>host</em> threads without having to implement
+mutual exclusion across these <em>host</em> threads i.e. they are also
+re-entrant-safe.</p>
+</dd>
+<dt class="hdlist1">Undefined </dt>
+<dd>
+<p>The behavior of an OpenCL API call, built-in function used inside a
+<em>kernel</em> or execution of a <em>kernel</em> that is explicitly not defined by
+OpenCL.
+A conforming implementation is not required to specify what occurs when
+an undefined construct is encountered in OpenCL.</p>
+</dd>
+<dt class="hdlist1">Unit of execution </dt>
+<dd>
+<p>A generic term for a process, OS managed thread running on the host (a
+host-thread), kernel-instance, host program, work-item or any other
+executable agent that advances the work associated with a program.</p>
+</dd>
+<dt class="hdlist1">Work-group </dt>
+<dd>
+<p>A collection of related <em>work-items</em> that execute on a single <em>compute
+unit</em>.
+The <em>work-items</em> in the group execute the same <em>kernel-instance</em> and
+share <em>local</em> <em>memory</em> and <em>work-group functions</em>.</p>
+</dd>
+<dt class="hdlist1">Work-group Barrier </dt>
+<dd>
+<p>See <em>Barrier</em>.</p>
+</dd>
+<dt class="hdlist1">Work-group Function </dt>
+<dd>
+<p>A function that carries out collective operations across all the
+work-items in a work-group.
+Available collective operations are a barrier, reduction, broadcast,
+prefix sum, and evaluation of a predicate.
+A work-group function must occur within a <em>converged control flow</em>; i.e.
+all work-items in the work-group must encounter precisely the same
+work-group function.</p>
+</dd>
+<dt class="hdlist1">Work-group Synchronization </dt>
+<dd>
+<p>Constraints on the order of execution for work-items in a single
+work-group.</p>
+</dd>
+<dt class="hdlist1">Work-pool </dt>
+<dd>
+<p>A logical pool associated with a device that holds commands and
+work-groups from kernel-instances that are ready to execute.
+OpenCL does not constrain the order that commands and work-groups are
+scheduled for execution from the work-pool; i.e. a programmer must
+assume that they could be interleaved.
+There is one work-pool per device used by all command-queues associated
+with that device.
+The work-pool may be implemented in any manner as long as it assures
+that work-groups placed in the pool will eventually execute.</p>
+</dd>
+<dt class="hdlist1">Work-item </dt>
+<dd>
+<p>One of a collection of parallel executions of a <em>kernel</em> invoked on a
+<em>device</em> by a <em>command</em>.
+A <em>work-item</em> is executed by one or more <em>processing elements</em> as part
+of a <em>work-group</em> executing on a <em>compute unit</em>.
+A <em>work-item</em> is distinguished from other work-items by its <em>global ID</em>
+or the combination of its <em>work-group</em> ID and its <em>local ID</em> within a
+<em>work-group</em>.</p>
+</dd>
+</dl>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_the_opencl_architecture">3. The OpenCL Architecture</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p><strong>OpenCL</strong> is an open industry standard for programming a heterogeneous
+collection of CPUs, GPUs and other discrete computing devices organized into
+a single platform.
+It is more than a language.
+OpenCL is a framework for parallel programming and includes a language, API,
+libraries and a runtime system to support software development.
+Using OpenCL, for example, a programmer can write general purpose programs
+that execute on GPUs without the need to map their algorithms onto a 3D
+graphics API such as OpenGL or DirectX.</p>
+</div>
+<div class="paragraph">
+<p>The target of OpenCL is expert programmers wanting to write portable yet
+efficient code.
+This includes library writers, middleware vendors, and performance oriented
+application programmers.
+Therefore OpenCL provides a low-level hardware abstraction plus a framework
+to support programming and many details of the underlying hardware are
+exposed.</p>
+</div>
+<div class="paragraph">
+<p>To describe the core ideas behind OpenCL, we will use a hierarchy of models:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Platform Model</p>
+</li>
+<li>
+<p>Memory Model</p>
+</li>
+<li>
+<p>Execution Model</p>
+</li>
+<li>
+<p>Programming Model</p>
+</li>
+</ul>
+</div>
+<div class="sect2">
+<h3 id="_platform_model">3.1. Platform Model</h3>
+<div class="paragraph">
+<p>The <a href="#platform-model-image">Platform model</a> for OpenCL is defined below.
+The model consists of a <strong>host</strong> connected to one or more <strong>OpenCL devices</strong>.
+An OpenCL device is divided into one or more <strong>compute units</strong> (CUs) which are
+further divided into one or more <strong>processing elements</strong> (PEs).
+Computations on a device occur within the processing elements.</p>
+</div>
+<div class="paragraph">
+<p>An OpenCL application is implemented as both host code and device kernel
+code.
+The host code portion of an OpenCL application runs on a host processor
+according to the models native to the host platform.
+The OpenCL application host code submits the kernel code as commands from
+the host to OpenCL devices.
+An OpenCL device executes the commands computation on the processing
+elements within the device.</p>
+</div>
+<div class="paragraph">
+<p>An OpenCL device has considerable latitude on how computations are mapped
+onto the devices processing elements.
+When processing elements within a compute unit execute the same sequence of
+statements across the processing elements, the control flow is said to be
+<em>converged</em>.
+Hardware optimized for executing a single stream of instructions over
+multiple processing elements is well suited to converged control flows.
+When the control flow varies from one processing element to another, it is
+said to be <em>diverged</em>.
+While a kernel always begins execution with a converged control flow, due to
+branching statements within a kernel, converged and diverged control flows
+may occur within a single kernel.
+This provides a great deal of flexibility in the algorithms that can be
+implemented with OpenCL.</p>
+</div>
+<div id="platform-model-image" class="imageblock" style="text-align: center">
+<div class="content">
+<img src="data:image/png;base64,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k6NHjzY37LRhmh+M59Xvg3nHDmBHuLp+rtoAz/j7778n11tvveTIkSOr7TAzZsywcuT+5ptvTrZo0SKpnUDy7LPPTirxJffZZ5+kknNSiTS5xx57JD/88MPkpptummzVqlXykUcesbDbb7998rDDDrNw22yzTVI7EDNbb711cty4cVbOhx56aLJXr17JNm3aJJX8kzfccEPyoYceSq699toW7tRTT7V3ox2EvUswatSo5Lrrrpv866+/7DcYPny4xaEdT1I7KAu71lprJS+99FIL37lz5+SwYcMszZ9++im55557Jq+88kp7HvDkk09amjzniy++aGEmTpxo/oiX+Hr37m1+tZOozkuIVYu65Mk1Q9xbArQcTOpBwsHUFZCqkBgZ+iMtckQe+60jiXkelaxMCuNeG7rZc8Xery454AezJoBnpsx4f0ir3LPHDxIsO1GyzPG5556T//znP3Yq1VtvvSXamcptt91m6h7Ki1EAH54h/eOXkcCjjz5qZcgOl+j7+/TpYyOFs846y8qaE60od96JEr60bdvWJspRFfHuOP3qhRdesLiJgzN6kbj9vfDOCR8E0jrmnnvukaefftrUOOSVOBjl8d3EnXfeaWneddddoh2PjTKoO3zEdcUVV9hzosJ67733bHRCXSJNztnt3r27hecoRkYpPDsmRMNFSPQB0HB8KFsXoLGxRzoN98QTT7RGSOMkT5AKCHZE2EEUhOPeGyykx29/Hg/b0EFZYNBZo07hHgJEd/3HH38YsTHReeSRR5oenDJm8zJIFXLnIyfCoCrbZZddbIsD3gFlzqlUkDZ+rrvuOtOtu9rG6wx+GzdubCqW9u3b2wdT+IGML7vsMksfwub9OLkH35eDPIDp06eb/S233CI33XSThYe4DzjgANGRgHUsXLt27WqqGdLX0Yuly9LbSy65xDoJOj5UQnQE3bp1M3Xg0KFD7dnpdDy9EA0XaxzR03BouBCoS1U0VMiBxsI97hhvfNy7tEzDBIR1gvX4/DdXDHb8duPuQePw33xCD8kgkQIaoadN3pigIz0H9r5sEEOakIvH57pg0gbBfDYk8EysRoLIOVoQQMJ8sYqEjXRPOUGEDv+SlXJF8gdB6Zp3gDtliI4ecgesfiItl8zXXXdds0fXzzsgHHFyT9jTTjvNiP6qq66Sgw8+2OIkL1wB74dVNg46Bjob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" alt="platform model">
+</div>
+<div class="title">Figure 1. Platform Model &#8230;&#8203; one host plus one or more compute devices each with one or more compute units composed of one or more processing elements.</div>
+</div>
+<div class="paragraph">
+<p>Programmers provide programs in the form of SPIR-V source binaries, OpenCL C
+or OpenCL C++ source strings or implementation-defined binary objects.
+The OpenCL platform provides a compiler to translate program input of either
+form into executable program objects.
+The device code compiler may be <em>online</em> or <em>offline</em>.
+An <em>online</em> <em>compiler</em> is available during host program execution using
+standard APIs.
+An <em>offline compiler</em> is invoked outside of host program control, using
+platform-specific methods.
+The OpenCL runtime allows developers to get a previously compiled device
+program executable and be able to load and execute a previously compiled
+device program executable.</p>
+</div>
+<div class="paragraph">
+<p>OpenCL defines two kinds of platform profiles: a <em>full profile</em> and a
+reduced-functionality <em>embedded profile</em>.
+A full profile platform must provide an online compiler for all its devices.
+An embedded platform may provide an online compiler, but is not required to
+do so.</p>
+</div>
+<div class="paragraph">
+<p>A device may expose special purpose functionality as a <em>built-in function</em>.
+The platform provides APIs for enumerating and invoking the built-in
+functions offered by a device, but otherwise does not define their
+construction or semantics.
+A <em>custom device</em> supports only built-in functions, and cannot be programmed
+via a kernel language.</p>
+</div>
+<div class="paragraph">
+<p>All device types support the OpenCL execution model, the OpenCL memory
+model, and the APIs used in OpenCL to manage devices.</p>
+</div>
+<div class="paragraph">
+<p>The platform model is an abstraction describing how OpenCL views the
+hardware.
+The relationship between the elements of the platform model and the hardware
+in a system may be a fixed property of a device or it may be a dynamic
+feature of a program dependent on how a compiler optimizes code to best
+utilize physical hardware.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_execution_model">3.2. Execution Model</h3>
+<div class="paragraph">
+<p>The OpenCL execution model is defined in terms of two distinct units of
+execution: <strong>kernels</strong> that execute on one or more OpenCL devices and a <strong>host
+program</strong> that executes on the host.
+With regard to OpenCL, the kernels are where the "work" associated with a
+computation occurs.
+This work occurs through <strong>work-items</strong> that execute in groups
+(<strong>work-groups</strong>).</p>
+</div>
+<div class="paragraph">
+<p>A kernel executes within a well-defined context managed by the host.
+The context defines the environment within which kernels execute.
+It includes the following resources:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>Devices</strong>: One or more devices exposed by the OpenCL platform.</p>
+</li>
+<li>
+<p><strong>Kernel Objects</strong>:The OpenCL functions with their associated argument
+values that run on OpenCL devices.</p>
+</li>
+<li>
+<p><strong>Program Objects</strong>:The program source and executable that implement the
+kernels.</p>
+</li>
+<li>
+<p><strong>Memory Objects</strong>:Variables visible to the host and the OpenCL devices.
+Instances of kernels operate on these objects as they execute.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The host program uses the OpenCL API to create and manage the context.
+Functions from the OpenCL API enable the host to interact with a device
+through a <em>command-queue</em>.
+Each command-queue is associated with a single device.
+The commands placed into the command-queue fall into one of three types:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>Kernel-enqueue commands</strong>: Enqueue a kernel for execution on a device.</p>
+</li>
+<li>
+<p><strong>Memory commands</strong>: Transfer data between the host and device memory,
+between memory objects, or map and unmap memory objects from the host
+address space.</p>
+</li>
+<li>
+<p><strong>Synchronization commands</strong>: Explicit synchronization points that define
+order constraints between commands.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>In addition to commands submitted from the host command-queue, a kernel
+running on a device can enqueue commands to a device-side command queue.
+This results in <em>child kernels</em> enqueued by a kernel executing on a device
+(the <em>parent kernel</em>).
+Regardless of whether the command-queue resides on the host or a device,
+each command passes through six states.</p>
+</div>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p><strong>Queued</strong>: The command is enqueued to a command-queue.
+A command may reside in the queue until it is flushed either explicitly
+(a call to <strong>clFlush</strong>) or implicitly by some other command.</p>
+</li>
+<li>
+<p><strong>Submitted</strong>: The command is flushed from the command-queue and submitted
+for execution on the device.
+Once flushed from the command-queue, a command will execute after any
+prerequisites for execution are met.</p>
+</li>
+<li>
+<p><strong>Ready</strong>: All prerequisites constraining execution of a command have been
+met.
+The command, or for a kernel-enqueue command the collection of work
+groups associated with a command, is placed in a device work-pool from
+which it is scheduled for execution.</p>
+</li>
+<li>
+<p><strong>Running</strong>: Execution of the command starts.
+For the case of a kernel-enqueue command, one or more work-groups
+associated with the command start to execute.</p>
+</li>
+<li>
+<p><strong>Ended</strong>: Execution of a command ends.
+When a Kernel-enqueue command ends, all of the work-groups associated
+with that command have finished their execution.
+<em>Immediate side effects</em>, i.e. those associated with the kernel but not
+necessarily with its child kernels, are visible to other units of
+execution.
+These side effects include updates to values in global memory.</p>
+</li>
+<li>
+<p><strong>Complete</strong>: The command and its child commands have finished execution
+and the status of the event object, if any, associated with the command
+is set to CL_COMPLETE.</p>
+</li>
+</ol>
+</div>
+<div class="paragraph">
+<p>The <a href="#profiled-states-image">execution states and the transitions between
+them</a> are summarized below.
+These states and the concept of a device work-pool are conceptual elements
+of the execution model.
+An implementation of OpenCL has considerable freedom in how these are
+exposed to a program.
+Five of the transitions, however, are directly observable through a
+profiling interface.
+These <a href="#profiled-states-image">profiled states</a> are shown below.</p>
+</div>
+<div id="profiled-states-image" class="imageblock" style="text-align: center">
+<div class="content">
+<img src="data:image/jpg;base64,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wqevIf7De4t/h/f3mtazc3d9cxyyu96+Axtnc7V6LyMcdiR3r16gDzTx34g074a/DRk8OCGJ7iRoLIRvvCuxLO4OT0+Y/XFc58Cfh+ltYL4x1WPzL67ybMScmND1k/3m559PrXmPjiG7tPCHg3Tr2Ga2CtfO0cqFSC1yecH2A/OvrPT7eG0021trcAQQwokYHQKAAP0oAs0UUUAFFFFABRRRQAx445BiRFcejDNVJdE0mf8A12mWUmf79up/mKvUU02gMl/C3h6TG/QdLbHTNnGf6Uz/AIRHw1/0L2lf+Acf+FbNFPml3FZGWvhrQVIK6Jpox0xapx+lW4tPsoP9TZ28f+5Eo/kKs0UrthZAAAMAYooopDCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigArMu9D0+81/TtYnVjfWCSpbkPgASABsjvwK064XxAsp+L3g1lWQxC2vt5AO0fIuM0Ad1RRRQAUUUUAFYN34J8MX2qHUrrQrGW8LBmlaEZYjuexP1reooAzrvQdKvr+K+utPt5rqKJoUkdASEYYZfcHJ4PrVOx8F+GtNAFlolnBgOoKRgHDjawz6EcYrdooAzbrw/pF7pttp9zp8EtpalDBEy8RlBhdvpgVpUUUAeDfF7yfHvwz0/xhpltMq2NxIjrIBuEe4oxOD03Kv4GvQvhP4pj8U+AbCYybru0QWtyCeQ6gAH8Rg/iau+E/B66J4GHhrUnivI388S7VIV1kdmxz7NivC9Pur/4GfFCa0uvNl0G86sB/rISflcf7adCPr6igD6eoqG1uoL60hu7WVJreZA8ciHIZSMgipqACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigArLu9fsbLxBpuiTGT7ZqCSvBhcriMAtk9utalcxq3h67vvH/h3XYniFrp0NykysTuJkUBcDHtQB09FFFABRRRQAUUUUAFFFFABRRRQByfw21y/8R+CLXU9TlWW6kmnVmVAoIWVlHA9gKPiF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" alt="profiled states">
+</div>
+<div class="title">Figure 2. The states and transitions between states defined in the OpenCL execution model. A subset of these transitions is exposed through the <a href="#profiling-operations">profiling interface</a>.</div>
+</div>
+<div class="paragraph">
+<p>Commands communicate their status through <em>Event objects</em>.
+Successful completion is indicated by setting the event status associated
+with a command to CL_COMPLETE.
+Unsuccessful completion results in abnormal termination of the command which
+is indicated by setting the event status to a negative value.
+In this case, the command-queue associated with the abnormally terminated
+command and all other command-queues in the same context may no longer be
+available and their behavior is implementation defined.</p>
+</div>
+<div class="paragraph">
+<p>A command submitted to a device will not launch until prerequisites that
+constrain the order of commands have been resolved.
+These prerequisites have three sources:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>They may arise from commands submitted to a command-queue that constrain
+the order in which commands are launched.
+For example, commands that follow a command queue barrier will not
+launch until all commands prior to the barrier are complete.</p>
+</li>
+<li>
+<p>The second source of prerequisites is dependencies between commands
+expressed through events.
+A command may include an optional list of events.
+The command will wait and not launch until all the events in the list
+are in the state CL COMPLETE.
+By this mechanism, event objects define order constraints between
+commands and coordinate execution between the host and one or more
+devices.</p>
+</li>
+<li>
+<p>The third source of prerequisities can be the presence of non-trivial C
+initializers or C constructors for program scope global variables.
+In this case, OpenCL C/C compiler shall generate program
+initialization kernels that perform C initialization or C++
+construction.
+These kernels must be executed by OpenCL runtime on a device before any
+kernel from the same program can be executed on the same device.
+The ND-range for any program initialization kernel is (1,1,1).
+When multiple programs are linked together, the order of execution of
+program initialization kernels that belong to different programs is
+undefined.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Program clean up may result in the execution of one or more program clean up
+kernels by the OpenCL runtime.
+This is due to the presence of non-trivial C++ destructors for
+program scope variables.
+The ND-range for executing any program clean up kernel is (1,1,1).
+The order of execution of clean up kernels from different programs (that are
+linked together) is undefined.</p>
+</div>
+<div class="paragraph">
+<p>Note that C initializers, C constructors, or C destructors for program
+scope variables cannot use pointers to coarse grain and fine grain SVM
+allocations.</p>
+</div>
+<div class="paragraph">
+<p>A command may be submitted to a device and yet have no visible side effects
+outside of waiting on and satisfying event dependences.
+Examples include markers, kernels executed over ranges of no work-items or
+copy operations with zero sizes.
+Such commands may pass directly from the <em>ready</em> state to the <em>ended</em> state.</p>
+</div>
+<div class="paragraph">
+<p>Command execution can be blocking or non-blocking.
+Consider a sequence of OpenCL commands.
+For blocking commands, the OpenCL API functions that enqueue commands don&#8217;t
+return until the command has completed.
+Alternatively, OpenCL functions that enqueue non-blocking commands return
+immediately and require that a programmer defines dependencies between
+enqueued commands to ensure that enqueued commands are not launched before
+needed resources are available.
+In both cases, the actual execution of the command may occur asynchronously
+with execution of the host program.</p>
+</div>
+<div class="paragraph">
+<p>Commands within a single command-queue execute relative to each other in one
+of two modes:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>In-order Execution</strong>: Commands and any side effects associated with
+commands appear to the OpenCL application as if they execute in the same
+order they are enqueued to a command-queue.</p>
+</li>
+<li>
+<p><strong>Out-of-order Execution</strong>: Commands execute in any order constrained only
+by explicit synchronization points (e.g. through command queue barriers)
+or explicit dependencies on events.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Multiple command-queues can be present within a single context.
+Multiple command-queues execute commands independently.
+Event objects visible to the host program can be used to define
+synchronization points between commands in multiple command queues.
+If such synchronization points are established between commands in multiple
+command-queues, an implementation must assure that the command-queues
+progress concurrently and correctly account for the dependencies established
+by the synchronization points.
+For a detailed explanation of synchronization points, see
+<a href="#execution-model-sync">Execution Model: Synchronization</a>.</p>
+</div>
+<div class="paragraph">
+<p>The core of the OpenCL execution model is defined by how the kernels
+execute.
+When a kernel-enqueue command submits a kernel for execution, an index space
+is defined.
+The kernel, the argument values associated with the arguments to the kernel,
+and the parameters that define the index space define a <em>kernel-instance</em>.
+When a kernel-instance executes on a device, the kernel function executes
+for each point in the defined index space.
+Each of these executing kernel functions is called a <em>work-item</em>.
+The work-items associated with a given kernel-instance are managed by the
+device in groups called <em>work-groups</em>.
+These work-groups define a coarse grained decomposition of the Index space.
+Work-groups are further divided into <em>sub-groups</em>, which provide an
+additional level of control over execution.</p>
+</div>
+<div class="paragraph">
+<p>Work-items have a global ID based on their coordinates within the Index
+space.
+They can also be defined in terms of their work-group and the local ID
+within a work-group.
+The details of this mapping are described in the following section.</p>
+</div>
+<div class="sect3">
+<h4 id="_execution_model_mapping_work_items_onto_an_ndrange">3.2.1. Execution Model: Mapping work-items onto an NDRange</h4>
+<div class="paragraph">
+<p>The index space supported by OpenCL is called an NDRange.
+An NDRange is an N-dimensional index space, where N is one, two or three.
+The NDRange is decomposed into work-groups forming blocks that cover the
+Index space.
+An NDRange is defined by three integer arrays of length N:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>The extent of the index space (or global size) in each dimension.</p>
+</li>
+<li>
+<p>An offset index F indicating the initial value of the indices in each
+dimension (zero by default).</p>
+</li>
+<li>
+<p>The size of a work-group (local size) in each dimension.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Each work-items global ID is an N-dimensional tuple.
+The global ID components are values in the range from F, to F plus the
+number of elements in that dimension minus one.</p>
+</div>
+<div class="paragraph">
+<p>If a kernel is created from OpenCL 2.0 or SPIR-V, the size of work-groups in
+an NDRange (the local size) need not be the same for all work-groups.
+In this case, any single dimension for which the global size is not
+divisible by the local size will be partitioned into two regions.
+One region will have work-groups that have the same number of work items as
+was specified for that dimension by the programmer (the local size).
+The other region will have work-groups with less than the number of work
+items specified by the local size parameter in that dimension (the
+<em>remainder work-groups</em>).
+Work-group sizes could be non-uniform in multiple dimensions, potentially
+producing work-groups of up to 4 different sizes in a 2D range and 8
+different sizes in a 3D range.</p>
+</div>
+<div class="paragraph">
+<p>Each work-item is assigned to a work-group and given a local ID to represent
+its position within the work-group.
+A work-item&#8217;s local ID is an N-dimensional tuple with components in the
+range from zero to the size of the work-group in that dimension minus one.</p>
+</div>
+<div class="paragraph">
+<p>Work-groups are assigned IDs similarly.
+The number of work-groups in each dimension is not directly defined but is
+inferred from the local and global NDRanges provided when a kernel-instance
+is enqueued.
+A work-group&#8217;s ID is an N-dimensional tuple with components in the range 0
+to the ceiling of the global size in that dimension divided by the local
+size in the same dimension.
+As a result, the combination of a work-group ID and the local-ID within a
+work-group uniquely defines a work-item.
+Each work-item is identifiable in two ways; in terms of a global index, and
+in terms of a work-group index plus a local index within a work group.</p>
+</div>
+<div class="paragraph">
+<p>For example, consider the <a href="#index-space-image">2-dimensional index space</a>
+shown below.
+We input the index space for the work-items (G<sub>x</sub>, G<sub>y</sub>), the size of each
+work-group (S<sub>x</sub>, S<sub>y</sub>) and the global ID offset (F<sub>x</sub>, F<sub>y</sub>).
+The global indices define an G<sub>x</sub>by G<sub>y</sub> index space where the total number
+of work-items is the product of G<sub>x</sub> and G<sub>y</sub>.
+The local indices define an S<sub>x</sub> by S<sub>y</sub> index space where the number of
+work-items in a single work-group is the product of S<sub>x</sub> and S<sub>y</sub>.
+Given the size of each work-group and the total number of work-items we can
+compute the number of work-groups.
+A 2-dimensional index space is used to uniquely identify a work-group.
+Each work-item is identified by its global ID (<em>g</em><sub>x</sub>, <em>g</em><sub>y</sub>) or by the
+combination of the work-group ID (<em>w</em><sub>x</sub>, <em>w</em><sub>y</sub>), the size of each
+work-group (S<sub>x</sub>,S<sub>y</sub>) and the local ID (s<sub>x</sub>, s<sub>y</sub>) inside the work-group
+such that</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p>(g<sub>x</sub> , g<sub>y</sub>) = (w<sub>x</sub> S<sub>x</sub> + s<sub>x</sub> + F<sub>x</sub>, w<sub>y</sub> S<sub>y</sub> + s<sub>y</sub> + F<sub>y</sub>)</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>The number of work-groups can be computed as:</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p>(W<sub>x</sub>, W<sub>y</sub>) = (ceil(G<sub>x</sub> / S<sub>x</sub>), ceil(G<sub>y</sub> / S<sub>y</sub>))</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>Given a global ID and the work-group size, the work-group ID for a work-item
+is computed as:</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p>(w<sub>x</sub>, w<sub>y</sub>) = ( (g<sub>x</sub> s<sub>x</sub> F<sub>x</sub>) / S<sub>x</sub>, (g<sub>y</sub> s<sub>y</sub> F<sub>y</sub>) / S<sub>y</sub> )</p>
+</dd>
+</dl>
+</div>
+<div id="index-space-image" class="imageblock" style="text-align: center">
+<div class="content">
+<img src="data:image/jpg;base64,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/wDwlWiHSbfVFv42sriN5IpVBIZVBLHpngA0AV/7N8T/APQw2v8A4Lx/8XR/Zvif/oYbX/wXj/4ukTx14ck0ufUU1EG3gkWOX904dGbhQUxu5zxxzWlo+t6dr1o11ptyJ4lcxt8pUqw7EEAg8jrQBnf2b4n/AOhhtf8AwXj/AOLo/s3xP/0MNr/4Lx/8XXQ0UAc9/Zvif/oYbX/wXj/4uj+zfE//AEMNr/4Lx/8AF10NRW9zFdRs8TEqrshypHKnB6+4oAw/7N8T/wDQw2v/AILx/wDF0f2b4n/6GG1/8F4/+LroaxNN8W6Jq+pPp9leiW4UMQNjKsgU4YoxGGweDgmgCH+zfE//AEMNr/4Lx/8AF1V1HR/FNxp1xCuvW7s6FQq2nlk/Rg+V+tdXRQB5poeleJdJ8X+H4fEeuRao5hvPJ2xYaMYTgvwX/IV6XUbQQvPHM8SNLGCEcqCyg9cHtnAqSgAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKAIrkFrSYKCWKMAB9K8ifw/rml21jBBp08umS6c1yY44yZLe58kK8e3/aPIHrmvYqKAPLr/T9S8Sa62tW1hqOn25extkeSHZO2ybe8pRgcBQcAsPWs7XdI1WCPUrEWmoXzvqMsovXs2laXdAnl4ClVyDuUP0Xb0ya9iooA8gk0S+XSrrV0tL+G+nuLjzJJWaN/IMQ4+Y4UEg496zL2xkv5b0aLp+o22mpcui2pt2leOZoI9h2bwY++CeFJyQM17dPBFdW8kE8aSwyKVdHGQwPUEVBp2l2OkWxt9PtIraEsXKxLgFj1J9TQBxXjqyv5U0Nktrq5mhUgqkLSo0nycMVIMbcHEnQc561i3VlfXPiNIW0fU4rqD7VLbXyQOVeZ3kESmQcKig7ueMlfSvWqKAPN/h1pOpQaZqcN0t1C0tvHE3n27Q/vwrB2GWJY5Iy44btTdIv9UtLnRom0nVo4dKs5Ir6E2ieUGSPAMTkZYsRng4I6816VUF7BJdWM8ENw1vJIhVZlGSme496GBT0PXbLxFYG+08yPalyiSsu0SY6lfUZ4+oNadZPh3QIPDWljTbSaWS0RyYUlOTGp5257jOT+Na1ABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFAH//2Q==" alt="index space">
+</div>
+<div class="title">Figure 3. An example of an NDRange index space showing work-items, their global IDs and their mapping onto the pair of work-group and local IDs. In this case, we assume that in each dimension, the size of the work-group evenly divides the global NDRange size (i.e. all work-groups have the same size) and that the offset is equal to zero.</div>
+</div>
+<div class="paragraph">
+<p>Within a work-group work-items may be divided into sub-groups.
+The mapping of work-items to sub-groups is implementation-defined and may be
+queried at runtime.
+While sub-groups may be used in multi-dimensional work-groups, each
+sub-group is 1-dimensional and any given work-item may query which sub-group
+it is a member of.</p>
+</div>
+<div class="paragraph">
+<p>Work items are mapped into sub-groups through a combination of compile-time
+decisions and the parameters of the dispatch.
+The mapping to sub-groups is invariant for the duration of a kernels
+execution, across dispatches of a given kernel with the same work-group
+dimensions, between dispatches and query operations consistent with the
+dispatch parameterization, and from one work-group to another within the
+dispatch (excluding the trailing edge work-groups in the presence of
+non-uniform work-group sizes).
+In addition, all sub-groups within a work-group will be the same size, apart
+from the sub-group with the maximum index which may be smaller if the size
+of the work-group is not evenly divisible by the size of the sub-groups.</p>
+</div>
+<div class="paragraph">
+<p>In the degenerate case, a single sub-group must be supported for each
+work-group.
+In this situation all sub-group scope functions are equivalent to their
+work-group level equivalents.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_execution_model_execution_of_kernel_instances">3.2.2. Execution Model: Execution of kernel-instances</h4>
+<div class="paragraph">
+<p>The work carried out by an OpenCL program occurs through the execution of
+kernel-instances on compute devices.
+To understand the details of OpenCLs execution model, we need to consider
+how a kernel object moves from the kernel-enqueue command, into a
+command-queue, executes on a device, and completes.</p>
+</div>
+<div class="paragraph">
+<p>A kernel-object is defined from a function within the program object and a
+collection of arguments connecting the kernel to a set of argument values.
+The host program enqueues a kernel-object to the command queue along with
+the NDRange, and the work-group decomposition.
+These define a <em>kernel-instance</em>.
+In addition, an optional set of events may be defined when the kernel is
+enqueued.
+The events associated with a particular kernel-instance are used to
+constrain when the kernel-instance is launched with respect to other
+commands in the queue or to commands in other queues within the same
+context.</p>
+</div>
+<div class="paragraph">
+<p>A kernel-instance is submitted to a device.
+For an in-order command queue, the kernel instances appear to launch and
+then execute in that same order; where we use the term appear to emphasize
+that when there are no dependencies between commands and hence differences
+in the order that commands execute cannot be observed in a program, an
+implementation can reorder commands even in an in-order command queue.
+For an out of order command-queue, kernel-instances wait to be launched
+until:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Synchronization commands enqueued prior to the kernel-instance are
+satisfied.</p>
+</li>
+<li>
+<p>Each of the events in an optional event list defined when the
+kernel-instance was enqueued are set to CL_COMPLETE.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Once these conditions are met, the kernel-instance is launched and the
+work-groups associated with the kernel-instance are placed into a pool of
+ready to execute work-groups.
+This pool is called a <em>work-pool</em>.
+The work-pool may be implemented in any manner as long as it assures that
+work-groups placed in the pool will eventually execute.
+The device schedules work-groups from the work-pool for execution on the
+compute units of the device.
+The kernel-enqueue command is complete when all work-groups associated with
+the kernel-instance end their execution, updates to global memory associated
+with a command are visible globally, and the device signals successful
+completion by setting the event associated with the kernel-enqueue command
+to CL_COMPLETE.</p>
+</div>
+<div class="paragraph">
+<p>While a command-queue is associated with only one device, a single device
+may be associated with multiple command-queues all feeding into the single
+work-pool.
+A device may also be associated with command queues associated with
+different contexts within the same platform, again all feeding into the
+single work-pool.
+The device will pull work-groups from the work-pool and execute them on one
+or several compute units in any order; possibly interleaving execution of
+work-groups from multiple commands.
+A conforming implementation may choose to serialize the work-groups so a
+correct algorithm cannot assume that work-groups will execute in parallel.
+There is no safe and portable way to synchronize across the independent
+execution of work-groups since once in the work-pool, they can execute in
+any order.</p>
+</div>
+<div class="paragraph">
+<p>The work-items within a single sub-group execute concurrently but not
+necessarily in parallel (i.e. they are not guaranteed to make independent
+forward progress).
+Therefore, only high-level synchronization constructs (e.g. sub-group
+functions such as barriers) that apply to all the work-items in a sub-group
+are well defined and included in OpenCL.</p>
+</div>
+<div class="paragraph">
+<p>Sub-groups execute concurrently within a given work-group and with
+appropriate device support (see <a href="#platform-querying-devices">Querying
+Devices</a>), may make independent forward progress with respect to each
+other, with respect to host threads and with respect to any entities
+external to the OpenCL system but running on an OpenCL device, even in the
+absence of work-group barrier operations.
+In this situation, sub-groups are able to internally synchronize using
+barrier operations without synchronizing with each other and may perform
+operations that rely on runtime dependencies on operations other sub-groups
+perform.</p>
+</div>
+<div class="paragraph">
+<p>The work-items within a single work-group execute concurrently but are only
+guaranteed to make independent progress in the presence of sub-groups and
+device support.
+In the absence of this capability, only high-level synchronization
+constructs (e.g. work-group functions such as barriers) that apply to all
+the work-items in a work-group are well defined and included in OpenCL for
+synchronization within the work-group.</p>
+</div>
+<div class="paragraph">
+<p>In the absence of synchronization functions (e.g. a barrier), work-items
+within a sub-group may be serialized.
+In the presence of sub -group functions, work-items within a sub -group may
+be serialized before any given sub -group function, between dynamically
+encountered pairs of sub-group functions and between a work-group function
+and the end of the kernel.</p>
+</div>
+<div class="paragraph">
+<p>In the absence of independent forward progress of constituent sub-groups,
+work-items within a work-group may be serialized before, after or between
+work-group synchronization functions.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="device-side-enqueue">3.2.3. Execution Model: Device-side enqueue</h4>
+<div class="paragraph">
+<p>Algorithms may need to generate additional work as they execute.
+In many cases, this additional work cannot be determined statically; so the
+work associated with a kernel only emerges at runtime as the kernel-instance
+executes.
+This capability could be implemented in logic running within the host
+program, but involvement of the host may add significant overhead and/or
+complexity to the application control flow.
+A more efficient approach would be to nest kernel-enqueue commands from
+inside other kernels.
+This <strong>nested parallelism</strong> can be realized by supporting the enqueuing of
+kernels on a device without direct involvement by the host program;
+so-called <strong>device-side enqueue</strong>.</p>
+</div>
+<div class="paragraph">
+<p>Device-side kernel-enqueue commands are similar to host-side kernel-enqueue
+commands.
+The kernel executing on a device (the <strong>parent kernel</strong>) enqueues a
+kernel-instance (the <strong>child kernel</strong>) to a device-side command queue.
+This is an out-of-order command-queue and follows the same behavior as the
+out-of-order command-queues exposed to the host program.
+Commands enqueued to a device side command-queue generate and use events to
+enforce order constraints just as for the command-queue on the host.
+These events, however, are only visible to the parent kernel running on the
+device.
+When these prerequisite events take on the value CL_COMPLETE, the
+work-groups associated with the child kernel are launched into the devices
+work pool.
+The device then schedules them for execution on the compute units of the
+device.
+Child and parent kernels execute asynchronously.
+However, a parent will not indicate that it is complete by setting its event
+to CL_COMPLETE until all child kernels have ended execution and have
+signaled completion by setting any associated events to the value
+CL_COMPLETE.
+Should any child kernel complete with an event status set to a negative
+value (i.e. abnormally terminate), the parent kernel will abnormally
+terminate and propagate the childs negative event value as the value of the
+parents event.
+If there are multiple children that have an event status set to a negative
+value, the selection of which childs negative event value is propagated is
+implementation-defined.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="execution-model-sync">3.2.4. Execution Model: Synchronization</h4>
+<div class="paragraph">
+<p>Synchronization refers to mechanisms that constrain the order of execution
+between two or more units of execution.
+Consider the following three domains of synchronization in OpenCL:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Work-group synchronization: Constraints on the order of execution for
+work-items in a single work-group</p>
+</li>
+<li>
+<p>Sub-group synchronization: Contraints on the order of execution for
+work-items in a single sub-group</p>
+</li>
+<li>
+<p>Command synchronization: Constraints on the order of commands launched
+for execution</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Synchronization across all work-items within a single work-group is carried
+out using a <em>work-group function</em>.
+These functions carry out collective operations across all the work-items in
+a work-group.
+Available collective operations are: barrier, reduction, broadcast, prefix
+sum, and evaluation of a predicate.
+A work-group function must occur within a converged control flow; i.e. all
+work-items in the work-group must encounter precisely the same work-group
+function.
+For example, if a work-group function occurs within a loop, the work-items
+must encounter the same work-group function in the same loop iterations.
+All the work-items of a work-group must execute the work-group function and
+complete reads and writes to memory before any are allowed to continue
+execution beyond the work-group function.
+Work-group functions that apply between work-groups are not provided in
+OpenCL since OpenCL does not define forward-progress or ordering relations
+between work-groups, hence collective synchronization operations are not
+well defined.</p>
+</div>
+<div class="paragraph">
+<p>Synchronization across all work-items within a single sub-group is carried
+out using a <em>sub-group function</em>.
+These functions carry out collective operations across all the work-items in
+a sub-group.
+Available collective operations are: barrier, reduction, broadcast, prefix
+sum, and evaluation of a predicate.
+A sub-group function must occur within a converged control flow; i.e. all
+work-items in the sub-group must encounter precisely the same sub-group
+function.
+For example, if a work-group function occurs within a loop, the work-items
+must encounter the same sub-group function in the same loop iterations.
+All the work-items of a sub-group must execute the sub-group function and
+complete reads and writes to memory before any are allowed to continue
+execution beyond the sub-group function.
+Synchronization between sub-groups must either be performed using work-group
+functions, or through memory operations.
+Using memory operations for sub-group synchronization should be used
+carefully as forward progress of sub-groups relative to each other is only
+supported optionally by OpenCL implementations.</p>
+</div>
+<div class="paragraph">
+<p>Command synchronization is defined in terms of distinct <strong>synchronization
+points</strong>.
+The synchronization points occur between commands in host command-queues and
+between commands in device-side command-queues.
+The synchronization points defined in OpenCL include:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>Launching a command:</strong> A kernel-instance is launched onto a device after
+all events that kernel is waiting-on have been set to CL_COMPLETE.</p>
+</li>
+<li>
+<p><strong>Ending a command:</strong> Child kernels may be enqueued such that they wait
+for the parent kernel to reach the <em>end</em> state before they can be
+launched.
+In this case, the ending of the parent command defines a synchronization
+point.</p>
+</li>
+<li>
+<p><strong>Completion of a command:</strong> A kernel-instance is complete after all of
+the work-groups in the kernel and all of its child kernels have
+completed.
+This is signaled to the host, a parent kernel or other kernels within
+command queues by setting the value of the event associated with a
+kernel to CL_COMPLETE.</p>
+</li>
+<li>
+<p><strong>Blocking Commands:</strong> A blocking command defines a synchronization point
+between the unit of execution that calls the blocking API function and
+the enqueued command reaching the complete state.</p>
+</li>
+<li>
+<p><strong>Command-queue barrier:</strong> The command-queue barrier ensures that all
+previously enqueued commands have completed before subsequently enqueued
+commands can be launched.</p>
+</li>
+<li>
+<p><strong>clFinish:</strong> This function blocks until all previously enqueued commands
+in the command queue have completed after which <strong>clFinish</strong> defines a
+synchronization point and the <strong>clFinish</strong> function returns.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>A synchronization point between a pair of commands (A and B) assures that
+results of command A happens-before command B is launched.
+This requires that any updates to memory from command A complete and are
+made available to other commands before the synchronization point completes.
+Likewise, this requires that command B waits until after the synchronization
+point before loading values from global memory.
+The concept of a synchronization point works in a similar fashion for
+commands such as a barrier that apply to two sets of commands.
+All the commands prior to the barrier must complete and make their results
+available to following commands.
+Furthermore, any commands following the barrier must wait for the commands
+prior to the barrier before loading values and continuing their execution.</p>
+</div>
+<div class="paragraph">
+<p>These <em>happens-before</em> relationships are a fundamental part of the OpenCL
+memory model.
+When applied at the level of commands, they are straightforward to define at
+a language level in terms of ordering relationships between different
+commands.
+Ordering memory operations inside different commands, however, requires
+rules more complex than can be captured by the high level concept of a
+synchronization point.
+These rules are described in detail in <a href="#memory-ordering-rules">Memory
+Ordering Rules</a>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_execution_model_categories_of_kernels">3.2.5. Execution Model: Categories of Kernels</h4>
+<div class="paragraph">
+<p>The OpenCL execution model supports three types of kernels:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>OpenCL kernels</strong> are managed by the OpenCL API as kernel-objects
+associated with kernel functions within program-objects.
+OpenCL kernels are provided via a kernel language.
+All OpenCL implementations must support OpenCL kernels supplied in the
+standard SPIR-V intermediate language with the appropriate environment
+specification, and the OpenCL C programming language defined in earlier
+versions of the OpenCL specification.
+Implementations must also support OpenCL kernels in SPIR-V intermediate
+language.
+SPIR-V binaries nay be generated from an OpenCL kernel language or by a
+third party compiler from an alternative input.</p>
+</li>
+<li>
+<p><strong>Native kernels</strong> are accessed through a host function pointer.
+Native kernels are queued for execution along with OpenCL kernels on a
+device and share memory objects with OpenCL kernels.
+For example, these native kernels could be functions defined in
+application code or exported from a library.
+The ability to execute native kernels is optional within OpenCL and the
+semantics of native kernels are implementation-defined.
+The OpenCL API includes functions to query capabilities of a device(s)
+and determine if this capability is supported.</p>
+</li>
+<li>
+<p><strong>Built-in kernels</strong> are tied to particular device and are not built at
+runtime from source code in a program object.
+The common use of built in kernels is to expose fixed-function hardware
+or firmware associated with a particular OpenCL device or custom device.
+The semantics of a built-in kernel may be defined outside of OpenCL and
+hence are implementation defined.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>All three types of kernels are manipulated through the OpenCL command queues
+and must conform to the synchronization points defined in the OpenCL
+execution model.</p>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_memory_model">3.3. Memory Model</h3>
+<div class="paragraph">
+<p>The OpenCL memory model describes the structure, contents, and behavior of
+the memory exposed by an OpenCL platform as an OpenCL program runs.
+The model allows a programmer to reason about values in memory as the host
+program and multiple kernel-instances execute.</p>
+</div>
+<div class="paragraph">
+<p>An OpenCL program defines a context that includes a host, one or more
+devices, command-queues, and memory exposed within the context.
+Consider the units of execution involved with such a program.
+The host program runs as one or more host threads managed by the operating
+system running on the host (the details of which are defined outside of
+OpenCL).
+There may be multiple devices in a single context which all have access to
+memory objects defined by OpenCL.
+On a single device, multiple work-groups may execute in parallel with
+potentially overlapping updates to memory.
+Finally, within a single work-group, multiple work-items concurrently
+execute, once again with potentially overlapping updates to memory.</p>
+</div>
+<div class="paragraph">
+<p>The memory model must precisely define how the values in memory as seen from
+each of these units of execution interact so a programmer can reason about
+the correctness of OpenCL programs.
+We define the memory model in four parts.</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Memory regions: The distinct memories visible to the host and the
+devices that share a context.</p>
+</li>
+<li>
+<p>Memory objects: The objects defined by the OpenCL API and their
+management by the host and devices.</p>
+</li>
+<li>
+<p>Shared Virtual Memory: A virtual address space exposed to both the host
+and the devices within a context.</p>
+</li>
+<li>
+<p>Consistency Model: Rules that define which values are observed when
+multiple units of execution load data from memory plus the atomic/fence
+operations that constrain the order of memory operations and define
+synchronization relationships.</p>
+</li>
+</ul>
+</div>
+<div class="sect3">
+<h4 id="_memory_model_fundamental_memory_regions">3.3.1. Memory Model: Fundamental Memory Regions</h4>
+<div class="paragraph">
+<p>Memory in OpenCL is divided into two parts.</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>Host Memory:</strong> The memory directly available to the host.
+The detailed behavior of host memory is defined outside of OpenCL.
+Memory objects move between the Host and the devices through functions
+within the OpenCL API or through a shared virtual memory interface.</p>
+</li>
+<li>
+<p><strong>Device Memory:</strong> Memory directly available to kernels executing on
+OpenCL devices.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Device memory consists of four named address spaces or <em>memory regions</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>Global Memory:</strong> This memory region permits read/write access to all
+work-items in all work-groups running on any device within a context.
+Work-items can read from or write to any element of a memory object.
+Reads and writes to global memory may be cached depending on the
+capabilities of the device.</p>
+</li>
+<li>
+<p><strong>Constant Memory</strong>: A region of global memory that remains constant
+during the execution of a kernel-instance.
+The host allocates and initializes memory objects placed into constant
+memory.</p>
+</li>
+<li>
+<p><strong>Local Memory</strong>: A memory region local to a work-group.
+This memory region can be used to allocate variables that are shared by
+all work-items in that work-group.</p>
+</li>
+<li>
+<p><strong>Private Memory</strong>: A region of memory private to a work-item.
+Variables defined in one work-items private memory are not visible to
+another work-item.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The <a href="#memory-regions-image">memory regions</a> and their relationship to the
+OpenCL Platform model are summarized below.
+Local and private memories are always associated with a particular device.
+The global and constant memories, however, are shared between all devices
+within a given context.
+An OpenCL device may include a cache to support efficient access to these
+shared memories</p>
+</div>
+<div class="paragraph">
+<p>To understand memory in OpenCL, it is important to appreciate the
+relationships between these named address spaces.
+The four named address spaces available to a device are disjoint meaning
+they do not overlap.
+This is a logical relationship, however, and an implementation may choose to
+let these disjoint named address spaces share physical memory.</p>
+</div>
+<div class="paragraph">
+<p>Programmers often need functions callable from kernels where the pointers
+manipulated by those functions can point to multiple named address spaces.
+This saves a programmer from the error-prone and wasteful practice of
+creating multiple copies of functions; one for each named address space.
+Therefore the global, local and private address spaces belong to a single
+<em>generic address space</em>.
+This is closely modeled after the concept of a generic address space used in
+the embedded C standard (ISO/IEC 9899:1999).
+Since they all belong to a single generic address space, the following
+properties are supported for pointers to named address spaces in device
+memory:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>A pointer to the generic address space can be cast to a pointer to a
+global, local or private address space</p>
+</li>
+<li>
+<p>A pointer to a global, local or private address space can be cast to a
+pointer to the generic address space.</p>
+</li>
+<li>
+<p>A pointer to a global, local or private address space can be implicitly
+converted to a pointer to the generic address space, but the converse is
+not allowed.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The constant address space is disjoint from the generic address space.</p>
+</div>
+<div class="paragraph">
+<p>The addresses of memory associated with memory objects in Global memory are
+not preserved between kernel instances, between a device and the host, and
+between devices.
+In this regard global memory acts as a global pool of memory objects rather
+than an address space.
+This restriction is relaxed when shared virtual memory (SVM) is used.</p>
+</div>
+<div class="paragraph">
+<p>SVM causes addresses to be meaningful between the host and all of the
+devices within a context hence supporting the use of pointer based data
+structures in OpenCL kernels.
+It logically extends a portion of the global memory into the host address
+space giving work-items access to the host address space.
+On platforms with hardware support for a shared address space between the
+host and one or more devices, SVM may also provide a more efficient way to
+share data between devices and the host.
+Details about SVM are presented in <a href="#shared-virtual-memory">Shared Virtual
+Memory</a>.</p>
+</div>
+<div id="memory-regions-image" class="imageblock" style="text-align: center">
+<div class="content">
+<img src="data:image/jpg;base64,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" alt="memory regions">
+</div>
+<div class="title">Figure 4. The named address spaces exposed in an OpenCL Platform. Global and Constant memories are shared between the one or more devices within a context, while local and private memories are associated with a single device. Each device may include an optional cache to support efficient access to their view of the global and constant address spaces.</div>
+</div>
+<div class="paragraph">
+<p>A programmer may use the features of the <a href="#memory-consistency-model">memory
+consistency model</a> to manage safe access to global memory from multiple
+work-items potentially running on one or more devices.
+In addition, when using shared virtual memory (SVM), the memory consistency
+model may also be used to ensure that host threads safely access memory
+locations in the shared memory region.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_memory_model_memory_objects">3.3.2. Memory Model: Memory Objects</h4>
+<div class="paragraph">
+<p>The contents of global memory are <em>memory objects</em>.
+A memory object is a handle to a reference counted region of global memory.
+Memory objects use the OpenCL type <em>cl_mem</em> and fall into three distinct
+classes.</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>Buffer</strong>: A memory object stored as a block of contiguous memory and
+used as a general purpose object to hold data used in an OpenCL program.
+The types of the values within a buffer may be any of the built in types
+(such as int, float), vector types, or user-defined structures.
+The buffer can be manipulated through pointers much as one would with
+any block of memory in C.</p>
+</li>
+<li>
+<p><strong>Image</strong>: An image memory object holds one, two or three dimensional
+images.
+The formats are based on the standard image formats used in graphics
+applications.
+An image is an opaque data structure managed by functions defined in the
+OpenCL API.
+To optimize the manipulation of images stored in the texture memories
+found in many GPUs, OpenCL kernels have traditionally been disallowed
+from both reading and writing a single image.
+In OpenCL 2.0, however, we have relaxed this restriction by providing
+synchronization and fence operations that let programmers properly
+synchronize their code to safely allow a kernel to read and write a
+single image.</p>
+</li>
+<li>
+<p><strong>Pipe</strong>: The <em>pipe</em> memory object conceptually is an ordered sequence of
+data items.
+A pipe has two endpoints: a write endpoint into which data items are
+inserted, and a read endpoint from which data items are removed.
+At any one time, only one kernel instance may write into a pipe, and
+only one kernel instance may read from a pipe.
+To support the producer consumer design pattern, one kernel instance
+connects to the write endpoint (the producer) while another kernel
+instance connects to the reading endpoint (the consumer).</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Memory objects are allocated by host APIs.
+The host program can provide the runtime with a pointer to a block of
+continuous memory to hold the memory object when the object is created
+(CL_MEM_USE_HOST_PTR).
+Alternatively, the physical memory can be managed by the OpenCL runtime and
+not be directly accessible to the host program.</p>
+</div>
+<div class="paragraph">
+<p>Allocation and access to memory objects within the different memory regions
+varies between the host and work-items running on a device.
+This is summarized in the <a href="#memory-regions-table">Memory Regions</a> table,
+which describes whether the kernel or the host can allocate from a memory
+region, the type of allocation (static at compile time vs.
+dynamic at runtime) and the type of access allowed (i.e. whether the kernel
+or the host can read and/or write to a memory region).</p>
+</div>
+<table id="memory-regions-table" class="tableblock frame-all grid-all" style="width: 80%;">
+<caption class="title">Table 1. Memory Regions</caption>
+<colgroup>
+<col style="width: 20%;">
+<col style="width: 20%;">
+<col style="width: 20%;">
+<col style="width: 20%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"></th>
+<th class="tableblock halign-left valign-top">Global</th>
+<th class="tableblock halign-left valign-top">Constant</th>
+<th class="tableblock halign-left valign-top">Local</th>
+<th class="tableblock halign-left valign-top">Private</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top" rowspan="2"><p class="tableblock">Host</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Dynamic Allocation</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Dynamic Allocation</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Dynamic Allocation</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">No Allocation</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Read/Write access to buffers and images but not pipes</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Read/Write access</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">No access</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">No access</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top" rowspan="2"><p class="tableblock">Kernel</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Static Allocation for program scope variables</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Static Allocation</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Static Allocation.</p>
+<p class="tableblock">            Dynamic allocation for child kernel</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Static Allocation</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Read/Write access</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Read-only access</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Read/Write access.</p>
+<p class="tableblock">        No access to child&#8217;s local memory.</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Read/Write access</p></td>
+</tr>
+</tbody>
+</table>
+<div class="sidebarblock">
+<div class="content">
+<div class="title">Caption</div>
+<div class="paragraph">
+<p>The <a href="#memory-regions-table">Memory Regions</a> table shows the different
+memory regions in OpenCL and how memory objects are allocated and accessed
+by the host and by an executing instance of a kernel.
+For the case of kernels, we distinguish between the behavior of local memory
+with respect to a kernel (self) and its child kernels.</p>
+</div>
+</div>
+</div>
+<div class="paragraph">
+<p>Once allocated, a memory object is made available to kernel-instances
+running on one or more devices.
+In addition to <a href="#shared-virtual-memory">Shared Virtual Memory</a>, there are
+three basic ways to manage the contents of buffers between the host and
+devices.</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>Read/Write/Fill commands</strong>: The data associated with a memory object is
+explicitly read and written between the host and global memory regions
+using commands enqueued to an OpenCL command queue.</p>
+</li>
+<li>
+<p><strong>Map/Unmap commands</strong>: Data from the memory object is mapped into a
+contiguous block of memory accessed through a host accessible pointer.
+The host program enqueues a <em>map</em> command on block of a memory object
+before it can be safely manipulated by the host program.
+When the host program is finished working with the block of memory, the
+host program enqueues an <em>unmap</em> command to allow a kernel-instance to
+safely read and/or write the buffer.</p>
+</li>
+<li>
+<p><strong>Copy commands:</strong> The data associated with a memory object is copied
+between two buffers, each of which may reside either on the host or on
+the device.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>In both cases, the commands to transfer data between devices and the host
+can be blocking or non-blocking operations.
+The OpenCL function call for a blocking memory transfer returns once the
+associated memory resources on the host can be safely reused.
+For a non-blocking memory transfer, the OpenCL function call returns as soon
+as the command is enqueued.</p>
+</div>
+<div class="paragraph">
+<p>Memory objects are bound to a context and hence can appear in multiple
+kernel-instances running on more than one physical device.
+The OpenCL platform must support a large range of hardware platforms
+including systems that do not support a single shared address space in
+hardware; hence the ways memory objects can be shared between
+kernel-instances is restricted.
+The basic principle is that multiple read operations on memory objects from
+multiple kernel-instances that overlap in time are allowed, but mixing
+overlapping reads and writes into the same memory objects from different
+kernel instances is only allowed when fine grained synchronization is used
+with <a href="#shared-virtual-memory">Shared Virtual Memory</a>.</p>
+</div>
+<div class="paragraph">
+<p>When global memory is manipulated by multiple kernel-instances running on
+multiple devices, the OpenCL runtime system must manage the association of
+memory objects with a given device.
+In most cases the OpenCL runtime will implicitly associate a memory object
+with a device.
+A kernel instance is naturally associated with the command queue to which
+the kernel was submitted.
+Since a command-queue can only access a single device, the queue uniquely
+defines which device is involved with any given kernel-instance; hence
+defining a clear association between memory objects, kernel-instances and
+devices.
+Programmers may anticipate these associations in their programs and
+explicitly manage association of memory objects with devices in order to
+improve performance.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="shared-virtual-memory">3.3.3. Memory Model: Shared Virtual Memory</h4>
+<div class="paragraph">
+<p>OpenCL extends the global memory region into the host memory region through
+a shared virtual memory (SVM) mechanism.
+There are three types of SVM in OpenCL</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>Coarse-Grained buffer SVM</strong>: Sharing occurs at the granularity of
+regions of OpenCL buffer memory objects.
+Consistency is enforced at synchronization points and with map/unmap
+commands to drive updates between the host and the device.
+This form of SVM is similar to non-SVM use of memory; however, it lets
+kernel-instances share pointer-based data structures (such as
+linked-lists) with the host program.
+Program scope global variables are treated as per-device coarse-grained
+SVM for addressing and sharing purposes.</p>
+</li>
+<li>
+<p><strong>Fine-Grained buffer SVM</strong>: Sharing occurs at the granularity of
+individual loads/stores into bytes within OpenCL buffer memory objects.
+Loads and stores may be cached.
+This means consistency is guaranteed at synchronization points.
+If the optional OpenCL atomics are supported, they can be used to
+provide fine-grained control of memory consistency.</p>
+</li>
+<li>
+<p><strong>Fine-Grained system SVM</strong>: Sharing occurs at the granularity of
+individual loads/stores into bytes occurring anywhere within the host
+memory.
+Loads and stores may be cached so consistency is guaranteed at
+synchronization points.
+If the optional OpenCL atomics are supported, they can be used to
+provide fine-grained control of memory consistency.</p>
+</li>
+</ul>
+</div>
+<table id="svm-summary-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 2. A summary of shared virtual memory (SVM) options in OpenCL</caption>
+<colgroup>
+<col style="width: 20%;">
+<col style="width: 20%;">
+<col style="width: 20%;">
+<col style="width: 20%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-center valign-top"></th>
+<th class="tableblock halign-center valign-top">Granularity of sharing</th>
+<th class="tableblock halign-center valign-top">Memory Allocation</th>
+<th class="tableblock halign-center valign-top">Mechanisms to enforce Consistency</th>
+<th class="tableblock halign-center valign-top">Explicit updates between host and device</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-center valign-top"><p class="tableblock">Non-SVM buffers</p></td>
+<td class="tableblock halign-center valign-top"><p class="tableblock">OpenCL Memory objects(buffer)</p></td>
+<td class="tableblock halign-center valign-top"><p class="tableblock"><strong>clCreateBuffer</strong></p></td>
+<td class="tableblock halign-center valign-top"><p class="tableblock">Host synchronization points on the same or between devices.</p></td>
+<td class="tableblock halign-center valign-top"><p class="tableblock">yes, through Map and Unmap commands.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-center valign-top"><p class="tableblock">Coarse-Grained buffer SVM</p></td>
+<td class="tableblock halign-center valign-top"><p class="tableblock">OpenCL Memory objects (buffer)</p></td>
+<td class="tableblock halign-center valign-top"><p class="tableblock"><strong>clSVMAlloc</strong></p></td>
+<td class="tableblock halign-center valign-top"><p class="tableblock">Host synchronization points between devices</p></td>
+<td class="tableblock halign-center valign-top"><p class="tableblock">yes, through Map and Unmap commands.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-center valign-top"><p class="tableblock">Fine Grained buffer SVM</p></td>
+<td class="tableblock halign-center valign-top"><p class="tableblock">Bytes within OpenCL Memory objects (buffer)</p></td>
+<td class="tableblock halign-center valign-top"><p class="tableblock"><strong>clSVMAlloc</strong></p></td>
+<td class="tableblock halign-center valign-top"><p class="tableblock">Synchronization points plus atomics (if supported)</p></td>
+<td class="tableblock halign-center valign-top"><p class="tableblock">No</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-center valign-top"><p class="tableblock">Fine-Grained system SVM</p></td>
+<td class="tableblock halign-center valign-top"><p class="tableblock">Bytes within Host memory (system)</p></td>
+<td class="tableblock halign-center valign-top"><p class="tableblock">Host memory allocation mechanisms (e.g. malloc)</p></td>
+<td class="tableblock halign-center valign-top"><p class="tableblock">Synchronization points plus atomics (if supported)</p></td>
+<td class="tableblock halign-center valign-top"><p class="tableblock">No</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>Coarse-Grained buffer SVM is required in the core OpenCL specification.
+The two finer grained approaches are optional features in OpenCL.
+The various SVM mechanisms to access host memory from the work-items
+associated with a kernel instance are <a href="#svm-summary-table">summarized
+above</a>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="memory-consistency-model">3.3.4. Memory Model: Memory Consistency Model</h4>
+<div class="paragraph">
+<p>The OpenCL memory model tells programmers what they can expect from an
+OpenCL implementation; which memory operations are guaranteed to happen in
+which order and which memory values each read operation will return.
+The memory model tells compiler writers which restrictions they must follow
+when implementing compiler optimizations; which variables they can cache in
+registers and when they can move reads or writes around a barrier or atomic
+operation.
+The memory model also tells hardware designers about limitations on hardware
+optimizations; for example, when they must flush or invalidate hardware
+caches.</p>
+</div>
+<div class="paragraph">
+<p>The memory consistency model in OpenCL is based on the memory model from the
+ISO C11 programming language.
+To help make the presentation more precise and self-contained, we include
+modified paragraphs taken verbatim from the ISO C11 international standard.
+When a paragraph is taken or modified from the C11 standard, it is
+identified as such along with its original location in the <a href="#iso-c11">C11
+standard</a>.</p>
+</div>
+<div class="paragraph">
+<p>For programmers, the most intuitive model is the <em>sequential consistency</em>
+memory model.
+Sequential consistency interleaves the steps executed by each of the units
+of execution.
+Each access to a memory location sees the last assignment to that location
+in that interleaving.
+While sequential consistency is relatively straightforward for a programmer
+to reason about, implementing sequential consistency is expensive.
+Therefore, OpenCL implements a relaxed memory consistency model; i.e. it is
+possible to write programs where the loads from memory violate sequential
+consistency.
+Fortunately, if a program does not contain any races and if the program only
+uses atomic operations that utilize the sequentially consistent memory order
+(the default memory ordering for OpenCL), OpenCL programs appear to execute
+with sequential consistency.</p>
+</div>
+<div class="paragraph">
+<p>Programmers can to some degree control how the memory model is relaxed by
+choosing the memory order for synchronization operations.
+The precise semantics of synchronization and the memory orders are formally
+defined in <a href="#memory-ordering-rules">Memory Ordering Rules</a>.
+Here, we give a high level description of how these memory orders apply to
+atomic operations on atomic objects shared between units of execution.
+OpenCL memory_order choices are based on those from the ISO C11 standard
+memory model.
+They are specified in certain OpenCL functions through the following
+enumeration constants:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>memory_order_relaxed</strong>: implies no order constraints.
+This memory order can be used safely to increment counters that are
+concurrently incremented, but it doesnt guarantee anything about the
+ordering with respect to operations to other memory locations.
+It can also be used, for example, to do ticket allocation and by expert
+programmers implementing lock-free algorithms.</p>
+</li>
+<li>
+<p><strong>memory_order_acquire</strong>: A synchronization operation (fence or atomic)
+that has acquire semantics "acquires" side-effects from a release
+operation that synchronises with it: if an acquire synchronises with a
+release, the acquiring unit of execution will see all side-effects
+preceding that release (and possibly subsequent side-effects.) As part
+of carefully-designed protocols, programmers can use an "acquire" to
+safely observe the work of another unit of execution.</p>
+</li>
+<li>
+<p><strong>memory_order_release</strong>: A synchronization operation (fence or atomic
+operation) that has release semantics "releases" side effects to an
+acquire operation that synchronises with it.
+All side effects that precede the release are included in the release.
+As part of carefully-designed protocols, programmers can use a "release"
+to make changes made in one unit of execution visible to other units of
+execution.</p>
+</li>
+</ul>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+In general, no acquire must <em>always</em> synchronise with any particular
+release.
+However, synchronisation can be forced by certain executions.
+See <a href="#memory-ordering-fence">Memory Order Rules: Fence Operations</a> for
+detailed rules for when synchronisation must occur.
+</td>
+</tr>
+</table>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>memory_order_acq_rel</strong>: A synchronization operation with acquire-release
+semantics has the properties of both the acquire and release memory
+orders.
+It is typically used to order read-modify-write operations.</p>
+</li>
+<li>
+<p><strong>memory_order_seq_cst</strong>: The loads and stores of each unit of execution
+appear to execute in program (i.e., sequenced-before) order, and the
+loads and stores from different units of execution appear to be simply
+interleaved.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Regardless of which memory_order is specified, resolving constraints on
+memory operations across a heterogeneous platform adds considerable overhead
+to the execution of a program.
+An OpenCL platform may be able to optimize certain operations that depend on
+the features of the memory consistency model by restricting the scope of the
+memory operations.
+Distinct memory scopes are defined by the values of the memory_scope
+enumeration constant:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>memory_scope_work_item</strong>: memory-ordering constraints only apply within
+the work-item<sup>1</sup>.</p>
+<div class="openblock">
+<div class="content">
+<div class="dlist">
+<dl>
+<dt class="hdlist1">1</dt>
+<dd>
+<p>This value for memory_scope can only be used with atomic_work_item_fence
+with flags set to CLK_IMAGE_MEM_FENCE.</p>
+</dd>
+</dl>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p><strong>memory_scope_sub_group</strong>:memory-ordering constraints only apply within
+the sub-group.</p>
+</li>
+<li>
+<p><strong>memory_scope_work_group</strong>: memory-ordering constraints only apply to
+work-items executing within a single work-group.</p>
+</li>
+<li>
+<p><strong>memory_scope_device:</strong> memory-ordering constraints only apply to
+work-items executing on a single device</p>
+</li>
+<li>
+<p><strong>memory_scope_all_svm_devices</strong>: memory-ordering constraints apply to
+work-items executing across multiple devices and (when using SVM) the
+host.
+A release performed with <strong>memory_scope_all_svm_devices</strong> to a buffer that
+does not have the CL_MEM_SVM_ATOMICS flag set will commit to at least
+<strong>memory_scope_device</strong> visibility, with full synchronization of the
+buffer at a queue synchronization point (e.g. an OpenCL event).</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>These memory scopes define a hierarchy of visibilities when analyzing the
+ordering constraints of memory operations.
+For example if a programmer knows that a sequence of memory operations will
+only be associated with a collection of work-items from a single work-group
+(and hence will run on a single device), the implementation is spared the
+overhead of managing the memory orders across other devices within the same
+context.
+This can substantially reduce overhead in a program.
+All memory scopes are valid when used on global memory or local memory.
+For local memory, all visibility is constrained to within a given work-group
+and scopes wider than <strong>memory_scope_work_group</strong> carry no additional meaning.</p>
+</div>
+<div class="paragraph">
+<p>In the following subsections (leading up to <a href="#opencl-framework">OpenCL
+Framework</a>), we will explain the synchronization constructs and detailed
+rules needed to use OpenCL&#8217;s relaxed memory models.
+It is important to appreciate, however, that many programs do not benefit
+from relaxed memory models.
+Even expert programmers have a difficult time using atomics and fences to
+write correct programs with relaxed memory models.
+A large number of OpenCL programs can be written using a simplified memory
+model.
+This is accomplished by following these guidelines.</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Write programs that manage safe sharing of global memory objects through
+the synchronization points defined by the command queues.</p>
+</li>
+<li>
+<p>Restrict low level synchronization inside work-groups to the work-group
+functions such as barrier.</p>
+</li>
+<li>
+<p>If you want sequential consistency behavior with system allocations or
+fine-grain SVM buffers with atomics support, use only
+<strong>memory_order_seq_cst</strong> operations with the scope
+<strong>memory_scope_all_svm_devices</strong>.</p>
+</li>
+<li>
+<p>If you want sequential consistency behavior when not using system
+allocations or fine-grain SVM buffers with atomics support, use only
+<strong>memory_order_seq_cst</strong> operations with the scope <strong>memory_scope_device</strong>
+or <strong>memory_scope_all_svm_devices</strong>.</p>
+</li>
+<li>
+<p>Ensure your program has no races.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If these guidelines are followed in your OpenCL programs, you can skip the
+detailed rules behind the relaxed memory models and go directly to
+<a href="#opencl-framework">OpenCL Framework</a>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_memory_model_overview_of_atomic_and_fence_operations">3.3.5. Memory Model: Overview of atomic and fence operations</h4>
+<div class="paragraph">
+<p>The OpenCL 2.0 specification defines a number of <em>synchronization
+operations</em> that are used to define memory order constraints in a program.
+They play a special role in controlling how memory operations in one unit of
+execution (such as work-items or, when using SVM a host thread) are made
+visible to another.
+There are two types of synchronization operations in OpenCL; <em>atomic
+operations</em> and <em>fences</em>.</p>
+</div>
+<div class="paragraph">
+<p>Atomic operations are indivisible.
+They either occur completely or not at all.
+These operations are used to order memory operations between units of
+execution and hence they are parameterized with the memory_order and
+memory_scope parameters defined by the OpenCL memory consistency model.
+The atomic operations for OpenCL kernel languages are similar to the
+corresponding operations defined by the C11 standard.</p>
+</div>
+<div class="paragraph">
+<p>The OpenCL 2.0 atomic operations apply to variables of an atomic type (a
+subset of those in the C11 standard) including atomic versions of the int,
+uint, long, ulong, float, double, half, intptr_t, uintptr_t, size_t, and
+ptrdiff_t types.
+However, support for some of these atomic types depends on support for the
+corresponding regular types.</p>
+</div>
+<div class="paragraph">
+<p>An atomic operation on one or more memory locations is either an acquire
+operation, a release operation, or both an acquire and release operation.
+An atomic operation without an associated memory location is a fence and can
+be either an acquire fence, a release fence, or both an acquire and release
+fence.
+In addition, there are relaxed atomic operations, which do not have
+synchronization properties, and atomic read-modify-write operations, which
+have special characteristics.
+<a href="#iso-c11">[C11 standard, Section 5.1.2.4, paragraph 5, modified.]</a></p>
+</div>
+<div class="paragraph">
+<p>The orders <strong>memory_order_acquire</strong> (used for reads), <strong>memory_order_release</strong>
+(used for writes), and <strong>memory_order_acq_rel</strong> (used for read-modify-write
+operations) are used for simple communication between units of execution
+using shared variables.
+Informally, executing a <strong>memory_order_release</strong> on an atomic object A makes
+all previous side effects visible to any unit of execution that later
+executes a <strong>memory_order_acquire</strong> on A.
+The orders <strong>memory_order_acquire</strong>, <strong>memory_order_release</strong>, and
+<strong>memory_order_acq_rel</strong> do not provide sequential consistency for race-free
+programs because they will not ensure that atomic stores followed by atomic
+loads become visible to other threads in that order.</p>
+</div>
+<div id="atomic-fence-orders" class="paragraph">
+<p>The fence operation is atomic_work_item_fence, which includes a memory_order
+argument as well as the memory_scope and cl_mem_fence_flags arguments.
+Depending on the memory_order argument, this operation:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>has no effects, if <strong>memory_order_relaxed</strong>;</p>
+</li>
+<li>
+<p>is an acquire fence, if <strong>memory_order_acquire</strong>;</p>
+</li>
+<li>
+<p>is a release fence, if <strong>memory_order_release</strong>;</p>
+</li>
+<li>
+<p>is both an acquire fence and a release fence, if <strong>memory_order_acq_rel</strong>;</p>
+</li>
+<li>
+<p>is a sequentially-consistent fence with both acquire and release
+semantics, if <strong>memory_order_seq_cst</strong>.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If specified, the cl_mem_fence_flags argument must be CLK_IMAGE_MEM_FENCE,
+CLK_GLOBAL_MEM_FENCE, CLK_LOCAL_MEM_FENCE, or CLK_GLOBAL_MEM_FENCE |
+CLK_LOCAL_MEM_FENCE.</p>
+</div>
+<div class="paragraph">
+<p>The atomic_work_item_fence(CLK_IMAGE_MEM_FENCE) built-in function must be
+used to make sure that sampler-less writes are visible to later reads by the
+same work-item.
+Without use of the atomic_work_item_fence function, write-read coherence on
+image objects is not guaranteed: if a work-item reads from an image to which
+it has previously written without an intervening atomic_work_item_fence, it
+is not guaranteed that those previous writes are visible to the work-item.</p>
+</div>
+<div class="paragraph">
+<p>The synchronization operations in OpenCL can be parameterized by a
+memory_scope.
+Memory scopes control the extent that an atomic operation or fence is
+visible with respect to the memory model.
+These memory scopes may be used when performing atomic operations and fences
+on global memory and local memory.
+When used on global memory visibility is bounded by the capabilities of that
+memory.
+When used on a fine-grained non-atomic SVM buffer, a coarse-grained SVM
+buffer, or a non-SVM buffer, operations parameterized with
+<strong>memory_scope_all_svm_devices</strong> will behave as if they were parameterized
+with <strong>memory_scope_device</strong>.
+When used on local memory, visibility is bounded by the work-group and, as a
+result, memory_scope with wider visibility than <strong>memory_scope_work_group</strong>
+will be reduced to <strong>memory_scope_work_group</strong>.</p>
+</div>
+<div class="paragraph">
+<p>Two actions <strong>A</strong> and <strong>B</strong> are defined to have an inclusive scope if they have
+the same scope <strong>P</strong> such that:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>P</strong> is <strong>memory_scope_sub_group</strong> and <strong>A</strong> and <strong>B</strong> are executed by
+work-items within the same sub-group.</p>
+</li>
+<li>
+<p><strong>P</strong> is <strong>memory_scope_work_group</strong> and <strong>A</strong> and <strong>B</strong> are executed by
+work-items within the same work-group.</p>
+</li>
+<li>
+<p><strong>P</strong> is <strong>memory_scope_device</strong> and <strong>A</strong> and <strong>B</strong> are executed by work-items
+on the same device when <strong>A</strong> and <strong>B</strong> apply to an SVM allocation or <strong>A</strong>
+and <strong>B</strong> are executed by work-items in the same kernel or one of its
+children when <strong>A</strong> and <strong>B</strong> apply to a cl_mem buffer.</p>
+</li>
+<li>
+<p><strong>P</strong> is <strong>memory_scope_all_svm_devices</strong> if <strong>A</strong> and <strong>B</strong> are executed by
+host threads or by work-items on one or more devices that can share SVM
+memory with each other and the host process.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="memory-ordering-rules">3.3.6. Memory Model: Memory Ordering Rules</h4>
+<div class="paragraph">
+<p>Fundamentally, the issue in a memory model is to understand the orderings in
+time of modifications to objects in memory.
+Modifying an object or calling a function that modifies an object are side
+effects, i.e. changes in the state of the execution environment.
+Evaluation of an expression in general includes both value computations and
+initiation of side effects.
+Value computation for an lvalue expression includes determining the identity
+of the designated object.
+<a href="#iso-c11">[C11 standard, Section 5.1.2.3, paragraph 2, modified.]</a></p>
+</div>
+<div class="paragraph">
+<p>We assume that the OpenCL kernel language and host programming languages
+have a sequenced-before relation between the evaluations executed by a
+single unit of execution.
+This sequenced-before relation is an asymmetric, transitive, pair-wise
+relation between those evaluations, which induces a partial order among
+them.
+Given any two evaluations <strong>A</strong> and <strong>B</strong>, if <strong>A</strong> is sequenced-before <strong>B</strong>, then
+the execution of <strong>A</strong> shall precede the execution of <strong>B</strong>.
+(Conversely, if <strong>A</strong> is sequenced-before <strong>B</strong>, then <strong>B</strong> is sequenced-after
+<strong>A</strong>.) If <strong>A</strong> is not sequenced-before or sequenced-after <strong>B</strong>, then <strong>A</strong> and
+<strong>B</strong> are unsequenced.
+Evaluations <strong>A</strong> and <strong>B</strong> are indeterminately sequenced when <strong>A</strong> is either
+sequenced-before or sequenced-after <strong>B</strong>, but it is unspecified which.
+<a href="#iso-c11">[C11 standard, Section 5.1.2.3, paragraph 3, modified.]</a></p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+Sequenced-before is a partial order of the operations executed by a
+single unit of execution (e.g. a host thread or work-item).
+It generally corresponds to the source program order of those operations,
+and is partial because of the undefined argument evaluation order of OpenCLs
+kernel C language.
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p>In an OpenCL kernel language, the value of an object visible to a work-item
+W at a particular point is the initial value of the object, a value stored
+in the object by W, or a value stored in the object by another work-item or
+host thread, according to the rules below.
+Depending on details of the host programming language, the value of an
+object visible to a host thread may also be the value stored in that object
+by another work-item or host thread.
+<a href="#iso-c11">[C11 standard, Section 5.1.2.4, paragraph 2, modified.]</a></p>
+</div>
+<div class="paragraph">
+<p>Two expression evaluations conflict if one of them modifies a memory
+location and the other one reads or modifies the same memory location.
+<a href="#iso-c11">[C11 standard, Section 5.1.2.4, paragraph 4.]</a></p>
+</div>
+<div class="paragraph">
+<p>All modifications to a particular atomic object <strong>M</strong> occur in some particular
+total order, called the modification order of <strong>M</strong>.
+If <strong>A</strong> and <strong>B</strong> are modifications of an atomic object <strong>M</strong>, and <strong>A</strong>
+happens-before <strong>B</strong>, then <strong>A</strong> shall precede <strong>B</strong> in the modification order of
+<strong>M</strong>, which is defined below.
+Note that the modification order of an atomic object <strong>M</strong> is independent of
+whether <strong>M</strong> is in local or global memory.
+<a href="#iso-c11">[C11 standard, Section 5.1.2.4, paragraph 7, modified.]</a></p>
+</div>
+<div class="paragraph">
+<p>A release sequence begins with a release operation <strong>A</strong> on an atomic object
+<strong>M</strong> and is the maximal contiguous sub-sequence of side effects in the
+modification order of <strong>M</strong>, where the first operation is <strong>A</strong> and every
+subsequent operation either is performed by the same work-item or host
+thread that performed the release or is an atomic read-modify-write
+operation.
+<a href="#iso-c11">[C11 standard, Section 5.1.2.4, paragraph 10, modified.]</a></p>
+</div>
+<div class="paragraph">
+<p>OpenCLs local and global memories are disjoint.
+Kernels may access both kinds of memory while host threads may only access
+global memory.
+Furthermore, the <em>flags</em> argument of OpenCLs work_group_barrier function
+specifies which memory operations the function will make visible: these
+memory operations can be, for example, just the ones to local memory, or the
+ones to global memory, or both.
+Since the visibility of memory operations can be specified for local memory
+separately from global memory, we define two related but independent
+relations, <em>global-synchronizes-with</em> and <em>local-synchronizes-with</em>.
+Certain operations on global memory may global-synchronize-with other
+operations performed by another work-item or host thread.
+An example is a release atomic operation in one work- item that
+global-synchronizes-with an acquire atomic operation in a second work-item.
+Similarly, certain atomic operations on local objects in kernels can
+local-synchronize- with other atomic operations on those local objects.
+<a href="#iso-c11">[C11 standard, Section 5.1.2.4, paragraph 11, modified.]</a></p>
+</div>
+<div class="paragraph">
+<p>We define two separate happens-before relations: global-happens-before and
+local-happens-before.</p>
+</div>
+<div class="paragraph">
+<p>A global memory action <strong>A</strong> global-happens-before a global memory action <strong>B</strong>
+if</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>A</strong> is sequenced before <strong>B</strong>, or</p>
+</li>
+<li>
+<p><strong>A</strong> global-synchronizes-with <strong>B</strong>, or</p>
+</li>
+<li>
+<p>For some global memory action <strong>C</strong>, <strong>A</strong> global-happens-before <strong>C</strong> and <strong>C</strong>
+global-happens-before <strong>B</strong>.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>A local memory action <strong>A</strong> local-happens-before a local memory action <strong>B</strong> if</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>A</strong> is sequenced before <strong>B</strong>, or</p>
+</li>
+<li>
+<p><strong>A</strong> local-synchronizes-with <strong>B</strong>, or</p>
+</li>
+<li>
+<p>For some local memory action <strong>C</strong>, <strong>A</strong> local-happens-before <strong>C</strong> and <strong>C</strong>
+local-happens-before <strong>B</strong>.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>An OpenCL implementation shall ensure that no program execution demonstrates
+a cycle in either the local-happens-before relation or the
+global-happens-before relation.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+The global- and local-happens-before relations are critical to
+defining what values are read and when data races occur.
+The global-happens-before relation, for example, defines what global memory
+operations definitely happen before what other global memory operations.
+If an operation <strong>A</strong> global-happens-before operation <strong>B</strong> then <strong>A</strong> must occur
+before <strong>B</strong>; in particular, any write done by <strong>A</strong> will be visible to <strong>B</strong>.
+The local-happens-before relation has similar properties for local memory.
+Programmers can use the local- and global-happens-before relations to reason
+about the order of program actions.
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p>A visible side effect <strong>A</strong> on a global object <strong>M</strong> with respect to a value
+computation <strong>B</strong> of <strong>M</strong> satisfies the conditions:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>A</strong> global-happens-before <strong>B</strong>, and</p>
+</li>
+<li>
+<p>there is no other side effect <strong>X</strong> to <strong>M</strong> such that <strong>A</strong>
+global-happens-before <strong>X</strong> and <strong>X</strong> global-happens-before <strong>B</strong>.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>We define visible side effects for local objects <strong>M</strong> similarly.
+The value of a non-atomic scalar object <strong>M</strong>, as determined by evaluation
+<strong>B</strong>, shall be the value stored by the visible side effect <strong>A</strong>.
+<a href="#iso-c11">[C11 standard, Section 5.1.2.4, paragraph 19, modified.]</a></p>
+</div>
+<div class="paragraph">
+<p>The execution of a program contains a data race if it contains two
+conflicting actions <strong>A</strong> and <strong>B</strong> in different units of execution, and</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>(1) at least one of <strong>A</strong> or <strong>B</strong> is not atomic, or <strong>A</strong> and <strong>B</strong> do not have
+inclusive memory scope, and</p>
+</li>
+<li>
+<p>(2) the actions are global actions unordered by the
+global-happens-before relation or are local actions unordered by the
+local-happens-before relation.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Any such data race results in undefined behavior.
+<a href="#iso-c11">[C11 standard, Section 5.1.2.4, paragraph 25, modified.]</a></p>
+</div>
+<div class="paragraph">
+<p>We also define the visible sequence of side effects on local and global
+atomic objects.
+The remaining paragraphs of this subsection define this sequence for a
+global atomic object <strong>M</strong>; the visible sequence of side effects for a local
+atomic object is defined similarly by using the local-happens-before
+relation.</p>
+</div>
+<div class="paragraph">
+<p>The visible sequence of side effects on a global atomic object <strong>M</strong>, with
+respect to a value computation <strong>B</strong> of <strong>M</strong>, is a maximal contiguous
+sub-sequence of side effects in the modification order of <strong>M</strong>, where the
+first side effect is visible with respect to <strong>B</strong>, and for every side effect,
+it is not the case that <strong>B</strong> global-happens-before it.
+The value of <strong>M</strong>, as determined by evaluation <strong>B</strong>, shall be the value stored
+by some operation in the visible sequence of <strong>M</strong> with respect to <strong>B</strong>.
+<a href="#iso-c11">[C11 standard, Section 5.1.2.4, paragraph 22, modified.]</a></p>
+</div>
+<div class="paragraph">
+<p>If an operation <strong>A</strong> that modifies an atomic object <strong>M</strong> global-happens before
+an operation <strong>B</strong> that modifies <strong>M</strong>, then <strong>A</strong> shall be earlier than <strong>B</strong> in
+the modification order of <strong>M</strong>.
+This requirement is known as write-write coherence.</p>
+</div>
+<div class="paragraph">
+<p>If a value computation <strong>A</strong> of an atomic object <strong>M</strong> global-happens-before a
+value computation <strong>B</strong> of <strong>M</strong>, and <strong>A</strong> takes its value from a side effect <strong>X</strong>
+on <strong>M</strong>, then the value computed by <strong>B</strong> shall either equal the value stored
+by <strong>X</strong>, or be the value stored by a side effect <strong>Y</strong> on <strong>M</strong>, where <strong>Y</strong>
+follows <strong>X</strong> in the modification order of <strong>M</strong>.
+This requirement is known as read-read coherence.
+<a href="#iso-c11">[C11 standard, Section 5.1.2.4, paragraph 22, modified.]</a></p>
+</div>
+<div class="paragraph">
+<p>If a value computation <strong>A</strong> of an atomic object <strong>M</strong> global-happens-before an
+operation <strong>B</strong> on <strong>M</strong>, then <strong>A</strong> shall take its value from a side effect <strong>X</strong>
+on <strong>M</strong>, where <strong>X</strong> precedes <strong>B</strong> in the modification order of <strong>M</strong>.
+This requirement is known as read-write coherence.</p>
+</div>
+<div class="paragraph">
+<p>If a side effect <strong>X</strong> on an atomic object <strong>M</strong> global-happens-before a value
+computation <strong>B</strong> of <strong>M</strong>, then the evaluation <strong>B</strong> shall take its value from
+<strong>X</strong> or from a side effect <strong>Y</strong> that follows <strong>X</strong> in the modification order of
+<strong>M</strong>.
+This requirement is known as write-read coherence.</p>
+</div>
+<div class="sect4">
+<h5 id="_memory_ordering_rules_atomic_operations">Memory Ordering Rules: Atomic Operations</h5>
+<div class="paragraph">
+<p>This and following sections describe how different program actions in kernel
+C code and the host program contribute to the local- and
+global-happens-before relations.
+This section discusses ordering rules for OpenCL 2.0 atomic operations.</p>
+</div>
+<div class="paragraph">
+<p><a href="#device-side-enqueue">Device-side enqueue</a> defines the enumerated type
+memory_order.</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>For <strong>memory_order_relaxed</strong>, no operation orders memory.</p>
+</li>
+<li>
+<p>For <strong>memory_order_release</strong>, <strong>memory_order_acq_rel</strong>, and
+<strong>memory_order_seq_cst</strong>, a store operation performs a release operation
+on the affected memory location.</p>
+</li>
+<li>
+<p>For <strong>memory_order_acquire</strong>, <strong>memory_order_acq_rel</strong>, and
+<strong>memory_order_seq_cst</strong>, a load operation performs an acquire operation
+on the affected memory location.
+<a href="#iso-c11">[C11 standard, Section 7.17.3, paragraphs 2-4, modified.]</a></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Certain built-in functions synchronize with other built-in functions
+performed by another unit of execution.
+This is true for pairs of release and acquire operations under specific
+circumstances.
+An atomic operation <strong>A</strong> that performs a release operation on a global object
+<strong>M</strong> global-synchronizes-with an atomic operation <strong>B</strong> that performs an
+acquire operation on <strong>M</strong> and reads a value written by any side effect in the
+release sequence headed by <strong>A</strong>.
+A similar rule holds for atomic operations on objects in local memory: an
+atomic operation <strong>A</strong> that performs a release operation on a local object <strong>M</strong>
+local-synchronizes-with an atomic operation <strong>B</strong> that performs an acquire
+operation on <strong>M</strong> and reads a value written by any side effect in the release
+sequence headed by <strong>A</strong>.
+<a href="#iso-c11">[C11 standard, Section 5.1.2.4, paragraph 11, modified.]</a></p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+Atomic operations specifying <strong>memory_order_relaxed</strong> are relaxed only
+with respect to memory ordering.
+Implementations must still guarantee that any given atomic access to a
+particular atomic object be indivisible with respect to all other atomic
+accesses to that object.
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p>There shall exist a single total order <strong>S</strong> for all <strong>memory_order_seq_cst</strong>
+operations that is consistent with the modification orders for all affected
+locations, as well as the appropriate global-happens-before and
+local-happens-before orders for those locations, such that each
+<strong>memory_order_seq</strong> operation <strong>B</strong> that loads a value from an atomic object
+<strong>M</strong> in global or local memory observes one of the following values:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>the result of the last modification <strong>A</strong> of <strong>M</strong> that precedes <strong>B</strong> in <strong>S</strong>,
+if it exists, or</p>
+</li>
+<li>
+<p>if <strong>A</strong> exists, the result of some modification of <strong>M</strong> in the visible
+sequence of side effects with respect to <strong>B</strong> that is not
+<strong>memory_order_seq_cst</strong> and that does not happen before <strong>A</strong>, or</p>
+</li>
+<li>
+<p>if <strong>A</strong> does not exist, the result of some modification of <strong>M</strong> in the
+visible sequence of side effects with respect to <strong>B</strong> that is not
+<strong>memory_order_seq_cst</strong>.
+<a href="#iso-c11">[C11 standard, Section 7.17.3, paragraph 6, modified.]</a></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Let X and Y be two <strong>memory_order_seq_cst</strong> operations.
+If X local-synchronizes-with or global-synchronizes-with Y then X both
+local-synchronizes-with Y and global-synchronizes-with Y.</p>
+</div>
+<div class="paragraph">
+<p>If the total order <strong>S</strong> exists, the following rules hold:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>For an atomic operation <strong>B</strong> that reads the value of an atomic object
+<strong>M</strong>, if there is a <strong>memory_order_seq_cst</strong> fence <strong>X</strong> sequenced-before
+<strong>B</strong>, then <strong>B</strong> observes either the last <strong>memory_order_seq_cst</strong>
+modification of <strong>M</strong> preceding <strong>X</strong> in the total order <strong>S</strong> or a later
+modification of <strong>M</strong> in its modification order.
+<a href="#iso-c11">[C11 standard, Section 7.17.3, paragraph 9.]</a></p>
+</li>
+<li>
+<p>For atomic operations <strong>A</strong> and <strong>B</strong> on an atomic object <strong>M</strong>, where <strong>A</strong>
+modifies <strong>M</strong> and <strong>B</strong> takes its value, if there is a
+<strong>memory_order_seq_cst</strong> fence <strong>X</strong> such that <strong>A</strong> is sequenced-before <strong>X</strong>
+and <strong>B</strong> follows <strong>X</strong> in <strong>S</strong>, then <strong>B</strong> observes either the effects of <strong>A</strong>
+or a later modification of <strong>M</strong> in its modification order.
+<a href="#iso-c11">[C11 standard, Section 7.17.3, paragraph 10.]</a></p>
+</li>
+<li>
+<p>For atomic operations <strong>A</strong> and <strong>B</strong> on an atomic object <strong>M</strong>, where <strong>A</strong>
+modifies <strong>M</strong> and <strong>B</strong> takes its value, if there are
+<strong>memory_order_seq_cst</strong> fences <strong>X</strong> and <strong>Y</strong> such that <strong>A</strong> is
+sequenced-before <strong>X</strong>, <strong>Y</strong> is sequenced-before <strong>B</strong>, and <strong>X</strong> precedes <strong>Y</strong>
+in <strong>S</strong>, then <strong>B</strong> observes either the effects of <strong>A</strong> or a later
+modification of <strong>M</strong> in its modification order.
+<a href="#iso-c11">[C11 standard, Section 7.17.3, paragraph 11.]</a></p>
+</li>
+<li>
+<p>For atomic operations <strong>A</strong> and <strong>B</strong> on an atomic object <strong>M</strong>, if there are
+<strong>memory_order_seq_cst</strong> fences <strong>X</strong> and <strong>Y</strong> such that <strong>A</strong> is
+sequenced-before <strong>X</strong>, <strong>Y</strong> is sequenced-before <strong>B</strong>, and <strong>X</strong> precedes <strong>Y</strong>
+in <strong>S</strong>, then <strong>B</strong> occurs later than <strong>A</strong> in the modification order of <strong>M</strong>.</p>
+</li>
+</ul>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<strong>memory_order_seq_cst</strong> ensures sequential consistency only for a
+program that is (1) free of data races, and (2) exclusively uses
+<strong>memory_order_seq_cst</strong> synchronization operations.
+Any use of weaker ordering will invalidate this guarantee unless extreme
+care is used.
+In particular, <strong>memory_order_seq_cst</strong> fences ensure a total order only for
+the fences themselves.
+Fences cannot, in general, be used to restore sequential consistency for
+atomic operations with weaker ordering specifications.
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p>Atomic read-modify-write operations should always read the last value (in
+the modification order) stored before the write associated with the
+read-modify-write operation.
+<a href="#iso-c11">[C11 standard, Section 7.17.3, paragraph 12.]</a></p>
+</div>
+<div class="paragraph">
+<p><span class="underline">Implementations should ensure that no "out-of-thin-air" values
+are computed that circularly depend on their own computation.</span></p>
+</div>
+<div class="paragraph">
+<p>Note: Under the rules described above, and independent to the previously
+footnoted C++ issue, it is known that <em>x == y == 42</em> is a valid final state
+in the following problematic example:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">global atomic_int x = ATOMIC_VAR_INIT(<span class="integer">0</span>);
+local atomic_int y = ATOMIC_VAR_INIT(<span class="integer">0</span>);
+
+<span class="label">unit_of_execution_1:</span>
+... [execution not reading or writing x or y, leading up to:]
+<span class="predefined-type">int</span> t = atomic_load_explicit(&amp;y, memory_order_acquire);
+atomic_store_explicit(&amp;x, t, memory_order_release);
+
+<span class="label">unit_of_execution_2:</span>
+... [execution not reading or writing x or y, leading up to:]
+<span class="predefined-type">int</span> t = atomic_load_explicit(&amp;x, memory_order_acquire);
+atomic_store_explicit(&amp;y, t, memory_order_release);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>This is not useful behavior and implementations should not exploit this
+phenomenon.
+It should be expected that in the future this may be disallowed by
+appropriate updates to the memory model description by the OpenCL committee.</p>
+</div>
+<div class="paragraph">
+<p>Implementations should make atomic stores visible to atomic loads within a
+reasonable amount of time.
+<a href="#iso-c11">[C11 standard, Section 7.17.3, paragraph 16.]</a></p>
+</div>
+<div class="paragraph">
+<p>As long as the following conditions are met, a host program sharing SVM
+memory with a kernel executing on one or more OpenCL devices may use atomic
+and synchronization operations to ensure that its assignments, and those of
+the kernel, are visible to each other:</p>
+</div>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>Either fine-grained buffer or fine-grained system SVM must be used to
+share memory.
+While coarse-grained buffer SVM allocations may support atomic
+operations, visibility on these allocations is not guaranteed except at
+map and unmap operations.</p>
+</li>
+<li>
+<p>The optional OpenCL 2.0 SVM atomic-controlled visibility specified by
+provision of the CL_MEM_SVM_ATOMICS flag must be supported by the device
+and the flag provided to the SVM buffer on allocation.</p>
+</li>
+<li>
+<p>The host atomic and synchronization operations must be compatible with
+those of an OpenCL kernel language.
+This requires that the size and representation of the data types that
+the host atomic operations act on be consistent with the OpenCL kernel
+language atomic types.</p>
+</li>
+</ol>
+</div>
+<div class="paragraph">
+<p>If these conditions are met, the host operations will apply at
+all_svm_devices scope.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="memory-ordering-fence">Memory Ordering Rules: Fence Operations</h5>
+<div class="paragraph">
+<p>This section describes how the OpenCL 2.0 fence operations contribute to the
+local- and global-happens-before relations.</p>
+</div>
+<div class="paragraph">
+<p>Earlier, we introduced synchronization primitives called fences.
+Fences can utilize the acquire memory_order, release memory_order, or both.
+A fence with acquire semantics is called an acquire fence; a fence with
+release semantics is called a release fence.  The <a href="#atomic-fence-orders">overview of atomic and fence operations</a> section decribes the memory orders
+that result in acquire and release fences.</p>
+</div>
+<div class="paragraph">
+<p>A global release fence <strong>A</strong> global-synchronizes-with a global acquire fence
+<strong>B</strong> if there exist atomic operations <strong>X</strong> and <strong>Y</strong>, both operating on some
+global atomic object <strong>M</strong>, such that <strong>A</strong> is sequenced-before <strong>X</strong>, <strong>X</strong>
+modifies <strong>M</strong>, <strong>Y</strong> is sequenced-before <strong>B</strong>, <strong>Y</strong> reads the value written by
+<strong>X</strong> or a value written by any side effect in the hypothetical release
+sequence <strong>X</strong> would head if it were a release operation, and that the scopes
+of <strong>A</strong>, <strong>B</strong> are inclusive.
+<a href="#iso-c11">[C11 standard, Section 7.17.4, paragraph 2, modified.]</a></p>
+</div>
+<div class="paragraph">
+<p>A global release fence <strong>A</strong> global-synchronizes-with an atomic operation <strong>B</strong>
+that performs an acquire operation on a global atomic object <strong>M</strong> if there
+exists an atomic operation <strong>X</strong> such that <strong>A</strong> is sequenced-before <strong>X</strong>, <strong>X</strong>
+modifies <strong>M</strong>, <strong>B</strong> reads the value written by <strong>X</strong> or a value written by any
+side effect in the hypothetical release sequence <strong>X</strong> would head if it were a
+release operation, and the scopes of <strong>A</strong> and <strong>B</strong> are inclusive.
+<a href="#iso-c11">[C11 standard, Section 7.17.4, paragraph 3, modified.]</a></p>
+</div>
+<div class="paragraph">
+<p>An atomic operation <strong>A</strong> that is a release operation on a global atomic
+object <strong>M</strong> global-synchronizes-with a global acquire fence <strong>B</strong> if there
+exists some atomic operation <strong>X</strong> on <strong>M</strong> such that <strong>X</strong> is sequenced-before
+<strong>B</strong> and reads the value written by <strong>A</strong> or a value written by any side effect
+in the release sequence headed by <strong>A</strong>, and the scopes of <strong>A</strong> and <strong>B</strong> are
+inclusive.
+<a href="#iso-c11">[C11 standard, Section 7.17.4, paragraph 4, modified.]</a></p>
+</div>
+<div class="paragraph">
+<p>A local release fence <strong>A</strong> local-synchronizes-with a local acquire fence <strong>B</strong>
+if there exist atomic operations <strong>X</strong> and <strong>Y</strong>, both operating on some local
+atomic object <strong>M</strong>, such that <strong>A</strong> is sequenced-before <strong>X</strong>, <strong>X</strong> modifies <strong>M</strong>,
+<strong>Y</strong> is sequenced-before <strong>B</strong>, and <strong>Y</strong> reads the value written by <strong>X</strong> or a
+value written by any side effect in the hypothetical release sequence <strong>X</strong>
+would head if it were a</p>
+</div>
+<div class="paragraph">
+<p>release operation, and the scopes of <strong>A</strong> and <strong>B</strong> are inclusive.
+<a href="#iso-c11">[C11 standard, Section 7.17.4, paragraph 2, modified.]</a></p>
+</div>
+<div class="paragraph">
+<p>A local release fence <strong>A</strong> local-synchronizes-with an atomic operation <strong>B</strong>
+that performs an acquire operation on a local atomic object <strong>M</strong> if there
+exists an atomic operation <strong>X</strong> such that <strong>A</strong> is sequenced-before <strong>X</strong>, <strong>X</strong>
+modifies <strong>M</strong>, and <strong>B</strong> reads the value written by <strong>X</strong> or a value written by
+any side effect in the hypothetical release sequence <strong>X</strong> would head if it
+were a release operation, and the scopes of <strong>A</strong> and <strong>B</strong> are inclusive.
+<a href="#iso-c11">[C11 standard, Section 7.17.4, paragraph 3, modified.]</a></p>
+</div>
+<div class="paragraph">
+<p>An atomic operation <strong>A</strong> that is a release operation on a local atomic object
+<strong>M</strong> local-synchronizes-with a local acquire fence <strong>B</strong> if there exists some
+atomic operation <strong>X</strong> on <strong>M</strong> such that <strong>X</strong> is sequenced-before <strong>B</strong> and reads
+the value written by <strong>A</strong> or a value written by any side effect in the
+release sequence headed by <strong>A</strong>, and the scopes of <strong>A</strong> and <strong>B</strong> are inclusive.
+<a href="#iso-c11">[C11 standard, Section 7.17.4, paragraph 4, modified.]</a></p>
+</div>
+<div class="paragraph">
+<p>Let <strong>X</strong> and <strong>Y</strong> be two work item fences that each have both the
+CLK_GLOBAL_MEM_FENCE and CLK_LOCAL_MEM_FENCE flags set.
+<strong>X</strong> global-synchronizes-with <strong>Y</strong> and <strong>X</strong> local synchronizes with <strong>Y</strong> if the
+conditions required for <strong>X</strong> to global-synchronize with <strong>Y</strong> are met, the
+conditions required for <strong>X</strong> to local-synchronize-with <strong>Y</strong> are met, or both
+sets of conditions are met.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="_memory_ordering_rules_work_group_functions">Memory Ordering Rules: Work-group Functions</h5>
+<div class="paragraph">
+<p>The OpenCL kernel execution model includes collective operations across the
+work-items within a single work-group.
+These are called work-group functions.
+Besides the work-group barrier function, they include the scan, reduction
+and pipe work-group functions described in the SPIR-V IL specifications.
+We will first discuss the work-group barrier.
+The other work-group functions are discussed afterwards.</p>
+</div>
+<div class="paragraph">
+<p>The barrier function provides a mechanism for a kernel to synchronize the
+work-items within a single work-group: informally, each work-item of the
+work-group must execute the barrier before any are allowed to proceed.
+It also orders memory operations to a specified combination of one or more
+address spaces such as local memory or global memory, in a similar manner to
+a fence.</p>
+</div>
+<div class="paragraph">
+<p>To precisely specify the memory ordering semantics for barrier, we need to
+distinguish between a dynamic and a static instance of the call to a
+barrier.
+A call to a barrier can appear in a loop, for example, and each execution of
+the same static barrier call results in a new dynamic instance of the
+barrier that will independently synchronize a work-groups work-items.</p>
+</div>
+<div class="paragraph">
+<p>A work-item executing a dynamic instance of a barrier results in two
+operations, both fences, that are called the entry and exit fences.
+These fences obey all the rules for fences specified elsewhere in this
+chapter as well as the following:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>The entry fence is a release fence with the same flags and scope as
+requested for the barrier.</p>
+</li>
+<li>
+<p>The exit fence is an acquire fence with the same flags and scope as
+requested for the barrier.</p>
+</li>
+<li>
+<p>For each work-item the entry fence is sequenced before the exit fence.</p>
+</li>
+<li>
+<p>If the flags have CLK_GLOBAL_MEM_FENCE set then for each work-item the
+entry fence global-synchronizes-with the exit fence of all other
+work-items in the same work-group.</p>
+</li>
+<li>
+<p>If the flags have CLK_LOCAL_MEM_FENCE set then for each work-item the
+entry fence local-synchronizes-with the exit fence of all other
+work-items in the same work-group.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The other work-group functions include such functions as work_group_all()
+and work_group_broadcast() and are described in the kernel language and IL
+specifications.
+The use of these work-group functions implies sequenced-before relationships
+between statements within the execution of a single work-item in order to
+satisfy data dependencies.
+For example, a work item that provides a value to a work-group function must
+behave as if it generates that value before beginning execution of that
+work-group function.
+Furthermore, the programmer must ensure that all work items in a work group
+must execute the same work-group function call site, or dynamic work-group
+function instance.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="_memory_ordering_rules_sub_group_functions">Memory Ordering Rules: Sub-group Functions</h5>
+<div class="paragraph">
+<p>The OpenCL kernel execution model includes collective operations across the
+work-items within a single sub-group.
+These are called sub-group functions.
+Besides the sub-group-barrier function, they include the scan, reduction and
+pipe sub-group functions described in the SPIR-V IL specification.
+We will first discuss the sub-group barrier.
+The other sub-group functions are discussed afterwards.</p>
+</div>
+<div class="paragraph">
+<p>The barrier function provides a mechanism for a kernel to synchronize the
+work-items within a single sub-group: informally, each work-item of the
+sub-group must execute the barrier before any are allowed to proceed.
+It also orders memory operations to a specified combination of one or more
+address spaces such as local memory or global memory, in a similar manner to
+a fence.</p>
+</div>
+<div class="paragraph">
+<p>To precisely specify the memory ordering semantics for barrier, we need to
+distinguish between a dynamic and a static instance of the call to a
+barrier.
+A call to a barrier can appear in a loop, for example, and each execution of
+the same static barrier call results in a new dynamic instance of the
+barrier that will independently synchronize a sub-groups work-items.</p>
+</div>
+<div class="paragraph">
+<p>A work-item executing a dynamic instance of a barrier results in two
+operations, both fences, that are called the entry and exit fences.
+These fences obey all the rules for fences specified elsewhere in this
+chapter as well as the following:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>The entry fence is a release fence with the same flags and scope as
+requested for the barrier.</p>
+</li>
+<li>
+<p>The exit fence is an acquire fence with the same flags and scope as
+requested for the barrier.</p>
+</li>
+<li>
+<p>For each work-item the entry fence is sequenced before the exit fence.</p>
+</li>
+<li>
+<p>If the flags have CLK_GLOBAL_MEM_FENCE set then for each work-item the
+entry fence global-synchronizes-with the exit fence of all other
+work-items in the same sub-group.</p>
+</li>
+<li>
+<p>If the flags have CLK_LOCAL_MEM_FENCE set then for each work-item the
+entry fence local-synchronizes-with the exit fence of all other
+work-items in the same sub-group.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The other sub-group functions include such functions as sub_group_all() and
+sub_group_broadcast() and are described in OpenCL kernel languages
+specifications.
+The use of these sub-group functions implies sequenced-before relationships
+between statements within the execution of a single work-item in order to
+satisfy data dependencies.
+For example, a work item that provides a value to a sub-group function must
+behave as if it generates that value before beginning execution of that
+sub-group function.
+Furthermore, the programmer must ensure that all work items in a sub-group
+must execute the same sub-group function call site, or dynamic sub-group
+function instance.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="_memory_ordering_rules_host_side_and_device_side_commands">Memory Ordering Rules: Host-side and Device-side Commands</h5>
+<div class="paragraph">
+<p>This section describes how the OpenCL API functions associated with
+command-queues contribute to happens-before relations.
+There are two types of command queues and associated API functions in OpenCL
+2.0; <em>host command-queues</em> and <em>device command-queues</em>.
+The interaction of these command queues with the memory model are for the
+most part equivalent.
+In a few cases, the rules only applies to the host command-queue.
+We will indicate these special cases by specifically denoting the host
+command-queue in the memory ordering rule.
+SVM memory consistency in such instances is implied only with respect to
+synchronizing host commands.</p>
+</div>
+<div class="paragraph">
+<p>Memory ordering rules in this section apply to all memory objects (buffers,
+images and pipes) as well as to SVM allocations where no earlier, and more
+fine-grained, rules apply.</p>
+</div>
+<div class="paragraph">
+<p>In the remainder of this section, we assume that each command <strong>C</strong> enqueued
+onto a command-queue has an associated event object <strong>E</strong> that signals its
+execution status, regardless of whether <strong>E</strong> was returned to the unit of
+execution that enqueued <strong>C</strong>.
+We also distinguish between the API function call that enqueues a command
+<strong>C</strong> and creates an event <strong>E</strong>, the execution of <strong>C</strong>, and the completion of
+<strong>C</strong>(which marks the event <strong>E</strong> as complete).</p>
+</div>
+<div class="paragraph">
+<p>The ordering and synchronization rules for API commands are defined as
+following:</p>
+</div>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>If an API function call <strong>X</strong> enqueues a command <strong>C</strong>, then <strong>X</strong>
+global-synchronizes-with <strong>C</strong>.
+For example, a host API function to enqueue a kernel
+global-synchronizes-with the start of that kernel-instances execution,
+so that memory updates sequenced-before the enqueue kernel function call
+will global-happen-before any kernel reads or writes to those same
+memory locations.
+For a device-side enqueue, global memory updates sequenced before <strong>X</strong>
+happens-before <strong>C</strong> reads or writes to those memory locations only in the
+case of fine-grained SVM.</p>
+</li>
+<li>
+<p>If <strong>E</strong> is an event upon which a command <strong>C</strong> waits, then <strong>E</strong>
+global-synchronizes-with <strong>C</strong>.
+In particular, if <strong>C</strong> waits on an event <strong>E</strong> that is tracking the
+execution status of the command <strong>C1</strong>, then memory operations done by
+<strong>C1</strong> will global-happen-before memory operations done by <strong>C</strong>.
+As an example, assume we have an OpenCL program using coarse-grain SVM
+sharing that enqueues a kernel to a host command-queue to manipulate the
+contents of a region of a buffer that the host thread then accesses
+after the kernel completes.
+To do this, the host thread can call <strong>clEnqueueMapBuffer</strong> to enqueue a
+blocking-mode map command to map that buffer region, specifying that the
+map command must wait on an event signaling the kernels completion.
+When <strong>clEnqueueMapBuffer</strong> returns, any memory operations performed by
+the kernel to that buffer region will global- happen-before subsequent
+memory operations made by the host thread.</p>
+</li>
+<li>
+<p>If a command <strong>C</strong> has an event <strong>E</strong> that signals its completion, then <strong>C</strong>
+global- synchronizes-with <strong>E</strong>.</p>
+</li>
+<li>
+<p>For a command <strong>C</strong> enqueued to a host-side command queue, if <strong>C</strong> has an
+event <strong>E</strong> that signals its completion, then <strong>E</strong> global-synchronizes-with
+an API call <strong>X</strong> that waits on <strong>E</strong>.
+For example, if a host thread or kernel-instance calls the
+wait-for-events function on <strong>E</strong> (e.g. the <strong>clWaitForEvents</strong> function
+called from a host thread), then <strong>E</strong> global-synchronizes-with that
+wait-for-events function call.</p>
+</li>
+<li>
+<p>If commands <strong>C</strong> and <strong>C1</strong> are enqueued in that sequence onto an in-order
+command-queue, then the event (including the event implied between <strong>C</strong>
+and <strong>C1</strong> due to the in-order queue) signaling <strong>C</strong>'s completion
+global-synchronizes-with <strong>C1</strong>.
+Note that in OpenCL 2.0, only a host command-queue can be configured as
+an in-order queue.</p>
+</li>
+<li>
+<p>If an API call enqueues a marker command <strong>C</strong> with an empty list of
+events upon which <strong>C</strong> should wait, then the events of all commands
+enqueued prior to <strong>C</strong> in the command-queue global-synchronize-with <strong>C</strong>.</p>
+</li>
+<li>
+<p>If a host API call enqueues a command-queue barrier command <strong>C</strong> with an
+empty list of events on which <strong>C</strong> should wait, then the events of all
+commands enqueued prior to <strong>C</strong> in the command-queue
+global-synchronize-with <strong>C</strong>.
+In addition, the event signaling the completion of <strong>C</strong>
+global-synchronizes-with all commands enqueued after <strong>C</strong> in the
+command-queue.</p>
+</li>
+<li>
+<p>If a host thread executes a <strong>clFinish</strong> call <strong>X</strong>, then the events of all
+commands enqueued prior to <strong>X</strong> in the command-queue
+global-synchronizes-with <strong>X</strong>.</p>
+</li>
+<li>
+<p>The start of a kernel-instance <strong>K</strong> global-synchronizes-with all
+operations in the work items of <strong>K</strong>.
+Note that this includes the execution of any atomic operations by the
+work items in a program using fine-grain SVM.</p>
+</li>
+<li>
+<p>All operations of all work items of a kernel-instance <strong>K</strong>
+global-synchronizes-with the event signaling the completion of <strong>K</strong>.
+Note that this also includes the execution of any atomic operations by
+the work items in a program using fine-grain SVM.</p>
+</li>
+<li>
+<p>If a callback procedure <strong>P</strong> is registered on an event <strong>E</strong>, then <strong>E</strong>
+global-synchronizes-with all operations of <strong>P</strong>.
+Note that callback procedures are only defined for commands within host
+command-queues.</p>
+</li>
+<li>
+<p>If <strong>C</strong> is a command that waits for an event <strong>E</strong>'s completion, and API
+function call <strong>X</strong> sets the status of a user event <strong>E</strong>'s status to
+CL_COMPLETE (for example, from a host thread using a
+<strong>clSetUserEventStatus</strong> function), then <strong>X</strong> global-synchronizes-with <strong>C</strong>.</p>
+</li>
+<li>
+<p>If a device enqueues a command <strong>C</strong> with the
+CLK_ENQUEUE_FLAGS_WAIT_KERNEL flag, then the end state of the parent
+kernel instance global-synchronizes with <strong>C</strong>.</p>
+</li>
+<li>
+<p>If a work-group enqueues a command <strong>C</strong> with the
+CLK_ENQUEUE_FLAGS_WAIT_WORK_GROUP flag, then the end state of the
+work-group global-synchronizes with <strong>C</strong>.</p>
+</li>
+</ol>
+</div>
+<div class="paragraph">
+<p>When using an out-of-order command queue, a wait on an event or a marker or
+command-queue barrier command can be used to ensure the correct ordering of
+dependent commands.
+In those cases, the wait for the event or the marker or barrier command will
+provide the necessary global-synchronizes-with relation.</p>
+</div>
+<div class="paragraph">
+<p>In this situation:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>access to shared locations or disjoint locations in a single cl_mem
+object when using atomic operations from different kernel instances
+enqueued from the host such that one or more of the atomic operations is
+a write is implementation-defined and correct behavior is not guaranteed
+except at synchronization points.</p>
+</li>
+<li>
+<p>access to shared locations or disjoint locations in a single cl_mem
+object when using atomic operations from different kernel instances
+consisting of a parent kernel and any number of child kernels enqueued
+by that kernel is guaranteed under the memory ordering rules described
+earlier in this section.</p>
+</li>
+<li>
+<p>access to shared locations or disjoint locations in a single program
+scope global variable, coarse-grained SVM allocation or fine-grained SVM
+allocation when using atomic operations from different kernel instances
+enqueued from the host to a single device is guaranteed under the memory
+ordering rules described earlier in this section.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If fine-grain SVM is used but without support for the OpenCL 2.0 atomic
+operations, then the host and devices can concurrently read the same memory
+locations and can concurrently update non-overlapping memory regions, but
+attempts to update the same memory locations are undefined.
+Memory consistency is guaranteed at the OpenCL synchronization points
+without the need for calls to <strong>clEnqueueMapBuffer</strong> and
+<strong>clEnqueueUnmapMemObject</strong>.
+For fine-grained SVM buffers it is guaranteed that at synchronization points
+only values written by the kernel will be updated.
+No writes to fine-grained SVM buffers can be introduced that were not in the
+original program.</p>
+</div>
+<div class="paragraph">
+<p>In the remainder of this section, we discuss a few points regarding the
+ordering rules for commands with a host command queue.</p>
+</div>
+<div class="paragraph">
+<p>The OpenCL 1.2 standard describes a synchronization point as a
+kernel-instance or host program location where the contents of memory
+visible to different work-items or command-queue commands are the same.
+It also says that waiting on an event and a command-queue barrier are
+synchronization points between commands in command- queues.
+Four of the rules listed above (2, 4, 7, and 8) cover these OpenCL
+synchronization points.</p>
+</div>
+<div class="paragraph">
+<p>A map operation (<strong>clEnqueueMapBuffer</strong> or <strong>clEnqueueMapImage</strong>) performed on a
+non-SVM buffer or a coarse-grained SVM buffer is allowed to overwrite the
+entire target region with the latest runtime view of the data as seen by the
+command with which the map operation synchronizes, whether the values were
+written by the executing kernels or not.
+Any values that were changed within this region by another kernel or host
+thread while the kernel synchronizing with the map operation was executing
+may be overwritten by the map operation.</p>
+</div>
+<div class="paragraph">
+<p>Access to non-SVM cl_mem buffers and coarse-grained SVM allocations is
+ordered at synchronization points between host commands.
+In the presence of an out-of-order command queue or a set of command queues
+mapped to the same device, multiple kernel instances may execute
+concurrently on the same device.</p>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="opencl-framework">3.4. The OpenCL Framework</h3>
+<div class="paragraph">
+<p>The OpenCL framework allows applications to use a host and one or more
+OpenCL devices as a single heterogeneous parallel computer system.
+The framework contains the following components:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>OpenCL Platform layer</strong>: The platform layer allows the host program to
+discover OpenCL devices and their capabilities and to create contexts.</p>
+</li>
+<li>
+<p><strong>OpenCL Runtime</strong>: The runtime allows the host program to manipulate
+contexts once they have been created.</p>
+</li>
+<li>
+<p><strong>OpenCL Compiler</strong>: The OpenCL compiler creates program executables that
+contain OpenCL kernels.
+SPIR-V intermediate language, OpenCL C, OpenCL C++, and OpenCL C
+language versions from earlier OpenCL specifications are supported by
+the compiler.
+Other input languages may be supported by some implementations.</p>
+</li>
+</ul>
+</div>
+<div class="sect3">
+<h4 id="_opencl_framework_mixed_version_support">3.4.1. OpenCL Framework: Mixed Version Support</h4>
+<div class="paragraph">
+<p>OpenCL supports devices with different capabilities under a single platform.
+This includes devices which conform to different versions of the OpenCL
+specification.
+There are three version identifiers to consider for an OpenCL system: the
+platform version, the version of a device, and the version(s) of the kernel
+language or IL supported on a device.</p>
+</div>
+<div class="paragraph">
+<p>The platform version indicates the version of the OpenCL runtime that is
+supported.
+This includes all of the APIs that the host can use to interact with
+resources exposed by the OpenCL runtime; including contexts, memory objects,
+devices, and command queues.</p>
+</div>
+<div class="paragraph">
+<p>The device version is an indication of the device&#8217;s capabilities separate
+from the runtime and compiler as represented by the device info returned by
+<strong>clGetDeviceInfo</strong>.
+Examples of attributes associated with the device version are resource
+limits (e.g., minimum size of local memory per compute unit) and extended
+functionality (e.g., list of supported KHR extensions).
+The version returned corresponds to the highest version of the OpenCL
+specification for which the device is conformant, but is not higher than the
+platform version.</p>
+</div>
+<div class="paragraph">
+<p>The language version for a device represents the OpenCL programming language
+features a developer can assume are supported on a given device.
+The version reported is the highest version of the language supported.</p>
+</div>
+<div class="paragraph">
+<p>Backwards compatibility is an important goal for the OpenCL standard.
+Backwards compatibility is expected such that a device will consume earlier
+versions of the SPIR-V and OpenCL C programming languages with the following
+minimum requirements:</p>
+</div>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>An OpenCL 1.x device must support at least one 1.x version of the OpenCL
+C programming language.</p>
+</li>
+<li>
+<p>An OpenCL 2.0 device must support all the requirements of an OpenCL 1.x
+device in addition to the OpenCL C 2.0 programming language.
+If multiple language versions are supported, the compiler defaults to
+using the highest OpenCL 1.x language version supported for the device
+(typically OpenCL 1.2).
+To utilize the OpenCL 2.0 Kernel programming language, a programmer must
+specifically set the appropriate compiler flag (-cl-std=CL2.0).
+The language version must not be higher than the platform version, but
+may exceed the <a href="#opencl-c-version">device version</a>.</p>
+</li>
+<li>
+<p>An OpenCL 2.1 device must support all the requirements of an OpenCL 2.0
+device in addition to the SPIR-V intermediate language at version 1.0 or
+above.
+Intermediate language versioning is encoded as part of the binary object
+and no flags are required to be passed to the compiler.</p>
+</li>
+<li>
+<p>An OpenCL 2.2 device must support all the requirements of an OpenCL 2.0
+device in addition to the SPIR-V intermediate language at version 1.2 or
+above.
+Intermediate language is encoded as a part of the binary object and no
+flags are required to be passed to the compiler.</p>
+</li>
+</ol>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="opencl-platform-layer">4. The OpenCL Platform Layer</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>This section describes the OpenCL platform layer which implements
+platform-specific features that allow applications to query OpenCL devices,
+device configuration information, and to create OpenCL contexts using one or
+more devices.</p>
+</div>
+<div class="sect2">
+<h3 id="_querying_platform_info">4.1. Querying Platform Info</h3>
+<div class="paragraph">
+<p>The list of platforms available can be obtained using the following
+function.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clGetPlatformIDs(cl_uint num_entries,
+                        cl_platform_id *platforms,
+                        cl_uint *num_platforms)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><em>num_entries</em> is the number of cl_platform_id entries that can be added to
+<em>platforms</em>.
+If <em>platforms</em> is not <code>NULL</code>, the <em>num_entries</em> must be greater than zero.</p>
+</div>
+<div class="paragraph">
+<p><em>platforms</em> returns a list of OpenCL platforms found.
+The cl_platform_id_ values returned in <em>platforms</em> can be used to identify a
+specific OpenCL platform.
+If <em>platforms</em> argument is <code>NULL</code>, this argument is ignored.
+The number of OpenCL platforms returned is the minimum of the value
+specified by <em>num_entries</em> or the number of OpenCL platforms available.</p>
+</div>
+<div class="paragraph">
+<p><em>num_platforms</em> returns the number of OpenCL platforms available.
+If <em>num_platforms</em> is <code>NULL</code>, this argument is ignored.</p>
+</div>
+<div class="paragraph">
+<p><strong>clGetPlatformIDs</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_VALUE if <em>num_entries</em> is equal to zero and <em>platforms</em> is
+not <code>NULL</code> or if both <em>num_platforms</em> and <em>platforms</em> are <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clGetPlatformInfo(cl_platform_id platform,
+                         cl_platform_info param_name,
+                         size_t param_value_size,
+                         <span class="directive">void</span> *param_value,
+                         size_t *param_value_size_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>gets specific information about the OpenCL platform.
+The information that can be queried using <strong>clGetPlatformInfo</strong> is specified
+in the <a href="#platform-queries-table">Platform Queries</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>platform</em> refers to the platform ID returned by <strong>clGetPlatformIDs</strong> or can
+be <code>NULL</code>.
+If <em>platform</em> is <code>NULL</code>, the behavior is implementation-defined.</p>
+</div>
+<div class="paragraph">
+<p><em>param_name</em> is an enumeration constant that identifies the platform
+information being queried.
+It can be one of the following values as specified in the
+<a href="#platform-queries-table">Platform Queries</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value</em> is a pointer to memory location where appropriate values for a
+given <em>param_name</em>, as specified in the <a href="#platform-queries-table">Platform
+Queries</a> table, will be returned.
+If <em>param_value</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size</em> specifies the size in bytes of memory pointed to by
+<em>param_value</em>.
+This size in bytes must be ≥ size of return type specified in the
+<a href="#platform-queries-table">Platform Queries</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size_ret</em> returns the actual size in bytes of data being
+queried by <em>param_name</em>.
+If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<table id="platform-queries-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 3. OpenCL Platform Queries</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 10%;">
+<col style="width: 40%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_platform_info</strong></th>
+<th class="tableblock halign-left valign-top">Return Type</th>
+<th class="tableblock halign-left valign-top">Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PLATFORM_PROFILE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">char[]<sup>1</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">OpenCL profile string.
+        Returns the profile name supported by the implementation.
+        The profile name returned can be one of the following strings:</p>
+<p class="tableblock">        FULL_PROFILE - if the implementation supports the OpenCL
+        specification (functionality defined as part of the core
+        specification and does not require any extensions to be supported).</p>
+<p class="tableblock">        EMBEDDED_PROFILE - if the implementation supports the OpenCL
+        embedded profile.
+        The embedded profile is defined to be a subset for each version of
+        OpenCL.
+        The embedded profile for OpenCL 2.2 is described in
+        <a href="#opencl-embedded-profile">OpenCL Embedded Profile</a>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PLATFORM_VERSION</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">OpenCL version string.
+        Returns the OpenCL version supported by the implementation.
+        This version string has the following format:</p>
+<p class="tableblock">        <em>OpenCL&lt;space&gt;&lt;major_version.minor_version&gt;&lt;space&gt;&lt;platform-specific
+        information&gt;</em></p>
+<p class="tableblock">        The <em>major_version.minor_version</em> value returned will be 2.2.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PLATFORM_NAME</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Platform name string.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PLATFORM_VENDOR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Platform vendor string.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PLATFORM_EXTENSIONS</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns a space separated list of extension names (the extension
+        names themselves do not contain any spaces) supported by the
+        platform.
+        Each extension that is supported by all devices associated with this
+        platform must be reported here.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PLATFORM_HOST_TIMER_RESOLUTION</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_ulong</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the resolution of the host timer in nanoseconds as used by
+        <strong>clGetDeviceAndHostTimer</strong>.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p><strong>clGetPlatformInfo</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors<sup>2</sup>.</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_PLATFORM if <em>platform</em> is not a valid platform.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>param_name</em> is not one of the supported values or
+if size in bytes specified by <em>param_value_size</em> is &lt; size of return
+type as specified in the <a href="#platform-queries-table">OpenCL Platform
+Queries</a> table, and <em>param_value</em> is not a <code>NULL</code> value.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+<div class="dlist">
+<dl>
+<dt class="hdlist1">1</dt>
+<dd>
+<p>A null terminated string is returned by OpenCL query function calls if
+the return type of the information being queried is a char[].</p>
+</dd>
+<dt class="hdlist1">2</dt>
+<dd>
+<p>The OpenCL specification does not describe the order of precedence for
+error codes returned by API calls.</p>
+</dd>
+</dl>
+</div>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect2">
+<h3 id="platform-querying-devices">4.2. Querying Devices</h3>
+<div class="paragraph">
+<p>The list of devices available on a platform can be obtained using the
+following function<sup>3</sup>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clGetDeviceIDs(cl_platform_id platform,
+                      cl_device_type device_type,
+                      cl_uint num_entries,
+                      cl_device_id * devices,
+                      cl_uint *num_devices)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><em>platform</em> refers to the platform ID returned by <strong>clGetPlatformIDs</strong> or can
+be <code>NULL</code>.
+If <em>platform</em> is <code>NULL</code>, the behavior is implementation-defined.</p>
+</div>
+<div class="paragraph">
+<p><em>device_type</em> is a bitfield that identifies the type of OpenCL device.
+The <em>device_type</em> can be used to query specific OpenCL devices or all OpenCL
+devices available.
+The valid values for <em>device_type</em> are specified in the
+<a href="#device-categories-table">Device Categories</a> table.</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1">3</dt>
+<dd>
+<p><strong>clGetDeviceIDs</strong> may return all or a subset of the actual physical
+devices present in the platform and that match <em>device_type</em>.</p>
+</dd>
+</dl>
+</div>
+<table id="device-categories-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 4. List of OpenCL Device Categories</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_device_type</strong></th>
+<th class="tableblock halign-left valign-top">Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_TYPE_CPU</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">An OpenCL device that is the host processor.
+    The host processor runs the OpenCL implementations and is a single or
+    multi-core CPU.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_TYPE_GPU</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">An OpenCL device that is a GPU.
+    By this we mean that the device can also be used to accelerate a 3D API
+    such as OpenGL or DirectX.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_TYPE_ACCELERATOR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Dedicated OpenCL accelerators (for example the IBM CELL Blade).
+    These devices communicate with the host processor using a peripheral
+    interconnect such as PCIe.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_TYPE_CUSTOM</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Dedicated accelerators that do not support programs written in an OpenCL
+    kernel language,</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_TYPE_DEFAULT</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The default OpenCL device in the system.
+    The default device cannot be a <strong>CL_DEVICE_TYPE_CUSTOM</strong> device.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_TYPE_ALL</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">All OpenCL devices available in the system except
+    <strong>CL_DEVICE_TYPE_CUSTOM</strong> devices..</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p><em>num_entries</em> is the number of cl_device_id entries that can be added to
+<em>devices</em>.
+If <em>devices</em> is not <code>NULL</code>, the <em>num_entries</em> must be greater than zero.</p>
+</div>
+<div class="paragraph">
+<p><em>devices</em> returns a list of OpenCL devices found.
+The cl_device_id values returned in <em>devices</em> can be used to identify a
+specific OpenCL device.
+If <em>devices</em> argument is <code>NULL</code>, this argument is ignored.
+The number of OpenCL devices returned is the minimum of the value specified
+by <em>num_entries</em> or the number of OpenCL devices whose type matches
+<em>device_type</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>num_devices</em> returns the number of OpenCL devices available that match
+<em>device_type</em>.
+If <em>num_devices</em> is <code>NULL</code>, this argument is ignored.</p>
+</div>
+<div class="paragraph">
+<p><strong>clGetDeviceIDs</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_PLATFORM if <em>platform</em> is not a valid platform.</p>
+</li>
+<li>
+<p>CL_INVALID_DEVICE_TYPE if <em>device_type</em> is not a valid value.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>num_entries</em> is equal to zero and <em>devices</em> is not
+<code>NULL</code> or if both <em>num_devices</em> and <em>devices</em> are <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_DEVICE_NOT_FOUND if no OpenCL devices that matched <em>device_type</em> were
+found.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The application can query specific capabilities of the OpenCL device(s)
+returned by <strong>clGetDeviceIDs</strong>.
+This can be used by the application to determine which device(s) to use.</p>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clGetDeviceInfo(cl_device_id device,
+                       cl_device_info param_name,
+                       size_t param_value_size,
+                       <span class="directive">void</span> *param_value,
+                       size_t *param_value_size_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>gets specific information about an OpenCL device.</p>
+</div>
+<div class="paragraph">
+<p><em>device</em> may be a device returned by <strong>clGetDeviceIDs</strong> or a sub-device
+created by <strong>clCreateSubDevices</strong>.
+If <em>device</em> is a sub-device, the specific information for the sub-device
+will be returned.
+The information that can be queried using <strong>clGetDeviceInfo</strong> is specified in
+the <a href="#device-queries-table">Device Queries</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>param_name</em> is an enumeration constant that identifies the device
+information being queried.
+It can be one of the following values as specified in the
+<a href="#device-queries-table">Device Queries</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value</em> is a pointer to memory location where appropriate values for a
+given <em>param_name</em>, as specified in the <a href="#device-queries-table">Device
+Queries</a> table, will be returned.
+If <em>param_value</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size</em> specifies the size in bytes of memory pointed to by
+<em>param_value</em>.
+This size in bytes must be ≥ size of return type specified in the
+<a href="#device-queries-table">Device Queries</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size_ret</em> returns the actual size in bytes of data being
+queried by <em>param_name</em>.
+If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<table id="device-queries-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 5. OpenCL Device Queries</caption>
+<colgroup>
+<col style="width: 30%;">
+<col style="width: 20%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_device_info</strong></th>
+<th class="tableblock halign-left valign-top">Return Type</th>
+<th class="tableblock halign-left valign-top">Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_TYPE</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_type</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The OpenCL device type.
+        Currently supported values are:</p>
+<p class="tableblock">        CL_DEVICE_TYPE_CPU, CL_DEVICE_TYPE_GPU, CL_DEVICE_TYPE_ACCELERATOR,
+        CL_DEVICE_TYPE_DEFAULT, a combination of the above types or
+        CL_DEVICE_TYPE_CUSTOM.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_VENDOR_ID</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A unique device vendor identifier.
+        An example of a unique device identifier could be the PCIe ID.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_COMPUTE_UNITS</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The number of parallel compute units on the OpenCL device.
+        A work-group executes on a single compute unit.
+        The minimum value is 1.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Maximum dimensions that specify the global and local work-item IDs
+        used by the data parallel execution model. (Refer to
+        <strong>clEnqueueNDRangeKernel</strong>).
+        The minimum value is 3 for devices that are not of type
+        CL_DEVICE_TYPE_CUSTOM.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_WORK_ITEM_SIZES</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t []</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Maximum number of work-items that can be specified in each dimension
+        of the work-group to <strong>clEnqueueNDRangeKernel</strong>.</p>
+<p class="tableblock">        Returns <em>n</em> size_t entries, where <em>n</em> is the value returned by the
+        query for CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS.</p>
+<p class="tableblock">        The minimum value is (1, 1, 1) for devices that are not of type
+        CL_DEVICE_TYPE_CUSTOM.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_WORK_GROUP_SIZE</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Maximum number of work-items in a work-group that a device is
+        capable of executing on a single compute unit, for any given
+        kernel-instance running on the device. (Refer also to
+        <strong>clEnqueueNDRangeKernel</strong> and CL_KERNEL_WORK_GROUP_SIZE ).
+        The minimum value is 1.
+        The returned value is an upper limit and will not necessarily
+        maximize performance.
+        This maximum may be larger than supported by a specific kernel
+        (refer to the CL_KERNEL_WORK_GROUP_SIZE query of <strong>clGetKernelWorkGroupInfo</strong>).</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR  <br>
+  CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT <br>
+  CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT   <br>
+  CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG  <br>
+  CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT <br>
+  CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE<br>
+  CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Preferred native vector width size for built-in scalar types that
+        can be put into vectors.
+        The vector width is defined as the number of scalar elements that
+        can be stored in the vector.</p>
+<p class="tableblock">        If double precision is not supported,
+        CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE must return 0.</p>
+<p class="tableblock">        If the <strong>cl_khr_fp16</strong> extension is not supported,
+        CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF must return 0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR  <br>
+  CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT <br>
+  CL_DEVICE_NATIVE_VECTOR_WIDTH_INT   <br>
+  CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG  <br>
+  CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT <br>
+  CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE<br>
+  CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the native ISA vector width.
+        The vector width is defined as the number of scalar elements that
+        can be stored in the vector.</p>
+<p class="tableblock">        If double precision is not supported,
+        CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE must return 0.</p>
+<p class="tableblock">        If the <strong>cl_khr_fp16</strong> extension is not supported,
+        CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF must return 0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_CLOCK_FREQUENCY</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Clock frequency of the device in MHz.
+        The meaning of this value is implementation-defined.
+        For devices with multiple clock domains, the clock frequency for any
+        of the clock domains may be returned.
+        For devices that dynamically change frequency for power or thermal
+        reasons, the returned clock frequency may be any valid frequency.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_ADDRESS_BITS</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The default compute device address space size of the global address
+        space specified as an unsigned integer value in bits.
+        Currently supported values are 32 or 64 bits.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_MEM_ALLOC_SIZE</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_ulong</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Max size of memory object allocation in bytes.
+        The minimum value is max(min(1024 × 1024 × 1024, 1/4<sup>th</sup>
+        of CL_DEVICE_GLOBAL_MEM_SIZE), 32 × 1024 × 1024) for
+        devices that are not of type CL_DEVICE_TYPE_CUSTOM.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_IMAGE_SUPPORT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Is CL_TRUE if images are supported by the OpenCL device and CL_FALSE
+        otherwise.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_READ_IMAGE_ARGS</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Max number of image objects arguments of a kernel declared with the
+        read_only qualifier.
+        The minimum value is 128 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_WRITE_IMAGE_ARGS</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Max number of image objects arguments of a kernel declared with the
+        write_only qualifier.
+        The minimum value is 64 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS<sup>4</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Max number of image objects arguments of a kernel declared with the
+        write_only or read_write qualifier.
+        The minimum value is 64 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_IL_VERSION</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The intermediate languages that can be supported by
+        <strong>clCreateProgramWithIL</strong> for this device.
+        Returns a space-separated list of IL version strings of the form
+        &lt;IL_Prefix&gt;_&lt;Major_Version&gt;.&lt;Minor_Version&gt;.
+        For OpenCL 2.2, SPIR-V is a required IL prefix.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_IMAGE2D_MAX_WIDTH</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Max width of 2D image or 1D image not created from a buffer object
+        in pixels.</p>
+<p class="tableblock">        The minimum value is 16384 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_IMAGE2D_MAX_HEIGHT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Max height of 2D image in pixels.</p>
+<p class="tableblock">        The minimum value is 16384 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_IMAGE3D_MAX_WIDTH</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Max width of 3D image in pixels.</p>
+<p class="tableblock">        The minimum value is 2048 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_IMAGE3D_MAX_HEIGHT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Max height of 3D image in pixels.</p>
+<p class="tableblock">        The minimum value is 2048 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_IMAGE3D_MAX_DEPTH</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Max depth of 3D image in pixels.</p>
+<p class="tableblock">        The minimum value is 2048 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_IMAGE_MAX_BUFFER_SIZE</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Max number of pixels for a 1D image created from a buffer object.</p>
+<p class="tableblock">        The minimum value is 65536 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_IMAGE_MAX_ARRAY_SIZE</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Max number of images in a 1D or 2D image array.</p>
+<p class="tableblock">        The minimum value is 2048 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_SAMPLERS</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Maximum number of samplers that can be used in a kernel.</p>
+<p class="tableblock">        The minimum value is 16 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_IMAGE_PITCH_ALIGNMENT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The row pitch alignment size in pixels for 2D images created from a
+        buffer.
+        The value returned must be a power of 2.</p>
+<p class="tableblock">        If the device does not support images, this value must be 0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This query should be used when a 2D image is created from a buffer
+        which was created using CL_MEM_USE_HOST_PTR.
+        The value returned must be a power of 2.</p>
+<p class="tableblock">        This query specifies the minimum alignment in pixels of the host_ptr
+        specified to <strong>clCreateBuffer</strong>.</p>
+<p class="tableblock">        If the device does not support images, this value must be 0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_PIPE_ARGS</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The maximum number of pipe objects that can be passed as arguments
+        to a kernel.
+        The minimum value is 16.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The maximum number of reservations that can be active for a pipe per
+        work-item in a kernel.
+        A work-group reservation is counted as one reservation per
+        work-item.
+        The minimum value is 1.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PIPE_MAX_PACKET_SIZE</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The maximum size of pipe packet in bytes.
+        The minimum value is 1024 bytes.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_PARAMETER_SIZE</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Max size in bytes of all arguments that can be passed to a kernel.</p>
+<p class="tableblock">        The minimum value is 1024 for devices that are not of type
+        CL_DEVICE_TYPE_CUSTOM.
+        For this minimum value, only a maximum of 128 arguments can be
+        passed to a kernel</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MEM_BASE_ADDR_ALIGN</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Alignment requirement (in bits) for sub-buffer offsets.
+        The minimum value is the size (in bits) of the largest OpenCL
+        built-in data type supported by the device (long16 in FULL profile,
+        long16 or int16 in EMBEDDED profile) for devices that are not of
+        type CL_DEVICE_TYPE_CUSTOM.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_SINGLE_FP_CONFIG<sup>5</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_fp_config</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Describes single precision floating-point capability of the device.
+        This is a bit-field that describes one or more of the following
+        values:</p>
+<p class="tableblock">        CL_FP_DENORM - denorms are supported</p>
+<p class="tableblock">        CL_FP_INF_NAN - INF and quiet NaNs are supported.</p>
+<p class="tableblock">        CL_FP_ROUND_TO_NEAREST-- round to nearest even rounding mode
+        supported</p>
+<p class="tableblock">        CL_FP_ROUND_TO_ZERO - round to zero rounding mode supported</p>
+<p class="tableblock">        CL_FP_ROUND_TO_INF - round to positive and negative infinity
+        rounding modes supported</p>
+<p class="tableblock">        CL_FP_FMA - IEEE754-2008 fused multiply-add is supported.</p>
+<p class="tableblock">        CL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT - divide and sqrt are correctly
+        rounded as defined by the IEEE754 specification.</p>
+<p class="tableblock">        CL_FP_SOFT_FLOAT - Basic floating-point operations (such as
+        addition, subtraction, multiplication) are implemented in software.</p>
+<p class="tableblock">        For the full profile, the mandated minimum floating-point capability
+        for devices that are not of type CL_DEVICE_TYPE_CUSTOM is:
+        CL_FP_ROUND_TO_NEAREST | CL_FP_INF_NAN.</p>
+<p class="tableblock">        For the embedded profile, see section 10.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_DOUBLE_FP_CONFIG<sup>6</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_fp_config</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Describes double precision floating-point capability of the OpenCL
+        device.
+        This is a bit-field that describes one or more of the following
+        values:</p>
+<p class="tableblock">        CL_FP_DENORM - denorms are supported</p>
+<p class="tableblock">        CL_FP_INF_NAN - INF and NaNs are supported.</p>
+<p class="tableblock">        CL_FP_ROUND_TO_NEAREST - round to nearest even rounding mode
+        supported.</p>
+<p class="tableblock">        CL_FP_ROUND_TO_ZERO - round to zero rounding mode supported.</p>
+<p class="tableblock">        CL_FP_ROUND_TO_INF - round to positive and negative infinity
+        rounding modes supported.</p>
+<p class="tableblock">        CP_FP_FMA - IEEE754-2008 fused multiply-add is supported.</p>
+<p class="tableblock">        CL_FP_SOFT_FLOAT - Basic floating-point operations (such as
+        addition, subtraction, multiplication) are implemented in software.</p>
+<p class="tableblock">        Double precision is an optional feature so the mandated minimum
+        double precision floating-point capability is 0.</p>
+<p class="tableblock">        If double precision is supported by the device, then the minimum
+        double precision floating-point capability must be:<br>
+        CL_FP_FMA |<br>
+        CL_FP_ROUND_TO_NEAREST |<br>
+        CL_FP_INF_NAN |<br>
+        CL_FP_DENORM.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_GLOBAL_MEM_CACHE_TYPE</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_mem_cache_type</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Type of global memory cache supported.
+        Valid values are: CL_NONE, CL_READ_ONLY_CACHE and
+        CL_READ_WRITE_CACHE.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Size of global memory cache line in bytes.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_GLOBAL_MEM_CACHE_SIZE</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_ulong</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Size of global memory cache in bytes.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_GLOBAL_MEM_SIZE</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_ulong</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Size of global device memory in bytes.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_ulong</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Max size in bytes of a constant buffer allocation.
+        The minimum value is 64 KB for devices that are not of type
+        CL_DEVICE_TYPE_CUSTOM.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_CONSTANT_ARGS</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Max number of arguments declared with the <code>__constant</code> qualifier
+        in a kernel.
+        The minimum value is 8 for devices that are not of type
+        CL_DEVICE_TYPE_CUSTOM.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The maximum number of bytes of storage that may be allocated for any
+        single variable in program scope or inside a function in an OpenCL
+        kernel language declared in the global address space.</p>
+<p class="tableblock">        The minimum value is 64 KB.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Maximum preferred total size, in bytes, of all program variables in
+        the global address space.
+        This is a performance hint.
+        An implementation may place such variables in storage with optimized
+        device access.
+        This query returns the capacity of such storage.
+        The minimum value is 0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_LOCAL_MEM_TYPE</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_local_mem_type</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Type of local memory supported.
+        This can be set to CL_LOCAL implying dedicated local memory storage
+        such as SRAM , or CL_GLOBAL.</p>
+<p class="tableblock">        For custom devices, CL_NONE can also be returned indicating no local
+        memory support.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_LOCAL_MEM_SIZE</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_ulong</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Size of local memory region in bytes.
+        The minimum value is 32 KB for devices that are not of type
+        CL_DEVICE_TYPE_CUSTOM.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_ERROR_CORRECTION_SUPPORT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Is CL_TRUE if the device implements error correction for all
+        accesses to compute device memory (global and constant).
+        Is CL_FALSE if the device does not implement such error correction.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PROFILING_TIMER_RESOLUTION</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Describes the resolution of device timer.
+        This is measured in nanoseconds.
+        Refer to <a href="#profiling-operations">Profiling Operations</a> for details.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_ENDIAN_LITTLE</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Is CL_TRUE if the OpenCL device is a little endian device and
+        CL_FALSE otherwise</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_AVAILABLE</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Is CL_TRUE if the device is available and CL_FALSE otherwise.
+        A device is considered to be available if the device can be expected
+        to successfully execute commands enqueued to the device.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_COMPILER_AVAILABLE</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Is CL_FALSE if the implementation does not have a compiler available
+        to compile the program source.</p>
+<p class="tableblock">        Is CL_TRUE if the compiler is available.
+        This can be CL_FALSE for the embedded platform profile only.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_LINKER_AVAILABLE</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Is CL_FALSE if the implementation does not have a linker available.
+        Is CL_TRUE if the linker is available.</p>
+<p class="tableblock">        This can be CL_FALSE for the embedded platform profile only.</p>
+<p class="tableblock">        This must be CL_TRUE if CL_DEVICE_COMPILER_AVAILABLE is CL_TRUE.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_EXECUTION_CAPABILITIES</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_exec_ capabilities</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Describes the execution capabilities of the device.
+        This is a bit-field that describes one or more of the following
+        values:</p>
+<p class="tableblock">        CL_EXEC_KERNEL - The OpenCL device can execute OpenCL kernels.</p>
+<p class="tableblock">        CL_EXEC_NATIVE_KERNEL - The OpenCL device can execute native
+        kernels.</p>
+<p class="tableblock">        The mandated minimum capability is: CL_EXEC_KERNEL.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_QUEUE_ON_HOST_PROPERTIES<sup>7</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_command_queue_properties</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Describes the on host command-queue properties supported by the
+        device.
+        This is a bit-field that describes one or more of the following
+        values:</p>
+<p class="tableblock">        CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE<br>
+        CL_QUEUE_PROFILING_ENABLE</p>
+<p class="tableblock">        These properties are described in the <a href="#queue-properties-table">Queue Properties</a> table.</p>
+<p class="tableblock">        The mandated minimum capability is: CL_QUEUE_PROFILING_ENABLE.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_command_queue_properties</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Describes the on device command-queue properties supported by the
+        device.
+        This is a bit-field that describes one or more of the following
+        values:</p>
+<p class="tableblock">        CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE<br>
+        CL_QUEUE_PROFILING_ENABLE</p>
+<p class="tableblock">        These properties are described in the <a href="#queue-properties-table">Queue Properties</a> table.</p>
+<p class="tableblock">        The mandated minimum capability is:
+        CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_PROFILING_ENABLE.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The size of the device queue in bytes preferred by the
+        implementation.
+        Applications should use this size for the device queue to ensure
+        good performance.</p>
+<p class="tableblock">        The minimum value is 16 KB</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The max. size of the device queue in bytes.
+        The minimum value is 256 KB for the full profile and 64 KB for the
+        embedded profile</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_ON_DEVICE_QUEUES</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The maximum number of device queues that can be created for this
+        device in a single context.</p>
+<p class="tableblock">        The minimum value is 1.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_ON_DEVICE_EVENTS</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The maximum number of events in use by a device queue.
+        These refer to events returned by the <code>enqueue_</code> built-in functions
+        to a device queue or user events returned by the <code>create_user_event</code>
+        built-in function that have not been released.</p>
+<p class="tableblock">        The minimum value is 1024.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_BUILT_IN_KERNELS</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A semi-colon separated list of built-in kernels supported by the
+        device.
+        An empty string is returned if no built-in kernels are supported by
+        the device.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PLATFORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_platform_id</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The platform associated with this device.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_NAME</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Device name string.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_VENDOR</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Vendor name string.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DRIVER_VERSION</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">OpenCL software driver version string.
+        Follows a vendor-specific format.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PROFILE<sup>8</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">OpenCL profile string.
+        Returns the profile name supported by the device.
+        The profile name returned can be one of the following strings:</p>
+<p class="tableblock">        FULL_PROFILE - if the device supports the OpenCL specification
+        (functionality defined as part of the core specification and does
+        not require any extensions to be supported).</p>
+<p class="tableblock">        EMBEDDED_PROFILE - if the device supports the OpenCL embedded
+        profile.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_VERSION</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">OpenCL version string.
+        Returns the OpenCL version supported by the device. This version
+        string has the following format:</p>
+<p class="tableblock">        <em>OpenCL&lt;space&gt;&lt;major_version.minor_version&gt;&lt;space&gt;&lt;vendor-specific
+        information&gt;</em></p>
+<p class="tableblock">        The major_version.minor_version value returned will be 2.2.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_OPENCL_C_VERSION</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">OpenCL C version string.
+        Returns the highest OpenCL C version supported by the compiler for
+        this device that is not of type CL_DEVICE_TYPE_CUSTOM.
+        This version string has the following format:</p>
+<p class="tableblock">        <em>OpenCL&lt;space&gt;C&lt;space&gt;&lt;major_version.minor_version&gt;&lt;space&gt;&lt;vendor-specific
+        information&gt;</em></p>
+<p class="tableblock">        The major_version.minor_version value returned must be 2.0 if
+        CL_DEVICE_VERSION is OpenCL 2.0.</p>
+<p class="tableblock">        The major_version.minor_version value returned must be 1.2 if
+        CL_DEVICE_VERSION is OpenCL 1.2.</p>
+<p class="tableblock">        The major_version.minor_version value returned must be 1.1 if
+        CL_DEVICE_VERSION is OpenCL 1.1.</p>
+<p class="tableblock">        The major_version.minor_version value returned can be 1.0 or 1.1 if
+        CL_DEVICE_VERSION is OpenCL 1.0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_EXTENSIONS</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns a space separated list of extension names (the extension
+        names themselves do not contain any spaces) supported by the device.
+        The list of extension names returned can be vendor supported
+        extension names and one or more of the following Khronos approved
+        extension names:</p>
+<p class="tableblock">        <strong>cl_khr_int64_base_atomics</strong><br>
+        <strong>cl_khr_int64_extended_atomics</strong><br>
+        <strong>cl_khr_fp16</strong><br>
+        <strong>cl_khr_gl_sharing</strong><br>
+        <strong>cl_khr_gl_event</strong><br>
+        <strong>cl_khr_d3d10_sharing</strong><br>
+        <strong>cl_khr_dx9_media_sharing</strong><br>
+        <strong>cl_khr_d3d11_sharing</strong><br>
+        <strong>cl_khr_gl_depth_images</strong><br>
+        <strong>cl_khr_gl_msaa_sharing</strong><br>
+        <strong>cl_khr_initialize_memory</strong><br>
+        <strong>cl_khr_terminate_context</strong><br>
+        <strong>cl_khr_spir</strong><br>
+        <strong>cl_khr_srgb_image_writes</strong></p>
+<p class="tableblock">        The following approved Khronos extension names must be returned by
+        all devices that support OpenCL C 2.0:</p>
+<p class="tableblock">        <strong>cl_khr_byte_addressable_store</strong><br>
+        <strong>cl_khr_fp64</strong> (for backward compatibility if double precision is
+        supported)<br>
+        <strong>cl_khr_3d_image_writes</strong><br>
+        <strong>cl_khr_image2d_from_buffer</strong><br>
+        <strong>cl_khr_depth_images</strong></p>
+<p class="tableblock">        Please refer to the OpenCL 2.0 Extension Specification for a
+        detailed description of these extensions.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PRINTF_BUFFER_SIZE</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Maximum size in bytes of the internal buffer that holds the output
+        of printf calls from a kernel.
+        The minimum value for the FULL profile is 1 MB.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PREFERRED_INTEROP_USER_SYNC</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Is CL_TRUE if the devices preference is for the user to be
+        responsible for synchronization, when sharing memory objects between
+        OpenCL and other APIs such as DirectX, CL_FALSE if the device /
+        implementation has a performant path for performing synchronization
+        of memory object shared between OpenCL and other APIs such as
+        DirectX.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PARENT_DEVICE</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_id</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the cl_device_id of the parent device to which this
+        sub-device belongs.
+        If <em>device</em> is a root-level device, a <code>NULL</code> value is returned.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PARTITION_MAX_SUB_DEVICES</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the maximum number of sub-devices that can be created when a
+        device is partitioned.</p>
+<p class="tableblock">        The value returned cannot exceed CL_DEVICE_MAX_COMPUTE_UNITS.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PARTITION_PROPERTIES</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_partition_ property[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the list of partition types supported by <em>device</em>.
+        This is an array of cl_device_partition_property values drawn from
+        the following list:</p>
+<p class="tableblock">        CL_DEVICE_PARTITION_EQUALLY<br>
+        CL_DEVICE_PARTITION_BY_COUNTS<br>
+        CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN</p>
+<p class="tableblock">        If the device cannot be partitioned (i.e. there is no partitioning
+        scheme supported by the device that will return at least two
+        subdevices), a value of 0 will be returned.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PARTITION_AFFINITY_DOMAIN</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_affinity_ domain</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the list of supported affinity domains for partitioning the
+        device using CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN.
+        This is a bit-field that describes one or more of the following
+        values:</p>
+<p class="tableblock">        CL_DEVICE_AFFINITY_DOMAIN_NUMA<br>
+        CL_DEVICE_AFFINITY_DOMAIN_L4_CACHE<br>
+        CL_DEVICE_AFFINITY_DOMAIN_L3_CACHE<br>
+        CL_DEVICE_AFFINITY_DOMAIN_L2_CACHE<br>
+        CL_DEVICE_AFFINITY_DOMAIN_L1_CACHE<br>
+        CL_DEVICE_AFFINITY_DOMAIN_NEXT_PARTITIONABLE</p>
+<p class="tableblock">        If the device does not support any affinity domains, a value of 0
+        will be returned.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PARTITION_TYPE</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_partition_ property[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the properties argument specified in <strong>clCreateSubDevices</strong> if
+        device is a sub-device.
+        In the case where the properties argument to <strong>clCreateSubDevices</strong> is
+        CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN,
+        CL_DEVICE_AFFINITY_DOMAIN_NEXT_PARTITIONABLE, the affinity domain
+        used to perform the partition will be returned.
+        This can be one of the following values:</p>
+<p class="tableblock">        CL_DEVICE_AFFINITY_DOMAIN_NUMA<br>
+        CL_DEVICE_AFFINITY_DOMAIN_L4_CACHE<br>
+        CL_DEVICE_AFFINITY_DOMAIN_L3_CACHE<br>
+        CL_DEVICE_AFFINITY_DOMAIN_L2_CACHE<br>
+        CL_DEVICE_AFFINITY_DOMAIN_L1_CACHE</p>
+<p class="tableblock">        Otherwise the implementation may either return a
+        <em>param_value_size_ret</em> of 0 i.e. there is no partition type
+        associated with device or can return a property value of 0 (where 0
+        is used to terminate the partition property list) in the memory that
+        <em>param_value</em> points to.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_REFERENCE_COUNT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the <em>device</em> reference count.
+        If the device is a root-level device, a reference count of one is
+        returned.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_SVM_CAPABILITIES</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_svm_ capabilities</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Describes the various shared virtual memory (a.k.a. SVM) memory
+        allocation types the device supports.
+        Coarse-grain SVM allocations are required to be supported by all
+        OpenCL 2.0 devices.
+        This is a bit-field that describes a combination of the following
+        values:</p>
+<p class="tableblock">        CL_DEVICE_SVM_COARSE_GRAIN_BUFFER - Support for coarse-grain buffer
+        sharing using <strong>clSVMAlloc</strong>.
+        Memory consistency is guaranteed at synchronization points and the
+        host must use calls to <strong>clEnqueueMapBuffer</strong> and
+        <strong>clEnqueueUnmapMemObject</strong>.</p>
+<p class="tableblock">        CL_DEVICE_SVM_FINE_GRAIN_BUFFER - Support for fine-grain buffer
+        sharing using <strong>clSVMAlloc</strong>.
+        Memory consistency is guaranteed at synchronization points without
+        need for <strong>clEnqueueMapBuffer</strong> and <strong>clEnqueueUnmapMemObject</strong>.</p>
+<p class="tableblock">        CL_DEVICE_SVM_FINE_GRAIN_SYSTEM - Support for sharing the host&#8217;s
+        entire virtual memory including memory allocated using <strong>malloc</strong>.
+        Memory consistency is guaranteed at synchronization points.</p>
+<p class="tableblock">        CL_DEVICE_SVM_ATOMICS - Support for the OpenCL 2.0 atomic
+        operations that provide memory consistency across the host and all
+        OpenCL devices supporting fine-grain SVM allocations.</p>
+<p class="tableblock">        The mandated minimum capability is
+        CL_DEVICE_SVM_COARSE_GRAIN_BUFFER.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PREFERRED_PLATFORM_ATOMIC_ALIGNMENT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the value representing the preferred alignment in bytes for
+        OpenCL 2.0 fine-grained SVM atomic types.
+        This query can return 0 which indicates that the preferred alignment
+        is aligned to the natural size of the type.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PREFERRED_GLOBAL_ATOMIC_ALIGNMENT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the value representing the preferred alignment in bytes for
+        OpenCL 2.0 atomic types to global memory.
+        This query can return 0 which indicates that the preferred alignment
+        is aligned to the natural size of the type.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_PREFERRED_LOCAL_ATOMIC_ALIGNMENT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the value representing the preferred alignment in bytes for
+        OpenCL 2.0 atomic types to local memory.
+        This query can return 0 which indicates that the preferred alignment
+        is aligned to the natural size of the type.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_MAX_NUM_SUB_GROUPS</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Maximum number of sub-groups in a work-group that a device is
+        capable of executing on a single compute unit, for any given
+        kernel-instance running on the device.
+        The minimum value is 1.
+        (Refer also to <strong>clGetKernelSubGroupInfo</strong>.)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICE_SUB_GROUP_INDEPENDENT_FORWARD_PROGRESS</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Is CL_TRUE if this device supports independent forward progress of
+        sub-groups, CL_FALSE otherwise.
+        If <strong>cl_khr_subgroups</strong> is supported by the device this must return
+        CL_TRUE.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="dlist">
+<dl>
+<dt class="hdlist1">4</dt>
+<dd>
+<p>NOTE: <strong>CL_DEVICE_MAX_WRITE_IMAGE_ARGS</strong> is only there for backward
+compatibility.
+<strong>CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS</strong> should be used instead.</p>
+</dd>
+<dt class="hdlist1">5</dt>
+<dd>
+<p>The optional rounding modes should be included as a device capability
+only if it is supported natively.
+All explicit conversion functions with specific rounding modes must
+still operate correctly.</p>
+</dd>
+<dt class="hdlist1">6</dt>
+<dd>
+<p>The optional rounding modes should be included as a device capability
+only if it is supported natively.
+All explicit conversion functions with specific rounding modes must
+still operate correctly.</p>
+</dd>
+<dt class="hdlist1">7</dt>
+<dd>
+<p>CL_DEVICE_QUEUE_PROPERTIES is deprecated and replaced by
+CL_DEVICE_QUEUE_ON_HOST_PROPERTIES.</p>
+</dd>
+<dt class="hdlist1">8</dt>
+<dd>
+<p>The platform profile returns the profile that is implemented by the
+OpenCL framework.
+If the platform profile returned is FULL_PROFILE, the OpenCL framework
+will support devices that are FULL_PROFILE and may also support devices
+that are EMBEDDED_PROFILE.
+The compiler must be available for all devices i.e.
+CL_DEVICE_COMPILER_AVAILABLE is CL_TRUE.
+If the platform profile returned is EMBEDDED_PROFILE, then devices that
+are only EMBEDDED_PROFILE are supported.</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>The device queries described in the <a href="#device-queries-table">Device Queries</a>
+table should return the same information for a root-level device i.e. a
+device returned by <strong>clGetDeviceIDs</strong> and any sub-devices created from this
+device except for the following queries:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_DEVICE_GLOBAL_MEM_CACHE_SIZE</p>
+</li>
+<li>
+<p>CL_DEVICE_BUILT_IN_KERNELS</p>
+</li>
+<li>
+<p>CL_DEVICE_PARENT_DEVICE</p>
+</li>
+<li>
+<p>CL_DEVICE_PARTITION_TYPE</p>
+</li>
+<li>
+<p>CL_DEVICE_REFERENCE_COUNT</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p><strong>clGetDeviceInfo</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_DEVICE if <em>device</em> is not valid.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>param_name</em> is not one of the supported values or
+if size in bytes specified by <em>param_value_size</em> is &lt; size of return
+type as specified in the <a href="#device-queries-table">Device Queries</a> table
+and <em>param_value</em> is not a <code>NULL</code> value or if <em>param_name</em> is a value
+that is available as an extension and the corresponding extension is not
+supported by the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clGetDeviceAndHostTimer(cl_device_id device,
+                               cl_ulong* device_timestamp,
+                               cl_ulong* host_timestamp)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns a reasonably synchronized pair of timestamps from the device timer
+and the host timer as seen by <em>device</em>.
+Implementations may need to execute this query with a high latency in order
+to provide reasonable synchronization of the timestamps.
+The host timestamp and device timestamp returned by this function and
+<strong>clGetHostTimer</strong> each have an implementation defined timebase.
+The timestamps will always be in their respective timebases regardless of
+which query function is used.
+The timestamp returned from <strong>clGetEventProfilingInfo</strong> for an event on a
+device and a device timestamp queried from the same device will always be in
+the same timebase.</p>
+</div>
+<div class="paragraph">
+<p><em>device</em> is a device returned by <strong>clGetDeviceIDs</strong>.</p>
+</div>
+<div class="paragraph">
+<p><em>device_timestamp</em> will be updated with the value of the device timer in
+nanoseconds.
+The resolution of the timer is the same as the device profiling timer
+returned by <strong>clGetDeviceInfo</strong> and the CL_DEVICE_PROFILING_TIMER_RESOLUTION
+query.</p>
+</div>
+<div class="paragraph">
+<p><em>host_timestamp</em> will be updated with the value of the host timer in
+nanoseconds at the closest possible point in time to that at which
+<em>device_timer</em> was returned.
+The resolution of the timer may be queried via <strong>clGetPlatformInfo</strong> and the
+flag CL_PLATFORM_HOST_TIMER_RESOLUTION.</p>
+</div>
+<div class="paragraph">
+<p><strong>clGetDeviceAndHostTimer</strong> will return CL_SUCCESS with a time value in
+<em>host_timestamp</em> if provided.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_DEVICE if <em>device</em> is not a valid OpenCL device.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>host_timestamp</em> or <em>device_timestamp</em> is <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clGetHostTimer(cl_device_id device,
+                      cl_ulong* host_timestamp)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Return the current value of the host clock as seen by <em>device</em>.
+This value is in the same timebase as the host_timestamp returned from
+<strong>clGetDeviceAndHostTimer</strong>.
+The implementation will return with as low a latency as possible to allow a
+correlation with a subsequent application sampled time.
+The host timestamp and device timestamp returned by this function and
+<strong>clGetDeviceAndHostTimer</strong> each have an implementation defined timebase.
+The timestamps will always be in their respective timebases regardless of
+which query function is used.
+The timestamp returned from <strong>clGetEventProfilingInfo</strong> for an event on a
+device and a device timestamp queried from the same device will always be in
+the same timebase.</p>
+</div>
+<div class="paragraph">
+<p><em>device</em> is a device returned by <strong>clGetDeviceIDs</strong>.</p>
+</div>
+<div class="paragraph">
+<p><em>host_timestamp</em> will be updated with the value of the current timer in
+nanoseconds.
+The resolution of the timer may be queried via <strong>clGetPlatformInfo</strong> and the
+flag CL_PLATFORM_HOST_TIMER_RESOLUTION.</p>
+</div>
+<div class="paragraph">
+<p><strong>clGetHostTimer</strong> will return CL_SUCCESS with a time value in
+<em>host_timestamp</em> if provided.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_DEVICE if <em>device</em> is not a valid OpenCL device.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>host_timestamp</em> is <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_partitioning_a_device">4.3. Partitioning a Device</h3>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clCreateSubDevices(cl_device_id in_device,
+                          <span class="directive">const</span> cl_device_partition_property *properties,
+                          cl_uint num_devices,
+                          cl_device_id *out_devices,
+                          cl_uint *num_devices_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>creates an array of sub-devices that each reference a non-intersecting set
+of compute units within in_device, according to a partition scheme given by
+<em>properties</em>.
+The output sub-devices may be used in every way that the root (or parent)
+device can be used, including creating contexts, building programs, further
+calls to <strong>clCreateSubDevices</strong> and creating command-queues.
+When a command-queue is created against a sub-device, the commands enqueued
+on the queue are executed only on the sub-device.</p>
+</div>
+<div class="paragraph">
+<p><em>in_device</em> is the device to be partitioned.</p>
+</div>
+<div class="paragraph">
+<p><em>properties</em> specifies how <em>in_device</em> is to be partition described by a
+partition name and its corresponding value.
+Each partition name is immediately followed by the corresponding desired
+value.
+The list is terminated with 0.
+The list of supported partitioning schemes is described in the
+<a href="#subdevice-partition-table">Subdevice Partition</a> table.
+Only one of the listed partitioning schemes can be specified in
+<em>properties</em>.</p>
+</div>
+<table id="subdevice-partition-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 6. <em>List of supported partition schemes by</em> <strong>clCreateSubDevices</strong></caption>
+<colgroup>
+<col style="width: 30%;">
+<col style="width: 20%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_device_partition_property enum</strong></th>
+<th class="tableblock halign-left valign-top">Partition value</th>
+<th class="tableblock halign-left valign-top">Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_PARTITION_EQUALLY</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Split the aggregate device into as many smaller aggregate devices as
+        can be created, each containing <em>n</em> compute units.
+        The value <em>n</em> is passed as the value accompanying this property.
+        If <em>n</em> does not divide evenly into
+        CL_DEVICE_PARTITION_MAX_COMPUTE_UNITS, then the remaining compute
+        units are not used.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_PARTITION_BY_COUNTS</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This property is followed by a
+        CL_DEVICE_PARTITION_BY_COUNTS_LIST_END terminated list of compute
+        unit counts.
+        For each non-zero count <em>m</em> in the list, a sub-device is created
+        with <em>m</em> compute units in it.
+        CL_DEVICE_PARTITION_BY_COUNTS_LIST_END is defined to be 0.</p>
+<p class="tableblock">        The number of non-zero count entries in the list may not exceed
+        CL_DEVICE_PARTITION_MAX_SUB_DEVICES.</p>
+<p class="tableblock">        The total number of compute units specified may not exceed
+        CL_DEVICE_PARTITION_MAX_COMPUTE_UNITS.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_affinity_ domain</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Split the device into smaller aggregate devices containing one or
+        more compute units that all share part of a cache hierarchy.
+        The value accompanying this property may be drawn from the following
+        list:</p>
+<p class="tableblock">        CL_DEVICE_AFFINITY_DOMAIN_NUMA - Split the device into sub-devices
+        comprised of compute units that share a NUMA node.</p>
+<p class="tableblock">        CL_DEVICE_AFFINITY_DOMAIN_L4_CACHE - Split the device into
+        sub-devices comprised of compute units that share a level 4 data
+        cache.</p>
+<p class="tableblock">        CL_DEVICE_AFFINITY_DOMAIN_L3_CACHE - Split the device into
+        sub-devices comprised of compute units that share a level 3 data
+        cache.</p>
+<p class="tableblock">        CL_DEVICE_AFFINITY_DOMAIN_L2_CACHE - Split the device into
+        sub-devices comprised of compute units that share a level 2 data
+        cache.</p>
+<p class="tableblock">        CL_DEVICE_AFFINITY_DOMAIN_L1_CACHE - Split the device into
+        sub-devices comprised of compute units that share a level 1 data
+        cache.</p>
+<p class="tableblock">        CL_DEVICE_AFFINITY_DOMAIN_NEXT_PARTITIONABLE - Split the device
+        along the next partitionable affinity domain.
+        The implementation shall find the first level along which the device
+        or sub-device may be further subdivided in the order NUMA, L4, L3,
+        L2, L1, and partition the device into sub-devices comprised of
+        compute units that share memory subsystems at this level.</p>
+<p class="tableblock">        The user may determine what happened by calling
+        <strong>clGetDeviceInfo</strong>(CL_DEVICE_PARTITION_TYPE) on the sub-devices.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p><em>num_devices</em> is the size of memory pointed to by <em>out_devices</em> specified as
+the number of cl_device_id entries.</p>
+</div>
+<div class="paragraph">
+<p><em>out_devices</em> is the buffer where the OpenCL sub-devices will be returned.
+If <em>out_devices</em> is <code>NULL</code>, this argument is ignored.
+If <em>out_devices</em> is not <code>NULL</code>, <em>num_devices</em> must be greater than or equal
+to the number of sub-devices that <em>device</em> may be partitioned into according
+to the partitioning scheme specified in <em>properties</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>num_devices_ret</em> returns the number of sub-devices that <em>device</em> may be
+partitioned into according to the partitioning scheme specified in
+<em>properties</em>.
+If <em>num_devices_ret</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<div class="paragraph">
+<p><strong>clCreateSubDevices</strong> returns CL_SUCCESS if the partition is created
+successfully.
+Otherwise, it returns a <code>NULL</code> value with the following error values
+returned in <em>errcode_ret</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_DEVICE if <em>in_device</em> is not valid.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if values specified in <em>properties</em> are not valid or if
+values specified in <em>properties</em> are valid but not supported by the
+device.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>out_devices</em> is not <code>NULL</code> and <em>num_devices</em> is
+less than the number of sub-devices created by the partition scheme.</p>
+</li>
+<li>
+<p>CL_DEVICE_PARTITION_FAILED if the partition name is supported by the
+implementation but in_device could not be further partitioned.</p>
+</li>
+<li>
+<p>CL_INVALID_DEVICE_PARTITION_COUNT if the partition name specified in
+<em>properties</em> is CL_DEVICE_PARTITION_BY_COUNTS and the number of
+sub-devices requested exceeds CL_DEVICE_PARTITION_MAX_SUB_DEVICES or the
+total number of compute units requested exceeds
+CL_DEVICE_PARTITION_MAX_COMPUTE_UNITS for <em>in_device</em>, or the number of
+compute units requested for one or more sub-devices is less than zero or
+the number of sub-devices requested exceeds
+CL_DEVICE_PARTITION_MAX_COMPUTE_UNITS for <em>in_device</em>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>A few examples that describe how to specify partition properties in
+<em>properties</em> argument to <strong>clCreateSubDevices</strong> are given below:</p>
+</div>
+<div class="paragraph">
+<p>To partition a device containing 16 compute units into two sub-devices, each
+containing 8 compute units, pass the following in <em>properties</em>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">{ CL_DEVICE_PARTITION_EQUALLY, <span class="integer">8</span>, <span class="integer">0</span> }</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>To partition a device with four compute units into two sub-devices with one
+sub-device containing 3 compute units and the other sub-device 1 compute
+unit, pass the following in properties argument:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">{ CL_DEVICE_PARTITION_BY_COUNTS,
+  <span class="integer">3</span>, <span class="integer">1</span>, CL_DEVICE_PARTITION_BY_COUNTS_LIST_END, <span class="integer">0</span> }</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>To split a device along the outermost cache line (if any), pass the
+following in properties argument:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">{ CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN,
+  CL_DEVICE_AFFINITY_DOMAIN_NEXT_PARTITIONABLE,
+  <span class="integer">0</span> }</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clRetainDevice(cl_device_id device)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>increments the <em>device</em> reference count if <em>device</em> is a valid sub-device
+created by a call to <strong>clCreateSubDevices</strong>.
+If <em>device</em> is a root level device i.e. a cl_device_id returned by
+<strong>clGetDeviceIDs</strong>, the <em>device</em> reference count remains unchanged.
+<strong>clRetainDevice</strong> returns CL_SUCCESS if the function is executed successfully
+or the device is a root-level device.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_DEVICE if <em>device</em> is not a valid sub-device created by a
+call to <strong>clCreateSubDevices</strong>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clReleaseDevice(cl_device_id device)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>decrements the <em>device</em> reference count if device is a valid sub-device
+created by a call to <strong>clCreateSubDevices</strong>.
+If <em>device</em> is a root level device i.e. a cl_device_id returned by
+<strong>clGetDeviceIDs</strong>, the <em>device</em> reference count remains unchanged.
+<strong>clReleaseDevice</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_DEVICE if <em>device</em> is not a valid sub-device created by a
+call to <strong>clCreateSubDevices</strong>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>After the <em>device</em> reference count becomes zero and all the objects attached
+to <em>device</em> (such as command-queues) are released, the <em>device</em> object is
+deleted.
+Using this function to release a reference that was not obtained by creating
+the object or by calling <strong>clRetainDevice</strong> causes undefined behavior.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_contexts">4.4. Contexts</h3>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_context clCreateContext(<span class="directive">const</span> cl_context_properties *properties,
+                           cl_uint num_devices,
+                           <span class="directive">const</span> cl_device_id *devices,
+                           <span class="directive">void</span>(CL_CALLBACK *pfn_notify)
+                               (<span class="directive">const</span> <span class="predefined-type">char</span> *errinfo,
+                               <span class="directive">const</span> <span class="directive">void</span> *private_info,
+                               size_t cb,
+                               <span class="directive">void</span> *user_data),
+                           <span class="directive">void</span> *user_data,
+                           cl_int *errcode_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>creates an OpenCL context.
+An OpenCL context is created with one or more devices.
+Contexts are used by the OpenCL runtime for managing objects such as
+command-queues, memory, program and kernel objects and for executing kernels
+on one or more devices specified in the context.</p>
+</div>
+<div class="paragraph">
+<p><em>properties</em> specifies a list of context property names and their
+corresponding values.
+Each property name is immediately followed by the corresponding desired
+value.
+The list is terminated with 0.
+The list of supported properties is described in the
+<a href="#context-properties-table">Context Properties</a> table.
+<em>properties</em> can be <code>NULL</code> in which case the platform that is selected is
+implementation-defined.</p>
+</div>
+<table id="context-properties-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 7. <em>List of supported properties by</em> <strong>clCreateContext</strong></caption>
+<colgroup>
+<col style="width: 34%;">
+<col style="width: 33%;">
+<col style="width: 33%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_context_properties enum</strong></th>
+<th class="tableblock halign-left valign-top">Property value</th>
+<th class="tableblock halign-left valign-top">Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_CONTEXT_PLATFORM</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_platform_id</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Specifies the platform to use.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_CONTEXT_INTEROP_USER_SYNC</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Specifies whether the user is responsible for synchronization
+        between OpenCL and other APIs.
+        Please refer to the specific sections in the OpenCL 2.0 extension
+        specification that describe sharing with other APIs for restrictions
+        on using this flag.</p>
+<p class="tableblock">        If CL_CONTEXT_INTEROP_USER_SYNC is not specified, a default of
+        CL_FALSE is assumed.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p><em>num_devices</em> is the number of devices specified in the <em>devices</em> argument.</p>
+</div>
+<div class="paragraph">
+<p><em>devices</em> is a pointer to a list of unique devices<sup>9</sup> returned by
+<strong>clGetDeviceIDs</strong> or sub-devices created by <strong>clCreateSubDevices</strong> for a
+platform.</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1">9</dt>
+<dd>
+<p>Duplicate devices specified in <em>devices</em> are ignored.</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p><em>pfn_notify</em> is a callback function that can be registered by the
+application.
+This callback function will be used by the OpenCL implementation to report
+information on errors during context creation as well as errors that occur
+at runtime in this context.
+This callback function may be called asynchronously by the OpenCL
+implementation.
+It is the applications responsibility to ensure that the callback function
+is thread-safe.
+The parameters to this callback function are:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><em>errinfo</em> is a pointer to an error string.</p>
+</li>
+<li>
+<p><em>private_info</em> and <em>cb</em> represent a pointer to binary data that is
+returned by the OpenCL implementation that can be used to log additional
+information helpful in debugging the error.</p>
+</li>
+<li>
+<p><em>user_data</em> is a pointer to user supplied data.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If <em>pfn_notify</em> is <code>NULL</code>, no callback function is registered.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+There are a number of cases where error notifications need to be
+delivered due to an error that occurs outside a context.
+Such notifications may not be delivered through the <em>pfn_notify</em> callback.
+Where these notifications go is implementation-defined.
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p><em>user_data</em> will be passed as the <em>user_data</em> argument when <em>pfn_notify</em> is
+called.
+<em>user_data</em> can be <code>NULL</code>.</p>
+</div>
+<div class="paragraph">
+<p><em>errcode_ret</em> will return an appropriate error code.
+If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p>
+</div>
+<div class="paragraph">
+<p><strong>clCreateContext</strong> returns a valid non-zero context and <em>errcode_ret</em> is set
+to CL_SUCCESS if the context is created successfully.
+Otherwise, it returns a <code>NULL</code> value with the following error values
+returned in <em>errcode_ret</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_PLATFORM if <em>properties</em> is <code>NULL</code> and no platform could be
+selected or if platform value specified in <em>properties</em> is not a valid
+platform.</p>
+</li>
+<li>
+<p>CL_INVALID_PROPERTY if context property name in <em>properties</em> is not a
+supported property name, if the value specified for a supported property
+name is not valid, or if the same property name is specified more than
+once.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>devices</em> is <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>num_devices</em> is equal to zero.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>pfn_notify</em> is <code>NULL</code> but <em>user_data</em> is not
+<code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_DEVICE if <em>devices</em> contains an invalid device.</p>
+</li>
+<li>
+<p>CL_DEVICE_NOT_AVAILABLE if a device in <em>devices</em> is currently not
+available even though the device was returned by <strong>clGetDeviceIDs</strong>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function<sup>10</sup></p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_context clCreateContextFromType(<span class="directive">const</span> cl_context_properties *properties,
+                                   cl_device_type device_type,
+                                   <span class="directive">void</span>(CL_CALLBACK *pfn_notify)(
+                                       (<span class="directive">const</span> <span class="predefined-type">char</span> *errinfo,
+                                        <span class="directive">const</span> <span class="directive">void</span> *private_info,
+                                        size_t cb,
+                                        <span class="directive">void</span> *user_data),
+                                   <span class="directive">void</span> *user_data,
+                                   cl_int *errcode_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>creates an OpenCL context from a device type that identifies the specific
+device(s) to use.
+Only devices that are returned by <strong>clGetDeviceIDs</strong> for <em>device_type</em> are
+used to create the context.
+The context does not reference any sub-devices that may have been created
+from these devices.</p>
+</div>
+<div class="paragraph">
+<p><em>properties</em> specifies a list of context property names and their
+corresponding values.
+Each property name is immediately followed by the corresponding desired
+value.
+The list of supported properties is described in the
+<a href="#context-properties-table">Context Properties</a> table.
+<em>properties</em> can also be <code>NULL</code> in which case the platform that is selected
+is implementation-defined.</p>
+</div>
+<div class="paragraph">
+<p><em>device_type</em> is a bit-field that identifies the type of device and is
+described in the <a href="#device-categories-table">Device Categories</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>pfn_notify</em> and <em>user_data</em> are described in <strong>clCreateContext</strong>.</p>
+</div>
+<div class="paragraph">
+<p><em>errcode_ret</em> will return an appropriate error code.
+If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p>
+</div>
+<div class="paragraph">
+<p><strong>clCreateContextFromType</strong> returns a valid non-zero context and <em>errcode_ret</em>
+is set to CL_SUCCESS if the context is created successfully.
+Otherwise, it returns a <code>NULL</code> value with the following error values
+returned in <em>errcode_ret</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_PLATFORM if <em>properties</em> is <code>NULL</code> and no platform could be
+selected or if platform value specified in <em>properties</em> is not a valid
+platform.</p>
+</li>
+<li>
+<p>CL_INVALID_PROPERTY if context property name in <em>properties</em> is not a
+supported property name, if the value specified for a supported property
+name is not valid, or if the same property name is specified more than
+once.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>pfn_notify</em> is <code>NULL</code> but <em>user_data</em> is not
+<code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_DEVICE_TYPE if <em>device_type</em> is not a valid value.</p>
+</li>
+<li>
+<p>CL_DEVICE_NOT_AVAILABLE if no devices that match <em>device_type</em> and
+property values specified in <em>properties</em> are currently available.</p>
+</li>
+<li>
+<p>CL_DEVICE_NOT_FOUND if no devices that match <em>device_type</em> and property
+values specified in <em>properties</em> were found.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+<div class="dlist">
+<dl>
+<dt class="hdlist1">10</dt>
+<dd>
+<p><strong>clCreateContextfromType</strong> may return all or a subset of the actual
+physical devices present in the platform and that match device_type.</p>
+</dd>
+</dl>
+</div>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clRetainContext(cl_context context)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>increments the <em>context</em> reference count.
+<strong>clRetainContext</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_CONTEXT if <em>context</em> is not a valid OpenCL context.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p><strong>clCreateContext</strong> and <strong>clCreateContextFromType</strong> perform an implicit retain.
+This is very helpful for 3<sup>rd</sup> party libraries, which typically get a
+context passed to them by the application.
+However, it is possible that the application may delete the context without
+informing the library.
+Allowing functions to attach to (i.e. retain) and release a context solves
+the problem of a context being used by a library no longer being valid.</p>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clReleaseContext(cl_context context)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>decrements the <em>context</em> reference count.
+<strong>clReleaseContext</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_CONTEXT if <em>context</em> is not a valid OpenCL context.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>After the <em>context</em> reference count becomes zero and all the objects
+attached to <em>context</em> (such as memory objects, command-queues) are released,
+the <em>context</em> is deleted.
+Using this function to release a reference that was not obtained by creating
+the object or by calling <strong>clRetainContext</strong> causes undefined behavior.</p>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clGetContextInfo(cl_context context,
+                        cl_context_info param_name,
+                        size_t param_value_size,
+                        <span class="directive">void</span> *param_value,
+                        size_t *param_value_size_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>can be used to query information about a context.</p>
+</div>
+<div class="paragraph">
+<p><em>context</em> specifies the OpenCL context being queried.</p>
+</div>
+<div class="paragraph">
+<p><em>param_name</em> is an enumeration constant that specifies the information to
+query.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value</em> is a pointer to memory where the appropriate result being
+queried is returned.
+If <em>param_value</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size</em> specifies the size in bytes of memory pointed to by
+<em>param_value</em>.
+This size must be greater than or equal to the size of return type as
+described in the <a href="#context-info-table">Context Attributes</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size_ret</em> returns the actual size in bytes of data being
+queried by <em>param_name</em>.
+If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<div class="paragraph">
+<p>The list of supported <em>param_name</em> values and the information returned in
+<em>param_value</em> by <strong>clGetContextInfo</strong> is described in the
+<a href="#context-info-table">Context Attributes</a> table.</p>
+</div>
+<table id="context-info-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 8. List of supported param_names by <strong>clGetContextInfo</strong></caption>
+<colgroup>
+<col style="width: 34%;">
+<col style="width: 33%;">
+<col style="width: 33%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_context_info</strong></th>
+<th class="tableblock halign-left valign-top">Return Type</th>
+<th class="tableblock halign-left valign-top">Information returned in param_value</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_CONTEXT_REFERENCE_COUNT</strong><sup>11</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the <em>context</em> reference count.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_CONTEXT_NUM_DEVICES</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the number of devices in <em>context</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_CONTEXT_DEVICES</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_id[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the list of devices and sub-devices in <em>context</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_CONTEXT_PROPERTIES</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_context_properties[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the properties argument specified in <strong>clCreateContext</strong> or
+        <strong>clCreateContextFromType</strong>.</p>
+<p class="tableblock">        If the <em>properties</em> argument specified in <strong>clCreateContext</strong> or
+        <strong>clCreateContextFromType</strong> used to create <em>context</em> is not <code>NULL</code>, the
+        implementation must return the values specified in the properties
+        argument.</p>
+<p class="tableblock">        If the <em>properties</em> argument specified in <strong>clCreateContext</strong> or
+        <strong>clCreateContextFromType</strong> used to create <em>context</em> is <code>NULL</code>, the
+        implementation may return either a <em>param_value_size_ret</em> of 0
+        i.e. there is no context property value to be returned or can return
+        a context property value of 0 (where 0 is used to terminate the
+        context properties list) in the memory that <em>param_value</em> points
+        to.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="dlist">
+<dl>
+<dt class="hdlist1">11</dt>
+<dd>
+<p>The reference count returned should be considered immediately stale.
+It is unsuitable for general use in applications.
+This feature is provided for identifying memory leaks.</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p><strong>clGetContextInfo</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>param_name</em> is not one of the supported values or
+if size in bytes specified by <em>param_value_size</em> is &lt; size of return
+type as specified in the <a href="#context-info-table">Context Attributes</a>
+table and <em>param_value</em> is not a <code>NULL</code> value.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="opencl-runtime">5. The OpenCL Runtime</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>In this section we describe the API calls that manage OpenCL objects such as
+command-queues, memory objects, program objects, kernel objects for kernel
+functions in a program and calls that allow you to enqueue commands to a
+command-queue such as executing a kernel, reading, or writing a memory
+object.</p>
+</div>
+<div class="sect2">
+<h3 id="_command_queues">5.1. Command Queues</h3>
+<div class="paragraph">
+<p>OpenCL objects such as memory, program and kernel objects are created using
+a context.
+Operations on these objects are performed using a command-queue.
+The command-queue can be used to queue a set of operations (referred to as
+commands) in order.
+Having multiple command-queues allows applications to queue multiple
+independent commands without requiring synchronization.
+Note that this should work as long as these objects are not being shared.
+Sharing of objects across multiple command-queues will require the
+application to perform appropriate synchronization.
+This is described in <a href="#shared-opencl-objects">Shared OpenCL Objects</a></p>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_command_queue clCreateCommandQueueWithProperties(
+    cl_context context,
+    cl_device_id device,
+    <span class="directive">const</span> cl_queue_properties *properties,
+    cl_int *errcode_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>creates a host or device command-queue on a specific device.</p>
+</div>
+<div class="paragraph">
+<p><em>context</em> must be a valid OpenCL context.</p>
+</div>
+<div class="paragraph">
+<p><em>device</em> must be a device or sub-device associated with <em>context</em>.
+It can either be in the list of devices and sub-devices specified when
+<em>context</em> is created using <strong>clCreateContext</strong> or be a root device with the
+same device type as specified when <em>context</em> is created using
+<strong>clCreateContextFromType</strong>.</p>
+</div>
+<div class="paragraph">
+<p><em>properties</em> specifies a list of properties for the command-queue and their
+corresponding values.
+Each property name is immediately followed by the corresponding desired
+value.
+The list is terminated with 0.
+The list of supported properties is described in the table below.
+If a supported property and its value is not specified in <em>properties</em>, its
+default value will be used.
+<em>properties</em> can be <code>NULL</code> in which case the default values for supported
+command-queue properties will be used.</p>
+</div>
+<table id="queue-properties-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 9. List of supported cl_queue_properties values and description</caption>
+<colgroup>
+<col style="width: 34%;">
+<col style="width: 33%;">
+<col style="width: 33%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Queue Properties</strong></th>
+<th class="tableblock halign-left valign-top">Property Value</th>
+<th class="tableblock halign-left valign-top">Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_QUEUE_PROPERTIES</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_bitfield</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This is a bitfield and can be set to a combination of the following
+        values:</p>
+<p class="tableblock">        CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE - Determines whether the
+        commands queued in the command-queue are executed in-order or
+        out-of-order.
+        If set, the commands in the command-queue are executed out-of-order.
+        Otherwise, commands are executed in-order.</p>
+<p class="tableblock">        CL_QUEUE_PROFILING_ENABLE - Enable or disable profiling of commands
+        in the command-queue.
+        If set, the profiling of commands is enabled.
+        Otherwise profiling of commands is disabled.</p>
+<p class="tableblock">        CL_QUEUE_ON_DEVICE - Indicates that this is a device queue.
+        If CL_QUEUE_ON_DEVICE is set,
+        CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE<sup>1</sup> must also be set.</p>
+<p class="tableblock">        CL_QUEUE_ON_DEVICE_DEFAULT<sup>2</sup> --indicates that this is the default
+        device queue.
+        This can only be used with CL_QUEUE_ON_DEVICE.</p>
+<p class="tableblock">        If CL_QUEUE_PROPERTIES is not specified an in-order host command
+        queue is created for the specified device</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_QUEUE_SIZE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Specifies the size of the device queue in bytes.</p>
+<p class="tableblock">        This can only be specified if CL_QUEUE_ON_DEVICE is set in
+        CL_QUEUE_PROPERTIES.
+        This must be a value ≤ CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE.</p>
+<p class="tableblock">        For best performance, this should be ≤
+        CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE.</p>
+<p class="tableblock">        If CL_QUEUE_SIZE is not specified, the device queue is created with
+        CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE as the size of the queue.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="dlist">
+<dl>
+<dt class="hdlist1">1</dt>
+<dd>
+<p>Only out-of-order device queues are supported.</p>
+</dd>
+<dt class="hdlist1">2</dt>
+<dd>
+<p>The application must create the default device queue if any kernels
+containing calls to get_default_queue are enqueued.
+There can only be one default device queue for each device within a
+context.
+<strong>clCreateCommandQueueWithProperties</strong> with CL_QUEUE_PROPERTIES set to
+CL_QUEUE_ON_DEVICE or CL_QUEUE_ON_DEVICE_DEFAULT will return the default
+device queue that has already been created and increment its retain
+count by 1.</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p><em>errcode_ret</em> will return an appropriate error code.
+If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p>
+</div>
+<div class="paragraph">
+<p><strong>clCreateCommandQueueWithProperties</strong> returns a valid non-zero command-queue
+and <em>errcode_ret</em> is set to CL_SUCCESS if the command-queue is created
+successfully.
+Otherwise, it returns a <code>NULL</code> value with one of the following error values
+returned in <em>errcode_ret</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p>
+</li>
+<li>
+<p>CL_INVALID_DEVICE if <em>device</em> is not a valid device or is not associated
+with <em>context</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if values specified in <em>properties</em> are not valid.</p>
+</li>
+<li>
+<p>CL_INVALID_QUEUE_PROPERTIES if values specified in <em>properties</em> are
+valid but are not supported by the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clSetDefaultDeviceCommandQueue(cl_context context,
+                                      cl_device_id device,
+                                      cl_command_queue command_queue)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>replaces the default command queue on the <em>device</em>.</p>
+</div>
+<div class="paragraph">
+<p><strong>clSetDefaultDeviceCommandQueue</strong> returns CL_SUCCESS if the function is
+executed successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p>
+</li>
+<li>
+<p>CL_INVALID_DEVICE if <em>device</em> is not a valid device or is not associated
+with <em>context</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid command-queue
+for <em>device</em>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p><strong>clSetDefaultDeviceCommandQueue</strong> may be used to replace a default device
+command queue created with <strong>clCreateCommandQueueWithProperties</strong> and the
+CL_QUEUE_ON_DEVICE_DEFAULT flag.</p>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clRetainCommandQueue(cl_command_queue command_queue)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>increments the <em>command_queue</em> reference count.
+<strong>clRetainCommandQueue</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid
+command-queue.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p><strong>clCreateCommandQueueWithProperties</strong> performs an implicit retain.
+This is very helpful for 3<sup>rd</sup> party libraries, which typically get a
+command-queue passed to them by the application.
+However, it is possible that the application may delete the command-queue
+without informing the library.
+Allowing functions to attach to (i.e. retain) and release a command-queue
+solves the problem of a command-queue being used by a library no longer
+being valid.</p>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clReleaseCommandQueue(cl_command_queue command_queue)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>decrements the <em>command_queue</em> reference count.
+<strong>clReleaseCommandQueue</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid
+command-queue.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>After the <em>command_queue</em> reference count becomes zero and all commands
+queued to <em>command_queue</em> have finished (eg.
+kernel-instances, memory object updates etc.), the command-queue is deleted.</p>
+</div>
+<div class="paragraph">
+<p><strong>clReleaseCommandQueue</strong> performs an implicit flush to issue any previously
+queued OpenCL commands in <em>command_queue</em>.
+Using this function to release a reference that was not obtained by creating
+the object or by calling <strong>clRetainCommandQueue</strong> causes undefined behavior.</p>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clGetCommandQueueInfo(cl_command_queue command_queue,
+                             cl_command_queue_info param_name,
+                             size_t param_value_size,
+                             <span class="directive">void</span> *param_value,
+                             size_t *param_value_size_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>can be used to query information about a command-queue.</p>
+</div>
+<div class="paragraph">
+<p><em>command_queue</em> specifies the command-queue being queried.</p>
+</div>
+<div class="paragraph">
+<p><em>param_name</em> specifies the information to query.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value</em> is a pointer to memory where the appropriate result being
+queried is returned.
+If <em>param_value</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size</em> is used to specify the size in bytes of memory pointed to
+by <em>param_value</em>.
+This size must be ≥ size of return type as described in the
+<a href="#command-queue-param-table">Command Queue Parameter</a> table.
+If <em>param_value</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size_ret</em> returns the actual size in bytes of data being
+queried by <em>param_name</em>.
+If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<div class="paragraph">
+<p>The list of supported <em>param_name</em> values and the information returned in
+<em>param_value</em> by <strong>clGetCommandQueueInfo</strong> is described in the
+<a href="#command-queue-param-table">Command Queue Parameter</a> table.</p>
+</div>
+<table id="command-queue-param-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 10. List of supported param_names by <strong>clGetCommandQueueInfo</strong></caption>
+<colgroup>
+<col style="width: 34%;">
+<col style="width: 33%;">
+<col style="width: 33%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_command_queue_info</strong></th>
+<th class="tableblock halign-left valign-top">Return Type</th>
+<th class="tableblock halign-left valign-top">Information returned in param_value</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_QUEUE_CONTEXT</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_context</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the context specified when the command-queue is created.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_QUEUE_DEVICE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_id</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the device specified when the command-queue is created.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_QUEUE_REFERENCE_COUNT</strong><sup>3</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the command-queue reference count.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_QUEUE_PROPERTIES</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_command_queue_properties</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the currently specified properties for the command-queue.
+        These properties are specified by the value associated with the
+        CL_COMMAND_QUEUE_PROPERTIES passed in <em>properties</em> argument in
+        <strong>clCreateCommandQueueWithProperties.</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_QUEUE_SIZE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the currently specified size for the device command-queue.
+        This query is only supported for device command queues.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_QUEUE_DEVICE_DEFAULT</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_command_queue</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the current default command queue for the underlying device.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="dlist">
+<dl>
+<dt class="hdlist1">3</dt>
+<dd>
+<p>The reference count returned should be considered immediately stale.
+It is unsuitable for general use in applications.
+This feature is provided for identifying memory leaks.</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p><strong>clGetCommandQueueInfo</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>param_name</em> is not one of the supported values or
+if size in bytes specified by <em>param_value_size</em> is &lt; size of return
+type as specified in the <a href="#command-queue-param-table">Command Queue
+Parameter</a> table, and <em>param_value</em> is not a <code>NULL</code> value.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>It is possible that a device(s) becomes unavailable after a context and
+command-queues that use this device(s) have been created and commands have
+been queued to command-queues.
+In this case the behavior of OpenCL API calls that use this context (and
+command-queues) are considered to be implementation-defined.
+The user callback function, if specified, when the context is created can be
+used to record appropriate information in the <em>errinfo</em>, <em>private_info</em>
+arguments passed to the callback function when the device becomes
+unavailable.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_buffer_objects">5.2. Buffer Objects</h3>
+<div class="paragraph">
+<p>A <em>buffer</em> object stores a one-dimensional collection of elements.
+Elements of a <em>buffer</em> object can be a scalar data type (such as an int,
+float), vector data type, or a user-defined structure.</p>
+</div>
+<div class="sect3">
+<h4 id="_creating_buffer_objects">5.2.1. Creating Buffer Objects</h4>
+<div class="paragraph">
+<p>A <strong>buffer object</strong> is created using the following function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_mem clCreateBuffer(cl_context context,
+                      cl_mem_flags flags,
+                      size_t size,
+                      <span class="directive">void</span> *host_ptr,
+                      cl_int *errcode_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><em>context</em> is a valid OpenCL context used to create the buffer object.</p>
+</div>
+<div class="paragraph">
+<p><em>flags</em> is a bit-field that is used to specify allocation and usage
+information such as the memory arena that should be used to allocate the
+buffer object and how it will be used.
+The <a href="#memory-flags-table">Memory Flags</a> table describes the possible values
+for <em>flags</em>.
+If value specified for <em>flags</em> is 0, the default is used which is
+CL_MEM_READ_WRITE.</p>
+</div>
+<table id="memory-flags-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 11. List of supported cl_mem_flags values</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_mem_flags</strong></th>
+<th class="tableblock halign-left valign-top">Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_READ_WRITE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This flag specifies that the memory object will be read
+    and written by a kernel.
+    This is the default.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_WRITE_ONLY</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This flag specifies that the memory object will be
+    written but not read by a kernel.</p>
+<p class="tableblock">    Reading from a buffer or image object created with CL_MEM_WRITE_ONLY
+    inside a kernel is undefined.</p>
+<p class="tableblock">    CL_MEM_READ_WRITE and CL_MEM_WRITE_ONLY are mutually exclusive.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_READ_ONLY</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This flag specifies that the memory object is a
+    readonly memory object when used inside a kernel.</p>
+<p class="tableblock">    Writing to a buffer or image object created with CL_MEM_READ_ONLY inside
+    a kernel is undefined.</p>
+<p class="tableblock">    CL_MEM_READ_WRITE or CL_MEM_WRITE_ONLY and CL_MEM_READ_ONLY are mutually
+    exclusive.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_USE_HOST_PTR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This flag is valid only if host_ptr is not <code>NULL</code>.
+    If specified, it indicates that the application wants the OpenCL
+    implementation to use memory referenced by host_ptr as the storage bits
+    for the memory object.</p>
+<p class="tableblock">    The contents of the memory pointed to by host_ptr at the time of the
+    clCreateBuffer call define the initial contents of the buffer object.</p>
+<p class="tableblock">    OpenCL implementations are allowed to cache the buffer contents pointed
+    to by host_ptr in device memory.
+    This cached copy can be used when kernels are executed on a device.</p>
+<p class="tableblock">    The result of OpenCL commands that operate on multiple buffer objects
+    created with the same host_ptr or from overlapping host or SVM regions
+    is considered to be undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_ALLOC_HOST_PTR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This flag specifies that the application wants the OpenCL implementation
+    to allocate memory from host accessible memory.</p>
+<p class="tableblock">    CL_MEM_ALLOC_HOST_PTR and CL_MEM_USE_HOST_PTR are mutually exclusive.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_COPY_HOST_PTR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This flag is valid only if host_ptr is not <code>NULL</code>.
+    If specified, it indicates that the application wants the OpenCL
+    implementation to allocate memory for the memory object and copy the
+    data from memory referenced by host_ptr.
+    The implementation will copy the memory immediately and host_ptr is
+    available for reuse by the application when the <strong>clCreateBuffer</strong> or
+    <strong>clCreateImage</strong> operation returns.</p>
+<p class="tableblock">    CL_MEM_COPY_HOST_PTR and CL_MEM_USE_HOST_PTR are mutually exclusive.</p>
+<p class="tableblock">    CL_MEM_COPY_HOST_PTR can be used with CL_MEM_ALLOC_HOST_PTR to
+    initialize the contents of the cl_mem object allocated using
+    hostaccessible (e.g. PCIe) memory.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_HOST_WRITE_ONLY</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This flag specifies that the host will only write to the memory object
+    (using OpenCL APIs that enqueue a write or a map for write).
+    This can be used to optimize write access from the host (e.g. enable
+    write-combined allocations for memory objects for devices that
+    communicate with the host over a system bus such as PCIe).</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_HOST_READ_ONLY</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This flag specifies that the host will only read
+    the memory object (using OpenCL APIs that enqueue a read or a map for
+    read).</p>
+<p class="tableblock">    CL_MEM_HOST_WRITE_ONLY and CL_MEM_HOST_READ_ONLY are mutually exclusive.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_HOST_NO_ACCESS</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This flag specifies that the host will not read or
+    write the memory object.</p>
+<p class="tableblock">    CL_MEM_HOST_WRITE_ONLY or CL_MEM_HOST_READ_ONLY and
+    CL_MEM_HOST_NO_ACCESS are mutually exclusive.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p><em>size</em> is the size in bytes of the buffer memory object to be allocated.</p>
+</div>
+<div class="paragraph">
+<p><em>host_ptr</em> is a pointer to the buffer data that may already be allocated by
+the application.
+The size of the buffer that <em>host_ptr</em> points to must be ≥ <em>size</em> bytes.</p>
+</div>
+<div class="paragraph">
+<p>The user is responsible for ensuring that data passed into and out of OpenCL
+images are natively aligned relative to the start of the buffer as per
+kernel language or IL requirements.
+OpenCL buffers created with CL_MEM_USE_HOST_PTR need to provide an
+appropriately aligned host memory pointer that is aligned to the data types
+used to access these buffers in a kernel(s).</p>
+</div>
+<div class="paragraph">
+<p><em>errcode_ret</em> will return an appropriate error code.
+If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p>
+</div>
+<div class="paragraph">
+<p>If <strong>clCreateBuffer</strong> is called with CL_MEM_USE_HOST_PTR set in its <em>flags</em>
+argument, the contents of the memory pointed to by <em>host_ptr</em> at the time
+of the <strong>clCreateBuffer</strong> call define the initial contents of the
+buffer object.</p>
+</div>
+<div class="paragraph">
+<p>If <strong>clCreateBuffer</strong> is called with a pointer returned by <strong>clSVMAlloc</strong> as its
+<em>host_ptr</em> argument, and CL_MEM_USE_HOST_PTR is set in its <em>flags</em> argument,
+<strong>clCreateBuffer</strong> will succeed and return a valid non-zero buffer object as
+long as the <em>size</em> argument to <strong>clCreateBuffer</strong> is no larger than the <em>size</em>
+argument passed in the original <strong>clSVMAlloc</strong> call.
+The new buffer object returned has the shared memory as the underlying
+storage.
+Locations in the buffers underlying shared memory can be operated on using
+atomic operations to the devices level of support as defined in the memory
+model.</p>
+</div>
+<div class="paragraph">
+<p><strong>clCreateBuffer</strong> returns a valid non-zero buffer object and <em>errcode_ret</em> is
+set to CL_SUCCESS if the buffer object is created successfully.
+Otherwise, it returns a <code>NULL</code> value with one of the following error values
+returned in <em>errcode_ret</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if values specified in <em>flags</em> are not valid as defined
+in the <a href="#memory-flags-table">Memory Flags</a> table.</p>
+</li>
+<li>
+<p>CL_INVALID_BUFFER_SIZE if <em>size</em> is 0<sup>4</sup>.</p>
+</li>
+<li>
+<p>CL_INVALID_HOST_PTR if <em>host_ptr</em> is <code>NULL</code> and CL_MEM_USE_HOST_PTR or
+CL_MEM_COPY_HOST_PTR are set in <em>flags</em> or if <em>host_ptr</em> is not <code>NULL</code>
+but CL_MEM_COPY_HOST_PTR or CL_MEM_USE_HOST_PTR are not set in <em>flags</em>.</p>
+</li>
+<li>
+<p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate
+memory for buffer object.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+<div class="dlist">
+<dl>
+<dt class="hdlist1">4</dt>
+<dd>
+<p>Implementations may return CL_INVALID_BUFFER_SIZE if size is greater
+than CL_DEVICE_MAX_MEM_ALLOC_SIZE value specified in the
+<a href="#device-queries-table">Device Queries</a> table for all devices in
+context.</p>
+</dd>
+</dl>
+</div>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_mem clCreateSubBuffer(cl_mem buffer,
+                         cl_mem_flags flags,
+                         cl_buffer_create_type buffer_create_type,
+                         <span class="directive">const</span> <span class="directive">void</span> *buffer_create_info,
+                         cl_int *errcode_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>can be used to create a new buffer object (referred to as a sub-buffer
+object) from an existing buffer object.</p>
+</div>
+<div class="paragraph">
+<p><em>buffer</em> must be a valid buffer object and cannot be a sub-buffer object.</p>
+</div>
+<div class="paragraph">
+<p><em>flags</em> is a bit-field that is used to specify allocation and usage
+information about the sub-buffer memory object being created and is
+described in the <a href="#memory-flags-table">Memory Flags</a> table.
+If the CL_MEM_READ_WRITE, CL_MEM_READ_ONLY or CL_MEM_WRITE_ONLY values are
+not specified in <em>flags</em>, they are inherited from the corresponding memory
+access qualifers associated with <em>buffer</em>.
+The CL_MEM_USE_HOST_PTR, CL_MEM_ALLOC_HOST_PTR and CL_MEM_COPY_HOST_PTR
+values cannot be specified in <em>flags</em> but are inherited from the
+corresponding memory access qualifiers associated with <em>buffer</em>.
+If CL_MEM_COPY_HOST_PTR is specified in the memory access qualifier values
+associated with <em>buffer</em> it does not imply any additional copies when the
+sub-buffer is created from <em>buffer</em>.
+If the CL_MEM_HOST_WRITE_ONLY, CL_MEM_HOST_READ_ONLY or
+CL_MEM_HOST_NO_ACCESS values are not specified in <em>flags</em>, they are
+inherited from the corresponding memory access qualifiers associated with
+<em>buffer</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>buffer_create_type</em> and <em>buffer_create_info</em> describe the type of buffer
+object to be created.
+The list of supported values for <em>buffer_create_type</em> and corresponding
+descriptor that <em>buffer_create_info</em> points to is described in the
+<a href="#subbuffer-create-info-table">SubBuffer Attributes</a> table.</p>
+</div>
+<table id="subbuffer-create-info-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 12. List of supported names and values in <strong>clCreateSubBuffer</strong></caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_buffer_create_type</strong></th>
+<th class="tableblock halign-left valign-top">Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_BUFFER_CREATE_TYPE_REGION</strong></p></td>
+<td class="tableblock halign-left valign-top"><div><div class="paragraph">
+<p>Create a buffer object that represents a
+    specific region in buffer.</p>
+</div>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>buffer_create_info is a pointer to the following structure:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="keyword">typedef</span> <span class="keyword">struct</span> _cl_buffer_region {
+    size_t origin;
+    size_t size;
+} cl_buffer_region;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>(<em>origin</em>, <em>size</em>) defines the offset and size in bytes in buffer.</p>
+</div>
+<div class="paragraph">
+<p>If buffer is created with CL_MEM_USE_HOST_PTR, the host_ptr associated with
+the buffer object returned is <em>host_ptr + origin</em>.</p>
+</div>
+<div class="paragraph">
+<p>The buffer object returned references the data store allocated for buffer
+and points to a specific region given by (origin, size) in this data store.</p>
+</div>
+<div class="paragraph">
+<p>CL_INVALID_VALUE is returned in errcode_ret if the region specified by
+(origin, size) is out of bounds in buffer.</p>
+</div>
+<div class="paragraph">
+<p>CL_INVALID_BUFFER_SIZE if size is 0.</p>
+</div>
+<div class="paragraph">
+<p>CL_MISALIGNED_SUB_BUFFER_OFFSET is returned in errcode_ret if there are no
+devices in context associated with buffer for which the origin value is
+aligned to the CL_DEVICE_MEM_BASE_ADDR_ALIGN value.</p>
+</div>
+</div>
+</div></div></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p><strong>clCreateSubBuffer</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors in <em>errcode_ret</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_MEM_OBJECT if <em>buffer</em> is not a valid buffer object or is a
+sub-buffer object.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>buffer</em> was created with CL_MEM_WRITE_ONLY and
+<em>flags</em> specifies CL_MEM_READ_WRITE or CL_MEM_READ_ONLY, or if <em>buffer</em>
+was created with CL_MEM_READ_ONLY and <em>flags</em> specifies
+CL_MEM_READ_WRITE or CL_MEM_WRITE_ONLY, or if <em>flags</em> specifies
+CL_MEM_USE_HOST_PTR or CL_MEM_ALLOC_HOST_PTR or CL_MEM_COPY_HOST_PTR.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>buffer</em> was created with CL_MEM_HOST_WRITE_ONLY and
+<em>flags</em> specify CL_MEM_HOST_READ_ONLY, or if <em>buffer</em> was created with
+CL_MEM_HOST_READ_ONLY and <em>flags</em> specify CL_MEM_HOST_WRITE_ONLY, or if
+<em>buffer</em> was created with CL_MEM_HOST_NO_ACCESS and <em>flags</em> specify
+CL_MEM_HOST_READ_ONLY or CL_MEM_HOST_WRITE_ONLY.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if value specified in <em>buffer_create_type</em> is not
+valid.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if value(s) specified in <em>buffer_create_info</em> (for a
+given <em>buffer_create_type</em>) is not valid or if <em>buffer_create_info</em> is
+<code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_BUFFER_SIZE if <em>size</em> is 0.</p>
+</li>
+<li>
+<p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate
+memory for sub-buffer object.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>Concurrent reading from, writing to and copying between both a buffer object
+and its sub-buffer object(s) is undefined.
+Concurrent reading from, writing to and copying between overlapping
+sub-buffer objects created with the same buffer object is undefined.
+Only reading from both a buffer object and its sub-buffer objects or reading
+from multiple overlapping sub-buffer objects is defined.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_reading_writing_and_copying_buffer_objects">5.2.2. Reading, Writing and Copying Buffer Objects</h4>
+<div class="paragraph">
+<p>The following functions enqueue commands to read from a buffer object to
+host memory or write to a buffer object from host memory.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueReadBuffer(cl_command_queue command_queue,
+                           cl_mem buffer,
+                           cl_bool blocking_read,
+                           size_t offset,
+                           size_t size,
+                           <span class="directive">void</span> *ptr,
+                           cl_uint num_events_in_wait_list,
+                           <span class="directive">const</span> cl_event *event_wait_list,
+                           cl_event *event)</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueWriteBuffer(cl_command_queue command_queue,
+                            cl_mem buffer,
+                            cl_bool blocking_write,
+                            size_t offset,
+                            size_t size,
+                            <span class="directive">const</span> <span class="directive">void</span> *ptr,
+                            cl_uint num_events_in_wait_list,
+                            <span class="directive">const</span> cl_event *event_wait_list,
+                            cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><em>command_queue</em> is a valid host command-queue in which the read / write
+command will be queued.
+<em>command_queue</em> and <em>buffer</em> must be created with the same OpenCL context.</p>
+</div>
+<div class="paragraph">
+<p><em>buffer</em> refers to a valid buffer object.</p>
+</div>
+<div class="paragraph">
+<p><em>blocking_read</em> and <em>blocking_write</em> indicate if the read and write
+operations are <em>blocking</em> or <em>non-blocking</em>.</p>
+</div>
+<div class="paragraph">
+<p>If <em>blocking_read</em> is CL_TRUE i.e. the read command is blocking,
+<strong>clEnqueueReadBuffer</strong> does not return until the buffer data has been read
+and copied into memory pointed to by <em>ptr</em>.</p>
+</div>
+<div class="paragraph">
+<p>If <em>blocking_read</em> is CL_FALSE i.e. the read command is non-blocking,
+<strong>clEnqueueReadBuffer</strong> queues a non-blocking read command and returns.
+The contents of the buffer that <em>ptr</em> points to cannot be used until the
+read command has completed.
+The <em>event</em> argument returns an event object which can be used to query the
+execution status of the read command.
+When the read command has completed, the contents of the buffer that <em>ptr</em>
+points to can be used by the application.</p>
+</div>
+<div class="paragraph">
+<p>If <em>blocking_write</em> is CL_TRUE, the OpenCL implementation copies the data
+referred to by <em>ptr</em> and enqueues the write operation in the command-queue.
+The memory pointed to by <em>ptr</em> can be reused by the application after the
+<strong>clEnqueueWriteBuffer</strong> call returns.</p>
+</div>
+<div class="paragraph">
+<p>If <em>blocking_write</em> is CL_FALSE, the OpenCL implementation will use <em>ptr</em> to
+perform a non-blocking write.
+As the write is non-blocking the implementation can return immediately.
+The memory pointed to by <em>ptr</em> cannot be reused by the application after the
+call returns.
+The <em>event</em> argument returns an event object which can be used to query the
+execution status of the write command.
+When the write command has completed, the memory pointed to by <em>ptr</em> can
+then be reused by the application.</p>
+</div>
+<div class="paragraph">
+<p><em>offset</em> is the offset in bytes in the buffer object to read from or write
+to.</p>
+</div>
+<div class="paragraph">
+<p><em>size</em> is the size in bytes of data being read or written.</p>
+</div>
+<div class="paragraph">
+<p><em>ptr</em> is the pointer to buffer in host memory where data is to be read into
+or to be written from.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before this particular command can be executed.
+If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait
+on any event to complete.
+If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event_wait_list</em> act as synchronization points.
+The context associated with events in <em>event_wait_list</em> and <em>command_queue</em>
+must be the same.
+The memory associated with <em>event_wait_list</em> can be reused or freed after
+the function returns.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> returns an event object that identifies this particular read / write
+command and can be used to query or queue a wait for this particular command
+to complete.
+<em>event</em> can be <code>NULL</code> in which case it will not be possible for the
+application to query the status of this command or queue a wait for this
+command to complete.
+If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the
+<em>event</em> argument should not refer to an element of the <em>event_wait_list</em>
+array.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueReadBuffer</strong> and <strong>clEnqueueWriteBuffer</strong> return CL_SUCCESS if the
+function is executed successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if the context associated with <em>command_queue</em> and
+<em>buffer</em> are not the same or if the context associated with
+<em>command_queue</em> and events in <em>event_wait_list</em> are not the same.</p>
+</li>
+<li>
+<p>CL_INVALID_MEM_OBJECT if <em>buffer</em> is not a valid buffer object.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if the region being read or written specified by
+(<em>offset</em>, <em>size</em>) is out of bounds or if <em>ptr</em> is a <code>NULL</code> value.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p>CL_MISALIGNED_SUB_BUFFER_OFFSET if <em>buffer</em> is a sub-buffer object and
+<em>offset</em> specified when the sub-buffer object is created is not aligned
+to CL_DEVICE_MEM_BASE_ADDR_ALIGN value for device associated with
+<em>queue</em>.</p>
+</li>
+<li>
+<p>CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST if the read and write
+operations are blocking and the execution status of any of the events in
+<em>event_wait_list</em> is a negative integer value.</p>
+</li>
+<li>
+<p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate
+memory for data store associated with <em>buffer</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if <strong>clEnqueueReadBuffer</strong> is called on <em>buffer</em>
+which has been created with CL_MEM_HOST_WRITE_ONLY or
+CL_MEM_HOST_NO_ACCESS.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if <strong>clEnqueueWriteBuffer</strong> is called on <em>buffer</em>
+which has been created with CL_MEM_HOST_READ_ONLY or
+CL_MEM_HOST_NO_ACCESS.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The following functions enqueue commands to read a 2D or 3D rectangular
+region from a buffer object to host memory or write a 2D or 3D rectangular
+region to a buffer object from host memory.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueReadBufferRect(cl_command_queue command_queue,
+                               cl_mem buffer,
+                               cl_bool blocking_read,
+                               <span class="directive">const</span> size_t *buffer_origin,
+                               <span class="directive">const</span> size_t *host_origin,
+                               <span class="directive">const</span> size_t *region,
+                               size_t buffer_row_pitch,
+                               size_t buffer_slice_pitch,
+                               size_t host_row_pitch,
+                               size_t host_slice_pitch,
+                               <span class="directive">void</span> *ptr,
+                               cl_uint num_events_in_wait_list,
+                               <span class="directive">const</span> cl_event *event_wait_list,
+                               cl_event *event)</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueWriteBufferRect(cl_command_queue command_queue,
+                                cl_mem buffer,
+                                cl_bool blocking_write,
+                                <span class="directive">const</span> size_t *buffer_origin,
+                                <span class="directive">const</span> size_t *host_origin,
+                                <span class="directive">const</span> size_t *region,
+                                size_t buffer_row_pitch,
+                                size_t buffer_slice_pitch,
+                                size_t host_row_pitch,
+                                size_t host_slice_pitch,
+                                <span class="directive">const</span> <span class="directive">void</span> *ptr,
+                                cl_uint num_events_in_wait_list,
+                                <span class="directive">const</span> cl_event *event_wait_list,
+                                cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><em>command_queue</em> refers is a valid host command-queue in which the read /
+write command will be queued.
+<em>command_queue</em> and <em>buffer</em> must be created with the same OpenCL context.</p>
+</div>
+<div class="paragraph">
+<p><em>buffer</em> refers to a valid buffer object.</p>
+</div>
+<div class="paragraph">
+<p><em>blocking_read</em> and <em>blocking_write</em> indicate if the read and write
+operations are <em>blocking</em> or <em>non-blocking</em>.</p>
+</div>
+<div class="paragraph">
+<p>If <em>blocking_read</em> is CL_TRUE i.e. the read command is blocking,
+<strong>clEnqueueReadBufferRect</strong> does not return until the buffer data has been
+read and copied into memory pointed to by <em>ptr</em>.</p>
+</div>
+<div class="paragraph">
+<p>If <em>blocking_read</em> is CL_FALSE i.e. the read command is non-blocking,
+<strong>clEnqueueReadBufferRect</strong> queues a non-blocking read command and returns.
+The contents of the buffer that <em>ptr</em> points to cannot be used until the
+read command has completed.
+The <em>event</em> argument returns an event object which can be used to query the
+execution status of the read command.
+When the read command has completed, the contents of the buffer that <em>ptr</em>
+points to can be used by the application.</p>
+</div>
+<div class="paragraph">
+<p>If <em>blocking_write</em> is CL_TRUE, the OpenCL implementation copies the data
+referred to by <em>ptr</em> and enqueues the write operation in the command-queue.
+The memory pointed to by <em>ptr</em> can be reused by the application after the
+<strong>clEnqueueWriteBufferRect</strong> call returns.</p>
+</div>
+<div class="paragraph">
+<p>If <em>blocking_write</em> is CL_FALSE, the OpenCL implementation will use <em>ptr</em> to
+perform a non-blocking write.
+As the write is non-blocking the implementation can return immediately.
+The memory pointed to by <em>ptr</em> cannot be reused by the application after the
+call returns.
+The <em>event</em> argument returns an event object which can be used to query the
+execution status of the write command.
+When the write command has completed, the memory pointed to by <em>ptr</em> can
+then be reused by the application.</p>
+</div>
+<div class="paragraph">
+<p><em>buffer_origin</em> defines the (<em>x</em>, <em>y</em>, <em>z</em>) offset in the memory region
+associated with <em>buffer</em>.
+For a 2D rectangle region, the <em>z</em> value given by <em>buffer_origin</em>[2] should
+be 0.
+The offset in bytes is computed as <em>buffer_origin</em>[2] ×
+<em>buffer_slice_pitch</em> + <em>buffer_origin</em>[1] × <em>buffer_row_pitch</em> + 
+<em>buffer_origin</em>[0].</p>
+</div>
+<div class="paragraph">
+<p><em>host_origin</em> defines the (<em>x</em>, <em>y</em>, <em>z</em>) offset in the memory region
+pointed to by <em>ptr</em>.
+For a 2D rectangle region, the <em>z</em> value given by <em>host_origin</em>[2] should be
+0.
+The offset in bytes is computed as <em>host_origin</em>[2] ×
+<em>host_slice_pitch</em> + <em>host_origin</em>[1] × <em>host_row_pitch</em> + 
+<em>host_origin</em>[0].</p>
+</div>
+<div class="paragraph">
+<p><em>region</em> defines the (<em>width</em> in bytes, <em>height</em> in rows, <em>depth</em> in slices)
+of the 2D or 3D rectangle being read or written.
+For a 2D rectangle copy, the <em>depth</em> value given by <em>region</em>[2] should be 1.
+The values in region cannot be 0.</p>
+</div>
+<div class="paragraph">
+<p><em>buffer_row_pitch</em> is the length of each row in bytes to be used for the
+memory region associated with <em>buffer</em>.
+If <em>buffer_row_pitch</em> is 0, <em>buffer_row_pitch</em> is computed as <em>region</em>[0].</p>
+</div>
+<div class="paragraph">
+<p><em>buffer_slice_pitch</em> is the length of each 2D slice in bytes to be used for
+the memory region associated with <em>buffer</em>.
+If <em>buffer_slice_pitch</em> is 0, <em>buffer_slice_pitch</em> is computed as
+<em>region</em>[1] × <em>buffer_row_pitch</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>host_row_pitch</em> is the length of each row in bytes to be used for the
+memory region pointed to by <em>ptr</em>.
+If <em>host_row_pitch</em> is 0, <em>host_row_pitch</em> is computed as <em>region</em>[0].</p>
+</div>
+<div class="paragraph">
+<p><em>host_slice_pitch</em> is the length of each 2D slice in bytes to be used for
+the memory region pointed to by <em>ptr</em>.
+If <em>host_slice_pitch</em> is 0, <em>host_slice_pitch</em> is computed as <em>region</em>[1]
+× <em>host_row_pitch</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>ptr</em> is the pointer to buffer in host memory where data is to be read into
+or to be written from.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before this particular command can be executed.
+If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait
+on any event to complete.
+If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event_wait_list</em> act as synchronization points.
+The context associated with events in <em>event_wait_list</em> and <em>command_queue</em>
+must be the same.
+The memory associated with <em>event_wait_list</em> can be reused or freed after
+the function returns.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> returns an event object that identifies this particular read / write
+command and can be used to query or queue a wait for this particular command
+to complete.
+<em>event</em> can be <code>NULL</code> in which case it will not be possible for the
+application to query the status of this command or queue a wait for this
+command to complete.
+If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the
+<em>event</em> argument should not refer to an element of the <em>event_wait_list</em>
+array.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueReadBufferRect</strong> and <strong>clEnqueueWriteBufferRect</strong> return CL_SUCCESS
+if the function is executed successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if the context associated with <em>command_queue</em> and
+<em>buffer</em> are not the same or if the context associated with
+<em>command_queue</em> and events in <em>event_wait_list</em> are not the same.</p>
+</li>
+<li>
+<p>CL_INVALID_MEM_OBJECT if <em>buffer</em> is not a valid buffer object.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if the region being read or written specified by
+(<em>buffer_origin</em>, <em>region</em>, <em>buffer_row_pitch</em>, <em>buffer_slice_pitch</em>) is
+out of bounds.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>ptr</em> is a <code>NULL</code> value.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if any <em>region</em> array element is 0.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>buffer_row_pitch</em> is not 0 and is less than
+<em>region</em>[0].</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>host_row_pitch</em> is not 0 and is less than
+<em>region</em>[0].</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>buffer_slice_pitch</em> is not 0 and is less than
+<em>region</em>[1] × <em>buffer_row_pitch</em> and not a multiple of
+<em>buffer_row_pitch</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>host_slice_pitch</em> is not 0 and is less than
+<em>region</em>[1] × <em>host_row_pitch</em> and not a multiple of
+<em>host_row_pitch</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p>CL_MISALIGNED_SUB_BUFFER_OFFSET if <em>buffer</em> is a sub-buffer object and
+<em>offset</em> specified when the sub-buffer object is created is not aligned
+to CL_DEVICE_MEM_BASE_ADDR_ALIGN value for device associated with
+<em>queue</em>.</p>
+</li>
+<li>
+<p>CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST if the read and write
+operations are blocking and the execution status of any of the events in
+<em>event_wait_list</em> is a negative integer value.</p>
+</li>
+<li>
+<p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate
+memory for data store associated with <em>buffer</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if <strong>clEnqueueReadBufferRect</strong> is called on <em>buffer</em>
+which has been created with CL_MEM_HOST_WRITE_ONLY or
+CL_MEM_HOST_NO_ACCESS.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if <strong>clEnqueueWriteBufferRect</strong> is called on <em>buffer</em>
+which has been created with CL_MEM_HOST_READ_ONLY or
+CL_MEM_HOST_NO_ACCESS.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>Calling <strong>clEnqueueReadBuffer</strong> to read a region of the buffer object with the
+<em>ptr</em> argument value set to <em>host_ptr</em> + <em>offset</em>, where <em>host_ptr</em> is a
+pointer to the memory region specified when the buffer object being read is
+created with CL_MEM_USE_HOST_PTR, must meet the following requirements in
+order to avoid undefined behavior:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>All commands that use this buffer object or a memory object (buffer or
+image) created from this buffer object have finished execution before
+the read command begins execution.</p>
+</li>
+<li>
+<p>The buffer object or memory objects created from this buffer object are
+not mapped.</p>
+</li>
+<li>
+<p>The buffer object or memory objects created from this buffer object are
+not used by any command-queue until the read command has finished
+execution.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Calling <strong>clEnqueueReadBufferRect</strong> to read a region of the buffer object with
+the <em>ptr</em> argument value set to <em>host_ptr</em> and <em>host_origin</em>,
+<em>buffer_origin</em> values are the same, where <em>host_ptr</em> is a pointer to the
+memory region specified when the buffer object being read is created with
+CL_MEM_USE_HOST_PTR, must meet the same requirements given above for
+<strong>clEnqueueReadBuffer</strong>.</p>
+</div>
+<div class="paragraph">
+<p>Calling <strong>clEnqueueWriteBuffer</strong> to update the latest bits in a region of the
+buffer object with the <em>ptr</em> argument value set to <em>host_ptr</em> + <em>offset</em>,
+where <em>host_ptr</em> is a pointer to the memory region specified when the buffer
+object being written is created with CL_MEM_USE_HOST_PTR, must meet the
+following requirements in order to avoid undefined behavior:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>The host memory region given by (<em>host_ptr</em> + <em>offset</em>, <em>cb</em>) contains
+the latest bits when the enqueued write command begins execution.</p>
+</li>
+<li>
+<p>The buffer object or memory objects created from this buffer object are
+not mapped.</p>
+</li>
+<li>
+<p>The buffer object or memory objects created from this buffer object are
+not used by any command-queue until the write command has finished
+execution.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Calling <strong>clEnqueueWriteBufferRect</strong> to update the latest bits in a region of
+the buffer object with the <em>ptr</em> argument value set to <em>host_ptr</em> and
+<em>host_origin</em>, <em>buffer_origin</em> values are the same, where <em>host_ptr</em> is a
+pointer to the memory region specified when the buffer object being written
+is created with CL_MEM_USE_HOST_PTR, must meet the following requirements in
+order to avoid undefined behavior:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>The host memory region given by (<em>buffer_origin region</em>) contains the
+latest bits when the enqueued write command begins execution.</p>
+</li>
+<li>
+<p>The buffer object or memory objects created from this buffer object are
+not mapped.</p>
+</li>
+<li>
+<p>The buffer object or memory objects created from this buffer object are
+not used by any command-queue until the write command has finished
+execution.</p>
+</li>
+</ul>
+</div>
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueCopyBuffer(cl_command_queue command_queue,
+                           cl_mem src_buffer,
+                           cl_mem dst_buffer,
+                           size_t src_offset,
+                           size_t dst_offset,
+                           size_t size,
+                           cl_uint num_events_in_wait_list,
+                           <span class="directive">const</span> cl_event *event_wait_list,
+                           cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>enqueues a command to copy a buffer object identified by <em>src_buffer</em> to
+another buffer object identified by <em>dst_buffer</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>command_queue</em> refers to a host command-queue in which the copy command
+will be queued.
+The OpenCL context associated with <em>command_queue</em>, <em>src_buffer</em> and
+<em>dst_buffer</em> must be the same.</p>
+</div>
+<div class="paragraph">
+<p><em>src_offset</em> refers to the offset where to begin copying data from
+<em>src_buffer</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>dst_offset</em> refers to the offset where to begin copying data into
+<em>dst_buffer</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>size</em> refers to the size in bytes to copy.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before this particular command can be executed.
+If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait
+on any event to complete.
+If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event_wait_list</em> act as synchronization points.
+The context associated with events in <em>event_wait_list</em> and <em>command_queue</em>
+must be the same.
+The memory associated with <em>event_wait_list</em> can be reused or freed after
+the function returns.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> returns an event object that identifies this particular copy command
+and can be used to query or queue a wait for this particular command to
+complete.
+<em>event</em> can be <code>NULL</code> in which case it will not be possible for the
+application to query the status of this command or queue a wait for this
+command to complete.
+<strong>clEnqueueBarrierWithWaitList</strong> can be used instead.
+If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the
+<em>event</em> argument should not refer to an element of the <em>event_wait_list</em>
+array.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueCopyBuffer</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if the context associated with <em>command_queue</em>,
+<em>src_buffer</em> and <em>dst_buffer</em> are not the same or if the context
+associated with <em>command_queue</em> and events in <em>event_wait_list</em> are not
+the same.</p>
+</li>
+<li>
+<p>CL_INVALID_MEM_OBJECT if <em>src_buffer</em> and <em>dst_buffer</em> are not valid
+buffer objects.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>src_offset</em>, <em>dst_offset</em>, <em>size</em>, <em>src_offset</em>
++  <em>size</em> or <em>dst_offset</em> + <em>size</em> require accessing elements
+outside the <em>src_buffer</em> and <em>dst_buffer</em> buffer objects respectively.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p>CL_MISALIGNED_SUB_BUFFER_OFFSET if <em>src_buffer</em> is a sub-buffer object
+and <em>offset</em> specified when the sub-buffer object is created is not
+aligned to CL_DEVICE_MEM_BASE_ADDR_ALIGN value for device associated
+with <em>queue</em>.</p>
+</li>
+<li>
+<p>CL_MISALIGNED_SUB_BUFFER_OFFSET if <em>dst_buffer</em> is a sub-buffer object
+and <em>offset</em> specified when the sub-buffer object is created is not
+aligned to CL_DEVICE_MEM_BASE_ADDR_ALIGN value for device associated
+with <em>queue</em>.</p>
+</li>
+<li>
+<p>CL_MEM_COPY_OVERLAP if <em>src_buffer</em> and <em>dst_buffer</em> are the same buffer
+or sub-buffer object and the source and destination regions overlap or
+if <em>src_buffer</em> and <em>dst_buffer</em> are different sub-buffers of the same
+associated buffer object and they overlap.
+The regions overlap if <em>src_offset</em> ≤ <em>dst_offset</em> ≤
+<em>src_offset</em> + <em>size</em> 1 or if <em>dst_offset</em> ≤ <em>src_offset</em> ≤
+<em>dst_offset</em> + <em>size</em> 1.</p>
+</li>
+<li>
+<p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate
+memory for data store associated with <em>src_buffer</em> or <em>dst_buffer</em>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueCopyBufferRect(cl_command_queue command_queue,
+                               cl_mem src_buffer,
+                               cl_mem dst_buffer,
+                               <span class="directive">const</span> size_t *src_origin,
+                               <span class="directive">const</span> size_t *dst_origin,
+                               <span class="directive">const</span> size_t *region,
+                               size_t src_row_pitch,
+                               size_t src_slice_pitch,
+                               size_t dst_row_pitch,
+                               size_t dst_slice_pitch,
+                               cl_uint num_events_in_wait_list,
+                               <span class="directive">const</span> cl_event *event_wait_list,
+                               cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>enqueues a command to copy a 2D or 3D rectangular region from the buffer
+object identified by <em>src_buffer</em> to a 2D or 3D region in the buffer object
+identified by <em>dst_buffer</em>.
+Copying begins at the source offset and destination offset which are
+computed as described below in the description for <em>src_origin</em> and
+<em>dst_origin</em>.
+Each byte of the region&#8217;s width is copied from the source offset to the
+destination offset.
+After copying each width, the source and destination offsets are incremented
+by their respective source and destination row pitches.
+After copying each 2D rectangle, the source and destination offsets are
+incremented by their respective source and destination slice pitches.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>If <em>src_buffer</em> and <em>dst_buffer</em> are the same buffer object, <em>src_row_pitch</em>
+must equal <em>dst_row_pitch</em> and <em>src_slice_pitch</em> must equal
+<em>dst_slice_pitch</em>.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p><em>command_queue</em> refers to the host command-queue in which the copy command
+will be queued.
+The OpenCL context associated with <em>command_queue</em>, <em>src_buffer</em> and
+<em>dst_buffer</em> must be the same.</p>
+</div>
+<div class="paragraph">
+<p><em>src_origin</em> defines the (<em>x</em>, <em>y</em>, <em>z</em>) offset in the memory region
+associated with <em>src_buffer</em>.
+For a 2D rectangle region, the <em>z</em> value given by <em>src_origin</em>[2] should be
+0.
+The offset in bytes is computed as <em>src_origin</em>[2] × <em>src_slice_pitch</em>
++ <em>src_origin</em>[1] × <em>src_row_pitch</em> + <em>src_origin</em>[0].</p>
+</div>
+<div class="paragraph">
+<p><em>dst_origin</em> defines the (<em>x</em>, <em>y</em>, <em>z</em>) offset in the memory region
+associated with <em>dst_buffer</em>.
+For a 2D rectangle region, the <em>z</em> value given by <em>dst_origin</em>[2] should be
+0.
+The offset in bytes is computed as <em>dst_origin</em>[2] × <em>dst_slice_pitch</em>
++ <em>dst_origin</em>[1] × <em>dst_row_pitch</em> + <em>dst_origin</em>[0].</p>
+</div>
+<div class="paragraph">
+<p><em>region</em> defines the (<em>width</em> in bytes, <em>height</em> in rows, <em>depth</em> in slices)
+of the 2D or 3D rectangle being copied.
+For a 2D rectangle, the <em>depth</em> value given by <em>region</em>[2] should be 1.
+The values in region cannot be 0.</p>
+</div>
+<div class="paragraph">
+<p><em>src_row_pitch</em> is the length of each row in bytes to be used for the memory
+region associated with <em>src_buffer</em>.
+If <em>src_row_pitch</em> is 0, <em>src_row_pitch</em> is computed as <em>region</em>[0].</p>
+</div>
+<div class="paragraph">
+<p><em>src_slice_pitch</em> is the length of each 2D slice in bytes to be used for the
+memory region associated with <em>src_buffer</em>.
+If <em>src_slice_pitch</em> is 0, <em>src_slice_pitch</em> is computed as <em>region</em>[1]
+× <em>src_row_pitch</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>dst_row_pitch</em> is the length of each row in bytes to be used for the memory
+region associated with <em>dst_buffer</em>.
+If <em>dst_row_pitch</em> is 0, <em>dst_row_pitch</em> is computed as <em>region</em>[0].</p>
+</div>
+<div class="paragraph">
+<p><em>dst_slice_pitch</em> is the length of each 2D slice in bytes to be used for the
+memory region associated with <em>dst_buffer</em>.
+If <em>dst_slice_pitch</em> is 0, <em>dst_slice_pitch</em> is computed as <em>region</em>[1]
+× <em>dst_row_pitch</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before this particular command can be executed.
+If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait
+on any event to complete.
+If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event_wait_list</em> act as synchronization points.
+The context associated with events in <em>event_wait_list</em> and <em>command_queue</em>
+must be the same.
+The memory associated with <em>event_wait_list</em> can be reused or freed after
+the function returns.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> returns an event object that identifies this particular copy command
+and can be used to query or queue a wait for this particular command to
+complete.
+<em>event</em> can be <code>NULL</code> in which case it will not be possible for the
+application to query the status of this command or queue a wait for this
+command to complete.
+<strong>clEnqueueBarrierWithWaitList</strong> can be used instead.
+If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the
+<em>event</em> argument should not refer to an element of the <em>event_wait_list</em>
+array.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueCopyBufferRect</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if the context associated with <em>command_queue</em>,
+<em>src_buffer</em> and <em>dst_buffer</em> are not the same or if the context
+associated with <em>command_queue</em> and events in <em>event_wait_list</em> are not
+the same.</p>
+</li>
+<li>
+<p>CL_INVALID_MEM_OBJECT if <em>src_buffer</em> and <em>dst_buffer</em> are not valid
+buffer objects.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if (<em>src_origin, region, src_row_pitch,
+src_slice_pitch</em>) or (<em>dst_origin, region, dst_row_pitch,
+dst_slice_pitch</em>) require accessing elements outside the <em>src_buffer</em>
+and <em>dst_buffer</em> buffer objects respectively.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if any <em>region</em> array element is 0.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>src_row_pitch</em> is not 0 and is less than
+<em>region</em>[0].</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>dst_row_pitch</em> is not 0 and is less than
+<em>region</em>[0].</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>src_slice_pitch</em> is not 0 and is less than
+<em>region</em>[1] × <em>src_row_pitch</em> or if <em>src_slice_pitch</em> is not 0 and
+is not a multiple of <em>src_row_pitch</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>dst_slice_pitch</em> is not 0 and is less than
+<em>region</em>[1] × <em>dst_row_pitch</em> or if <em>dst_slice_pitch</em> is not 0 and
+is not a multiple of <em>dst_row_pitch</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>src_buffer</em> and <em>dst_buffer</em> are the same buffer
+object and <em>src_slice_pitch</em> is not equal to <em>dst_slice_pitch</em> and
+<em>src_row_pitch</em> is not equal to <em>dst_row_pitch</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p>CL_MEM_COPY_OVERLAP if <em>src_buffer</em> and <em>dst_buffer</em> are the same buffer
+or sub-buffer object and the source and destination regions overlap or
+if <em>src_buffer</em> and <em>dst_buffer</em> are different sub-buffers of the same
+associated buffer object and they overlap.
+Refer to <a href="#check-copy-overlap">CL_MEM_COPY_OVERLAP</a> for details on how
+to determine if source and destination regions overlap.</p>
+</li>
+<li>
+<p>CL_MISALIGNED_SUB_BUFFER_OFFSET if <em>src_buffer</em> is a sub-buffer object
+and <em>offset</em> specified when the sub-buffer object is created is not
+aligned to CL_DEVICE_MEM_BASE_ADDR_ALIGN value for device associated
+with <em>queue</em>.</p>
+</li>
+<li>
+<p>CL_MISALIGNED_SUB_BUFFER_OFFSET if <em>dst_buffer</em> is a sub-buffer object
+and <em>offset</em> specified when the sub-buffer object is created is not
+aligned to CL_DEVICE_MEM_BASE_ADDR_ALIGN value for device associated
+with <em>queue</em>.</p>
+</li>
+<li>
+<p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate
+memory for data store associated with <em>src_buffer</em> or <em>dst_buffer</em>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_filling_buffer_objects">5.2.3. Filling Buffer Objects</h4>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueFillBuffer(cl_command_queue command_queue,
+                           cl_mem buffer,
+                           <span class="directive">const</span> <span class="directive">void</span> *pattern,
+                           size_t pattern_size,
+                           size_t offset,
+                           size_t size,
+                           cl_uint num_events_in_wait_list,
+                           <span class="directive">const</span> cl_event *event_wait_list,
+                           cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>enqueues a command to fill a buffer object with a pattern of a given pattern
+size.
+The usage information which indicates whether the memory object can be read
+or written by a kernel and/or the host and is given by the cl_mem_flags
+argument value specified when <em>buffer</em> is created is ignored by
+<strong>clEnqueueFillBuffer</strong>.</p>
+</div>
+<div class="paragraph">
+<p><em>command_queue</em> refers to the host command-queue in which the fill command
+will be queued.
+The OpenCL context associated with <em>command_queue</em> and <em>buffer</em> must be the
+same.</p>
+</div>
+<div class="paragraph">
+<p><em>buffer</em> is a valid buffer object.</p>
+</div>
+<div class="paragraph">
+<p><em>pattern</em> is a pointer to the data pattern of size <em>pattern_size</em> in bytes.
+<em>pattern</em> will be used to fill a region in <em>buffer</em> starting at <em>offset</em> and
+is <em>size</em> bytes in size.
+The data pattern must be a scalar or vector integer or floating-point data
+type supported by OpenCL as described in <a href="#scalar-data-types">Shared
+Application Scalar Data Types</a> and <a href="#vector-data-types">Supported
+Application Vector Data Types</a>.
+For example, if <em>buffer</em> is to be filled with a pattern of <code>float4</code> values,
+then <em>pattern</em> will be a pointer to a <code>cl_float4</code> value and <em>pattern_size</em>
+will be <code>sizeof(cl_float4)</code>.
+The maximum value of <em>pattern_size</em> is the size of the largest integer or
+floating-point vector data type supported by the OpenCL device.
+The memory associated with <em>pattern</em> can be reused or freed after the
+function returns.</p>
+</div>
+<div class="paragraph">
+<p><em>offset</em> is the location in bytes of the region being filled in <em>buffer</em> and
+must be a multiple of <em>pattern_size</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>size</em> is the size in bytes of region being filled in <em>buffer</em> and must be a
+multiple of <em>pattern_size</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before this particular command can be executed.
+If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait
+on any event to complete.
+If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event_wait_list</em> act as synchronization points.
+The context associated with events in <em>event_wait_list</em> and <em>command_queue</em>
+must be the same.
+The memory associated with <em>event_wait_list</em> can be reused or freed after
+the function returns.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> returns an event object that identifies this particular command and
+can be used to query or queue a wait for this particular command to
+complete.
+<em>event</em> can be <code>NULL</code> in which case it will not be possible for the
+application to query the status of this command or queue a wait for this
+command to complete.
+<strong>clEnqueueBarrierWithWaitList</strong> can be used instead.
+If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the
+<em>event</em> argument should not refer to an element of the <em>event_wait_list</em>
+array.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueFillBuffer</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if the context associated with <em>command_queue</em> and
+<em>buffer</em> are not the same or if the context associated with
+<em>command_queue</em> and events in <em>event_wait_list</em> are not the same.</p>
+</li>
+<li>
+<p>CL_INVALID_MEM_OBJECT if <em>buffer</em> is not a valid buffer object.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>offset</em> or <em>offset</em> + <em>size</em> require accessing
+elements outside the <em>buffer</em> buffer object respectively.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>pattern</em> is <code>NULL</code> or if <em>pattern_size</em> is 0 or if
+<em>pattern_size</em> is not one of { 1, 2, 4, 8, 16, 32, 64, 128 }.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>offset</em> and <em>size</em> are not a multiple of
+<em>pattern_size</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p>CL_MISALIGNED_SUB_BUFFER_OFFSET if <em>buffer</em> is a sub-buffer object and
+offset specified when the sub-buffer object is created is not aligned to
+CL_DEVICE_MEM_BASE_ADDR_ALIGN value for device associated with <em>queue</em>.</p>
+</li>
+<li>
+<p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate
+memory for data store associated with <em>buffer</em>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mapping_buffer_objects">5.2.4. Mapping Buffer Objects</h4>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="directive">void</span> clEnqueueMapBuffer(cl_command_queue command_queue,
+                        cl_mem buffer,
+                        cl_bool blocking_map,
+                        cl_map_flags map_flags,
+                        size_t offset,
+                        size_t size,
+                        cl_uint num_events_in_wait_list,
+                        <span class="directive">const</span> cl_event *event_wait_list,
+                        cl_event *event,
+                        cl_int *errcode_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>enqueues a command to map a region of the buffer object given by <em>buffer</em>
+into the host address space and returns a pointer to this mapped region.</p>
+</div>
+<div class="paragraph">
+<p><em>command_queue</em> must be a valid host command-queue.</p>
+</div>
+<div class="paragraph">
+<p><em>blocking_map</em> indicates if the map operation is <em>blocking</em> or
+<em>non-blocking</em>.</p>
+</div>
+<div class="paragraph">
+<p>If <em>blocking_map</em> is CL_TRUE, <strong>clEnqueueMapBuffer</strong> does not return until the
+specified region in <em>buffer</em> is mapped into the host address space and the
+application can access the contents of the mapped region using the pointer
+returned by <strong>clEnqueueMapBuffer</strong>.</p>
+</div>
+<div class="paragraph">
+<p>If <em>blocking_map</em> is CL_FALSE i.e. map operation is non-blocking, the
+pointer to the mapped region returned by <strong>clEnqueueMapBuffer</strong> cannot be used
+until the map command has completed.
+The <em>event</em> argument returns an event object which can be used to query the
+execution status of the map command.
+When the map command is completed, the application can access the contents
+of the mapped region using the pointer returned by <strong>clEnqueueMapBuffer</strong>.</p>
+</div>
+<div class="paragraph">
+<p><em>map_flags</em> is a bit-field and is described in the
+<a href="#memory-map-flags-table">Memory Map Flags</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>buffer</em> is a valid buffer object.
+The OpenCL context associated with <em>command_queue</em> and <em>buffer</em> must be the
+same.</p>
+</div>
+<div class="paragraph">
+<p><em>offset</em> and <em>size</em> are the offset in bytes and the size of the region in
+the buffer object that is being mapped.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before this particular command can be executed.
+If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait
+on any event to complete.
+If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event_wait_list</em> act as synchronization points.
+The context associated with events in <em>event_wait_list</em> and <em>command_queue</em>
+must be the same.
+The memory associated with <em>event_wait_list</em> can be reused or freed after
+the function returns.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> returns an event object that identifies this particular command and
+can be used to query or queue a wait for this particular command to
+complete.
+<em>event</em> can be <code>NULL</code> in which case it will not be possible for the
+application to query the status of this command or queue a wait for this
+command to complete.
+If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the
+<em>event</em> argument should not refer to an element of the <em>event_wait_list</em>
+array.</p>
+</div>
+<div class="paragraph">
+<p><em>errcode_ret</em> will return an appropriate error code.
+If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueMapBuffer</strong> will return a pointer to the mapped region.
+The <em>errcode_ret</em> is set to CL_SUCCESS.</p>
+</div>
+<div class="paragraph">
+<p>A <code>NULL</code> pointer is returned otherwise with one of the following error
+values returned in <em>errcode_ret</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if context associated with <em>command_queue</em> and
+<em>buffer</em> are not the same or if the context associated with
+<em>command_queue</em> and events in <em>event_wait_list</em> are not the same.</p>
+</li>
+<li>
+<p>CL_INVALID_MEM_OBJECT if <em>buffer</em> is not a valid buffer object.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if region being mapped given by (<em>offset</em>, <em>size</em>) is
+out of bounds or if <em>size</em> is 0 or if values specified in <em>map_flags</em>
+are not valid.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p>CL_MISALIGNED_SUB_BUFFER_OFFSET if <em>buffer</em> is a sub-buffer object and
+<em>offset</em> specified when the sub-buffer object is created is not aligned
+to CL_DEVICE_MEM_BASE_ADDR_ALIGN value for the device associated with
+<em>queue</em>.</p>
+</li>
+<li>
+<p>CL_MAP_FAILURE if there is a failure to map the requested region into
+the host address space.
+This error cannot occur for buffer objects created with
+CL_MEM_USE_HOST_PTR or CL_MEM_ALLOC_HOST_PTR.</p>
+</li>
+<li>
+<p>CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST if the map operation is
+blocking and the execution status of any of the events in
+<em>event_wait_list</em> is a negative integer value.</p>
+</li>
+<li>
+<p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate
+memory for data store associated with <em>buffer</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if buffer_ has been created with
+CL_MEM_HOST_WRITE_ONLY or CL_MEM_HOST_NO_ACCESS and CL_MAP_READ is set
+in <em>map_flags</em> or if <em>buffer</em> has been created with
+CL_MEM_HOST_READ_ONLY or CL_MEM_HOST_NO_ACCESS and CL_MAP_WRITE or
+CL_MAP_WRITE_INVALIDATE_REGION is set in <em>map_flags</em>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if mapping would lead to overlapping regions being
+mapped for writing.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The pointer returned maps a region starting at <em>offset</em> and is at least
+<em>size</em> bytes in size.
+The result of a memory access outside this region is undefined.</p>
+</div>
+<div class="paragraph">
+<p>If the buffer object is created with CL_MEM_USE_HOST_PTR set in <em>mem_flags</em>,
+the following will be true:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>The <em>host_ptr</em> specified in <strong>clCreateBuffer</strong> to contain the latest bits
+in the region being mapped when the <strong>clEnqueueMapBuffer</strong> command has
+completed.</p>
+</li>
+<li>
+<p>The pointer value returned by <strong>clEnqueueMapBuffer</strong> will be derived from
+the <em>host_ptr</em> specified when the buffer object is created.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Mapped buffer objects are unmapped using <strong>clEnqueueUnmapMemObject</strong>.
+This is described in <a href="#unmapping-mapped-memory">Unmapping Mapped Memory
+Objects</a>.</p>
+</div>
+<table id="memory-map-flags-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 13. List of supported cl_map_flags values</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_map_flags</strong></th>
+<th class="tableblock halign-left valign-top">Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MAP_READ</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This flag specifies that the region being mapped in the memory object is
+    being mapped for reading.</p>
+<p class="tableblock">    The pointer returned by <strong>clEnqueueMapBuffer</strong> (<strong>clEnqueueMapImage</strong>) is
+    guaranteed to contain the latest bits in the region being mapped when
+    the <strong>clEnqueueMapBuffer</strong> (<strong>clEnqueueMapImage</strong>) command has completed.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MAP_WRITE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This flag specifies that the region being mapped in the memory object is
+    being mapped for writing.</p>
+<p class="tableblock">    The pointer returned by <strong>clEnqueueMapBuffer</strong> (<strong>clEnqueueMapImage</strong>) is
+    guaranteed to contain the latest bits in the region being mapped when
+    the <strong>clEnqueueMapBuffer</strong> (<strong>clEnqueueMapImage</strong>) command has completed</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MAP_WRITE_INVALIDATE_REGION</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This flag specifies that the region being mapped in the memory object is
+    being mapped for writing.</p>
+<p class="tableblock">    The contents of the region being mapped are to be discarded.
+    This is typically the case when the region being mapped is overwritten
+    by the host.
+    This flag allows the implementation to no longer guarantee that the
+    pointer returned by <strong>clEnqueueMapBuffer</strong> (<strong>clEnqueueMapImage</strong>) contains
+    the latest bits in the region being mapped which can be a significant
+    performance enhancement.</p>
+<p class="tableblock">    CL_MAP_READ or CL_MAP_WRITE and CL_MAP_WRITE_INVALIDATE_REGION are
+    mutually exclusive.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_image_objects">5.3. Image Objects</h3>
+<div class="paragraph">
+<p>An <em>image</em> object is used to store a one-, two- or three-dimensional
+texture, frame-buffer or image.
+The elements of an image object are selected from a list of predefined image
+formats.
+The minimum number of elements in a memory object is one.</p>
+</div>
+<div class="sect3">
+<h4 id="_creating_image_objects">5.3.1. Creating Image Objects</h4>
+<div class="paragraph">
+<p>A <strong>1D image</strong>, <strong>1D image buffer</strong>, <strong>1D image array</strong>, <strong>2D image</strong>, <strong>2D image
+array</strong> and <strong>3D image object</strong> can be created using the following function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_mem clCreateImage(cl_context context,
+                     cl_mem_flags flags,
+                     <span class="directive">const</span> cl_image_format *image_format,
+                     <span class="directive">const</span> cl_image_desc *image_desc,
+                     <span class="directive">void</span>  *host_ptr,
+                     cl_int *errcode_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><em>context</em> is a valid OpenCL context on which the image object is to be
+created.</p>
+</div>
+<div class="paragraph">
+<p><em>flags</em> is a bit-field that is used to specify allocation and usage
+information about the image memory object being created and is described in
+the <a href="#memory-flags-table">Memory Flags</a> table.</p>
+</div>
+<div class="paragraph">
+<p>For all image types except CL_MEM_OBJECT_IMAGE1D_BUFFER, if value specified
+for <em>flags</em> is 0, the default is used which is CL_MEM_READ_WRITE.</p>
+</div>
+<div class="paragraph">
+<p>For CL_MEM_OBJECT_IMAGE1D_BUFFER image type, or an image created from
+another memory object (image or buffer), if the CL_MEM_READ_WRITE,
+CL_MEM_READ_ONLY or CL_MEM_WRITE_ONLY values are not specified in <em>flags</em>,
+they are inherited from the corresponding memory access qualifers associated
+with <em>mem_object</em>.
+The CL_MEM_USE_HOST_PTR, CL_MEM_ALLOC_HOST_PTR and CL_MEM_COPY_HOST_PTR
+values cannot be specified in <em>flags</em> but are inherited from the
+corresponding memory access qualifiers associated with <em>mem_object</em>.
+If CL_MEM_COPY_HOST_PTR is specified in the memory access qualifier values
+associated with <em>mem_object</em> it does not imply any additional copies when
+the image is created from <em>mem_object</em>.
+If the CL_MEM_HOST_WRITE_ONLY, CL_MEM_HOST_READ_ONLY or
+CL_MEM_HOST_NO_ACCESS values are not specified in <em>flags</em>, they are
+inherited from the corresponding memory access qualifiers associated with
+<em>mem_object</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>image_format</em> is a pointer to a structure that describes format properties
+of the image to be allocated.
+A 1D image buffer or 2D image can be created from a buffer by specifying a
+buffer object in the <em>image_desc&#8594;mem_object</em>.
+A 2D image can be created from another 2D image object by specifying an
+image object in the <em>image_desc</em>&#8594;_mem_object_.
+Refer to <a href="#image-format-descriptor">Image Format Descriptor</a> for a detailed
+description of the image format descriptor.</p>
+</div>
+<div class="paragraph">
+<p><em>image_desc</em> is a pointer to a structure that describes type and dimensions
+of the image to be allocated.
+Refer to <a href="#image-descriptor">Image Descriptor</a> for a detailed description
+of the image descriptor.</p>
+</div>
+<div class="paragraph">
+<p><em>host_ptr</em> is a pointer to the image data that may already be allocated by
+the application.
+It is only used to initialize the image, and can be freed after the call to
+<strong>clCreateImage</strong>.
+Refer to table below for a description of how large the buffer that
+<em>host_ptr</em> points to must be.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top">Image Type</th>
+<th class="tableblock halign-left valign-top">Size of buffer that <em>host_ptr</em> points to</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_OBJECT_IMAGE1D</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≥ image_row_pitch</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_OBJECT_IMAGE1D_BUFFER</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≥ image_row_pitch</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_OBJECT_IMAGE2D</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≥ image_row_pitch × image_height</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_OBJECT_IMAGE3D</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≥ image_slice_pitch × image_depth</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_OBJECT_IMAGE1D_ARRAY</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≥ image_slice_pitch × image_array_size</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_OBJECT_IMAGE2D_ARRAY</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≥ image_slice_pitch × image_array_size</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>For a 3D image or 2D image array, the image data specified by <em>host_ptr</em> is
+stored as a linear sequence of adjacent 2D image slices or 2D images
+respectively.
+Each 2D image is a linear sequence of adjacent scanlines.
+Each scanline is a linear sequence of image elements.</p>
+</div>
+<div class="paragraph">
+<p>For a 2D image, the image data specified by <em>host_ptr</em> is stored as a linear
+sequence of adjacent scanlines.
+Each scanline is a linear sequence of image elements.</p>
+</div>
+<div class="paragraph">
+<p>For a 1D image array, the image data specified by <em>host_ptr</em> is stored as a
+linear sequence of adjacent 1D images.
+Each 1D image is stored as a single scanline which is a linear sequence of
+adjacent elements.</p>
+</div>
+<div class="paragraph">
+<p>For 1D image or 1D image buffer, the image data specified by <em>host_ptr</em> is
+stored as a single scanline which is a linear sequence of adjacent elements.</p>
+</div>
+<div class="paragraph">
+<p>Image elements are stored according to their image format as described in
+<a href="#image-format-descriptor">Image Format Descriptor</a>.</p>
+</div>
+<div class="paragraph">
+<p><em>errcode_ret</em> will return an appropriate error code.
+If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p>
+</div>
+<div class="paragraph">
+<p><strong>clCreateImage</strong> returns a valid non-zero image object created and the
+<em>errcode_ret</em> is set to CL_SUCCESS if the image object is created
+successfully.
+Otherwise, it returns a <code>NULL</code> value with one of the following error values
+returned in <em>errcode_ret</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if values specified in <em>flags</em> are not valid.</p>
+</li>
+<li>
+<p>CL_INVALID_IMAGE_FORMAT_DESCRIPTOR if values specified in <em>image_format</em>
+are not valid or if <em>image_format</em> is <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_IMAGE_FORMAT_DESCRIPTOR if a 2D image is created from a
+buffer and the row pitch and base address alignment does not follow the
+rules described for creating a 2D image from a buffer.</p>
+</li>
+<li>
+<p>CL_INVALID_IMAGE_FORMAT_DESCRIPTOR if a 2D image is created from a 2D
+image object and the rules described above are not followed.</p>
+</li>
+<li>
+<p>CL_INVALID_IMAGE_DESCRIPTOR if values specified in <em>image_desc</em> are not
+valid or if <em>image_desc</em> is <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_IMAGE_SIZE if image dimensions specified in <em>image_desc</em>
+exceed the maximum image dimensions described in the
+<a href="#device-queries-table">Device Queries</a> table for all devices
+in_context_.</p>
+</li>
+<li>
+<p>CL_INVALID_HOST_PTR if <em>host_ptr</em> is <code>NULL</code> and CL_MEM_USE_HOST_PTR or
+CL_MEM_COPY_HOST_PTR are set in <em>flags</em> or if <em>host_ptr</em> is not <code>NULL</code>
+but CL_MEM_COPY_HOST_PTR or CL_MEM_USE_HOST_PTR are not set in <em>flags</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if an image is being created from another memory object
+(buffer or image) under one of the following circumstances: 1)
+<em>mem_object</em> was created with CL_MEM_WRITE_ONLY and <em>flags</em> specifies
+CL_MEM_READ_WRITE or CL_MEM_READ_ONLY, 2) <em>mem_object</em> was created with
+CL_MEM_READ_ONLY and <em>flags</em> specifies CL_MEM_READ_WRITE or
+CL_MEM_WRITE_ONLY, 3) <em>flags</em> specifies CL_MEM_USE_HOST_PTR or
+CL_MEM_ALLOC_HOST_PTR or CL_MEM_COPY_HOST_PTR.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if an image is being created from another memory object
+(buffer or image) and <em>mem_object</em> object was created with
+CL_MEM_HOST_WRITE_ONLY and <em>flags</em> specifies CL_MEM_HOST_READ_ONLY, or
+if <em>mem_object</em> was created with CL_MEM_HOST_READ_ONLY and <em>flags</em>
+specifies CL_MEM_HOST_WRITE_ONLY, or if <em>mem_object</em> was created with
+CL_MEM_HOST_NO_ACCESS and_flags_ specifies CL_MEM_HOST_READ_ONLY or
+CL_MEM_HOST_WRITE_ONLY.</p>
+</li>
+<li>
+<p>CL_IMAGE_FORMAT_NOT_SUPPORTED if the <em>image_format</em> is not supported.</p>
+</li>
+<li>
+<p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate
+memory for image object.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if there are no devices in <em>context</em> that support
+images (i.e. CL_DEVICE_IMAGE_SUPPORT specified in the
+<a href="#device-queries-table">Device Queries</a> table is CL_FALSE).</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="sect4">
+<h5 id="image-format-descriptor">Image Format Descriptor</h5>
+<div class="paragraph">
+<p>The image format descriptor structure is defined as</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="keyword">typedef</span> <span class="keyword">struct</span> cl_image_format {
+    cl_channel_order image_channel_order;
+    cl_channel_type image_channel_data_type;
+} cl_image_format;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><code>image_channel_order</code> specifies the number of channels and the channel
+layout i.e. the memory layout in which channels are stored in the image.
+Valid values are described in the <a href="#image-channel-order-table">Image Channel
+Order</a> table.</p>
+</div>
+<div class="paragraph">
+<p><code>image_channel_data_type</code> describes the size of the channel data type.
+The list of supported values is described in the
+<a href="#image-channel-data-types-table">Image Channel Data Types</a> table.
+The number of bits per element determined by the <code>image_channel_data_type</code>
+and <code>image_channel_order</code> must be a power of two.</p>
+</div>
+<table id="image-channel-order-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 14. List of supported Image Channel Order Values</caption>
+<colgroup>
+<col style="width: 100%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top">Enum values that can be specified in channel_order</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_R</strong>, <strong>CL_Rx</strong> or <strong>CL_A</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_INTENSITY</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_LUMINANCE</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEPTH</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_RG</strong>, <strong>CL_RGx</strong> or <strong>CL_RA</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_RGB</strong> or <strong>CL_RGBx</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_RGBA</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_sRGB</strong>, <strong>CL_sRGBx</strong>, <strong>CL_sRGBA</strong>, or <strong>CL_sBGRA</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_ARGB</strong>, <strong>CL_BGRA</strong>, or <strong>CL_ABGR</strong></p></td>
+</tr>
+</tbody>
+</table>
+<table id="image-channel-data-types-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 15. List of supported Image Channel Data Types</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top">Image Channel Data Type</th>
+<th class="tableblock halign-left valign-top">Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SNORM_INT8</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Each channel component is a normalized signed 8-bit integer value</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SNORM_INT16</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Each channel component is a normalized signed 16-bit integer value</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_UNORM_INT8</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Each channel component is a normalized unsigned 8-bit integer value</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_UNORM_INT16</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Each channel component is a normalized unsigned 16-bit integer value</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_UNORM_SHORT_565</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Represents a normalized 5-6-5 3-channel RGB image.
+    The channel order must be CL_RGB or CL_RGBx.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_UNORM_SHORT_555</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Represents a normalized x-5-5-5 4-channel xRGB image.
+    The channel order must be CL_RGB or CL_RGBx.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_UNORM_INT_101010</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Represents a normalized x-10-10-10 4-channel xRGB image.
+    The channel order must be CL_RGB or CL_RGBx.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_UNORM_INT_101010_2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Represents a normalized 10-10-10-2 four-channel RGBA image.
+    The channel order must be CL_RGBA.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SIGNED_INT8</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Each channel component is an unnormalized signed 8-bit integer value</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SIGNED_INT16</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Each channel component is an unnormalized signed 16-bit integer value</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SIGNED_INT32</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Each channel component is an unnormalized signed 32-bit integer value</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_UNSIGNED_INT8</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Each channel component is an unnormalized unsigned 8-bit integer value</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_UNSIGNED_INT16</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Each channel component is an unnormalized unsigned 16-bit integer value</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_UNSIGNED_INT32</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Each channel component is an unnormalized unsigned 32-bit integer value</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_HALF_FLOAT</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Each channel component is a 16-bit half-float value</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_FLOAT</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Each channel component is a single precision floating-point value</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>For example, to specify a normalized unsigned 8-bit / channel RGBA image,
+<code>image_channel_order</code> = CL_RGBA, and <code>image_channel_data_type</code> =
+CL_UNORM_INT8.
+The memory layout of this image format is described below:</p>
+</div>
+<table class="tableblock frame-all grid-all" style="width: 60%;">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 10%;">
+<col style="width: 10%;">
+<col style="width: 10%;">
+<col style="width: 60%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">R</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">G</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">B</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&#8230;&#8203;</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>with the corresponding byte offsets</p>
+</div>
+<table class="tableblock frame-all grid-all" style="width: 60%;">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 10%;">
+<col style="width: 10%;">
+<col style="width: 10%;">
+<col style="width: 60%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">1</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">2</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">3</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&#8230;&#8203;</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>Similar, if <code>image_channel_order</code> = CL_RGBA and <code>image_channel_data_type</code> =
+CL_SIGNED_INT16, the memory layout of this image format is described below:</p>
+</div>
+<table class="tableblock frame-all grid-all" style="width: 60%;">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 10%;">
+<col style="width: 10%;">
+<col style="width: 10%;">
+<col style="width: 60%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">R</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">G</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">B</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&#8230;&#8203;</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>with the corresponding byte offsets</p>
+</div>
+<table class="tableblock frame-all grid-all" style="width: 60%;">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 10%;">
+<col style="width: 10%;">
+<col style="width: 10%;">
+<col style="width: 60%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">2</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">4</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">6</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&#8230;&#8203;</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p><code>image_channel_data_type</code> values of CL_UNORM_SHORT_565, CL_UNORM_SHORT_555,
+CL_UNORM_INT_101010 and CL_UNORM_INT_101010_2 are special cases of packed
+image formats where the channels of each element are packed into a single
+unsigned short or unsigned int.
+For these special packed image formats, the channels are normally packed
+with the first channel in the most significant bits of the bitfield, and
+successive channels occupying progressively less significant locations.
+For CL_UNORM_SHORT_565, R is in bits 15:11, G is in bits 10:5 and B is in
+bits 4:0.
+For CL_UNORM_SHORT_555, bit 15 is undefined, R is in bits 14:10, G in bits
+9:5 and B in bits 4:0.
+For CL_UNORM_INT_101010, bits 31:30 are undefined, R is in bits 29:20, G in
+bits 19:10 and B in bits 9:0.
+For CL_UNORM_INT_101010_2, R is in bits 31:22, G in bits 21:12, B in bits
+11:2 and A in bits 1:0.</p>
+</div>
+<div class="paragraph">
+<p>OpenCL implementations must maintain the minimum precision specified by the
+number of bits in <code>image_channel_data_type</code>.
+If the image format specified by <code>image_channel_order</code>, and
+<code>image_channel_data_type</code> cannot be supported by the OpenCL implementation,
+then the call to <strong>clCreateImage</strong> will return a <code>NULL</code> memory object.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="image-descriptor">Image Descriptor</h5>
+<div class="paragraph">
+<p>The image descriptor structure describes the type and dimensions of the
+image or image array and is defined as:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="keyword">typedef</span> <span class="keyword">struct</span> cl_image_desc {
+    cl_mem_object_type image_type,
+    size_t image_width;
+    size_t image_height;
+    size_t image_depth;
+    size_t image_array_size;
+    size_t image_row_pitch;
+    size_t image_slice_pitch;
+    cl_uint num_mip_levels;
+    cl_uint num_samples;
+    cl_mem mem_object;
+} cl_image_desc;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><code>image_type</code> describes the image type and must be either
+CL_MEM_OBJECT_IMAGE1D, CL_MEM_OBJECT_IMAGE1D_BUFFER,
+CL_MEM_OBJECT_IMAGE1D_ARRAY, CL_MEM_OBJECT_IMAGE2D,
+CL_MEM_OBJECT_IMAGE2D_ARRAY or CL_MEM_OBJECT_IMAGE3D.</p>
+</div>
+<div class="paragraph">
+<p><code>image_width</code> is the width of the image in pixels.
+For a 2D image and image array, the image width must be a value ≥ 1 and
+≤ CL_DEVICE_IMAGE2D_MAX_WIDTH.
+For a 3D image, the image width must be a value ≥1 and ≤
+CL_DEVICE_IMAGE3D_MAX_WIDTH.
+For a 1D image buffer, the image width must be a value ≥1 and ≤
+CL_DEVICE_IMAGE_MAX_BUFFER_SIZE.
+For a 1D image and 1D image array, the image width must be a value ≥1
+and ≤ CL_DEVICE_IMAGE2D_MAX_WIDTH.</p>
+</div>
+<div class="paragraph">
+<p><code>image_height</code> is height of the image in pixels.
+This is only used if the image is a 2D or 3D image, or a 2D image array.
+For a 2D image or image array, the image height must be a value ≥ 1 and
+≤ CL_DEVICE_IMAGE2D_MAX_HEIGHT.
+For a 3D image, the image height must be a value ≥ 1 and ≤
+CL_DEVICE_IMAGE3D_MAX_HEIGHT.</p>
+</div>
+<div class="paragraph">
+<p><code>image_depth</code> is the depth of the image in pixels.
+This is only used if the image is a 3D image and must be a value ≥ 1 and
+≤ CL_DEVICE_IMAGE3D_MAX_DEPTH.</p>
+</div>
+<div class="paragraph">
+<p><code>image_array_size</code><sup>5</sup> is the number of images in the image array.
+This is only used if the image is a 1D or 2D image array.
+The values for <code>image_array_size</code>, if specified, must be a value ≥ 1 and
+≤ CL_DEVICE_IMAGE_MAX_ARRAY_SIZE.</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1">5</dt>
+<dd>
+<p>Note that reading and writing 2D image arrays from a kernel with
+<code>image_array_size</code>=1 may be lower performance than 2D images.</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p><code>image_row_pitch</code> is the scan-line pitch in bytes.
+This must be 0 if <em>host_ptr</em> is <code>NULL</code> and can be either 0 or ≥
+<code>image_width</code> × size of element in bytes if <em>host_ptr</em> is not <code>NULL</code>.
+If <em>host_ptr</em> is not <code>NULL</code> and <code>image_row_pitch</code> = 0, <code>image_row_pitch</code> is
+calculated as <code>image_width</code> × size of element in bytes.
+If <code>image_row_pitch</code> is not 0, it must be a multiple of the image element
+size in bytes.
+For a 2D image created from a buffer, the pitch specified (or computed if
+pitch specified is 0) must be a multiple of the maximum of the
+CL_DEVICE_IMAGE_PITCH_ALIGNMENT value for all devices in the context
+associated with <code>image_desc</code>&#8594;`mem_object` and that support images.</p>
+</div>
+<div class="paragraph">
+<p><code>image_slice_pitch</code> is the size in bytes of each 2D slice in the 3D image or
+the size in bytes of each image in a 1D or 2D image array.
+This must be 0 if <em>host_ptr</em> is <code>NULL</code>.
+If <em>host_ptr</em> is not <code>NULL</code>, <code>image_slice_pitch</code> can be either 0 or ≥
+<code>image_row_pitch</code> × <code>image_height</code> for a 2D image array or 3D image
+and can be either 0 or ≥ <code>image_row_pitch</code> for a 1D image array.
+If <em>host_ptr</em> is not <code>NULL</code> and <code>image_slice_pitch</code> = 0, <code>image_slice_pitch</code>
+is calculated as <code>image_row_pitch</code> × <code>image_height</code> for a 2D image
+array or 3D image and <code>image_row_pitch</code> for a 1D image array.
+If <code>image_slice_pitch</code> is not 0, it must be a multiple of the
+<code>image_row_pitch</code>.</p>
+</div>
+<div class="paragraph">
+<p>num_mip_levels and num_samples must be 0.</p>
+</div>
+<div class="paragraph">
+<p>mem_object may refer to a valid buffer or image memory object.
+mem_object can be a buffer memory object if <code>image_type</code> is
+CL_MEM_OBJECT_IMAGE1D_BUFFER or CL_MEM_OBJECT_IMAGE2D<sup>6</sup>.
+mem_object can be an image object if <code>image_type</code> is
+CL_MEM_OBJECT_IMAGE2D<sup>7</sup>.
+Otherwise it must be <code>NULL</code>.
+The image pixels are taken from the memory objects data store.
+When the contents of the specified memory objects data store are modified,
+those changes are reflected in the contents of the image object and
+vice-versa at corresponding synchronization points.</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1">6</dt>
+<dd>
+<p>To create a 2D image from a buffer object that share the data store
+between the image and buffer object.</p>
+</dd>
+<dt class="hdlist1">7</dt>
+<dd>
+<p>To create an image object from another image object that share the data
+store between these image objects.</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>For a 1D image buffer create from a buffer object, the <code>image_width</code> ×
+size of element in bytes must be ≤ size of the buffer object.
+The image data in the buffer object is stored as a single scanline which is
+a linear sequence of adjacent elements.</p>
+</div>
+<div class="paragraph">
+<p>For a 2D image created from a buffer object, the <code>image_row_pitch</code> ×
+<code>image_height</code> must be ≤ size of the buffer object specified by
+mem_object.
+The image data in the buffer object is stored as a linear sequence of
+adjacent scanlines.
+Each scanline is a linear sequence of image elements padded to
+<code>image_row_pitch</code> bytes.</p>
+</div>
+<div class="paragraph">
+<p>For an image object created from another image object, the values specified
+in the image descriptor except for mem_object must match the image
+descriptor information associated with mem_object.</p>
+</div>
+<div class="paragraph">
+<p>Image elements are stored according to their image format as described in
+<a href="#image-format-descriptor">Image Format Descriptor</a>.</p>
+</div>
+<div class="paragraph">
+<p>If the buffer object specified by mem_object is created with
+CL_MEM_USE_HOST_PTR, the <em>host_ptr</em> specified to <strong>clCreateBuffer</strong> must be
+aligned to the minimum of the <strong>CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT</strong> value
+for all devices in the context associated with the buffer specified by
+mem_object and that support images.</p>
+</div>
+<div class="paragraph">
+<p>Creating a 2D image object from another 2D image object allows users to
+create a new image object that shares the image data store with mem_object
+but views the pixels in the image with a different channel order.
+The restrictions are:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>all the values specified in `image_desc except for mem_object must match
+the image descriptor information associated with mem_object.</p>
+</li>
+<li>
+<p>The <em>`image_desc</em> used for creation of <em>mem_object</em> may not be
+equivalent to image descriptor information associated with mem_object.
+To ensure the values in <em>`image_desc</em> will match one can query
+mem_object for associated information using <strong>clGetImageInfo</strong> function
+described in <a href="#image-object-queries">Image Object Queries</a>.</p>
+</li>
+<li>
+<p>the channel data type specified in <code>image_format</code> must match the channel
+data type associated with mem_object.
+The channel order values<sup>8</sup> supported are:</p>
+<div class="openblock">
+<div class="content">
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><code>image_channel_order</code> specified in <code>image_format</code></th>
+<th class="tableblock halign-left valign-top">image channel order of mem_object</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_sBGRA</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_BGRA</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_BGRA</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_sBGRA</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_sRGBA</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_sRGBA</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_sRGB</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGB</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGB</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_sRGB</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_sRGBx</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBx</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBx</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_sRGBx</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEPTH</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+</li>
+<li>
+<p>the channel order specified must have the same number of channels as the
+channel order of mem_object.</p>
+<div class="dlist">
+<dl>
+<dt class="hdlist1">8</dt>
+<dd>
+<p>This allows developers to create a sRGB view of the image from a linear
+RGB view or vice-versa i.e. the pixels stored in the image can be
+accessed as linear RGB or sRGB values.</p>
+</dd>
+</dl>
+</div>
+</li>
+</ul>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>Concurrent reading from, writing to and copying between both a buffer object
+and 1D image buffer or 2D image object associated with the buffer object is
+undefined.
+Only reading from both a buffer object and 1D image buffer or 2D image
+object associated with the buffer object is defined.</p>
+</div>
+<div class="paragraph">
+<p>Writing to an image created from a buffer and then reading from this buffer
+in a kernel even if appropriate synchronization operations (such as a
+barrier) are performed between the writes and reads is undefined.
+Similarly, writing to the buffer and reading from the image created from
+this buffer with appropriate synchronization between the writes and reads is
+undefined.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_querying_list_of_supported_image_formats">5.3.2. Querying List of Supported Image Formats</h4>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clGetSupportedImageFormats(cl_context context,
+                                    cl_mem_flags flags,
+                                    cl_mem_object_type image_type,
+                                    cl_uint num_entries,
+                                    cl_image_format *image_formats,
+                                    cl_uint *num_image_formats)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>can be used to get the list of image formats supported by an OpenCL
+implementation when the following information about an image memory object
+is specified:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Context</p>
+</li>
+<li>
+<p>Image type 1D, 2D, or 3D image, 1D image buffer, 1D or 2D image array.</p>
+</li>
+<li>
+<p>Image object allocation information</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p><strong>clGetSupportedImageFormats</strong> returns a union of image formats supported by
+all devices in the context.</p>
+</div>
+<div class="paragraph">
+<p><em>context</em> is a valid OpenCL context on which the image object(s) will be
+created.</p>
+</div>
+<div class="paragraph">
+<p><em>flags</em> is a bit-field that is used to specify allocation and usage
+information about the image memory object being queried and is described in
+the <a href="#memory-flags-table">Memory Flags</a> table.
+To get a list of supported image formats that can be read from or written to
+by a kernel, <em>flags</em> must be set to CL_MEM_READ_WRITE (get a list of images
+that can be read from and written to by different kernel instances when
+correctly ordered by event dependencies), CL_MEM_READ_ONLY (list of images
+that can be read from by a kernel) or CL_MEM_WRITE_ONLY (list of images that
+can be written to by a kernel).
+To get a list of supported image formats that can be both read from and
+written to by the same kernel instance, <em>flags</em> must be set to
+CL_MEM_KERNEL_READ_AND_WRITE.
+Please see <a href="#image-format-mapping">Image Format Mapping</a> for clarification.</p>
+</div>
+<div class="paragraph">
+<p><em>image_type</em> describes the image type and must be either
+CL_MEM_OBJECT_IMAGE1D, CL_MEM_OBJECT_IMAGE1D_BUFFER, CL_MEM_OBJECT_IMAGE2D,
+CL_MEM_OBJECT_IMAGE3D, CL_MEM_OBJECT_IMAGE1D_ARRAY or
+CL_MEM_OBJECT_IMAGE2D_ARRAY.</p>
+</div>
+<div class="paragraph">
+<p><em>num_entries</em> specifies the number of entries that can be returned in the
+memory location given by <em>image_formats</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>image_formats</em> is a pointer to a memory location where the list of
+supported image formats are returned.
+Each entry describes a <em>cl_image_format</em> structure supported by the OpenCL
+implementation.
+If <em>image_formats</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<div class="paragraph">
+<p><em>num_image_formats</em> is the actual number of supported image formats for a
+specific <em>context</em> and values specified by <em>flags</em>.
+If <em>num_image_formats</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<div class="paragraph">
+<p><strong>clGetSupportedImageFormats</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>flags</em> or <em>image_type</em> are not valid, or if
+<em>num_entries</em> is 0 and <em>image_formats</em> is not <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If CL_DEVICE_IMAGE_SUPPORT specified in the <a href="#device-queries-table">Device
+Queries</a> table is CL_TRUE, the values assigned to
+CL_DEVICE_MAX_READ_IMAGE_ARGS, CL_DEVICE_MAX_WRITE_IMAGE_ARGS,
+CL_DEVICE_IMAGE2D_MAX_WIDTH, CL_DEVICE_IMAGE2D_MAX_HEIGHT,
+CL_DEVICE_IMAGE3D_MAX_WIDTH, CL_DEVICE_IMAGE3D_MAX_HEIGHT,
+CL_DEVICE_IMAGE3D_MAX_DEPTH and CL_DEVICE_MAX_SAMPLERS by the implementation
+must be greater than or equal to the minimum values specified in the
+<a href="#device-queries-table">Device Queries</a> table.</p>
+</div>
+<div class="sect4">
+<h5 id="_minimum_list_of_supported_image_formats">Minimum List of Supported Image Formats</h5>
+<div class="paragraph">
+<p>For 1D, 1D image from buffer, 2D, 3D image objects, 1D and 2D image array
+objects, the mandated minimum list of image formats that can be read from
+and written to by different kernel instances when correctly ordered by event
+dependencies and that must be supported by all devices that support images
+is described in the <a href="#min-supported-cross-kernel-table">Supported Formats -
+Kernel Read Or Write</a> table.</p>
+</div>
+<table id="min-supported-cross-kernel-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 16. Min. list of supported image formats kernel read or write</caption>
+<colgroup>
+<col style="width: 34%;">
+<col style="width: 33%;">
+<col style="width: 33%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top">num_channels</th>
+<th class="tableblock halign-left valign-top">channel_order</th>
+<th class="tableblock halign-left valign-top">channel_data_type</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">1</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_UNORM_INT8<br>
+        CL_UNORM_INT16<br>
+        CL_SNORM_INT8<br>
+        CL_SNORM_INT16<br>
+        CL_SIGNED_INT8<br>
+        CL_SIGNED_INT16<br>
+        CL_SIGNED_INT32<br>
+        CL_UNSIGNED_INT8<br>
+        CL_UNSIGNED_INT16<br>
+        CL_UNSIGNED_INT32<br>
+        CL_HALF_FLOAT<br>
+        CL_FLOAT</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">1</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEPTH<sup>9</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_UNORM_INT16<br>
+        CL_FLOAT</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">2</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_UNORM_INT8<br>
+        CL_UNORM_INT16<br>
+        CL_SNORM_INT8<br>
+        CL_SNORM_INT16<br>
+        CL_SIGNED_INT8<br>
+        CL_SIGNED_INT16<br>
+        CL_SIGNED_INT32<br>
+        CL_UNSIGNED_INT8<br>
+        CL_UNSIGNED_INT16<br>
+        CL_UNSIGNED_INT32<br>
+        CL_HALF_FLOAT<br>
+        CL_FLOAT</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">4</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_UNORM_INT8<br>
+        CL_UNORM_INT16<br>
+        CL_SNORM_INT8<br>
+        CL_SNORM_INT16<br>
+        CL_SIGNED_INT8<br>
+        CL_SIGNED_INT16<br>
+        CL_SIGNED_INT32<br>
+        CL_UNSIGNED_INT8<br>
+        CL_UNSIGNED_INT16<br>
+        CL_UNSIGNED_INT32<br>
+        CL_HALF_FLOAT<br>
+        CL_FLOAT</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">4</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_BGRA</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_UNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">4</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_sRGBA</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_UNORM_INT8<sup>10</sup></p></td>
+</tr>
+</tbody>
+</table>
+<div class="dlist">
+<dl>
+<dt class="hdlist1">9</dt>
+<dd>
+<p>CL_DEPTH channel order is supported only for 2D image and 2D image array
+objects.</p>
+</dd>
+<dt class="hdlist1">10</dt>
+<dd>
+<p>sRGB channel order support is not required for 1D image buffers.
+Writes to images with sRGB channel orders requires device support of the
+<strong>cl_khr_srgb_image_writes</strong> extension.</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>For 1D, 1D image from buffer, 2D, 3D image objects, 1D and 2D image array
+objects, the mandated minimum list of image formats that can be read from
+and written to by the same kernel instance and that must be supported by all
+devices that support images is described in the
+<a href="#min-supported-same-kernel-table">Supported Formats - Kernel Read And
+Write</a> table.</p>
+</div>
+<table id="min-supported-same-kernel-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 17. Min. list of supported image formats kernel read and write</caption>
+<colgroup>
+<col style="width: 34%;">
+<col style="width: 33%;">
+<col style="width: 33%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top">num_channels</th>
+<th class="tableblock halign-left valign-top">channel_order</th>
+<th class="tableblock halign-left valign-top">channel_data_type</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">1</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_UNORM_INT8<br>
+        CL_SIGNED_INT8<br>
+        CL_SIGNED_INT16<br>
+        CL_SIGNED_INT32<br>
+        CL_UNSIGNED_INT8<br>
+        CL_UNSIGNED_INT16<br>
+        CL_UNSIGNED_INT32<br>
+        CL_HALF_FLOAT<br>
+        CL_FLOAT</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">4</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_UNORM_INT8<br>
+        CL_SIGNED_INT8<br>
+        CL_SIGNED_INT16<br>
+        CL_SIGNED_INT32<br>
+        CL_UNSIGNED_INT8<br>
+        CL_UNSIGNED_INT16<br>
+        CL_UNSIGNED_INT32<br>
+        CL_HALF_FLOAT<br>
+        CL_FLOAT</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect4">
+<h5 id="image-format-mapping">Image format mapping to OpenCL kernel language image access qualifiers</h5>
+<div class="paragraph">
+<p>Image arguments to kernels may have the <code>read_only</code>, <code>write_only</code> or
+<code>read_write</code> qualifier.
+Not all image formats supported by the device and platform are valid to be
+passed to all of these access qualifiers.
+For each access qualifier, only images whose format is in the list of
+formats returned by <strong>clGetSupportedImageFormats</strong> with the given flag
+arguments in the <a href="#image-format-mapping-table">Image Format Mapping</a> table
+are permitted.
+It is not valid to pass an image supporting writing as both a <code>read_only</code>
+image and a <code>write_only</code> image parameter, or to a <code>read_write</code> image
+parameter and any other image parameter.</p>
+</div>
+<table id="image-format-mapping-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 18. Mapping from format flags passed to <strong>clGetSupportedImageFormats</strong> to OpenCL kernel language image access qualifiers</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top">Access Qualifier</th>
+<th class="tableblock halign-left valign-top">cl_mem_flags</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>read_only</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_MEM_READ_ONLY,<br>
+    CL_MEM_READ_WRITE,<br>
+    CL_MEM_KERNEL_READ_AND_WRITE</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>write_only</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_MEM_WRITE_ONLY,<br>
+    CL_MEM_READ_WRITE,<br>
+    CL_MEM_KERNEL_READ_AND_WRITE</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>read_write</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_MEM_KERNEL_READ_AND_WRITE</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_reading_writing_and_copying_image_objects">5.3.3. Reading, Writing and Copying Image Objects</h4>
+<div class="paragraph">
+<p>The following functions enqueue commands to read from an image or image
+array object to host memory or write to an image or image array object from
+host memory.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueReadImage(cl_command_queue command_queue,
+                          cl_mem image,
+                          cl_bool blocking_read,
+                          <span class="directive">const</span> size_t *origin,
+                          <span class="directive">const</span> size_t *region,
+                          size_t row_pitch,
+                          size_t slice_pitch,
+                          <span class="directive">void</span> *ptr,
+                          cl_uint num_events_in_wait_list,
+                          <span class="directive">const</span> cl_event *event_wait_list,
+                          cl_event *event)</code></pre>
+</div>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueWriteImage(cl_command_queue command_queue,
+                           cl_mem image,
+                           cl_bool blocking_write,
+                           <span class="directive">const</span> size_t *origin,
+                           <span class="directive">const</span> size_t *region,
+                           size_t input_row_pitch,
+                           size_t input_slice_pitch,
+                           <span class="directive">const</span> <span class="directive">void</span> *ptr,
+                           cl_uint num_events_in_wait_list,
+                           <span class="directive">const</span> cl_event *event_wait_list,
+                           cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><em>command_queue</em> refers to the host command-queue in which the read / write
+command will be queued.
+<em>command_queue</em> and <em>image</em> must be created with the same OpenCL context.</p>
+</div>
+<div class="paragraph">
+<p><em>image</em> refers to a valid image or image array object.</p>
+</div>
+<div class="paragraph">
+<p><em>blocking_read</em> and <em>blocking_write</em> indicate if the read and write
+operations are <em>blocking</em> or <em>non-blocking</em>.</p>
+</div>
+<div class="paragraph">
+<p>If <em>blocking_read</em> is CL_TRUE i.e. the read command is blocking,
+<strong>clEnqueueReadImage</strong> does not return until the buffer data has been read and
+copied into memory pointed to by <em>ptr</em>.</p>
+</div>
+<div class="paragraph">
+<p>If <em>blocking_read</em> is CL_FALSE i.e. the read command is non-blocking,
+<strong>clEnqueueReadImage</strong> queues a non-blocking read command and returns.
+The contents of the buffer that <em>ptr</em> points to cannot be used until the
+read command has completed.
+The <em>event</em> argument returns an event object which can be used to query the
+execution status of the read command.
+When the read command has completed, the contents of the buffer that <em>ptr</em>
+points to can be used by the application.</p>
+</div>
+<div class="paragraph">
+<p>If <em>blocking_write</em> is CL_TRUE, the OpenCL implementation copies the data
+referred to by <em>ptr</em> and enqueues the write command in the command-queue.
+The memory pointed to by <em>ptr</em> can be reused by the application after the
+<strong>clEnqueueWriteImage</strong> call returns.</p>
+</div>
+<div class="paragraph">
+<p>If <em>blocking_write</em> is CL_FALSE, the OpenCL implementation will use <em>ptr</em> to
+perform a non-blocking write.
+As the write is non-blocking the implementation can return immediately.
+The memory pointed to by <em>ptr</em> cannot be reused by the application after the
+call returns.
+The <em>event</em> argument returns an event object which can be used to query the
+execution status of the write command.
+When the write command has completed, the memory pointed to by <em>ptr</em> can
+then be reused by the application.</p>
+</div>
+<div class="paragraph">
+<p><em>origin</em> defines the (<em>x</em>, <em>y</em>, <em>z</em>) offset in pixels in the 1D, 2D or 3D
+image, the (<em>x</em>, <em>y</em>) offset and the image index in the 2D image array or
+the (<em>x</em>) offset and the image index in the 1D image array.
+If <em>image</em> is a 2D image object, <em>origin</em>[2] must be 0.
+If <em>image</em> is a 1D image or 1D image buffer object, <em>origin</em>[1] and
+<em>origin</em>[2] must be 0.
+If <em>image</em> is a 1D image array object, <em>origin</em>[2] must be 0.
+If <em>image</em> is a 1D image array object, <em>origin</em>[1] describes the image index
+in the 1D image array.
+If <em>image</em> is a 2D image array object, <em>origin</em>[2] describes the image index
+in the 2D image array.</p>
+</div>
+<div class="paragraph">
+<p><em>region</em> defines the (<em>width</em>, <em>height</em>, <em>depth</em>) in pixels of the 1D, 2D or
+3D rectangle, the (<em>width</em>, <em>height</em>) in pixels of the 2D rectangle and the
+number of images of a 2D image array or the (<em>width</em>) in pixels of the 1D
+rectangle and the number of images of a 1D image array.
+If <em>image</em> is a 2D image object, <em>region</em>[2] must be 1.
+If <em>image</em> is a 1D image or 1D image buffer object, <em>region</em>[1] and
+<em>region</em>[2] must be 1.
+If <em>image</em> is a 1D image array object, <em>region</em>[2] must be 1.
+The values in <em>region</em> cannot be 0.</p>
+</div>
+<div class="paragraph">
+<p><em>row_pitch</em> in <strong>clEnqueueReadImage</strong> and <em>input_row_pitch</em> in
+<strong>clEnqueueWriteImage</strong> is the length of each row in bytes.
+This value must be greater than or equal to the element size in bytes
+× <em>width</em>.
+If <em>row_pitch</em> (or <em>input_row_pitch</em>) is set to 0, the appropriate row pitch
+is calculated based on the size of each element in bytes multiplied by
+<em>width</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>slice_pitch</em> in <strong>clEnqueueReadImage</strong> and <em>input_slice_pitch</em> in
+<strong>clEnqueueWriteImage</strong> is the size in bytes of the 2D slice of the 3D region
+of a 3D image or each image of a 1D or 2D image array being read or written
+respectively.
+This must be 0 if <em>image</em> is a 1D or 2D image.
+Otherwise this value must be greater than or equal to <em>row_pitch</em> ×
+<em>height</em>.
+If <em>slice_pitch</em> (or <em>input_slice_pitch</em>) is set to 0, the appropriate slice
+pitch is calculated based on the <em>row_pitch</em> × <em>height</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>ptr</em> is the pointer to a buffer in host memory where image data is to be
+read from or to be written to.
+The alignment requirements for ptr are specified in
+<a href="#alignment-app-data-types">Alignment of Application Data Types</a>.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before this particular command can be executed.
+If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait
+on any event to complete.
+If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event_wait_list</em> act as synchronization points.
+The context associated with events in <em>event_wait_list</em> and <em>command_queue</em>
+must be the same.
+The memory associated with <em>event_wait_list</em> can be reused or freed after
+the function returns.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> returns an event object that identifies this particular read / write
+command and can be used to query or queue a wait for this particular command
+to complete.
+<em>event</em> can be <code>NULL</code> in which case it will not be possible for the
+application to query the status of this command or queue a wait for this
+command to complete.
+If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the
+<em>event</em> argument should not refer to an element of the <em>event_wait_list</em>
+array.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueReadImage</strong> and <strong>clEnqueueWriteImage</strong> return CL_SUCCESS if the
+function is executed successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if the context associated with <em>command_queue</em> and
+<em>image</em> are not the same or if the context associated with
+<em>command_queue</em> and events in <em>event_wait_list</em> are not the same.</p>
+</li>
+<li>
+<p>CL_INVALID_MEM_OBJECT if i_mage_ is not a valid image object.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if the region being read or written specified by
+<em>origin</em> and <em>region</em> is out of bounds or if <em>ptr</em> is a <code>NULL</code> value.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if values in <em>origin</em> and <em>region</em> do not follow rules
+described in the argument description for <em>origin</em> and <em>region</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p>CL_INVALID_IMAGE_SIZE if image dimensions (image width, height,
+specified or compute row and/or slice pitch) for <em>image</em> are not
+supported by device associated with <em>queue</em>.</p>
+</li>
+<li>
+<p>CL_IMAGE_FORMAT_NOT_SUPPORTED if image format (image channel order and
+data type) for <em>image</em> are not supported by device associated with
+<em>queue</em>.</p>
+</li>
+<li>
+<p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate
+memory for data store associated with <em>image</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if the device associated with <em>command_queue</em> does
+not support images (i.e. CL_DEVICE_IMAGE_SUPPORT specified in the
+<a href="#device-queries-table">Device Queries</a> table is CL_FALSE).</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if <strong>clEnqueueReadImage</strong> is called on <em>image</em> which
+has been created with CL_MEM_HOST_WRITE_ONLY or CL_MEM_HOST_NO_ACCESS.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if <strong>clEnqueueWriteImage</strong> is called on <em>image</em> which
+has been created with CL_MEM_HOST_READ_ONLY or CL_MEM_HOST_NO_ACCESS.</p>
+</li>
+<li>
+<p>CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST if the read and write
+operations are blocking and the execution status of any of the events in
+<em>event_wait_list</em> is a negative integer value.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>Calling <strong>clEnqueueReadImage</strong> to read a region of the <em>image</em> with the <em>ptr</em>
+argument value set to <em>host_ptr</em> + (<em>origin</em>[2] × <em>image slice pitch</em>
++  <em>origin</em>[1] × <em>image row pitch</em> + <em>origin</em>[0] × <em>bytes
+per pixel</em>), where <em>host_ptr</em> is a pointer to the memory region specified
+when the <em>image</em> being read is created with CL_MEM_USE_HOST_PTR, must meet
+the following requirements in order to avoid undefined behavior:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>All commands that use this image object have finished execution before
+the read command begins execution.</p>
+</li>
+<li>
+<p>The <em>row_pitch</em> and <em>slice_pitch</em> argument values in
+<strong>clEnqueueReadImage</strong> must be set to the image row pitch and slice pitch.</p>
+</li>
+<li>
+<p>The image object is not mapped.</p>
+</li>
+<li>
+<p>The image object is not used by any command-queue until the read command
+has finished execution.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Calling <strong>clEnqueueWriteImage</strong> to update the latest bits in a region of the
+<em>image</em> with the <em>ptr</em> argument value set to <em>host_ptr</em> + (<em>origin</em>[2]
+× <em>image slice pitch</em> + <em>origin</em>[1] × <em>image row pitch</em> + 
+<em>origin</em>[0] × <em>bytes per pixel</em>), where <em>host_ptr</em> is a pointer to the
+memory region specified when the <em>image</em> being written is created with
+CL_MEM_USE_HOST_PTR, must meet the following requirements in order to avoid
+undefined behavior:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>The host memory region being written contains the latest bits when the
+enqueued write command begins execution.</p>
+</li>
+<li>
+<p>The <em>input_row_pitch</em> and <em>input_slice_pitch</em> argument values in
+<strong>clEnqueueWriteImage</strong> must be set to the image row pitch and slice
+pitch.</p>
+</li>
+<li>
+<p>The image object is not mapped.</p>
+</li>
+<li>
+<p>The image object is not used by any command-queue until the write
+command has finished execution.</p>
+</li>
+</ul>
+</div>
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueCopyImage(cl_command_queue command_queue,
+                          cl_mem src_image,
+                          cl_mem dst_image,
+                          <span class="directive">const</span> size_t *src_origin,
+                          <span class="directive">const</span> size_t *dst_origin,
+                          <span class="directive">const</span> size_t *region,
+                          cl_uint num_events_in_wait_list,
+                          <span class="directive">const</span> cl_event *event_wait_list,
+                          cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>enqueues a command to copy image objects.
+<em>src_image</em> and <em>dst_image</em> can be 1D, 2D, 3D image or a 1D, 2D image array
+objects.
+It is possible to copy subregions between any combinations of source and
+destination types, provided that the dimensions of the subregions are the
+same e.g., one can copy a rectangular region from a 2D image to a slice of a
+3D image.</p>
+</div>
+<div class="paragraph">
+<p><em>command_queue</em> refers to the host command-queue in which the copy command
+will be queued.
+The OpenCL context associated with <em>command_queue</em>, <em>src_image</em> and
+<em>dst_image</em> must be the same.</p>
+</div>
+<div class="paragraph">
+<p><em>src_origin</em> defines the (<em>x</em>, <em>y</em>, <em>z</em>) offset in pixels in the 1D, 2D or
+3D image, the (<em>x</em>, <em>y</em>) offset and the image index in the 2D image array or
+the (<em>x</em>) offset and the image index in the 1D image array.
+If <em>image</em> is a 2D image object, <em>src_origin</em>[2] must be 0.
+If <em>src_image</em> is a 1D image object, <em>src_origin</em>[1] and <em>src_origin</em>[2]
+must be 0.
+If <em>src_image</em> is a 1D image array object, <em>src_origin</em>[2] must be 0.
+If <em>src_image</em> is a 1D image array object, <em>src_origin</em>[1] describes the
+image index in the 1D image array.
+If <em>src_image</em> is a 2D image array object, <em>src_origin</em>[2] describes the
+image index in the 2D image array.</p>
+</div>
+<div class="paragraph">
+<p><em>dst_origin</em> defines the (<em>x</em>, <em>y</em>, <em>z</em>) offset in pixels in the 1D, 2D or
+3D image, the (<em>x</em>, <em>y</em>) offset and the image index in the 2D image array or
+the (<em>x</em>) offset and the image index in the 1D image array.
+If <em>dst_image</em> is a 2D image object, <em>dst_origin</em>[2] must be 0.
+If <em>dst_image</em> is a 1D image or 1D image buffer object, <em>dst_origin</em>[1] and
+<em>dst_origin</em>[2] must be 0.
+If <em>dst_image</em> is a 1D image array object, <em>dst_origin</em>[2] must be 0.
+If <em>dst_image</em> is a 1D image array object, <em>dst_origin</em>[1] describes the
+image index in the 1D image array.
+If <em>dst_image</em> is a 2D image array object, <em>dst_origin</em>[2] describes the
+image index in the 2D image array.</p>
+</div>
+<div class="paragraph">
+<p><em>region</em> defines the (<em>width</em>, <em>height</em>, <em>depth</em>) in pixels of the 1D, 2D or
+3D rectangle, the (<em>width</em>, <em>height</em>) in pixels of the 2D rectangle and the
+number of images of a 2D image array or the (<em>width</em>) in pixels of the 1D
+rectangle and the number of images of a 1D image array.
+If <em>src_image</em> or <em>dst_image</em> is a 2D image object, <em>region</em>[2] must be 1.
+If <em>src_image</em> or <em>dst_image</em> is a 1D image or 1D image buffer object,
+<em>region</em>[1] and <em>region</em>[2] must be 1.
+If <em>src_image</em> or <em>dst_image</em> is a 1D image array object, <em>region</em>[2] must
+be 1.
+The values in <em>region</em> cannot be 0.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before this particular command can be executed.
+If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait
+on any event to complete.
+If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event_wait_list</em> act as synchronization points.
+The context associated with events in <em>event_wait_list</em> and <em>command_queue</em>
+must be the same.
+The memory associated with <em>event_wait_list</em> can be reused or freed after
+the function returns.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> returns an event object that identifies this particular copy command
+and can be used to query or queue a wait for this particular command to
+complete.
+<em>event</em> can be <code>NULL</code> in which case it will not be possible for the
+application to query the status of this command or queue a wait for this
+command to complete.
+<strong>clEnqueueBarrierWithWaitList</strong> can be used instead.
+If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the
+<em>event</em> argument should not refer to an element of the <em>event_wait_list</em>
+array.</p>
+</div>
+<div class="paragraph">
+<p>It is currently a requirement that the <em>src_image</em> and <em>dst_image</em> image
+memory objects for <strong>clEnqueueCopyImage</strong> must have the exact same image
+format (i.e. the cl_image_format descriptor specified when <em>src_image</em> and
+<em>dst_image</em> are created must match).</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueCopyImage</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if the context associated with <em>command_queue</em>,
+<em>src_image</em> and <em>dst_image</em> are not the same or if the context
+associated with <em>command_queue</em> and events in <em>event_wait_list</em> are not
+the same.</p>
+</li>
+<li>
+<p>CL_INVALID_MEM_OBJECT if <em>src_image</em> and <em>dst_image</em> are not valid image
+objects.</p>
+</li>
+<li>
+<p>CL_IMAGE_FORMAT_MISMATCH if <em>src_image</em> and <em>dst_image</em> do not use the
+same image format.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if the 2D or 3D rectangular region specified by
+<em>src_origin</em> and <em>src_origin</em> +  <em>region</em> refers to a region outside
+<em>src_image</em>, or if the 2D or 3D rectangular region specified by
+<em>dst_origin</em> and <em>dst_origin</em> +  <em>region</em> refers to a region outside
+<em>dst_image</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if values in <em>src_origin</em>, <em>dst_origin</em> and <em>region</em> do
+not follow rules described in the argument description for <em>src_origin</em>,
+<em>dst_origin</em> and <em>region</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p>CL_INVALID_IMAGE_SIZE if image dimensions (image width, height,
+specified or compute row and/or slice pitch) for <em>src_image</em> or
+<em>dst_image</em> are not supported by device associated with <em>queue</em>.</p>
+</li>
+<li>
+<p>CL_IMAGE_FORMAT_NOT_SUPPORTED if image format (image channel order and
+data type) for <em>src_image</em> or <em>dst_image</em> are not supported by device
+associated with <em>queue</em>.</p>
+</li>
+<li>
+<p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate
+memory for data store associated with <em>src_image</em> or <em>dst_image</em>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if the device associated with <em>command_queue</em> does
+not support images (i.e. CL_DEVICE_IMAGE_SUPPORT specified in the
+<a href="#device-queries-table">Device Queries</a> table is CL_FALSE).</p>
+</li>
+<li>
+<p>CL_MEM_COPY_OVERLAP if <em>src_image</em> and <em>dst_image</em> are the same image
+object and the source and destination regions overlap.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_filling_image_objects">5.3.4. Filling Image Objects</h4>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueFillImage(cl_command_queue command_queue,
+                           cl_mem image,
+                           <span class="directive">const</span> <span class="directive">void</span> *fill_color,
+                           <span class="directive">const</span> size_t *origin,
+                           <span class="directive">const</span> size_t *region,
+                           cl_uint num_events_in_wait_list,
+                           <span class="directive">const</span> cl_event *event_wait_list,
+                           cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>enqueues a command to fill an image object with a specified color.
+The usage information which indicates whether the memory object can be read
+or written by a kernel and/or the host and is given by the cl_mem_flags
+argument value specified when <em>image</em> is created is ignored by
+<strong>clEnqueueFillImage</strong>.</p>
+</div>
+<div class="paragraph">
+<p><em>command_queue</em> refers to the host command-queue in which the fill command
+will be queued.
+The OpenCL context associated with <em>command_queue</em> and <em>image</em> must be the
+same.</p>
+</div>
+<div class="paragraph">
+<p><em>image</em> is a valid image object.</p>
+</div>
+<div class="paragraph">
+<p><em>fill_color</em> is the color used to fill the image.
+The fill color is a single floating point value if the channel order is
+CL_DEPTH.
+Otherwise, the fill color is a four component RGBA floating-point color
+value if the <em>image</em> channel data type is not an unnormalized signed or
+unsigned integer type, is a four component signed integer value if the
+<em>image</em> channel data type is an unnormalized signed integer type and is a
+four component unsigned integer value if the <em>image</em> channel data type is an
+unnormalized unsigned integer type.
+The fill color will be converted to the appropriate image channel format and
+order associated with <em>image</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>origin</em> defines the (<em>x</em>, <em>y</em>, <em>z</em>) offset in pixels in the 1D, 2D or 3D
+image, the (<em>x</em>, <em>y</em>) offset and the image index in the 2D image array or
+the (<em>x</em>) offset and the image index in the 1D image array.
+If <em>image</em> is a 2D image object, <em>origin</em>[2] must be 0.
+If <em>image</em> is a 1D image or 1D image buffer object, <em>origin</em>[1] and
+<em>origin</em>[2] must be 0.
+If <em>image</em> is a 1D image array object, <em>origin</em>[2] must be 0.
+If <em>image</em> is a 1D image array object, <em>origin</em>[1] describes the image index
+in the 1D image array.
+If <em>image</em> is a 2D image array object, <em>origin</em>[2] describes the image index
+in the 2D image array.</p>
+</div>
+<div class="paragraph">
+<p><em>region</em> defines the (<em>width</em>, <em>height</em>, <em>depth</em>) in pixels of the 1D, 2D or
+3D rectangle, the (<em>width</em>, <em>height</em>) in pixels of the 2D rectangle and the
+number of images of a 2D image array or the (<em>width</em>) in pixels of the 1D
+rectangle and the number of images of a 1D image array.
+If <em>image</em> is a 2D image object, <em>region</em>[2] must be 1.
+If <em>image</em> is a 1D image or 1D image buffer object, <em>region</em>[1] and
+<em>region</em>[2] must be 1.
+If <em>image</em> is a 1D image array object, <em>region</em>[2] must be 1.
+The values in <em>region</em> cannot be 0.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before this particular command can be executed.
+If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait
+on any event to complete.
+If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event_wait_list</em> act as synchronization points.
+The context associated with events in <em>event_wait_list</em> and <em>command_queue</em>
+must be the same.
+The memory associated with <em>event_wait_list</em> can be reused or freed after
+the function returns.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> returns an event object that identifies this particular command and
+can be used to query or queue a wait for this particular command to
+complete.
+<em>event</em> can be <code>NULL</code> in which case it will not be possible for the
+application to query the status of this command or queue a wait for this
+command to complete.
+<strong>clEnqueueBarrierWithWaitList</strong> can be used instead.
+If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the
+<em>event</em> argument should not refer to an element of the <em>event_wait_list</em>
+array.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueFillImage</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if the context associated with <em>command_queue</em> and
+<em>image</em> are not the same or if the context associated with
+<em>command_queue</em> and events in <em>event_wait_list</em> are not the same.</p>
+</li>
+<li>
+<p>CL_INVALID_MEM_OBJECT if <em>image</em> is not a valid image object.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>fill_color</em> is <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if the region being filled as specified by <em>origin</em> and
+<em>region</em> is out of bounds or if <em>ptr</em> is a <code>NULL</code> value.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if values in <em>origin</em> and <em>region</em> do not follow rules
+described in the argument description for <em>origin</em> and <em>region</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p>CL_INVALID_IMAGE_SIZE if image dimensions (image width, height,
+specified or compute row and/or slice pitch) for <em>image</em> are not
+supported by device associated with <em>queue</em>.</p>
+</li>
+<li>
+<p>CL_IMAGE_FORMAT_NOT_SUPPORTED if image format (image channel order and
+data type) for <em>image</em> are not supported by device associated with
+<em>queue</em>.</p>
+</li>
+<li>
+<p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate
+memory for data store associated with <em>image</em>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_copying_between_image_and_buffer_objects">5.3.5. Copying between Image and Buffer Objects</h4>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueCopyImageToBuffer(cl_command_queue command_queue,
+                                  cl_mem src_image,
+                                  cl_mem dst_buffer,
+                                  <span class="directive">const</span> size_t *src_origin,
+                                  <span class="directive">const</span> size_t *region,
+                                  size_t dst_offset,
+                                  cl_uint num_events_in_wait_list,
+                                  <span class="directive">const</span> cl_event *event_wait_list,
+                                  cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>enqueues a command to copy an image object to a buffer object.</p>
+</div>
+<div class="paragraph">
+<p><em>command_queue</em> must be a valid host command-queue.
+The OpenCL context associated with <em>command_queue</em>, <em>src_image</em> and
+<em>dst_buffer</em> must be the same.</p>
+</div>
+<div class="paragraph">
+<p><em>src_image</em> is a valid image object.</p>
+</div>
+<div class="paragraph">
+<p><em>dst_buffer</em> is a valid buffer object.</p>
+</div>
+<div class="paragraph">
+<p><em>src_origin</em> defines the (<em>x</em>, <em>y</em>, <em>z</em>) offset in pixels in the 1D, 2D or
+3D image, the (<em>x</em>, <em>y</em>) offset and the image index in the 2D image array or
+the (<em>x</em>) offset and the image index in the 1D image array.
+If <em>src_image</em> is a 2D image object, <em>src_origin</em>[2] must be 0.
+If <em>src_image</em> is a 1D image or 1D image buffer object, <em>src_origin</em>[1] and
+<em>src_origin</em>[2] must be 0.
+If <em>src_image</em> is a 1D image array object, <em>src_origin</em>[2] must be 0.
+If <em>src_image</em> is a 1D image array object, <em>src_origin</em>[1] describes the
+image index in the 1D image array.
+If <em>src_image</em> is a 2D image array object, <em>src_origin</em>[2] describes the
+image index in the 2D image array.</p>
+</div>
+<div class="paragraph">
+<p><em>region</em> defines the (<em>width</em>, <em>height</em>, <em>depth</em>) in pixels of the 1D, 2D or
+3D rectangle, the (<em>width</em>, <em>height</em>) in pixels of the 2D rectangle and the
+number of images of a 2D image array or the (<em>width</em>) in pixels of the 1D
+rectangle and the number of images of a 1D image array.
+If <em>src_image</em> is a 2D image object, <em>region</em>[2] must be 1.
+If <em>src_image</em> is a 1D image or 1D image buffer object, <em>region</em>[1] and
+<em>region</em>[2] must be 1.
+If <em>src_image</em> is a 1D image array object, <em>region</em>[2] must be 1.
+The values in <em>region</em> cannot be 0.</p>
+</div>
+<div class="paragraph">
+<p><em>dst_offset</em> refers to the offset where to begin copying data into
+<em>dst_buffer</em>.
+The size in bytes of the region to be copied referred to as <em>dst_cb</em> is
+computed as <em>width</em> × <em>height</em> × <em>depth</em> × <em>bytes/image
+element</em> if <em>src_image</em> is a 3D image object, is computed as <em>width</em> ×
+<em>height</em> × <em>bytes/image element</em> if <em>src_image</em> is a 2D image, is
+computed as <em>width</em> × <em>height</em> × <em>arraysize</em> ×
+<em>bytes/image element</em> if <em>src_image</em> is a 2D image array object, is computed
+as <em>width</em> × <em>bytes/image element</em> if <em>src_image</em> is a 1D image or 1D
+image buffer object and is computed as <em>width</em> × <em>arraysize</em> ×
+<em>bytes/image element</em> if <em>src_image</em> is a 1D image array object.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before this particular command can be executed.
+If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait
+on any event to complete.
+If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event_wait_list</em> act as synchronization points.
+The context associated with events in <em>event_wait_list</em> and <em>command_queue</em>
+must be the same.
+The memory associated with <em>event_wait_list</em> can be reused or freed after
+the function returns.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> returns an event object that identifies this particular copy command
+and can be used to query or queue a wait for this particular command to
+complete.
+<em>event</em> can be <code>NULL</code> in which case it will not be possible for the
+application to query the status of this command or queue a wait for this
+command to complete.
+<strong>clEnqueueBarrierWithWaitList</strong> can be used instead.
+If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the
+<em>event</em> argument should not refer to an element of the <em>event_wait_list</em>
+array.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueCopyImageToBuffer</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if the context associated with <em>command_queue</em>,
+<em>src_image</em> and <em>dst_buffer</em> are not the same or if the context
+associated with <em>command_queue</em> and events in <em>event_wait_list</em> are not
+the same.</p>
+</li>
+<li>
+<p>CL_INVALID_MEM_OBJECT if <em>src_image</em> is not a valid image object or
+<em>dst_buffer</em> is not a valid buffer object or if <em>src_image</em> is a 1D
+image buffer object created from <em>dst_buffer</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if the 1D, 2D or 3D rectangular region specified by
+<em>src_origin</em> and <em>src_origin</em> + <em>region</em> refers to a region outside
+<em>src_image</em>, or if the region specified by <em>dst_offset</em> and <em>dst_offset</em>
++ <em>dst_cb</em> to a region outside <em>dst_buffer</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if values in <em>src_origin</em> and <em>region</em> do not follow
+rules described in the argument description for <em>src_origin</em> and
+<em>region</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p>CL_MISALIGNED_SUB_BUFFER_OFFSET if <em>dst_buffer</em> is a sub-buffer object
+and <em>offset</em> specified when the sub-buffer object is created is not
+aligned to CL_DEVICE_MEM_BASE_ADDR_ALIGN value for device associated
+with <em>queue</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_IMAGE_SIZE if image dimensions (image width, height,
+specified or compute row and/or slice pitch) for <em>src_image</em> are not
+supported by device associated with <em>queue</em>.</p>
+</li>
+<li>
+<p>CL_IMAGE_FORMAT_NOT_SUPPORTED if image format (image channel order and
+data type) for <em>src_image</em> are not supported by device associated with
+<em>queue</em>.</p>
+</li>
+<li>
+<p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate
+memory for data store associated with <em>src_image</em> or <em>dst_buffer</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if the device associated with <em>command_queue</em> does
+not support images (i.e. CL_DEVICE_IMAGE_SUPPORT specified in the
+<a href="#device-queries-table">Device Queries</a> table is CL_FALSE).</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueCopyBufferToImage(cl_command_queue command_queue,
+                                  cl_mem src_buffer,
+                                  cl_mem dst_image,
+                                  size_t src_offset,
+                                  <span class="directive">const</span> size_t *dst_origin,
+                                  <span class="directive">const</span> size_t *region,
+                                  cl_uint num_events_in_wait_list,
+                                  <span class="directive">const</span> cl_event *event_wait_list,
+                                  cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>enqueues a command to copy a buffer object to an image object.</p>
+</div>
+<div class="paragraph">
+<p><em>command_queue</em> must be a valid host command-queue.
+The OpenCL context associated with <em>command_queue</em>, <em>src_buffer</em> and
+<em>dst_image</em> must be the same.</p>
+</div>
+<div class="paragraph">
+<p><em>src_buffer</em> is a valid buffer object.</p>
+</div>
+<div class="paragraph">
+<p><em>dst_image</em> is a valid image object.</p>
+</div>
+<div class="paragraph">
+<p><em>src_offset</em> refers to the offset where to begin copying data from
+<em>src_buffer</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>dst_origin</em> defines the (<em>x</em>, <em>y</em>, <em>z</em>) offset in pixels in the 1D, 2D or
+3D image, the (<em>x</em>, <em>y</em>) offset and the image index in the 2D image array or
+the (<em>x</em>) offset and the image index in the 1D image array.
+If <em>dst_image</em> is a 2D image object, <em>dst_origin</em>[2] must be 0.
+If <em>dst_image</em> is a 1D image or 1D image buffer object, <em>dst_origin</em>[1] and
+<em>dst_origin</em>[2] must be 0.
+If <em>dst_image</em> is a 1D image array object, <em>dst_origin</em>[2] must be 0.
+If <em>dst_image</em> is a 1D image array object, <em>dst_origin</em>[1] describes the
+image index in the 1D image array.
+If <em>dst_image</em> is a 2D image array object, <em>dst_origin</em>[2] describes the
+image index in the 2D image array.</p>
+</div>
+<div class="paragraph">
+<p><em>region</em> defines the (<em>width</em>, <em>height</em>, <em>depth</em>) in pixels of the 1D, 2D or
+3D rectangle, the (<em>width</em>, <em>height</em>) in pixels of the 2D rectangle and the
+number of images of a 2D image array or the (<em>width</em>) in pixels of the 1D
+rectangle and the number of images of a 1D image array.
+If <em>dst_image</em> is a 2D image object, <em>region</em>[2] must be 1.
+If <em>dst_image</em> is a 1D image or 1D image buffer object, <em>region</em>[1] and
+<em>region</em>[2] must be 1.
+If <em>dst_image</em> is a 1D image array object, <em>region</em>[2] must be 1.
+The values in <em>region</em> cannot be 0.</p>
+</div>
+<div class="paragraph">
+<p>The size in bytes of the region to be copied from <em>src_buffer</em> referred to
+as <em>src_cb</em> is computed as <em>width</em> × <em>height</em> × <em>depth</em> ×
+<em>bytes/image element</em> if <em>dst_image</em> is a 3D image object, is computed as
+<em>width</em> × <em>height</em> × <em>bytes/image element</em> if <em>dst_image</em> is a
+2D image, is computed as <em>width</em> × <em>height</em> × <em>arraysize</em>
+× <em>bytes/image element</em> if <em>dst_image</em> is a 2D image array object, is
+computed as <em>width</em> × <em>bytes/image element</em> if <em>dst_image</em> is a 1D
+image or 1D image buffer object and is computed as <em>width</em> ×
+<em>arraysize</em> × <em>bytes/image element</em> if <em>dst_image</em> is a 1D image array
+object.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before this particular command can be executed.
+If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait
+on any event to complete.
+If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event_wait_list</em> act as synchronization points.
+The context associated with events in <em>event_wait_list</em> and <em>command_queue</em>
+must be the same.
+The memory associated with <em>event_wait_list</em> can be reused or freed after
+the function returns.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> returns an event object that identifies this particular copy command
+and can be used to query or queue a wait for this particular command to
+complete.
+<em>event</em> can be <code>NULL</code> in which case it will not be possible for the
+application to query the status of this command or queue a wait for this
+command to complete.
+<strong>clEnqueueBarrierWithWaitList</strong> can be used instead.
+If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the
+<em>event</em> argument should not refer to an element of the <em>event_wait_list</em>
+array.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueCopyBufferToImage</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if the context associated with <em>command_queue</em>,
+<em>src_buffer</em> and <em>dst_image</em> are not the same or if the context
+associated with <em>command_queue</em> and events in <em>event_wait_list</em> are not
+the same.</p>
+</li>
+<li>
+<p>CL_INVALID_MEM_OBJECT if <em>src_buffer</em> is not a valid buffer object or
+<em>dst_image</em> is not a valid image object or if <em>dst_image</em> is a 1D image
+buffer object created from <em>src_buffer</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if the 1D, 2D or 3D rectangular region specified by
+<em>dst_origin</em> and <em>dst_origin</em> + <em>region</em> refer to a region outside
+<em>dst_image</em>, or if the region specified by <em>src_offset</em> and <em>src_offset</em>
++ <em>src_cb</em> refer to a region outside <em>src_buffer</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if values in <em>dst_origin</em> and <em>region</em> do not follow
+rules described in the argument description for <em>dst_origin</em> and
+<em>region</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p>CL_MISALIGNED_SUB_BUFFER_OFFSET if <em>src_buffer</em> is a sub-buffer object
+and <em>offset</em> specified when the sub-buffer object is created is not
+aligned to CL_DEVICE_MEM_BASE_ADDR_ALIGN value for device associated
+with <em>queue</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_IMAGE_SIZE if image dimensions (image width, height,
+specified or compute row and/or slice pitch) for <em>dst_image</em> are not
+supported by device associated with <em>queue</em>.</p>
+</li>
+<li>
+<p>CL_IMAGE_FORMAT_NOT_SUPPORTED if image format (image channel order and
+data type) for <em>dst_image</em> are not supported by device associated with
+<em>queue</em>.</p>
+</li>
+<li>
+<p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate
+memory for data store associated with <em>src_buffer</em> or <em>dst_image</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if the device associated with <em>command_queue</em> does
+not support images (i.e. CL_DEVICE_IMAGE_SUPPORT specified in the
+<a href="#device-queries-table">Device Queries</a> table is CL_FALSE).</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mapping_image_objects">5.3.6. Mapping Image Objects</h4>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="directive">void</span> clEnqueueMapImage(cl_command_queue command_queue,
+                       cl_mem image,
+                       cl_bool blocking_map,
+                       cl_map_flags map_flags,
+                       <span class="directive">const</span> size_t *origin,
+                       <span class="directive">const</span> size_t *region,
+                       size_t *image_row_pitch,
+                       size_t *image_slice_pitch,
+                       cl_uint num_events_in_wait_list,
+                       <span class="directive">const</span> cl_event *event_wait_list,
+                       cl_event *event,
+                       cl_int *errcode_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>enqueues a command to map a region in the image object given by <em>image</em> into
+the host address space and returns a pointer to this mapped region.</p>
+</div>
+<div class="paragraph">
+<p><em>command_queue</em> must be a valid host command-queue.</p>
+</div>
+<div class="paragraph">
+<p><em>image</em> is a valid image object.
+The OpenCL context associated with <em>command_queue</em> and <em>image</em> must be the
+same.</p>
+</div>
+<div class="paragraph">
+<p><em>blocking_map</em> indicates if the map operation is <em>blocking</em> or
+<em>non-blocking</em>.</p>
+</div>
+<div class="paragraph">
+<p>If <em>blocking_map</em> is CL_TRUE, <strong>clEnqueueMapImage</strong> does not return until the
+specified region in <em>image</em> is mapped into the host address space and the
+application can access the contents of the mapped region using the pointer
+returned by <strong>clEnqueueMapImage</strong>.</p>
+</div>
+<div class="paragraph">
+<p>If <em>blocking_map</em> is CL_FALSE i.e. map operation is non-blocking, the
+pointer to the mapped region returned by <strong>clEnqueueMapImage</strong> cannot be used
+until the map command has completed.
+The <em>event</em> argument returns an event object which can be used to query the
+execution status of the map command.
+When the map command is completed, the application can access the contents
+of the mapped region using the pointer returned by <strong>clEnqueueMapImage</strong>.</p>
+</div>
+<div class="paragraph">
+<p><em>map_flags</em> is a bit-field and is described in the
+<a href="#memory-map-flags-table">Memory Map Flags</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>origin</em> defines the (<em>x</em>, <em>y</em>, <em>z</em>) offset in pixels in the 1D, 2D or 3D
+image, the (<em>x</em>, <em>y</em>) offset and the image index in the 2D image array or
+the (<em>x</em>) offset and the image index in the 1D image array.
+If <em>image</em> is a 2D image object, <em>origin</em>[2] must be 0.
+If <em>image</em> is a 1D image or 1D image buffer object, <em>origin</em>[1] and
+<em>origin</em>[2] must be 0.
+If <em>image</em> is a 1D image array object, <em>origin</em>[2] must be 0.
+If <em>image</em> is a 1D image array object, <em>origin</em>[1] describes the image index
+in the 1D image array.
+If <em>image</em> is a 2D image array object, <em>origin</em>[2] describes the image index
+in the 2D image array.</p>
+</div>
+<div class="paragraph">
+<p><em>region</em> defines the (<em>width</em>, <em>height</em>, <em>depth</em>) in pixels of the 1D, 2D or
+3D rectangle, the (<em>width</em>, <em>height</em>) in pixels of the 2D rectangle and the
+number of images of a 2D image array or the (<em>width</em>) in pixels of the 1D
+rectangle and the number of images of a 1D image array.
+If <em>image</em> is a 2D image object, <em>region</em>[2] must be 1.
+If <em>image</em> is a 1D image or 1D image buffer object, <em>region</em>[1] and
+<em>region</em>[2] must be 1.
+If <em>image</em> is a 1D image array object, <em>region</em>[2] must be 1.
+The values in <em>region</em> cannot be 0.</p>
+</div>
+<div class="paragraph">
+<p><em>image_row_pitch</em> returns the scan-line pitch in bytes for the mapped
+region.
+This must be a non-<code>NULL</code> value.</p>
+</div>
+<div class="paragraph">
+<p><em>image_slice_pitch</em> returns the size in bytes of each 2D slice of a 3D image
+or the size of each 1D or 2D image in a 1D or 2D image array for the mapped
+region.
+For a 1D and 2D image, zero is returned if this argument is not <code>NULL</code>.
+For a 3D image, 1D and 2D image array, <em>image_slice_pitch</em> must be a
+non-<code>NULL</code> value.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before <strong>clEnqueueMapImage</strong> can be executed.
+If <em>event_wait_list</em> is <code>NULL</code>, then <strong>clEnqueueMapImage</strong> does not wait on
+any event to complete.
+If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event_wait_list</em> act as synchronization points.
+The context associated with events in <em>event_wait_list</em> and <em>command_queue</em>
+must be the same.
+The memory associated with <em>event_wait_list</em> can be reused or freed after
+the function returns.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> returns an event object that identifies this particular command and
+can be used to query or queue a wait for this particular command to
+complete.
+<em>event</em> can be <code>NULL</code> in which case it will not be possible for the
+application to query the status of this command or queue a wait for this
+command to complete.
+If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the
+<em>event</em> argument should not refer to an element of the <em>event_wait_list</em>
+array.</p>
+</div>
+<div class="paragraph">
+<p><em>errcode_ret</em> will return an appropriate error code.
+If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueMapImage</strong> will return a pointer to the mapped region.
+The <em>errcode_ret</em> is set to CL_SUCCESS.</p>
+</div>
+<div class="paragraph">
+<p>A <code>NULL</code> pointer is returned otherwise with one of the following error
+values returned in <em>errcode_ret</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if context associated with <em>command_queue</em> and
+<em>image</em> are not the same or if context associated with <em>command_queue</em>
+and events in <em>event_wait_list</em> are not the same.</p>
+</li>
+<li>
+<p>CL_INVALID_MEM_OBJECT if <em>image</em> is not a valid image object.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if region being mapped given by (<em>origin</em>,
+<em>origin+region</em>) is out of bounds or if values specified in <em>map_flags</em>
+are not valid.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if values in <em>origin</em> and <em>region</em> do not follow rules
+described in the argument description for <em>origin</em> and <em>region</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>image_row_pitch</em> is <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>image</em> is a 3D image, 1D or 2D image array object
+and <em>image_slice_pitch</em> is <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p>CL_INVALID_IMAGE_SIZE if image dimensions (image width, height,
+specified or compute row and/or slice pitch) for <em>image</em> are not
+supported by device associated with <em>queue</em>.</p>
+</li>
+<li>
+<p>CL_IMAGE_FORMAT_NOT_SUPPORTED if image format (image channel order and
+data type) for <em>image</em> are not supported by device associated with
+<em>queue</em>.</p>
+</li>
+<li>
+<p>CL_MAP_FAILURE if there is a failure to map the requested region into
+the host address space.
+This error cannot occur for image objects created with
+CL_MEM_USE_HOST_PTR or CL_MEM_ALLOC_HOST_PTR.</p>
+</li>
+<li>
+<p>CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST if the map operation is
+blocking and the execution status of any of the events in
+<em>event_wait_list</em> is a negative integer value.</p>
+</li>
+<li>
+<p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate
+memory for data store associated with <em>image</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if the device associated with <em>command_queue</em> does
+not support images (i.e. CL_DEVICE_IMAGE_SUPPORT specified in the
+<a href="#device-queries-table">Device Queries</a> table is CL_FALSE).</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if <em>image</em> has been created with
+CL_MEM_HOST_WRITE_ONLY or CL_MEM_HOST_NO_ACCESS and CL_MAP_READ is set
+in <em>map_flags</em> or if <em>image</em> has been created with CL_MEM_HOST_READ_ONLY
+or CL_MEM_HOST_NO_ACCESS and CL_MAP_WRITE or
+CL_MAP_WRITE_INVALIDATE_REGION is set in <em>map_flags</em>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if mapping would lead to overlapping regions being
+mapped for writing.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The pointer returned maps a 1D, 2D or 3D region starting at <em>origin</em> and is
+at least <em>region</em>[0] pixels in size for a 1D image, 1D image buffer or 1D
+image array, (<em>image_row_pitch × region[1])</em> pixels in size for a 2D
+image or 2D image array, and (<em>image_slice_pitch × region[2])</em> pixels
+in size for a 3D image.
+The result of a memory access outside this region is undefined.</p>
+</div>
+<div class="paragraph">
+<p>If the image object is created with CL_MEM_USE_HOST_PTR set in <em>mem_flags</em>,
+the following will be true:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>The <em>host_ptr</em> specified in <strong>clCreateImage</strong> is guaranteed to contain the
+latest bits in the region being mapped when the <strong>clEnqueueMapImage</strong>
+command has completed.</p>
+</li>
+<li>
+<p>The pointer value returned by <strong>clEnqueueMapImage</strong> will be derived from
+the <em>host_ptr</em> specified when the image object is created.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Mapped image objects are unmapped using <strong>clEnqueueUnmapMemObject</strong>.
+This is described in <a href="#unmapping-mapped-memory">Unmapping Mapped Memory
+Objects</a>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="image-object-queries">5.3.7. Image Object Queries</h4>
+<div class="paragraph">
+<p>To get information that is common to all memory objects, use the
+<strong>clGetMemObjectInfo</strong> function described in <a href="#memory-object-queries">Memory
+Object Queries</a>.</p>
+</div>
+<div class="paragraph">
+<p>To get information specific to an image object created with <strong>clCreateImage</strong>,
+use the following function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clGetImageInfo(cl_mem image,
+                      cl_image_info param_name,
+                      size_t param_value_size,
+                      <span class="directive">void</span> *param_value,
+                      size_t *param_value_size_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><em>image</em> specifies the image object being queried.</p>
+</div>
+<div class="paragraph">
+<p><em>param_name</em> specifies the information to query.
+The list of supported <em>param_name</em> types and the information returned in
+<em>param_value</em> by <strong>clGetImageInfo</strong> is described in the
+<a href="#image-info-table">Image Object Queries</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value</em> is a pointer to memory where the appropriate result being
+queried is returned.
+If <em>param_value</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size</em> is used to specify the size in bytes of memory pointed to
+by <em>param_value</em>.
+This size must be ≥ size of return type as described in the
+<a href="#image-info-table">Image Object Queries</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size_ret</em> returns the actual size in bytes of data being
+queried by <em>param_name</em>.
+If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<div class="paragraph">
+<p><strong>clGetImageInfo</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_VALUE if <em>param_name</em> is not valid, or if size in bytes
+specified by <em>param_value_size</em> is &lt; size of return type as described in
+the <a href="#image-info-table">Image Object Queries</a> table and <em>param_value</em> is
+not <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_MEM_OBJECT if <em>image</em> is a not a valid image object.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<table id="image-info-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 19. List of supported param_names by <strong>clGetImageInfo</strong></caption>
+<colgroup>
+<col style="width: 34%;">
+<col style="width: 33%;">
+<col style="width: 33%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_image_info</strong></th>
+<th class="tableblock halign-left valign-top">Return type</th>
+<th class="tableblock halign-left valign-top">Info. returned in <em>param_value</em></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_IMAGE_FORMAT</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_image_format</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return image format descriptor specified when <em>image</em> is created
+        with <strong>clCreateImage</strong>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_IMAGE_ELEMENT_SIZE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return size of each element of the image memory object given by
+        <em>image</em> in bytes.
+        An element is made up of <em>n</em> channels.
+        The value of <em>n</em> is given in <em>cl_image_format</em> descriptor.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_IMAGE_ROW_PITCH</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return calculated row pitch in bytes of a row of elements of the
+        image object given by <em>image</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_IMAGE_SLICE_PITCH</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return calculated slice pitch in bytes of a 2D slice for the 3D
+        image object or size of each image in a 1D or 2D image array given
+        by <em>image</em>.
+        For a 1D image, 1D image buffer and 2D image object return 0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_IMAGE_WIDTH</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return width of the image in pixels.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_IMAGE_HEIGHT</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return height of the image in pixels.
+        For a 1D image, 1D image buffer and 1D image array object, height =
+        0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_IMAGE_DEPTH</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return depth of the image in pixels.
+        For a 1D image, 1D image buffer, 2D image or 1D and 2D image array
+        object, depth = 0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_IMAGE_ARRAY_SIZE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return number of images in the image array.
+        If <em>image</em> is not an image array, 0 is returned.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_IMAGE_NUM_MIP_LEVELS</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return num_mip_levels associated with <em>image</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_IMAGE_NUM_SAMPLES</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return num_samples associated with <em>image</em>.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_pipes">5.4. Pipes</h3>
+<div class="paragraph">
+<p>A <em>pipe</em> is a memory object that stores data organized as a FIFO.
+Pipe objects can only be accessed using built-in functions that read from
+and write to a pipe.
+Pipe objects are not accessible from the host.
+A pipe object encapsulates the following information:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Packet size in bytes</p>
+</li>
+<li>
+<p>Maximum capacity in packets</p>
+</li>
+<li>
+<p>Information about the number of packets currently in the pipe</p>
+</li>
+<li>
+<p>Data packets</p>
+</li>
+</ul>
+</div>
+<div class="sect3">
+<h4 id="_creating_pipe_objects">5.4.1. Creating Pipe Objects</h4>
+<div class="paragraph">
+<p>A <strong>pipe object</strong> is created using the following function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_mem clCreatePipe(cl_context context,
+                    cl_mem_flags flags,
+                    cl_uint pipe_packet_size,
+                    cl_uint pipe_max_packets,
+                    <span class="directive">const</span> cl_pipe_properties *properties,
+                    cl_int *errcode_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><em>context</em> is a valid OpenCL context used to create the pipe object.</p>
+</div>
+<div class="paragraph">
+<p><em>flags</em> is a bit-field that is used to specify allocation and usage
+information such as the memory arena that should be used to allocate the
+pipe object and how it will be used.
+The <a href="#memory-flags">Memory Flags</a> table describes the possible values for
+<em>flags</em>.
+Only CL_MEM_READ_WRITE and CL_MEM_HOST_NO_ACCESS can be specified when
+creating a pipe object.
+If the value specified for <em>flags</em> is 0, the default is used which is
+CL_MEM_READ_WRITE | CL_MEM_HOST_NO_ACCESS.</p>
+</div>
+<div class="paragraph">
+<p><em>pipe_packet_size</em> is the size in bytes of a pipe packet.</p>
+</div>
+<div class="paragraph">
+<p><em>pipe_max_packets</em> specifies the pipe capacity by specifying the maximum
+number of packets the pipe can hold.</p>
+</div>
+<div class="paragraph">
+<p><em>properties</em> specifies a list of properties for the pipe and their
+corresponding values.
+Each property name is immediately followed by the corresponding desired
+value.
+The list is terminated with 0.
+In OpenCL 2.2, <em>properties</em> must be <code>NULL</code>.</p>
+</div>
+<div class="paragraph">
+<p><em>errcode_ret</em> will return an appropriate error code.
+If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p>
+</div>
+<div class="paragraph">
+<p><strong>clCreatePipe</strong> returns a valid non-zero pipe object and <em>errcode_ret</em> is set
+to CL_SUCCESS if the pipe object is created successfully.
+Otherwise, it returns a <code>NULL</code> value with one of the following error values
+returned in <em>errcode_ret</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if values specified in <em>flags</em> are not as defined
+above.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>properties</em> is not <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_PIPE_SIZE if <em>pipe_packet_size</em> is 0 or the
+<em>pipe_packet_size</em> exceeds CL_DEVICE_PIPE_MAX_PACKET_SIZE value
+specified in the <a href="#device-queries-table">Device Queries</a> table for all
+devices in <em>context</em> or if <em>pipe_max_packets</em> is 0.</p>
+</li>
+<li>
+<p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate
+memory for the pipe object.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Pipes follow the same memory consistency model as defined for buffer and
+image objects.
+The pipe state i.e. contents of the pipe across kernel-instances (on the
+same or different devices) is enforced at a synchronization point.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_pipe_object_queries">5.4.2. Pipe Object Queries</h4>
+<div class="paragraph">
+<p>To get information that is common to all memory objects, use the
+<strong>clGetMemObjectInfo</strong> function described in <a href="#memory-object-queries">Memory
+Object Queries</a>.</p>
+</div>
+<div class="paragraph">
+<p>To get information specific to a pipe object created with <strong>clCreatePipe</strong>,
+use the following function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clGetPipeInfo(cl_mem pipe,
+                     cl_pipe_info param_name,
+                     size_t param_value_size,
+                     <span class="directive">void</span> *param_value,
+                     size_t *param_value_size_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><em>pipe</em> specifies the pipe object being queried.</p>
+</div>
+<div class="paragraph">
+<p><em>param_name</em> specifies the information to query.
+The list of supported <em>param_name</em> types and the information returned in
+<em>param_value</em> by <strong>clGetPipeInfo</strong> is described in the <a href="#pipe-info-table">Pipe
+Object Queries</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value</em> is a pointer to memory where the appropriate result being
+queried is returned.
+If <em>param_value</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size</em> is used to specify the size in bytes of memory pointed to
+by <em>param_value</em>.
+This size must be ≥ size of return type as described in the
+<a href="#pipe-info-table">Pipe Object Queries</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size_ret</em> returns the actual size in bytes of data being
+queried by <em>param_name</em>.
+If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<div class="paragraph">
+<p><strong>clGetPipeInfo</strong> returns CL_SUCCESS if the function is executed successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_VALUE if <em>param_name</em> is not valid, or if size in bytes
+specified by <em>param_value_size</em> is &lt; size of return type as described in
+the <a href="#pipe-info-table">Pipe Object Queries</a> table and <em>param_value</em> is
+not <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_MEM_OBJECT if <em>pipe</em> is a not a valid pipe object.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<table id="pipe-info-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 20. List of supported param_names by <strong>clGetPipeInfo</strong></caption>
+<colgroup>
+<col style="width: 34%;">
+<col style="width: 33%;">
+<col style="width: 33%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_pipe_info</strong></th>
+<th class="tableblock halign-left valign-top">Return type</th>
+<th class="tableblock halign-left valign-top">Info. returned in <em>param_value</em></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PIPE_PACKET_SIZE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return pipe packet size specified when <em>pipe</em> is created with
+        <strong>clCreatePipe</strong>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PIPE_MAX_PACKETS</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return max. number of packets specified when <em>pipe</em> is created with
+        <strong>clCreatePipe</strong>.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_querying_unmapping_migrating_retaining_and_releasing_memory_objects">5.5. Querying, Unmapping, Migrating, Retaining and Releasing Memory Objects</h3>
+<div class="sect3">
+<h4 id="_retaining_and_releasing_memory_objects">5.5.1. Retaining and Releasing Memory Objects</h4>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clRetainMemObject(cl_mem memobj)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>increments the <em>memobj</em> reference count.
+<strong>clRetainMemObject</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_MEM_OBJECT if <em>memobj</em> is not a valid memory object (buffer
+or image object).</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p><strong>clCreateBuffer</strong>, <strong>clCreateSubBuffer</strong>, <strong>clCreateImage</strong> and <strong>clCreatePipe</strong>
+perform an implicit retain.</p>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clReleaseMemObject(cl_mem memobj)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>decrements the <em>memobj</em> reference count.
+<strong>clReleaseMemObject</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_MEM_OBJECT if <em>memobj</em> is not a valid memory object.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>After the <em>memobj</em> reference count becomes zero and commands queued for
+execution on a command-queue(s) that use <em>memobj</em> have finished, the memory
+object is deleted.
+If <em>memobj</em> is a buffer object, <em>memobj</em> cannot be deleted until all
+sub-buffer objects associated with <em>memobj</em> are deleted.
+Using this function to release a reference that was not obtained by creating
+the object or by calling <strong>clRetainMemObject</strong> causes undefined behavior.</p>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clSetMemObjectDestructorCallback
+       (cl_mem memobj,
+        <span class="directive">void</span> (CL_CALLBACK *pfn_notify)(cl_mem memobj,<span class="directive">void</span> *user_data),
+        <span class="directive">void</span> *user_data)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>registers a user callback function with a memory object.
+Each call to <strong>clSetMemObjectDestructorCallback</strong> registers the specified user
+callback function on a callback stack associated with <em>memobj</em>.
+The registered user callback functions are called in the reverse order in
+which they were registered.
+The user callback functions are called and then the memory objects resources
+are freed and the memory object is deleted.
+This provides a mechanism for the application (and libraries) using <em>memobj</em>
+to be notified when the memory referenced by <em>host_ptr</em>, specified when the
+memory object is created and used as the storage bits for the memory object,
+can be reused or freed.</p>
+</div>
+<div class="paragraph">
+<p><em>memobj</em> is a valid memory object.</p>
+</div>
+<div class="paragraph">
+<p><em>pfn_notify</em> is the callback function that can be registered by the
+application.
+This callback function may be called asynchronously by the OpenCL
+implementation.
+It is the applications responsibility to ensure that the callback function
+is thread-safe.
+The parameters to this callback function are:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><em>memobj</em> is the memory object being deleted.
+When the user callback is called by the implementation, this memory
+object is not longer valid.
+<em>memobj</em> is only provided for reference purposes.</p>
+</li>
+<li>
+<p><em>user_data</em> is a pointer to user supplied data.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p><em>user_data</em> will be passed as the <em>user_data</em> argument when <em>pfn_notify</em> is
+called.
+<em>user_data</em> can be <code>NULL</code>.</p>
+</div>
+<div class="paragraph">
+<p><strong>clSetMemObjectDestructorCallback</strong> returns CL_SUCCESS if the function is
+executed successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_MEM_OBJECT if <em>memobj</em> is not a valid memory object.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>pfn_notify</em> is <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>When the user callback function is called by the implementation, the
+contents of the memory region pointed to by <em>host_ptr</em> (if the memory object
+is created with CL_MEM_USE_HOST_PTR) are undefined.
+The callback function is typically used by the application to either free or
+reuse the memory region pointed to by <em>host_ptr</em>.</p>
+</div>
+<div class="paragraph">
+<p>The behavior of calling expensive system routines, OpenCL API calls to
+create contexts or command-queues, or blocking OpenCL operations from the
+following list below, in a callback is undefined.</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>clFinish</strong>,</p>
+</li>
+<li>
+<p><strong>clWaitForEvents</strong>,</p>
+</li>
+<li>
+<p>blocking calls to <strong>clEnqueueReadBuffer</strong>, <strong>clEnqueueReadBufferRect</strong>,
+<strong>clEnqueueWriteBuffer</strong>, <strong>clEnqueueWriteBufferRect</strong>,</p>
+</li>
+<li>
+<p>blocking calls to <strong>clEnqueueReadImage</strong> and <strong>clEnqueueWriteImage</strong>,</p>
+</li>
+<li>
+<p>blocking calls to <strong>clEnqueueMapBuffer</strong>, <strong>clEnqueueMapImage</strong>,</p>
+</li>
+<li>
+<p>blocking calls to <strong>clBuildProgram</strong>, <strong>clCompileProgram</strong> or
+<strong>clLinkProgram</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If an application needs to wait for completion of a routine from the above
+list in a callback, please use the non-blocking form of the function, and
+assign a completion callback to it to do the remainder of your work.
+Note that when a callback (or other code) enqueues commands to a
+command-queue, the commands are not required to begin execution until the
+queue is flushed.
+In standard usage, blocking enqueue calls serve this role by implicitly
+flushing the queue.
+Since blocking calls are not permitted in callbacks, those callbacks that
+enqueue commands on a command queue should either call <strong>clFlush</strong> on the
+queue before returning or arrange for <strong>clFlush</strong> to be called later on
+another thread.</p>
+</div>
+<div class="paragraph">
+<p>The user callback function may not call OpenCL APIs with the memory object
+for which the callback function is invoked and for such cases the behavior
+of OpenCL APIs is considered to be undefined.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+</div>
+<div class="sect3">
+<h4 id="unmapping-mapped-memory">5.5.2. Unmapping Mapped Memory Objects</h4>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueUnmapMemObject(cl_command_queue command_queue,
+                               cl_mem memobj,
+                               <span class="directive">void</span> *mapped_ptr,
+                               cl_uint num_events_in_wait_list,
+                               <span class="directive">const</span> cl_event *event_wait_list,
+                               cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>enqueues a command to unmap a previously mapped region of a memory object.
+Reads or writes from the host using the pointer returned by
+<strong>clEnqueueMapBuffer</strong> or <strong>clEnqueueMapImage</strong> are considered to be complete.</p>
+</div>
+<div class="paragraph">
+<p><em>command_queue</em> must be a valid host command-queue.</p>
+</div>
+<div class="paragraph">
+<p><em>memobj</em> is a valid memory (buffer or image) object.
+The OpenCL context associated with <em>command_queue</em> and <em>memobj</em> must be the
+same.</p>
+</div>
+<div class="paragraph">
+<p><em>mapped_ptr</em> is the host address returned by a previous call to
+<strong>clEnqueueMapBuffer</strong>, or <strong>clEnqueueMapImage</strong> for <em>memobj</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before <strong>clEnqueueUnmapMemObject</strong> can be executed.
+If <em>event_wait_list</em> is <code>NULL</code>, then <strong>clEnqueueUnmapMemObject</strong> does not wait
+on any event to complete.
+If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event_wait_list</em> act as synchronization points.
+The context associated with events in <em>event_wait_list</em> and <em>command_queue</em>
+must be the same.
+The memory associated with <em>event_wait_list</em> can be reused or freed after
+the function returns.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> returns an event object that identifies this particular command and
+can be used to query or queue a wait for this particular command to
+complete.
+<em>event</em> can be <code>NULL</code> in which case it will not be possible for the
+application to query the status of this command or queue a wait for this
+command to complete.
+<strong>clEnqueueBarrierWithWaitList</strong> can be used instead.
+If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the
+<em>event</em> argument should not refer to an element of the <em>event_wait_list</em>
+array.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueUnmapMemObject</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_MEM_OBJECT if <em>memobj</em> is not a valid memory object or is a
+pipe object.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>mapped_ptr</em> is not a valid pointer returned by
+<strong>clEnqueueMapBuffer</strong> or <strong>clEnqueueMapImage</strong> for <em>memobj</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or if <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if context associated with <em>command_queue</em> and
+<em>memobj</em> are not the same or if the context associated with
+<em>command_queue</em> and events in <em>event_wait_list</em> are not the same.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueMapBuffer</strong> and <strong>clEnqueueMapImage</strong> increment the mapped count of
+the memory object.
+The initial mapped count value of the memory object is zero.
+Multiple calls to <strong>clEnqueueMapBuffer</strong>, or <strong>clEnqueueMapImage</strong> on the same
+memory object will increment this mapped count by appropriate number of
+calls.
+<strong>clEnqueueUnmapMemObject</strong> decrements the mapped count of the memory object.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueMapBuffer</strong>, and <strong>clEnqueueMapImage</strong> act as synchronization points
+for a region of the buffer object being mapped.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="accessing-mapped-regions">5.5.3. Accessing mapped regions of a memory object</h4>
+<div class="paragraph">
+<p>This section describes the behavior of OpenCL commands that access mapped
+regions of a memory object.</p>
+</div>
+<div class="paragraph">
+<p>The contents of the region of a memory object and associated memory objects
+(sub-buffer objects or 1D image buffer objects that overlap this region)
+mapped for writing (i.e. CL_MAP_WRITE or CL_MAP_WRITE_INVALIDATE_REGION is
+set in <em>map_flags</em> argument to <strong>clEnqueueMapBuffer</strong>, or <strong>clEnqueueMapImage</strong>)
+are considered to be undefined until this region is unmapped.</p>
+</div>
+<div class="paragraph">
+<p>Multiple commands in command-queues can map a region or overlapping regions
+of a memory object and associated memory objects (sub-buffer objects or 1D
+image buffer objects that overlap this region) for reading (i.e. <em>map_flags</em>
+= CL_MAP_READ).
+The contents of the regions of a memory object mapped for reading can also
+be read by kernels and other OpenCL commands (such as <strong>clEnqueueCopyBuffer</strong>)
+executing on a device(s).</p>
+</div>
+<div class="paragraph">
+<p>Mapping (and unmapping) overlapped regions in a memory object and/or
+associated memory objects (sub-buffer objects or 1D image buffer objects
+that overlap this region) for writing is an error and will result in
+CL_INVALID_OPERATION error returned by <strong>clEnqueueMapBuffer</strong>, or
+<strong>clEnqueueMapImage</strong>.</p>
+</div>
+<div class="paragraph">
+<p>If a memory object is currently mapped for writing, the application must
+ensure that the memory object is unmapped before any enqueued kernels or
+commands that read from or write to this memory object or any of its
+associated memory objects (sub-buffer or 1D image buffer objects) or its
+parent object (if the memory object is a sub-buffer or 1D image buffer
+object) begin execution; otherwise the behavior is undefined.</p>
+</div>
+<div class="paragraph">
+<p>If a memory object is currently mapped for reading, the application must
+ensure that the memory object is unmapped before any enqueued kernels or
+commands that write to this memory object or any of its associated memory
+objects (sub-buffer or 1D image buffer objects) or its parent object (if the
+memory object is a sub-buffer or 1D image buffer object) begin execution;
+otherwise the behavior is undefined.</p>
+</div>
+<div class="paragraph">
+<p>A memory object is considered as mapped if there are one or more active
+mappings for the memory object irrespective of whether the mapped regions
+span the entire memory object.</p>
+</div>
+<div class="paragraph">
+<p>Accessing the contents of the memory region referred to by the mapped
+pointer that has been unmapped is undefined.</p>
+</div>
+<div class="paragraph">
+<p>The mapped pointer returned by <strong>clEnqueueMapBuffer</strong> or <strong>clEnqueueMapImage</strong>
+can be used as <em>ptr</em> argument value to <strong>clEnqueue{Read\|Write}Buffer</strong>,
+<strong>clEnqeue{Read\|Write}BufferRect</strong>, <strong>clEnqueue{Read\|Write}Image</strong> provided
+the rules described above are adhered to.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_migrating_memory_objects">5.5.4. Migrating Memory Objects</h4>
+<div class="paragraph">
+<p>This section describes a mechanism for assigning which device an OpenCL
+memory object resides.
+A user may wish to have more explicit control over the location of their
+memory objects on creation.
+This could be used to:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Ensure that an object is allocated on a specific device prior to usage.</p>
+</li>
+<li>
+<p>Preemptively migrate an object from one device to another.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueMigrateMemObjects(cl_command_queue command_queue,
+                                  cl_uint num_mem_objects,
+                                  <span class="directive">const</span> cl_mem *mem_objects,
+                                  cl_mem_migration_flags flags,
+                                  cl_uint num_events_in_wait_list
+                                  <span class="directive">const</span> cl_event *event_wait_list,
+                                  cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>enqueues a command to indicate which device a set of memory objects should
+be associated with.
+Typically, memory objects are implicitly migrated to a device for which
+enqueued commands, using the memory object, are targeted.
+<strong>clEnqueueMigrateMemObjects</strong> allows this migration to be explicitly
+performed ahead of the dependent commands.
+This allows a user to preemptively change the association of a memory
+object, through regular command queue scheduling, in order to prepare for
+another upcoming command.
+This also permits an application to overlap the placement of memory objects
+with other unrelated operations before these memory objects are needed
+potentially hiding transfer latencies.
+Once the event, returned from <strong>clEnqueueMigrateMemObjects</strong>, has been marked
+CL_COMPLETE the memory objects specified in <em>mem_objects</em> have been
+successfully migrated to the device associated with <em>command_queue</em>.
+The migrated memory object shall remain resident on the device until another
+command is enqueued that either implicitly or explicitly migrates it away.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueMigrateMemObjects</strong> can also be used to direct the initial
+placement of a memory object, after creation, possibly avoiding the initial
+overhead of instantiating the object on the first enqueued command to use
+it.</p>
+</div>
+<div class="paragraph">
+<p>The user is responsible for managing the event dependencies, associated with
+this command, in order to avoid overlapping access to memory objects.
+Improperly specified event dependencies passed to
+<strong>clEnqueueMigrateMemObjects</strong> could result in undefined results.</p>
+</div>
+<div class="paragraph">
+<p><em>command_queue</em> is a valid host command-queue.
+The specified set of memory objects in <em>mem_objects</em> will be migrated to the
+OpenCL device associated with <em>command_queue</em> or to the host if the
+CL_MIGRATE_MEM_OBJECT_HOST has been specified.</p>
+</div>
+<div class="paragraph">
+<p><em>num_mem_objects</em> is the number of memory objects specified in
+<em>mem_objects</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>mem_objects</em> is a pointer to a list of memory objects.</p>
+</div>
+<div class="paragraph">
+<p><em>flags</em> is a bit-field that is used to specify migration options.
+The <a href="#migration-flags-table">Memory Migration Flags</a> describes the possible
+values for flags.</p>
+</div>
+<table id="migration-flags-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 21. Supported values for cl_mem_migration_flags</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_mem_migration flags</strong></th>
+<th class="tableblock halign-left valign-top">Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MIGRATE_MEM_OBJECT_HOST</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This flag indicates that the specified set of memory objects are to be
+    migrated to the host, regardless of the target command-queue.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MIGRATE_MEM_OBJECT_CONTENT_UNDEFINED</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This flag indicates that the contents of the set of memory objects are
+    undefined after migration.
+    The specified set of memory objects are migrated to the device
+    associated with <em>command_queue</em> without incurring the overhead of
+    migrating their contents.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before this particular command can be executed.
+If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait
+on any event to complete.
+If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event_wait_list</em> act as synchronization points.
+The context associated with events in <em>event_wait_list</em> and <em>command_queue</em>
+must be the same.
+The memory associated with <em>event_wait_list</em> can be reused or freed after
+the function returns.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> returns an event object that identifies this particular command and
+can be used to query or queue a wait for this particular command to
+complete.
+<em>event</em> can be <code>NULL</code> in which case it will not be possible for the
+application to query the status of this command or queue a wait for this
+command to complete.
+If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the
+<em>event</em> argument should not refer to an element of the <em>event_wait_list</em>
+array.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueMigrateMemObjects</strong> return CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if the context associated with <em>command_queue</em> and
+memory objects in <em>mem_objects</em> are not the same or if the context
+associated with <em>command_queue</em> and events in <em>event_wait_list</em> are not
+the same.</p>
+</li>
+<li>
+<p>CL_INVALID_MEM_OBJECT if any of the memory objects in <em>mem_objects</em> is
+not a valid memory object.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>num_mem_objects</em> is zero or if <em>mem_objects</em> is
+<code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>flags</em> is not 0 or is not any of the values
+described in the table above.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate
+memory for the specified set of memory objects in <em>mem_objects</em>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="memory-object-queries">5.5.5. Memory Object Queries</h4>
+<div class="paragraph">
+<p>To get information that is common to all memory objects (buffer and image
+objects), use the following function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clGetMemObjectInfo(cl_mem memobj,
+                          cl_mem_info param_name,
+                          size_t param_value_size,
+                          <span class="directive">void</span> *param_value,
+                          size_t *param_value_size_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><em>memobj</em> specifies the memory object being queried.</p>
+</div>
+<div class="paragraph">
+<p><em>param_name</em> specifies the information to query.
+The list of supported <em>param_name</em> types and the information returned in
+<em>param_value</em> by <strong>clGetMemObjectInfo</strong> is described in the
+<a href="#mem-info-table">Memory Object Info</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value</em> is a pointer to memory where the appropriate result being
+queried is returned.
+If <em>param_value</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size</em> is used to specify the size in bytes of memory pointed to
+by <em>param_value</em>.
+This size must be ≥ size of return type as described in the
+<a href="#mem-info-table">Memory Object Info</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size_ret</em> returns the actual size in bytes of data being
+queried by <em>param_name</em>.
+If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<div class="paragraph">
+<p><strong>clGetMemObjectInfo</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_VALUE if <em>param_name</em> is not valid, or if size in bytes
+specified by <em>param_value_size</em> is &lt; size of return type as described in
+the <a href="#mem-info-table">Memory Object Info</a> table and <em>param_value</em> is not
+<code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_MEM_OBJECT if <em>memobj</em> is a not a valid memory object.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<table id="mem-info-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 22. List of supported param_names by <strong>clGetMemObjectInfo</strong></caption>
+<colgroup>
+<col style="width: 34%;">
+<col style="width: 33%;">
+<col style="width: 33%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_mem_info</strong></th>
+<th class="tableblock halign-left valign-top">Return type</th>
+<th class="tableblock halign-left valign-top">Info. returned in <em>param_value</em></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_TYPE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_mem_object_type</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns one of the following values:</p>
+<p class="tableblock">        CL_MEM_OBJECT_BUFFER if <em>memobj</em> is created with <strong>clCreateBuffer</strong> or
+        <strong>clCreateSubBuffer</strong>.</p>
+<p class="tableblock">        cl_image_desc.image_type argument value if <em>memobj</em> is created with
+        <strong>clCreateImage</strong>.</p>
+<p class="tableblock">        CL_MEM_OBJECT_PIPE if <em>memobj</em> is created with <strong>clCreatePipe</strong>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_FLAGS</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_mem_flags</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the flags argument value specified when <em>memobj</em> is created
+        with <strong>clCreateBuffer</strong>,<br>
+        <strong>clCreateSubBuffer</strong>,<br>
+        <strong>clCreateImage</strong> or<br>
+        <strong>clCreatePipe</strong>.</p>
+<p class="tableblock">        If <em>memobj</em> is a sub-buffer the memory access qualifiers inherited
+        from parent buffer is also returned.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_SIZE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return actual size of the data store associated with <em>memobj</em> in
+        bytes.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_HOST_PTR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void *</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">If <em>memobj</em> is created with <strong>clCreateBuffer</strong> or <strong>clCreateImage</strong> and
+        CL_MEM_USE_HOST_PTR is specified in mem_flags, return the host_ptr
+        argument value specified when <em>memobj</em> is created.
+        Otherwise a <code>NULL</code> value is returned.</p>
+<p class="tableblock">        If <em>memobj</em> is created with <strong>clCreateSubBuffer</strong>, return the host_ptr
+        +  origin value specified when <em>memobj</em> is created.
+        host_ptr is the argument value specified to <strong>clCreateBuffer</strong> and
+        CL_MEM_USE_HOST_PTR is specified in mem_flags for memory object from
+        which <em>memobj</em> is created.
+        Otherwise a <code>NULL</code> value is returned.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_MAP_COUNT</strong><sup>11</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Map count.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_REFERENCE_COUNT</strong><sup>12</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return <em>memobj</em> reference count.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_CONTEXT</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_context</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return context specified when memory object is created.
+        If <em>memobj</em> is created using <strong>clCreateSubBuffer</strong>, the context
+        associated with the memory object specified as the <em>buffer</em> argument
+        to <strong>clCreateSubBuffer</strong> is returned.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_ASSOCIATED_MEMOBJECT</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_mem</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return memory object from which <em>memobj</em> is created.
+        This returns the memory object specified as buffer argument to
+        <strong>clCreateSubBuffer</strong> if <em>memobj</em> is a subbuffer object created using
+        <strong>clCreateSubBuffer</strong>.</p>
+<p class="tableblock">        This returns the mem_object specified in cl_image_desc if <em>memobj</em>
+        is an image object.</p>
+<p class="tableblock">        Otherwise a <code>NULL</code> value is returned.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_OFFSET</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return offset if <em>memobj</em> is a sub-buffer object created using
+        <strong>clCreateSubBuffer</strong>.</p>
+<p class="tableblock">        This return 0 if <em>memobj</em> is not a subbuffer object.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_USES_SVM_POINTER</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return CL_TRUE if <em>memobj</em> is a buffer object that was created with
+        CL_MEM_USE_HOST_PTR or is a sub-buffer object of a buffer object
+        that was created with CL_MEM_USE_HOST_PTR and the <em>host_ptr</em>
+        specified when the buffer object was created is a SVM pointer;
+        otherwise returns CL_FALSE.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="dlist">
+<dl>
+<dt class="hdlist1">11</dt>
+<dd>
+<p>The map count returned should be considered immediately stale.
+It is unsuitable for general use in applications.
+This feature is provided for debugging.</p>
+</dd>
+<dt class="hdlist1">12</dt>
+<dd>
+<p>The reference count returned should be considered immediately stale.
+It is unsuitable for general use in applications.
+This feature is provided for identifying memory leaks.</p>
+</dd>
+</dl>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_shared_virtual_memory">5.6. Shared Virtual Memory</h3>
+<div class="paragraph">
+<p>OpenCL 2.2 adds support for shared virtual memory (a.k.a.
+SVM).
+SVM allows the host and kernels executing on devices to directly share
+complex, pointer-containing data structures such as trees and linked lists.
+It also eliminates the need to marshal data between the host and devices.
+As a result, SVM substantially simplifies OpenCL programming and may improve
+performance.</p>
+</div>
+<div class="sect3">
+<h4 id="_svm_sharing_granularity_coarse_and_fine_grained_sharing">5.6.1. SVM sharing granularity: coarse- and fine- grained sharing</h4>
+<div class="paragraph">
+<p>OpenCL maintains memory consistency in a coarse-grained fashion in regions
+of buffers.
+We call this coarse-grained sharing.
+Many platforms such as those with integrated CPU-GPU processors and ones
+using the SVM-related PCI-SIG IOMMU services can do better, and can support
+sharing at a granularity smaller than a buffer.
+We call this fine-grained sharing.
+OpenCL 2.0 requires that the host and all OpenCL 2.2 devices support
+coarse-grained sharing at a minimum.</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Coarse-grained sharing: Coarse-grain sharing may be used for memory and
+virtual pointer sharing between multiple devices as well as between the
+host and one or more devices.
+The shared memory region is a memory buffer allocated using
+<strong>clSVMAlloc</strong>.
+Memory consistency is guaranteed at synchronization points and the host
+can use calls to <strong>clEnqueueSVMMap</strong> and <strong>clEnqueueSVMUnmap</strong> or create a
+cl_mem buffer object using the SVM pointer and use OpenCLs existing host
+API functions <strong>clEnqueueMapBuffer</strong> and <strong>clEnqueueUnmapMemObject</strong> to
+update regions of the buffer.
+What coarse-grain buffer SVM adds to OpenCLs earlier buffer support are
+the ability to share virtual memory pointers and a guarantee that
+concurrent access to the same memory allocation from multiple kernels on
+a single device is valid.
+The coarse-grain buffer SVM provides a memory consistency model similar
+to the global memory consistency model described in <em>sections 3.3.1</em> and
+<em>3.4.3</em> of the OpenCL 1.2 specification.
+This memory consistency applies to the regions of buffers being shared
+in a coarse-grained fashion.
+It is enforced at the synchronization points between commands enqueued
+to command queues in a single context with the additional consideration
+that multiple kernels concurrently running on the same device may safely
+share the data.</p>
+</li>
+<li>
+<p>Fine-grained sharing: Shared virtual memory where memory consistency is
+maintained at a granularity smaller than a buffer.
+How fine-grained SVM is used depends on whether the device supports SVM
+atomic operations.</p>
+<div class="ulist">
+<ul>
+<li>
+<p>If SVM atomic operations are supported, they provide memory consistency
+for loads and stores by the host and kernels executing on devices
+supporting SVM.
+This means that the host and devices can concurrently read and update
+the same memory.
+The consistency provided by SVM atomics is in addition to the
+consistency provided at synchronization points.
+There is no need for explicit calls to <strong>clEnqueueSVMMap</strong> and
+<strong>clEnqueueSVMUnmap</strong> or <strong>clEnqueueMapBuffer</strong> and
+<strong>clEnqueueUnmapMemObject</strong> on a cl_mem buffer object created using the
+SVM pointer.</p>
+</li>
+<li>
+<p>If SVM atomic operations are not supported, the host and devices can
+concurrently read the same memory locations and can concurrently update
+non-overlapping memory regions, but attempts to update the same memory
+locations are undefined.
+Memory consistency is guaranteed at synchronization points without the
+need for explicit calls to to <strong>clEnqueueSVMMap</strong> and <strong>clEnqueueSVMUnmap</strong>
+or <strong>clEnqueueMapBuffer</strong> and <strong>clEnqueueUnmapMemObject</strong> on a cl_mem
+buffer object created using the SVM pointer.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p>There are two kinds of fine-grain sharing support.
+Devices may support either fine-grain buffer sharing or fine-grain
+system sharing.</p>
+<div class="ulist">
+<ul>
+<li>
+<p>Fine-grain buffer sharing provides fine-grain SVM only within buffers
+and is an extension of coarse-grain sharing.
+To support fine-grain buffer sharing in an OpenCL context, all devices
+in the context must support CL_DEVICE_SVM_FINE_GRAIN_BUFFER.</p>
+</li>
+<li>
+<p>Fine-grain system sharing enables fine-grain sharing of the hosts
+entire virtual memory, including memory regions allocated by the system
+<strong>malloc</strong> API.
+OpenCL buffer objects are unnecessary and programmers can pass pointers
+allocated using <strong>malloc</strong> to OpenCL kernels.</p>
+</li>
+</ul>
+</div>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>As an illustration of fine-grain SVM using SVM atomic operations to maintain
+memory consistency, consider the following example.
+The host and a set of devices can simultaneously access and update a shared
+work-queue data structure holding work-items to be done.
+The host can use atomic operations to insert new work-items into the queue
+at the same time as the devices using similar atomic operations to remove
+work-items for processing.</p>
+</div>
+<div class="paragraph">
+<p>It is the programmers responsibility to ensure that no host code or
+executing kernels attempt to access a shared memory region after that memory
+is freed.
+We require the SVM implementation to work with either 32- or 64- bit host
+applications subject to the following requirement: the address space size
+must be the same for the host and all OpenCL devices in the context.</p>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="directive">void</span>* clSVMAlloc(cl_context context,
+                 cl_svm_mem_flags flags,
+                 size_t size,
+                 cl_uint alignment)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>allocates a shared virtual memory buffer (referred to as a SVM buffer) that
+can be shared by the host and all devices in an OpenCL context that support
+shared virtual memory.</p>
+</div>
+<div class="paragraph">
+<p><em>context</em> is a valid OpenCL context used to create the SVM buffer.</p>
+</div>
+<div class="paragraph">
+<p><em>flags</em> is a bit-field that is used to specify allocation and usage
+information.
+The <a href="#svm-flags-table">SVM Memory Flags</a> table describes the possible values
+for <em>flags</em>.</p>
+</div>
+<table id="svm-flags-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 23. List of supported cl_svm_mem_flags_ values</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_svm_mem_flags</strong></th>
+<th class="tableblock halign-left valign-top">Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_READ_WRITE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This flag specifies that the SVM buffer will be read and written by a
+    kernel.
+    This is the default.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_WRITE_ONLY</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This flag specifies that the SVM buffer will be written but not read by
+    a kernel.</p>
+<p class="tableblock">    Reading from a SVM buffer created with CL_MEM_WRITE_ONLY inside a kernel
+    is undefined.</p>
+<p class="tableblock">    CL_MEM_READ_WRITE and CL_MEM_WRITE_ONLY are mutually exclusive.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_READ_ONLY</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This flag specifies that the SVM buffer object is a read-only memory
+    object when used inside a kernel.</p>
+<p class="tableblock">    Writing to a SVM buffer created with CL_MEM_READ_ONLY inside a kernel is
+    undefined.</p>
+<p class="tableblock">    CL_MEM_READ_WRITE or CL_MEM_WRITE_ONLY and CL_MEM_READ_ONLY are mutually
+    exclusive.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_SVM_FINE_GRAIN_BUFFER</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This specifies that the application wants the OpenCL implementation to
+    do a fine-grained allocation.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_SVM_ATOMICS</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This flag is valid only if CL_MEM_SVM_FINE_GRAIN_BUFFER is specified in
+    flags.
+    It is used to indicate that SVM atomic operations can control visibility
+    of memory accesses in this SVM buffer.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>If CL_MEM_SVM_FINE_GRAIN_BUFFER is not specified, the buffer can be created
+as a coarse grained SVM allocation.
+Similarly, if CL_MEM_SVM_ATOMICS is not specified, the buffer can be created
+without support for SVM atomic operations (refer to an OpenCL kernel
+language specifications).</p>
+</div>
+<div class="paragraph">
+<p><em>size</em> is the size in bytes of the SVM buffer to be allocated.</p>
+</div>
+<div class="paragraph">
+<p><em>alignment</em> is the minimum alignment in bytes that is required for the newly
+created buffers memory region.
+It must be a power of two up to the largest data type supported by the
+OpenCL device.
+For the full profile, the largest data type is long16.
+For the embedded profile, it is long16 if the device supports 64-bit
+integers; otherwise it is int16.
+If alignment is 0, a default alignment will be used that is equal to the
+size of largest data type supported by the OpenCL implementation.</p>
+</div>
+<div class="paragraph">
+<p><strong>clSVMAlloc</strong> returns a valid non-<code>NULL</code> shared virtual memory address if the
+SVM buffer is successfully allocated.
+Otherwise, like <strong>malloc</strong>, it returns a <code>NULL</code> pointer value.
+<strong>clSVMAlloc</strong> will fail if</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><em>context</em> is not a valid context.</p>
+</li>
+<li>
+<p><em>flags</em> does not contain CL_MEM_SVM_FINE_GRAIN_BUFFER but does contain
+CL_MEM_SVM_ATOMICS.</p>
+</li>
+<li>
+<p>Values specified in <em>flags</em> do not follow rules described for supported
+values in the <a href="#svm-flags-table">SVM Memory Flags</a> table.</p>
+</li>
+<li>
+<p>CL_MEM_SVM_FINE_GRAIN_BUFFER or CL_MEM_SVM_ATOMICS is specified in
+<em>flags</em> and these are not supported by at least one device in <em>context</em>.</p>
+</li>
+<li>
+<p>The values specified in <em>flags</em> are not valid, i.e. don&#8217;t match those
+defined in the <a href="#svm-flags-table">SVM Memory Flags</a> table.</p>
+</li>
+<li>
+<p><em>size</em> is 0 or &gt; CL_DEVICE_MAX_MEM_ALLOC_SIZE value for any device in
+<em>context</em>.</p>
+</li>
+<li>
+<p><em>alignment</em> is not a power of two or the OpenCL implementation cannot
+support the specified alignment for at least one device in <em>context</em>.</p>
+</li>
+<li>
+<p>There was a failure to allocate resources.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Calling <strong>clSVMAlloc</strong> does not itself provide consistency for the shared
+memory region.
+When the host cant use the SVM atomic operations, it must rely on OpenCLs
+guaranteed memory consistency at synchronization points.</p>
+</div>
+<div class="paragraph">
+<p>For SVM to be used efficiently, the host and any devices sharing a buffer
+containing virtual memory pointers should have the same endianness.
+If the context passed to <strong>clSVMAlloc</strong> has devices with mixed endianness and
+the OpenCL implementation is unable to implement SVM because of that mixed
+endianness, <strong>clSVMAlloc</strong> will fail and return <code>NULL</code>.</p>
+</div>
+<div class="paragraph">
+<p>Although SVM is generally not supported for image objects, <strong>clCreateImage</strong>
+may create an image from a buffer (a 1D image from a buffer or a 2D image
+from buffer) if the buffer specified in its image description parameter is a
+SVM buffer.
+Such images have a linear memory representation so their memory can be
+shared using SVM.
+However, fine grained sharing and atomics are not supported for image reads
+and writes in a kernel.</p>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="directive">void</span> clSVMFree(cl_context context,
+               <span class="directive">void</span> *svm_pointer)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>frees a shared virtual memory buffer allocated using <strong>clSVMAlloc</strong>.</p>
+</div>
+<div class="paragraph">
+<p><em>context</em> is a valid OpenCL context used to create the SVM buffer.</p>
+</div>
+<div class="paragraph">
+<p><em>svm_pointer</em> must be the value returned by a call to <strong>clSVMAlloc</strong>.
+If a <code>NULL</code> pointer is passed in <em>svm_pointer</em>, no action occurs.</p>
+</div>
+<div class="paragraph">
+<p>Note that <strong>clSVMFree</strong> does not wait for previously enqueued commands that
+may be using <em>svm_pointer</em> to finish before freeing <em>svm_pointer</em>.
+It is the responsibility of the application to make sure that enqueued
+commands that use <em>svm_pointer</em> have finished before freeing <em>svm_pointer</em>.
+This can be done by enqueuing a blocking operation such as <strong>clFinish</strong>,
+<strong>clWaitForEvents</strong>, <strong>clEnqueueReadBuffer</strong> or by registering a callback with
+the events associated with enqueued commands and when the last enqueued
+comamnd has finished freeing <em>svm_pointer</em>.</p>
+</div>
+<div class="paragraph">
+<p>The behavior of using <em>svm_pointer</em> after it has been freed is undefined.
+In addition, if a buffer object is created using <strong>clCreateBuffer</strong> with
+<em>svm_pointer</em>, the buffer object must first be released before the
+<em>svm_pointer</em> is freed.</p>
+</div>
+<div class="paragraph">
+<p>The <strong>clEnqueueSVMFree</strong> API can also be used to enqueue a callback to free
+the shared virtual memory buffer allocated using <strong>clSVMAlloc</strong> or a shared
+system memory pointer.</p>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueSVMFree(cl_command_queue command_queue,
+                        cl_uint num_svm_pointers,
+                        <span class="directive">void</span> *svm_pointers[],
+                        <span class="directive">void</span> (CL_CALLBACK *pfn_free_func)
+                            (cl_command_queue queue,
+                            cl_uint num_svm_pointers,
+                            <span class="directive">void</span> *svm_pointers[],
+                            <span class="directive">void</span> *user_data),
+                        <span class="directive">void</span> *user_data,
+                        cl_uint num_events_in_wait_list,
+                        <span class="directive">const</span> cl_event *event_wait_list,
+                        cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>enqueues a command to free the shared virtual memory allocated using
+<strong>clSVMAlloc</strong> or a shared system memory pointer.</p>
+</div>
+<div class="paragraph">
+<p><em>command_queue</em> is a valid host command-queue.</p>
+</div>
+<div class="paragraph">
+<p><em>svm_pointers</em> and <em>num_svm_pointers</em> specify shared virtual memory pointers
+to be freed.
+Each pointer in <em>svm_pointers</em> that was allocated using <strong>clSVMAlloc</strong> must
+have been allocated from the same context from which <em>command_queue</em> was
+created.
+The memory associated with <em>svm_pointers</em> can be reused or freed after the
+function returns.</p>
+</div>
+<div class="paragraph">
+<p><em>pfn_free_func</em> specifies the callback function to be called to free the SVM
+pointers.
+<em>pfn_free_func</em> takes four arguments: <em>queue</em> which is the command queue in
+which <strong>clEnqueueSVMFree</strong> was enqueued, the count and list of SVM pointers to
+free and <em>user_data</em> which is a pointer to user specified data.
+If <em>pfn_free_func</em> is <code>NULL</code>, all pointers specified in <em>svm_pointers</em> must
+be allocated using <strong>clSVMAlloc</strong> and the OpenCL implementation will free
+these SVM pointers.
+<em>pfn_free_func</em> must be a valid callback function if any SVM pointer to be
+freed is a shared system memory pointer i.e. not allocated using
+<strong>clSVMAlloc</strong>.
+If <em>pfn_free_func</em> is a valid callback function, the OpenCL implementation
+will call <em>pfn_free_func</em> to free all the SVM pointers specified in
+<em>svm_pointers</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>user_data</em> will be passed as the <em>user_data</em> argument when <em>pfn_free_func</em>
+is called.
+<em>user_data</em> can be <code>NULL</code>.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before <strong>clEnqueueSVMFree</strong> can be executed.
+If <em>event_wait_list</em> is <code>NULL</code>, then <strong>clEnqueueSVMFree</strong> does not wait on any
+event to complete.
+If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event_wait_list</em> act as synchronization points.
+The context associated with events in <em>event_wait_list</em> and <em>command_queue</em>
+must be the same.
+The memory associated with <em>event_wait_list</em> can be reused or freed after
+the function returns.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> returns an event object that identifies this particular command and
+can be used to query or queue a wait for this particular command to
+complete.
+<em>event</em> can be <code>NULL</code> in which case it will not be possible for the
+application to query the status of this command or queue a wait for this
+command to complete.
+If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the
+<em>event</em> argument should not refer to an element of the <em>event_wait_list</em>
+array.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueSVMFree</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>num_svm_pointers</em> is 0 and <em>svm_pointers</em> is
+non-<code>NULL</code>, <em>or</em> if <em>svm_pointers</em> is <code>NULL</code> and <em>num_svm_pointers</em> is
+not 0.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The following function enqueues a command to do a memcpy operation.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueSVMMemcpy(cl_command_queue command_queue,
+                          cl_bool blocking_copy,
+                          <span class="directive">void</span> *dst_ptr,
+                          <span class="directive">const</span> <span class="directive">void</span> *src_ptr,
+                          size_t size,
+                          cl_uint num_events_in_wait_list,
+                          <span class="directive">const</span> cl_event *event_wait_list,
+                          cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><em>command_queue</em> refers to the host command-queue in which the read / write
+command will be queued.
+If either <em>dst_ptr</em> or <em>src_ptr</em> is allocated using <strong>clSVMAlloc</strong> then the
+OpenCL context allocated against must match that of <em>command_queue</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>blocking_copy</em> indicates if the copy operation is <em>blocking</em> or
+<em>non-blocking</em>.</p>
+</div>
+<div class="paragraph">
+<p>If <em>blocking_copy</em> is CL_TRUE i.e. the copy command is blocking,
+<strong>clEnqueueSVMMemcpy</strong> does not return until the buffer data has been copied
+into memory pointed to by <em>dst_ptr</em>.</p>
+</div>
+<div class="paragraph">
+<p>If <em>blocking_copy</em> is CL_FALSE i.e. the copy command is non-blocking,
+<strong>clEnqueueSVMMemcpy</strong> queues a non-blocking copy command and returns.
+The contents of the buffer that <em>dst_ptr</em> points to cannot be used until the
+copy command has completed.
+The <em>event</em> argument returns an event object which can be used to query the
+execution status of the read command.
+When the copy command has completed, the contents of the buffer that
+<em>dst_ptr</em> points to can be used by the application.</p>
+</div>
+<div class="paragraph">
+<p><em>size</em> is the size in bytes of data being copied.</p>
+</div>
+<div class="paragraph">
+<p><em>dst_ptr</em> is the pointer to a host or SVM memory allocation where data is
+copied to.</p>
+</div>
+<div class="paragraph">
+<p><em>src_ptr</em> is the pointer to a host or SVM memory allocation where data is
+copied from.</p>
+</div>
+<div class="paragraph">
+<p>If the memory allocation(s) containing <em>dst_ptr</em> and/or <em>src_ptr</em> are
+allocated using <strong>clSVMAlloc</strong> and either is not allocated from the same
+context from which <em>command_queue</em> was created the behavior is undefined.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before this particular command can be executed.
+If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait
+on any event to complete.
+If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event_wait_list</em> act as synchronization points.
+The context associated with events in <em>event_wait_list</em> and <em>command_queue</em>
+must be the same.
+The memory associated with <em>event_wait_list</em> can be reused or freed after
+the function returns.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> returns an event object that identifies this particular read / write
+command and can be used to query or queue a wait for this particular command
+to complete.
+<em>event</em> can be <code>NULL</code> in which case it will not be possible for the
+application to query the status of this command or queue a wait for this
+command to complete.
+If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the
+<em>event</em> argument should not refer to an element of the <em>event_wait_list</em>
+array.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueSVMMemcpy</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if the context associated with <em>command_queue</em> and
+events in <em>event_wait_list</em> are not the same.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p>CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST if the copy operation is
+blocking and the execution status of any of the events in
+<em>event_wait_list</em> is a negative integer value.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>dst_ptr</em> or <em>src_ptr</em> are <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_MEM_COPY_OVERLAP if the values specified for <em>dst_ptr</em>, <em>src_ptr</em> and
+<em>size</em> result in an overlapping copy.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueSVMMemFill(cl_command_queue command_queue,
+                           <span class="directive">void</span> *svm_ptr,
+                           <span class="directive">const</span> <span class="directive">void</span> *pattern,
+                           size_t pattern_size,
+                           size_t size,
+                           cl_uint num_events_in_wait_list,
+                           <span class="directive">const</span> cl_event *event_wait_list,
+                           cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>enqueues a command to fill a region in memory with a pattern of a given
+pattern size.</p>
+</div>
+<div class="paragraph">
+<p><em>command_queue</em> refers to the host command-queue in which the fill command
+will be queued.
+The OpenCL context associated with <em>command_queue</em> and SVM pointer referred
+to by <em>svm_ptr</em> must be the same.</p>
+</div>
+<div class="paragraph">
+<p><em>svm_ptr</em> is a pointer to a memory region that will be filled with
+<em>pattern</em>.
+It must be aligned to <em>pattern_size</em> bytes.
+If <em>svm_ptr</em> is allocated using <strong>clSVMAlloc</strong> then it must be allocated from
+the same context from which <em>command_queue</em> was created.
+Otherwise the behavior is undefined.</p>
+</div>
+<div class="paragraph">
+<p><em>pattern</em> is a pointer to the data pattern of size <em>pattern_size</em> in bytes.
+<em>pattern</em> will be used to fill a region in <em>buffer</em> starting at <em>svm_ptr</em>
+and is <em>size</em> bytes in size.
+The data pattern must be a scalar or vector integer or floating-point data
+type supported by OpenCL as described in <a href="#scalar-data-types">Shared
+Application Scalar Data Types</a> and <a href="#vector-data-types">Supported
+Application Vector Data Types</a>.
+For example, if region pointed to by <em>svm_ptr</em> is to be filled with a
+pattern of float4 values, then <em>pattern</em> will be a pointer to a cl_float4
+value and <em>pattern_size</em> will be <code>sizeof(cl_float4)</code>.
+The maximum value of <em>pattern_size</em> is the size of the largest integer or
+floating-point vector data type supported by the OpenCL device.
+The memory associated with <em>pattern</em> can be reused or freed after the
+function returns.</p>
+</div>
+<div class="paragraph">
+<p><em>size</em> is the size in bytes of region being filled starting with <em>svm_ptr</em>
+and must be a multiple of <em>pattern_size</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before this particular command can be executed.
+If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait
+on any event to complete.
+If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event_wait_list</em> act as synchronization points.
+The context associated with events in <em>event_wait_list</em> and <em>command_queue</em>
+must be the same.
+The memory associated with <em>event_wait_list</em> can be reused or freed after
+the function returns.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> returns an event object that identifies this particular command and
+can be used to query or queue a wait for this particular command to
+complete.
+<em>event</em> can be <code>NULL</code> in which case it will not be possible for the
+application to query the status of this command or queue a wait for this
+command to complete.
+<strong>clEnqueueBarrierWithWaitList</strong> can be used instead.
+If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the
+<em>event</em> argument should not refer to an element of the <em>event_wait_list</em>
+array.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueSVMMemFill</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if the context associated with <em>command_queue</em> and
+events in <em>event_wait_list</em> are not the same.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>svm_ptr</em> is <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>svm_ptr</em> is not aligned to <em>pattern_size</em> bytes.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>pattern</em> is <code>NULL</code> or if <em>pattern_size</em> is 0 or if
+<em>pattern_size</em> is not one of {1, 2, 4, 8, 16, 32, 64, 128}.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>size</em> is not a multiple of <em>pattern_size</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueSVMMap(cl_command_queue command_queue,
+                       cl_bool blocking_map,
+                       cl_map_flags map_flags,
+                       <span class="directive">void</span> *svm_ptr,
+                       size_t size,
+                       cl_uint num_events_in_wait_list,
+                       <span class="directive">const</span> cl_event *event_wait_list,
+                       cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>enqueues a command that will allow the host to update a region of a SVM
+buffer.
+Note that since we are enqueuing a command with a SVM buffer, the region is
+already mapped in the host address space.</p>
+</div>
+<div class="paragraph">
+<p><em>command_queue</em> must be a valid host command-queue.</p>
+</div>
+<div class="paragraph">
+<p><em>blocking_map</em> indicates if the map operation is <em>blocking</em> or
+<em>non-blocking</em>.</p>
+</div>
+<div class="paragraph">
+<p>If <em>blocking_map</em> is CL_TRUE, <strong>clEnqueueSVMMap</strong> does not return until the
+application can access the contents of the SVM region specified by <em>svm_ptr</em>
+and <em>size</em> on the host.</p>
+</div>
+<div class="paragraph">
+<p>If <em>blocking_map</em> is CL_FALSE i.e. map operation is non-blocking, the region
+specified by <em>svm_ptr</em> and <em>size</em> cannot be used until the map command has
+completed.
+The <em>event</em> argument returns an event object which can be used to query the
+execution status of the map command.
+When the map command is completed, the application can access the contents
+of the region specified by <em>svm_ptr</em> and <em>size</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>map_flags</em> is a bit-field and is described in the
+<a href="#memory-map-flags-table">Memory Map Flags</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>svm_ptr</em> and <em>size</em> are a pointer to a memory region and size in bytes that
+will be updated by the host.
+If <em>svm_ptr</em> is allocated using <strong>clSVMAlloc</strong> then it must be allocated from
+the same context from which <em>command_queue</em> was created.
+Otherwise the behavior is undefined.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before this particular command can be executed.
+If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait
+on any event to complete.
+If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event_wait_list</em> act as synchronization points.
+The context associated with events in <em>event_wait_list</em> and <em>command_queue</em>
+must be the same.
+The memory associated with <em>event_wait_list</em> can be reused or freed after
+the function returns.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> returns an event object that identifies this particular command and
+can be used to query or queue a wait for this particular command to
+complete.
+<em>event</em> can be <code>NULL</code> in which case it will not be possible for the
+application to query the status of this command or queue a wait for this
+command to complete.
+<strong>clEnqueueBarrierWithWaitList</strong> can be used instead.
+If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the
+<em>event</em> argument should not refer to an element of the <em>event_wait_list</em>
+array.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueSVMMap</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if context associated with <em>command_queue</em> and events
+in <em>event_wait_list</em> are not the same.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>svm_ptr</em> is <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>size</em> is 0 or if values specified in <em>map_flags</em>
+are not valid.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p>CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST if the map operation is
+blocking and the execution status of any of the events in
+<em>event_wait_list</em> is a negative integer value.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueSVMUnmap(cl_command_queue command_queue,
+                         <span class="directive">void</span> *svm_ptr,
+                         cl_uint num_events_in_wait_list,
+                         <span class="directive">const</span> cl_event *event_wait_list,
+                         cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>enqueues a command to indicate that the host has completed updating the
+region given by <em>svm_ptr</em> and which was specified in a previous call to
+<strong>clEnqueueSVMMap</strong>.</p>
+</div>
+<div class="paragraph">
+<p><em>command_queue</em> must be a valid host command-queue.</p>
+</div>
+<div class="paragraph">
+<p><em>svm_ptr</em> is a pointer that was specified in a previous call to
+<strong>clEnqueueSVMMap</strong>.
+If <em>svm_ptr</em> is allocated using <strong>clSVMAlloc</strong> then it must be allocated from
+the same context from which <em>command_queue</em> was created.
+Otherwise the behavior is undefined.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before <strong>clEnqueueSVMUnmap</strong> can be executed.
+If <em>event_wait_list</em> is <code>NULL</code>, then <strong>clEnqueueUnmap</strong> does not wait on any
+event to complete.
+If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event_wait_list</em> act as synchronization points.
+The context associated with events in <em>event_wait_list</em> and <em>command_queue</em>
+must be the same.
+The memory associated with <em>event_wait_list</em> can be reused or freed after
+the function returns.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> returns an event object that identifies this particular command and
+can be used to query or queue a wait for this particular command to
+complete.
+<em>event</em> can be <code>NULL</code> in which case it will not be possible for the
+application to query the status of this command or queue a wait for this
+command to complete.
+<strong>clEnqueueBarrierWithWaitList</strong> can be used instead.
+If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the
+<em>event</em> argument should not refer to an element of the <em>event_wait_list</em>
+array.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueSVMUnmap</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if context associated with <em>command_queue</em> and events
+in <em>event_wait_list</em> are not the same.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>svm_ptr</em> is <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or if <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueSVMMap</strong> and <strong>clEnqueueSVMUnmap</strong> act as synchronization points for
+the region of the SVM buffer specified in these calls.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>If a coarse-grained SVM buffer is currently mapped for writing, the
+application must ensure that the SVM buffer is unmapped before any enqueued
+kernels or commands that read from or write to this SVM buffer or any of its
+associated cl_mem buffer objects begin execution; otherwise the behavior is
+undefined.</p>
+</div>
+<div class="paragraph">
+<p>If a coarse-grained SVM buffer is currently mapped for reading, the
+application must ensure that the SVM buffer is unmapped before any enqueued
+kernels or commands that write to this memory object or any of its
+associated cl_mem buffer objects begin execution; otherwise the behavior is
+undefined.</p>
+</div>
+<div class="paragraph">
+<p>A SVM buffer is considered as mapped if there are one or more active
+mappings for the SVM buffer irrespective of whether the mapped regions span
+the entire SVM buffer.</p>
+</div>
+<div class="paragraph">
+<p>The above note does not apply to fine-grained SVM buffers (fine-grained
+buffers allocated using <strong>clSVMAlloc</strong> or fine-grained system allocations).</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueSVMMigrateMem(cl_command_queue command_queue,
+                              cl_uint num_svm_pointers,
+                              <span class="directive">const</span> <span class="directive">void</span> **svm_pointers,
+                              <span class="directive">const</span> size_t *sizes,
+                              cl_mem_migration_flags flags,
+                              cl_uint num_events_in_wait_list,
+                              <span class="directive">const</span> cl_event *event_wait_list,
+                              cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>enqueues a command to indicate which device a set of ranges of SVM
+allocations should be associated with.
+Once the event returned by <strong>clEnqueueSVMMigrateMem</strong> has become CL_COMPLETE,
+the ranges specified by svm pointers and sizes have been successfully
+migrated to the device associated with command queue.</p>
+</div>
+<div class="paragraph">
+<p>The user is responsible for managing the event dependencies associated with
+this command in order to avoid overlapping access to SVM allocations.
+Improperly specified event dependencies passed to <strong>clEnqueueSVMMigrateMem</strong>
+could result in undefined results.</p>
+</div>
+<div class="paragraph">
+<p><em>command_queue</em> is a valid host command queue.
+The specified set of allocation ranges will be migrated to the OpenCL device
+associated with <em>command_queue</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>num_svm_pointers</em> is the number of pointers in the specified <em>svm_pointers</em>
+array, and the number of sizes in the <em>sizes</em> array, if <em>sizes</em> is not
+<code>NULL</code>.</p>
+</div>
+<div class="paragraph">
+<p><em>svm_pointers</em> is a pointer to an array of pointers.
+Each pointer in this array must be within an allocation produced by a call
+to <strong>clSVMAlloc</strong>.</p>
+</div>
+<div class="paragraph">
+<p><em>sizes</em> is an array of sizes.
+The pair <em>svm_pointers</em>[i] and <em>sizes</em>[i] together define the starting
+address and number of bytes in a range to be migrated.
+<em>sizes</em> may be <code>NULL</code> indicating that every allocation containing any
+<em>svm_pointer</em>[i] is to be migrated.
+Also, if <em>sizes</em>[i] is zero, then the entire allocation containing
+<em>svm_pointer</em>[i] is migrated.</p>
+</div>
+<div class="paragraph">
+<p><em>flags</em> is a bit-field that is used to specify migration options.
+The <a href="#migration-flags-table">Memory Migration Flags</a> describes the possible
+values for <em>flags</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before this particular command can be executed.
+If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait
+on any event to complete.
+If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event_wait_list</em> act as synchronization points.
+The context associated with events in <em>event_wait_list</em> and <em>command_queue</em>
+must be the same.
+The memory associated with <em>event_wait_list</em> can be reused or freed after
+the function returns.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> returns an event object that identifies this particular command and
+can be used to query or queue a wait for this particular command to
+complete.
+<em>event</em> can be <code>NULL</code> in which case it will not be possible for the
+application to query the status of this command or queue another command
+that waits for this command to complete.
+If the <em>event_wait_list</em> and <em>event</em> arguments are not <code>NULL</code>, the <em>event</em>
+argument should not refer to an element of the <em>event_wait_list</em> array.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueSVMMigrateMem</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if context associated with <em>command_queue</em> and events
+in <em>event_wait_list</em> are not the same.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>num_svm_pointers</em> is zero or <em>svm_pointers</em> is
+<code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>sizes</em>[i] is non-zero range [<em>svm_pointers</em>[i],
+<em>svm_pointers</em>[i]+<em>sizes</em>[i]) is not contained within an existing
+<strong>clSVMAlloc</strong> allocation.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or if <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_memory_consistency_for_svm_allocations">5.6.2. Memory consistency for SVM allocations</h4>
+<div class="paragraph">
+<p>To ensure memory consistency in SVM allocations, the program can rely on the
+guaranteed memory consistency at synchronization points.
+This consistency support already exists in OpenCL 1.x and can be used for
+coarse-grained SVM allocations or for fine-grained buffer SVM allocations;
+what SVM adds is the ability to share pointers between the host and all SVM
+devices.</p>
+</div>
+<div class="paragraph">
+<p>In addition, sub-buffers can also be used to ensure that each device gets a
+consistent view of a SVM buffers memory when it is shared by multiple
+devices.
+For example, assume that two devices share a SVM pointer.
+The host can create a cl_mem buffer object using <strong>clCreateBuffer</strong> with
+CL_MEM_USE_HOST_PTR and <em>host_ptr</em> set to the SVM pointer and then create
+two disjoint sub-buffers with starting virtual addresses <em>sb1_ptr</em> and
+<em>sb2_ptr</em>.
+These pointers (<em>sb1_ptr</em> and <em>sb2_ptr</em>) can be passed to kernels executing
+on the two devices.
+<strong>clEnqueueMapBuffer</strong> and <strong>clEnqueueUnmapMemObject</strong> and the existing
+<a href="#accessing-mapped-regions">access rules for memory objects</a> ensure
+consistency for buffer regions (<em>sb1_ptr</em> and <em>sb2_ptr</em>) read and written by
+these kernels.</p>
+</div>
+<div class="paragraph">
+<p>When the host and devices are able to use SVM atomic operations (i.e.
+CL_DEVICE_SVM_ATOMICS is set in CL_DEVICE_SVM_CAPABILITIES), these atomic
+operations can be used to provide memory consistency at a fine grain in a
+shared memory region.
+The effect of these operations is visible to the host and all devices with
+which that memory is shared.</p>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_sampler_objects">5.7. Sampler Objects</h3>
+<div class="paragraph">
+<p>A sampler object describes how to sample an image when the image is read in
+the kernel.
+The built-in functions to read from an image in a kernel take a sampler as
+an argument.
+The sampler arguments to the image read function can be sampler objects
+created using OpenCL functions and passed as argument values to the kernel
+or can be samplers declared inside a kernel.
+In this section we discuss how sampler objects are created using OpenCL
+functions.</p>
+</div>
+<div class="sect3">
+<h4 id="_creating_sampler_objects">5.7.1. Creating Sampler Objects</h4>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_sampler clCreateSamplerWithProperties(cl_context context,
+                                         <span class="directive">const</span> cl_sampler_properties *sampler_properties,
+                                         cl_int *errcode_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>creates a sampler object.</p>
+</div>
+<div class="paragraph">
+<p><em>context</em> must be a valid OpenCL context.</p>
+</div>
+<div class="paragraph">
+<p><em>sampler_properties</em> specifies a list of sampler property names and their
+corresponding values.
+Each sampler property name is immediately followed by the corresponding
+desired value.
+The list is terminated with 0.
+The list of supported properties is described in the
+<a href="#sampler-properties-table">Sampler Properties</a> table.
+If a supported property and its value is not specified in
+<em>sampler_properties</em>, its default value will be used.
+<em>sampler_properties</em> can be <code>NULL</code> in which case the default values for
+supported sampler properties will be used.</p>
+</div>
+<table id="sampler-properties-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 24. List of supported cl_sampler_properties values and description</caption>
+<colgroup>
+<col style="width: 34%;">
+<col style="width: 33%;">
+<col style="width: 33%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_sampler_properties</strong> enum</th>
+<th class="tableblock halign-left valign-top">Property Value</th>
+<th class="tableblock halign-left valign-top">Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SAMPLER_NORMALIZED_COORDS</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A boolean value that specifies whether the image coordinates
+        specified are normalized or not.</p>
+<p class="tableblock">        The default value (i.e. the value used if this property is not
+        specified in sampler_properties) is CL_TRUE.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SAMPLER_ADDRESSING_MODE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_addressing_mode</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Specifies how out-of-range image coordinates are handled when
+        reading from an image.</p>
+<p class="tableblock">        Valid values are:</p>
+<p class="tableblock">        CL_ADDRESS_MIRRORED_REPEAT<br>
+        CL_ADDRESS_REPEAT<br>
+        CL_ADDRESS_CLAMP_TO_EDGE<br>
+        CL_ADDRESS_CLAMP<br>
+        CL_ADDRESS_NONE</p>
+<p class="tableblock">        The default is CL_ADDRESS_CLAMP.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SAMPLER_FILTER_MODE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_filter_mode</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Specifies the type of filter that must be applied when reading an
+        image.
+        Valid values are:</p>
+<p class="tableblock">        CL_FILTER_NEAREST<br>
+        CL_FILTER_LINEAR</p>
+<p class="tableblock">        The default value is CL_FILTER_NEAREST.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p><em>errcode_ret</em> will return an appropriate error code.
+If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p>
+</div>
+<div class="paragraph">
+<p><strong>clCreateSamplerWithProperties</strong> returns a valid non-zero sampler object and
+<em>errcode_ret</em> is set to CL_SUCCESS if the sampler object is created
+successfully.
+Otherwise, it returns a <code>NULL</code> value with one of the following error values
+returned in <em>errcode_ret</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if the property name in <em>sampler_properties</em> is not a
+supported property name, if the value specified for a supported property
+name is not valid, or if the same property name is specified more than
+once.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if images are not supported by any device
+associated with <em>context</em> (i.e. CL_DEVICE_IMAGE_SUPPORT specified in the
+<a href="#device-queries-table">Device Queries</a> table is CL_FALSE).</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clRetainSampler(cl_sampler sampler)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>increments the <em>sampler</em> reference count.
+<strong>clCreateSamplerWithProperties</strong> performs an implicit retain.
+<strong>clRetainSampler</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_SAMPLER if <em>sampler</em> is not a valid sampler object.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clReleaseSampler(cl_sampler sampler)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>decrements the <em>sampler</em> reference count.
+The sampler object is deleted after the reference count becomes zero and
+commands queued for execution on a command-queue(s) that use <em>sampler</em> have
+finished.
+<strong>clReleaseSampler</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_SAMPLER if <em>sampler</em> is not a valid sampler object.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Using this function to release a reference that was not obtained by creating
+the object or by calling <strong>clRetainSampler</strong> causes undefined behavior.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_sampler_object_queries">5.7.2. Sampler Object Queries</h4>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clGetSamplerInfo(cl_sampler sampler,
+                        cl_sampler_info param_name,
+                        size_t param_value_size,
+                        <span class="directive">void</span> *param_value,
+                        size_t *param_value_size_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>returns information about the sampler object.</p>
+</div>
+<div class="paragraph">
+<p><em>sampler</em> specifies the sampler being queried.</p>
+</div>
+<div class="paragraph">
+<p><em>param_name</em> specifies the information to query.
+The list of supported <em>param_name</em> types and the information returned in
+<em>param_value</em> by <strong>clGetSamplerInfo</strong> is described in the
+<a href="#sampler-info-table">Sampler Object Queries</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value</em> is a pointer to memory where the appropriate result being
+queried is returned.
+If <em>param_value</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size</em> is used to specify the size in bytes of memory pointed to
+by <em>param_value</em>.
+This size must be ≥ size of return type as described in the
+<a href="#sampler-info-table">Sampler Object Queries</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size_ret</em> returns the actual size in bytes of data being
+queried by <em>param_name</em>.
+If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<table id="sampler-info-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 25. <strong>clGetSamplerInfo</strong> parameter queries</caption>
+<colgroup>
+<col style="width: 34%;">
+<col style="width: 33%;">
+<col style="width: 33%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_sampler_info</strong></th>
+<th class="tableblock halign-left valign-top">Return Type</th>
+<th class="tableblock halign-left valign-top">Info. returned in <em>param_value</em></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SAMPLER_REFERENCE_COUNT</strong><sup>13</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the <em>sampler</em> reference count.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SAMPLER_CONTEXT</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_context</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the context specified when the sampler is created.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SAMPLER_NORMALIZED_COORDS</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the normalized coords value associated with <em>sampler</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SAMPLER_ADDRESSING_MODE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_addressing_mode</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the addressing mode value associated with <em>sampler</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SAMPLER_FILTER_MODE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_filter_mode</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the filter mode value associated with <em>sampler</em>.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="dlist">
+<dl>
+<dt class="hdlist1">13</dt>
+<dd>
+<p>The reference count returned should be considered immediately stale.
+It is unsuitable for general use in applications.
+This feature is provided for identifying memory leaks.</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p><strong>clGetSamplerInfo</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_VALUE if <em>param_name</em> is not valid, or if size in bytes
+specified by <em>param_value_size</em> is &lt; size of return type as described in
+the <a href="#sampler-info-table">Sampler Object Queries</a> table and
+<em>param_value</em> is not <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_SAMPLER if <em>sampler</em> is a not a valid sampler object.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_program_objects">5.8. Program Objects</h3>
+<div class="paragraph">
+<p>An OpenCL program consists of a set of kernels that are identified as
+functions declared with the <code>__kernel</code> qualifier in the program source.
+OpenCL programs may also contain auxiliary functions and constant data that
+can be used by <code>__kernel</code> functions.
+The program executable can be generated <em>online</em> or <em>offline</em> by the OpenCL
+compiler for the appropriate target device(s).</p>
+</div>
+<div class="paragraph">
+<p>A program object encapsulates the following information:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>An associated context.</p>
+</li>
+<li>
+<p>A program source or binary.</p>
+</li>
+<li>
+<p>The latest successfully built program executable, library or compiled
+binary, the list of devices for which the program executable, library or
+compiled binary is built, the build options used and a build log.</p>
+</li>
+<li>
+<p>The number of kernel objects currently attached.</p>
+</li>
+</ul>
+</div>
+<div class="sect3">
+<h4 id="_creating_program_objects">5.8.1. Creating Program Objects</h4>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_program clCreateProgramWithSource(cl_context context,
+                                     cl_uint count,
+                                     <span class="directive">const</span> <span class="predefined-type">char</span> **strings,
+                                     <span class="directive">const</span> size_t *lengths,
+                                     cl_int *errcode_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>creates a program object for a context, and loads the source code specified
+by the text strings in the <em>strings</em> array into the program object.
+The devices associated with the program object are the devices associated
+with <em>context</em>.
+The source code specified by <em>strings</em> is either an OpenCL C program source,
+header or implementation-defined source for custom devices that support an
+online compiler.
+OpenCL C++ is not supported as an online-compiled kernel language through
+this interface.</p>
+</div>
+<div class="paragraph">
+<p><em>context</em> must be a valid OpenCL context.</p>
+</div>
+<div class="paragraph">
+<p><em>strings</em> is an array of <em>count</em> pointers to optionally null-terminated
+character strings that make up the source code.</p>
+</div>
+<div class="paragraph">
+<p>The <em>lengths</em> argument is an array with the number of chars in each string
+(the string length).
+If an element in <em>lengths</em> is zero, its accompanying string is
+null-terminated.
+If <em>lengths</em> is <code>NULL</code>, all strings in the <em>strings</em> argument are considered
+null-terminated.
+Any length value passed in that is greater than zero excludes the null
+terminator in its count.</p>
+</div>
+<div class="paragraph">
+<p><em>errcode_ret</em> will return an appropriate error code.
+If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p>
+</div>
+<div class="paragraph">
+<p><strong>clCreateProgramWithSource</strong> returns a valid non-zero program object and
+<em>errcode_ret</em> is set to CL_SUCCESS if the program object is created
+successfully.
+Otherwise, it returns a <code>NULL</code> value with one of the following error values
+returned in <em>errcode_ret</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>count</em> is zero or if <em>strings</em> or any entry in
+<em>strings</em> is <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_program clCreateProgramWithIL(cl_context context,
+                                 <span class="directive">const</span> <span class="directive">void</span> *il,
+                                 size_t length,
+                                 cl_int *errcode_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>creates a program object for a context, and loads the IL pointed to by <em>il</em>
+and with length in bytes <em>length</em> into the program object.  The devices
+associated with the program object are the devices associated with <em>context</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>context</em> must be a valid OpenCL context.</p>
+</div>
+<div class="paragraph">
+<p><em>il</em> is a pointer to a <em>length</em>-byte block of memory containing SPIR-V or an
+implementation-defined intermediate language.</p>
+</div>
+<div class="paragraph">
+<p><em>errcode_ret</em> will return an appropriate error code.
+If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p>
+</div>
+<div class="paragraph">
+<p><strong>clCreateProgramWithIL</strong> returns a valid non-zero program object and
+<em>errcode_ret</em> is set to CL_SUCCESS if the program object is created
+successfully.
+Otherwise, it returns a <code>NULL</code> value with one of the following error values
+returned in <em>errcode_ret</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>il</em> is <code>NULL</code> or if <em>length</em> is zero.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if the <em>length</em>-byte memory pointed to by <em>il</em> does not
+contain well-formed intermediate language input that can be consumed by
+the OpenCL runtime.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_program clCreateProgramWithBinary(cl_context context,
+                                     cl_uint num_devices,
+                                     <span class="directive">const</span> cl_device_id *device_list,
+                                     <span class="directive">const</span> size_t *lengths,
+                                     <span class="directive">const</span> <span class="predefined-type">unsigned</span> <span class="predefined-type">char</span> **binaries,
+                                     cl_int *binary_status,
+                                     cl_int *errcode_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>creates a program object for a context, and loads the binary bits specified
+by <em>binary</em> into the program object.</p>
+</div>
+<div class="paragraph">
+<p><em>context</em> must be a valid OpenCL context.</p>
+</div>
+<div class="paragraph">
+<p><em>device_list</em> is a pointer to a list of devices that are in <em>context</em>.
+<em>device_list</em> must be a non-<code>NULL</code> value.
+The binaries are loaded for devices specified in this list.</p>
+</div>
+<div class="paragraph">
+<p><em>num_devices</em> is the number of devices listed in <em>device_list</em>.</p>
+</div>
+<div class="paragraph">
+<p>The devices associated with the program object will be the list of devices
+specified by <em>device_list</em>.
+The list of devices specified by <em>device_list</em> must be devices associated
+with <em>context</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>lengths</em> is an array of the size in bytes of the program binaries to be
+loaded for devices specified by <em>device_list</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>binaries</em> is an array of pointers to program binaries to be loaded for
+devices specified by <em>device_list</em>.
+For each device given by <em>device_list</em>[i], the pointer to the program binary
+for that device is given by <em>binaries</em>[i] and the length of this
+corresponding binary is given by <em>lengths</em>[i].
+<em>lengths</em>[i] cannot be zero and <em>binaries</em>[i] cannot be a <code>NULL</code> pointer.</p>
+</div>
+<div class="paragraph">
+<p>The program binaries specified by <em>binaries</em> contain the bits that describe
+one of the following:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>a program executable to be run on the device(s) associated with
+<em>context</em>,</p>
+</li>
+<li>
+<p>a compiled program for device(s) associated with <em>context</em>, or</p>
+</li>
+<li>
+<p>a library of compiled programs for device(s) associated with <em>context</em>.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The program binary can consist of either or both:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Device-specific code and/or,</p>
+</li>
+<li>
+<p>Implementation-specific intermediate representation (IR) which will be
+converted to the device-specific code.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p><em>binary_status</em> returns whether the program binary for each device specified
+in <em>device_list</em> was loaded successfully or not.
+It is an array of <em>num_devices</em> entries and returns CL_SUCCESS in
+<em>binary_status</em>[i] if binary was successfully loaded for device specified by
+<em>device_list</em>[i]; otherwise returns CL_INVALID_VALUE if <em>lengths</em>[i] is zero
+or if <em>binaries</em>[i] is a <code>NULL</code> value or CL_INVALID_BINARY in
+<em>binary_status</em>[i] if program binary is not a valid binary for the specified
+device.
+If <em>binary_status</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<div class="paragraph">
+<p><em>errcode_ret</em> will return an appropriate error code.
+If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p>
+</div>
+<div class="paragraph">
+<p><strong>clCreateProgramWithBinary</strong> returns a valid non-zero program object and
+<em>errcode_ret</em> is set to CL_SUCCESS if the program object is created
+successfully.
+Otherwise, it returns a <code>NULL</code> value with one of the following error values
+returned in <em>errcode_ret</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>device_list</em> is <code>NULL</code> or <em>num_devices</em> is zero.</p>
+</li>
+<li>
+<p>CL_INVALID_DEVICE if OpenCL devices listed in <em>device_list</em> are not in
+the list of devices associated with <em>context</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>lengths</em> or <em>binaries</em> are <code>NULL</code> or if any entry
+in <em>lengths</em>[i] is zero or <em>binaries</em>[i] is <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_BINARY if an invalid program binary was encountered for any
+device.
+<em>binary_status</em> will return specific status for each device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>OpenCL allows applications to create a program object using the program
+source or binary and build appropriate program executables.
+This can be very useful as it allows applications to load program source and
+then compile and link to generate a program executable online on its first
+instance for appropriate OpenCL devices in the system.
+These executables can now be queried and cached by the application.
+The cached executables can be read and loaded by the application, which can
+help significantly reduce the application initialization time.</p>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_program clCreateProgramWithBuiltInKernels(cl_context context,
+                                             cl_uint num_devices,
+                                             <span class="directive">const</span> cl_device_id *device_list,
+                                             <span class="directive">const</span> <span class="predefined-type">char</span> *kernel_names,
+                                             cl_int *errcode_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>creates a program object for a context, and loads the information related to
+the built-in kernels into a program object.</p>
+</div>
+<div class="paragraph">
+<p><em>context</em> must be a valid OpenCL context.</p>
+</div>
+<div class="paragraph">
+<p><em>num_devices</em> is the number of devices listed in <em>device_list</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>device_list</em> is a pointer to a list of devices that are in <em>context</em>.
+<em>device_list</em> must be a non-<code>NULL</code> value.
+The built-in kernels are loaded for devices specified in this list.</p>
+</div>
+<div class="paragraph">
+<p>The devices associated with the program object will be the list of devices
+specified by <em>device_list</em>.
+The list of devices specified by <em>device_list</em> must be devices associated
+with <em>context</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>kernel_names</em> is a semi-colon separated list of built-in kernel names.</p>
+</div>
+<div class="paragraph">
+<p><strong>clCreateProgramWithBuiltInKernels</strong> returns a valid non-zero program object
+and <em>errcode_ret</em> is set to CL_SUCCESS if the program object is created
+successfully.
+Otherwise, it returns a <code>NULL</code> value with one of the following error values
+returned in <em>errcode_ret</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>device_list</em> is <code>NULL</code> or <em>num_devices</em> is zero.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>kernel_names</em> is <code>NULL</code> or <em>kernel_names</em> contains
+a kernel name that is not supported by any of the devices in
+<em>device_list</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_DEVICE if devices listed in <em>device_list</em> are not in the list
+of devices associated with <em>context</em>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_retaining_and_releasing_program_objects">5.8.2. Retaining and Releasing Program Objects</h4>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clRetainProgram(cl_program program)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>increments the <em>program</em> reference count.
+All <strong>clCreateProgram</strong> APIs do an implicit retain.
+<strong>clRetainProgram</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_PROGRAM if <em>program</em> is not a valid program object.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clReleaseProgram(cl_program program)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>decrements the <em>program</em> reference count.
+The program object is deleted after all kernel objects associated with
+<em>program</em> have been deleted and the <em>program</em> reference count becomes zero.
+<strong>clReleaseProgram</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_PROGRAM if <em>program</em> is not a valid program object.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Using this function to release a reference that was not obtained by creating
+the object or by calling <strong>clRetainProgram</strong> causes undefined behavior.</p>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clSetProgramReleaseCallback(cl_program program,
+                                   <span class="directive">void</span> (CL_CALLBACK *pfn_notify)
+                                       (cl_program prog,
+                                       <span class="directive">void</span> *user_data),
+                                   <span class="directive">void</span> *user_data)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>registers a user callback function with a program object.
+Each call to <strong>clSetProgramReleaseCallback</strong> registers the specified user
+callback function on a callback stack associated with program.
+The registered user callback functions are called in the reverse order in
+which they were registered.
+The user callback functions are called after destructors (if any) for
+program scope global variables (if any) are called and before the program is
+released.
+This provides a mechanism for the application (and libraries) to be notified
+when destructors are complete.</p>
+</div>
+<div class="paragraph">
+<p><em>program</em> is a valid program object</p>
+</div>
+<div class="paragraph">
+<p><em>pfn_notify</em> is the callback function that can be registered by the
+application.
+This callback function may be called asynchronously by the OpenCL
+implementation.
+It is the applications responsibility to ensure that the callback function
+is thread safe.
+The parameters to this callback function are:</p>
+</div>
+<div class="paragraph">
+<p><em>prog</em> is the program object whose destructors are being called.
+When the user callback is called by the implementation, this program object
+is not longer valid.
+prog is only provided for reference purposes.</p>
+</div>
+<div class="paragraph">
+<p><em>user_data</em> is a pointer to user supplied data.
+<em>user_data</em> will be passed as the <em>user_data</em> argument when <em>pfn_notify</em> is
+called.
+user data can be <code>NULL</code>.</p>
+</div>
+<div class="paragraph">
+<p><strong>clSetProgramReleaseCallback</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_PROGRAM if <em>program</em> is not a valid program object.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>pfn_notify</em> is <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_setting_spir_v_specialization_constants">5.8.3. Setting SPIR-V specialization constants</h4>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clSetProgramSpecializationConstant(cl_program program,
+                                          cl_uint spec_id,
+                                          size_t spec_size,
+                                          <span class="directive">const</span> <span class="directive">void</span> *spec_value)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>sets the values of a SPIR-V specialization constants.</p>
+</div>
+<div class="paragraph">
+<p><em>program</em> must be a valid OpenCL program created from a SPIR-V module.</p>
+</div>
+<div class="paragraph">
+<p><em>spec</em> id_ identifies the SPIR-V specialization constant whose value will be
+set.</p>
+</div>
+<div class="paragraph">
+<p><em>spec_size</em> specifies the size in bytes of the data pointed to by
+<em>spec_value</em>.
+This should be 1 for boolean constants.
+For all other constant types this should match the size of the
+specialization constant in the SPIR-V module.</p>
+</div>
+<div class="paragraph">
+<p><em>spec_value</em> is a pointer to the memory location that contains the value of
+the specialization constant.
+The data pointed to by <em>spec_value</em> are copied and can be safely reused by
+the application after <strong>clSetProgramSpecializationConstant</strong> returns.
+This specialization value will be used by subsequent calls to
+<strong>clBuildProgram</strong> until another call to <strong>clSetProgramSpecializationConstant</strong>
+changes it.
+If a specialization constant is a boolean constant, <em>spec_value</em> should be a
+pointer to a cl_uchar value.
+A value of zero will set the specialization constant to false; any other
+value will set it to true.</p>
+</div>
+<div class="paragraph">
+<p>Calling this function multiple times for the same specialization constant
+shall cause the last provided value to override any previously specified
+value.
+The values are used by a subsequent <strong>clBuildProgram</strong> call for the <em>program</em>.</p>
+</div>
+<div class="paragraph">
+<p>Application is not required to provide values for every specialization
+constant contained in SPIR-V module.
+SPIR-V provides default values for all specialization constants.</p>
+</div>
+<div class="paragraph">
+<p><strong>clSetProgramSpecializationConstant</strong> returns CL_SUCCESS if the function is
+executed successfully.</p>
+</div>
+<div class="paragraph">
+<p>Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_PROGRAM if <em>program</em> is not a valid program object created
+from a SPIR-V module.</p>
+</li>
+<li>
+<p>CL_INVALID_SPEC_ID if <em>spec_id</em> is not a valid specialization constant
+ID</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>spec_size</em> does not match the size of the
+specialization constant in the SPIR-V module, or if <em>spec_value</em> is
+<code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_building_program_executables">5.8.4. Building Program Executables</h4>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clBuildProgram(cl_program program,
+                      cl_uint num_devices,
+                      <span class="directive">const</span> cl_device_id *device_list,
+                      <span class="directive">const</span> <span class="predefined-type">char</span> *options,
+                      <span class="directive">void</span> (CL_CALLBACK *pfn_notify)
+                          (cl_program program,
+                          <span class="directive">void</span> *user_data),
+                      <span class="directive">void</span> *user_data)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>builds (compiles &amp; links) a program executable from the program source or
+binary for all the devices or a specific device(s) in the OpenCL context
+associated with <em>program</em>.
+OpenCL allows program executables to be built using the source or the
+binary.
+<strong>clBuildProgram</strong> must be called for <em>program</em> created using
+<strong>clCreateProgramWithSource</strong>, <strong>clCreateProgramWithIL</strong> or
+<strong>clCreateProgramWithBinary</strong> to build the program executable for one or more
+devices associated with <em>program</em>.
+If <em>program</em> is created with <strong>clCreateProgramWithBinary</strong>, then the program
+binary must be an executable binary (not a compiled binary or library).</p>
+</div>
+<div class="paragraph">
+<p>The executable binary can be queried using <strong>clGetProgramInfo</strong>(<em>program</em>,
+CL_PROGRAM_BINARIES, &#8230;&#8203;) and can be specified to
+<strong>clCreateProgramWithBinary</strong> to create a new program object.</p>
+</div>
+<div class="paragraph">
+<p><em>program</em> is the program object.</p>
+</div>
+<div class="paragraph">
+<p><em>device_list</em> is a pointer to a list of devices associated with <em>program</em>.
+If <em>device_list</em> is a <code>NULL</code> value, the program executable is built for all
+devices associated with <em>program</em> for which a source or binary has been
+loaded.
+If <em>device_list</em> is a non-<code>NULL</code> value, the program executable is built for
+devices specified in this list for which a source or binary has been loaded.</p>
+</div>
+<div class="paragraph">
+<p><em>num_devices</em> is the number of devices listed in <em>device_list</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>options</em> is a pointer to a null-terminated string of characters that
+describes the build options to be used for building the program executable.
+The list of supported options is described in <a href="#compiler-options">Compiler
+Options</a>.
+If the program was created using <strong>clCreateProgramWithBinary</strong> and <em>options</em>
+is a <code>NULL</code> pointer, the program will be built as if <em>options</em> were the same
+as when the program binary was originally built.
+If the program was created using <strong>clCreateProgramWithBinary</strong> and <em>options</em>
+string contains anything other than the same options in the same order
+(whitespace ignored) as when the program binary was originally built, then
+the behavior is implementation defined.</p>
+</div>
+<div class="paragraph">
+<p><em>pfn_notify</em> is a function pointer to a notification routine.
+The notification routine is a callback function that an application can
+register and which will be called when the program executable has been built
+(successfully or unsuccessfully).
+If <em>pfn_notify</em> is not <code>NULL</code>, <strong>clBuildProgram</strong> does not need to wait for
+the build to complete and can return immediately once the build operation
+can begin.
+The build operation can begin if the context, program whose sources are
+being compiled and linked, list of devices and build options specified are
+all valid and appropriate host and device resources needed to perform the
+build are available.
+If <em>pfn_notify</em> is <code>NULL</code>, <strong>clBuildProgram</strong> does not return until the build
+has completed.
+This callback function may be called asynchronously by the OpenCL
+implementation.
+It is the applications responsibility to ensure that the callback function
+is thread-safe.</p>
+</div>
+<div class="paragraph">
+<p><em>user_data</em> will be passed as an argument when <em>pfn_notify</em> is called.
+<em>user_data</em> can be <code>NULL</code>.</p>
+</div>
+<div class="paragraph">
+<p><strong>clBuildProgram</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_PROGRAM if <em>program</em> is not a valid program object.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>device_list</em> is <code>NULL</code> and <em>num_devices</em> is greater
+than zero, or if <em>device_list</em> is not <code>NULL</code> and <em>num_devices</em> is zero.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>pfn_notify</em> is <code>NULL</code> but <em>user_data</em> is not
+<code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_DEVICE if OpenCL devices listed in <em>device_list</em> are not in
+the list of devices associated with <em>program</em></p>
+</li>
+<li>
+<p>CL_INVALID_BINARY if <em>program</em> is created with
+<strong>clCreateProgramWithBinary</strong> and devices listed in <em>device_list</em> do not
+have a valid program binary loaded.</p>
+</li>
+<li>
+<p>CL_INVALID_BUILD_OPTIONS if the build options specified by <em>options</em> are
+invalid.</p>
+</li>
+<li>
+<p>CL_COMPILER_NOT_AVAILABLE if <em>program</em> is created with
+<strong>clCreateProgramWithSource</strong> and a compiler is not available i.e.
+CL_DEVICE_COMPILER_AVAILABLE specified in the
+<a href="#device-queries-table">Device Queries</a> table is set to CL_FALSE.</p>
+</li>
+<li>
+<p>CL_BUILD_PROGRAM_FAILURE if there is a failure to build the program
+executable.
+This error will be returned if <strong>clBuildProgram</strong> does not return until
+the build has completed.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if the build of a program executable for any of the
+devices listed in <em>device_list</em> by a previous call to <strong>clBuildProgram</strong>
+for <em>program</em> has not completed.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if there are kernel objects attached to <em>program</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if <em>program</em> was not created with
+<strong>clCreateProgramWithSource</strong>, <strong>clCreateProgramWithIL</strong> or
+<strong>clCreateProgramWithBinary</strong>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_separate_compilation_and_linking_of_programs">5.8.5. Separate Compilation and Linking of Programs</h4>
+<div class="paragraph">
+<p>OpenCL programs are compiled and linked to support the following:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Separate compilation and link stages.
+Program sources can be compiled to generate a compiled binary object and
+linked in a separate stage with other compiled program objects to the
+program exectuable.</p>
+</li>
+<li>
+<p>Embedded headers.
+In OpenCL 1.0 and 1.1, the I build option could be used to specify the
+list of directories to be searched for headers files that are included
+by a program source(s).
+OpenCL 1.2 extends this by allowing the header sources to come from
+program objects instead of just header files.</p>
+</li>
+<li>
+<p>Libraries.
+The linker can be used to link compiled objects and libraries into a
+program executable or to create a library of compiled binaries.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clCompileProgram(cl_program program,
+                        cl_uint num_devices,
+                        <span class="directive">const</span> cl_device_id *device_list,
+                        <span class="directive">const</span> <span class="predefined-type">char</span> *options,
+                        cl_uint num_input_headers,
+                        <span class="directive">const</span> cl_program *input_headers,
+                        <span class="directive">const</span> <span class="predefined-type">char</span> **header_include_names,
+                        <span class="directive">void</span> (CL_CALLBACK *pfn_notify)
+                            (cl_program program,
+                            <span class="directive">void</span> *user_data),
+                        <span class="directive">void</span> *user_data)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>compiles a programs source for all the devices or a specific device(s) in
+the OpenCL context associated with <em>program</em>.
+The pre-processor runs before the program sources are compiled.
+The compiled binary is built for all devices associated with <em>program</em> or
+the list of devices specified.
+The compiled binary can be queried using <strong>clGetProgramInfo</strong>(<em>program</em>,
+CL_PROGRAM_BINARIES, &#8230;&#8203;) and can be passed to <strong>clCreateProgramWithBinary</strong>
+to create a new program object.</p>
+</div>
+<div class="paragraph">
+<p><em>program</em> is the program object that is the compilation target.</p>
+</div>
+<div class="paragraph">
+<p><em>device_list</em> is a pointer to a list of devices associated with <em>program</em>.
+If <em>device_list</em> is a <code>NULL</code> value, the compile is performed for all devices
+associated with <em>program</em>.
+If <em>device_list</em> is a non-<code>NULL</code> value, the compile is performed for devices
+specified in this list.</p>
+</div>
+<div class="paragraph">
+<p><em>num_devices</em> is the number of devices listed in <em>device_list</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>options</em> is a pointer to a null-terminated string of characters that
+describes the compilation options to be used for building the program
+executable.
+Certain options are ignored when program is created with IL.
+The list of supported options is as described in <a href="#compiler-options">Compiler Options</a>.</p>
+</div>
+<div class="paragraph">
+<p><em>num_input_headers</em> specifies the number of programs that describe headers
+in the array referenced by <em>input_headers</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>input_headers</em> is an array of program embedded headers created with
+<strong>clCreateProgramWithSource</strong>.</p>
+</div>
+<div class="paragraph">
+<p><em>header_include_names</em> is an array that has a one to one correspondence with
+<em>input_headers</em>.
+Each entry in <em>header_include_names</em> specifies the include name used by
+source in <em>program</em> that comes from an embedded header.
+The corresponding entry in <em>input_headers</em> identifies the program object
+which contains the header source to be used.
+The embedded headers are first searched before the headers in the list of
+directories specified by the <code>-I</code> compile option (as described in
+<a href="#preprocessor-options">Preprocessor options</a>).
+If multiple entries in <em>header_include_names</em> refer to the same header name,
+the first one encountered will be used.</p>
+</div>
+<div class="paragraph">
+<p>If <em>program</em> was created using <strong>clCreateProgramWithIL</strong>, then
+<em>num_input_headers</em>, <em>input_headers</em>, and <em>header_include_names</em> are
+ignored.</p>
+</div>
+<div class="paragraph">
+<p>For example, consider the following program source:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="preprocessor">#include</span> <span class="include">&lt;foo.h&gt;</span>
+<span class="preprocessor">#include</span> <span class="include">&lt;mydir/myinc.h&gt;</span>
+__kernel <span class="directive">void</span>
+image_filter (<span class="predefined-type">int</span> n, <span class="predefined-type">int</span> m,
+              __constant <span class="predefined-type">float</span> *filter_weights,
+              __read_only image2d_t src_image,
+              __write_only image2d_t dst_image)
+{
+...
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>This kernel includes two headers foo.h and mydir/myinc.h.
+The following describes how these headers can be passed as embedded headers
+in program objects:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_program foo_pg = clCreateProgramWithSource(context,
+    <span class="integer">1</span>, &amp;foo_header_src, <span class="predefined-constant">NULL</span>, &amp;err);
+cl_program myinc_pg = clCreateProgramWithSource(context,
+    <span class="integer">1</span>, &amp;myinc_header_src, <span class="predefined-constant">NULL</span>, &amp;err);
+
+<span class="comment">// lets assume the program source described above is given</span>
+<span class="comment">// by program_A and is loaded via clCreateProgramWithSource</span>
+cl_program input_headers[<span class="integer">2</span>] = { foo_pg, myinc_pg };
+<span class="predefined-type">char</span> * input_header_names[<span class="integer">2</span>] = { foo.h, mydir/myinc.h };
+clCompileProgram(program_A,
+                 <span class="integer">0</span>, <span class="predefined-constant">NULL</span>, <span class="comment">// num_devices &amp; device_list</span>
+                 <span class="predefined-constant">NULL</span>,    <span class="comment">// compile_options</span>
+                 <span class="integer">2</span>,       <span class="comment">// num_input_headers</span>
+                 input_headers,
+                 input_header_names,
+                 <span class="predefined-constant">NULL</span>, <span class="predefined-constant">NULL</span>); <span class="comment">// pfn_notify &amp; user_data</span></code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><em>pfn_notify</em> is a function pointer to a notification routine.
+The notification routine is a callback function that an application can
+register and which will be called when the program executable has been built
+(successfully or unsuccessfully).
+If <em>pfn_notify</em> is not <code>NULL</code>, <strong>clCompileProgram</strong> does not need to wait for
+the compiler to complete and can return immediately once the compilation can
+begin.
+The compilation can begin if the context, program whose sources are being
+compiled, list of devices, input headers, programs that describe input
+headers and compiler options specified are all valid and appropriate host
+and device resources needed to perform the compile are available.
+If <em>pfn_notify</em> is <code>NULL</code>, <strong>clCompileProgram</strong> does not return until the
+compiler has completed.
+This callback function may be called asynchronously by the OpenCL
+implementation.
+It is the applications responsibility to ensure that the callback function
+is thread-safe.</p>
+</div>
+<div class="paragraph">
+<p><em>user_data</em> will be passed as an argument when <em>pfn_notify</em> is called.
+<em>user_data</em> can be <code>NULL</code>.</p>
+</div>
+<div class="paragraph">
+<p><strong>clCompileProgram</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_PROGRAM if <em>program</em> is not a valid program object.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>device_list</em> is <code>NULL</code> and <em>num_devices</em> is greater
+than zero, or if <em>device_list</em> is not <code>NULL</code> and <em>num_devices</em> is zero.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>num_input_headers</em> is zero and
+<em>header_include_names</em> or <em>input_headers</em> are not <code>NULL</code> or if
+<em>num_input_headers</em> is not zero and <em>header_include_names</em> or
+<em>input_headers</em> are <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>pfn_notify</em> is <code>NULL</code> but <em>user_data</em> is not
+<code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_DEVICE if OpenCL devices listed in <em>device_list</em> are not in
+the list of devices associated with <em>program</em></p>
+</li>
+<li>
+<p>CL_INVALID_COMPILER_OPTIONS if the compiler options specified by
+<em>options</em> are invalid.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if the compilation or build of a program executable
+for any of the devices listed in <em>device_list</em> by a previous call to
+<strong>clCompileProgram</strong> or <strong>clBuildProgram</strong> for <em>program</em> has not completed.</p>
+</li>
+<li>
+<p>CL_COMPILER_NOT_AVAILABLE if a compiler is not available i.e.
+CL_DEVICE_COMPILER_AVAILABLE specified in the
+<a href="#device-queries-table">Device Queries</a> table is set to CL_FALSE.</p>
+</li>
+<li>
+<p>CL_COMPILE_PROGRAM_FAILURE if there is a failure to compile the program
+source.
+This error will be returned if <strong>clCompileProgram</strong> does not return until
+the compile has completed.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if there are kernel objects attached to <em>program</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if <em>program</em> has no source or IL available, i.e. it
+has not been created with <strong>clCreateProgramWithSource</strong> or
+<strong>clCreateProgramWithIL</strong>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_program clLinkProgram(cl_context context,
+                         cl_uint num_devices,
+                         <span class="directive">const</span> cl_device_id *device_list,
+                         <span class="directive">const</span> <span class="predefined-type">char</span> *options,
+                         cl_uint num_input_programs,
+                         <span class="directive">const</span> cl_program *input_programs,
+                         <span class="directive">void</span> (CL_CALLBACK *pfn_notify)
+                             (cl_program program,
+                             <span class="directive">void</span> *user_data),
+                         <span class="directive">void</span> *user_data,
+                         cl_int *errcode_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>links a set of compiled program objects and libraries for all the devices or
+a specific device(s) in the OpenCL context and creates a library or
+executable.
+<strong>clLinkProgram</strong> creates a new program object which contains the library or
+executable.
+The library or executable binary can be queried using
+<strong>clGetProgramInfo</strong>(<em>program</em>, CL_PROGRAM_BINARIES, &#8230;&#8203;) and can be specified
+to <strong>clCreateProgramWithBinary</strong> to create a new program object.</p>
+</div>
+<div class="paragraph">
+<p>The devices associated with the returned program object will be the list of
+devices specified by <em>device_list</em> or if <em>device_list</em> is <code>NULL</code> it will be
+the list of devices associated with <em>context</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>context</em> must be a valid OpenCL context.</p>
+</div>
+<div class="paragraph">
+<p><em>device_list</em> is a pointer to a list of devices that are in <em>context</em>.
+If <em>device_list</em> is a <code>NULL</code> value, the link is performed for all devices
+associated with <em>context</em> for which a compiled object is available.
+If <em>device_list</em> is a non-<code>NULL</code> value, the link is performed for devices
+specified in this list for which a compiled object is available.</p>
+</div>
+<div class="paragraph">
+<p><em>num_devices</em> is the number of devices listed in <em>device_list</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>options</em> is a pointer to a null-terminated string of characters that
+describes the link options to be used for building the program executable.
+The list of supported options is as described in <a href="#linker-options">Linker
+Options</a>.
+If the program was created using <strong>clCreateProgramWithBinary</strong> and <em>options</em>
+is a <code>NULL</code> pointer, the program will be linked as if <em>options</em> were the
+same as when the program binary was originally built.
+If the program was created using <strong>clCreateProgramWithBinary</strong> and <em>options</em>
+string contains anything other than the same options in the same order
+(whitespace ignored) as when the program binary was originally built, then
+the behavior is implementation defined.</p>
+</div>
+<div class="paragraph">
+<p><em>num_input_programs</em> specifies the number of programs in array referenced by
+<em>input_programs</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>input_programs</em> is an array of program objects that are compiled binaries
+or libraries that are to be linked to create the program executable.
+For each device in <em>device_list</em> or if <em>device_list</em> is <code>NULL</code> the list of
+devices associated with context, the following cases occur:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>All programs specified by <em>input_programs</em> contain a compiled binary or
+library for the device.
+In this case, a link is performed to generate a program executable for
+this device.</p>
+</li>
+<li>
+<p>None of the programs contain a compiled binary or library for that
+device.
+In this case, no link is performed and there will be no program
+executable generated for this device.</p>
+</li>
+<li>
+<p>All other cases will return a CL_INVALID_OPERATION error.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p><em>pfn_notify</em> is a function pointer to a notification routine.
+The notification routine is a callback function that an application can
+register and which will be called when the program executable has been built
+(successfully or unsuccessfully).</p>
+</div>
+<div class="paragraph">
+<p>If <em>pfn_notify</em> is not <code>NULL</code>, <strong>clLinkProgram</strong> does not need to wait for the
+linker to complete and can return immediately once the linking operation can
+begin.
+Once the linker has completed, the <em>pfn_notify</em> callback function is called
+which returns the program object returned by <strong>clLinkProgram</strong>.
+The application can query the link status and log for this program object.
+This callback function may be called asynchronously by the OpenCL
+implementation.
+It is the applications responsibility to ensure that the callback function
+is thread-safe.</p>
+</div>
+<div class="paragraph">
+<p>If <em>pfn_notify</em> is <code>NULL</code>, <strong>clLinkProgram</strong> does not return until the linker
+has completed.</p>
+</div>
+<div class="paragraph">
+<p><em>user_data</em> will be passed as an argument when <em>pfn_notify</em> is called.
+<em>user_data</em> can be <code>NULL</code>.</p>
+</div>
+<div class="paragraph">
+<p>The linking operation can begin if the context, list of devices, input
+programs and linker options specified are all valid and appropriate host and
+device resources needed to perform the link are available.
+If the linking operation can begin, <strong>clLinkProgram</strong> returns a valid non-zero
+program object.</p>
+</div>
+<div class="paragraph">
+<p>If <em>pfn_notify</em> is <code>NULL</code>, the <em>errcode_ret</em> will be set to CL_SUCCESS if
+the link operation was successful and CL_LINK_PROGRAM_FAILURE if there is a
+failure to link the compiled binaries and/or libraries.</p>
+</div>
+<div class="paragraph">
+<p>If <em>pfn_notify</em> is not <code>NULL</code>, <strong>clLinkProgram</strong> does not have to wait until
+the linker to complete and can return CL_SUCCESS in <em>errcode_ret</em> if the
+linking operation can begin.
+The <em>pfn_notify</em> callback function will return a CL_SUCCESS or
+CL_LINK_PROGRAM_FAILURE if the linking operation was successful or not.</p>
+</div>
+<div class="paragraph">
+<p>Otherwise <strong>clLinkProgram</strong> returns a <code>NULL</code> program object with an
+appropriate error in <em>errcode_ret</em>.
+The application should query the linker status of this program object to
+check if the link was successful or not.
+The list of errors that can be returned are:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>device_list</em> is <code>NULL</code> and <em>num_devices</em> is greater
+than zero, or if <em>device_list</em> is not <code>NULL</code> and <em>num_devices</em> is zero.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>num_input_programs</em> is zero and <em>input_programs</em> is
+<code>NULL</code> or if <em>num_input_programs</em> is zero and <em>input_programs</em> is not
+<code>NULL</code> or if <em>num_input_programs</em> is not zero and <em>input_programs</em> is
+<code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_PROGRAM if programs specified in <em>input_programs</em> are not
+valid program objects.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>pfn_notify</em> is <code>NULL</code> but <em>user_data</em> is not
+<code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_DEVICE if OpenCL devices listed in <em>device_list</em> are not in
+the list of devices associated with <em>context</em></p>
+</li>
+<li>
+<p>CL_INVALID_LINKER_OPTIONS if the linker options specified by <em>options</em>
+are invalid.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if the compilation or build of a program executable
+for any of the devices listed in <em>device_list</em> by a previous call to
+<strong>clCompileProgram</strong> or <strong>clBuildProgram</strong> for <em>program</em> has not completed.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if the rules for devices containing compiled
+binaries or libraries as described in <em>input_programs</em> argument above
+are not followed.</p>
+</li>
+<li>
+<p>CL_LINKER_NOT_AVAILABLE if a linker is not available i.e.
+CL_DEVICE_LINKER_AVAILABLE specified in the
+<a href="#device-queries-table">Device Queries</a> table is set to CL_FALSE.</p>
+</li>
+<li>
+<p>CL_LINK_PROGRAM_FAILURE if there is a failure to link the compiled
+binaries and/or libraries.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="compiler-options">5.8.6. Compiler Options</h4>
+<div class="paragraph">
+<p>The compiler options are categorized as pre-processor options, options for
+math intrinsics, options that control optimization and miscellaneous
+options.
+This specification defines a standard set of options that must be supported
+by the compiler when building program executables online or offline from
+OpenCL C/C++ or, where relevant, from an IL.
+These may be extended by a set of vendor- or platform-specific options.</p>
+</div>
+<div class="sect4">
+<h5 id="preprocessor-options">Preprocessor options</h5>
+<div class="paragraph">
+<p>These options control the OpenCL C/C++ preprocessor which is run on each
+program source before actual compilation.
+These options are ignored for programs created with IL.</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"><code>-D name</code> </dt>
+<dd>
+<p>Predefine <em>name</em> as a macro, with definition 1.</p>
+</dd>
+<dt class="hdlist1"><code>-D name=definition</code> </dt>
+<dd>
+<p>The contents of <em>definition</em> are tokenized and processed as if they
+appeared during translation phase three in a `#define' directive.
+In particular, the definition will be truncated by embedded newline
+characters.</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>-D options are processed in the order they are given in the <em>options</em>
+argument to <strong>clBuildProgram</strong> or <strong>clCompileProgram</strong>.
+Note that a space is required between the -D option and the symbol it
+defines, otherwise behavior is implementation defined.</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"><code>-I dir</code> </dt>
+<dd>
+<p>Add the directory <em>dir</em> to the list of directories to be searched for
+header files.
+<em>dir</em> can optionally be enclosed in double quotes.</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>This option is not portable due to its dependency on host file system and
+host operating system.
+It is supported for backwards compatibility with previous OpenCL versions.
+Developers are encouraged to create and use explicit header objects by means
+of <strong>clCompileProgram</strong> followed by <strong>clLinkProgram</strong>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="math-intrinsics-options">Math Intrinsics Options</h5>
+<div class="paragraph">
+<p>These options control compiler behavior regarding floating-point arithmetic.
+These options trade off between speed and correctness.</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"><code>-cl-single-precision-constant</code> </dt>
+<dd>
+<p>Treat double precision floating-point constant as single precision
+constant.
+This option is ignored for programs created with IL.</p>
+</dd>
+<dt class="hdlist1"><code>-cl-denorms-are-zero</code> </dt>
+<dd>
+<p>This option controls how single precision and double precision
+denormalized numbers are handled.
+If specified as a build option, the single precision denormalized
+numbers may be flushed to zero; double precision denormalized numbers
+may also be flushed to zero if the optional extension for double
+precision is supported.
+This is intended to be a performance hint and the OpenCL compiler can
+choose not to flush denorms to zero if the device supports single
+precision (or double precision) denormalized numbers.</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>This option is ignored for single precision numbers if the device does not
+support single precision denormalized numbers i.e. CL_FP_DENORM bit is not
+set in CL_DEVICE_SINGLE_FP_CONFIG.</p>
+</div>
+<div class="paragraph">
+<p>This option is ignored for double precision numbers if the device does not
+support double precision or if it does support double precision but not
+double precision denormalized numbers i.e. CL_FP_DENORM bit is not set in
+CL_DEVICE_DOUBLE_FP_CONFIG.</p>
+</div>
+<div class="paragraph">
+<p>This flag only applies for scalar and vector single precision floating-point
+variables and computations on these floating-point variables inside a
+program.
+It does not apply to reading from or writing to image objects.</p>
+</div>
+</div>
+</div>
+</dd>
+<dt class="hdlist1"><code>-cl-fp32-correctly-rounded-divide-sqrt</code> </dt>
+<dd>
+<p>The <code>-cl-fp32-correctly-rounded-divide-sqrt</code> build option to
+<strong>clBuildProgram</strong> or <strong>clCompileProgram</strong> allows an application to specify
+that single precision floating-point divide (x/y and 1/x) and sqrt used
+in the program source are correctly rounded.
+If this build option is not specified, the minimum numerical accuracy of
+single precision floating-point divide and sqrt are as defined in the
+SPIR-V OpenCL environment specification.</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>This build option can only be specified if the
+CL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT is set in CL_DEVICE_SINGLE_FP_CONFIG (as
+defined in the <a href="#device-queries-table">Device Queries</a> table) for devices
+that the program is being build.
+<strong>clBuildProgram</strong> or <strong>clCompileProgram</strong> will fail to compile the program for
+a device if the <code>-cl-fp32-correctly-rounded-divide-sqrt</code> option is specified
+and CL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT is not set for the device.</p>
+</div>
+</div>
+</div>
+</dd>
+</dl>
+</div>
+</div>
+<div class="sect4">
+<h5 id="optimization-options">Optimization Options</h5>
+<div class="paragraph">
+<p>These options control various sorts of optimizations.
+Turning on optimization flags makes the compiler attempt to improve the
+performance and/or code size at the expense of compilation time and possibly
+the ability to debug the program.</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"><code>-cl-opt-disable</code> </dt>
+<dd>
+<p>This option disables all optimizations.
+The default is optimizations are enabled.</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>The following options control compiler behavior regarding floating-point
+arithmetic.
+These options trade off between performance and correctness and must be
+specifically enabled.
+These options are not turned on by default since it can result in incorrect
+output for programs which depend on an exact implementation of IEEE 754
+rules/specifications for math functions.</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"><code>-cl-mad-enable</code> </dt>
+<dd>
+<p>Allow <code>a * b + c</code> to be replaced by a <strong>mad</strong> instruction.
+The <strong>mad</strong> instruction may compute <code>a * b + c</code> with reduced accuracy
+in the embedded profile.  See the SPIR-V OpenCL environment specification for
+accuracy details.  On some hardware the <strong>mad</strong> instruction may provide better
+performance than the expanded computation.</p>
+</dd>
+<dt class="hdlist1"><code>-cl-no-signed-zeros</code> </dt>
+<dd>
+<p>Allow optimizations for floating-point arithmetic that ignore the
+signedness of zero.
+IEEE 754 arithmetic specifies the distinct behavior of <code>+0.0</code> and <code>-0.0</code>
+values, which then prohibits simplification of expressions such as <code>x
++  0.0</code> or <code>0.0 * x</code> (even with <code>-cl-finite-math-only</code>).
+This option implies that the sign of a zero result isn&#8217;t significant.</p>
+</dd>
+<dt class="hdlist1"><code>-cl-unsafe-math-optimizations</code> </dt>
+<dd>
+<p>Allow optimizations for floating-point arithmetic that (a) assume that
+arguments and results are valid, (b) may violate the IEEE 754 standard,
+(c) assume relaxed OpenCL numerical compliance requirements as defined
+in the unsafe math optimization section of the SPIR-V OpenCL environment
+specification, and (d) may violate edge case behavior in the SPIR-V OpenCL
+environment specification. This option includes the <code>-cl-no-signed-zeros</code>
+and <code>-cl-mad-enable</code> options.</p>
+</dd>
+<dt class="hdlist1"><code>-cl-finite-math-only</code> </dt>
+<dd>
+<p>Allow optimizations for floating-point arithmetic that assume that
+arguments and results are not NaNs, +Inf, -Inf.
+This option may violate the OpenCL numerical compliance requirements for
+single precision and double precision floating-point, as well as edge
+case behavior.
+The original and modified values are defined in the SPIR-V OpenCL
+environment specification</p>
+</dd>
+<dt class="hdlist1"><code>-cl-fast-relaxed-math</code> </dt>
+<dd>
+<p>Sets the optimization options <code>-cl-finite-math-only</code> and
+<code>-cl-unsafe-math-optimizations</code>.
+This option causes the preprocessor macro <code>__FAST_RELAXED_MATH__</code> to
+be defined in the OpenCL program.</p>
+</dd>
+<dt class="hdlist1"><code>-cl-uniform-work-group-size</code> </dt>
+<dd>
+<p>This requires that the global work-size be a multiple of the work-group
+size specified to <strong>clEnqueueNDRangeKernel</strong>.
+Allow optimizations that are made possible by this restriction.</p>
+</dd>
+<dt class="hdlist1"><code>-cl-no-subgroup-ifp</code> </dt>
+<dd>
+<p>This indicates that kernels in this program do not require subgroups to
+make independent forward progress.
+Allows optimizations that are made possible by this restriction.
+This option has no effect for devices that do not support independent
+forward progress for subgroups.</p>
+</dd>
+</dl>
+</div>
+</div>
+<div class="sect4">
+<h5 id="_options_to_request_or_suppress_warnings">Options to Request or Suppress Warnings</h5>
+<div class="paragraph">
+<p>Warnings are diagnostic messages that report constructions which are not
+inherently erroneous but which are risky or suggest there may have been an
+error.
+The following language-independent options do not enable specific warnings
+but control the kinds of diagnostics produced by the OpenCL compiler.
+These options are ignored for programs created with IL.</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"><code>-w</code> </dt>
+<dd>
+<p>Inhibit all warning messages.</p>
+</dd>
+<dt class="hdlist1"><code>-Werror</code> </dt>
+<dd>
+<p>Make all warnings into errors.</p>
+</dd>
+</dl>
+</div>
+</div>
+<div class="sect4">
+<h5 id="opencl-c-version">Options Controlling the OpenCL C version</h5>
+<div class="paragraph">
+<p>The following option controls the version of OpenCL C that the compiler
+accepts.
+These options are ignored for programs created with IL.</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"><code>-cl-std=</code> </dt>
+<dd>
+<p>Determine the OpenCL C language version to use.
+A value for this option must be provided.
+Valid values are:</p>
+<div class="openblock">
+<div class="content">
+<div class="ulist">
+<ul>
+<li>
+<p>CL1.1 Support all OpenCL C programs that use the OpenCL C language
+features defined in <em>section 6</em> of the OpenCL 1.1 specification.</p>
+</li>
+<li>
+<p>CL1.2 Support all OpenCL C programs that use the OpenCL C language
+features defined in <em>section 6</em> of the OpenCL 1.2 specification.</p>
+</li>
+<li>
+<p>CL2.0 Support all OpenCL C programs that use the OpenCL C language
+features defined in <em>section 6</em> of the OpenCL C 2.0 specification.</p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>Calls to <strong>clBuildProgram</strong> or <strong>clCompileProgram</strong> with the <code>-cl-std=CL1.1</code>
+option <strong>will fail</strong> to compile the program for any devices with
+CL_DEVICE_OPENCL_C_VERSION = OpenCL C 1.0.</p>
+</div>
+<div class="paragraph">
+<p>Calls to <strong>clBuildProgram</strong> or <strong>clCompileProgram</strong> with the <code>-cl-std=CL1.2</code>
+option <strong>will fail</strong> to compile the program for any devices with
+CL_DEVICE_OPENCL_C_VERSION = OpenCL C 1.0.</p>
+</div>
+<div class="paragraph">
+<p>Calls to <strong>clBuildProgram</strong> or <strong>clCompileProgram</strong> with the <code>-cl-std=CL2.0</code>
+option <strong>will fail</strong> to compile the program for any devices with
+CL_DEVICE_OPENCL_C_VERSION = OpenCL C 1.0, OpenCL C 1.1 or OpenCL C 1.2.</p>
+</div>
+<div class="paragraph">
+<p>If the cl-std build option is not specified, the highest OpenCL C 1.x
+language version supported by each device is used when compiling the program
+for each device.
+Applications are required to specify the cl-std=CL2.0 option if they want to
+compile or build their programs with OpenCL C 2.0.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="_options_for_querying_kernel_argument_information">Options for Querying Kernel Argument Information</h5>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"><code>-cl-kernel-arg-info</code> </dt>
+<dd>
+<p>This option allows the compiler to store information about the arguments
+of a kernel(s) in the program executable.
+The argument information stored includes the argument name, its type,
+the address space and access qualifiers used.
+Refer to description of <strong>clGetKernelArgInfo</strong> on how to query this
+information.</p>
+</dd>
+</dl>
+</div>
+</div>
+<div class="sect4">
+<h5 id="_options_for_debugging_your_program">Options for debugging your program</h5>
+<div class="paragraph">
+<p>The following option is available.</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"><code>-g</code> </dt>
+<dd>
+<p>This option can currently be used to generate additional errors for the
+built-in functions that allow you to enqueue commands on a device (refer
+to OpenCL kernel languages specifications).</p>
+</dd>
+</dl>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="linker-options">5.8.7. Linker Options</h4>
+<div class="paragraph">
+<p>This specification defines a standard set of linker options that must be
+supported by the OpenCL C compiler when linking compiled programs online or
+offline.
+These linker options are categorized as library linking options and program
+linking options.
+These may be extended by a set of vendor- or platform-specific options.</p>
+</div>
+<div class="sect4">
+<h5 id="_library_linking_options">Library Linking Options</h5>
+<div class="paragraph">
+<p>The following options can be specified when creating a library of compiled
+binaries.</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"><code>-create-library</code> </dt>
+<dd>
+<p>Create a library of compiled binaries specified in <em>input_programs</em>
+argument to <strong>clLinkProgram</strong>.</p>
+</dd>
+<dt class="hdlist1"><code>-enable-link-options</code> </dt>
+<dd>
+<p>Allows the linker to modify the library behavior based on one or more
+link options (described in <a href="#program-linking-options">Program Linking
+Options</a>) when this library is linked with a program executable.
+This option must be specified with the create-library option.</p>
+</dd>
+</dl>
+</div>
+</div>
+<div class="sect4">
+<h5 id="program-linking-options">Program Linking Options</h5>
+<div class="paragraph">
+<p>The following options can be specified when linking a program executable.</p>
+</div>
+<div class="paragraph">
+<p><code>-cl-denorms-are-zero</code><br>
+<code>-cl-no-signed-zeroes</code><br>
+<code>-cl-unsafe-math-optimizations</code><br>
+<code>-cl-finite-math-only</code><br>
+<code>-cl-fast-relaxed-math</code><br>
+<code>-cl-no-subgroup-ifp</code></p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p>The options are described in <a href="#math-intrinsics-options">Math Intrinsics
+Options</a> and <a href="#optimization-options">Optimization Options</a>.
+The linker may apply these options to all compiled program objects
+specified to <strong>clLinkProgram</strong>.
+The linker may apply these options only to libraries which were created
+with the enable-link-option.</p>
+</dd>
+</dl>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_unloading_the_opencl_compiler">5.8.8. Unloading the OpenCL Compiler</h4>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clUnloadPlatformCompiler(cl_platform_id platform)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>allows the implementation to release the resources allocated by the OpenCL
+compiler for <em>platform</em>.
+This is a hint from the application and does not guarantee that the compiler
+will not be used in the future or that the compiler will actually be
+unloaded by the implementation.
+Calls to <strong>clBuildProgram</strong>, <strong>clCompileProgram</strong> or <strong>clLinkProgram</strong> after
+<strong>clUnloadPlatformCompiler</strong> will reload the compiler, if necessary, to build
+the appropriate program executable.</p>
+</div>
+<div class="paragraph">
+<p><strong>clUnloadPlatformCompiler</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_PLATFORM if <em>platform</em> is not a valid platform.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_program_object_queries">5.8.9. Program Object Queries</h4>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clGetProgramInfo(cl_program program,
+                        cl_program_info param_name,
+                        size_t param_value_size,
+                        <span class="directive">void</span> *param_value,
+                        size_t *param_value_size_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>returns information about the program object.</p>
+</div>
+<div class="paragraph">
+<p><em>program</em> specifies the program object being queried.</p>
+</div>
+<div class="paragraph">
+<p><em>param_name</em> specifies the information to query.
+The list of supported <em>param_name</em> types and the information returned in
+<em>param_value</em> by <strong>clGetProgramInfo</strong> is described in the
+<a href="#program-info-table">Program Object Queries</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value</em> is a pointer to memory where the appropriate result being
+queried is returned.
+If <em>param_value</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size</em> is used to specify the size in bytes of memory pointed to
+by <em>param_value</em>.
+This size must be ≥ size of return type as described in the
+<a href="#program-info-table">Program Object Queries</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size_ret</em> returns the actual size in bytes of data being
+queried by <em>param_name</em>.
+If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<table id="program-info-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 26. <strong>clGetProgramInfo</strong> parameter queries</caption>
+<colgroup>
+<col style="width: 34%;">
+<col style="width: 33%;">
+<col style="width: 33%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_program_info</strong></th>
+<th class="tableblock halign-left valign-top">Return Type</th>
+<th class="tableblock halign-left valign-top">Info. returned in <em>param_value</em></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROGRAM_REFERENCE_COUNT</strong><sup>14</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the <em>program</em> reference count.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROGRAM_CONTEXT</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_context</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the context specified when the program object is created</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROGRAM_NUM_DEVICES</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the number of devices associated with <em>program</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROGRAM_DEVICES</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_id[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the list of devices associated with the program object.
+        This can be the devices associated with context on which the program
+        object has been created or can be a subset of devices that are
+        specified when a progam object is created using
+        <strong>clCreateProgramWithBinary</strong>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROGRAM_SOURCE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the program source code specified by
+        <strong>clCreateProgramWithSource</strong>.
+        The source string returned is a concatenation of all source strings
+        specified to <strong>clCreateProgramWithSource</strong> with a null terminator.
+        The concatenation strips any nulls in the original source strings.</p>
+<p class="tableblock">        If <em>program</em> is created using <strong>clCreateProgramWithBinary</strong>,
+        <strong>clCreateProgramWithIL</strong> or <strong>clCreateProgramWithBuiltinKernels</strong>, a
+        null string or the appropriate program source code is returned
+        depending on whether or not the program source code is stored in the
+        binary.</p>
+<p class="tableblock">        The actual number of characters that represents the program source
+        code including the null terminator is returned in
+        <em>param_value_size_ret</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROGRAM_IL</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the program IL for programs created with
+        <strong>clCreateProgramWithIL</strong>.</p>
+<p class="tableblock">        If <em>program</em> is created with <strong>clCreateProgramWithSource</strong>,
+        <strong>clCreateProgramWithBinary</strong> or <strong>clCreateProgramWithBuiltinKernels</strong>
+        the memory pointed to by param_value will be unchanged and
+        param_value_size_retwill be set to 0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROGRAM_BINARY_SIZES</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns an array that contains the size in bytes of the program
+        binary (could be an executable binary, compiled binary or library
+        binary) for each device associated with program.
+        The size of the array is the number of devices associated with
+        program.
+        If a binary is not available for a device(s), a size of zero is
+        returned.</p>
+<p class="tableblock">        If <em>program</em> is created using <strong>clCreateProgramWithBuiltinKernels</strong>,
+        the implementation may return zero in any entries of the returned
+        array.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROGRAM_BINARIES</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">unsigned char *[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the program binaries (could be an executable binary, compiled
+        binary or library binary) for all devices associated with program.
+        For each device in program, the binary returned can be the binary
+        specified for the device when program is created with
+        <strong>clCreateProgramWithBinary</strong> or it can be the executable binary
+        generated by <strong>clBuildProgram</strong> or <strong>clLinkProgram</strong>.
+        If <em>program</em> is created with <strong>clCreateProgramWithSource</strong> or
+        <strong>clCreateProgramWithIL</strong>, the binary returned is the binary generated
+        by <strong>clBuildProgram</strong>, <strong>clCompileProgram</strong> or <strong>clLinkProgram</strong>.
+        The bits returned can be an implementation-specific intermediate
+        representation (a.k.a. IR) or device specific executable bits or
+        both.
+        The decision on which information is returned in the binary is up to
+        the OpenCL implementation.</p>
+<p class="tableblock">        param_value points to an array of <code>n</code> pointers allocated by the
+        caller, where <code>n</code> is the number of devices associated with program.
+        The buffer sizes needed to allocate the memory that these <code>n</code>
+        pointers refer to can be queried using the CL_PROGRAM_BINARY_SIZES
+        query as described in this table.</p>
+<p class="tableblock">        Each entry in this array is used by the implementation as the
+        location in memory where to copy the program binary for a specific
+        device, if there is a binary available.
+        To find out which device the program binary in the array refers to,
+        use the CL_PROGRAM_DEVICES query to get the list of devices.
+        There is a one-to-one correspondence between the array of n pointers
+        returned by CL_PROGRAM_BINARIES and array of devices returned by
+        CL_PROGRAM_DEVICES.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROGRAM_NUM_KERNELS</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the number of kernels declared in <em>program</em> that can be
+        created with <strong>clCreateKernel</strong>.
+        This information is only available after a successful program
+        executable has been built for at least one device in the list of
+        devices associated with <em>program</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROGRAM_KERNEL_NAMES</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns a semi-colon separated list of kernel names in <em>program</em>
+        that can be created with <strong>clCreateKernel</strong>.
+        This information is only available after a successful program
+        executable has been built for at least one device in the list of
+        devices associated with <em>program</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This indicates that the <em>program</em> object contains non-trivial
+        constructor(s) that will be executed by runtime before any kernel
+        from the program is executed.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This indicates that the program object contains non-trivial
+        destructor(s) that will be executed by runtime when <em>program</em> is
+        destroyed.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="dlist">
+<dl>
+<dt class="hdlist1">14</dt>
+<dd>
+<p>The reference count returned should be considered immediately stale.
+It is unsuitable for general use in applications.
+This feature is provided for identifying memory leaks.</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p><strong>clGetProgramInfo</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_VALUE if <em>param_name</em> is not valid, or if size in bytes
+specified by <em>param_value_size</em> is &lt; size of return type as described in
+the <a href="#program-info-table">Program Object Queries</a> table and
+<em>param_value</em> is not <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_PROGRAM if <em>program</em> is a not a valid program object.</p>
+</li>
+<li>
+<p>CL_INVALID_PROGRAM_EXECUTABLE if <em>param_name</em> is CL_PROGRAM_NUM_KERNELS
+or CL_PROGRAM_KERNEL_NAMES and a successful program executable has not
+been built for at least one device in the list of devices associated
+with <em>program</em>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clGetProgramBuildInfo(cl_program program,
+                             cl_device_id device,
+                             cl_program_build_info param_name,
+                             size_t param_value_size,
+                             <span class="directive">void</span> *param_value,
+                             size_t *param_value_size_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>returns build information for each device in the program object.</p>
+</div>
+<div class="paragraph">
+<p><em>program</em> specifies the program object being queried.</p>
+</div>
+<div class="paragraph">
+<p><em>device</em> specifies the device for which build information is being queried.
+<em>device</em> must be a valid device associated with <em>program</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>param_name</em> specifies the information to query.
+The list of supported <em>param_name</em> types and the information returned in
+<em>param_value</em> by <strong>clGetProgramBuildInfo</strong> is described in the
+<a href="#program-build-info-table">Program Build Queries</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value</em> is a pointer to memory where the appropriate result being
+queried is returned.
+If <em>param_value</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size</em> is used to specify the size in bytes of memory pointed to
+by <em>param_value</em>.
+This size must be ≥ size of return type as described in the
+<a href="#program-build-info-table">Program Build Queries</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size_ret</em> returns the actual size in bytes of data being
+queried by <em>param_name</em>.
+If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<table id="program-build-info-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 27. <strong>clGetProgramBuildInfo</strong> parameter queries.</caption>
+<colgroup>
+<col style="width: 34%;">
+<col style="width: 33%;">
+<col style="width: 33%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_program_build_info</strong></th>
+<th class="tableblock halign-left valign-top">Return Type</th>
+<th class="tableblock halign-left valign-top">Info. returned in <em>param_value</em></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_PROGRAM_BUILD_STATUS</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_build_status</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the build, compile or link status, whichever was performed
+        last on program for device.</p>
+<p class="tableblock">        This can be one of the following:</p>
+<p class="tableblock">        CL_BUILD_NONE - The build status returned if no <strong>clBuildProgram</strong>,
+        <strong>clCompileProgram</strong> or <strong>clLinkProgram</strong> has been performed on the
+        specified program object for device.</p>
+<p class="tableblock">        CL_BUILD_ERROR - The build status returned if <strong>clBuildProgram</strong>,
+        <strong>clCompileProgram</strong> or <strong>clLinkProgram</strong> whichever was performed last
+        on the specified program object for device generated an error.</p>
+<p class="tableblock">        CL_BUILD_SUCCESS - The build status returned if <strong>clBuildProgram</strong>,
+        <strong>clCompileProgram</strong> or <strong>clLinkProgram</strong> whichever was performed last
+        on the specified program object for device was successful.</p>
+<p class="tableblock">        CL_BUILD_IN_PROGRESS - The build status returned if
+        <strong>clBuildProgram</strong>, <strong>clCompileProgram</strong> or <strong>clLinkProgram</strong> whichever
+        was performed last on the specified program object for device has
+        not finished.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_PROGRAM_BUILD_OPTIONS</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the build, compile or link options specified by the options
+        argument in <strong>clBuildProgram</strong>, <strong>clCompileProgram</strong> or <strong>clLinkProgram</strong>,
+        whichever was performed last on program for device.</p>
+<p class="tableblock">        If build status of program for device is CL_BUILD_NONE, an empty
+        string is returned.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_PROGRAM_BUILD_LOG</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the build, compile or link log for <strong>clBuildProgram</strong>,
+        <strong>clCompileProgram</strong> or <strong>clLinkProgram</strong>, whichever was performed last
+        on program for device.</p>
+<p class="tableblock">        If build status of program for device is CL_BUILD_NONE, an empty
+        string is returned.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_PROGRAM_BINARY_TYPE</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_program_binary_type</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the program binary type for device.
+        This can be one of the following values:</p>
+<p class="tableblock">        CL_PROGRAM_BINARY_TYPE_NONE - There is no binary associated with
+        device.</p>
+<p class="tableblock">        CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT - A compiled binary is
+        associated with device.
+        This is the case if program was created using
+        <strong>clCreateProgramWithSource</strong> and compiled using <strong>clCompileProgram</strong> or
+        a compiled binary is loaded using <strong>clCreateProgramWithBinary</strong>.</p>
+<p class="tableblock">        CL_PROGRAM_BINARY_TYPE_LIBRARY - A library binary is associated with
+        device.
+        This is the case if program was created by <strong>clLinkProgram</strong> which is
+        called with the <code>-create-library</code> link option or if a library binary
+        is loaded using <strong>clCreateProgramWithBinary</strong>.</p>
+<p class="tableblock">        CL_PROGRAM_BINARY_TYPE_EXECUTABLE - An executable binary is
+        associated with device.
+        This is the case if program was created by <strong>clLinkProgram</strong> without
+        the <code>-create-library link</code> option or program was created by
+        <strong>clBuildProgram</strong> or an executable binary is loaded using
+        <strong>clCreateProgramWithBinary</strong>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROGRAM_BUILD_GLOBAL_VARIABLE_TOTAL_SIZE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The total amount of storage, in bytes, used by program variables in
+        the global address space.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p><strong>clGetProgramBuildInfo</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_DEVICE if <em>device</em> is not in the list of devices associated
+with <em>program</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>param_name</em> is not valid, or if size in bytes
+specified by <em>param_value_size</em> is &lt; size of return type as described in
+the <a href="#program-build-info-table">Program Build Queries</a> table and
+<em>param_value</em> is not <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_PROGRAM if <em>program</em> is a not a valid program object.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>A program binary (compiled binary, library binary or executable binary)
+built for a parent device can be used by all its sub-devices.
+If a program binary has not been built for a sub-device, the program binary
+associated with the parent device will be used.</p>
+</div>
+<div class="paragraph">
+<p>A program binary for a device specified with <strong>clCreateProgramWithBinary</strong> or
+queried using <strong>clGetProgramInfo</strong> can be used as the binary for the
+associated root device, and all sub-devices created from the root-level
+device or sub-devices thereof.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_kernel_objects">5.9. Kernel Objects</h3>
+<div class="paragraph">
+<p>A kernel is a function declared in a program.
+A kernel is identified by the <code>__kernel</code> qualifier applied to any function
+in a program.
+A kernel object encapsulates the specific <code>__kernel</code> function declared in
+a program and the argument values to be used when executing this
+<code>__kernel</code> function.</p>
+</div>
+<div class="sect3">
+<h4 id="_creating_kernel_objects">5.9.1. Creating Kernel Objects</h4>
+<div class="paragraph">
+<p>To create a kernel object, use the function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_kernel clCreateKernel(cl_program program,
+                         <span class="directive">const</span> <span class="predefined-type">char</span> *kernel_name,
+                         cl_int *errcode_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><em>program</em> is a program object with a successfully built executable.</p>
+</div>
+<div class="paragraph">
+<p><em>kernel_name</em> is a function name in the program declared with the
+<code>__kernel</code> qualifier.</p>
+</div>
+<div class="paragraph">
+<p><em>errcode_ret</em> will return an appropriate error code.
+If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p>
+</div>
+<div class="paragraph">
+<p><strong>clCreateKernel</strong> returns a valid non-zero kernel object and <em>errcode_ret</em> is
+set to CL_SUCCESS if the kernel object is created successfully.
+Otherwise, it returns a <code>NULL</code> value with one of the following error values
+returned in <em>errcode_ret</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_PROGRAM if <em>program</em> is not a valid program object.</p>
+</li>
+<li>
+<p>CL_INVALID_PROGRAM_EXECUTABLE if there is no successfully built
+executable for <em>program</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_KERNEL_NAME if <em>kernel_name</em> is not found in <em>program</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_KERNEL_DEFINITION if the function definition for <code>__kernel</code>
+function given by <em>kernel_name</em> such as the number of arguments, the
+argument types are not the same for all devices for which the <em>program</em>
+executable has been built.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>kernel_name</em> is <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clCreateKernelsInProgram(cl_program program,
+                                cl_uint num_kernels,
+                                cl_kernel *kernels,
+                                cl_uint *num_kernels_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>creates kernel objects for all kernel functions in <em>program</em>.
+Kernel objects are not created for any <code>__kernel</code> functions in <em>program</em>
+that do not have the same function definition across all devices for which a
+program executable has been successfully built.</p>
+</div>
+<div class="paragraph">
+<p><em>program</em> is a program object with a successfully built executable.</p>
+</div>
+<div class="paragraph">
+<p><em>num_kernels</em> is the size of memory pointed to by <em>kernels</em> specified as the
+number of cl_kernel entries.</p>
+</div>
+<div class="paragraph">
+<p><em>kernels</em> is the buffer where the kernel objects for kernels in <em>program</em>
+will be returned.
+If <em>kernels</em> is <code>NULL</code>, it is ignored.
+If <em>kernels</em> is not <code>NULL</code>, <em>num_kernels</em> must be greater than or equal to
+the number of kernels in <em>program</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>num_kernels_ret</em> is the number of kernels in <em>program</em>.
+If <em>num_kernels_ret</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<div class="paragraph">
+<p><strong>clCreateKernelsInProgram</strong> will return CL_SUCCESS if the kernel objects were
+successfully allocated.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_PROGRAM if <em>program</em> is not a valid program object.</p>
+</li>
+<li>
+<p>CL_INVALID_PROGRAM_EXECUTABLE if there is no successfully built
+executable for any device in <em>program</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>kernels</em> is not <code>NULL</code> and <em>num_kernels</em> is less
+than the number of kernels in <em>program</em>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Kernel objects can only be created once you have a program object with a
+valid program source or binary loaded into the program object and the
+program executable has been successfully built for one or more devices
+associated with program.
+No changes to the program executable are allowed while there are kernel
+objects associated with a program object.
+This means that calls to <strong>clBuildProgram</strong> and <strong>clCompileProgram</strong> return
+CL_INVALID_OPERATION if there are kernel objects attached to a program
+object.
+The OpenCL context associated with <em>program</em> will be the context associated
+with <em>kernel</em>.
+The list of devices associated with <em>program</em> are the devices associated
+with <em>kernel</em>.
+Devices associated with a program object for which a valid program
+executable has been built can be used to execute kernels declared in the
+program object.</p>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clRetainKernel(cl_kernel kernel)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>increments the <em>kernel</em> reference count.
+<strong>clRetainKernel</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_KERNEL if <em>kernel</em> is not a valid kernel object.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p><strong>clCreateKernel</strong> or <strong>clCreateKernelsInProgram</strong> do an implicit retain.</p>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clReleaseKernel(cl_kernel kernel)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>decrements the <em>kernel</em> reference count.
+<strong>clReleaseKernel</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_KERNEL if <em>kernel</em> is not a valid kernel object.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The kernel object is deleted once the number of instances that are retained
+to <em>kernel</em> become zero and the kernel object is no longer needed by any
+enqueued commands that use <em>kernel</em>.
+Using this function to release a reference that was not obtained by creating
+the object or by calling <strong>clRetainKernel</strong> causes undefined behavior.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_setting_kernel_arguments">5.9.2. Setting Kernel Arguments</h4>
+<div class="paragraph">
+<p>To execute a kernel, the kernel arguments must be set.</p>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clSetKernelArg(cl_kernel kernel,
+                       cl_uint arg_index,
+                       size_t arg_size,
+                       <span class="directive">const</span> <span class="directive">void</span> *arg_value)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>is used to set the argument value for a specific argument of a kernel.</p>
+</div>
+<div class="paragraph">
+<p><em>kernel</em> is a valid kernel object.</p>
+</div>
+<div class="paragraph">
+<p><em>arg_index</em> is the argument index.
+Arguments to the kernel are referred by indices that go from 0 for the
+leftmost argument to <em>n</em> - 1, where <em>n</em> is the total number of arguments
+declared by a kernel.</p>
+</div>
+<div class="paragraph">
+<p>For example, consider the following kernel:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">kernel <span class="directive">void</span> image_filter (<span class="predefined-type">int</span> n,
+                          <span class="predefined-type">int</span> m,
+                          constant <span class="predefined-type">float</span> *filter_weights,
+                          read_only image2d_t src_image,
+                          write_only image2d_t dst_image)
+{
+...
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Argument index values for <code>image_filter</code> will be 0 for <code>n</code>, 1 for <code>m</code>, 2 for
+<code>filter_weights</code>, 3 for <code>src_image</code> and 4 for <code>dst_image</code>.</p>
+</div>
+<div class="paragraph">
+<p><em>arg_value</em> is a pointer to data that should be used as the argument value
+for argument specified by <em>arg_index</em>.
+The argument data pointed to by_arg_value_ is copied and the <em>arg_value</em>
+pointer can therefore be reused by the application after <strong>clSetKernelArg</strong>
+returns.
+The argument value specified is the value used by all API calls that enqueue
+<em>kernel</em> (<strong>clEnqueueNDRangeKernel</strong>) until the argument value is changed by a
+call to <strong>clSetKernelArg</strong> for <em>kernel</em>.</p>
+</div>
+<div class="paragraph">
+<p>If the argument is a memory object (buffer, pipe, image or image array), the
+<em>arg_value</em> entry will be a pointer to the appropriate buffer, pipe, image
+or image array object.
+The memory object must be created with the context associated with the
+kernel object.
+If the argument is a buffer object, the <em>arg_value</em> pointer can be <code>NULL</code> or
+point to a <code>NULL</code> value in which case a <code>NULL</code> value will be used as the
+value for the argument declared as a pointer to <code>global</code> or <code>constant</code>
+memory in the kernel.
+If the argument is declared with the <code>local</code> qualifier, the <em>arg_value</em>
+entry must be <code>NULL</code>.
+If the argument is of type <em>sampler_t</em>, the <em>arg_value</em> entry must be a
+pointer to the sampler object.
+If the argument is of type <em>queue_t</em>, the <em>arg_value</em> entry must be a
+pointer to the device queue object.</p>
+</div>
+<div class="paragraph">
+<p>If the argument is declared to be a pointer of a built-in scalar or vector
+type, or a user defined structure type in the global or constant address
+space, the memory object specified as argument value must be a buffer object
+(or <code>NULL</code>).
+If the argument is declared with the <code>constant</code> qualifier, the size in bytes
+of the memory object cannot exceed CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE and
+the number of arguments declared as pointers to <code>constant</code> memory cannot
+exceed CL_DEVICE_MAX_CONSTANT_ARGS.</p>
+</div>
+<div class="paragraph">
+<p>The memory object specified as argument value must be a pipe object if the
+argument is declared with the <em>pipe</em> qualifier.</p>
+</div>
+<div class="paragraph">
+<p>The memory object specified as argument value must be a 2D image object if
+the argument is declared to be of type <em>image2d_t</em>.
+The memory object specified as argument value must be a 2D image object with
+image channel order = CL_DEPTH if the argument is declared to be of type
+<em>image2d_depth_t</em>.
+The memory object specified as argument value must be a 3D image object if
+argument is declared to be of type <em>image3d_t</em>.
+The memory object specified as argument value must be a 1D image object if
+the argument is declared to be of type <em>image1d_t</em>.
+The memory object specified as argument value must be a 1D image buffer
+object if the argument is declared to be of type <em>image1d_buffer_t</em>.
+The memory object specified as argument value must be a 1D image array
+object if argument is declared to be of type <em>image1d_array_t</em>.
+The memory object specified as argument value must be a 2D image array
+object if argument is declared to be of type <em>image2d_array_t</em>.
+The memory object specified as argument value must be a 2D image array
+object with image channel order = CL_DEPTH if argument is declared to be of
+type <em>image2d_array_depth_t</em>.</p>
+</div>
+<div class="paragraph">
+<p>For all other kernel arguments, the <em>arg_value</em> entry must be a pointer to
+the actual data to be used as argument value.</p>
+</div>
+<div class="paragraph">
+<p><em>arg_size</em> specifies the size of the argument value.
+If the argument is a memory object, the size is the size of the memory
+object.
+For arguments declared with the <code>local</code> qualifier, the size specified will
+be the size in bytes of the buffer that must be allocated for the <code>local</code>
+argument.
+If the argument is of type <em>sampler_t</em>, the <em>arg_size</em> value must be equal
+to <code>sizeof(cl_sampler)</code>.
+If the argument is of type <em>queue_t</em>, the <em>arg_size</em> value must be equal to
+<code>sizeof(cl_command_queue)</code>.
+For all other arguments, the size will be the size of argument type.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>A kernel object does not update the reference count for objects such as
+memory or sampler objects specified as argument values by <strong>clSetKernelArg</strong>.
+Users may not rely on a kernel object to retain objects specified as
+argument values to the kernel.</p>
+</div>
+<div class="paragraph">
+<p>Implementations shall not allow cl_kernel objects to hold reference
+counts to cl_kernel arguments, because no mechanism is provided for the
+user to tell the kernel to release that ownership right.
+If the kernel holds ownership rights on kernel args, that would make it
+impossible for the user to tell with certainty when he may safely
+release user allocated resources associated with OpenCL objects such as
+the cl_mem backing store used with CL_MEM_USE_HOST_PTR.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p><strong>clSetKernelArg</strong> returns CL_SUCCESS if the function was executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_KERNEL if <em>kernel</em> is not a valid kernel object.</p>
+</li>
+<li>
+<p>CL_INVALID_ARG_INDEX if <em>arg_index</em> is not a valid argument index.</p>
+</li>
+<li>
+<p>CL_INVALID_ARG_VALUE if <em>arg_value</em> specified is not a valid value.</p>
+</li>
+<li>
+<p>CL_INVALID_MEM_OBJECT for an argument declared to be a memory object
+when the specified <em>arg_value</em> is not a valid memory object.</p>
+</li>
+<li>
+<p>CL_INVALID_SAMPLER for an argument declared to be of type <em>sampler_t</em>
+when the specified <em>arg_value</em> is not a valid sampler object.</p>
+</li>
+<li>
+<p>CL_INVALID_DEVICE_QUEUE for an argument declared to be of type <em>queue_t</em>
+when the specified <em>arg_value</em> is not a valid device queue object.</p>
+</li>
+<li>
+<p>CL_INVALID_ARG_SIZE if <em>arg_size</em> does not match the size of the data
+type for an argument that is not a memory object or if the argument is a
+memory object and <em>arg_size</em> != <code>sizeof(cl_mem)</code> or if <em>arg_size</em> is
+zero and the argument is declared with the local qualifier or if the
+argument is a sampler and <em>arg_size</em> != <code>sizeof(cl_sampler)</code>.</p>
+</li>
+<li>
+<p>CL_MAX_SIZE_RESTRICTION_EXCEEDED if the size in bytes of the memory
+object (if the argument was declared with constant qualifier) or
+<em>arg_size</em> (if the argument was declared with local qualifier) exceed
+the maximum size restriction that was set with the optional language
+attribute.
+The optional attribute can be <code>cl::max_size</code> defined in OpenCL 2.2 C++
+Kernel Languange specification or <code>SpvDecorationMaxByteOffset</code> defined
+in SPIR-V 1.2 Specification.</p>
+</li>
+<li>
+<p>CL_INVALID_ARG_VALUE if the argument is an image declared with the
+<code>read_only</code> qualifier and <em>arg_value</em> refers to an image object created
+with <em>cl_mem_flags</em> of CL_MEM_WRITE_ONLY or if the image argument is
+declared with the <code>write_only</code> qualifier and <em>arg_value</em> refers to an
+image object created with <em>cl_mem_flags</em> of CL_MEM_READ_ONLY.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clSetKernelArgSVMPointer(cl_kernel kernel,
+                                 cl_uint arg_index,
+                                 <span class="directive">const</span> <span class="directive">void</span> *arg_value)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>is used to set a SVM pointer as the argument value for a specific argument
+of a kernel.</p>
+</div>
+<div class="paragraph">
+<p><em>kernel</em> is a valid kernel object.</p>
+</div>
+<div class="paragraph">
+<p><em>arg_index</em> is the argument index.
+Arguments to the kernel are referred by indices that go from 0 for the
+leftmost argument to <em>n</em> - 1, where <em>n</em> is the total number of arguments
+declared by a kernel.</p>
+</div>
+<div class="paragraph">
+<p><em>arg_value</em> is the SVM pointer that should be used as the argument value for
+argument specified by <em>arg_index</em>.
+The SVM pointer specified is the value used by all API calls that enqueue
+<em>kernel</em> (<strong>clEnqueueNDRangeKernel</strong>) until the argument value is changed by a
+call to <strong>clSetKernelArgSVMPointer</strong> for <em>kernel</em>.
+The SVM pointer can only be used for arguments that are declared to be a
+pointer to <code>global</code> or <code>constant</code> memory.
+The SVM pointer value must be aligned according to the arguments type.
+For example, if the argument is declared to be <code>global float4 <strong>p</code>, the SVM
+pointer value passed for <code>p</code> must be at a minimum aligned to a <code>float4</code>.
+The SVM pointer value specified as the argument value can be the pointer
+returned by *clSVMAlloc</strong> or can be a pointer offset into the SVM region.</p>
+</div>
+<div class="paragraph">
+<p><strong>clSetKernelArgSVMPointer</strong> returns CL_SUCCESS if the function was executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_KERNEL if <em>kernel</em> is not a valid kernel object.</p>
+</li>
+<li>
+<p>CL_INVALID_ARG_INDEX if <em>arg_index</em> is not a valid argument index.</p>
+</li>
+<li>
+<p>CL_INVALID_ARG_VALUE if <em>arg_value</em> specified is not a valid value.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clSetKernelExecInfo(cl_kernel kernel,
+                            cl_kernel_exec_info param_name,
+                            size_t param_value_size,
+                            <span class="directive">const</span> <span class="directive">void</span> *param_value)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>can be used to pass additional information other than argument values to a
+kernel.</p>
+</div>
+<div class="paragraph">
+<p><em>kernel</em> specifies the kernel object being queried.</p>
+</div>
+<div class="paragraph">
+<p><em>param_name</em> specifies the information to be passed to kernel.
+The list of supported <em>param_name</em> types and the corresponding values passed
+in <em>param_value</em> is described in the <a href="#kernel-exec-info-table">Kernel
+Execution Properties</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size</em> specifies the size in bytes of the memory pointed to by
+<em>param_value</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value</em> is a pointer to memory where the appropriate values determined
+by <em>param_name</em> are specified.</p>
+</div>
+<table id="kernel-exec-info-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 28. <strong>clSetKernelExecInfo_</strong> parameter values</caption>
+<colgroup>
+<col style="width: 34%;">
+<col style="width: 33%;">
+<col style="width: 33%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_kernel_exec_info</strong></th>
+<th class="tableblock halign-left valign-top">Type</th>
+<th class="tableblock halign-left valign-top">Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_EXEC_INFO_SVM_PTRS</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void *[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">SVM pointers must reference locations contained entirely within
+        buffers that are passed to kernel as arguments, or that are passed
+        through the execution information.</p>
+<p class="tableblock">        Non-argument SVM buffers must be specified by passing pointers to
+        those buffers via <strong>clSetKernelExecInfo</strong> for coarse-grain and
+        fine-grain buffer SVM allocations but not for finegrain system SVM
+        allocations.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_EXEC_INFO_SVM_FINE_GRAIN_SYSTEM</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This flag indicates whether the kernel uses pointers that are fine
+        grain system SVM allocations.
+        These fine grain system SVM pointers may be passed as arguments or
+        defined in SVM buffers that are passed as arguments to <em>kernel</em>.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p><strong>clSetKernelExecInfo</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_KERNEL if <em>kernel</em> is a not a valid kernel object.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>param_name</em> is not valid, if <em>param_value</em> is
+<code>NULL</code> or if the size specified by <em>param_value_size</em> is not valid.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if <em>param_name</em> =
+CL_KERNEL_EXEC_INFO_SVM_FINE_GRAIN_SYSTEM and <em>param_value</em> = CL_TRUE
+but no devices in context associated with <em>kernel</em> support fine-grain
+system SVM allocations.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>Coarse-grain or fine-grain buffer SVM pointers used by a kernel which
+are not passed as a kernel arguments must be specified using
+<strong>clSetKernelExecInfo</strong> with CL_KERNEL_EXEC_INFO_SVM_PTRS.
+For example, if SVM buffer A contains a pointer to another SVM buffer B,
+and the kernel dereferences that pointer, then a pointer to B must
+either be passed as an argument in the call to that kernel or it must be
+made available to the kernel using <strong>clSetKernelExecInfo</strong>.
+For example, we might pass extra SVM pointers as follows:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">clSetKernelExecInfo(kernel,
+                    CL_KERNEL_EXEC_INFO_SVM_PTRS,
+                    num_ptrs * <span class="keyword">sizeof</span>(<span class="directive">void</span> *),
+                    extra_svm_ptr_list);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Here <code>num_ptrs</code> specifies the number of additional SVM pointers while
+<code>extra_svm_ptr_list</code> specifies a pointer to memory containing those SVM
+pointers.</p>
+</div>
+<div class="paragraph">
+<p>When calling <strong>clSetKernelExecInfo</strong> with CL_KERNEL_EXEC_INFO_SVM_PTRS to
+specify pointers to non-argument SVM buffers as extra arguments to a kernel,
+each of these pointers can be the SVM pointer returned by <strong>clSVMAlloc</strong> or
+can be a pointer + offset into the SVM region.
+It is sufficient to provide one pointer for each SVM buffer used.</p>
+</div>
+<div class="paragraph">
+<p>CL_KERNEL_EXEC_INFO_SVM_FINE_GRAIN_SYSTEM is used to indicate whether
+SVM pointers used by a kernel will refer to system allocations or not.</p>
+</div>
+<div class="paragraph">
+<p>CL_KERNEL_EXEC_INFO_SVM_FINE_GRAIN_SYSTEM = CL_FALSE indicates that the
+OpenCL implementation may assume that system pointers are not passed as
+kernel arguments and are not stored inside SVM allocations passed as kernel
+arguments.</p>
+</div>
+<div class="paragraph">
+<p>CL_KERNEL_EXEC_INFO_SVM_FINE_GRAIN_SYSTEM = CL_TRUE indicates that the
+OpenCL implementation must assume that system pointers might be passed as
+kernel arguments and/or stored inside SVM allocations passed as kernel
+arguments.
+In this case, if the device to which the kernel is enqueued does not support
+system SVM pointers, <strong>clEnqueueNDRangeKernel</strong> will return a
+CL_INVALID_OPERATION error.
+If none of the devices in the context associated with kernel support
+fine-grain system SVM allocations, <strong>clSetKernelExecInfo</strong> will return a
+CL_INVALID_OPERATION error.</p>
+</div>
+<div class="paragraph">
+<p>If <strong>clSetKernelExecInfo</strong> has not been called with a value for
+<strong>CL_KERNEL_EXEC_INFO_SVM_FINE_GRAIN_SYSTEM</strong>, the default value is used for
+this kernel attribute.
+The default value depends on whether the device on which the kernel is
+enqueued supports fine-grain system SVM allocations.
+If so, the default value used is CL_TRUE (system pointers might be passed);
+otherwise, the default is CL_FALSE.</p>
+</div>
+<div class="paragraph">
+<p>A call to <strong>clSetKernelExecInfo</strong> for a given value of <em>param_name</em>
+replaces any prior value passed for that value of <em>param_name</em>.
+Only one <em>param_value</em> will be stored for each value of <em>param_name</em>.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_copying_kernel_objects">5.9.3. Copying Kernel Objects</h4>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_kernel clCloneKernel(cl_kernel source_kernel,
+                        cl_int *errcode_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>is used to make a shallow copy of the kernel object, its arguments and any
+information passed to the kernel object using <strong>clSetKernelExecInfo</strong>.
+If the kernel object was ready to be enqueued before copying it, the clone
+of the kernel object is ready to enqueue.</p>
+</div>
+<div class="paragraph">
+<p><em>source_kernel</em> is a valid cl_kernel object that will be copied.
+<em>source_kernel</em> will not be modified in any way by this function.</p>
+</div>
+<div class="paragraph">
+<p><em>errcode_ret</em> will be assigned an appropriate error code.
+If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p>
+</div>
+<div class="paragraph">
+<p><strong>clCloneKernel</strong> returns a valid non-zero kernel object and <em>errcode_ret</em> is
+set to CL_SUCCESS if the kernel is successfully copied.
+Otherwise it returns a <code>NULL</code> value with one of the following error values
+returned in <em>errcode_ret</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_KERNEL if <em>kernel</em> is not a valid kernel object.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The returned kernel object is an exact copy of <em>source_kernel</em>, with one
+caveat: the reference count on the returned kernel object is set as if it
+had been returned by <strong>clCreateKernel</strong>.
+The reference count of <em>source_kernel will</em> not be changed.</p>
+</div>
+<div class="paragraph">
+<p>The resulting kernel will be in the same state as if <strong>clCreateKernel</strong> is
+called to create the resultant kernel with the same arguments as those used
+to create <em>source_kernel</em>, the latest call to <strong>clSetKernelArg</strong> or
+<strong>clSetKernelArgSVMPointer</strong> for each argument index applied to kernel and the
+last call to <strong>clSetKernelExecInfo</strong> for each value of the param name
+parameter are applied to the new kernel object.</p>
+</div>
+<div class="paragraph">
+<p>All arguments of the new kernel object must be intact and it may be
+correctly used in the same situations as kernel except those that assume a
+pre-existing reference count.
+Setting arguments on the new kernel object will not affect <em>source_kernel</em>
+except insofar as the argument points to a shared underlying entity and in
+that situation behavior is as if two kernel objects had been created and the
+same argument applied to each.
+Only the data stored in the kernel object is copied; data referenced by the
+kernels arguments are not copied.
+For example, if a buffer or pointer argument is set on a kernel object, the
+pointer is copied but the underlying memory allocation is not.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_kernel_object_queries">5.9.4. Kernel Object Queries</h4>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clGetKernelInfo(cl_kernel kernel,
+                        cl_kernel_info param_name,
+                        size_t param_value_size,
+                        <span class="directive">void</span> *param_value,
+                        size_t *param_value_size_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>returns information about the kernel object.</p>
+</div>
+<div class="paragraph">
+<p><em>kernel</em> specifies the kernel object being queried.</p>
+</div>
+<div class="paragraph">
+<p><em>param_name</em> specifies the information to query.
+The list of supported <em>param_name</em> types and the information returned in
+<em>param_value</em> by <strong>clGetKernelInfo</strong> is described in the
+<a href="#kernel-info-table">Kernel Object Queries</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value</em> is a pointer to memory where the appropriate result being
+queried is returned.
+If <em>param_value</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size</em> is used to specify the size in bytes of memory pointed to
+by <em>param_value</em>.
+This size must be ≥ size of return type as described in the
+<a href="#kernel-info-table">Kernel Object Queries</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size_ret</em> returns the actual size in bytes of data being
+queried by <em>param_name</em>.
+If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<table id="kernel-info-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 29. <strong>clGetKernelInfo</strong> parameter queries</caption>
+<colgroup>
+<col style="width: 34%;">
+<col style="width: 33%;">
+<col style="width: 33%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_kernel_info</strong></th>
+<th class="tableblock halign-left valign-top">Return Type</th>
+<th class="tableblock halign-left valign-top">Info. returned in <em>param_value</em></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_FUNCTION_NAME</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the kernel function name.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_NUM_ARGS</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the number of arguments to kernel.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_REFERENCE_COUNT</strong><sup>16</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the <em>kernel</em> reference count.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_CONTEXT</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_context</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the context associated with <em>kernel</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_PROGRAM</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_program</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the program object associated with kernel.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_ATTRIBUTES</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns any attributes specified using the <code>__attribute__</code>
+        OpenCL C qualifier (or using an OpenCL C++ qualifier syntax [[]] )
+        with the kernel function declaration in the program source.
+        These attributes include attributes described in the earlier OpenCL
+        C kernel language specifications and other attributes supported by
+        an implementation.</p>
+<p class="tableblock">        Attributes are returned as they were declared inside
+        <code>__attribute__((...))</code>, with any surrounding whitespace and
+        embedded newlines removed.
+        When multiple attributes are present, they are returned as a single,
+        space delimited string.</p>
+<p class="tableblock">        For kernels not created from OpenCL C source and the
+        <strong>clCreateProgramWithSource</strong> API call the string returned from this
+        query will be empty.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="dlist">
+<dl>
+<dt class="hdlist1">16</dt>
+<dd>
+<p>The reference count returned should be considered immediately stale.
+It is unsuitable for general use in applications.
+This feature is provided for identifying memory leaks.</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p><strong>clGetKernelInfo</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_VALUE if <em>param_name</em> is not valid, or if size in bytes
+specified by <em>param_value_size</em> is &lt; size of return type as described in
+the <a href="#kernel-info-table">Kernel Object Queries</a> table and <em>param_value</em>
+is not <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_KERNEL if <em>kernel</em> is a not a valid kernel object.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clGetKernelWorkGroupInfo(cl_kernel kernel,
+                                cl_device_id device,
+                                cl_kernel_work_group_info param_name,
+                                size_t param_value_size,
+                                <span class="directive">void</span> *param_value,
+                                size_t *param_value_size_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>returns information about the kernel object that may be specific to a
+device.</p>
+</div>
+<div class="paragraph">
+<p><em>kernel</em> specifies the kernel object being queried.</p>
+</div>
+<div class="paragraph">
+<p><em>device</em> identifies a specific device in the list of devices associated with
+<em>kernel</em>.
+The list of devices is the list of devices in the OpenCL context that is
+associated with <em>kernel</em>.
+If the list of devices associated with <em>kernel</em> is a single device, <em>device</em>
+can be a <code>NULL</code> value.</p>
+</div>
+<div class="paragraph">
+<p><em>param_name</em> specifies the information to query.
+The list of supported <em>param_name</em> types and the information returned in
+<em>param_value</em> by <strong>clGetKernelWorkGroupInfo</strong> is described in the
+<a href="#kernel-workgroup-info-table">Kernel Object Device Queries</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value</em> is a pointer to memory where the appropriate result being
+queried is returned.
+If <em>param_value</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size</em> is used to specify the size in bytes of memory pointed to
+by <em>param_value</em>.
+This size must be ≥ size of return type as described in the
+<a href="#kernel-workgroup-info-table">Kernel Object Device Queries</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size_ret</em> returns the actual size in bytes of data being
+queried by <em>param_name</em>.
+If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<table id="kernel-workgroup-info-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 30. <strong>clGetKernelWorkGroupInfo</strong> parameter queries</caption>
+<colgroup>
+<col style="width: 34%;">
+<col style="width: 33%;">
+<col style="width: 33%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_kernel_work_group_info</strong></th>
+<th class="tableblock halign-left valign-top">Return Type</th>
+<th class="tableblock halign-left valign-top">Info. returned in <em>param_value</em></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_GLOBAL_WORK_SIZE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t[3]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This provides a mechanism for the application to query the maximum
+        global size that can be used to execute a kernel (i.e.
+        <em>global_work_size</em> argument to <strong>clEnqueueNDRangeKernel</strong>) on a custom
+        device given by device or a built-in kernel on an OpenCL device
+        given by device.</p>
+<p class="tableblock">        If device is not a custom device and kernel is not a built-in
+        kernel, <strong>clGetKernelWorkGroupInfo</strong> returns the error
+        CL_INVALID_VALUE.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_WORK_GROUP_SIZE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This provides a mechanism for the application to query the maximum
+        workgroup size that can be used to execute the kernel on a specific
+        device given by device.
+        The OpenCL implementation uses the resource requirements of the
+        kernel (register usage etc.) to determine what this work-group size
+        should be.</p>
+<p class="tableblock">        As a result and unlike CL_DEVICE_MAX_WORK_GROUP_SIZE this value may
+        vary from one kernel to another as well as one device to another.</p>
+<p class="tableblock">        CL_KERNEL_WORK_GROUP_SIZE will be less than or equal to
+        CL_DEVICE_MAX_WORK_GROUP_SIZE for a given kernel object.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_COMPILE_WORK_GROUP_SIZE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t[3]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the work-group size specified in the kernel source or IL.</p>
+<p class="tableblock">        If the work-group size is not specified in the kernel source or IL,
+        (0, 0, 0) is returned.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_LOCAL_MEM_SIZE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_ulong</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the amount of local memory in bytes being used by a kernel.
+        This includes local memory that may be needed by an implementation
+        to execute the kernel, variables declared inside the kernel with the
+        <code>__local</code> address qualifier and local memory to be allocated for
+        arguments to the kernel declared as pointers with the <code>__local</code>
+        address qualifier and whose size is specified with <strong>clSetKernelArg</strong>.</p>
+<p class="tableblock">        If the local memory size, for any pointer argument to the kernel
+        declared with the <code>__local</code> address qualifier, is not specified,
+        its size is assumed to be 0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the preferred multiple of work-group size for launch.
+        This is a performance hint.
+        Specifying a work-group size that is not a multiple of the value
+        returned by this query as the value of the local work size argument
+        to <strong>clEnqueueNDRangeKernel</strong> will not fail to enqueue the kernel for
+        execution unless the work-group size specified is larger than the
+        device maximum.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_PRIVATE_MEM_SIZE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_ulong</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the minimum amount of private memory, in bytes, used by each
+        work-item in the kernel.
+        This value may include any private memory needed by an
+        implementation to execute the kernel, including that used by the
+        language built-ins and variable declared inside the kernel with the
+        <code>__private</code> qualifier.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p><strong>clGetKernelWorkGroupInfo</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_DEVICE if <em>device</em> is not in the list of devices associated
+with <em>kernel</em> or if <em>device</em> is <code>NULL</code> but there is more than one device
+associated with <em>kernel</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>param_name</em> is not valid, or if size in bytes
+specified by <em>param_value_size</em> is &lt; size of return type as described in
+the <a href="#kernel-workgroup-info-table">Kernel Object Device Queries</a> table
+and <em>param_value</em> is not <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>param_name</em> is CL_KERNEL_GLOBAL_WORK_SIZE and
+<em>device</em> is not a custom device and <em>kernel</em> is not a built-in kernel.</p>
+</li>
+<li>
+<p>CL_INVALID_KERNEL if <em>kernel</em> is a not a valid kernel object.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clGetKernelSubGroupInfo(cl_kernel kernel,
+                               cl_device_id device,
+                               cl_kernel_sub_group_info param_name,
+                               size_t input_value_size,
+                               <span class="directive">const</span> <span class="directive">void</span> *input_value,
+                               size_t param_value_size,
+                               <span class="directive">void</span> *param_value,
+                               size_t *param_value_size_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>returns information about the kernel object.</p>
+</div>
+<div class="paragraph">
+<p><em>kernel</em> specifies the kernel object being queried.</p>
+</div>
+<div class="paragraph">
+<p><em>device</em> identifies a specific device in the list of devices associated with
+<em>kernel</em>.
+The list of devices is the list of devices in the OpenCL context that is
+associated with <em>kernel</em>.
+If the list of devices associated with <em>kernel</em> is a single device, <em>device</em>
+can be a <code>NULL</code> value.</p>
+</div>
+<div class="paragraph">
+<p><em>param_name</em> specifies the information to query.
+The list of supported <em>param_name</em> types and the information returned in
+<em>param_value</em> by <strong>clGetKernelSubGroupInfo</strong> is described in the
+<a href="#kernel-subgroup-info-table">Kernel Object Subgroup Queries</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>input_value_size</em> is used to specify the size in bytes of memory pointed to
+by <em>input_value</em>.
+This size must be == size of input type as described in the table below.</p>
+</div>
+<div class="paragraph">
+<p><em>input_value</em> is a pointer to memory where the appropriate parameterization
+of the query is passed from.
+If <em>input_value</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value</em> is a pointer to memory where the appropriate result being
+queried is returned.
+If <em>param_value</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size</em> is used to specify the size in bytes of memory pointed to
+by <em>param_value</em>.
+This size must be ≥ size of return type as described in the
+<a href="#kernel-subgroup-info-table">Kernel Object Subgroup Queries</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size_ret</em> returns the actual size in bytes of data being
+queried by <em>param_name</em>.
+If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<table id="kernel-subgroup-info-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 31. <strong>clGetKernelSubGroupInfo</strong> parameter queries</caption>
+<colgroup>
+<col style="width: 25%;">
+<col style="width: 25%;">
+<col style="width: 25%;">
+<col style="width: 25%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_kernel_sub_group_info</strong></th>
+<th class="tableblock halign-left valign-top">Input Type</th>
+<th class="tableblock halign-left valign-top">Return Type</th>
+<th class="tableblock halign-left valign-top">Info. returned in <em>param_value</em></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t *</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the maximum sub-group size for this kernel.
+            All sub-groups must be the same size, while the last subgroup in
+            any work-group (i.e. the subgroup with the maximum index) could
+            be the same or smaller size.</p>
+<p class="tableblock">            The <em>input_value</em> must be an array of size_t values
+            corresponding to the local work size parameter of the intended
+            dispatch.
+            The number of dimensions in the ND-range will be inferred from
+            the value specified for <em>input_value_size</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t *</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the number of sub-groups that will be present in each
+            work-group for a given local work size.
+            All workgroups, apart from the last work-group in each dimension
+            in the presence of non-uniform work-group sizes, will have the
+            same number of sub-groups.</p>
+<p class="tableblock">            The <em>input_value</em> must be an array of size_t values
+            corresponding to the local work size parameter of the intended
+            dispatch.
+            The number of dimensions in the ND-range will be inferred from
+            the value specified for <em>input_value_size</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the local size that will generate the requested number
+            of sub-groups for the kernel.
+            The output array must be an array of size_t values corresponding
+            to the local size parameter.
+            Any returned work-group will have one dimension.
+            Other dimensions inferred from the value specified for
+            param_value_size will be filled with the value 1.
+            The returned value will produce an exact number of sub-groups
+            and result in no partial groups for an executing kernel except
+            in the case where the last work-group in a dimension has a size
+            different from that of the other groups.
+            If no work-group size can accommodate the requested number of
+            sub-groups, 0 will be returned in each element of the return
+            array.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_MAX_NUM_SUB_GROUPS</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">ignored</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This provides a mechanism for the application to query the
+            maximum number of sub-groups that may make up each work-group to
+            execute a kernel on a specific device given by device.
+            The OpenCL implementation uses the resource requirements of the
+            kernel (register usage etc.) to determine what this work-group
+            size should be.
+            The returned value may be used to compute a work-group size to
+            enqueue the kernel with to give a round number of sub-groups for
+            an enqueue.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_COMPILE_NUM_SUB_GROUPS</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">ignored</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the number of sub-groups specified in the kernel source
+            or IL.
+            If the sub-group count is not specified using the above
+            attribute then 0 is returned.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p><strong>clGetKernelSubGroupInfo</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_DEVICE if <em>device</em> is not in the list of devices associated
+with <em>kernel</em> or if <em>device</em> is <code>NULL</code> but there is more than one device
+associated with <em>kernel</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>param_name</em> is not valid, or if size in bytes
+specified by <em>param_value_size</em> is &lt; size of return type as described in
+the <a href="#kernel-subgroup-info-table">Kernel Object Subgroup Queries</a> table
+and <em>param_value</em> is not <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>param_name</em> is
+CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE and the size in bytes specified by
+<em>input_value_size</em> is not valid or if <em>input_value</em> is <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_KERNEL if <em>kernel</em> is a not a valid kernel object.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clGetKernelArgInfo(cl_kernel kernel,
+                          cl_uint arg_indx,
+                          cl_kernel_arg_info param_name,
+                          size_t param_value_size,
+                          <span class="directive">void</span> *param_value,
+                          size_t *param_value_size_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>returns information about the arguments of a kernel.</p>
+</div>
+<div class="paragraph">
+<p>Kernel argument information is only available if the program object
+associated with <em>kernel</em> is created with <strong>clCreateProgramWithSource</strong> and the
+program executable was built with the <code>-cl-kernel-arg-info option</code> specified
+in options argument to <strong>clBuildProgram</strong> or <strong>clCompileProgram</strong>.</p>
+</div>
+<div class="paragraph">
+<p><em>kernel</em> specifies the kernel object being queried.</p>
+</div>
+<div class="paragraph">
+<p><em>arg_indx</em> is the argument index.
+Arguments to the kernel are referred by indices that go from 0 for the
+leftmost argument to <em>n</em> - 1, where <em>n</em> is the total number of arguments
+declared by a kernel.</p>
+</div>
+<div class="paragraph">
+<p><em>param_name</em> specifies the argument information to query.
+The list of supported <em>param_name</em> types and the information returned in
+<em>param_value</em> by <strong>clGetKernelArgInfo</strong> is described in the
+<a href="#kernel-argument-info-table">Kernel Argument Queries</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value</em> is a pointer to memory where the appropriate result being
+queried is returned.
+If <em>param_value</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size</em> is used to specify the size in bytes of memory pointed to
+by <em>param_value</em>.
+This size must be &gt; size of return type as described in the
+<a href="#kernel-argument-info-table">Kernel Argument Queries</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size ret</em> returns the actual size in bytes of data being
+queried by <em>param_name</em>.
+If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<table id="kernel-argument-info-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 32. <strong>clGetKernelArgInfo</strong> parameter queries</caption>
+<colgroup>
+<col style="width: 34%;">
+<col style="width: 33%;">
+<col style="width: 33%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_kernel_arg_info</strong></th>
+<th class="tableblock halign-left valign-top">Return Type</th>
+<th class="tableblock halign-left valign-top">Info. returned in <em>param_value</em></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_ARG_ADDRESS_QUALIFIER</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_kernel_arg_address_qualifier</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the address qualifier specified for the argument given by
+        <em>arg_indx</em>.
+        This can be one of the following values:</p>
+<p class="tableblock">        CL_KERNEL_ARG_ADDRESS_GLOBAL<br>
+        CL_KERNEL_ARG_ADDRESS_LOCAL<br>
+        CL_KERNEL_ARG_ADDRESS_CONSTANT<br>
+        CL_KERNEL_ARG_ADDRESS_PRIVATE</p>
+<p class="tableblock">        If no address qualifier is specified, the default address qualifier
+        which is CL_KERNEL_ARG_ADDRESS_PRIVATE is returned.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_ARG_ACCESS_QUALIFIER</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_kernel_arg_access_qualifier</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the access qualifier specified for the argument given by
+        <em>arg_indx</em>.
+        This can be one of the following values:</p>
+<p class="tableblock">        CL_KERNEL_ARG_ACCESS_READ_ONLY<br>
+        CL_KERNEL_ARG_ACCESS_WRITE_ONLY<br>
+        CL_KERNEL_ARG_ACCESS_READ_WRITE<br>
+        CL_KERNEL_ARG_ACCESS_NONE</p>
+<p class="tableblock">        If argument is not an image type and is not declared with the pipe
+        qualifier, CL_KERNEL_ARG_ACCESS_NONE is returned.
+        If argument is an image type, the access qualifier specified or the
+        default access qualifier is returned.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_ARG_TYPE_NAME</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the type name specified for the argument given by
+        <em>arg_indx</em>.
+        The type name returned will be the argument type name as it was
+        declared with any whitespace removed.
+        If argument type name is an unsigned scalar type (i.e. unsigned
+        char, unsigned short, unsigned int, unsigned long), uchar, ushort,
+        uint and ulong will be returned.
+        The argument type name returned does not include any type
+        qualifiers.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_ARG_TYPE_QUALIFIER</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_kernel_arg_type_qualifier</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the type qualifier specified for the argument given by
+        <em>arg_indx</em>.
+        The returned value can be: CL_KERNEL_ARG_TYPE_CONST<sup>17</sup>,
+        CL_KERNEL_ARG_TYPE_RESTRICT, CL_KERNEL_ARG_TYPE_VOLATILE<sup>18</sup>, a
+        combination of the above enums, CL_KERNEL_ARG_TYPE_PIPE or
+        CL_KERNEL_ARG_TYPE_NONE.</p>
+<p class="tableblock">        CL_KERNEL_ARG_TYPE_NONE is returned for all parameters passed by
+        value.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_KERNEL_ARG_NAME</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the name specified for the argument given by <em>arg_indx</em>.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="dlist">
+<dl>
+<dt class="hdlist1">17</dt>
+<dd>
+<p>CL_KERNEL_ARG_TYPE_CONST is returned for
+CL_KERNEL_ARG_TYPE_QUALIFIER if the argument is declared with the
+<code>constant</code> address space qualifier.</p>
+</dd>
+<dt class="hdlist1">18</dt>
+<dd>
+<p>CL_KERNEL_ARG_TYPE_VOLATILE is returned for
+CL_KERNEL_ARG_TYPE_QUALIFIER if the argument is a pointer and the
+referenced type is declared with the volatile qualifier.
+For example, a kernel argument declared as <code>global int volatile *x</code>
+returns CL_KERNEL_ARG_TYPE_VOLATILE but a kernel argument declared
+as <code>global int * volatile x</code> does not.
+Similarly, CL_KERNEL_ARG_TYPE_CONST is returned if the argument is a
+pointer and the referenced type is declared with the restrict or
+const qualifier.
+For example, a kernel argument declared as <code>global int const *x</code>
+returns CL_KERNEL_ARG_TYPE_CONST but a kernel argument declared as
+<code>global int * const x</code> does not.
+CL_KERNEL_ARG_TYPE_RESTRICT will be returned if the pointer type is
+marked <code>restrict</code>.
+For example, <code>global int * restrict x</code> returns
+CL_KERNEL_ARG_TYPE_RESTRICT.</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p><strong>clGetKernelArgInfo</strong> returns CL SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_ARG_INDEX if <em>arg_indx</em> is not a valid argument index.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>param_name</em> is not valid, or if size in bytes
+specified by <em>param_value</em> size is &lt; size of return type as described in
+the <a href="#kernel-argument-info-table">Kernel Argument Queries</a> table and
+<em>param_value</em> is not <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_KERNEL_ARG_INFO_NOT_AVAILABLE if the argument information is not
+available for kernel.</p>
+</li>
+<li>
+<p>CL_INVALID_KERNEL if <em>kernel</em> is a not a valid kernel object.</p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_executing_kernels">5.10. Executing Kernels</h3>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueNDRangeKernel(cl_command_queue command_queue,
+                              cl_kernel kernel,
+                              cl_uint work_dim,
+                              <span class="directive">const</span> size_t *global_work_offset,
+                              <span class="directive">const</span> size_t *global_work_size,
+                              <span class="directive">const</span> size_t *local_work_size,
+                              cl_uint num_events_in_wait_list,
+                              <span class="directive">const</span> cl_event *event_wait_list,
+                              cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>enqueues a command to execute a kernel on a device.</p>
+</div>
+<div class="paragraph">
+<p><em>command_queue</em> is a valid host command-queue.
+The kernel will be queued for execution on the device associated with
+<em>command_queue</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>kernel</em> is a valid kernel object.
+The OpenCL context associated with <em>kernel</em> and <em>command-queue</em> must be the
+same.</p>
+</div>
+<div class="paragraph">
+<p><em>work_dim</em> is the number of dimensions used to specify the global work-items
+and work-items in the work-group.
+<em>work_dim</em> must be greater than zero and less than or equal to
+CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS.
+If <em>global_work_size</em> is <code>NULL</code>, or the value in any passed dimension is 0
+then the kernel command will trivially succeed after its event dependencies
+are satisfied and subsequently update its completion event.
+The behavior in this situation is similar to that of an enqueued marker,
+except that unlike a marker, an enqueued kernel with no events passed to
+<em>event_wait_list</em> may run at any time.</p>
+</div>
+<div class="paragraph">
+<p><em>global_work_offset</em> can be used to specify an array of <em>work_dim</em> unsigned
+values that describe the offset used to calculate the global ID of a
+work-item.
+If <em>global_work_offset</em> is <code>NULL</code>, the global IDs start at offset (0, 0, 0).</p>
+</div>
+<div class="paragraph">
+<p><em>global_work_size</em> points to an array of <em>work_dim</em> unsigned values that
+describe the number of global work-items in <em>work_dim</em> dimensions that will
+execute the kernel function.
+The total number of global work-items is computed as <em>global_work_size</em>[0]
+× &#8230;&#8203; × <em>global_work_size</em>[<em>work_dim</em> - 1].</p>
+</div>
+<div class="paragraph">
+<p><em>local_work_size</em> points to an array of <em>work_dim</em> unsigned values that
+describe the number of work-items that make up a work-group (also referred
+to as the size of the work-group) that will execute the kernel specified by
+<em>kernel</em>.
+The total number of work-items in a work-group is computed as
+<em>local_work_size</em>[0] × &#8230;&#8203; × <em>local_work_size</em>[<em>work_dim</em> - 1].
+The total number of work-items in the work-group must be less than or equal
+to the CL_KERNEL_WORK_GROUP_SIZE value specified in the
+<a href="#kernel-workgroup-info-table">Kernel Object Device Queries</a> table, and the
+number of work-items specified in <em>local_work_size</em>[0], &#8230;&#8203;,
+<em>local_work_size</em>[<em>work_dim</em> - 1] must be less than or equal to the
+corresponding values specified by CL_DEVICE_MAX_WORK_ITEM_SIZES[0], &#8230;&#8203;,
+CL_DEVICE_MAX_WORK_ITEM_SIZES[<em>work_dim</em> - 1].
+The explicitly specified <em>local_work_size</em> will be used to determine how to
+break the global work-items specified by <em>global_work_size</em> into appropriate
+work-group instances.</p>
+</div>
+<div class="paragraph">
+<p>Enabling non-uniform work-groups requires the <em>kernel</em>'s program to be
+compiled without the <code>-cl-uniform-work-group-size</code> flag.
+If the program was created with <strong>clCreateProgramWithSource</strong>, non-uniform
+work-groups are enabled only if the program was compiled with the
+<code>-cl-std=CL2.0</code> flag and without the <code>-cl-uniform-work-group-size</code> flag.
+If the program was created using <strong>clLinkProgram</strong> and any of the linked
+programs were compiled in a way that only supports uniform work-group sizes,
+the linked program only supports uniform work group sizes.
+If <em>local_work_size</em> is specified and the OpenCL <em>kernel</em> is compiled
+without non-uniform work-groups enabled, the values specified in
+<em>global_work_size</em>[0], &#8230;&#8203;, <em>global_work_size</em>[<em>work_dim</em> - 1] must be
+evenly divisible by the corresponding values specified in
+<em>local_work_size</em>[0], &#8230;&#8203;, <em>local_work_size</em>[<em>work_dim</em> - 1].</p>
+</div>
+<div class="paragraph">
+<p>If non-uniform work-groups are enabled for the kernel, any single dimension
+for which the global size is not divisible by the local size will be
+partitioned into two regions.
+One region will have work-groups that have the same number of work items as
+was specified by the local size parameter in that dimension.
+The other region will have work-groups with less than the number of work
+items specified by the local size parameter in that dimension.
+The global IDs and group IDs of the work items in the first region will be
+numerically lower than those in the second, and the second region will be at
+most one work-group wide in that dimension.
+Work-group sizes could be non-uniform in multiple dimensions, potentially
+producing work-groups of up to 4 different sizes in a 2D range and 8
+different sizes in a 3D range.</p>
+</div>
+<div class="paragraph">
+<p>If <em>local_work_size</em> is <code>NULL</code> and the kernel is compiled without support
+for non-uniform work-groups, the OpenCL runtime will implement the ND-range
+with uniform work-group sizes.
+If <em>local_work_size</em> is <code>NULL</code> and non-uniform-work-groups are enabled, the
+OpenCL runtime is free to implement the ND-range using uniform or
+non-uniform work-group sizes, regardless of the divisibility of the global
+work size.
+If the ND-range is implemented using non-uniform work-group sizes, the
+work-group sizes, global IDs and group IDs will follow the same pattern as
+described in above paragraph.</p>
+</div>
+<div class="paragraph">
+<p>The work-group size to be used for <em>kernel</em> can also be specified in the
+program source or intermediate language.
+In this case the size of work group specified by <em>local_work_size</em> must
+match the value specified in the program source.</p>
+</div>
+<div class="paragraph">
+<p>These work-group instances are executed in parallel across multiple compute
+units or concurrently on the same compute unit.</p>
+</div>
+<div class="paragraph">
+<p>Each work-item is uniquely identified by a global identifier.
+The global ID, which can be read inside the kernel, is computed using the
+value given by <em>global_work_size</em> and <em>global_work_offset</em>.
+In addition, a work-item is also identified within a work-group by a unique
+local ID.
+The local ID, which can also be read by the kernel, is computed using the
+value given by <em>local_work_size</em>.
+The starting local ID is always (0, 0, &#8230;&#8203;, 0).</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before this particular command can be executed.
+If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait
+on any event to complete.
+If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event_wait_list</em> act as synchronization points.
+The context associated with events in <em>event_wait_list</em> and <em>command_queue</em>
+must be the same.
+The memory associated with <em>event_wait_list</em> can be reused or freed after
+the function returns.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> returns an event object that identifies this particular
+kernel-instance.
+Event objects are unique and can be used to identify a particular
+kernel-instance later on.
+If <em>event</em> is <code>NULL</code>, no event will be created for this kernel-instance and
+therefore it will not be possible for the application to query or queue a
+wait for this particular kernel-instance.
+If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the
+<em>event</em> argument should not refer to an element of the <em>event_wait_list</em>
+array.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueNDRangeKernel</strong> returns CL_SUCCESS if the kernel-instance was
+successfully queued.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_PROGRAM_EXECUTABLE if there is no successfully built program
+executable available for device associated with <em>command_queue</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_KERNEL if <em>kernel</em> is not a valid kernel object.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if context associated with <em>command_queue</em> and
+<em>kernel</em> are not the same or if the context associated with
+<em>command_queue</em> and events in <em>event_wait_list</em> are not the same.</p>
+</li>
+<li>
+<p>CL_INVALID_KERNEL_ARGS if the kernel argument values have not been
+specified or if a kernel argument declared to be a pointer to a type
+does not point to a named address space.</p>
+</li>
+<li>
+<p>CL_INVALID_WORK_DIMENSION if <em>work_dim</em> is not a valid value (i.e. a
+value between 1 and 3).</p>
+</li>
+<li>
+<p>CL_INVALID_GLOBAL_WORK_SIZE if any of the values specified in
+<em>global_work_size</em>[0], &#8230;&#8203; <em>global_work_size</em>[<em>work_dim</em> - 1] exceed the
+maximum value representable by size_t on the device on which the
+kernel-instance will be enqueued.</p>
+</li>
+<li>
+<p>CL_INVALID_GLOBAL_OFFSET if the value specified in <em>global_work_size</em>
++  the corresponding values in <em>global_work_offset</em> for any
+dimensions is greater than the maximum value representable by size t on
+the device on which the kernel-instance will be enqueued.</p>
+</li>
+<li>
+<p>CL_INVALID_WORK_GROUP_SIZE if <em>local_work_size</em> is specified and does
+not match the required work-group size for <em>kernel</em> in the program
+source.</p>
+</li>
+<li>
+<p>CL_INVALID_WORK_GROUP_SIZE if <em>local_work_size</em> is specified and is not
+consistent with the required number of sub-groups for <em>kernel</em> in the
+program source.</p>
+</li>
+<li>
+<p>CL_INVALID_WORK_GROUP_SIZE if <em>local_work_size</em> is specified and the
+total number of work-items in the work-group computed as
+<em>local_work_size</em>[0] × &#8230;&#8203; <em>local_work_size</em>[<em>work_dim</em> - 1] is
+greater than the value specified by CL_KERNEL_WORK_GROUP_SIZE in the
+<a href="#kernel-workgroup-info-table">Kernel Object Device Queries</a> table.</p>
+</li>
+<li>
+<p>CL_INVALID_WORK_GROUP_SIZE if the program was compiled with
+cl-uniform-work-group-size and the number of work-items specified by
+<em>global_work_size</em> is not evenly divisible by size of work-group given
+by <em>local_work_size</em> or by the required work-group size specified in the
+kernel source.</p>
+</li>
+<li>
+<p>CL_INVALID_WORK_ITEM_SIZE if the number of work-items specified in any
+of <em>local_work_size</em>[0], &#8230;&#8203; <em>local_work_size</em>[<em>work_dim</em> - 1] is
+greater than the corresponding values specified by
+CL_DEVICE_MAX_WORK_ITEM_SIZES[0], &#8230;&#8203;,
+CL_DEVICE_MAX_WORK_ITEM_SIZES[<em>work_dim</em> - 1].</p>
+</li>
+<li>
+<p>CL_MISALIGNED_SUB_BUFFER_OFFSET if a sub-buffer object is specified as
+the value for an argument that is a buffer object and the <em>offset</em>
+specified when the sub-buffer object is created is not aligned to
+CL_DEVICE_MEM_BASE_ADDR_ALIGN value for device associated with <em>queue</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_IMAGE_SIZE if an image object is specified as an argument
+value and the image dimensions (image width, height, specified or
+compute row and/or slice pitch) are not supported by device associated
+with <em>queue</em>.</p>
+</li>
+<li>
+<p>CL_IMAGE_FORMAT_NOT_SUPPORTED if an image object is specified as an
+argument value and the image format (image channel order and data type)
+is not supported by device associated with <em>queue</em>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to queue the execution
+instance of <em>kernel</em> on the command-queue because of insufficient
+resources needed to execute the kernel.
+For example, the explicitly specified <em>local_work_size</em> causes a failure
+to execute the kernel because of insufficient resources such as
+registers or local memory.
+Another example would be the number of read-only image args used in
+<em>kernel</em> exceed the CL_DEVICE_MAX_READ_IMAGE_ARGS value for device or
+the number of write-only and read-write image args used in <em>kernel</em>
+exceed the CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS value for device or the
+number of samplers used in <em>kernel</em> exceed CL_DEVICE_MAX_SAMPLERS for
+device.</p>
+</li>
+<li>
+<p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate
+memory for data store associated with image or buffer objects specified
+as arguments to <em>kernel</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if SVM pointers are passed as arguments to a kernel
+and the device does not support SVM or if system pointers are passed as
+arguments to a kernel and/or stored inside SVM allocations passed as
+kernel arguments and the device does not support fine grain system SVM
+allocations.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueNativeKernel(cl_command_queue command_queue,
+                             <span class="directive">void</span> (CL_CALLBACK *user_func)(<span class="directive">void</span> *),
+                             <span class="directive">void</span> *args,
+                             size_t cb_args,
+                             cl_uint num_mem_objects,
+                             <span class="directive">const</span> cl_mem *mem_list,
+                             <span class="directive">const</span> <span class="directive">void</span> **args_mem_loc,
+                             cl_uint num_events_in_wait_list,
+                             <span class="directive">const</span> cl_event *event_wait_list,
+                             cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>enqueues a command to execute a native C/C++ function not compiled using the
+OpenCL compiler.</p>
+</div>
+<div class="paragraph">
+<p><em>command_queue</em> is a valid host command-queue.
+A native user function can only be executed on a command-queue created on a
+device that has CL_EXEC_NATIVE_KERNEL capability set in
+CL_DEVICE_EXECUTION_CAPABILITIES as specified in the
+<a href="#device-queries-table">Device Queries</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>user_func</em> is a pointer to a host-callable user function.</p>
+</div>
+<div class="paragraph">
+<p><em>args</em> is a pointer to the args list that <em>user_func</em> should be called with.</p>
+</div>
+<div class="paragraph">
+<p><em>cb_args</em> is the size in bytes of the args list that <em>args</em> points to.</p>
+</div>
+<div class="paragraph">
+<p>The data pointed to by <em>args</em> and <em>cb_args</em> bytes in size will be copied and
+a pointer to this copied region will be passed to <em>user_func</em>.
+The copy needs to be done because the memory objects (cl_mem values) that
+<em>args</em> may contain need to be modified and replaced by appropriate pointers
+to global memory.
+When <strong>clEnqueueNativeKernel</strong> returns, the memory region pointed to by <em>args</em>
+can be reused by the application.</p>
+</div>
+<div class="paragraph">
+<p><em>num_mem_objects</em> is the number of buffer objects that are passed in <em>args</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>mem_list</em> is a list of valid buffer objects, if <em>num_mem_objects</em> &gt; 0.
+The buffer object values specified in <em>mem_list</em> are memory object handles
+(cl_mem values) returned by <strong>clCreateBuffer</strong> or <code>NULL</code>.</p>
+</div>
+<div class="paragraph">
+<p><em>args_mem_loc</em> is a pointer to appropriate locations that <em>args</em> points to
+where memory object handles (cl_mem values) are stored.
+Before the user function is executed, the memory object handles are replaced
+by pointers to global memory.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em>, <em>num_events_in_wait_list</em> and <em>event</em> are as described in
+<strong>clEnqueueNDRangeKernel</strong>.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueNativeKernel</strong> returns CL_SUCCESS if the user function execution
+instance was successfully queued.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if context associated with <em>command_queue</em> and events
+in <em>event_wait_list</em> are not the same.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>user_func</em> is <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>args</em> is a <code>NULL</code> value and <em>cb_args</em> &gt; 0, or if
+<em>args</em> is a <code>NULL</code> value and <em>num_mem_objects</em> &gt; 0.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>args</em> is not <code>NULL</code> and <em>cb_args</em> is 0.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>num_mem_objects</em> &gt; 0 and <em>mem_list</em> or
+<em>args_mem_loc</em> are <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>num_mem_objects</em> = 0 and <em>mem_list</em> or
+<em>args_mem_loc</em> are not <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if the device associated with <em>command_queue</em>
+cannot execute the native kernel.</p>
+</li>
+<li>
+<p>CL_INVALID_MEM_OBJECT if one or more memory objects specified in
+<em>mem_list</em> are not valid or are not buffer objects.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to queue the execution
+instance of <em>kernel</em> on the command-queue because of insufficient
+resources needed to execute the kernel.</p>
+</li>
+<li>
+<p>CL_MEM_OBJECT_ALLOCATION_FAILURE if there is a failure to allocate
+memory for data store associated with buffer objects specified as
+arguments to <em>kernel</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if SVM pointers are passed as arguments to a kernel
+and the device does not support SVM or if system pointers are passed as
+arguments to a kernel and/or stored inside SVM allocations passed as
+kernel arguments and the device does not support fine grain system SVM
+allocations.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>The total number of read-only images specified as arguments to a kernel
+cannot exceed CL_DEVICE_MAX_READ_IMAGE_ARGS.
+Each image array argument to a kernel declared with the <code>read_only</code>
+qualifier counts as one image.
+The total number of write-only images specified as arguments to a kernel
+cannot exceed CL_DEVICE_MAX_WRITE_IMAGE_ARGS.
+Each image array argument to a kernel declared with the <code>write_only</code>
+qualifier counts as one image.</p>
+</div>
+<div class="paragraph">
+<p>The total number of read-write images specified as arguments to a kernel
+cannot exceed CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS.
+Each image array argument to a kernel declared with the <code>read_write</code>
+qualifier counts as one image.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+</div>
+<div class="sect2">
+<h3 id="event-objects">5.11. Event Objects</h3>
+<div class="paragraph">
+<p>Event objects can be used to refer to a kernel-instance command
+(<strong>clEnqueueNDRangeKernel</strong>, <strong>clEnqueueNativeKernel</strong>), read, write, map and
+copy commands on memory objects (<strong>clEnqueue{Read|Write|Map}Buffer</strong>,
+<strong>clEnqueueUnmapMemObject</strong>, <strong>clEnqueue{Read|Write}BufferRect</strong>,
+<strong>clEnqueue{Read|Write|Map}Image</strong>, <strong>clEnqueueCopy{Buffer|Image}</strong>,
+<strong>clEnqueueCopyBufferRect</strong>, <strong>clEnqueueCopyBufferToImage</strong>,
+<strong>clEnqueueCopyImageToBuffer</strong>), <strong>clEnqueueSVMMemcpy</strong>, <strong>clEnqueueSVMMemFill</strong>,
+<strong>clEnqueueSVMMap</strong>, <strong>clEnqueueSVMUnmap</strong>, <strong>clEnqueueSVMFree</strong>,
+<strong>clEnqueueMarkerWithWaitList</strong>, <strong>clEnqueueBarrierWithWaitList</strong> (refer to
+<a href="#markers-barriers-waiting-for-events">Markers, Barriers and Waiting for
+Events</a>) or user events.</p>
+</div>
+<div class="paragraph">
+<p>An event object can be used to track the execution status of a command.
+The API calls that enqueue commands to a command-queue create a new event
+object that is returned in the <em>event</em> argument.
+In case of an error enqueuing the command in the command-queue the event
+argument does not return an event object.</p>
+</div>
+<div class="paragraph">
+<p>The execution status of an enqueued command at any given point in time can
+be one of the following:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_QUEUED This indicates that the command has been enqueued in a
+command-queue.
+This is the initial state of all events except user events.</p>
+</li>
+<li>
+<p>CL_SUBMITTED This is the initial state for all user events.
+For all other events, this indicates that the command has been submitted
+by the host to the device.</p>
+</li>
+<li>
+<p>CL_RUNNING This indicates that the device has started executing this
+command.
+In order for the execution status of an enqueued command to change from
+CL_SUBMITTED to CL_RUNNING, all events that this command is waiting on
+must have completed successfully i.e. their execution status must be
+CL_COMPLETE.</p>
+</li>
+<li>
+<p>CL_COMPLETE This indicates that the command has successfully completed.</p>
+</li>
+<li>
+<p>Error code The error code is a negative integer value and indicates that
+the command was abnormally terminated.
+Abnormal termination may occur for a number of reasons such as a bad
+memory access.</p>
+</li>
+</ul>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>A command is considered to be complete if its execution status is
+CL_COMPLETE or is a negative integer value.</p>
+</div>
+<div class="paragraph">
+<p>If the execution of a command is terminated, the command-queue associated
+with this terminated command, and the associated context (and all other
+command-queues in this context) may no longer be available.
+The behavior of OpenCL API calls that use this context (and command-queues
+associated with this context) are now considered to be
+implementation-defined.
+The user registered callback function specified when context is created can
+be used to report appropriate error information.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_event clCreateUserEvent(cl_context context,
+                           cl_int *errcode_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>creates a user event object.
+User events allow applications to enqueue commands that wait on a user event
+to finish before the command is executed by the device.</p>
+</div>
+<div class="paragraph">
+<p><em>context</em> must be a valid OpenCL context.</p>
+</div>
+<div class="paragraph">
+<p><em>errcode_ret</em> will return an appropriate error code.
+If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p>
+</div>
+<div class="paragraph">
+<p><strong>clCreateUserEvent</strong> returns a valid non-zero event object and <em>errcode_ret</em>
+is set to CL_SUCCESS if the user event object is created successfully.
+Otherwise, it returns a <code>NULL</code> value with one of the following error values
+returned in <em>errcode_ret</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The execution status of the user event object created is set to
+CL_SUBMITTED.</p>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clSetUserEventStatus(cl_event event,
+                            cl_int execution_status)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>sets the execution status of a user event object.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> is a user event object created using <strong>clCreateUserEvent</strong>.</p>
+</div>
+<div class="paragraph">
+<p><em>execution_status</em> specifies the new execution status to be set and can be
+CL_COMPLETE or a negative integer value to indicate an error.
+A negative integer value causes all enqueued commands that wait on this user
+event to be terminated.
+<strong>clSetUserEventStatus</strong> can only be called once to change the execution
+status of <em>event</em>.</p>
+</div>
+<div class="paragraph">
+<p><strong>clSetUserEventStatus</strong> returns CL_SUCCESS if the function was executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_EVENT if <em>event</em> is not a valid user event object.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if the <em>execution_status</em> is not CL_COMPLETE or a
+negative integer value.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if the <em>execution_status</em> for <em>event</em> has already
+been changed by a previous call to <strong>clSetUserEventStatus</strong>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>If there are enqueued commands with user events in the <em>event_wait_list</em>
+argument of <strong>clEnqueue*</strong> commands, the user must ensure that the status of
+these user events being waited on are set using <strong>clSetUserEventStatus</strong>
+before any OpenCL APIs that release OpenCL objects except for event objects
+are called; otherwise the behavior is undefined.</p>
+</div>
+<div class="paragraph">
+<p>For example, the following code sequence will result in undefined behavior
+of <strong>clReleaseMemObject</strong>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">ev1 = clCreateUserEvent(ctx, <span class="predefined-constant">NULL</span>);
+clEnqueueWriteBuffer(cq, buf1, CL_FALSE, ..., <span class="integer">1</span>, &amp;ev1, <span class="predefined-constant">NULL</span>);
+clEnqueueWriteBuffer(cq, buf2, CL_FALSE, ...);
+clReleaseMemObject(buf2);
+clSetUserEventStatus(ev1, CL_COMPLETE);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The following code sequence, however, works correctly.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">ev1 = clCreateUserEvent(ctx, <span class="predefined-constant">NULL</span>);
+clEnqueueWriteBuffer(cq, buf1, CL_FALSE, ..., <span class="integer">1</span>, &amp;ev1, <span class="predefined-constant">NULL</span>);
+clEnqueueWriteBuffer(cq, buf2, CL_FALSE, ...);
+clSetUserEventStatus(ev1, CL_COMPLETE);
+clReleaseMemObject(buf2);</code></pre>
+</div>
+</div>
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clWaitForEvents(cl_uint num_events,
+                       <span class="directive">const</span> cl_event *event_list)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>waits on the host thread for commands identified by event objects in
+<em>event_list</em> to complete.
+A command is considered complete if its execution status is CL_COMPLETE or a
+negative value.
+The events specified in <em>event_list</em> act as synchronization points.</p>
+</div>
+<div class="paragraph">
+<p><strong>clWaitForEvents</strong> returns CL_SUCCESS if the execution status of all events
+in <em>event_list</em> is CL_COMPLETE.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_VALUE if <em>num_events</em> is zero or <em>event_list</em> is <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if events specified in <em>event_list</em> do not belong to
+the same context.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT if event objects specified in <em>event_list</em> are not
+valid event objects.</p>
+</li>
+<li>
+<p>CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST if the execution status of
+any of the events in <em>event_list</em> is a negative integer value.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clGetEventInfo(cl_event event,
+                      cl_event_info param_name,
+                      size_t param_value_size,
+                      <span class="directive">void</span> *param_value,
+                      size_t *param_value_size_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>returns information about the event object.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> specifies the event object being queried.</p>
+</div>
+<div class="paragraph">
+<p><em>param_name</em> specifies the information to query.
+The list of supported <em>param_name</em> types and the information returned in
+<em>param_value</em> by <strong>clGetEventInfo</strong> is described in the
+<a href="#event-info-table">Event Object Queries</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value</em> is a pointer to memory where the appropriate result being
+queried is returned.
+If <em>param_value</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size</em> is used to specify the size in bytes of memory pointed to
+by <em>param_value</em>.
+This size must be ≥ size of return type as described in the
+<a href="#event-info-table">Event Object Queries</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size_ret</em> returns the actual size in bytes of data being
+queried by <em>param_name</em>.
+If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<table id="event-info-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 33. <strong>clGetEventInfo</strong> parameter queries</caption>
+<colgroup>
+<col style="width: 30%;">
+<col style="width: 33%;">
+<col style="width: 37%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_event_info</strong></th>
+<th class="tableblock halign-left valign-top">Return Type</th>
+<th class="tableblock halign-left valign-top">Info. returned in <em>param_value</em></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_EVENT_COMMAND_QUEUE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_command_queue</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the command-queue associated with <em>event</em>.
+        For user event objects, a <code>NULL</code> value is returned.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_EVENT_CONTEXT</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_context</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the context associated with <em>event</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_EVENT_COMMAND_TYPE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_command_type</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the command associated with event.
+        Can be one of the following values:</p>
+<p class="tableblock">        CL_COMMAND_NDRANGE_KERNEL<br>
+        CL_COMMAND_NATIVE_KERNEL<br>
+        CL_COMMAND_READ_BUFFER<br>
+        CL_COMMAND_WRITE_BUFFER<br>
+        CL_COMMAND_COPY_BUFFER<br>
+        CL_COMMAND_READ_IMAGE<br>
+        CL_COMMAND_WRITE_IMAGE<br>
+        CL_COMMAND_COPY_IMAGE<br>
+        CL_COMMAND_COPY_BUFFER_TO_IMAGE<br>
+        CL_COMMAND_COPY_IMAGE_TO_BUFFER<br>
+        CL_COMMAND_MAP_BUFFER<br>
+        CL_COMMAND_MAP_IMAGE<br>
+        CL_COMMAND_UNMAP_MEM_OBJECT<br>
+        CL_COMMAND_MARKER<br>
+        CL_COMMAND_ACQUIRE_GL_OBJECTS<br>
+        CL_COMMAND_RELEASE_GL_OBJECTS<br>
+        CL_COMMAND_READ_BUFFER_RECT<br>
+        CL_COMMAND_WRITE_BUFFER_RECT<br>
+        CL_COMMAND_COPY_BUFFER_RECT<br>
+        CL_COMMAND_USER<br>
+        CL_COMMAND_BARRIER<br>
+        CL_COMMAND_MIGRATE_MEM_OBJECTS<br>
+        CL_COMMAND_FILL_BUFFER<br>
+        CL_COMMAND_FILL_IMAGE<br>
+        CL_COMMAND_SVM_FREE<br>
+        CL_COMMAND_SVM_MEMCPY<br>
+        CL_COMMAND_SVM_MEMFILL<br>
+        CL_COMMAND_SVM_MAP<br>
+        CL_COMMAND_SVM_UNMAP</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_EVENT_COMMAND_EXECUTION_STATUS</strong><sup>19</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_int</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the execution status of the command identified by event.
+        Valid values are:</p>
+<p class="tableblock">        CL_QUEUED (command has been enqueued n the command-queue),</p>
+<p class="tableblock">        CL_SUBMITTED (enqueued command has been submitted by the host to the
+        device associated with the command-queue),</p>
+<p class="tableblock">        CL_RUNNING (device is currently executing this command),</p>
+<p class="tableblock">        CL_COMPLETE (the command has completed), or</p>
+<p class="tableblock">        Error code given by a negative integer value. (command was
+        abnormally terminated - this may be caused by a bad memory access
+        etc.).
+        These error codes come from the same set of error codes that are
+        returned from the platform or runtime API calls as return values or
+        errcode_ret values.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_EVENT_REFERENCE_COUNT</strong><sup>20</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the <em>event</em> reference count.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="dlist">
+<dl>
+<dt class="hdlist1">19</dt>
+<dd>
+<p>The error code values are negative, and event state values are positive.
+The event state values are ordered from the largest value (CL_QUEUED)
+for the first or initial state to the smallest value (CL_COMPLETE or
+negative integer value) for the last or complete state.
+The value of CL_COMPLETE and CL_SUCCESS are the same.</p>
+</dd>
+<dt class="hdlist1">20</dt>
+<dd>
+<p>The reference count returned should be considered immediately stale.
+It is unsuitable for general use in applications.
+This feature is provided for identifying memory leaks.</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>Using <strong>clGetEventInfo</strong> to determine if a command identified by <em>event</em> has
+finished execution (i.e. CL_EVENT_COMMAND_EXECUTION_STATUS returns
+CL_COMPLETE) is not a synchronization point.
+There are no guarantees that the memory objects being modified by command
+associated with <em>event</em> will be visible to other enqueued commands.</p>
+</div>
+<div class="paragraph">
+<p><strong>clGetEventInfo</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_VALUE if <em>param_name</em> is not valid, or if size in bytes
+specified by <em>param_value_size</em> is &lt; size of return type as described in
+the <a href="#kernel-argument-info-table">Kernel Argument Queries</a> table and
+<em>param_value</em> is not <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if information to query given in <em>param_name</em> cannot be
+queried for <em>event</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT if <em>event</em> is a not a valid event object.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clSetEventCallback(cl_event event,
+                          cl_int command_exec_callback_type,
+                          <span class="directive">void</span> (CL_CALLBACK *pfn_event_notify)(
+                              cl_event event,
+                              cl_int event_command_exec_status,
+                              <span class="directive">void</span> *user_data),
+                          <span class="directive">void</span> *user_data)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>registers a user callback function for a specific command execution status.
+The registered callback function will be called when the execution status of
+command associated with <em>event</em> changes to an execution status equal to or
+past the status specified by <em>command_exec_status</em>.</p>
+</div>
+<div class="paragraph">
+<p>Each call to <strong>clSetEventCallback</strong> registers the specified user callback
+function on a callback stack associated with <em>event</em>.
+The order in which the registered user callback functions are called is
+undefined.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> is a valid event object.</p>
+</div>
+<div class="paragraph">
+<p><em>command_exec_callback_type</em> specifies the command execution status for
+which the callback is registered.
+The command execution callback values for which a callback can be registered
+are: CL_SUBMITTED, CL_RUNNING or CL_COMPLETE<sup>21</sup>.
+There is no guarantee that the callback functions registered for various
+execution status values for an event will be called in the exact order that
+the execution status of a command changes.
+Furthermore, it should be noted that receiving a call back for an event with
+a status other than CL_COMPLETE, in no way implies that the memory model or
+execution model as defined by the OpenCL specification has changed.
+For example, it is not valid to assume that a corresponding memory transfer
+has completed unless the event is in a state CL_COMPLETE.</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1">21</dt>
+<dd>
+<p>The callback function registered for a command_exec_callback_type value
+of CL_COMPLETE will be called when the command has completed
+successfully or is abnormally terminated.</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p><em>pfn_event_notify</em> is the event callback function that can be registered by
+the application.
+This callback function may be called asynchronously by the OpenCL
+implementation.
+It is the applications responsibility to ensure that the callback function
+is thread-safe.
+The parameters to this callback function are:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><em>event</em> is the event object for which the callback function is invoked.</p>
+</li>
+<li>
+<p><em>event_command_exec_status</em> is equal to the <em>command_exec_callback_type</em>
+used while registering the callback.
+Refer to the <a href="#kernel-argument-info-table">Kernel Argument Queries</a>
+table for the command execution status values.
+If the callback is called as the result of the command associated with
+event being abnormally terminated, an appropriate error code for the
+error that caused the termination will be passed to
+<em>event_command_exec_status</em> instead.</p>
+</li>
+<li>
+<p><em>user_data</em> is a pointer to user supplied data.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p><em>user_data</em> will be passed as the <em>user_data</em> argument when <em>pfn_notify</em> is
+called.
+<em>user_data</em> can be <code>NULL</code>.</p>
+</div>
+<div class="paragraph">
+<p>All callbacks registered for an event object must be called.
+All enqueued callbacks shall be called before the event object is destroyed.
+Callbacks must return promptly.
+The behavior of calling expensive system routines, OpenCL API calls to
+create contexts or command-queues, or blocking OpenCL operations from the
+following list below, in a callback is undefined.</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>clFinish</strong>,</p>
+</li>
+<li>
+<p><strong>clWaitForEvents</strong>,</p>
+</li>
+<li>
+<p>blocking calls to <strong>clEnqueueReadBuffer</strong>, <strong>clEnqueueReadBufferRect</strong>,</p>
+</li>
+<li>
+<p><strong>clEnqueueWriteBuffer</strong>, <strong>clEnqueueWriteBufferRect</strong>,</p>
+</li>
+<li>
+<p>blocking calls to <strong>clEnqueueReadImage</strong> and <strong>clEnqueueWriteImage</strong>,</p>
+</li>
+<li>
+<p>blocking calls to <strong>clEnqueueMapBuffer</strong> and <strong>clEnqueueMapImage</strong>,</p>
+</li>
+<li>
+<p>blocking calls to <strong>clBuildProgram</strong>, <strong>clCompileProgram</strong> or
+<strong>clLinkProgram</strong>,</p>
+</li>
+<li>
+<p>blocking calls to <strong>clEnqueueSVMMemcpy</strong> or <strong>clEnqueueSVMMap</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If an application needs to wait for completion of a routine from the above
+list in a callback, please use the non-blocking form of the function, and
+assign a completion callback to it to do the remainder of your work.
+Note that when a callback (or other code) enqueues commands to a
+command-queue, the commands are not required to begin execution until the
+queue is flushed.
+In standard usage, blocking enqueue calls serve this role by implicitly
+flushing the queue.
+Since blocking calls are not permitted in callbacks, those callbacks that
+enqueue commands on a command queue should either call <strong>clFlush</strong> on the
+queue before returning or arrange for <strong>clFlush</strong> to be called later on
+another thread.</p>
+</div>
+<div class="paragraph">
+<p><strong>clSetEventCallback</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_EVENT if <em>event</em> is not a valid event object.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>pfn_event_notify</em> is <code>NULL</code> or if
+<em>command_exec_callback_type</em> is not CL_SUBMITTED, CL_RUNNING or</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clRetainEvent(cl_event event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>increments the <em>event</em> reference count.
+The OpenCL commands that return an event perform an implicit retain.</p>
+</div>
+<div class="paragraph">
+<p><strong>clRetainEvent</strong> returns CL_SUCCESS if the function is executed successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_EVENT if <em>event</em> is not a valid event object.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>To release an event, use the following function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clReleaseEvent(cl_event event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>decrements the <em>event</em> reference count.</p>
+</div>
+<div class="paragraph">
+<p><strong>clReleaseEvent</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_EVENT if <em>event</em> is not a valid event object.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The event object is deleted once the reference count becomes zero, the
+specific command identified by this event has completed (or terminated) and
+there are no commands in the command-queues of a context that require a wait
+for this event to complete.
+Using this function to release a reference that was not obtained by creating
+the object or by calling <strong>clRetainEvent</strong> causes undefined behavior.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>Developers should be careful when releasing their last reference count on
+events created by <strong>clCreateUserEvent</strong> that have not yet been set to status
+of CL_COMPLETE or an error.
+If the user event was used in the event_wait_list argument passed to a
+<strong>clEnqueue*</strong> API or another application host thread is waiting for it in
+<strong>clWaitForEvents</strong>, those commands and host threads will continue to wait for
+the event status to reach CL_COMPLETE or error, even after the application
+has released the object.
+Since in this scenario the application has released its last reference count
+to the user event, it would be in principle no longer valid for the
+application to change the status of the event to unblock all the other
+machinery.
+As a result the waiting tasks will wait forever, and associated events,
+cl_mem objects, command queues and contexts are likely to leak.
+In-order command queues caught up in this deadlock may cease to do any work.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+</div>
+<div class="sect2">
+<h3 id="markers-barriers-waiting-for-events">5.12. Markers, Barriers and Waiting for Events</h3>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueMarkerWithWaitList(cl_command_queue command_queue,
+                                   cl_uint num_events_in_wait_list,
+                                   <span class="directive">const</span> cl_event *event_wait_list,
+                                   cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>enqueues a marker command which waits for either a list of events to
+complete, or if the list is empty it waits for all commands previously
+enqueued in <em>command_queue</em> to complete before it completes.
+This command returns an <em>event</em> which can be waited on, i.e. this event can
+be waited on to insure that all events either in the <em>event_wait_list</em> or
+all previously enqueued commands, queued before this command to
+<em>command_queue</em>, have completed.</p>
+</div>
+<div class="paragraph">
+<p><em>command_queue</em> is a valid host command-queue.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before this particular command can be executed.</p>
+</div>
+<div class="paragraph">
+<p>If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event_wait_list</em> act as synchronization points.
+The context associated with events in <em>event_wait_list</em> and <em>command_queue</em>
+must be the same.
+The memory associated with <em>event_wait_list</em> can be reused or freed after
+the function returns.</p>
+</div>
+<div class="paragraph">
+<p>If <em>event_wait_list</em> is <code>NULL</code>, then this particular command waits until all
+previous enqueued commands to <em>command_queue</em> have completed.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> returns an event object that identifies this particular command.
+Event objects are unique and can be used to identify this marker command
+later on.
+<em>event</em> can be <code>NULL</code> in which case it will not be possible for the
+application to query the status of this command or queue a wait for this
+command to complete.
+If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the
+<em>event</em> argument should not refer to an element of the <em>event_wait_list</em>
+array.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueMarkerWithWaitList</strong> returns CL_SUCCESS if the function is
+successfully executed.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if context associated with <em>command_queue</em> and events
+in <em>event_wait_list</em> are not the same.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clEnqueueBarrierWithWaitList(cl_command_queue command_queue,
+                                    cl_uint num_events_in_wait_list,
+                                    <span class="directive">const</span> cl_event *event_wait_list,
+                                    cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>enqueues a barrier command which waits for either a list of events to
+complete, or if the list is empty it waits for all commands previously
+enqueued in <em>command_queue</em> to complete before it completes.
+This command blocks command execution, that is, any following commands
+enqueued after it do not execute until it completes.
+This command returns an <em>event</em> which can be waited on, i.e. this event can
+be waited on to insure that all events either in the <em>event_wait_list</em> or
+all previously enqueued commands, queued before this command to
+<em>command_queue</em>, have completed</p>
+</div>
+<div class="paragraph">
+<p><em>command_queue</em> is a valid host command-queue.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before this particular command can be executed.</p>
+</div>
+<div class="paragraph">
+<p>If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event_wait_list</em> act as synchronization points.
+The context associated with events in <em>event_wait_list</em> and <em>command_queue</em>
+must be the same.
+The memory associated with <em>event_wait_list</em> can be reused or freed after
+the function returns.</p>
+</div>
+<div class="paragraph">
+<p>If <em>event_wait_list</em> is <code>NULL</code>, then this particular command waits until all
+previous enqueued commands to <em>command_queue</em> have completed.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> returns an event object that identifies this particular command.
+Event objects are unique and can be used to identify this barrier command
+later on.
+<em>event</em> can be <code>NULL</code> in which case it will not be possible for the
+application to query the status of this command or queue a wait for this
+command to complete.
+If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the
+<em>event</em> argument should not refer to an element of the <em>event_wait_list</em>
+array.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueBarrierWithWaitList</strong> returns CL_SUCCESS if the function is
+successfully executed.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if context associated with <em>command_queue</em> and events
+in <em>event_wait_list</em> are not the same.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_out_of_order_execution_of_kernels_and_memory_object_commands">5.13. Out-of-order Execution of Kernels and Memory Object Commands</h3>
+<div class="paragraph">
+<p>The OpenCL functions that are submitted to a command-queue are enqueued in
+the order the calls are made but can be configured to execute in-order or
+out-of-order.
+The <em>properties</em> argument in <strong>clCreateCommandQueueWithProperties</strong> can be
+used to specify the execution order.</p>
+</div>
+<div class="paragraph">
+<p>If the CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE property of a command-queue is
+not set, the commands enqueued to a command-queue execute in order.
+For example, if an application calls <strong>clEnqueueNDRangeKernel</strong> to execute
+kernel A followed by a <strong>clEnqueueNDRangeKernel</strong> to execute kernel B, the
+application can assume that kernel A finishes first and then kernel B is
+executed.
+If the memory objects output by kernel A are inputs to kernel B then kernel
+B will see the correct data in memory objects produced by execution of
+kernel A.
+If the CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE property of a command-queue is
+set, then there is no guarantee that kernel A will finish before kernel B
+starts execution.</p>
+</div>
+<div class="paragraph">
+<p>Applications can configure the commands enqueued to a command-queue to
+execute out-of-order by setting the CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE
+property of the command-queue.
+This can be specified when the command-queue is created.
+In out-of-order execution mode there is no guarantee that the enqueued
+commands will finish execution in the order they were queued.
+As there is no guarantee that kernels will be executed in order, i.e. based
+on when the <strong>clEnqueueNDRangeKernel</strong> calls are made within a command-queue,
+it is therefore possible that an earlier <strong>clEnqueueNDRangeKernel</strong> call to
+execute kernel A identified by event A may execute and/or finish later than
+a <strong>clEnqueueNDRangeKernel</strong> call to execute kernel B which was called by the
+application at a later point in time.
+To guarantee a specific order of execution of kernels, a wait on a
+particular event (in this case event A) can be used.
+The wait for event A can be specified in the <em>event_wait_list</em> argument to
+<strong>clEnqueueNDRangeKernel</strong> for kernel B.</p>
+</div>
+<div class="paragraph">
+<p>In addition, a marker (<strong>clEnqueueMarkerWithWaitList</strong>) or a barrier
+(<strong>clEnqueueBarrierWithWaitList</strong>) command can be enqueued to the
+command-queue.
+The marker command ensures that previously enqueued commands identified by
+the list of events to wait for (or all previous commands) have finished.
+A barrier command is similar to a marker command, but additionally
+guarantees that no later-enqueued commands will execute until the waited-for
+commands have executed.</p>
+</div>
+<div class="paragraph">
+<p>Similarly, commands to read, write, copy or map memory objects that are
+enqueued after <strong>clEnqueueNDRangeKernel</strong> or <strong>clEnqueueNativeKernel</strong> commands
+are not guaranteed to wait for kernels scheduled for execution to have
+completed (if the CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE property is set).
+To ensure correct ordering of commands, the event object returned by
+<strong>clEnqueueNDRangeKernel</strong> or <strong>clEnqueueNativeKernel</strong> can be used to enqueue a
+wait for event or a barrier command can be enqueued that must complete
+before reads or writes to the memory object(s) occur.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="profiling-operations">5.14. Profiling Operations on Memory Objects and Kernels</h3>
+<div class="paragraph">
+<p>This section describes profiling of OpenCL functions that are enqueued as
+commands to a command-queue.
+The specific functions<sup>22</sup> being referred to are:
+<strong>clEnqueue{Read|Write|Map}Buffer</strong>, <strong>clEnqueue{Read|Write}BufferRect</strong>,
+<strong>clEnqueue{Read|Write|Map}Image</strong>, <strong>clEnqueueUnmapMemObject</strong>,
+<strong>clEnqueueSVMMemcpy</strong>, <strong>clEnqueueSVMMemFill</strong>, <strong>clEnqueueSVMMap</strong>,
+<strong>clEnqueueSVMUnmap</strong>, <strong>clEnqueueSVMFree</strong>, <strong>clEnqueueCopyBuffer</strong>,
+<strong>clEnqueueCopyBufferRect</strong>, <strong>clEnqueueCopyImage</strong>,
+<strong>clEnqueueCopyImageToBuffer</strong>, <strong>clEnqueueCopyBufferToImage</strong>,
+<strong>clEnqueueNDRangeKernel</strong> and <strong>clEnqueueNativeKernel</strong>.
+These enqueued commands are identified by unique event objects.</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1">22</dt>
+<dd>
+<p><strong>clEnqueueAcquireGLObjects</strong> and <strong>clEnqueueReleaseGLObjects</strong> defined in
+<em>section 9.4.6</em> of the OpenCL 2.2 Extension Specification are also
+included.</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>Event objects can be used to capture profiling information that measure
+execution time of a command.
+Profiling of OpenCL commands can be enabled either by using a command-queue
+created with CL_QUEUE_PROFILING_ENABLE flag set in <em>properties</em> argument to
+<strong>clCreateCommandQueueWithProperties</strong>.</p>
+</div>
+<div class="paragraph">
+<p>If profiling is enabled, the function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clGetEventProfilingInfo(cl_event event,
+                               cl_profiling_info param_name,
+                               size_t param_value_size,
+                               <span class="directive">void</span> *param_value,
+                               size_t *param_value_size_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>returns profiling information for the command associated with event.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> specifies the event object.</p>
+</div>
+<div class="paragraph">
+<p><em>param_name</em> specifies the profiling data to query.
+The list of supported <em>param_name</em> types and the information returned in
+<em>param_value</em> by <strong>clGetEventProfilingInfo</strong> is described in the
+<a href="#event-profiling-info-table">Event Profiling Queries</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value</em> is a pointer to memory where the appropriate result being
+queried is returned.
+If <em>param_value</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size</em> is used to specify the size in bytes of memory pointed to
+by <em>param_value</em>.
+This size must be ≥ size of return type as described in the
+<a href="#event-profiling-info-table">Event Profiling Queries</a> table.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size_ret</em> returns the actual size in bytes of data being
+queried by <em>param_name</em>.
+If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<table id="event-profiling-info-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 34. <strong>clGetEventProfilingInfo</strong> parameter queries</caption>
+<colgroup>
+<col style="width: 34%;">
+<col style="width: 33%;">
+<col style="width: 33%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_profiling_info</strong></th>
+<th class="tableblock halign-left valign-top">Return Type</th>
+<th class="tableblock halign-left valign-top">Info. returned in <em>param_value</em></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROFILING_COMMAND_QUEUED</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_ulong</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 64-bit value that describes the current device time counter in
+        nanoseconds when the command identified by event is enqueued in a
+        command-queue by the host.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROFILING_COMMAND_SUBMIT</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_ulong</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 64-bit value that describes the current device time counter in
+        nanoseconds when the command identified by event that has been
+        enqueued is submitted by the host to the device associated with the
+        command-queue.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROFILING_COMMAND_START</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_ulong</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 64-bit value that describes the current device time counter in
+        nanoseconds when the command identified by event starts execution on
+        the device.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROFILING_COMMAND_END</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_ulong</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 64-bit value that describes the current device time counter in
+        nanoseconds when the command identified by event has finished
+        execution on the device.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROFILING_COMMAND_COMPLETE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_ulong</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 64-bit value that describes the current device time counter in
+        nanoseconds when the command identified by event and any child
+        commands enqueued by this command on the device have finished
+        execution.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>The unsigned 64-bit values returned can be used to measure the time in
+nano-seconds consumed by OpenCL commands.</p>
+</div>
+<div class="paragraph">
+<p>OpenCL devices are required to correctly track time across changes in device
+frequency and power states.
+The CL_DEVICE_PROFILING_TIMER_RESOLUTION specifies the resolution of the
+timer i.e. the number of nanoseconds elapsed before the timer is
+incremented.</p>
+</div>
+<div class="paragraph">
+<p><strong>clGetEventProfilingInfo</strong> returns CL_SUCCESS if the function is executed
+successfully and the profiling information has been recorded.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_PROFILING_INFO_NOT_AVAILABLE if the CL_QUEUE_PROFILING_ENABLE flag is
+not set for the command-queue, if the execution status of the command
+identified by <em>event</em> is not CL_COMPLETE or if <em>event</em> refers to the
+<strong>clEnqueueSVMFree</strong> command or is a user event object.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>param_name</em> is not valid, or if size in bytes
+specified by <em>param_value_size</em> is &lt; size of return type as described in
+the <a href="#event-profiling-info-table">Event Profiling Queries</a> table and
+<em>param_value</em> is not <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT if <em>event</em> is a not a valid event object.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_flush_and_finish">5.15. Flush and Finish</h3>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clFlush(cl_command_queue command_queue)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>issues all previously queued OpenCL commands in <em>command_queue_to the device
+associated with_command_queue</em>.
+<strong>clFlush</strong> only guarantees that all queued commands to <em>command_queue</em> will
+eventually be submitted to the appropriate device.
+There is no guarantee that they will be complete after <strong>clFlush</strong> returns.</p>
+</div>
+<div class="paragraph">
+<p><strong>clFlush</strong> returns CL_SUCCESS if the function call was executed successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host
+command-queue.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Any blocking commands queued in a command-queue and <strong>clReleaseCommandQueue</strong>
+perform an implicit flush of the command-queue.
+These blocking commands are <strong>clEnqueueReadBuffer</strong>,
+<strong>clEnqueueReadBufferRect</strong>, <strong>clEnqueueReadImage</strong>, with <em>blocking_read</em> set to
+CL_TRUE; <strong>clEnqueueWriteBuffer</strong>, <strong>clEnqueueWriteBufferRect</strong>,
+<strong>clEnqueueWriteImage</strong> with <em>blocking_write</em> set to CL_TRUE;
+<strong>clEnqueueMapBuffer</strong>, <strong>clEnqueueMapImage</strong> with <em>blocking_map</em> set to
+CL_TRUE; <strong>clEnqueueSVMMemcpy</strong> with <em>blocking_copy</em> set to CL_TRUE;
+<strong>clEnqueueSVMMap</strong> with <em>blocking_map</em> set to CL_TRUE or <strong>clWaitForEvents</strong>.</p>
+</div>
+<div class="paragraph">
+<p>To use event objects that refer to commands enqueued in a command-queue as
+event objects to wait on by commands enqueued in a different command-queue,
+the application must call a <strong>clFlush</strong> or any blocking commands that perform
+an implicit flush of the command-queue where the commands that refer to
+these event objects are enqueued.</p>
+</div>
+<div class="paragraph">
+<p>The function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_int clFinish(cl_command_queue command_queue)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>blocks until all previously queued OpenCL commands in <em>command_queue</em> are
+issued to the associated device and have completed.
+<strong>clFinish</strong> does not return until all previously queued commands in
+<em>command_queue</em> have been processed and completed.
+<strong>clFinish</strong> is also a synchronization point.</p>
+</div>
+<div class="paragraph">
+<p><strong>clFinish</strong> returns CL_SUCCESS if the function call was executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid host
+command-queue.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_associated_opencl_specification">6. Associated OpenCL specification</h2>
+<div class="sectionbody">
+<div class="sect2">
+<h3 id="spirv-il">6.1. SPIR-V Intermediate language</h3>
+<div class="paragraph">
+<p>The OpenCL 2.2 specification requires support for the SPIR-V intermediate
+language that allows offline, or linked online, compilation to a binary
+format that may be consumed by the <strong>clCreateProgramWithIL</strong> interface.</p>
+</div>
+<div class="paragraph">
+<p>The OpenCL specification includes a specification for the SPIR-V 1.2
+intermediate language as a cross-platform input language.
+In addition, platform vendors may support their own IL if this is
+appropriate.
+The OpenCL runtime will return a list of supported IL versions using the
+<strong>CL_DEVICE_IL_VERSION</strong> parameter to the <strong>clGetDeviceInfo</strong> query.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="opencl-extensions">6.2. Extensions to OpenCL</h3>
+<div class="paragraph">
+<p>In addition to the specification of core features, OpenCL provides a number
+of extensions to the API, kernel language or intermediate representation.
+These features are defined in the OpenCL 2.2 extensions specification
+document.</p>
+</div>
+<div class="paragraph">
+<p>Extensions defined against earlier versions of the OpenCL specifications,
+whether the API or language specification, are defined in the matching
+versions of the extension specification document.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_support_for_earlier_opencl_c_kernel_languages">6.3. Support for earlier OpenCL C kernel languages</h3>
+<div class="paragraph">
+<p>The OpenCL C kernel language is not defined in the OpenCL 2.2 specification.
+New language features are described in the OpenCL C++ specification as well
+as the SPIR-V 1.2 specification and in kernel languages that target it.
+A kernel language defined by any of the OpenCL 1.0, OpenCL 1.1, OpenCL 1.2
+and OpenCL 2.0 kernel language specifications as well as kernels language
+extensions defined by the matching versions of OpenCL extension
+specifications are valid to pass to <strong>clCreateProgramWithSource</strong> executing
+against an OpenCL 2.2 runtime.</p>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="opencl-embedded-profile">7. OpenCL Embedded Profile</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>The OpenCL 2.2 specification describes the feature requirements for desktop
+platforms.
+This section describes the OpenCL 2.2 embedded profile that allows us to
+target a subset of the OpenCL 2.2 specification for handheld and embedded
+platforms.
+The optional extensions defined in the OpenCL 2.2 Extension Specification
+apply to both profiles.</p>
+</div>
+<div class="paragraph">
+<p>The OpenCL 2.2 embedded profile has the following restrictions:</p>
+</div>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>64 bit integers i.e. long, ulong including the appropriate vector data
+types and operations on 64-bit integers are optional.
+The <strong>cles_khr_int64</strong><sup>1</sup> extension string will be reported if the
+embedded profile implementation supports 64-bit integers.</p>
+<div class="openblock">
+<div class="content">
+<div class="dlist">
+<dl>
+<dt class="hdlist1">1</dt>
+<dd>
+<p>Note that the performance of 64-bit integer arithmetic can vary
+significantly between embedded devices.</p>
+</dd>
+</dl>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p><span class="line-through">Support for 3D images is optional.</span></p>
+<div class="openblock line-through">
+<div class="content">
+<div class="paragraph">
+<p>If <strong>CL_DEVICE_IMAGE3D_MAX_WIDTH</strong>, <strong>CL_DEVICE_IMAGE3D_MAX_HEIGHT</strong> and
+<strong>CL_DEVICE_IMAGE3D_MAX_DEPTH</strong> are zero, the call to <strong>clCreateImage</strong> in the
+embedded profile will fail to create the 3D image.
+The <em>errcode_ret</em> argument in <strong>clCreateImage</strong> returns CL_INVALID_OPERATION.
+Declaring arguments of type <code>image3d_t</code> in a kernel will result in a
+compilation error.</p>
+</div>
+<div class="paragraph">
+<p>If <strong>CL_DEVICE_IMAGE3D_MAX_WIDTH</strong>, <strong>CL_DEVICE_IMAGE3D_MAX_HEIGHT</strong> and
+CL_DEVICE_IMAGE3D_MAX_DEPTH &gt; 0, 3D images are supported by the OpenCL
+embedded profile implementation.
+<strong>clCreateImage</strong> will work as defined by the OpenCL specification.
+The <code>image3d_t</code> data type can be used in a kernel(s).</p>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p><span class="line-through">Support for 2D image array writes is optional.
+If the <strong>cles_khr_2d_image_array_writes</strong> extension is supported by the
+embedded profile, writes to 2D image arrays are supported.</span></p>
+</li>
+<li>
+<p><span class="line-through">Image and image arrays created with an
+<code>image_channel_data_type</code> value of CL_FLOAT or CL_HALF_FLOAT can only be
+used with samplers that use a filter mode of CL_FILTER_NEAREST.
+The values returned by <strong>read_imagef</strong> and <strong>read_imageh</strong><sup>2</sup> for 2D and 3D
+images if <code>image_channel_data_type</code> value is CL_FLOAT or CL_HALF_FLOAT
+and sampler with filter_mode = CL_FILTER_LINEAR are undefined.</span></p>
+<div class="openblock">
+<div class="content">
+<div class="dlist">
+<dl>
+<dt class="hdlist1">2</dt>
+<dd>
+<p>If <strong>cl_khr_fp16</strong> extension is supported.</p>
+</dd>
+</dl>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p>The mandated minimum single precision floating-point capability given by
+CL_DEVICE_SINGLE_FP_CONFIG is CL_FP_ROUND_TO_ZERO or
+CL_FP_ROUND_TO_NEAREST.
+If CL_FP_ROUND_TO_NEAREST is supported, the default rounding mode will
+be round to nearest even; otherwise the default rounding mode will be
+round to zero.</p>
+</li>
+<li>
+<p>The single precision floating-point operations (addition, subtraction
+and multiplication) shall be correctly rounded.
+Zero results may always be positive 0.0.
+The accuracy of division and sqrt are given in the SPIR-V OpenCL
+environment specification.</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>If CL_FP_INF_NAN is not set in CL_DEVICE_SINGLE_FP_CONFIG, and one of the
+operands or the result of addition, subtraction, multiplication or division
+would signal the overflow or invalid exception (see IEEE 754 specification),
+the value of the result is implementation-defined.
+Likewise, single precision comparison operators (&lt;, &gt;, &lt;=, &gt;=, ==,
+!=) return implementation-defined values when one or more operands is a
+NaN.</p>
+</div>
+<div class="paragraph">
+<p>In all cases, conversions (see the SPIR-V OpenCL environment specification)
+shall be correctly rounded as described for the FULL_PROFILE, including
+those that consume or produce an INF or NaN.
+The built-in math functions shall behave as described for the FULL_PROFILE,
+including edge case behavior but with slightly different accuracy rules.
+Edge case behavior and accuracy rules are described in the SPIR-V OpenCL
+environment specification.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="title">Note</div>
+<div class="paragraph">
+<p>If addition, subtraction and multiplication have default round to zero
+rounding mode, then <strong>fract</strong>, <strong>fma</strong> and <strong>fdim</strong> shall produce the correctly
+rounded result for round to zero rounding mode.</p>
+</div>
+<div class="paragraph">
+<p>This relaxation of the requirement to adhere to IEEE 754 requirements for
+basic floating-point operations, though extremely undesirable, is to provide
+flexibility for embedded devices that have lot stricter requirements on
+hardware area budgets.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p>Denormalized numbers for the half data type which may be generated when
+converting a float to a half using variants of the <strong>vstore_half</strong>
+function or when converting from a half to a float using variants of the
+<strong>vload_half</strong> function can be flushed to zero.
+The SPIR-V environment specification for details.</p>
+</li>
+<li>
+<p>The precision of conversions from CL_UNORM_INT8, CL_SNORM_INT8,
+CL_UNORM_INT16, CL_SNORM_INT16, CL_UNORM_INT_101010 and
+CL_UNORM_INT_101010_2 to float is ≤ 2 ulp for the embedded profile
+instead of ≤ 1.5 ulp as defined in the full profile.
+The exception cases described in the full profile and given below apply
+to the embedded profile.</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>For CL_UNORM_INT8</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>0 must convert to 0.0f and</p>
+</li>
+<li>
+<p>255 must convert to 1.0f</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For CL_UNORM_INT16</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>0 must convert to 0.0f and</p>
+</li>
+<li>
+<p>65535 must convert to 1.0f</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For CL_SNORM_INT8</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>-128 and -127 must convert to -1.0f,</p>
+</li>
+<li>
+<p>0 must convert to 0.0f and</p>
+</li>
+<li>
+<p>127 must convert to 1.0f</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For CL_SNORM_INT16</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>-32768 and -32767 must convert to -1.0f,</p>
+</li>
+<li>
+<p>0 must convert to 0.0f and</p>
+</li>
+<li>
+<p>32767 must convert to 1.0f</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For CL_UNORM_INT_101010</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>0 must convert to 0.0f and</p>
+</li>
+<li>
+<p>1023 must convert to 1.0f</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For CL_UNORM_INT_101010_2</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>0 must convert to 0.0f and</p>
+</li>
+<li>
+<p>1023 must convert to 1.0f (for RGB)</p>
+</li>
+<li>
+<p>3 must convert to 1.0f (for A)</p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+</li>
+</ol>
+</div>
+<div class="paragraph">
+<p>The following optional extensions defined in the OpenCL 2.2 Extension
+Specification are available to the embedded profile:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>cl_khr_int64_base_atomics</strong></p>
+</li>
+<li>
+<p><strong>cl_khr_int64_extended_atomics</strong></p>
+</li>
+<li>
+<p><strong>cl_khr_fp16</strong></p>
+</li>
+<li>
+<p><strong>cles_khr_int64</strong>.
+If double precision is supported i.e. CL_DEVICE_DOUBLE_FP_CONFIG is not
+zero, then cles_khr_int64 must also be supported.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>CL_PLATFORM_PROFILE defined in the <a href="#platform-queries-table">OpenCL Platform
+Queries</a> table will return the string EMBEDDED_PROFILE if the OpenCL
+implementation supports the embedded profile only.</p>
+</div>
+<div class="paragraph">
+<p>The minimum maximum values specified in the <a href="#device-queries-table">OpenCL
+Device Queries</a> table that have been modified for the OpenCL embedded
+profile are listed in the <a href="#embedded-device-queries-table">OpenCL Embedded
+Device Queries</a> table.</p>
+</div>
+<table id="embedded-device-queries-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 35. OpenCL Embedded Device Queries</caption>
+<colgroup>
+<col style="width: 33.3333%;">
+<col style="width: 33.3333%;">
+<col style="width: 33.3334%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_device_info</strong></th>
+<th class="tableblock halign-left valign-top">Return Type</th>
+<th class="tableblock halign-left valign-top">Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_MAX_READ_IMAGE_ARGS</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Max number of image objects arguments of a kernel declared with the
+        <code>read_only</code> qualifier.
+        The minimum value is 8 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_MAX_WRITE_IMAGE_ARGS</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Max number of image objects arguments of a kernel declared with the
+        <code>write_only</code> qualifier.
+        The minimum value is 8 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Max number of image objects arguments of a kernel declared with the
+        <code>write_only</code> or <code>read_write</code> qualifier.
+        The minimum value is 8 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_IMAGE2D_MAX_WIDTH</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Max width of 2D image in pixels.
+        The minimum value is 2048 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_IMAGE2D_MAX_HEIGHT</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Max height of 2D image in pixels.
+        The minimum value is 2048 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_IMAGE3D_MAX_WIDTH</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Max width of 3D image in pixels.
+        The minimum value is 2048 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_IMAGE3D_MAX_HEIGHT</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Max height of 3D image in pixels.
+        The minimum value is 2048.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_IMAGE3D_MAX_DEPTH</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Max depth of 3D image in pixels.
+        The minimum value is 2048.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_IMAGE_MAX_BUFFER_SIZE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Max number of pixels for a 1D image created from a buffer object.</p>
+<p class="tableblock">        The minimum value is 2048 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_IMAGE_MAX_ARRAY_SIZE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Max number of images in a 1D or 2D image array.</p>
+<p class="tableblock">        The minimum value is 256 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_MAX_SAMPLERS</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Maximum number of samplers that can be used in a kernel.</p>
+<p class="tableblock">        The minimum value is 8 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_MAX_PARAMETER_SIZE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Max size in bytes of all arguments that can be passed to a kernel.
+        The minimum value is 256 bytes for devices that are not of type
+        CL_DEVICE_TYPE_CUSTOM.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_SINGLE_FP_CONFIG</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_fp_config</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Describes single precision floatingpoint capability of the device.
+        This is a bit-field that describes one or more of the following
+        values:</p>
+<p class="tableblock">        CL_FP_DENORM - denorms are supported</p>
+<p class="tableblock">        CL_FP_INF_NAN - INF and quiet NaNs are supported.</p>
+<p class="tableblock">        CL_FP_ROUND_TO_NEAREST - round to nearest even rounding mode
+        supported</p>
+<p class="tableblock">        CL_FP_ROUND_TO_ZERO - round to zero rounding mode supported</p>
+<p class="tableblock">        CL_FP_ROUND_TO_INF - round to positive and negative infinity
+        rounding modes supported</p>
+<p class="tableblock">        CL_FP_FMA - IEEE754-2008 fused multiply-add is supported.</p>
+<p class="tableblock">        CL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT - divide and sqrt are correctly
+        rounded as defined by the IEEE754 specification.</p>
+<p class="tableblock">        CL_FP_SOFT_FLOAT - Basic floating-point operations (such as
+        addition, subtraction, multiplication) are implemented in software.</p>
+<p class="tableblock">        The mandated minimum floating-point capability is:
+        CL_FP_ROUND_TO_ZERO or CL_FP_ROUND_TO_NEAREST for devices that are
+        not of type CL_DEVICE_TYPE_CUSTOM.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_ulong</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Max size in bytes of a constant buffer allocation.
+        The minimum value is 1 KB for devices that are not of type
+        CL_DEVICE_TYPE_CUSTOM.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_MAX_CONSTANT_ARGS</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Max number of arguments declared with the <code>__constant</code> qualifier
+        in a kernel.
+        The minimum value is 4 for devices that are not of type
+        CL_DEVICE_TYPE_CUSTOM.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_LOCAL_MEM_SIZE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_ulong</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Size of local memory arena in bytes.
+        The minimum value is 1 KB for devices that are not of type
+        CL_DEVICE_TYPE_CUSTOM.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_COMPILER_AVAILABLE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Is CL_FALSE if the implementation does not have a compiler available
+        to compile the program source.</p>
+<p class="tableblock">        Is CL_TRUE if the compiler is available.
+        This can be CL_FALSE for the embedded platform profile only.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_LINKER_AVAILABLE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_bool</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Is CL_FALSE if the implementation does not have a linker available.
+        Is CL_TRUE if the linker is available.</p>
+<p class="tableblock">        This can be CL_FALSE for the embedded platform profile only.</p>
+<p class="tableblock">        This must be CL_TRUE if CL_DEVICE_COMPILER_AVAILABLE is CL_TRUE.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_uint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The max. size of the device queue in bytes.
+        The minimum value is 64 KB for the embedded profile</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_PRINTF_BUFFER_SIZE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Maximum size in bytes of the internal buffer that holds the output
+        of printf calls from a kernel.
+        The minimum value for the EMBEDDED profile is 1 KB.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>If CL_DEVICE_IMAGE_SUPPORT specified in the <a href="#device-queries-table">OpenCL
+Device Queries</a> table is CL_TRUE, the values assigned to
+CL_DEVICE_MAX_READ_IMAGE_ARGS, CL_DEVICE_MAX_WRITE_IMAGE_ARGS,
+CL_DEVICE_IMAGE2D_MAX_WIDTH, CL_DEVICE_IMAGE2D_MAX_HEIGHT,
+CL_DEVICE_IMAGE3D_MAX_WIDTH, CL_DEVICE_IMAGE3D_MAX_HEIGHT,
+CL_DEVICE_IMAGE3D_MAX_DEPTH and CL_DEVICE_MAX_SAMPLERS by the implementation
+must be greater than or equal to the minimum values specified in the
+<a href="#embedded-device-queries-table">OpenCL Embedded Device Queries</a> table.</p>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_shared_objects_thread_safety">Appendix A: Shared Objects, Thread Safety</h2>
+<div class="sectionbody">
+<div class="sect2">
+<h3 id="shared-opencl-objects">Shared OpenCL Objects</h3>
+<div class="paragraph">
+<p>This section describes which objects can be shared across multiple
+command-queues created within a host process.</p>
+</div>
+<div class="paragraph">
+<p>OpenCL memory objects, program objects and kernel objects are created using
+a context and can be shared across multiple command-queues created using the
+same context.
+Event objects can be created when a command is queued to a command-queue.
+These event objects can be shared across multiple command-queues created
+using the same context.</p>
+</div>
+<div class="paragraph">
+<p>The application needs to implement appropriate synchronization across
+threads on the host processor to ensure that the changes to the state of a
+shared object (such as a command-queue object, memory object, program or
+kernel object) happen in the correct order (deemed correct by the
+application) when multiple command-queues in multiple threads are making
+changes to the state of a shared object.</p>
+</div>
+<div class="paragraph">
+<p>A command-queue can cache changes to the state of a memory object on the
+device associated with the command-queue.
+To synchronize changes to a memory object across command-queues, the
+application must do the following:</p>
+</div>
+<div class="paragraph">
+<p>In the command-queue that includes commands that modify the state of a
+memory object, the application must do the following:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Get appropriate event objects for commands that modify the state of the
+shared memory object.</p>
+</li>
+<li>
+<p>Call the <strong>clFlush</strong> (or <strong>clFinish</strong>) API to issue any outstanding commands
+from this command-queue.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>In the command-queue that wants to synchronize to the latest state of a
+memory object, commands queued by the application must use the appropriate
+event objects that represent commands that modify the state of the shared
+memory object as event objects to wait on.
+This is to ensure that commands that use this shared memory object complete
+in the previous command-queue before the memory objects are used by commands
+executing in this command-queue.</p>
+</div>
+<div class="paragraph">
+<p>The results of modifying a shared resource in one command-queue while it is
+being used by another command-queue are undefined.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_multiple_host_threads">Multiple Host Threads</h3>
+<div class="paragraph">
+<p>All OpenCL API calls are thread-safe<sup>1</sup> except those that modify the state
+of cl_kernel objects: <strong>clSetKernelArg</strong>, <strong>clSetKernelArgSVMPointer</strong>,
+<strong>clSetKernelExecInfo</strong> and <strong>clCloneKernel</strong>.
+<strong>clSetKernelArg</strong> , <strong>clSetKernelArgSVMPointer</strong>, <strong>clSetKernelExecInfo</strong> and
+<strong>clCloneKernel</strong> are safe to call from any host thread, and safe to call
+re-entrantly so long as concurrent calls to any combination of these API
+calls operate on different cl_kernel objects.
+The state of the cl_kernel object is undefined if <strong>clSetKernelArg</strong>,
+<strong>clSetKernelArgSVMPointer</strong>, <strong>clSetKernelExecInfo</strong> or <strong>clCloneKernel</strong> are
+called from multiple host threads on the same cl_kernel object at the same
+time<sup>2</sup>.
+Please note that there are additional limitations as to which OpenCL APIs
+may be called from <a href="#event-objects">OpenCL callback functions</a>.</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1">1</dt>
+<dd>
+<p>Please refer to the OpenCL glossary for the OpenCL definition of
+thread-safe.
+This definition may be different from usage of the term in other
+contexts.</p>
+</dd>
+<dt class="hdlist1">2</dt>
+<dd>
+<p>There is an inherent race condition in the design of OpenCL that occurs
+between setting a kernel argument and using the kernel with
+<strong>clEnqueueNDRangeKernel</strong>.
+Another host thread might change the kernel arguments between when a
+host thread sets the kernel arguments and then enqueues the kernel,
+causing the wrong kernel arguments to be enqueued.
+Rather than attempt to share cl_kernel objects among multiple host
+threads, applications are strongly encouraged to make additional
+cl_kernel objects for kernel functions for each host thread.</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>The behavior of OpenCL APIs called from an interrupt or signal handler is
+implementation-defined</p>
+</div>
+<div class="paragraph">
+<p>The OpenCL implementation should be able to create multiple command-queues
+for a given OpenCL context and multiple OpenCL contexts in an application
+running on the host processor.</p>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_portability">Appendix B: Portability</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>OpenCL is designed to be portable to other architectures and hardware
+designs.
+OpenCL has used at its core a C99 based programming language and follows
+rules based on that heritage.
+Floating-point arithmetic is based on the <strong>IEEE-754</strong> and <strong>IEEE-754-2008</strong>
+standards.
+The memory objects, pointer qualifiers and weakly ordered memory are
+designed to provide maximum compatibility with discrete memory architectures
+implemented by OpenCL devices.
+Command-queues and barriers allow for synchronization between the host and
+OpenCL devices.
+The design, capabilities and limitations of OpenCL are very much a
+reflection of the capabilities of underlying hardware.</p>
+</div>
+<div class="paragraph">
+<p>Unfortunately, there are a number of areas where idiosyncrasies of one
+hardware platform may allow it to do some things that do not work on
+another.
+By virtue of the rich operating system resident on the CPU, on some
+implementations the kernels executing on a CPU may be able to call out to
+system services whereas the same calls on the GPU will likely fail for now.
+Since there is some advantage to having these services available for
+debugging purposes, implementations can use the OpenCL extension mechanism
+to implement these services.</p>
+</div>
+<div class="paragraph">
+<p>Likewise, the heterogeneity of computing architectures might mean that a
+particular loop construct might execute at an acceptable speed on the CPU
+but very poorly on a GPU, for example.
+CPUs are designed in general to work well on latency sensitive algorithms on
+single threaded tasks, whereas common GPUs may encounter extremely long
+latencies, potentially orders of magnitude worse.
+A developer interested in writing portable code may find that it is
+necessary to test his design on a diversity of hardware designs to make sure
+that key algorithms are structured in a way that works well on a diversity
+of hardware.
+We suggest favoring more work-items over fewer.
+It is anticipated that over the coming months and years experience will
+produce a set of best practices that will help foster a uniformly favorable
+experience on a diversity of computing devices.</p>
+</div>
+<div class="paragraph">
+<p>Of somewhat more concern is the topic of endianness.
+Since a majority of devices supported by the initial implementation of
+OpenCL are little-endian, developers need to make sure that their kernels
+are tested on both big-endian and little-endian devices to ensure source
+compatibility with OpenCL devices now and in the future.
+The endian attribute qualifier is supported by the SPIR-V IL to allow
+developers to specify whether the data uses the endianness of the host or
+the OpenCL device.
+This allows the OpenCL compiler to do appropriate endian-conversion on load
+and store operations from or to this data.</p>
+</div>
+<div class="paragraph">
+<p>We also describe how endianness can leak into an implementation causing
+kernels to produce unintended results:</p>
+</div>
+<div class="paragraph">
+<p>When a big-endian vector machine (e.g. AltiVec, CELL SPE) loads a vector,
+the order of the data is retained.
+That is both the order of the bytes within each element and the order of the
+elements in the vector are the same as in memory.
+When a little-endian vector machine (e.g. SSE) loads a vector, the order of
+the data in register (where all the work is done) is reversed.
+<strong>Both</strong> the order of the bytes within each element and the order of the
+elements with respect to one another in the vector are reversed.</p>
+</div>
+<div class="paragraph">
+<p>Memory:</p>
+</div>
+<div class="paragraph">
+<p>uint4 a =</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 25%;">
+<col style="width: 25%;">
+<col style="width: 25%;">
+<col style="width: 25%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0x00010203</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0x04050607</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0x08090A0B</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0x0C0D0E0F</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>In register (big-endian):</p>
+</div>
+<div class="paragraph">
+<p>uint4 a =</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 25%;">
+<col style="width: 25%;">
+<col style="width: 25%;">
+<col style="width: 25%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0x00010203</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0x04050607</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0x08090A0B</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0x0C0D0E0F</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>In register (little-endian):</p>
+</div>
+<div class="paragraph">
+<p>uint4 a =</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 25%;">
+<col style="width: 25%;">
+<col style="width: 25%;">
+<col style="width: 25%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0x0F0E0D0C</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0x0B0A0908</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0x07060504</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0x03020100</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>This allows little-endian machines to use a single vector load to load
+little-endian data, regardless of how large each piece of data is in the
+vector.
+That is the transformation is equally valid whether that vector was a
+<code>uchar16</code> or a <code>ulong2</code>.
+Of course, as is well known, little-endian machines actually<sup>1</sup> store their
+data in reverse byte order to compensate for the little-endian storage
+format of the array elements:</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1">1</dt>
+<dd>
+<p>Note that we are talking about the programming model here.
+In reality, little endian systems might choose to simply address their
+bytes from "the right" or reverse the "order" of the bits in the byte.
+Either of these choices would mean that no big swap would need to occur
+in hardware.</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>Memory (big-endian):</p>
+</div>
+<div class="paragraph">
+<p>uint4 a =</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 25%;">
+<col style="width: 25%;">
+<col style="width: 25%;">
+<col style="width: 25%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0x00010203</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0x04050607</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0x08090A0B</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0x0C0D0E0F</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>Memory (little-endian):</p>
+</div>
+<div class="paragraph">
+<p>uint4 a =</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 25%;">
+<col style="width: 25%;">
+<col style="width: 25%;">
+<col style="width: 25%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0x03020100</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0x07060504</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0x0B0A0908</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0x0F0E0D0C</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>Once that data is loaded into a vector, we end up with this:</p>
+</div>
+<div class="paragraph">
+<p>In register (big-endian):</p>
+</div>
+<div class="paragraph">
+<p>uint4 a =</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 25%;">
+<col style="width: 25%;">
+<col style="width: 25%;">
+<col style="width: 25%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0x00010203</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0x04050607</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0x08090A0B</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0x0C0D0E0F</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>In register (little-endian):</p>
+</div>
+<div class="paragraph">
+<p>uint4 a =</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 25%;">
+<col style="width: 25%;">
+<col style="width: 25%;">
+<col style="width: 25%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0x0C0D0E0F</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0x08090A0B</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0x04050607</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0x00010203</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>That is, in the process of correcting the endianness of the bytes within
+each element, the machine ends up reversing the order that the elements
+appear in the vector with respect to each other within the vector.
+0x00010203 appears at the left of the big-endian vector and at the right of
+the little-endian vector.</p>
+</div>
+<div class="paragraph">
+<p>When the host and device have different endianness, the developer must
+ensure that kernel argument values are processed correctly.
+The implementation may or may not automatically convert endianness of kernel
+arguments.
+Developers should consult vendor documentation for guidance on how to handle
+kernel arguments in these situations.</p>
+</div>
+<div class="paragraph">
+<p>OpenCL provides a consistent programming model across architectures by
+numbering elements according to their order in memory.
+Concepts such as <code>even</code>/<code>odd</code> and <code>high</code>/<code>low</code> follow accordingly.
+Once the data is loaded into registers, we find that element 0 is at the
+left of the big-endian vector and element 0 is at the right of the
+little-endian vector:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="predefined-type">float</span> x[<span class="integer">4</span>];
+float4 v = vload4( <span class="integer">0</span>, x );</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Big-endian:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">v contains { x[<span class="integer">0</span>], x[<span class="integer">1</span>], x[<span class="integer">2</span>], x[<span class="integer">3</span>] }</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Little-endian:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">v contains { x[<span class="integer">3</span>], x[<span class="integer">2</span>], x[<span class="integer">1</span>], x[<span class="integer">0</span>] }</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The compiler is aware that this swap occurs and references elements
+accordingly.
+So long as we refer to them by a numeric index such as <code>.s0123456789abcdef</code>
+or by descriptors such as <code>.xyzw</code>, <code>.hi</code>, <code>.lo</code>, <code>.even</code> and <code>.odd</code>,
+everything works transparently.
+Any ordering reversal is undone when the data is stored back to memory.
+The developer should be able to work with a big-endian programming model and
+ignore the element ordering problem in the vector &#8230;&#8203; for most problems.
+This mechanism relies on the fact that we can rely on a consistent element
+numbering.
+Once we change numbering system, for example by conversion-free casting
+(using <code>as_type_</code><em>n</em>) a vector to another vector of the same size but a
+different number of elements, then we get different results on different
+implementations depending on whether the system is big-endian, or
+little-endian or indeed has no vector unit at all.
+(Thus, the behavior of bitcasts to vectors of different numbers of elements
+is implementation-defined, see section 1.2.4 of OpenCL 2.0C specification)</p>
+</div>
+<div class="paragraph">
+<p>An example follows:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="predefined-type">float</span> x[<span class="integer">4</span>] = { <span class="float">0</span><span class="float">.0f</span>, <span class="float">1</span><span class="float">.0f</span>, <span class="float">2</span><span class="float">.0f</span>, <span class="float">3</span><span class="float">.0f</span> };
+float4 v = vload4( <span class="integer">0</span>, x );
+uint4 y = as_uint4(v);      <span class="comment">// legal, portable</span>
+ushort8 z = as_ushort8(v);  <span class="comment">// legal, not portable</span>
+                            <span class="comment">// element size changed</span></code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Big-endian:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">v contains { <span class="float">0</span><span class="float">.0f</span>, <span class="float">1</span><span class="float">.0f</span>, <span class="float">2</span><span class="float">.0f</span>, <span class="float">3</span><span class="float">.0f</span> }
+y contains { <span class="hex">0x00000000</span>, <span class="hex">0x3f800000</span>,
+             <span class="hex">0x40000000</span>, <span class="hex">0x40400000</span> }
+z contains { <span class="hex">0x0000</span>, <span class="hex">0x0000</span>, <span class="hex">0x3f80</span>, <span class="hex">0x0000</span>,
+             <span class="hex">0x4000</span>, <span class="hex">0x0000</span>, <span class="hex">0x4040</span>, <span class="hex">0x0000</span> }
+z.z is <span class="hex">0x3f80</span></code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Little-endian:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">v contains { <span class="float">3</span><span class="float">.0f</span>, <span class="float">2</span><span class="float">.0f</span>, <span class="float">1</span><span class="float">.0f</span>, <span class="float">0</span><span class="float">.0f</span> }
+y contains { <span class="hex">0x40400000</span>, <span class="hex">0x40000000</span>,
+             <span class="hex">0x3f800000</span>, <span class="hex">0x00000000</span> }
+z contains { <span class="hex">0x4040</span>, <span class="hex">0x0000</span>, <span class="hex">0x4000</span>, <span class="hex">0x0000</span>,
+             <span class="hex">0x3f80</span>, <span class="hex">0x0000</span>, <span class="hex">0x0000</span>, <span class="hex">0x0000</span> }
+z.z is <span class="integer">0</span></code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Here, the value in <code>z.z</code> is not the same between big- and little-endian
+vector machines</p>
+</div>
+<div class="paragraph">
+<p>OpenCL could have made it illegal to do a conversion free cast that changes
+the number of elements in the name of portability.
+However, while OpenCL provides a common set of operators drawing from the
+set that are typically found on vector machines, it can not provide access
+to everything every ISA may offer in a consistent uniform portable manner.
+Many vector ISAs provide special purpose instructions that greatly
+accelerate specific operations such as DCT, SAD, or 3D geometry.
+It is not intended for OpenCL to be so heavy handed that time-critical
+performance sensitive algorithms can not be written by knowledgeable
+developers to perform at near peak performance.
+Developers willing to throw away portability should be able to use the
+platform-specific instructions in their code.
+For this reason, OpenCL is designed to allow traditional vector C language
+programming extensions, such as the AltiVec C Programming Interface or the
+Intel C programming interfaces (such as those found in emmintrin.h) to be
+used directly in OpenCL with OpenCL data types as an extension to OpenCL.
+As these interfaces rely on the ability to do conversion-free casts that
+change the number of elements in the vector to function properly, OpenCL
+allows them too.</p>
+</div>
+<div class="paragraph">
+<p>As a general rule, any operation that operates on vector types in segments
+that are not the same size as the vector element size may break on other
+hardware with different endianness or different vector architecture.</p>
+</div>
+<div class="paragraph">
+<p>Examples might include:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Combining two <code>uchar8</code>'s containing high and low bytes of a ushort, to
+make a <code>ushort8</code> using <code>.even</code> and <code>.odd</code> operators (please use
+<strong>upsample()</strong> for this)</p>
+</li>
+<li>
+<p>Any bitcast that changes the number of elements in the vector.
+(Operations on the new type are non-portable.)</p>
+</li>
+<li>
+<p>Swizzle operations that change the order of data using chunk sizes that
+are not the same as the element size</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Examples of operations that are portable:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Combining two <code>uint8</code>'s to make a <code>uchar16</code> using <code>.even</code> and <code>.odd</code>
+operators.
+For example to interleave left and right audio streams.</p>
+</li>
+<li>
+<p>Any bitcast that does not change the number of elements (e.g. <code>(float4)
+uint4</code>)&#8201;&#8212;&#8201;we define the storage format for floating-point types)</p>
+</li>
+<li>
+<p>Swizzle operations that swizzle elements of the same size as the
+elements of the vector.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>OpenCL has made some additions to C to make application behavior more
+dependable than C.
+Most notably in a few cases OpenCL defines the behavior of some operations
+that are undefined in C99:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>OpenCL provides <code>convert_</code> operators for conversion between all types.
+C99 does not define what happens when a floating-point type is converted
+to integer type and the floating-point value lies outside the
+representable range of the integer type after rounding.
+When the <code><em>sat</code> variant of the conversion is used, the float shall be
+converted to the nearest representable integer value.
+Similarly, OpenCL also makes recommendations about what should happen
+with NaN.
+Hardware manufacturers that provide the saturated conversion in hardware
+may use the saturated conversion hardware for both the saturated and
+non-saturated versions of the OpenCL <code>convert</em></code> operator.
+OpenCL does not define what happens for the non-saturated conversions
+when floating-point operands are outside the range representable
+integers after rounding.</p>
+</li>
+<li>
+<p>The format of <code>half</code>, <code>float</code>, and <code>double</code> types is defined to be the
+binary16, binary32 and binary64 formats in the draft IEEE-754 standard.
+(The latter two are identical to the existing IEEE-754 standard.) You
+may depend on the positioning and meaning of the bits in these types.</p>
+</li>
+<li>
+<p>OpenCL defines behavior for oversized shift values.
+Shift operations that shift greater than or equal to the number of bits
+in the first operand reduce the shift value modulo the number of bits in
+the element.
+For example, if we shift an <code>int4</code> left by <code>33</code> bits, OpenCL treats this
+as shift left by <code>33%32 = 1</code> bit.</p>
+</li>
+<li>
+<p>A number of edge cases for math library functions are more rigorously
+defined than in C99.
+Please see <em>section 3.5</em> of the OpenCL 2.0 C specification.</p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="data-types">Appendix C: Application Data Types</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>This section documents the provided host application types and constant
+definitions.
+The documented material describes the commonly defined data structures,
+types and constant values available to all platforms and architectures.
+The addition of these details demonstrates our commitment to maintaining a
+portable programming environment and potentially deters changes to the
+supplied headers.</p>
+</div>
+<div class="sect2">
+<h3 id="scalar-data-types">Shared Application Scalar Data Types</h3>
+<div class="paragraph">
+<p>The following application scalar types are provided for application
+convenience.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_char
+cl_uchar
+cl_short
+cl_ushort
+cl_int
+cl_uint
+cl_long
+cl_ulong
+cl_half
+cl_float
+cl_double</code></pre>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="vector-data-types">Supported Application Vector Data Types</h3>
+<div class="paragraph">
+<p>Application vector types are unions used to create vectors of the above
+application scalar types.
+The following application vector types are provided for application
+convenience.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_char&lt;n&gt;
+cl_uchar&lt;n&gt;
+cl_short&lt;n&gt;
+cl_ushort&lt;n&gt;
+cl_int&lt;n&gt;
+cl_uint&lt;n&gt;
+cl_long&lt;n&gt;
+cl_ulong&lt;n&gt;
+cl_half&lt;n&gt;
+cl_float&lt;n&gt;
+cl_double&lt;n&gt;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><em>n</em> can be 2, 3, 4, 8 or 16.</p>
+</div>
+<div class="paragraph">
+<p>The application scalar and vector data types are defined in the
+<strong>cl_platform.h</strong> header file.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="alignment-app-data-types">Alignment of Application Data Types</h3>
+<div class="paragraph">
+<p>The user is responsible for ensuring that pointers passed into and out of
+OpenCL kernels are natively aligned relative to the data type of the
+parameter as defined in the kernel language and SPIR-V specifications.
+This implies that OpenCL buffers created with CL_MEM_USE_HOST_PTR need to
+provide an appropriately aligned host memory pointer that is aligned to the
+data types used to access these buffers in a kernel(s), that SVM allocations
+must correctly align and that pointers into SVM allocations must also be
+correctly aligned.
+The user is also responsible for ensuring image data passed is aligned to
+the granularity of the data representing a single pixel (e.g.
+<code>image_num_channels * sizeof(image_channel_data_type)</code>) except for CL_RGB
+and CL_RGBx images where the data must be aligned to the granularity of a
+single channel in a pixel (i.e. <code>sizeof(image_channel_data_type)</code>).
+This implies that OpenCL images created with CL_MEM_USE_HOST_PTR must align
+correctly.
+The image alignment value can be queried using the
+CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT query.
+In addition, source pointers for <strong>clEnqueueWriteImage</strong> and other operations
+that copy to the OpenCL runtime, as well as destination pointers for
+<strong>clEnqueueReadImage</strong> and other operations that copy from the OpenCL runtime
+must follow the same alignment rules.</p>
+</div>
+<div class="paragraph">
+<p>OpenCL makes no requirement about the alignment of OpenCL application
+defined data types outside of buffers and images, except that the underlying
+vector primitives (e.g. <code>__cl_float4</code>) where defined shall be directly
+accessible as such using appropriate named fields in the cl_type union (see
+<a href="#vector-components">Vector Components</a>.
+Nevertheless, it is recommended that the <strong>cl_platform.h</strong> header should
+attempt to naturally align OpenCL defined application data types (e.g.
+<code>cl_float4</code>) according to their type.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_vector_literals">Vector Literals</h3>
+<div class="paragraph">
+<p>Application vector literals may be used in assignments of individual vector
+components.
+Literal usage follows the convention of the underlying application compiler.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">cl_float2 foo = { .s[<span class="integer">1</span>] = <span class="float">2</span><span class="float">.0f</span> };
+cl_int8 bar = {{ <span class="integer">2</span>, <span class="integer">4</span>, <span class="integer">6</span>, <span class="integer">8</span>, <span class="integer">10</span>, <span class="integer">12</span>, <span class="integer">14</span>, <span class="integer">16</span> }};</code></pre>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="vector-components">Vector Components</h3>
+<div class="paragraph">
+<p>The components of application vector types can be addressed using the
+<code>&lt;vector_name&gt;.s[&lt;index&gt;]</code> notation.</p>
+</div>
+<div class="paragraph">
+<p>For example:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">foo.s[<span class="integer">0</span>] = <span class="float">1</span><span class="float">.0f</span>; <span class="comment">// Sets the 1st vector component of foo</span>
+pos.s[<span class="integer">6</span>] = <span class="integer">2</span>;    <span class="comment">// Sets the 7th vector component of bar</span></code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>In some cases vector components may also be accessed using the following
+notations.
+These notations are not guaranteed to be supported on all implementations,
+so their use should be accompanied by a check of the corresponding
+preprocessor symbol.</p>
+</div>
+<div class="sect3">
+<h4 id="_named_vector_components_notation">Named vector components notation</h4>
+<div class="paragraph">
+<p>Vector data type components may be accessed using the <code>.sN</code>, <code>.sn</code> or
+<code>.xyzw</code> field naming convention, similar to how they are used within the
+OpenCL language.
+Use of the <code>.xyzw</code> field naming convention only allows accessing of the
+first 4 component fields.
+Support of these notations is identified by the CL_HAS_NAMED_VECTOR_FIELDS
+preprocessor symbol.
+For example:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="preprocessor">#ifdef</span> CL_HAS_NAMED_VECTOR_FIELDS
+    cl_float4 foo;
+    cl_int16 bar;
+    foo.x = <span class="float">1</span><span class="float">.0f</span>;  <span class="comment">// Set first component</span>
+    foo.s0 = <span class="float">1</span><span class="float">.0f</span>; <span class="comment">// Same as above</span>
+    bar.z = <span class="integer">3</span>;     <span class="comment">// Set third component</span>
+    bar.se = <span class="integer">11</span>;   <span class="comment">// Same as bar.s[0xe]</span>
+    bar.sD = <span class="integer">12</span>;   <span class="comment">// Same as bar.s[0xd]</span>
+<span class="preprocessor">#endif</span></code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Unlike the OpenCL language type usage of named vector fields, only one
+component field may be accessed at a time.
+This restriction prevents the ability to swizzle or replicate components as
+is possible with the OpenCL language types.
+Attempting to access beyond the number of components for a type also results
+in a failure.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">foo.xy    <span class="comment">// illegal - illegal field name combination</span>
+bar.s1234 <span class="comment">// illegal - illegal field name combination</span>
+foo.s7    <span class="comment">// illegal - no component s7</span></code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_high_low_vector_component_notation">High/Low vector component notation</h4>
+<div class="paragraph">
+<p>Vector data type components may be accessed using the <code>.hi</code> and <code>.lo</code>
+notation similar to that supported within the language types.
+Support of this notation is identified by the CL_HAS_HI_LO_VECTOR_FIELDS
+preprocessor symbol.
+For example:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="preprocessor">#ifdef</span> CL_HAS_HI_LO_VECTOR_FIELDS
+    cl_float4 foo;
+    cl_float2 new_hi = <span class="float">2</span><span class="float">.0f</span>, new_lo = <span class="float">4</span><span class="float">.0f</span>;
+    foo.hi = new_hi;
+    foo.lo = new_lo;
+<span class="preprocessor">#endif</span></code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_native_vector_type_notation">Native vector type notation</h4>
+<div class="paragraph">
+<p>Certain native vector types are defined for providing a mapping of vector
+types to architecturally builtin vector types.
+Unlike the above described application vector types, these native types are
+supported on a limited basis depending on the supporting architecture and
+compiler.</p>
+</div>
+<div class="paragraph">
+<p>These types are not unions, but rather convenience mappings to the
+underlying architectures' builtin vector types.
+The native types share the name of their application counterparts but are
+preceded by a double underscore "__".</p>
+</div>
+<div class="paragraph">
+<p>For example, <code>__cl_float4</code> is the native builtin vector type equivalent of
+the <code>cl_float4</code> application vector type.
+The <code>__cl_float4</code> type may provide direct access to the architectural
+builtin <code>__m128</code> or vector float type, whereas the <code>cl_float4</code> is treated
+as a union.</p>
+</div>
+<div class="paragraph">
+<p>In addition, the above described application data types may have native
+vector data type members for access convenience.
+The native components are accessed using the <code>.vN</code> sub-vector notation,
+where <code>N</code> is the number of elements in the sub-vector.
+In cases where the native type is a subset of a larger type (more
+components), the notation becomes an index based array of the sub-vector
+type.</p>
+</div>
+<div class="paragraph">
+<p>Support of the native vector types is identified by a <code>__CL_TYPEN__</code>
+preprocessor symbol matching the native type name.
+For example:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="preprocessor">#ifdef</span> __CL_FLOAT4__ <span class="comment">// Check for native cl_float4 type</span>
+    cl_float8 foo;
+    __cl_float4 bar; <span class="comment">// Use of native type</span>
+    bar = foo.v4[<span class="integer">1</span>]; <span class="comment">// Access the second native float4 vector</span>
+<span class="preprocessor">#endif</span></code></pre>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_implicit_conversions">Implicit Conversions</h3>
+<div class="paragraph">
+<p>Implicit conversions between application vector types are not supported.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_explicit_casts">Explicit Casts</h3>
+<div class="paragraph">
+<p>Explicit casting of application vector types (<code>cl_typen</code>) is not supported.
+Explicit casting of native vector types (<code>__cl_typen</code>) is defined by the
+external compiler.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_other_operators_and_functions">Other operators and functions</h3>
+<div class="paragraph">
+<p>The behavior of standard operators and function on both application vector
+types (<code>cl_typen</code>) and native vector types (<code>__cl_typen</code>) is defined by
+the external compiler.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_application_constant_definitions">Application constant definitions</h3>
+<div class="paragraph">
+<p>In addition to the above application type definitions, the following literal
+defintions are also available.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_CHAR_BIT</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Bit width of a character</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SCHAR_MAX</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Maximum value of a type <code>cl_char</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SCHAR_MIN</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Minimum value of a type <code>cl_char</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_CHAR_MAX</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Maximum value of a type <code>cl_char</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_CHAR_MIN</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Minimum value of a type <code>cl_char</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_UCHAR_MAX</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Maximum value of a type <code>cl_uchar</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SHORT_MAX</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Maximum value of a type <code>cl_short</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SHORT_MIN</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Minimum value of a type <code>cl_short</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_USHORT_MAX</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Maximum value of a type <code>cl_ushort</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_INT_MAX</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Maximum value of a type <code>cl_int</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_INT_MIN</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Minimum value of a type <code>cl_int</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_UINT_MAX</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Maximum value of a type <code>cl_uint</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_LONG_MAX</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Maximum value of a type <code>cl_long</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_LONG_MIN</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Minimum value of a type <code>cl_long</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_ULONG_MAX</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Maximum value of a type <code>cl_ulong</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_FLT_DIAG</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Number of decimal digits of precision for the type <code>cl_float</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_FLT_MANT_DIG</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Number of digits in the mantissa of type <code>cl_float</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_FLT_MAX_10_EXP</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Maximum positive integer such that 10 raised to this power minus one can
+    be represented as a normalized floating-point number of type <code>cl_float</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_FLT_MAX_EXP</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Maximum exponent value of type <code>cl_float</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_FLT_MIN_10_EXP</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Minimum negative integer such that 10 raised to this power minus one can
+    be represented as a normalized floating-point number of type <code>cl_float</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_FLT_MIN_EXP</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Minimum exponent value of type <code>cl_float</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_FLT_RADIX</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Base value of type <code>cl_float</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_FLT_MAX</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Maximum value of type <code>cl_float</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_FLT_MIN</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Minimum value of type <code>cl_float</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_FLT_EPSILON</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Minimum positive floating-point number of type <code>cl_float</code> such that <code>1.0
+    +  CL_FLT_EPSILON != 1</code> is true.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DBL_DIG</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Number of decimal digits of precision for the type <code>cl_double</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DBL_MANT_DIG</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Number of digits in the mantissa of type <code>cl_double</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DBL_MAX_10_EXP</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Maximum positive integer such that 10 raised to this power minus one can
+    be represented as a normalized floating-point number of type <code>cl_double</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DBL_MAX_EXP</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Maximum exponent value of type <code>cl_double</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DBL_MIN_10_EXP</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Minimum negative integer such that 10 raised to this power minus one can
+    be represented as a normalized floating-point number of type <code>cl_double</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DBL_MIN_EXP</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Minimum exponent value of type <code>cl_double</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DBL_RADIX</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Base value of type <code>cl_double</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DBL_MAX</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Maximum value of type <code>cl_double</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DBL_MIN</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Minimum value of type <code>cl_double</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DBL_EPSILON</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Minimum positive floating-point number of type <code>cl_double</code> such that
+    <code>1.0 +  CL_DBL_EPSILON != 1</code> is true.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_NAN</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Macro expanding to a value representing NaN</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_HUGE_VALF</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Largest representative value of type <code>cl_float</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_HUGE_VAL</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Largest representative value of type <code>cl_double</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MAXFLOAT</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Maximum value of type <code>cl_float</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_INFINITY</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Macro expanding to a value represnting infinity</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>These literal definitions are defined in the <strong>cl_platform.h</strong> header.</p>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="check-copy-overlap">Appendix D: CL_MEM_COPY_OVERLAP</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>The following code describes how to determine if there is overlap between
+the source and destination rectangles specified to <strong>clEnqueueCopyBufferRect</strong>
+provided the source and destination buffers refer to the same buffer object.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="predefined-type">unsigned</span> <span class="predefined-type">int</span>
+check_copy_overlap(<span class="directive">const</span> size_t src_origin[],
+                   <span class="directive">const</span> size_t dst_origin[],
+                   <span class="directive">const</span> size_t region[],
+                   <span class="directive">const</span> size_t row_pitch,
+                   <span class="directive">const</span> size_t slice_pitch )
+{
+  <span class="directive">const</span> size_t slice_size = (region[<span class="integer">1</span>] - <span class="integer">1</span>) * row_pitch + region[<span class="integer">0</span>];
+  <span class="directive">const</span> size_t block_size = (region[<span class="integer">2</span>] - <span class="integer">1</span>) * slice_pitch + slice_size;
+  <span class="directive">const</span> size_t src_start = src_origin[<span class="integer">2</span>] * slice_pitch
+                           + src_origin[<span class="integer">1</span>] * row_pitch
+                           + src_origin[<span class="integer">0</span>];
+  <span class="directive">const</span> size_t src_end = src_start + block_size;
+  <span class="directive">const</span> size_t dst_start = dst_origin[<span class="integer">2</span>] * slice_pitch
+                           + dst_origin[<span class="integer">1</span>] * row_pitch
+                           + dst_origin[<span class="integer">0</span>];
+  <span class="directive">const</span> size_t dst_end = dst_start + block_size;
+
+  <span class="comment">/* No overlap if dst ends before src starts or if src ends
+   * before dst starts.
+   */</span>
+  <span class="keyword">if</span>( (dst_end &lt;= src_start) || (src_end &lt;= dst_start) ){
+    <span class="keyword">return</span> <span class="integer">0</span>;
+  }
+
+  <span class="comment">/* No overlap if region[0] for dst or src fits in the gap
+   * between region[0] and row_pitch.
+   */</span>
+  {
+    <span class="directive">const</span> size_t src_dx = src_origin[<span class="integer">0</span>] % row_pitch;
+    <span class="directive">const</span> size_t dst_dx = dst_origin[<span class="integer">0</span>] % row_pitch;
+
+    <span class="keyword">if</span>( ((dst_dx &gt;= src_dx + region[<span class="integer">0</span>]) &amp;&amp;
+        (dst_dx + region[<span class="integer">0</span>] &lt;= src_dx + row_pitch)) ||
+        ((src_dx &gt;= dst_dx + region[<span class="integer">0</span>]) &amp;&amp;
+        (src_dx + region[<span class="integer">0</span>] &lt;= dst_dx + row_pitch)) )
+      {
+        <span class="keyword">return</span> <span class="integer">0</span>;
+      }
+  }
+
+  <span class="comment">/* No overlap if region[1] for dst or src fits in the gap
+   * between region[1] and slice_pitch.
+   */</span>
+   {
+      <span class="directive">const</span> size_t src_dy =
+        (src_origin[<span class="integer">1</span>] * row_pitch + src_origin[<span class="integer">0</span>]) % slice_pitch;
+      <span class="directive">const</span> size_t dst_dy =
+        (dst_origin[<span class="integer">1</span>] * row_pitch + dst_origin[<span class="integer">0</span>]) % slice_pitch;
+
+      <span class="keyword">if</span>( ((dst_dy &gt;= src_dy + slice_size) &amp;&amp;
+          (dst_dy + slice_size &lt;= src_dy + slice_pitch)) ||
+          ((src_dy &gt;= dst_dy + slice_size) &amp;&amp;
+          (src_dy + slice_size &lt;= dst_dy + slice_pitch)) ) {
+        <span class="keyword">return</span> <span class="integer">0</span>;
+      }
+   }
+
+ <span class="comment">/* Otherwise src and dst overlap. */</span>
+ <span class="keyword">return</span> <span class="integer">1</span>;
+}</code></pre>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_changes">Appendix E: Changes</h2>
+<div class="sectionbody">
+<div class="sect2">
+<h3 id="_summary_of_changes_from_opencl_1_0">Summary of changes from OpenCL 1.0</h3>
+<div class="paragraph">
+<p>The following features are added to the OpenCL 1.1 platform layer and
+runtime (<em>sections 4 and 5</em>):</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Following queries to <em>table 4.3</em></p>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_DEVICE_NATIVE_VECTOR_WIDTH_{CHAR | SHORT | INT | LONG | FLOAT |
+DOUBLE | HALF}</p>
+</li>
+<li>
+<p>CL_DEVICE_HOST_UNIFIED_MEMORY</p>
+</li>
+<li>
+<p>CL_DEVICE_OPENCL_C_VERSION</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p>CL_CONTEXT_NUM_DEVICES to the list of queries specified to
+<strong>clGetContextInfo</strong>.</p>
+</li>
+<li>
+<p>Optional image formats: CL_Rx, CL_RGx and CL_RGBx.</p>
+</li>
+<li>
+<p>Support for sub-buffer objects ability to create a buffer object that
+refers to a specific region in another buffer object using
+<strong>clCreateSubBuffer</strong>.</p>
+</li>
+<li>
+<p><strong>clEnqueueReadBufferRect</strong>, <strong>clEnqueueWriteBufferRect</strong> and
+<strong>clEnqueueCopyBufferRect</strong> APIs to read from, write to and copy a
+rectangular region of a buffer object respectively.</p>
+</li>
+<li>
+<p><strong>clSetMemObjectDestructorCallback</strong> API to allow a user to register a
+callback function that will be called when the memory object is deleted
+and its resources freed.</p>
+</li>
+<li>
+<p>Options that <a href="#opencl-c-version">control the OpenCL C version</a> used
+when building a program executable.</p>
+</li>
+<li>
+<p>CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE to the list of queries
+specified to <strong>clGetKernelWorkGroupInfo</strong>.</p>
+</li>
+<li>
+<p>Support for user events.
+User events allow applications to enqueue commands that wait on a user
+event to finish before the command is executed by the device.
+Following new APIs are added - <strong>clCreateUserEvent</strong> and
+<strong>clSetUserEventStatus</strong>.</p>
+</li>
+<li>
+<p><strong>clSetEventCallback</strong> API to register a callback function for a specific
+command execution status.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The following modifications are made to the OpenCL 1.1 platform layer and
+runtime (<em>sections 4 and 5</em>):</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Following queries in <em>table 4.3</em></p>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_DEVICE_MAX_PARAMETER_SIZE from 256 to 1024 bytes</p>
+</li>
+<li>
+<p>CL_DEVICE_LOCAL_MEM_SIZE from 16 KB to 32 KB.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p>The <em>global_work_offset</em> argument in <strong>clEnqueueNDRangeKernel</strong> can be a
+non-<code>NULL</code> value.</p>
+</li>
+<li>
+<p>All API calls except <strong>clSetKernelArg</strong> are thread-safe.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The following features are added to the OpenCL C programming language
+(<em>section 6</em>) in OpenCL 1.1:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>3-component vector data types.</p>
+</li>
+<li>
+<p>New built-in functions</p>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>get_global_offset</strong> work-item function defined in section <em>6.12.1</em>.</p>
+</li>
+<li>
+<p><strong>minmag</strong>, <strong>maxmag</strong> math functions defined in section <em>6.12.2</em>.</p>
+</li>
+<li>
+<p><strong>clamp</strong> integer function defined in <em>section 6.12.3</em>.</p>
+</li>
+<li>
+<p>(vector, scalar) variant of integer functions <strong>min</strong> and <strong>max</strong> in
+<em>section 6.12.3</em>.</p>
+</li>
+<li>
+<p><strong>async_work_group_strided_copy</strong> defined in section <em>6.12.10</em>.</p>
+</li>
+<li>
+<p><strong>vec_step</strong>, <strong>shuffle</strong> and <strong>shuffle2</strong> defined in section <em>6.12.12</em>.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><strong>cl_khr_byte_addressable_store</strong> extension is a core feature.</p>
+</li>
+<li>
+<p><strong>cl_khr_global_int32_base_atomics</strong>,
+<strong>cl_khr_global_int32_extended_atomics</strong>,
+<strong>cl_khr_local_int32_base_atomics</strong> and
+<strong>cl_khr_local_int32_extended_atomics</strong> extensions are core features.
+The built-in atomic function names are changed to use the <strong>atomic_</strong>
+prefix instead of <strong>atom_</strong>.</p>
+</li>
+<li>
+<p>Macros CL_VERSION_1_0 and CL_VERSION_1_1.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The following features in OpenCL 1.0 are deprecated (see glossary) in OpenCL
+1.1:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>The <strong>clSetCommandQueueProperty</strong> API is no longer supported in OpenCL
+1.1.</p>
+</li>
+<li>
+<p>The <code>__ROUNDING_MODE__</code> macro is no longer supported in OpenCL C 1.1.</p>
+</li>
+<li>
+<p>The cl-strict-aliasing option that can be specified in <em>options</em>
+argument to <strong>clBuildProgram</strong> is no longer supported in OpenCL 1.1.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The following new extensions are added to <em>section 9</em> in OpenCL 1.1:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>cl_khr_gl_event</strong> for creating a CL event object from a GL sync object.</p>
+</li>
+<li>
+<p><strong>cl_khr_d3d10_sharing</strong> for sharing memory objects with Direct3D 10.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The following modifications are made to the OpenCL ES Profile described in
+<em>section 10</em> in OpenCL 1.1:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>64-bit integer support is optional.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_summary_of_changes_from_opencl_1_1">Summary of changes from OpenCL 1.1</h3>
+<div class="paragraph">
+<p>The following features are added to the OpenCL 1.2 platform layer and
+runtime (<em>sections 4 and 5</em>):</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Custom devices and built-in kernels are supported.</p>
+</li>
+<li>
+<p>Device partitioning that allows a device to be partitioned based on a
+number of partitioning schemes supported by the device.</p>
+</li>
+<li>
+<p>Extend <em>cl_mem_flags</em> to describe how the host accesses the data in a
+cl_mem object.</p>
+</li>
+<li>
+<p><strong>clEnqueueFillBuffer</strong> and <strong>clEnqueueFillImage</strong> to support filling a
+buffer with a pattern or an image with a color.</p>
+</li>
+<li>
+<p>Add CL_MAP_WRITE_INVALIDATE_REGION to <em>cl_map_flags</em>.
+Appropriate clarification to the behavior of CL_MAP_WRITE has been added
+to the spec.</p>
+</li>
+<li>
+<p>New image types: 1D image, 1D image from a buffer object, 1D image array
+and 2D image arrays.</p>
+</li>
+<li>
+<p><strong>clCreateImage</strong> to create an image object.</p>
+</li>
+<li>
+<p><strong>clEnqueueMigrateMemObjects</strong> API that allows a developer to have
+explicit control over the location of memory objects or to migrate a
+memory object from one device to another.</p>
+</li>
+<li>
+<p>Support separate compilation and linking of programs.</p>
+</li>
+<li>
+<p>Additional queries to get the number of kernels and kernel names in a
+program have been added to <strong>clGetProgramInfo</strong>.</p>
+</li>
+<li>
+<p>Additiional queries to get the compile and link status and options have
+been added to <strong>clGetProgramBuildInfo</strong>.</p>
+</li>
+<li>
+<p><strong>clGetKernelArgInfo</strong> API that returns information about the arguments of
+a kernel.</p>
+</li>
+<li>
+<p><strong>clEnqueueMarkerWithWaitList</strong> and <strong>clEnqueueBarrierWithWaitList</strong> APIs.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The following features are added to the OpenCL C programming language
+(<em>section 6</em>) in OpenCL 1.2:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Double-precision is now an optional core feature instead of an
+extension.</p>
+</li>
+<li>
+<p>New built in image types: <strong>image1d_t</strong>, <strong>image1d_array_t</strong> and
+<strong>image2d_array_t</strong> .</p>
+</li>
+<li>
+<p>New built-in functions</p>
+<div class="ulist">
+<ul>
+<li>
+<p>Functions to read from and write to a 1D image, 1D and 2D image arrays
+described in <em>sections 6.12.14.2</em>, <em>6.12.14.3</em> and <em>6.12.14.4</em>.</p>
+</li>
+<li>
+<p>Sampler-less image read functions described in <em>section 6.12.14.3</em>.</p>
+</li>
+<li>
+<p><strong>popcount</strong> integer function described in <em>section 6.12.3</em>.</p>
+</li>
+<li>
+<p><strong>printf</strong> function described in <em>section 6.12.13</em>.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p>Storage class specifiers extern and static as described in <em>section
+6.8</em>.</p>
+</li>
+<li>
+<p>Macros <code>CL_VERSION_1_2</code> and <code>__OPENCL_C_VERSION__</code>.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The following APIs in OpenCL 1.1 are deprecated (see glossary) in OpenCL
+1.2:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>clEnqueueMarker</strong>, <strong>clEnqueueBarrier</strong> and <strong>clEnqueueWaitForEvents</strong></p>
+</li>
+<li>
+<p><strong>clCreateImage2D</strong> and <strong>clCreateImage3D</strong></p>
+</li>
+<li>
+<p><strong>clUnloadCompiler</strong> and <strong>clGetExtensionFunctionAddress</strong></p>
+</li>
+<li>
+<p><strong>clCreateFromGLTexture2D</strong> and <strong>clCreateFromGLTexture3D</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The following queries are deprecated (see glossary) in OpenCL 1.2:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE</strong> in <em>table 4.3</em> queried using
+<strong>clGetDeviceInfo</strong>.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_summary_of_changes_from_opencl_1_2">Summary of changes from OpenCL 1.2</h3>
+<div class="paragraph">
+<p>The following features are added to the OpenCL 2.0 platform layer and
+runtime (<em>sections 4 and 5</em>):</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Shared virtual memory.</p>
+</li>
+<li>
+<p>Device queues used to enqueue kernels on the device.</p>
+</li>
+<li>
+<p>Pipes.</p>
+</li>
+<li>
+<p>Images support for 2D image from buffer, depth images and sRGB images.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The following modifications are made to the OpenCL 2.0 platform layer and
+runtime (sections 4 and 5):</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>All API calls except <strong>clSetKernelArg</strong>, <strong>clSetKernelArgSVMPointer</strong> and
+<strong>clSetKernelExecInfo</strong> are thread-safe.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The following features are added to the OpenCL C programming language
+(<em>section 6</em>) in OpenCL 2.0:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Clang Blocks.</p>
+</li>
+<li>
+<p>Kernels enqueing kernels to a device queue.</p>
+</li>
+<li>
+<p>Program scope variables in global address space.</p>
+</li>
+<li>
+<p>Generic address space.</p>
+</li>
+<li>
+<p>C1x atomics.</p>
+</li>
+<li>
+<p>New built-in functions (sections 6.13.9, 6.13.11, 6.13.15 and 6.14).</p>
+</li>
+<li>
+<p>Support images with the read_write qualifier.</p>
+</li>
+<li>
+<p>3D image writes are a core feature.</p>
+</li>
+<li>
+<p>The CL_VERSION_2_0 macro.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The following APIs are deprecated (see glossary) in OpenCL 2.0:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>clCreateCommandQueue</strong>, <strong>clCreateSampler</strong> and <strong>clEnqueueTask</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The following queries are deprecated (see glossary) in OpenCL 2.0:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>CL_DEVICE_HOST_UNIFIED_MEMORY</strong> in <em>table 4.3</em> queried using
+<strong>clGetDeviceInfo</strong>.</p>
+</li>
+<li>
+<p><strong>CL_IMAGE_BUFFER</strong> in <em>table 5.10</em> is deprecated.</p>
+</li>
+<li>
+<p><strong>CL_DEVICE_QUEUE_PROPERTIES</strong> is replaced by
+<strong>CL_DEVICE_QUEUE_ON_HOST_PROPERTIES</strong>.</p>
+</li>
+<li>
+<p>The explicit memory fence functions defined in section 6.12.9 of the
+OpenCL 1.2 specification.</p>
+</li>
+<li>
+<p>The OpenCL 1.2 atomic built-in functions for 32-bit integer and
+floating-point data types defined in section 6.12.11 of the OpenCL 1.2
+specification.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_summary_of_changes_from_opencl_2_0">Summary of changes from OpenCL 2.0</h3>
+<div class="paragraph">
+<p>The following features are added to the OpenCL 2.1 platform layer and
+runtime (<em>sections 4 and 5</em>):</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>clGetKernelSubGroupInfo</strong> API call.</p>
+</li>
+<li>
+<p><strong>CL_KERNEL_MAX_NUM_SUB_GROUPS</strong>, <strong>CL_KERNEL_COMPILE_NUM_SUB_GROUPS</strong>
+additions to table 5.21 of the API specification.</p>
+</li>
+<li>
+<p><strong>clCreateProgramWithIL</strong> API call.</p>
+</li>
+<li>
+<p><strong>clGetHostTimer</strong> and <strong>clGetDeviceAndHostTimer</strong> API calls.</p>
+</li>
+<li>
+<p><strong>clEnqueueSVMMigrateMem</strong> API call.</p>
+</li>
+<li>
+<p><strong>clCloneKernel</strong> API call.</p>
+</li>
+<li>
+<p><strong>clSetDefaultDeviceCommandQueue</strong> API call.</p>
+</li>
+<li>
+<p><strong>CL_PLATFORM_HOST_TIMER_RESOLUTION</strong> added to table 4.1 of the API
+specification.</p>
+</li>
+<li>
+<p><strong>CL_DEVICE_IL_VERSION</strong>, <strong>CL_DEVICE_MAX_NUM_SUB_GROUPS</strong>,
+<strong>CL_DEVICE_SUB_GROUP_INDEPENDENT_FORWARD_PROGRESS</strong> added to table 4.3 of
+the API specification.</p>
+</li>
+<li>
+<p><strong>CL_PROGRAM_IL</strong> to table 5.17 of the API specification.</p>
+</li>
+<li>
+<p><strong>CL_QUEUE_DEVICE_DEFAULT</strong> added to table 5.2 of the API specification.</p>
+</li>
+<li>
+<p>Added table 5.22 to the API specification with the enums:
+<strong>CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE</strong>,
+<strong>CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE</strong> and
+<strong>CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The following modifications are made to the OpenCL 2.1 platform layer and
+runtime (sections 4 and 5):</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>All API calls except <strong>clSetKernelArg</strong>, <strong>clSetKernelArgSVMPointer</strong>,
+<strong>clSetKernelExecInfo</strong> and <strong>clCloneKernel</strong> are thread-safe.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The OpenCL C kernel language is no longer chapter 6.
+The OpenCL C kernel language is not updated for OpenCL 2.1.
+The OpenCL 2.0 kernel language will still be consumed by OpenCL 2.1
+runtimes.</p>
+</div>
+<div class="paragraph">
+<p>The SPIR-V IL specification has been added.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_summary_of_changes_from_opencl_2_1">Summary of changes from OpenCL 2.1</h3>
+<div class="paragraph">
+<p>The following changes have been made to the OpenCL 2.2 execution model
+(section 3)</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Added the third prerequisite (executing non-trivial constructors for
+program scope global variables).</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The following features are added to the OpenCL 2.2 platform layer and
+runtime (<em>sections 4 and 5</em>):</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>clSetProgramSpecializationConstant</strong> API call</p>
+</li>
+<li>
+<p><strong>clSetProgramReleaseCallback</strong> API call</p>
+</li>
+<li>
+<p>Queries for CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT,
+CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The following modifications are made to the OpenCL 2.2 platform layer and
+runtime (section 4 and 5):</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Modified description of CL_DEVICE_MAX_CLOCK_FREQUENCY query.</p>
+</li>
+<li>
+<p>Added a new error code CL_MAX_SIZE_RESTRICTION_EXCEEDED to
+<strong>clSetKernelArg</strong> API call</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Added definition of Deprecation and Specialization constants to the
+glossary.</p>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div id="footer">
+<div id="footer-text">
+Version 2.2-7<br>
+Last updated 2018-05-07 12:41:34 BST
+</div>
+</div>
+
+
+</body>
+</html>
\ No newline at end of file
diff --git a/specs/2.2/html/OpenCL_C.html b/specs/2.2/html/OpenCL_C.html
new file mode 100644
index 0000000..69bd709
--- /dev/null
+++ b/specs/2.2/html/OpenCL_C.html
@@ -0,0 +1,15713 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<meta name="generator" content="Asciidoctor 1.5.6.1">
+<meta name="author" content="Document Revision: 40">
+<title>The OpenCL&#8482; C 2.0 Specification</title>
+<style>
+/*! normalize.css v2.1.2 | MIT License | git.io/normalize */
+/* ========================================================================== HTML5 display definitions ========================================================================== */
+/** Correct `block` display not defined in IE 8/9. */
+article, aside, details, figcaption, figure, footer, header, hgroup, main, nav, section, summary { display: block; }
+
+/** Correct `inline-block` display not defined in IE 8/9. */
+audio, canvas, video { display: inline-block; }
+
+/** Prevent modern browsers from displaying `audio` without controls. Remove excess height in iOS 5 devices. */
+audio:not([controls]) { display: none; height: 0; }
+
+/** Address `[hidden]` styling not present in IE 8/9. Hide the `template` element in IE, Safari, and Firefox < 22. */
+[hidden], template { display: none; }
+
+script { display: none !important; }
+
+/* ========================================================================== Base ========================================================================== */
+/** 1. Set default font family to sans-serif. 2. Prevent iOS text size adjust after orientation change, without disabling user zoom. */
+html { font-family: sans-serif; /* 1 */ -ms-text-size-adjust: 100%; /* 2 */ -webkit-text-size-adjust: 100%; /* 2 */ }
+
+/** Remove default margin. */
+body { margin: 0; }
+
+/* ========================================================================== Links ========================================================================== */
+/** Remove the gray background color from active links in IE 10. */
+a { background: transparent; }
+
+/** Address `outline` inconsistency between Chrome and other browsers. */
+a:focus { outline: thin dotted; }
+
+/** Improve readability when focused and also mouse hovered in all browsers. */
+a:active, a:hover { outline: 0; }
+
+/* ========================================================================== Typography ========================================================================== */
+/** Address variable `h1` font-size and margin within `section` and `article` contexts in Firefox 4+, Safari 5, and Chrome. */
+h1 { font-size: 2em; margin: 0.67em 0; }
+
+/** Address styling not present in IE 8/9, Safari 5, and Chrome. */
+abbr[title] { border-bottom: 1px dotted; }
+
+/** Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome. */
+b, strong { font-weight: bold; }
+
+/** Address styling not present in Safari 5 and Chrome. */
+dfn { font-style: italic; }
+
+/** Address differences between Firefox and other browsers. */
+hr { -moz-box-sizing: content-box; box-sizing: content-box; height: 0; }
+
+/** Address styling not present in IE 8/9. */
+mark { background: #ff0; color: #000; }
+
+/** Correct font family set oddly in Safari 5 and Chrome. */
+code, kbd, pre, samp { font-family: monospace, serif; font-size: 1em; }
+
+/** Improve readability of pre-formatted text in all browsers. */
+pre { white-space: pre-wrap; }
+
+/** Set consistent quote types. */
+q { quotes: "\201C" "\201D" "\2018" "\2019"; }
+
+/** Address inconsistent and variable font size in all browsers. */
+small { font-size: 80%; }
+
+/** Prevent `sub` and `sup` affecting `line-height` in all browsers. */
+sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }
+
+sup { top: -0.5em; }
+
+sub { bottom: -0.25em; }
+
+/* ========================================================================== Embedded content ========================================================================== */
+/** Remove border when inside `a` element in IE 8/9. */
+img { border: 0; }
+
+/** Correct overflow displayed oddly in IE 9. */
+svg:not(:root) { overflow: hidden; }
+
+/* ========================================================================== Figures ========================================================================== */
+/** Address margin not present in IE 8/9 and Safari 5. */
+figure { margin: 0; }
+
+/* ========================================================================== Forms ========================================================================== */
+/** Define consistent border, margin, and padding. */
+fieldset { border: 1px solid #c0c0c0; margin: 0 2px; padding: 0.35em 0.625em 0.75em; }
+
+/** 1. Correct `color` not being inherited in IE 8/9. 2. Remove padding so people aren't caught out if they zero out fieldsets. */
+legend { border: 0; /* 1 */ padding: 0; /* 2 */ }
+
+/** 1. Correct font family not being inherited in all browsers. 2. Correct font size not being inherited in all browsers. 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome. */
+button, input, select, textarea { font-family: inherit; /* 1 */ font-size: 100%; /* 2 */ margin: 0; /* 3 */ }
+
+/** Address Firefox 4+ setting `line-height` on `input` using `!important` in the UA stylesheet. */
+button, input { line-height: normal; }
+
+/** Address inconsistent `text-transform` inheritance for `button` and `select`. All other form control elements do not inherit `text-transform` values. Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+. Correct `select` style inheritance in Firefox 4+ and Opera. */
+button, select { text-transform: none; }
+
+/** 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` and `video` controls. 2. Correct inability to style clickable `input` types in iOS. 3. Improve usability and consistency of cursor style between image-type `input` and others. */
+button, html input[type="button"], input[type="reset"], input[type="submit"] { -webkit-appearance: button; /* 2 */ cursor: pointer; /* 3 */ }
+
+/** Re-set default cursor for disabled elements. */
+button[disabled], html input[disabled] { cursor: default; }
+
+/** 1. Address box sizing set to `content-box` in IE 8/9. 2. Remove excess padding in IE 8/9. */
+input[type="checkbox"], input[type="radio"] { box-sizing: border-box; /* 1 */ padding: 0; /* 2 */ }
+
+/** 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome (include `-moz` to future-proof). */
+input[type="search"] { -webkit-appearance: textfield; /* 1 */ -moz-box-sizing: content-box; -webkit-box-sizing: content-box; /* 2 */ box-sizing: content-box; }
+
+/** Remove inner padding and search cancel button in Safari 5 and Chrome on OS X. */
+input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; }
+
+/** Remove inner padding and border in Firefox 4+. */
+button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; }
+
+/** 1. Remove default vertical scrollbar in IE 8/9. 2. Improve readability and alignment in all browsers. */
+textarea { overflow: auto; /* 1 */ vertical-align: top; /* 2 */ }
+
+/* ========================================================================== Tables ========================================================================== */
+/** Remove most spacing between table cells. */
+table { border-collapse: collapse; border-spacing: 0; }
+
+meta.foundation-mq-small { font-family: "only screen and (min-width: 768px)"; width: 768px; }
+
+meta.foundation-mq-medium { font-family: "only screen and (min-width:1280px)"; width: 1280px; }
+
+meta.foundation-mq-large { font-family: "only screen and (min-width:1440px)"; width: 1440px; }
+
+*, *:before, *:after { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; }
+
+html, body { font-size: 100%; }
+
+body { background: white; color: #222222; padding: 0; margin: 0; font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; font-weight: normal; font-style: normal; line-height: 1; position: relative; cursor: auto; }
+
+a:hover { cursor: pointer; }
+
+img, object, embed { max-width: 100%; height: auto; }
+
+object, embed { height: 100%; }
+
+img { -ms-interpolation-mode: bicubic; }
+
+#map_canvas img, #map_canvas embed, #map_canvas object, .map_canvas img, .map_canvas embed, .map_canvas object { max-width: none !important; }
+
+.left { float: left !important; }
+
+.right { float: right !important; }
+
+.text-left { text-align: left !important; }
+
+.text-right { text-align: right !important; }
+
+.text-center { text-align: center !important; }
+
+.text-justify { text-align: justify !important; }
+
+.hide { display: none; }
+
+.antialiased { -webkit-font-smoothing: antialiased; }
+
+img { display: inline-block; vertical-align: middle; }
+
+textarea { height: auto; min-height: 50px; }
+
+select { width: 100%; }
+
+object, svg { display: inline-block; vertical-align: middle; }
+
+.center { margin-left: auto; margin-right: auto; }
+
+.spread { width: 100%; }
+
+p.lead, .paragraph.lead > p, #preamble > .sectionbody > .paragraph:first-of-type p { font-size: 1.21875em; line-height: 1.6; }
+
+.subheader, .admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { line-height: 1.4; color: black; font-weight: 300; margin-top: 0.2em; margin-bottom: 0.5em; }
+
+/* Typography resets */
+div, dl, dt, dd, ul, ol, li, h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6, pre, form, p, blockquote, th, td { margin: 0; padding: 0; direction: ltr; }
+
+/* Default Link Styles */
+a { color: #0068b0; text-decoration: none; line-height: inherit; }
+a:hover, a:focus { color: #333333; }
+a img { border: none; }
+
+/* Default paragraph styles */
+p { font-family: Noto, sans-serif; font-weight: normal; font-size: 1em; line-height: 1.6; margin-bottom: 0.75em; text-rendering: optimizeLegibility; }
+p aside { font-size: 0.875em; line-height: 1.35; font-style: italic; }
+
+/* Default header styles */
+h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { font-family: Noto, sans-serif; font-weight: normal; font-style: normal; color: black; text-rendering: optimizeLegibility; margin-top: 0.5em; margin-bottom: 0.5em; line-height: 1.2125em; }
+h1 small, h2 small, h3 small, #toctitle small, .sidebarblock > .content > .title small, h4 small, h5 small, h6 small { font-size: 60%; color: #4d4d4d; line-height: 0; }
+
+h1 { font-size: 2.125em; }
+
+h2 { font-size: 1.6875em; }
+
+h3, #toctitle, .sidebarblock > .content > .title { font-size: 1.375em; }
+
+h4 { font-size: 1.125em; }
+
+h5 { font-size: 1.125em; }
+
+h6 { font-size: 1em; }
+
+hr { border: solid #dddddd; border-width: 1px 0 0; clear: both; margin: 1.25em 0 1.1875em; height: 0; }
+
+/* Helpful Typography Defaults */
+em, i { font-style: italic; line-height: inherit; }
+
+strong, b { font-weight: bold; line-height: inherit; }
+
+small { font-size: 60%; line-height: inherit; }
+
+code { font-family: Consolas, "Liberation Mono", Courier, monospace; font-weight: normal; color: #264357; }
+
+/* Lists */
+ul, ol, dl { font-size: 1em; line-height: 1.6; margin-bottom: 0.75em; list-style-position: outside; font-family: Noto, sans-serif; }
+
+ul, ol { margin-left: 1.5em; }
+ul.no-bullet, ol.no-bullet { margin-left: 1.5em; }
+
+/* Unordered Lists */
+ul li ul, ul li ol { margin-left: 1.25em; margin-bottom: 0; font-size: 1em; /* Override nested font-size change */ }
+ul.square li ul, ul.circle li ul, ul.disc li ul { list-style: inherit; }
+ul.square { list-style-type: square; }
+ul.circle { list-style-type: circle; }
+ul.disc { list-style-type: disc; }
+ul.no-bullet { list-style: none; }
+
+/* Ordered Lists */
+ol li ul, ol li ol { margin-left: 1.25em; margin-bottom: 0; }
+
+/* Definition Lists */
+dl dt { margin-bottom: 0.3em; font-weight: bold; }
+dl dd { margin-bottom: 0.75em; }
+
+/* Abbreviations */
+abbr, acronym { text-transform: uppercase; font-size: 90%; color: black; border-bottom: 1px dotted #dddddd; cursor: help; }
+
+abbr { text-transform: none; }
+
+/* Blockquotes */
+blockquote { margin: 0 0 0.75em; padding: 0.5625em 1.25em 0 1.1875em; border-left: 1px solid #dddddd; }
+blockquote cite { display: block; font-size: 0.8125em; color: #5e93b8; }
+blockquote cite:before { content: "\2014 \0020"; }
+blockquote cite a, blockquote cite a:visited { color: #5e93b8; }
+
+blockquote, blockquote p { line-height: 1.6; color: #333333; }
+
+/* Microformats */
+.vcard { display: inline-block; margin: 0 0 1.25em 0; border: 1px solid #dddddd; padding: 0.625em 0.75em; }
+.vcard li { margin: 0; display: block; }
+.vcard .fn { font-weight: bold; font-size: 0.9375em; }
+
+.vevent .summary { font-weight: bold; }
+.vevent abbr { cursor: auto; text-decoration: none; font-weight: bold; border: none; padding: 0 0.0625em; }
+
+@media only screen and (min-width: 768px) { h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { line-height: 1.4; }
+  h1 { font-size: 2.75em; }
+  h2 { font-size: 2.3125em; }
+  h3, #toctitle, .sidebarblock > .content > .title { font-size: 1.6875em; }
+  h4 { font-size: 1.4375em; } }
+/* Tables */
+table { background: white; margin-bottom: 1.25em; border: solid 1px #d8d8ce; }
+table thead, table tfoot { background: -webkit-linear-gradient(top, #add386, #90b66a); font-weight: bold; }
+table thead tr th, table thead tr td, table tfoot tr th, table tfoot tr td { padding: 0.5em 0.625em 0.625em; font-size: inherit; color: white; text-align: left; }
+table tr th, table tr td { padding: 0.5625em 0.625em; font-size: inherit; color: #6d6e71; }
+table tr.even, table tr.alt, table tr:nth-of-type(even) { background: #edf2f2; }
+table thead tr th, table tfoot tr th, table tbody tr td, table tr td, table tfoot tr td { display: table-cell; line-height: 1.4; }
+
+body { -moz-osx-font-smoothing: grayscale; -webkit-font-smoothing: antialiased; tab-size: 4; }
+
+h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { line-height: 1.4; }
+
+a:hover, a:focus { text-decoration: underline; }
+
+.clearfix:before, .clearfix:after, .float-group:before, .float-group:after { content: " "; display: table; }
+.clearfix:after, .float-group:after { clear: both; }
+
+*:not(pre) > code { font-size: inherit; font-style: normal !important; letter-spacing: 0; padding: 0; background-color: white; -webkit-border-radius: 0; border-radius: 0; line-height: inherit; word-wrap: break-word; }
+*:not(pre) > code.nobreak { word-wrap: normal; }
+*:not(pre) > code.nowrap { white-space: nowrap; }
+
+pre, pre > code { line-height: 1.6; color: #264357; font-family: Consolas, "Liberation Mono", Courier, monospace; font-weight: normal; }
+
+em em { font-style: normal; }
+
+strong strong { font-weight: normal; }
+
+.keyseq { color: #333333; }
+
+kbd { font-family: Consolas, "Liberation Mono", Courier, monospace; display: inline-block; color: black; font-size: 0.65em; line-height: 1.45; background-color: #f7f7f7; border: 1px solid #ccc; -webkit-border-radius: 3px; border-radius: 3px; -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 0.1em white inset; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 0.1em white inset; margin: 0 0.15em; padding: 0.2em 0.5em; vertical-align: middle; position: relative; top: -0.1em; white-space: nowrap; }
+
+.keyseq kbd:first-child { margin-left: 0; }
+
+.keyseq kbd:last-child { margin-right: 0; }
+
+.menuseq, .menuref { color: #000; }
+
+.menuseq b:not(.caret), .menuref { font-weight: inherit; }
+
+.menuseq { word-spacing: -0.02em; }
+.menuseq b.caret { font-size: 1.25em; line-height: 0.8; }
+.menuseq i.caret { font-weight: bold; text-align: center; width: 0.45em; }
+
+b.button:before, b.button:after { position: relative; top: -1px; font-weight: normal; }
+
+b.button:before { content: "["; padding: 0 3px 0 2px; }
+
+b.button:after { content: "]"; padding: 0 2px 0 3px; }
+
+#header, #content, #footnotes, #footer { width: 100%; margin-left: auto; margin-right: auto; margin-top: 0; margin-bottom: 0; max-width: 62.5em; *zoom: 1; position: relative; padding-left: 1.5em; padding-right: 1.5em; }
+#header:before, #header:after, #content:before, #content:after, #footnotes:before, #footnotes:after, #footer:before, #footer:after { content: " "; display: table; }
+#header:after, #content:after, #footnotes:after, #footer:after { clear: both; }
+
+#content { margin-top: 1.25em; }
+
+#content:before { content: none; }
+
+#header > h1:first-child { color: black; margin-top: 2.25rem; margin-bottom: 0; }
+#header > h1:first-child + #toc { margin-top: 8px; border-top: 1px solid #dddddd; }
+#header > h1:only-child, body.toc2 #header > h1:nth-last-child(2) { border-bottom: 1px solid #dddddd; padding-bottom: 8px; }
+#header .details { border-bottom: 1px solid #dddddd; line-height: 1.45; padding-top: 0.25em; padding-bottom: 0.25em; padding-left: 0.25em; color: #5e93b8; display: -ms-flexbox; display: -webkit-flex; display: flex; -ms-flex-flow: row wrap; -webkit-flex-flow: row wrap; flex-flow: row wrap; }
+#header .details span:first-child { margin-left: -0.125em; }
+#header .details span.email a { color: #333333; }
+#header .details br { display: none; }
+#header .details br + span:before { content: "\00a0\2013\00a0"; }
+#header .details br + span.author:before { content: "\00a0\22c5\00a0"; color: #333333; }
+#header .details br + span#revremark:before { content: "\00a0|\00a0"; }
+#header #revnumber { text-transform: capitalize; }
+#header #revnumber:after { content: "\00a0"; }
+
+#content > h1:first-child:not([class]) { color: black; border-bottom: 1px solid #dddddd; padding-bottom: 8px; margin-top: 0; padding-top: 1rem; margin-bottom: 1.25rem; }
+
+#toc { border-bottom: 0 solid #dddddd; padding-bottom: 0.5em; }
+#toc > ul { margin-left: 0.125em; }
+#toc ul.sectlevel0 > li > a { font-style: italic; }
+#toc ul.sectlevel0 ul.sectlevel1 { margin: 0.5em 0; }
+#toc ul { font-family: Noto, sans-serif; list-style-type: none; }
+#toc li { line-height: 1.3334; margin-top: 0.3334em; }
+#toc a { text-decoration: none; }
+#toc a:active { text-decoration: underline; }
+
+#toctitle { color: black; font-size: 1.2em; }
+
+@media only screen and (min-width: 768px) { #toctitle { font-size: 1.375em; }
+  body.toc2 { padding-left: 15em; padding-right: 0; }
+  #toc.toc2 { margin-top: 0 !important; background-color: white; position: fixed; width: 15em; left: 0; top: 0; border-right: 1px solid #dddddd; border-top-width: 0 !important; border-bottom-width: 0 !important; z-index: 1000; padding: 1.25em 1em; height: 100%; overflow: auto; }
+  #toc.toc2 #toctitle { margin-top: 0; margin-bottom: 0.8rem; font-size: 1.2em; }
+  #toc.toc2 > ul { font-size: 0.9em; margin-bottom: 0; }
+  #toc.toc2 ul ul { margin-left: 0; padding-left: 1em; }
+  #toc.toc2 ul.sectlevel0 ul.sectlevel1 { padding-left: 0; margin-top: 0.5em; margin-bottom: 0.5em; }
+  body.toc2.toc-right { padding-left: 0; padding-right: 15em; }
+  body.toc2.toc-right #toc.toc2 { border-right-width: 0; border-left: 1px solid #dddddd; left: auto; right: 0; } }
+@media only screen and (min-width: 1280px) { body.toc2 { padding-left: 20em; padding-right: 0; }
+  #toc.toc2 { width: 20em; }
+  #toc.toc2 #toctitle { font-size: 1.375em; }
+  #toc.toc2 > ul { font-size: 0.95em; }
+  #toc.toc2 ul ul { padding-left: 1.25em; }
+  body.toc2.toc-right { padding-left: 0; padding-right: 20em; } }
+#content #toc { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 0; border-radius: 0; }
+#content #toc > :first-child { margin-top: 0; }
+#content #toc > :last-child { margin-bottom: 0; }
+
+#footer { max-width: 100%; background-color: none; padding: 1.25em; }
+
+#footer-text { color: black; line-height: 1.44; }
+
+#content { margin-bottom: 0.625em; }
+
+.sect1 { padding-bottom: 0.625em; }
+
+@media only screen and (min-width: 768px) { #content { margin-bottom: 1.25em; }
+  .sect1 { padding-bottom: 1.25em; } }
+.sect1:last-child { padding-bottom: 0; }
+
+.sect1 + .sect1 { border-top: 0 solid #dddddd; }
+
+#content h1 > a.anchor, h2 > a.anchor, h3 > a.anchor, #toctitle > a.anchor, .sidebarblock > .content > .title > a.anchor, h4 > a.anchor, h5 > a.anchor, h6 > a.anchor { position: absolute; z-index: 1001; width: 1.5ex; margin-left: -1.5ex; display: block; text-decoration: none !important; visibility: hidden; text-align: center; font-weight: normal; }
+#content h1 > a.anchor:before, h2 > a.anchor:before, h3 > a.anchor:before, #toctitle > a.anchor:before, .sidebarblock > .content > .title > a.anchor:before, h4 > a.anchor:before, h5 > a.anchor:before, h6 > a.anchor:before { content: "\00A7"; font-size: 0.85em; display: block; padding-top: 0.1em; }
+#content h1:hover > a.anchor, #content h1 > a.anchor:hover, h2:hover > a.anchor, h2 > a.anchor:hover, h3:hover > a.anchor, #toctitle:hover > a.anchor, .sidebarblock > .content > .title:hover > a.anchor, h3 > a.anchor:hover, #toctitle > a.anchor:hover, .sidebarblock > .content > .title > a.anchor:hover, h4:hover > a.anchor, h4 > a.anchor:hover, h5:hover > a.anchor, h5 > a.anchor:hover, h6:hover > a.anchor, h6 > a.anchor:hover { visibility: visible; }
+#content h1 > a.link, h2 > a.link, h3 > a.link, #toctitle > a.link, .sidebarblock > .content > .title > a.link, h4 > a.link, h5 > a.link, h6 > a.link { color: black; text-decoration: none; }
+#content h1 > a.link:hover, h2 > a.link:hover, h3 > a.link:hover, #toctitle > a.link:hover, .sidebarblock > .content > .title > a.link:hover, h4 > a.link:hover, h5 > a.link:hover, h6 > a.link:hover { color: black; }
+
+.audioblock, .imageblock, .literalblock, .listingblock, .stemblock, .videoblock { margin-bottom: 1.25em; }
+
+.admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { text-rendering: optimizeLegibility; text-align: left; }
+
+table.tableblock > caption.title { white-space: nowrap; overflow: visible; max-width: 0; }
+
+.paragraph.lead > p, #preamble > .sectionbody > .paragraph:first-of-type p { color: black; }
+
+table.tableblock #preamble > .sectionbody > .paragraph:first-of-type p { font-size: inherit; }
+
+.admonitionblock > table { border-collapse: separate; border: 0; background: none; width: 100%; }
+.admonitionblock > table td.icon { text-align: center; width: 80px; }
+.admonitionblock > table td.icon img { max-width: initial; }
+.admonitionblock > table td.icon .title { font-weight: bold; font-family: Noto, sans-serif; text-transform: uppercase; }
+.admonitionblock > table td.content { padding-left: 1.125em; padding-right: 1.25em; border-left: 1px solid #dddddd; color: #5e93b8; }
+.admonitionblock > table td.content > :last-child > :last-child { margin-bottom: 0; }
+
+.exampleblock > .content { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 0; border-radius: 0; }
+.exampleblock > .content > :first-child { margin-top: 0; }
+.exampleblock > .content > :last-child { margin-bottom: 0; }
+
+.sidebarblock { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 0; border-radius: 0; }
+.sidebarblock > :first-child { margin-top: 0; }
+.sidebarblock > :last-child { margin-bottom: 0; }
+.sidebarblock > .content > .title { color: black; margin-top: 0; }
+
+.exampleblock > .content > :last-child > :last-child, .exampleblock > .content .olist > ol > li:last-child > :last-child, .exampleblock > .content .ulist > ul > li:last-child > :last-child, .exampleblock > .content .qlist > ol > li:last-child > :last-child, .sidebarblock > .content > :last-child > :last-child, .sidebarblock > .content .olist > ol > li:last-child > :last-child, .sidebarblock > .content .ulist > ul > li:last-child > :last-child, .sidebarblock > .content .qlist > ol > li:last-child > :last-child { margin-bottom: 0; }
+
+.literalblock pre, .listingblock pre:not(.highlight), .listingblock pre[class="highlight"], .listingblock pre[class^="highlight "], .listingblock pre.CodeRay, .listingblock pre.prettyprint { background: #eeeeee; }
+.sidebarblock .literalblock pre, .sidebarblock .listingblock pre:not(.highlight), .sidebarblock .listingblock pre[class="highlight"], .sidebarblock .listingblock pre[class^="highlight "], .sidebarblock .listingblock pre.CodeRay, .sidebarblock .listingblock pre.prettyprint { background: #f2f1f1; }
+
+.literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { border: 1px hidden #666666; -webkit-border-radius: 0; border-radius: 0; word-wrap: break-word; padding: 1.25em 1.5625em 1.125em 1.5625em; font-size: 0.8125em; }
+.literalblock pre.nowrap, .literalblock pre[class].nowrap, .listingblock pre.nowrap, .listingblock pre[class].nowrap { overflow-x: auto; white-space: pre; word-wrap: normal; }
+@media only screen and (min-width: 768px) { .literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { font-size: 0.90625em; } }
+@media only screen and (min-width: 1280px) { .literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { font-size: 1em; } }
+
+.literalblock.output pre { color: #eeeeee; background-color: #264357; }
+
+.listingblock pre.highlightjs { padding: 0; }
+.listingblock pre.highlightjs > code { padding: 1.25em 1.5625em 1.125em 1.5625em; -webkit-border-radius: 0; border-radius: 0; }
+
+.listingblock > .content { position: relative; }
+
+.listingblock code[data-lang]:before { display: none; content: attr(data-lang); position: absolute; font-size: 0.75em; top: 0.425rem; right: 0.5rem; line-height: 1; text-transform: uppercase; color: #999; }
+
+.listingblock:hover code[data-lang]:before { display: block; }
+
+.listingblock.terminal pre .command:before { content: attr(data-prompt); padding-right: 0.5em; color: #999; }
+
+.listingblock.terminal pre .command:not([data-prompt]):before { content: "$"; }
+
+table.pyhltable { border-collapse: separate; border: 0; margin-bottom: 0; background: none; }
+
+table.pyhltable td { vertical-align: top; padding-top: 0; padding-bottom: 0; line-height: 1.6; }
+
+table.pyhltable td.code { padding-left: .75em; padding-right: 0; }
+
+pre.pygments .lineno, table.pyhltable td:not(.code) { color: #999; padding-left: 0; padding-right: .5em; border-right: 1px solid #dddddd; }
+
+pre.pygments .lineno { display: inline-block; margin-right: .25em; }
+
+table.pyhltable .linenodiv { background: none !important; padding-right: 0 !important; }
+
+.quoteblock { margin: 0 1em 0.75em 1.5em; display: table; }
+.quoteblock > .title { margin-left: -1.5em; margin-bottom: 0.75em; }
+.quoteblock blockquote, .quoteblock blockquote p { color: #333333; font-size: 1.15rem; line-height: 1.75; word-spacing: 0.1em; letter-spacing: 0; font-style: italic; text-align: justify; }
+.quoteblock blockquote { margin: 0; padding: 0; border: 0; }
+.quoteblock blockquote:before { content: "\201c"; float: left; font-size: 2.75em; font-weight: bold; line-height: 0.6em; margin-left: -0.6em; color: black; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); }
+.quoteblock blockquote > .paragraph:last-child p { margin-bottom: 0; }
+.quoteblock .attribution { margin-top: 0.5em; margin-right: 0.5ex; text-align: right; }
+.quoteblock .quoteblock { margin-left: 0; margin-right: 0; padding: 0.5em 0; border-left: 3px solid #5e93b8; }
+.quoteblock .quoteblock blockquote { padding: 0 0 0 0.75em; }
+.quoteblock .quoteblock blockquote:before { display: none; }
+
+.verseblock { margin: 0 1em 0.75em 1em; }
+.verseblock pre { font-family: "Open Sans", "DejaVu Sans", sans; font-size: 1.15rem; color: #333333; font-weight: 300; text-rendering: optimizeLegibility; }
+.verseblock pre strong { font-weight: 400; }
+.verseblock .attribution { margin-top: 1.25rem; margin-left: 0.5ex; }
+
+.quoteblock .attribution, .verseblock .attribution { font-size: 0.8125em; line-height: 1.45; font-style: italic; }
+.quoteblock .attribution br, .verseblock .attribution br { display: none; }
+.quoteblock .attribution cite, .verseblock .attribution cite { display: block; letter-spacing: -0.025em; color: #5e93b8; }
+
+.quoteblock.abstract { margin: 0 0 0.75em 0; display: block; }
+.quoteblock.abstract blockquote, .quoteblock.abstract blockquote p { text-align: left; word-spacing: 0; }
+.quoteblock.abstract blockquote:before, .quoteblock.abstract blockquote p:first-of-type:before { display: none; }
+
+table.tableblock { max-width: 100%; border-collapse: separate; }
+table.tableblock td > .paragraph:last-child p > p:last-child, table.tableblock th > p:last-child, table.tableblock td > p:last-child { margin-bottom: 0; }
+
+table.tableblock, th.tableblock, td.tableblock { border: 0 solid #d8d8ce; }
+
+table.grid-all > thead > tr > .tableblock, table.grid-all > tbody > tr > .tableblock { border-width: 0 1px 1px 0; }
+
+table.grid-all > tfoot > tr > .tableblock { border-width: 1px 1px 0 0; }
+
+table.grid-cols > * > tr > .tableblock { border-width: 0 1px 0 0; }
+
+table.grid-rows > thead > tr > .tableblock, table.grid-rows > tbody > tr > .tableblock { border-width: 0 0 1px 0; }
+
+table.grid-rows > tfoot > tr > .tableblock { border-width: 1px 0 0 0; }
+
+table.grid-all > * > tr > .tableblock:last-child, table.grid-cols > * > tr > .tableblock:last-child { border-right-width: 0; }
+
+table.grid-all > tbody > tr:last-child > .tableblock, table.grid-all > thead:last-child > tr > .tableblock, table.grid-rows > tbody > tr:last-child > .tableblock, table.grid-rows > thead:last-child > tr > .tableblock { border-bottom-width: 0; }
+
+table.frame-all { border-width: 1px; }
+
+table.frame-sides { border-width: 0 1px; }
+
+table.frame-topbot { border-width: 1px 0; }
+
+th.halign-left, td.halign-left { text-align: left; }
+
+th.halign-right, td.halign-right { text-align: right; }
+
+th.halign-center, td.halign-center { text-align: center; }
+
+th.valign-top, td.valign-top { vertical-align: top; }
+
+th.valign-bottom, td.valign-bottom { vertical-align: bottom; }
+
+th.valign-middle, td.valign-middle { vertical-align: middle; }
+
+table thead th, table tfoot th { font-weight: bold; }
+
+tbody tr th { display: table-cell; line-height: 1.4; background: -webkit-linear-gradient(top, #add386, #90b66a); }
+
+tbody tr th, tbody tr th p, tfoot tr th, tfoot tr th p { color: white; font-weight: bold; }
+
+p.tableblock > code:only-child { background: none; padding: 0; }
+
+p.tableblock { font-size: 1em; }
+
+td > div.verse { white-space: pre; }
+
+ol { margin-left: 1.75em; }
+
+ul li ol { margin-left: 1.5em; }
+
+dl dd { margin-left: 1.125em; }
+
+dl dd:last-child, dl dd:last-child > :last-child { margin-bottom: 0; }
+
+ol > li p, ul > li p, ul dd, ol dd, .olist .olist, .ulist .ulist, .ulist .olist, .olist .ulist { margin-bottom: 0.375em; }
+
+ul.checklist, ul.none, ol.none, ul.no-bullet, ol.no-bullet, ol.unnumbered, ul.unstyled, ol.unstyled { list-style-type: none; }
+
+ul.no-bullet, ol.no-bullet, ol.unnumbered { margin-left: 0.625em; }
+
+ul.unstyled, ol.unstyled { margin-left: 0; }
+
+ul.checklist { margin-left: 0.625em; }
+
+ul.checklist li > p:first-child > .fa-square-o:first-child, ul.checklist li > p:first-child > .fa-check-square-o:first-child { width: 1.25em; font-size: 0.8em; position: relative; bottom: 0.125em; }
+
+ul.checklist li > p:first-child > input[type="checkbox"]:first-child { margin-right: 0.25em; }
+
+ul.inline { display: -ms-flexbox; display: -webkit-box; display: flex; -ms-flex-flow: row wrap; -webkit-flex-flow: row wrap; flex-flow: row wrap; list-style: none; margin: 0 0 0.375em -0.75em; }
+
+ul.inline > li { margin-left: 0.75em; }
+
+.unstyled dl dt { font-weight: normal; font-style: normal; }
+
+ol.arabic { list-style-type: decimal; }
+
+ol.decimal { list-style-type: decimal-leading-zero; }
+
+ol.loweralpha { list-style-type: lower-alpha; }
+
+ol.upperalpha { list-style-type: upper-alpha; }
+
+ol.lowerroman { list-style-type: lower-roman; }
+
+ol.upperroman { list-style-type: upper-roman; }
+
+ol.lowergreek { list-style-type: lower-greek; }
+
+.hdlist > table, .colist > table { border: 0; background: none; }
+.hdlist > table > tbody > tr, .colist > table > tbody > tr { background: none; }
+
+td.hdlist1, td.hdlist2 { vertical-align: top; padding: 0 0.625em; }
+
+td.hdlist1 { font-weight: bold; padding-bottom: 0.75em; }
+
+.literalblock + .colist, .listingblock + .colist { margin-top: -0.5em; }
+
+.colist > table tr > td:first-of-type { padding: 0.4em 0.75em 0 0.75em; line-height: 1; vertical-align: top; }
+.colist > table tr > td:first-of-type img { max-width: initial; }
+.colist > table tr > td:last-of-type { padding: 0.25em 0; }
+
+.thumb, .th { line-height: 0; display: inline-block; border: solid 4px white; -webkit-box-shadow: 0 0 0 1px #dddddd; box-shadow: 0 0 0 1px #dddddd; }
+
+.imageblock.left, .imageblock[style*="float: left"] { margin: 0.25em 0.625em 1.25em 0; }
+.imageblock.right, .imageblock[style*="float: right"] { margin: 0.25em 0 1.25em 0.625em; }
+.imageblock > .title { margin-bottom: 0; }
+.imageblock.thumb, .imageblock.th { border-width: 6px; }
+.imageblock.thumb > .title, .imageblock.th > .title { padding: 0 0.125em; }
+
+.image.left, .image.right { margin-top: 0.25em; margin-bottom: 0.25em; display: inline-block; line-height: 0; }
+.image.left { margin-right: 0.625em; }
+.image.right { margin-left: 0.625em; }
+
+a.image { text-decoration: none; display: inline-block; }
+a.image object { pointer-events: none; }
+
+sup.footnote, sup.footnoteref { font-size: 0.875em; position: static; vertical-align: super; }
+sup.footnote a, sup.footnoteref a { text-decoration: none; }
+sup.footnote a:active, sup.footnoteref a:active { text-decoration: underline; }
+
+#footnotes { padding-top: 0.75em; padding-bottom: 0.75em; margin-bottom: 0.625em; }
+#footnotes hr { width: 20%; min-width: 6.25em; margin: -0.25em 0 0.75em 0; border-width: 1px 0 0 0; }
+#footnotes .footnote { padding: 0 0.375em 0 0.225em; line-height: 1.3334; font-size: 0.875em; margin-left: 1.2em; margin-bottom: 0.2em; }
+#footnotes .footnote a:first-of-type { font-weight: bold; text-decoration: none; margin-left: -1.05em; }
+#footnotes .footnote:last-of-type { margin-bottom: 0; }
+#content #footnotes { margin-top: -0.625em; margin-bottom: 0; padding: 0.75em 0; }
+
+.gist .file-data > table { border: 0; background: #fff; width: 100%; margin-bottom: 0; }
+.gist .file-data > table td.line-data { width: 99%; }
+
+div.unbreakable { page-break-inside: avoid; }
+
+.big { font-size: larger; }
+
+.small { font-size: smaller; }
+
+.underline { text-decoration: underline; }
+
+.overline { text-decoration: overline; }
+
+.line-through { text-decoration: line-through; }
+
+.aqua { color: #00bfbf; }
+
+.aqua-background { background-color: #00fafa; }
+
+.black { color: black; }
+
+.black-background { background-color: black; }
+
+.blue { color: #0000bf; }
+
+.blue-background { background-color: #0000fa; }
+
+.fuchsia { color: #bf00bf; }
+
+.fuchsia-background { background-color: #fa00fa; }
+
+.gray { color: #606060; }
+
+.gray-background { background-color: #7d7d7d; }
+
+.green { color: #006000; }
+
+.green-background { background-color: #007d00; }
+
+.lime { color: #00bf00; }
+
+.lime-background { background-color: #00fa00; }
+
+.maroon { color: #600000; }
+
+.maroon-background { background-color: #7d0000; }
+
+.navy { color: #000060; }
+
+.navy-background { background-color: #00007d; }
+
+.olive { color: #606000; }
+
+.olive-background { background-color: #7d7d00; }
+
+.purple { color: #600060; }
+
+.purple-background { background-color: #7d007d; }
+
+.red { color: #bf0000; }
+
+.red-background { background-color: #fa0000; }
+
+.silver { color: #909090; }
+
+.silver-background { background-color: #bcbcbc; }
+
+.teal { color: #006060; }
+
+.teal-background { background-color: #007d7d; }
+
+.white { color: #bfbfbf; }
+
+.white-background { background-color: #fafafa; }
+
+.yellow { color: #bfbf00; }
+
+.yellow-background { background-color: #fafa00; }
+
+span.icon > .fa { cursor: default; }
+a span.icon > .fa { cursor: inherit; }
+
+.admonitionblock td.icon [class^="fa icon-"] { font-size: 2.5em; text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5); cursor: default; }
+.admonitionblock td.icon .icon-note:before { content: "\f05a"; color: #29475c; }
+.admonitionblock td.icon .icon-tip:before { content: "\f0eb"; text-shadow: 1px 1px 2px rgba(155, 155, 0, 0.8); color: #111; }
+.admonitionblock td.icon .icon-warning:before { content: "\f071"; color: #bf6900; }
+.admonitionblock td.icon .icon-caution:before { content: "\f06d"; color: #bf3400; }
+.admonitionblock td.icon .icon-important:before { content: "\f06a"; color: #bf0000; }
+
+.conum[data-value] { display: inline-block; color: #fff !important; background-color: black; -webkit-border-radius: 100px; border-radius: 100px; text-align: center; font-size: 0.75em; width: 1.67em; height: 1.67em; line-height: 1.67em; font-family: "Open Sans", "DejaVu Sans", sans-serif; font-style: normal; font-weight: bold; }
+.conum[data-value] * { color: #fff !important; }
+.conum[data-value] + b { display: none; }
+.conum[data-value]:after { content: attr(data-value); }
+pre .conum[data-value] { position: relative; top: -0.125em; }
+
+b.conum * { color: inherit !important; }
+
+.conum:not([data-value]):empty { display: none; }
+
+h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { border-bottom: 1px solid #dddddd; }
+
+.sect1 { padding-bottom: 0; }
+
+#toctitle { color: #00406F; font-weight: normal; margin-top: 1.5em; }
+
+.sidebarblock { border-color: #aaa; }
+
+code { -webkit-border-radius: 4px; border-radius: 4px; }
+
+p.tableblock.header { color: #6d6e71; }
+
+.literalblock pre, .listingblock pre { background: #eeeeee; }
+
+</style>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css">
+<style>
+/* Stylesheet for CodeRay to match GitHub theme | MIT License | http://foundation.zurb.com */
+/*pre.CodeRay {background-color:#f7f7f8;}*/
+.CodeRay .line-numbers{border-right:1px solid #d8d8d8;padding:0 0.5em 0 .25em}
+.CodeRay span.line-numbers{display:inline-block;margin-right:.5em;color:rgba(0,0,0,.3)}
+.CodeRay .line-numbers strong{color:rgba(0,0,0,.4)}
+table.CodeRay{border-collapse:separate;border-spacing:0;margin-bottom:0;border:0;background:none}
+table.CodeRay td{vertical-align: top;line-height:1.45}
+table.CodeRay td.line-numbers{text-align:right}
+table.CodeRay td.line-numbers>pre{padding:0;color:rgba(0,0,0,.3)}
+table.CodeRay td.code{padding:0 0 0 .5em}
+table.CodeRay td.code>pre{padding:0}
+.CodeRay .debug{color:#fff !important;background:#000080 !important}
+.CodeRay .annotation{color:#007}
+.CodeRay .attribute-name{color:#000080}
+.CodeRay .attribute-value{color:#700}
+.CodeRay .binary{color:#509}
+.CodeRay .comment{color:#998;font-style:italic}
+.CodeRay .char{color:#04d}
+.CodeRay .char .content{color:#04d}
+.CodeRay .char .delimiter{color:#039}
+.CodeRay .class{color:#458;font-weight:bold}
+.CodeRay .complex{color:#a08}
+.CodeRay .constant,.CodeRay .predefined-constant{color:#008080}
+.CodeRay .color{color:#099}
+.CodeRay .class-variable{color:#369}
+.CodeRay .decorator{color:#b0b}
+.CodeRay .definition{color:#099}
+.CodeRay .delimiter{color:#000}
+.CodeRay .doc{color:#970}
+.CodeRay .doctype{color:#34b}
+.CodeRay .doc-string{color:#d42}
+.CodeRay .escape{color:#666}
+.CodeRay .entity{color:#800}
+.CodeRay .error{color:#808}
+.CodeRay .exception{color:inherit}
+.CodeRay .filename{color:#099}
+.CodeRay .function{color:#900;font-weight:bold}
+.CodeRay .global-variable{color:#008080}
+.CodeRay .hex{color:#058}
+.CodeRay .integer,.CodeRay .float{color:#099}
+.CodeRay .include{color:#555}
+.CodeRay .inline{color:#000}
+.CodeRay .inline .inline{background:#ccc}
+.CodeRay .inline .inline .inline{background:#bbb}
+.CodeRay .inline .inline-delimiter{color:#d14}
+.CodeRay .inline-delimiter{color:#d14}
+.CodeRay .important{color:#555;font-weight:bold}
+.CodeRay .interpreted{color:#b2b}
+.CodeRay .instance-variable{color:#008080}
+.CodeRay .label{color:#970}
+.CodeRay .local-variable{color:#963}
+.CodeRay .octal{color:#40e}
+.CodeRay .predefined{color:#369}
+.CodeRay .preprocessor{color:#579}
+.CodeRay .pseudo-class{color:#555}
+.CodeRay .directive{font-weight:bold}
+.CodeRay .type{font-weight:bold}
+.CodeRay .predefined-type{color:inherit}
+.CodeRay .reserved,.CodeRay .keyword {color:#000;font-weight:bold}
+.CodeRay .key{color:#808}
+.CodeRay .key .delimiter{color:#606}
+.CodeRay .key .char{color:#80f}
+.CodeRay .value{color:#088}
+.CodeRay .regexp .delimiter{color:#808}
+.CodeRay .regexp .content{color:#808}
+.CodeRay .regexp .modifier{color:#808}
+.CodeRay .regexp .char{color:#d14}
+.CodeRay .regexp .function{color:#404;font-weight:bold}
+.CodeRay .string{color:#d20}
+.CodeRay .string .string .string{background:#ffd0d0}
+.CodeRay .string .content{color:#d14}
+.CodeRay .string .char{color:#d14}
+.CodeRay .string .delimiter{color:#d14}
+.CodeRay .shell{color:#d14}
+.CodeRay .shell .delimiter{color:#d14}
+.CodeRay .symbol{color:#990073}
+.CodeRay .symbol .content{color:#a60}
+.CodeRay .symbol .delimiter{color:#630}
+.CodeRay .tag{color:#008080}
+.CodeRay .tag-special{color:#d70}
+.CodeRay .variable{color:#036}
+.CodeRay .insert{background:#afa}
+.CodeRay .delete{background:#faa}
+.CodeRay .change{color:#aaf;background:#007}
+.CodeRay .head{color:#f8f;background:#505}
+.CodeRay .insert .insert{color:#080}
+.CodeRay .delete .delete{color:#800}
+.CodeRay .change .change{color:#66f}
+.CodeRay .head .head{color:#f4f}
+</style>
+<link rel="stylesheet" href="../katex/katex.min.css">
+<script src="../katex/katex.min.js"></script>
+<script src="../katex/contrib/auto-render.min.js"></script>
+    <!-- Use KaTeX to render math once document is loaded, see
+         https://github.com/Khan/KaTeX/tree/master/contrib/auto-render -->
+<script>
+    document.addEventListener("DOMContentLoaded", function () {
+        renderMathInElement(
+            document.body,
+            {
+                delimiters: [
+                    { left: "$$", right: "$$", display: true},
+                    { left: "\\[", right: "\\]", display: true},
+                    { left: "$", right: "$", display: false},
+                    { left: "\\(", right: "\\)", display: false}
+                ]
+            }
+        );
+    });
+</script></head>
+<body class="book toc2 toc-left" style="max-width: 100;">
+<div id="header">
+<h1>The OpenCL<sup>&#8482;</sup> C 2.0 Specification</h1>
+<div class="details">
+<span id="author" class="author">Document Revision: 40</span><br>
+<span id="revnumber">version 2.2-7,</span>
+<span id="revdate">Sat, 12 May 2018 13:21:28 +0000</span>
+<br><span id="revremark">from git branch: master commit: ab6da3001e9eeafaa36c18888ca7eb4ebb9768af</span>
+</div>
+<div id="toc" class="toc2">
+<div id="toctitle">Table of Contents</div>
+<ul class="sectlevel1">
+<li><a href="#the-opencl-c-programming-language">1. The OpenCL C Programming Language</a>
+<ul class="sectlevel2">
+<li><a href="#supported-data-types">1.1. Supported Data Types</a>
+<ul class="sectlevel3">
+<li><a href="#built-in-scalar-data-types">1.1.1. Built-in Scalar Data Types</a></li>
+<li><a href="#built-in-vector-data-types">1.1.2. Built-in Vector Data Types<sup>4</sup></a></li>
+<li><a href="#other-built-in-data-types">1.1.3. Other Built-in Data Types</a></li>
+<li><a href="#reserved-data-types">1.1.4. Reserved Data Types</a></li>
+<li><a href="#alignment-of-types">1.1.5. Alignment of Types</a></li>
+<li><a href="#vector-literals">1.1.6. Vector Literals</a></li>
+<li><a href="#vector-components">1.1.7. Vector Components</a></li>
+<li><a href="#aliasing-rules">1.1.8. Aliasing Rules</a></li>
+<li><a href="#keywords">1.1.9. Keywords</a></li>
+</ul>
+</li>
+<li><a href="#conversions-and-type-casting">1.2. Conversions and Type Casting</a>
+<ul class="sectlevel3">
+<li><a href="#implicit-conversions">1.2.1. Implicit Conversions</a></li>
+<li><a href="#explicit-casts">1.2.2. Explicit Casts</a></li>
+<li><a href="#explicit-conversions">1.2.3. Explicit Conversions</a></li>
+<li><a href="#reinterpreting-data-as-another-type">1.2.4. Reinterpreting Data As Another Type</a></li>
+<li><a href="#pointer-casting">1.2.5. Pointer Casting</a></li>
+<li><a href="#usual-arithmetic-conversions">1.2.6. Usual Arithmetic Conversions</a></li>
+</ul>
+</li>
+<li><a href="#operators">1.3. Operators</a>
+<ul class="sectlevel3">
+<li><a href="#operators-arithmetic">1.3.1. Arithmetic Operators</a></li>
+<li><a href="#operators-unary">1.3.2. Unary Operators</a></li>
+<li><a href="#operators-prepost">1.3.3. Operators</a></li>
+<li><a href="#operators-relational">1.3.4. Relational Operators</a></li>
+<li><a href="#operators-equality">1.3.5. Equality Operators</a></li>
+<li><a href="#operators-bitwise">1.3.6. Bitwise Operators</a></li>
+<li><a href="#operators-logical">1.3.7. Logical Operators</a></li>
+<li><a href="#operators-logical-unary">1.3.8. Unary Logical Operator</a></li>
+<li><a href="#operators-ternary-selection">1.3.9. Ternary Selection Operator</a></li>
+<li><a href="#operators-shift">1.3.10. Shift Operators</a></li>
+<li><a href="#operators-sizeof">1.3.11. Sizeof Operator</a></li>
+<li><a href="#operators-comma">1.3.12. Comma Operator</a></li>
+<li><a href="#operators-indirection">1.3.13. Indirection Operator</a></li>
+<li><a href="#operators-address">1.3.14. Address Operator</a></li>
+<li><a href="#operators-assignment">1.3.15. Assignment Operator</a></li>
+</ul>
+</li>
+<li><a href="#vector-operations">1.4. Vector Operations</a></li>
+<li><a href="#address-space-qualifiers">1.5. Address Space Qualifiers</a>
+<ul class="sectlevel3">
+<li><a href="#global-or-global">1.5.1. <code>__global</code> (or <code>global</code>)</a></li>
+<li><a href="#local-or-local">1.5.2. <code>__local</code> (or <code>local</code>)</a></li>
+<li><a href="#constant-or-constant">1.5.3. <code>__constant</code> (or <code>constant</code>)</a></li>
+<li><a href="#private-or-private">1.5.4. <code>__private</code> (or <code>private</code>)</a></li>
+<li><a href="#the-generic-address-space">1.5.5. The generic address space</a></li>
+<li><a href="#changes-to-C99">1.5.6. Changes to C99</a></li>
+</ul>
+</li>
+<li><a href="#access-qualifiers">1.6. Access Qualifiers</a></li>
+<li><a href="#function-qualifiers">1.7. Function Qualifiers</a>
+<ul class="sectlevel3">
+<li><a href="#kernel-or-kernel">1.7.1. <code>__kernel</code> (or <code>kernel</code>)</a></li>
+<li><a href="#optional-attribute-qualifiers">1.7.2. Optional Attribute Qualifiers</a></li>
+</ul>
+</li>
+<li><a href="#storage-class-specifiers">1.8. Storage-Class Specifiers</a></li>
+<li><a href="#restrictions">1.9. Restrictions</a></li>
+<li><a href="#preprocessor-directives-and-macros">1.10. Preprocessor Directives and Macros</a></li>
+<li><a href="#attribute-qualifiers">1.11. Attribute Qualifiers</a>
+<ul class="sectlevel3">
+<li><a href="#specifying-attributes-of-types">1.11.1. Specifying Attributes of Types</a></li>
+<li><a href="#specifying-attributes-of-functions">1.11.2. Specifying Attributes of Functions</a></li>
+<li><a href="#specifying-attributes-of-variables">1.11.3. Specifying Attributes of Variables</a></li>
+<li><a href="#specifying-attributes-of-blocks-and-control-flow-statements">1.11.4. Specifying Attributes of Blocks and Control-Flow-Statements</a></li>
+<li><a href="#specifying-attribute-for-unrolling-loops">1.11.5. Specifying Attribute For Unrolling Loops</a></li>
+<li><a href="#extending-attribute-qualifiers">1.11.6. Extending Attribute Qualifiers</a></li>
+</ul>
+</li>
+<li><a href="#blocks">1.12. Blocks</a>
+<ul class="sectlevel3">
+<li><a href="#declaring-and-using-a-block">1.12.1. Declaring and Using a Block</a></li>
+<li><a href="#declaring-a-block-reference">1.12.2. Declaring a Block Reference</a></li>
+<li><a href="#block-literal-expressions">1.12.3. Block Literal Expressions</a></li>
+<li><a href="#control-flow">1.12.4. Control Flow</a></li>
+<li><a href="#restrictions-1">1.12.5. Restrictions</a></li>
+</ul>
+</li>
+<li><a href="#built-in-functions">1.13. Built-in Functions</a>
+<ul class="sectlevel3">
+<li><a href="#work-item-functions">1.13.1. Work-Item Functions</a></li>
+<li><a href="#math-functions">1.13.2. Math Functions</a></li>
+<li><a href="#integer-functions">1.13.3. Integer Functions</a></li>
+<li><a href="#common-functions">1.13.4. Common Functions<sup>33</sup></a></li>
+<li><a href="#geometric-functions">1.13.5. Geometric Functions<sup>34</sup></a></li>
+<li><a href="#relational-functions">1.13.6. Relational Functions</a></li>
+<li><a href="#vector-data-load-and-store-functions">1.13.7. Vector Data Load and Store Functions</a></li>
+<li><a href="#synchronization-functions">1.13.8. Synchronization Functions</a></li>
+<li><a href="#address-space-qualifier-functions">1.13.9. Address Space Qualifier Functions</a></li>
+<li><a href="#async-copies">1.13.10. Async Copies from Global to Local Memory, Local to Global Memory, and Prefetch</a></li>
+<li><a href="#atomic-functions">1.13.11. Atomic Functions</a></li>
+<li><a href="#miscellaneous-vector-functions">1.13.12. Miscellaneous Vector Functions</a></li>
+<li><a href="#printf">1.13.13. printf</a></li>
+<li><a href="#image-read-and-write-functions">1.13.14. Image Read and Write Functions</a></li>
+<li><a href="#work-group-functions">1.13.15. Work-group Functions</a></li>
+<li><a href="#pipe-functions">1.13.16. Pipe Functions</a></li>
+<li><a href="#enqueuing-kernels">1.13.17. Enqueuing Kernels</a></li>
+</ul>
+</li>
+</ul>
+</li>
+<li><a href="#opencl-numerical-compliance">2. OpenCL Numerical Compliance</a>
+<ul class="sectlevel2">
+<li><a href="#rounding-modes-1">2.1. Rounding Modes</a></li>
+<li><a href="#inf-nan-and-denormalized-numbers">2.2. INF, NaN and Denormalized Numbers</a></li>
+<li><a href="#floating-point-exceptions">2.3. Floating-Point Exceptions</a></li>
+<li><a href="#relative-error-as-ulps">2.4. Relative Error as ULPs</a></li>
+<li><a href="#edge-case-behavior">2.5. Edge Case Behavior</a>
+<ul class="sectlevel3">
+<li><a href="#additional-requirements-beyond-c99-tc2">2.5.1. Additional Requirements Beyond C99 TC2</a></li>
+<li><a href="#changes-to-c99-tc2-behavior">2.5.2. Changes to C99 TC2 Behavior</a></li>
+<li><a href="#edge-case-behavior-in-flush-to-zero-mode">2.5.3. Edge Case Behavior in Flush To Zero Mode</a></li>
+</ul>
+</li>
+</ul>
+</li>
+<li><a href="#image-addressing-and-filtering">3. Image Addressing and Filtering</a>
+<ul class="sectlevel2">
+<li><a href="#image-coordinates">3.1. Image Coordinates</a></li>
+<li><a href="#addressing-and-filter-modes">3.2. Addressing and Filter Modes</a></li>
+<li><a href="#conversion-rules">3.3. Conversion Rules</a>
+<ul class="sectlevel3">
+<li><a href="#conversion-rules-for-normalized-integer-channel-data-types">3.3.1. Conversion rules for normalized integer channel data types</a></li>
+<li><a href="#conversion-rules-for-half-precision-floating-point-channel-data-type">3.3.2. Conversion rules for half precision floating-point channel data type</a></li>
+<li><a href="#conversion-rules-for-floating-point-channel-data-type">3.3.3. Conversion rules for floating-point channel data type</a></li>
+<li><a href="#conversion-rules-for-signed-and-unsigned-8-bit-16-bit-and-32-bit-integer-channel-data-types">3.3.4. Conversion rules for signed and unsigned 8-bit, 16-bit and 32-bit integer channel data types</a></li>
+<li><a href="#conversion-rules-for-srgba-and-sbgra-images">3.3.5. Conversion rules for sRGBA and sBGRA images</a></li>
+</ul>
+</li>
+<li><a href="#selecting-an-image-from-an-image-array">3.4. Selecting an Image from an Image Array</a></li>
+</ul>
+</li>
+<li><a href="#references">4. Normative References</a></li>
+</ul>
+</div>
+</div>
+<div id="content">
+<div id="preamble">
+<div class="sectionbody">
+<div style="page-break-after: always;"></div>
+<div class="paragraph">
+<p>Copyright 2008-2018 The Khronos Group.</p>
+</div>
+<div class="paragraph">
+<p>This specification is protected by copyright laws and contains material proprietary
+to the Khronos Group, Inc. Except as described by these terms, it or any components
+may not be reproduced, republished, distributed, transmitted, displayed, broadcast
+or otherwise exploited in any manner without the express prior written permission
+of Khronos Group.</p>
+</div>
+<div class="paragraph">
+<p>Khronos Group grants a conditional copyright license to use and reproduce the
+unmodified specification for any purpose, without fee or royalty, EXCEPT no licenses
+to any patent, trademark or other intellectual property rights are granted under
+these terms. Parties desiring to implement the specification and make use of
+Khronos trademarks in relation to that implementation, and receive reciprocal patent
+license protection under the Khronos IP Policy must become Adopters and confirm the
+implementation as conformant under the process defined by Khronos for this
+specification; see <a href="https://www.khronos.org/adopters" class="bare">https://www.khronos.org/adopters</a>.</p>
+</div>
+<div class="paragraph">
+<p>Khronos Group makes no, and expressly disclaims any, representations or warranties,
+express or implied, regarding this specification, including, without limitation:
+merchantability, fitness for a particular purpose, non-infringement of any
+intellectual property, correctness, accuracy, completeness, timeliness, and
+reliability. Under no circumstances will the Khronos Group, or any of its Promoters,
+Contributors or Members, or their respective partners, officers, directors,
+employees, agents or representatives be liable for any damages, whether direct,
+indirect, special or consequential damages for lost revenues, lost profits, or
+otherwise, arising from or in connection with these materials.</p>
+</div>
+<div class="paragraph">
+<p>Vulkan is a registered trademark and Khronos, OpenXR, SPIR, SPIR-V, SYCL, WebGL,
+WebCL, OpenVX, OpenVG, EGL, COLLADA, glTF, NNEF, OpenKODE, OpenKCAM, StreamInput,
+OpenWF, OpenSL ES, OpenMAX, OpenMAX AL, OpenMAX IL, OpenMAX DL, OpenML and DevU are
+trademarks of the Khronos Group Inc. ASTC is a trademark of ARM Holdings PLC,
+OpenCL is a trademark of Apple Inc. and OpenGL and OpenML are registered trademarks
+and the OpenGL ES and OpenGL SC logos are trademarks of Silicon Graphics
+International used under license by Khronos. All other product names, trademarks,
+and/or company names are used solely for identification and belong to their
+respective owners.</p>
+</div>
+<div style="page-break-after: always;"></div>
+<div class="paragraph">
+<p><strong>Acknowledgements</strong></p>
+</div>
+<div class="paragraph">
+<p>The OpenCL specification is the result of the contributions of many people,
+representing a cross section of the desktop, hand-held, and embedded
+computer industry.
+Following is a partial list of the contributors, including the company that
+they represented at the time of their contribution:</p>
+</div>
+<div class="paragraph">
+<p>Chuck Rose, Adobe<br>
+Eric Berdahl, Adobe<br>
+Shivani Gupta, Adobe<br>
+Bill Licea Kane, AMD<br>
+Ed Buckingham, AMD<br>
+Jan Civlin, AMD<br>
+Laurent Morichetti, AMD<br>
+Mark Fowler, AMD<br>
+Marty Johnson, AMD<br>
+Michael Mantor, AMD<br>
+Norm Rubin, AMD<br>
+Ofer Rosenberg, AMD<br>
+Brian Sumner, AMD<br>
+Victor Odintsov, AMD<br>
+Aaftab Munshi, Apple<br>
+Abe Stephens, Apple<br>
+Alexandre Namaan, Apple<br>
+Anna Tikhonova, Apple<br>
+Chendi Zhang, Apple<br>
+Eric Bainville, Apple<br>
+David Hayward, Apple<br>
+Giridhar Murthy, Apple<br>
+Ian Ollmann, Apple<br>
+Inam Rahman, Apple<br>
+James Shearer, Apple<br>
+MonPing Wang, Apple<br>
+Tanya Lattner, Apple<br>
+Mikael Bourges-Sevenier, Aptina<br>
+Anton Lokhmotov, ARM<br>
+Dave Shreiner, ARM<br>
+Hedley Francis, ARM<br>
+Robert Elliott, ARM<br>
+Scott Moyers, ARM<br>
+Tom Olson, ARM<br>
+Anastasia Stulova, ARM<br>
+Christopher Thompson-Walsh, Broadcom<br>
+Holger Waechtler, Broadcom<br>
+Norman Rink, Broadcom<br>
+Andrew Richards, Codeplay<br>
+Maria Rovatsou, Codeplay<br>
+Alistair Donaldson, Codeplay<br>
+Alastair Murray, Codeplay<br>
+Stephen Frye, Electronic Arts<br>
+Eric Schenk, Electronic Arts<br>
+Daniel Laroche, Freescale<br>
+David Neto, Google<br>
+Robin Grosman, Huawei<br>
+Craig Davies, Huawei<br>
+Brian Horton, IBM<br>
+Brian Watt, IBM<br>
+Gordon Fossum, IBM<br>
+Greg Bellows, IBM<br>
+Joaquin Madruga, IBM<br>
+Mark Nutter, IBM<br>
+Mike Perks, IBM<br>
+Sean Wagner, IBM<br>
+Jon Parr, Imagination Technologies<br>
+Robert Quill, Imagination Technologies<br>
+James McCarthy, Imagination Technologie<br>
+Jon Leech, Independent<br>
+Aaron Kunze, Intel<br>
+Aaron Lefohn, Intel<br>
+Adam Lake, Intel<br>
+Alexey Bader, Intel<br>
+Allen Hux, Intel<br>
+Andrew Brownsword, Intel<br>
+Andrew Lauritzen, Intel<br>
+Bartosz Sochacki, Intel<br>
+Ben Ashbaugh, Intel<br>
+Brian Lewis, Intel<br>
+Geoff Berry, Intel<br>
+Hong Jiang, Intel<br>
+Jayanth Rao, Intel<br>
+Josh Fryman, Intel<br>
+Larry Seiler, Intel<br>
+Mike MacPherson, Intel<br>
+Murali Sundaresan, Intel<br>
+Paul Lalonde, Intel<br>
+Raun Krisch, Intel<br>
+Stephen Junkins, Intel<br>
+Tim Foley, Intel<br>
+Timothy Mattson, Intel<br>
+Yariv Aridor, Intel<br>
+Michael Kinsner, Intel<br>
+Kevin Stevens, Intel<br>
+Jon Leech, Khronos<br>
+Benjamin Bergen, Los Alamos National Laboratory<br>
+Roy Ju, Mediatek<br>
+Bor-Sung Liang, Mediatek<br>
+Rahul Agarwal, Mediatek<br>
+Michal Witaszek, Mobica<br>
+JenqKuen Lee, NTHU<br>
+Amit Rao, NVIDIA<br>
+Ashish Srivastava, NVIDIA<br>
+Bastiaan Aarts, NVIDIA<br>
+Chris Cameron, NVIDIA<br>
+Christopher Lamb, NVIDIA<br>
+Dibyapran Sanyal, NVIDIA<br>
+Guatam Chakrabarti, NVIDIA<br>
+Ian Buck, NVIDIA<br>
+Jaydeep Marathe, NVIDIA<br>
+Jian-Zhong Wang, NVIDIA<br>
+Karthik Raghavan Ravi, NVIDIA<br>
+Kedar Patil, NVIDIA<br>
+Manjunath Kudlur, NVIDIA<br>
+Mark Harris, NVIDIA<br>
+Michael Gold, NVIDIA<br>
+Neil Trevett, NVIDIA<br>
+Richard Johnson, NVIDIA<br>
+Sean Lee, NVIDIA<br>
+Tushar Kashalikar, NVIDIA<br>
+Vinod Grover, NVIDIA<br>
+Xiangyun Kong, NVIDIA<br>
+Yogesh Kini, NVIDIA<br>
+Yuan Lin, NVIDIA<br>
+Mayuresh Pise, NVIDIA<br>
+Allan Tzeng, QUALCOMM<br>
+Alex Bourd, QUALCOMM<br>
+Anirudh Acharya, QUALCOMM<br>
+Andrew Gruber, QUALCOMM<br>
+Andrzej Mamona, QUALCOMM<br>
+Benedict Gaster, QUALCOMM<br>
+Bill Torzewski, QUALCOMM<br>
+Bob Rychlik, QUALCOMM<br>
+Chihong Zhang, QUALCOMM<br>
+Chris Mei, QUALCOMM<br>
+Colin Sharp, QUALCOMM<br>
+David Garcia, QUALCOMM<br>
+David Ligon, QUALCOMM<br>
+Jay Yun, QUALCOMM<br>
+Lee Howes, QUALCOMM<br>
+Richard Ruigrok, QUALCOMM<br>
+Robert J. Simpson, QUALCOMM<br>
+Sumesh Udayakumaran, QUALCOMM<br>
+Vineet Goel, QUALCOMM<br>
+Lihan Bin, QUALCOMM<br>
+Vlad Shimanskiy, QUALCOMM<br>
+Jian Liu, QUALCOMM<br>
+Tasneem Brutch, Samsung<br>
+Yoonseo Choi, Samsung<br>
+Dennis Adams, Sony<br>
+Pr-Anders Aronsson, Sony<br>
+Jim Rasmusson, Sony<br>
+Thierry Lepley, STMicroelectronics<br>
+Anton Gorenko, StreamHPC<br>
+Jakub Szuppe, StreamHPC<br>
+Vincent Hindriksen, StreamHPC<br>
+Alan Ward, Texas Instruments<br>
+Yuan Zhao, Texas Instruments<br>
+Pete Curry, Texas Instruments<br>
+Simon McIntosh-Smith, University of Bristol<br>
+James Price, University of Bristol<br>
+Paul Preney, University of Windsor<br>
+Shane Peelar, University of Windsor<br>
+Brian Hutsell, Vivante<br>
+Mike Cai, Vivante<br>
+Sumeet Kumar, Vivante<br>
+Wei-Lun Kao, Vivante<br>
+Xing Wang, Vivante<br>
+Jeff Fifield, Xilinx<br>
+Hem C. Neema, Xilinx<br>
+Henry Styles, Xilinx<br>
+Ralph Wittig, Xilinx<br>
+Ronan Keryell, Xilinx<br>
+AJ Guillon, YetiWare Inc<br></p>
+</div>
+<div style="page-break-after: always;"></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="the-opencl-c-programming-language">1. The OpenCL C Programming Language</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>This section describes the OpenCL C programming language used to create
+kernels that are executed on OpenCL device(s).
+The OpenCL C programming language (also referred to as OpenCL C) is based on
+the <a href="#C99-spec">ISO/IEC 9899:1999 C language</a> Specification (a.k.a. &#8220;C99
+Specification&#8221; or just &#8220;C99&#8221;) with specific extensions and restrictions.
+Please refer to that Specification for a detailed description of the
+language grammar.
+This document describes modifications and restrictions to C99 supported in
+OpenCL C.</p>
+</div>
+<div class="paragraph">
+<p>In addition, some features of OpenCL C are based on the <a href="#C11-spec">ISO/IEC
+9899:2011 C language</a> Specification (a.k.a. &#8220;C11 Specification&#8221; or just
+&#8220;C11&#8221;.
+Such features are described by reference to that Specification.</p>
+</div>
+<div class="sect2">
+<h3 id="supported-data-types">1.1. Supported Data Types</h3>
+<div class="paragraph">
+<p>The following data types are supported.</p>
+</div>
+<div class="sect3">
+<h4 id="built-in-scalar-data-types">1.1.1. Built-in Scalar Data Types</h4>
+<div class="paragraph">
+<p>The following table describes the list of built-in scalar data types.</p>
+</div>
+<table id="table-builtin-scalar-types" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 1. Built-in Scalar Data Types</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Type</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>bool</code><sup>1</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A conditional data type which is either <em>true</em> or <em>false</em>.
+     The value <em>true</em> expands to the integer constant 1 and the value
+     <em>false</em> expands to the integer constant 0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>char</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A signed two&#8217;s complement 8-bit integer.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>unsigned char</code>, <code>uchar</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">An unsigned 8-bit integer.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>short</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A signed two&#8217;s complement 16-bit integer.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>unsigned short</code>, <code>ushort</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">An unsigned 16-bit integer.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>int</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A signed two&#8217;s complement 32-bit integer.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>unsigned int</code>, <code>uint</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">An unsigned 32-bit integer.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>long</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A signed two&#8217;s complement 64-bit integer.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>unsigned long</code>, <code>ulong</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">An unsigned 64-bit integer.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>float</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 32-bit floating-point.
+      The <code>float</code> data type must conform to the IEEE 754 single precision
+      storage format.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>double</code><sup>2</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 64-bit floating-point.
+      The <code>double</code> data type must conform to the IEEE 754 double precision
+      storage format.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>half</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 16-bit floating-point.
+      The <code>half</code> data type must conform to the IEEE 754-2008 half precision
+      storage format.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>size_t</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The unsigned integer type<sup>3</sup> of the result of the <code>sizeof</code> operator.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>ptrdiff_t</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A signed integer type<sup>3</sup> that is the result of subtracting two
+      pointers.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>intptr_t</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A signed integer type<sup>3</sup> with the property that any valid pointer to
+      <code>void</code> can be converted to this type, then converted back to pointer
+      to <code>void</code>, and the result will compare equal to the original pointer.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>uintptr_t</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">An unsigned integer type<sup>3</sup> with the property that any valid pointer
+      to <code>void</code> can be converted to this type, then converted back to
+      pointer to <code>void</code>, and the result will compare equal to the original
+      pointer.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>void</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The <code>void</code> type comprises an empty set of values; it is an incomplete
+      type that cannot be completed.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>[1] When any scalar value is converted to <code>bool</code>, the result is 0 if the
+value compares equal to 0; otherwise, the result is 1.</p>
+</div>
+<div class="paragraph">
+<p>[2] The <code>double</code> scalar type is an optional type that is supported if the
+value of the <a href="#opencl-device-queries"><code>CL_DEVICE_DOUBLE_FP_CONFIG</code> device
+query</a> is not zero.</p>
+</div>
+<div class="paragraph">
+<p>[3] These are 32-bit types if the value of the <a href="#opencl-device-queries"><code>CL_DEVICE_ADDRESS_BITS</code> device query</a> is 32-bits, and 64-bit types if the
+value of the query is 64-bits.</p>
+</div>
+<div class="paragraph">
+<p>Most built-in scalar data types are also declared as appropriate types in
+the OpenCL API (and header files) that can be used by an application.
+The following table describes the built-in scalar data type in the OpenCL C
+programming language and the corresponding data type available to the
+application:</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Type in OpenCL Language</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>API type for application</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>bool</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">n/a</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>char</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_char</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>unsigned char</code>, <code>uchar</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_uchar</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>short</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_short</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>unsigned short</code>, <code>ushort</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_ushort</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>int</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_int</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>unsigned int</code>, <code>uint</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_uint</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>long</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_long</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>unsigned long</code>, <code>ulong</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_ulong</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>float</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_float</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>double</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_double</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>half</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_half</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>size_t</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">n/a</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>ptrdiff_t</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">n/a</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>intptr_t</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">n/a</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>uintptr_t</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">n/a</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>void</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>void</code></p></td>
+</tr>
+</tbody>
+</table>
+<div class="sect4">
+<h5 id="the-half-data-type">The <code>half</code> data type</h5>
+<div class="paragraph">
+<p>The <code>half</code> data type must be IEEE 754-2008 compliant.
+<code>half</code> numbers have 1 sign bit, 5 exponent bits, and 10 mantissa bits.
+The interpretation of the sign, exponent and mantissa is analogous to IEEE
+754 floating-point numbers.
+The exponent bias is 15.
+The <code>half</code> data type must represent finite and normal numbers, denormalized
+numbers, infinities and NaN.
+Denormalized numbers for the <code>half</code> data type which may be generated when
+converting a <code>float</code> to a <code>half</code> using <strong>vstore_half</strong> and converting a <code>half</code>
+to a <code>float</code> using <strong>vload_half</strong> cannot be flushed to zero.
+Conversions from <code>float</code> to <code>half</code> correctly round the mantissa to 11 bits
+of precision.
+Conversions from <code>half</code> to <code>float</code> are lossless; all <code>half</code> numbers are
+exactly representable as <code>float</code> values.</p>
+</div>
+<div class="paragraph">
+<p>The <code>half</code> data type can only be used to declare a pointer to a buffer that
+contains <code>half</code> values.
+A few valid examples are given below:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="directive">void</span>
+bar (__global half *p)
+{
+    ...
+}
+
+__kernel <span class="directive">void</span>
+foo (__global half *pg, __local half *pl)
+{
+    __global half *ptr;
+    <span class="predefined-type">int</span> offset;
+
+    ptr = pg + offset;
+    bar(ptr);
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Below are some examples that are not valid usage of the <code>half</code> type:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">half a;
+half b[<span class="integer">100</span>];
+half *p;
+a = *p; <span class="comment">//  not allowed. must use *vload_half* function</span></code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Loads from a pointer to a <code>half</code> and stores to a pointer to a <code>half</code> can be
+performed using the <a href="#vector-data-load-and-store-functions">vector data load
+and store functions</a> <strong>vload_half</strong>, <strong>vload_half<em>n</em></strong>, <strong>vloada_halfn</strong> and
+<strong>vstore_half</strong>, <strong>vstore_half<em>n</em></strong>, and <strong>vstorea_halfn</strong>.
+The load functions read scalar or vector <code>half</code> values from memory and
+convert them to a scalar or vector <code>float</code> value.
+The store functions take a scalar or vector <code>float</code> value as input, convert
+it to a <code>half</code> scalar or vector value (with appropriate rounding mode) and
+write the <code>half</code> scalar or vector value to memory.</p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="built-in-vector-data-types">1.1.2. Built-in Vector Data Types<sup>4</sup></h4>
+<div class="paragraph">
+<p>The <code>char</code>, <code>unsigned char</code>, <code>short</code>, <code>unsigned short</code>, <code>int</code>, <code>unsigned
+int</code>, <code>long</code>, <code>unsigned long</code>, and <code>float</code> vector data types are supported.
+The vector data type is defined with the type name, i.e. <code>char</code>, <code>uchar</code>,
+<code>short</code>, <code>ushort</code>, <code>int</code>, <code>uint</code>, <code>long</code>, <code>ulong</code>, or <code>float</code>, followed by a
+literal value <em>n</em> that defines the number of elements in the vector.
+Supported values of <em>n</em> are 2, 3, 4, 8, and 16 for all vector data types.</p>
+</div>
+<div class="paragraph">
+<p>[4] Built-in vector data types are supported by the OpenCL implementation
+even if the underlying compute device does not support any or all of the
+vector data types.
+These are to be converted by the device compiler to appropriate instructions
+that use underlying built-in types supported natively by the compute device.
+Refer to Appendix B for a description of the order of the components of a
+vector type in memory.</p>
+</div>
+<div class="paragraph">
+<p>The following table describes the list of built-in vector data types.</p>
+</div>
+<table id="table-builtin-vector-types" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 2. Built-in Vector Data Types</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Type</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>char<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A vector of <em>n</em> 8-bit signed two&#8217;s complement integer values.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>uchar<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A vector of <em>n</em> 8-bit unsigned integer values.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>short<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A vector of <em>n</em> 16-bit signed two&#8217;s complement integer values.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>ushort<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A vector of <em>n</em> 16-bit unsigned integer values.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>int<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A vector of <em>n</em> 32-bit signed two&#8217;s complement integer values.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>uint<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A vector of <em>n</em> 32-bit unsigned integer values.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>long<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A vector of <em>n</em> 64-bit signed two&#8217;s complement integer values.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>ulong<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A vector of <em>n</em> 64-bit unsigned integer values.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>float<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A vector of <em>n</em> 32-bit floating-point values.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>double<em>n</em></code><sup>5</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A vector of <em>n</em> 64-bit floating-point values.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>[5] The <code>double</code> vector type is an optional type that is supported if the
+value of the <a href="#opencl-device-queries"><code>CL_DEVICE_DOUBLE_FP_CONFIG</code> device
+query</a> is not zero.</p>
+</div>
+<div class="paragraph">
+<p>The built-in vector data types are also declared as appropriate types in the
+OpenCL API (and header files) that can be used by an application.
+The following table describes the built-in vector data type in the OpenCL C
+programming language and the corresponding data type available to the
+application:</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Type in OpenCL Language</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>API type for application</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>char<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_char<em>n</em></code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>uchar<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_uchar<em>n</em></code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>short<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_short<em>n</em></code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>ushort<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_ushort<em>n</em></code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>int<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_int<em>n</em></code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>uint<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_uint<em>n</em></code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>long<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_long<em>n</em></code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>ulong<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_ulong<em>n</em></code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>float<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_float<em>n</em></code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>double<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_double<em>n</em></code></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="other-built-in-data-types">1.1.3. Other Built-in Data Types</h4>
+<div class="paragraph">
+<p>The following table describes the list of additional data types supported by
+OpenCL.</p>
+</div>
+<table id="table-other-builtin-types" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 3. Other Built-in Data Types</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Type</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>image2d_t</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 2D image<sup>6</sup>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>image3d_t</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 3D image<sup>6</sup>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>image2d_array_t</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 2D image array<sup>6</sup>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>image1d_t</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 1D image<sup>6</sup>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>image1d_buffer_t</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 1D image created from a buffer object<sup>6</sup>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>image1d_array_t</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 1D image array<sup>6</sup>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>image2d_depth_t</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 2D depth image<sup>6</sup>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>image2d_array_depth_t</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 2D depth image array<sup>6</sup>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>sampler_t</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A sampler type<sup>6</sup>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>queue_t</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A device command queue.
+      This queue can only be used to enqueue commands from kernels executing
+      on the device.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>ndrange_t</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The N-dimensional range over which a kernel executes.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>clk_event_t</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A device side event that identifies a command enqueue to
+      a device command queue.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>reserve_id_t</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A reservation ID.
+      This opaque type is used to identify the reservation for
+      <a href="#pipe-functions">reading and writing a pipe</a>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>event_t</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">An event.
+      This can be used to identify <a href="#async-copies">async copies</a> from
+      <code>global</code> to <code>local</code> memory and vice-versa.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_mem_fence_flags</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This is a bitfield and can be 0 or a combination of the following
+      values ORed together:</p>
+<p class="tableblock">      <code>CLK_GLOBAL_MEM_FENCE</code><br>
+      <code>CLK_LOCAL_MEM_FENCE</code><br>
+      <code>CLK_IMAGE_MEM_FENCE</code></p>
+<p class="tableblock">      These flags are described in detail in the
+      <a href="#synchronization-functions">synchronization functions</a> section.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>[6] Refer to the detailed description of the built-in
+<a href="#image-read-and-write-functions">functions that use this type</a>.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>The <code>image2d_t</code>, <code>image3d_t</code>, <code>image2d_array_t</code>, <code>image1d_t</code>,
+<code>image1d_buffer_t</code>, <code>image1d_array_t</code>, <code>image2d_depth_t</code>,
+<code>image2d_array_depth_t</code> and <code>sampler_t</code> types are only defined if the device
+supports images, i.e. the value of the <a href="#opencl-device-queries"><code>CL_DEVICE_IMAGE_SUPPORT</code> device query</a>) is <code>CL_TRUE</code>.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p>The C99 derived types (arrays, structs, unions, functions, and pointers),
+constructed from the built-in <a href="#built-in-scalar-data-types">scalar</a>,
+<a href="#built-in-vector-data-types">vector</a>, and
+<a href="#other-built-in-data-types">other</a> data types are supported, with specified
+<a href="#restrictions">restrictions</a>.</p>
+</div>
+<div class="paragraph">
+<p>The following tables describe the other built-in data types in OpenCL
+described in <a href="#table-other-builtin-types">Other Built-in Data Types</a> and the corresponding data type
+available to the application:</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Type in OpenCL C</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>API type for application</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>queue_t</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_command_queue</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>clk_event_t</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_event</code></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="reserved-data-types">1.1.4. Reserved Data Types</h4>
+<div class="paragraph">
+<p>The data type names described in the following table are reserved and cannot
+be used by applications as type names.
+The vector data type names defined in <a href="#table-builtin-vector-types">Built-in Vector Data Types</a>, but
+where <em>n</em> is any value other than 2, 3, 4, 8 and 16, are also reserved.</p>
+</div>
+<table id="table-reserved-types" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 4. Reserved Data Types</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Type</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>bool<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A boolean vector.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>half<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 16-bit floating-point vector.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>quad</code>, <code>quad<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 128-bit floating-point scalar and vector.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>complex half</code>, <code>complex half<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A complex 16-bit floating-point scalar and vector.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>imaginary half</code>, <code>imaginary half<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">An imaginary 16-bit floating-point scalar and vector.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>complex float</code>, <code>complex float<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A complex 32-bit floating-point scalar and vector.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>imaginary float</code>, <code>imaginary float<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">An imaginary 32-bit floating-point scalar and vector.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>complex double</code>, <code>complex double<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A complex 64-bit floating-point scalar and vector.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>imaginary double</code>, <code>imaginary double<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">An imaginary 64-bit floating-point scalar and vector.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>complex quad</code>, <code>complex quad<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A complex 128-bit floating-point scalar and vector.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>imaginary quad</code>, <code>imaginary quad<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">An imaginary 128-bit floating-point scalar and vector.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>float<em>n</em>x<em>m</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">An <em>n</em> × <em>m</em> matrix of single precision floating-point values
+      stored in column-major order.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>double<em>n</em>x<em>m</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">An <em>n</em> × <em>m</em> matrix of double precision floating-point values
+      stored in column-major order.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>long double</code> <code>long double<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A floating-point scalar and vector type with at least as much
+      precision and range as a <code>double</code> and no more precision and range than
+      a quad.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>long long, long long<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 128-bit signed integer scalar and vector.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>unsigned long long</code>,
+  <code>ulong long</code>,
+  <code>ulong long<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 128-bit unsigned integer scalar and vector.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="alignment-of-types">1.1.5. Alignment of Types</h4>
+<div class="paragraph">
+<p>A data item declared to be a data type in memory is always aligned to the
+size of the data type in bytes.
+For example, a <code>float4</code> variable will be aligned to a 16-byte boundary, a
+<code>char2</code> variable will be aligned to a 2-byte boundary.</p>
+</div>
+<div class="paragraph">
+<p>For 3-component vector data types, the size of the data type is <code>4 *
+sizeof(component)</code>.
+This means that a 3-component vector data type will be aligned to a <code>4 *
+sizeof(component)</code> boundary.
+The <strong>vload3</strong> and <strong>vstore3</strong> built-in functions can be used to read and write,
+respectively, 3-component vector data types from an array of packed scalar
+data type.</p>
+</div>
+<div class="paragraph">
+<p>A built-in data type that is not a power of two bytes in size must be
+aligned to the next larger power of two.
+This rule applies to built-in types only, not structs or unions.</p>
+</div>
+<div class="paragraph">
+<p>The OpenCL compiler is responsible for aligning data items to the
+appropriate alignment as required by the data type.
+For arguments to a <code>__kernel</code> function declared to be a pointer to a data
+type, the OpenCL compiler can assume that the pointee is always
+appropriately aligned as required by the data type.
+The behavior of an unaligned load or store is undefined, except for the
+<a href="#vector-data-load-and-store-functions">vector data load and store
+functions</a> <strong>vload<em>n</em></strong>, <strong>vload_half<em>n</em></strong>, <strong>vstore<em>n</em></strong>, and
+<strong>vstore_half<em>n</em></strong>.
+The vector load functions can read a vector from an address aligned to the
+element type of the vector.
+The vector store functions can write a vector to an address aligned to the
+element type of the vector.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="vector-literals">1.1.6. Vector Literals</h4>
+<div class="paragraph">
+<p>Vector literals can be used to create vectors from a list of scalars,
+vectors or a mixture thereof.
+A vector literal can be used either as a vector initializer or as a primary
+expression.
+A vector literal cannot be used as an l-value.</p>
+</div>
+<div class="paragraph">
+<p>A vector literal is written as a parenthesized vector type followed by a
+parenthesized comma delimited list of parameters.
+A vector literal operates as an overloaded function.
+The forms of the function that are available is the set of possible argument
+lists for which all arguments have the same element type as the result
+vector, and the total number of elements is equal to the number of elements
+in the result vector.
+In addition, a form with a single scalar of the same type as the element
+type of the vector is available.
+For example, the following forms are available for <code>float4</code>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">(float4)( <span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="predefined-type">float</span> )
+(float4)( float2, <span class="predefined-type">float</span>, <span class="predefined-type">float</span> )
+(float4)( <span class="predefined-type">float</span>, float2, <span class="predefined-type">float</span> )
+(float4)( <span class="predefined-type">float</span>, <span class="predefined-type">float</span>, float2 )
+(float4)( float2, float2 )
+(float4)( float3, <span class="predefined-type">float</span> )
+(float4)( <span class="predefined-type">float</span>, float3 )
+(float4)( <span class="predefined-type">float</span> )</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Operands are evaluated by standard rules for function evaluation, except
+that implicit scalar widening shall not occur.
+The order in which the operands are evaluated is undefined.
+The operands are assigned to their respective positions in the result vector
+as they appear in memory order.
+That is, the first element of the first operand is assigned to <code>result.x</code>,
+the second element of the first operand (or the first element of the second
+operand if the first operand was a scalar) is assigned to <code>result.y</code>, etc.
+In the case of the form that has a single scalar operand, the operand is
+replicated across all lanes of the vector.</p>
+</div>
+<div class="paragraph">
+<p>Examples:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">float4 f = (float4)(<span class="float">1</span><span class="float">.0f</span>, <span class="float">2</span><span class="float">.0f</span>, <span class="float">3</span><span class="float">.0f</span>, <span class="float">4</span><span class="float">.0f</span>);
+uint4 u = (uint4)(<span class="integer">1</span>); <span class="comment">//  u will be (1, 1, 1, 1).</span>
+float4 f = (float4)float2)(<span class="float">1</span><span class="float">.0f</span>, <span class="float">2</span><span class="float">.0f</span>), (float2)(<span class="float">3</span><span class="float">.0f</span>, <span class="float">4</span><span class="float">.0f</span>;
+float4 f = (float4)(<span class="float">1</span><span class="float">.0f</span>, (float2)(<span class="float">2</span><span class="float">.0f</span>, <span class="float">3</span><span class="float">.0f</span>), <span class="float">4</span><span class="float">.0f</span>);
+float4 f = (float4)(<span class="float">1</span><span class="float">.0f</span>, <span class="float">2</span><span class="float">.0f</span>); <span class="comment">//  error</span></code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="vector-components">1.1.7. Vector Components</h4>
+<div class="paragraph">
+<p>The components of vector data types with 1 &#8230;&#8203; 4 components can be addressed
+as <code>&lt;vector_data_type&gt;.xyzw</code>.
+Vector data types of type <code>char2</code>, <code>uchar2</code>, <code>short2</code>, <code>ushort2</code>, <code>int2</code>,
+<code>uint2</code>, <code>long2</code>, <code>ulong2</code>, and <code>float2</code> can access <code>.xy</code> elements.
+Vector data types of type <code>char3</code>, <code>uchar3</code>, <code>short3</code>, <code>ushort3</code>, <code>int3</code>,
+<code>uint3</code>, <code>long3</code>, <code>ulong3</code>, and <code>float3</code> can access <code>.xyz</code> elements.
+Vector data types of type <code>char4</code>, <code>uchar4</code>, <code>short4</code>, <code>ushort4</code>, <code>int4</code>,
+<code>uint4</code>, <code>long4</code>, <code>ulong4</code>, and <code>float4</code> can access <code>.xyzw</code> elements.</p>
+</div>
+<div class="paragraph">
+<p>Accessing components beyond those declared for the vector type is an error
+so, for example:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">float2 pos;
+pos.x = <span class="float">1</span><span class="float">.0f</span>; <span class="comment">// is legal</span>
+pos.z = <span class="float">1</span><span class="float">.0f</span>; <span class="comment">// is illegal</span>
+
+float3 pos;
+pos.z = <span class="float">1</span><span class="float">.0f</span>; <span class="comment">// is legal</span>
+pos.w = <span class="float">1</span><span class="float">.0f</span>; <span class="comment">// is illegal</span></code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The component selection syntax allows multiple components to be selected by
+appending their names after the period (<strong>.</strong>).</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">float4 c;
+
+c.xyzw = (float4)(<span class="float">1</span><span class="float">.0f</span>, <span class="float">2</span><span class="float">.0f</span>, <span class="float">3</span><span class="float">.0f</span>, <span class="float">4</span><span class="float">.0f</span>);
+c.z = <span class="float">1</span><span class="float">.0f</span>;
+c.xy = (float2)(<span class="float">3</span><span class="float">.0f</span>, <span class="float">4</span><span class="float">.0f</span>);
+c.xyz = (float3)(<span class="float">3</span><span class="float">.0f</span>, <span class="float">4</span><span class="float">.0f</span>, <span class="float">5</span><span class="float">.0f</span>);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The component selection syntax also allows components to be permuted or
+replicated.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">float4 pos = (float4)(<span class="float">1</span><span class="float">.0f</span>, <span class="float">2</span><span class="float">.0f</span>, <span class="float">3</span><span class="float">.0f</span>, <span class="float">4</span><span class="float">.0f</span>);
+
+float4 swiz= pos.wzyx; <span class="comment">// swiz = (4.0f, 3.0f, 2.0f, 1.0f)</span>
+
+float4 dup = pos.xxyy; <span class="comment">// dup = (1.0f, 1.0f, 2.0f, 2.0f)</span></code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The component group notation can occur on the left hand side of an
+expression.
+To form an l-value, swizzling must be applied to an l-value of vector type,
+contain no duplicate components, and it results in an l-value of scalar or
+vector type, depending on number of components specified.
+Each component must be a supported scalar or vector type.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">float4 pos = (float4)(<span class="float">1</span><span class="float">.0f</span>, <span class="float">2</span><span class="float">.0f</span>, <span class="float">3</span><span class="float">.0f</span>, <span class="float">4</span><span class="float">.0f</span>);
+
+pos.xw = (float2)(<span class="float">5</span><span class="float">.0f</span>, <span class="float">6</span><span class="float">.0f</span>);<span class="comment">// pos = (5.0f, 2.0f, 3.0f, 6.0f)</span>
+pos.wx = (float2)(<span class="float">7</span><span class="float">.0f</span>, <span class="float">8</span><span class="float">.0f</span>);<span class="comment">// pos = (8.0f, 2.0f, 3.0f, 7.0f)</span>
+pos.xyz = (float3)(<span class="float">3</span><span class="float">.0f</span>, <span class="float">5</span><span class="float">.0f</span>, <span class="float">9</span><span class="float">.0f</span>); <span class="comment">// pos = (3.0f, 5.0f, 9.0f, 4.0f)</span>
+pos.xx = (float2)(<span class="float">3</span><span class="float">.0f</span>, <span class="float">4</span><span class="float">.0f</span>);<span class="comment">// illegal - 'x' used twice</span>
+
+<span class="comment">// illegal - mismatch between float2 and float4</span>
+pos.xy = (float4)(<span class="float">1</span><span class="float">.0f</span>, <span class="float">2</span><span class="float">.0f</span>, <span class="float">3</span><span class="float">.0f</span>, <span class="float">4</span><span class="float">.0f</span>);
+
+float4 a, b, c, d;
+float16 x;
+x = (float16)(a, b, c, d);
+x = (float16)(a.xxxx, b.xyz, c.xyz, d.xyz, a.yzw);
+
+<span class="comment">// illegal - component a.xxxxxxx is not a valid vector type</span>
+x = (float16)(a.xxxxxxx, b.xyz, c.xyz, d.xyz);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Elements of vector data types can also be accessed using a numeric index to
+refer to the appropriate element in the vector.
+The numeric indices that can be used are given in the table below:</p>
+</div>
+<table id="table-vector-indices" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 5. Numeric indices for built-in vector data types</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Vector Components</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Numeric indices that can be used</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">2-component</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0, 1</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">3-component</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0, 1, 2</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">4-component</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0, 1, 2, 3</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">8-component</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0, 1, 2, 3, 4, 5, 6, 7</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">16-component</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+                        a, A, b, B, c, C, d, D, e, E, f, F</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>The numeric indices must be preceded by the letter <code>s</code> or <code>S</code>.</p>
+</div>
+<div class="paragraph">
+<p>In the following example</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">float8 f;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><code>f.s0</code> refers to the 1<sup>st</sup> element of the <code>float8</code> variable <code>f</code> and <code>f.s7</code>
+refers to the 8<sup>th</sup> element of the <code>float8</code> variable <code>f</code>.</p>
+</div>
+<div class="paragraph">
+<p>In the following example</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">float16 x;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><code>x.sa</code> (or <code>x.sA</code>) refers to the 11<sup>th</sup> element of the <code>float16</code> variable
+<code>x</code> and <code>x.sf</code> (or <code>x.sF</code>) refers to the 16<sup>th</sup> element of the <code>float16</code>
+variable <code>x</code>.</p>
+</div>
+<div class="paragraph">
+<p>The numeric indices used to refer to an appropriate element in the vector
+cannot be intermixed with <code>.xyzw</code> notation used to access elements of a 1 ..
+4 component vector.</p>
+</div>
+<div class="paragraph">
+<p>For example</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">float4 f, a;
+
+a = f.x12w;       <span class="comment">// illegal use of numeric indices with .xyzw</span>
+
+a.xyzw = f.s0123; <span class="comment">// valid</span></code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Vector data types can use the <code>.lo</code> (or <code>.even</code>) and <code>.hi</code> (or <code>.odd</code>)
+suffixes to get smaller vector types or to combine smaller vector types to a
+larger vector type.
+Multiple levels of <code>.lo</code> (or <code>.even</code>) and <code>.hi</code> (or <code>.odd</code>) suffixes can be
+used until they refer to a scalar term.</p>
+</div>
+<div class="paragraph">
+<p>The <code>.lo</code> suffix refers to the lower half of a given vector.
+The <code>.hi</code> suffix refers to the upper half of a given vector.</p>
+</div>
+<div class="paragraph">
+<p>The <code>.even</code> suffix refers to the even elements of a vector.
+The <code>.odd</code> suffix refers to the odd elements of a vector.</p>
+</div>
+<div class="paragraph">
+<p>Some examples to help illustrate this are given below:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">float4 vf;
+
+float2 low = vf.lo;    <span class="comment">// returns vf.xy</span>
+float2 high = vf.hi;   <span class="comment">// returns vf.zw</span>
+
+float2 even = vf.even; <span class="comment">// returns vf.xz</span>
+float2 odd = vf.odd;   <span class="comment">// returns vf.yw</span></code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The suffixes <code>.lo</code> (or <code>.even</code>) and <code>.hi</code> (or <code>.odd</code>) for a 3-component
+vector type operate as if the 3-component vector type is a 4-component
+vector type with the value in the <code>w</code> component undefined.</p>
+</div>
+<div class="paragraph">
+<p>Some examples are given below:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">float8 vf;
+float4 odd = vf.odd;
+float4 even = vf.even;
+float2 high = vf.even.hi;
+float2 low = vf.odd.lo;
+
+<span class="comment">// interleave LR stereo stream</span>
+float4 left, right;
+float8 interleaved;
+interleaved.even = left;
+interleaved.odd = right;
+
+<span class="comment">// deinterleave</span>
+left = interleaved.even;
+right = interleaved.odd;
+
+<span class="comment">// transpose a 4x4 matrix</span>
+
+<span class="directive">void</span> transpose( float4 m[<span class="integer">4</span>] )
+{
+    <span class="comment">// read matrix into a float16 vector</span>
+    float16 x = (float16)( m[<span class="integer">0</span>], m[<span class="integer">1</span>], m[<span class="integer">2</span>], m[<span class="integer">3</span>] );
+    float16 t;
+
+    <span class="comment">// transpose</span>
+    t.even = x.lo;
+    t.odd = x.hi;
+    x.even = t.lo;
+    x.odd = t.hi;
+
+    <span class="comment">// write back</span>
+    m[<span class="integer">0</span>] = x.lo.lo; <span class="comment">// { m[0][0], m[1][0], m[2][0], m[3][0] }</span>
+    m[<span class="integer">1</span>] = x.lo.hi; <span class="comment">// { m[0][1], m[1][1], m[2][1], m[3][1] }</span>
+    m[<span class="integer">2</span>] = x.hi.lo; <span class="comment">// { m[0][2], m[1][2], m[2][2], m[3][2] }</span>
+    m[<span class="integer">3</span>] = x.hi.hi; <span class="comment">// { m[0][3], m[1][3], m[2][3], m[3][3] }</span>
+}
+
+float3 vf = (float3)(<span class="float">1</span><span class="float">.0f</span>, <span class="float">2</span><span class="float">.0f</span>, <span class="float">3</span><span class="float">.0f</span>);
+float2 low = vf.lo; <span class="comment">// (1.0f, 2.0f);</span>
+float2 high = vf.hi; <span class="comment">// (3.0f, _undefined_);</span></code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>It is an error to take the address of a vector element and will result in a
+compilation error.
+For example:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">float8 vf;
+
+<span class="predefined-type">float</span> *f = &amp;vf.x; m         <span class="comment">// is illegal</span>
+float2 *f2 = &amp;vf.s07;       <span class="comment">// is illegal</span>
+
+float4 *odd = &amp;vf.odd;      <span class="comment">// is illegal</span>
+float4 *even = &amp;vf.even;    <span class="comment">// is illegal</span>
+float2 *high = &amp;vf.even.hi; <span class="comment">// is illegal</span>
+float2 *low = &amp;vf.odd.lo;   <span class="comment">// is illegal</span></code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="aliasing-rules">1.1.8. Aliasing Rules</h4>
+<div class="paragraph">
+<p>OpenCL C programs shall comply with the C99 type-based aliasing rules
+defined in <a href="#C99-spec">section 6.5, item 7 of the C99 Specification</a>.
+The OpenCL C built-in vector data types are considered aggregate<sup>7</sup> types
+for the purpose of applying these aliasing rules.</p>
+</div>
+<div class="paragraph">
+<p>[7] That is, for the purpose of applying type-based aliasing rules, a
+built-in vector data type will be considered equivalent to the corresponding
+array type.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="keywords">1.1.9. Keywords</h4>
+<div class="paragraph">
+<p>The following names are reserved for use as keywords in OpenCL C and shall
+not be used otherwise.</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Names reserved as keywords by C99.</p>
+</li>
+<li>
+<p>OpenCL C data types defined in <a href="#table-builtin-vector-types">Built-in Vector Data Types</a>,
+<a href="#table-other-builtin-types">Other Built-in Data Types</a>, and <a href="#table-reserved-types">Reserved Data Types</a>.</p>
+</li>
+<li>
+<p>Address space qualifiers: <code>__global</code>, <code>global</code>, <code>__local</code>, <code>local</code>,
+<code>__constant</code>, <code>constant</code>, <code>__private</code>, and <code>private</code>.
+<code>__generic</code> and <code>generic</code> are reserved for future use.</p>
+</li>
+<li>
+<p>Function qualifiers: <code>__kernel</code> and <code>kernel</code>.</p>
+</li>
+<li>
+<p>Access qualifiers: <code>__read_only</code>, <code>read_only</code>, <code>__write_only</code>,
+<code>write_only</code>, <code>__read_write</code> and <code>read_write</code>.</p>
+</li>
+<li>
+<p><code>uniform</code>, <code>pipe</code>.</p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="conversions-and-type-casting">1.2. Conversions and Type Casting</h3>
+<div class="sect3">
+<h4 id="implicit-conversions">1.2.1. Implicit Conversions</h4>
+<div class="paragraph">
+<p>Implicit conversions between scalar built-in types defined in
+<a href="#table-builtin-scalar-types">Built-in Scalar Data Types</a> (except <code>void</code> and <code>half</code><sup>8</sup>) are supported.
+When an implicit conversion is done, it is not just a re-interpretation of
+the expression&#8217;s value but a conversion of that value to an equivalent value
+in the new type.
+For example, the integer value 5 will be converted to the floating-point
+value 5.0.</p>
+</div>
+<div class="paragraph">
+<p>[8] Unless the <strong>cl_khr_fp16</strong> extension is supported and has been enabled.</p>
+</div>
+<div class="paragraph">
+<p>Implicit conversions from a scalar type to a vector type are allowed.
+In this case, the scalar may be subject to the usual arithmetic conversion
+to the element type used by the vector.
+The scalar type is then widened to the vector.</p>
+</div>
+<div class="paragraph">
+<p>Implicit conversions between built-in vector data types are disallowed.</p>
+</div>
+<div class="paragraph">
+<p>Implicit conversions for pointer types follow the rules described in the
+&lt;C99-spec,C99 Specification&gt;&gt;.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="explicit-casts">1.2.2. Explicit Casts</h4>
+<div class="paragraph">
+<p>Standard typecasts for built-in scalar data types defined in
+<a href="#table-builtin-scalar-types">Built-in Scalar Data Types</a> will perform appropriate conversion (except
+<code>void</code> and <code>half</code><sup>9</sup>).
+In the example below:</p>
+</div>
+<div class="paragraph">
+<p>[9] Unless the <strong>cl_khr_fp16</strong> extension is supported and has been enabled.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="predefined-type">float</span> f = <span class="float">1</span><span class="float">.0f</span>;
+<span class="predefined-type">int</span> i = (<span class="predefined-type">int</span>)f;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><code>f</code> stores <code>0x3F800000</code> and <code>i</code> stores <code>0x1</code> which is the floating-point
+value <code>1.0f</code> in <code>f</code> converted to an integer value.</p>
+</div>
+<div class="paragraph">
+<p>Explicit casts between vector types are not legal.
+The examples below will generate a compilation error.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">int4 i;
+uint4 u = (uint4) i; <span class="comment">//  not allowed</span>
+
+float4 f;
+int4 i = (int4) f; <span class="comment">//  not allowed</span>
+
+float4 f;
+int8 i = (int8) f; <span class="comment">//  not allowed</span></code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Scalar to vector conversions may be performed by casting the scalar to the
+desired vector data type.
+Type casting will also perform appropriate arithmetic conversion.
+The round to zero rounding mode will be used for conversions to built-in
+integer vector types.
+The default rounding mode will be used for conversions to floating-point
+vector types.
+When casting a <code>bool</code> to a vector integer data type, the vector components
+will be set to -1 (i.e. all bits set) if the bool value is <em>true</em> and 0
+otherwise.</p>
+</div>
+<div class="paragraph">
+<p>Below are some correct examples of explicit casts.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="predefined-type">float</span> f = <span class="float">1</span><span class="float">.0f</span>;
+float4 va = (float4)f;
+
+<span class="comment">// va is a float4 vector with elements (f, f, f, f).</span>
+
+uchar u = <span class="hex">0xFF</span>;
+float4 vb = (float4)u;
+
+<span class="comment">// vb is a float4 vector with elements</span>
+<span class="comment">// ((float)u, (float)u, (float)u, (float)u).</span>
+
+<span class="predefined-type">float</span> f = <span class="float">2</span><span class="float">.0f</span>;
+int2 vc = (int2)f;
+
+<span class="comment">// vc is an int2 vector with elements ((int)f, (int)f).</span>
+
+uchar4 vtrue = (uchar4)<span class="predefined-constant">true</span>;
+
+<span class="comment">// vtrue is a uchar4 vector with elements (0xff, 0xff,</span>
+<span class="comment">// 0xff, 0xff).</span></code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="explicit-conversions">1.2.3. Explicit Conversions</h4>
+<div class="paragraph">
+<p>Explicit conversions may be performed using the</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">convert_destType(sourceType)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>suite of functions.
+These provide a full set of type conversions between supported
+<a href="#built-in-scalar-data-types">scalar</a>,
+<a href="#built-in-vector-data-types">vector</a>, and
+<a href="#other-built-in-data-types">other</a> data types except for the following
+types: <code>bool</code>, <code>half</code>, <code>size_t</code>, <code>ptrdiff_t</code>, <code>intptr_t</code>, <code>uintptr_t</code>, and
+<code>void</code>.</p>
+</div>
+<div class="paragraph">
+<p>The number of elements in the source and destination vectors must match.</p>
+</div>
+<div class="paragraph">
+<p>In the example below:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">uchar4 u;
+int4 c = convert_int4(u);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><code>convert_int4</code> converts a <code>uchar4</code> vector <code>u</code> to an <code>int4</code> vector <code>c</code>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="predefined-type">float</span> f;
+<span class="predefined-type">int</span> i = convert_int(f);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><code>convert_int</code> converts a <code>float</code> scalar <code>f</code> to an int scalar <code>i</code>.</p>
+</div>
+<div class="paragraph">
+<p>The behavior of the conversion may be modified by one or two optional
+modifiers that specify saturation for out-of-range inputs and rounding
+behavior.</p>
+</div>
+<div class="paragraph">
+<p>The full form of the scalar convert function is:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">destType *convert_destType&lt;_sat&gt;&lt;_roundingMode&gt;*(sourceType)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The full form of the vector convert function is:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">destType__n__ *convert_destType__n__&lt;_sat&gt;&lt;_roundingMode&gt;*(sourceType__n__)</code></pre>
+</div>
+</div>
+<div class="sect4">
+<h5 id="data-types">Data Types</h5>
+<div class="paragraph">
+<p>Conversions are available for the following scalar types: <code>char</code>, <code>uchar</code>,
+<code>short</code>, <code>ushort</code>, <code>int</code>, <code>uint</code>, <code>long</code>, <code>ulong</code>, <code>float</code>, and built-in
+vector types derived therefrom.
+The operand and result type must have the same number of elements.
+The operand and result type may be the same type in which case the
+conversion has no effect on the type or value of an expression.</p>
+</div>
+<div class="paragraph">
+<p>Conversions between integer types follow the conversion rules specified in
+<a href="#C99-spec">sections 6.3.1.1 and 6.3.1.3 of the C99 Specification</a> except
+for <a href="#out-of-range-behavior">out-of-range behavior and saturated
+conversions</a>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="rounding-modes">Rounding Modes</h5>
+<div class="paragraph">
+<p>Conversions to and from floating-point type shall conform to IEEE-754
+rounding rules.
+Conversions may have an optional rounding mode modifier described in the
+following table.</p>
+</div>
+<table id="table-rounding-mode" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 6. Rounding Modes</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Modifier</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Rounding Mode Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>_rte</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Round to nearest even</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>_rtz</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Round toward zero</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>_rtp</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Round toward positive infinity</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>_rtn</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Round toward negative infinity</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">no modifier specified</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use the default rounding mode for this destination
+                          type, <code>_rtz</code> for conversion to integers or the
+                          default rounding mode for conversion to
+                          floating-point types.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>By default, conversions to integer type use the <code>_rtz</code> (round toward zero)
+rounding mode and conversions to floating-point type<sup>10</sup> use the default
+rounding mode.
+The only default floating-point rounding mode supported is round to nearest
+even i.e the default rounding mode will be <code>_rte</code> for floating-point types.</p>
+</div>
+<div class="paragraph">
+<p>[10] For conversions to floating-point format, when a finite source value
+exceeds the maximum representable finite floating-point destination value,
+the rounding mode will affect whether the result is the maximum finite
+floating-point value or infinity of same sign as the source value, per
+IEEE-754 rules for rounding.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="out-of-range-behavior">Out-of-Range Behavior and Saturated Conversions</h5>
+<div class="paragraph">
+<p>When the conversion operand is either greater than the greatest
+representable destination value or less than the least representable
+destination value, it is said to be out-of-range.
+The result of out-of-range conversion is determined by the conversion rules
+specified by <a href="#C99-spec">section 6.3 of the C99 Specification</a>.
+When converting from a floating-point type to integer type, the behavior is
+implementation-defined.</p>
+</div>
+<div class="paragraph">
+<p>Conversions to integer type may opt to convert using the optional saturated
+mode by appending the _sat modifier to the conversion function name.
+When in saturated mode, values that are outside the representable range
+shall clamp to the nearest representable value in the destination format.
+(NaN should be converted to 0).</p>
+</div>
+<div class="paragraph">
+<p>Conversions to floating-point type shall conform to IEEE-754 rounding rules.
+The <code>_sat</code> modifier may not be used for conversions to floating-point
+formats.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="explicit-conversion-examples">Explicit Conversion Examples</h5>
+<div class="paragraph">
+<p>Example 1:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">short4 s;
+
+<span class="comment">// negative values clamped to 0</span>
+ushort4 u = convert_ushort4_sat( s );
+
+<span class="comment">// values &gt; CHAR_MAX converted to CHAR_MAX</span>
+<span class="comment">// values &lt; CHAR_MIN converted to CHAR_MIN</span>
+char4 c = convert_char4_sat( s );</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Example 2:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">float4 f;
+
+<span class="comment">// values implementation defined for</span>
+<span class="comment">// f &gt; INT_MAX, f &lt; INT_MIN or NaN</span>
+int4 i = convert_int4( f );
+
+<span class="comment">// values &gt; INT_MAX clamp to INT_MAX, values &lt; INT_MIN clamp</span>
+<span class="comment">// to INT_MIN. NaN should produce 0.</span>
+<span class="comment">// The _rtz_ rounding mode is used to produce the integer values.</span>
+int4 i2 = convert_int4_sat( f );
+
+<span class="comment">// similar to convert_int4, except that floating-point values</span>
+<span class="comment">// are rounded to the nearest integer instead of truncated</span>
+int4 i3 = convert_int4_rte( f );
+
+<span class="comment">// similar to convert_int4_sat, except that floating-point values</span>
+<span class="comment">// are rounded to the nearest integer instead of truncated</span>
+int4 i4 = convert_int4_sat_rte( f );</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Example 3:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">int4 i;
+
+<span class="comment">// convert ints to floats using the default rounding mode.</span>
+float4 f = convert_float4( i );
+
+<span class="comment">// convert ints to floats. integer values that cannot</span>
+<span class="comment">// be exactly represented as floats should round up to the</span>
+<span class="comment">// next representable float.</span>
+float4 f = convert_float4_rtp( i );</code></pre>
+</div>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="reinterpreting-data-as-another-type">1.2.4. Reinterpreting Data As Another Type</h4>
+<div class="paragraph">
+<p>It is frequently necessary to reinterpret bits in a data type as another
+data type in OpenCL.
+This is typically required when direct access to the bits in a
+floating-point type is needed, for example to mask off the sign bit or make
+use of the result of a vector <a href="#operators-relational">relational operator</a>
+on floating-point data<sup>11</sup>.
+Several methods to achieve this (non-) conversion are frequently practiced
+in C, including pointer aliasing, unions and memcpy.
+Of these, only memcpy is strictly correct in C99.
+Since OpenCL does not provide <strong>memcpy</strong>, other methods are needed.</p>
+</div>
+<div class="paragraph">
+<p>[11] In addition, some other extensions to the C language designed to support
+particular vector ISA (e.g. AltiVec™, CELL Broadband Engine™
+Architecture) use such conversions in conjunction with swizzle operators to
+achieve type unconversion.
+So as to support legacy code of this type, <strong>as_typen</strong>() allows conversions
+between vectors of the same size but different numbers of elements, even
+though the behavior of this sort of conversion is not likely to be portable
+except to other OpenCL implementations for the same hardware architecture.
+AltiVec is a trademark of Motorola Inc.
+Cell Broadband Engine is a trademark of Sony Computer Entertainment, Inc.</p>
+</div>
+<div class="sect4">
+<h5 id="reinterpreting-types-using-unions">Reinterpreting Types Using Unions</h5>
+<div class="paragraph">
+<p>The OpenCL language extends the union to allow the program to access a
+member of a union object using a member of a different type.
+The relevant bytes of the representation of the object are treated as an
+object of the type used for the access.
+If the type used for access is larger than the representation of the object,
+then the value of the additional bytes is undefined.</p>
+</div>
+<div class="paragraph">
+<p>Examples:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="comment">// d only if double precision is supported</span>
+<span class="keyword">union</span> { <span class="predefined-type">float</span> f; uint u; <span class="predefined-type">double</span> d; } u;
+
+u.u = <span class="integer">1</span>;    <span class="comment">// u.f contains 2**-149.  u.d is undefined --</span>
+            <span class="comment">// depending on endianness the low or high half</span>
+            <span class="comment">// of d is unknown</span>
+
+u.f = <span class="float">1</span><span class="float">.0f</span>; <span class="comment">// u.u contains 0x3f800000, u.d contains an</span>
+            <span class="comment">// undefined value -- depending on endianness</span>
+            <span class="comment">// the low or high half of d is unknown</span>
+
+u.d = <span class="float">1</span><span class="float">.0</span>;  <span class="comment">// u.u contains 0x3ff00000 (big endian) or 0</span>
+            <span class="comment">// (little endian). u.f contains either 0x1.ep0f</span>
+            <span class="comment">// (big endian) or 0.0f (little endian)</span></code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="reinterpreting-types-using-as_type-and-as_typen">Reinterpreting Types Using <strong>as_type</strong>() and <strong>as_type<em>n</em></strong>()</h5>
+<div class="paragraph">
+<p>All data types described in <a href="#table-builtin-scalar-types">Built-in Scalar Data Types</a> and
+<a href="#table-builtin-vector-types">Built-in Vector Data Types</a> (except <code>bool</code>, <code>half</code><sup>12</sup> and <code>void</code>) may be
+also reinterpreted as another data type of the same size using the
+<strong>as_type</strong>() operator for scalar data types and the <strong>as_type<em>n</em></strong>()
+operator<sup>13</sup> for vector data types.
+When the operand and result type contain the same number of elements, the
+bits in the operand shall be returned directly without modification as the
+new type.
+The usual type promotion for function arguments shall not be performed.</p>
+</div>
+<div class="paragraph">
+<p>[12] Unless the <strong>cl_khr_fp16</strong> extension is supported and has been enabled.</p>
+</div>
+<div class="paragraph">
+<p>[13] While the union is intended to reflect the organization of data in
+memory, the <strong>as_type</strong>() and <strong>as_type<em>n</em></strong>() constructs are intended to
+reflect the organization of data in register.
+The <strong>as_type</strong>() and <strong>as_type<em>n</em></strong>() constructs are intended to compile to
+no instructions on devices that use a shared register file designed to
+operate on both the operand and result types.
+Note that while differences in memory organization are expected to largely
+be limited to those arising from endianness, the register based
+representation may also differ due to size of the element in register.
+(For example, an architecture may load a <code>char</code> into a 32-bit register, or a
+<code>char</code> vector into a SIMD vector register with fixed 32-bit element size.)
+If the element count does not match, then the implementation should pick a
+data representation that most closely matches what would happen if an
+appropriate result type operator was applied to a register containing data
+of the source type.
+If the number of elements matches, then the <strong>as_type<em>n</em></strong>() should
+faithfully reproduce the behavior expected from a similar data type
+reinterpretation using memory/unions.
+So, for example if an implementation stores all single precision data as
+<code>double</code> in register, it should implement <strong>as_int</strong>(<code>float</code>) by first
+downconverting the <code>double</code> to single precision and then (if necessary)
+moving the single precision bits to a register suitable for operating on
+integer data.
+If data stored in different address spaces do not have the same endianness,
+then the &#8220;dominant endianness&#8221; of the device should prevail.</p>
+</div>
+<div class="paragraph">
+<p>For example, <code><strong>as_float</strong>(0x3f800000)</code> returns <code>1.0f</code>, which is the value
+that the bit pattern <code>0x3f800000</code> has if viewed as an IEEE-754 single
+precision value.</p>
+</div>
+<div class="paragraph">
+<p>When the operand and result type contain a different number of elements, the
+result shall be implementation-defined except if the operand is a
+4-component vector and the result is a 3-component vector.
+In this case, the bits in the operand shall be returned directly without
+modification as the new type.
+That is, a conforming implementation shall explicitly define a behavior, but
+two conforming implementations need not have the same behavior when the
+number of elements in the result and operand types does not match.
+The implementation may define the result to contain all, some or none of the
+original bits in whatever order it chooses.
+It is an error to use <strong>as_type</strong>() or <strong>as_type<em>n</em></strong>() operator to
+reinterpret data to a type of a different number of bytes.</p>
+</div>
+<div class="paragraph">
+<p>Examples:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="predefined-type">float</span> f = <span class="float">1</span><span class="float">.0f</span>;
+uint u = as_uint(f); <span class="comment">// Legal. Contains:  0x3f800000</span>
+
+float4 f = (float4)(<span class="float">1</span><span class="float">.0f</span>, <span class="float">2</span><span class="float">.0f</span>, <span class="float">3</span><span class="float">.0f</span>, <span class="float">4</span><span class="float">.0f</span>);
+<span class="comment">// Legal. Contains:</span>
+<span class="comment">// (int4)(0x3f800000, 0x40000000, 0x40400000, 0x40800000)</span>
+int4 i = as_int4(f);
+
+float4 f, g;
+int4  is_less = f &lt; g;
+
+<span class="comment">// Legal. f[i] = f[i] &lt; g[i] ? f[i] : 0.0f</span>
+f = as_float4(as_int4(f) &amp; is_less);
+
+<span class="predefined-type">int</span> i;
+<span class="comment">// Legal. Result is implementation-defined.</span>
+short2 j = as_short2(i);
+
+int4 i;
+<span class="comment">// Legal. Result is implementation-defined.</span>
+short8 j = as_short8(i);
+
+float4 f;
+<span class="comment">// Error. Result and operand have different sizes</span>
+double4 g = as_double4(f); <span class="comment">// Only if double precision is supported.</span>
+
+float4 f;
+<span class="comment">// Legal. g.xyz will have same values as f.xyz. g.w is undefined</span>
+float3 g = as_float3(f);</code></pre>
+</div>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="pointer-casting">1.2.5. Pointer Casting</h4>
+<div class="paragraph">
+<p>Pointers to old and new types may be cast back and forth to each other.
+Casting a pointer to a new type represents an unchecked assertion that the
+address is correctly aligned.
+The developer will also need to know the endianness of the OpenCL device and
+the endianness of the data to determine how the scalar and vector data
+elements are stored in memory.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="usual-arithmetic-conversions">1.2.6. Usual Arithmetic Conversions</h4>
+<div class="paragraph">
+<p>Many operators that expect operands of arithmetic type cause conversions and
+yield result types in a similar way.
+The purpose is to determine a common real type for the operands and result.
+For the specified operands, each operand is converted, without change of
+type domain, to a type whose corresponding real type is the common real
+type.
+For this purpose, all vector types shall be considered to have higher
+conversion ranks than scalars.
+Unless explicitly stated otherwise, the common real type is also the
+corresponding real type of the result, whose type domain is the type domain
+of the operands if they are the same, and complex otherwise.
+This pattern is called the usual arithmetic conversions.
+If the operands are of more than one vector type, then an error shall occur.
+<a href="#implicit-conversions">Implicit conversions</a> between vector types are not
+permitted.</p>
+</div>
+<div class="paragraph">
+<p>Otherwise, if there is only a single vector type, and all other operands are
+scalar types, the scalar types are converted to the type of the vector
+element, then widened into a new vector containing the same number of
+elements as the vector, by duplication of the scalar value across the width
+of the new vector.
+An error shall occur if any scalar operand has greater rank than the type of
+the vector element.
+For this purpose, the rank order defined as follows:</p>
+</div>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>The rank of a floating-point type is greater than the rank of another
+floating-point type, if the first floating-point type can exactly
+represent all numeric values in the second floating-point type.
+(For this purpose, the encoding of the floating-point value is used,
+rather than the subset of the encoding usable by the device.)</p>
+</li>
+<li>
+<p>The rank of any floating-point type is greater than the rank of any
+integer type.</p>
+</li>
+<li>
+<p>The rank of an integer type is greater than the rank of an integer type
+with less precision.</p>
+</li>
+<li>
+<p>The rank of an unsigned integer type is <strong>greater than</strong> the rank of a
+signed integer type with the same precision<sup>14</sup>.</p>
+</li>
+<li>
+<p>The rank of the bool type is less than the rank of any other type.</p>
+</li>
+<li>
+<p>The rank of an enumerated type shall equal the rank of the compatible
+integer type.</p>
+</li>
+<li>
+<p>For all types, <code>T1</code>, <code>T2</code> and <code>T3</code>, if <code>T1</code> has greater rank than <code>T2</code>,
+and <code>T2</code> has greater rank than <code>T3</code>, then <code>T1</code> has greater rank than
+<code>T3</code>.</p>
+</li>
+</ol>
+</div>
+<div class="paragraph">
+<p>[14] This is different from the standard integer conversion rank described in
+<a href="#C99-spec">section 6.3.1.1 of the C99 Specification</a></p>
+</div>
+<div class="paragraph">
+<p>Otherwise, if all operands are scalar, the usual arithmetic conversions
+apply, per <a href="#C99-spec">section 6.3.1.8 of the C99 Specification</a>.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>Both the standard orderings in <a href="#C99-spec">sections 6.3.1.8 and 6.3.1.1 of
+the C99 Specification</a> were examined and rejected.
+Had we used integer conversion rank here, <code>int4 + 0U</code> would have been legal
+and had <code>int4</code> return type.
+Had we used standard C99 usual arithmetic conversion rules for scalars, then
+the standard integer promotion would have been performed on vector integer
+element types and <code>short8 + char</code> would either have return type of <code>int8</code> or
+be illegal.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="operators">1.3. Operators</h3>
+<div class="sect3">
+<h4 id="operators-arithmetic">1.3.1. Arithmetic Operators</h4>
+<div class="paragraph">
+<p>The arithmetic operators add (<strong>+</strong>), subtract (<strong>-</strong>), multiply (<strong>*</strong>) and
+divide (<strong>/</strong>) operate on built-in integer and floating-point scalar, and
+vector data types.
+The remainder (<strong>%</strong>) operates on built-in integer scalar and integer vector
+data types.
+All arithmetic operators return result of the same built-in type (integer or
+floating-point) as the type of the operands, after operand type conversion.
+After conversion, the following cases are valid:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>The two operands are scalars.
+In this case, the operation is applied, resulting in a scalar.</p>
+</li>
+<li>
+<p>One operand is a scalar, and the other is a vector.
+In this case, the scalar may be subject to the usual arithmetic
+conversion to the element type used by the vector operand.
+The scalar type is then widened to a vector that has the same number of
+components as the vector operand.
+The operation is done component-wise resulting in the same size vector.</p>
+</li>
+<li>
+<p>The two operands are vectors of the same type.
+In this case, the operation is done component-wise resulting in the same
+size vector.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>All other cases of implicit conversions are illegal.
+Division on integer types which results in a value that lies outside of the
+range bounded by the maximum and minimum representable values of the integer
+type will not cause an exception but will result in an unspecified value.
+A divide by zero with integer types does not cause an exception but will
+result in an unspecified value.
+Division by zero for floating-point types will result in ±∞ or
+NaN as prescribed by the IEEE-754 standard.
+Use the built-in functions <strong>dot</strong> and <strong>cross</strong> to get, respectively, the
+vector dot product and the vector cross product.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="operators-unary">1.3.2. Unary Operators</h4>
+<div class="paragraph">
+<p>The arithmetic unary operators (<strong>+</strong> and <strong>-</strong>) operate on built-in scalar and
+vector types.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="operators-prepost">1.3.3. Operators</h4>
+<div class="paragraph">
+<p>The arithmetic post- and pre-increment and decrement operators (<strong>--</strong> and
+<strong>++</strong>) operate on built-in scalar and vector types except the built-in scalar
+and vector <code>float</code> types<sup>15</sup>.
+All unary operators work component-wise on their operands.
+These result with the same type they operated on.
+For post- and pre-increment and decrement, the expression must be one that
+could be assigned to (an l-value).
+Pre-increment and pre-decrement add or subtract 1 to the contents of the
+expression they operate on, and the value of the pre-increment or
+pre-decrement expression is the resulting value of that modification.
+Post-increment and post-decrement expressions add or subtract 1 to the
+contents of the expression they operate on, but the resulting expression has
+the expression&#8217;s value before the post-increment or post-decrement was
+executed.</p>
+</div>
+<div class="paragraph">
+<p>[15] The pre- and post- increment operators may have unexpected behavior on
+floating-point values and are therefore not supported for floating-point
+scalar and vector built-in types.
+For example, if variable <em>a</em> has type <code>float</code> and holds the value
+<code>0x1.0p25f</code>, then <code><em>a</em>++</code> returns <code>0x1.0p25f</code>.
+Also, <code>(<em>a</em>++)--</code> is not guaranteed to return <em>a</em>, if <em>a</em> has fractional
+value.
+In non-default rounding modes, <code>(<em>a</em>++)--</code> may produce the same result as
+<code><em>a</em>++</code> or <code><em>a</em>--</code> for large <em>a</em>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="operators-relational">1.3.4. Relational Operators</h4>
+<div class="paragraph">
+<p>The relational operators<sup>16</sup> greater than (<strong>&gt;</strong>), less than (<strong>&lt;</strong>), greater
+than or equal (<strong>&gt;=</strong>), and less than or equal (<strong>&lt;=</strong>) operate on scalar and
+vector types.
+All relational operators result in an integer type.
+After operand type conversion, the following cases are valid:</p>
+</div>
+<div class="paragraph">
+<p>[16] To test whether any or all elements in the result of a vector relational
+operator test <em>true</em>, for example to use in the context in an <strong>if ( )</strong>
+statement, please see the <a href="#relational-functions"><strong>any</strong> and <strong>all</strong> builtins</a>.</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>The two operands are scalars.
+In this case, the operation is applied, resulting in an <code>int</code> scalar.</p>
+</li>
+<li>
+<p>One operand is a scalar, and the other is a vector.
+In this case, the scalar may be subject to the usual arithmetic
+conversion to the element type used by the vector operand.
+The scalar type is then widened to a vector that has the same number of
+components as the vector operand.
+The operation is done component-wise resulting in the same size vector.</p>
+</li>
+<li>
+<p>The two operands are vectors of the same type.
+In this case, the operation is done component-wise resulting in the same
+size vector.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>All other cases of implicit conversions are illegal.</p>
+</div>
+<div class="paragraph">
+<p>The result is a scalar signed integer of type <code>int</code> if the source operands
+are scalar and a vector signed integer type of the same size as the source
+operands if the source operands are vector types.
+Vector source operands of type <code>char<em>n</em></code> and <code>uchar<em>n</em></code> return a
+<code>char<em>n</em></code> result; vector source operands of type <code>short<em>n</em></code> and
+<code>ushort<em>n</em></code> return a <code>short<em>n</em></code> result; vector source operands of type
+<code>int<em>n</em></code>, <code>uint<em>n</em></code> and <code>float<em>n</em></code> return an <code>int<em>n</em></code> result; vector
+source operands of type <code>long<em>n</em></code>, <code>ulong<em>n</em></code> and <code>double<em>n</em></code> return a
+<code>long<em>n</em></code> result.
+For scalar types, the relational operators shall return 0 if the specified
+relation is <em>false</em> and 1 if the specified relation is <em>true</em>.
+For vector types, the relational operators shall return 0 if the specified
+relation is <em>false</em> and -1 (i.e. all bits set) if the specified relation is
+<em>true</em>.
+The relational operators always return 0 if either argument is not a number
+(NaN).</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="operators-equality">1.3.5. Equality Operators</h4>
+<div class="paragraph">
+<p>The equality operators<sup>17</sup> equal (<strong>==</strong>) and not equal (<strong>!=</strong>) operate on
+built-in scalar and vector types.
+All equality operators result in an integer type.
+After operand type conversion, the following cases are valid:</p>
+</div>
+<div class="paragraph">
+<p>[17] To test whether any or all elements in the result of a vector equality
+operator test true, for example to use in the context in an <strong>if ( )</strong>
+statement, please see the <a href="#relational-functions"><strong>any</strong> and <strong>all</strong> builtins</a>.</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>The two operands are scalars.
+In this case, the operation is applied, resulting in a scalar.</p>
+</li>
+<li>
+<p>One operand is a scalar, and the other is a vector.
+In this case, the scalar may be subject to the usual arithmetic
+conversion to the element type used by the vector operand.
+The scalar type is then widened to a vector that has the same number of
+components as the vector operand.
+The operation is done component-wise resulting in the same size vector.</p>
+</li>
+<li>
+<p>The two operands are vectors of the same type.
+In this case, the operation is done component-wise resulting in the same
+size vector.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>All other cases of implicit conversions are illegal.</p>
+</div>
+<div class="paragraph">
+<p>The result is a scalar signed integer of type <code>int</code> if the source operands
+are scalar and a vector signed integer type of the same size as the source
+operands if the source operands are vector types.
+Vector source operands of type <code>char<em>n</em></code> and <code>uchar<em>n</em></code> return a
+<code>char<em>n</em></code> result; vector source operands of type <code>short<em>n</em></code> and
+<code>ushort<em>n</em></code> return a <code>short<em>n</em></code> result; vector source operands of type
+<code>int<em>n</em></code>, <code>uint<em>n</em></code> and <code>float<em>n</em></code> return an <code>int<em>n</em></code> result; vector
+source operands of type <code>long<em>n</em></code>, <code>ulong<em>n</em></code> and <code>double<em>n</em></code> return a
+<code>long<em>n</em></code> result.</p>
+</div>
+<div class="paragraph">
+<p>For scalar types, the equality operators return 0 if the specified relation
+is <em>false</em> and return 1 if the specified relation is <em>true</em>.
+For vector types, the equality operators shall return 0 if the specified
+relation is <em>false</em> and -1 (i.e. all bits set) if the specified relation is
+<em>true</em>.
+The equality operator equal (<strong>==</strong>) returns 0 if one or both arguments are
+not a number (NaN).
+The equality operator not equal (<strong>!=</strong>) returns 1 (for scalar source
+operands) or -1 (for vector source operands) if one or both arguments are
+not a number (NaN).</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="operators-bitwise">1.3.6. Bitwise Operators</h4>
+<div class="paragraph">
+<p>The bitwise operators and (<strong>&amp;</strong>), or (<strong>|</strong>), exclusive or (<strong>^</strong>), and not
+(<strong>~</strong>) operate on all scalar and vector built-in types except the built-in
+scalar and vector <code>float</code> types.
+For vector built-in types, the operators are applied component-wise.
+If one operand is a scalar and the other is a vector, the scalar may be
+subject to the usual arithmetic conversion to the element type used by the
+vector operand.
+The scalar type is then widened to a vector that has the same number of
+components as the vector operand.
+The operation is done component-wise resulting in the same size vector.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="operators-logical">1.3.7. Logical Operators</h4>
+<div class="paragraph">
+<p>The logical operators and (<strong>&amp;&amp;</strong>) and or (<strong>||</strong>) operate on all scalar and
+vector built-in types.
+For scalar built-in types only, and (<strong>&amp;&amp;</strong>) will only evaluate the right hand
+operand if the left hand operand compares unequal to 0.
+For scalar built-in types only, or (<strong>||</strong>) will only evaluate the right hand
+operand if the left hand operand compares equal to 0.
+For built-in vector types, both operands are evaluated and the operators are
+applied component-wise.
+If one operand is a scalar and the other is a vector, the scalar may be
+subject to the usual arithmetic conversion to the element type used by the
+vector operand.
+The scalar type is then widened to a vector that has the same number of
+components as the vector operand.
+The operation is done component-wise resulting in the same size vector.</p>
+</div>
+<div class="paragraph">
+<p>The logical operator exclusive or (<strong>^^</strong>) is reserved.</p>
+</div>
+<div class="paragraph">
+<p>The result is a scalar signed integer of type <code>int</code> if the source operands
+are scalar and a vector signed integer type of the same size as the source
+operands if the source operands are vector types.
+Vector source operands of type <code>char<em>n</em></code> and <code>uchar<em>n</em></code> return a
+<code>char<em>n</em></code> result; vector source operands of type <code>short<em>n</em></code> and
+<code>ushort<em>n</em></code> return a <code>short<em>n</em></code> result; vector source operands of type
+<code>int<em>n</em></code>, <code>uint<em>n</em></code> and <code>float<em>n</em></code> return an <code>int<em>n</em></code> result; vector
+source operands of type <code>long<em>n</em></code>, <code>ulong<em>n</em></code> and <code>double<em>n</em></code> return a
+<code>long<em>n</em></code> result.</p>
+</div>
+<div class="paragraph">
+<p>For scalar types, the logical operators shall return 0 if the result of the
+operation is <em>false</em> and 1 if the result is <em>true</em>.
+For vector types, the logical operators shall return 0 if the result of the
+operation is <em>false</em> and -1 (i.e. all bits set) if the result is <em>true</em>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="operators-logical-unary">1.3.8. Unary Logical Operator</h4>
+<div class="paragraph">
+<p>The logical unary operator not (<strong>!</strong>) operates on all scalar and vector
+built-in types.
+For built-in vector types, the operators are applied component-wise.</p>
+</div>
+<div class="paragraph">
+<p>The result is a scalar signed integer of type <code>int</code> if the source operands
+are scalar and a vector signed integer type of the same size as the source
+operands if the source operands are vector types.
+Vector source operands of type <code>char<em>n</em></code> and <code>uchar<em>n</em></code> return a
+<code>char<em>n</em></code> result; vector source operands of type <code>short<em>n</em></code> and
+<code>ushort<em>n</em></code> return a <code>short<em>n</em></code> result; vector source operands of type
+<code>int<em>n</em></code>, <code>uint<em>n</em></code> and <code>float<em>n</em></code> return an <code>int<em>n</em></code> result; vector
+source operands of type <code>long<em>n</em></code>, <code>ulong<em>n</em></code> and <code>double<em>n</em></code> return a
+<code>long<em>n</em></code> result.</p>
+</div>
+<div class="paragraph">
+<p>For scalar types, the result of the logical unary operator is 0 if the value
+of its operand compares unequal to 0, and 1 if the value of its operand
+compares equal to 0.
+For vector types, the unary operator shall return a 0 if the value of its
+operand compares unequal to 0, and -1 (i.e. all bits set) if the value of
+its operand compares equal to 0.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="operators-ternary-selection">1.3.9. Ternary Selection Operator</h4>
+<div class="paragraph">
+<p>The ternary selection operator (<strong>?:</strong>) operates on three expressions (<em>exp1</em>
+<strong>?</strong> <em>exp2</em> <strong>:</strong> <em>exp3</em>).
+This operator evaluates the first expression <em>exp1</em>, which can be a scalar
+or vector result except <code>float</code>.
+If all three expressions are scalar values, the C99 rules for ternary
+operator are followed.
+If the result is a vector value, then this is equivalent to calling
+<strong>select</strong>(<em>exp3</em>, <em>exp2</em>, <em>exp1</em>).
+The <strong>select</strong> function is described in <a href="#table-builtin-relational">Scalar and Vector Relational Functions</a>.
+The second and third expressions can be any type, as long their types match,
+or there is an <a href="#implicit-conversions">implicit conversion</a> that can be
+applied to one of the expressions to make their types match, or one is a
+vector and the other is a scalar and the scalar may be subject to the usual
+arithmetic conversion to the element type used by the vector operand and
+widened to the same type as the vector type.
+This resulting matching type is the type of the entire expression.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="operators-shift">1.3.10. Shift Operators</h4>
+<div class="paragraph">
+<p>The operators right-shift (<strong>&gt;&gt;</strong>), left-shift (<strong>&lt;&lt;</strong>) operate on all scalar
+and vector built-in types except the built-in scalar and vector <code>float</code>
+types.
+For built-in vector types, the operators are applied component-wise.
+For the right-shift (<strong>&gt;&gt;</strong>), left-shift (<strong>&lt;&lt;</strong>) operators, the rightmost
+operand must be a scalar if the first operand is a scalar, and the rightmost
+operand can be a vector or scalar if the first operand is a vector.</p>
+</div>
+<div class="paragraph">
+<p>The result of <code>E1</code> <strong>&lt;&lt;</strong> <code>E2</code> is <code>E1</code> left-shifted by log<sub>2</sub>(N) least
+significant bits in <code>E2</code> viewed as an unsigned integer value, where N is the
+number of bits used to represent the data type of <code>E1</code> after integer
+promotion<sup>18</sup>, if <code>E1</code> is a scalar, or the number of bits used to represent
+the type of <code>E1</code> elements, if <code>E1</code> is a vector.
+The vacated bits are filled with zeros.</p>
+</div>
+<div class="paragraph">
+<p>[18] Integer promotion is described in <a href="#C99-spec">section 6.3.1.1 of the C99
+Specification</a>.</p>
+</div>
+<div class="paragraph">
+<p>The result of <code>E1</code> <strong>&gt;&gt;</strong> <code>E2</code> is <code>E1</code> right-shifted by log<sub>2</sub>(N) least
+significant bits in <code>E2</code> viewed as an unsigned integer value, where N is the
+number of bits used to represent the data type of <code>E1</code> after integer
+promotion, if <code>E1</code> is a scalar, or the number of bits used to represent the
+type of <code>E1</code> elements, if <code>E1</code> is a vector.
+If <code>E1</code> has an unsigned type or if <code>E1</code> has a signed type and a nonnegative
+value, the vacated bits are filled with zeros.
+If <code>E1</code> has a signed type and a negative value, the vacated bits are filled
+with ones.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="operators-sizeof">1.3.11. Sizeof Operator</h4>
+<div class="paragraph">
+<p>The <code>sizeof</code> operator yields the size (in bytes) of its operand, including
+any <a href="#alignment-of-types">padding bytes needed for alignment</a>, which may be
+an expression or the parenthesized name of a type.
+The size is determined from the type of the operand.
+The result is of type <code>size_t</code>.
+If the type of the operand is a variable length array<sup>19</sup> type, the operand
+is evaluated; otherwise, the operand is not evaluated and the result is an
+integer constant.</p>
+</div>
+<div class="paragraph">
+<p>[19] Variable length arrays are <a href="#restrictions-variable-length">not supported
+in OpenCL C</a>.</p>
+</div>
+<div class="paragraph">
+<p>When applied to an operand that has type <code>char</code> or <code>uchar</code>, the result is 1.
+When applied to an operand that has type <code>short</code>, <code>ushort</code>, or <code>half</code> the
+result is 2.
+When applied to an operand that has type <code>int</code>, <code>uint</code> or <code>float</code>, the
+result is 4.
+When applied to an operand that has type <code>long</code>, <code>ulong</code> or <code>double</code>, the
+result is 8.
+When applied to an operand that is a vector type, the result<sup>20</sup> is number of
+components * size of each scalar component.
+When applied to an operand that has array type, the result is the total
+number of bytes in the array.
+When applied to an operand that has structure or union type, the result is
+the total number of bytes in such an object, including internal and trailing
+padding.
+The <code>sizeof</code> operator shall not be applied to an expression that has
+function type or an incomplete type, to the parenthesized name of such a
+type, or to an expression that designates a bit-field struct member<sup>21</sup>.</p>
+</div>
+<div class="paragraph">
+<p>[20] Except for 3-component vectors whose size is defined as 4 * size of each
+scalar component.</p>
+</div>
+<div class="paragraph">
+<p>[21] Bit-field struct members are <a href="#restrictions-bitfield">not supported in
+OpenCL C</a>.</p>
+</div>
+<div class="paragraph">
+<p>The behavior of applying the <code>sizeof</code> operator to the <code>bool</code>, <code>image2d_t</code>,
+<code>image3d_t</code>, <code>image2d_array_t</code>, <code>image2d_depth_t</code>, <code>image2d_array_depth_t</code>,
+<code>image1d_t</code>, <code>image1d_buffer_t</code> or <code>image1d_array_t</code>, <code>sampler_t</code>,
+<code>clk_event_t</code>, <code>queue_t</code> and <code>event_t</code> types is implementation-defined.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="operators-comma">1.3.12. Comma Operator</h4>
+<div class="paragraph">
+<p>The comma (<strong>,</strong>) operator operates on expressions by returning the type and
+value of the right-most expression in a comma separated list of expressions.
+All expressions are evaluated, in order, from left to right.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="operators-indirection">1.3.13. Indirection Operator</h4>
+<div class="paragraph">
+<p>The unary (<strong>*</strong>) operator denotes indirection.
+If the operand points to an object, the result is an l-value designating the
+object.
+If the operand has type &#8220;pointer to <em>type</em>&#8221;, the result has type
+&#8220;<em>type</em>&#8221;.
+If an invalid value has been assigned to the pointer, the behavior of the
+unary <strong>*</strong> operator is undefined<sup>22</sup>.</p>
+</div>
+<div class="paragraph">
+<p>[22] Among the invalid values for dereferencing a pointer by the unary <strong>*</strong>
+operator are a null pointer, an address inappropriately aligned for the type
+of object pointed to, and the address of an object after the end of its
+lifetime.
+If <strong>P</strong> is an l-value and <strong>T</strong> is the name of an object pointer type, <strong>(T)P</strong>
+is an l-value that has a type compatible with that to which <strong>T</strong> points.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="operators-address">1.3.14. Address Operator</h4>
+<div class="paragraph">
+<p>The unary (<strong>&amp;</strong>) operator returns the address of its operand.
+If the operand has type &#8220;<em>type</em>&#8221;, the result has type &#8220;pointer to
+<em>type</em>&#8221;.
+If the operand is the result of a unary <strong>*</strong> operator, neither that operator
+nor the <strong>&amp;</strong> operator is evaluated and the result is as if both were omitted,
+except that the constraints on the operators still apply and the result is
+not an l-value.
+Similarly, if the operand is the result of a <strong>[]</strong> operator, neither the <strong>&amp;</strong>
+operator nor the unary <strong>*</strong> that is implied by the <strong>[]</strong> is evaluated and the
+result is as if the <strong>&amp;</strong> operator were removed and the <strong>[]</strong> operator were
+changed to a <strong>+</strong> operator.
+Otherwise, the result is a pointer to the object designated by its
+operand<sup>23</sup>.</p>
+</div>
+<div class="paragraph">
+<p>[23] Thus, <strong>&amp;*E</strong> is equivalent to <strong>E</strong> (even if <strong>E</strong> is a null pointer), and
+<strong>&amp;(E1[E2])</strong> to <strong>((E1)+ (E2))</strong>.
+It is always true that if <strong>E</strong> is an l-value that is a valid operand of the
+unary <strong>&amp;</strong> operator, <strong>&amp;E</strong> is an l-value equal to <strong>E</strong>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="operators-assignment">1.3.15. Assignment Operator</h4>
+<div class="paragraph">
+<p>Assignments of values to variable names are done with the assignment
+operator (<strong>=</strong>), like</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p><em>lvalue</em> = <em>expression</em></p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>The assignment operator stores the value of <em>expression</em> into <em>lvalue</em>.
+The <em>expression</em> and <em>lvalue</em> must have the same type, or the expression
+must have a type in <a href="#table-builtin-scalar-types">Built-in Scalar Data Types</a>, in which case an
+implicit conversion will be done on the expression before the assignment is
+done.</p>
+</div>
+<div class="paragraph">
+<p>If <em>expression</em> is a scalar type and <em>lvalue</em> is a vector type, the scalar
+is converted to the element type used by the vector operand.
+The scalar type is then widened to a vector that has the same number of
+components as the vector operand.
+The operation is done component-wise resulting in the same size vector.</p>
+</div>
+<div class="paragraph">
+<p>Any other desired type-conversions must be specified explicitly.
+L-values must be writable.
+Variables that are built-in types, entire structures or arrays, structure
+fields, l-values with the field selector (<strong>.</strong>) applied to select components
+or swizzles without repeated fields, l-values within parentheses, and
+l-values dereferenced with the array subscript operator (<strong>[]</strong>) are all
+l-values.
+Other binary or unary expressions, function names, swizzles with repeated
+fields, and constants cannot be l-values.
+The ternary operator (<strong>?:</strong>) is also not allowed as an l-value.</p>
+</div>
+<div class="paragraph">
+<p>The order of evaluation of the operands is unspecified.
+If an attempt is made to modify the result of an assignment operator or to
+access it after the next sequence point, the behavior is undefined.
+Other assignment operators are the assignments add into (<strong>+=</strong>), subtract
+from (<strong>-=</strong>), multiply into (<strong>=</strong>), divide into (<strong>/=</strong>), modulus into (<strong>%=</strong>),
+left shift by (<strong>&lt;&lt;=</strong>), right shift by (<strong>&gt;&gt;=</strong>), and into (<strong>&amp;=</strong>), inclusive
+or into (<strong>|=</strong>), and exclusive or into (<strong>^=</strong>).</p>
+</div>
+<div class="paragraph">
+<p>The expression</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p><em>lvalue</em> <em>op</em>*=* <em>expression</em></p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>is equivalent to</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p><em>lvalue</em> = <em>lvalue</em> <em>op</em> <em>expression</em></p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>and the <em>lvalue</em> and <em>expression</em> must satisfy the requirements for both
+operator <em>op</em> and assignment (<strong>=</strong>).</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>Except for the <code>sizeof</code> operator, the <code>half</code> data type cannot be used with
+any of the operators described in this section.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="vector-operations">1.4. Vector Operations</h3>
+<div class="paragraph">
+<p>Vector operations are component-wise.
+Usually, when an operator operates on a vector, it is operating
+independently on each component of the vector, in a component-wise fashion.</p>
+</div>
+<div class="paragraph">
+<p>For example,</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">float4 v, u;
+<span class="predefined-type">float</span> f;
+
+v = u + f;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>will be equivalent to</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">v.x = u.x + f;
+v.y = u.y + f;
+v.z = u.z + f;
+v.w = u.w + f;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>And</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">float4 v, u, w;
+
+w = v + u;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>will be equivalent to</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">w.x = v.x + u.x;
+w.y = v.y + u.y;
+w.z = v.z + u.z;
+w.w = v.w + u.w;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>and likewise for most operators and all integer and floating-point vector
+types.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="address-space-qualifiers">1.5. Address Space Qualifiers</h3>
+<div class="paragraph">
+<p>OpenCL implements the following disjoint named address spaces: <code>__global</code>,
+<code>__local</code>, <code>__constant</code> and <code>__private</code>.
+The address space qualifier may be used in variable declarations to specify
+the region of memory that is used to allocate the object.
+The C syntax for type qualifiers is extended in OpenCL to include an address
+space name as a valid type qualifier.
+If the type of an object is qualified by an address space name, the object
+is allocated in the specified address name; otherwise, the object is
+allocated in the generic address space.</p>
+</div>
+<div class="paragraph">
+<p>The address space names without the <code>__</code> prefix, i.e. <code>global</code>, <code>local</code>,
+<code>constant</code> and <code>private</code>, may be substituted for the corresponding address
+space names with the <code>__</code> prefix.</p>
+</div>
+<div class="paragraph">
+<p>The address space name for arguments to a function in a program, or local
+variables of a function is <code>__private</code>.
+All function arguments shall be in the <code>__private</code> address space.
+The address space for a variable at program scope, a <code>static</code> or <code>extern</code>
+variable inside a function can either be <code>__global</code> or <code>__constant</code>, but
+defaults to <code>__global</code> if not specified.</p>
+</div>
+<div class="paragraph">
+<p>Examples:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="comment">// declares a pointer p in the private address space that</span>
+<span class="comment">// points to an object in address space global</span>
+global <span class="predefined-type">int</span> *p;
+
+<span class="directive">void</span> foo (...)
+{
+    <span class="comment">// declares an array of 4 floats in the private address space</span>
+    <span class="predefined-type">float</span> x[<span class="integer">4</span>];
+    ...
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>OpenCL 2.0 adds support for an unnamed generic address space.
+Pointers that are declared without pointing to a named address space point
+to the generic address space.
+Before referring to the region pointed to, the pointer must be associated
+with a named address space.
+Functions written with pointer arguments and return values which do not
+declare an address space are defined to point to the generic address space.</p>
+</div>
+<div class="paragraph">
+<p>kernel function arguments declared to be a pointer or an array of a type
+must point to one of the named address spaces <code>__global</code>, <code>__local</code> or
+<code>__constant</code>.</p>
+</div>
+<div class="paragraph">
+<p>The named address spaces are a subset of the generic address space except
+for the <code>constant</code> address space.</p>
+</div>
+<div class="paragraph">
+<p>A pointer to address space A can only be assigned to a pointer to the same
+address space A or a pointer to the generic address space.
+Casting a pointer to address space A to a pointer to address space is
+illegal if A and B are named address spaces and A is not the same as B.</p>
+</div>
+<div class="paragraph">
+<p>Examples:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">private <span class="predefined-type">int</span> f() { ... }          <span class="comment">// should generate an error</span>
+
+local <span class="predefined-type">int</span> *f() { ... }           <span class="comment">// allowed</span>
+
+local <span class="predefined-type">int</span> * private f() { ... }; <span class="comment">// should generate an error.</span></code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The <code>__global</code>, <code>__constant</code>, <code>__local</code>, <code>__private</code>, <code>global</code>,
+<code>constant</code>, <code>local</code>, and <code>private</code> names are reserved for use as address
+space qualifiers and shall not be used otherwise.
+The <code>__generic</code> and <code>generic</code> names are reserved for future use.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>The size of pointers to different address spaces may differ.
+It is not correct to assume that, for example, <code>sizeof(__global int *)</code>
+always equals <code>sizeof(__local int *)</code>.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+<div class="sect3">
+<h4 id="global-or-global">1.5.1. <code>__global</code> (or <code>global</code>)</h4>
+<div class="paragraph">
+<p>The <code>__global</code> or <code>global</code> address space name is used to refer to memory
+objects (buffer or image objects) allocated from the <code>global</code> memory pool.</p>
+</div>
+<div class="paragraph">
+<p>A buffer memory object can be declared as a pointer to a scalar, vector or
+user-defined struct.
+This allows the kernel to read and/or write any location in the buffer.</p>
+</div>
+<div class="paragraph">
+<p>The actual size of the array memory object is determined when the memory
+object is allocated via appropriate API calls in the host code.</p>
+</div>
+<div class="paragraph">
+<p>Some examples are:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">global float4 *color; <span class="comment">// An array of float4 elements</span>
+
+<span class="keyword">typedef</span> <span class="keyword">struct</span> {
+    <span class="predefined-type">float</span> a[<span class="integer">3</span>];
+    <span class="predefined-type">int</span> b[<span class="integer">2</span>];
+} foo_t;
+
+global foo_t *my_info; <span class="comment">// An array of foo_t elements.</span></code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>As image objects are always allocated from the <code>global</code> address space, the
+<code>__global</code> or <code>global</code> qualifier should not be specified for image types.
+The elements of an image object cannot be directly accessed.
+Built-in functions to read from and write to an image object are provided.</p>
+</div>
+<div class="paragraph">
+<p>Variables defined at program scope and <code>static</code> variables inside a function
+can also be declared in the <code>global</code> address space.
+They can be defined with any valid OpenCL C data type except for those in
+<a href="#table-other-builtin-types">Other Built-in Data Types</a>.
+In particular, such program scope variables may be of any user-defined type,
+or a pointer to a user-defined type.
+In the presence of shared virtual memory, these pointers or pointer members
+should work as expected as long as they are shared virtual memory pointers
+and the referenced storage has been mapped appropriately.
+These variables in the <code>global</code> address space have the same lifetime as the
+program, and their values persist between calls to any of the kernels in the
+program.
+These variables are not shared across devices.
+They have distinct storage.</p>
+</div>
+<div class="paragraph">
+<p>Program scope and <code>static</code> variables in the <code>global</code> address space may be
+initialized, but only with constant expressions.</p>
+</div>
+<div class="paragraph">
+<p>Examples:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">global <span class="predefined-type">int</span> foo;         <span class="comment">// OK.</span>
+<span class="predefined-type">int</span> foo;                <span class="comment">// OK. Declared in the global address space</span>
+global uchar buf[<span class="integer">512</span>];  <span class="comment">// OK.</span>
+global <span class="predefined-type">int</span> baz = <span class="integer">12</span>;    <span class="comment">// OK. Initialization is allowed</span>
+<span class="directive">static</span> global <span class="predefined-type">int</span> bat;  <span class="comment">// OK. Internal linkage</span>
+
+<span class="directive">static</span> <span class="predefined-type">int</span> foo;         <span class="comment">// OK. Declared in the global address space</span>
+<span class="directive">static</span> global <span class="predefined-type">int</span> foo;  <span class="comment">// OK.</span>
+
+<span class="predefined-type">int</span> *foo;               <span class="comment">// OK. foo is allocated in global address space.</span>
+                        <span class="comment">// pointer to foo in generic address space</span>
+
+<span class="directive">void</span> func(...)
+{
+    <span class="predefined-type">int</span> *foo;           <span class="comment">// OK. foo is allocated in private address space.</span>
+                        <span class="comment">// foo points to a location in generic address space.</span>
+    ...
+}
+
+global <span class="predefined-type">int</span> * global ptr;          <span class="comment">// OK.</span>
+<span class="predefined-type">int</span> * global ptr;                 <span class="comment">// OK.</span>
+constant <span class="predefined-type">int</span> *global ptr=&amp;baz;    <span class="comment">// error since baz is in global address</span>
+                                  <span class="comment">// space.</span>
+global <span class="predefined-type">int</span> * constant ptr = &amp;baz; <span class="comment">// OK</span>
+
+<span class="comment">// Pointers work. Also, initialization to a constant known at</span>
+<span class="comment">// program load time</span>
+global <span class="predefined-type">int</span> *global baz_ptr = &amp;baz;
+
+global image2d_t im; <span class="comment">// Error. Invalid type for program scope</span>
+                     <span class="comment">// variables</span>
+
+global event_t ev;   <span class="comment">// Error. Invalid type for program scope variables</span>
+
+global <span class="predefined-type">int</span> *bad_ptr; <span class="comment">// Error. No implicit address space</span></code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The <code>const</code> qualifier can also be used with the <code>__global</code> qualifier to
+specify a read-only buffer memory object.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="local-or-local">1.5.2. <code>__local</code> (or <code>local</code>)</h4>
+<div class="paragraph">
+<p>The <code>__local</code> or <code>local</code> address space name is used to describe variables
+that need to be allocated in local memory and are shared by all work-items
+of a work-group.
+Pointers to the <code>__local</code> address space are allowed as arguments to
+functions (including kernel functions).
+Variables declared in the <code>__local</code> address space inside a kernel function
+must occur at kernel function scope.</p>
+</div>
+<div class="paragraph">
+<p>Some examples of variables allocated in the <code>__local</code> address space inside
+a kernel function are:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">kernel <span class="directive">void</span> my_func(...)
+{
+    local <span class="predefined-type">float</span> a;     <span class="comment">// A single float allocated</span>
+                       <span class="comment">// in local address space</span>
+
+    local <span class="predefined-type">float</span> b[<span class="integer">10</span>]; <span class="comment">// An array of 10 floats</span>
+                       <span class="comment">// allocated in local address space.</span>
+
+    <span class="keyword">if</span> (...)
+    {
+        <span class="comment">// example of variable in __local address space but not</span>
+        <span class="comment">// declared at __kernel function scope.</span>
+        local <span class="predefined-type">float</span> c; <span class="comment">// not allowed.</span>
+    }
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Variables allocated in the <code>__local</code> address space inside a kernel
+function cannot be initialized.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">kernel <span class="directive">void</span> my_func(...)
+{
+    local <span class="predefined-type">float</span> a = <span class="integer">1</span>; <span class="comment">// not allowed</span>
+
+    local <span class="predefined-type">float</span> b;
+    b = <span class="integer">1</span>;             <span class="comment">// allowed</span>
+}</code></pre>
+</div>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>Variables allocated in the <code>__local</code> address space inside a kernel
+function are allocated for each work-group executing the kernel and exist
+only for the lifetime of the work-group executing the kernel.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+</div>
+<div class="sect3">
+<h4 id="constant-or-constant">1.5.3. <code>__constant</code> (or <code>constant</code>)</h4>
+<div class="paragraph">
+<p>The <code>__constant</code> or <code>constant</code> address space name is used to describe
+variables allocated in <code>global</code> memory and which are accessed inside a
+kernel(s) as read-only variables.
+These read-only variables can be accessed by all (global) work-items of the
+kernel during its execution.
+Pointers to the <code>__constant</code> address space are allowed as arguments to
+functions (including kernel functions) and for variables declared inside
+functions.</p>
+</div>
+<div class="paragraph">
+<p>All string literal storage shall be in the <code>__constant</code> address space.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>Each argument to a kernel that is a pointer to the <code>__constant</code> address
+space is counted separately towards the maximum number of such arguments,
+defined as the value of the <a href="#opencl-device-queries"><code>CL_DEVICE_MAX_CONSTANT_ARGS</code> device query</a>.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p>Variables in the program scope can be declared in the <code>__constant</code> address
+space.
+Variables in the outermost scope of kernel functions can be declared in the
+<code>__constant</code> address space.
+These variables are required to be initialized and the values used to
+initialize these variables must be a compile time constant.
+Writing to such a variable results in a compile-time error.</p>
+</div>
+<div class="paragraph">
+<p>Implementations are not required to aggregate these declarations into the
+fewest number of constant arguments.
+This behavior is implementation defined.</p>
+</div>
+<div class="paragraph">
+<p>Thus portable code must conservatively assume that each variable declared
+inside a function or in program scope allocated in the <code>__constant</code>
+address space counts as a separate constant argument.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="private-or-private">1.5.4. <code>__private</code> (or <code>private</code>)</h4>
+<div class="paragraph">
+<p>Variables inside a kernel function not declared with an address space
+qualifier, all variables inside non-kernel functions, and all function
+arguments are in the <code>__private</code> or <code>private</code> address space.
+<strong class="line-through">Variables declared as pointers are considered to point to the
+<code>__private</code> address space if an address space qualifier is not specified</strong>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="the-generic-address-space">1.5.5. The generic address space</h4>
+<div class="paragraph">
+<p>The following rules apply when using pointers that point to the generic
+address space:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>A pointer that points to the <code>global</code>, <code>local</code> or <code>private</code> address
+space can be implicitly converted to a pointer to the unnamed generic
+address space but not vice-versa.</p>
+</li>
+<li>
+<p>Pointer casts can be used to cast a pointer that points to the <code>global</code>,
+<code>local</code> or <code>private</code> space to the unnamed generic address space and
+vice-versa.</p>
+</li>
+<li>
+<p>A pointer that points to the <code>constant</code> address space cannot be cast or
+implicitly converted to the generic address space.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>A few examples follow.</p>
+</div>
+<div class="paragraph">
+<p>This is the canonical example.
+In this example, function <code>foo</code> is declared with an argument that is a
+pointer with no address space qualifier.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="directive">void</span> foo(<span class="predefined-type">int</span> *a)
+{
+    *a = *a + <span class="integer">2</span>;
+}
+
+kernel <span class="directive">void</span> k1(local <span class="predefined-type">int</span> *a)
+{
+    ...
+    foo(a);
+    ...
+}
+
+kernel <span class="directive">void</span> k2(global <span class="predefined-type">int</span> *a)
+{
+    ...
+    foo(a);
+    ...
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>In the example below, <code>var</code> is in the unnamed generic address space which
+gets mapped to the <code>global</code> or <code>local</code> address space depending on the result
+of the conditional expression.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">kernel <span class="directive">void</span> bar(global <span class="predefined-type">int</span> *g, local <span class="predefined-type">int</span> *l)
+{
+    <span class="predefined-type">int</span> *var;
+
+    <span class="keyword">if</span> (is_even(get_global_id(<span class="integer">0</span>))
+        var = g;
+    <span class="keyword">else</span>
+        var = l;
+    *var = <span class="integer">42</span>;
+    ...
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The example below is an example with one unnamed generic address space
+pointer with multiple named address space assignments.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="predefined-type">int</span> *ptr;
+global <span class="predefined-type">int</span> g;
+ptr = &amp;g; <span class="comment">// legal</span>
+
+local <span class="predefined-type">int</span> l;
+ptr = &amp;l; <span class="comment">// legal</span>
+
+private <span class="predefined-type">int</span> p;
+ptr = &amp;p; <span class="comment">// legal</span>
+
+constant <span class="predefined-type">int</span> c;
+ptr = &amp;c; <span class="comment">// illegal</span></code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The example below is an example with one unnamed generic address space
+pointer being assigned to point to several named address spaces.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">global <span class="predefined-type">int</span> *gp;
+local <span class="predefined-type">int</span> *lp;
+private <span class="predefined-type">int</span> *pp;
+
+<span class="predefined-type">int</span> *p;
+p = gp; <span class="comment">// legal</span>
+p = lp; <span class="comment">// legal</span>
+p = pp; <span class="comment">// legal</span>
+
+<span class="comment">// it is illegal to convert from a generic pointer</span>
+<span class="comment">// to an explicit address space pointer without a cast:</span>
+gp = p; <span class="comment">// compile-time error</span>
+lp = p; <span class="comment">// compile-time error</span>
+pp = p; <span class="comment">// compile-time error</span></code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="changes-to-C99">1.5.6. Changes to C99</h4>
+<div class="paragraph">
+<p>This section details the modifications to the <a href="#C99-spec">C99
+Specification</a> needed to incorporate the functionality of named address
+space and the generic address space:</p>
+</div>
+<div class="paragraph">
+<p><strong>Clause 6.2.5 - Types, replace paragraph 26 with the following paragraphs</strong>:</p>
+</div>
+<div class="paragraph">
+<p>If type <code>T</code> is qualified by the address space qualifier for address space
+<code>A</code>, then " <code>T</code> is in <code>A</code> ".
+If type <code>T</code> is in address space <code>A</code>, a pointer to <code>T</code> is also a " pointer
+into <code>A</code> " and the referenced address space of the pointer is <code>A</code>.</p>
+</div>
+<div class="paragraph">
+<p>A pointer to <code>void</code> in any address space shall have the same representation
+and alignment requirements as a pointer to a character type in the same
+address space.
+Similarly, pointers to differently access-qualified versions of compatible
+types shall have the same representation and alignment requirements.
+All pointers to structure types in the same address space shall have the
+same representation and alignment requirements as each other.
+All pointers to union types in the same address space shall have the same
+representation and alignment requirements as each other.</p>
+</div>
+<div class="paragraph">
+<p><strong>Clause 6.3.2.3 - Pointers, replace the first two paragraphs with the
+following paragraphs</strong>:</p>
+</div>
+<div class="paragraph">
+<p>If a pointer into one address space is converted to a pointer into another
+address space, then unless the original pointer is a null pointer or the
+location referred to by the original pointer is within the second address
+space, the behavior is undefined.
+(For the original pointer to refer to a location within the second address
+space, the two address spaces must overlap).</p>
+</div>
+<div class="paragraph">
+<p>A pointer to <code>void</code> in any address space may be converted to or from a
+pointer to any incomplete or object type.
+A pointer to any incomplete or object type in some address space may be
+converted to a pointer to <code>void</code> in an enclosing address space and back
+again; the result shall compare equal to the original pointer.</p>
+</div>
+<div class="paragraph">
+<p>For any qualifier <em>q</em>, a pointer to a non-<em>q</em>-qualified type may be
+converted to a pointer to the <em>q</em>-qualified version of the type (but with
+the same address-space qualifier or the generic address space); the values
+stored in the original and converted pointers shall compare equal.</p>
+</div>
+<div class="paragraph">
+<p><strong>Clause 6.3.2.3 - Pointers, replace the last sentence of paragraph 4 with</strong>:</p>
+</div>
+<div class="paragraph">
+<p>Conversion of a null pointer to another pointer type yields a null pointer
+of that type.
+Any two null pointers whose referenced address spaces overlap shall compare
+equal.</p>
+</div>
+<div class="paragraph">
+<p><strong>Clause 6.5.2.2 - Function calls, change the second bullet of paragraph 6
+to</strong>:</p>
+</div>
+<div class="paragraph">
+<p>both types are pointers to qualified or unqualified versions of a character
+type or <code>void</code> in the same address space or one type is a pointer in a named
+address space and the other is a pointer in the generic address space.</p>
+</div>
+<div class="paragraph">
+<p><strong>Clause 6.5.6 - Additive operators, add another constraint paragraph</strong>:</p>
+</div>
+<div class="paragraph">
+<p>For subtraction, if the two operands are pointers into different address
+spaces, the address spaces must overlap.</p>
+</div>
+<div class="paragraph">
+<p><strong>Clause 6.5.8 - Relational operators, add another constraint paragraph</strong>:</p>
+</div>
+<div class="paragraph">
+<p>If the two operands are pointers into different address spaces, the address
+spaces must overlap.</p>
+</div>
+<div class="paragraph">
+<p><strong>Clause 6.5.8 - Relational operators, add a new paragraph between existing
+paragraphs 3 and 4</strong>:</p>
+</div>
+<div class="paragraph">
+<p>If the two operands are pointers into different address spaces, one of the
+address spaces encloses the other.
+The pointer into the enclosed address space is first converted to a pointer
+to the same reference type except with any address-space qualifier removed
+and any address-space qualifier of the other pointer&#8217;s reference type added.
+(After this conversion, both pointers are pointers into the same address
+space).</p>
+</div>
+<div class="paragraph">
+<p>Examples:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">kernel <span class="directive">void</span> test1()
+{
+    global <span class="predefined-type">int</span> arr[<span class="integer">5</span>] = { <span class="integer">0</span>, <span class="integer">1</span>, <span class="integer">2</span>, <span class="integer">3</span>, <span class="integer">4</span> };
+    <span class="predefined-type">int</span> *p = &amp;arr[<span class="integer">1</span>];
+    global <span class="predefined-type">int</span> *q = &amp;arr[<span class="integer">3</span>];
+
+    <span class="comment">// q implicitly converted to the generic address space</span>
+    <span class="comment">// since the generic address space encloses the global</span>
+    <span class="comment">// address space</span>
+    <span class="keyword">if</span> (q &gt;= p)
+        printf(<span class="string"><span class="delimiter">&quot;</span><span class="content">true</span><span class="char">\n</span><span class="delimiter">&quot;</span></span>);
+
+    <span class="comment">// q implicitly converted to the generic address space</span>
+    <span class="comment">// since the generic address space encloses the global</span>
+    <span class="comment">// address space</span>
+    <span class="keyword">if</span> (p &lt;= q)
+        printf(<span class="string"><span class="delimiter">&quot;</span><span class="content">true</span><span class="char">\n</span><span class="delimiter">&quot;</span></span>);
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><strong>Clause 6.5.9 - Equality operators, add another constraint paragraph</strong>:</p>
+</div>
+<div class="paragraph">
+<p>If the two operands are pointers into different address spaces, the address
+spaces must overlap.</p>
+</div>
+<div class="paragraph">
+<p><strong>Clause 6.5.9 - Equality operators, replace paragraph 5 with</strong>:</p>
+</div>
+<div class="paragraph">
+<p>Otherwise, at least one operand is a pointer.
+If one operand is a pointer and the other is a null pointer constant, the
+null pointer constant is converted to the type of the pointer.
+If both operands are pointers, each of the following conversions is
+performed as applicable:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>If the two operands are pointers into different address spaces, one of
+the address spaces encloses the other.
+The pointer into the enclosed address space is first converted to a
+pointer to the same reference type except with any address-space
+qualifier removed and any address-space qualifier of the other pointer&#8217;s
+reference type added.
+(After this conversion, both pointers are pointers into the same address
+space).</p>
+</li>
+<li>
+<p>Then, if one operand is a pointer to an object or incomplete type and
+the other is a pointer to a qualified or unqualified version of <code>void</code>,
+the former is converted to the type of the latter.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Examples:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="predefined-type">int</span> *ptr = <span class="predefined-constant">NULL</span>;
+local <span class="predefined-type">int</span> lval = SOME_VAL;
+local <span class="predefined-type">int</span> *lptr = &amp;lval;
+global <span class="predefined-type">int</span> gval = SOME_OTHER_VAL;
+global <span class="predefined-type">int</span> *gptr = &amp;gval;
+
+ptr = lptr;
+
+<span class="keyword">if</span> (ptr == gptr) <span class="comment">// legal</span>
+{
+    ...
+}
+
+<span class="keyword">if</span> (ptr == lptr) <span class="comment">// legal</span>
+{
+    ...
+}
+
+<span class="keyword">if</span> (lptr == gptr) <span class="comment">// illegal, compiler error</span>
+{
+    ...
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Consider the following example:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="predefined-type">bool</span> callee(<span class="predefined-type">int</span> *p1, <span class="predefined-type">int</span> *p2)
+{
+    <span class="keyword">if</span> (p1 == p2)
+        <span class="keyword">return</span> <span class="predefined-constant">true</span>;
+    <span class="keyword">return</span> <span class="predefined-constant">false</span>;
+}
+
+<span class="directive">void</span> caller()
+{
+    global <span class="predefined-type">int</span> *gptr = <span class="hex">0xdeadbeef</span>;
+    private <span class="predefined-type">int</span> *pptr = <span class="hex">0xdeadbeef</span>;
+
+    <span class="comment">// behavior of callee is undefined</span>
+    <span class="predefined-type">bool</span> b = callee(gptr, pptr);
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The behavior of callee is undefined as gptr and pptr are in different
+address spaces.
+The example above would have the same undefined behavior if the equality
+operator is replaced with a relational operator.</p>
+</div>
+<div class="paragraph">
+<p>Examples:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="predefined-type">int</span> *ptr = <span class="predefined-constant">NULL</span>;
+local <span class="predefined-type">int</span> *lptr = <span class="predefined-constant">NULL</span>;
+global <span class="predefined-type">int</span> *gptr = <span class="predefined-constant">NULL</span>;
+
+<span class="keyword">if</span> (ptr == <span class="predefined-constant">NULL</span>) <span class="comment">// legal</span>
+{
+    ...
+}
+
+<span class="keyword">if</span> (ptr == lptr) <span class="comment">// legal</span>
+{
+    ...
+}
+
+<span class="keyword">if</span> (lptr == gptr) <span class="comment">// compile-time error</span>
+{
+    ...
+}
+
+ptr = lptr; <span class="comment">// legal</span>
+
+intptr l = (intptr_t)lptr;
+<span class="keyword">if</span> (l == <span class="integer">0</span>) <span class="comment">// legal</span>
+{
+    ...
+}
+
+<span class="keyword">if</span> (l == <span class="predefined-constant">NULL</span>) <span class="comment">// legal</span>
+{
+    ...
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><strong>Clause 6.5.9 - Equality operators, replace first sentence of paragraph 6
+with</strong>:</p>
+</div>
+<div class="paragraph">
+<p>Two pointers compare equal if and only if both are null pointers with
+overlapping address spaces.</p>
+</div>
+<div class="paragraph">
+<p><strong>Clause 6.5.15 - Conditional operator, add another constraint paragraph</strong>:</p>
+</div>
+<div class="paragraph">
+<p>If the second and third operands are pointers into different address spaces,
+the address spaces must overlap.</p>
+</div>
+<div class="paragraph">
+<p>Examples:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">kernel <span class="directive">void</span> test1()
+{
+    global <span class="predefined-type">int</span> arr[<span class="integer">5</span>] = { <span class="integer">0</span>, <span class="integer">1</span>, <span class="integer">2</span>, <span class="integer">3</span>, <span class="integer">4</span> };
+    <span class="predefined-type">int</span> *p = &amp;arr[<span class="integer">1</span>];
+    global <span class="predefined-type">int</span> *q = &amp;arr[<span class="integer">3</span>];
+    local <span class="predefined-type">int</span> *r = <span class="predefined-constant">NULL</span>;
+    <span class="predefined-type">int</span> *val = <span class="predefined-constant">NULL</span>;
+
+    <span class="comment">// legal. 2nd and 3rd operands are in address spaces</span>
+    <span class="comment">// that overlap</span>
+    val = (q &gt;= p) ? q : p;
+
+    <span class="comment">// compiler error. 2nd and 3rd operands are in disjoint</span>
+    <span class="comment">// address spaces</span>
+    val = (q &gt;= p) ? q : r;
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><strong>Clause 6.5.16.1 - Simple assignment, change the third and fourth bullets of
+paragraph 1 to</strong>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>both operands are pointers to qualified or unqualified versions of
+compatible types, the referenced address space of the left encloses the
+referenced address space of the right, and the type pointed to by the
+left has all the qualifiers of the type pointed to by the right.</p>
+</li>
+<li>
+<p>one operand is a pointer to an object or incomplete type and the other
+is a pointer to a qualified or unqualified version of <code>void</code>, the
+referenced address space of the left encloses the referenced address
+space of the right, and the type pointed to by the left has all the
+qualifiers of the type pointed to by the right.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Examples:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">kernel <span class="directive">void</span> f()
+{
+<span class="predefined-type">int</span> *ptr;
+local <span class="predefined-type">int</span> *lptr;
+global <span class="predefined-type">int</span> *gptr;
+local <span class="predefined-type">int</span> val = <span class="integer">55</span>;
+
+ptr = &amp;val;  <span class="comment">// legal: implicit cast to generic, then assign</span>
+lptr = ptr;  <span class="comment">// illegal: no implicit cast from</span>
+             <span class="comment">// generic to local</span>
+lptr = gptr; <span class="comment">// illegal: no implicit cast from</span>
+             <span class="comment">// global to local</span>
+ptr = gptr;  <span class="comment">// legal: implicit cast from global to generic,</span>
+             <span class="comment">// then assign</span>
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><strong>Clause 6.7.2.1 - Structure and union specifiers, add a new constraint
+paragraph</strong>:</p>
+</div>
+<div class="paragraph">
+<p>Within a structure or union specifier, the type of a member shall not be
+qualified by an address space qualifier.</p>
+</div>
+<div class="paragraph">
+<p><strong>Clause 6.7.3 - Type qualifiers, add three new constraint paragraphs</strong>:</p>
+</div>
+<div class="paragraph">
+<p>No type shall be qualified by qualifiers for two or more different address
+spaces.</p>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="access-qualifiers">1.6. Access Qualifiers</h3>
+<div class="paragraph">
+<p>Image objects specified as arguments to a kernel can be declared to be
+read-only, write-only or read-write.
+<span class="line-through">A kernel cannot read from and write to the same image
+object</span>.
+The <code>__read_only</code> (or read_only) and <code>__write_only</code> (or <code>write_only</code>)
+qualifiers must be used with image object arguments to declare if the image
+object is being read or written by a kernel or function.
+The <code>__read_write</code> (or <code>read_write</code>) qualifier must be used with image
+object arguments of kernels and of user-defined functions to declare if the
+image object is being both read and written by the kernel.
+If no qualifier is provided, <code>read_only</code> is assumed.</p>
+</div>
+<div class="paragraph">
+<p>In the following example</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">kernel <span class="directive">void</span>
+foo (read_only image2d_t imageA,
+     write_only image2d_t imageB)
+{
+    ...
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>imageA is a read-only 2D image object, and image is a write-only 2D image
+object.</p>
+</div>
+<div class="paragraph">
+<p>The sampler-less read image and write image built-ins can be used with image
+declared with the <code>__read_write</code> (or <code>read_write</code>) qualifier.
+Calls to built-ins that read from an image using a sampler for images
+declared with the <code>__read_write</code> (or <code>read_write</code>) qualifier will be a
+compilation error.</p>
+</div>
+<div class="paragraph">
+<p>Pipe objects specified as arguments to a kernel also use these access
+qualifiers.
+See the <a href="#pipe-functions">detailed description on how these access qualifiers
+can be used with pipes</a>.</p>
+</div>
+<div class="paragraph">
+<p>The <code>__read_only</code>, <code>__write_only</code>, <code>__read_write</code>, <code>read_only</code>,
+<code>write_only</code> and <code>read_write</code> names are reserved for use as access
+qualifiers and shall not be used otherwise.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="function-qualifiers">1.7. Function Qualifiers</h3>
+<div class="sect3">
+<h4 id="kernel-or-kernel">1.7.1. <code>__kernel</code> (or <code>kernel</code>)</h4>
+<div class="paragraph">
+<p>The <code>__kernel</code> (or <code>kernel</code>) qualifier declares a function to be a kernel
+that can be executed by an application on an OpenCL device(s).
+The following rules apply to functions that are declared with this
+qualifier:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>It can be executed on the device only</p>
+</li>
+<li>
+<p>It can be called by the host</p>
+</li>
+<li>
+<p>It is just a regular function call if a <code>__kernel</code> function is called
+by another kernel function.</p>
+</li>
+</ul>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>Kernel functions with variables declared inside the function with the
+<code>__local</code> or <code>local</code> qualifier can be called by the host using appropriate
+APIs such as <strong>clEnqueueNDRangeKernel</strong>.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p>The <code>__kernel</code> and <code>kernel</code> names are reserved for use as functions
+qualifiers and shall not be used otherwise.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="optional-attribute-qualifiers">1.7.2. Optional Attribute Qualifiers</h4>
+<div class="paragraph">
+<p>The <code>__kernel</code> qualifier can be used with the keyword <em>attribute</em> to
+declare additional information about the kernel function as described below.</p>
+</div>
+<div class="paragraph">
+<p>The optional <code>__attribute__((vec_type_hint(&lt;type&gt;)))</code><sup>24</sup> is a hint to the
+compiler and is intended to be a representation of the computational <em>width</em>
+of the <code>__kernel</code>, and should serve as the basis for calculating processor
+bandwidth utilization when the compiler is looking to autovectorize the
+code.
+In the <code>__attribute__((vec_type_hint(&lt;type&gt;)))</code> qualifier &lt;type&gt; is one of
+the built-in vector types listed in <a href="#table-builtin-vector-types">Built-in Vector Data Types</a> or the
+constituent scalar element types.
+If <code>vec_type_hint (&lt;type&gt;)</code> is not specified, the kernel is assumed to have
+the <code>__attribute__((vec_type_hint(int)))</code> qualifier.</p>
+</div>
+<div class="paragraph">
+<p>[24] Implicit in autovectorization is the assumption that any libraries
+called from the <code>__kernel</code> must be recompilable at run time to handle
+cases where the compiler decides to merge or separate workitems.
+This probably means that such libraries can never be hard coded binaries or
+that hard coded binaries must be accompanied either by source or some
+retargetable intermediate representation.
+This may be a code security question for some.</p>
+</div>
+<div class="paragraph">
+<p>For example, where the developer specified a width of <code>float4</code>, the compiler
+should assume that the computation usually uses up to 4 lanes of a <code>float</code>
+vector, and would decide to merge work-items or possibly even separate one
+work-item into many threads to better match the hardware capabilities.
+A conforming implementation is not required to autovectorize code, but shall
+support the hint.
+A compiler may autovectorize, even if no hint is provided.
+If an implementation merges N work-items into one thread, it is responsible
+for correctly handling cases where the number of <code>global</code> or <code>local</code>
+work-items in any dimension modulo N is not zero.</p>
+</div>
+<div class="paragraph">
+<p>Examples:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="comment">// autovectorize assuming float4 as the</span>
+<span class="comment">// basic computation width</span>
+__kernel __attribute__((vec_type_hint(float4)))
+<span class="directive">void</span> foo( __global float4 *p ) { ... }
+
+<span class="comment">// autovectorize assuming double as the</span>
+<span class="comment">// basic computation width</span>
+__kernel __attribute__((vec_type_hint(<span class="predefined-type">double</span>)))
+<span class="directive">void</span> foo( __global float4 *p ) { ... }
+
+<span class="comment">// autovectorize assuming int (default)</span>
+<span class="comment">// as the basic computation width</span>
+__kernel
+<span class="directive">void</span> foo( __global float4 *p ) { ... }</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>If for example, a <code>__kernel</code> function is declared with</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p><code>__attribute__(( vec_type_hint (float4)))</code></p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>(meaning that most operations in the <code>__kernel</code> function are explicitly
+vectorized using <code>float4</code>) and the kernel is running using Intel<sup>®</sup>
+Advanced Vector Instructions (Intel<sup>®</sup> AVX) which implements a
+8-float-wide vector unit, the autovectorizer might choose to merge two
+work-items to one thread, running a second work-item in the high half of the
+256-bit AVX register.</p>
+</div>
+<div class="paragraph">
+<p>As another example, a Power4 machine has two scalar double precision
+floating-point units with an 6-cycle deep pipe.
+An autovectorizer for the Power4 machine might choose to interleave six
+kernels declared with the <code>__attribute__(( vec_type_hint (double2)))</code>
+qualifier into one hardware thread, to ensure that there is always 12-way
+parallelism available to saturate the FPUs.
+It might also choose to merge 4 or 8 work-items (or some other number) if it
+concludes that these are better choices, due to resource utilization
+concerns or some preference for divisibility by 2.</p>
+</div>
+<div class="paragraph">
+<p>The optional <code>__attribute__((work_group_size_hint(X, Y, Z)))</code> is a hint to
+the compiler and is intended to specify the work-group size that may be used
+i.e. value most likely to be specified by the <em>local_work_size</em> argument to
+<strong>clEnqueueNDRangeKernel</strong>.
+For example, the <code>__attribute__((work_group_size_hint(1, 1, 1)))</code> is a
+hint to the compiler that the kernel will most likely be executed with a
+work-group size of 1.</p>
+</div>
+<div class="paragraph">
+<p>The optional <code>__attribute__((reqd_work_group_size(X, Y, Z)))</code> is the
+work-group size that must be used as the <em>local_work_size</em> argument to
+<strong>clEnqueueNDRangeKernel</strong>.
+This allows the compiler to optimize the generated code appropriately for
+this kernel.</p>
+</div>
+<div class="paragraph">
+<p>If <code>Z</code> is one, the <em>work_dim</em> argument to <strong>clEnqueueNDRangeKernel</strong> can be 2
+or 3.
+If <code>Y</code> and <code>Z</code> are one, the <em>work_dim</em> argument to <strong>clEnqueueNDRangeKernel</strong>
+can be 1, 2 or 3.</p>
+</div>
+<div class="paragraph">
+<p>The optional <code>__attribute__((nosvm))</code> qualifier can be used with a pointer
+variable to inform the compiler that the pointer does not refer to a shared
+virtual memory region.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p><code>__attribute__((nosvm))</code> is deprecated, and the compiler can ignore it.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="storage-class-specifiers">1.8. Storage-Class Specifiers</h3>
+<div class="paragraph">
+<p>The <code>typedef</code>, <code>extern</code> and <code>static</code> storage-class specifiers are supported.
+The <code>auto</code> and <code>register</code> storage-class specifiers are not supported.</p>
+</div>
+<div class="paragraph">
+<p>The <code>extern</code> storage-class specifier can only be used for functions (kernel
+and non-kernel functions) and <code>global</code> variables declared in program scope
+or variables declared inside a function (kernel and non-kernel functions).
+The <code>static</code> storage-class specifier can only be used for non-kernel
+functions, <code>global</code> variables declared in program scope and variables inside
+a function declared in the <code>global</code> or <code>constant</code> address space.</p>
+</div>
+<div class="paragraph">
+<p>Examples:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="directive">extern</span> constant float4 noise_table[<span class="integer">256</span>];
+<span class="directive">static</span> constant float4 color_table[<span class="integer">256</span>];
+
+<span class="directive">extern</span> kernel <span class="directive">void</span> my_foo(image2d_t img);
+<span class="directive">extern</span> <span class="directive">void</span> my_bar(global <span class="predefined-type">float</span> *a);
+
+kernel <span class="directive">void</span> my_func(image2d_t img, global <span class="predefined-type">float</span> *a)
+{
+    <span class="directive">extern</span> constant float4 a;
+    <span class="directive">static</span> constant float4 b = (float4)(<span class="float">1</span><span class="float">.0f</span>); <span class="comment">// OK.</span>
+    <span class="directive">static</span> <span class="predefined-type">float</span> c;  <span class="comment">// Error: No implicit address space</span>
+    global <span class="predefined-type">int</span> hurl; <span class="comment">// Error: Must be static</span>
+    ...
+    my_foo(img);
+    ...
+    my_bar(a);
+    ...
+    <span class="keyword">while</span> (<span class="integer">1</span>)
+    {
+        <span class="directive">static</span> global <span class="predefined-type">int</span> inside; <span class="comment">// OK.</span>
+        ...
+    }
+    ...
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="restrictions">1.9. Restrictions</h3>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>Items struckthrough are restrictions in a previous version of OpenCL C that
+are no longer present in OpenCL C 2.0.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+<div class="olist loweralpha">
+<ol class="loweralpha" type="a">
+<li>
+<p>The use of pointers is somewhat restricted.
+The following rules apply:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>Arguments to kernel functions declared in a program that are pointers
+must be declared with the <code>__global</code>, <code>__constant</code> or <code>__local</code>
+qualifier.</p>
+</li>
+<li>
+<p>A pointer declared with the <code>__constant</code> qualifier can only be
+assigned to a pointer declared with the <code>__constant</code> qualifier
+respectively.</p>
+</li>
+<li>
+<p>Pointers to functions are not allowed.</p>
+</li>
+<li>
+<p><span class="line-through">Arguments to kernel functions in a program cannot be
+declared as a pointer to a pointer(s).
+Variables inside a function or arguments to non-kernel functions in a
+program can be declared as a pointer to a pointer(s).</span></p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p>An image type (<code>image2d_t</code>, <code>image3d_t</code>, <code>image2d_array_t</code>, <code>image1d_t</code>,
+<code>image1d_buffer_t</code> or <code>image1d_array_t</code>) can only be used as the type of
+a function argument.
+An image function argument cannot be modified.
+Elements of an image can only be accessed using the built-in
+<a href="#image-read-and-write-functions">image read and write functions</a>.</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>An image type cannot be used to declare a variable, a structure or union
+field, an array of images, a pointer to an image, or the return type of a
+function.
+An image type cannot be used with the <code>__global</code>, <code>__private</code>,
+<code>__local</code> and <code>__constant</code> address space qualifiers.
+<span class="line-through">The <code>image3d_t</code> type cannot be used with the <code>__write_only</code>
+access qualifier unless the <strong>cl_khr_3d_image_writes</strong> extension is enabled.
+An image type cannot be used with the <code>__read_write</code> access qualifer which
+is reserved for future use.</span></p>
+</div>
+<div class="paragraph">
+<p>The sampler type (<code>sampler_t</code>) can only be used as the type of a function
+argument or a variable declared in the program scope or the outermost scope
+of a kernel function.
+The behavior of a sampler variable declared in a non-outermost scope of a
+kernel function is implementation-defined.
+A sampler argument or variable cannot be modified.</p>
+</div>
+<div class="paragraph">
+<p>The sampler type cannot be used to declare a structure or union field, an
+array of samplers, a pointer to a sampler, or the return type of a function.
+The sampler type cannot be used with the <code>__local</code> and <code>__global</code>
+address space qualifiers.</p>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p><a id="restrictions-bitfield"></a> Bit-field struct members are currently not
+supported.</p>
+</li>
+<li>
+<p><a id="restrictions-variable-length"></a> Variable length arrays and structures
+with flexible (or unsized) arrays are not supported.</p>
+</li>
+<li>
+<p>Variadic macros and functions with the exception of printf and
+enqueue_kernel are not supported.</p>
+</li>
+<li>
+<p>Unless defined in the OpenCL specification, the library functions,
+macros, types, and constants defined in the C99 standard headers
+<code>assert.h</code>, <code>ctype.h</code>, <code>complex.h</code>, <code>errno.h</code>, <code>fenv.h</code>, <code>float.h</code>,
+<code>inttypes.h</code>, <code>limits.h</code>, <code>locale.h</code>, <code>setjmp.h</code>, <code>signal.h</code>,
+<code>stdarg.h</code>, <code>stdio.h</code>, <code>stdlib.h</code>, <code>string.h</code>, <code>tgmath.h</code>, <code>time.h</code>,
+<code>wchar.h</code> and <code>wctype.h</code> are not available and cannot be included by a
+program.</p>
+</li>
+<li>
+<p>The <code>auto</code> and <code>register</code> storage-class specifiers are not supported.</p>
+</li>
+<li>
+<p><span class="line-through">Predefined identifiers are not supported.</span></p>
+</li>
+<li>
+<p>Recursion is not supported.</p>
+</li>
+<li>
+<p>The return type of a kernel function must be <code>void</code>.</p>
+</li>
+<li>
+<p>Arguments to kernel functions in a program cannot be declared with the
+built-in scalar types <code>bool</code>, <code>size_t</code>, <code>ptrdiff_t</code>, <code>intptr_t</code>, and
+<code>uintptr_t</code> or a struct and/or union that contain fields declared to be
+one of these built-in scalar types.
+The size in bytes of these types are implementation-defined and in
+addition can also be different for the OpenCL device and the host
+processor making it difficult to allocate buffer objects to be passed as
+arguments to a kernel declared as pointer to these types.</p>
+</li>
+<li>
+<p><code>half</code> is not supported as <code>half</code> can be used as a storage format<sup>25</sup>
+only and is not a data type on which floating-point arithmetic can be
+performed.</p>
+</li>
+<li>
+<p>Whether or not irreducible control flow is illegal is implementation
+defined.</p>
+</li>
+<li>
+<p><span class="line-through">Built-in types that are less than 32-bits in size, i.e.
+<code>char</code>, <code>uchar</code>, <code>char2</code>, <code>uchar2</code>, <code>short</code>, <code>ushort</code>, and <code>half</code>, have
+the following restriction:</span></p>
+<div class="ulist">
+<ul>
+<li>
+<p><span class="line-through">Writes to a pointer (or arrays) of type <code>char</code>,
+<code>uchar</code>, <code>char2</code>, <code>uchar2</code>, <code>short</code>, <code>ushort</code>, and <code>half</code> or to
+elements of a struct that are of type <code>char</code>, <code>uchar</code>, <code>char2</code>,
+<code>uchar2</code>, <code>short</code> and <code>ushort</code> are not supported.
+Refer to <em>section 9.9</em> for additional information.</span></p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p><span class="line-through">The kernel example below shows what memory operations are not
+supported on built-in types less than 32-bits in size.</span></p>
+</div>
+<div class="listingblock line-through">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">kernel <span class="directive">void</span>
+do_proc (__global <span class="predefined-type">char</span> *pA, <span class="predefined-type">short</span> b,
+         __global <span class="predefined-type">short</span> *pB)
+{
+    <span class="predefined-type">char</span> x[<span class="integer">100</span>];
+    __private <span class="predefined-type">char</span> *px = x;
+    <span class="predefined-type">int</span> id = (<span class="predefined-type">int</span>)get_global_id(<span class="integer">0</span>);
+    <span class="predefined-type">short</span> f;
+
+    f = pB[id] + b; <span class="comment">// is allowed</span>
+    px[<span class="integer">1</span>] = pA[<span class="integer">1</span>]; <span class="comment">// error. px cannot be written.</span>
+    pB[id] = b; <span class="comment">// error. pB cannot be written</span>
+}</code></pre>
+</div>
+</div>
+</div>
+</div>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p>The type qualifiers <code>const</code>, <code>restrict</code> and <code>volatile</code> as defined by the
+C99 specification are supported.
+These qualifiers cannot be used with <code>image2d_t</code>, <code>image3d_t</code>,
+<code>image2d_array_t</code>, <code>image2d_depth_t</code>, <code>image2d_array_depth_t</code>,
+<code>image1d_t</code>, <code>image1d_buffer_t</code> and <code>image1d_array_t</code> types.
+Types other than pointer types shall not use the <code>restrict</code> qualifier.</p>
+</li>
+<li>
+<p>The event type (<code>event_t</code>) cannot be used as the type of a kernel
+function argument.
+The event type cannot be used to declare a program scope variable.
+The event type cannot be used to declare a structure or union field.
+The event type cannot be used with the <code>__local</code>, <code>__constant</code> and
+<code>__global</code> address space qualifiers.</p>
+</li>
+<li>
+<p>The <code>clk_event_t</code>, <code>ndrange_t</code> and <code>reserve_id_t</code> types cannot be used
+as arguments to kernel functions that get enqueued from the host.
+The <code>clk_event_t</code> and <code>reserve_id_t</code> types cannot be declared in program
+scope.</p>
+</li>
+<li>
+<p>The values returned by applying the <code>sizeof</code> operator to the <code>queue_t</code>,
+<code>clk_event_t</code>, <code>ndrange_t</code> and <code>reserve_id_t</code> types is
+implementation-defined.</p>
+</li>
+<li>
+<p>Kernels enqueued by the host must continue to have their arguments that
+are a pointer to a type declared to point to a named address space.</p>
+</li>
+<li>
+<p>A function in an OpenCL program cannot be called <code>main</code>.</p>
+</li>
+<li>
+<p>Implicit function declaration is not supported.</p>
+</li>
+</ol>
+</div>
+<div class="paragraph">
+<p>[25] Unless the <strong>cl_khr_fp16</strong> extension is supported and has been enabled.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="preprocessor-directives-and-macros">1.10. Preprocessor Directives and Macros</h3>
+<div class="paragraph">
+<p>The preprocessing directives defined by the C99 specification are supported.</p>
+</div>
+<div class="paragraph">
+<p>The <strong>#pragma</strong> directive is described as:</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>#pragma</strong> <em>pp-tokens<sub>opt</sub></em> <em>new-line</em></p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>A <strong>#pragma</strong> directive where the preprocessing token <code>OPENCL</code> (used instead
+of <strong><code>STDC</code></strong>) does not immediately follow <strong>pragma</strong> in the directive (prior to
+any macro replacement) causes the implementation to behave in an
+implementation-defined manner.
+The behavior might cause translation to fail or cause the translator or the
+resulting program to behave in a non-conforming manner.
+Any such <strong>pragma</strong> that is not recognized by the implementation is ignored.
+If the preprocessing token <code>OPENCL</code> does immediately follow <strong>#pragma</strong> in the
+directive (prior to any macro replacement), then no macro replacement is
+performed on the directive, and the directive shall have one of the
+following forms whose meanings are described elsewhere:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="comment">// on-off-switch is one of ON, OFF, or DEFAULT</span>
+<span class="preprocessor">#pragma</span> OPENCL FP_CONTRACT on-off-<span class="keyword">switch</span>
+
+<span class="preprocessor">#pragma</span> OPENCL EXTENSION extensionname : behavior
+
+<span class="preprocessor">#pragma</span> OPENCL EXTENSION all : behavior</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The following predefined macro names are available.</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"><code>__FILE__</code> </dt>
+<dd>
+<p>The presumed name of the current source file (a character string
+literal).</p>
+</dd>
+<dt class="hdlist1"><code>__LINE__</code> </dt>
+<dd>
+<p>The presumed line number (within the current source file) of the current
+source line (an integer constant).</p>
+</dd>
+<dt class="hdlist1"><code>__OPENCL_VERSION__</code> </dt>
+<dd>
+<p>Substitutes an integer reflecting the version number of the OpenCL
+supported by the OpenCL device.
+The version of OpenCL described in this document will have
+<code>__OPENCL_VERSION__</code> substitute the integer 200.</p>
+</dd>
+<dt class="hdlist1"><code>CL_VERSION_1_0</code> </dt>
+<dd>
+<p>Substitutes the integer 100 reflecting the OpenCL 1.0 version.</p>
+</dd>
+<dt class="hdlist1"><code>CL_VERSION_1_1</code> </dt>
+<dd>
+<p>Substitutes the integer 110 reflecting the OpenCL 1.1 version.</p>
+</dd>
+<dt class="hdlist1"><code>CL_VERSION_1_2</code> </dt>
+<dd>
+<p>Substitutes the integer 120 reflecting the OpenCL 1.2 version.</p>
+</dd>
+<dt class="hdlist1"><code>CL_VERSION_2_0</code> </dt>
+<dd>
+<p>Substitutes the integer 200 reflecting the OpenCL 2.0 version.</p>
+</dd>
+<dt class="hdlist1"><code>__OPENCL_C_VERSION__</code> </dt>
+<dd>
+<p>Substitutes an integer reflecting the OpenCL C version specified by the
+<code>-cl-std</code> build option (see <a href="#opencl-spec">section 5.8.4.5 of the OpenCL
+Specification</a>) to <strong>clBuildProgram</strong> or <strong>clCompileProgram</strong>.
+If the <code>-cl-std</code> build option is not specified, the highest OpenCL C 1.x
+language version supported by each device is used as the version of
+OpenCL C when compiling the program for each device.
+The version of OpenCL C described in this document will have
+<code>__OPENCL_C_VERSION__</code> substitute the integer 200 if <code>-cl-std=CL2.0</code>
+is specified.</p>
+</dd>
+<dt class="hdlist1"><code>__ENDIAN_LITTLE__</code> </dt>
+<dd>
+<p>Used to determine if the OpenCL device is a little endian architecture
+or a big endian architecture (an integer constant of 1 if device is
+little endian and is undefined otherwise).
+Also refer to the value of the <a href="#opencl-device-queries"><code>CL_DEVICE_ENDIAN_LITTLE</code> device query</a>.</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p><code>__kernel_exec(X, type__n__)</code> (and <code>kernel_exec(X, type<em>n</em>)</code>)
+    is defined as</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">__kernel __attribute__((work_group_size_hint(X, <span class="integer">1</span>, <span class="integer">1</span>))) \
+    __attribute__((vec_type_hint(type__n__)))</code></pre>
+</div>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"><code>__IMAGE_SUPPORT__</code> </dt>
+<dd>
+<p>Used to determine if the OpenCL device supports images.
+This is an integer constant of 1 if images are supported and is
+undefined otherwise.
+Also refer to the value of the <a href="#opencl-device-queries"><code>CL_DEVICE_IMAGE_SUPPORT</code> device query</a>.</p>
+</dd>
+<dt class="hdlist1"><code>__FAST_RELAXED_MATH__</code> </dt>
+<dd>
+<p>Used to determine if the <code>-cl-fast-relaxed-math</code> optimization option is
+specified in build options given to <strong>clBuildProgram</strong> or
+<strong>clCompileProgram</strong>.
+This is an integer constant of 1 if the <code>-cl-fast-relaxed-math</code> build
+option is specified and is undefined otherwise.</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>The <code>NULL</code> macro expands to a null pointer constant.
+An integer constant expression with the value 0, or such an expression cast
+to type <code>void *</code> is called a <em>null pointer constant</em>.</p>
+</div>
+<div class="paragraph">
+<p>The macro names defined by the C99 specification but not currently supported
+by OpenCL are reserved for future use.</p>
+</div>
+<div class="paragraph">
+<p>The predefined identifier <code>__func__</code> is available.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="attribute-qualifiers">1.11. Attribute Qualifiers</h3>
+<div class="paragraph">
+<p>This section describes the syntax with which <code>__attribute__</code> may be used,
+and the constructs to which attribute specifiers bind.</p>
+</div>
+<div class="paragraph">
+<p>An attribute specifier is of the form</p>
+</div>
+<div class="paragraph">
+<p><code>__attribute__ ((_attribute-list_))</code>.</p>
+</div>
+<div class="paragraph">
+<p>An attribute list is defined as:</p>
+</div>
+<div class="openblock bnf">
+<div class="content">
+<div class="dlist">
+<dl>
+<dt class="hdlist1"><em>attribute-list</em> : </dt>
+<dd>
+<p><em>attribute<sub>opt</sub></em><br>
+<em>attribute-list</em> , <em>attribute<sub>opt</sub></em></p>
+</dd>
+<dt class="hdlist1"><em>attribute</em> : </dt>
+<dd>
+<p><em>attribute-token</em> <em>attribute-argument-clause<sub>opt</sub></em></p>
+</dd>
+<dt class="hdlist1"><em>attribute-token</em> : </dt>
+<dd>
+<p><em>identifier</em></p>
+</dd>
+<dt class="hdlist1"><em>attribute-argument-clause</em> : </dt>
+<dd>
+<p>( <em>attribute-argument-list</em> )</p>
+</dd>
+<dt class="hdlist1"><em>attribute-argument-list</em> : </dt>
+<dd>
+<p><em>attribute-argument</em><br>
+<em>attribute-argument-list</em> , <em>attribute-argument</em></p>
+</dd>
+<dt class="hdlist1"><em>attribute-argument</em> : </dt>
+<dd>
+<p><em>assignment-expression</em></p>
+</dd>
+</dl>
+</div>
+</div>
+</div>
+<div class="paragraph">
+<p>This syntax is taken directly from GCC but unlike GCC, which allows
+attributes to be applied only to functions, types, and variables, OpenCL
+attributes can be associated with:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>types;</p>
+</li>
+<li>
+<p>functions;</p>
+</li>
+<li>
+<p>variables;</p>
+</li>
+<li>
+<p>blocks; and</p>
+</li>
+<li>
+<p>control-flow statements.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>In general, the rules for how an attribute binds, for a given context, are
+non-trivial and the reader is pointed to GCC&#8217;s documentation and Maurer and
+Wong&#8217;s paper [See 16.
+and 17.
+in <em>section 11</em> - <strong>References</strong>] for the details.</p>
+</div>
+<div class="sect3">
+<h4 id="specifying-attributes-of-types">1.11.1. Specifying Attributes of Types</h4>
+<div class="paragraph">
+<p>The keyword <code>__attribute__</code> allows you to specify special attributes of
+enum, struct and union types when you define such types.
+This keyword is followed by an attribute specification inside double
+parentheses.
+Two attributes are currently defined for types: aligned, and packed.</p>
+</div>
+<div class="paragraph">
+<p>You may specify type attributes in an enum, struct or union type declaration
+or definition, or for other types in a <code>typedef</code> declaration.</p>
+</div>
+<div class="paragraph">
+<p>For an enum, struct or union type, you may specify attributes either between
+the enum, struct or union tag and the name of the type, or just past the
+closing curly brace of the <em>definition</em>.
+The former syntax is preferred.</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"><code>aligned (<em>alignment</em>)</code> </dt>
+<dd>
+<p>This attribute specifies a minimum alignment (in bytes) for variables of the
+specified type.
+For example, the declarations:</p>
+<div class="openblock">
+<div class="content">
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="keyword">struct</span> S { <span class="predefined-type">short</span> f[<span class="integer">3</span>]; } __attribute__ ((aligned (<span class="integer">8</span>)));
+<span class="keyword">typedef</span> <span class="predefined-type">int</span> more_aligned_int __attribute__ ((aligned (<span class="integer">8</span>)));</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>force the compiler to insure (as far as it can) that each variable whose
+type is <code>struct S</code> or <code>more_aligned_int</code> will be allocated and aligned <em>at
+least</em> on a 8-byte boundary.</p>
+</div>
+<div class="paragraph">
+<p>Note that the alignment of any given struct or union type is required by the
+ISO C standard to be at least a perfect multiple of the lowest common
+multiple of the alignments of all of the members of the struct or union in
+question and must also be a power of two.
+This means that you <em>can</em> effectively adjust the alignment of a struct or
+union type by attaching an aligned attribute to any one of the members of
+such a type, but the notation illustrated in the example above is a more
+obvious, intuitive, and readable way to request the compiler to adjust the
+alignment of an entire struct or union type.</p>
+</div>
+<div class="paragraph">
+<p>As in the preceding example, you can explicitly specify the alignment (in
+bytes) that you wish the compiler to use for a given struct or union type.
+Alternatively, you can leave out the alignment factor and just ask the
+compiler to align a type to the maximum useful alignment for the target
+machine you are compiling for.
+For example, you could write:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="keyword">struct</span> S { <span class="predefined-type">short</span> f[<span class="integer">3</span>]; } __attribute__ ((aligned));</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Whenever you leave out the alignment factor in an aligned attribute
+specification, the compiler automatically sets the alignment for the type to
+the largest alignment which is ever used for any data type on the target
+machine you are compiling for.
+In the example above, the size of each <code>short</code> is 2 bytes, and therefore the
+size of the entire <code>struct S</code> type is 6 bytes.
+The smallest power of two which is greater than or equal to that is 8, so
+the compiler sets the alignment for the entire <code>struct S</code> type to 8 bytes.</p>
+</div>
+<div class="paragraph">
+<p>Note that the effectiveness of aligned attributes may be limited by inherent
+limitations of the OpenCL device and compiler.
+For some devices, the OpenCL compiler may only be able to arrange for
+variables to be aligned up to a certain maximum alignment.
+If the OpenCL compiler is only able to align variables up to a maximum of 8
+byte alignment, then specifying <code>aligned(16)</code> in an <code>__attribute__</code> will
+still only provide you with 8 byte alignment.
+See your platform-specific documentation for further information.</p>
+</div>
+<div class="paragraph">
+<p>The aligned attribute can only increase the alignment; but you can decrease
+it by specifying packed as well.
+See below.</p>
+</div>
+</div>
+</div>
+</dd>
+<dt class="hdlist1"><code>packed</code> </dt>
+<dd>
+<p>This attribute, attached to struct or union type definition, specifies that
+each member of the structure or union is placed to minimize the memory
+required.
+When attached to an enum definition, it indicates that the smallest integral
+type should be used.</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>Specifying this attribute for struct and union types is equivalent to
+specifying the packed attribute on each of the structure or union members.</p>
+</div>
+<div class="paragraph">
+<p>In the following example struct <code>my_packed_struct&#8217;s members are packed
+closely together, but the internal layout of its `s</code> member is not packed.
+To do that, struct <code>my_unpacked_struct</code> would need to be packed, too.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="keyword">struct</span> my_unpacked_struct
+{
+    <span class="predefined-type">char</span> c;
+    <span class="predefined-type">int</span> i;
+};
+
+<span class="keyword">struct</span> __attribute__ ((packed)) my_packed_struct
+{
+    <span class="predefined-type">char</span> c;
+    <span class="predefined-type">int</span> i;
+    <span class="keyword">struct</span> my_unpacked_struct s;
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>You may only specify this attribute on the definition of a enum, struct or
+union, not on a <code>typedef</code> which does not also define the enumerated type,
+structure or union.</p>
+</div>
+</div>
+</div>
+</dd>
+</dl>
+</div>
+</div>
+<div class="sect3">
+<h4 id="specifying-attributes-of-functions">1.11.2. Specifying Attributes of Functions</h4>
+<div class="paragraph">
+<p>See <a href="#function-qualifiers">Function Qualifiers</a> for the function attribute
+qualifiers currently supported.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="specifying-attributes-of-variables">1.11.3. Specifying Attributes of Variables</h4>
+<div class="paragraph">
+<p>The keyword <code>__attribute__</code> allows you to specify special attributes of
+variables or structure fields.
+This keyword is followed by an attribute specification inside double
+parentheses.
+The following attribute qualifiers are currently defined:</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"><code>aligned (<em>alignment</em>)</code> </dt>
+<dd>
+<p>This attribute specifies a minimum alignment for the variable or structure
+field, measured in bytes.
+For example, the declaration:</p>
+<div class="openblock">
+<div class="content">
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="predefined-type">int</span> x __attribute__ ((aligned (<span class="integer">16</span>))) = <span class="integer">0</span>;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>causes the compiler to allocate the global variable <code>x</code> on a 16-byte
+boundary.
+The alignment value specified must be a power of two.</p>
+</div>
+<div class="paragraph">
+<p>You can also specify the alignment of structure fields.
+For example, to create a double-word aligned <code>int</code> pair, you could write:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="keyword">struct</span> foo { <span class="predefined-type">int</span> x[<span class="integer">2</span>] __attribute__ ((aligned (<span class="integer">8</span>))); };</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>This is an alternative to creating a union with a <code>double</code> member that
+forces the union to be double-word aligned.</p>
+</div>
+<div class="paragraph">
+<p>As in the preceding examples, you can explicitly specify the alignment (in
+bytes) that you wish the compiler to use for a given variable or structure
+field.
+Alternatively, you can leave out the alignment factor and just ask the
+compiler to align a variable or field to the maximum useful alignment for
+the target machine you are compiling for.
+For example, you could write:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="predefined-type">short</span> array[<span class="integer">3</span>] __attribute__ ((aligned));</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Whenever you leave out the alignment factor in an aligned attribute
+specification, the OpenCL compiler automatically sets the alignment for the
+declared variable or field to the largest alignment which is ever used for
+any data type on the target device you are compiling for.</p>
+</div>
+<div class="paragraph">
+<p>When used on a struct, or struct member, the aligned attribute can only
+increase the alignment; in order to decrease it, the packed attribute must
+be specified as well.
+When used as part of a <code>typedef</code>, the aligned attribute can both increase
+and decrease alignment, and specifying the packed attribute will generate a
+warning.</p>
+</div>
+<div class="paragraph">
+<p>Note that the effectiveness of aligned attributes may be limited by inherent
+limitations of the OpenCL device and compiler.
+For some devices, the OpenCL compiler may only be able to arrange for
+variables to be aligned up to a certain maximum alignment.
+If the OpenCL compiler is only able to align variables up to a maximum of 8
+byte alignment, then specifying <code>aligned(16)</code> in an <code>__attribute__</code> will
+still only provide you with 8 byte alignment.
+See your platform-specific documentation for further information.</p>
+</div>
+</div>
+</div>
+</dd>
+<dt class="hdlist1"><code>packed</code> </dt>
+<dd>
+<p>The packed attribute specifies that a variable or structure field should
+have the smallest possible alignment&#8201;&#8212;&#8201;one byte for a variable, unless you
+specify a larger value with the aligned attribute.</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>Here is a structure in which the field <code>x</code> is packed, so that it immediately
+follows a:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="keyword">struct</span> foo
+{
+    <span class="predefined-type">char</span> a;
+    <span class="predefined-type">int</span> x[<span class="integer">2</span>] __attribute__ ((packed));
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>An attribute list placed at the beginning of a user-defined type applies to
+the variable of that type and not the type, while attributes following the
+type body apply to the type.</p>
+</div>
+<div class="paragraph">
+<p>For example:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="comment">/* a has alignment of 128 */</span>
+__attribute__((aligned(<span class="integer">128</span>))) <span class="keyword">struct</span> A {<span class="predefined-type">int</span> i;} a;
+
+<span class="comment">/* b has alignment of 16 */</span>
+__attribute__((aligned(<span class="integer">16</span>))) <span class="keyword">struct</span> B {<span class="predefined-type">double</span> d;}
+__attribute__((aligned(<span class="integer">32</span>))) b ;
+
+<span class="keyword">struct</span> A a1; <span class="comment">/* a1 has alignment of 4 */</span>
+
+<span class="keyword">struct</span> B b1; <span class="comment">/* b1 has alignment of 32 */</span></code></pre>
+</div>
+</div>
+</div>
+</div>
+</dd>
+<dt class="hdlist1"><code>endian (<em>endiantype</em>)</code> </dt>
+<dd>
+<p>The endian attribute determines the byte ordering of a variable.
+<em>endiantype</em> can be set to <code>host</code> indicating the variable uses the
+endianness of the host processor or can be set to <code>device</code> indicating the
+variable uses the endianness of the device on which the kernel will be
+executed.
+The default is <code>device</code>.</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>For example:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">global float4 *p __attribute__ ((endian(host)));</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>specifies that data stored in memory pointed to by p will be in the host
+endian format.</p>
+</div>
+<div class="paragraph">
+<p>The endian attribute can only be applied to pointer types that are in the
+<code>global</code> or <code>constant</code> address space.
+The endian attribute cannot be used for variables that are not a pointer
+type.
+The endian attribute value for both pointers must be the same when one
+pointer is assigned to another.</p>
+</div>
+</div>
+</div>
+</dd>
+</dl>
+</div>
+</div>
+<div class="sect3">
+<h4 id="specifying-attributes-of-blocks-and-control-flow-statements">1.11.4. Specifying Attributes of Blocks and Control-Flow-Statements</h4>
+<div class="paragraph">
+<p>For basic blocks and control-flow-statements the attribute is placed before
+the structure in question, for example:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">__attribute__((attr1)) {...}
+
+<span class="keyword">for</span> __attribute__((attr2)) (...) __attribute__((attr3)) {...}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Here <code>attr1</code> applies to the block in braces and <code>attr2</code> and <code>attr3</code> apply to
+the loop&#8217;s control construct and body, respectively.</p>
+</div>
+<div class="paragraph">
+<p>No attribute qualifiers for blocks and control-flow-statements are currently
+defined.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="specifying-attribute-for-unrolling-loops">1.11.5. Specifying Attribute For Unrolling Loops</h4>
+<div class="paragraph">
+<p>The <code>__attribute__((opencl_unroll_hint))</code> and
+<code>__attribute__((opencl_unroll_hint(n)))</code> attribute qualifiers can be used
+to specify that a loop (for, while and do loops) can be unrolled.
+This attribute qualifier can be used to specify full unrolling or partial
+unrolling by a specified amount.
+This is a compiler hint and the compiler may ignore this directive.</p>
+</div>
+<div class="paragraph">
+<p>n is the loop unrolling factor and must be a positive integral compile time
+constant expression.
+An unroll factor of 1 disables unrolling.
+If n is not specified, the compiler determines the unrolling factor for the
+loop.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>The <code>__attribute__((opencl_unroll_hint(n)))</code> attribute qualifier must
+appear immediately before the loop to be affected.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p>Examples:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">__attribute__((opencl_unroll_hint(<span class="integer">2</span>)))
+<span class="keyword">while</span> (*s != <span class="integer">0</span>)
+    *p++ = *s++;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The tells the compiler to unroll the above while loop by a factor of 2.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">__attribute__((opencl_unroll_hint))
+<span class="keyword">for</span> (<span class="predefined-type">int</span> i=<span class="integer">0</span>; i&lt;<span class="integer">2</span>; i++)
+{
+    ...
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>In the example above, the compiler will determine how much to unroll the
+loop.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">__attribute__((opencl_unroll_hint(<span class="integer">1</span>)))
+<span class="keyword">for</span> (<span class="predefined-type">int</span> i=<span class="integer">0</span>; i&lt;<span class="integer">32</span>; i++)
+{
+    ...
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The above is an example where the loop should not be unrolled.</p>
+</div>
+<div class="paragraph">
+<p>Below are some examples of invalid usage of
+<code>__attribute__((opencl_unroll_hint(n)))</code>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">__attribute__((opencl_unroll_hint(-<span class="integer">1</span>)))
+<span class="keyword">while</span> (...)
+{
+    ...
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The above example is an invalid usage of the loop unroll factor as the loop
+unroll factor is negative.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">__attribute__((opencl_unroll_hint))
+<span class="keyword">if</span> (...)
+{
+    ...
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The above example is invalid because the unroll attribute qualifier is used
+on a non-loop construct</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">kernel <span class="directive">void</span>
+my_kernel( ... )
+{
+    <span class="predefined-type">int</span> x;
+    __attribute__((opencl_unroll_hint(x))
+    <span class="keyword">for</span> (<span class="predefined-type">int</span> i=<span class="integer">0</span>; i&lt;x; i++)
+    {
+        ...
+    }
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The above example is invalid because the loop unroll factor is not a
+compile-time constant expression.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="extending-attribute-qualifiers">1.11.6. Extending Attribute Qualifiers</h4>
+<div class="paragraph">
+<p>The attribute syntax can be extended for standard language extensions and
+vendor specific extensions.
+Any extensions should follow the naming conventions outlined in the
+introduction to <a href="#opencl-extension-spec">section 9 in the OpenCL 2.0
+Extension Specification</a>.</p>
+</div>
+<div class="paragraph">
+<p>Attributes are intended as useful hints to the compiler.
+It is our intention that a particular implementation of OpenCL be free to
+ignore all attributes and the resulting executable binary will produce the
+same result.
+This does not preclude an implementation from making use of the additional
+information provided by attributes and performing optimizations or other
+transformations as it sees fit.
+In this case it is the programmer&#8217;s responsibility to guarantee that the
+information provided is in some sense correct.</p>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="blocks">1.12. Blocks</h3>
+<div class="paragraph">
+<p>OpenCL C 2.0 adds support for the clang block syntax<sup>26</sup>.
+Like function types, the Block type is a pair consisting of a result value
+type and a list of parameter types very similar to a function type.
+Blocks are intended to be used much like functions with the key distinction
+being that in addition to executable code they also contain various variable
+bindings to automatic (stack) or <code>global</code> memory.</p>
+</div>
+<div class="paragraph">
+<p>[26] This syntax is already part of the clang source tree on which most
+vendors have based their OpenCL implementations.
+Additionally, blocks based closures are supported by the clang open source C
+compiler as well as Mac OS X&#8217;s C and Objective C compilers.
+Specifically, Mac OS X&#8217;s Grand Central Dispatch allows applications to queue
+tasks as a block.</p>
+</div>
+<div class="sect3">
+<h4 id="declaring-and-using-a-block">1.12.1. Declaring and Using a Block</h4>
+<div class="paragraph">
+<p>You use the ^ operator to declare a Block variable and to indicate the
+beginning of a Block literal.
+The body of the Block itself is contained within {}, as shown in this
+example (as usual with C, ; indicates the end of the statement):</p>
+</div>
+<div class="paragraph">
+<p>The example is explained in the following illustration:</p>
+</div>
+<div class="paragraph">
+<p><span class="image"><img src="data:image/jpg;base64,/9j/4AAQSkZJRgABAgAAZABkAAD/7AARRHVja3kAAQAEAAAAUAAA/+4ADkFkb2JlAGTAAAAAAf/bAIQAAgICAgICAgICAgMCAgIDBAMCAgMEBQQEBAQEBQYFBQUFBQUGBgcHCAcHBgkJCgoJCQwMDAwMDAwMDAwMDAwMDAEDAwMFBAUJBgYJDQsJCw0PDg4ODg8PDAwMDAwPDwwMDAwMDA8MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM/8AAEQgA5AIsAwERAAIRAQMRAf/EAN4AAQACAgMBAQAAAAAAAAAAAAAGBwUIAQMEAgkBAQADAQEBAQAAAAAAAAAAAAABAgMEBQYHEAAABQIEAAcIDAgGDAoIBwABAgMEBQAGERITByFhFNQXVwgxUdEiFZUWGEFxobEyUmIj05RWlpGik1RktCVYgUJjJHY38ILSM1Nzs3W1psZHkkM0RHQ1VYUmZ+KDhGXFNmYocqTERoaHSBEAAgEBBQQGCAUEAgMAAwEAAAECESExEgMEQVGRE2Fx0VIUBYGhscHhIjIWQpJTFQbwcjM08WKi0iOCsiTi/9oADAMBAAIRAxEAPwD9/KAUAoBQCgFAKAUBgLkuSFs+AmbpuR+nFwUA0VfSr9TESpoolExhApQExhHDApSgJjDgAAIiAUBSEfaN6bupluDc+QmLJtF8GeC2fiHasa55KcByKXC/aHI4UcKFEBM2QVIil8A+uYBPQGZL2a+zvlKC2x9jPlAAAM6fQLB4ufD2TruElFDjxmMNAffq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegHq19nLqD28+7EVzegOB7NfZ1w+b2KsFsf8Airt7djkFS8ZFEkCnKPGAgNAYl5txdm2qYzWysy+fsGJQO92dn5BZ5GP0SYiZKLevTqrxrgQEdPBQWwmwKdIoDqEAmvTBZnRl0rcoeej2j/yDkxvKfLtfkfkvkfw+W8r/AJto93W8SgLUoBQCgFAKAUAoBQFC7tASevXZWwnJTHiZi4HVyTjfHArhG2WgvGqJw9koP1GqogPd08KAuzV46nCUxIavHTCMSMDc9xEte35S4VYiWnkopIFTxMGzUkJBfEwFyt2qXjqG8bHAPYxH2KgtUz4GMPcKI+0FTQVI/I3Zb8RO23bElKIs7gu8XhbZilM2q8GPRBw6BPABD5pMcw4iHBShJn9biphKYkfWJ/iG/BShap1KraSaqgpKKaJDHFJMuY4gUMcCl9kR9gKUFSudst1rf3Wj7gewEdNRC9qzSlv3DDT8epGvmr9Ju3dimdBXEcBScpmAQHAcaUJJVa122/e0Cxue05RKdgJIVgYSjbMKaot1ToKgXMUo+KomYo8HdClALWuIl1QEVcCMRLQacqjrlh5xkpHyLcMwlyOWqvjpG4McB9jAaUIqRDdXdq3tnLfRum7IudcwIuCoP5GHjlZAjApxAoLvNPhSSzGAMw+zUEkxuK4SW4zavFYiWmQdyTKM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E9YwAAAA/wQBAAAAAAD/BAEAAAAAAP8EAQAAAAAA/wQBAAAAAAD/BAEAAAAAAP8EAQAAFPYDkCQVNgEY9gMAADXWBQABAywQNdYFAQIDZBRh9gNsAIUAFiQBFyQBSWYBAAAAAZZsACF2AAJoASN2AAEsECN2AQJkFDpWCwAClmwACnQAAOABE9YwAAAA/wQBAAAAAAD/BAEAAAAAAP8EAQAAAAAA/wQBAAAAAAD/BAEAAAAAAP8EAQAAFPYDkCQVNgEY9gMAADXWBQABAywQNdYFAQIDZBRh9gNsAIUAFiQBFyQBSWYBAAAAAZZsACF2AAJoASN2AAEsECN2AQJkFDpWCwAClmwACnQAAOABE9YwAAAA/wQBAAAAAAD/BAEAAAAAAP8EAQAAAAAA/wQBAAAAAAD/BAEAAAAAAP8EAQAAFPYDkCQVNgEY9gMAADXWBQABAywQNdYFAQIDZBRh9gNsAIUAFiQBFyQBSWYBAAAAAZZsACF2AAJoASN2AAEsECN2AQJkFDpWCwAClmwACnQAAOABE9YwAAAA/wQBAAAAAAD/BAEAAAAAAP8EAQAAAAAA/wQBAAAAAAD/BAEAAAAAAP8EAQAAFPYDkCQVNgEY9gMAADXWBQABAywQNdYFAQIDZBRh9gNsAIUAFiQBFyQBSWYBAAAAAZZsACF2AAJoASN2AAEsECN2AQJkFDpWCwAClmwACnQAAOABE9YwAAAA/wQBAAAAAAD/BAEAAAAAAP8EAQAAAAAA/wQBAAAAAAD/BAEAAAAAAP8EAQAAFPYDkCQVNgEY9gMAADXWBQABAywQNdYFAQIDZBRh9gNsAIUAFiQBFyQBSWYBAAAAAZZsACF2AAJoASN2AAEsECN2AQJkFDpWCwAClmwACnQAAOABE9YwAAAA/wQBAAAAAAD/BAEAAAAAAP8EAQAAAAAA/wQBAAAAAAD/BAEAAAAAAP8EAQAAFPYDkCQVNgEY9gMAADXWBQABAywQNdYFAQIDZBRh9gNsAIUAFiQBFyQBSWYBAAAAAZZsACF2AAJoASN2AAEsECN2AQJkFDpWCwAClmwACnQAAOABE9YwAAAA/wQBAAAAAAD/BAEAAAAAAP8EAQAAAAAA/wQBAAAAAAD/BAEAAAAAAP8EAQAAFPYDkCQVNgEY9gMAADXWBQABAywQNdYFAQIDZBRh9gNsAIUAFiQBFyQBSWYBAAAAAZZsACF2AAJoASN2AAEsECN2AQJkFDpWCwAClmwACnQAAOABE9YwAAAA/wQBAAAAAAD/BAEAAAAAAP8EAQAAAAAA/wQBAAAAAAD/BAEAAAAAAP8EAQAAFPYDkCQVNgEY9gMAADXWBQABAywQNdYFAQIDZBRh9gNsAIUAFiQBFyQBSWYBAAAAAZZsACF2AAJoASN2AAEsECN2AQJkFDpWCwAClmwACnQAAOABE9YwAAAA/wQBAAAAAAD/BAEAAAAAAP8EAQAAAAAA/wQBAAAAAAD/BAEAAAAAAP8EAQAAFPYDkCQVNgEY9gMAADXWBQABAywQNdYFAQIDZBRh9gNsAIUAFiQBFyQBSWYBAAAAAZZsACF2AAJoASN2AAEsECN2AQJkFDpWCwAClmwACnQAAOABE9YwAAAA/wQBAAAAAAD/BAEAAAAAAP8EAQAAAAAA/wQBAAAAAAD/BAEAAAAAAP8EAQAAFPYDkCQVNgEY9gMAADXWBQABAywQNdYFAQIDZBRh9gNsAIUAFiQBFyQBSWYBAAAAAZZsACF2AAJoASN2AAEsECN2AQJkFDpWCwAClmwACnQAAOABE9YwAAAA/wQBAAAAAAD/BAEAAAAAAP8EAQAAAAAA/wQBAAAAAAD/BAEAAAAAAP8EAQAAFPYDkCQVNgEY9gMAADXWBQABAywQNdYFAQIDZBRh9gNsAIUAFiQBFyQBSWYBAAAAAZZsACF2AAJoASN2AAEsECN2AQJkFDpWCwAClmwACnQAAOABE9YwAAAA/wQBAAAAAAD/BAEAAAAAAP8EAQAAAAAA/wQBAAAAAAD/BAEAAAAAAP8EAQAAFPYDkCQVNgE=" alt="block example" title="Block Example"></span></p>
+</div>
+<div class="paragraph">
+<p>Notice that the Block is able to make use of variables from the same scope
+in which it was defined.</p>
+</div>
+<div class="paragraph">
+<p>If you declare a Block as a variable, you can then use it just as you would
+a function:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="predefined-type">int</span> multiplier = <span class="integer">7</span>;
+
+<span class="predefined-type">int</span> (^myBlock)(<span class="predefined-type">int</span>) = ^(<span class="predefined-type">int</span> num) {
+    <span class="keyword">return</span> num * multiplier;
+};
+
+printf(<span class="string"><span class="delimiter">&quot;</span><span class="content">%d</span><span class="char">\n</span><span class="delimiter">&quot;</span></span>, myBlock(<span class="integer">3</span>));
+<span class="comment">// prints 21</span></code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="declaring-a-block-reference">1.12.2. Declaring a Block Reference</h4>
+<div class="paragraph">
+<p>Block variables hold references to Blocks.
+You declare them using syntax similar to that you use to declare a pointer
+to a function, except that you use ^ instead of *.
+The Block type fully interoperates with the rest of the C type system.
+The following are valid Block variable declarations:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="directive">void</span> (^blockReturningVoidWithVoidArgument)(<span class="directive">void</span>);
+<span class="predefined-type">int</span> (^blockReturningIntWithIntAndCharArguments)(<span class="predefined-type">int</span>, <span class="predefined-type">char</span>);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>A Block that takes no arguments must specify <code>void</code> in the argument list.
+A Block reference may not be dereferenced via the pointer dereference
+operation *, and thus a Block&#8217;s size may not be computed at compile time.</p>
+</div>
+<div class="paragraph">
+<p>Blocks are designed to be fully type safe by giving the compiler a full set
+of metadata to use to validate use of Blocks, parameters passed to blocks,
+and assignment of the return value.</p>
+</div>
+<div class="paragraph">
+<p>You can also create types for Blocks&#8201;&#8212;&#8201;doing so is generally considered to
+be best practice when you use a block with a given signature in multiple
+places:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="keyword">typedef</span> <span class="predefined-type">float</span> (^MyBlockType)(<span class="predefined-type">float</span>, <span class="predefined-type">float</span>);
+
+MyBlockType myFirstBlock = <span class="comment">// ...;</span>
+MyBlockType mySecondBlock = <span class="comment">// ...;</span></code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="block-literal-expressions">1.12.3. Block Literal Expressions</h4>
+<div class="paragraph">
+<p>A Block literal expression produces a reference to a Block.
+It is introduced by the use of the <strong>^</strong> token as a unary operator.</p>
+</div>
+<div class="openblock bnf">
+<div class="content">
+<div class="dlist">
+<dl>
+<dt class="hdlist1">Block_literal_expression : </dt>
+<dd>
+<p>^ <em>block_decl</em> <em>compound_statement_body</em></p>
+</dd>
+<dt class="hdlist1"><em>block_decl</em> : </dt>
+<dd>
+<p>empty<br>
+<em>parameter_list</em><br>
+<em>type_expression</em></p>
+</dd>
+</dl>
+</div>
+</div>
+</div>
+<div class="paragraph">
+<p>where <em>type_expression</em> is extended to allow ^ as a Block reference where *
+is allowed as a function reference.</p>
+</div>
+<div class="paragraph">
+<p>The following Block literal:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">^ <span class="directive">void</span> (<span class="directive">void</span>) { printf(<span class="string"><span class="delimiter">&quot;</span><span class="content">hello world**</span><span class="char">\n</span><span class="content">**</span><span class="delimiter">&quot;</span></span>); }</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>produces a reference to a Block with no arguments with no return value.</p>
+</div>
+<div class="paragraph">
+<p>The return type is optional and is inferred from the return statements.
+If the return statements return a value, they all must return a value of the
+same type.
+If there is no value returned the inferred type of the Block is <code>void</code>;
+otherwise it is the type of the return statement value.
+If the return type is omitted and the argument list is <code>( void )</code>, the <code>(
+void )</code> argument list may also be omitted.</p>
+</div>
+<div class="paragraph">
+<p>So:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">^ ( <span class="directive">void</span> ) { printf(<span class="string"><span class="delimiter">&quot;</span><span class="content">hello world**</span><span class="char">\n</span><span class="content">**</span><span class="delimiter">&quot;</span></span>); }</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>and:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">^ { printf(<span class="string"><span class="delimiter">&quot;</span><span class="content">hello world**</span><span class="char">\n</span><span class="content">**</span><span class="delimiter">&quot;</span></span>); }</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>are exactly equivalent constructs for the same expression.</p>
+</div>
+<div class="paragraph">
+<p>The compound statement body establishes a new lexical scope within that of
+its parent.
+Variables used within the scope of the compound statement are bound to the
+Block in the normal manner with the exception of those in automatic (stack)
+storage.
+Thus one may access functions and global variables as one would expect, as
+well as <code>static</code> local variables.</p>
+</div>
+<div class="paragraph">
+<p>Local automatic (stack) variables referenced within the compound statement
+of a Block are imported and captured by the Block as const copies.
+The capture (binding) is performed at the time of the Block literal
+expression evaluation.</p>
+</div>
+<div class="paragraph">
+<p>The compiler is not required to capture a variable if it can prove that no
+references to the variable will actually be evaluated.</p>
+</div>
+<div class="paragraph">
+<p>The lifetime of variables declared in a Block is that of a function..</p>
+</div>
+<div class="paragraph">
+<p>Block literal expressions may occur within Block literal expressions
+(nested) and all variables captured by any nested blocks are implicitly also
+captured in the scopes of their enclosing Blocks.</p>
+</div>
+<div class="paragraph">
+<p>A Block literal expression may be used as the initialization value for Block
+variables at global or local <code>static</code> scope.</p>
+</div>
+<div class="paragraph">
+<p>You can also declare a Block as a global literal in program scope.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="predefined-type">int</span> GlobalInt = <span class="integer">0</span>;
+
+<span class="predefined-type">int</span> (^getGlobalInt)(<span class="directive">void</span>) = ^{ <span class="keyword">return</span> GlobalInt; };</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="control-flow">1.12.4. Control Flow</h4>
+<div class="paragraph">
+<p>The compound statement of a Block is treated much like a function body with
+respect to control flow in that continue, break and goto do not escape the
+Block.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="restrictions-1">1.12.5. Restrictions</h4>
+<div class="paragraph">
+<p>The following Blocks features are currently not supported in OpenCL C.</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>The <code>__block</code> storage type.</p>
+</li>
+<li>
+<p>The <strong>Block_copy</strong>() and <strong>Block_release</strong>() functions that copy and release
+Blocks.</p>
+</li>
+<li>
+<p>Blocks with variadic arguments.</p>
+</li>
+<li>
+<p>Arrays of Blocks.</p>
+</li>
+<li>
+<p>Blocks as structures and union members.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Block literals are assumed to allocate memory at the point of definition and
+to be destroyed at the end of the same scope.
+To support these behaviors, additional restrictions<sup>27</sup> in addition to the
+above feature restrictions are:</p>
+</div>
+<div class="paragraph">
+<p>[27] OpenCL C <a href="#restrictions">does not allow function pointers</a> primarily
+because it is difficult or expensive to implement generic indirections to
+executable code in many hardware architectures that OpenCL targets.
+OpenCL C&#8217;s design of Blocks is intended to respect that same condition,
+yielding the restrictions listed here.
+As such, Blocks allow a form of dynamically enqueued function scheduling
+without providing a form of runtime synchronous dynamic dispatch analogous
+to function pointers.</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Block variables must be defined and used in a way that allows them to be
+statically determinable at build or &#8220;link to executable&#8221; time.
+In particular:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>Block variables assigned in one scope must be used only with the same
+or any nested scope.</p>
+</li>
+<li>
+<p>The <code>extern</code> storage-class specified cannot be used with program scope
+block variables.</p>
+</li>
+<li>
+<p>Block variable declarations are implicitly qualified with const.
+Therefore all block variables must be initialized at declaration time
+and may not be reassigned.</p>
+</li>
+<li>
+<p>A block cannot be the return value of a function.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p>The unary operators (<strong>*</strong> and <strong>&amp;</strong>) cannot be used with a Block.</p>
+</li>
+<li>
+<p>Pointers to Blocks are not allowed.</p>
+</li>
+<li>
+<p>Blocks cannot be used as expressions of the ternary selection operator
+(<strong>?:</strong>).</p>
+</li>
+<li>
+<p>A Block cannot capture another Block variable declared in the outer
+scope (Example 4).</p>
+</li>
+<li>
+<p>Block capture semantics follows regular C argument passing convention,
+i.e. arrays are captured by reference (decayed to pointers) and structs
+are captured by value (Example 5).</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Some examples that describe legal and illegal issue of Blocks in OpenCL C
+are described below.</p>
+</div>
+<div class="paragraph">
+<p>Example 1:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="directive">void</span> foo(<span class="predefined-type">int</span> *x, <span class="predefined-type">int</span> (^bar)(<span class="predefined-type">int</span>, <span class="predefined-type">int</span>))
+{
+    *x = bar(*x, *x);
+}
+
+kernel
+<span class="directive">void</span> k(global <span class="predefined-type">int</span> *x, global <span class="predefined-type">int</span> *z)
+{
+    <span class="keyword">if</span> (some expression)
+        foo(x, ^<span class="predefined-type">int</span>(<span class="predefined-type">int</span> x, <span class="predefined-type">int</span> y){<span class="keyword">return</span> x+y+*z;}); <span class="comment">// legal</span>
+    <span class="keyword">else</span>
+        foo(x, ^<span class="predefined-type">int</span>(<span class="predefined-type">int</span> x, <span class="predefined-type">int</span> y){<span class="keyword">return</span> (x*y)-*z;}); <span class="comment">// legal</span>
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Example 2:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">kernel
+<span class="directive">void</span> k(global <span class="predefined-type">int</span> *x, global <span class="predefined-type">int</span> *z)
+{
+    <span class="predefined-type">int</span> ^(tmp)(<span class="predefined-type">int</span>, <span class="predefined-type">int</span>);
+    <span class="keyword">if</span> (some expression)
+    {
+        tmp = ^<span class="predefined-type">int</span>(<span class="predefined-type">int</span> x, <span class="predefined-type">int</span> y){<span class="keyword">return</span> x+y+*z;}); <span class="comment">// illegal</span>
+    }
+    *x = foo(x, tmp);
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Example 3:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="predefined-type">int</span> GlobalInt = <span class="integer">0</span>;
+<span class="predefined-type">int</span> (^getGlobalInt)(<span class="directive">void</span>) = ^{ <span class="keyword">return</span> GlobalInt; }; <span class="comment">// legal</span>
+<span class="predefined-type">int</span> (^getAnotherGlobalInt)(<span class="directive">void</span>);                   <span class="comment">// illegal</span>
+<span class="directive">extern</span> <span class="predefined-type">int</span> (^getExternGlobalInt)(<span class="directive">void</span>);             <span class="comment">// illegal</span>
+
+<span class="directive">void</span> foo()
+
+{
+    ...
+    getGlobalInt = ^{ <span class="keyword">return</span> <span class="integer">0</span>; }; <span class="comment">// illegal - cannot assign to</span>
+                                   <span class="comment">// a global block variable</span>
+    ...
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Example 4:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="directive">void</span> (^bl0)(<span class="directive">void</span>) = ^{
+    ...
+};
+
+kernel <span class="directive">void</span> k()
+{
+    <span class="directive">void</span>(^bl1)(<span class="directive">void</span>) = ^{
+        ...
+    };
+
+    <span class="directive">void</span>(^bl2)(<span class="directive">void</span>) = ^{
+        bl0(); <span class="comment">// legal because bl0 is a global</span>
+               <span class="comment">// variable available in this scope</span>
+        bl1(); <span class="comment">// illegal because bl1 would have to be captured</span>
+    };
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Example 5:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="keyword">struct</span> v {
+    <span class="predefined-type">int</span> arr[<span class="integer">2</span>];
+} s = {<span class="integer">0</span>, <span class="integer">1</span>};
+
+<span class="directive">void</span> (^bl1)() = ^(){printf(<span class="string"><span class="delimiter">&quot;</span><span class="content">%d</span><span class="char">\n</span><span class="delimiter">&quot;</span></span>, s.arr[<span class="integer">1</span>]);};
+<span class="comment">// array content copied into captured struct location</span>
+
+<span class="predefined-type">int</span> arr[<span class="integer">2</span>] = {<span class="integer">0</span>, <span class="integer">1</span>};
+<span class="directive">void</span> (^bl2)() = ^(){printf(<span class="string"><span class="delimiter">&quot;</span><span class="content">%d</span><span class="char">\n</span><span class="delimiter">&quot;</span></span>, arr[<span class="integer">1</span>]);};
+<span class="comment">// array decayed to pointer while captured</span>
+
+s.arr[<span class="integer">1</span>] = arr[<span class="integer">1</span>] = <span class="integer">8</span>;
+
+bl1(); <span class="comment">// prints - 1</span>
+bl2(); <span class="comment">// prints - 8</span></code></pre>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="built-in-functions">1.13. Built-in Functions</h3>
+<div class="paragraph">
+<p>The OpenCL C programming language provides a rich set of built-in functions
+for scalar and vector operations.
+Many of these functions are similar to the function names provided in common
+C libraries but they support scalar and vector argument types.
+Applications should use the built-in functions wherever possible instead of
+writing their own version.</p>
+</div>
+<div class="paragraph">
+<p>User defined OpenCL C functions behave per C standard rules for functions as
+defined in <a href="#C99-spec">section 6.9.1 of the C99 Specification</a>.
+On entry to the function, the size of each variably modified parameter is
+evaluated and the value of each argument expression is converted to the type
+of the corresponding parameter as per the
+<a href="#usual-arithmetic-conversions">usual arithmetic conversion rules</a>.
+Built-in functions described in this section behave similarly, except that
+in order to avoid ambiguity between multiple forms of the same built-in
+function, implicit scalar widening shall not occur.
+Note that some built-in functions described in this section do have forms
+that operate on mixed scalar and vector types, however.</p>
+</div>
+<div class="sect3">
+<h4 id="work-item-functions">1.13.1. Work-Item Functions</h4>
+<div class="paragraph">
+<p>The following table describes the list of built-in work-item functions that
+can be used to query the number of dimensions, the global and local work
+size specified to <strong>clEnqueueNDRangeKernel</strong>, and the global and local
+identifier of each work-item when this kernel is being executed on a device.</p>
+</div>
+<table id="table-work-item-functions" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 7. Work-Item Functions Table</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Function</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">uint <strong>get_work_dim</strong>()</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the number of dimensions in use.
+      This is the value given to the <em>work_dim</em> argument specified in
+      <strong>clEnqueueNDRangeKernel</strong>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t <strong>get_global_size</strong>(uint <em>dimindx</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the number of global work-items specified for dimension
+      identified by <em>dimindx</em>.
+      This value is given by the <em>global_work_size</em> argument to
+      <strong>clEnqueueNDRangeKernel</strong>.</p>
+<p class="tableblock">      Valid values of <em>dimindx</em> are 0 to <strong>get_work_dim</strong>() - 1.
+      For other values of <em>dimindx</em>, <strong>get_global_size</strong>() returns 1.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t <strong>get_global_id</strong>(uint <em>dimindx</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the unique global work-item ID value for dimension identified
+      by <em>dimindx</em>.
+      The global work-item ID specifies the work-item ID based on the number
+      of global work-items specified to execute the kernel.</p>
+<p class="tableblock">      Valid values of <em>dimindx</em> are 0 to <strong>get_work_dim</strong>() - 1.
+      For other values of <em>dimindx</em>, <strong>get_global_id</strong>() returns 0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t <strong>get_local_size</strong>(uint <em>dimindx</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the number of local work-items specified in dimension
+      identified by <em>dimindx</em>.
+      This value is at most the value given by the <em>local_work_size</em>
+      argument to <strong>clEnqueueNDRangeKernel</strong> if <em>local_work_size</em> is not
+      <code>NULL</code>; otherwise the OpenCL implementation chooses an appropriate
+      <em>local_work_size</em> value which is returned by this function.
+      If the kernel is executed with a non-uniform work-group size<sup>28</sup>, calls
+      to this built-in from some work-groups may return different values
+      than calls to this built-in from other work-groups.</p>
+<p class="tableblock">      Valid values of <em>dimindx</em> are 0 to <strong>get_work_dim</strong>() - 1.
+      For other values of <em>dimindx</em>, <strong>get_local_size</strong>() returns 1.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t <strong>get_enqueued_local_size</strong>(
+      uint <em>dimindx</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the same value as that returned by <strong>get_local_size</strong>(<em>dimindx</em>)
+      if the kernel is executed with a uniform work-group size.</p>
+<p class="tableblock">      If the kernel is executed with a non-uniform work-group size, returns
+      the number of local work-items in each of the work-groups that make up
+      the uniform region of the global range in the dimension identified by
+      <em>dimindx</em>.
+      If the <em>local_work_size</em> argument to <strong>clEnqueueNDRangeKernel</strong> is not
+      <code>NULL</code>, this value will match the value specified in
+      <em>local_work_size</em>[<em>dimindx</em>].
+      If <em>local_work_size</em> is <code>NULL</code>, this value will match the local size
+      that the implementation determined would be most efficient at
+      implementing the uniform region of the global range.</p>
+<p class="tableblock">      Valid values of <em>dimindx</em> are 0 to <strong>get_work_dim</strong>() - 1.
+      For other values of <em>dimindx</em>, <strong>get_enqueued_local_size</strong>() returns 1.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t <strong>get_local_id</strong>(uint <em>dimindx</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the unique local work-item ID, i.e. a work-item within a
+      specific work-group for dimension identified by <em>dimindx</em>.</p>
+<p class="tableblock">      Valid values of <em>dimindx</em> are 0 to <strong>get_work_dim</strong>() - 1.
+      For other values of <em>dimindx</em>, <strong>get_local_id</strong>() returns 0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t <strong>get_num_groups</strong>(uint <em>dimindx</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the number of work-groups that will execute a kernel for
+      dimension identified by <em>dimindx</em>.</p>
+<p class="tableblock">      Valid values of <em>dimindx</em> are 0 to <strong>get_work_dim</strong>() - 1.
+      For other values of <em>dimindx</em>, <strong>get_num_groups</strong>() returns 1.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t <strong>get_group_id</strong>(uint <em>dimindx</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>get_group_id</strong> returns the work-group ID which is a number from 0 ..
+      <strong>get_num_groups</strong>(<em>dimindx</em>) - 1.</p>
+<p class="tableblock">      Valid values of <em>dimindx</em> are 0 to <strong>get_work_dim</strong>() - 1.
+      For other values, <strong>get_group_id</strong>() returns 0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t <strong>get_global_offset</strong>(uint <em>dimindx</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>get_global_offset</strong> returns the offset values specified in
+      <em>global_work_offset</em> argument to <strong>clEnqueueNDRangeKernel</strong>.</p>
+<p class="tableblock">      Valid values of <em>dimindx</em> are 0 to <strong>get_work_dim</strong>() - 1.
+      For other values, <strong>get_global_offset</strong>() returns 0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t <strong>get_global_linear_id</strong>()</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the work-items 1-dimensional global ID.</p>
+<p class="tableblock">      For 1D work-groups, it is computed as <strong>get_global_id</strong>(0) -
+      <strong>get_global_offset</strong>(0).</p>
+<p class="tableblock">      For 2D work-groups, it is computed as (<strong>get_global_id</strong>(1) -
+      <strong>get_global_offset</strong>(1)) * <strong>get_global_size</strong>(0) + (<strong>get_global_id</strong>(0) -
+      <strong>get_global_offset</strong>(0)).</p>
+<p class="tableblock">      For 3D work-groups, it is computed as <strong>get_global_id</strong>(2) -       <strong>get_global_offset</strong>(2 * <strong>get_global_size</strong>(1) * <strong>get_global_size</strong>(0))
+      + <strong>get_global_id</strong>(1) - <strong>get_global_offset</strong>(1 * <strong>get_global_size</strong>
+      (0)) + (<strong>get_global_id</strong>(0) - <strong>get_global_offset</strong>(0)).</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t <strong>get_local_linear_id</strong>()</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the work-items 1-dimensional local ID.</p>
+<p class="tableblock">      For 1D work-groups, it is the same value as</p>
+<p class="tableblock">      <strong>get_local_id</strong>(0).</p>
+<p class="tableblock">      For 2D work-groups, it is computed as</p>
+<p class="tableblock">      <strong>get_local_id</strong>(1) * <strong>get_local_size</strong>(0) + <strong>get_local_id</strong>(0).</p>
+<p class="tableblock">      For 3D work-groups, it is computed as</p>
+<p class="tableblock">      <strong>(get_local_id</strong>(2) * <strong>get_local_size</strong>(1) * <strong>get_local_size</strong>(0)) + 
+      (<strong>get_local_id</strong>(1) * <strong>get_local_size</strong>(0)) + <strong>get_local_id</strong>(0).</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>[28] I.e. the <em>global_work_size</em> values specified to <strong>clEnqueueNDRangeKernel</strong>
+are not evenly divisable by the <em>local_work_size</em> values for each dimension.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="math-functions">1.13.2. Math Functions</h4>
+<div class="paragraph">
+<p>The built-in math functions are categorized into the following:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>A list of built-in functions that have scalar or vector argument
+versions, and,</p>
+</li>
+<li>
+<p>A list of built-in functions that only take scalar <code>float</code> arguments.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The vector versions of the math functions operate component-wise.
+The description is per-component.</p>
+</div>
+<div class="paragraph">
+<p>The built-in math functions are not affected by the prevailing rounding mode
+in the calling environment, and always return the same value as they would
+if called with the round to nearest even rounding mode.</p>
+</div>
+<div class="paragraph">
+<p>The <a href="#table-builtin-math">following table</a> describes the list of built-in
+math functions that can take scalar or vector arguments.
+We use the generic type name <code>gentype</code> to indicate that the function can
+take <code>float</code>, <code>float2</code>, <code>float3</code>, <code>float4</code>, <code>float8</code>, <code>float16</code>, <code>double</code>,
+<code>double2</code>, <code>double3</code>, <code>double4</code>, <code>double8</code> or <code>double16</code> as the type for the
+arguments.
+We use the generic type name <code>gentypef</code> to indicate that the function can
+take <code>float</code>, <code>float2</code>, <code>float3</code>, <code>float4</code>, <code>float8</code>, or <code>float16</code> as the
+type for the arguments.
+We use the generic type name <code>gentyped</code> to indicate that the function can
+take <code>double</code>, <code>double2</code>, <code>double3</code>, <code>double4</code>, <code>double8</code> or <code>double16</code> as
+the type for the arguments.
+For any specific use of a function, the actual type has to be the same for
+all arguments and the return type, unless otherwise specified.</p>
+</div>
+<table id="table-builtin-math" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 8. Scalar and Vector Argument Built-in Math Function Table</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Function</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>acos</strong>(gentype)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Arc cosine function. Returns an angle in radians.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>acosh</strong>(gentype)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Inverse hyperbolic cosine. Returns an angle in radians.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>acospi</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute <strong>acos</strong>(<em>x</em>) / π.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>asin</strong>(gentype)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Arc sine function. Returns an angle in radians.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>asinh</strong>(gentype)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Inverse hyperbolic sine. Returns an angle in radians.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>asinpi</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute <strong>asin</strong>(<em>x</em>) / π.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>atan</strong>(gentype <em>y_over_x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Arc tangent function. Returns an angle in radians.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>atan2</strong>(gentype <em>y</em>, gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Arc tangent of <em>y</em> / <em>x</em>. Returns an angle in radians.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>atanh</strong>(gentype)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Hyperbolic arc tangent. Returns an angle in radians.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>atanpi</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute <strong>atan</strong>(<em>x</em>) / π.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>atan2pi</strong>(gentype <em>y</em>, gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute <strong>atan2</strong>(<em>y</em>, <em>x</em>) / π.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>cbrt</strong>(gentype)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute cube-root.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>ceil</strong>(gentype)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Round to integral value using the round to positive infinity rounding
+      mode.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>copysign</strong>(gentype <em>x</em>, gentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <em>x</em> with its sign changed to match the sign of <em>y</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>cos</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute cosine, where <em>x</em> is an angle in radians.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>cosh</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute hyperbolic consine, where <em>x</em> is an angle in radians.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>cospi</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute <strong>cos</strong>(π <em>x</em>).</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>erfc</strong>(gentype)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Complementary error function.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>erf</strong>(gentype)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Error function encountered in integrating the
+      <a href="http://mathworld.wolfram.com/NormalDistribution.html"><em>normal
+      distribution</em></a>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>exp</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute the base-<em>e</em> exponential of <em>x</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>exp2</strong>(gentype)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Exponential base 2 function.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>exp10</strong>(gentype)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Exponential base 10 function.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>expm1</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute <em>e<sup>x</sup></em> - 1.0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>fabs</strong>(gentype)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute absolute value of a floating-point number.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>fdim</strong>(gentype <em>x</em>, gentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>x</em> - <em>y</em> if <em>x</em> &gt; <em>y</em>, +0 if <em>x</em> is less than or equal to y.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>floor</strong>(gentype)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Round to integral value using the round to negative infinity rounding
+      mode.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>fma</strong>(gentype <em>a</em>, gentype <em>b</em>, gentype <em>c</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the correctly rounded floating-point representation of the sum
+      of <em>c</em> with the infinitely precise product of <em>a</em> and <em>b</em>.
+      Rounding of intermediate products shall not occur.
+      Edge case behavior is per the IEEE 754-2008 standard.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>fmax</strong>(gentype <em>x</em>, gentype <em>y</em>)<br>
+  gentypef <strong>fmax</strong>(gentypef <em>x</em>, float <em>y</em>)<br>
+  gentyped <strong>fmax</strong>(gentyped <em>x</em>, double <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <em>y</em> if <em>x</em> &lt; <em>y</em>, otherwise it returns <em>x</em>.
+      If one argument is a NaN, <strong>fmax</strong>() returns the other argument.
+      If both arguments are NaNs, <strong>fmax</strong>() returns a NaN.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>fmin</strong><sup>29</sup>(gentype <em>x</em>, gentype <em>y</em>)<br>
+  gentypef <strong>fmin</strong>(gentypef <em>x</em>, float <em>y</em>)<br>
+  gentyped <strong>fmin</strong>(gentyped <em>x</em>, double <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <em>y</em> if <em>y</em> &lt; <em>x</em>, otherwise it returns <em>x</em>.
+      If one argument is a NaN, <strong>fmin</strong>() returns the other argument.
+      If both arguments are NaNs, <strong>fmin</strong>() returns a NaN.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>fmod</strong>(gentype <em>x</em>, gentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Modulus.
+      Returns <em>x</em> - <em>y</em> * <strong>trunc</strong>(<em>x</em>/<em>y</em>).</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>fract</strong>(gentype <em>x</em>, gentype <em>*iptr</em>)<sup>30</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <strong>fmin</strong>(<em>x</em> - <strong>floor</strong>(<em>x</em>), <code>0x1.fffffep-1f</code>).
+      <strong>floor</strong>(x) is returned in <em>iptr</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">float<em>n</em> <strong>frexp</strong>(float<em>n</em> <em>x</em>, int<em>n</em> *exp)<br>
+  float <strong>frexp</strong>(float <em>x</em>, int *exp)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Extract mantissa and exponent from <em>x</em>.
+      For each component the mantissa returned is a <code>float</code> with magnitude
+      in the interval [1/2, 1) or 0.
+      Each component of <em>x</em> equals mantissa returned * 2<em><sup>exp</sup></em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">double<em>n</em> <strong>frexp</strong>(double<em>n</em> <em>x</em>, int<em>n</em> *exp)<br>
+  double <strong>frexp</strong>(double <em>x</em>, int *exp)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Extract mantissa and exponent from <em>x</em>.
+      For each component the mantissa returned is a <code>float</code> with magnitude
+      in the interval [1/2, 1) or 0.
+      Each component of <em>x</em> equals mantissa returned * 2<em><sup>exp</sup></em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>hypot</strong>(gentype <em>x</em>, gentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute the value of the square root of <em>x</em><sup>2</sup>+ <em>y</em><sup>2</sup> without
+      undue overflow or underflow.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int<em>n</em> <strong>ilogb</strong>(float<em>n</em> <em>x</em>)<br>
+  int <strong>ilogb</strong>(float <em>x</em>)<br>
+  int<em>n</em> <strong>ilogb</strong>(double<em>n</em> <em>x</em>)<br>
+  int <strong>ilogb</strong>(double <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the exponent as an integer value.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">float<em>n</em> <strong>ldexp</strong>(float<em>n</em> <em>x</em>, int<em>n</em> <em>k</em>)<br>
+  float<em>n</em> <strong>ldexp</strong>(float<em>n</em> <em>x</em>, int <em>k</em>)<br>
+  float <strong>ldexp</strong>(float <em>x</em>, int <em>k</em>)<br>
+  double<em>n</em> <strong>ldexp</strong>(double<em>n</em> <em>x</em>, int<em>n</em> <em>k</em>)<br>
+  double<em>n</em> <strong>ldexp</strong>(double<em>n</em> <em>x</em>, int <em>k</em>)<br>
+  double <strong>ldexp</strong>(double <em>x</em>, int <em>k</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Multiply <em>x</em> by 2 to the power <em>k</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>lgamma</strong>(gentype <em>x</em>)<br>
+  float<em>n</em> <strong>lgamma_r</strong>(float<em>n</em> <em>x</em>, int<em>n</em> *<em>signp</em>)<br>
+  float <strong>lgamma_r</strong>(float <em>x</em>, int *<em>signp</em>)<br>
+  double<em>n</em> <strong>lgamma_r</strong>(double<em>n</em> <em>x</em>, int<em>n</em> *<em>signp</em>)<br>
+  double <strong>lgamma_r</strong>(double <em>x</em>, int *<em>signp</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Log gamma function.
+      Returns the natural logarithm of the absolute value of the gamma
+      function.
+      The sign of the gamma function is returned in the <em>signp</em> argument of
+      <strong>lgamma_r</strong>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>log</strong>(gentype)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute natural logarithm.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>log2</strong>(gentype)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute a base 2 logarithm.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>log10</strong>(gentype)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute a base 10 logarithm.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>log1p</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute log<sub>e</sub>(1.0 + <em>x</em>).</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>logb</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute the exponent of <em>x</em>, which is the integral part of
+      log<em><sub>r</sub></em>(|<em>x</em>|).</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>mad</strong>(gentype <em>a</em>, gentype <em>b</em>, gentype <em>c</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mad</strong> computes <em>a</em> * <em>b</em> + <em>c</em>.
+    The function may compute <em>a</em> * <em>b</em> + <em>c</em> with reduced accuracy
+    in the embedded profile.  See the SPIR-V OpenCL environment specification
+    for details. On some hardware the mad instruction may provide better
+    performance than expanded computation of <em>a</em> * <em>b</em> + <em>c</em>.<sup>31</sup></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>maxmag</strong>(gentype <em>x</em>, gentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <em>x</em> if |<em>x</em>| &gt; |<em>y</em>|, <em>y</em> if |<em>y</em>| &gt; |<em>x</em>|, otherwise
+      <strong>fmax</strong>(<em>x</em>, <em>y</em>).</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>minmag</strong>(gentype <em>x</em>, gentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <em>x</em> if |<em>x</em>| &lt; |<em>y</em>|, <em>y</em> if |<em>y</em>| &lt; |<em>x</em>|, otherwise
+      <strong>fmin</strong>(<em>x</em>, <em>y</em>).</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>modf</strong>(gentype <em>x</em>, gentype *<em>iptr</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Decompose a floating-point number.
+      The <strong>modf</strong> function breaks the argument <em>x</em> into integral and
+      fractional parts, each of which has the same sign as the argument.
+      It stores the integral part in the object pointed to by <em>iptr</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">float<em>n</em> <strong>nan</strong>(uint<em>n</em> <em>nancode</em>)<br>
+  float <strong>nan</strong>(uint <em>nancode</em>)<br>
+  double<em>n</em> <strong>nan</strong>(ulong<em>n</em> <em>nancode</em>)<br>
+  double <strong>nan</strong>(ulong <em>nancode</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns a quiet NaN.
+      The <em>nancode</em> may be placed in the significand of the resulting NaN.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>nextafter</strong>(gentype <em>x</em>, gentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Computes the next representable single-precision floating-point value
+      following <em>x</em> in the direction of <em>y</em>.
+      Thus, if <em>y</em> is less than <em>x</em>, <strong>nextafter</strong>() returns the largest
+      representable floating-point number less than <em>x</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>pow</strong>(gentype <em>x</em>, gentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute <em>x</em> to the power <em>y</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">float<em>n</em> <strong>pown</strong>(float<em>n</em> <em>x</em>, int<em>n</em> <em>y</em>)<br>
+  float <strong>pown</strong>(float <em>x</em>, int <em>y</em>)<br>
+  double<em>n</em> <strong>pown</strong>(double<em>n</em> <em>x</em>, int<em>n</em> <em>y</em>)<br>
+  double <strong>pown</strong>(double <em>x</em>, int <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute <em>x</em> to the power <em>y</em>, where <em>y</em> is an integer.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>powr</strong>(gentype <em>x</em>, gentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute <em>x</em> to the power <em>y</em>, where <em>x</em> is &gt;= 0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>remainder</strong>(gentype <em>x</em>, gentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute the value <em>r</em> such that <em>r</em> = <em>x</em> - <em>n</em>*<em>y</em>, where <em>n</em> is the
+      integer nearest the exact value of <em>x</em>/<em>y</em>.
+      If there are two integers closest to <em>x</em>/<em>y</em>, <em>n</em> shall be the even
+      one.
+      If <em>r</em> is zero, it is given the same sign as <em>x</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">float<em>n</em> <strong>remquo</strong>(float<em>n</em> <em>x</em>, float<em>n</em> <em>y</em>, int<em>n</em> *<em>quo</em>)<br>
+  float <strong>remquo</strong>(float <em>x</em>, float <em>y</em>, int *<em>quo</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The <strong>remquo</strong> function computes the value r such that <em>r</em> = <em>x</em> -
+      <em>k</em>*<em>y</em>, where <em>k</em> is the integer nearest the exact value of <em>x</em>/<em>y</em>.
+      If there are two integers closest to <em>x</em>/<em>y</em>, <em>k</em> shall be the even
+      one.
+      If <em>r</em> is zero, it is given the same sign as <em>x</em>.
+      This is the same value that is returned by the <strong>remainder</strong> function.
+      <strong>remquo</strong> also calculates the lower seven bits of the integral quotient
+      <em>x</em>/<em>y</em>, and gives that value the same sign as <em>x</em>/<em>y</em>.
+      It stores this signed value in the object pointed to by <em>quo</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">double<em>n</em> <strong>remquo</strong>(double<em>n</em> <em>x</em>, double<em>n</em> <em>y</em>, int<em>n</em> *<em>quo</em>)<br>
+  double <strong>remquo</strong>(double <em>x</em>, double <em>y</em>, int *<em>quo</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The <strong>remquo</strong> function computes the value r such that <em>r</em> = <em>x</em> -
+      <em>k</em>*<em>y</em>, where <em>k</em> is the integer nearest the exact value of <em>x</em>/<em>y</em>.
+      If there are two integers closest to <em>x</em>/<em>y</em>, <em>k</em> shall be the even
+      one.
+      If <em>r</em> is zero, it is given the same sign as <em>x</em>.
+      This is the same value that is returned by the <strong>remainder</strong> function.
+      <strong>remquo</strong> also calculates the lower seven bits of the integral quotient
+      <em>x</em>/<em>y</em>, and gives that value the same sign as <em>x</em>/<em>y</em>.
+      It stores this signed value in the object pointed to by <em>quo</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>rint</strong>(gentype)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Round to integral value (using round to nearest even rounding mode) in
+      floating-point format.
+      Refer to section 7.1 for description of rounding modes.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">float<em>n</em> <strong>rootn</strong>(float<em>n</em> <em>x</em>, int<em>n</em> <em>y</em>)<br>
+  float <strong>rootn</strong>(float <em>x</em>, int <em>y</em>)<br>
+  double<em>n</em> <strong>rootn</strong>(double<em>n</em> <em>x</em>, int<em>n</em> <em>y</em>)<br>
+  double<em>n</em> <strong>rootn</strong>(double <em>x</em>, int <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute <em>x</em> to the power 1/<em>y</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>round</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the integral value nearest to <em>x</em> rounding halfway cases away
+      from zero, regardless of the current rounding direction.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>rsqrt</strong>(gentype)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute inverse square root.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>sin</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute sine, where <em>x</em> is an angle in radians.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>sincos</strong>(gentype <em>x</em>, gentype *<em>cosval</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute sine and cosine of x.
+      The computed sine is the return value and computed cosine is returned
+      in <em>cosval</em>, where <em>x</em> is an angle in radians.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>sinh</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute hyperbolic sine, where <em>x</em> is an angle in radians</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>sinpi</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute <strong>sin</strong>(π <em>x</em>).</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>sqrt</strong>(gentype)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute square root.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>tan</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute tangent, where <em>x</em> is an angle in radians.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>tanh</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute hyperbolic tangent, where <em>x</em> is an angle in radians.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>tanpi</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute <strong>tan</strong>(π <em>x</em>).</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>tgamma</strong>(gentype)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute the gamma function.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>trunc</strong>(gentype)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Round to integral value using the round to zero rounding mode.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>[29] <strong>fmin</strong> and <strong>fmax</strong> behave as defined by C99 and may not match the IEEE
+754-2008 definition for <strong>minNum</strong> and <strong>maxNum</strong> with regard to signaling NaNs.
+Specifically, signaling NaNs may behave as quiet NaNs.</p>
+</div>
+<div class="paragraph">
+<p>[30] The <strong>min</strong>() operator is there to prevent <strong>fract</strong>(-small) from returning
+1.0.
+It returns the largest positive floating-point number less than 1.0.</p>
+</div>
+<div class="paragraph">
+<p>[31] The user is cautioned that for some usages, e.g. <strong>mad</strong>(a, b, -a*b), the
+definition of <strong>mad</strong>() is loose enough in the embedded profile that almost any result is allowed from
+<strong>mad</strong>() for some values of a and b.</p>
+</div>
+<div class="paragraph">
+<p>The following table describes the following functions:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>A subset of functions from <a href="#table-builtin-math">Scalar and Vector Argument Built-in Math Function Table</a> that are defined with
+the half_ prefix .
+These functions are implemented with a minimum of 10-bits of accuracy,
+i.e. an ULP value &lt;= 8192 ulp.</p>
+</li>
+<li>
+<p>A subset of functions from <a href="#table-builtin-math">Scalar and Vector Argument Built-in Math Function Table</a> that are defined with
+the native_ prefix.
+These functions may map to one or more native device instructions and
+will typically have better performance compared to the corresponding
+functions (without the <code>native_</code> prefix) described in
+<a href="#table-builtin-math">Scalar and Vector Argument Built-in Math Function Table</a>.
+The accuracy (and in some cases the input range(s)) of these functions
+is implementation-defined.</p>
+</li>
+<li>
+<p><code>half_</code> and <code>native_</code> functions for following basic operations:
+divide and reciprocal.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>We use the generic type name <code>gentype</code> to indicate that the functions in the
+following table can take <code>float</code>, <code>float2</code>, <code>float3</code>, <code>float4</code>, <code>float8</code> or
+<code>float16</code> as the type for the arguments.</p>
+</div>
+<table id="table-builtin-half-native-math" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 9. Scalar and Vector Argument Built-in <em>half</em> and <em>native</em> Math Functions</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Function</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>half_cos</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute cosine.
+      <em>x</em> is an angle in radians, and must be in the range [-2<sup>16</sup>, +2<sup>16</sup>].</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>half_divide</strong>(gentype <em>x</em>, gentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute <em>x</em> / <em>y</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>half_exp</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute the base-<em>e</em> exponential of <em>x</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>half_exp2</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute the base- 2 exponential of <em>x</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>half_exp10</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute the base- 10 exponential of <em>x</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>half_log</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute natural logarithm.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>half_log2</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute a base 2 logarithm.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>half_log10</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute a base 10 logarithm.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>half_powr</strong>(gentype <em>x</em>, gentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute <em>x</em> to the power <em>y</em>, where <em>x</em> is &gt;= 0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>half_recip</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute reciprocal.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>half_rsqrt</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute inverse square root.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>half_sin</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute sine.
+      <em>x</em> is an angle in radians, and must be in the range [-2<sup>16</sup>, +2<sup>16</sup>].</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>half_sqrt</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute square root.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>half_tan</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute tangent.
+      <em>x</em> is an angle in radians, and must be in the range [-2<sup>16</sup>, +2<sup>16</sup>].</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>native_cos</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute cosine over an implementation-defined range, where <em>x</em> is an
+      angle in radians.
+      The maximum error is implementation-defined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>native_divide</strong>(gentype <em>x</em>, gentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute <em>x</em> / <em>y</em> over an implementation-defined range.
+      The maximum error is implementation-defined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>native_exp</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute the base-<em>e</em> exponential of <em>x</em> over an
+      implementation-defined range.
+      The maximum error is implementation-defined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>native_exp2</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute the base-2 exponential of <em>x</em> over an implementation-defined
+      range.
+      The maximum error is implementation-defined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>native_exp10</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute the base-10 exponential of <em>x</em> over an implementation-defined
+      range.
+      The maximum error is implementation-defined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>native_log</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute natural logarithm over an implementation-defined range.
+      The maximum error is implementation-defined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>native_log2</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute a base 2 logarithm over an
+      implementation-defined range.
+      The maximum error is implementation-defined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>native_log10</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute a base 10 logarithm over
+      an implementation-defined range.
+      The maximum error is implementation-defined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>native_powr</strong>(gentype <em>x</em>, gentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute <em>x</em> to the power <em>y</em>, where <em>x</em> is &gt;= 0.
+      The range of <em>x</em> and <em>y</em> are implementation-defined.
+      The maximum error is implementation-defined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>native_recip</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute reciprocal over an implementation-defined range.
+      The maximum error is implementation-defined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>native_rsqrt</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute inverse square root over an implementation-defined range.
+      The maximum error is implementation-defined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>native_sin</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute sine over an implementation-defined range, where <em>x</em> is an
+      angle in radians.
+      The maximum error is implementation-defined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>native_sqrt</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute square root over an implementation-defined range.
+      The maximum error is implementation-defined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>native_tan</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute tangent over an implementation-defined range, where <em>x</em> is an
+      angle in radians.
+      The maximum error is implementation-defined.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>Support for denormal values is optional for <strong>half_</strong> functions.
+The <strong>half_</strong> functions may return any result allowed by
+<a href="#edge-case-behavior-in-flush-to-zero-mode">Edge Case Behavior</a>, even when
+<code>-cl-denorms-are-zero</code> (see <a href="#opencl-spec">section 5.8.4.2 of the OpenCL
+Specification</a>) is not in force.
+Support for denormal values is implementation-defined for <strong>native_</strong>
+functions.</p>
+</div>
+<div class="paragraph">
+<p>The following symbolic constants are available.
+Their values are of type <code>float</code> and are accurate within the precision of a
+single precision floating-point number.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Constant Name</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>MAXFLOAT</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of maximum non-infinite single-precision floating-point number.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>HUGE_VALF</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A positive <code>float</code> constant expression.
+      <code>HUGE_VALF</code> evaluates to +infinity.
+      Used as an error value returned by the built-in math functions.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>INFINITY</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A constant expression of type <code>float</code> representing positive or
+      unsigned infinity.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>NAN</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A constant expression of type <code>float</code> representing a quiet NaN.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>If double precision is supported by the device, the following symbolic
+constants will also be available:</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Constant Name</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>HUGE_VAL</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A positive double constant expression.
+      <code>HUGE_VAL</code> evaluates to +infinity.
+      Used as an error value returned by the built-in math functions.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="sect4">
+<h5 id="floating-point-macros-and-pragmas">Floating-point macros and pragmas</h5>
+<div class="paragraph">
+<p>The <code>FP_CONTRACT</code> pragma can be used to allow (if the state is on) or
+disallow (if the state is off) the implementation to contract expressions.
+Each pragma can occur either outside external declarations or preceding all
+explicit declarations and statements inside a compound statement.
+When outside external declarations, the pragma takes effect from its
+occurrence until another <code>FP_CONTRACT</code> pragma is encountered, or until the
+end of the translation unit.
+When inside a compound statement, the pragma takes effect from its
+occurrence until another <code>FP_CONTRACT</code> pragma is encountered (including
+within a nested compound statement), or until the end of the compound
+statement; at the end of a compound statement the state for the pragma is
+restored to its condition just before the compound statement.
+If this pragma is used in any other context, the behavior is undefined.</p>
+</div>
+<div class="paragraph">
+<p>The pragma definition to set <code>FP_CONTRACT</code> is:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="comment">// on-off-switch is one of ON, OFF, or DEFAULT.</span>
+<span class="comment">// The DEFAULT value is ON.</span>
+<span class="preprocessor">#pragma</span> OPENCL FP_CONTRACT on-off-<span class="keyword">switch</span></code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The <code>FP_FAST_FMAF</code> macro indicates whether the <strong>fma</strong> function is fast
+compared with direct code for single precision floating-point.
+If defined, the <code>FP_FAST_FMAF</code> macro shall indicate that the <strong>fma</strong> function
+generally executes about as fast as, or faster than, a multiply and an add
+of <code>float</code> operands.</p>
+</div>
+<div class="paragraph">
+<p>The macro names given in the following list must use the values specified.
+These constant expressions are suitable for use in <code>#if</code> preprocessing
+directives.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="preprocessor">#define</span> FLT_DIG         <span class="integer">6</span>
+<span class="preprocessor">#define</span> FLT_MANT_DIG    <span class="integer">24</span>
+<span class="preprocessor">#define</span> FLT_MAX_10_EXP  +<span class="integer">38</span>
+<span class="preprocessor">#define</span> FLT_MAX_EXP     +<span class="integer">128</span>
+<span class="preprocessor">#define</span> FLT_MIN_10_EXP  -<span class="integer">37</span>
+<span class="preprocessor">#define</span> FLT_MIN_EXP     -<span class="integer">125</span>
+<span class="preprocessor">#define</span> FLT_RADIX       <span class="integer">2</span>
+<span class="preprocessor">#define</span> FLT_MAX         <span class="hex">0x1</span>.fffffep127f
+<span class="preprocessor">#define</span> FLT_MIN         <span class="hex">0x1</span><span class="float">.0</span>p-<span class="integer">12</span><span class="float">6f</span>
+<span class="preprocessor">#define</span> FLT_EPSILON     <span class="hex">0x1</span><span class="float">.0</span>p-<span class="integer">2</span><span class="float">3f</span></code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The following table describes the built-in macro names given above in the
+OpenCL C programming language and the corresponding macro names available to
+the application.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Macro in OpenCL Language</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Macro for application</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>FLT_DIG</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_FLT_DIG</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>FLT_MANT_DIG</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_FLT_MANT_DIG</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>FLT_MAX_10_EXP</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_FLT_MAX_10_EXP</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>FLT_MAX_EXP</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_FLT_MAX_EXP</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>FLT_MIN_10_EXP</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_FLT_MIN_10_EXP</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>FLT_MIN_EXP</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_FLT_MIN_EXP</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>FLT_RADIX</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_FLT_RADIX</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>FLT_MAX</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_FLT_MAX</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>FLT_MIN</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_FLT_MIN</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>FLT_EPSILSON</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_FLT_EPSILON</code></p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>The following macros shall expand to integer constant expressions whose
+values are returned by <strong>ilogb</strong>(<em>x</em>) if <em>x</em> is zero or NaN, respectively.
+The value of <code>FP_ILOGB0</code> shall be either <code>INT_MIN</code> or <code>-INT_MAX</code>.
+The value of <code>FP_ILOGBNAN</code> shall be either <code>INT_MAX</code> or <code>INT_MIN</code>.</p>
+</div>
+<div class="paragraph">
+<p>The following constants are also available.
+They are of type <code>float</code> and are accurate within the precision of the
+<code>float</code> type.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Constant</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>M_E_F</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of <em>e</em></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>M_LOG2E_F</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of log<sub>2</sub>e</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>M_LOG10E_F</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of log<sub>10</sub>e</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>M_LN2_F</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of log<sub>e</sub>2</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>M_LN10_F</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of log<sub>e</sub>10</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>M_PI_F</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of π</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>M_PI_2_F</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of π / 2</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>M_PI_4_F</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of π / 4</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>M_1_PI_F</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of 1 / π</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>M_2_PI_F</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of 2 / π</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>M_2_SQRTPI_F</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of 2 / √π</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>M_SQRT2_F</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of √2</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>M_SQRT1_2_F</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of 1 / √2</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>If double precision is supported by the device, the following macros and
+constants are also available:</p>
+</div>
+<div class="paragraph">
+<p>The <code>FP_FAST_FMA</code> macro indicates whether the <strong>fma</strong>() family of functions
+are fast compared with direct code for double precision floating-point.
+If defined, the <code>FP_FAST_FMA</code> macro shall indicate that the <strong>fma</strong>() function
+generally executes about as fast as, or faster than, a multiply and an add
+of <code>double</code> operands</p>
+</div>
+<div class="paragraph">
+<p>The macro names given in the following list must use the values specified.
+These constant expressions are suitable for use in <code>#if</code> preprocessing
+directives.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="preprocessor">#define</span> DBL_DIG         <span class="integer">15</span>
+<span class="preprocessor">#define</span> DBL_MANT_DIG    <span class="integer">53</span>
+<span class="preprocessor">#define</span> DBL_MAX_10_EXP  +<span class="integer">308</span>
+<span class="preprocessor">#define</span> DBL_MAX_EXP     +<span class="integer">1024</span>
+<span class="preprocessor">#define</span> DBL_MIN_10_EXP  -<span class="integer">307</span>
+<span class="preprocessor">#define</span> DBL_MIN_EXP     -<span class="integer">1021</span>
+<span class="preprocessor">#define</span> DBL_MAX         <span class="hex">0x1</span>.fffffffffffffp1023
+<span class="preprocessor">#define</span> DBL_MIN         <span class="hex">0x1</span><span class="float">.0</span>p-<span class="integer">1022</span>
+<span class="preprocessor">#define</span> DBL_EPSILON     <span class="hex">0x1</span><span class="float">.0</span>p-<span class="integer">52</span></code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The following table describes the built-in macro names given above in the
+OpenCL C programming language and the corresponding macro names available to
+the application.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Macro in OpenCL Language</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Macro for application</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>DBL_DIG</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_DBL_DIG</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>DBL_MANT_DIG</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_DBL_MANT_DIG</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>DBL_MAX_10_EXP</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_DBL_MAX_10_EXP</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>DBL_MAX_EXP</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_DBL_MAX_EXP</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>DBL_MIN_10_EXP</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_DBL_MIN_10_EXP</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>DBL_MIN_EXP</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_DBL_MIN_EXP</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>DBL_MAX</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_DBL_MAX</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>DBL_MIN</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_DBL_MIN</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>DBL_EPSILSON</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_DBL_EPSILON</code></p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>The following constants are also available.
+They are of type <code>double</code> and are accurate within the precision of the
+double type.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Constant</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>M_E</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of <em>e</em></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>M_LOG2E</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of log<sub>2</sub>e</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>M_LOG10E</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of log<sub>10</sub>e</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>M_LN2</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of log<sub>e</sub>2</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>M_LN10</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of log<sub>e</sub>10</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>M_PI</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of π</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>M_PI_2</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of π / 2</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>M_PI_4</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of π / 4</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>M_1_PI</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of 1 / π</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>M_2_PI</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of 2 / π</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>M_2_SQRTPI</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of 2 / √π</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>M_SQRT2</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of √2</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>M_SQRT1_2</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of 1 / √2</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+<div class="sect3">
+<h4 id="integer-functions">1.13.3. Integer Functions</h4>
+<div class="paragraph">
+<p>The following table describes the built-in integer functions that take
+scalar or vector arguments.
+The vector versions of the integer functions operate component-wise.
+The description is per-component.</p>
+</div>
+<div class="paragraph">
+<p>We use the generic type name <code>gentype</code> to indicate that the function can
+take <code>char</code>, <code>char{2|3|4|8|16}</code>, <code>uchar</code>, <code>uchar{2|3|4|8|16}</code>, <code>short</code>,
+<code>short{2|3|4|8|16}</code>, <code>ushort</code>, <code>ushort{2|3|4|8|16}</code>, <code>int</code>,
+<code>int{2|3|4|8|16}</code>, <code>uint</code>, <code>uint{2|3|4|8|16}</code>, <code>long</code>, <code>long{2|3|4|8|16}
+ulong</code>, or <code>ulong{2|3|4|8|16}</code> as the type for the arguments.
+We use the generic type name <code>ugentype</code> to refer to unsigned versions of
+<code>gentype</code>.
+For example, if <code>gentype</code> is <code>char4</code>, <code>ugentype</code> is <code>uchar4</code>.
+We also use the generic type name <code>sgentype</code> to indicate that the function
+can take a scalar data type, i.e. <code>char</code>, <code>uchar</code>, <code>short</code>, <code>ushort</code>, <code>int</code>,
+<code>uint</code>, <code>long</code>, or <code>ulong</code>, as the type for the arguments.
+For built-in integer functions that take <code>gentype</code> and <code>sgentype</code> arguments,
+the <code>gentype</code> argument must be a vector or scalar version of the <code>sgentype</code>
+argument.
+For example, if <code>sgentype</code> is <code>uchar</code>, <code>gentype</code> must be <code>uchar</code> or
+<code>uchar{2|3|4|8|16}</code>.
+For vector versions, <code>sgentype</code> is implicitly widened to <code>gentype</code> as
+described for <a href="#operators-arithmetic">arithmetic operators</a>.</p>
+</div>
+<div class="paragraph">
+<p>For any specific use of a function, the actual type has to be the same for
+all arguments and the return type unless otherwise specified.</p>
+</div>
+<table id="table-builtin-functions" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 10. Scalar and Vector Integer Argument Built-in Functions</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Function</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">ugentype <strong>abs</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns |x|.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">ugentype <strong>abs_diff</strong>(gentype <em>x</em>, gentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns |x - y| without modulo overflow.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>add_sat</strong>(gentype <em>x</em>, gentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <em>x</em> + <em>y</em> and saturates the result.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>hadd</strong>(gentype <em>x</em>, gentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns (<em>x</em> + <em>y</em>) &gt;&gt; 1.
+      The intermediate sum does not modulo overflow.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>rhadd</strong>(gentype <em>x</em>, gentype <em>y</em>)<sup>32</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns (<em>x</em> + <em>y</em> + 1) &gt;&gt; 1.
+      The intermediate sum does not modulo overflow.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>clamp</strong>(gentype <em>x</em>, gentype <em>minval</em>, gentype <em>maxval</em>)<br>
+  gentype <strong>clamp</strong>(gentype <em>x</em>, sgentype <em>minval</em>, sgentype <em>maxval</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <strong>min</strong>(<strong>max</strong>(<em>x</em>, <em>minval</em>), <em>maxval</em>).
+      Results are undefined if <em>minval</em> &gt; <em>maxval</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>clz</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the number of leading 0-bits in <em>x</em>, starting at the most
+      significant bit position.
+      If <em>x</em> is 0, returns the size in bits of the type of <em>x</em> or component
+      type of <em>x</em>, if <em>x</em> is a vector.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>ctz</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the count of trailing 0-bits in <em>x</em>.
+      If <em>x</em> is 0, returns the size in bits of the type of <em>x</em> or component
+      type of <em>x</em>, if <em>x</em> is a vector.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>mad_hi</strong>(gentype <em>a</em>, gentype <em>b</em>, gentype <em>c</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <strong>mul_hi</strong>(<em>a</em>, <em>b</em>) + <em>c</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>mad_sat</strong>(gentype <em>a</em>, gentype <em>b</em>, gentype <em>c</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <em>a</em> * <em>b</em> + <em>c</em> and saturates the result.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>max</strong>(gentype <em>x</em>, gentype <em>y</em>)<br>
+  gentype <strong>max</strong>(gentype <em>x</em>, sgentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <em>y</em> if <em>x</em> &lt; <em>y</em>, otherwise it returns <em>x</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>min</strong>(gentype <em>x</em>, gentype <em>y</em>)<br>
+  gentype <strong>min</strong>(gentype <em>x</em>, sgentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <em>y</em> if <em>y</em> &lt; <em>x</em>, otherwise it returns <em>x</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>mul_hi</strong>(gentype <em>x</em>, gentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Computes <em>x</em> * <em>y</em> and returns the high half of the product of <em>x</em> and
+      <em>y</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>rotate</strong>(gentype <em>v</em>, gentype <em>i</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">For each element in <em>v</em>, the bits are shifted left by the number of
+      bits given by the corresponding element in <em>i</em> (subject to the usual
+      <a href="#operators-shift">shift modulo rules</a>).
+      Bits shifted off the left side of the element are shifted back in from
+      the right.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>sub_sat</strong>(gentype <em>x</em>, gentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <em>x</em> - <em>y</em> and saturates the result.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">short <strong>upsample</strong>(char <em>hi</em>, uchar <em>lo</em>)<br>
+  ushort <strong>upsample</strong>(uchar <em>hi</em>, uchar <em>lo</em>)<br>
+  short<em>n</em> <strong>upsample</strong>(char<em>n</em> <em>hi</em>, uchar<em>n</em> <em>lo</em>)<br>
+  ushort<em>n</em> <strong>upsample</strong>(uchar<em>n</em> <em>hi</em>, uchar<em>n</em> <em>lo</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>result</em>[i] = ((short)<em>hi</em>[i] &lt;&lt; 8) | <em>lo</em>[i]<br>
+      <em>result</em>[i] = ((ushort)<em>hi</em>[i] &lt;&lt; 8) | <em>lo</em>[i]<br></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>upsample</strong>(short <em>hi</em>, ushort <em>lo</em>)<br>
+  uint <strong>upsample</strong>(ushort <em>hi</em>, ushort <em>lo</em>)<br>
+  int<em>n</em> <strong>upsample</strong>(short<em>n</em> <em>hi</em>, ushort<em>n</em> <em>lo</em>)<br>
+  uint<em>n</em> <strong>upsample</strong>(ushort<em>n</em> <em>hi</em>, ushort<em>n</em> <em>lo</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>result</em>[i] = ((int)<em>hi</em>[i] &lt;&lt; 16) | <em>lo</em>[i]<br>
+      <em>result</em>[i] = ((uint)<em>hi</em>[i] &lt;&lt; 16) | <em>lo</em>[i]<br></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">long <strong>upsample</strong>(int <em>hi</em>, uint <em>lo</em>)<br>
+  ulong <strong>upsample</strong>(uint <em>hi</em>, uint <em>lo</em>)<br>
+  long<em>n</em> <strong>upsample</strong>(int<em>n</em> <em>hi</em>, uint<em>n</em> <em>lo</em>)<br>
+  ulong<em>n</em> <strong>upsample</strong>(uint<em>n</em> <em>hi</em>, uint<em>n</em> <em>lo</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>result</em>[i] = ((long)<em>hi</em>[i] &lt;&lt; 32) | <em>lo</em>[i]<br>
+      <em>result</em>[i] = ((ulong)<em>hi</em>[i] &lt;&lt; 32) | <em>lo</em>[i]</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>popcount</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the number of non-zero bits in <em>x</em>.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>[32] Frequently vector operations need n + 1 bits temporarily to calculate a
+result.
+The <strong>rhadd</strong> instruction gives you an extra bit without needing to upsample
+and downsample.
+This can be a profound performance win.</p>
+</div>
+<div class="paragraph">
+<p>The following table describes fast integer functions that can be used for
+optimizing performance of kernels.
+We use the generic type name <code>gentype</code> to indicate that the function can
+take <code>int</code>, <code>int2</code>, <code>int3</code>, <code>int4</code>, <code>int8</code>, <code>int16</code>, <code>uint</code>, <code>uint2</code>,
+<code>uint3</code>, <code>uint4</code>, <code>uint8</code> or <code>uint16</code> as the type for the arguments.</p>
+</div>
+<table id="table-builtin-fast-integer" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 11. Fast Integer Built-in Functions</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Function</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>mad24</strong>(gentype <em>x</em>, gentype <em>y</em>, gentype z)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Multipy two 24-bit integer values <em>x</em> and <em>y</em> and add the 32-bit
+      integer result to the 32-bit integer <em>z</em>.
+      Refer to definition of <strong>mul24</strong> to see how the 24-bit integer
+      multiplication is performed.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>mul24</strong>(gentype <em>x</em>, gentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Multiply two 24-bit integer values <em>x</em> and <em>y</em>.
+      <em>x</em> and <em>y</em> are 32-bit integers but only the low 24-bits are used to
+      perform the multiplication.
+      <strong>mul24</strong> should only be used when values in <em>x</em> and <em>y</em> are in the
+      range [-2<sup>23</sup>, 2<sup>23</sup>-1] if <em>x</em> and <em>y</em> are signed integers and in the
+      range [0, 2<sup>24</sup>-1] if <em>x</em> and <em>y</em> are unsigned integers.
+      If <em>x</em> and <em>y</em> are not in this range, the multiplication result is
+      implementation-defined.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>The macro names given in the following list must use the values specified.
+The values shall all be constant expressions suitable for use in <code>#if</code>
+preprocessing directives.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="preprocessor">#define</span> CHAR_BIT        <span class="integer">8</span>
+<span class="preprocessor">#define</span> CHAR_MAX        SCHAR_MAX
+<span class="preprocessor">#define</span> CHAR_MIN        SCHAR_MIN
+<span class="preprocessor">#define</span> INT_MAX         <span class="integer">2147483647</span>
+<span class="preprocessor">#define</span> INT_MIN         (-<span class="integer">2147483647</span> - <span class="integer">1</span>)
+<span class="preprocessor">#define</span> LONG_MAX        <span class="hex">0x7fffffffffffffff</span>L
+<span class="preprocessor">#define</span> LONG_MIN        (-<span class="hex">0x7fffffffffffffff</span>L - <span class="integer">1</span>)
+<span class="preprocessor">#define</span> SCHAR_MAX       <span class="integer">127</span>
+<span class="preprocessor">#define</span> SCHAR_MIN       (-<span class="integer">127</span> - <span class="integer">1</span>)
+<span class="preprocessor">#define</span> SHRT_MAX        <span class="integer">32767</span>
+<span class="preprocessor">#define</span> SHRT_MIN        (-<span class="integer">32767</span> - <span class="integer">1</span>)
+<span class="preprocessor">#define</span> UCHAR_MAX       <span class="integer">255</span>
+<span class="preprocessor">#define</span> USHRT_MAX       <span class="integer">65535</span>
+<span class="preprocessor">#define</span> UINT_MAX        <span class="hex">0xffffffff</span>
+<span class="preprocessor">#define</span> ULONG_MAX       <span class="hex">0xffffffffffffffff</span>UL</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The following table describes the built-in macro names given above in the
+OpenCL C programming language and the corresponding macro names available to
+the application.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Macro in OpenCL Language</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Macro for application</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CHAR_BIT</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_CHAR_BIT</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CHAR_MAX</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_CHAR_MAX</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CHAR_MIN</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_CHAR_MIN</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>INT_MAX</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_INT_MAX</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>INT_MIN</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_INT_MIN</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>LONG_MAX</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_LONG_MAX</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>LONG_MIN</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_LONG_MIN</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>SCHAR_MAX</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_SCHAR_MAX</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>SCHAR_MIN</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_SCHAR_MIN</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>SHRT_MAX</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_SHRT_MAX</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>SHRT_MIN</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_SHRT_MIN</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>UCHAR_MAX</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_UCHAR_MAX</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>USHRT_MAX</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_USHRT_MAX</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>UINT_MAX</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_UINT_MAX</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>ULONG_MAX</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_ULONG_MAX</code></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="common-functions">1.13.4. Common Functions<sup>33</sup></h4>
+<div class="paragraph">
+<p>[33] The <strong>mix</strong> and <strong>smoothstep</strong> functions can be implemented using
+contractions such as <strong>mad</strong> or <strong>fma</strong>.</p>
+</div>
+<div class="paragraph">
+<p>The following table describes the list of built-in common functions.
+These all operate component-wise.
+The description is per-component.
+We use the generic type name <code>gentype</code> to indicate that the function can
+take <code>float</code>, <code>float2</code>, <code>float3</code>, <code>float4</code>, <code>float8</code>, <code>float16</code>, <code>double</code>,
+<code>double2</code>, <code>double3</code>, <code>double4</code>, <code>double8</code> or <code>double16</code> as the type for the
+arguments.
+We use the generic type name <code>gentypef</code> to indicate that the function can
+take <code>float</code>, <code>float2</code>, <code>float3</code>, <code>float4</code>, <code>float8</code>, or <code>float16</code> as the
+type for the arguments.
+We use the generic type name <code>gentyped</code> to indicate that the function can
+take <code>double</code>, <code>double2</code>, <code>double3</code>, <code>double4</code>, <code>double8</code> or <code>double16</code> as
+the type for the arguments.</p>
+</div>
+<div class="paragraph">
+<p>The built-in common functions are implemented using the round to nearest
+even rounding mode.</p>
+</div>
+<table id="table-builtin-common" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 12. Scalar and Vector Argument Built-in Common Function Table</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Function</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>clamp</strong>(gentype <em>x</em>, gentype <em>minval</em>, gentype <em>maxval</em>)<br>
+  gentypef <strong>clamp</strong>(gentypef <em>x</em>, float <em>minval</em>, float <em>maxval</em>)<br>
+  gentyped <strong>clamp</strong>(gentyped <em>x</em>, double <em>minval</em>, double <em>maxval</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <strong>fmin</strong>(<strong>fmax</strong>(<em>x</em>, <em>minval</em>), <em>maxval</em>).
+      Results are undefined if <em>minval</em> &gt; <em>maxval</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>degrees</strong>(gentype <em>radians</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Converts <em>radians</em> to degrees, i.e. (180 / π) * <em>radians</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>max</strong>(gentype <em>x</em>, gentype <em>y</em>)<br>
+  gentypef <strong>max</strong>(gentypef <em>x</em>, float <em>y</em>)<br>
+  gentyped <strong>max</strong>(gentyped <em>x</em>, double <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <em>y</em> if <em>x</em> &lt; <em>y</em>, otherwise it returns <em>x</em>.
+      If <em>x</em> or <em>y</em> are infinite or NaN, the return values are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>min</strong>(gentype <em>x</em>, gentype <em>y</em>)<br>
+  gentypef <strong>min</strong>(gentypef <em>x</em>, float <em>y</em>)<br>
+  gentyped <strong>min</strong>(gentyped <em>x</em>, double <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <em>y</em> if <em>y</em> &lt; <em>x</em>, otherwise it returns <em>x</em>.
+      If <em>x</em> or <em>y</em> are infinite or NaN, the return values are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>mix</strong>(gentype <em>x</em>, gentype <em>y</em>, gentype <em>a</em>)<br>
+  gentypef <strong>mix</strong>(gentypef <em>x</em>, gentypef <em>y</em>, float <em>a</em>)<br>
+  gentyped <strong>mix</strong>(gentyped <em>x</em>, gentyped <em>y</em>, double <em>a</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the linear blend of <em>x</em> &amp; <em>y</em> implemented as:</p>
+<p class="tableblock">      <em>x</em> + (<em>y</em> - <em>x</em>) * <em>a</em></p>
+<p class="tableblock">      <em>a</em> must be a value in the range [0.0, 1.0].
+      If <em>a</em> is not in the range [0.0, 1.0], the return values are
+      undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>radians</strong>(gentype <em>degrees</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Converts <em>degrees</em> to radians, i.e. (π / 180) * <em>degrees</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>step</strong>(gentype <em>edge</em>, gentype <em>x</em>)<br>
+  gentypef <strong>step</strong>(float <em>edge</em>, gentypef <em>x</em>)<br>
+  gentyped <strong>step</strong>(double <em>edge</em>, gentyped <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns 0.0 if <em>x</em> &lt; <em>edge</em>, otherwise it returns 1.0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>smoothstep</strong>(gentype <em>edge0</em>, gentype <em>edge1</em>, gentype <em>x</em>)<br>
+  gentypef <strong>smoothstep</strong>(float <em>edge0</em>, float <em>edge1</em>, gentypef <em>x</em>)<br>
+  gentyped <strong>smoothstep</strong>(double <em>edge0</em>, double <em>edge1</em>, gentyped <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><div><div class="paragraph">
+<p>Returns 0.0 if <em>x</em> &lt;= <em>edge0</em> and 1.0 if <em>x</em> &gt;= <em>edge1</em> and performs
+      smooth Hermite interpolation between 0 and 1 when <em>edge0</em> &lt; <em>x</em> &lt;
+      <em>edge1</em>.
+      This is useful in cases where you would want a threshold function with
+      a smooth transition.</p>
+</div>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>This is equivalent to:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">gentype t;
+t = clamp ((x - edge0) / (edge1 - edge0), <span class="integer">0</span>, <span class="integer">1</span>);
+<span class="keyword">return</span> t * t * (<span class="integer">3</span> - <span class="integer">2</span> * t);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Results are undefined if <em>edge0</em> &gt;= <em>edge1</em> or if <em>x</em>, <em>edge0</em> or <em>edge1</em> is
+a NaN.</p>
+</div>
+</div>
+</div></div></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>sign</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns 1.0 if <em>x</em> &gt; 0, -0.0 if <em>x</em> = -0.0, +0.0 if <em>x</em> = +0.0, or
+      -1.0 if <em>x</em> &lt; 0.
+      Returns 0.0 if <em>x</em> is a NaN.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="geometric-functions">1.13.5. Geometric Functions<sup>34</sup></h4>
+<div class="paragraph">
+<p>[34] The geometric functions can be implemented using contractions such as
+<strong>mad</strong> or <strong>fma</strong>.</p>
+</div>
+<div class="paragraph">
+<p>The following table describes the list of built-in geometric functions.
+These all operate component-wise.
+The description is per-component.
+<code>float<em>n</em></code> is <code>float</code>, <code>float2</code>, <code>float3</code>, or <code>float4</code> and <code>double<em>n</em></code>
+is <code>double</code>, <code>double2</code>, <code>double3</code>, or <code>double4</code>.
+The built-in geometric functions are implemented using the round to nearest
+even rounding mode.</p>
+</div>
+<table id="table-builtin-geometric" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 13. Scalar and Vector Argument Built-in Geometric Function Table</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Function</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">float4 <strong>cross</strong>(float4 <em>p0</em>, float4 <em>p1</em>)<br>
+  float3 <strong>cross</strong>(float3 <em>p0</em>, float3 <em>p1</em>)<br>
+  double4 <strong>cross</strong>(double4 <em>p0</em>, double4 <em>p1</em>)<br>
+  double3 <strong>cross</strong>(double3 <em>p0</em>, double3 <em>p1</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the cross product of <em>p0.xyz</em> and <em>p1.xyz</em>.
+      The <em>w</em> component of <code>float4</code> result returned will be 0.0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">float <strong>dot</strong>(float<em>n</em> <em>p0</em>, float<em>n</em> <em>p1</em>)<br>
+  double <strong>dot</strong>(double<em>n</em> <em>p0</em>, double<em>n</em> <em>p1</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute dot product.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">float <strong>distance</strong>(float<em>n</em> <em>p0</em>, float<em>n</em> <em>p1</em>)<br>
+  double <strong>distance</strong>(double<em>n</em> <em>p0</em>, double<em>n</em> <em>p1</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the distance between <em>p0</em> and <em>p1</em>.
+      This is calculated as <strong>length</strong>(<em>p0</em> - <em>p1</em>).</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">float <strong>length</strong>(float<em>n</em> <em>p</em>)<br>
+  double <strong>length</strong>(double<em>n</em> <em>p</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the length of vector <em>p</em>, i.e., √ <em>p.x</em><sup>2</sup> + <em>p.y</em> <sup>2</sup>
+      +  &#8230;&#8203;</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">float<em>n</em> <strong>normalize</strong>(float<em>n</em> <em>p</em>)<br>
+  double<em>n</em> <strong>normalize</strong>(double<em>n</em> <em>p</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns a vector in the same direction as <em>p</em> but with a length of 1.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">float <strong>fast_distance</strong>(float<em>n</em> <em>p0</em>, float<em>n</em> <em>p1</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <strong>fast_length</strong>(<em>p0</em> - <em>p1</em>).</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">float <strong>fast_length</strong>(float<em>n</em> <em>p</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the length of vector <em>p</em> computed as:</p>
+<p class="tableblock">      <strong>half_sqrt</strong>(<em>p.x</em><sup>2</sup> + <em>p.y</em><sup>2</sup> + &#8230;&#8203;)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">float<em>n</em> <strong>fast_normalize</strong>(float<em>n</em> <em>p</em>)</p></td>
+<td class="tableblock halign-left valign-top"><div><div class="paragraph">
+<p>Returns a vector in the same direction as <em>p</em> but with a length of 1.
+      <strong>fast_normalize</strong> is computed as:</p>
+</div>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p><em>p</em> * <strong>half_rsqrt</strong>(<em>p.x</em><sup>2</sup> + <em>p.y</em><sup>2</sup> + &#8230;&#8203;)</p>
+</div>
+<div class="paragraph">
+<p>The result shall be within 8192 ulps error from the infinitely precise
+result of</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="keyword">if</span> (all(p == <span class="float">0</span><span class="float">.0f</span>))
+    result = p;
+<span class="keyword">else</span>
+    result = p / sqrt(p.x^<span class="integer">2</span> + p.y^<span class="integer">2</span> + ...);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>with the following exceptions:</p>
+</div>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>If the sum of squares is greater than <code>FLT_MAX</code> then the value of the
+floating-point values in the result vector are undefined.</p>
+</li>
+<li>
+<p>If the sum of squares is less than <code>FLT_MIN</code> then the implementation
+may return back <em>p</em>.</p>
+</li>
+<li>
+<p>If the device is in &#8220;denorms are flushed to zero&#8221; mode, individual
+operand elements with magnitude less than <strong>sqrt</strong>(<code>FLT_MIN</code>) may be flushed
+to zero before proceeding with the calculation.</p>
+</li>
+</ol>
+</div>
+</div>
+</div></div></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="relational-functions">1.13.6. Relational Functions</h4>
+<div class="paragraph">
+<p>The <a href="#operators-relational">relational</a> and <a href="#operators-equality">equality</a>
+operators (<strong>&lt;</strong>, <strong>&lt;=</strong>, <strong>&gt;</strong>, <strong>&gt;=</strong>, <strong>!=</strong>, <strong>==</strong>) can be used with scalar and
+vector built-in types and produce a scalar or vector signed integer result
+respectively.</p>
+</div>
+<div class="paragraph">
+<p>The functions<sup>35</sup> described in the following table can be used with built-in
+scalar or vector types as arguments and return a scalar or vector integer
+result.
+The argument type <code>gentype</code> refers to the following built-in types: <code>char</code>,
+<code>char<em>n</em></code>, <code>uchar</code>, <code>uchar<em>n</em></code>, <code>short</code>, <code>short<em>n</em></code>, <code>ushort</code>,
+<code>ushort<em>n</em></code>, <code>int</code>, <code>int<em>n</em></code>, <code>uint</code>, <code>uint<em>n</em></code>, <code>long</code>, <code>long<em>n</em></code>,
+<code>ulong</code>, <code>ulong<em>n</em></code>, <code>float</code>, <code>float<em>n</em></code>, <code>double</code>, and <code>double<em>n</em></code>.
+The argument type <code>igentype</code> refers to the built-in signed integer types
+i.e. <code>char</code>, <code>char<em>n</em></code>, <code>short</code>, <code>short<em>n</em></code>, <code>int</code>, <code>int<em>n</em></code>, <code>long</code>
+and <code>long<em>n</em></code>.
+The argument type <code>ugentype</code> refers to the built-in unsigned integer types
+i.e. <strong>uchar</strong>, <strong>uchar<em>n</em></strong>, <strong>ushort</strong>, <strong>ushort<em>n</em></strong>, <code>uint</code>, <code>uint<em>n</em></code>,
+<code>ulong</code> and <code>ulong<em>n</em></code>.
+<em>n</em> is 2, 3, 4, 8, or 16.</p>
+</div>
+<div class="paragraph">
+<p>[35] If an implementation extends this specification to support IEEE-754
+flags or exceptions, then all builtin functions defined in the following
+table shall proceed without raising the <em>invalid</em> floating-point exception
+when one or more of the operands are NaNs.</p>
+</div>
+<div class="paragraph">
+<p>The functions <strong>isequal</strong>, <strong>isnotequal</strong>, <strong>isgreater</strong>, <strong>isgreaterequal</strong>,
+<strong>isless</strong>, <strong>islessequal</strong>, <strong>islessgreater</strong>, <strong>isfinite</strong>, <strong>isinf</strong>, <strong>isnan</strong>,
+<strong>isnormal</strong>, <strong>isordered</strong>, <strong>isunordered</strong> and <strong>signbit</strong> described in the
+following table shall return a 0 if the specified relation is <em>false</em> and a
+1 if the specified relation is <em>true</em> for scalar argument types.
+These functions shall return a 0 if the specified relation is <em>false</em> and a
+-1 (i.e. all bits set) if the specified relation is <em>true</em> for vector
+argument types.</p>
+</div>
+<div class="paragraph">
+<p>The relational functions <strong>isequal</strong>, <strong>isgreater</strong>, <strong>isgreaterequal</strong>, <strong>isless</strong>,
+<strong>islessequal</strong>, and <strong>islessgreater</strong> always return 0 if either argument is not
+a number (NaN).
+<strong>isnotequal</strong> returns 1 if one or both arguments are not a number (NaN) and
+the argument type is a scalar and returns -1 if one or both arguments are
+not a number (NaN) and the argument type is a vector.</p>
+</div>
+<table id="table-builtin-relational" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 14. Scalar and Vector Relational Functions</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Function</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>isequal</strong>(float <em>x</em>, float <em>y</em>)<br>
+  int<em>n</em> <strong>isequal</strong>(float<em>n</em> <em>x</em>, float<em>n</em> <em>y</em>)<br>
+  int <strong>isequal</strong>(double <em>x</em>, double <em>y</em>)<br>
+  long<em>n</em> <strong>isequal</strong>(double<em>n</em> <em>x</em>, double<em>n</em> <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the component-wise compare of <em>x</em> == <em>y</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>isnotequal</strong>(float <em>x</em>, float <em>y</em>)<br>
+  int<em>n</em> <strong>isnotequal</strong>(float<em>n</em> <em>x</em>, float<em>n</em> <em>y</em>)<br>
+  int <strong>isnotequal</strong>(double <em>x</em>, double <em>y</em>)<br>
+  long<em>n</em> <strong>isnotequal</strong>(double<em>n</em> <em>x</em>, double<em>n</em> <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the component-wise compare of <em>x</em> != <em>y</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>isgreater</strong>(float <em>x</em>, float <em>y</em>)<br>
+  int<em>n</em> <strong>isgreater</strong>(float<em>n</em> <em>x</em>, float<em>n</em> <em>y</em>)<br>
+  int <strong>isgreater</strong>(double <em>x</em>, double <em>y</em>)<br>
+  long<em>n</em> <strong>isgreater</strong>(double<em>n</em> <em>x</em>, double<em>n</em> <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the component-wise compare of <em>x</em> &gt; <em>y</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>isgreaterequal</strong>(float <em>x</em>, float <em>y</em>)<br>
+  int<em>n</em> <strong>isgreaterequal</strong>(float<em>n</em> <em>x</em>, float<em>n</em> <em>y</em>)<br>
+  int <strong>isgreaterequal</strong>(double <em>x</em>, double <em>y</em>)<br>
+  long<em>n</em> <strong>isgreaterequal</strong>(double<em>n</em> <em>x</em>, double<em>n</em> <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the component-wise compare of <em>x</em> &gt;= <em>y</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>isless</strong>(float <em>x</em>, float <em>y</em>)<br>
+  int<em>n</em> <strong>isless</strong>(float<em>n</em> <em>x</em>, float<em>n</em> <em>y</em>)<br>
+  int <strong>isless</strong>(double <em>x</em>, double <em>y</em>)<br>
+  long<em>n</em> <strong>isless</strong>(double<em>n</em> <em>x</em>, double<em>n</em> <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the component-wise compare of <em>x</em> &lt; <em>y</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>islessequal</strong>(float <em>x</em>, float <em>y</em>)<br>
+  int<em>n</em> <strong>islessequal</strong>(float<em>n</em> <em>x</em>, float<em>n</em> <em>y</em>)<br>
+  int <strong>islessequal</strong>(double <em>x</em>, double <em>y</em>)<br>
+  long<em>n</em> <strong>islessequal</strong>(double<em>n</em> <em>x</em>, double<em>n</em> <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the component-wise compare of <em>x</em> &lt;= <em>y</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>islessgreater</strong>(float <em>x</em>, float <em>y</em>)<br>
+  int<em>n</em> <strong>islessgreater</strong>(float<em>n</em> <em>x</em>, float<em>n</em> <em>y</em>)<br>
+  int <strong>islessgreater</strong>(double <em>x</em>, double <em>y</em>)<br>
+  long<em>n</em> <strong>islessgreater</strong>(double<em>n</em> <em>x</em>, double<em>n</em> <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the component-wise compare of (<em>x</em> &lt; <em>y</em>) || (<em>x</em> &gt; <em>y</em>) .</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>isfinite</strong>(float)<br>
+  int<em>n</em> <strong>isfinite</strong>(float<em>n</em>)<br>
+  int <strong>isfinite</strong>(double)<br>
+  long<em>n</em> <strong>isfinite</strong>(double<em>n</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Test for finite value.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>isinf</strong>(float)<br>
+  int<em>n</em> <strong>isinf</strong>(float<em>n</em>)<br>
+  int <strong>isinf</strong>(double)<br>
+  long<em>n</em> <strong>isinf</strong>(double<em>n</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Test for infinity value (positive or negative).</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>isnan</strong>(float)<br>
+  int<em>n</em> <strong>isnan</strong>(float<em>n</em>)<br>
+  int <strong>isnan</strong>(double)<br>
+  long<em>n</em> <strong>isnan</strong>(double<em>n</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Test for a NaN.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>isnormal</strong>(float)<br>
+  int<em>n</em> <strong>isnormal</strong>(float<em>n</em>)<br>
+  int <strong>isnormal</strong>(double)<br>
+  long<em>n</em> <strong>isnormal</strong>(double<em>n</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Test for a normal value.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>isordered</strong>(float <em>x</em>, float <em>y</em>)<br>
+  int<em>n</em> <strong>isordered</strong>(float<em>n</em> <em>x</em>, float<em>n</em> <em>y</em>)<br>
+  int <strong>isordered</strong>(double <em>x</em>, double <em>y</em>)<br>
+  long<em>n</em> <strong>isordered</strong>(double<em>n</em> <em>x</em>, double<em>n</em> <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Test if arguments are ordered.
+     <strong>isordered</strong>() takes arguments <em>x</em> and <em>y</em>, and returns the result
+     <strong>isequal</strong>(<em>x</em>, <em>x</em>) &amp;&amp; <strong>isequal</strong>(<em>y</em>, <em>y</em>).</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>isunordered</strong>(float <em>x</em>, float <em>y</em>)<br>
+  int<em>n</em> <strong>isunordered</strong>(float<em>n</em> <em>x</em>, float<em>n</em> <em>y</em>)<br>
+  int <strong>isunordered</strong>(double <em>x</em>, double <em>y</em>)<br>
+  long<em>n</em> <strong>isunordered</strong>(double<em>n</em> <em>x</em>, double<em>n</em> <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Test if arguments are unordered.
+     <strong>isunordered</strong>() takes arguments <em>x</em> and <em>y</em>, returning non-zero if <em>x</em>
+     or <em>y</em> is NaN, and zero otherwise.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>signbit</strong>(float)<br>
+  int<em>n</em> <strong>signbit</strong>(float<em>n</em>)<br>
+  int <strong>signbit</strong>(double)<br>
+  long<em>n</em> <strong>signbit</strong>(double<em>n</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Test for sign bit.
+     The scalar version of the function returns a 1 if the sign bit in the
+     float is set else returns 0.
+     The vector version of the function returns the following for each
+     component in <code>float<em>n</em></code>: -1 (i.e all bits set) if the sign bit in the
+     float is set else returns 0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>any</strong>(igentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns 1 if the most significant bit in any component of <em>x</em> is set;
+      otherwise returns 0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>all</strong>(igentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns 1 if the most significant bit in all components of <em>x</em> is set;
+      otherwise returns 0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>bitselect</strong>(gentype <em>a</em>, gentype <em>b</em>, gentype <em>c</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Each bit of the result is the corresponding bit of <em>a</em> if the
+     corresponding bit of <em>c</em> is 0.
+     Otherwise it is the corresponding bit of <em>b</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>select</strong>(gentype <em>a</em>, gentype <em>b</em>, igentype <em>c</em>)
+  gentype <strong>select</strong>(gentype <em>a</em>, gentype <em>b</em>, ugentype <em>c</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">For each component of a vector type,</p>
+<p class="tableblock">      <em>result[i]</em> = if MSB of <em>c[i]</em> is set ? <em>b[i]</em> : <em>a[i]</em>.</p>
+<p class="tableblock">      For a scalar type, <em>result</em> = <em>c</em> ? <em>b</em> : <em>a</em>.</p>
+<p class="tableblock">      <code>igentype</code> and <code>ugentype</code> must have the same number of elements and
+      bits as <code>gentype</code><sup>36</sup>.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>[36] The above definition means that the behavior of select and the ternary
+operator for vector and scalar types is dependent on different
+interpretations of the bit pattern of <em>c</em>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="vector-data-load-and-store-functions">1.13.7. Vector Data Load and Store Functions</h4>
+<div class="paragraph">
+<p>The following table describes the list of supported functions that allow you
+to read and write vector types from a pointer to memory.
+We use the generic type <code>gentype</code> to indicate the built-in data types
+<code>char</code>, <code>uchar</code>, <code>short</code>, <code>ushort</code>, <code>int</code>, <code>uint</code>, <code>long</code>, <code>ulong</code>, <code>float</code>
+or <code>double</code>.
+We use the generic type name <code>gentype<em>n</em></code> to represent n-element vectors
+of <code>gentype</code> elements.
+We use the type name <code>half<em>n</em></code> to represent n-element vectors of half
+elements<sup>37</sup>.
+The suffix <em>n</em> is also used in the function names (i.e. <strong>vload<em>n</em></strong>,
+<strong>vstore<em>n</em></strong> etc.), where <em>n</em> = 2, 3, 4, 8 or 16.</p>
+</div>
+<div class="paragraph">
+<p>[37] The <code>half<em>n</em></code> type is only defined by the <strong>cl_khr_fp16</strong> extension
+described in <a href="#opencl-extension-spec">section 9.4 of the OpenCL 2.0 Extension
+Specification</a>.</p>
+</div>
+<table id="table-vector-loadstore" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 15. Vector Data Load and Store Functions<sup>38</sup></caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Function</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype<em>n</em> <strong>vload<em>n</em></strong>(size_t <em>offset</em>, const gentype *<em>p</em>)<br>
+  gentype<em>n</em> <strong>vload<em>n</em></strong>(size_t <em>offset</em>, const constant gentype *<em>p</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return <code>sizeof(gentype<em>n</em>)</code> bytes of data, where the first <code>(<em>n</em> *
+      sizeof(gentype))</code> bytes are read from the address
+      computed as <code>(<em>p</em> +  (<em>offset</em> * <em>n</em>))</code>.
+      The computed address must be 8-bit aligned if <code>gentype</code> is <code>char</code> or
+      <code>uchar</code>; 16-bit aligned if <code>gentype</code> is <code>short</code> or <code>ushort</code>; 32-bit
+      aligned if <code>gentype</code> is <code>int</code>, <code>uint</code>, or <code>float</code>; and 64-bit aligned
+      if <code>gentype</code> is <code>long</code> or <code>ulong</code>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>vstore<em>n</em></strong>(gentype<em>n</em> <em>data</em>, size_t <em>offset</em>, gentype *<em>p</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Write <code><em>n</em> * sizeof(gentype)</code> bytes given by <em>data</em> to the address
+      computed as <code>(<em>p</em> +  (<em>offset</em> * <em>n</em>))</code>.
+      The computed address must be 8-bit aligned if <code>gentype</code> is <code>char</code> or
+      <code>uchar</code>; 16-bit aligned if <code>gentype</code> is <code>short</code> or <code>ushort</code>; 32-bit
+      aligned if <code>gentype</code> is <code>int</code>, <code>uint</code>, or <code>float</code>; and 64-bit aligned
+      if <code>gentype</code> is <code>long</code> or <code>ulong</code>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">float <strong>vload_half</strong>(size_t <em>offset</em>, const half *<em>p</em>)<br>
+  float <strong>vload_half</strong>(size_t <em>offset</em>, const constant half *<em>p</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Read <code>sizeof(half)</code> bytes of data from the address computed as <code>(<em>p</em>
+      +  <em>offset</em>)</code>.
+      The data read is interpreted as a <code>half</code> value.
+      The <code>half</code> value is converted to a <code>float</code> value and the <code>float</code> value
+      is returned.
+      The computed read address must be 16-bit aligned.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">float<em>n</em> <strong>vload_half<em>n</em></strong>(size_t <em>offset</em>, const half *<em>p</em>)<br>
+  float<em>n</em> <strong>vload_half<em>n</em></strong>(size_t <em>offset</em>, const constant half *<em>p</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Read <code>(<em>n</em> * sizeof(half))</code> bytes of data from the address computed as
+      <code>(<em>p</em> +  (<em>offset * n</em>))</code>.
+      The data read is interpreted as a <code>half<em>n</em></code> value.
+      The <code>half<em>n</em></code> value read is converted to a <code>float<em>n</em></code> value and
+      the <code>float<em>n</em></code> value is returned.
+      The computed read address must be 16-bit aligned.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>vstore_half</strong>(float <em>data</em>, size_t <em>offset</em>, half *<em>p</em>)<br>
+  void <strong>vstore_half<em><em>rte</em></strong>(float _data</em>, size_t <em>offset</em>, half *<em>p</em>)<br>
+  void <strong>vstore_half<em><em>rtz</em></strong>(float _data</em>, size_t <em>offset</em>, half *<em>p</em>)<br>
+  void <strong>vstore_half<em><em>rtp</em></strong>(float _data</em>, size_t <em>offset</em>, half *<em>p</em>)<br>
+  void <strong>vstore_half<em><em>rtn</em></strong>(float _data</em>, size_t <em>offset</em>, half *<em>p</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The <code>float</code> value given by <em>data</em> is first converted to a <code>half</code> value
+      using the appropriate rounding mode.
+      The <code>half</code> value is then written to the address computed as <code>(<em>p</em>
+      +  <em>offset</em>)</code>.
+      The computed address must be 16-bit aligned.</p>
+<p class="tableblock">      <strong>vstore_half</strong> uses the default rounding mode.
+      The default rounding mode is round to nearest even.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>vstore_half<em>n</em></strong>(float<em>n</em> <em>data</em>, size_t <em>offset</em>, half *<em>p</em>)<br>
+  void <strong>vstore_half<em>n_rte</em></strong>(float<em>n</em> <em>data</em>, size_t <em>offset</em>, half *<em>p</em>)<br>
+  void <strong>vstore_half<em>n_rtz</em></strong>(float<em>n</em> <em>data</em>, size_t <em>offset</em>, half *<em>p</em>)<br>
+  void <strong>vstore_half<em>n_rtp</em></strong>(float<em>n</em> <em>data</em>, size_t <em>offset</em>, half *<em>p</em>)<br>
+  void <strong>vstore_half<em>n_rtn</em></strong>(float<em>n</em> <em>data</em>, size_t <em>offset</em>, half *<em>p</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The <code>float<em>n</em></code> value given by <em>data</em> is converted to a <code>half<em>n</em></code>
+      value using the appropriate rounding mode.
+      <code><em>n</em> * sizeof(half)</code> bytes from the <code>half<em>n</em></code> value are then written to
+      the address computed as <code>(<em>p</em>
+      +  (<em>offset</em> * <em>n</em>))</code>.
+      The computed address must be 16-bit aligned.</p>
+<p class="tableblock">      <strong>vstore_half<em>n</em></strong> uses the default rounding mode.
+      The default rounding mode is round to nearest even.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>vstore_half</strong>(double <em>data</em>, size_t <em>offset</em>, half *<em>p</em>)<br>
+  void <strong>vstore_half<em><em>rte</em></strong>(double _data</em>, size_t <em>offset</em>, half *<em>p</em>)<br>
+  void <strong>vstore_half<em><em>rtz</em></strong>(double _data</em>, size_t <em>offset</em>, half *<em>p</em>)<br>
+  void <strong>vstore_half<em><em>rtp</em></strong>(double _data</em>, size_t <em>offset</em>, half *<em>p</em>)<br>
+  void <strong>vstore_half<em><em>rtn</em></strong>(double _data</em>, size_t <em>offset</em>, half *<em>p</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The <code>double</code> value given by <em>data</em> is first converted to a <code>half</code>
+      value using the appropriate rounding mode.
+      The <code>half</code> value is then written to the address computed as <code>(<em>p</em>
+      +  <em>offset</em>)</code>.
+      The computed address must be 16-bit aligned.</p>
+<p class="tableblock">      <strong>vstore_half</strong> uses the default rounding mode.
+      The default rounding mode is round to nearest even.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>vstore_half<em>n</em></strong>(double<em>n</em> <em>data</em>, size_t <em>offset</em>, half *<em>p</em>)<br>
+  void <strong>vstore_half<em>n_rte</em></strong>(double<em>n</em> <em>data</em>, size_t <em>offset</em>, half *<em>p</em>)<br>
+  void <strong>vstore_half<em>n_rtz</em></strong>(double<em>n</em> <em>data</em>, size_t <em>offset</em>, half *<em>p</em>)<br>
+  void <strong>vstore_half<em>n_rtp</em></strong>(double<em>n</em> <em>data</em>, size_t <em>offset</em>, half *<em>p</em>)<br>
+  void <strong>vstore_half<em>n_rtn</em></strong>(double<em>n</em> <em>data</em>, size_t <em>offset</em>, half *<em>p</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The <code>double<em>n</em></code> value given by <em>data</em> is converted to a <code>half<em>n</em></code>
+      value using the appropriate rounding mode.
+      <code><em>n</em> * sizeof(half)</code> bytes from the <code>half<em>n</em></code> value are then written to
+      the address computed as <code>(<em>p</em> +  (<em>offset</em> * <em>n</em>))</code>.
+      The computed address must be 16-bit aligned.</p>
+<p class="tableblock">      <strong>vstore_half<em>n</em></strong> uses the default rounding mode.
+      The default rounding mode is round to nearest even.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">float<em>n</em> <strong>vloada_half<em>n</em></strong>(size_t <em>offset</em>, const half *<em>p</em>)<br>
+  float<em>n</em> <strong>vloada_half<em>n</em></strong>(size_t <em>offset</em>, const constant half *<em>p</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">For n = 2, 4, 8 and 16, read <code>sizeof(half<em>n</em>)</code> bytes of data from
+      the address computed as (<em>p</em> + (<em>offset</em> * <em>n</em>)).
+      The data read is interpreted as a <code>half<em>n</em></code> value.
+      The <code>half<em>n</em></code> value read is converted to a <code>float<em>n</em></code> value and
+      the <code>float<em>n</em></code> value is returned.
+      The computed address must be aligned to <code>sizeof(half<em>n</em>)</code> bytes.</p>
+<p class="tableblock">      For n = 3, <strong>vloada_half3</strong> reads a <code>half3</code> from the address computed as
+      <code>(<em>p</em> +  (<em>offset * 4</em>))</code> and returns a <code>float3</code>.
+      The computed address must be aligned to <code>sizeof(half)</code> * 4 bytes.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>vstorea_half<em>n</em></strong>(float<em>n</em> <em>data</em>, size_t <em>offset</em>, half *<em>p</em>)<br>
+  void <strong>vstorea_half<em>n_rte</em></strong>(float<em>n</em> <em>data</em>, size_t <em>offset</em>, half *<em>p</em>)<br>
+  void <strong>vstorea_half<em>n_rtz</em></strong>(float<em>n</em> <em>data</em>, size_t <em>offset</em>, half *<em>p</em>)<br>
+  void <strong>vstorea_half<em>n_rtp</em></strong>(float<em>n</em> <em>data</em>, size_t <em>offset</em>, half *<em>p</em>)<br>
+  void <strong>vstorea_half<em>n_rtn</em></strong>(float<em>n</em> <em>data</em>, size_t <em>offset</em>, half *<em>p</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The <code>float<em>n</em></code> value given by <em>data</em> is converted to a <code>half<em>n</em></code>
+      value using the appropriate rounding mode.</p>
+<p class="tableblock">      For n = 2, 4, 8 and 16, the <code>half<em>n</em></code> value is written to the
+      address computed as <code>(<em>p</em> +  (<em>offset</em> * <em>n</em>))</code>.
+      The computed address must be aligned to <code>sizeof(half<em>n</em>)</code> bytes.</p>
+<p class="tableblock">      For n = 3, the <code>half3</code> value is written
+      to the address computed as <code>(<em>p</em> +  (<em>offset</em> * 4))</code>.
+      The computed address must be aligned to <code>sizeof(half) * 4</code> bytes.</p>
+<p class="tableblock">      <strong>vstorea_half<em>n</em></strong> uses the default rounding mode.
+      The default rounding mode is round to nearest even.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>vstorea_half<em>n</em></strong>(double<em>n</em> <em>data</em>, size_t <em>offset</em>, half *<em>p</em>)<br>
+  void <strong>vstorea_half<em>n_rte</em></strong>(double<em>n</em> <em>data</em>, size_t <em>offset</em>, half *<em>p</em>)<br>
+  void <strong>vstorea_half<em>n_rtz</em></strong>(double<em>n</em> <em>data</em>, size_t <em>offset</em>, half *<em>p</em>)<br>
+  void <strong>vstorea_half<em>n_rtp</em></strong>(double<em>n</em> <em>data</em>, size_t <em>offset</em>, half *<em>p</em>)<br>
+  void <strong>vstorea_half<em>n_rtn</em></strong>(double<em>n</em> <em>data</em>, size_t <em>offset</em>, half *<em>p</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The <code>double<em>n</em></code> value is converted to a <code>half<em>n</em></code> value using the
+      appropriate rounding mode.</p>
+<p class="tableblock">      For n = 2, 4, 8 or 16, the <code>half<em>n</em></code> value is written to the address
+      computed as <code>(<em>p</em> +  (<em>offset</em> * <em>n</em>))</code>.
+      The computed address must be aligned to <code>sizeof(half<em>n</em>)</code> bytes.</p>
+<p class="tableblock">      For n = 3, the <code>half3</code> value is written
+      to the address computed as <code>(<em>p</em> +  (<em>offset</em> * 4))</code>.
+      The computed address must be aligned to <code>sizeof(half) * 4</code> bytes.</p>
+<p class="tableblock">      <strong>vstorea_half<em>n</em></strong> uses the default rounding mode.
+      The default rounding mode is round to nearest even.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>[38] <strong>vload3</strong> and <strong>vload_half3</strong> read (<em>x</em>,<em>y</em>,<em>z</em>) components from address
+<code>(<em>p</em> + (<em>offset</em> * 3))</code> into a 3-component vector.
+<strong>vstore3</strong> and <strong>vstore_half3</strong> write (<em>x</em>,<em>y</em>,<em>z</em>) components from a
+3-component vector to address <code>(<em>p</em> + (<em>offset</em> * 3))</code>. In addition,
+<strong>vloada_half3</strong> reads (<em>x</em>,<em>y</em>,<em>z</em>) components from address
+<code>(<em>p</em> + (<em>offset</em> * 4))</code> into a 3-component vector and <strong>vstorea_half3</strong>
+writes (<em>x</em>,<em>y</em>,<em>z</em>) components from a 3-component vector to address <code>(<em>p</em>
++  (<em>offset</em> * 4))</code>.  Whether <strong>vloada_half3</strong> and <strong>vstorea_half3</strong> read/write
+padding data between the third vector element and the next alignment boundary is
+implementation defined.  <strong>vloada_</strong> and <strong>vstorea_</strong> variants are provided to access
+data that is aligned to the size of the vector, and are intended to enable
+performance on hardware that can take advantage of the increased alignment.</p>
+</div>
+<div class="paragraph">
+<p>The results of vector data load and store functions are undefined if the
+address being read from or written to is not correctly aligned as described
+in <a href="#table-vector-loadstore">Vector Data Load and Store Functions<sup>38</sup></a>.
+The pointer argument p can be a pointer to <code>global</code>, <code>local</code>, or <code>private</code>
+memory for store functions described in <a href="#table-vector-loadstore">Vector Data Load and Store Functions<sup>38</sup></a>.
+The pointer argument p can be a pointer to <code>global</code>, <code>local</code>, <code>constant</code>, or
+<code>private</code> memory for load functions described in <a href="#table-vector-loadstore">Vector Data Load and Store Functions<sup>38</sup></a>.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>The vector data load and store functions variants that take pointer
+arguments which point to the generic address space are also supported.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+</div>
+<div class="sect3">
+<h4 id="synchronization-functions">1.13.8. Synchronization Functions</h4>
+<div class="paragraph">
+<p>The OpenCL C programming language implements the following synchronization
+functions.</p>
+</div>
+<table id="table-builtin-synchronization" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 16. Built-in Synchronization Functions</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Function</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>work_group_barrier</strong><sup>39</sup>(cl_mem_fence_flags <em>flags</em>)<br>
+  void <strong>work_group_barrier</strong>(cl_mem_fence_flags <em>flags</em>,
+  memory_scope <em>scope</em><sup>40</sup>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">All work-items in a work-group executing the kernel on a processor
+      must execute this function before any are allowed to continue
+      execution beyond the <strong>work_group_barrier</strong>.
+      This function must be encountered by all work-items in a work-group
+      executing the kernel.
+      These rules apply to ND-ranges implemented with uniform and
+      non-uniform work-groups.</p>
+<p class="tableblock">      If <strong>work_group_barrier</strong> is inside a conditional statement, then all
+      work-items must enter the conditional if any work-item enters the
+      conditional statement and executes the <strong>work_group_barrier</strong>.</p>
+<p class="tableblock">      If <strong>work_group_barrier</strong> is inside a loop, all work-items must execute
+      the <strong>work_group_barrier</strong> for each iteration of the loop before any are
+      allowed to continue execution beyond the <strong>work_group_barrier</strong>.</p>
+<p class="tableblock">      The <strong>work_group_barrier</strong> function also supports a variant that
+      specifies the memory scope.
+      For the <strong>work_group_barrier</strong> variant that does not take a memory
+      scope, the <em>scope</em> is <code>memory_scope_work_group</code>.</p>
+<p class="tableblock">      The <em>scope</em> argument specifies whether the memory accesses of
+      work-items in the work-group to memory address space(s) identified by
+      <em>flags</em> become visible to all work-items in the work-group, the device
+      or all SVM devices.</p>
+<p class="tableblock">      The <strong>work_group_barrier</strong> function can also be used to specify which
+      memory operations, i.e. to <code>global</code> memory, <code>local</code> memory or images
+      become visible to the appropriate memory scope identified by <em>scope</em>.
+      The <em>flags</em> argument specifies the memory address spaces.
+      This is a bitfield and can be set to 0 or a combination of the
+      following values ORed together.
+      When these flags are OR&#8217;ed together the <strong>work_group_barrier</strong> acts as a
+      combined barrier for all address spaces specified by the flags
+      ordering memory accesses both within and across the specified address
+      spaces.</p>
+<p class="tableblock">      <code>CLK_LOCAL_MEM_FENCE</code> - The <strong>work_group_barrier</strong> function will ensure
+      that all local memory accesses become visible to all work-items in the
+      work-group.
+      Note that the value of <em>scope</em> is ignored as the memory scope is
+      always <code>memory_scope_work_group</code>.</p>
+<p class="tableblock">      <code>CLK_GLOBAL_MEM_FENCE</code> - The <strong>work_group_barrier</strong> function ensure that
+      all <code>global</code> memory accesses become visible to the appropriate scope
+      as given by <em>scope</em>.</p>
+<p class="tableblock">      <code>CLK_IMAGE_MEM_FENCE</code> - The <strong>work_group_barrier</strong> function will ensure
+      that all image memory accesses become visible to the appropriate scope
+      as given by <em>scope</em>.
+      The value of <em>scope</em> must be <code>memory_scope_work_group</code>.</p>
+<p class="tableblock">      The values of <em>flags</em> and <em>scope</em> must be the same for all work-items
+      in the work-group.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>[39] The built-in function <strong>barrier</strong> has been renamed <strong>work_group_barrier</strong>.
+For backward compatibility, <strong>barrier</strong> is also supported.</p>
+</div>
+<div class="paragraph">
+<p>[40] Refer to the <a href="#atomic-functions">description of <code>memory_scope</code></a>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="address-space-qualifier-functions">1.13.9. Address Space Qualifier Functions</h4>
+<div class="paragraph">
+<p>The OpenCL C programming language implements the following address space
+qualifier functions.
+We use the generic type name <code>gentype</code> to indicate any of the built-in data
+types supported by OpenCL C or a user defined type.</p>
+</div>
+<table id="table-builtin-address-qualifier" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 17. Built-in Address Space Qualifier Functions</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Function</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">global gentype * <strong>to_global</strong>(gentype *<em>ptr</em>)<br>
+  const global gentype * <strong>to_global</strong>(const gentype *<em>ptr</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns a pointer that points to a region in the <code>global</code> address
+      space if <strong>to_global</strong> can cast <em>ptr</em> to the <code>global</code> address space.
+      Otherwise it returns <code>NULL</code>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">local gentype * <strong>to_local</strong>(gentype *<em>ptr</em>)<br>
+  const local gentype * <strong>to_local</strong>(const gentype *<em>ptr</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns a pointer that points to a region in the <code>local</code> address space
+      if <strong>to_local</strong> can cast <em>ptr</em> to the local address space.
+      Otherwise it returns <code>NULL</code>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">private gentype * <strong>to_private</strong>(gentype *<em>ptr</em>)<br>
+  const private gentype * <strong>to_private</strong>(const gentype *<em>ptr</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns a pointer that points to a region in the <code>private</code> address
+      space if <strong>to_private</strong> can cast <em>ptr</em> to the <code>private</code> address space.
+      Otherwise it returns <code>NULL</code>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_mem_fence_flags <strong>get_fence</strong>(gentype *<em>ptr</em>)<br>
+  cl_mem_fence_flags <strong>get_fence</strong>(const gentype *<em>ptr</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns a valid memory fence value for <em>ptr</em>.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="async-copies">1.13.10. Async Copies from Global to Local Memory, Local to Global Memory, and Prefetch</h4>
+<div class="paragraph">
+<p>The OpenCL C programming language implements the following functions that
+provide asynchronous copies between <code>global</code> and local memory and a prefetch
+from <code>global</code> memory.</p>
+</div>
+<div class="paragraph">
+<p>We use the generic type name <code>gentype</code> to indicate the built-in data types
+char, <code>char{2|3<sup>41</sup>|4|8|16}</code>, <code>uchar</code>, <code>uchar{2|3|4|8|16}</code>, <code>short</code>,
+<code>short{2|3|4|8|16}</code>, <code>ushort</code>, <code>ushort{2|3|4|8|16}</code>, <code>int</code>,
+<code>int{2|3|4|8|16}</code>, <code>uint</code>, <code>uint{2|3|4|8|16}</code>, <code>long</code>, <code>long{2|3|4|8|16}</code>,
+<code>ulong</code>, <code>ulong{2|3|4|8|16}</code>, <code>float</code>, <code>float{2|3|4|8|16}</code>, or <code>double</code>,
+<code>double{2|3|4|8|16}</code> as the type for the arguments unless otherwise stated.</p>
+</div>
+<div class="paragraph">
+<p>[41] <strong>async_work_group_copy</strong> and <strong>async_work_group_strided_copy</strong> for
+3-component vector types behave as <strong>async_work_group_copy</strong> and
+<strong>async_work_group_strided_copy</strong> respectively for 4-component vector types.</p>
+</div>
+<table id="table-builtin-async-copy" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 18. Built-in Async Copy and Prefetch Functions</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Function</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">event_t <strong>async_work_group_copy</strong>(<em>local gentype <em>*dst</em>,
+  const </em>global gentype *<em>src</em>, size_t <em>num_gentypes</em>, event_t <em>event</em>)<br>
+  event_t <strong>async_work_group_copy</strong>(<em>global gentype <em>*dst</em>,
+  const </em>local gentype *<em>src</em>, size_t <em>num_gentypes</em>, event_t <em>event</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Perform an async copy of <em>num_gentypes</em> gentype elements from <em>src</em> to
+      <em>dst</em>.
+      The async copy is performed by all work-items in a work-group and this
+      built-in function must therefore be encountered by all work-items in a
+      work-group executing the kernel with the same argument values;
+      otherwise the results are undefined.
+      This rule applies to ND-ranges implemented with uniform and
+      non-uniform work-groups.</p>
+<p class="tableblock">      Returns an event object that can be used by <strong>wait_group_events</strong> to
+      wait for the async copy to finish.
+      The <em>event</em> argument can also be used to associate the
+      <strong>async_work_group_copy</strong> with a previous async copy allowing an event
+      to be shared by multiple async copies; otherwise <em>event</em> should be
+      zero.</p>
+<p class="tableblock">      0 can be implicitly and explicitly cast to <code>event_t</code> type.</p>
+<p class="tableblock">      If <em>event</em> argument is non-zero, the event object supplied in <em>event</em>
+      argument will be returned.</p>
+<p class="tableblock">      This function does not perform any implicit synchronization of source
+      data such as using a <strong>barrier</strong> before performing the copy.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">event_t <strong>async_work_group_strided_copy</strong>(<em>local gentype <em>*dst</em>,
+  const </em>global gentype *<em>src</em>, size_t <em>num_gentypes</em>, size_t <em>src_stride</em>,
+  event_t <em>event</em>)<br>
+  event_t <strong>async_work_group_strided_copy</strong>(<em>global gentype <em>*dst</em>,
+  const </em>local gentype *<em>src</em>, size_t <em>num_gentypes</em>, size_t <em>dst_stride</em>,
+  event_t <em>event</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Perform an async gather of <em>num_gentypes</em> <code>gentype</code> elements from
+      <em>src</em> to <em>dst</em>.
+      The <em>src_stride</em> is the stride in elements for each <code>gentype</code>
+      element read from <em>src</em>.
+      The <em>dst_stride</em> is the stride in elements for each <code>gentype</code> element
+      written to <em>dst</em>.
+      The async gather is performed by all work-items in a work-group.
+      This built-in function must therefore be encountered by all work-items
+      in a work-group executing the kernel with the same argument values;
+      otherwise the results are undefined.
+      This rule applies to ND-ranges implemented with uniform and
+      non-uniform work-groups</p>
+<p class="tableblock">      Returns an event object that can be used by <strong>wait_group_events</strong> to
+      wait for the async copy to finish.
+      The <em>event</em> argument can also be used to associate the
+      <strong>async_work_group_strided_copy</strong> with a previous async copy allowing an
+      event to be shared by multiple async copies; otherwise <em>event</em> should
+      be zero.</p>
+<p class="tableblock">      0 can be implicitly and explicitly cast to event_t type.</p>
+<p class="tableblock">      If <em>event</em> argument is non-zero, the event object supplied in <em>event</em>
+      argument will be returned.</p>
+<p class="tableblock">      This function does not perform any implicit synchronization of source
+      data such as using a <strong>barrier</strong> before performing the copy.</p>
+<p class="tableblock">      The behavior of <strong>async_work_group_strided_copy</strong> is undefined if
+      <em>src_stride</em> or <em>dst_stride</em> is 0, or if the <em>src_stride</em> or
+      <em>dst_stride</em> values cause the <em>src</em> or <em>dst</em> pointers to exceed the
+      upper bounds of the address space during the copy.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>wait_group_events</strong>(int <em>num_events</em>, event_t *<em>event_list</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Wait for events that identify the <strong>async_work_group_copy</strong> operations
+      to complete.
+      The event objects specified in <em>event_list</em> will be released after the
+      wait is performed.</p>
+<p class="tableblock">      This function must be encountered by all work-items in a work-group
+      executing the kernel with the same <em>num_events</em> and event objects
+      specified in <em>event_list</em>; otherwise the results are undefined.
+      This rule applies to ND-ranges implemented with uniform and
+      non-uniform work-groups</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>prefetch</strong>(const <em>_global gentype *_p</em>, size_t <em>num_gentypes</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Prefetch <code><em>num_gentypes</em> * sizeof(gentype)</code> bytes into the global
+      cache.
+      The prefetch instruction is applied to a work-item in a work-group and
+      does not affect the functional behavior of the kernel.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>The kernel must wait for the completion of all async copies using the
+<strong>wait_group_events</strong> built-in function before exiting; otherwise the behavior
+is undefined.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+</div>
+<div class="sect3">
+<h4 id="atomic-functions">1.13.11. Atomic Functions</h4>
+<div class="paragraph">
+<p>The OpenCL C programming language implements a subset of the C11 atomics
+(refer to <a href="#C11-spec">section 7.17 of the C11 Specification</a>) and
+synchronization operations.
+These operations play a special role in making assignments in one work-item
+visible to another.
+A synchronization operation on one or more memory locations is either an
+acquire operation, a release operation, or both an acquire and release
+operation<sup>42</sup>.
+A synchronization operation without an associated memory location is a fence
+and can be either an acquire fence, a release fence or both an acquire and
+release fence.
+In addition, there are relaxed atomic operations, which are not
+synchronization operations, and atomic read-modify-write operations which
+have special characteristics.</p>
+</div>
+<div class="paragraph">
+<p>[42] The <a href="#C11-spec">C11</a> consume operation is not supported.</p>
+</div>
+<div class="paragraph">
+<p>The types include</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p><code>memory_order</code></p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>which is an enumerated type whose enumerators identify memory ordering
+constraints;</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p><code>memory_scope</code></p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>which is an enumerated type whose enumerators identify scope of memory
+ordering constraints;</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p><code>atomic_flag</code></p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>which is a 32-bit integer type representing a lock-free, primitive atomic
+flag; and several atomic analogs of integer types.</p>
+</div>
+<div class="paragraph">
+<p>In the following operation definitions:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>An A refers to one of the atomic types.</p>
+</li>
+<li>
+<p>A C refers to its corresponding non-atomic type.</p>
+</li>
+<li>
+<p>An M refers to the type of the other argument for arithmetic operations.
+For atomic integer types, M is C.</p>
+</li>
+<li>
+<p>The functions not ending in explicit have the same semantics as the
+corresponding explicit function with <code>memory_order_seq_cst</code> for the
+<code>memory_order</code> argument.</p>
+</li>
+<li>
+<p>The functions that do not have <code>memory_scope</code> argument have the same
+semantics as the corresponding functions with the <code>memory_scope</code>
+argument set to <code>memory_scope_device</code>.</p>
+</li>
+</ul>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>With fine-grained system SVM, sharing happens at the granularity of
+individual loads and stores anywhere in host memory.
+Memory consistency is always guaranteed at synchronization points, but to
+obtain finer control over consistency, the OpenCL atomics functions may be
+used to ensure that the updates to individual data values made by one unit
+of execution are visible to other execution units.
+In particular, when a host thread needs fine control over the consistency of
+memory that is shared with one or more OpenCL devices, it must use atomic
+and fence operations that are compatible with the C11 atomic operations.</p>
+</div>
+<div class="paragraph">
+<p>We can&#8217;t require <a href="#C11-spec">C11 atomics</a> since host programs can be
+implemented in other programming languages and versions of C or C++, but we
+do require that the host programs use atomics and that those atomics be
+compatible with those in C11.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+<div class="sect4">
+<h5 id="the-atomic_var_init-macro">The <code>ATOMIC_VAR_INIT</code> macro</h5>
+<div class="paragraph">
+<p>The <code>ATOMIC_VAR_INIT</code> macro expands to a token sequence suitable for
+initializing an atomic object of a type that is initialization-compatible
+with value.
+An atomic object with automatic storage duration that is not explicitly
+initialized using <code>ATOMIC_VAR_INIT</code> is initially in an indeterminate state;
+however, the default (zero) initialization for objects with <code>static</code> storage
+duration is guaranteed to produce a valid state.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="preprocessor">#define</span> ATOMIC_VAR_INIT(C value)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>This macro can only be used to initialize atomic objects that are declared
+in program scope in the <code>global</code> address space.</p>
+</div>
+<div class="paragraph">
+<p>Examples:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">global atomic_int guide = ATOMIC_VAR_INIT(<span class="integer">42</span>);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Concurrent access to the variable being initialized, even via an atomic
+operation, constitutes a data-race.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="the-atomic_init-function">The atomic_init function</h5>
+<div class="paragraph">
+<p>The atomic_init function non-atomically initializes the atomic object
+pointed to by obj to the value value.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="directive">void</span> atomic_init(<span class="directive">volatile</span> A *obj, C value)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Examples:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">local atomic_int local_guide;
+<span class="keyword">if</span> (get_local_id(<span class="integer">0</span>) == <span class="integer">0</span>)
+    atomic_init(&amp;guide, <span class="integer">42</span>);
+work_group_barrier(CLK_LOCAL_MEM_FENCE);</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="order-and-consistency">Order and Consistency</h5>
+<div class="paragraph">
+<p>The enumerated type <code>memory_order</code> specifies the detailed regular
+(non-atomic) memory synchronization operations as defined in
+<a href="#C11-spec">section 5.1.2.4 of the C11 Specification</a>, and may provide for
+operation ordering.
+Its enumeration constants are as follows:</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p><code>memory_order_relaxed</code></p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><code>memory_order_acquire</code></p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><code>memory_order_release</code></p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><code>memory_order_acq_rel</code></p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><code>memory_order_seq_cst</code></p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>The <code>memory_order</code> can be used when performing atomic operations to <code>global</code>
+or <code>local</code> memory.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="memory-scope">Memory Scope</h5>
+<div class="paragraph">
+<p>The enumerated type <code>memory_scope</code> specifies whether the memory ordering
+constraints given by <code>memory_order</code> apply to work-items in a work-group or
+work-items of a kernel(s) executing on the device or across devices (in the
+case of shared virtual memory).
+Its enumeration constants are as follows:</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p><code>memory_scope_work_item</code><sup>44</sup></p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><code>memory_scope_work_group</code></p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><code>memory_scope_device</code></p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><code>memory_scope_all_svm_devices</code></p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>[44] This value for <code>memory_scope</code> can only be used with
+<code>atomic_work_item_fence</code> with flags set to <code>CLK_IMAGE_MEM_FENCE</code>.</p>
+</div>
+<div class="paragraph">
+<p>The memory scope should only be used when performing atomic operations to
+global memory.
+Atomic operations to <code>local</code> memory only guarantee memory ordering in the
+work-group not across work-groups and therefore ignore the <code>memory_scope</code>
+value.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="fences">Fences</h5>
+<div class="paragraph">
+<p>The following fence operations are supported.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="directive">void</span> atomic_work_item_fence(cl_mem_fence_flags flags,
+                            memory_order order,
+                            memory_scope scope)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><code>flags</code> must be set to <code>CLK_GLOBAL_MEM_FENCE</code>, <code>CLK_LOCAL_MEM_FENCE</code>,
+<code>CLK_IMAGE_MEM_FENCE</code> or a combination of these values ORed together;
+otherwise the behavior is undefined.
+The behavior of calling <code>atomic_work_item_fence</code> with <code>CLK_IMAGE_MEM_FENCE</code>
+ORed together with either <code>CLK_GLOBAL_MEM_FENCE</code> or <code>CLK_LOCAL_MEM_FENCE</code> is
+equivalent to calling <code>atomic_work_item_fence</code> individually for
+<code>CLK_IMAGE_MEM_FENCE</code> and the other flags.
+Passing both <code>CLK_GLOBAL_MEM_FENCE</code> and <code>CLK_LOCAL_MEM_FENCE</code> to
+<code>atomic_work_item_fence</code> will synchronize memory operations to both <code>local</code>
+and <code>global</code> memory through some shared atomic action, as described in
+<a href="#opencl-spec">section 3.3.6.2 of the OpenCL Specification</a>.</p>
+</div>
+<div class="paragraph">
+<p>Depending on the value of order, this operation:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>has no effects, if <em>order</em> == <code>memory_order_relaxed</code>.</p>
+</li>
+<li>
+<p>is an acquire fence, if <em>order</em> == <code>memory_order_acquire</code>.</p>
+</li>
+<li>
+<p>is a release fence, if <em>order</em> == <code>memory_order_release</code>.</p>
+</li>
+<li>
+<p>is both an acquire fence and a release fence, if <em>order</em> ==
+<code>memory_order_acq_rel</code>.</p>
+</li>
+<li>
+<p>is a sequentially consistent acquire and release fence, if <em>order</em> ==
+<code>memory_order_seq_cst</code>.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For images declared with the <code>read_write</code> qualifier, the
+<code>atomic_work_item_fence</code> must be called to make sure that writes to the
+image by a work-item become visible to that work-item on subsequent reads to
+that image by that work-item.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="atomic-integer-and-floating-point-types">Atomic integer and floating-point types</h5>
+<div class="paragraph">
+<p>The list of supported atomic type names are:</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p><code>atomic_int</code></p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><code>atomic_uint</code></p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><code>atomic_long</code><sup>45</sup></p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><code>atomic_ulong</code></p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><code>atomic_float</code></p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><code>atomic_double</code><sup>46</sup></p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><code>atomic_intptr_t</code><sup>47</sup></p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><code>atomic_uintptr_t</code></p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><code>atomic_size_t</code></p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><code>atomic_ptrdiff_t</code></p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>[45] The atomic_long and atomic_ulong types are supported if the
+<strong>cl_khr_int64_base_atomics</strong> and <strong>cl_khr_int64_extended_atomics</strong> extensions
+are supported and have been enabled.</p>
+</div>
+<div class="paragraph">
+<p>[46] The <code>atomic_double</code> type is only supported if double precision is
+supported and the <strong>cl_khr_int64_base_atomics</strong> and
+<strong>cl_khr_int64_extended_atomics</strong> extensions are supported and have been
+enabled.</p>
+</div>
+<div class="paragraph">
+<p>[47] If the device address space is 64-bits, the data types
+<code>atomic_intptr_t</code>, <code>atomic_uintptr_t</code>, <code>atomic_size_t</code> and
+<code>atomic_ptrdiff_t</code> are supported if the <strong>cl_khr_int64_base_atomics</strong> and
+<strong>cl_khr_int64_extended_atomics</strong> extensions are supported and have been
+enabled.</p>
+</div>
+<div class="paragraph">
+<p>Arguments to a kernel can be declared to be a pointer to the above atomic
+types or the atomic_flag type.</p>
+</div>
+<div class="paragraph">
+<p>The representation of atomic integer, floating-point and pointer types have
+the same size as their corresponding regular types.
+The atomic_flag type must be implemented as a 32-bit integer.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="operations-on-atomic-types">Operations on atomic types</h5>
+<div class="paragraph">
+<p>There are only a few kinds of operations on atomic types, though there are
+many instances of those kinds.
+This section specifies each general kind.</p>
+</div>
+<div class="sect5">
+<h6 id="_strong_the_atomic_store_functions_strong"><strong>The atomic_store functions</strong></h6>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="directive">void</span> atomic_store(<span class="directive">volatile</span> A *object, C desired)
+
+<span class="directive">void</span> atomic_store_explicit(<span class="directive">volatile</span> A *object,
+                           C desired,
+                           memory_order order)
+
+<span class="directive">void</span> atomic_store_explicit(<span class="directive">volatile</span> A *object,
+                           C desired,
+                           memory_order order,
+                           memory_scope scope)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The <em>order</em> argument shall not be <code>memory_order_acquire</code>, nor
+<code>memory_order_acq_rel</code>.
+Atomically replace the value pointed to by <em>object</em> with the value of
+<em>desired</em>.
+Memory is affected according to the value of <em>order</em>.</p>
+</div>
+</div>
+<div class="sect5">
+<h6 id="_strong_the_atomic_load_functions_strong"><strong>The atomic_load functions</strong></h6>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">C atomic_load(<span class="directive">volatile</span> A *object)
+
+C atomic_load_explicit(<span class="directive">volatile</span> A *object,
+                       memory_order order)
+
+C atomic_load_explicit(<span class="directive">volatile</span> A *object,
+                       memory_order order,
+                       memory_scope scope)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The <em>order</em> argument shall not be <code>memory_order_release</code> nor
+<code>memory_order_acq_rel</code>.
+Memory is affected according to the value of <em>order</em>.
+Atomically returns the value pointed to by <em>object</em>.</p>
+</div>
+</div>
+<div class="sect5">
+<h6 id="_strong_the_atomic_exchange_functions_strong"><strong>The atomic_exchange functions</strong></h6>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">C atomic_exchange(<span class="directive">volatile</span> A *object, C desired)
+
+C atomic_exchange_explicit(<span class="directive">volatile</span> A *object,
+                           C desired,
+                           memory_order order)
+
+C atomic_exchange_explicit(<span class="directive">volatile</span> A *object,
+                           C desired,
+                           memory_order order,
+                           memory_scope scope)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Atomically replace the value pointed to by object with desired.
+Memory is affected according to the value of order.
+These operations are read-modify-write operations (as defined by
+<a href="#C11-spec">section 5.1.2.4 of the C11 Specification</a>).
+Atomically returns the value pointed to by object immediately before the
+effects.</p>
+</div>
+</div>
+<div class="sect5">
+<h6 id="_strong_the_atomic_compare_exchange_functions_strong"><strong>The atomic_compare_exchange functions</strong></h6>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="predefined-type">bool</span> atomic_compare_exchange_strong(
+    <span class="directive">volatile</span> A *object,
+    C *expected, C desired)
+
+<span class="predefined-type">bool</span> atomic_compare_exchange_strong_explicit(
+    <span class="directive">volatile</span> A *object,
+    C *expected,
+    C desired,
+    memory_order success,
+    memory_order failure)
+
+<span class="predefined-type">bool</span> atomic_compare_exchange_strong_explicit(
+    <span class="directive">volatile</span> A *object,
+    C *expected,
+    C desired,
+    memory_order success,
+    memory_order failure,
+    memory_scope scope)
+
+<span class="predefined-type">bool</span> atomic_compare_exchange_weak(
+    <span class="directive">volatile</span> A *object,
+    C *expected, C desired)
+
+<span class="predefined-type">bool</span> atomic_compare_exchange_weak_explicit(
+    <span class="directive">volatile</span> A *object,
+    C *expected,
+    C desired,
+    memory_order success,
+    memory_order failure)
+
+<span class="predefined-type">bool</span> atomic_compare_exchange_weak_explicit(
+    <span class="directive">volatile</span> A *object,
+    C *expected,
+    C desired,
+    memory_order success,
+    memory_order failure,
+    memory_scope scope)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The <em>failure</em> argument shall not be <code>memory_order_release</code> nor
+<code>memory_order_acq_rel</code>.
+The <code>failure</code> argument shall be no stronger than the <code>success</code> argument.
+Atomically, compares the value pointed to by object for equality with that
+in expected, and if <em>true</em>, replaces the value pointed to by <code>object</code> with
+<code>desired</code>, and if <em>false</em>, updates the value in <code>expected</code> with the value
+pointed to by <code>object</code>.
+Further, if the comparison is <em>true</em>, memory is affected according to the
+value of <code>success</code>, and if the comparison is <em>false</em>, memory is affected
+according to the value of <code>failure</code>.
+If the comparison is <em>true</em>, these operations are atomic read-modify-write operations (as defined by
+<a href="#C11-spec">section 5.1.2.4 of the C11 Specification</a>).
+Otherwise, these operations are atomic load operations.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>The effect of the compare-and-exchange operations is</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="keyword">if</span> (memcmp(object, expected, <span class="keyword">sizeof</span>(*object) == <span class="integer">0</span>)
+    memcpy(object, &amp;desired, <span class="keyword">sizeof</span>(*object));
+<span class="keyword">else</span>
+    memcpy(expected, object, <span class="keyword">sizeof</span>(*object));</code></pre>
+</div>
+</div>
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p>The weak compare-and-exchange operations may fail spuriously<sup>48</sup>.
+That is, even when the contents of memory referred to by <code>expected</code> and
+<code>object</code> are equal, it may return zero and store back to <code>expected</code> the same
+memory contents that were originally there.</p>
+</div>
+<div class="paragraph">
+<p>[48] This spurious failure enables implementation of compare-and-exchange on
+a broader class of machines, e.g. load-locked store-conditional machines.</p>
+</div>
+<div class="paragraph">
+<p>These generic functions return the result of the comparison.</p>
+</div>
+</div>
+<div class="sect5">
+<h6 id="_strong_the_code_atomic_fetch_code_and_modify_functions_strong"><strong>The <code>atomic_fetch</code> and modify functions</strong></h6>
+<div class="paragraph">
+<p>The following operations perform arithmetic and bitwise computations.
+All of these operations are applicable to an object of any atomic integer
+type.
+The key, operator, and computation correspondence is given in table below:</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 33.3333%;">
+<col style="width: 33.3333%;">
+<col style="width: 33.3334%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>key</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>op</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>computation</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>add</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>+</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">addition</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>sub</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>-</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">subtraction</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>or</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>|</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">bitwise inclusive or</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>xor</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>^</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">bitwise exclusive or</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>and</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>&amp;</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">bitwise and</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>min</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>min</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">compute min</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>max</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>max</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">compute max</p></td>
+</tr>
+</tbody>
+</table>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>For <strong>atomic_fetch</strong> and modify functions with <strong>key</strong> = <code>add</code> or <code>sub</code> on
+atomic types <code>atomic_intptr_t</code> and <code>atomic_uintptr_t</code>, <code>M</code> is <code>ptrdiff_t</code>.
+For <strong>atomic_fetch</strong> and modify functions with <strong>key</strong> = <code>or</code>, <code>xor</code>, <code>and</code>,
+<code>min</code> and <code>max</code> on atomic types <code>atomic_intptr_t</code> and <code>atomic_uintptr_t</code>,
+<code>M</code> is <code>intptr_t</code> and <code>uintptr_t</code>.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">C atomic_fetch_key(<span class="directive">volatile</span> A *object, M operand)
+
+C atomic_fetch_key_explicit(<span class="directive">volatile</span> A *object,
+                            M operand,
+                            memory_order order)
+
+C atomic_fetch_key_explicit(<span class="directive">volatile</span> A *object,
+                            M operand,
+                            memory_order order,
+                            memory_scope scope)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Atomically replaces the value pointed to by object with the result of the
+computation applied to the value pointed to by <code>object</code> and the given
+operand.
+Memory is affected according to the value of <code>order</code>.
+These operations are atomic read-modify-write operations (as defined by
+<a href="#C11-spec">section 5.1.2.4 of the C11 Specification</a>).
+For signed integer types, arithmetic is defined to use two&#8217;s complement
+representation with silent wrap-around on overflow; there are no undefined
+results.
+For address types, the result may be an undefined address, but the
+operations otherwise have no undefined behavior.
+Returns atomically the value pointed to by <code>object</code> immediately before the
+effects.</p>
+</div>
+</div>
+<div class="sect5">
+<h6 id="_strong_atomic_flag_type_and_operations_strong"><strong>Atomic flag type and operations</strong></h6>
+<div class="paragraph">
+<p>The atomic_flag type provides the classic test-and-set functionality.
+It has two states, <em>set</em> (value is non-zero) and <em>clear</em> (value is 0).
+Operations on an object of type atomic_flag shall be lock free.</p>
+</div>
+<div class="paragraph">
+<p>The macro <code>ATOMIC_FLAG_INIT</code> may be used to initialize an atomic_flag to the
+<em>clear</em> state.
+An atomic_flag that is not explicitly initialized with <code>ATOMIC_FLAG_INIT</code> is
+initially in an indeterminate state.</p>
+</div>
+<div class="paragraph">
+<p>This macro can only be used for atomic objects that are declared in program
+scope in the <code>global</code> address space with the <code>atomic_flag</code> type.</p>
+</div>
+<div class="paragraph">
+<p>Example:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">global atomic_flag guard = <span class="error">`</span>ATOMIC_FLAG_INIT<span class="error">`</span>;</code></pre>
+</div>
+</div>
+</div>
+<div class="sect5">
+<h6 id="_strong_the_atomic_flag_test_and_set_functions_strong"><strong>The atomic_flag_test_and_set functions</strong></h6>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="predefined-type">bool</span> atomic_flag_test_and_set(
+    <span class="directive">volatile</span> atomic_flag *object)
+
+<span class="predefined-type">bool</span> atomic_flag_test_and_set_explicit(
+    <span class="directive">volatile</span> atomic_flag *object,
+    memory_order order)
+
+<span class="predefined-type">bool</span> atomic_flag_test_and_set_explicit(
+    <span class="directive">volatile</span> atomic_flag *object,
+    memory_order order,
+    memory_scope scope)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Atomically sets the value pointed to by <code>object</code> to <em>true</em>.
+Memory is affected according to the value of <code>order</code>.
+These operations are atomic read-modify-write operations (as defined by
+<a href="#C11-spec">section 5.1.2.4 of the C11 Specification</a>).
+Returns atomically the value of the <code>object</code> immediately before the effects.</p>
+</div>
+</div>
+<div class="sect5">
+<h6 id="_strong_the_atomic_flag_clear_functions_strong"><strong>The atomic_flag_clear functions</strong></h6>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="directive">void</span> atomic_flag_clear(<span class="directive">volatile</span> atomic_flag *object)
+
+<span class="directive">void</span> atomic_flag_clear_explicit(
+    <span class="directive">volatile</span> atomic_flag *object,
+    memory_order order)
+
+<span class="directive">void</span> atomic_flag_clear_explicit(
+    <span class="directive">volatile</span> atomic_flag *object,
+    memory_order order,
+    memory_scope scope)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The <code>order</code> argument shall not be <code>memory_order_acquire</code> nor
+<code>memory_order_acq_rel</code>.
+Atomically sets the value pointed to by object to false.
+Memory is affected according to the value of order.</p>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="restrictions-2">Restrictions</h5>
+<div class="ulist">
+<ul>
+<li>
+<p>All operations on atomic types must be performed using the built-in
+atomic functions.
+C11 and C++11 support operators on atomic types.
+OpenCL C does not support operators with atomic types.
+Using atomic types with operators should result in a compilation error.</p>
+</li>
+<li>
+<p>The <code>atomic_bool</code>, <code>atomic_char</code>, <code>atomic_uchar</code>, <code>atomic_short</code>,
+<code>atomic_ushort</code>, <code>atomic_intmax_t</code> and <code>atomic_uintmax_t</code> types are not
+supported by OpenCL C.</p>
+</li>
+<li>
+<p>OpenCL C requires that the built-in atomic functions on atomic types are
+lock-free.</p>
+</li>
+<li>
+<p>The _Atomic type specifier and _Atomic type qualifier are not supported
+by OpenCL C.</p>
+</li>
+<li>
+<p>The behavior of atomic operations where pointer arguments to the atomic
+functions refers to an atomic type in the <code>private</code> address space is
+undefined.</p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="miscellaneous-vector-functions">1.13.12. Miscellaneous Vector Functions</h4>
+<div class="paragraph">
+<p>The OpenCL C programming language implements the following additional
+built-in vector functions.
+We use the generic type name <code>gentype<em>n</em></code> (or <code>gentype<em>m</em></code>) to indicate
+the built-in data types <code>char{2|4|8|16}</code>, <code>uchar{2|4|8|16}</code>,
+<code>short{2|4|8|16}</code>, <code>ushort{2|4|8|16}</code>, <code>half{2|4|8|16}</code><sup>49</sup>, <code>int{2|4|8|16}</code>,
+<code>uint{2|4|8|16}</code>, <code>long{2|4|8|16}</code>, <code>ulong{2|4|8|16}</code>, <code>float{2|4|8|16}</code>, or
+<code>double{2|4|8|16}</code><sup>50</sup> as the type for the arguments unless otherwise stated.
+We use the generic name <code>ugentype<em>n</em></code> to indicate the built-in unsigned
+integer data types.</p>
+</div>
+<div class="paragraph">
+<p>[49] Only if the <strong>cl_khr_fp16</strong> extension is supported and has been enabled.</p>
+</div>
+<div class="paragraph">
+<p>[50] Only if double precision is supported.</p>
+</div>
+<table id="table-misc-vector" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 19. Built-in Miscellaneous Vector Functions</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Function</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>vec_step</strong>(gentype<em>n</em> <em>a</em>)<br>
+  int <strong>vec_step</strong>(char3 <em>a</em>)<br>
+  int <strong>vec_step</strong>(uchar3 <em>a</em>)<br>
+  int <strong>vec_step</strong>(short3 <em>a</em>)<br>
+  int <strong>vec_step</strong>(ushort3 <em>a</em>)<br>
+  int <strong>vec_step</strong>(half3 <em>a</em>)<br>
+  int <strong>vec_step</strong>(int3 <em>a</em>)<br>
+  int <strong>vec_step</strong>(uint3 <em>a</em>)<br>
+  int <strong>vec_step</strong>(long3 <em>a</em>)<br>
+  int <strong>vec_step</strong>(ulong3 <em>a</em>)<br>
+  int <strong>vec_step</strong>(float3 <em>a</em>)<br>
+  int <strong>vec_step</strong>(double3 <em>a</em>)<br>
+  int <strong>vec_step</strong>(<em>type</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The <strong>vec_step</strong> built-in function takes a built-in scalar or vector
+      data type argument and returns an integer value representing the
+      number of elements in the scalar or vector.</p>
+<p class="tableblock">      For all scalar types, <strong>vec_step</strong> returns 1.</p>
+<p class="tableblock">      The <strong>vec_step</strong> built-in functions that take a 3-component vector
+      return 4.</p>
+<p class="tableblock">      <strong>vec_step</strong> may also take a pure type as an argument, e.g.
+      <strong>vec_step</strong>(float2)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype<em>n</em> <strong>shuffle</strong>(gentype<em>m</em> <em>x</em>,
+                          ugentype<em>n</em> <em>mask</em>)<br>
+  gentype<em>n</em> <strong>shuffle2</strong>(gentype<em>m</em> <em>x</em>,
+                           gentype<em>m</em> <em>y</em>,
+                           ugentype<em>n</em> <em>mask</em>)</p></td>
+<td class="tableblock halign-left valign-top"><div><div class="paragraph">
+<p>The <strong>shuffle</strong> and <strong>shuffle2</strong> built-in functions construct a
+      permutation of elements from one or two input vectors respectively
+      that are of the same type, returning a vector with the same element
+      type as the input and length that is the same as the shuffle mask.
+      The size of each element in the <em>mask</em> must match the size of each
+      element in the result.
+      For <strong>shuffle</strong>, only the <strong>ilogb</strong>(2_m_-1) least significant bits of each
+      <em>mask</em> element are considered.
+      For <strong>shuffle2</strong>, only the <strong>ilogb</strong>(2_m_-1)+1 least significant bits of
+      each <em>mask</em> element are considered.
+      Other bits in the mask shall be ignored.</p>
+</div>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>The elements of the input vectors are numbered from left to right across one
+or both of the vectors.
+For this purpose, the number of elements in a vector is given by
+<strong>vec_step</strong>(gentype_m_).
+The shuffle <em>mask</em> operand specifies, for each element of the result vector,
+which element of the one or two input vectors the result element gets.</p>
+</div>
+<div class="paragraph">
+<p>Examples:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">uint4 mask = (uint4)(<span class="integer">3</span>, <span class="integer">2</span>, <span class="integer">1</span>, <span class="integer">0</span>);
+float4 a;
+float4 r = shuffle(a, mask);
+
+uint8 mask = (uint8)(<span class="integer">0</span>, <span class="integer">1</span>, <span class="integer">2</span>, <span class="integer">3</span>, <span class="integer">4</span>, <span class="integer">5</span>, <span class="integer">6</span>, <span class="integer">7</span>);
+float4 a, b;
+float8 r = shuffle2(a, b, mask);
+
+uint4 mask;
+float8 a;
+float4 b;
+
+b = shuffle(a, mask);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Examples that are not valid are:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">uint8 mask;
+short16 a;
+short8 b;
+
+b = shuffle(a, mask); <span class="comment">//  not valid</span></code></pre>
+</div>
+</div>
+</div>
+</div></div></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="printf">1.13.13. printf</h4>
+<div class="paragraph">
+<p>The OpenCL C programming language implements the <strong>printf</strong> function.</p>
+</div>
+<table id="table-printf" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 20. Built-in printf Function</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Function</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>printf</strong>(constant char restrict <em>format</em>, &#8230;&#8203;)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The <strong>printf</strong> built-in function writes output to an
+      implementation-defined stream such as stdout under control of the
+      string pointed to by <em>format</em> that specifies how subsequent arguments
+      are converted for output.
+      If there are insufficient arguments for the format, the behavior is
+      undefined.
+      If the format is exhausted while arguments remain, the excess
+      arguments are evaluated (as always) but are otherwise ignored.
+      The <strong>printf</strong> function returns when the end of the format string is
+      encountered.</p>
+<p class="tableblock">      <strong>printf</strong> returns 0 if it was executed successfully and -1 otherwise.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="sect4">
+<h5 id="printf-output-synchronization">printf output synchronization</h5>
+<div class="paragraph">
+<p>When the event that is associated with a particular kernel invocation is
+completed, the output of all printf() calls executed by this kernel
+invocation is flushed to the implementation-defined output stream.
+Calling <strong>clFinish</strong> on a command queue flushes all pending output by printf
+in previously enqueued and completed commands to the implementation-defined
+output stream.
+In the case that printf is executed from multiple work-items concurrently,
+there is no guarantee of ordering with respect to written data.
+For example, it is valid for the output of a work-item with a global id
+(0,0,1) to appear intermixed with the output of a work-item with a global id
+(0,0,4) and so on.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="printf-format-string">printf format string</h5>
+<div class="paragraph">
+<p>The format shall be a character sequence, beginning and ending in its
+initial shift state.
+The format is composed of zero or more directives: ordinary characters (not
+<strong>%</strong>), which are copied unchanged to the output stream; and conversion
+specifications, each of which results in fetching zero or more subsequent
+arguments, converting them, if applicable, according to the corresponding
+conversion specifier, and then writing the result to the output stream.
+The format is in the constant address space and must be resolvable at
+compile time, i.e. cannot be dynamically created by the executing program
+itself.</p>
+</div>
+<div class="paragraph">
+<p>Each conversion specification is introduced by the character <strong>%</strong>.
+After the <strong>%</strong>, the following appear in sequence:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Zero or more <em>flags</em> (in any order) that modify the meaning of the
+conversion specification.</p>
+</li>
+<li>
+<p>An optional minimum <em>field width</em>.
+If the converted value has fewer characters than the field width, it is
+padded with spaces (by default) on the left (or right, if the left
+adjustment flag, described later, has been given) to the field width.
+The field width takes the form of a nonnegative decimal integer<sup>51</sup>.</p>
+</li>
+<li>
+<p>An optional <em>precision</em> that gives the minimum number of digits to
+appear for the <strong>d</strong>, <strong>i</strong>, <strong>o</strong>, <strong>u</strong>, <strong>x</strong>, and <strong>X</strong> conversions, the number
+of digits to appear after the decimal-point character for <strong>a</strong>, <strong>A</strong>, <strong>e</strong>,
+<strong>E</strong>, <strong>f</strong>, and <strong>F</strong> conversions, the maximum number of significant digits
+for the <strong>g</strong> and <strong>G</strong> conversions, or the maximum number of bytes to be
+written for <strong>s</strong> conversions.
+The precision takes the form of a period (<strong>.</strong>) followed by an optional
+decimal integer; if only the period is specified, the precision is taken
+as zero.
+If a precision appears with any other conversion specifier, the behavior
+is undefined.</p>
+</li>
+<li>
+<p>An optional <em>vector specifier</em>.</p>
+</li>
+<li>
+<p>A <em>length modifier</em> that specifies the size of the argument.
+The <em>length modifier</em> is required with a vector specifier and together
+specifies the vector type.
+<a href="#implicit-conversions">Implicit conversions</a> between vector types are
+disallowed.
+If the <em>vector specifier</em> is not specified, the <em>length modifier</em> is
+optional.</p>
+</li>
+<li>
+<p>A <em>conversion specifier</em> character that specifies the type of
+conversion to be applied.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>[51] Note that <strong>0</strong> is taken as a flag, not as the beginning of a field width.</p>
+</div>
+<div class="paragraph">
+<p>The flag characters and their meanings are:</p>
+</div>
+<div class="paragraph">
+<p><strong>-</strong> The result of the conversion is left-justified within the field.
+(It is right-justified if this flag is not specified.)</p>
+</div>
+<div class="paragraph">
+<p><strong>+</strong> The result of a signed conversion always begins with a plus or minus
+sign.
+(It begins with a sign only when a negative value is converted if this flag
+is not specified.)<sup>52</sup></p>
+</div>
+<div class="paragraph">
+<p>[52] The results of all floating conversions of a negative zero, and of
+negative values that round to zero, include a minus sign.</p>
+</div>
+<div class="paragraph">
+<p><em>space</em> If the first character of a signed conversion is not a sign, or if a
+signed conversion results in no characters, a space is prefixed to the
+result.
+If the <em>space</em> and <strong>+</strong> flags both appear, the <em>space</em> flag is ignored.</p>
+</div>
+<div class="paragraph">
+<p><strong>#</strong> The result is converted to an &#8220;alternative form&#8221;.
+For <strong>o</strong> conversion, it increases the precision, if and only if necessary,
+to force the first digit of the result to be a zero (if the value and
+precision are both 0, a single 0 is printed).
+For <strong>x</strong> (or <strong>X</strong>) conversion, a nonzero result has <strong>0x</strong> (or <strong>0X</strong>)
+prefixed to it.
+For <strong>a</strong>, <strong>A</strong>, <strong>e</strong>, <strong>E</strong>, <strong>f</strong>, <strong>F</strong>, <strong>g</strong>, and <strong>G</strong> conversions,
+the result of converting a floating-point number always contains a
+decimal-point character, even if no digits follow it.
+(Normally, a decimal-point character appears in the result of these
+conversions only if a digit follows it.) For <strong>g</strong> and <strong>G</strong> conversions,
+trailing zeros are <strong>not</strong> removed from the result.
+For other conversions, the behavior is undefined.</p>
+</div>
+<div class="paragraph">
+<p><strong>0</strong> For <strong>d</strong>, <strong>i</strong>, <strong>o</strong>, <strong>u</strong>, <strong>x</strong>, <strong>X</strong>, <strong>a</strong>, <strong>A</strong>, <strong>e</strong>,
+<strong>E</strong>, <strong>f</strong>, <strong>F</strong>, <strong>g</strong>, and <strong>G</strong> conversions, leading zeros (following
+any indication of sign or base) are used to pad to the field width rather
+than performing space padding, except when converting an infinity or NaN.
+If the <strong>0</strong> and <strong>-</strong> flags both appear, the <strong>0</strong> flag is ignored.
+For <strong>d</strong>, <strong>i</strong>, <strong>o</strong>, <strong>u</strong>, <strong>x</strong>, and <strong>X</strong> conversions, if a precision
+is specified, the <strong>0</strong> flag is ignored.
+For other conversions, the behavior is undefined.</p>
+</div>
+<div class="paragraph">
+<p>The vector specifier and its meaning is:</p>
+</div>
+<div class="paragraph">
+<p><strong>v</strong><em>n</em> Specifies that a following <strong>a</strong>, <strong>A</strong>, <strong>e</strong>, <strong>E</strong>, <strong>f</strong>, <strong>F</strong>, <strong>g</strong>, <strong>G</strong>,
+<strong>d</strong>, <strong>i</strong>, <strong>o</strong>, <strong>u</strong>, <strong>x</strong>, or <strong>X</strong> conversion specifier applies to a vector
+argument, where <em>n</em> is the size of the vector and must be 2, 3, 4, 8 or 16.</p>
+</div>
+<div class="paragraph">
+<p>The vector value is displayed in the following general form:</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p>value1 C value2 C &#8230;&#8203; C value<em>n</em></p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>where C is a separator character.
+The value for this separator character is a comma.</p>
+</div>
+<div class="paragraph">
+<p>If the vector specifier is not used, the length modifiers and their meanings
+are:</p>
+</div>
+<div class="paragraph">
+<p><strong>hh</strong> Specifies that a following <strong>d</strong>, <strong>i</strong>, <strong>o</strong>, <strong>u</strong>, <strong>x</strong>, or <strong>X</strong> conversion
+specifier applies to a <code>char</code> or <code>uchar</code> argument (the argument will have
+been promoted according to the integer promotions, but its value shall be
+converted to <code>char</code> or <code>uchar</code> before printing).</p>
+</div>
+<div class="paragraph">
+<p><strong>h</strong> Specifies that a following <strong>d</strong>, <strong>i</strong>, <strong>o</strong>, <strong>u</strong>, <strong>x</strong>, or <strong>X</strong> conversion
+specifier applies to a <code>short</code> or <code>ushort</code> argument (the argument will have
+been promoted according to the integer promotions, but its value shall be
+converted to <code>short</code> or <code>unsigned short</code> before printing).</p>
+</div>
+<div class="paragraph">
+<p><strong>l</strong> (ell) Specifies that a following <strong>d</strong>, <strong>i</strong>, <strong>o</strong>, <strong>u</strong>, <strong>x</strong>, or <strong>X</strong>
+conversion specifier applies to a <code>long</code> or <code>ulong</code> argument.
+The <strong>l</strong> modifier is supported by the full profile.
+For the embedded profile, the <strong>l</strong> modifier is supported only if 64-bit
+integers are supported by the device.</p>
+</div>
+<div class="paragraph">
+<p>If the vector specifier is used, the length modifiers and their meanings
+are:</p>
+</div>
+<div class="paragraph">
+<p><strong>hh</strong> Specifies that a following <strong>d</strong>, <strong>i</strong>, <strong>o</strong>, <strong>u</strong>, <strong>x</strong>, or <strong>X</strong> conversion
+specifier applies to a <code>char<em>n</em></code> or <code>uchar<em>n</em></code> argument (the argument
+will not be promoted).</p>
+</div>
+<div class="paragraph">
+<p><strong>h</strong> Specifies that a following <strong>d</strong>, <strong>i</strong>, <strong>o</strong>, <strong>u</strong>, <strong>x</strong>, or <strong>X</strong> conversion
+specifier applies to a <code>short<em>n</em></code> or <code>ushort<em>n</em></code> argument (the argument
+will not be promoted); that a following <strong>a</strong>, <strong>A</strong>, <strong>e</strong>, <strong>E</strong>, <strong>f</strong>, <strong>F</strong>, <strong>g</strong>,
+or <strong>G</strong> conversion specifier applies to a <code>half<em>n</em></code><sup>53</sup> argument.</p>
+</div>
+<div class="paragraph">
+<p>[53] Only if the cl_khr_fp16 extension is supported and has been enabled.</p>
+</div>
+<div class="paragraph">
+<p><strong>hl</strong> This modifier can only be used with the vector specifier.
+Specifies that a following <strong>d</strong>, <strong>i</strong>, <strong>o</strong>, <strong>u</strong>, <strong>x</strong>, or <strong>X</strong> conversion
+specifier applies to a <code>int<em>n</em></code> or <code>uint<em>n</em></code> argument; that a following
+<strong>a</strong>, <strong>A</strong>, <strong>e</strong>, <strong>E</strong>, <strong>f</strong>, <strong>F</strong>, <strong>g</strong>, or <strong>G</strong> conversion specifier applies to a
+<code>float<em>n</em></code> argument.</p>
+</div>
+<div class="paragraph">
+<p><strong>l</strong>(ell) Specifies that a following <strong>d</strong>, <strong>i</strong>, <strong>o</strong>, <strong>u</strong>, <strong>x</strong>, or <strong>X</strong>
+conversion specifier applies to a <code>long<em>n</em></code> or <code>ulong<em>n</em></code> argument; that
+a following <strong>a</strong>, <strong>A</strong>, <strong>e</strong>, <strong>E</strong>, <strong>f</strong>, <strong>F</strong>, <strong>g</strong>, or <strong>G</strong> conversion specifier
+applies to a <code>double<em>n</em></code> argument.
+The <strong>l</strong> modifier is supported by the full profile.
+For the embedded profile, the <strong>l</strong> modifier is supported only if 64-bit
+integers or double-precision floating-point are supported by the device.</p>
+</div>
+<div class="paragraph">
+<p>If a vector specifier appears without a length modifier, the behavior is
+undefined.
+The vector data type described by the vector specifier and length modifier
+must match the data type of the argument; otherwise the behavior is
+undefined.</p>
+</div>
+<div class="paragraph">
+<p>If a length modifier appears with any conversion specifier other than as
+specified above, the behavior is undefined.</p>
+</div>
+<div class="paragraph">
+<p>The conversion specifiers and their meanings are:</p>
+</div>
+<div class="paragraph">
+<p><strong>d,i</strong> The <code>int</code>, <code>char<em>n</em></code>, <code>short<em>n</em></code>, <code>int<em>n</em></code> or <code>long<em>n</em></code>
+argument is converted to signed decimal in the style <em>[</em><strong>-</strong><em>]dddd</em>.
+The precision specifies the minimum number of digits to appear; if the value
+being converted can be represented in fewer digits, it is expanded with
+leading zeros.
+The default precision is 1.
+The result of converting a zero value with a precision of zero is no
+characters.</p>
+</div>
+<div class="paragraph">
+<p><strong>o,u,</strong></p>
+</div>
+<div class="paragraph">
+<p><strong>x,X</strong> The <code>unsigned int</code>, <code>uchar<em>n</em></code>, <code>ushort<em>n</em></code>, <code>uint<em>n</em></code> or
+<code>ulong<em>n</em></code> argument is converted to unsigned octal (<strong>o</strong>), unsigned decimal
+(<strong>u</strong>), or unsigned hexadecimal notation (<strong>x</strong> or <strong>X</strong>) in the style <em>dddd</em>;
+the letters <strong>abcdef</strong> are used for <strong>x</strong> conversion and the letters <strong>ABCDEF</strong>
+for <strong>X</strong> conversion.
+The precision specifies the minimum number of digits to appear; if the value
+being converted can be represented in fewer digits, it is expanded with
+leading zeros.
+The default precision is 1.
+The result of converting a zero value with a precision of zero is no
+characters.</p>
+</div>
+<div class="paragraph">
+<p><strong>f,F</strong> A <code>double</code>, <code>half<em>n</em></code>, <code>float<em>n</em></code> or <code>double<em>n</em></code> argument
+representing a floating-point number is converted to decimal notation in the
+style <em>[</em><strong>-</strong><em>]ddd</em><strong>.</strong><em>ddd</em>, where the number of digits after the
+decimal-point character is equal to the precision specification.
+If the precision is missing, it is taken as 6; if the precision is zero and
+the <strong># </strong>flag is not specified, no decimal-point character appears.
+If a decimal-point character appears, at least one digit appears before it.
+The value is rounded to the appropriate number of digits.
+A <code>double</code>, <code>half<em>n</em></code>, <code>float<em>n</em></code> or <code>double<em>n</em></code> argument representing
+an infinity is converted in one of the styles <em>[</em><strong>-</strong><em>]</em><strong>inf </strong>or
+<em>[</em><strong>-</strong><em>]</em><strong>infinity </strong>&#8201;&#8212;&#8201;which style is implementation-defined.
+A <code>double</code>, <code>half<em>n</em></code>, <code>float<em>n</em></code> or <code>double<em>n</em></code> argument representing
+a NaN is converted in one of the styles <em>[</em><strong>-</strong><em>]</em><strong>nan </strong>or
+<em>[</em><strong>-</strong><em>]</em><strong>nan(</strong><em>n-char-sequence</em><strong>) </strong>&#8201;&#8212;&#8201;which style, and the meaning of any <em>n-char-sequence</em>, is
+implementation-defined.
+The <strong>F</strong> conversion specifier produces <code>INF</code>, <code>INFINITY</code>, or <code>NAN</code> instead of
+<strong>inf</strong>, <strong>infinity</strong>, or <strong>nan</strong>, respectively<sup>54</sup>.</p>
+</div>
+<div class="paragraph">
+<p>[54] When applied to infinite and NaN values, the <strong>-</strong>, <strong>+</strong>, and <em>space</em> flag
+characters have their usual meaning; the <strong>#</strong> and <strong>0</strong> flag characters have no
+effect.</p>
+</div>
+<div class="paragraph">
+<p><strong>e,E</strong> A <code>double</code>, <code>half<em>n</em></code>, <code>float<em>n</em></code> or <code>double<em>n</em></code> argument
+representing a floating-point number is converted in the style
+<em>[</em><strong>-</strong><em>]d</em><strong>.</strong><em>ddd </em><strong>e±}</strong><em>dd</em>, where there is one digit
+(which is nonzero if the argument is nonzero) before the decimal-point
+character and the number of digits after it is equal to the precision; if
+the precision is missing, it is taken as 6; if the precision is zero and the
+<strong>#</strong> flag is not specified, no decimal-point character appears.
+The value is rounded to the appropriate number of digits.
+The <strong>E</strong> conversion specifier produces a number with <strong>E</strong> instead of <strong>e</strong>
+introducing the exponent.
+The exponent always contains at least two digits, and only as many more
+digits as necessary to represent the exponent.
+If the value is zero, the exponent is zero.
+A <code>double</code>, <code>half<em>n</em></code>, <code>float<em>n</em></code> or <code>double<em>n</em></code> argument representing
+an infinity or NaN is converted in the style of an <strong>f</strong> or <strong>F</strong> conversion
+specifier.</p>
+</div>
+<div class="paragraph">
+<p><strong>g,G</strong> A <code>double</code>, <code>half<em>n</em></code>, <code>float<em>n</em></code> or <code>double<em>n</em></code> argument
+representing a floating-point number is converted in style <strong>f</strong> or <strong>e</strong> (or in
+style <strong>F</strong> or <strong>E</strong> in the case of a <strong>G</strong> conversion specifier), depending on
+the value converted and the precision.
+Let <em>P </em>equal the precision if nonzero, 6 if the precision is omitted, or
+1 if the precision is zero.
+Then, if a conversion with style <strong>E</strong> would have an exponent of <em>X</em>:&#8201;&#8212;&#8201;if
+<em>P</em> &gt; <em>X</em> ≥ -4, the conversion is with style <strong>f</strong> (or <strong>F</strong>) and precision
+<em>P</em> <strong>-</strong> (<em>X</em> <strong>+</strong> 1).&#8201;&#8212;&#8201;otherwise, the conversion is with style <strong>e *(or *E</strong>) and precision <em>P</em>
+<strong>-</strong> 1.
+Finally, unless the <strong>#</strong> flag is used, any trailing zeros are removed from
+the fractional portion of the result and the decimal-point character is
+removed if there is no fractional portion remaining.
+A <code>double</code>, <code>half<em>n</em></code>, <code>float<em>n</em></code> or <code>double<em>n</em></code> <strong>e</strong> argument
+representing an infinity or NaN is converted in the style of an <strong>f</strong> or <strong>F</strong>
+conversion specifier.</p>
+</div>
+<div class="paragraph">
+<p><strong>a,A</strong> A <code>double</code>, <code>half<em>n</em></code>, <code>float<em>n</em></code> or <code>double<em>n</em></code> argument
+representing a floating-point number is converted in the style
+<em>[</em><strong>-</strong><em>]</em><strong>0x</strong><em>h</em><strong>.</strong><em>hhhh </em><strong>p±</strong><em>d</em>, where there is one
+hexadecimal digit (which is nonzero if the argument is a normalized
+floating-point number and is otherwise unspecified) before the decimal-point
+character<sup>55</sup> and the number of hexadecimal digits after it is equal to the
+precision; if the precision is missing, then the precision is sufficient for
+an exact representation of the value; if the precision is zero and the <strong>#</strong>
+flag is not specified, no decimal point character appears.
+The letters <strong>abcdef</strong> are used for <strong>a</strong> conversion and the letters <strong>ABCDEF</strong>
+for <strong>A</strong> conversion.
+The <strong>A</strong> conversion specifier produces a number with <strong>X</strong> and <strong>P</strong> instead of
+<strong>x</strong> and <strong>p</strong>.
+The exponent always contains at least one digit, and only as many more
+digits as necessary to represent the decimal exponent of 2.
+If the value is zero, the exponent is zero.
+A <code>double</code>, <code>half<em>n</em></code>, <code>float<em>n</em></code> or <code>double<em>n</em></code> argument representing
+an infinity or NaN is converted in the style of an <strong>f</strong> or <strong>F</strong> conversion
+specifier.</p>
+</div>
+<div class="paragraph">
+<p>[55] Binary implementations can choose the hexadecimal digit to the left of
+the decimal-point character so that subsequent digits align to nibble
+(4-bit) boundaries.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>The conversion specifiers <strong>e,E,g,G,a,A</strong> convert a <code>float</code> or <code>half</code> argument
+that is a scalar type to a <code>double</code> only if the <code>double</code> data type is
+supported.
+If the <code>double</code> data type is not supported, the argument will be a <code>float</code>
+instead of a <code>double</code> and the <code>half</code> type will be converted to a <code>float</code>.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p><strong>c</strong> The <code>int</code> argument is converted to an <code>unsigned char</code>, and the resulting
+character is written.</p>
+</div>
+<div class="paragraph">
+<p><strong>s</strong> The argument shall be a literal string<sup>56</sup>.
+Characters from the literal string array are written up to (but not
+including) the terminating null character.
+If the precision is specified, no more than that many bytes are written.
+If the precision is not specified or is greater than the size of the array,
+the array shall contain a null character.</p>
+</div>
+<div class="paragraph">
+<p>[56] No special provisions are made for multibyte characters.
+The behavior of <strong>printf</strong> with the <strong>s</strong> conversion specifier is undefined if
+the argument value is not a pointer to a literal string.</p>
+</div>
+<div class="paragraph">
+<p><strong>p</strong> The argument shall be a pointer to <strong>void</strong>.
+The pointer can refer to a memory region in the <code>global</code>, <code>constant</code>,
+<code>local</code>, <code>private</code>, or generic address space.
+The value of the pointer is converted to a sequence of printing characters
+in an implementation-defined manner.</p>
+</div>
+<div class="paragraph">
+<p><strong>%</strong> A <strong>%</strong> character is written.
+No argument is converted.
+The complete conversion specification shall be <strong>%%</strong>.</p>
+</div>
+<div class="paragraph">
+<p>If a conversion specification is invalid, the behavior is undefined.
+If any argument is not the correct type for the corresponding conversion
+specification, the behavior is undefined.</p>
+</div>
+<div class="paragraph">
+<p>In no case does a nonexistent or small field width cause truncation of a
+field; if the result of a conversion is wider than the field width, the
+field is expanded to contain the conversion result.</p>
+</div>
+<div class="paragraph">
+<p>For <strong>a</strong> and <strong>A</strong> conversions, the value is correctly rounded to a hexadecimal
+floating number with the given precision.</p>
+</div>
+<div class="paragraph">
+<p>A few examples of printf are given below:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">float4  f = (float4)(<span class="float">1</span><span class="float">.0f</span>, <span class="float">2</span><span class="float">.0f</span>, <span class="float">3</span><span class="float">.0f</span>, <span class="float">4</span><span class="float">.0f</span>);
+uchar4 uc = (uchar4)(<span class="hex">0xFA</span>, <span class="hex">0xFB</span>, <span class="hex">0xFC</span>, <span class="hex">0xFD</span>);
+
+printf(<span class="string"><span class="delimiter">&quot;</span><span class="content">f4 = %2.2v4hlf</span><span class="char">\n</span><span class="delimiter">&quot;</span></span>, f);
+printf(<span class="string"><span class="delimiter">&quot;</span><span class="content">uc = %#v4hhx</span><span class="char">\n</span><span class="delimiter">&quot;</span></span>, uc);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The above two printf calls print the following:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">f4 = <span class="float">1</span><span class="float">.00</span>,<span class="float">2</span><span class="float">.00</span>,<span class="float">3</span><span class="float">.00</span>,<span class="float">4</span><span class="float">.00</span>
+uc = <span class="hex">0xfa</span>,<span class="hex">0xfb</span>,<span class="hex">0xfc</span>,<span class="hex">0xfd</span></code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>A few examples of valid use cases of printf for the conversion specifier <strong>s</strong>
+are given below.
+The argument value must be a pointer to a literal string.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">kernel <span class="directive">void</span> my_kernel( ... )
+{
+    printf(<span class="string"><span class="delimiter">&quot;</span><span class="content">%s</span><span class="char">\n</span><span class="delimiter">&quot;</span></span>, <span class="string"><span class="delimiter">&quot;</span><span class="content">this is a test string</span><span class="char">\n</span><span class="delimiter">&quot;</span></span>);
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>A few examples of invalid use cases of printf for the conversion specifier
+<strong>s</strong> are given below:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">kernel <span class="directive">void</span> my_kernel(global <span class="predefined-type">char</span> *s, ... )
+{
+    printf(<span class="string"><span class="delimiter">&quot;</span><span class="content">%s</span><span class="char">\n</span><span class="delimiter">&quot;</span></span>, s);
+    constant <span class="predefined-type">char</span> *p = <span class="string"><span class="delimiter">&quot;</span><span class="content">`this is a test string</span><span class="char">\n</span><span class="content">`</span><span class="delimiter">&quot;</span></span>;
+    printf(<span class="string"><span class="delimiter">&quot;</span><span class="content">%s</span><span class="char">\n</span><span class="delimiter">&quot;</span></span>, p);
+    printf(<span class="string"><span class="delimiter">&quot;</span><span class="content">%s</span><span class="char">\n</span><span class="delimiter">&quot;</span></span>, &amp;p[<span class="integer">3</span>]);
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>A few examples of invalid use cases of printf where data types given by the
+vector specifier and length modifier do not match the argument type are
+given below:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">kernel <span class="directive">void</span> my_kernel(global <span class="predefined-type">char</span> *s, ... )
+{
+    uint2 ui = (uint2)(<span class="hex">0x12345678</span>, <span class="hex">0x87654321</span>);
+
+    printf(<span class="string"><span class="delimiter">&quot;</span><span class="content">unsigned short value = (%#v2hx)</span><span class="char">\n</span><span class="delimiter">&quot;</span></span>, ui)
+    printf(<span class="string"><span class="delimiter">&quot;</span><span class="content">unsigned char value = (%#v2hhx)</span><span class="char">\n</span><span class="delimiter">&quot;</span></span>, ui)
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="differences-between-opencl-c-and-c99-printf">Differences between OpenCL C and C99 printf</h5>
+<div class="ulist">
+<ul>
+<li>
+<p>The <strong>l</strong> modifier followed by a <strong>c</strong> conversion specifier or <strong>s</strong>
+conversion specifier is not supported by OpenCL C.</p>
+</li>
+<li>
+<p>The <strong>ll</strong>, <strong>j</strong>, <strong>z</strong>, <strong>t</strong>, and <strong>L</strong> length modifiers are not supported by
+OpenCL C but are reserved.</p>
+</li>
+<li>
+<p>The <strong>n</strong> conversion specifier is not supported by OpenCL C but is
+reserved.</p>
+</li>
+<li>
+<p>OpenCL C adds the optional *v*<em>n</em> vector specifier to support printing
+of vector types.</p>
+</li>
+<li>
+<p>The conversion specifiers <strong>f</strong>, <strong>F</strong>, <strong>e</strong>, <strong>E</strong>, <strong>g</strong>, <strong>G</strong>, <strong>a</strong>, <strong>A</strong> convert
+a <code>float</code> argument to a <code>double</code> only if the <code>double</code> data type is
+supported.
+Refer to the value of the <a href="#opencl-device-queries"><code>CL_DEVICE_DOUBLE_FP_CONFIG</code> device query</a>.
+If the <code>double</code> data type is not supported, the argument will be a
+<code>float</code> instead of a <code>double</code>.</p>
+</li>
+<li>
+<p>For the embedded profile, the <strong>l</strong> length modifier is supported only if
+64-bit integers are supported.</p>
+</li>
+<li>
+<p>In OpenCL C, <strong>printf</strong> returns 0 if it was executed successfully and -1
+otherwise vs.
+C99 where <strong>printf</strong> returns the number of characters printed or a
+negative value if an output or encoding error occurred.</p>
+</li>
+<li>
+<p>In OpenCL C, the conversion specifier <strong>s</strong> can only be used for arguments
+that are literal strings.</p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="image-read-and-write-functions">1.13.14. Image Read and Write Functions</h4>
+<div class="paragraph">
+<p>The built-in functions defined in this section can only be used with image
+memory objects.
+An image memory object can be accessed by specific function calls that read
+from and/or write to specific locations in the image.</p>
+</div>
+<div class="paragraph">
+<p>Image memory objects that are being read by a kernel should be declared with
+the <code>read_only</code> qualifier.
+<strong>write_image</strong> calls to image memory objects declared with the read_only
+qualifier will generate a compilation error.
+Image memory objects that are being written to by a kernel should be
+declared with the write_only qualifier.
+<strong>read_image</strong> calls to image memory objects declared with the <code>write_only</code>
+qualifier will generate a compilation error.
+<strong>read_image</strong> and <strong>write_image</strong> calls to the same image memory object in a
+kernel are supported.
+Image memory objects that are being read and written by a kernel should be
+declared with the <code>read_write</code> qualifier.</p>
+</div>
+<div class="paragraph">
+<p>The <strong>read_image</strong> calls returns a four component floating-point, integer or
+unsigned integer color value.
+The color values returned by <strong>read_image</strong> are identified as <em>x</em>, <em>y</em>, <em>z</em>,
+<em>w</em> where <em>x</em> refers to the red component, <em>y</em> refers to the green
+component, <em>z</em> refers to the blue component and <em>w</em> refers to the alpha
+component.</p>
+</div>
+<div class="sect4">
+<h5 id="samplers">Samplers</h5>
+<div class="paragraph">
+<p>The image read functions take a sampler argument.
+The sampler can be passed as an argument to the kernel using
+<strong>clSetKernelArg</strong>, or can be declared in the outermost scope of kernel
+functions, or it can be a constant variable of type <code>sampler_t</code> declared in
+the program source.</p>
+</div>
+<div class="paragraph">
+<p>Sampler variables in a program are declared to be of type <code>sampler_t</code>.
+A variable of <code>sampler_t</code> type declared in the program source must be
+initialized with a 32-bit unsigned integer constant, which is interpreted as
+a bit-field specifiying the following properties:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Addressing Mode</p>
+</li>
+<li>
+<p>Filter Mode</p>
+</li>
+<li>
+<p>Normalized Coordinates</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>These properties control how elements of an image object are read by
+<strong>read_image{f|i|ui}</strong>.</p>
+</div>
+<div class="paragraph">
+<p>Samplers can also be declared as global constants in the program source
+using the following syntax.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="directive">const</span> sampler_t &lt;sampler name&gt; = &lt;value&gt;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>or</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">constant sampler_t &lt;sampler name&gt; = &lt;value&gt;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>or</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">__constant sampler_t &lt;sampler_name&gt; = &lt;value&gt;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Note that samplers declared using the <code>constant</code> qualifier are not counted
+towards the maximum number of arguments pointing to the constant address
+space or the maximum size of the <code>constant</code> address space allowed per device
+(i.e. the value of the <a href="#opencl-device-queries"><code>CL_DEVICE_MAX_CONSTANT_ARGS</code></a> and <a href="#opencl-device-queries"><code>CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE</code></a> device queries).</p>
+</div>
+<div class="paragraph">
+<p>The sampler fields are described in the following table.</p>
+</div>
+<table id="table-sampler-descriptor" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 21. Sampler Descriptor</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Sampler State</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>&lt;normalized coords&gt;</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Specifies whether the <em>x</em>, <em>y</em> and <em>z</em> coordinates are passed in as
+      normalized or unnormalized values.
+      This must be a literal value and can be one of the following
+      predefined enums:</p>
+<p class="tableblock">      <code>CLK_NORMALIZED_COORDS_TRUE</code> or <code>CLK_NORMALIZED_COORDS_FALSE</code>.</p>
+<p class="tableblock">      The samplers used with an image in multiple calls to
+      <strong>read_image{f|i|ui}</strong> declared in a kernel must use the same value
+      for &lt;normalized coords&gt;.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>&lt;addressing mode&gt;</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Specifies the image addressing mode, i.e. how out-of-range image
+      coordinates are handled.
+      This must be a literal value and can be one of the following
+      predefined enums:</p>
+<p class="tableblock">      <code>CLK_ADDRESS_MIRRORED_REPEAT</code> - Flip the image coordinate at every
+      integer junction.
+      This addressing mode can only be used with normalized coordinates.
+      If normalized coordinates are not used, this addressing mode may
+      generate image coordinates that are undefined.</p>
+<p class="tableblock">      <code>CLK_ADDRESS_REPEAT</code> - out-of-range image coordinates are wrapped to
+      the valid range.
+      This addressing mode can only be used with normalized coordinates.
+      If normalized coordinates are not used, this addressing mode may
+      generate image coordinates that are undefined.</p>
+<p class="tableblock">      <code>CLK_ADDRESS_CLAMP_TO_EDGE</code> - out-of-range image coordinates are
+      clamped to the extent.</p>
+<p class="tableblock">      <code>CLK_ADDRESS_CLAMP</code><sup>57</sup> - out-of-range image coordinates will return a
+      border color.</p>
+<p class="tableblock">      <code>CLK_ADDRESS_NONE</code> - for this addressing mode the programmer
+      guarantees that the image coordinates used to sample elements of the
+      image refer to a location inside the image; otherwise the results are
+      undefined.</p>
+<p class="tableblock">      For 1D and 2D image arrays, the addressing mode applies only to the
+      <em>x</em> and (<em>x, y</em>) coordinates.
+      The addressing mode for the coordinate which specifies the array index
+      is always <code>CLK_ADDRESS_CLAMP_TO_EDGE</code>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>&lt;filter mode&gt;</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Specifies the filter mode to use.
+      This must be a literal value and can be one of the following
+      predefined enums: <code>CLK_FILTER_NEAREST</code> or <code>CLK_FILTER_LINEAR</code>.</p>
+<p class="tableblock">      Refer to the <a href="#addressing-and-filter-modes">detailed description of
+      these filter modes</a>.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>[57] This is similar to the <code>GL_ADDRESS_CLAMP_TO_BORDER</code> addressing mode.</p>
+</div>
+<div class="paragraph">
+<p><strong>Examples</strong>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="directive">const</span> sampler_t samplerA = CLK_NORMALIZED_COORDS_TRUE |
+                           CLK_ADDRESS_REPEAT |
+                           CLK_FILTER_NEAREST;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><code>samplerA</code> specifies a sampler that uses normalized coordinates, the repeat
+addressing mode and a nearest filter.</p>
+</div>
+<div class="paragraph">
+<p>The maximum number of samplers that can be declared in a kernel can be
+queried using the <code>CL_DEVICE_MAX_SAMPLERS</code> token in <strong>clGetDeviceInfo</strong>.</p>
+</div>
+<div class="sect5">
+<h6 id="determining-the-border-color-or-value"><strong>Determining the border color or value</strong></h6>
+<div class="paragraph">
+<p>If <code>&lt;addressing mode&gt;</code> in sampler is <code>CLK_ADDRESS_CLAMP</code>, then out-of-range
+image coordinates return the border color.
+The border color selected depends on the image channel order and can be one
+of the following values:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>If the image channel order is <code>CL_A</code>, <code>CL_INTENSITY</code>, <code>CL_Rx</code>,
+<code>CL_RA</code>, <code>CL_RGx</code>, <code>CL_RGBx</code>, <code>CL_sRGBx</code>, <code>CL_ARGB</code>, <code>CL_BGRA</code>,
+<code>CL_ABGR</code>, <code>CL_RGBA</code>, <code>CL_sRGBA</code> or <code>CL_sBGRA</code>, the border color is
+<code>(0.0f, 0.0f, 0.0f, 0.0f)</code>.</p>
+</li>
+<li>
+<p>If the image channel order is <code>CL_R</code>, <code>CL_RG</code>, <code>CL_RGB</code>, or
+<code>CL_LUMINANCE</code>, the border color is <code>(0.0f, 0.0f, 0.0f, 1.0f)</code>.</p>
+</li>
+<li>
+<p>If the image channel order is <code>CL_DEPTH</code>, the border value is <code>0.0f</code>.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect5">
+<h6 id="srgb-images"><strong>sRGB Images</strong></h6>
+<div class="paragraph">
+<p>The built-in image read functions will perform sRGB to linear RGB
+conversions if the image is an sRGB image.
+Writing to sRGB images from a kernel is an optional extension.
+The <strong>cl_khr_srgb_image_writes</strong> extension will be reported in the
+<code>CL_DEVICE_EXTENSIONS</code> string if a device supports writing to sRGB images
+using <strong>write_imagef</strong>.
+<strong>clGetSupportedImageFormats</strong> will return the supported sRGB images if
+<code>CL_MEM_READ_WRITE</code> or <code>CL_MEM_WRITE_ONLY</code> is specified in <em>flags</em> argument
+and the device supports writing to an sRGB image.
+If <strong>cl_khr_srgb_image_writes</strong> is supported, the built-in image write
+functions will perform the linear to sRGB conversion.</p>
+</div>
+<div class="paragraph">
+<p>Only the R, G and B components are converted from linear to sRGB and
+vice-versa.
+The alpha component is returned as is.</p>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="built-in-image-read-functions">Built-in Image Read Functions</h5>
+<div class="paragraph">
+<p>The following built-in function calls to read images with a sampler<sup>58</sup> are
+supported.</p>
+</div>
+<div class="paragraph">
+<p>[58] The built-in function calls to read images with a sampler are not
+supported for <code>image1d_buffer_t</code> image types.</p>
+</div>
+<table id="table-image-read" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 22. Built-in Image Read Functions</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Function</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">float4 <strong>read_imagef</strong>(read_only image2d_t <em>image</em>, sampler_t <em>sampler</em>,
+  int2 <em>coord</em>)<br>
+  float4 <strong>read_imagef</strong>(read_only image2d_t <em>image</em>, sampler_t <em>sampler</em>,
+  float2 <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use the coordinate (<em>coord.x</em>, <em>coord.y</em>) to do an element lookup in
+      the 2D image object specified by <em>image</em>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns floating-point values in the range [0.0, 1.0]
+      for image objects created with <em>image_channel_data_type</em> set to one of
+      the pre-defined packed formats or <code>CL_UNORM_INT8</code>, or
+      <code>CL_UNORM_INT16</code>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns floating-point values in the range [-1.0, 1.0]
+      for image objects created with <em>image_channel_data_type</em> set to
+      <code>CL_SNORM_INT8</code>, or <code>CL_SNORM_INT16</code>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns floating-point values for image objects created
+      with <em>image_channel_data_type</em> set to <code>CL_HALF_FLOAT</code> or <code>CL_FLOAT</code>.</p>
+<p class="tableblock">      The <strong>read_imagef</strong> calls that take integer coordinates must use a
+      sampler with filter mode set to <code>CLK_FILTER_NEAREST</code>, normalized
+      coordinates set to <code>CLK_NORMALIZED_COORDS_FALSE</code> and addressing mode
+      set to <code>CLK_ADDRESS_CLAMP_TO_EDGE</code>, <code>CLK_ADDRESS_CLAMP</code> or
+      <code>CLK_ADDRESS_NONE</code>; otherwise the values returned are undefined.</p>
+<p class="tableblock">      Values returned by <strong>read_imagef</strong> for image objects with
+      <em>image_channel_data_type</em> values not specified in the description
+      above are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int4 <strong>read_imagei</strong>(read_only image2d_t <em>image</em>, sampler_t <em>sampler</em>,
+  int2 <em>coord</em>)<br>
+  int4 <strong>read_imagei</strong>(read_only image2d_t <em>image</em>, sampler_t <em>sampler</em>,
+  float2 <em>coord</em>)<br>
+  uint4 <strong>read_imageui</strong>(read_only image2d_t <em>image</em>, sampler_t <em>sampler</em>,
+  int2 <em>coord</em>)<br>
+  uint4 <strong>read_imageui</strong>(read_only image2d_t <em>image</em>, sampler_t <em>sampler</em>,
+  float2 <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use the coordinate (<em>coord.x</em>, <em>coord.y</em>) to do an element lookup in
+      the 2D image object specified by <em>image</em>.</p>
+<p class="tableblock">      <strong>read_imagei</strong> and <strong>read_imageui</strong> return unnormalized signed integer
+      and unsigned integer values respectively.
+      Each channel will be stored in a 32-bit integer.</p>
+<p class="tableblock">      <strong>read_imagei</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the following values:</p>
+<p class="tableblock">      <code>CL_SIGNED_INT8</code>,<br>
+      <code>CL_SIGNED_INT16</code> and<br>
+      <code>CL_SIGNED_INT32</code>.</p>
+<p class="tableblock">      If the <em>image_channel_data_type</em> is not one of the above values, the
+      values returned by <strong>read_imagei</strong> are undefined.</p>
+<p class="tableblock">      <strong>read_imageui</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the following values:</p>
+<p class="tableblock">      <code>CL_UNSIGNED_INT8</code>,<br>
+      <code>CL_UNSIGNED_INT16</code> and<br>
+      <code>CL_UNSIGNED_INT32</code>.</p>
+<p class="tableblock">      If the <em>image_channel_data_type</em> is not one of the above values, the
+      values returned by <strong>read_imageui</strong> are undefined.</p>
+<p class="tableblock">      The <strong>read_image{i|ui}</strong> calls support a nearest filter only.
+      The filter_mode specified in <em>sampler</em> must be set to
+      <code>CLK_FILTER_NEAREST</code>; otherwise the values returned are undefined.</p>
+<p class="tableblock">      Furthermore, the <strong>read_image{i|ui}</strong> calls that take integer
+      coordinates must use a sampler with normalized coordinates set to
+      <code>CLK_NORMALIZED_COORDS_FALSE</code> and addressing mode set to
+      <code>CLK_ADDRESS_CLAMP_TO_EDGE</code>, <code>CLK_ADDRESS_CLAMP</code> or
+      <code>CLK_ADDRESS_NONE</code>; otherwise the values returned are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">float4 <strong>read_imagef</strong>(read_only image3d_t <em>image</em>, sampler_t <em>sampler</em>,
+  int4 <em>coord</em> )<br>
+  float4 <strong>read_imagef</strong>(read_only image3d_t <em>image</em>, sampler_t <em>sampler</em>,
+  float4 <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use the coordinate (<em>coord.x</em>, <em>coord.y</em>, <em>coord.z</em>) to do an element
+      lookup in the 3D image object specified by <em>image</em>.
+      <em>coord.w</em> is ignored.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns floating-point values in the range [0.0, 1.0]
+      for image objects created with <em>image_channel_data_type</em> set to one of
+      the pre-defined packed formats or <code>CL_UNORM_INT8</code>, or
+      <code>CL_UNORM_INT16</code>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns floating-point values in the range [-1.0, 1.0]
+      for image objects created with <em>image_channel_data_type</em> set to
+      <code>CL_SNORM_INT8</code>, or <code>CL_SNORM_INT16</code>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns floating-point values for image objects created
+      with <em>image_channel_data_type</em> set to <code>CL_HALF_FLOAT</code> or <code>CL_FLOAT</code>.</p>
+<p class="tableblock">      The <strong>read_imagef</strong> calls that take integer coordinates must use a
+      sampler with filter mode set to <code>CLK_FILTER_NEAREST</code>, normalized
+      coordinates set to <code>CLK_NORMALIZED_COORDS_FALSE</code> and addressing mode
+      set to <code>CLK_ADDRESS_CLAMP_TO_EDGE</code>, <code>CLK_ADDRESS_CLAMP</code> or
+      <code>CLK_ADDRESS_NONE</code>; otherwise the values returned are undefined.</p>
+<p class="tableblock">      Values returned by <strong>read_imagef</strong> for image objects with
+      <em>image_channel_data_type</em> values not specified in the description are
+      undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int4 <strong>read_imagei</strong>(read_only image3d_t <em>image</em>, sampler_t <em>sampler</em>,
+  int4 <em>coord</em>)<br>
+  int4 <strong>read_imagei</strong>(read_only image3d_t <em>image</em>, sampler_t <em>sampler</em>,
+  float4 <em>coord</em>)<br>
+  uint4 <strong>read_imageui</strong>(read_only image3d_t <em>image</em>, sampler_t <em>sampler</em>,
+  int4 <em>coord</em>)<br>
+  uint4 <strong>read_imageui</strong>(read_only image3d_t <em>image</em>, sampler_t <em>sampler</em>,
+  float4 <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use the coordinate (<em>coord.x</em>, <em>coord.y</em>, <em>coord.z</em>) to do an element
+      lookup in the 3D image object specified by <em>image</em>.
+      <em>coord.w</em> is ignored.</p>
+<p class="tableblock">      <strong>read_imagei</strong> and <strong>read_imageui</strong> return unnormalized signed integer
+      and unsigned integer values respectively.
+      Each channel will be stored in a 32-bit integer.</p>
+<p class="tableblock">      <strong>read_imagei</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the following values:</p>
+<p class="tableblock">      <code>CL_SIGNED_INT8</code>,<br>
+      <code>CL_SIGNED_INT16</code> and<br>
+      <code>CL_SIGNED_INT32</code>.</p>
+<p class="tableblock">      If the <em>image_channel_data_type</em> is not one of the above values, the
+      values returned by <strong>read_imagei</strong> are undefined.</p>
+<p class="tableblock">      <strong>read_imageui</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the following values:</p>
+<p class="tableblock">      <code>CL_UNSIGNED_INT8</code>,<br>
+      <code>CL_UNSIGNED_INT16</code> and<br>
+      <code>CL_UNSIGNED_INT32</code>.</p>
+<p class="tableblock">      If the <em>image_channel_data_type</em> is not one of the above values, the
+      values returned by <strong>read_imageui</strong> are undefined.</p>
+<p class="tableblock">      The <strong>read_image{i|ui}</strong> calls support a nearest filter only.
+      The filter_mode specified in <em>sampler</em> must be set to
+      <code>CLK_FILTER_NEAREST</code>; otherwise the values returned are undefined.</p>
+<p class="tableblock">      Furthermore, the <strong>read_image{i|ui}</strong> calls that take integer
+      coordinates must use a sampler with normalized coordinates set to
+      <code>CLK_NORMALIZED_COORDS_FALSE</code> and addressing mode set to
+      <code>CLK_ADDRESS_CLAMP_TO_EDGE</code>, <code>CLK_ADDRESS_CLAMP</code> or
+      <code>CLK_ADDRESS_NONE</code>; otherwise the values returned are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">float4 <strong>read_imagef</strong>(read_only image2d_array_t <em>image</em>,
+  sampler_t <em>sampler</em>, int4 <em>coord</em>)<br>
+  float4 <strong>read_imagef</strong>(read_only image2d_array_t <em>image</em>,
+  sampler_t <em>sampler</em>, float4 <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use <em>coord.xy</em> to do an element lookup in the 2D image identified by
+      <em>coord.z</em> in the 2D image array specified by <em>image</em>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns floating-point values in the range [0.0, 1.0]
+      for image objects created with image_channel_data_type set to one of
+      the pre-defined packed formats or <code>CL_UNORM_INT8</code>, or
+      <code>CL_UNORM_INT16</code>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns floating-point values in the range [-1.0, 1.0]
+      for image objects created with image_channel_data_type set to
+      <code>CL_SNORM_INT8</code>, or <code>CL_SNORM_INT16</code>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns floating-point values for image objects created
+      with image_channel_data_type set to <code>CL_HALF_FLOAT</code> or <code>CL_FLOAT</code>.</p>
+<p class="tableblock">      The <strong>read_imagef</strong> calls that take integer coordinates must use a
+      sampler with filter mode set to <code>CLK_FILTER_NEAREST</code>, normalized
+      coordinates set to <code>CLK_NORMALIZED_COORDS_FALSE</code> and addressing mode
+      set to <code>CLK_ADDRESS_CLAMP_TO_EDGE</code>, <code>CLK_ADDRESS_CLAMP</code> or
+      <code>CLK_ADDRESS_NONE</code>; otherwise the values returned are undefined.</p>
+<p class="tableblock">      Values returned by <strong>read_imagef</strong> for image objects with
+      image_channel_data_type values not specified in the description above
+      are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int4 <strong>read_imagei</strong>(read_only image2d_array_t <em>image</em>, sampler_t <em>sampler</em>,
+  int4 <em>coord</em>)<br>
+  int4 <strong>read_imagei</strong>(read_only image2d_array_t <em>image</em>, sampler_t <em>sampler</em>,
+  float4 <em>coord</em>)<br>
+  uint4 <strong>read_imageui</strong>(read_only image2d_array_t <em>image</em>,
+  sampler_t <em>sampler</em>, int4 <em>coord</em>)<br>
+  uint4 <strong>read_imageui</strong>(read_only image2d_array_t <em>image</em>,
+  sampler_t <em>sampler</em>, float4 <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use <em>coord.xy</em> to do an element lookup in the 2D image identified by
+      <em>coord.z</em> in the 2D image array specified by <em>image</em>.</p>
+<p class="tableblock">      <strong>read_imagei</strong> and <strong>read_imageui</strong> return unnormalized signed integer
+      and unsigned integer values respectively.
+      Each channel will be stored in a 32-bit integer.</p>
+<p class="tableblock">      <strong>read_imagei</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the following values:</p>
+<p class="tableblock">      <code>CL_SIGNED_INT8</code>,<br>
+      <code>CL_SIGNED_INT16</code> and<br>
+      <code>CL_SIGNED_INT32</code>.</p>
+<p class="tableblock">      If the <em>image_channel_data_type</em> is not one of the above values, the
+      values returned by <strong>read_imagei</strong> are undefined.</p>
+<p class="tableblock">      <strong>read_imageui</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the following values:</p>
+<p class="tableblock">      <code>CL_UNSIGNED_INT8</code>,<br>
+      <code>CL_UNSIGNED_INT16</code> and<br>
+      <code>CL_UNSIGNED_INT32</code>.</p>
+<p class="tableblock">      If the <em>image_channel_data_type</em> is not one of the above values, the
+      values returned by <strong>read_imageui</strong> are undefined.</p>
+<p class="tableblock">      The <strong>read_image{i|ui}</strong> calls support a nearest filter only.
+      The filter_mode specified in <em>sampler</em> must be set to
+      <code>CLK_FILTER_NEAREST</code>; otherwise the values returned are undefined.</p>
+<p class="tableblock">      Furthermore, the <strong>read_image{i|ui}</strong> calls that take integer
+      coordinates must use a sampler with normalized coordinates set to
+      <code>CLK_NORMALIZED_COORDS_FALSE</code> and addressing mode set to
+      <code>CLK_ADDRESS_CLAMP_TO_EDGE</code>, <code>CLK_ADDRESS_CLAMP</code> or
+      <code>CLK_ADDRESS_NONE</code>; otherwise the values returned are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">float4 <strong>read_imagef</strong>(read_only image1d_t <em>image</em>, sampler_t <em>sampler</em>,
+  int <em>coord</em>)<br>
+  float4 <strong>read_imagef</strong>(read_only image1d_t <em>image</em>, sampler_t <em>sampler</em>,
+  float <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use <em>coord</em> to do an element lookup in the 1D image object specified
+      by <em>image</em>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns floating-point values in the range [0.0, 1.0]
+      for image objects created with <em>image_channel_data_type</em> set to one of
+      the pre-defined packed formats or <code>CL_UNORM_INT8</code>, or
+      <code>CL_UNORM_INT16</code>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns floating-point values in the range [-1.0, 1.0]
+      for image objects created with <em>image_channel_data_type</em> set to
+      <code>CL_SNORM_INT8</code>, or <code>CL_SNORM_INT16</code>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns floating-point values for image objects created
+      with <em>image_channel_data_type</em> set to <code>CL_HALF_FLOAT</code> or <code>CL_FLOAT</code>.</p>
+<p class="tableblock">      The <strong>read_imagef</strong> calls that take integer coordinates must use a
+      sampler with filter mode set to <code>CLK_FILTER_NEAREST</code>, normalized
+      coordinates set to <code>CLK_NORMALIZED_COORDS_FALSE</code> and addressing mode
+      set to <code>CLK_ADDRESS_CLAMP_TO_EDGE</code>, <code>CLK_ADDRESS_CLAMP</code> or
+      <code>CLK_ADDRESS_NONE</code>; otherwise the values returned are undefined.</p>
+<p class="tableblock">      Values returned by <strong>read_imagef</strong> for image objects with
+      <em>image_channel_data_type</em> values not specified in the description
+      above are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int4 <strong>read_imagei</strong>(read_only image1d_t <em>image</em>, sampler_t <em>sampler</em>,
+  int <em>coord</em>)<br>
+  int4 <strong>read_imagei</strong>(read_only image1d_t <em>image</em>, sampler_t <em>sampler</em>,
+  float <em>coord</em>)<br>
+  uint4 <strong>read_imageui</strong>(read_only image1d_t <em>image</em>, sampler_t <em>sampler</em>,
+  int <em>coord</em>)<br>
+  uint4 <strong>read_imageui</strong>(read_only image1d_t <em>image</em>, sampler_t <em>sampler</em>,
+  float <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use <em>coord</em> to do an element lookup in the 1D image object specified
+      by <em>image</em>.</p>
+<p class="tableblock">      <strong>read_imagei</strong> and <strong>read_imageui</strong> return unnormalized signed integer
+      and unsigned integer values respectively.
+      Each channel will be stored in a 32-bit integer.</p>
+<p class="tableblock">      <strong>read_imagei</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the following values:</p>
+<p class="tableblock">      <code>CL_SIGNED_INT8</code>,<br>
+      <code>CL_SIGNED_INT16</code> and<br>
+      <code>CL_SIGNED_INT32</code>.</p>
+<p class="tableblock">      If the <em>image_channel_data_type</em> is not one of the above values, the
+      values returned by <strong>read_imagei</strong> are undefined.</p>
+<p class="tableblock">      <strong>read_imageui</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the following values:</p>
+<p class="tableblock">      <code>CL_UNSIGNED_INT8</code>,<br>
+      <code>CL_UNSIGNED_INT16</code> and<br>
+      <code>CL_UNSIGNED_INT32</code>.</p>
+<p class="tableblock">      If the <em>image_channel_data_type</em> is not one of the above values, the
+      values returned by <strong>read_imageui</strong> are undefined.</p>
+<p class="tableblock">      The <strong>read_image{i|ui}</strong> calls support a nearest filter only.
+      The filter_mode specified in <em>sampler</em> must be set to
+      <code>CLK_FILTER_NEAREST</code>; otherwise the values returned are undefined.</p>
+<p class="tableblock">      Furthermore, the <strong>read_image{i|ui}</strong> calls that take integer
+      coordinates must use a sampler with normalized coordinates set to
+      <code>CLK_NORMALIZED_COORDS_FALSE</code> and addressing mode set to
+      <code>CLK_ADDRESS_CLAMP_TO_EDGE</code>, <code>CLK_ADDRESS_CLAMP</code> or
+      <code>CLK_ADDRESS_NONE</code>; otherwise the values returned are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">float4 <strong>read_imagef</strong>(read_only image1d_array_t <em>image</em>,
+  sampler_t <em>sampler</em>, int2 <em>coord</em>)<br>
+  float4 <strong>read_imagef</strong>(read_only image1d_array_t <em>image</em>,
+  sampler_t <em>sampler</em>, float2 <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use <em>coord.x</em> to do an element lookup in the 1D image identified by
+      <em>coord.y</em> in the 1D image array specified by <em>image</em>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns floating-point values in the range [0.0, 1.0]
+      for image objects created with image_channel_data_type set to one of
+      the pre-defined packed formats or <code>CL_UNORM_INT8</code>, or
+      <code>CL_UNORM_INT16</code>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns floating-point values in the range [-1.0, 1.0]
+      for image objects created with image_channel_data_type set to
+      <code>CL_SNORM_INT8</code>, or <code>CL_SNORM_INT16</code>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns floating-point values for image objects created
+      with image_channel_data_type set to <code>CL_HALF_FLOAT</code> or <code>CL_FLOAT</code>.</p>
+<p class="tableblock">      The <strong>read_imagef</strong> calls that take integer coordinates must use a
+      sampler with filter mode set to <code>CLK_FILTER_NEAREST</code>, normalized
+      coordinates set to <code>CLK_NORMALIZED_COORDS_FALSE</code> and addressing mode
+      set to <code>CLK_ADDRESS_CLAMP_TO_EDGE</code>, <code>CLK_ADDRESS_CLAMP</code> or
+      <code>CLK_ADDRESS_NONE</code>; otherwise the values returned are undefined.</p>
+<p class="tableblock">      Values returned by <strong>read_imagef</strong> for image objects with
+      image_channel_data_type values not specified in the description above
+      are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int4 <strong>read_imagei</strong>(read_only image1d_array_t <em>image</em>, sampler_t <em>sampler</em>,
+  int2 <em>coord</em>)<br>
+  int4 <strong>read_imagei</strong>(read_only image1d_array_t <em>image</em>, sampler_t <em>sampler</em>,
+  float2 <em>coord</em>)<br>
+  uint4 <strong>read_imageui</strong>(read_only image1d_array_t <em>image</em>,
+  sampler_t <em>sampler</em>, int2 <em>coord</em>)<br>
+  uint4 <strong>read_imageui</strong>(read_only image1d_array_t <em>image</em>,
+  sampler_t <em>sampler</em>, float2 <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use <em>coord.x</em> to do an element lookup in the 1D image identified by
+      <em>coord.y</em> in the 1D image array specified by <em>image</em>.</p>
+<p class="tableblock">      <strong>read_imagei</strong> and <strong>read_imageui</strong> return unnormalized signed integer
+      and unsigned integer values respectively. Each channel will be stored
+      in a 32-bit integer.</p>
+<p class="tableblock">      <strong>read_imagei</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the following values:</p>
+<p class="tableblock">      <code>CL_SIGNED_INT8</code>,<br>
+      <code>CL_SIGNED_INT16</code> and<br>
+      <code>CL_SIGNED_INT32</code>.</p>
+<p class="tableblock">      If the <em>image_channel_data_type</em> is not one of the above values, the
+      values returned by <strong>read_imagei</strong> are undefined.</p>
+<p class="tableblock">      <strong>read_imageui</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the following values:</p>
+<p class="tableblock">      <code>CL_UNSIGNED_INT8</code>,<br>
+      <code>CL_UNSIGNED_INT16</code> and<br>
+      <code>CL_UNSIGNED_INT32</code>.</p>
+<p class="tableblock">      If the <em>image_channel_data_type</em> is not one of the above values, the
+      values returned by <strong>read_imageui</strong> are undefined.</p>
+<p class="tableblock">      The <strong>read_image{i|ui}</strong> calls support a nearest filter only.
+      The filter_mode specified in <em>sampler</em> must be set to
+      <code>CLK_FILTER_NEAREST</code>; otherwise the values returned are undefined.</p>
+<p class="tableblock">      Furthermore, the <strong>read_image{i|ui}</strong> calls that take integer
+      coordinates must use a sampler with normalized coordinates set to
+      <code>CLK_NORMALIZED_COORDS_FALSE</code> and addressing mode set to
+      <code>CLK_ADDRESS_CLAMP_TO_EDGE</code>, <code>CLK_ADDRESS_CLAMP</code> or
+      <code>CLK_ADDRESS_NONE</code>; otherwise the values returned are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">float <strong>read_imagef</strong>(read_only image2d_depth_t <em>image</em>,
+  sampler_t <em>sampler</em>, int2 <em>coord</em>)<br>
+  float <strong>read_imagef</strong>(read_only image2d_depth_t <em>image</em>,
+  sampler_t <em>sampler</em>, float2 <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use the coordinate (<em>coord.x</em>, <em>coord.y</em>) to do an element lookup in
+      the 2D depth image object specified by <em>image</em>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns a floating-point value in the range [0.0, 1.0]
+      for depth image objects created with <em>image_channel_data_type</em> set to
+      <code>CL_UNORM_INT16</code> or <code>CL_UNORM_INT24</code>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns a floating-point value for depth image objects
+      created with <em>image_channel_data_type</em> set to <code>CL_FLOAT</code>.</p>
+<p class="tableblock">      The <strong>read_imagef</strong> calls that take integer coordinates must use a
+      sampler with filter mode set to <code>CLK_FILTER_NEAREST</code>, normalized
+      coordinates set to <code>CLK_NORMALIZED_COORDS_FALSE</code> and addressing mode
+      set to <code>CLK_ADDRESS_CLAMP_TO_EDGE</code>, <code>CLK_ADDRESS_CLAMP</code> or
+      <code>CLK_ADDRESS_NONE</code>; otherwise the values returned are undefined.</p>
+<p class="tableblock">      Values returned by <strong>read_imagef</strong> for depth image objects with
+      <em>image_channel_data_type</em> values not specified in the description
+      above are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">float <strong>read_imagef</strong>(read_only image2d_array_depth_t <em>image</em>,
+  sampler_t <em>sampler</em>, int4 <em>coord</em>)<br>
+  float <strong>read_imagef</strong>(read_only image2d_array_depth_t <em>image</em>,
+  sampler_t <em>sampler</em>, float4 <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use <em>coord.xy</em> to do an element lookup in the 2D image identified by
+      <em>coord.z</em> in the 2D depth image array specified by <em>image</em>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns a floating-point value in the range [0.0, 1.0]
+      for depth image objects created with <em>image_channel_data_type</em> set to
+      <code>CL_UNORM_INT16</code> or <code>CL_UNORM_INT24</code>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns a floating-point value for depth image objects
+      created with <em>image_channel_data_type</em> set to <code>CL_FLOAT</code>.</p>
+<p class="tableblock">      The <strong>read_imagef</strong> calls that take integer coordinates must use a
+      sampler with filter mode set to <code>CLK_FILTER_NEAREST</code>, normalized
+      coordinates set to <code>CLK_NORMALIZED_COORDS_FALSE</code> and addressing mode
+      set to <code>CLK_ADDRESS_CLAMP_TO_EDGE</code>, <code>CLK_ADDRESS_CLAMP</code> or
+      <code>CLK_ADDRESS_NONE</code>; otherwise the values returned are undefined.</p>
+<p class="tableblock">      Values returned by <strong>read_imagef</strong> for image objects with
+      <em>image_channel_data_type</em> values not specified in the description
+      above are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect4">
+<h5 id="built-in-image-sampler-less-read-functions">Built-in Image Sampler-less Read Functions</h5>
+<div class="paragraph">
+<p>The sampler-less image read functions behave exactly as the corresponding
+<a href="#built-in-image-read-functions">built-in image read functions</a> that take
+integer coordinates and a sampler with filter mode set to
+<code>CLK_FILTER_NEAREST</code>, normalized coordinates set to
+<code>CLK_NORMALIZED_COORDS_FALSE</code> and addressing mode to <code>CLK_ADDRESS_NONE</code>.</p>
+</div>
+<div class="paragraph">
+<p><em>aQual</em> in the following table refers to one of the access qualifiers.
+For samplerless read functions this may be <code>read_only</code> or <code>read_write</code>.</p>
+</div>
+<table id="table-image-samplerless-read" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 23. Built-in Image Sampler-less Read Functions</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Function</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">float4 <strong>read_imagef</strong>(<em>aQual</em> image2d_t <em>image</em>, int2 <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use the coordinate (<em>coord.x</em>, <em>coord.y</em>) to do an element lookup in
+      the 2D image object specified by <em>image</em>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns floating-point values in the range [0.0, 1.0]
+      for image objects created with <em>image_channel_data_type</em> set to one of
+      the pre-defined packed formats or <code>CL_UNORM_INT8</code>, or
+      <code>CL_UNORM_INT16</code>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns floating-point values in the range [-1.0, 1.0]
+      for image objects created with <em>image_channel_data_type</em> set to
+      <code>CL_SNORM_INT8</code>, or <code>CL_SNORM_INT16</code>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns floating-point values for image objects created
+      with <em>image_channel_data_type</em> set to <code>CL_HALF_FLOAT</code> or <code>CL_FLOAT</code>.</p>
+<p class="tableblock">      Values returned by <strong>read_imagef</strong> for image objects with
+      <em>image_channel_data_type</em> values not specified in the description
+      above are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int4 <strong>read_imagei</strong>(<em>aQual</em> image2d_t <em>image</em>, int2 <em>coord</em>)<br>
+  uint4 <strong>read_imageui</strong>(<em>aQual</em> image2d_t <em>image</em>, int2 <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use the coordinate (<em>coord.x</em>, <em>coord.y</em>) to do an element lookup in
+      the 2D image object specified by <em>image</em>.</p>
+<p class="tableblock">      <strong>read_imagei</strong> and <strong>read_imageui</strong> return unnormalized signed integer
+      and unsigned integer values respectively. Each channel will be stored
+      in a 32-bit integer.</p>
+<p class="tableblock">      <strong>read_imagei</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the following values:</p>
+<p class="tableblock">      <code>CL_SIGNED_INT8</code>,<br>
+      <code>CL_SIGNED_INT16</code> and<br>
+      <code>CL_SIGNED_INT32</code>.</p>
+<p class="tableblock">      If the <em>image_channel_data_type</em> is not one of the above values, the
+      values returned by <strong>read_imagei</strong> are undefined.</p>
+<p class="tableblock">      <strong>read_imageui</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the following values:</p>
+<p class="tableblock">      <code>CL_UNSIGNED_INT8</code>,<br>
+      <code>CL_UNSIGNED_INT16</code> and<br>
+      <code>CL_UNSIGNED_INT32</code>.</p>
+<p class="tableblock">      If the <em>image_channel_data_type</em> is not one of the above values, the
+      values returned by <strong>read_imageui</strong> are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">float4 <strong>read_imagef</strong>(<em>aQual</em> image3d_t <em>image</em>, int4 <em>coord</em> )</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use the coordinate (<em>coord.x</em>, <em>coord.y</em>, <em>coord.z</em>) to do an element
+      lookup in the 3D image object specified by <em>image</em>.
+      <em>coord.w</em> is ignored.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns floating-point values in the range [0.0, 1.0]
+      for image objects created with <em>image_channel_data_type</em> set to one of
+      the pre-defined packed formats or <code>CL_UNORM_INT8</code>, or
+      <code>CL_UNORM_INT16</code>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns floating-point values in the range [-1.0, 1.0]
+      for image objects created with <em>image_channel_data_type</em> set to
+      <code>CL_SNORM_INT8</code>, or <code>CL_SNORM_INT16</code>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns floating-point values for image objects created
+      with <em>image_channel_data_type</em> set to <code>CL_HALF_FLOAT</code> or <code>CL_FLOAT</code>.</p>
+<p class="tableblock">      Values returned by <strong>read_imagef</strong> for image objects with
+      <em>image_channel_data_type</em> values not specified in the description are
+      undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int4 <strong>read_imagei</strong>(<em>aQual</em> image3d_t <em>image</em>, int4 <em>coord</em>)<br>
+  uint4 <strong>read_imageui</strong>(<em>aQual</em> image3d_t <em>image</em>, int4 <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use the coordinate (<em>coord.x</em>, <em>coord.y</em>, <em>coord.z</em>) to do an element
+      lookup in the 3D image object specified by <em>image</em>.
+      <em>coord.w</em> is ignored.</p>
+<p class="tableblock">      <strong>read_imagei</strong> and <strong>read_imageui</strong> return unnormalized signed integer
+      and unsigned integer values respectively.
+      Each channel will be stored in a 32-bit integer.</p>
+<p class="tableblock">      <strong>read_imagei</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the following values:</p>
+<p class="tableblock">      <code>CL_SIGNED_INT8</code>,<br>
+      <code>CL_SIGNED_INT16</code> and<br>
+      <code>CL_SIGNED_INT32</code>.</p>
+<p class="tableblock">      If the <em>image_channel_data_type</em> is not one of the above values, the
+      values returned by <strong>read_imagei</strong> are undefined.</p>
+<p class="tableblock">      <strong>read_imageui</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the following values:</p>
+<p class="tableblock">      <code>CL_UNSIGNED_INT8</code>,<br>
+      <code>CL_UNSIGNED_INT16</code> and<br>
+      <code>CL_UNSIGNED_INT32</code>.</p>
+<p class="tableblock">      If the <em>image_channel_data_type</em> is not one of the above values, the
+      values returned by <strong>read_imageui</strong> are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">float4 <strong>read_imagef</strong>(<em>aQual</em> image2d_array_t <em>image</em>, int4 <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use <em>coord.xy</em> to do an element lookup in the 2D image identified by
+      <em>coord.z</em> in the 2D image array specified by <em>image</em>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns floating-point values in the range [0.0, 1.0]
+      for image objects created with <em>image_channel_data_type</em> set to one of
+      the pre-defined packed formats or <code>CL_UNORM_INT8</code>, or
+      <code>CL_UNORM_INT16</code>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns floating-point values in the range [-1.0, 1.0]
+      for image objects created with <em>image_channel_data_type</em> set to
+      <code>CL_SNORM_INT8</code>, or <code>CL_SNORM_INT16</code>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns floating-point values for image objects created
+      with <em>image_channel_data_type</em> set to <code>CL_HALF_FLOAT</code> or <code>CL_FLOAT</code>.</p>
+<p class="tableblock">      Values returned by <strong>read_imagef</strong> for image objects with
+      <em>image_channel_data_type</em> values not specified in the description
+      above are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int4 <strong>read_imagei</strong>(<em>aQual</em> image2d_array_t <em>image</em>, int4 <em>coord</em>)<br>
+  uint4 <strong>read_imageui</strong>(<em>aQual</em> image2d_array_t <em>image</em>, int4 <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use <em>coord.xy</em> to do an element lookup in the 2D image identified by
+      <em>coord.z</em> in the 2D image array specified by <em>image</em>.</p>
+<p class="tableblock">      <strong>read_imagei</strong> and <strong>read_imageui</strong> return unnormalized signed integer
+      and unsigned integer values respectively. Each channel will be stored
+      in a 32-bit integer.</p>
+<p class="tableblock">      <strong>read_imagei</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the following values:</p>
+<p class="tableblock">      <code>CL_SIGNED_INT8</code>,<br>
+      <code>CL_SIGNED_INT16</code> and<br>
+      <code>CL_SIGNED_INT32</code>.</p>
+<p class="tableblock">      If the <em>image_channel_data_type</em> is not one of the above values, the
+      values returned by <strong>read_imagei</strong> are undefined.</p>
+<p class="tableblock">      <strong>read_imageui</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the following values:</p>
+<p class="tableblock">      <code>CL_UNSIGNED_INT8</code>,<br>
+      <code>CL_UNSIGNED_INT16</code> and<br>
+      <code>CL_UNSIGNED_INT32</code>.</p>
+<p class="tableblock">      If the <em>image_channel_data_type</em> is not one of the above values, the
+      values returned by <strong>read_imageui</strong> are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">float4 <strong>read_imagef</strong>(<em>aQual</em> image1d_t <em>image</em>, int <em>coord</em>)<br>
+  float4 <strong>read_imagef</strong>(<em>aQual</em> image1d_buffer_t <em>image</em>, int <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use <em>coord</em> to do an element lookup in the 1D image or 1D image buffer
+      object specified by <em>image</em>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns floating-point values in the range [0.0, 1.0]
+      for image objects created with <em>image_channel_data_type</em> set to one of
+      the pre-defined packed formats or <code>CL_UNORM_INT8</code>, or
+      <code>CL_UNORM_INT16</code>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns floating-point values in the range [-1.0, 1.0]
+      for image objects created with <em>image_channel_data_type</em> set to
+      <code>CL_SNORM_INT8</code>, or <code>CL_SNORM_INT16</code>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns floating-point values for image objects created
+      with <em>image_channel_data_type</em> set to <code>CL_HALF_FLOAT</code> or <code>CL_FLOAT</code>.</p>
+<p class="tableblock">      Values returned by <strong>read_imagef</strong> for image objects with
+      <em>image_channel_data_type</em> values not specified in the description
+      above are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int4 <strong>read_imagei</strong>(<em>aQual</em> image1d_t <em>image</em>, int <em>coord</em>)<br>
+  uint4 <strong>read_imageui</strong>(<em>aQual</em> image1d_t <em>image</em>, int <em>coord</em>)<br>
+  int4 <strong>read_imagei</strong>(<em>aQual</em> image1d_buffer_t <em>image</em>, int <em>coord</em>)<br>
+  uint4 <strong>read_imageui</strong>(<em>aQual</em> image1d_buffer_t <em>image</em>, int <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use <em>coord</em> to do an element lookup in the 1D image or 1D image buffer
+      object specified by <em>image</em>.</p>
+<p class="tableblock">      <strong>read_imagei</strong> and <strong>read_imageui</strong> return unnormalized signed integer
+      and unsigned integer values respectively. Each channel will be stored
+      in a 32-bit integer.</p>
+<p class="tableblock">      <strong>read_imagei</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the following values:</p>
+<p class="tableblock">      <code>CL_SIGNED_INT8</code>,<br>
+      <code>CL_SIGNED_INT16</code> and<br>
+      <code>CL_SIGNED_INT32</code>.</p>
+<p class="tableblock">      If the <em>image_channel_data_type</em> is not one of the above values, the
+      values returned by <strong>read_imagei</strong> are undefined.</p>
+<p class="tableblock">      <strong>read_imageui</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the following values:</p>
+<p class="tableblock">      <code>CL_UNSIGNED_INT8</code>,<br>
+      <code>CL_UNSIGNED_INT16</code> and<br>
+      <code>CL_UNSIGNED_INT32</code>.</p>
+<p class="tableblock">      If the <em>image_channel_data_type</em> is not one of the above values, the
+      values returned by <strong>read_imageui</strong> are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">float4 <strong>read_imagef</strong>(<em>aQual</em> image1d_array_t <em>image</em>, int2 <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use <em>coord.x</em> to do an element lookup in the 1D image identified by
+      <em>coord.y</em> in the 1D image array specified by <em>image</em>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns floating-point values in the range [0.0, 1.0]
+      for image objects created with <em>image_channel_data_type</em> set to one of
+      the pre-defined packed formats or <code>CL_UNORM_INT8</code>, or
+      <code>CL_UNORM_INT16</code>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns floating-point values in the range [-1.0, 1.0]
+      for image objects created with <em>image_channel_data_type</em> set to
+      <code>CL_SNORM_INT8</code>, or <code>CL_SNORM_INT16</code>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns floating-point values for image objects created
+      with <em>image_channel_data_type</em> set to <code>CL_HALF_FLOAT</code> or <code>CL_FLOAT</code>.</p>
+<p class="tableblock">      Values returned by <strong>read_imagef</strong> for image objects with
+      <em>image_channel_data_type</em> values not specified in the description
+      above are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int4 <strong>read_imagei</strong>(<em>aQual</em> image1d_array_t <em>image</em>, int2 <em>coord</em>)<br>
+  uint4 <strong>read_imageui</strong>(<em>aQual</em> image1d_array_t <em>image</em>, int2 <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use <em>coord.x</em> to do an element lookup in the 1D image identified by
+      <em>coord.y</em> in the 1D image array specified by <em>image</em>.</p>
+<p class="tableblock">      <strong>read_imagei</strong> and <strong>read_imageui</strong> return unnormalized signed integer
+      and unsigned integer values respectively. Each channel will be stored
+      in a 32-bit integer.</p>
+<p class="tableblock">      <strong>read_imagei</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the following values:</p>
+<p class="tableblock">      <code>CL_SIGNED_INT8</code>,<br>
+      <code>CL_SIGNED_INT16</code> and<br>
+      <code>CL_SIGNED_INT32</code>.</p>
+<p class="tableblock">      If the <em>image_channel_data_type</em> is not one of the above values, the
+      values returned by <strong>read_imagei</strong> are undefined.</p>
+<p class="tableblock">      <strong>read_imageui</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the following values:</p>
+<p class="tableblock">      <code>CL_UNSIGNED_INT8</code>,<br>
+      <code>CL_UNSIGNED_INT16</code> and<br>
+      <code>CL_UNSIGNED_INT32</code>.</p>
+<p class="tableblock">      If the <em>image_channel_data_type</em> is not one of the above values, the
+      values returned by <strong>read_imageui</strong> are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">float <strong>read_imagef</strong>(<em>aQual</em> image2d_depth_t <em>image</em>, int2 <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use the coordinate (<em>coord.x</em>, <em>coord.y</em>) to do an element lookup in
+      the 2D depth image object specified by <em>image</em>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns a floating-point value in the range [0.0, 1.0]
+      for depth image objects created with <em>image_channel_data_type</em> set to
+      <code>CL_UNORM_INT16</code> or <code>CL_UNORM_INT24</code>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns a floating-point value for depth image objects
+      created with <em>image_channel_data_type</em> set to <code>CL_FLOAT</code>.</p>
+<p class="tableblock">      Values returned by <strong>read_imagef</strong> for image objects with
+      <em>image_channel_data_type</em> values not specified in the description
+      above are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">float <strong>read_imagef</strong>(<em>aQual</em> image2d_array_depth_t <em>image</em>, int4 <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use <em>coord.xy</em> to do an element lookup in the 2D image identified by
+      <em>coord.z</em> in the 2D depth image array specified by <em>image</em>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns a floating-point value in the range [0.0, 1.0]
+      for depth image objects created with <em>image_channel_data_type</em> set to
+      <code>CL_UNORM_INT16</code> or <code>CL_UNORM_INT24</code>.</p>
+<p class="tableblock">      <strong>read_imagef</strong> returns a floating-point value for depth image objects
+      created with <em>image_channel_data_type</em> set to <code>CL_FLOAT</code>.</p>
+<p class="tableblock">      Values returned by <strong>read_imagef</strong> for image objects with
+      <em>image_channel_data_type</em> values not specified in the description
+      above are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect4">
+<h5 id="built-in-image-write-functions">Built-in Image Write Functions</h5>
+<div class="paragraph">
+<p>The following built-in function calls to write images are supported.
+Note that image writes to sRGB images are only supported if the
+<strong>cl_khr_srgb_image_writes</strong> extension is supported; otherwise the behavior of
+writing to a sRGB image is undefined.</p>
+</div>
+<div class="paragraph">
+<p><em>aQual</em> in the following table refers to one of the access qualifiers.
+For write functions this may be <code>write_only</code> or <code>read_write</code>.</p>
+</div>
+<table id="table-image-write" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 24. Built-in Image Write Functions</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Function</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>write_imagef</strong>(<em>aQual</em> image2d_t <em>image</em>, int2 <em>coord</em>, float4 <em>color</em>)<br>
+  void <strong>write_imagei</strong>(<em>aQual</em> image2d_t <em>image</em>, int2 <em>coord</em>, int4 <em>color</em>)<br>
+  void <strong>write_imageui</strong>(<em>aQual</em> image2d_t <em>image</em>, int2 <em>coord</em>, uint4 <em>color</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Write <em>color</em> value to location specified by <em>coord.xy</em> in the 2D
+      image object specified by <em>image</em>.
+      Appropriate data format conversion to the specified image format is
+      done before writing the color value.
+      <em>coord.x</em> and <em>coord.y</em> are considered to be unnormalized coordinates,
+      and must be in the range [0, image width-1] and [0, image height-1]
+      respectively.</p>
+<p class="tableblock">      <strong>write_imagef</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the pre-defined packed formats
+      or set to <code>CL_SNORM_INT8</code>, <code>CL_UNORM_INT8</code>, <code>CL_SNORM_INT16</code>,
+      <code>CL_UNORM_INT16</code>, <code>CL_HALF_FLOAT</code> or <code>CL_FLOAT</code>.
+      Appropriate data format conversion will be done to convert channel
+      data from a floating-point value to actual data format in which the
+      channels are stored.</p>
+<p class="tableblock">      <strong>write_imagei</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the following values:</p>
+<p class="tableblock">      <code>CL_SIGNED_INT8</code>,<br>
+      <code>CL_SIGNED_INT16</code> and<br>
+      <code>CL_SIGNED_INT32</code>.</p>
+<p class="tableblock">      <strong>write_imageui</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the following values:</p>
+<p class="tableblock">      <code>CL_UNSIGNED_INT8</code>,<br>
+      <code>CL_UNSIGNED_INT16</code> and<br>
+      <code>CL_UNSIGNED_INT32</code>.</p>
+<p class="tableblock">      The behavior of <strong>write_imagef</strong>, <strong>write_imagei</strong> and <strong>write_imageui</strong> for
+      image objects created with <em>image_channel_data_type</em> values not
+      specified in the description above or with <em>x</em> and <em>y</em> coordinate
+      values that are not in the range [0, image width-1] and [0, image
+      height-1], respectively, is undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>write_imagef</strong>(<em>aQual</em> image2d_array_t <em>image</em>, int4 <em>coord</em>,
+  float4 <em>color</em>)<br>
+  void <strong>write_imagei</strong>(<em>aQual</em> image2d_array_t <em>image</em>, int4 <em>coord</em>,
+  int4 <em>color</em>)<br>
+  void <strong>write_imageui</strong>(<em>aQual</em> image2d_array_t <em>image</em>, int4 <em>coord</em>,
+  uint4 <em>color</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Write <em>color</em> value to location specified by <em>coord.xy</em> in the 2D
+      image identified by <em>coord.z</em> in the 2D image array specified by
+      <em>image</em>.
+      Appropriate data format conversion to the specified image format is
+      done before writing the color value.
+      <em>coord.x</em>, <em>coord.y</em> and <em>coord.z</em> are considered to be unnormalized
+      coordinates, and must be in the range [0, image width-1] and [0, image
+      height-1], and [0, image number of layers-1], respectively.</p>
+<p class="tableblock">      <strong>write_imagef</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the pre-defined packed formats
+      or set to <code>CL_SNORM_INT8</code>, <code>CL_UNORM_INT8</code>, <code>CL_SNORM_INT16</code>,
+      <code>CL_UNORM_INT16</code>, <code>CL_HALF_FLOAT</code> or <code>CL_FLOAT</code>.
+      Appropriate data format conversion will be done to convert channel
+      data from a floating-point value to actual data format in which the
+      channels are stored.</p>
+<p class="tableblock">      <strong>write_imagei</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the following values:</p>
+<p class="tableblock">      <code>CL_SIGNED_INT8</code>,<br>
+      <code>CL_SIGNED_INT16</code> and<br>
+      <code>CL_SIGNED_INT32</code>.</p>
+<p class="tableblock">      <strong>write_imageui</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the following values:</p>
+<p class="tableblock">      <code>CL_UNSIGNED_INT8</code>,<br>
+      <code>CL_UNSIGNED_INT16</code> and<br>
+      <code>CL_UNSIGNED_INT32</code>.</p>
+<p class="tableblock">      The behavior of <strong>write_imagef</strong>, <strong>write_imagei</strong> and <strong>write_imageui</strong> for
+      image objects created with <em>image_channel_data_type</em> values not
+      specified in the description above or with (<em>x</em>, <em>y</em>, <em>z</em>) coordinate
+      values that are not in the range [0, image width-1], [0, image
+      height-1], and [0, image number of layers-1], respectively, is
+      undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>write_imagef</strong>(<em>aQual</em> image1d_t <em>image</em>, int <em>coord</em>,
+  float4 <em>color</em>)<br>
+  void <strong>write_imagei</strong>(<em>aQual</em> image1d_t <em>image</em>, int <em>coord</em>,
+  int4 <em>color</em>)<br>
+  void <strong>write_imageui</strong>(<em>aQual</em> image1d_t <em>image</em>, int <em>coord</em>,
+  uint4 <em>color</em>)<br>
+  void <strong>write_imagef</strong>(<em>aQual</em> image1d_buffer_t <em>image</em>, int <em>coord</em>,
+  float4 <em>color</em>)<br>
+  void <strong>write_imagei</strong>(<em>aQual</em> image1d_buffer_t <em>image</em>, int <em>coord</em>,
+  int4 <em>color</em>)<br>
+  void <strong>write_imageui</strong>(<em>aQual</em> image1d_buffer_t <em>image</em>, int <em>coord</em>,
+  uint4 <em>color</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Write <em>color</em> value to location specified by <em>coord</em> in the 1D image
+      or 1D image buffer object specified by <em>image</em>.
+      Appropriate data format conversion to the specified image format is
+      done before writing the color value.
+      <em>coord</em> is considered to be an unnormalized coordinate, and must be in
+      the range [0, image width-1].</p>
+<p class="tableblock">      <strong>write_imagef</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the pre-defined packed formats
+      or set to <code>CL_SNORM_INT8</code>, <code>CL_UNORM_INT8</code>, <code>CL_SNORM_INT16</code>,
+      <code>CL_UNORM_INT16</code>, <code>CL_HALF_FLOAT</code> or <code>CL_FLOAT</code>.
+      Appropriate data format conversion will be done to convert channel
+      data from a floating-point value to actual data format in which the
+      channels are stored.</p>
+<p class="tableblock">      <strong>write_imagei</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the following values:</p>
+<p class="tableblock">      <code>CL_SIGNED_INT8</code>,<br>
+      <code>CL_SIGNED_INT16</code> and<br>
+      <code>CL_SIGNED_INT32</code>.</p>
+<p class="tableblock">      <strong>write_imageui</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the following values:</p>
+<p class="tableblock">      <code>CL_UNSIGNED_INT8</code>,<br>
+      <code>CL_UNSIGNED_INT16</code> and<br>
+      <code>CL_UNSIGNED_INT32</code>.</p>
+<p class="tableblock">      The behavior of <strong>write_imagef</strong>, <strong>write_imagei</strong> and <strong>write_imageui</strong> for
+      image objects created with <em>image_channel_data_type</em> values not
+      specified in the description above, or with a coordinate value that is
+      not in the range [0, image width-1], is undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>write_imagef</strong>(<em>aQual</em> image1d_array_t <em>image</em>, int2 <em>coord</em>,
+  float4 <em>color</em>)<br>
+  void <strong>write_imagei</strong>(<em>aQual</em> image1d_array_t <em>image</em>, int2 <em>coord</em>,
+  int4 <em>color</em>)<br>
+  void <strong>write_imageui</strong>(<em>aQual</em> image1d_array_t <em>image</em>, int2 <em>coord</em>,
+  uint4 <em>color</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Write <em>color</em> value to location specified by <em>coord.x</em> in the 1D image
+      identified by <em>coord.y</em> in the 1D image array specified by <em>image</em>.
+      Appropriate data format conversion to the specified image format is
+      done before writing the color value.
+      <em>coord.x</em> and <em>coord.y</em> are considered to be unnormalized coordinates
+      and must be in the range [0, image width-1] and [0, image number of
+      layers-1], respectively.</p>
+<p class="tableblock">      <strong>write_imagef</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the pre-defined packed formats
+      or set to <code>CL_SNORM_INT8</code>, <code>CL_UNORM_INT8</code>, <code>CL_SNORM_INT16</code>,
+      <code>CL_UNORM_INT16</code>, <code>CL_HALF_FLOAT</code> or <code>CL_FLOAT</code>.
+      Appropriate data format conversion will be done to convert channel
+      data from a floating-point value to actual data format in which the
+      channels are stored.</p>
+<p class="tableblock">      <strong>write_imagei</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the following values:</p>
+<p class="tableblock">      <code>CL_SIGNED_INT8</code>,<br>
+      <code>CL_SIGNED_INT16</code> and<br>
+      <code>CL_SIGNED_INT32</code>.</p>
+<p class="tableblock">      <strong>write_imageui</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to one of the following values:</p>
+<p class="tableblock">      <code>CL_UNSIGNED_INT8</code>,<br>
+      <code>CL_UNSIGNED_INT16</code> and<br>
+      <code>CL_UNSIGNED_INT32</code>.</p>
+<p class="tableblock">      The behavior of <strong>write_imagef</strong>, <strong>write_imagei</strong> and <strong>write_imageui</strong> for
+      image objects created with <em>image_channel_data_type</em> values not
+      specified in the description above or with (<em>x</em>, <em>y</em>) coordinate
+      values that are not in the range [0, image width-1] and [0, image
+      number of layers-1], respectively, is undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>write_imagef</strong>(<em>aQual</em> image2d_depth_t <em>image</em>, int2 <em>coord</em>,
+  float <em>depth</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Write <em>depth</em> value to location specified by <em>coord.xy</em> in the 2D
+      depth image object specified by <em>image</em>.
+      Appropriate data format conversion to the specified image format is
+      done before writing the depth value.
+      <em>coord.x</em> and <em>coord.y</em> are considered to be unnormalized coordinates,
+      and must be in the range [0, image width-1], and [0, image height-1],
+      respectively.</p>
+<p class="tableblock">      <strong>write_imagef</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to <code>CL_UNORM_INT16</code>, <code>CL_UNORM_INT24</code> or
+      <code>CL_FLOAT</code>.
+      Appropriate data format conversion will be done to convert depth valye
+      from a floating-point value to actual data format associated with the
+      image.</p>
+<p class="tableblock">      The behavior of <strong>write_imagef</strong>, <strong>write_imagei</strong> and <strong>write_imageui</strong> for
+      image objects created with <em>image_channel_data_type</em> values not
+      specified in the description above or with (<em>x</em>, <em>y</em>) coordinate
+      values that are not in the range [0, image width-1] and [0, image
+      height-1], respectively, is undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>write_imagef</strong>(<em>aQual</em> image2d_array_depth_t <em>image</em>, int4 <em>coord</em>,
+  float <em>depth</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Write <em>depth</em> value to location specified by <em>coord.xy</em> in the 2D
+      image identified by <em>coord.z</em> in the 2D depth image array specified by
+      <em>image</em>.
+      Appropriate data format conversion to the specified image format is
+      done before writing the depth value.
+      <em>coord.x</em>, <em>coord.y</em> and <em>coord.z</em> are considered to be unnormalized
+      coordinates, and must be in the range [0, image width-1], [0, image
+      height-1], and [0, image number of layers-1], respectively.</p>
+<p class="tableblock">      <strong>write_imagef</strong> can only be used with image objects created with
+      <em>image_channel_data_type</em> set to <code>CL_UNORM_INT16</code>, <code>CL_UNORM_INT24</code> or
+      <code>CL_FLOAT</code>.
+      Appropriate data format conversion will be done to convert depth valye
+      from a floating-point value to actual data format associated with the
+      image.</p>
+<p class="tableblock">      The behavior of <strong>write_imagef</strong>, <strong>write_imagei</strong> and <strong>write_imageui</strong> for
+      image objects created with <em>image_channel_data_type</em> values not
+      specified in the description above or with (<em>x</em>, <em>y</em>, <em>z</em>) coordinate
+      values that are not in the range [0, image width-1], [0, image
+      height-1], [0, image number of layers-1], respectively, is undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>write_imagef</strong>(<em>aQual</em> image3d_t <em>image</em>, int4 <em>coord</em>,
+  float4 <em>color</em>)<br>
+  void <strong>write_imagei</strong>(<em>aQual</em> image3d_t <em>image</em>, int4 <em>coord</em>,
+  int4 <em>color</em>)<br>
+  void <strong>write_imageui</strong>(<em>aQual</em> image3d_t <em>image</em>, int4 <em>coord</em>,
+  uint4 <em>color</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Write color value to location specified by <em>coord.xyz</em> in the 3D image
+      object specified by <em>image</em>.
+      Appropriate data format conversion to the specified image format is
+      done before writing the color value.
+      <em>coord.x</em>, <em>coord.y</em> and <em>coord.z</em> are considered to be unnormalized
+      coordinates, and must be in the range [0, image width-1], [0, image
+      height-1], and [0, image depth-1], respectively.</p>
+<p class="tableblock">      <strong>write_imagef</strong> can only be used with image objects created with
+      image_channel_data_type set to one of the pre-defined packed formats
+      or set to <code>CL_SNORM_INT8</code>, <code>CL_UNORM_INT8</code>, <code>CL_SNORM_INT16</code>,
+      <code>CL_UNORM_INT16</code>, <code>CL_HALF_FLOAT</code> or <code>CL_FLOAT</code>.
+      Appropriate data format conversion will be done to convert channel
+      data from a floating-point value to actual data format in which the
+      channels are stored.</p>
+<p class="tableblock">      <strong>write_imagei</strong> can only be used with image objects created with
+      image_channel_data_type set to one of the following values:</p>
+<p class="tableblock">      <code>CL_SIGNED_INT8</code>,<br>
+      <code>CL_SIGNED_INT16</code> and<br>
+      <code>CL_SIGNED_INT32</code>.</p>
+<p class="tableblock">      <strong>write_imageui</strong> can only be used with image objects created with
+      image_channel_data_type set to one of the following values:</p>
+<p class="tableblock">      <code>CL_UNSIGNED_INT8</code>,<br>
+      <code>CL_UNSIGNED_INT16</code> and<br>
+      <code>CL_UNSIGNED_INT32</code>.</p>
+<p class="tableblock">      The behavior of <strong>write_imagef</strong>, <strong>write_imagei</strong> and <strong>write_imageui</strong> for
+      image objects with <em>image_channel_data_type</em> values not specified in
+      the description above or with (<em>x</em>, <em>y</em>, <em>z</em>) coordinate values that
+      are not in the range [0, image width-1], [0, image height-1], and [0,
+      image depth-1], respectively, is undefined.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect4">
+<h5 id="built-in-image-query-functions">Built-in Image Query Functions</h5>
+<div class="paragraph">
+<p>The following built-in function calls to query image information are
+supported.</p>
+</div>
+<div class="paragraph">
+<p><em>aQual</em> in the following table refers to one of the access qualifiers.
+For query functions this may be <code>read_only</code>, <code>write_only</code> or <code>read_write</code>.</p>
+</div>
+<table id="table-image-query" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 25. Built-in Image Query Functions</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Function</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>get_image_width</strong>(<em>aQual</em> image1d_t <em>image</em>)<br>
+  int <strong>get_image_width</strong>(<em>aQual</em> image1d_buffer_t <em>image</em>)<br>
+  int <strong>get_image_width</strong>(<em>aQual</em> image2d_t <em>image</em>)<br>
+  int <strong>get_image_width</strong>(<em>aQual</em> image3d_t <em>image</em>)<br>
+  int <strong>get_image_width</strong>(<em>aQual</em> image1d_array_t <em>image</em>)<br>
+  int <strong>get_image_width</strong>(<em>aQual</em> image2d_array_t <em>image</em>)<br>
+  int <strong>get_image_width</strong>(<em>aQual</em> image2d_depth_t <em>image</em>)<br>
+  int <strong>get_image_width</strong>(<em>aQual</em> image2d_array_depth_t <em>image</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the image width in pixels.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>get_image_height</strong>(<em>aQual</em> image2d_t <em>image</em>)<br>
+  int <strong>get_image_height</strong>(<em>aQual</em> image3d_t <em>image</em>)<br>
+  int <strong>get_image_height</strong>(<em>aQual</em> image2d_array_t <em>image</em>)<br>
+  int <strong>get_image_height</strong>(<em>aQual</em> image2d_depth_t <em>image</em>)<br>
+  int <strong>get_image_height</strong>(<em>aQual</em> image2d_array_depth_t <em>image</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the image height in pixels.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>get_image_depth</strong>(image3d_t <em>image</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the image depth in pixels.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>get_image_channel_data_type</strong>(<em>aQual</em> image1d_t <em>image</em>)<br>
+  int <strong>get_image_channel_data_type</strong>(<em>aQual</em> image1d_buffer_t <em>image</em>)<br>
+  int <strong>get_image_channel_data_type</strong>(<em>aQual</em> image2d_t <em>image</em>)<br>
+  int <strong>get_image_channel_data_type</strong>(<em>aQual</em> image3d_t <em>image</em>)<br>
+  int <strong>get_image_channel_data_type</strong>(<em>aQual</em> image1d_array_t <em>image</em>)<br>
+  int <strong>get_image_channel_data_type</strong>(<em>aQual</em> image2d_array_t <em>image</em>)<br>
+  int <strong>get_image_channel_data_type</strong>(<em>aQual</em> image2d_depth_t <em>image</em>)<br>
+  int <strong>get_image_channel_data_type</strong>(<em>aQual</em> image2d_array_depth_t <em>image</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the channel data type. Valid values are:</p>
+<p class="tableblock">      <code>CLK_SNORM_INT8</code><br>
+      <code>CLK_SNORM_INT16</code><br>
+      <code>CLK_UNORM_INT8</code><br>
+      <code>CLK_UNORM_INT16</code><br>
+      <code>CLK_UNORM_SHORT_565</code><br>
+      <code>CLK_UNORM_SHORT_555</code><br>
+      <code>CLK_UNORM_SHORT_101010</code><br>
+      <code>CLK_SIGNED_INT8</code><br>
+      <code>CLK_SIGNED_INT16</code><br>
+      <code>CLK_SIGNED_INT32</code><br>
+      <code>CLK_UNSIGNED_INT8</code><br>
+      <code>CLK_UNSIGNED_INT16</code><br>
+      <code>CLK_UNSIGNED_INT32</code><br>
+      <code>CLK_HALF_FLOAT</code><br>
+      <code>CLK_FLOAT</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>get_image_channel_order</strong>(<em>aQual</em> image1d_t <em>image</em>)<br>
+  int <strong>get_image_channel_order</strong>(<em>aQual</em> image1d_buffer_t <em>image</em>)<br>
+  int <strong>get_image_channel_order</strong>(<em>aQual</em> image2d_t <em>image</em>)<br>
+  int <strong>get_image_channel_order</strong>(<em>aQual</em> image3d_t <em>image</em>)<br>
+  int <strong>get_image_channel_order</strong>(<em>aQual</em> image1d_array_t <em>image</em>)<br>
+  int <strong>get_image_channel_order</strong>(<em>aQual</em> image2d_array_t <em>image</em>)<br>
+  int <strong>get_image_channel_order</strong>(<em>aQual</em> image2d_depth_t <em>image</em>)<br>
+  int <strong>get_image_channel_order</strong>(<em>aQual</em> image2d_array_depth_t <em>image</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the image channel order. Valid values are:</p>
+<p class="tableblock">      <code>CLK_A</code><br>
+      <code>CLK_R</code><br>
+      <code>CLK_Rx</code><br>
+      <code>CLK_RG</code><br>
+      <code>CLK_RGx</code><br>
+      <code>CLK_RA</code><br>
+      <code>CLK_RGB</code><br>
+      <code>CLK_RGBx</code><br>
+      <code>CLK_RGBA</code><br>
+      <code>CLK_ARGB</code><br>
+      <code>CLK_BGRA</code><br>
+      <code>CLK_INTENSITY</code><br>
+      <code>CLK_LUMINANCE</code><br>
+      <code>CLK_ABGR</code><br>
+      <code>CLK_DEPTH</code><br>
+      <code>CLK_sRGB</code><br>
+      <code>CLK_sRGBx</code><br>
+      <code>CLK_sRGBA</code><br>
+      <code>CLK_sBGRA</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int2 <strong>get_image_dim</strong>(<em>aQual</em> image2d_t <em>image</em>)<br>
+  int2 <strong>get_image_dim</strong>(<em>aQual</em> image2d_array_t <em>image</em>)<br>
+  int2 <strong>get_image_dim</strong>(<em>aQual</em> image2d_depth_t <em>image</em>)<br>
+  int2 <strong>get_image_dim</strong>(<em>aQual</em> image2d_array_depth_t <em>image</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the 2D image width and height as an int2 type.
+      The width is returned in the <em>x</em> component, and the height in the <em>y</em>
+      component.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int4 <strong>get_image_dim</strong>(<em>aQual</em> image3d_t <em>image</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the 3D image width, height, and depth as an <code>int4</code> type.
+      The width is returned in the <em>x</em> component, height in the <em>y</em>
+      component, depth in the <em>z</em> component and the <em>w</em> component is 0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t <strong>get_image_array_size</strong>(<em>aQual</em> image2d_array_t <em>image</em>)<br>
+  size_t <strong>get_image_array_size</strong>(<em>aQual</em> image2d_array_depth_t <em>image</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the number of images in the 2D image array.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">size_t <strong>get_image_array_size</strong>(<em>aQual</em> image1d_array_t <em>image</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the number of images in the 1D image array.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>The values returned by <strong>get_image_channel_data_type</strong> and
+<strong>get_image_channel_order</strong> as specified in <a href="#table-image-query">Built-in Image Query Functions</a> with the
+<code>CLK_</code> prefixes correspond to the <code>CL_</code> prefixes used to describe the
+<a href="#opencl-channel-order">image channel order</a> and
+<a href="#opencl-channel-data-type">data type</a> in the <a href="#opencl-spec">OpenCL
+Specification</a>.
+For example, both <code>CL_UNORM_INT8</code> and <code>CLK_UNORM_INT8</code> refer to an image
+channel data type that is an unnormalized unsigned 8-bit integer.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="reading-and-writing-to-the-same-image-in-a-kernel">Reading and writing to the same image in a kernel</h5>
+<div class="paragraph">
+<p>The <strong>atomic_work_item_fence</strong>(<code>CLK_IMAGE_MEM_FENCE</code>) built-in function can be
+used to make sure that sampler-less writes are visible to later reads by the
+same work-item.
+Only a scope of <code>memory_scope_work_item</code> and an order of
+<code>memory_order_acq_rel</code> is valid for <code>atomic_work_item_fence</code> when passed the
+<code>CLK_IMAGE_MEM_FENCE</code> flag.
+If multiple work-items are writing to and reading from multiple locations in
+an image, the <strong>work_group_barrier</strong>(<code>CLK_IMAGE_MEM_FENCE</code>) should be used.</p>
+</div>
+<div class="paragraph">
+<p>Consider the following example:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">kernel <span class="directive">void</span>
+foo(read_write image2d_t img, ... )
+{
+    int2 coord;
+    coord.x = (<span class="predefined-type">int</span>)get_global_id(<span class="integer">0</span>);
+    coord.y = (<span class="predefined-type">int</span>)get_global_id(<span class="integer">1</span>);
+
+    float4 clr = read_imagef(img, coord);
+    ...
+    write_imagef(img, coord, clr);
+
+    <span class="comment">// required to ensure that following read from image at</span>
+    <span class="comment">// location coord returns the latest color value.</span>
+    atomic_work_item_fence(
+        <span class="error">`</span>CLK_IMAGE_MEM_FENCE<span class="error">`</span>,
+        memory_order_acq_rel,
+        memory_scope_work_item);
+
+    float4 clr_new = read_imagef(img, coord);
+    ...
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="mapping-image-channels-to-color-values-returned-by-read_image-and-color-values-passed-to-write_image-to-image-channels">Mapping image channels to color values returned by read_image and color values passed to write_image to image channels</h5>
+<div class="paragraph">
+<p>The following table describes the mapping of the number of channels of an
+image element to the appropriate components in the <code>float4</code>, <code>int4</code> or
+<code>uint4</code> vector data type for the color values returned by
+<strong>read_image{f|i|ui}</strong> or supplied to <strong>write_image{f|i|ui}</strong>.
+The unmapped components will be set to 0.0 for red, green and blue channels
+and will be set to 1.0 for the alpha channel.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Channel Order</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>float4</code>, <code>int4</code> or <code>uint4</code> <strong>components of channel data</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_R</code>, <code>CL_Rx</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">(r, 0.0, 0.0, 1.0)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_A</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">(0.0, 0.0, 0.0, a)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_RG</code>, <code>CL_RGx</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">(r, g, 0.0, 1.0)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_RA</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">(r, 0.0, 0.0, a)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_RGB</code>, <code>CL_RGBx</code>, <code>CL_sRGB</code>, <code>CL_sRGBx</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">(r, g, b, 1.0)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_RGBA</code>, <code>CL_BGRA</code>, <code>CL_ARGB</code>, <code>CL_ABGR</code>, <code>CL_sRGBA</code>, <code>CL_sBGRA</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">(r, g, b, a)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_INTENSITY</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">(I, I, I, I)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_LUMINANCE</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">(L, L, L, 1.0)</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>For <code>CL_DEPTH</code> images, a scalar value is returned by <strong>read_imagef</strong> or
+supplied to <strong>write_imagef</strong>.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>A kernel that uses a sampler with the <code>CL_ADDRESS_CLAMP</code> addressing mode
+with multiple images may result in additional samplers being used internally
+by an implementation.
+If the same sampler is used with multiple images called via
+<strong>read_image{f|i|ui}</strong>, then it is possible that an implementation may need to
+allocate an additional sampler to handle the different border color values
+that may be needed depending on the image formats being used.
+These implementation allocated samplers will count against the maximum
+sampler values supported by the device and given by
+<code>CL_DEVICE_MAX_SAMPLERS</code>.
+Enqueuing a kernel that requires more samplers than the implementation can
+support will result in a <code>CL_OUT_OF_RESOURCES</code> error being returned.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="work-group-functions">1.13.15. Work-group Functions</h4>
+<div class="paragraph">
+<p>The OpenCL C programming language implements the following built-in
+functions that operate on a work-group level.
+These built-in functions must be encountered by all work-items in a
+work-group executing the kernel.
+We use the generic type name <code>gentype</code> to indicate the built-in data types
+<code>half</code><sup>59</sup>, <code>int</code>, <code>uint</code>, <code>long</code>, <code>ulong</code>, <code>float</code> or <code>double</code><sup>60</sup> as the
+type for the arguments.</p>
+</div>
+<div class="paragraph">
+<p>[59] Only if the <strong>cl_khr_fp16</strong> extension is supported and has been enabled.</p>
+</div>
+<div class="paragraph">
+<p>[60] Only if double precision is supported.</p>
+</div>
+<table id="table-builtin-work-group" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 26. Built-in Work-group Functions</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Function</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>work_group_all</strong>(int <em>predicate</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Evaluates <em>predicate</em> for all work-items in the work-group and returns
+      a non-zero value if <em>predicate</em> evaluates to non-zero for all
+      work-items in the work-group.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>work_group_any</strong>(int <em>predicate</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Evaluates <em>predicate</em> for all work-items in the work-group and returns
+      a non-zero value if <em>predicate</em> evaluates to non-zero for any
+      work-items in the work-group.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>work_group_broadcast</strong>(gentype <em>a</em>, size_t <em>local_id</em>)<br>
+  gentype <strong>work_group_broadcast</strong>(gentype <em>a</em>, size_t <em>local_id<em>x,
+  size_t _local_id_y</em>)<br>
+  gentype <strong>work_group_broadcast</strong>(gentype <em>a</em>, size_t <em>local_id</em>x,
+  size_t _local_id__y, size_t _local_id_z</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Broadcast the value of <em>x</em> for work-item identified by <em>local_id</em> to
+      all work-items in the work-group.</p>
+<p class="tableblock">      <em>local_id</em> must be the same value for all work-items in the
+      work-group.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>work_group_reduce_&lt;op&gt;</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return result of reduction operation specified by <strong>&lt;op&gt;</strong> for all
+      values of <em>x</em> specified by work-items in a work-group.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>work_group_scan_exclusive_&lt;op&gt;</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Do an exclusive scan operation specified by <strong>&lt;op&gt;</strong> of all values
+      specified by work-items in the work-group. The scan results are
+      returned for each work-item.</p>
+<p class="tableblock">      The scan order is defined by increasing 1D linear global ID within the
+      work-group.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>work_group_scan_inclusive_&lt;op&gt;</strong>(gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Do an inclusive scan operation specified by <strong>&lt;op&gt;</strong> of all values
+      specified by work-items in the work-group. The scan results are
+      returned for each work-item.</p>
+<p class="tableblock">      The scan order is defined by increasing 1D linear global ID within the
+      work-group.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>The <strong>&lt;op&gt;</strong> in <strong>work_group_reduce_&lt;op&gt;</strong>, <strong>work_group_scan_exclusive_&lt;op&gt;</strong> and
+<strong>work_group_scan_inclusive_&lt;op&gt;</strong> defines the operator and can be <strong>add</strong>,
+<strong>min</strong> or <strong>max</strong>.</p>
+</div>
+<div class="paragraph">
+<p>The inclusive scan operation takes a binary operator <strong>op</strong> with an identity I
+and <em>n</em> (where <em>n</em> is the size of the work-group) elements [a<sub>0</sub>, a<sub>1</sub>, &#8230;&#8203;
+a<sub>n-1</sub>] and returns [a<sub>0</sub>, (a<sub>0</sub> <strong>op</strong> a<sub>1</sub>), &#8230;&#8203; (a<sub>0</sub> <strong>op</strong> a<sub>1</sub> <strong>op</strong> &#8230;&#8203;
+<strong>op</strong> a<sub>n-1</sub>)].
+If <strong>op</strong> = add, the identity I is 0.
+If <strong>op</strong> = min, the identity I is <code>INT_MAX</code>, <code>UINT_MAX</code>, <code>LONG_MAX</code>,
+<code>ULONG_MAX</code>, for <code>int</code>, <code>uint</code>, <code>long</code>, <code>ulong</code> types and is <code>+INF</code> for
+floating-point types.
+Similarly if <strong>op</strong> = max, the identity I is <code>INT_MIN</code>, 0, <code>LONG_MIN</code>, 0 and
+<code>-INF</code>.</p>
+</div>
+<div class="paragraph">
+<p>Consider the following example:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="directive">void</span> foo(<span class="predefined-type">int</span> *p)
+{
+    ...
+    <span class="predefined-type">int</span> prefix_sum_val = work_group_scan_inclusive_add(
+                            p[get_local_id(<span class="integer">0</span>)]);
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>For the example above, let&#8217;s assume that the work-group size is 8 and <em>p</em>
+points to the following elements [3 1 7 0 4 1 6 3].
+Work-item 0 calls <strong>work_group_scan_inclusive_add</strong> with 3 and returns 3.
+Work-item 1 calls <strong>work_group_scan_inclusive_add</strong> with 1 and returns 4.
+The full set of values returned by <strong>work_group_scan_inclusive_add</strong> for
+work-items 0 &#8230;&#8203; 7 are [3 4 11 11 15 16 22 25].</p>
+</div>
+<div class="paragraph">
+<p>The exclusive scan operation takes a binary associative operator <strong>op</strong> with
+an identity I and n (where n is the size of the work-group) elements [a<sub>0</sub>,
+a<sub>1</sub>, &#8230;&#8203; a<sub>n-1</sub>] and returns [I, a<sub>0</sub>, (a<sub>0</sub> <strong>op</strong> a<sub>1</sub>), &#8230;&#8203; (a<sub>0</sub> <strong>op</strong>
+a<sub>1</sub> <strong>op</strong> &#8230;&#8203; <strong>op</strong> a<sub>n-2</sub>)].
+For the example above, the exclusive scan add operation on the ordered set
+[3 1 7 0 4 1 6 3] would return [0 3 4 11 11 15 16 22].</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>The order of floating-point operations is not guaranteed for the
+<strong>work_group_reduce_&lt;op&gt;</strong>, <strong>work_group_scan_inclusive_&lt;op&gt;</strong> and
+<strong>work_group_scan_exclusive_&lt;op&gt;</strong> built-in functions that operate on <code>half</code>,
+<code>float</code> and <code>double</code> data types.
+The order of these floating-point operations is also non-deterministic for a
+given work-group.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+</div>
+<div class="sect3">
+<h4 id="pipe-functions">1.13.16. Pipe Functions</h4>
+<div class="paragraph">
+<p>A pipe is identified by specifying the <code>pipe</code> keyword with a type.
+The data type specifies the size of each packet in the pipe.
+The <code>pipe</code> keyword is a type modifier.
+When it is applied to another type <strong>T</strong>, the result is a pipe type whose
+elements (or packets) are of type <strong>T</strong>.
+The packet type <strong>T</strong> may be any supported OpenCL C scalar and vector integer
+or floating-point data types, or a user-defined type built from these scalar
+and vector data types.</p>
+</div>
+<div class="paragraph">
+<p>Examples:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">pipe int4 pipeA; <span class="comment">// a pipe with int4 packets</span>
+
+pipe user_type_t pipeB; <span class="comment">// a pipe with user_type_t packets</span></code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The <code>read_only</code> (or <code>__read_only</code>) and <code>write_only</code> (or <code>__write_only</code>)
+qualifiers must be used with the <code>pipe</code> qualifier when a pipe is a parameter
+of a kernel or of a user-defined function to identify if a pipe can be read
+from or written to by a kernel and its callees and enqueued child kernels.
+If no qualifier is specified, <code>read_only</code> is assumed.</p>
+</div>
+<div class="paragraph">
+<p>A kernel cannot read from and write to the same pipe object.
+Using the <code>read_write</code> (or <code>__read_write</code>) qualifier with the <code>pipe</code>
+qualifier is a compilation error.</p>
+</div>
+<div class="paragraph">
+<p>In the following example</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">kernel <span class="directive">void</span>
+foo (read_only pipe fooA_t pipeA,
+     write_only pipe fooB_t pipeB)
+{
+    ...
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><code>pipeA</code> is a read-only pipe object, and <code>pipeB</code> is a write-only pipe object.</p>
+</div>
+<div class="paragraph">
+<p>The macro <code>CLK_NULL_RESERVE_ID</code> refers to an invalid reservation ID.</p>
+</div>
+<div class="sect4">
+<h5 id="restrictions-3">Restrictions</h5>
+<div class="ulist">
+<ul>
+<li>
+<p>Pipes can only be passed as arguments to a function (including kernel
+functions).
+The <a href="#operators">C operators</a> cannot be used with variables declared
+with the pipe qualifier.</p>
+</li>
+<li>
+<p>The <code>pipe</code> qualifier cannot be used with variables declared inside a
+kernel, a structure or union field, a pointer type, an array, global
+variables declared in program scope or the return type of a function.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect4">
+<h5 id="built-in-pipe-read-and-write-functions">Built-in Pipe Read and Write Functions</h5>
+<div class="paragraph">
+<p>The OpenCL C programming language implements the following built-in
+functions that read from or write to a pipe.
+We use the generic type name <code>gentype</code> to indicate the built-in OpenCL C
+scalar or vector integer or floating-point data types<sup>61</sup> or any user defined
+type built from these scalar and vector data types can be used as the type
+for the arguments to the pipe functions listed in the following table.</p>
+</div>
+<div class="paragraph">
+<p>[61] The <code>half</code> scalar and vector types can only be used if the <strong>cl_khr_fp16</strong>
+extension is supported and has been enabled.
+The <code>double</code> scalar and vector types can only be used if <code>double</code> precision
+is supported.</p>
+</div>
+<table id="table-builtin-pipe" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 27. Built-in Pipe Functions</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Function</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>read_pipe</strong>(read_only pipe gentype <em>p</em>, gentype *<em>ptr</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Read packet from pipe <em>p</em> into <em>ptr</em>.
+      Returns 0 if <strong>read_pipe</strong> is successful and a negative value if the
+      pipe is empty.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>write_pipe</strong>(write_only pipe gentype <em>p</em>, const gentype *<em>ptr</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Write packet specified by <em>ptr</em> to pipe <em>p</em>.
+      Returns 0 if <strong>write_pipe</strong> is successful and a negative value if the
+      pipe is full.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>read_pipe</strong>(read_only pipe gentype <em>p</em>, reserve_id_t <em>reserve_id</em>,
+  uint <em>index</em>, gentype *<em>ptr</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Read packet from the reserved area of the pipe referred to by
+      <em>reserve_id</em> and <em>index</em> into <em>ptr</em>.</p>
+<p class="tableblock">      The reserved pipe entries are referred to by indices that go from 0
+      &#8230;&#8203; <em>num_packets</em> - 1.</p>
+<p class="tableblock">      Returns 0 if <strong>read_pipe</strong> is successful and a negative value otherwise.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>write_pipe</strong>(write_only pipe gentype <em>p</em>, reserve_id_t
+  <em>reserve_id</em>, uint <em>index</em>, const gentype *<em>ptr</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Write packet specified by <em>ptr</em> to the reserved area of the pipe
+      referred to by <em>reserve_id</em> and <em>index</em>.</p>
+<p class="tableblock">      The reserved pipe entries are referred to by indices that go from 0
+      &#8230;&#8203; <em>num_packets</em> - 1.</p>
+<p class="tableblock">      Returns 0 if <strong>write_pipe</strong> is successful and a negative value
+      otherwise.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">reserve_id_t <strong>reserve_read_pipe</strong>(read_only pipe gentype <em>p</em>,
+  uint <em>num_packets</em>)<br>
+  reserve_id_t <strong>reserve_write_pipe</strong>(write_only pipe gentype <em>p</em>,
+  uint <em>num_packets</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Reserve <em>num_packets</em> entries for reading from or writing to pipe <em>p</em>.
+      Returns a valid reservation ID if the reservation is successful.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>commit_read_pipe</strong>(read_only pipe gentype <em>p</em>,
+  reserve_id_t <em>reserve_id</em>)<br>
+  void <strong>commit_write_pipe</strong>(write_only pipe gentype <em>p</em>,
+  reserve_id_t <em>reserve_id</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Indicates that all reads and writes to <em>num_packets</em> associated with
+      reservation <em>reserve_id</em> are completed.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">bool <strong>is_valid_reserve_id</strong>(reserve_id_t <em>reserve_id</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return <em>true</em> if <em>reserve_id</em> is a valid reservation ID and <em>false</em>
+      otherwise.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect4">
+<h5 id="built-in-work-group-pipe-read-and-write-functions">Built-in Work-group Pipe Read and Write Functions</h5>
+<div class="paragraph">
+<p>The OpenCL C programming language implements the following built-in pipe
+functions that operate at a work-group level.
+These built-in functions must be encountered by all work-items in a
+work-group executing the kernel with the same argument values; otherwise the
+behavior is undefined.
+We use the generic type name <code>gentype</code> to indicate the built-in OpenCL C
+scalar or vector integer or floating-point data types<sup>62</sup> or any user defined
+type built from these scalar and vector data types can be used as the type
+for the arguments to the pipe functions listed in the following table.</p>
+</div>
+<div class="paragraph">
+<p>[62] The <code>half</code> scalar and vector types can only be used if the <strong>cl_khr_fp16</strong>
+extension is supported and has been enabled.
+The <code>double</code> scalar and vector types can only be used if <code>double</code> precision
+is supported.</p>
+</div>
+<table id="table-builtin-pipe-work-group" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 28. Built-in Pipe Work-group Functions</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Function</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">reserve_id_t <strong>work_group_reserve_read_pipe</strong>(read_only pipe gentype <em>p</em>,
+  uint <em>num_packets</em>)<br>
+  reserve_id_t <strong>work_group_reserve_write_pipe</strong>(write_only pipe gentype <em>p</em>,
+  uint <em>num_packets</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Reserve <em>num_packets</em> entries for reading from or writing to pipe <em>p</em>.
+      Returns a valid reservation ID if the reservation is successful.</p>
+<p class="tableblock">      The reserved pipe entries are referred to by indices that go from 0
+      &#8230;&#8203; <em>num_packets</em> - 1.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>work_group_commit_read_pipe</strong>(read_only pipe gentype <em>p</em>,
+  reserve_id_t <em>reserve_id</em>)
+  void <strong>work_group_commit_write_pipe</strong>(write_only pipe gentype <em>p</em>,
+  reserve_id_t <em>reserve_id</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Indicates that all reads and writes to <em>num_packets</em> associated with
+      reservation <em>reserve_id</em> are completed.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>The <strong>read_pipe</strong> and <strong>write_pipe</strong> functions that take a reservation ID as an
+argument can be used to read from or write to a packet index.
+These built-ins can be used to read from or write to a packet index one or
+multiple times.
+If a packet index that is reserved for writing is not written to using the
+<strong>write_pipe</strong> function, the contents of that packet in the pipe are
+undefined.
+<strong>commit_read_pipe</strong> and <strong>work_group_commit_read_pipe</strong> remove the entries
+reserved for reading from the pipe.
+<strong>commit_write_pipe</strong> and <strong>work_group_commit_write_pipe</strong> ensures that the
+entries reserved for writing are all added in-order as one contiguous set of
+packets to the pipe.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p>There can only be the value of the <a href="#opencl-device-queries"><code>CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS</code> device query</a> reservations active
+(i.e. reservation IDs that have been reserved but not committed) per
+work-item or work-group for a pipe in a kernel executing on a device.</p>
+</div>
+<div class="paragraph">
+<p>Work-item based reservations made by a work-item are ordered in the pipe as
+they are ordered in the program.
+Reservations made by different work-items that belong to the same work-group
+can be ordered using the work-group barrier function.
+The order of work-item based reservations that belong to different
+work-groups is implementation defined.</p>
+</div>
+<div class="paragraph">
+<p>Work-group based reservations made by a work-group are ordered in the pipe
+as they are ordered in the program.
+The order of work-group based reservations by different work-groups is
+implementation defined.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="built-in-pipe-query-functions">Built-in Pipe Query Functions</h5>
+<div class="paragraph">
+<p>The OpenCL C programming language implements the following built-in query
+functions for a pipe.
+We use the generic type name <code>gentype</code> to indicate the built-in OpenCL C
+scalar or vector integer or floating-point data types<sup>63</sup> or any user defined
+type built from these scalar and vector data types can be used as the type
+for the arguments to the pipe functions listed in the following table.</p>
+</div>
+<div class="paragraph">
+<p>[63] The <code>half</code> scalar and vector types can only be used if the <strong>cl_khr_fp16</strong>
+extension is supported and has been enabled.
+The <code>double</code> scalar and vector types can only be used if <code>double</code> precision
+is supported.</p>
+</div>
+<div class="paragraph">
+<p><em>aQual</em> in the following table refers to one of the access qualifiers.
+For pipe query functions this may be <code>read_only</code> or <code>write_only</code>.</p>
+</div>
+<table id="table-builtin-pipe-query" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 29. Built-in Pipe Query Functions</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Function</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">uint <strong>get_pipe_num_packets</strong>(<em>aQual</em> pipe gentype <em>p</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the number of available entries in the pipe.
+      The number of available entries in a pipe is a dynamic value.
+      The value returned should be considered immediately stale.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">uint <strong>get_pipe_max_packets</strong>(<em>aQual</em> pipe gentype <em>p</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the maximum number of packets specified when <em>pipe</em> was
+      created.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect4">
+<h5 id="restrictions-4">Restrictions</h5>
+<div class="paragraph">
+<p>The following behavior is undefined:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>A kernel fails to call <strong>reserve_pipe</strong> before calling <strong>read_pipe</strong> or
+<strong>write_pipe</strong> that take a reservation ID.</p>
+</li>
+<li>
+<p>A kernel calls <strong>read_pipe</strong>, <strong>write_pipe</strong>, <strong>commit_read_pipe</strong> or
+<strong>commit_write_pipe</strong> with an invalid reservation ID.</p>
+</li>
+<li>
+<p>A kernel calls <strong>read_pipe</strong> or <strong>write_pipe</strong> with an valid reservation ID
+but with an <em>index</em> that is not a value in the range [0,
+<em>num_packets</em>-1] specified to the corresponding call to <em>reserve_pipe</em>.</p>
+</li>
+<li>
+<p>A kernel calls <strong>read_pipe</strong> or <strong>write_pipe</strong> with a reservation ID that
+has already been committed (i.e. a <strong>commit_read_pipe</strong> or
+<strong>commit_write_pipe</strong> with this reservation ID has already been called).</p>
+</li>
+<li>
+<p>A kernel fails to call <strong>commit_read_pipe</strong> for any reservation ID
+obtained by a prior call to <strong>reserve_read_pipe</strong>.</p>
+</li>
+<li>
+<p>A kernel fails to call <strong>commit_write_pipe</strong> for any reservation ID
+obtained by a prior call to <strong>reserve_write_pipe</strong>.</p>
+</li>
+<li>
+<p>The contents of the reserved data packets in the pipe are undefined if
+the kernel does not call <strong>write_pipe</strong> for all entries that were reserved
+by the corresponding call to <strong>reserve_pipe</strong>.</p>
+</li>
+<li>
+<p>Calls to <strong>read_pipe</strong> that takes a reservation ID and <strong>commit_read_pipe</strong>
+or <strong>write_pipe</strong> that takes a reservation ID and <strong>commit_write_pipe</strong> for
+a given reservation ID must be called by the same kernel that made the
+reservation using <strong>reserve_read_pipe</strong> or <strong>reserve_write_pipe</strong>.
+The reservation ID cannot be passed to another kernel including child
+kernels.</p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="enqueuing-kernels">1.13.17. Enqueuing Kernels</h4>
+<div class="paragraph">
+<p>OpenCL 2.0 allows a kernel to independently enqueue to the same device,
+without host interaction.
+A kernel may enqueue code represented by Block syntax, and control execution
+order with event dependencies including user events and markers.
+There are several advantages to using the Block syntax: it is more compact;
+it does not require a cl_kernel object; and enqueuing can be done as a
+single semantic step.</p>
+</div>
+<div class="paragraph">
+<p>The following table describes the list of built-in functions that can be
+used to enqueue a kernel(s).</p>
+</div>
+<div class="paragraph">
+<p>The macro <code>CLK_NULL_EVENT</code> refers to an invalid device event.
+The macro <code>CLK_NULL_QUEUE</code> refers to an invalid device queue.</p>
+</div>
+<div class="sect4">
+<h5 id="built-in-functions-enqueuing-a-kernel">Built-in Functions - Enqueuing a kernel</h5>
+<table id="table-builtin-kernel-enqueue" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 30. Built-in Kernel Enqueue Functions</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Built-in Function</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>enqueue_kernel</strong>(queue_t <em>queue</em>, kernel_enqueue_flags_t <em>flags</em>,
+  const ndrange_t <em>ndrange</em>, void (^<em>block</em>)(void))<br>
+  int <strong>enqueue_kernel</strong>(queue_t <em>queue</em>, kernel_enqueue_flags_t <em>flags</em>,
+  const ndrange_t <em>ndrange</em>, uint <em>num_events_in_wait_list</em>,
+  const clk_event_t *<em>event_wait_list</em>, clk_event_t *<em>event_ret</em>,
+  void (^<em>block</em>)(void))<br>
+  int <strong>enqueue_kernel</strong>(queue_t <em>queue</em>, kernel_enqueue_flags_t <em>flags</em>,
+  const ndrange_t <em>ndrange</em>, void (^<em>block</em>)(local void *, &#8230;&#8203;),
+  uint size0, &#8230;&#8203;)<br>
+  int <strong>enqueue_kernel</strong>(queue_t <em>queue</em>, kernel_enqueue_flags_t <em>flags</em>,
+  const ndrange_t <em>ndrange</em>, uint <em>num_events_in_wait_list</em>,
+  const clk_event_t *<em>event_wait_list</em>, clk_event_t *<em>event_ret</em>,
+  void (^<em>block</em>)(local void *, &#8230;&#8203;), uint size0, &#8230;&#8203;)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Enqueue the block for execution to <em>queue</em>.</p>
+<p class="tableblock">      If an event is returned, <strong>enqueue_kernel</strong> performs an implicit retain
+      on the returned event.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>The <strong>enqueue_kernel</strong> built-in function allows a work-item to enqueue a
+block.
+Work-items can enqueue multiple blocks to a device queue(s).</p>
+</div>
+<div class="paragraph">
+<p>The <strong>enqueue_kernel</strong> built-in function returns <code>CLK_SUCCESS</code> if the block is
+enqueued successfully and returns <code>CLK_ENQUEUE_FAILURE</code> otherwise.
+If the -g compile option is specified in compiler options passed to
+<strong>clCompileProgram</strong> or <strong>clBuildProgram</strong> when compiling or building the parent
+program, the following errors may be returned instead of
+<code>CLK_ENQUEUE_FAILURE</code> to indicate why <strong>enqueue_kernel</strong> failed to enqueue the
+block:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>CLK_INVALID_QUEUE</code> if <em>queue</em> is not a valid device queue.</p>
+</li>
+<li>
+<p><code>CLK_INVALID_NDRANGE</code> if <em>ndrange</em> is not a valid ND-range descriptor or
+if the program was compiled with <code>-cl-uniform-work-group-size</code> and the
+<em>local_work_size</em> is specified in <em>ndrange</em> but the <em>global_work_size</em>
+specified in <em>ndrange</em> is not a multiple of the <em>local_work_size</em>.</p>
+</li>
+<li>
+<p><code>CLK_INVALID_EVENT_WAIT_LIST</code> if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or if <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p><code>CLK_DEVICE_QUEUE_FULL</code> if <em>queue</em> is full.</p>
+</li>
+<li>
+<p><code>CLK_INVALID_ARG_SIZE</code> if size of local memory arguments is 0.</p>
+</li>
+<li>
+<p><code>CLK_EVENT_ALLOCATION_FAILURE</code> if <em>event_ret</em> is not <code>NULL</code> and an event
+could not be allocated.</p>
+</li>
+<li>
+<p><code>CLK_OUT_OF_RESOURCES</code> if there is a failure to queue the block in
+<em>queue</em> because of insufficient resources needed to execute the kernel.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Below are some examples of how to enqueue a block.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">kernel <span class="directive">void</span>
+my_func_A(global <span class="predefined-type">int</span> *a, global <span class="predefined-type">int</span> *b, global <span class="predefined-type">int</span> *c)
+{
+    ...
+}
+
+kernel <span class="directive">void</span>
+my_func_B(global <span class="predefined-type">int</span> *a, global <span class="predefined-type">int</span> *b, global <span class="predefined-type">int</span> *c)
+{
+    ndrange_t ndrange;
+    <span class="comment">// build ndrange information</span>
+    ...
+
+    <span class="comment">// example - enqueue a kernel as a block</span>
+    enqueue_kernel(get_default_queue(), ndrange,
+                   ^{my_func_A(a, b, c);});
+
+    ...
+}
+
+kernel <span class="directive">void</span>
+my_func_C(global <span class="predefined-type">int</span> *a, global <span class="predefined-type">int</span> *b, global <span class="predefined-type">int</span> *c)
+{
+    ndrange_t ndrange;
+    <span class="comment">// build ndrange information</span>
+    ...
+
+    <span class="comment">// note that a, b and c are variables in scope of</span>
+    <span class="comment">// the block</span>
+    <span class="directive">void</span> (^my_block_A)(<span class="directive">void</span>) = ^{my_func_A(a, b, c);};
+
+    <span class="comment">// enqueue the block variable</span>
+    enqueue_kernel(get_default_queue(),
+                   CLK_ENQUEUE_FLAGS_WAIT_KERNEL,
+                   ndrange,
+                   my_block_A);
+    ...
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The example below shows how to declare a block literal and enqueue it.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">kernel <span class="directive">void</span>
+my_func(global <span class="predefined-type">int</span> *a, global <span class="predefined-type">int</span> *b)
+{
+    ndrange_t ndrange;
+    <span class="comment">// build ndrange information</span>
+    ...
+
+    <span class="comment">// note that a, b and c are variables in scope of</span>
+    <span class="comment">// the block</span>
+    <span class="directive">void</span> (^my_block_A)(<span class="directive">void</span>) =
+    ^{
+        size_t id = get_global_id(<span class="integer">0</span>);
+        b[id] += a[id];
+    };
+
+    <span class="comment">// enqueue the block variable</span>
+    enqueue_kernel(get_default_queue(),
+                   CLK_ENQUEUE_FLAGS_WAIT_KERNEL,
+                   ndrange,
+                   my_block_A);
+
+    <span class="comment">// or we could have done the following</span>
+    enqueue_kernel(get_default_queue(),
+                   CLK_ENQUEUE_FLAGS_WAIT_KERNEL,
+                   ndrange,
+                   ^{
+                       size_t id = get_global_id(<span class="integer">0</span>);
+                       b[id] += a[id];
+                   };
+}</code></pre>
+</div>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>Blocks passed to enqueue_kernel cannot use global variables or stack
+variables local to the enclosing lexical scope that are a pointer type in
+the <code>local</code> or <code>private</code> address space.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p>Example:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">kernel <span class="directive">void</span>
+foo(global <span class="predefined-type">int</span> *a, local <span class="predefined-type">int</span> *lptr, ...)
+{
+    enqueue_kernel(get_default_queue(),
+                   CLK_ENQUEUE_FLAGS_WAIT_KERNEL,
+                   ndrange,
+                   ^{
+                       size_t id = get_global_id(<span class="integer">0</span>);
+                       local <span class="predefined-type">int</span> *p = lptr; <span class="comment">// undefined behavior</span>
+                   } );
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="arguments-that-are-a-pointer-type-to-local-address-space">Arguments that are a pointer type to local address space</h5>
+<div class="paragraph">
+<p>A block passed to enqueue_kernel can have arguments declared to be a pointer
+to <code>local</code> memory.
+The enqueue_kernel built-in function variants allow blocks to be enqueued
+with a variable number of arguments.
+Each argument must be declared to be a <code>void</code> pointer to local memory.
+These enqueue_kernel built-in function variants also have a corresponding
+number of arguments each of type <code>uint</code> that follow the block argument.
+These arguments specify the size of each local memory pointer argument of
+the enqueued block.</p>
+</div>
+<div class="paragraph">
+<p>Some examples follow:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">kernel <span class="directive">void</span>
+my_func_A_local_arg1(global <span class="predefined-type">int</span> *a, local <span class="predefined-type">int</span> *lptr, ...)
+{
+    ...
+}
+
+kernel <span class="directive">void</span>
+my_func_A_local_arg2(global <span class="predefined-type">int</span> *a,
+                     local <span class="predefined-type">int</span> *lptr1, local float4 *lptr2, ...)
+{
+    ...
+}
+
+kernel <span class="directive">void</span>
+my_func_B(global <span class="predefined-type">int</span> *a, ...)
+{
+    ...
+
+    ndrange_t ndrange = ndrange_1d(...);
+
+    uint local_mem_size = compute_local_mem_size();
+
+    enqueue_kernel(get_default_queue(),
+                   CLK_ENQUEUE_FLAGS_WAIT_KERNEL,
+                   ndrange,
+                   ^(local <span class="directive">void</span> *p){
+                       my_func_A_local_arg1(a, (local <span class="predefined-type">int</span> *)p, ...);},
+                   local_mem_size);
+}
+
+kernel <span class="directive">void</span>
+my_func_C(global <span class="predefined-type">int</span> *a, ...)
+{
+    ...
+    ndrange_t ndrange = ndrange_1d(...);
+
+    <span class="directive">void</span> (^my_blk_A)(local <span class="directive">void</span> *, local <span class="directive">void</span> *) =
+        ^(local <span class="directive">void</span> *lptr1, local <span class="directive">void</span> *lptr2){
+        my_func_A_local_arg2(
+            a,
+            (local <span class="predefined-type">int</span> *)lptr1,
+            (local float4 *)lptr2, ...);};
+
+    <span class="comment">// calculate local memory size for lptr</span>
+    <span class="comment">// argument in local address space for my_blk_A</span>
+    uint local_mem_size = compute_local_mem_size();
+
+    enqueue_kernel(get_default_queue(),
+                   CLK_ENQUEUE_FLAGS_WAIT_KERNEL,
+                   ndrange,
+                   my_blk_A,
+                   local_mem_size, local_mem_size*<span class="integer">4</span>);
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="a-complete-example">A Complete Example</h5>
+<div class="paragraph">
+<p>The example below shows how to implement an iterative algorithm where the
+host enqueues the first instance of the nd-range kernel (dp_func_A).
+The kernel dp_func_A will launch a kernel (evaluate_dp_work_A) that will
+determine if new nd-range work needs to be performed.
+If new nd-range work does need to be performed, then evaluate_dp_work_A will
+enqueue a new instance of dp_func_A .
+This process is repeated until all the work is completed.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">kernel <span class="directive">void</span>
+dp_func_A(queue_t q, ...)
+{
+    ...
+
+    <span class="comment">// queue a single instance of evaluate_dp_work_A to</span>
+    <span class="comment">// device queue q. queued kernel begins execution after</span>
+    <span class="comment">// kernel dp_func_A finishes</span>
+
+    <span class="keyword">if</span> (get_global_id(<span class="integer">0</span>) == <span class="integer">0</span>)
+    {
+        enqueue_kernel(q,
+                       CLK_ENQUEUE_FLAGS_WAIT_KERNEL,
+                       ndrange_1d(<span class="integer">1</span>),
+                       ^{evaluate_dp_work_A(q, ...);});
+    }
+}
+
+kernel <span class="directive">void</span>
+evaluate_dp_work_A(queue_t q,...)
+{
+    <span class="comment">// check if more work needs to be performed</span>
+    <span class="predefined-type">bool</span> more_work = check_new_work(...);
+    <span class="keyword">if</span> (more_work)
+    {
+        size_t global_work_size = compute_global_size(...);
+
+        <span class="directive">void</span> (^dp_func_A_blk)(<span class="directive">void</span>) =
+            ^{dp_func_A(q, ...});
+
+        <span class="comment">// get local WG-size for kernel dp_func_A</span>
+        size_t local_work_size =
+            get_kernel_work_group_size(dp_func_A_blk);
+
+        <span class="comment">// build nd-range descriptor</span>
+        ndrange_t ndrange = ndrange_1D(global_work_size,
+                                       local_work_size);
+
+        <span class="comment">// enqueue dp_func_A</span>
+        enqueue_kernel(q,
+                       CLK_ENQUEUE_FLAGS_WAIT_KERNEL,
+                       ndrange,
+                       dp_func_A_blk);
+    }
+    ...
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="determining-when-a-child-kernel-begins-execution">Determining when a child kernel begins execution</h5>
+<div class="paragraph">
+<p>The <code>kernel_enqueue_flags_t</code><sup>64</sup> argument to enqueue_kernel built-in
+functions can be used to specify when the child kernel begins execution.
+Supported values are described in the table below:</p>
+</div>
+<div class="paragraph">
+<p>[64] Implementations are not required to honor this flag.
+Implementations may not schedule kernel launch earlier than the point
+specified by this flag, however.</p>
+</div>
+<table id="table-kernel-enqueue-flags" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 31. Kernel Enqueue Flags</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>kernel_enqueue_flags_t</code> <strong>enum</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CLK_ENQUEUE_FLAGS_NO_WAIT</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Indicates that the enqueued kernels do not need to wait for the parent
+      kernel to finish execution before they begin execution.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CLK_ENQUEUE_FLAGS_WAIT_KERNEL</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Indicates that all work-items of the parent kernel must finish
+      executing and all immediate<sup>65</sup> side effects committed before the
+      enqueued child kernel may begin execution.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CLK_ENQUEUE_FLAGS_WAIT_WORK_GROUP</code><sup>66</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Indicates that the enqueued kernels wait only for the workgroup that
+      enqueued the kernels to finish before they begin execution.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>[65] Immediate meaning not side effects resulting from child kernels.
+The side effects would include stores to <code>global</code> memory and pipe reads and
+writes.</p>
+</div>
+<div class="paragraph">
+<p>[66] This acts as a memory synchronization point between work-items in a
+work-group and child kernels enqueued by work-items in the work-group.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>The <code>kernel_enqueue_flags_t</code> flags are useful when a kernel enqueued from
+the host and executing on a device enqueues kernels on the device.
+The kernel enqueued from the host may not have an event associated with it.
+The <code>kernel_enqueue_flags_t</code> flags allow the developer to indicate when the
+child kernels can begin execution.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+</div>
+<div class="sect4">
+<h5 id="determining-when-a-parent-kernel-has-finished-execution">Determining when a parent kernel has finished execution</h5>
+<div class="paragraph">
+<p>A parent kernel&#8217;s execution status is considered to be complete when it and
+all its child kernels have finished execution.
+The execution status of a parent kernel will be <code>CL_COMPLETE</code> if this kernel
+and all its child kernels finish execution successfully.
+The execution status of the kernel will be an error code (given by a
+negative integer value) if it or any of its child kernels encounter an
+error, or are abnormally terminated.</p>
+</div>
+<div class="paragraph">
+<p>For example, assume that the host enqueues a kernel <code>k</code> for execution on a
+device.
+Kernel <code>k</code> when executing on the device enqueues kernels <code>A</code> and <code>B</code> to a
+device queue(s).
+The enqueue_kernel call to enqueue kernel <code>B</code> specifies the event associated
+with kernel <code>A</code> in the <code>event_wait_list</code> argument, i.e. wait for kernel <code>A</code>
+to finish execution before kernel <code>B</code> can begin execution.
+Let&#8217;s assume kernel <code>A</code> enqueues kernels <code>X</code>, <code>Y</code> and <code>Z</code>.
+Kernel <code>A</code> is considered to have finished execution, i.e. its execution
+status is <code>CL_COMPLETE</code>, only after <code>A</code> and the kernels <code>A</code> enqueued (and
+any kernels these enqueued kernels enqueue and so on) have finished
+execution.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="built-in-functions-kernel-query-functions">Built-in Functions - Kernel Query Functions</h5>
+<table id="table-builtin-kernel-query" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 32. Built-in Kernel Query Functions</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Built-in Function</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">uint <strong>get_kernel_work_group_size</strong>(void (^block)(void))<br>
+  uint <strong>get_kernel_work_group_size</strong>(void (^block)(local void *, &#8230;&#8203;))</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This provides a mechanism to query the maximum work-group size that
+      can be used to execute a block on a specific device given by <em>device</em>.</p>
+<p class="tableblock">      <em>block</em> specifies the block to be enqueued.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">uint <strong>get_kernel_preferred_</strong> <strong>work_group_size_multiple</strong>(
+  void (^block)(void))<br>
+  uint <strong>get_kernel_preferred_</strong> <strong>work_group_size_multiple</strong>(
+  void (^block)(local void *, &#8230;&#8203;))</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the preferred multiple of work-group size for launch.
+      This is a performance hint.
+      Specifying a work-group size that is not a multiple of the value
+      returned by this query as the value of the local work size argument to
+      enqueue_kernel will not fail to enqueue the block for execution unless
+      the work-group size specified is larger than the device maximum.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect4">
+<h5 id="built-in-functions-queuing-other-commands">Built-in Functions - Queuing other commands</h5>
+<div class="paragraph">
+<p>The following table describes the list of built-in functions that can be
+used to enqueue commands such as a marker.</p>
+</div>
+<table id="table-builtin-other-enqueue" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 33. Built-in Other Enqueue Functions</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Built-in Function</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>enqueue_marker</strong>(queue_t <em>queue</em>, uint <em>num_events_in_wait_list</em>,
+  const clk_event_t *<em>event_wait_list</em>, clk_event_t *<em>event_ret</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Enqueue a marker command to <em>queue</em>.</p>
+<p class="tableblock">      The marker command waits for a list of events specified by
+      <em>event_wait_list</em> to complete before the marker completes.</p>
+<p class="tableblock">      <em>event_ret</em> must not be <code>NULL</code> as otherwise this is a no-op.</p>
+<p class="tableblock">      If an event is returned, <strong>enqueue_marker</strong> performs an implicit retain
+      on the returned event.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>The <strong>enqueue_marker</strong> built-in function returns <code>CLK_SUCCESS</code> if the marked
+command is enqueued successfully and returns <code>CLK_ENQUEUE_FAILURE</code>
+otherwise.
+If the -g compile option is specified in compiler options passed to
+<strong>clCompileProgram</strong> or <strong>clBuildProgram</strong>, the following errors may be returned
+instead of <code>CLK_ENQUEUE_FAILURE</code> to indicate why <strong>enqueue_marker</strong> failed to
+enqueue the marker command:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>CLK_INVALID_QUEUE</code> if <em>queue</em> is not a valid device queue.</p>
+</li>
+<li>
+<p><code>CLK_INVALID_EVENT_WAIT_LIST</code> if <em>event_wait_list</em> is <code>NULL</code>, or if
+<em>event_wait_list</em> is not <code>NULL</code> and <em>num_events_in_wait_list</em> is 0, or
+if event objects in <em>event_wait_list</em> are not valid events.</p>
+</li>
+<li>
+<p><code>CLK_DEVICE_QUEUE_FULL</code> if <em>queue</em> is full.</p>
+</li>
+<li>
+<p><code>CLK_EVENT_ALLOCATION_FAILURE</code> if <em>event_ret</em> is not <code>NULL</code> and an event
+could not be allocated.</p>
+</li>
+<li>
+<p><code>CLK_OUT_OF_RESOURCES</code> if there is a failure to queue the block in
+<em>queue</em> because of insufficient resources needed to execute the kernel.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect4">
+<h5 id="built-in-functions-event-functions">Built-in Functions - Event Functions</h5>
+<div class="paragraph">
+<p>The following table describes the list of built-in functions that work on
+events.</p>
+</div>
+<table id="table-builtin-event" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 34. Built-in Event Functions</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Built-in Function</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>retain_event</strong>(clk_event_t <em>event</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Increments the event reference count. <em>event</em> must be an event
+      returned by enqueue_kernel or enqueue_marker or a user event.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>release_event</strong>(clk_event_t <em>event</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Decrements the event reference count.
+      The event object is deleted once the event reference count is zero,
+      the specific command identified by this event has completed (or
+      terminated) and there are no commands in any device command queue that
+      require a wait for this event to complete.</p>
+<p class="tableblock">      <em>event</em> must be an event returned by enqueue_kernel, enqueue_marker or
+      a user event.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">clk_event_t <strong>create_user_event</strong>()</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Create a user event.
+      Returns the user event.
+      The execution status of the user event created is set to
+      <code>CL_SUBMITTED</code>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">bool <strong>is_valid_event</strong>(clk_event_t <em>event</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <em>true</em> if <em>event</em> is a valid event.
+      Otherwise returns <em>false</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>set_user_event_status</strong>(clk_event_t <em>event</em>, int <em>status</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Sets the execution status of a user event.
+      <em>event</em> must be a user-event.
+      <em>status</em> can be either <code>CL_COMPLETE</code> or a negative integer value
+      indicating an error.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>capture_event_profiling_info</strong>(clk_event_t <em>event</em>,
+  clk_profiling_info <em>name</em>, global void *<em>value</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Captures the profiling information for functions that are enqueued as
+      commands.
+      The specific function being referred to is: enqueue_kernel.
+      These enqueued commands are identified by unique event objects.
+      The profiling information will be available in <em>value</em> once the
+      command identified by <em>event</em> has completed.&#8201;&#8212;&#8201;<em>event</em> must be an event returned by enqueue_kernel.</p>
+<p class="tableblock"><em>name</em> identifies which profiling information is to be queried and can be:</p>
+<p class="tableblock">  <code>CLK_PROFILING_COMMAND_EXEC_TIME</code></p>
+<p class="tableblock"><em>value</em> is a pointer to two 64-bit values.</p>
+<p class="tableblock">The first 64-bit value describes the elapsed time <code>CL_PROFILING_COMMAND_END</code>
+- <code>CL_PROFLING_COMMAND_START</code> for the command identified by <em>event</em> in
+nanoseconds.</p>
+<p class="tableblock">The second 64-bit value describes the elapsed time
+<code>CL_PROFILING_COMMAND_COMPLETE</code> - <code>CL_PROFILING_COMAMND_START</code> for the
+command identified by <em>event</em> in nanoseconds.</p>
+<p class="tableblock">[NOTE]
+====
+The behavior of capture_event_profiling_info when called multiple times for
+the same <em>event</em> is undefined.
+====&#8201;&#8212;&#8201;</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>Events can be used to identify commands enqueued to a command-queue from the
+host.
+These events created by the OpenCL runtime can only be used on the host,
+i.e. as events passed in the <em>event_wait_list</em> argument to various
+<strong>clEnqueue</strong> APIs or runtime APIs that take events as arguments, such as
+<strong>clRetainEvent</strong>, <strong>clReleaseEvent</strong>, and <strong>clGetEventProfilingInfo</strong>.</p>
+</div>
+<div class="paragraph">
+<p>Similarly, events can be used to identify commands enqueued to a device
+queue (from a kernel).
+These event objects cannot be passed to the host or used by OpenCL runtime
+APIs such as the <strong>clEnqueue</strong> APIs or runtime APIs that take event arguments.</p>
+</div>
+<div class="paragraph">
+<p><strong>clRetainEvent</strong> and <strong>clReleaseEvent</strong> will return <code>CL_INVALID_OPERATION</code> if
+<em>event</em> specified is an event that refers to any kernel enqueued to a device
+queue using <strong>enqueue_kernel</strong> or <strong>enqueue_marker</strong>, or is a user event created
+by <strong>create_user_event</strong>.</p>
+</div>
+<div class="paragraph">
+<p>Similarly, <strong>clSetUserEventStatus</strong> can only be used to set the execution
+status of events created using <strong>clCreateUserEvent</strong>.
+User events created on the device can be set using set_user_event_status
+built-in function.</p>
+</div>
+<div class="paragraph">
+<p>The example below shows how events can be used with kernels enqueued to
+multiple device queues.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="directive">extern</span> <span class="directive">void</span> barA_kernel(...);
+<span class="directive">extern</span> <span class="directive">void</span> barB_kernel(...);
+
+kernel <span class="directive">void</span>
+foo(queue_t q0, queue q1, ...)
+{
+    ...
+    clk_event_t evt0;
+
+    <span class="comment">// enqueue kernel to queue q0</span>
+    enqueue_kernel(q0,
+                   CLK_ENQUEUE_FLAGS_NO_WAIT,
+                   ndrange_A,
+                   <span class="integer">0</span>, <span class="predefined-constant">NULL</span>, &amp;evt0,
+                   ^{barA_kernel(...);} );
+
+    <span class="comment">// enqueue kernel to queue q1</span>
+    enqueue_kernel(q1,
+                   CLK_ENQUEUE_FLAGS_NO_WAIT,
+                   ndrange_B,
+                   <span class="integer">1</span>, &amp;evt0, <span class="predefined-constant">NULL</span>,
+                   ^{barB_kernel(...);} );
+
+    <span class="comment">// release event evt0. This will get released</span>
+    <span class="comment">// after barA_kernel enqueued in queue q0 has finished</span>
+    <span class="comment">// execution and barB_kernel enqueued in queue q1 and</span>
+    <span class="comment">// waits for evt0 is submitted for execution, i.e. wait</span>
+    <span class="comment">// for evt0 is satisfied.</span>
+    release_event(evt0);
+
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The example below shows how the marker command can be used with kernels
+enqueued to a device queue.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">kernel <span class="directive">void</span>
+foo(queue_t q, ...)
+{
+    ...
+    clk_event_t marker_event;
+    clk_event_t events[<span class="integer">2</span>];
+
+    enqueue_kernel(q,
+                   CLK_ENQUEUE_FLAGS_NO_WAIT,
+                   ndrange,
+                   <span class="integer">0</span>, <span class="predefined-constant">NULL</span>, &amp;events[<span class="integer">0</span>],
+                   ^{barA_kernel(...);} );
+
+    enqueue_kernel(q,
+                   CLK_ENQUEUE_FLAGS_NO_WAIT,
+                   ndrange,
+                   <span class="integer">0</span>, <span class="predefined-constant">NULL</span>, &amp;events[<span class="integer">1</span>],
+                   ^{barB_kernel(...);} );
+
+    <span class="comment">// barA_kernel and barB_kernel can be executed</span>
+    <span class="comment">// out of order. we need to wait for both these</span>
+    <span class="comment">// kernels to finish execution before barC_kernel</span>
+    <span class="comment">// starts execution so we enqueue a marker command and</span>
+    <span class="comment">// then enqueue barC_kernel that waits on the event</span>
+    <span class="comment">// associated with the marker.</span>
+    enqueue_marker(q, <span class="integer">2</span>, events, &amp;marker_event);
+
+    enqueue_kernel(q,
+                   CLK_ENQUEUE_FLAGS_NO_WAIT,
+                   <span class="integer">1</span>, &amp;marker_event, <span class="predefined-constant">NULL</span>,
+                   ^{barC_kernel(...);} );
+
+    release_event(events[<span class="integer">0</span>];
+    release_event(events[<span class="integer">1</span>]);
+    release_event(marker_event);
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="built-in-functions-helper-functions">Built-in Functions - Helper Functions</h5>
+<table id="table-builtin-helper" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 35. Built-in Helper Functions</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Built-in Function</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">queue_t <strong>get_default_queue</strong>(void)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the default device queue.
+      If a default device queue has not been created, <code>CLK_NULL_QUEUE</code> is
+      returned.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">ndrange_t <strong>ndrange_1D</strong>(size_t <em>global_work_size</em>)<br>
+  ndrange_t <strong>ndrange_1D</strong>(size_t <em>global_work_size</em>,
+  size_t <em>local_work_size</em>)<br>
+  ndrange_t <strong>ndrange_1D</strong>(size_t <em>global_work_offset</em>,
+  size_t <em>global_work_size</em>, size_t <em>local_work_size</em>)<br>
+  ndrange_t <strong>ndrange_2D</strong>(const size_t <em>global_work_size</em>[2])<br>
+  ndrange_t <strong>ndrange_2D</strong>(const size_t <em>global_work_size</em>[2],
+  const size_t <em>local_work_size</em>[2])<br>
+  ndrange_t <strong>ndrange_2D</strong>(const size_t <em>global_work_offset</em>[2],
+  const size_t <em>global_work_size</em>[2],
+  const size_t <em>local_work_size</em>[2])<br>
+  ndrange_t <strong>ndrange_3D</strong>(const size_t <em>global_work_size</em>[3])<br>
+  ndrange_t <strong>ndrange_3D</strong>(const size_t <em>global_work_size</em>[3],
+  const size_t <em>local_work_size</em>[3])<br>
+  ndrange_t <strong>ndrange_3D</strong>(const size_t <em>global_work_offset</em>[3],
+  const size_t <em>global_work_size</em>[3],
+  const size_t <em>local_work_size</em>[3])</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Builds a 1D, 2D or 3D ND-range descriptor.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="opencl-numerical-compliance">2. OpenCL Numerical Compliance</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>This section describes features of the <a href="#C99-spec">C99</a> and IEEE 754
+standards that must be supported by all OpenCL compliant devices.</p>
+</div>
+<div class="paragraph">
+<p>This section describes the functionality that must be supported by all
+OpenCL devices for single precision floating-point numbers.
+Currently, only single precision floating-point is a requirement.
+Double precision floating-point is an optional feature.</p>
+</div>
+<div class="sect2">
+<h3 id="rounding-modes-1">2.1. Rounding Modes</h3>
+<div class="paragraph">
+<p>Floating-point calculations may be carried out internally with extra
+precision and then rounded to fit into the destination type.
+IEEE 754 defines four possible rounding modes:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Round to nearest even</p>
+</li>
+<li>
+<p>Round toward +∞</p>
+</li>
+<li>
+<p>Round toward -∞</p>
+</li>
+<li>
+<p>Round toward zero</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p><em>Round to nearest</em> <em>even</em> is currently the only rounding mode required<sup>67</sup> by
+the OpenCL specification for single precision and double precision
+operations and is therefore the default rounding mode.
+In addition, only static selection of rounding mode is supported.
+Dynamically reconfiguring the rounding modes as specified by the IEEE 754
+spec is unsupported.</p>
+</div>
+<div class="paragraph">
+<p>[67] Except for the embedded profile whether either round to zero or round to
+nearest rounding mode may be supported for single precision floating-point.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="inf-nan-and-denormalized-numbers">2.2. INF, NaN and Denormalized Numbers</h3>
+<div class="paragraph">
+<p><code>INF</code> and NaNs must be supported.
+Support for signaling NaNs is not required.</p>
+</div>
+<div class="paragraph">
+<p>Support for denormalized numbers with single precision floating-point is
+optional.
+Denormalized single precision floating-point numbers passed as input or
+produced as the output of single precision floating-point operations such as
+add, sub, mul, divide, and the functions defined in <a href="#math-functions">math
+functions</a>, <a href="#common-functions">common functions</a>, and
+<a href="#geometric-functions">geometric functions</a> may be flushed to zero.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="floating-point-exceptions">2.3. Floating-Point Exceptions</h3>
+<div class="paragraph">
+<p>Floating-point exceptions are disabled in OpenCL.
+The result of a floating-point exception must match the IEEE 754 spec for
+the exceptions not enabled case.
+Whether and when the implementation sets floating-point flags or raises
+floating-point exceptions is implementation-defined.
+This standard provides no method for querying, clearing or setting
+floating-point flags or trapping raised exceptions.
+Due to non-performance, non-portability of trap mechanisms and the
+impracticality of servicing precise exceptions in a vector context
+(especially on heterogeneous hardware), such features are discouraged.</p>
+</div>
+<div class="paragraph">
+<p>Implementations that nevertheless support such operations through an
+extension to the standard shall initialize with all exception flags cleared
+and the exception masks set so that exceptions raised by arithmetic
+operations do not trigger a trap to be taken.
+If the underlying work is reused by the implementation, the implementation
+is however not responsible for reclearing the flags or resetting exception
+masks to default values before entering the kernel.
+That is to say that kernels that do not inspect flags or enable traps are
+licensed to expect that their arithmetic will not trigger a trap.
+Those kernels that do examine flags or enable traps are responsible for
+clearing flag state and disabling all traps before returning control to the
+implementation.
+Whether or when the underlying work-item (and accompanying global
+floating-point state if any) is reused is implementation-defined.</p>
+</div>
+<div class="paragraph">
+<p>The expressions <strong>math_errorhandling</strong> and <code>MATH_ERREXCEPT</code> are reserved for
+use by this standard, but not defined.
+Implementations that extend this specification with support for
+floating-point exceptions shall define <strong>math_errorhandling</strong> and
+<code>MATH_ERREXCEPT</code> per <a href="#C99-spec">TC2 to the C99 Specification</a>.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="relative-error-as-ulps">2.4. Relative Error as ULPs</h3>
+<div class="paragraph">
+<p>In this section we discuss the maximum relative error defined as ulp (units
+in the last place).
+Addition, subtraction, multiplication, fused multiply-add and conversion
+between integer and a single precision floating-point format are IEEE 754
+compliant and are therefore correctly rounded.
+Conversion between floating-point formats and
+<a href="#explicit-conversions">explicit conversions</a> must be correctly rounded.</p>
+</div>
+<div class="paragraph">
+<p>The ULP is defined as follows:</p>
+</div>
+<div class="exampleblock">
+<div class="content">
+<div class="paragraph">
+<p>If <em>x</em> is a real number that lies between two finite consecutive
+floating-point numbers <em>a</em> and <em>b</em>, without being equal to one of them, then
+ulp(<em>x</em>) = |<em>b</em> - <em>a</em>|, otherwise ulp(<em>x</em>) is the distance between the two
+non-equal finite floating-point numbers nearest <em>x</em>.
+Moreover, ulp(NaN) is NaN.</p>
+</div>
+</div>
+</div>
+<div class="paragraph">
+<p><em>Attribution: This definition was taken with consent from Jean-Michel Muller
+with slight clarification for behavior at zero.
+Refer to
+<a href="ftp://ftp.inria.fr/INRIA/publication/publi-pdf/RR/RR-5504.pdf">_ftp://ftp.inria.fr/INRIA/publication/publi-pdf/RR/RR-5504.pdf</em></a>._</p>
+</div>
+<div class="paragraph">
+<p>The following table<sup>68</sup> describes the minimum accuracy of single precision
+floating-point arithmetic operations given as ULP values.
+The reference value used to compute the ULP value of an arithmetic operation
+is the infinitely precise result.</p>
+</div>
+<div class="paragraph">
+<p>[68] The ULP values for built-in math functions <strong>lgamma</strong> and <strong>lgamma_r</strong> is
+currently undefined.</p>
+</div>
+<table id="table-ulp-float-math" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 36. ULP values for single precision built-in math functions</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Function</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Min Accuracy - ULP values</strong><sup>69</sup></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>x</em> + <em>y</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>x</em> - <em>y</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>x</em> * <em>y</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>1.0 / <em>x</em></strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 2.5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>x</em> / <em>y</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 2.5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>acos</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>acospi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>asin</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>asinpi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>atan</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>atan2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 6 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>atanpi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>atan2pi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 6 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>acosh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>asinh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>atanh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cbrt</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ceil</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>copysign</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cos</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cosh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cospi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>erfc</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>erf</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>exp</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>exp2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>exp10</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>expm1</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>fabs</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>fdim</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>floor</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>fma</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>fmax</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>fmin</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>fmod</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>fract</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>frexp</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>hypot</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ilogb</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ldexp</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>log</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>log2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>log10</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>log1p</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>logb</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mad</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented either as a correctly rounded fma or
+                          as a multiply followed by an add both of which are
+                          correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>maxmag</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>minmag</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>modf</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>nan</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>nextafter</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>pow</strong>(<em>x</em>, <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>pown</strong>(<em>x</em>, <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>powr</strong>(<em>x</em>, <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>remainder</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>remquo</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>rint</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>rootn</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>round</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>rsqrt</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sin</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sincos</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp for sine and cosine values</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sinh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sinpi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sqrt</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>tan</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>tanh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>tanpi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 6 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>tgamma</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>trunc</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half_cos</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half_divide</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half_exp</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half_exp2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half_exp10</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half_log</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half_log2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half_log10</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half_powr</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half_recip</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half_rsqrt</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half_sin</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half_sqrt</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half_tan</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>native_cos</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>native_divide</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>native_exp</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>native_exp2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>native_exp10</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>native_log</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>native_log2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>native_log10</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>native_powr</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>native_recip</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>native_rsqrt</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>native_sin</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>native_sqrt</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>native_tan</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>[69] 0 ulp is used for math functions that do not require rounding.</p>
+</div>
+<div class="paragraph">
+<p>The following table describes the minimum accuracy of single precision
+floating-point arithmetic operations given as ULP values for the embedded
+profile.
+The reference value used to compute the ULP value of an arithmetic operation
+is the infinitely precise result.</p>
+</div>
+<table id="table-ulp-embedded" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 37. ULP values for the embedded profile</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Function</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Min Accuracy - ULP values</strong><sup>70</sup></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>x</em> + <em>y</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>x</em> - <em>y</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>x</em> * <em>y</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>1.0 / <em>x</em></strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>x</em> / <em>y</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>acos</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>acospi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>asin</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>asinpi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>atan</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>atan2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 6 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>atanpi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>atan2pi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 6 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>acosh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>asinh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>atanh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cbrt</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ceil</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>copysign</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cos</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cosh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cospi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>erfc</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>erf</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>exp</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>exp2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>exp10</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>expm1</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>fabs</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>fdim</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>floor</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>fma</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>fmax</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>fmin</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>fmod</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>fract</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>frexp</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>hypot</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ilogb</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ldexp</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>log</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>log2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>log10</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>log1p</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>logb</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mad</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Any value allowed (infinite ulp)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>maxmag</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>minmag</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>modf</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>nan</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>nextafter</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>pow</strong>(<em>x</em>, <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>pown</strong>(<em>x</em>, <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>powr</strong>(<em>x</em>, <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>remainder</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>remquo</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>rint</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>rootn</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>round</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>rsqrt</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sin</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sincos</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp for sine and cosine values</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sinh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sinpi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sqrt</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>tan</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>tanh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>tanpi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 6 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>tgamma</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>trunc</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half_cos</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half_divide</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half_exp</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half_exp2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half_exp10</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half_log</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half_log2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half_log10</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half_powr</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half_recip</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half_rsqrt</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half_sin</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half_sqrt</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half_tan</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>native_cos</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>native_divide</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>native_exp</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>native_exp2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>native_exp10</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>native_log</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>native_log2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>native_log10</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>native_powr</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>native_recip</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>native_rsqrt</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>native_sin</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>native_sqrt</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>native_tan</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>[70] 0 ulp is used for math functions that do not require rounding.</p>
+</div>
+<div class="paragraph">
+<p>The following table describes the minimum accuracy of commonly used single
+precision floating-point arithmetic operations given as ULP values if the
+<code>-cl-unsafe-math-optimizations</code> compiler option is specified when compiling or
+building an OpenCL program.
+For derived implementations, the operations used in the derivation may
+themselves be relaxed according to the following table.
+The minimum accuracy of math functions not defined in the following table
+when the <code>-cl-unsafe-math-optimizations</code> compiler option is specified is as defined
+in <a href="#table-ulp-float-math">ULP values for single precision built-in math functions</a> when operating in the full profile, and as
+defined in <a href="#table-ulp-embedded">ULP values for the embedded profile</a> when operating in the embedded profile.
+The reference value used to compute the ULP value of an arithmetic operation
+is the infinitely precise result.</p>
+</div>
+<table id="table-float-ulp-relaxed" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 38. ULP values for single precision built-in math functions with unsafe math optimizations in the full and embedded profiles</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Function</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Min Accuracy - ULP values</strong><sup>71</sup></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>1.0 / <em>x</em></strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 2.5 ulp for <em>x</em> in the domain of 2<sup>-126</sup> to 2<sup>126</sup> for the full
+      profile, and ≤ 3 ulp for the embedded profile.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>x</em> / <em>y</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 2.5 ulp for <em>x</em> in the domain of 2<sup>-62</sup> to 2<sup>62</sup> and <em>y</em> in the
+      domain of 2<sup>-62</sup> to 2<sup>62</sup> for the full profile, and ≤ 3 ulp for
+      the embedded profile.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>acos</strong>(<em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4096 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>acospi</strong>(<em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented as <strong>acos</strong>(<em>x</em>) * <code>M_PI_F</code>.
+      For non-derived implementations, the error is ≤ 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>asin</strong>(<em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4096 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>asinpi</strong>(<em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented as <strong>asin</strong>(<em>x</em>) * <code>M_PI_F</code>.
+      For non-derived implementations, the error is ≤ 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>atan</strong>(<em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4096 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>atan2</strong>(<em>y</em>, <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented as <strong>atan</strong>(<em>y</em> / <em>x</em>) for <em>x</em> &gt; 0, <strong>atan</strong>(<em>y</em> / <em>x</em>)<br>
+      <code>M_1_PI_F</code> for <em>x</em> &lt; 0 and <em>y</em> &gt; 0 and <strong>atan</strong>(<em>y</em> / <em>x</em>) -
+      <code>M_1_PI_F</code> for <em>x</em> &lt; 0 and <em>y</em> &lt; 0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>atanpi</strong>(<em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented as <strong>atan</strong>(<em>x</em>) * <code>M_1_PI_F</code>.
+      For non-derived implementations, the error is ≤ 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>atan2pi</strong>(<em>y</em>, <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented as <strong>atan2</strong>(<em>y</em>, <em>x</em>) * <code>M_PI_F</code>.
+      For non-derived implementations, the error is ≤ 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>acosh</strong>(<em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented as <strong>log</strong>(<em>x</em> + <strong>sqrt</strong>(<em>x</em> * <em>x</em> - 1)).</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>asinh</strong>(<em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented as <strong>log</strong>(<em>x</em> + <strong>sqrt</strong>(<em>x</em> * <em>x</em> + 1)).</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cbrt</strong>(<em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented as <strong>rootn</strong>(<em>x</em>, 3).
+      For non-derived implementations, the error is ≤ 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cos</strong>(<em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">For <em>x</em> in the domain [-π, π], the maximum absolute error
+      is ≤ 2<sup>-11</sup> and larger otherwise.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cosh</strong>(<em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Defined for <em>x</em> in the domain [-88,88] and implemented as 0.5f *
+      (<strong>exp</strong>(<em>x</em>) + <strong>exp</strong>(-<em>x</em>)).
+      For non-derived implementations, the error is ≤ 8192 ULP.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cospi</strong>(<em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">For <em>x</em> in the domain [-1, 1], the maximum absolute error is ≤
+      2<sup>-11</sup> and larger otherwise.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>exp</strong>(<em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 3 + <strong>floor</strong>(<strong>fabs</strong>(2 * <em>x</em>)) ulp for the full profile, and ≤
+      4 ulp for the embedded profile.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>exp2</strong>(<em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 3 + <strong>floor</strong>(<strong>fabs</strong>(2 * <em>x</em>)) ulp for the full profile, and ≤
+      4 ulp for the embedded profile.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>exp10</strong>(<em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Derived implementations implement this as <strong>exp2</strong>(<em>x</em> * <strong>log2</strong>(10)).
+      For non-derived implementations, the error is ≤ 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>expm1</strong>(<em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Derived implementations implement this as <strong>exp</strong>(<em>x</em>) - 1.
+      For non-derived implementations, the error is ≤ 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>log</strong>(<em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">For <em>x</em> in the domain [0.5, 2] the maximum absolute error is ≤
+      2<sup>-21</sup>; otherwise the maximum error is ≤3 ulp for the full profile
+      and ≤ 4 ulp for the embedded profile</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>log2</strong>(<em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">For <em>x</em> in the domain [0.5, 2] the maximum absolute error is ≤
+      2<sup>-21</sup>; otherwise the maximum error is ≤3 ulp for the full profile
+      and ≤ 4 ulp for the embedded profile</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>log10</strong>(<em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">For <em>x</em> in the domain [0.5, 2] the maximum absolute error is ≤
+      2<sup>-21</sup>; otherwise the maximum error is ≤3 ulp for the full profile
+      and ≤ 4 ulp for the embedded profile</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>log1p</strong>(<em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Derived implementations implement this as <strong>log</strong>(<em>x</em> + 1).
+      For non-derived implementations, the error is ≤ 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>pow</strong>(<em>x</em>, <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Undefined for <em>x</em> = 0 and <em>y</em> = 0.
+      Undefined for <em>x</em> &lt; 0 and non-integer y.
+      Undefined for <em>x</em> &lt; 0 and <em>y</em> outside the domain [-2^24, 2^24].
+      For <em>x</em> &gt; 0 or <em>x</em> &lt; 0 and even <em>y</em>, derived implementations implement
+      this as <strong>exp2</strong>(y * log2(<em>x</em>)).
+      For <em>x</em> &lt; 0 and odd <em>y</em>, derived implementations implement this as
+      <strong>-exp2(y * *log2</strong>(fabs(<em>x</em>))<sup>72</sup>.
+      For <em>x</em> == 0 and nonzero <em>y</em>, derived implementations return zero.
+      For non-derived implementations, the error is ≤ 8192 ULP</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>pown</strong>(<em>x</em>, <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Defined only for integer values of y.
+      Undefined for <em>x</em> = 0 and <em>y</em> = 0.
+      For <em>x</em> &gt;= 0 or <em>x</em> &lt; 0 and even <em>y</em>, derived implementations
+      implement this as <strong>exp2</strong>(<em>y</em> * <strong>log2</strong>(<em>x</em>)).
+      For <em>x</em> &lt; 0 and odd <em>y</em>, derived implementations implement this as
+      <strong>-exp2</strong>(<em>y</em> * <strong>log2</strong>(<strong>fabs</strong>(<em>x</em>)).
+      For non-derived implementations, the error is ≤ 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>powr</strong>(<em>x</em>, <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Defined only for <em>x</em> &gt;= 0.
+      Undefined for <em>x</em> = 0 and <em>y</em> = 0.
+      Derived implementations implement this as <strong>exp2</strong>(<em>y</em> * <strong>log2</strong>(<em>x</em>)).
+      For non-derived implementations, the error is ≤ 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>rootn</strong>(<em>x</em>, <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Defined for <em>x</em> &gt; 0 when <em>y</em> is nonzero, derived implementations
+      implement this case as <strong>exp2</strong>(log2(<em>x</em>) / <em>y</em>).
+      Defined for <em>x</em> &lt; 0 when <em>y</em> is odd, derived implementations implement
+      this case as -<strong>exp2</strong>(<strong>log2</strong>(-<em>x</em>) / <em>y</em>).
+      Defined for <em>x</em> = +/-0 when <em>y</em> &gt; 0, derived implementations will
+      return +0 in this case.
+      For non-derived implementations, the error is ≤ 8192 ULP.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sin</strong>(<em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">For <em>x</em> in the domain [-π, π], the maximum absolute error is
+      ≤ 2<sup>-11</sup> and larger otherwise.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sincos</strong>(<em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">ulp values as defined for <strong>sin</strong>(<em>x</em>) and <strong>cos</strong>(<em>x</em>)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sinh</strong>(<em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Defined for <em>x</em> in the domain [-88,88].
+      For <em>x</em> in [-2<sup>-10,2</sup>-10], derived implementations implement as <em>x</em>.
+      For <em>x</em> outside of [-2<sup>10,2</sup>10], derived implement as <strong>0.5f *
+      (*exp</strong>(<em>x</em>) - <strong>exp</strong>(-<em>x</em>)).
+      For non-derived implementations, the error is ≤ 8192 ULP.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sinpi</strong>(<em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">For <em>x</em> in the domain [-1, 1], the maximum absolute error is ≤
+      2<sup>-11</sup> and larger otherwise.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>tan</strong>(<em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Derived implementations implement this as <strong>sin</strong>(<em>x</em>) * (<code>1.0f</code> /
+      <strong>cos</strong>(<em>x</em>)).
+      For non-derived implementations, the error is ≤ 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>tanpi</strong>(<em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Derived implementations implement this as <strong>tan</strong>(<em>x</em> * <code>M_PI_F</code>).
+      For non-derived implementations, the error is ≤ 8192 ulp for <em>x</em>
+      in the domain [-1, 1].</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>x</em> * <em>y</em> + <em>z</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented either as a correctly rounded <strong>fma</strong> or as a multiply and
+      an add both of which are correctly rounded.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>[71] 0 ulp is used for math functions that do not require rounding.</p>
+</div>
+<div class="paragraph">
+<p>[72] On some implementations, <strong>powr</strong>() or <strong>pown</strong>() may perform faster than
+<strong>pow</strong>().
+If <em>x</em> is known to be &gt;= 0, consider using <strong>powr</strong>() in place of <strong>pow</strong>(), or
+if <em>y</em> is known to be an integer, consider using <strong>pown</strong>() in place of
+<strong>pow</strong>().</p>
+</div>
+<div class="paragraph">
+<p>The following table describes the minimum accuracy of double precision
+floating-point arithmetic operations given as ULP values.
+The reference value used to compute the ULP value of an arithmetic operation
+is the infinitely precise result.</p>
+</div>
+<table id="table-ulp-double" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 39. ULP values for double precision built-in math functions</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Function</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Min Accuracy - ULP values</strong><sup>73</sup></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>x</em> + <em>y</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>x</em> - <em>y</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>x</em> * <em>y</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">1.0 / <em>x</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>x</em> / <em>y</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>acos</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>acospi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>asin</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>asinpi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>atan</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>atan2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 6 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>atanpi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>atan2pi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 6 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>acosh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>asinh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>atanh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cbrt</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ceil</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>copysign</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cos</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cosh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cospi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>erfc</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>erf</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>exp</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>exp2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>exp10</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>expm1</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>fabs</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>fdim</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>floor</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>fma</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>fmax</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>fmin</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>fmod</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>fract</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>frexp</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>hypot</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ilogb</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ldexp</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>log</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>log2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>log10</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>log1p</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>logb</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mad</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Any value allowed (infinite ulp)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>maxmag</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>minmag</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>modf</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>nan</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>nextafter</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>pow</strong>(<em>x</em>, <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>pown</strong>(<em>x</em>, <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>powr</strong>(<em>x</em>, <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>remainder</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>remquo</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>rint</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>rootn</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>round</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>rsqrt</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sin</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sincos</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp for sine and cosine values</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sinh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sinpi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>fsqrt</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>tan</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>tanh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>tanpi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 6 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>tgamma</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">≤ 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>trunc</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>[73] 0 ulp is used for math functions that do not require rounding.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="edge-case-behavior">2.5. Edge Case Behavior</h3>
+<div class="paragraph">
+<p>The edge case behavior of the <a href="#math-functions">math functions</a> shall
+conform to <a href="#C99-spec">sections F.9 and G.6 of the C99 Specification</a>,
+except <a href="#additional-requirements-beyond-c99-tc2">where noted below</a>.</p>
+</div>
+<div class="sect3">
+<h4 id="additional-requirements-beyond-c99-tc2">2.5.1. Additional Requirements Beyond C99 TC2</h4>
+<div class="paragraph">
+<p>Functions that return a NaN with more than one NaN operand shall return one
+of the NaN operands.
+Functions that return a NaN operand may silence the NaN if it is a signaling
+NaN.
+A non-signaling NaN shall be converted to a non-signaling NaN.
+A signaling NaN shall be converted to a NaN, and should be converted to a
+non-signaling NaN.
+How the rest of the NaN payload bits or the sign of NaN is converted is
+undefined.</p>
+</div>
+<div class="paragraph">
+<p><strong>half_&lt;funcname&gt;</strong> functions behave identically to the function of the same
+name without the <strong>half_</strong> prefix.
+They must conform to the same edge case requirements (<a href="#C99-spec">see
+sections F.9 and G.6 of the C99 Specification</a>).
+For other cases, except where otherwise noted, these single precision
+functions are permitted to have up to 8192 ulps of error (as measured in the
+single precision result), although better accuracy is encouraged.</p>
+</div>
+<div class="paragraph">
+<p>The usual allowances for <a href="#relative-error-as-ulps">rounding error</a> or
+<a href="#edge-case-behavior-in-flush-to-zero-mode">flushing behavior</a> shall not
+apply for those values for which <a href="#C99-spec">section F.9 of the C99
+Specification</a>, or the <a href="#additional-requirements-beyond-c99-tc2">additional
+requirements</a> and <a href="#edge-case-behavior-in-flush-to-zero-mode">edge case
+behavior</a> below (and similar sections for other floating-point precisions)
+prescribe a result (e.g. <strong>ceil</strong>(-1 &lt; <em>x</em> &lt; 0) returns -0).
+Those values shall produce exactly the prescribed answers, and no other.
+Where the ± symbol is used, the sign shall be preserved.
+For example, <strong>sin</strong>(±0) = ±0 shall be interpreted to mean
+<strong>sin</strong>(+0) is +0 and <strong>sin</strong>(-0) is -0.</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>acospi</strong>(1) = +0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>acospi</strong>(<em>x</em>) returns a NaN for |<em>x</em>| &gt; 1.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>asinpi</strong>(±0) = ±0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>asinpi</strong>(<em>x</em>) returns a NaN for |<em>x</em>| &gt; 1.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>atanpi</strong>(±0) = ±0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>atanpi</strong>(±∞) = ±0.5.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>atan2pi</strong>(±0, -0) = ±1.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>atan2pi</strong>(±0, +0) = ±0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>atan2pi</strong>(±0, <em>x</em>) returns ±1 for <em>x</em> &lt; 0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>atan2pi</strong>(±0, <em>x</em>) returns ±0 for <em>x</em> &gt; 0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>atan2pi</strong>(<em>y</em>, ±0) returns -0.5 for <em>y</em> &lt; 0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>atan2pi</strong>(<em>y</em>, ±0) returns 0.5 for <em>y</em> &gt; 0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>atan2pi</strong>(±_y_, -∞) returns ±1 for finite <em>y</em> &gt; 0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>atan2pi</strong>(±_y_, +∞) returns ±0 for finite <em>y</em> &gt; 0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>atan2pi</strong>(±∞, <em>x</em>) returns ±0.5 for finite <em>x.</em></p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>atan2pi</strong>(±∞, -∞) returns ±0.75.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>atan2pi</strong>(±∞, +∞) returns ±0.25.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>ceil</strong>(-1 &lt; <em>x</em> &lt; 0) returns -0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>cospi</strong>(±0) returns 1</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>cospi</strong>(<em>n</em> + 0.5) is +0 for any integer <em>n</em> where <em>n</em> + 0.5 is
+representable.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>cospi</strong>(±∞) returns a NaN.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>exp10</strong>(-∞) returns +0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>exp10</strong>(+∞) returns +∞.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>distance</strong>(<em>x</em>, <em>y</em>) calculates the distance from <em>x</em> to <em>y</em> without
+overflow or extraordinary precision loss due to underflow.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>fdim</strong>(any, NaN) returns NaN.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>fdim</strong>(NaN, any) returns NaN.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>fmod</strong>(±0, NaN) returns NaN.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>frexp</strong>(±∞, <em>exp</em>) returns ±∞ and stores 0 in
+<em>exp</em>.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>frexp</strong>(NaN, <em>exp</em>) returns the NaN and stores 0 in <em>exp</em>.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>fract</strong>(<em>x</em>, <em>iptr</em>) shall not return a value greater than or equal to
+1.0, and shall not return a value less than 0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>fract</strong>(+0, <em>iptr</em>) returns +0 and +0 in iptr.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>fract</strong>(-0, <em>iptr</em>) returns -0 and -0 in iptr.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>fract</strong>(+∞, <em>iptr</em>) returns +0 and +∞ in <em>iptr</em>.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>fract</strong>(-∞, <em>iptr</em>) returns -0 and -∞ in <em>iptr</em>.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>fract</strong>(NaN, <em>iptr</em>) returns the NaN and NaN in <em>iptr</em>.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>length</strong> calculates the length of a vector without overflow or
+extraordinary precision loss due to underflow.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>lgamma_r</strong>(<em>x</em>, <em>signp</em>) returns 0 in <em>signp</em> if <em>x</em> is zero or a
+negative integer.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>nextafter</strong>(-0, <em>y</em> &gt; 0) returns smallest positive denormal value.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>nextafter</strong>(+0, <em>y</em> &lt; 0) returns smallest negative denormal value.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>normalize</strong> shall reduce the vector to unit length, pointing in the
+same direction without overflow or extraordinary precision loss due to
+underflow.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>normalize</strong>(<em>v</em>) returns <em>v</em> if all elements of <em>v</em> are zero.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>normalize</strong>(<em>v</em>) returns a vector full of NaNs if any element is a NaN.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>normalize</strong>(<em>v</em>) for which any element in <em>v</em> is infinite shall proceed
+as if the elements in <em>v</em> were replaced as follows:</p>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="keyword">for</span> (i = <span class="integer">0</span>; i &lt; <span class="keyword">sizeof</span>(v) / <span class="keyword">sizeof</span>(v[<span class="integer">0</span>]); i++)
+   v[i] = isinf(v[i]) ? copysign(<span class="float">1</span><span class="float">.0</span>, v[i]) : <span class="float">0</span><span class="float">.0</span> * v[i];</code></pre>
+</div>
+</div>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>pow</strong>(±0, -∞) returns +∞</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>pown</strong>(<em>x</em>, 0) is 1 for any <em>x</em>, even zero, NaN or infinity.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>pown</strong>(±0, <em>n</em>) is ±∞ for odd <em>n</em> &lt; 0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>pown</strong>(±0, <em>n</em>) is +∞ for even <em>n</em> &lt; 0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>pown</strong>(±0, <em>n</em>) is +0 for even <em>n</em> &gt; 0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>pown</strong>(±0, <em>n</em>) is ±0 for odd <em>n</em> &gt; 0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>powr</strong>(<em>x</em>, ±0) is 1 for finite <em>x</em> &gt; 0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>powr</strong>(±0, <em>y</em>) is +∞ for finite <em>y</em> &lt; 0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>powr</strong>(±0, -∞) is +∞.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>powr</strong>(±0, <em>y</em>) is +0 for <em>y</em> &gt; 0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>powr</strong>(+1, <em>y</em>) is 1 for finite <em>y.</em></p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>powr</strong>(<em>x</em>, <em>y</em>) returns NaN for <em>x</em> &lt; 0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>powr</strong>(±0, ±0) returns NaN.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>powr</strong>(+∞, ±0) returns NaN.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>powr</strong>(+1, ±∞) returns NaN.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>powr</strong>(<em>x</em>, NaN) returns the NaN for <em>x</em> &gt;= 0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>powr</strong>(NaN, <em>y</em>) returns the NaN.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>rint</strong>(-0.5 &lt;= <em>x</em> &lt; 0) returns -0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>remquo</strong>(<em>x</em>, <em>y</em>, &amp;_quo_) returns a NaN and 0 in <em>quo</em> if <em>x</em> is
+±∞, or if <em>y</em> is 0 and the other argument is non-NaN or if
+either argument is a NaN.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>rootn</strong>(±0, <em>n</em>) is ±∞ for odd <em>n</em> &lt; 0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>rootn</strong>(±0, <em>n</em>) is +∞ for even <em>n</em> &lt; 0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>rootn</strong>(±0, <em>n</em>) is +0 for even <em>n</em> &gt; 0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>rootn</strong>(±0, <em>n</em>) is ±0 for odd <em>n</em> &gt; 0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>rootn</strong>(<em>x</em>, <em>n</em>) returns a NaN for <em>x</em> &lt; 0 and <em>n</em> is even.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>rootn</strong>(<em>x</em>, 0) returns a NaN.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>round</strong>(-0.5 &lt; <em>x</em> &lt; 0) returns -0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>sinpi</strong>(±0) returns ±0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>sinpi</strong>(+<em>n</em>) returns +0 for positive integers <em>n</em>.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>sinpi</strong>(-<em>n</em>) returns -0 for negative integers <em>n</em>.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>sinpi</strong>(±∞) returns a NaN.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>tanpi</strong>(±0) returns ±0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>tanpi</strong>(±∞) returns a NaN.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>tanpi</strong>(<em>n</em>) is <strong>copysign</strong>(0.0, <em>n</em>) for even integers <em>n</em>.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>tanpi</strong>(<em>n</em>) is <strong>copysign</strong>(0.0, - <em>n</em>) for odd integers <em>n</em>.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>tanpi</strong>(<em>n</em> + 0.5) for even integer <em>n</em> is +∞ where <em>n</em> + 0.5 is
+representable.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>tanpi</strong>(<em>n</em> + 0.5) for odd integer <em>n</em> is -∞ where <em>n</em> + 0.5 is
+representable.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>trunc</strong>(-1 &lt; <em>x</em> &lt; 0) returns -0.
+Binary file (standard input) matches</p>
+</dd>
+</dl>
+</div>
+</div>
+<div class="sect3">
+<h4 id="changes-to-c99-tc2-behavior">2.5.2. Changes to C99 TC2 Behavior</h4>
+<div class="paragraph">
+<p><strong>modf</strong> behaves as though implemented by:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">gentype modf(gentype value, gentype *iptr)
+{
+    *iptr = trunc( value );
+    <span class="keyword">return</span> copysign(isinf( value ) ? <span class="float">0</span><span class="float">.0</span> : value - *iptr, value);
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><strong>rint</strong> always rounds according to round to nearest even rounding mode even
+if the caller is in some other rounding mode.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="edge-case-behavior-in-flush-to-zero-mode">2.5.3. Edge Case Behavior in Flush To Zero Mode</h4>
+<div class="paragraph">
+<p>If denormals are flushed to zero, then a function may return one of four
+results:</p>
+</div>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>Any conforming result for non-flush-to-zero mode</p>
+</li>
+<li>
+<p>If the result given by 1.
+is a sub-normal before rounding, it may be flushed to zero</p>
+</li>
+<li>
+<p>Any non-flushed conforming result for the function if one or more of its
+sub-normal operands are flushed to zero.</p>
+</li>
+<li>
+<p>If the result of 3.
+is a sub-normal before rounding, the result may be flushed to zero.</p>
+</li>
+</ol>
+</div>
+<div class="paragraph">
+<p>In each of the above cases, if an operand or result is flushed to zero, the
+sign of the zero is undefined.</p>
+</div>
+<div class="paragraph">
+<p>If subnormals are flushed to zero, a device may choose to conform to the
+following edge cases for <strong>nextafter</strong> instead of those listed in the
+<a href="#additional-requirements-beyond-c99-tc2">additional requirements</a> section.</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>nextafter</strong>(+smallest normal, <em>y</em> &lt; +smallest normal) = +0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>nextafter</strong>(-smallest normal, <em>y</em> &gt; -smallest normal) = -0.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>nextafter</strong>(-0, <em>y</em> &gt; 0) returns smallest positive normal value.</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>nextafter</strong>(+0, <em>y</em> &lt; 0) returns smallest negative normal value.</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>For clarity, subnormals or denormals are defined to be the set of
+representable numbers in the range 0 &lt; <em>x</em> &lt; <code>TYPE_MIN</code> and <code>-TYPE_MIN</code> &lt;
+<em>x</em> &lt; -0.
+They do not include ±0.
+A non-zero number is said to be sub-normal before rounding if after
+normalization, its radix-2 exponent is less than (<code>TYPE_MIN_EXP</code> - 1)<sup>74</sup>.</p>
+</div>
+<div class="paragraph">
+<p>[74] Here <code>TYPE_MIN</code> and <code>TYPE_MIN_EXP</code> should be substituted by constants
+appropriate to the floating-point type under consideration, such as
+<code>FLT_MIN</code> and <code>FLT_MIN_EXP</code> for <code>float</code>.</p>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="image-addressing-and-filtering">3. Image Addressing and Filtering</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>Let w<sub>t</sub>, h<sub>t</sub> and d<sub>t</sub> be the width, height (or image array size for a 1D
+image array) and depth (or image array size for a 2D image array) of the
+image in pixels.
+Let <em>coord.xy</em> (also referred to as (<em>s</em>,<em>t</em>)) or <em>coord.xyz</em> (also referred
+to as (<em>s</em>,<em>t</em>,<em>r</em>)) be the coordinates specified to <strong>read_image{f|i|ui}</strong>.
+The sampler specified in <strong>read_image{f|i|ui}</strong> is used to determine how to
+sample the image and return an appropriate color.</p>
+</div>
+<div class="sect2">
+<h3 id="image-coordinates">3.1. Image Coordinates</h3>
+<div class="paragraph">
+<p>This affects the interpretation of image coordinates.
+If image coordinates specified to <strong>read_image{f|i|ui}</strong> are normalized (as
+specified in the sampler), the <em>s</em>, <em>t</em>, and <em>r</em> coordinate values are
+multiplied by w<sub>t</sub>, h<sub>t,</sub> and d<sub>t</sub> respectively to generate the unnormalized
+coordinate values.
+For image arrays, the image array coordinate (i.e. <em>t</em> if it is a 1D image
+array or <em>r</em> if it is a 2D image array) specified to <strong>read_image{f|i|ui}</strong>
+must always be the un-normalized image coordinate value.</p>
+</div>
+<div class="paragraph">
+<p>Let (<em>u</em>,<em>v</em>,<em>w</em>) represent the unnormalized image coordinate values.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="addressing-and-filter-modes">3.2. Addressing and Filter Modes</h3>
+<div class="paragraph">
+<p>We first describe how the addressing and filter modes are applied to
+generate the appropriate sample locations to read from the image if the
+addressing mode is not <code>CLK_ADDRESS_REPEAT</code> nor
+<code>CLK_ADDRESS_MIRRORED_REPEAT</code>.</p>
+</div>
+<div class="paragraph">
+<p>After generating the image coordinate (<em>u</em>,<em>v</em>,<em>w</em>) we apply the appropriate
+addressing and filter mode to generate the appropriate sample locations to
+read from the image.</p>
+</div>
+<div class="paragraph">
+<p>If values in (<em>u</em>,<em>v</em>,<em>w</em>) are <code>INF</code> or NaN, the behavior of
+<strong>read_image{f|i|ui}</strong> is undefined.</p>
+</div>
+<div class="paragraph">
+<p><strong>Filter Mode</strong> <code>CLK_FILTER_NEAREST</code></p>
+</div>
+<div class="paragraph">
+<p>When filter mode is <code>CLK_FILTER_NEAREST</code>, the image element in the image
+that is nearest (in Manhattan distance) to that specified by (<em>u</em>,<em>v</em>,<em>w</em>)
+is obtained.
+This means the image element at location (<em>i</em>,<em>j</em>,<em>k</em>) becomes the image
+element value, where</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">i = address_mode((<span class="predefined-type">int</span>)floor(u))
+j = address_mode((<span class="predefined-type">int</span>)floor(v))
+k = address_mode((<span class="predefined-type">int</span>)floor(w))</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>For a 3D image, the image element at location (<em>i</em>,<em>j</em>,<em>k</em>) becomes the
+color value.
+For a 2D image, the image element at location (<em>i</em>,<em>j</em>) becomes the color
+value.</p>
+</div>
+<div class="paragraph">
+<p>The following table describes the address_mode function.</p>
+</div>
+<table id="table-address-modes-texel-location" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 40. Addressing modes to generate texel location</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Addressing Mode</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Result of address_mode(coord)</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CLK_ADDRESS_CLAMP_TO_EDGE</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">clamp (coord, 0, size - 1)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CLK_ADDRESS_CLAMP</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">clamp (coord, -1, size)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CLK_ADDRESS_NONE</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">coord</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>The <code>size</code> term in this table is w<sub>t</sub> for <em>u</em>, h<sub>t</sub> for <em>v</em> and d<sub>t</sub> for
+<em>w</em>.</p>
+</div>
+<div class="paragraph">
+<p>The <code>clamp</code> function used in this table is defined as:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">clamp(a, b, c) = <span class="keyword">return</span> (a &lt; b) ? b : ((a &gt; c) ? c : a)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>If the selected texel location (<em>i</em>,<em>j</em>,<em>k</em>) refers to a location outside
+the image, the border color is used as the color value for this texel.</p>
+</div>
+<div class="paragraph">
+<p><strong>Filter Mode</strong> <code>CLK_FILTER_LINEAR</code></p>
+</div>
+<div class="paragraph">
+<p>When filter mode is <code>CLK_FILTER_LINEAR</code>, a 2×2 square of image
+elements for a 2D image or a 2×2×2 cube of image elements for a
+3D image is selected.
+This 2×2 square or 2×2×2 cube is obtained as follows.</p>
+</div>
+<div class="paragraph">
+<p>Let</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">i0 = address_mode((<span class="predefined-type">int</span>)floor(u - <span class="float">0</span><span class="float">.5</span>))
+j0 = address_mode((<span class="predefined-type">int</span>)floor(v - <span class="float">0</span><span class="float">.5</span>))
+k0 = address_mode((<span class="predefined-type">int</span>)floor(w - <span class="float">0</span><span class="float">.5</span>))
+i1 = address_mode((<span class="predefined-type">int</span>)floor(u - <span class="float">0</span><span class="float">.5</span>) + <span class="integer">1</span>)
+j1 = address_mode((<span class="predefined-type">int</span>)floor(v - <span class="float">0</span><span class="float">.5</span>) + <span class="integer">1</span>)
+k1 = address_mode((<span class="predefined-type">int</span>)floor(w - <span class="float">0</span><span class="float">.5</span>) + <span class="integer">1</span>)
+a = frac(u - <span class="float">0</span><span class="float">.5</span>)
+b = frac(v - <span class="float">0</span><span class="float">.5</span>)
+c = frac(w - <span class="float">0</span><span class="float">.5</span>)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>where <code>frac(x)</code> denotes the fractional part of x and is computed as <code>x -
+floor(x)</code>.</p>
+</div>
+<div class="paragraph">
+<p>For a 3D image, the image element value is found as</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">T = (<span class="integer">1</span> - a) * (<span class="integer">1</span> - b) * (<span class="integer">1</span> - c) * T_i0j0k0
+    + a * (<span class="integer">1</span> - b) * (<span class="integer">1</span> - c) * T_i1j0k0
+    + (<span class="integer">1</span> - a) * b * (<span class="integer">1</span> - c) * T_i0j1k0
+    + a * b * (<span class="integer">1</span> - c) * T_i1j1k0
+    + (<span class="integer">1</span> - a) * (<span class="integer">1</span> - b) * c * T_i0j0k1
+    + a * (<span class="integer">1</span> - b) * c * T_i1j0k1
+    + (<span class="integer">1</span> - a) * b * c * T_i0j1k1
+    + a * b * c * T_i1j1k1</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>where <code>T_ijk</code> is the image element at location (<em>i</em>,<em>j</em>,<em>k</em>) in the 3D image.</p>
+</div>
+<div class="paragraph">
+<p>For a 2D image, the image element value is found as</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">T = (<span class="integer">1</span> - a) * (<span class="integer">1</span> - b) * T_i0j0
+    + a * (<span class="integer">1</span> - b) * T_i1j0
+    + (<span class="integer">1</span> - a) * b * T_i0j1
+    + a * b * T_i1j1</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>where <code>T_ij</code> is the image element at location (<em>i</em>,<em>j</em>) in the 2D image.</p>
+</div>
+<div class="paragraph">
+<p>If any of the selected <code>T_ijk</code> or <code>T_ij</code> in the above equations refers to a
+location outside the image, the border color is used as the color value for
+<code>T_ijk</code> or <code>T_ij</code>.</p>
+</div>
+<div class="paragraph">
+<p>If the image channel type is <code>CL_FLOAT</code> or <code>CL_HALF_FLOAT</code> and any of the
+image elements <code>T_ijk</code> or <code>T_ij</code> is <code>INF</code> or NaN, the behavior of the built-in
+image read function is undefined.</p>
+</div>
+<div class="paragraph">
+<p>We now discuss how the addressing and filter modes are applied to generate
+the appropriate sample locations to read from the image if the addressing
+mode is <code>CLK_ADDRESS_REPEAT</code>.</p>
+</div>
+<div class="paragraph">
+<p>If values in (<em>s</em>,<em>t</em>,<em>r</em>) are <code>INF</code> or NaN, the behavior of the built-in
+image read functions is undefined.</p>
+</div>
+<div class="paragraph">
+<p><strong>Filter Mode</strong> <code>CLK_FILTER_NEAREST</code></p>
+</div>
+<div class="paragraph">
+<p>When filter mode is <code>CLK_FILTER_NEAREST</code>, the image element at location
+(<em>i</em>,<em>j</em>,<em>k</em>) becomes the image element value, with <em>i</em>, <em>j</em>, and <em>k</em>
+computed as</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">u = (s - floor(s)) * w_t
+i = (<span class="predefined-type">int</span>)floor(u)
+<span class="keyword">if</span> (i &gt; w_t - <span class="integer">1</span>)
+    i = i - w_t
+
+v = (t - floor(t)) * h_t
+j = (<span class="predefined-type">int</span>)floor(v)
+<span class="keyword">if</span> (j &gt; h_t - <span class="integer">1</span>)
+    j = j - h_t
+
+w = (r - floor(r)) * d_t
+k = (<span class="predefined-type">int</span>)floor(w)
+<span class="keyword">if</span> (k &gt; d_t - <span class="integer">1</span>)
+    k = k - d_t</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>For a 3D image, the image element at location (<em>i</em>,<em>j</em>,<em>k</em>) becomes the
+color value.
+For a 2D image, the image element at location (<em>i</em>,<em>j</em>) becomes the color
+value.</p>
+</div>
+<div class="paragraph">
+<p><strong>Filter Mode</strong> <code>CLK_FILTER_LINEAR</code></p>
+</div>
+<div class="paragraph">
+<p>When filter mode is <code>CLK_FILTER_LINEAR</code>, a 2×2 square of image
+elements for a 2D image or a 2×2×2 cube of image elements for a
+3D image is selected.
+This 2×2 square or 2×2×2 cube is obtained as follows.</p>
+</div>
+<div class="paragraph">
+<p>Let</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">u = (s - floor(s)) * w_t
+i0 = (<span class="predefined-type">int</span>)floor(u - <span class="float">0</span><span class="float">.5</span>)
+i1 = i0 + <span class="integer">1</span>
+<span class="keyword">if</span> (i0 &lt; <span class="integer">0</span>)
+    i0 = w_t + i0
+<span class="keyword">if</span> (i1 &gt; w_t - <span class="integer">1</span>)
+    i1 = i1 - w_t
+
+v = (t - floor(t)) * h_t
+j0 = (<span class="predefined-type">int</span>)floor(v - <span class="float">0</span><span class="float">.5</span>)
+j1 = j0 + <span class="integer">1</span>
+<span class="keyword">if</span> (j0 &lt; <span class="integer">0</span>)
+    j0 = h_t + j0
+<span class="keyword">if</span> (j1 &gt; h_t - <span class="integer">1</span>)
+    j1 = j1 - h_t
+
+w = (r - floor(r)) * d_t
+k0 = (<span class="predefined-type">int</span>)floor(w - <span class="float">0</span><span class="float">.5</span>)
+k1 = k0 + <span class="integer">1</span>
+<span class="keyword">if</span> (k0 &lt; <span class="integer">0</span>)
+    k0 = d_t + k0
+<span class="keyword">if</span> (k1 &gt; d_t - <span class="integer">1</span>)
+    k1 = k1 - d_t
+
+a = frac(u - <span class="float">0</span><span class="float">.5</span>)
+b = frac(v - <span class="float">0</span><span class="float">.5</span>)
+c = frac(w - <span class="float">0</span><span class="float">.5</span>)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>where <code>frac(x)</code> denotes the fractional part of x and is computed as <code>x -
+floor(x)</code>.</p>
+</div>
+<div class="paragraph">
+<p>For a 3D image, the image element value is found as</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">T = (<span class="integer">1</span> - a) * (<span class="integer">1</span> - b) * (<span class="integer">1</span> - c) * T_i0j0k0
+    + a * (<span class="integer">1</span> - b) * (<span class="integer">1</span> - c) * T_i1j0k0
+    + (<span class="integer">1</span> - a) * b * (<span class="integer">1</span> - c) * T_i0j1k0
+    + a * b * (<span class="integer">1</span> - c) * T_i1j1k0
+    + (<span class="integer">1</span> - a) * (<span class="integer">1</span> - b) * c * T_i0j0k1
+    + a * (<span class="integer">1</span> - b) * c * T_i1j0k1
+    + (<span class="integer">1</span> - a) * b * c * T_i0j1k1
+    + a * b * c * T_i1j1k1</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>where <code>T_ijk</code> is the image element at location (<em>i</em>,<em>j</em>,<em>k</em>) in the 3D image.</p>
+</div>
+<div class="paragraph">
+<p>For a 2D image, the image element value is found as</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">T = (<span class="integer">1</span> - a) * (<span class="integer">1</span> - b) * T_i0j0
+    + a * (<span class="integer">1</span> - b) * T_i1j0
+    + (<span class="integer">1</span> - a) * b * T_i0j1
+    + a * b * T_i1j1</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>where <code>T_ij</code> is the image element at location (<em>i</em>,<em>j</em>) in the 2D image.</p>
+</div>
+<div class="paragraph">
+<p>If the image channel type is <code>CL_FLOAT</code> or <code>CL_HALF_FLOAT</code> and any of the
+image elements <code>T_ijk</code> or <code>T_ij</code> is <code>INF</code> or NaN, the behavior of the built-in
+image read function is undefined.</p>
+</div>
+<div class="paragraph">
+<p>We now discuss how the addressing and filter modes are applied to generate
+the appropriate sample locations to read from the image if the addressing
+mode is <code>CLK_ADDRESS_MIRRORED_REPEAT</code>.
+The <code>CLK_ADDRESS_MIRRORED_REPEAT</code> addressing mode causes the image to be
+read as if it is tiled at every integer seam with the interpretation of the
+image data flipped at each integer crossing.
+For example, the (<em>s</em>,<em>t</em>,<em>r</em>) coordinates between 2 and 3 are addressed
+into the image as coordinates from 1 down to 0.
+If values in (<em>s</em>,<em>t</em>,<em>r</em>) are <code>INF</code> or NaN, the behavior of the built-in
+image read functions is undefined.</p>
+</div>
+<div class="paragraph">
+<p><strong>Filter Mode</strong> <code>CLK_FILTER_NEAREST</code></p>
+</div>
+<div class="paragraph">
+<p>When filter mode is <code>CLK_FILTER_NEAREST</code>, the image element at location
+(<em>i</em>,<em>j</em>,<em>k</em>) becomes the image element value, with <em>i</em>,<em>j</em> and k computed
+as</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">s<span class="char">' </span>= <span class="float">2</span><span class="float">.0f</span> * rint(<span class="float">0</span><span class="float">.5f</span> * s)
+s<span class="char">' </span>= fabs(s - s<span class="char">')</span>
+u = s<span class="char">' </span>* w_t
+i = (<span class="predefined-type">int</span>)floor(u)
+i = min(i, w_t - <span class="integer">1</span>)
+
+t<span class="char">' </span>= <span class="float">2</span><span class="float">.0f</span> * rint(<span class="float">0</span><span class="float">.5f</span> * t)
+t<span class="char">' </span>= fabs(t - t<span class="char">')</span>
+v = t<span class="char">' </span>* h_t
+j = (<span class="predefined-type">int</span>)floor(v)
+j = min(j, h_t - <span class="integer">1</span>)
+
+r<span class="char">' </span>= <span class="float">2</span><span class="float">.0f</span> * rint(<span class="float">0</span><span class="float">.5f</span> * r)
+r<span class="char">' </span>= fabs(r - r<span class="char">')</span>
+w = r<span class="char">' </span>* d_t
+k = (<span class="predefined-type">int</span>)floor(w)
+k = min(k, d_t - <span class="integer">1</span>)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>For a 3D image, the image element at location (<em>i</em>,<em>j</em>,<em>k</em>) becomes the
+color value.
+For a 2D image, the image element at location (<em>i</em>,<em>j</em>) becomes the color
+value.</p>
+</div>
+<div class="paragraph">
+<p><strong>Filter Mode</strong> <code>CLK_FILTER_LINEAR</code></p>
+</div>
+<div class="paragraph">
+<p>When filter mode is <code>CLK_FILTER_LINEAR</code>, a 2×2 square of image
+elements for a 2D image or a 2×2×2 cube of image elements for a
+3D image is selected.
+This 2×2 square or 2×2×2 cube is obtained as follows.</p>
+</div>
+<div class="paragraph">
+<p>Let</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">s<span class="char">' </span>= <span class="float">2</span><span class="float">.0f</span> * rint(<span class="float">0</span><span class="float">.5f</span> * s)
+s<span class="char">' </span>= fabs(s - s<span class="char">')</span>
+u = s<span class="char">' </span>* w_t
+i0 = (<span class="predefined-type">int</span>)floor(u - <span class="float">0</span><span class="float">.5f</span>)
+i1 = i0 + <span class="integer">1</span>
+i0 = max(i0, <span class="integer">0</span>)
+i1 = min(i1, w_t - <span class="integer">1</span>)
+
+t<span class="char">' </span>= <span class="float">2</span><span class="float">.0f</span> * rint(<span class="float">0</span><span class="float">.5f</span> * t)
+t<span class="char">' </span>= fabs(t - t<span class="char">')</span>
+v = t<span class="char">' </span>* h_t
+j0 = (<span class="predefined-type">int</span>)floor(v - <span class="float">0</span><span class="float">.5f</span>)
+j1 = j0 + <span class="integer">1</span>
+j0 = max(j0, <span class="integer">0</span>)
+j1 = min(j1, h_t - <span class="integer">1</span>)
+
+r<span class="char">' </span>= <span class="float">2</span><span class="float">.0f</span> * rint(<span class="float">0</span><span class="float">.5f</span> * r)
+r<span class="char">' </span>= fabs(r - r<span class="char">')</span>
+w = r<span class="char">' </span>* d_t
+k0 = (<span class="predefined-type">int</span>)floor(w - <span class="float">0</span><span class="float">.5f</span>)
+k1 = k0 + <span class="integer">1</span>
+k0 = max(k0, <span class="integer">0</span>)
+k1 = min(k1, d_t - <span class="integer">1</span>)
+
+a = frac(u - <span class="float">0</span><span class="float">.5</span>)
+b = frac(v - <span class="float">0</span><span class="float">.5</span>)
+c = frac(w - <span class="float">0</span><span class="float">.5</span>)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>where <code>frac(x)</code> denotes the fractional part of x and is computed as <code>x -
+floor(x)</code>.</p>
+</div>
+<div class="paragraph">
+<p>For a 3D image, the image element value is found as</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">T = (<span class="integer">1</span> - a) * (<span class="integer">1</span> - b) * (<span class="integer">1</span> - c) * T_i0j0k0
+    + a * (<span class="integer">1</span> - b) * (<span class="integer">1</span> - c) * T_i1j0k0
+    + (<span class="integer">1</span> - a) * b * (<span class="integer">1</span> - c) * T_i0j1k0
+    + a * b * (<span class="integer">1</span> - c) * T_i1j1k0
+    + (<span class="integer">1</span> - a) * (<span class="integer">1</span> - b) * c * T_i0j0k1
+    + a * (<span class="integer">1</span> - b) * c * T_i1j0k1
+    + (<span class="integer">1</span> - a) * b * c * T_i0j1k1
+    + a * b * c * T_i1j1k1</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>where <code>T_ijk</code> is the image element at location (<em>i</em>,<em>j</em>,<em>k</em>) in the 3D image.</p>
+</div>
+<div class="paragraph">
+<p>For a 2D image, the image element value is found as</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">T = (<span class="integer">1</span> - a) * (<span class="integer">1</span> - b) * T_i0j0
+    + a * (<span class="integer">1</span> - b) * T_i1j0
+    + (<span class="integer">1</span> - a) * b * T_i0j1
+    + a * b * T_i1j1</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>where <code>T_ij</code> is the image element at location (<em>i</em>,<em>j</em>) in the 2D image.</p>
+</div>
+<div class="paragraph">
+<p>For a 1D image, the image element value is found as</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c">T = (<span class="integer">1</span> - a) * T_i0
+    + a * T_i1</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>where <code>T_i</code> is the image element at location (<em>i</em>) in the 1D image.</p>
+</div>
+<div class="paragraph">
+<p>If the image channel type is <code>CL_FLOAT</code> or <code>CL_HALF_FLOAT</code> and any of the
+image elements <code>T_ijk</code> or <code>T_ij</code> is <code>INF</code> or NaN, the behavior of the built-in
+image read function is undefined.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<div class="paragraph">
+<p>If the sampler is specified as using unnormalized coordinates
+(floating-point or integer coordinates), filter mode set to
+<code>CLK_FILTER_NEAREST</code> and addressing mode set to one of the following modes -
+<code>CLK_ADDRESS_NONE</code>, <code>CLK_ADDRESS_CLAMP_TO_EDGE</code> or <code>CLK_ADDRESS_CLAMP</code>, the
+<a href="#addressing-and-filter-modes">location of the image element in the image</a>
+given by (<em>i</em>,<em>j</em>,<em>k</em>) will be computed without any loss of precision.</p>
+</div>
+<div class="paragraph">
+<p>For all other sampler combinations of normalized or unnormalized
+coordinates, filter and addressing modes, the relative error or precision of
+the addressing mode calculations and the image filter operation are not
+defined by this revision of the OpenCL specification.
+To ensure a minimum precision of image addressing and filter calculations
+across any OpenCL device, for these sampler combinations, developers should
+unnormalize the image coordinate in the kernel and implement the linear
+filter in the kernel with appropriate calls to <strong>read_image{f|i|ui}</strong> with a
+sampler that uses unnormalized coordinates, filter mode set to
+<code>CLK_FILTER_NEAREST</code>, addressing mode set to <code>CLK_ADDRESS_NONE</code>,
+<code>CLK_ADDRESS_CLAMP_TO_EDGE</code> <em>or</em> <code>CLK_ADDRESS_CLAMP</code>, and finally performing
+the interpolation of color values read from the image to generate the
+filtered color value.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+</div>
+<div class="sect2">
+<h3 id="conversion-rules">3.3. Conversion Rules</h3>
+<div class="paragraph">
+<p>In this section we discuss conversion rules that are applied when reading
+and writing images in a kernel.</p>
+</div>
+<div class="sect3">
+<h4 id="conversion-rules-for-normalized-integer-channel-data-types">3.3.1. Conversion rules for normalized integer channel data types</h4>
+<div class="paragraph">
+<p>In this section we discuss converting normalized integer channel data types
+to floating-point values and vice-versa.</p>
+</div>
+<div class="sect4">
+<h5 id="converting-normalized-integer-channel-data-types-to-floating-point-values">Converting normalized integer channel data types to floating-point values</h5>
+<div class="paragraph">
+<p>For images created with image channel data type of <code>CL_UNORM_INT8</code> and
+<code>CL_UNORM_INT16</code>, <strong>read_imagef</strong> will convert the channel values from an
+8-bit or 16-bit unsigned integer to normalized floating-point values in the
+range [<code>0.0f</code>, <code>1.0</code>].</p>
+</div>
+<div class="paragraph">
+<p>For images created with image channel data type of <code>CL_SNORM_INT8</code> and
+<code>CL_SNORM_INT16</code>, <strong>read_imagef</strong> will convert the channel values from an
+8-bit or 16-bit signed integer to normalized floating-point values in the
+range [<code>-1.0</code>, <code>1.0</code>].</p>
+</div>
+<div class="paragraph">
+<p>These conversions are performed as follows:</p>
+</div>
+<div class="paragraph">
+<p><code>CL_UNORM_INT8</code> (8-bit unsigned integer) → <code>float</code></p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p>normalized <code>float</code> value = <code>(float)c / 255.0f</code></p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p><code>CL_UNORM_INT_101010</code> (10-bit unsigned integer) → <code>float</code></p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p>normalized <code>float</code> value = <code>(float)c / 1023.0f</code></p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p><code>CL_UNORM_INT16</code> (16-bit unsigned integer) → <code>float</code></p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p>normalized <code>float</code> value = <code>(float)c / 65535.0f</code></p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p><code>CL_SNORM_INT8</code> (8-bit signed integer) → <code>float</code></p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p>normalized <code>float</code> value = <strong>max</strong>(<code>-1.0f</code>, <code>(float)c / 127.0f</code>)</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p><code>CL_SNORM_INT16</code> (16-bit signed integer) → <code>float</code></p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p>normalized <code>float</code> value = <strong>max</strong>(<code>-1.0f</code>, <code>(float)c / 32767.0f</code>)</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>The precision of the above conversions is &lt;= 1.5 ulp except for the
+following cases.</p>
+</div>
+<div class="paragraph">
+<p>For <code>CL_UNORM_INT8</code></p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p>0 must convert to <code>0.0f</code> and</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p>255 must convert to <code>1.0f</code></p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>For <code>CL_UNORM_INT_101010</code></p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p>0 must convert to <code>0.0f</code> and</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p>1023 must convert to <code>1.0f</code></p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>For <code>CL_UNORM_INT16</code></p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p>0 must convert to <code>0.0f</code> and</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p>65535 must convert to <code>1.0f</code></p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>For <code>CL_SNORM_INT8</code></p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p>-128 and -127 must convert to <code>-1.0f</code>,</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p>0 must convert to <code>0.0f</code> and</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p>127 must convert to <code>1.0f</code></p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>For <code>CL_SNORM_INT16</code></p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p>-32768 and -32767 must convert to <code>-1.0f</code>,</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p>0 must convert to <code>0.0f</code> and</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p>32767 must convert to <code>1.0f</code></p>
+</dd>
+</dl>
+</div>
+</div>
+<div class="sect4">
+<h5 id="converting-floating-point-values-to-normalized-integer-channel-data-types">Converting floating-point values to normalized integer channel data types</h5>
+<div class="paragraph">
+<p>For images created with image channel data type of <code>CL_UNORM_INT8</code> and
+<code>CL_UNORM_INT16</code>, <strong>write_imagef</strong> will convert the floating-point color value
+to an 8-bit or 16-bit unsigned integer.</p>
+</div>
+<div class="paragraph">
+<p>For images created with image channel data type of <code>CL_SNORM_INT8</code> and
+<code>CL_SNORM_INT16</code>, <strong>write_imagef</strong> will convert the floating-point color value
+to an 8-bit or 16-bit signed integer.</p>
+</div>
+<div class="paragraph">
+<p>The preferred method for how conversions from floating-point values to
+normalized integer values are performed is as follows:</p>
+</div>
+<div class="paragraph">
+<p><code>float</code> → <code>CL_UNORM_INT8</code> (8-bit unsigned integer)</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>convert_uchar_sat_rte</strong>(<code>f * 255.0f</code>)</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p><code>float</code> → <code>CL_UNORM_INT_101010</code> (10-bit unsigned integer)</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>min</strong>(<strong>convert_ushort_sat_rte</strong>(<code>f * 1023.0f</code>), <code>0x3ff</code>)</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p><code>float</code> → <code>CL_UNORM_INT16</code> (16-bit unsigned integer)</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>convert_ushort_sat_rte</strong>(<code>f * 65535.0f</code>)</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p><code>float</code> → <code>CL_SNORM_INT8</code> (8-bit signed integer)</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>convert_char_sat_rte</strong>(<code>f * 127.0f</code>)</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p><code>float</code> → <code>CL_SNORM_INT16</code> (16-bit signed integer)</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>convert_short_sat_rte</strong>(<code>f * 32767.0f</code>)</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>Please refer to the <a href="#out-of-range-behavior">out-of-range behavior and
+saturated conversion</a> rules.</p>
+</div>
+<div class="paragraph">
+<p>OpenCL implementations may choose to approximate the rounding mode used in
+the conversions described above.
+If a rounding mode other than round to nearest even (<code>_rte</code>) is used, the
+absolute error of the implementation dependant rounding mode vs.
+the result produced by the round to nearest even rounding mode must be ≤
+0.6.</p>
+</div>
+<div class="paragraph">
+<p><code>float</code> → <code>CL_UNORM_INT8</code> (8-bit unsigned integer)</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p>Let f<sub>preferred</sub> = <strong>convert_uchar_sat_rte</strong>(f * <code>255.0f</code>)</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p>Let f<sub>approx</sub> = <strong>convert_uchar_sat_&lt;impl-rounding-mode&gt;</strong>(f * <code>255.0f</code>)</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>fabs</strong>(f<sub>preferred</sub> - f<sub>approx</sub>) must be &lt;= 0.6</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p><code>float</code> → <code>CL_UNORM_INT_101010</code> (10-bit unsigned integer)</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p>Let f<sub>preferred</sub> = <strong>convert_ushort_sat_rte</strong>(f * <code>1023.0f</code>)</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p>Let f<sub>approx</sub> = <strong>convert_ushort_sat_&lt;impl-rounding-mode&gt;</strong>(f *
+<code>1023.0f</code>)</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>fabs</strong>(f<sub>preferred</sub> - f<sub>approx</sub>) must be &lt;= 0.6</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p><code>float</code> → <code>CL_UNORM_INT16</code> (16-bit unsigned integer)</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p>Let f<sub>preferred</sub> = <strong>convert_ushort_sat_rte</strong>(f * <code>65535.0f</code>)</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p>Let f<sub>approx</sub> = <strong>convert_ushort_sat_&lt;impl-rounding-mode&gt;</strong>(f *
+<code>65535.0f</code>)</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>fabs</strong>(f<sub>preferred</sub> - f<sub>approx</sub>) must be &lt;= 0.6</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p><code>float</code> → <code>CL_SNORM_INT8</code> (8-bit signed integer)</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p>Let f<sub>preferred</sub> = <strong>convert_char_sat_rte</strong>(f * <code>127.0f</code>)</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p>Let f<sub>approx</sub> = <strong>convert_char_sat_&lt;impl_rounding_mode&gt;</strong>(f * <code>127.0f</code>)</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>fabs</strong>(f<sub>preferred</sub> - f<sub>approx</sub>) must be &lt;= 0.6</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p><code>float</code> → <code>CL_SNORM_INT16</code> (16-bit signed integer)</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p>Let f<sub>preferred</sub> = <strong>convert_short_sat_rte</strong>(f * <code>32767.0f</code>)</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p>Let f<sub>approx</sub> = <strong>convert_short_sat_&lt;impl-rounding-mode&gt;</strong>(f *
+<code>32767.0f</code>)</p>
+</dd>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>fabs</strong>(f<sub>preferred</sub> - f<sub>approx</sub>) must be &lt;= 0.6</p>
+</dd>
+</dl>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="conversion-rules-for-half-precision-floating-point-channel-data-type">3.3.2. Conversion rules for half precision floating-point channel data type</h4>
+<div class="paragraph">
+<p>For images created with a channel data type of <code>CL_HALF_FLOAT</code>, the
+conversions from <code>half</code> to <code>float</code> are lossless (as described in
+<a href="#the-half-data-type">"The half data type"</a>).
+Conversions from <code>float</code> to <code>half</code> round the mantissa using the round to
+nearest even or round to zero rounding mode.
+Denormalized numbers for the <code>half</code> data type which may be generated when
+converting a <code>float</code> to a <code>half</code> may be flushed to zero.
+A <code>float</code> NaN must be converted to an appropriate NaN in the <code>half</code> type.
+A <code>float</code> <code>INF</code> must be converted to an appropriate <code>INF</code> in the <code>half</code>
+type.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="conversion-rules-for-floating-point-channel-data-type">3.3.3. Conversion rules for floating-point channel data type</h4>
+<div class="paragraph">
+<p>The following rules apply for reading and writing images created with
+channel data type of <code>CL_FLOAT</code>.</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>NaNs may be converted to a NaN value(s) supported by the device.</p>
+</li>
+<li>
+<p>Denorms can be flushed to zero.</p>
+</li>
+<li>
+<p>All other values must be preserved.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="conversion-rules-for-signed-and-unsigned-8-bit-16-bit-and-32-bit-integer-channel-data-types">3.3.4. Conversion rules for signed and unsigned 8-bit, 16-bit and 32-bit integer channel data types</h4>
+<div class="paragraph">
+<p>Calls to <strong>read_imagei</strong> with channel data type values of <code>CL_SIGNED_INT8</code>,
+<code>CL_SIGNED_INT16</code> and <code>CL_SIGNED_INT32</code> return the unmodified integer values
+stored in the image at specified location.</p>
+</div>
+<div class="paragraph">
+<p>Calls to <strong>read_imageui</strong> with channel data type values of <code>CL_UNSIGNED_INT8</code>,
+<code>CL_UNSIGNED_INT16</code> and <code>CL_UNSIGNED_INT32</code> return the unmodified integer
+values stored in the image at specified location.</p>
+</div>
+<div class="paragraph">
+<p>Calls to <strong>write_imagei</strong> will perform one of the following conversions:</p>
+</div>
+<div class="paragraph">
+<p>32 bit signed integer → 8-bit signed integer</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>convert_char_sat</strong>(i)</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>32 bit signed integer → 16-bit signed integer</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>convert_short_sat</strong>(i)</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>32 bit signed integer → 32-bit signed integer</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p>no conversion is performed</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>Calls to <strong>write_imageui</strong> will perform one of the following conversions:</p>
+</div>
+<div class="paragraph">
+<p>32 bit unsigned integer → 8-bit unsigned integer</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>convert_uchar_sat</strong>(i)</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>32 bit unsigned integer → 16-bit unsigned integer</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p><strong>convert_ushort_sat</strong>(i)</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>32 bit unsigned integer → 32-bit unsigned integer</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p>no conversion is performed</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>The conversions described in this section must be correctly saturated.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="conversion-rules-for-srgba-and-sbgra-images">3.3.5. Conversion rules for sRGBA and sBGRA images</h4>
+<div class="paragraph">
+<p>Standard RGB data, which roughly displays colors in a linear ramp of
+luminosity levels such that an average observer, under average viewing
+conditions, can view them as perceptually equal steps on an average display.
+All 0&#8217;s maps to <code>0.0f</code>, and all 1&#8217;s maps to <code>1.0f</code>.
+The sequence of unsigned integer encodings between all 0&#8217;s and all 1&#8217;s
+represent a nonlinear progression in the floating-point interpretation of
+the numbers between <code>0.0f</code> to <code>1.0f</code>.
+For more detail, see the <a href="#sRGB-spec">SRGB color standard</a>.</p>
+</div>
+<div class="paragraph">
+<p>Conversion from sRGB space is automatically done by <strong>read_imagef</strong> built-in
+functions if the image channel order is one of the sRGB values described
+above.
+When reading from an sRGB image, the conversion from sRGB to linear RGB is
+performed before the filter specified in the sampler specified to
+read_imagef is applied.
+If the format has an alpha channel, the alpha data is stored in linear color
+space.
+Conversion to sRGB space is automatically done by <strong>write_imagef</strong> built-in
+functions if the image channel order is one of the sRGB values described
+above and the device supports writing to sRGB images.</p>
+</div>
+<div class="paragraph">
+<p>If the format has an alpha channel, the alpha data is stored in linear color
+space.</p>
+</div>
+<div class="paragraph">
+<p>The following is the conversion rule for converting a normalized 8-bit
+unsigned integer sRGB color value to a floating-point linear RGB color value
+using <strong>read_imagef</strong>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="comment">// Convert the normalized 8-bit unsigned integer R, G and B channel values</span>
+<span class="comment">// to a floating-point value (call it c) as per rules described in section</span>
+<span class="comment">// 8.3.1.1.</span>
+
+<span class="keyword">if</span> (c &lt;= <span class="float">0</span><span class="float">.04045</span>),
+    result = c / <span class="integer">1</span><span class="float">2</span><span class="float">.92</span>;
+<span class="keyword">else</span>
+    result = powr((c + <span class="float">0</span><span class="float">.055</span>) / <span class="float">1</span><span class="float">.055</span>, <span class="float">2</span><span class="float">.4</span>);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The resulting floating point value, if converted back to an sRGB value
+without rounding to a 8-bit unsigned integer value, must be within 0.5 ulp
+of the original sRGB value.</p>
+</div>
+<div class="paragraph">
+<p>The following are the conversion rules for converting a linear RGB
+floating-point color value (call it <em>c</em>) to a normalized 8-bit unsigned
+integer sRGB value using <strong>write_imagef</strong>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code data-lang="c"><span class="keyword">if</span> (c is NaN)
+    c = <span class="float">0</span><span class="float">.0</span>;
+<span class="keyword">if</span> (c &gt; <span class="float">1</span><span class="float">.0</span>)
+    c = <span class="float">1</span><span class="float">.0</span>;
+<span class="keyword">else</span> <span class="keyword">if</span> (c &lt; <span class="float">0</span><span class="float">.0</span>)
+    c = <span class="float">0</span><span class="float">.0</span>;
+<span class="keyword">else</span> <span class="keyword">if</span> (c &lt; <span class="float">0</span><span class="float">.0031308</span>)
+    c = <span class="integer">1</span><span class="float">2</span><span class="float">.92</span> * c;
+<span class="keyword">else</span>
+    c = <span class="float">1</span><span class="float">.055</span> * powr(c, <span class="float">1</span><span class="float">.0</span>/<span class="float">2</span><span class="float">.4</span>) - <span class="float">0</span><span class="float">.055</span>;
+
+scaled_reference_result = c * <span class="integer">255</span>
+channel_component = floor(scaled_reference_result + <span class="float">0</span><span class="float">.5</span>);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The precision of the above conversion should be such that</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p><code>|generated_channel_component - scaled_reference_result|</code> ≤ 0.6</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>where <code>generated_channel_component</code> is the actual value that the
+implementation produces and being checked for conformance.</p>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="selecting-an-image-from-an-image-array">3.4. Selecting an Image from an Image Array</h3>
+<div class="paragraph">
+<p>Let (<em>u</em>,<em>v</em>,<em>w</em>) represent the unnormalized image coordinate values for
+reading from and/or writing to a 2D image in a 2D image array.</p>
+</div>
+<div class="paragraph">
+<p>When read using a sampler, the 2D image layer selected is computed as:</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p>layer = <strong>clamp</strong>(<strong>rint</strong>(<em>w</em>), 0, d<sub>t</sub> - 1)</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>otherwise the layer selected is computed as:</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p>layer = <em>w</em></p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>(since <em>w</em> is already an integer) and the result is undefined if <em>w</em> is not
+one of the integers 0, 1, &#8230;&#8203; d<sub>t</sub> - 1.</p>
+</div>
+<div class="paragraph">
+<p>Let (<em>u</em>,<em>v</em>) represent the unnormalized image coordinate values for reading
+from and/or writing to a 1D image in a 1D image array.</p>
+</div>
+<div class="paragraph">
+<p>When read using a sampler, the 1D image layer selected is computed as:</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p>layer = <strong>clamp</strong>(<strong>rint</strong>(<em>v</em>), 0, h<sub>t</sub> - 1)</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>otherwise the layer selected is computed as:</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p>layer = <em>v</em></p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>(since <em>v</em> is already an integer) and the result is undefined if <em>v</em> is not
+one of the integers 0, 1, &#8230;&#8203; h<sub>t</sub> - 1.</p>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="references">4. Normative References</h2>
+<div class="sectionbody">
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p><a id="C99-spec"></a> &#8220;ISO/IEC 9899:1999 - Programming Languages - C&#8221;, with
+technical corrigenda TC1 and TC2,
+<a href="https://www.iso.org/standard/29237.html" class="bare">https://www.iso.org/standard/29237.html</a> .
+References are to sections of this specific version, referred to as the
+&#8220;C99 Specification&#8221;, although other versions exist.</p>
+</li>
+<li>
+<p><a id="C11-spec"></a> &#8220;ISO/IEC 9899:2011 - Information technology - Programming
+languages - C&#8221;, <a href="https://www.iso.org/standard/57853.html" class="bare">https://www.iso.org/standard/57853.html</a> .
+References are to sections of this specific version, referred to as the
+&#8220;C11 Specification&#8221;, although other versions exist.</p>
+</li>
+<li>
+<p><a id="opencl-spec"></a> &#8220;The OpenCL Specification, Version 2.0&#8221;,
+<a href="https://www.khronos.org/registry/OpenCL/" class="bare">https://www.khronos.org/registry/OpenCL/</a> .
+References are to sections and tables of this specific version, although
+other versions exists.</p>
+</li>
+<li>
+<p><a id="opencl-device-queries"></a> &#8220;Device Queries&#8221; are defined in the
+<a href="#opencl-spec">OpenCL Specification</a> for <strong>clGetDeviceInfo</strong>, and the
+individual queries are defined in the &#8220;OpenCL Device Queries&#8221; table
+(4.3) of that Specification.</p>
+</li>
+<li>
+<p><a id="opencl-channel-order"></a> &#8220;Image Channel Order&#8221; is
+defined in the <a href="#opencl-spec">OpenCL Specification</a> in the &#8220;Image
+Format Descriptor&#8221; section (5.3.1.1), and the individual channel orders
+are defined in the &#8220;List of supported Image Channel Order Values&#8221;
+table (5.6) of that Specification.</p>
+</li>
+<li>
+<p><a id="opencl-channel-data-type"></a> &#8220;Image Channel
+Data Type" is defined in the <a href="#opencl-spec">OpenCL Specification</a> in the
+"`Image Format Descriptor&#8221; section (5.3.1.1), and the individual
+channel data types are defined in the "`List of supported Image Channel
+Data Types" table (5.7) of that Specification.</p>
+</li>
+<li>
+<p><a id="opencl-extension-spec"></a> &#8220;The OpenCL Extension Specification, Version
+2.0&#8221;, <a href="https://www.khronos.org/registry/OpenCL/" class="bare">https://www.khronos.org/registry/OpenCL/</a> .
+References are to sections and tables of this specific version, although
+other versions exists.</p>
+</li>
+<li>
+<p><a id="sRGB-spec"></a> &#8220;IEC 61966-2-1:1999 Multimedia systems and equipment -
+Colour measurement and management - Part 2-1: Colour management -
+Default RGB colour space - sRGB&#8221;,
+<a href="https://webstore.iec.ch/publication/6169" class="bare">https://webstore.iec.ch/publication/6169</a> .</p>
+</li>
+</ol>
+</div>
+</div>
+</div>
+</div>
+<div id="footer">
+<div id="footer-text">
+Version 2.2-7<br>
+Last updated 2018-05-12 14:11:33 BST
+</div>
+</div>
+
+
+</body>
+</html>
\ No newline at end of file
diff --git a/specs/2.2/html/OpenCL_Cxx.html b/specs/2.2/html/OpenCL_Cxx.html
new file mode 100644
index 0000000..f948bde
--- /dev/null
+++ b/specs/2.2/html/OpenCL_Cxx.html
@@ -0,0 +1,20926 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<meta name="generator" content="Asciidoctor 1.5.6.1">
+<meta name="author" content="Khronos OpenCL Working Group">
+<title>The OpenCL&#8482; C++ 1.0 Specification</title>
+<style>
+/*! normalize.css v2.1.2 | MIT License | git.io/normalize */
+/* ========================================================================== HTML5 display definitions ========================================================================== */
+/** Correct `block` display not defined in IE 8/9. */
+article, aside, details, figcaption, figure, footer, header, hgroup, main, nav, section, summary { display: block; }
+
+/** Correct `inline-block` display not defined in IE 8/9. */
+audio, canvas, video { display: inline-block; }
+
+/** Prevent modern browsers from displaying `audio` without controls. Remove excess height in iOS 5 devices. */
+audio:not([controls]) { display: none; height: 0; }
+
+/** Address `[hidden]` styling not present in IE 8/9. Hide the `template` element in IE, Safari, and Firefox < 22. */
+[hidden], template { display: none; }
+
+script { display: none !important; }
+
+/* ========================================================================== Base ========================================================================== */
+/** 1. Set default font family to sans-serif. 2. Prevent iOS text size adjust after orientation change, without disabling user zoom. */
+html { font-family: sans-serif; /* 1 */ -ms-text-size-adjust: 100%; /* 2 */ -webkit-text-size-adjust: 100%; /* 2 */ }
+
+/** Remove default margin. */
+body { margin: 0; }
+
+/* ========================================================================== Links ========================================================================== */
+/** Remove the gray background color from active links in IE 10. */
+a { background: transparent; }
+
+/** Address `outline` inconsistency between Chrome and other browsers. */
+a:focus { outline: thin dotted; }
+
+/** Improve readability when focused and also mouse hovered in all browsers. */
+a:active, a:hover { outline: 0; }
+
+/* ========================================================================== Typography ========================================================================== */
+/** Address variable `h1` font-size and margin within `section` and `article` contexts in Firefox 4+, Safari 5, and Chrome. */
+h1 { font-size: 2em; margin: 0.67em 0; }
+
+/** Address styling not present in IE 8/9, Safari 5, and Chrome. */
+abbr[title] { border-bottom: 1px dotted; }
+
+/** Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome. */
+b, strong { font-weight: bold; }
+
+/** Address styling not present in Safari 5 and Chrome. */
+dfn { font-style: italic; }
+
+/** Address differences between Firefox and other browsers. */
+hr { -moz-box-sizing: content-box; box-sizing: content-box; height: 0; }
+
+/** Address styling not present in IE 8/9. */
+mark { background: #ff0; color: #000; }
+
+/** Correct font family set oddly in Safari 5 and Chrome. */
+code, kbd, pre, samp { font-family: monospace, serif; font-size: 1em; }
+
+/** Improve readability of pre-formatted text in all browsers. */
+pre { white-space: pre-wrap; }
+
+/** Set consistent quote types. */
+q { quotes: "\201C" "\201D" "\2018" "\2019"; }
+
+/** Address inconsistent and variable font size in all browsers. */
+small { font-size: 80%; }
+
+/** Prevent `sub` and `sup` affecting `line-height` in all browsers. */
+sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }
+
+sup { top: -0.5em; }
+
+sub { bottom: -0.25em; }
+
+/* ========================================================================== Embedded content ========================================================================== */
+/** Remove border when inside `a` element in IE 8/9. */
+img { border: 0; }
+
+/** Correct overflow displayed oddly in IE 9. */
+svg:not(:root) { overflow: hidden; }
+
+/* ========================================================================== Figures ========================================================================== */
+/** Address margin not present in IE 8/9 and Safari 5. */
+figure { margin: 0; }
+
+/* ========================================================================== Forms ========================================================================== */
+/** Define consistent border, margin, and padding. */
+fieldset { border: 1px solid #c0c0c0; margin: 0 2px; padding: 0.35em 0.625em 0.75em; }
+
+/** 1. Correct `color` not being inherited in IE 8/9. 2. Remove padding so people aren't caught out if they zero out fieldsets. */
+legend { border: 0; /* 1 */ padding: 0; /* 2 */ }
+
+/** 1. Correct font family not being inherited in all browsers. 2. Correct font size not being inherited in all browsers. 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome. */
+button, input, select, textarea { font-family: inherit; /* 1 */ font-size: 100%; /* 2 */ margin: 0; /* 3 */ }
+
+/** Address Firefox 4+ setting `line-height` on `input` using `!important` in the UA stylesheet. */
+button, input { line-height: normal; }
+
+/** Address inconsistent `text-transform` inheritance for `button` and `select`. All other form control elements do not inherit `text-transform` values. Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+. Correct `select` style inheritance in Firefox 4+ and Opera. */
+button, select { text-transform: none; }
+
+/** 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` and `video` controls. 2. Correct inability to style clickable `input` types in iOS. 3. Improve usability and consistency of cursor style between image-type `input` and others. */
+button, html input[type="button"], input[type="reset"], input[type="submit"] { -webkit-appearance: button; /* 2 */ cursor: pointer; /* 3 */ }
+
+/** Re-set default cursor for disabled elements. */
+button[disabled], html input[disabled] { cursor: default; }
+
+/** 1. Address box sizing set to `content-box` in IE 8/9. 2. Remove excess padding in IE 8/9. */
+input[type="checkbox"], input[type="radio"] { box-sizing: border-box; /* 1 */ padding: 0; /* 2 */ }
+
+/** 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome (include `-moz` to future-proof). */
+input[type="search"] { -webkit-appearance: textfield; /* 1 */ -moz-box-sizing: content-box; -webkit-box-sizing: content-box; /* 2 */ box-sizing: content-box; }
+
+/** Remove inner padding and search cancel button in Safari 5 and Chrome on OS X. */
+input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; }
+
+/** Remove inner padding and border in Firefox 4+. */
+button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; }
+
+/** 1. Remove default vertical scrollbar in IE 8/9. 2. Improve readability and alignment in all browsers. */
+textarea { overflow: auto; /* 1 */ vertical-align: top; /* 2 */ }
+
+/* ========================================================================== Tables ========================================================================== */
+/** Remove most spacing between table cells. */
+table { border-collapse: collapse; border-spacing: 0; }
+
+meta.foundation-mq-small { font-family: "only screen and (min-width: 768px)"; width: 768px; }
+
+meta.foundation-mq-medium { font-family: "only screen and (min-width:1280px)"; width: 1280px; }
+
+meta.foundation-mq-large { font-family: "only screen and (min-width:1440px)"; width: 1440px; }
+
+*, *:before, *:after { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; }
+
+html, body { font-size: 100%; }
+
+body { background: white; color: #222222; padding: 0; margin: 0; font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; font-weight: normal; font-style: normal; line-height: 1; position: relative; cursor: auto; }
+
+a:hover { cursor: pointer; }
+
+img, object, embed { max-width: 100%; height: auto; }
+
+object, embed { height: 100%; }
+
+img { -ms-interpolation-mode: bicubic; }
+
+#map_canvas img, #map_canvas embed, #map_canvas object, .map_canvas img, .map_canvas embed, .map_canvas object { max-width: none !important; }
+
+.left { float: left !important; }
+
+.right { float: right !important; }
+
+.text-left { text-align: left !important; }
+
+.text-right { text-align: right !important; }
+
+.text-center { text-align: center !important; }
+
+.text-justify { text-align: justify !important; }
+
+.hide { display: none; }
+
+.antialiased { -webkit-font-smoothing: antialiased; }
+
+img { display: inline-block; vertical-align: middle; }
+
+textarea { height: auto; min-height: 50px; }
+
+select { width: 100%; }
+
+object, svg { display: inline-block; vertical-align: middle; }
+
+.center { margin-left: auto; margin-right: auto; }
+
+.spread { width: 100%; }
+
+p.lead, .paragraph.lead > p, #preamble > .sectionbody > .paragraph:first-of-type p { font-size: 1.21875em; line-height: 1.6; }
+
+.subheader, .admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { line-height: 1.4; color: black; font-weight: 300; margin-top: 0.2em; margin-bottom: 0.5em; }
+
+/* Typography resets */
+div, dl, dt, dd, ul, ol, li, h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6, pre, form, p, blockquote, th, td { margin: 0; padding: 0; direction: ltr; }
+
+/* Default Link Styles */
+a { color: #0068b0; text-decoration: none; line-height: inherit; }
+a:hover, a:focus { color: #333333; }
+a img { border: none; }
+
+/* Default paragraph styles */
+p { font-family: Noto, sans-serif; font-weight: normal; font-size: 1em; line-height: 1.6; margin-bottom: 0.75em; text-rendering: optimizeLegibility; }
+p aside { font-size: 0.875em; line-height: 1.35; font-style: italic; }
+
+/* Default header styles */
+h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { font-family: Noto, sans-serif; font-weight: normal; font-style: normal; color: black; text-rendering: optimizeLegibility; margin-top: 0.5em; margin-bottom: 0.5em; line-height: 1.2125em; }
+h1 small, h2 small, h3 small, #toctitle small, .sidebarblock > .content > .title small, h4 small, h5 small, h6 small { font-size: 60%; color: #4d4d4d; line-height: 0; }
+
+h1 { font-size: 2.125em; }
+
+h2 { font-size: 1.6875em; }
+
+h3, #toctitle, .sidebarblock > .content > .title { font-size: 1.375em; }
+
+h4 { font-size: 1.125em; }
+
+h5 { font-size: 1.125em; }
+
+h6 { font-size: 1em; }
+
+hr { border: solid #dddddd; border-width: 1px 0 0; clear: both; margin: 1.25em 0 1.1875em; height: 0; }
+
+/* Helpful Typography Defaults */
+em, i { font-style: italic; line-height: inherit; }
+
+strong, b { font-weight: bold; line-height: inherit; }
+
+small { font-size: 60%; line-height: inherit; }
+
+code { font-family: Consolas, "Liberation Mono", Courier, monospace; font-weight: normal; color: #264357; }
+
+/* Lists */
+ul, ol, dl { font-size: 1em; line-height: 1.6; margin-bottom: 0.75em; list-style-position: outside; font-family: Noto, sans-serif; }
+
+ul, ol { margin-left: 1.5em; }
+ul.no-bullet, ol.no-bullet { margin-left: 1.5em; }
+
+/* Unordered Lists */
+ul li ul, ul li ol { margin-left: 1.25em; margin-bottom: 0; font-size: 1em; /* Override nested font-size change */ }
+ul.square li ul, ul.circle li ul, ul.disc li ul { list-style: inherit; }
+ul.square { list-style-type: square; }
+ul.circle { list-style-type: circle; }
+ul.disc { list-style-type: disc; }
+ul.no-bullet { list-style: none; }
+
+/* Ordered Lists */
+ol li ul, ol li ol { margin-left: 1.25em; margin-bottom: 0; }
+
+/* Definition Lists */
+dl dt { margin-bottom: 0.3em; font-weight: bold; }
+dl dd { margin-bottom: 0.75em; }
+
+/* Abbreviations */
+abbr, acronym { text-transform: uppercase; font-size: 90%; color: black; border-bottom: 1px dotted #dddddd; cursor: help; }
+
+abbr { text-transform: none; }
+
+/* Blockquotes */
+blockquote { margin: 0 0 0.75em; padding: 0.5625em 1.25em 0 1.1875em; border-left: 1px solid #dddddd; }
+blockquote cite { display: block; font-size: 0.8125em; color: #5e93b8; }
+blockquote cite:before { content: "\2014 \0020"; }
+blockquote cite a, blockquote cite a:visited { color: #5e93b8; }
+
+blockquote, blockquote p { line-height: 1.6; color: #333333; }
+
+/* Microformats */
+.vcard { display: inline-block; margin: 0 0 1.25em 0; border: 1px solid #dddddd; padding: 0.625em 0.75em; }
+.vcard li { margin: 0; display: block; }
+.vcard .fn { font-weight: bold; font-size: 0.9375em; }
+
+.vevent .summary { font-weight: bold; }
+.vevent abbr { cursor: auto; text-decoration: none; font-weight: bold; border: none; padding: 0 0.0625em; }
+
+@media only screen and (min-width: 768px) { h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { line-height: 1.4; }
+  h1 { font-size: 2.75em; }
+  h2 { font-size: 2.3125em; }
+  h3, #toctitle, .sidebarblock > .content > .title { font-size: 1.6875em; }
+  h4 { font-size: 1.4375em; } }
+/* Tables */
+table { background: white; margin-bottom: 1.25em; border: solid 1px #d8d8ce; }
+table thead, table tfoot { background: -webkit-linear-gradient(top, #add386, #90b66a); font-weight: bold; }
+table thead tr th, table thead tr td, table tfoot tr th, table tfoot tr td { padding: 0.5em 0.625em 0.625em; font-size: inherit; color: white; text-align: left; }
+table tr th, table tr td { padding: 0.5625em 0.625em; font-size: inherit; color: #6d6e71; }
+table tr.even, table tr.alt, table tr:nth-of-type(even) { background: #edf2f2; }
+table thead tr th, table tfoot tr th, table tbody tr td, table tr td, table tfoot tr td { display: table-cell; line-height: 1.4; }
+
+body { -moz-osx-font-smoothing: grayscale; -webkit-font-smoothing: antialiased; tab-size: 4; }
+
+h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { line-height: 1.4; }
+
+a:hover, a:focus { text-decoration: underline; }
+
+.clearfix:before, .clearfix:after, .float-group:before, .float-group:after { content: " "; display: table; }
+.clearfix:after, .float-group:after { clear: both; }
+
+*:not(pre) > code { font-size: inherit; font-style: normal !important; letter-spacing: 0; padding: 0; background-color: white; -webkit-border-radius: 0; border-radius: 0; line-height: inherit; word-wrap: break-word; }
+*:not(pre) > code.nobreak { word-wrap: normal; }
+*:not(pre) > code.nowrap { white-space: nowrap; }
+
+pre, pre > code { line-height: 1.6; color: #264357; font-family: Consolas, "Liberation Mono", Courier, monospace; font-weight: normal; }
+
+em em { font-style: normal; }
+
+strong strong { font-weight: normal; }
+
+.keyseq { color: #333333; }
+
+kbd { font-family: Consolas, "Liberation Mono", Courier, monospace; display: inline-block; color: black; font-size: 0.65em; line-height: 1.45; background-color: #f7f7f7; border: 1px solid #ccc; -webkit-border-radius: 3px; border-radius: 3px; -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 0.1em white inset; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 0.1em white inset; margin: 0 0.15em; padding: 0.2em 0.5em; vertical-align: middle; position: relative; top: -0.1em; white-space: nowrap; }
+
+.keyseq kbd:first-child { margin-left: 0; }
+
+.keyseq kbd:last-child { margin-right: 0; }
+
+.menuseq, .menuref { color: #000; }
+
+.menuseq b:not(.caret), .menuref { font-weight: inherit; }
+
+.menuseq { word-spacing: -0.02em; }
+.menuseq b.caret { font-size: 1.25em; line-height: 0.8; }
+.menuseq i.caret { font-weight: bold; text-align: center; width: 0.45em; }
+
+b.button:before, b.button:after { position: relative; top: -1px; font-weight: normal; }
+
+b.button:before { content: "["; padding: 0 3px 0 2px; }
+
+b.button:after { content: "]"; padding: 0 2px 0 3px; }
+
+#header, #content, #footnotes, #footer { width: 100%; margin-left: auto; margin-right: auto; margin-top: 0; margin-bottom: 0; max-width: 62.5em; *zoom: 1; position: relative; padding-left: 1.5em; padding-right: 1.5em; }
+#header:before, #header:after, #content:before, #content:after, #footnotes:before, #footnotes:after, #footer:before, #footer:after { content: " "; display: table; }
+#header:after, #content:after, #footnotes:after, #footer:after { clear: both; }
+
+#content { margin-top: 1.25em; }
+
+#content:before { content: none; }
+
+#header > h1:first-child { color: black; margin-top: 2.25rem; margin-bottom: 0; }
+#header > h1:first-child + #toc { margin-top: 8px; border-top: 1px solid #dddddd; }
+#header > h1:only-child, body.toc2 #header > h1:nth-last-child(2) { border-bottom: 1px solid #dddddd; padding-bottom: 8px; }
+#header .details { border-bottom: 1px solid #dddddd; line-height: 1.45; padding-top: 0.25em; padding-bottom: 0.25em; padding-left: 0.25em; color: #5e93b8; display: -ms-flexbox; display: -webkit-flex; display: flex; -ms-flex-flow: row wrap; -webkit-flex-flow: row wrap; flex-flow: row wrap; }
+#header .details span:first-child { margin-left: -0.125em; }
+#header .details span.email a { color: #333333; }
+#header .details br { display: none; }
+#header .details br + span:before { content: "\00a0\2013\00a0"; }
+#header .details br + span.author:before { content: "\00a0\22c5\00a0"; color: #333333; }
+#header .details br + span#revremark:before { content: "\00a0|\00a0"; }
+#header #revnumber { text-transform: capitalize; }
+#header #revnumber:after { content: "\00a0"; }
+
+#content > h1:first-child:not([class]) { color: black; border-bottom: 1px solid #dddddd; padding-bottom: 8px; margin-top: 0; padding-top: 1rem; margin-bottom: 1.25rem; }
+
+#toc { border-bottom: 0 solid #dddddd; padding-bottom: 0.5em; }
+#toc > ul { margin-left: 0.125em; }
+#toc ul.sectlevel0 > li > a { font-style: italic; }
+#toc ul.sectlevel0 ul.sectlevel1 { margin: 0.5em 0; }
+#toc ul { font-family: Noto, sans-serif; list-style-type: none; }
+#toc li { line-height: 1.3334; margin-top: 0.3334em; }
+#toc a { text-decoration: none; }
+#toc a:active { text-decoration: underline; }
+
+#toctitle { color: black; font-size: 1.2em; }
+
+@media only screen and (min-width: 768px) { #toctitle { font-size: 1.375em; }
+  body.toc2 { padding-left: 15em; padding-right: 0; }
+  #toc.toc2 { margin-top: 0 !important; background-color: white; position: fixed; width: 15em; left: 0; top: 0; border-right: 1px solid #dddddd; border-top-width: 0 !important; border-bottom-width: 0 !important; z-index: 1000; padding: 1.25em 1em; height: 100%; overflow: auto; }
+  #toc.toc2 #toctitle { margin-top: 0; margin-bottom: 0.8rem; font-size: 1.2em; }
+  #toc.toc2 > ul { font-size: 0.9em; margin-bottom: 0; }
+  #toc.toc2 ul ul { margin-left: 0; padding-left: 1em; }
+  #toc.toc2 ul.sectlevel0 ul.sectlevel1 { padding-left: 0; margin-top: 0.5em; margin-bottom: 0.5em; }
+  body.toc2.toc-right { padding-left: 0; padding-right: 15em; }
+  body.toc2.toc-right #toc.toc2 { border-right-width: 0; border-left: 1px solid #dddddd; left: auto; right: 0; } }
+@media only screen and (min-width: 1280px) { body.toc2 { padding-left: 20em; padding-right: 0; }
+  #toc.toc2 { width: 20em; }
+  #toc.toc2 #toctitle { font-size: 1.375em; }
+  #toc.toc2 > ul { font-size: 0.95em; }
+  #toc.toc2 ul ul { padding-left: 1.25em; }
+  body.toc2.toc-right { padding-left: 0; padding-right: 20em; } }
+#content #toc { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 0; border-radius: 0; }
+#content #toc > :first-child { margin-top: 0; }
+#content #toc > :last-child { margin-bottom: 0; }
+
+#footer { max-width: 100%; background-color: none; padding: 1.25em; }
+
+#footer-text { color: black; line-height: 1.44; }
+
+#content { margin-bottom: 0.625em; }
+
+.sect1 { padding-bottom: 0.625em; }
+
+@media only screen and (min-width: 768px) { #content { margin-bottom: 1.25em; }
+  .sect1 { padding-bottom: 1.25em; } }
+.sect1:last-child { padding-bottom: 0; }
+
+.sect1 + .sect1 { border-top: 0 solid #dddddd; }
+
+#content h1 > a.anchor, h2 > a.anchor, h3 > a.anchor, #toctitle > a.anchor, .sidebarblock > .content > .title > a.anchor, h4 > a.anchor, h5 > a.anchor, h6 > a.anchor { position: absolute; z-index: 1001; width: 1.5ex; margin-left: -1.5ex; display: block; text-decoration: none !important; visibility: hidden; text-align: center; font-weight: normal; }
+#content h1 > a.anchor:before, h2 > a.anchor:before, h3 > a.anchor:before, #toctitle > a.anchor:before, .sidebarblock > .content > .title > a.anchor:before, h4 > a.anchor:before, h5 > a.anchor:before, h6 > a.anchor:before { content: "\00A7"; font-size: 0.85em; display: block; padding-top: 0.1em; }
+#content h1:hover > a.anchor, #content h1 > a.anchor:hover, h2:hover > a.anchor, h2 > a.anchor:hover, h3:hover > a.anchor, #toctitle:hover > a.anchor, .sidebarblock > .content > .title:hover > a.anchor, h3 > a.anchor:hover, #toctitle > a.anchor:hover, .sidebarblock > .content > .title > a.anchor:hover, h4:hover > a.anchor, h4 > a.anchor:hover, h5:hover > a.anchor, h5 > a.anchor:hover, h6:hover > a.anchor, h6 > a.anchor:hover { visibility: visible; }
+#content h1 > a.link, h2 > a.link, h3 > a.link, #toctitle > a.link, .sidebarblock > .content > .title > a.link, h4 > a.link, h5 > a.link, h6 > a.link { color: black; text-decoration: none; }
+#content h1 > a.link:hover, h2 > a.link:hover, h3 > a.link:hover, #toctitle > a.link:hover, .sidebarblock > .content > .title > a.link:hover, h4 > a.link:hover, h5 > a.link:hover, h6 > a.link:hover { color: black; }
+
+.audioblock, .imageblock, .literalblock, .listingblock, .stemblock, .videoblock { margin-bottom: 1.25em; }
+
+.admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { text-rendering: optimizeLegibility; text-align: left; }
+
+table.tableblock > caption.title { white-space: nowrap; overflow: visible; max-width: 0; }
+
+.paragraph.lead > p, #preamble > .sectionbody > .paragraph:first-of-type p { color: black; }
+
+table.tableblock #preamble > .sectionbody > .paragraph:first-of-type p { font-size: inherit; }
+
+.admonitionblock > table { border-collapse: separate; border: 0; background: none; width: 100%; }
+.admonitionblock > table td.icon { text-align: center; width: 80px; }
+.admonitionblock > table td.icon img { max-width: initial; }
+.admonitionblock > table td.icon .title { font-weight: bold; font-family: Noto, sans-serif; text-transform: uppercase; }
+.admonitionblock > table td.content { padding-left: 1.125em; padding-right: 1.25em; border-left: 1px solid #dddddd; color: #5e93b8; }
+.admonitionblock > table td.content > :last-child > :last-child { margin-bottom: 0; }
+
+.exampleblock > .content { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 0; border-radius: 0; }
+.exampleblock > .content > :first-child { margin-top: 0; }
+.exampleblock > .content > :last-child { margin-bottom: 0; }
+
+.sidebarblock { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 0; border-radius: 0; }
+.sidebarblock > :first-child { margin-top: 0; }
+.sidebarblock > :last-child { margin-bottom: 0; }
+.sidebarblock > .content > .title { color: black; margin-top: 0; }
+
+.exampleblock > .content > :last-child > :last-child, .exampleblock > .content .olist > ol > li:last-child > :last-child, .exampleblock > .content .ulist > ul > li:last-child > :last-child, .exampleblock > .content .qlist > ol > li:last-child > :last-child, .sidebarblock > .content > :last-child > :last-child, .sidebarblock > .content .olist > ol > li:last-child > :last-child, .sidebarblock > .content .ulist > ul > li:last-child > :last-child, .sidebarblock > .content .qlist > ol > li:last-child > :last-child { margin-bottom: 0; }
+
+.literalblock pre, .listingblock pre:not(.highlight), .listingblock pre[class="highlight"], .listingblock pre[class^="highlight "], .listingblock pre.CodeRay, .listingblock pre.prettyprint { background: #eeeeee; }
+.sidebarblock .literalblock pre, .sidebarblock .listingblock pre:not(.highlight), .sidebarblock .listingblock pre[class="highlight"], .sidebarblock .listingblock pre[class^="highlight "], .sidebarblock .listingblock pre.CodeRay, .sidebarblock .listingblock pre.prettyprint { background: #f2f1f1; }
+
+.literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { border: 1px hidden #666666; -webkit-border-radius: 0; border-radius: 0; word-wrap: break-word; padding: 1.25em 1.5625em 1.125em 1.5625em; font-size: 0.8125em; }
+.literalblock pre.nowrap, .literalblock pre[class].nowrap, .listingblock pre.nowrap, .listingblock pre[class].nowrap { overflow-x: auto; white-space: pre; word-wrap: normal; }
+@media only screen and (min-width: 768px) { .literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { font-size: 0.90625em; } }
+@media only screen and (min-width: 1280px) { .literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { font-size: 1em; } }
+
+.literalblock.output pre { color: #eeeeee; background-color: #264357; }
+
+.listingblock pre.highlightjs { padding: 0; }
+.listingblock pre.highlightjs > code { padding: 1.25em 1.5625em 1.125em 1.5625em; -webkit-border-radius: 0; border-radius: 0; }
+
+.listingblock > .content { position: relative; }
+
+.listingblock code[data-lang]:before { display: none; content: attr(data-lang); position: absolute; font-size: 0.75em; top: 0.425rem; right: 0.5rem; line-height: 1; text-transform: uppercase; color: #999; }
+
+.listingblock:hover code[data-lang]:before { display: block; }
+
+.listingblock.terminal pre .command:before { content: attr(data-prompt); padding-right: 0.5em; color: #999; }
+
+.listingblock.terminal pre .command:not([data-prompt]):before { content: "$"; }
+
+table.pyhltable { border-collapse: separate; border: 0; margin-bottom: 0; background: none; }
+
+table.pyhltable td { vertical-align: top; padding-top: 0; padding-bottom: 0; line-height: 1.6; }
+
+table.pyhltable td.code { padding-left: .75em; padding-right: 0; }
+
+pre.pygments .lineno, table.pyhltable td:not(.code) { color: #999; padding-left: 0; padding-right: .5em; border-right: 1px solid #dddddd; }
+
+pre.pygments .lineno { display: inline-block; margin-right: .25em; }
+
+table.pyhltable .linenodiv { background: none !important; padding-right: 0 !important; }
+
+.quoteblock { margin: 0 1em 0.75em 1.5em; display: table; }
+.quoteblock > .title { margin-left: -1.5em; margin-bottom: 0.75em; }
+.quoteblock blockquote, .quoteblock blockquote p { color: #333333; font-size: 1.15rem; line-height: 1.75; word-spacing: 0.1em; letter-spacing: 0; font-style: italic; text-align: justify; }
+.quoteblock blockquote { margin: 0; padding: 0; border: 0; }
+.quoteblock blockquote:before { content: "\201c"; float: left; font-size: 2.75em; font-weight: bold; line-height: 0.6em; margin-left: -0.6em; color: black; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); }
+.quoteblock blockquote > .paragraph:last-child p { margin-bottom: 0; }
+.quoteblock .attribution { margin-top: 0.5em; margin-right: 0.5ex; text-align: right; }
+.quoteblock .quoteblock { margin-left: 0; margin-right: 0; padding: 0.5em 0; border-left: 3px solid #5e93b8; }
+.quoteblock .quoteblock blockquote { padding: 0 0 0 0.75em; }
+.quoteblock .quoteblock blockquote:before { display: none; }
+
+.verseblock { margin: 0 1em 0.75em 1em; }
+.verseblock pre { font-family: "Open Sans", "DejaVu Sans", sans; font-size: 1.15rem; color: #333333; font-weight: 300; text-rendering: optimizeLegibility; }
+.verseblock pre strong { font-weight: 400; }
+.verseblock .attribution { margin-top: 1.25rem; margin-left: 0.5ex; }
+
+.quoteblock .attribution, .verseblock .attribution { font-size: 0.8125em; line-height: 1.45; font-style: italic; }
+.quoteblock .attribution br, .verseblock .attribution br { display: none; }
+.quoteblock .attribution cite, .verseblock .attribution cite { display: block; letter-spacing: -0.025em; color: #5e93b8; }
+
+.quoteblock.abstract { margin: 0 0 0.75em 0; display: block; }
+.quoteblock.abstract blockquote, .quoteblock.abstract blockquote p { text-align: left; word-spacing: 0; }
+.quoteblock.abstract blockquote:before, .quoteblock.abstract blockquote p:first-of-type:before { display: none; }
+
+table.tableblock { max-width: 100%; border-collapse: separate; }
+table.tableblock td > .paragraph:last-child p > p:last-child, table.tableblock th > p:last-child, table.tableblock td > p:last-child { margin-bottom: 0; }
+
+table.tableblock, th.tableblock, td.tableblock { border: 0 solid #d8d8ce; }
+
+table.grid-all > thead > tr > .tableblock, table.grid-all > tbody > tr > .tableblock { border-width: 0 1px 1px 0; }
+
+table.grid-all > tfoot > tr > .tableblock { border-width: 1px 1px 0 0; }
+
+table.grid-cols > * > tr > .tableblock { border-width: 0 1px 0 0; }
+
+table.grid-rows > thead > tr > .tableblock, table.grid-rows > tbody > tr > .tableblock { border-width: 0 0 1px 0; }
+
+table.grid-rows > tfoot > tr > .tableblock { border-width: 1px 0 0 0; }
+
+table.grid-all > * > tr > .tableblock:last-child, table.grid-cols > * > tr > .tableblock:last-child { border-right-width: 0; }
+
+table.grid-all > tbody > tr:last-child > .tableblock, table.grid-all > thead:last-child > tr > .tableblock, table.grid-rows > tbody > tr:last-child > .tableblock, table.grid-rows > thead:last-child > tr > .tableblock { border-bottom-width: 0; }
+
+table.frame-all { border-width: 1px; }
+
+table.frame-sides { border-width: 0 1px; }
+
+table.frame-topbot { border-width: 1px 0; }
+
+th.halign-left, td.halign-left { text-align: left; }
+
+th.halign-right, td.halign-right { text-align: right; }
+
+th.halign-center, td.halign-center { text-align: center; }
+
+th.valign-top, td.valign-top { vertical-align: top; }
+
+th.valign-bottom, td.valign-bottom { vertical-align: bottom; }
+
+th.valign-middle, td.valign-middle { vertical-align: middle; }
+
+table thead th, table tfoot th { font-weight: bold; }
+
+tbody tr th { display: table-cell; line-height: 1.4; background: -webkit-linear-gradient(top, #add386, #90b66a); }
+
+tbody tr th, tbody tr th p, tfoot tr th, tfoot tr th p { color: white; font-weight: bold; }
+
+p.tableblock > code:only-child { background: none; padding: 0; }
+
+p.tableblock { font-size: 1em; }
+
+td > div.verse { white-space: pre; }
+
+ol { margin-left: 1.75em; }
+
+ul li ol { margin-left: 1.5em; }
+
+dl dd { margin-left: 1.125em; }
+
+dl dd:last-child, dl dd:last-child > :last-child { margin-bottom: 0; }
+
+ol > li p, ul > li p, ul dd, ol dd, .olist .olist, .ulist .ulist, .ulist .olist, .olist .ulist { margin-bottom: 0.375em; }
+
+ul.checklist, ul.none, ol.none, ul.no-bullet, ol.no-bullet, ol.unnumbered, ul.unstyled, ol.unstyled { list-style-type: none; }
+
+ul.no-bullet, ol.no-bullet, ol.unnumbered { margin-left: 0.625em; }
+
+ul.unstyled, ol.unstyled { margin-left: 0; }
+
+ul.checklist { margin-left: 0.625em; }
+
+ul.checklist li > p:first-child > .fa-square-o:first-child, ul.checklist li > p:first-child > .fa-check-square-o:first-child { width: 1.25em; font-size: 0.8em; position: relative; bottom: 0.125em; }
+
+ul.checklist li > p:first-child > input[type="checkbox"]:first-child { margin-right: 0.25em; }
+
+ul.inline { display: -ms-flexbox; display: -webkit-box; display: flex; -ms-flex-flow: row wrap; -webkit-flex-flow: row wrap; flex-flow: row wrap; list-style: none; margin: 0 0 0.375em -0.75em; }
+
+ul.inline > li { margin-left: 0.75em; }
+
+.unstyled dl dt { font-weight: normal; font-style: normal; }
+
+ol.arabic { list-style-type: decimal; }
+
+ol.decimal { list-style-type: decimal-leading-zero; }
+
+ol.loweralpha { list-style-type: lower-alpha; }
+
+ol.upperalpha { list-style-type: upper-alpha; }
+
+ol.lowerroman { list-style-type: lower-roman; }
+
+ol.upperroman { list-style-type: upper-roman; }
+
+ol.lowergreek { list-style-type: lower-greek; }
+
+.hdlist > table, .colist > table { border: 0; background: none; }
+.hdlist > table > tbody > tr, .colist > table > tbody > tr { background: none; }
+
+td.hdlist1, td.hdlist2 { vertical-align: top; padding: 0 0.625em; }
+
+td.hdlist1 { font-weight: bold; padding-bottom: 0.75em; }
+
+.literalblock + .colist, .listingblock + .colist { margin-top: -0.5em; }
+
+.colist > table tr > td:first-of-type { padding: 0.4em 0.75em 0 0.75em; line-height: 1; vertical-align: top; }
+.colist > table tr > td:first-of-type img { max-width: initial; }
+.colist > table tr > td:last-of-type { padding: 0.25em 0; }
+
+.thumb, .th { line-height: 0; display: inline-block; border: solid 4px white; -webkit-box-shadow: 0 0 0 1px #dddddd; box-shadow: 0 0 0 1px #dddddd; }
+
+.imageblock.left, .imageblock[style*="float: left"] { margin: 0.25em 0.625em 1.25em 0; }
+.imageblock.right, .imageblock[style*="float: right"] { margin: 0.25em 0 1.25em 0.625em; }
+.imageblock > .title { margin-bottom: 0; }
+.imageblock.thumb, .imageblock.th { border-width: 6px; }
+.imageblock.thumb > .title, .imageblock.th > .title { padding: 0 0.125em; }
+
+.image.left, .image.right { margin-top: 0.25em; margin-bottom: 0.25em; display: inline-block; line-height: 0; }
+.image.left { margin-right: 0.625em; }
+.image.right { margin-left: 0.625em; }
+
+a.image { text-decoration: none; display: inline-block; }
+a.image object { pointer-events: none; }
+
+sup.footnote, sup.footnoteref { font-size: 0.875em; position: static; vertical-align: super; }
+sup.footnote a, sup.footnoteref a { text-decoration: none; }
+sup.footnote a:active, sup.footnoteref a:active { text-decoration: underline; }
+
+#footnotes { padding-top: 0.75em; padding-bottom: 0.75em; margin-bottom: 0.625em; }
+#footnotes hr { width: 20%; min-width: 6.25em; margin: -0.25em 0 0.75em 0; border-width: 1px 0 0 0; }
+#footnotes .footnote { padding: 0 0.375em 0 0.225em; line-height: 1.3334; font-size: 0.875em; margin-left: 1.2em; margin-bottom: 0.2em; }
+#footnotes .footnote a:first-of-type { font-weight: bold; text-decoration: none; margin-left: -1.05em; }
+#footnotes .footnote:last-of-type { margin-bottom: 0; }
+#content #footnotes { margin-top: -0.625em; margin-bottom: 0; padding: 0.75em 0; }
+
+.gist .file-data > table { border: 0; background: #fff; width: 100%; margin-bottom: 0; }
+.gist .file-data > table td.line-data { width: 99%; }
+
+div.unbreakable { page-break-inside: avoid; }
+
+.big { font-size: larger; }
+
+.small { font-size: smaller; }
+
+.underline { text-decoration: underline; }
+
+.overline { text-decoration: overline; }
+
+.line-through { text-decoration: line-through; }
+
+.aqua { color: #00bfbf; }
+
+.aqua-background { background-color: #00fafa; }
+
+.black { color: black; }
+
+.black-background { background-color: black; }
+
+.blue { color: #0000bf; }
+
+.blue-background { background-color: #0000fa; }
+
+.fuchsia { color: #bf00bf; }
+
+.fuchsia-background { background-color: #fa00fa; }
+
+.gray { color: #606060; }
+
+.gray-background { background-color: #7d7d7d; }
+
+.green { color: #006000; }
+
+.green-background { background-color: #007d00; }
+
+.lime { color: #00bf00; }
+
+.lime-background { background-color: #00fa00; }
+
+.maroon { color: #600000; }
+
+.maroon-background { background-color: #7d0000; }
+
+.navy { color: #000060; }
+
+.navy-background { background-color: #00007d; }
+
+.olive { color: #606000; }
+
+.olive-background { background-color: #7d7d00; }
+
+.purple { color: #600060; }
+
+.purple-background { background-color: #7d007d; }
+
+.red { color: #bf0000; }
+
+.red-background { background-color: #fa0000; }
+
+.silver { color: #909090; }
+
+.silver-background { background-color: #bcbcbc; }
+
+.teal { color: #006060; }
+
+.teal-background { background-color: #007d7d; }
+
+.white { color: #bfbfbf; }
+
+.white-background { background-color: #fafafa; }
+
+.yellow { color: #bfbf00; }
+
+.yellow-background { background-color: #fafa00; }
+
+span.icon > .fa { cursor: default; }
+a span.icon > .fa { cursor: inherit; }
+
+.admonitionblock td.icon [class^="fa icon-"] { font-size: 2.5em; text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5); cursor: default; }
+.admonitionblock td.icon .icon-note:before { content: "\f05a"; color: #29475c; }
+.admonitionblock td.icon .icon-tip:before { content: "\f0eb"; text-shadow: 1px 1px 2px rgba(155, 155, 0, 0.8); color: #111; }
+.admonitionblock td.icon .icon-warning:before { content: "\f071"; color: #bf6900; }
+.admonitionblock td.icon .icon-caution:before { content: "\f06d"; color: #bf3400; }
+.admonitionblock td.icon .icon-important:before { content: "\f06a"; color: #bf0000; }
+
+.conum[data-value] { display: inline-block; color: #fff !important; background-color: black; -webkit-border-radius: 100px; border-radius: 100px; text-align: center; font-size: 0.75em; width: 1.67em; height: 1.67em; line-height: 1.67em; font-family: "Open Sans", "DejaVu Sans", sans-serif; font-style: normal; font-weight: bold; }
+.conum[data-value] * { color: #fff !important; }
+.conum[data-value] + b { display: none; }
+.conum[data-value]:after { content: attr(data-value); }
+pre .conum[data-value] { position: relative; top: -0.125em; }
+
+b.conum * { color: inherit !important; }
+
+.conum:not([data-value]):empty { display: none; }
+
+h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { border-bottom: 1px solid #dddddd; }
+
+.sect1 { padding-bottom: 0; }
+
+#toctitle { color: #00406F; font-weight: normal; margin-top: 1.5em; }
+
+.sidebarblock { border-color: #aaa; }
+
+code { -webkit-border-radius: 4px; border-radius: 4px; }
+
+p.tableblock.header { color: #6d6e71; }
+
+.literalblock pre, .listingblock pre { background: #eeeeee; }
+
+</style>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css">
+<style>
+/* Stylesheet for CodeRay to match GitHub theme | MIT License | http://foundation.zurb.com */
+/*pre.CodeRay {background-color:#f7f7f8;}*/
+.CodeRay .line-numbers{border-right:1px solid #d8d8d8;padding:0 0.5em 0 .25em}
+.CodeRay span.line-numbers{display:inline-block;margin-right:.5em;color:rgba(0,0,0,.3)}
+.CodeRay .line-numbers strong{color:rgba(0,0,0,.4)}
+table.CodeRay{border-collapse:separate;border-spacing:0;margin-bottom:0;border:0;background:none}
+table.CodeRay td{vertical-align: top;line-height:1.45}
+table.CodeRay td.line-numbers{text-align:right}
+table.CodeRay td.line-numbers>pre{padding:0;color:rgba(0,0,0,.3)}
+table.CodeRay td.code{padding:0 0 0 .5em}
+table.CodeRay td.code>pre{padding:0}
+.CodeRay .debug{color:#fff !important;background:#000080 !important}
+.CodeRay .annotation{color:#007}
+.CodeRay .attribute-name{color:#000080}
+.CodeRay .attribute-value{color:#700}
+.CodeRay .binary{color:#509}
+.CodeRay .comment{color:#998;font-style:italic}
+.CodeRay .char{color:#04d}
+.CodeRay .char .content{color:#04d}
+.CodeRay .char .delimiter{color:#039}
+.CodeRay .class{color:#458;font-weight:bold}
+.CodeRay .complex{color:#a08}
+.CodeRay .constant,.CodeRay .predefined-constant{color:#008080}
+.CodeRay .color{color:#099}
+.CodeRay .class-variable{color:#369}
+.CodeRay .decorator{color:#b0b}
+.CodeRay .definition{color:#099}
+.CodeRay .delimiter{color:#000}
+.CodeRay .doc{color:#970}
+.CodeRay .doctype{color:#34b}
+.CodeRay .doc-string{color:#d42}
+.CodeRay .escape{color:#666}
+.CodeRay .entity{color:#800}
+.CodeRay .error{color:#808}
+.CodeRay .exception{color:inherit}
+.CodeRay .filename{color:#099}
+.CodeRay .function{color:#900;font-weight:bold}
+.CodeRay .global-variable{color:#008080}
+.CodeRay .hex{color:#058}
+.CodeRay .integer,.CodeRay .float{color:#099}
+.CodeRay .include{color:#555}
+.CodeRay .inline{color:#000}
+.CodeRay .inline .inline{background:#ccc}
+.CodeRay .inline .inline .inline{background:#bbb}
+.CodeRay .inline .inline-delimiter{color:#d14}
+.CodeRay .inline-delimiter{color:#d14}
+.CodeRay .important{color:#555;font-weight:bold}
+.CodeRay .interpreted{color:#b2b}
+.CodeRay .instance-variable{color:#008080}
+.CodeRay .label{color:#970}
+.CodeRay .local-variable{color:#963}
+.CodeRay .octal{color:#40e}
+.CodeRay .predefined{color:#369}
+.CodeRay .preprocessor{color:#579}
+.CodeRay .pseudo-class{color:#555}
+.CodeRay .directive{font-weight:bold}
+.CodeRay .type{font-weight:bold}
+.CodeRay .predefined-type{color:inherit}
+.CodeRay .reserved,.CodeRay .keyword {color:#000;font-weight:bold}
+.CodeRay .key{color:#808}
+.CodeRay .key .delimiter{color:#606}
+.CodeRay .key .char{color:#80f}
+.CodeRay .value{color:#088}
+.CodeRay .regexp .delimiter{color:#808}
+.CodeRay .regexp .content{color:#808}
+.CodeRay .regexp .modifier{color:#808}
+.CodeRay .regexp .char{color:#d14}
+.CodeRay .regexp .function{color:#404;font-weight:bold}
+.CodeRay .string{color:#d20}
+.CodeRay .string .string .string{background:#ffd0d0}
+.CodeRay .string .content{color:#d14}
+.CodeRay .string .char{color:#d14}
+.CodeRay .string .delimiter{color:#d14}
+.CodeRay .shell{color:#d14}
+.CodeRay .shell .delimiter{color:#d14}
+.CodeRay .symbol{color:#990073}
+.CodeRay .symbol .content{color:#a60}
+.CodeRay .symbol .delimiter{color:#630}
+.CodeRay .tag{color:#008080}
+.CodeRay .tag-special{color:#d70}
+.CodeRay .variable{color:#036}
+.CodeRay .insert{background:#afa}
+.CodeRay .delete{background:#faa}
+.CodeRay .change{color:#aaf;background:#007}
+.CodeRay .head{color:#f8f;background:#505}
+.CodeRay .insert .insert{color:#080}
+.CodeRay .delete .delete{color:#800}
+.CodeRay .change .change{color:#66f}
+.CodeRay .head .head{color:#f4f}
+</style>
+<link rel="stylesheet" href="../katex/katex.min.css">
+<script src="../katex/katex.min.js"></script>
+<script src="../katex/contrib/auto-render.min.js"></script>
+    <!-- Use KaTeX to render math once document is loaded, see
+         https://github.com/Khan/KaTeX/tree/master/contrib/auto-render -->
+<script>
+    document.addEventListener("DOMContentLoaded", function () {
+        renderMathInElement(
+            document.body,
+            {
+                delimiters: [
+                    { left: "$$", right: "$$", display: true},
+                    { left: "\\[", right: "\\]", display: true},
+                    { left: "$", right: "$", display: false},
+                    { left: "\\(", right: "\\)", display: false}
+                ]
+            }
+        );
+    });
+</script></head>
+<body class="book toc2 toc-left" style="max-width: 100;">
+<div id="header">
+<h1>The OpenCL<sup>&#8482;</sup> C++ 1.0 Specification</h1>
+<div class="details">
+<span id="author" class="author">Khronos OpenCL Working Group</span><br>
+<span id="revnumber">version 2.2-7,</span>
+<span id="revdate">Sat, 12 May 2018 13:21:28 +0000</span>
+<br><span id="revremark">from git branch: master commit: ab6da3001e9eeafaa36c18888ca7eb4ebb9768af</span>
+</div>
+<div id="toc" class="toc2">
+<div id="toctitle">Table of Contents</div>
+<ul class="sectlevel1">
+<li><a href="#generic-type-name-notation">1. Generic Type Name Notation</a></li>
+<li><a href="#openclcpp-programming-language">2. OpenCL C++ Programming Language</a>
+<ul class="sectlevel2">
+<li><a href="#supported-builtin-data-types">2.1. Supported Built-in Data Types</a></li>
+<li><a href="#keywords">2.2. Keywords</a></li>
+<li><a href="#implicit-type-conversions">2.3. Implicit Type Conversions</a></li>
+<li><a href="#expressions">2.4. Expressions</a></li>
+<li><a href="#address-spaces">2.5. Address Spaces</a></li>
+<li><a href="#kernel-functions">2.6. Kernel Functions</a></li>
+<li><a href="#preprocessor-directives-and-macros">2.7. Preprocessor Directives and Macros</a></li>
+<li><a href="#attribute-qualifiers">2.8. Attribute Qualifiers</a></li>
+<li><a href="#opencl_cxx_restrictions">2.9. Restrictions</a></li>
+</ul>
+</li>
+<li><a href="#opencl-c-standard-library">3. OpenCL C++ Standard Library</a>
+<ul class="sectlevel2">
+<li><a href="#opencl-definitions">3.1. OpenCL Definitions</a></li>
+<li><a href="#conversions-library">3.2. Conversions Library</a></li>
+<li><a href="#reinterpreting-data-library">3.3. Reinterpreting Data Library</a></li>
+<li><a href="#address-spaces-library">3.4. Address Spaces Library</a></li>
+<li><a href="#specialization-constants-library">3.5. Specialization Constants Library</a></li>
+<li><a href="#half-wrapper-library">3.6. Half Wrapper Library</a></li>
+<li><a href="#vector-wrapper-library">3.7. Vector Wrapper Library</a></li>
+<li><a href="#range-library">3.8. Range Library</a></li>
+<li><a href="#vector-utilities-library">3.9. Vector Utilities Library</a></li>
+<li><a href="#marker-types">3.10. Marker Types</a></li>
+<li><a href="#images-and-samplers-library">3.11. Images and Samplers Library</a></li>
+<li><a href="#pipes-library">3.12. Pipes Library</a></li>
+<li><a href="#device-enqueue-library">3.13. Device Enqueue Library</a></li>
+<li><a href="#work-item-functions">3.14. Work-Item Functions</a></li>
+<li><a href="#work-group-functions">3.15. Work-group Functions</a></li>
+<li><a href="#synchronization-functions">3.16. Synchronization Functions</a></li>
+<li><a href="#common-functions">3.17. Common Functions</a></li>
+<li><a href="#geometric-functions">3.18. Geometric Functions</a></li>
+<li><a href="#math-functions">3.19. Math Functions</a></li>
+<li><a href="#integer-functions">3.20. Integer Functions</a></li>
+<li><a href="#relational-functions">3.21. Relational Functions</a></li>
+<li><a href="#vector-data-load-and-store-functions">3.22. Vector Data Load and Store Functions</a></li>
+<li><a href="#printf">3.23. printf</a></li>
+<li><a href="#atomic-operations-library">3.24. Atomic Operations Library</a></li>
+<li><a href="#array-library">3.25. Array Library</a></li>
+<li><a href="#limits-library">3.26. Limits Library</a></li>
+<li><a href="#math-constants-library">3.27. Math Constants Library</a></li>
+<li><a href="#tuple-library">3.28. Tuple Library</a></li>
+<li><a href="#type-traits-library">3.29. Type Traits Library</a></li>
+<li><a href="#iterator-library">3.30. Iterator Library</a></li>
+<li><a href="#general-utilities-library">3.31. General Utilities Library</a></li>
+</ul>
+</li>
+<li><a href="#opencl-numerical-compliance">4. OpenCL Numerical Compliance</a>
+<ul class="sectlevel2">
+<li><a href="#rounding-modes-1">4.1. Rounding Modes</a></li>
+<li><a href="#inf-nan-and-denormalized-numbers">4.2. INF, NaN and Denormalized Numbers</a></li>
+<li><a href="#floating-point-exceptions">4.3. Floating-Point Exceptions</a></li>
+<li><a href="#relative-error-as-ulps">4.4. Relative Error as ULPs</a></li>
+<li><a href="#edge-case-behavior">4.5. Edge Case Behavior</a></li>
+</ul>
+</li>
+<li><a href="#image-addressing-and-filtering">5. Image Addressing and Filtering</a>
+<ul class="sectlevel2">
+<li><a href="#image-coordinates">5.1. Image Coordinates</a></li>
+<li><a href="#addressing-and-filter-modes">5.2. Addressing and Filter Modes</a></li>
+<li><a href="#conversion-rules">5.3. Conversion Rules</a></li>
+<li><a href="#selecting-an-image-from-an-image-array">5.4. Selecting an Image from an Image Array</a></li>
+</ul>
+</li>
+<li><a href="#compiler_options">6. Compiler options</a>
+<ul class="sectlevel2">
+<li><a href="#preprocessor_options">6.1. Preprocessor options</a></li>
+<li><a href="#options-controlling_the-opencl_c_version">6.2. Options Controlling the OpenCL C++ version</a></li>
+<li><a href="#fp16_and_fp64_options">6.3. Double and half-precision floating-point options</a></li>
+<li><a href="#other_options">6.4. Other options</a></li>
+</ul>
+</li>
+</ul>
+</div>
+</div>
+<div id="content">
+<div id="preamble">
+<div class="sectionbody">
+<div class="paragraph">
+<p>Copyright 2008-2018 The Khronos Group.</p>
+</div>
+<div class="paragraph">
+<p>This specification is protected by copyright laws and contains material proprietary
+to the Khronos Group, Inc. Except as described by these terms, it or any components
+may not be reproduced, republished, distributed, transmitted, displayed, broadcast
+or otherwise exploited in any manner without the express prior written permission
+of Khronos Group.</p>
+</div>
+<div class="paragraph">
+<p>Khronos Group grants a conditional copyright license to use and reproduce the
+unmodified specification for any purpose, without fee or royalty, EXCEPT no licenses
+to any patent, trademark or other intellectual property rights are granted under
+these terms. Parties desiring to implement the specification and make use of
+Khronos trademarks in relation to that implementation, and receive reciprocal patent
+license protection under the Khronos IP Policy must become Adopters and confirm the
+implementation as conformant under the process defined by Khronos for this
+specification; see <a href="https://www.khronos.org/adopters" class="bare">https://www.khronos.org/adopters</a>.</p>
+</div>
+<div class="paragraph">
+<p>Khronos Group makes no, and expressly disclaims any, representations or warranties,
+express or implied, regarding this specification, including, without limitation:
+merchantability, fitness for a particular purpose, non-infringement of any
+intellectual property, correctness, accuracy, completeness, timeliness, and
+reliability. Under no circumstances will the Khronos Group, or any of its Promoters,
+Contributors or Members, or their respective partners, officers, directors,
+employees, agents or representatives be liable for any damages, whether direct,
+indirect, special or consequential damages for lost revenues, lost profits, or
+otherwise, arising from or in connection with these materials.</p>
+</div>
+<div class="paragraph">
+<p>Vulkan is a registered trademark and Khronos, OpenXR, SPIR, SPIR-V, SYCL, WebGL,
+WebCL, OpenVX, OpenVG, EGL, COLLADA, glTF, NNEF, OpenKODE, OpenKCAM, StreamInput,
+OpenWF, OpenSL ES, OpenMAX, OpenMAX AL, OpenMAX IL, OpenMAX DL, OpenML and DevU are
+trademarks of the Khronos Group Inc. ASTC is a trademark of ARM Holdings PLC,
+OpenCL is a trademark of Apple Inc. and OpenGL and OpenML are registered trademarks
+and the OpenGL ES and OpenGL SC logos are trademarks of Silicon Graphics
+International used under license by Khronos. All other product names, trademarks,
+and/or company names are used solely for identification and belong to their
+respective owners.</p>
+</div>
+<div style="page-break-after: always;"></div>
+<h2 id="acknowledgements" class="float">Acknowledgements</h2>
+<div class="paragraph">
+<p>The OpenCL C++ specification is the result of the contributions of many people, representing a cross section of the desktop, hand-held, and embedded computer industry.
+Following is a partial list of the contributors, including the company that they represented at the time of their contribution:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Eric Berdahl, Adobe</p>
+</li>
+<li>
+<p>Aaftab Munshi, Apple</p>
+</li>
+<li>
+<p>Brian Sumner, AMD</p>
+</li>
+<li>
+<p>Andrew Richards, Codeplay</p>
+</li>
+<li>
+<p>Maria Rovatsou, Codeplay</p>
+</li>
+<li>
+<p>Adam Stański, Intel</p>
+</li>
+<li>
+<p>Alexey Bader, Intel</p>
+</li>
+<li>
+<p>Allen Hux, Intel</p>
+</li>
+<li>
+<p>Bartosz Sochacki, Intel</p>
+</li>
+<li>
+<p>Ben Ashbaugh, Intel</p>
+</li>
+<li>
+<p>Kevin Stevens, Intel</p>
+</li>
+<li>
+<p>Łukasz Dudziak, Intel</p>
+</li>
+<li>
+<p>Łukasz Towarek, Intel</p>
+</li>
+<li>
+<p>Marcin Walkowiak, Intel</p>
+</li>
+<li>
+<p>Michael Kinsner, Intel</p>
+</li>
+<li>
+<p>Raun Krisch, Intel</p>
+</li>
+<li>
+<p>Tomasz Fiechowski, Intel</p>
+</li>
+<li>
+<p>Kedar Patil, NVIDIA</p>
+</li>
+<li>
+<p>Yuan Lin, NVIDIA</p>
+</li>
+<li>
+<p>Alex Bourd, Qualcomm</p>
+</li>
+<li>
+<p>Lee Howes, Qualcomm</p>
+</li>
+<li>
+<p>Anton Gorenko, StreamComputing</p>
+</li>
+<li>
+<p>Jakub Szuppe, StreamComputing</p>
+</li>
+<li>
+<p>James Price, University of Bristol</p>
+</li>
+<li>
+<p>Paul Preney, University of Windsor</p>
+</li>
+<li>
+<p>Ronan Keryell, Xilinx</p>
+</li>
+<li>
+<p>AJ Guillon, YetiWare Inc.</p>
+</li>
+</ul>
+</div>
+<div style="page-break-after: always;"></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="generic-type-name-notation">1. Generic Type Name Notation</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>The generic type names are used when some entity has multiple overloads which differ only by argument(s).
+They can map to one or more built-in data types.
+The tables below describe these mappings in details.</p>
+</div>
+<div class="paragraph">
+<p>Assuming that <code>gentype</code> maps to built-in types: <code>float</code>, <code>int</code> and <code>uint</code>, when coming across definition:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype function(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>reader should understand that such function has in fact three overloads:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>float function(float x);
+int function(int x);
+uint function(uint x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Note that if a function signature has multiple usages of <code>gentype</code> they all should map to the same type.
+Following this rule such overloads are then invalid:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>float function(int x);
+uint function(float x);
+// etc.</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>If a function is meant to have such overloads, respective gentypes in its signature should be postfixed with numbers to indicate they represent different types.
+Declaration like this:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl::common_type_t&lt;gentype1, gentype2&gt; greater(gentype1 x, gentype2 y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>would match following overloads:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl::common_type_t&lt;float, float&gt; greater(float x, float y);
+cl::common_type_t&lt;float, int&gt; greater(float x, int y);
+cl::common_type_t&lt;float, uint&gt; greater(float x, uint y);
+cl::common_type_t&lt;int, float&gt; greater(int x, float y);
+
+// etc.</code></pre>
+</div>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 1. generic types</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>generic type</strong></th>
+<th class="tableblock halign-left valign-top"><strong>corresponding built-in types</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>typen</code></p></td>
+<td class="tableblock halign-left valign-top"><div><div class="paragraph">
+<p>scalar and all vector types of type</p>
+</div>
+<div class="paragraph">
+<p>Example:</p>
+</div>
+<div class="exampleblock">
+<div class="content">
+<div class="paragraph">
+<p><code>floatn</code> matches: <code>float</code>, <code>float2</code>, <code>float3</code>, <code>float4</code>, <code>float8</code> and <code>float16</code><br>
+<code>floatn</code> doesn&#8217;t match: <code>half</code>, <code>int2</code></p>
+</div>
+</div>
+</div></div></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>gentype</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">unspecified in global context, should be defined whenever used</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>sgentype</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">subset of scalar types from types matched by <code>gentype</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>ugentype</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">subset of unsigned integer types from types matched by <code>gentype</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>gentypeh</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>half</code>, <code>half2</code>, <code>half3</code>, <code>half4</code>, <code>half8</code> or <code>half16</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>gentypef</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>float</code>, <code>float2</code>, <code>float3</code>, <code>float4</code>, <code>float8</code> or <code>float16</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>gentyped</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>double</code>, <code>double2</code>, <code>double3</code>, <code>double4</code>, <code>double8</code> or <code>double16</code></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+<div class="sect1">
+<h2 id="openclcpp-programming-language">2. OpenCL C++ Programming Language</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>This section describes the OpenCL C++ programming language used to create kernels that are executed on OpenCL device(s).
+The OpenCL C++ programming language is based on the ISO/IEC JTC1 SC22 WG21 N 3690 language specification (a.k.a. C++14 specification) with specific restrictions (see the <a href="#opencl_cxx_restrictions"><em>OpenCL C++ restrictions</em></a> section).
+Please refer to this specification for a detailed description of the language grammar.
+This section describes restrictions to the C++14 specification supported in OpenCL C++.</p>
+</div>
+<div class="sect2">
+<h3 id="supported-builtin-data-types">2.1. Supported Built-in Data Types</h3>
+<div class="paragraph">
+<p>The following data types are supported.</p>
+</div>
+<div class="sect3">
+<h4 id="builtin-scalar-data-types">2.1.1. Built-in Scalar Data Types</h4>
+<table id="device_builtin_scalar_data_types" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 2. Device Built-in scalar data types</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Type</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>bool</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A data type which is either <code>true</code> or <code>false</code>. (<em>See section 2.14.6 lex.bool and section 3.9.1 basic.fundamental of the C++14 Specification.</em>)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>char</code>, <code>signed char</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A signed two&#8217;s complement 8-bit integer.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>unsigned char</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">An unsigned 8-bit integer.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>short</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A signed two&#8217;s complement 16-bit integer.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>unsigned short</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">An unsigned 16-bit integer.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>int</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A signed two&#8217;s complement 32-bit integer.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>unsigned int</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">An unsigned 32-bit integer.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>long</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A signed two&#8217;s complement 64-bit integer.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>unsigned long</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">An unsigned 64-bit integer.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>float</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 32-bit floating-point.
+  The float data type must conform to the IEEE 754 single precision storage format.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>double</code> <a id="ftnref2"></a> <a href="#ftn2">[2]</a></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 64-bit floating-point.
+  The double data type must conform to the IEEE 754 double precision storage format.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>half</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 16-bit floating-point.
+  The half data type must conform to the IEEE 754-2008 half precision storage format.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>void</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The <code>void</code> type comprises an empty set of values; it is an incomplete type that cannot be completed.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>Most built-in scalar data types are also declared as appropriate types in the OpenCL API (and header files) that can be used by an application.
+The following table describes the built-in scalar data type in the OpenCL C++ programming language and the corresponding data type available to the application:</p>
+</div>
+<table id="host_scalar_builtin_data_types" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 3. Host Scalar Built-in Data Types</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Type in OpenCL Language</strong></th>
+<th class="tableblock halign-left valign-top"><strong>API type for application</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>bool</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">n/a, i.e., there is no corresponding <code>cl_bool</code> type.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>char</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_char</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>unsigned char</code>, <code>uchar</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_uchar</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>short</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_short</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>unsigned short</code>, <code>ushort</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_ushort</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>int</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_int</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>unsigned int</code>, <code>uint</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_uint</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>long</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_long</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>unsigned long</code>, <code>ulong</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_ulong</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>float</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_float</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>double</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_double</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>half</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_half</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>void</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>void</code></p></td>
+</tr>
+</tbody>
+</table>
+<div class="sect4">
+<h5 id="builtin-half-data-type">Built-in Half Data Type</h5>
+<div class="paragraph">
+<p>The <code>half</code> data type must be IEEE 754-2008 compliant.
+<code>half</code> numbers have 1 sign bit, 5 exponent bits, and 10 mantissa bits.
+The interpretation of the sign, exponent and mantissa is analogous to IEEE 754 floating-point numbers.</p>
+</div>
+<div class="paragraph">
+<p>The exponent bias is 15.
+The <code>half</code> data type must represent finite and normal numbers, denormalized numbers, infinities and NaN.
+Denormalized numbers for the <code>half</code> data type which may be generated when converting a <code>float</code> to a <code>half</code> using <code>vstore_half</code> and converting a <code>half</code> to a <code>float</code> using <code>vload_half</code> cannot be flushed to zero.</p>
+</div>
+<div class="paragraph">
+<p>Conversions from <code>float</code> to <code>half</code> correctly round the mantissa to 11 bits of precision.</p>
+</div>
+<div class="paragraph">
+<p>Conversions from <code>half</code> to <code>float</code> are lossless; all <code>half</code> numbers are exactly representable as <code>float</code> values.</p>
+</div>
+<div class="paragraph">
+<p>The <code>half</code> data type can only be used to declare a pointer to a buffer that contains <code>half</code> values.
+All other operations are not allowed if the <strong>cl_khr_fp16</strong> extension is not supported.</p>
+</div>
+<div class="paragraph">
+<p>A few valid examples are given below:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_def&gt;
+#include &lt;opencl_memory&gt;
+#include &lt;opencl_vector_load_store&gt;
+
+float bar(half *a) {
+  return cl::vload_half&lt; 1 &gt;(0, a);
+}
+
+kernel void foo(cl::global_ptr&lt;half&gt; pg) { //ok: a global pointer
+                                           // passed from the host
+    int offset = 1;
+
+    half *ptr = pg.get() + offset; //ok: half pointer arithmetic
+    float b = bar(ptr);
+
+    if(b &lt; *ptr) { //not allowed: it is only supported if cl_khr_fp16
+                   // extension is enabled
+      //...
+    }
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The <code>half</code> scalar data type is required to be supported as a data storage format.
+Vector data load and store functions (described in the <a href="#vector-data-load-and-store-functions"><em>Vector Data Load and Store Functions</em></a> section) must be supported.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="cl_khr_fp16-extension"><strong>cl_khr_fp16</strong> extension</h5>
+<div class="paragraph">
+<p>This extension adds support for <code>half</code> scalar and vector types as built-in types that can be used for arithmetic operations, conversions etc.
+An application that wants to use <code>half</code> and <code>halfn</code> types will need to specify the <code>-cl-fp16-enable</code> compiler option (see the <a href="#fp16_and_fp64_options"><em>Double and half-precision floating-point options</em></a> section).</p>
+</div>
+<div class="paragraph">
+<p>The OpenCL compiler accepts an h and H suffix on floating point literals, indicating the literal is typed as a <code>half</code></p>
+</div>
+<div class="paragraph">
+<p>A few valid examples:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_def&gt;
+#include &lt;opencl_memory&gt;
+
+half bar(half a) {
+    half b = a;
+    b += 10.0h; //ok: cl_khr_fp16 extension is enabled. All arithmetic
+                // operations on half built-in type are available
+
+    return b;
+}
+
+kernel void foo(cl::global_ptr&lt;half&gt; pg) {
+    int offset = 1;
+
+    half *ptr = pg.get() + offset;
+    half b = bar(*ptr);
+
+    if(b &lt; *ptr) { //ok: cl_khr_fp16 extension is enabled.
+                   // All comparison operations are available
+      //...
+    }
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="hexadecimal-floating-point-literals">Hexadecimal floating point literals</h5>
+<div class="paragraph">
+<p>Hexadecimal floating point literals are supported in OpenCL C++.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>float f = 0x1.fffffep127f
+double d = 0x1.fffffffffffffp1023;
+half h = 0x1.ffcp15h;</code></pre>
+</div>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="builtin-vector-data-types">2.1.2. Built-in Vector Data Types</h4>
+<div class="sect4">
+<h5 id="supported-vector-data-types">Supported Vector Data Types</h5>
+<div class="paragraph">
+<p>The <code>bool</code>, <code>char</code>, <code>unsigned char</code>, <code>short</code>, <code>unsigned short</code>, <code>int</code>, <code>unsigned int</code>, <code>long</code>, <code>unsigned long</code>, <code>half</code>, <code>float</code> and <code>double</code> vector data types are supported.
+The vector data type is defined with the type name i.e. <code>bool</code>, <code>char</code>, <code>uchar</code>, <code>short</code>, <code>ushort</code>, <code>int</code>, <code>uint</code>, <code>long</code>, <code>ulong</code>, <code>half</code>, <code>float</code> or <code>double</code> followed by a literal value <em>n</em> that defines the number of elements in the vector.
+Supported values of <em>n</em> are 2, 3, 4, 8, and 16 for all vector data types.</p>
+</div>
+<table id="device_builtin_vector_data_types" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 4. Device Built-in Vector Data Types</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Type</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>bool<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A vector of <em>n</em> boolean values.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>char<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A vector of <em>n</em> 8-bit signed two&#8217;s complement integer values.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>uchar<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A vector of <em>n</em> 8-bit unsigned integer values.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>short<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">vector of <em>n</em> 16-bit signed two&#8217;s complement integer values.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>ushort<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A vector of <em>n</em> 16-bit unsigned integer values.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>int<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A vector of <em>n</em> 32-bit signed two&#8217;s complement integer values.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>uint<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A vector of <em>n</em> 32-bit unsigned integer values.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>long<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A vector of <em>n</em> 64-bit signed two&#8217;s complement integer values.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>ulong<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A vector of <em>n</em> 64-bit unsigned integer values.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>half<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A vector of <em>n</em> 16-bit floating-point values.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>float<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A vector of <em>n</em> 32-bit floating-point values.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>double<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A vector of <em>n</em> 64-bit floating-point values.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>The built-in vector data types are also declared as appropriate types in the OpenCL API (and header files) that can be used by an application.
+The following table describes the built-in vector data type in the OpenCL C++ programming language and the corresponding data type available to the application:</p>
+</div>
+<table id="host_builtin_vector_data_types" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 5. Host Built-in Vector Data Types</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Type in OpenCL Language</strong></th>
+<th class="tableblock halign-left valign-top"><strong>API type for application</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>bool<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">n/a, i.e., there is no corresponding <code>cl_bool<em>n</em></code> type.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>char<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_char<em>n</em></code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>uchar<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_uchar<em>n</em></code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>short<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_short<em>n</em></code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>ushort<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_ushort<em>n</em></code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>int<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_int<em>n</em></code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>uint<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_uint<em>n</em></code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>long<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_long<em>n</em></code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>ulong<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_ulong<em>n</em></code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>half<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_half<em>n</em></code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>float<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_float<em>n</em></code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>double<em>n</em></code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_double<em>n</em></code></p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>The <code>half<em>n</em></code> vector data type is required to be supported as a data storage format.
+Vector data load and store functions (described in the <a href="#vector-data-load-and-store-functions"><em>Vector Data Load and Store Functions</em></a> section) must be supported.</p>
+</div>
+<div class="paragraph">
+<p>Support for the <code>double<em>n</em></code> vector data type is optional.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="vector-changes-to-cpp14-standard">Vector Changes to C++14 standard</h5>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>Vector types are classified as fundamental (<em>[ISO/IEC 14882:2014: basic.fundamental, ch. 3.9.1]</em>) and literal types</p>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+A vector type behave similarly to a trivially destructible class with all data members of literal type and all of its constructors defined as constexpr constructors
+</td>
+</tr>
+</table>
+</div>
+</li>
+<li>
+<p>Abbreviating vector type as Tn, T is called the component type of a vector.
+The numerical value n specifies number of components in a vector.
+<a href="#device_builtin_vector_data_types">Device built-in vector data types</a> table specifies supported vector types.</p>
+<div class="paragraph">
+<p>A vector type which component type is <em>integral type</em> is called <em>integral vector type</em>.
+A vector type which component is <em>floating-point type</em> is called <em>floating-point vector type</em>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>float8 a; // component type: float, number of components: 8
+uint16 b; // component type: uint, number of components: 16</code></pre>
+</div>
+</div>
+</li>
+<li>
+<p>An <em>integral vector type</em> can be used as type of value of non-type template-parameter.
+The change is introduced by following changes in C++ specification:</p>
+<div class="openblock">
+<div class="content">
+<div class="ulist">
+<ul>
+<li>
+<p><em>[ISO/IEC 14882:2014: temp.param, ch. 14.1 (4, 4.1)]</em> Template parameters: A non-type template-parameter shall have one of the following (optionally cv-qualified) types:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>integral, integral vector or enumeration type,</p>
+</li>
+<li>
+<p>integral, integral vector or enumeration type,</p>
+</li>
+<li>
+<p>[ &#8230;&#8203; ]</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><em>[ISO/IEC 14882:2014: temp.param, ch. 14.1 (7)]</em> Template parameters: A non-type <em>template-parameter</em> shall not be declared to have floating point, floating-point vector, class, or void type.</p>
+</li>
+<li>
+<p><em>[ISO/IEC 14882:2014: temp.type, ch. 14.4 (1, 1.3)]</em> Type equivalence: Two <em>template-ids</em> refer to the same class, function, or variable if</p>
+<div class="ulist">
+<ul>
+<li>
+<p>[ &#8230;&#8203; ]</p>
+</li>
+<li>
+<p>their corresponding non-type template arguments of integral, integral vector or enumeration type have identical values and</p>
+</li>
+<li>
+<p>[ &#8230;&#8203; ]</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><em>[ISO/IEC 14882:2014: temp.res, ch. 14.6 (8, 8.3, 8.3.1)]</em> Name resolution: [&#8230;&#8203;] If the interpretation of such a construct in the hypothetical instantiation is different from the interpretation of the corresponding construct</p>
+<div class="ulist">
+<ul>
+<li>
+<p>integral, integral vector or enumeration type, in any actual instantiation of the template, the program is ill-formed; no diagnostic is required.
+This can happen in situations including the following:</p>
+</li>
+<li>
+<p>[ &#8230;&#8203; ]</p>
+</li>
+<li>
+<p>constant expression evaluation (5.20) within the template instantiation uses</p>
+<div class="ulist">
+<ul>
+<li>
+<p>the value of a const object of integral, integral vector or unscoped enumeration type or</p>
+</li>
+<li>
+<p>[ &#8230;&#8203; ]</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p>[ &#8230;&#8203; ]</p>
+</li>
+</ul>
+</div>
+</li>
+</ul>
+</div>
+</div>
+</div>
+</li>
+</ol>
+</div>
+</div>
+<div class="sect4">
+<h5 id="vector-component-access">Vector Component Access</h5>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>The components of vector type can be accessed using swizzle expression.
+The syntax of a swizzle expression is similar to syntax used in class member access expression <em>[ISO/IEC 14882:2014: expr.ref, ch. 5.2.5]</em>:
+The swizzle expression is a postfix expression formed with a postfix expression followed by a dot <code>.</code> or an arrow <code>-&gt;</code> and then followed by an <em>vector-swizzle-selector</em>. The postfix expression before the dot or arrow is evaluated. The result of that evaluation, together with the <em>vector-swizzle-selector</em>, determines the result of the entire postfix expression.</p>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>float4 v1 = float4(1.0f, 2.0f, 3.0f, 4.0f);
+float4 *pv1 = &amp;v1;
+
+float2 v2 = v1.xz; // v1.xz is a swizzle expression
+float3 v3 = pv1-&gt;s321; // pv1-&gt;s321 is a swizzle expression
+                       // equivalent to (*pv1).s321
+(*pv1).rgb = float3(0.0f, 0.5f, 1.0f); // (*pv1).rgb is a swizzle expression
+pv1-&gt;lo.hi = 0.0f; // pv1-&gt;lo and pv1-&gt;lo.hi are swizzle
+                   // expressions</code></pre>
+</div>
+</div>
+</li>
+<li>
+<p>For the first option (dot) the first expression shall have vector type or be a swizzle expression which results in vector-swizzle of vector type.
+For the second option (arrow) the first expression shall have pointer to vector type.
+The expression <code>E1-&gt;E2</code> is converted to the equivalent form <code>(*(E1)).E2</code>; the remainder of <a href="#vector-component-access">Vector Component Access</a> will address only the first option (dot).</p>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<code>(*(E1))</code> is lvalue. In either case, the <em>vector-swizzle-selector</em> shall name a vector component selection of a swizzle.
+</td>
+</tr>
+</table>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>uint8 v1 = uint8(10, 11, 12, 13, 14, 15, 16, 17);
+
+uint4 v2 = v1.s7301; // correct
+uint3 v3 = (&amp;v1)-&gt;s246; // correct
+uint4 v4 = v1-&gt;s0123; // ill-formed: v1 is not a pointer to
+                      //             vector type
+
+uint8 *pv1 = &amp;v1;
+
+uint2 v5 = pv1-&gt;S13; // correct
+uint2 v6 = (*pv1).s0745.even; // correct
+uint4 v7 = pv1.odd; // ill-formed: pv1 is not vector or
+                    // vector-swizzle</code></pre>
+</div>
+</div>
+</li>
+<li>
+<p>Abbreviating <em>postfix-expression.vector-swizzle-selector</em> as <code>E1.E2</code>, <code>E1</code> is called the vector expression.
+The type and value category of <code>E1.E2</code> are determined as follows.
+In the remainder of <a href="#vector-component-access">Vector Component Access</a>, <em>cq</em> represents either <code>const</code> or the absence of <code>const</code> and <em>vq</em> represents either <code>volatile</code> or the absence of <code>volatile</code>.
+cv represents an arbitrary set of cv-qualifiers, as defined in <em>[ISO/IEC 14882:2014: basic.type.qualifier, ch. 3.9.3]</em> .</p>
+</li>
+<li>
+<p><em>vector-swizzle-selector</em> is subset of <em>identifier</em> with following syntax:</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>
+<em>vector-swizzle-selector</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><em>vector-swizzle-xyzw-selector</em>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p><em>vector-swizzle-xyzw-selector-value</em></p>
+</li>
+<li>
+<p><em>vector-swizzle-xyzw-selector vector-swizzle-xyzw-selector-value</em></p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><em>vector-swizzle-rgba-selector</em>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p><em>vector-swizzle-rgba-selector-value</em></p>
+</li>
+<li>
+<p><em>vector-swizzle-rgba-selector vector-swizzle-rgba-selector-value</em></p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><em>vector-swizzle-special-selector</em>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p><code>hi</code></p>
+</li>
+<li>
+<p><code>lo</code></p>
+</li>
+<li>
+<p><code>even</code></p>
+</li>
+<li>
+<p><code>odd</code></p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><em>vector-swizzle-num-selector</em>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p><code>s</code> <em>vector-swizzle-num-selector-values</em></p>
+</li>
+<li>
+<p><code>S</code> <em>vector-swizzle-num-selector-values</em></p>
+</li>
+</ul>
+</div>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>
+<em>vector-swizzle-num-selector-values</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><em>vector-swizzle-num-selector-value</em></p>
+</li>
+<li>
+<p><em>vector-swizzle-num-selector-values vector-swizzle-num-selector-value</em></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="paragraph">
+<p>
+<em>vector-swizzle-xyzw-selector-value</em>: one of <code>x y z w</code></p>
+</div>
+<div class="paragraph">
+<p>
+<em>vector-swizzle-rgba-selector-value</em>: one of <code>r g b a</code></p>
+</div>
+<div class="paragraph">
+<p>
+<em>vector-swizzle-num-selector-value</em>: one of <code>0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F</code></p>
+</div>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>
+with following restrictions:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><em>vector-swizzle-selector</em> in a form of <em>vector-swizzle-special-selector</em> shall only be used with vector expression with at least 2 components.</p>
+</li>
+<li>
+<p><em>vector-swizzle-selector</em> shall not select components beyond those available in vector expression.</p>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<a href="#selector_values_and_their_corresponding_components_in_swizzle">Selector values and their corresponding components in swizzle</a> table describes relation between selector value and components.
+</td>
+</tr>
+</table>
+</div>
+</li>
+<li>
+<p><em>vector-swizzle-selector</em> shall have swizzle size of 1, 2, 3, 4, 8 or 16.</p>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+Result from the swizzle expression shall be either of scalar or of valid vector type.
+</td>
+</tr>
+</table>
+</div>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="paragraph">
+<p>
+If <em>vector-swizzle-selector</em> does not meet requirements, the swizzle expression is ill-formed.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int2 v2;
+int3 v3;
+int4 v4;
+int8 v8;
+int16 v16;
+
+v4.xyz = int3(1, 2, 3); // correct: xyz selector
+v4.baS01 = v8.lo; // ill-formed: baS01 is mix of rgba
+                  // and numerical selectors
+v3.rx = int2(20, 7); // ill-formed: mix of rgba and
+                     // xyzw selectors
+
+int v2c1 = v2.z; // correct: xyzw selector
+int v3c1 = v3.b; // correct: rgba selector
+int2 v4c1 = v4.ww; // correct: xyzw selector
+int3 v8c1 = v8.xyz; // ill-formed: xyzw and rgba selectors
+                    // are not allowed on vector expressions
+                    // with more than 4 components
+int2 v8c2 = v8.hi.xyz; // correct: xyzw selector on vector
+                       // expression v8.hi (vector-swizzle
+                       // of int4 type)
+
+int2 v3c2 = v3.odd; // correct: special selector
+int2 v3c2 = v3.x.even; // ill-formed: #1 vector expression
+                       // is invalid (vector swizzle of
+                       // scalar type)
+                       // #2 special selector cannot be
+                       // used with less than 2 components
+
+v3.x = 1; // correct: xyzw selector
+v3.w = 2; // ill-formed: there is no "w" component in int3
+v2.gb = v4.hi; // ill-formed: there is no "b" component in int2
+v8.S7890 = v4; // ill-formed: int8 allows numerical selector
+               // in range 0-7
+
+auto v16c1 = v16.s012; // correct: numerical selector
+auto v16c2 = v16.s467899; // ill-formed: swizzle expression
+                          // has not allowed size
+                          // (there is no int6 type)
+
+int16 vv1 = int16(v16.S98aabb01, v2, v2.gr, v3.xxxx); // correct
+int16 vv2 = int16(v16.S98aabb0123, v2.gr, v3.xxxx);
+                           // ill-formed:
+                           // although it sums up to 16
+                           // components the
+                           // S98aabb0123 selector has invalid
+                           // swizzle size (there is no int10)</code></pre>
+</div>
+</div>
+</li>
+<li>
+<p><em>vector-swizzle-selector</em>, in a form of <em>vector-swizzle-xyzw-selector</em>, <em>vector-swizzle-rgba-selector</em> or <em>vector-swizzle-num-selector</em> can specify multiple values.
+Each value selects single component.
+Values in a selector can be repeated and specified in any order.
+A number of values in a selector including repeated values is called the swizzle size.</p>
+<table id="selector_values_and_their_corresponding_components_in_swizzle" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 6. Selector values and their corresponding components in swizzle</caption>
+<colgroup>
+<col style="width: 25%;">
+<col style="width: 25%;">
+<col style="width: 25%;">
+<col style="width: 25%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Selector</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Selector value</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Selected component</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Required number of components in vector expression</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>vector-swizzle-xyzw-selector</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>x</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">1<sup>st</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">2, 3 or 4</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>vector-swizzle-xyzw-selector</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>y</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">2<sup>nd</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">2, 3 or 4</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>vector-swizzle-xyzw-selector</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>z</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">3<sup>rd</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">3 or 4</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>vector-swizzle-xyzw-selector</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>w</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">4<sup>th</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">4</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>vector-swizzle-rgba-selector</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>r</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">1<sup>st</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">2, 3 or 4</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>vector-swizzle-rgba-selector</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>g</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">2<sup>nd</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">2, 3 or 4</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>vector-swizzle-rgba-selector</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>b</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">3<sup>rd</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">3 or 4</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>vector-swizzle-rgba-selector</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>a</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">4<sup>th</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">4</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>vector-swizzle-num-selector</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>0</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">1<sup>st</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">2, 3, 4, 8 or 16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>vector-swizzle-num-selector</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>1</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">2<sup>nd</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">2, 3, 4, 8 or 16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>vector-swizzle-num-selector</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>2</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">3<sup>rd</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">3, 4, 8 or 16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>vector-swizzle-num-selector</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>3</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">4<sup>th</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">4, 8 or 16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>vector-swizzle-num-selector</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>4</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">5<sup>th</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">8 or 16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>vector-swizzle-num-selector</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>5</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">6<sup>th</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">8 or 16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>vector-swizzle-num-selector</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>6</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">7<sup>th</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">8 or 16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>vector-swizzle-num-selector</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>7</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">8<sup>th</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">8 or 16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>vector-swizzle-num-selector</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>8</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">9<sup>th</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>vector-swizzle-num-selector</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>9</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">10<sup>th</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>vector-swizzle-num-selector</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>a</code> or <code>A</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">11<sup>th</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>vector-swizzle-num-selector</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>b</code> or <code>B</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">12<sup>th</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>vector-swizzle-num-selector</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>c</code> or <code>C</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">13<sup>th</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>vector-swizzle-num-selector</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>d</code> or <code>D</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">14<sup>th</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>vector-swizzle-num-selector</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>e</code> or <code>E</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">15<sup>th</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>vector-swizzle-num-selector</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>f</code> or <code>F</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">16<sup>th</sup></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">16</p></td>
+</tr>
+</tbody>
+</table>
+</li>
+<li>
+<p><em>vector-swizzle-selector</em> in a form of <em>vector-swizzle-special-selector</em> shall select:</p>
+<div class="openblock">
+<div class="content">
+<div class="ulist">
+<ul>
+<li>
+<p>if number of components in vector expression is 3, the same components as if number of components of the vector expression was 4 and the 4-th component was undefined.</p>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+If 4-th component is read, the returned value is undefined; all writes to 4-th component shall be discarded.
+</td>
+</tr>
+</table>
+</div>
+</li>
+<li>
+<p>otherwise, half of components of <em>vector expression</em> with</p>
+<div class="ulist">
+<ul>
+<li>
+<p><code>hi</code> - highest numerical selector values in ascending order (higher half of the vector)</p>
+</li>
+<li>
+<p><code>lo</code> - lowest numerical selector values in ascending order (lower half of the vector)</p>
+</li>
+<li>
+<p><code>even</code> - even numerical selector values in ascending order</p>
+</li>
+<li>
+<p><code>odd</code> - odd numerical selector values in ascending order</p>
+</li>
+</ul>
+</div>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="paragraph">
+<p>The following <a href="#special_selector_values">Special selector values</a> table describes special selector values and their numerical equivalents.</p>
+</div>
+<table id="special_selector_values" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 7. Special selector values</caption>
+<colgroup>
+<col style="width: 25%;">
+<col style="width: 25%;">
+<col style="width: 25%;">
+<col style="width: 25%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Number of components in vector expression</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Selector value</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Equivalent numerical selector</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Number of components in result vector swizzle (swizzle size)</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">2</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>hi</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>s1</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">1</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">3</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>hi</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>s2?</code> <a href="#ftn3">[3]</a></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">2</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">4</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>hi</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>s23</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">2</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">8</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>hi</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>s4567</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">4</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">16</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>hi</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>s89abcdef</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">2</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>lo</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>s0</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">1</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">3</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>lo</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>s01</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">2</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">4</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>lo</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>s01</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">2</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">8</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>lo</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>s0123</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">4</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">16</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>lo</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>s01234567</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">2</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>even</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>s0</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">1</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">3</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>even</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>s02</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">2</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">4</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>even</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>s02</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">2</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">8</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>even</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>s0246</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">4</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">16</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>even</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>s02468ace</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">2</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>odd</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>s1</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">1</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">3</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>odd</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>s1?</code> <a href="#ftn3">[3]</a></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">2</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">4</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>odd</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>s13</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">2</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">8</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>odd</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>s1357</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">4</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">16</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>odd</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>s13579bdf</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">8</p></td>
+</tr>
+</tbody>
+</table>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>float8 v = float8(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f);
+
+auto vv1 = v.hi;   // vv1 = float4(5, 6, 7, 8)
+auto vv2 = v.lo;  // vv2 = float4(1, 2, 3, 4)
+auto vv3 = v.even; // equivalent of v.s0246; vv3 = float4(1, 3, 5, 7)
+auto vv4 = v.odd;  // equivalent of v.s1357; vv4 = float4(2, 4, 6, 8)
+
+auto vv5 = v.odd.even; // vv5 = float2(2, 6)
+
+int3 sv = int3(10, 20, 30);
+
+// ? means undefined value
+auto svv1 = sv.hi;  // svv1 = int2(30, ?)
+auto svv2 = sv.odd; // svv2 = int2(20, ?)
+
+sv.hi = int2(-123, 456); // write to 4-th channel in sv is discarded;
+                         // equivalent of sv.s2 = int2(-123, 456).s0</code></pre>
+</div>
+</div>
+</li>
+<li>
+<p>The value of a swizzle expression <code>E1.E2</code> is <em>vector-swizzle</em>.
+The expression designates group of components of the object designated by expression <code>E1</code>.
+Selector <code>E2</code> specifies which components are designated, how many times and in which order.</p>
+<div class="paragraph">
+<p>Assuming that in the type of a vector expression <code>E1</code> is <code>cv Tn</code> where <code>T</code> denotes type of components and <code>n</code> their number in vector type, the resulting <em>vector-swizzle</em> shall have:</p>
+</div>
+<div class="openblock">
+<div class="content">
+<div class="ulist">
+<ul>
+<li>
+<p>scalar type <code>cv T</code> if it is result of a swizzle expression with swizzle size of one or</p>
+</li>
+<li>
+<p>vector type <code>cv Tm</code> if it is result of a swizzle expression with swizzle size of two or more.</p>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<code>m</code> is a swizzle size.
+</td>
+</tr>
+</table>
+</div>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="paragraph">
+<p>If <code>E1</code> is an lvalue, then <code>E1.E2</code> is an lvalue; if <code>E1</code> is an xvalue, then <code>E1.E2</code> is an xvalue; otherwise, it is a prvalue.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>long2 v;
+const long2  pv = &amp;v;
+
+auto vc1 = pv-&gt;x; // pv-&gt;x is lvalue vector-swizzle of
+                  // scalar type: const long
+auto vc2 = pv-&gt;rg; // pv-&gt;rg is lvalue vector-swizzle of
+                   // vector type: const long2
+
+auto  vc3 = uchar4(1).xxy; // uchar4(1).xxy is prvalue
+                           // vector-swizzle
+                           // of vector type: uchar3
+
+v.x = long2(1, 2); // ill-formed: cannot assign prvalue of long2
+                   // to lvalue vector-swizzle of
+                   // scalar type: long - types do not
+                   // match</code></pre>
+</div>
+</div>
+</li>
+<li>
+<p>A <em>vector-swizzle</em> with vector type <code>T</code> shall have the same number of components as number of components of <code>T</code>.
+Each component of the vector-swizzle refers to component from <code>E1</code> designated by corresponding value specified in selector <code>E2</code>, assuming that <code>E1.E2</code> is swizzle expression used to create the <em>vector-swizzle</em>.</p>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+First component refers to component from <code>E1</code> selected by first value in selector <code>E2</code>, second - by second value and so on.
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p>A <em>vector-swizzle</em> with scalar type <code>T</code> shall behave as value of <code>T</code> and refer to component from <code>E1</code> designated by <code>E2</code>'s value, assuming <code>E1.E2</code> is swizzle expression used to create the <em>vector-swizzle</em>.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+It is similar to reference bounded to value of selected component from <code>E1</code>.
+</td>
+</tr>
+</table>
+</div>
+</li>
+<li>
+<p>A <em>vector-swizzle</em> shall have scalar or vector type.
+The address-of operator <code>&amp;</code> shall not be applied to <em>vector-swizzle</em>, so there are no pointers to <em>vector-swizzles</em>.
+A non-const reference shall not be bound to <em>vector-swizzle</em>.</p>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+If the initializer for a reference of type <code>const T&amp;</code> is lvalue that refers to vector-swizzle, the reference is bound to a temporary initialized to hold the value of the vector-swizzle; the reference is not bound to the vector-swizzle directly.
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p>There is no declarator for <em>vector-swizzle</em>.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+Any variable, member or type declaration shall not involve vector-swizzle; vector-swizzle cannot be stored.
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p>An <em>alignment-specifier</em> shall not be applied to <em>vector-swizzle</em>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>float4 v;
+
+auto pv1 = &amp;v; // correct: pv1 points to v
+auto pv2 = &amp;v.xy; // ill-formed: address-of operator &amp; is not
+                  // allowed on vector-swizzle
+
+const auto &amp;rv1 = v.xx; // correct: refers to temporary value of
+                        // float2 type initialized with
+                        // value of vector-swizzle
+float2 &amp;rv2 = v.xy; // ill-formed: binding to non-const reference
+                    // is not allowed</code></pre>
+</div>
+</div>
+</li>
+<li>
+<p>A result <em>vector-swizzle</em> from swizzle expression <code>E1.E2</code> is modifiable if:</p>
+<div class="openblock">
+<div class="content">
+<div class="ulist">
+<ul>
+<li>
+<p>Vector expression <code>E1</code> is modifiable lvalue and</p>
+</li>
+<li>
+<p>Each component selected by <em>vector-swizzle-selector</em> <code>E2</code> is selected at most once.</p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="paragraph">
+<p>Expression which modifies unmodifiable <em>vector-swizzle</em> is ill-formed.</p>
+</div>
+<div class="paragraph">
+<p>Changes applied to modifiable <em>vector-swizzle</em> are applied to components of <code>E1</code> referred by the <em>vector-swizzle</em> or by its components.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>char4 v;
+const char4  cv;
+
+v.yx = char2(33, 45); // correct
+v.zzwx = cv; // ill-formed: v.zzwx is not modifiable
+             // (repeated components)
+cv.zxy = char3(1); // ill-formed: cv.zxy is not modifiable
+                   // (cv is const)</code></pre>
+</div>
+</div>
+</li>
+<li>
+<p>A prvalue for <em>vector-swizzle</em> of <code>T</code> type can be converted to a prvalue of <code>T</code> type.</p>
+<div class="paragraph">
+<p>This conversion is called <em>swizzle-to-vector</em> conversion.
+<em>swizzle-to-vector</em> conversion shall be applied if necessary in all contexts where lvalue-to-rvalue conversions are allowed.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+swizzle-to-vector conversion shall be applied after lvalue-to-rvalue conversions and before any arithmetic conversions.
+</td>
+</tr>
+</table>
+</div>
+</li>
+<li>
+<p>A glvalue <em>vector-swizzle</em> of scalar or vector type <code>T</code> can be used in all expressions where glvalue of type <code>T</code> can be used except those which do not meet requirements and restrictions for <em>vector-swizzle</em>.</p>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+For example the address-of operator <code>&amp;</code> and binding to non-const reference are one of them.
+</td>
+</tr>
+</table>
+</div>
+</li>
+<li>
+<p>A swizzle expression <code>E1.E2</code> where <code>E2</code> selects all components of vector expression <code>E1</code> in order of their numerical selector values is called identity swizzle.</p>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+Components selected in <code>E2</code> are not repeated.
+</td>
+</tr>
+</table>
+</div>
+</li>
+<li>
+<p>Additional changes to C++ specification:</p>
+<div class="ulist">
+<ul>
+<li>
+<p><em>[ISO/IEC 14882:2014: expr.static.cast, ch. 5.2.9 (3)]</em> static_cast: If value is not a bit-field or a <em>vector-swizzle</em>, [&#8230;&#8203;]; if value is a <em>vector-swizzle</em>, the <em>lvalue-to-rvalue</em> conversion and <em>swizzle-to-vector</em> conversion are applied to the <em>vector-swizzle</em> and the resulting prvalue is used as the expression of the <code>static_cast</code> for the remainder of this section; otherwise, [&#8230;&#8203;]</p>
+</li>
+<li>
+<p><em>[ISO/IEC 14882:2014: expr.unary.op, ch. 5.3.1 (5)]</em> Unary operators: [&#8230;&#8203;] The operand of <code>&amp;</code> shall not be a bit-field or a <em>vector-swizzle</em>.</p>
+</li>
+<li>
+<p><em>[ISO/IEC 14882:2014: expr.pre.incr, ch. 5.3.2 (1)]</em> Increment and decrement: The result is the updated operand; it is an lvalue, and it is a bit-field or a <em>vector-swizzle</em> if the operand is respectively a bit-field or a <em>vector-swizzle</em>.</p>
+</li>
+<li>
+<p><em>[ISO/IEC 14882:2014: expr.sizeof, ch. 5.3.3 (2)]</em> Sizeof: [&#8230;&#8203;] When applied to a <em>vector-swizzle</em> which has type <code>T</code>, the result is the same as result from <code>sizeof(T)</code>.</p>
+</li>
+<li>
+<p><em>[ISO/IEC 14882:2014: expr.cond, ch. 5.16 (2.1)]</em> Conditional operator: - [&#8230;&#8203;] The conditional-expression is a bit-field or a <em>vector-swizzle</em> if that operand is respectively a bit-field or a <em>vector-swizzle</em>.</p>
+</li>
+<li>
+<p><em>[ISO/IEC 14882:2014: expr.cond, ch. 5.16 (4)]</em> Conditional operator: If the second and third operands are glvalues of the same value category and have the same type, the result is of that type and value category and it is a bit-field if the second or the third operand is a bit-field, or if both are bit-fields.
+The result is also a <em>vector-swizzle</em> if the second or the third operand is a <em>vector-swizzle</em>, or if both are <em>vector-swizzles</em>.</p>
+</li>
+</ul>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+An operand is converted to vector-swizzle if required by applying identity swizzle expression to it.
+</td>
+</tr>
+</table>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><em>[ISO/IEC 14882:2014: expr.ass, ch. 5.18 (1)]</em> Assignment and compound assignment operators: The result in all cases is a bit-field or a <em>vector-swizzle</em> if the left operand is respectively a bit-field or a <em>vector-swizzle</em>.</p>
+</li>
+<li>
+<p><em>[ISO/IEC 14882:2014: expr.comma, ch. 5.19 (1)]</em> Comma operator: The type and value of the result are the type and value of the right operand; the result is of the same value category as its right operand, and is a bit-field if its right operand is a glvalue and a bit-field, and is a <em>vector-swizzle</em> its right operand is a glvalue and a <em>vector-swizzle</em>.</p>
+</li>
+<li>
+<p><em>[ISO/IEC 14882:2014: dcl.type.simple, ch. 7.1.6.2 (4, 4.1)]</em> Simple type specifiers: For an expression e, the type denoted by decltype(e) is defined as follows:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>if e is an unparenthesized id-expression or an unparenthesized class member access (5.2.5) or unparenthesized swizzle expression, <code>decltype(e)</code> is the type of the entity named by e. If there is no such entity, or if e names a set of overloaded functions, the program is ill-formed.</p>
+</li>
+</ul>
+</div>
+</li>
+</ul>
+</div>
+</li>
+</ol>
+</div>
+</div>
+<div class="sect4">
+<h5 id="vector-constructors">Vector Constructors</h5>
+<div class="paragraph">
+<p>Vector constructors are defined to initialize a vector data type from a list of scalar or vectors.
+The forms of the constructors that are available is the set of possible argument lists for which all arguments have the same element type as the result vector, and the total number of elements is equal to the number of elements in the result vector.
+In addition, a form with a single scalar of the same type as the element type of the vector is available.</p>
+</div>
+<div class="paragraph">
+<p>For example, the following forms are available for <code>float4</code>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>float4( float, float, float, float )
+float4( float2, float, float )
+float4( float, float2, float )
+float4( float, float, float2 )
+float4( float2, float2 )
+float4( float3, float )
+float4( float, float3 )
+float4( float )
+
+float4{ float, float, float, float }
+float4{ float2, float, float }
+float4{ float, float2, float }
+float4{ float, float, float2 }
+float4{ float2, float2 }
+float4{ float3, float }
+float4{ float, float3 }
+float4{ float }</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Operands are evaluated by standard rules for function evaluation, except that implicit scalar-to-vector conversion shall not occur.
+The order in which the operands are evaluated is undefined.
+The operands are assigned to their respective positions in the result vector as they appear in memory order.
+That is, the first element of the first operand is assigned to result.x, the second element of the first operand (or the first element of the second operand if the first operand was a scalar) is assigned to result.y, etc.
+In the case of the form that has a single scalar operand, the operand is replicated across all lanes of the vector.</p>
+</div>
+<div class="paragraph">
+<p>Examples:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>float4 f = float4(1.0f, 2.0f, 3.0f, 4.0f);
+
+uint4  u = uint4(1); // u will be (1, 1, 1, 1).
+
+float4 f = float4(float2(1.0f, 2.0f),
+                  float2(3.0f, 4.0f));
+
+float4 f = float4(1.0f, float2(2.0f, 3.0f), 4.0f);
+
+float4 f = float4(1.0f, 2.0f); // error
+
+int4 i = (int4)(1, 2, 3, 4); // warning, vector literals (from OpenCL C) are
+                             // not part of OpenCL C++,
+                             // this expression will be evaluated to (int4)4,
+                             // and i will be (4, 4, 4, 4)</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="vector-types-and-usual-arithmetic-conversions">Vector Types and Usual Arithmetic Conversions</h5>
+<div class="paragraph">
+<p>Many operators that expect operands of arithmetic type cause conversions and yield result types in a similar way.
+The purpose is to determine a common real type for the operands and result.
+For the specified operands, each operand is converted, without change of type domain, to a type whose corresponding real type is the common real type.
+For this purpose, all vector types shall be considered to have higher conversion ranks than scalars.
+Unless explicitly stated otherwise, the common real type is also the corresponding real type of the result, whose type domain is the type domain of the operands if they are the same, and complex otherwise.
+This pattern is called the usual arithmetic conversions.
+If the operands are of more than one vector type, then an error shall occur.
+Implicit conversions between vector types are not permitted, per the <a href="#implicit-type-conversions"><em>Implicit Type Conversions</em></a> section.</p>
+</div>
+<div class="paragraph">
+<p>Otherwise, if there is only a single vector type, and all other operands are scalar types, the scalar types are converted to the type of the vector element, then widened into a new vector containing the same number of elements as the vector, by duplication of the scalar value across the width of the new vector.</p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="alignment-of-types">2.1.3. Alignment of Types</h4>
+<div class="paragraph">
+<p>A data item declared to be a data type in memory is always aligned to the size of the data type in bytes.
+For example, a <code>float4</code> variable will be aligned to a 16-byte boundary, a <code>char2</code> variable will be aligned to a 2-byte boundary.</p>
+</div>
+<div class="paragraph">
+<p>For 3-component vector data types, the size of the data type is <code>4 * sizeof(component)</code>.
+This means that a 3-component vector data type will be aligned to a <code>4 * sizeof(component)</code> boundary.
+The <code>vload3</code> and <code>vstore3</code> built-in functions can be used to read and write, respectively, 3-component vector data types from an array of packed scalar data type.</p>
+</div>
+<div class="paragraph">
+<p>A built-in data type that is not a power of two bytes in size must be aligned to the next larger power of two.
+This rule applies to built-in types only, not structs or unions.</p>
+</div>
+<div class="paragraph">
+<p>The OpenCL C++ compiler is responsible for aligning data items to the appropriate alignment as required by the data type.
+For arguments to a kernel function declared to be a pointer to a data type, the OpenCL compiler can assume that the pointee is always appropriately aligned as required by the data type.
+The behavior of an unaligned load or store is undefined, except for the <code>vload<em>n</em></code>, <code>vload_half<em>n</em></code>, <code>vstore<em>n</em></code>, and <code>vstore_half<em>n</em></code> functions defined in the <a href="#vector-data-load-and-store-functions"><em>Vector Data Load and Store Functions</em></a> section.
+The vector load functions can read a vector from an address aligned to the element type of the vector.
+The vector store functions can write a vector to an address aligned to the element type of the vector.</p>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="keywords">2.2. Keywords</h3>
+<div class="paragraph">
+<p>The following names are reserved for use as keywords in OpenCL C++ and shall not be used otherwise.</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Names reserved as keywords by C++14.</p>
+</li>
+<li>
+<p>OpenCL C++ data types defined in <a href="#device_builtin_scalar_data_types">Device built-in scalar data types</a> and <a href="#device_builtin_vector_data_types">Device built-in vector data types</a> tables.</p>
+</li>
+<li>
+<p>Function qualifiers: <code>__kernel</code> and <code>kernel</code>.</p>
+</li>
+<li>
+<p>Access qualifiers: <code>__read_only</code>, <code>read_only</code>, <code>\__write_only</code>, <code>write_only</code>, <code>__read_write</code> and <code>read_write</code>.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect2">
+<h3 id="implicit-type-conversions">2.3. Implicit Type Conversions</h3>
+<div class="paragraph">
+<p>Implicit conversions between scalar built-in types defined in <a href="#device_builtin_scalar_data_types">Device built-in scalar data types</a> table (except <code>void</code>) are supported.
+When an implicit conversion is done, it is not just a re-interpretation of the expression&#8217;s value, but a conversion of that value to an equivalent value in the new type.
+For example, the integer value 5 will be converted to the floating-point value 5.0.</p>
+</div>
+<div class="paragraph">
+<p>Implicit conversions from a scalar type to a vector type are allowed.
+In this case, the scalar may be subject to the usual arithmetic conversion to the element type used by the vector.
+The scalar type is then widened to the vector.
+If conversion from a scalar type to the element type used by the vector result in truncation or precision loss, the program is ill-formed, with the exception that:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>if scalar value is prvalue of literal type and the value is representable as the element type, the conversion should take place without error (warnings may be generated in this case).</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Implicit conversions between built-in vector data types are disallowed.
+Explicit conversions described in the <a href="#conversions-library"><em>Conversions Library</em></a> section must be used instead.</p>
+</div>
+<div class="paragraph">
+<p>Implicit conversions for pointer types follow the rules described in the C++14 specification.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="expressions">2.4. Expressions</h3>
+<div class="paragraph">
+<p>All expressions behave as described in <em>[ISO/IEC 14882:2014: expr, ch. 5]</em> with the the restrictions described in the <a href="#opencl_cxx_restrictions"><em>OpenCL C++ Restrictions</em></a> section and the following changes:</p>
+</div>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>All built-in operators have their vector counterparts.</p>
+</li>
+<li>
+<p>All built-in vector operations, apart from conditional operator, are performed component-wise.</p>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+Conditional operator logical-or-expression cannot be of vector type.
+</td>
+</tr>
+</table>
+</div>
+</li>
+<li>
+<p>Built in operators taking two vectors require that vectors have the same number of components, otherwise expression is ill-formed.</p>
+</li>
+<li>
+<p>Vector swizzle operations meet extra requirements and restrictions described in the <a href="#vector-component-access"><em>Vector Component Access</em></a> section.</p>
+</li>
+<li>
+<p>Implicit and explicit casts between vector types are not legal.
+The conversion between vector types can be done only using <code>convert_cast</code> from the <a href="#conversions-library"><em>Conversions Library</em></a> section.</p>
+<div class="paragraph">
+<p>Examples:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int4   i;
+uint4  u = (uint4) i; // not allowed
+
+float4 f;
+int4   i = static_cast&lt;int4&gt;(f); // not allowed
+
+float4 f;
+int8   i = (int8) f; // not allowed</code></pre>
+</div>
+</div>
+</li>
+<li>
+<p>Implicit and explicit casts from scalar to vector types are supported.</p>
+</li>
+<li>
+<p>All built-in arithmetic operators return result of the same built-in type (integer or floating-point) as the type of the operands, after operand type conversion.
+After conversion, the following cases are valid:</p>
+<div class="olist loweralpha">
+<ol class="loweralpha" type="a">
+<li>
+<p>The two operands are scalars.  In this case, the operation is applied, resulting in a scalar.</p>
+</li>
+<li>
+<p>One operand is a scalar, and the other is a vector.
+In this case, the scalar may be subject to the usual arithmetic conversion to the element type used by the vector operand.
+The scalar type is then widened to a vector that has the same number of components as the vector operand.
+The operation is done component-wise resulting in the same size vector.</p>
+</li>
+<li>
+<p>The two operands are vectors of the same type.
+In this case, the operation is done component-wise resulting in the same size vector.</p>
+</li>
+</ol>
+</div>
+</li>
+<li>
+<p>The built-in relational and equality operators equal (<code>==</code>), not equal (<code>!=</code>), greater than (<code>&gt;</code>), greater than or equal (<code>&gt;=</code>), less than (<code>&lt;</code>), and less than or equal (<code>&lt;=</code>) operate on scalar and vector types.
+All relational and equality operators result in a boolean (scalar or vector) type.
+After operand type conversion, the following cases are valid:</p>
+<div class="olist loweralpha">
+<ol class="loweralpha" type="a">
+<li>
+<p>The two operands are scalars.
+In this case, the operation is applied, resulting in a boolean scalar.</p>
+</li>
+<li>
+<p>One operand is a scalar, and the other is a vector.
+In this case, the scalar may be subject to the usual arithmetic conversion to the element type used by the vector operand.
+The scalar type is then widened to a vector that has the same number of components as the vector operand.
+The operation is done component-wise resulting in the same size boolean vector.</p>
+</li>
+<li>
+<p>The two operands are vectors of the same type.
+In this case, the operation is done component-wise resulting in the same size boolean vector.</p>
+</li>
+</ol>
+</div>
+</li>
+<li>
+<p>The built-in bitwise operators and (<code>&amp;</code>), or (<code>|</code>), exclusive or (<code>^</code>), not (<code>~</code>) operate on all scalar and vector built-in types except the built-in scalar and vector float types.
+For vector built-in types, the operators are applied component-wise.
+If one operand is a scalar and the other is a vector, the scalar may be subject to the usual arithmetic conversion to the element type used by the vector operand.
+The scalar type is then widened to a vector that has the same number of components as the vector operand.
+The operation is done component-wise resulting in the same size vector.</p>
+</li>
+<li>
+<p>The built-in logical operators and (<code>&amp;&amp;</code>), or (<code>||</code>) operate on all scalar and vector built-in types.
+For scalar built-in types the logical operator and (<code>&amp;&amp;</code>) will only evaluate the right hand operand if the left hand operand compares unequal to <code>false</code>.
+For scalar built-in types the logical operator or (<code>||</code>) will only evaluate the right hand operand if the left hand operand compares equal to <code>false</code>.
+For built-in vector types, both operands are evaluated and the operators are applied component-wise.
+If one operand is a scalar and the other is a vector, the scalar may be subject to the usual arithmetic conversion to the element type used by the vector operand.
+The scalar type is then widened to a vector that has the same number of components as the vector operand.
+The operation is done component-wise resulting in the same size vector.</p>
+<div class="paragraph">
+<p>The result is a scalar or vector boolean.</p>
+</div>
+</li>
+<li>
+<p>The built-in logical unary operator not (<code>!</code>) operates on all scalar and vector built-in types.
+For built-in vector types, the operators are applied component-wise.</p>
+<div class="paragraph">
+<p>The result is a scalar or vector boolean.</p>
+</div>
+</li>
+<li>
+<p>The built-in conditional operator (<code>?:</code>) described in <em>[ISO/IEC 14882:2014: expr, ch. 5.2]</em> operates on three expressions (<code>exp1 ? exp2 : exp3</code>).
+This operator evaluates the first expression <code>exp1</code>, which must be a scalar boolean result.
+If the result is <em>true</em> it selects to evaluate the second expression, otherwise it selects to evaluate the third expression.
+The second and third expressions can be any type, as long their types match, or there is a conversion in the <a href="#implicit-type-conversions"><em>Implicit Type Conversions</em></a> section that can be applied to one of the expressions to make their types match, or one is a vector and the other is a scalar and the scalar may be subject to the usual arithmetic conversion to the element type used by the vector operand and widened to the same type as the vector type.</p>
+<div class="paragraph">
+<p>This resulting matching type is the type of the entire expression.</p>
+</div>
+</li>
+<li>
+<p>The built-in shift operators are supported for built-in vector types except the built-in scalar and vector float types.
+For built-in vector types, the operators are applied component-wise.
+For the right-shift (<code>&gt;&gt;</code>), left-shift (<code>&lt;&lt;</code>) operators, the rightmost operand must be a scalar if the first operand is a scalar, and the rightmost operand can be a vector or scalar if the first operand is a vector.
+The result of <code>E1 &lt;&lt; E2</code> is <code>E1</code> left-shifted by <code>log2(N)</code> least significant bits in <code>E2</code> viewed as an unsigned integer value, where <code>N</code> is the number of bits used to represent the data type of <code>E1</code> after integer promotion, if <code>E1</code> is a scalar, or the number of bits used to represent the type of <code>E1</code> elements, if <code>E1</code> is a vector.
+The vacated bits are filled with zeros.
+The result of <code>E1 &gt;&gt; E2</code> is <code>E1</code> right-shifted by <code>log2(N)</code> least significant bits in <code>E2</code> viewed as an unsigned integer value, where <code>N</code> is the number of bits used to represent the data type of <code>E1</code> after integer promotion, if <code>E1</code> is a scalar, or the number of bits used to represent the type of <code>E1</code> elements, if <code>E1</code> is a vector.</p>
+<div class="paragraph">
+<p>If <code>E1</code> has an unsigned type or if <code>E1</code> has a signed type and a nonnegative value, the vacated bits are filled with zeros.</p>
+</div>
+<div class="paragraph">
+<p>If <code>E1</code> has a signed type and a negative value, the vacated bits are filled with ones.</p>
+</div>
+</li>
+</ol>
+</div>
+</div>
+<div class="sect2">
+<h3 id="address-spaces">2.5. Address Spaces</h3>
+<div class="paragraph">
+<p>The OpenCL C++ kernel language doesn&#8217;t introduce any explicit named address spaces, but they are implemented as part of the standard library described in the <a href="#address-spaces-library"><em>Address Spaces Library</em></a> section.
+There are 4 types of memory supported by all OpenCL devices: global, local, private and constant.
+The developers should be aware of them and know their limitations.</p>
+</div>
+<div class="sect3">
+<h4 id="implicit-storage-classes">2.5.1. Implicit Storage Classes</h4>
+<div class="paragraph">
+<p>The OpenCL C++ compiler can deduce an address space based on the scope where an object is declared:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>If a variable is declared in program scope, with <code>static</code> or <code>extern</code> specifier and the standard library storage class (see the <a href="#address-spaces-library"><em>Address Spaces Library</em></a> section) is not used, the variable is allocated in the global memory of a device.</p>
+</li>
+<li>
+<p>If a variable is declared in function scope, without <code>static</code> specifier and the standard library storage class (see the <a href="#address-spaces-library"><em>Address Spaces Library</em></a> section) is not used, the variable is allocated in the private memory of a device.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="memory-pools">2.5.2. Memory Pools</h4>
+<div class="sect4">
+<h5 id="global">Global</h5>
+<div class="paragraph">
+<p>The variables are allocated from the global memory pool if they meet the criteria described in the <a href="#implicit-storage-classes"><em>Implicit Storage Classes</em></a> section for the implicit global storage class or they are declared using explicit global storage class from the standard library (see the <a href="#global-class"><em>global class</em></a> section).</p>
+</div>
+<div class="paragraph">
+<p>The global memory objects can be:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Passed by pointer or reference to a kernel from the host.
+In such case the host manages their visibility, lifetime and a type of allocation.</p>
+</li>
+<li>
+<p>Declared in the program source (<code>static</code>, <code>extern</code> and program scope global variables).
+In such case they are:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>the coarse-grained SVM allocations that can be usable by multiple kernels on the same device safely</p>
+</li>
+<li>
+<p>not shared across devices</p>
+</li>
+<li>
+<p>not accessible from the host</p>
+</li>
+<li>
+<p>their lifetime is the same as a program</p>
+</li>
+</ul>
+</div>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The non-trivial constructors and destructors are supported with limitations described in the <a href="#memory-initialization"><em>Memory initialization</em></a> section.</p>
+</div>
+<div class="paragraph">
+<p>The constructors of objects in global memory are executed before the first kernel execution in the program.
+The destructors executed at program release time.</p>
+</div>
+<div class="paragraph">
+<p>The additional restrictions may apply if the explicit global storage class is used.
+Please refer to the <a href="#restrictions-2"><em>Restrictions</em></a> section for more details.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="local">Local</h5>
+<div class="paragraph">
+<p>The local variables can be only allocated in a program using the explicit local storage class from the standard library (see the <a href="#local-class"><em>local class</em></a> section).
+This type of memory is allocated for each work-group executing the kernel and exist only for the lifetime of the work-group executing the kernel.</p>
+</div>
+<div class="paragraph">
+<p>The non-trivial constructors and destructors are supported with limitations described in the <a href="#memory-initialization"><em>Memory initialization</em></a> section.</p>
+</div>
+<div class="paragraph">
+<p>The constructors of objects in local memory are executed by one work-item before the kernel body execution.
+The destructors are executed by one work-item after the kernel body execution.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+initialization of local variables can cause performance degradation.
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p>The additional restrictions may apply if the explicit local storage class is used.
+Please refer to the <a href="#restrictions-2"><em>Restrictions</em></a> section for more details.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="private">Private</h5>
+<div class="paragraph">
+<p>The variables are allocated from the private memory pool if they meet the criteria described in <a href="#implicit-storage-classes">Implicit Storage Classes</a> for the implicit private storage class or they were declared using explicit private storage class from the standard library (see the <a href="#priv-class"><em>priv class</em></a> section).</p>
+</div>
+<div class="paragraph">
+<p>The non-trivial constructors and destructors are supported.</p>
+</div>
+<div class="paragraph">
+<p>The additional restrictions may apply if the explicit priv storage class is used.
+Please refer to the <a href="#restrictions-2"><em>Restrictions</em></a> section for more details.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="constant">Constant</h5>
+<div class="paragraph">
+<p>The constant variables can be only allocated in a program using the explicit constant storage class from the standard library (see the <a href="#constant-class"><em>constant class</em></a> section).
+The variables declared using the <code>constant&lt;T&gt;</code> class refer to memory objects allocated from the global memory pool and which are accessed inside a kernel(s) as read-only variables.
+These read-only variables can be accessed by all (global) work-items of the kernel during its execution.</p>
+</div>
+<div class="paragraph">
+<p>The constant objects must be constructible at compile time, they cannot have any user defined constructors, destructors, methods and operators.
+Otherwise behavior is undefined.</p>
+</div>
+<div class="paragraph">
+<p>The additional restrictions may apply if the explicit constant storage class is used.
+Please refer to the <a href="#restrictions-2"><em>Restrictions</em></a> section for more details.</p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="pointers-and-references">2.5.3. Pointers and references</h4>
+<div class="paragraph">
+<p>All C++ pointers and references point to an object in the unnamed/generic address space if the explicit address space pointer classes are not used.
+The explicit address space pointer classes are implemented as a part of the standard library and they are described in the <a href="#explicit-address-space-pointer-classes"><em>Explicit address space pointer classes</em></a> section.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="memory-initialization">2.5.4. Memory initialization</h4>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 8. Supported memory initializers</caption>
+<colgroup>
+<col style="width: 13%;">
+<col style="width: 12%;">
+<col style="width: 25%;">
+<col style="width: 25%;">
+<col style="width: 25%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Storage memory (address space)</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Scope type</strong></th>
+<th class="tableblock halign-left valign-top" colspan="3"><strong>Initialization type</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">uninitialized (no constructor or trivial default constructor)</p>
+<p class="tableblock">  <strong>AND</strong></p>
+<p class="tableblock">  trivial destructor</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">initialized by constant expression</p>
+<p class="tableblock">  <strong>AND</strong></p>
+<p class="tableblock">  trivial destructor</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">custom initializer</p>
+<p class="tableblock">  <strong>OR</strong></p>
+<p class="tableblock">  custom destructor</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top" rowspan="4"><p class="tableblock">local</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">program</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">supported (not zero-pre-init)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">not supported</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">not supported</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">kernel</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">supported</p>
+<p class="tableblock">  Variables are not zero-pre-initialized.</p>
+<p class="tableblock">  Optional zero-pre-initialization possible using switch: -cl-zero-init-local-mem-vars</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">supported</p>
+<p class="tableblock">  Variables are not zero-pre-initialized.</p>
+<p class="tableblock">  Materialize temporary expressions are not supported.</p>
+<p class="tableblock">  Optional zero-pre-initialization possible using switch: -cl-zero-init-local-mem-vars</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">supported</p>
+<p class="tableblock">  Variables are not zero-pre-initialized.</p>
+<p class="tableblock">  Materialize temporary expressions are not supported.</p>
+<p class="tableblock">  Optional zero-pre-initialization possible using switch: -cl-zero-init-local-mem-vars</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">local (non-kernel)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">not supported</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">not supported</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">not supported</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">class (static data member)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">supported</p>
+<p class="tableblock">  Variables are not zero-pre-initialized.</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">not supported</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">not supported</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top" rowspan="3"><p class="tableblock">global</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">program</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">supported</p>
+<p class="tableblock">  Variables are zero-pre-initialized.</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">supported</p>
+<p class="tableblock">  Variables are zero or constexpr-pre-initialized.</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">supported</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">kernel / local</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">supported</p>
+<p class="tableblock">  Variables are zero-pre-initialized.</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">supported</p>
+<p class="tableblock">  Variables are zero or constexpr-pre-initialized.</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">not supported</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">class (static data member)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">supported</p>
+<p class="tableblock">  Variables are zero-pre-initialized.</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">supported</p>
+<p class="tableblock">  Variables are zero or constexpr-pre-initialized.</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">not supported</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">constant</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">(any)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">supported</p>
+<p class="tableblock">  Variables are zero-pre-initialized.</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">supported</p>
+<p class="tableblock">  Variables are zero or constexpr-pre-initialized.</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">not supported</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">private</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">(any)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">supported</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">supported</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">supported</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+<div class="sect2">
+<h3 id="kernel-functions">2.6. Kernel Functions</h3>
+<div class="sect3">
+<h4 id="function-qualifiers">2.6.1. Function Qualifiers</h4>
+<div class="paragraph">
+<p>The <code>kernel</code> (or <code>__kernel</code>) qualifier declares a function to be a kernel that can be executed by an application on an OpenCL device(s).
+The following rules apply to functions that are declared with this qualifier:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>It can be executed on the device only.</p>
+</li>
+<li>
+<p>It can be enqueued by the host or on the device.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The <code>kernel</code> and <code>__kernel</code> names are reserved for use as functions qualifiers and shall not be used otherwise.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="restrictions">2.6.2. Restrictions</h4>
+<div class="sect4">
+<h5 id="kernel-function-restrictions">Kernel Function Restrictions</h5>
+<div class="ulist">
+<ul>
+<li>
+<p>Kernel functions are implicitly declared as <code>extern "C"</code>.</p>
+</li>
+<li>
+<p>Kernel functions cannot be overloaded.</p>
+</li>
+<li>
+<p>Kernel functions cannot be template functions.</p>
+</li>
+<li>
+<p>Kernel functions cannot be called by other kernel functions.</p>
+</li>
+<li>
+<p>Kernel functions cannot have parameters specified with default values.</p>
+</li>
+<li>
+<p>Kernel functions must have the return type <code>void</code>.</p>
+</li>
+<li>
+<p>Kernel functions cannot be called <code>main</code>.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect4">
+<h5 id="kernel-parameter-restrictions">Kernel Parameter Restrictions</h5>
+<div class="paragraph">
+<p>The OpenCL host compiler and the OpenCL C++ kernel language device compiler can have different requirements for i.e. type sizes, data packing and alignment, etc., therefore the kernel parameters must meet the following requirements:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Types passed by pointer or reference must be standard layout types.</p>
+</li>
+<li>
+<p>Types passed by value must be POD types.</p>
+</li>
+<li>
+<p>Types cannot be declared with the built-in <code>bool</code> scalar type, vector type or a class that contain <code>bool</code> scalar or vector type fields.</p>
+</li>
+<li>
+<p>Types cannot be structures or classes with bit field members.</p>
+</li>
+<li>
+<p>Marker types must be passed by value (see the <a href="#marker-types"><em>Marker Types</em></a> section).</p>
+</li>
+<li>
+<p><code>global</code>, <code>constant</code>, and <code>local</code> storage classes can be passed only by reference or pointer. More details in the <a href="#explicit-address-space-storage-classes"><em>Explicit address space storage classes</em></a> section.</p>
+</li>
+<li>
+<p>Pointers and references must point to one of the following address spaces: global, local or constant.</p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="preprocessor-directives-and-macros">2.7. Preprocessor Directives and Macros</h3>
+<div class="paragraph">
+<p>The preprocessing directives defined by the C++14  specification (<em>section 16</em>) are supported.</p>
+</div>
+<div class="paragraph">
+<p>The <code>#pragma</code> directive is described as:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#pragma pp-tokensopt new-line</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>A <code>#pragma</code> directive where the preprocessing token <code>OPENCL</code> (used instead of <code>STDC</code>) does not immediately follow pragma in the directive (prior to any macro replacement) causes the implementation to behave in an implementation-defined manner.
+The behavior might cause translation to fail or cause the translator or the resulting program to behave in a non-conforming manner.
+Any such pragma that is not recognized by the implementation is ignored.
+If the preprocessing token <code>OPENCL</code> does immediately follow pragma in the directive (prior to any macro replacement), then no macro replacement is performed on the directive, and the directive shall have one of the following forms whose meanings are described elsewhere:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#pragma OPENCL FP_CONTRACT on-off-switch // on-off-switch: one of ON OFF DEFAULT
+
+#pragma OPENCL EXTENSION extensionname : behavior
+#pragma OPENCL EXTENSION all : behavior</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The following predefined macro names are available.</p>
+</div>
+<div class="paragraph">
+<p><code>__FILE__</code> The presumed name of the current source file (a character string literal).</p>
+</div>
+<div class="paragraph">
+<p><code>__LINE__</code> The presumed line number (within the current source file) of the current source line (an integer constant).</p>
+</div>
+<div class="paragraph">
+<p><code>__OPENCL_CPP_VERSION__</code> substitutes an integer reflecting the OpenCL C++ version specified when compiling the OpenCL C++ program.
+The version of OpenCL C++ described in this document will have <code>__OPENCL_CPP_VERSION__</code> substitute the integer <code>100</code>.</p>
+</div>
+<div class="paragraph">
+<p>The macro names defined by the C++14 specification in <em>section 16</em> but not currently supported by OpenCL are reserved for future use.</p>
+</div>
+<div class="paragraph">
+<p>The predefined identifier <code>__func__</code> is available.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="attribute-qualifiers">2.8. Attribute Qualifiers</h3>
+<div class="paragraph">
+<p>The <code>[[ ]]</code> attribute qualifier syntax allows additional attributes to be attached to types, variables, kernel functions, kernel parameters, or loops.</p>
+</div>
+<div class="paragraph">
+<p>Some attributes change the semantics of the program and are required for program correctness.
+Other attributes are optional hints that may be ignored without affecting program correctness.
+Nevertheless, frontend compilers that compile to an intermediate representation are required to faithfully pass optional attribute hints with an intermediate representation to device compilers for further processing.</p>
+</div>
+<div class="sect3">
+<h4 id="optional-type-attributes">2.8.1. Optional Type Attributes</h4>
+<div class="paragraph">
+<p><code>[[ ]]</code> attribute syntax can be used to specify special attributes of enum, class and union types when you define such types.
+Two attributes are currently defined for types: <code>aligned</code>, and <code>packed</code>.</p>
+</div>
+<div class="paragraph">
+<p>You may specify type attributes in an enum, class or union type declaration or definition, or for other types in a typedef declaration.</p>
+</div>
+<div class="paragraph">
+<p>For an enum, class or union type, you may specify attributes either between the enum, class or union tag and the name of the type, or just past the closing curly brace of the definition.
+The former syntax is preferred.</p>
+</div>
+<div class="sect4">
+<h5 id="claligned-alignment">cl::aligned (alignment)</h5>
+<div class="paragraph">
+<p>This attribute specifies a minimum alignment (in bytes) for variables of the specified type.
+For example, the declarations:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>struct S { short f[3]; } [[cl::aligned(8)]];
+typedef int more_aligned_int [[cl::aligned(8)]];</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>force the compiler to insure (as far as it can) that each variable whose type is struct S or <code>more_aligned_int</code> will be allocated and aligned <em>at least</em> on a 8-byte boundary.</p>
+</div>
+<div class="paragraph">
+<p>Note that the alignment of any given struct or union type is required by the C++ standard to be at least a perfect multiple of the lowest common multiple of the alignments of all of the members of the struct or union in question and must also be a power of two.
+This means that you <em>can</em> effectively adjust the alignment of a class or union type by attaching an aligned attribute to any one of the members of such a type, but the notation illustrated in the example above is a more obvious, intuitive, and readable way to request the compiler to adjust the alignment of an entire class or union type.</p>
+</div>
+<div class="paragraph">
+<p>As in the preceding example, you can explicitly specify the alignment (in bytes) that you wish the compiler to use for a given class or union type.
+Alternatively, you can leave out the alignment factor and just ask the compiler to align a type to the maximum useful alignment for the target machine you are compiling for.
+For example, you could write:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>struct S { short f[3]; } [[cl::aligned]];</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Whenever you leave out the alignment factor in an aligned attribute specification, the compiler automatically sets the alignment for the type to the largest alignment which is ever used for any data type on the target machine you are compiling for.
+In the example above, the size of each short is 2 bytes, and therefore the size of the entire struct S type is 6 bytes.
+The smallest power of two which is greater than or equal to that is 8, so the compiler sets the alignment for the entire struct S type to 8 bytes.</p>
+</div>
+<div class="paragraph">
+<p>Note that the effectiveness of aligned attributes may be limited by inherent limitations of the OpenCL device and compiler.
+For some devices, the OpenCL compiler may only be able to arrange for variables to be aligned up to a certain maximum alignment.
+If the OpenCL compiler is only able to align variables up to a maximum of 8 byte alignment, then specifying <code>aligned(16)</code> will still only provide you with 8 byte alignment.
+See your platform-specific documentation for further information.</p>
+</div>
+<div class="paragraph">
+<p>The aligned attribute can only increase the alignment; but you can decrease it by specifying packed as well.
+See below.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="clpacked">cl::packed</h5>
+<div class="paragraph">
+<p>This attribute, attached to class or union type definition, specifies that each member of the structure or union is placed to minimize the memory required.
+When attached to an enum definition, it indicates that the smallest integral type should be used.</p>
+</div>
+<div class="paragraph">
+<p>Specifying this attribute for class and union types is equivalent to specifying the packed attribute on each of the structure or union members.</p>
+</div>
+<div class="paragraph">
+<p>In the following example struct my_packed_struct&#8217;s members are packed closely together, but the internal layout of its s member is not packed.
+To do that, struct <code>my_unpacked_struct</code> would need to be packed, too.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>struct my_unpacked_struct
+{
+  char c;
+  int i;
+};
+
+struct [[cl::packed]] my_packed_struct
+{
+  char c;
+  int  i;
+  struct my_unpacked_struct s;
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>You may only specify this attribute on the definition of an enum, class or union, not on a typedef which does not also define the enumerated type, structure or union.</p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="optional-variable-attributes">2.8.2. Optional Variable Attributes</h4>
+<div class="paragraph">
+<p>[[ ]] syntax allows you to specify special attributes of variables or structure fields.
+The following attribute qualifiers are currently defined:</p>
+</div>
+<div class="sect4">
+<h5 id="claligned">cl::aligned</h5>
+<div class="paragraph">
+<p>This attribute specifies a minimum alignment for the variable or class field, measured in bytes.
+For example, the declaration:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int x [[cl::aligned(16)]] = 0;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>causes the compiler to allocate the global variable <code>x</code> on a 16-byte boundary.
+The alignment value specified must be a power of two.</p>
+</div>
+<div class="paragraph">
+<p>You can also specify the alignment of structure fields.
+For example, to create double-word aligned int pair, you could write:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>struct foo { int x[2] [[cl::aligned(8)]]; };</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>This is an alternative to creating a union with a double member that forces the union to be double-word aligned.</p>
+</div>
+<div class="paragraph">
+<p>As in the preceding examples, you can explicitly specify the alignment (in bytes) that you wish the compiler to use for a given variable or structure field.
+Alternatively, you can leave out the alignment factor and just ask the compiler to align a variable or field to the maximum useful alignment for the target machine you are compiling for.
+For example, you could write:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>short array[3] [[cl::aligned]];</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Whenever you leave out the alignment factor in an aligned attribute specification, the OpenCL compiler automatically sets the alignment for the declared variable or field to the largest alignment which is ever used for any data type on the target device you are compiling for.</p>
+</div>
+<div class="paragraph">
+<p>When used on a class, or class member, the aligned attribute can only increase the alignment; in order to decrease it, the packed attribute must be specified as well.
+When used as part of a typedef, the aligned attribute can both increase and decrease alignment, and specifying the packed attribute will generate a warning.</p>
+</div>
+<div class="paragraph">
+<p>Note that the effectiveness of aligned attributes may be limited by inherent limitations of the OpenCL device and compiler.
+For some devices, the OpenCL compiler may only be able to arrange for variables to be aligned up to a certain maximum alignment.
+If the OpenCL
+compiler is only able to align variables up to a maximum of 8 byte alignment, then specifying <code>aligned(16)</code> will still only provide you with 8 byte alignment.
+See your platform-specific documentation for further information.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="clpacked-1">cl::packed</h5>
+<div class="paragraph">
+<p>The <code>packed</code> attribute specifies that a variable or class field should have the smallest possible alignment - one byte for a variable, unless you specify a larger value with the aligned attribute.</p>
+</div>
+<div class="paragraph">
+<p>Here is a structure in which the field <code>x</code> is packed, so that it immediately follows a:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>struct foo
+{
+  char a;
+  int x[2] [[cl::packed]];
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>An attribute list placed at the beginning of a user-defined type applies to the variable of that type and not the type, while attributes following the type body apply to the type.</p>
+</div>
+<div class="paragraph">
+<p>For example:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>/* a has alignment of 128 */
+[[cl::aligned(128)]] struct A { int i; } a;
+
+/* b has alignment of 16 */
+[[cl::aligned(16)]] struct B { double d; } [[cl::aligned(32)]] b;
+
+struct A a1; /* a1 has alignment of 4 */
+
+struct B b1; /* b1 has alignment of 32 */</code></pre>
+</div>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="optional-kernel-function-attributes">2.8.3. Optional Kernel Function Attributes</h4>
+<div class="paragraph">
+<p>The kernel qualifier can be used with the <code>[[ ]]</code> attribute syntax to declare additional information about the kernel function.
+The kernel function attributes must appear immediately before the kernel function to be affected.</p>
+</div>
+<div class="paragraph">
+<p>The following attributes are supported:</p>
+</div>
+<div class="sect4">
+<h5 id="clwork_group_size_hint">cl::work_group_size_hint</h5>
+<div class="paragraph">
+<p>The optional <code>[[cl::work_group_size_hint(X, Y, Z)]]</code> is a hint to the compiler and is intended to specify the work-group size that may be used i.e. value most likely to be specified by the <code>local_work_size</code> argument to <code>clEnqueueNDRangeKernel</code>.
+For example the <code>[[cl::work_group_size_hint(1, 1, 1)]]</code> is a hint to the compiler that the kernel will most likely be executed with a work-group size of 1.</p>
+</div>
+<div class="paragraph">
+<p>The specialization constants (see the <a href="#specialization-constants-library"><em>Specialization Constants</em></a> section) can be used as arguments of <code>cl::work_group_size_hint</code> attribute.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="clrequired_work_group_size">cl::required_work_group_size</h5>
+<div class="paragraph">
+<p>The optional <code>[[cl::required_work_group_size(X, Y, Z)]]</code> is the work-group size that must be used as the <code>local_work_size</code> argument to <code>clEnqueueNDRangeKernel</code>.
+This allows the compiler to optimize the generated code appropriately for this kernel.</p>
+</div>
+<div class="paragraph">
+<p>If <code>Z</code> is one, the <code>work_dim</code> argument to <code>clEnqueueNDRangeKernel</code> can be 2 or 3.
+If <code>Y</code> and <code>Z</code> are one, the <code>work_dim</code> argument to <code>clEnqueueNDRangeKernel</code> can be 1, 2 or 3.</p>
+</div>
+<div class="paragraph">
+<p>The specialization constants (see the <a href="#specialization-constants-library"><em>Specialization Constants</em></a> section) can be used as arguments of <code>cl::required_work_group_size(X, Y, Z)</code> attribute.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="clrequired_num_sub_groups">cl::required_num_sub_groups</h5>
+<div class="paragraph">
+<p>The optional <code>[[cl::required_num_sub_groups(X)]]</code> is the number of sub-groups that must be generated by a kernel launch.
+To ensure that this number is created the queries mapping number of sub-groups to local size may be used.
+This allows the compiler to optimize the kernel based on the sub-group count and in addition allows the API to enforce correctness of kernel use to the user when concurrency of sub-groups is a requirement.</p>
+</div>
+<div class="paragraph">
+<p>The specialization constants (see the <a href="#specialization-constants-library"><em>Specialization Constants</em></a> section) can be used as argument of <code>cl::required_num_sub_groups</code> attribute.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="clvec_type_hint">cl::vec_type_hint</h5>
+<div class="paragraph">
+<p>The optional <code>[[cl::vec_type_hint(&lt;type&gt;)]]</code> is a hint to the compiler and is intended to be a representation of the computational <em>width</em> of the kernel, and should serve as the basis for calculating processor bandwidth utilization when the compiler is looking to autovectorize the code.
+In the <code>[[cl::vec_type_hint(&lt;type&gt;)]]</code> qualifier <code>&lt;type&gt;</code> is one of the built-in vector types listed in <a href="#device_builtin_vector_data_types">Device built-in vector data types</a> table or the constituent scalar element types.
+If <code>cl::vec_type_hint(&lt;type&gt;)</code> is not specified, the kernel is assumed to have the <code>[[cl::vec_type_hint(int)]]</code> qualifier.</p>
+</div>
+<div class="paragraph">
+<p>For example, where the developer specified a width of <code>float4</code>, the compiler should assume that the computation usually uses up to 4 lanes of a float vector, and would decide to merge work-items or possibly even separate one work-item into many threads to better match the hardware capabilities.
+A conforming implementation is not required to autovectorize code, but shall support the hint.
+A compiler may autovectorize, even if no hint is provided.
+If an implementation merges N work-items into one thread, it is responsible for correctly handling cases where the number of global or local work-items in any dimension modulo N is not zero.</p>
+</div>
+<div class="paragraph">
+<p>Examples:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>// autovectorize assuming float4 as the
+// basic computation width
+[[cl::vec_type_hint(float4)]] kernel
+void foo(cl::global_ptr&lt;float4&gt; p) { ... }
+
+// autovectorize assuming double as the
+// basic computation width
+[[cl::vec_type_hint(double)]] kernel
+void foo(cl::global_ptr&lt;float4&gt; p) { ... }
+
+// autovectorize assuming int (default)
+// as the basic computation width
+kernel void foo(cl::global_ptr&lt;float4&gt; p) { ... }</code></pre>
+</div>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="optional-kernel-parameter-attributes">2.8.4. Optional Kernel Parameter Attributes</h4>
+<div class="paragraph">
+<p>The kernel parameter can be used with the <code>[[ ]]</code> attribute syntax to declare additional information about an argument passed to the kernel.
+The kernel parameter attributes must appear immediately before or after the kernel parameter declaration to be affected.</p>
+</div>
+<div class="paragraph">
+<p>The following attributes are supported:</p>
+</div>
+<div class="sect4">
+<h5 id="clmax_size">cl::max_size</h5>
+<div class="paragraph">
+<p>This attribute can be provided with a kernel argument of type <code>constant_ptr&lt;T&gt;</code>, <code>constant&lt;T&gt;*</code>, <code>constant&lt;T&gt;&amp;</code>, <code>local_ptr&lt;T&gt;</code>, <code>local&lt;T&gt;*</code>, <code>local&lt;T&gt;&amp;</code>.
+The value of the attribute specifies the maximum size in bytes of the corresponding memory object.
+This size cannot exceed the limits supported by the device:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE</code> for the kernel arguments in constant memory</p>
+</li>
+<li>
+<p><code>CL_DEVICE_LOCAL_MEM_SIZE</code> for the kernel arguments in local memory</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The specialization constants (see the <a href="#specialization-constants-library"><em>Specialization Constants</em></a> section) can be used as argument of <code>cl::max_size</code> attribute.</p>
+</div>
+<div class="paragraph">
+<p>Examples:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_memory&gt;
+
+kernel void foo([[cl::max_size(65536)]] cl::constant_ptr&lt;int&gt; arg) {
+  //...
+}</code></pre>
+</div>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="optional-loop-attributes">2.8.5. Optional Loop Attributes</h4>
+<div class="sect4">
+<h5 id="_cl_unroll_hint">cl::unroll_hint</h5>
+<div class="paragraph">
+<p>The <code><a id="cl::unroll_hint"></a></code> and <code>[[cl::unroll_hint(n)]]</code> attribute qualifiers can be used to specify that a loop (<code>for</code>, <code>while</code> and <code>do</code> loops) can be unrolled.
+This attribute qualifier can be used to specify full unrolling or partial unrolling by a specified amount.
+This is a compiler hint and the compiler may ignore this directive.</p>
+</div>
+<div class="paragraph">
+<p><code>n</code> is the loop unrolling factor and must be a positive integral compile time constant expression.
+An unroll factor of 1 disables unrolling.
+If <code>n</code> is not specified, the compiler determines the unrolling factor for the loop.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+The <code>[[cl::unroll_hint(n)]]</code> attribute qualifier must appear immediately before the loop to be affected.
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p>Examples:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>[[cl::unroll_hint(2)]]
+while (*s != 0)
+    *p++ = *s++;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>This tells the compiler to unroll the above while loop by a factor of 2.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>[[cl::unroll_hint]]
+for (int i=0; i&lt;2; i++) {
+   //...
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>In the example above, the compiler will determine how much to unroll the loop.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>[[cl::unroll_hint(1)]]
+for (int i=0; i&lt;32; i++) {
+  //...
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The above is an example where the loop should not be unrolled.</p>
+</div>
+<div class="paragraph">
+<p>Below are some examples of invalid usage of <code>[[cl::unroll_hint(n)]]</code>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>[[cl::unroll_hint(-1)]]
+while (/* ... */) {
+  //...
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The above example is an invalid usage of the loop unroll factor as the loop unroll factor is negative.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>[[cl::unroll_hint]]
+if(/* ... */) {
+  //...
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The above example is invalid because the <code>unroll_hint</code> attribute qualifier is used on a non-loop construct.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>kernel void my_kernel(/* ... */) {
+  int x;
+  [[cl::unroll_hint(x)]]
+  for (int i=0; i&lt;x; i++) {
+    //...
+  }
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The above example is invalid because the loop unroll factor is not a compile-time constant expression.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="clivdep">cl::ivdep</h5>
+<div class="paragraph">
+<p>The <code>[[cl::ivdep]]</code> (ignore vector dependencies) attribute qualifier is a hint to the compiler and may appear in loops to indicate that the compiler may assume there are no memory dependencies across loop iterations in order to autovectorize consecutive iterations of the loop.
+This attribute qualifier may appear in one of the following
+forms:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>[[cl::ivdep]]
+[[cl::ivdep(len)]]</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>If the parameter <code>len</code> is specified, it is used to specify the maximum number of consecutive iterations without loop-carried dependencies.
+<code>len</code> is a lower bound on the distance of any loop-carried dependence, and it applies to arbitrary alignment.
+For example, any 4 consecutive iterations can be vectorized with <code>cl::ivdep(4)</code>.
+The <code>len</code> parameter must be a positive integer.
+The final decision whether to autovectorize the complete loop may be subject to other compiler heuristics as well as flags e.g., <em>-cl-fast-relaxed-math</em> to ignore non-associated operations.</p>
+</div>
+<div class="paragraph">
+<p>Examples:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>[[cl::ivdep]]
+for (int i=0; i&lt;N; i++) {
+    C[i+offset] = A[i+offset] * B[i+offset];
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>In the example above, assuming that <code>A</code> and <code>B</code> are not restricted pointers, it is unknown if <code>C</code> aliases <code>A</code> or <code>B</code>.
+Placing the <code>[[cl::ivdep]]</code> attribute before the loop lets the compiler assume there are no memory dependencies across the loop iterations.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>[[cl::ivdep(8)]]
+for (int i=0; i&lt;N; i++) {
+    A[i+K] = A[i] * B[i];
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>In the example above, buffer <code>A</code> is read from and written to in the loop iterations.
+In each iteration, the read and write to <code>A</code> are to different indices.
+In this case it is not safe to vectorize the loop to a vector length greater than <code>K</code>, so the <code>len</code> parameter is specified with a value that is known to be not greater than any value that <code>K</code> may take during the execution of loop.
+In this example we are guaranteed (by <code>len</code>) that <code>K</code> will always be greater than or equal to 8.</p>
+</div>
+<div class="paragraph">
+<p>Below is an example of invalid usage of <code>[[cl::ivdep]]</code>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>[[cl::ivdep(-1)]]
+for (int i=0; i&lt;N; i++) {
+    C[i+offset] = A[i+offset] * B[i+offset];
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The above example is an invalid usage of the attribute qualifier as <code>len</code> is negative.</p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="extending-attribute-qualifiers">2.8.6. Extending Attribute Qualifiers</h4>
+<div class="paragraph">
+<p>The attribute syntax can be extended for standard language extensions and vendor specific extensions.
+Any extensions should follow the naming conventions outlined in the introduction to <em>section 9</em> in the OpenCL 2.2 Extension Specification.</p>
+</div>
+<div class="paragraph">
+<p>Attributes are intended as useful hints to the compiler.
+It is our intention that a particular implementation of OpenCL be free to ignore all attributes and the resulting executable binary will produce the same result.
+This does not preclude an implementation from making use of the additional information provided by attributes and performing optimizations or other transformations as it sees fit.
+In this case it is the programmer&#8217;s responsibility to guarantee that the information provided is in some sense correct.</p>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="opencl_cxx_restrictions">2.9. Restrictions</h3>
+<div class="paragraph">
+<p>The following C++14 features are not supported by OpenCL C++:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>the <code>dynamic_cast</code> operator (<em>ISO C++ Section 5.2.7</em>)</p>
+</li>
+<li>
+<p>type identification (<em>ISO C++ Section 5.2.8</em>)</p>
+</li>
+<li>
+<p>recursive function calls (<em>ISO C++ Section 5.2.2, item 9</em>) unless they are a compile-time constant expression</p>
+</li>
+<li>
+<p>non-placement <code>new</code> and <code>delete</code> operators (<em>ISO C++ Sections 5.3.4 and 5.3.5</em>)</p>
+</li>
+<li>
+<p><code>goto</code> statement (<em>ISO C++ Section 6.6</em>)</p>
+</li>
+<li>
+<p><code>register</code> and <code>thread_local</code> storage qualifiers (<em>ISO C++ Section 7.1.1</em>)</p>
+</li>
+<li>
+<p>virtual function qualifier (<em>ISO C++ Section 7.1.2</em>)</p>
+</li>
+<li>
+<p>function pointers (<em>ISO C++ Sections 8.3.5 and 8.5.3</em>) unless they are a compile-time  constant expression</p>
+</li>
+<li>
+<p>virtual functions and abstract classes (<em>ISO C++ Sections 10.3 and 10.4</em>)</p>
+</li>
+<li>
+<p>exception handling (<em>ISO C++ Section 15</em>)</p>
+</li>
+<li>
+<p>the C++ standard library (<em>ISO C++ Sections 17 &#8230;&#8203; 30</em>)</p>
+</li>
+<li>
+<p><code>asm</code> declaration (<em>ISO C++ Section 7.4</em>)</p>
+</li>
+<li>
+<p>no implicit lambda to function pointer conversion (<em>ISO C++ Section 5.1.2, item 6</em>)</p>
+</li>
+<li>
+<p>variadic functions (<em>ISO C99 Section 7.15, Variable arguments &lt;stdarg.h&gt;</em>)</p>
+</li>
+<li>
+<p>and, like C++, OpenCL C++ does not support variable length arrays (<em>ISO C99, Section 6.7.5</em>).</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>To avoid potential confusion with the above, please note the following features <em>are</em> supported in OpenCL C++:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>All variadic templates (<em>ISO C++ Section 14.5.3</em>) including variadic function templates are supported.</p>
+</li>
+</ul>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+This page refers to <em>ISO C99</em> instead of <em>ISO C11</em> since the <em>ISO C++14</em> document refers to <em>ISO C99</em> in <em>ISO C++ Section 1.2 and Annex C</em>.
+</td>
+</tr>
+</table>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="opencl-c-standard-library">3. OpenCL C++ Standard Library</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>OpenCL C++ does not support the C++14 standard library, but instead implements its own standard library.
+No OpenCL types and functions are auto-included.</p>
+</div>
+<div class="sect2">
+<h3 id="opencl-definitions">3.1. OpenCL Definitions</h3>
+<div class="paragraph">
+<p>Header <em>&lt;opencl_def&gt;</em> defines OpenCL scalar, vector types and macros.
+<code>cl_</code>* types are guaranteed to have exactly the same size as their host counterparts defined in <em>cl_platform.h</em> file.</p>
+</div>
+<div class="sect3">
+<h4 id="header-opencl_def-synopsis">3.1.1. Header &lt;opencl_def&gt; Synopsis</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#define __OPENCL_CPP_VERSION__ 100
+
+typedef __SIZE_TYPE__     size_t;
+typedef __PTRDIFF_TYPE__  ptrdiff_t;
+typedef decltype(nullptr) nullptr_t;
+#define NULL              nullptr
+
+typedef __INT8_TYPE__     int8_t     [[cl::aligned(1)]];
+typedef __UINT8_TYPE__    uint8_t    [[cl::aligned(1)]];
+typedef __INT16_TYPE__    int16_t    [[cl::aligned(2)]];
+typedef __UINT16_TYPE__   uint16_t   [[cl::aligned(2)]];
+typedef __INT32_TYPE__    int32_t    [[cl::aligned(4)]];
+typedef __UINT32_TYPE__   uint32_t   [[cl::aligned(4)]];
+typedef __INT64_TYPE__    int64_t    [[cl::aligned(8)]];
+typedef __UINT64_TYPE__   uint64_t   [[cl::aligned(8)]];
+
+#if   __INTPTR_WIDTH__ == 32
+typedef int32_t           intptr_t;
+typedef uint32_t          uintptr_t;
+#elif __INTPTR_WIDTH__ == 64
+typedef int64_t           intptr_t;
+typedef uint64_t          uintptr_t;
+#endif
+
+namespace cl
+{
+using ::intptr_t;
+using ::uintptr_t;
+using ::ptrdiff_t;
+using ::nullptr_t;
+using ::size_t;
+}
+
+typedef int8_t            cl_char;
+typedef uint8_t           cl_uchar;
+typedef int16_t           cl_short
+typedef uint16_t          cl_ushort;
+typedef int32_t           cl_int;
+typedef uint32_t          cl_uint;
+typedef int64_t           cl_long;
+typedef uint64_t          cl_ulong;
+
+#ifdef cl_khr_fp16
+typedef half              cl_half   [[aligned(2)]];
+#endif
+typedef float             cl_float  [[aligned(4)]];
+#ifdef cl_khr_fp64
+typedef double            cl_double [[aligned(8)]];
+#endif
+
+typedef implementation-defined bool2;
+typedef implementation-defined bool3;
+typedef implementation-defined bool4;
+typedef implementation-defined bool8;
+typedef implementation-defined bool16;
+typedef implementation-defined char2;
+typedef implementation-defined char3;
+typedef implementation-defined char4;
+typedef implementation-defined char8;
+typedef implementation-defined char16;
+typedef implementation-defined uchar2;
+typedef implementation-defined uchar3;
+typedef implementation-defined uchar4;
+typedef implementation-defined uchar8;
+typedef implementation-defined uchar16;
+typedef implementation-defined short2;
+typedef implementation-defined short3;
+typedef implementation-defined short4;
+typedef implementation-defined short8;
+typedef implementation-defined short16;
+typedef implementation-defined ushort2;
+typedef implementation-defined ushort3;
+typedef implementation-defined ushort4;
+typedef implementation-defined ushort8;
+typedef implementation-defined ushort16;
+typedef implementation-defined int2;
+typedef implementation-defined int3;
+typedef implementation-defined int4;
+typedef implementation-defined int8;
+typedef implementation-defined int16;
+typedef implementation-defined uint2;
+typedef implementation-defined uint3;
+typedef implementation-defined uint4;
+typedef implementation-defined uint8;
+typedef implementation-defined uint16;
+typedef implementation-defined long2;
+typedef implementation-defined long3;
+typedef implementation-defined long4;
+typedef implementation-defined long8;
+typedef implementation-defined long16;
+typedef implementation-defined ulong2;
+typedef implementation-defined ulong3;
+typedef implementation-defined ulong4;
+typedef implementation-defined ulong8;
+typedef implementation-defined ulong16;
+typedef implementation-defined float2;
+typedef implementation-defined float3;
+typedef implementation-defined float4;
+typedef implementation-defined float8;
+typedef implementation-defined float16;
+#ifdef cl_khr_fp16
+typedef implementation-defined half2;
+typedef implementation-defined half3;
+typedef implementation-defined half4;
+typedef implementation-defined half8;
+typedef implementation-defined half16;
+#endif
+#ifdef cl_khr_fp64
+typedef implementation-defined double2;
+typedef implementation-defined double3;
+typedef implementation-defined double4;
+typedef implementation-defined double8;
+typedef implementation-defined double16;
+#endif
+
+typedef bool2    cl_bool2;
+typedef bool3    cl_bool3;
+typedef bool4    cl_bool4;
+typedef bool8    cl_bool8;
+typedef bool16   cl_bool16;
+typedef char2    cl_char2;
+typedef char3    cl_char3;
+typedef char4    cl_char4;
+typedef char8    cl_char8;
+typedef char16   cl_char16;
+typedef uchar2   cl_uchar2;
+typedef uchar3   cl_uchar3;
+typedef uchar4   cl_uchar4;
+typedef uchar8   cl_uchar8;
+typedef uchar16  cl_uchar16;
+typedef short2   cl_short2;
+typedef short3   cl_short3;
+typedef short4   cl_short4;
+typedef short8   cl_short8;
+typedef short16  cl_short16;
+typedef ushort2  cl_ushort2;
+typedef ushort3  cl_ushort3;
+typedef ushort4  cl_ushort4;
+typedef ushort8  cl_ushort8;
+typedef ushort16 cl_ushort16;
+typedef int2     cl_int2;
+typedef int3     cl_int3;
+typedef int4     cl_int4;
+typedef int8     cl_int8;
+typedef int16    cl_int16;
+typedef uint2    cl_uint2;
+typedef uint3    cl_uint3;
+typedef uint4    cl_uint4;
+typedef uint8    cl_uint8;
+typedef uint16   cl_uint16;
+typedef long2    cl_long2;
+typedef long3    cl_long3;
+typedef long4    cl_long4;
+typedef long8    cl_long8;
+typedef long16   cl_long16;
+typedef ulong2   cl_ulong2;
+typedef ulong3   cl_ulong3;
+typedef ulong4   cl_ulong4;
+typedef ulong8   cl_ulong8;
+typedef ulong16  cl_ulong16;
+typedef float2   cl_float2;
+typedef float3   cl_float3;
+typedef float4   cl_float4;
+typedef float8   cl_float8;
+typedef float16  cl_float16;
+#ifdef cl_khr_fp16
+typedef half2    cl_half2;
+typedef half3    cl_half3;
+typedef half4    cl_half4;
+typedef half8    cl_half8;
+typedef half16   cl_half16;
+#endif
+#ifdef cl_khr_fp64
+typedef double2  cl_double2;
+typedef double3  cl_double3;
+typedef double4  cl_double4;
+typedef double8  cl_double8;
+typedef double16 cl_double16;
+#endif</code></pre>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="conversions-library">3.2. Conversions Library</h3>
+<div class="paragraph">
+<p>This section describes the explicit conversion cast functions.
+These functions provide a full set of type conversions between supported scalar and vector data types (see the <a href="#builtin-scalar-data-types"><em>Built-in Scalar Data Types</em></a> and the <a href="#builtin-vector-data-types"><em>Built-in Vector Data Types</em></a> sections) except for the following types: <code>size_t</code>, <code>ptrdiff_t</code>, <code>intptr_t</code>, <code>uintptr_t</code>, and <code>void</code>.</p>
+</div>
+<div class="paragraph">
+<p>The behavior of the conversion may be modified by one or two optional modifiers that specify saturation for out-of-range inputs and rounding behavior.</p>
+</div>
+<div class="paragraph">
+<p>The <code>convert_cast</code> type conversion operator that specifies a rounding mode and saturation is also provided.</p>
+</div>
+<div class="sect3">
+<h4 id="header-opencl_convert-synopsis">3.2.1. Header &lt;opencl_convert&gt; Synopsis</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+enum class rounding_mode { rte, rtz, rtp, rtn };
+enum class saturate { off, on };
+
+template &lt;class T, class U&gt;
+T convert_cast(U const&amp; arg);
+template &lt;class T&gt;
+T convert_cast(T const&amp; arg);
+
+template &lt;class T, rounding_mode rmode, class U&gt;
+T convert_cast(U const&amp; arg);
+template &lt;class T, rounding_mode rmode&gt;
+T convert_cast(T const&amp; arg);
+
+template &lt;class T, saturate smode, class U&gt;
+T convert_cast(U const&amp; arg);
+template &lt;class T, saturate smode&gt;
+T convert_cast(T const&amp; arg);
+
+template &lt;class T, rounding_mode rmode, saturate smode, class U&gt;
+T convert_cast(U const&amp; arg);
+template &lt;class T, rounding_mode rmode, saturate smode&gt;
+T convert_cast(T const&amp; arg);
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="data-types">3.2.2. Data Types</h4>
+<div class="paragraph">
+<p>Conversions are available for the following scalar types: <code>bool</code>, <code>char</code>, <code>uchar</code>, <code>short</code>, <code>ushort</code>, <code>int</code>, <code>uint</code>, <code>long</code>, <code>ulong</code>, <code>half</code> <a id="ftnref4"></a> <a href="#ftn4">[4]</a>, <code>float</code>, <code>double</code>, and built-in vector types derived therefrom.
+The operand and result type must have the same number of elements.
+The operand and result type may be the same type in which case the conversion has no effect on the type or value of an expression.</p>
+</div>
+<div class="paragraph">
+<p>Conversions between integer types follow the conversion rules specified in the C++14 specification except for out-of-range behavior and saturated conversions which are described in the <a href="#out-of-range-behavior-and-saturated-conversions"><em>Out-of-Range Behavior and Saturated Conversions</em></a> section below.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="rounding-modes">3.2.3. Rounding Modes</h4>
+<div class="paragraph">
+<p>Conversions to and from floating-point type shall conform to IEEE-754 rounding rules.
+Conversions may have an optional rounding mode specified as described in the table belows.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 9. Rounding Modes</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Rounding Mode</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>rte</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Round to nearest even</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>rtz</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Round toward zero</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>rtp</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Round toward positive infinity</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>rtn</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Round toward negative infinity</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>If a rounding mode is not specified, conversions to integer type use the <code>rtz</code> (round toward zero) rounding mode and conversions to floating-point type <a id="ftnref5"></a> <a href="#ftn5">[5]</a> uses the <code>rte</code> rounding mode.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="out-of-range-behavior-and-saturated-conversions">3.2.4. Out-of-Range Behavior and Saturated Conversions</h4>
+<div class="paragraph">
+<p>When the conversion operand is either greater than the greatest representable destination value or less than the least representable destination value, it is said to be out-of-range.
+The result of out-of-range conversion is determined by the conversion rules specified by the C++14 specification in <em>chapter 4.9</em>.
+When converting from a floating-point type to integer type, the behavior is implementation-defined.</p>
+</div>
+<div class="paragraph">
+<p>Conversions to integer type may opt to convert using the optional saturation mode.
+When in saturated mode, values that are outside the representable range shall clamp to the nearest representable value in the destination format.
+(NaN should be converted to 0).</p>
+</div>
+<div class="paragraph">
+<p>Conversions to floating-point type shall conform to IEEE-754 rounding rules. The <code>convert_cast</code> operator with a saturate argument may not be used for conversions to floating-point formats.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="examples-1">3.2.5. Examples</h4>
+<div class="sect4">
+<h5 id="example-1-1">Example 1</h5>
+<div class="paragraph">
+<p>Examples of casting between two vector types with saturation.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_convert&gt;
+using namespace cl;
+
+kernel void Foo() {
+short4 s;
+       // negative values clamped to 0
+       ushort4 u = convert_cast&lt;ushort4,saturate::on&gt;(s);
+
+// values &gt; CHAR_MAX converted to CHAR_MAX
+       // values &lt; CHAR_MIN converted to CHAR_MIN
+       char4 c = convert_cast&lt;char4, saturate::on&gt;(s);
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="example-2-1">Example 2</h5>
+<div class="paragraph">
+<p>Examples of casting from float to integer vector type with saturation and rounding mode specified.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_convert&gt;
+using namespace cl;
+
+kernel void Foo() {
+       float4  f;
+
+       // values implementation defined for
+       // f &gt; INT_MAX, f &lt; INT_MIN or NaN
+       int4    i1 = convert_cast&lt;int4&gt;(f);
+
+       // values &gt; INT_MAX clamp to INT_MAX, values &lt; INT_MIN clamp
+       // to INT_MIN. NaN should produce 0.
+       // The rtz rounding mode is used to produce the integer
+       // values.
+       int4    i2 = convert_cast&lt;int4,saturate::on&gt;(f);
+
+       // similar to convert_cast&lt;int4&gt;, except that floating-point
+       // values are rounded to the nearest integer instead of
+       // truncated
+       int4    i3 = convert_cast&lt;int4, rounding_mode::rte&gt;(f);
+
+       // similar to convert_cast&lt;int4, saturate::on&gt;, except that
+       // floating-point values are rounded to the nearest integer
+       // instead of truncated
+       int4    i4 = convert_cast&lt;int4, rounding_mode::rte,
+       saturate::on&gt;(f);
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="example-3">Example 3</h5>
+<div class="paragraph">
+<p>Examples of casting from integer to float vector type.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_convert&gt;
+using namespace cl;
+
+kernel void Foo() {
+       int4    i;
+
+       // convert ints to floats using the default rounding mode.
+       float4  f1 = convert_cast&lt;float4&gt;(i);
+
+       // convert ints to floats. integer values that cannot
+       // be exactly represented as floats should round up to the
+       // next representable float.
+       float4  f2 = convert_cast&lt;float4, rounding_mode::rtp&gt;(i);
+}</code></pre>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="reinterpreting-data-library">3.3. Reinterpreting Data Library</h3>
+<div class="paragraph">
+<p>It is frequently necessary to reinterpret bits in a data type as another data type in OpenCL C++.
+This is typically required when direct access to the bits in a floating-point type is needed, for example to mask off the sign bit or make use of the result of a vector relational operator on floating-point data.</p>
+</div>
+<div class="sect3">
+<h4 id="header-opencl_reinterpret-synopsis">3.3.1. Header &lt;opencl_reinterpret&gt; Synopsis</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+template &lt;class T, class U&gt;
+T as_type(U const&amp; arg);
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="reinterpreting-types">3.3.2. Reinterpreting Types</h4>
+<div class="paragraph">
+<p>All data types described in <a href="#device_builtin_scalar_data_types">Device built-in scalar data types</a> and <a href="#device_builtin_vector_data_types">Device built-in vector data types</a> tables (except <code>bool</code> and <code>void</code>) may be also reinterpreted as another data type of the same size using the <code>as_type()</code> <a id="ftnref6"></a> <a href="#ftn6">[6]</a> function for scalar and vector data types.
+When the operand and result type contain the same number of elements, the bits in the operand shall be returned directly without modification as the new type.
+The usual type promotion for function arguments shall not be performed.</p>
+</div>
+<div class="paragraph">
+<p>For example, <code>as_type&lt;float&gt;(0x3f800000)</code> returns <code>1.0f</code>, which is the value that the bit pattern <code>0x3f800000</code> has if viewed as an IEEE-754 single precision value.</p>
+</div>
+<div class="paragraph">
+<p>When the operand and result type contain a different number of elements, the result shall be implementation-defined except if the operand is a 4-component vector and the result is a 3-component vector.
+In this case, the bits in the operand shall be returned directly without modification as the new type.
+That is, a conforming implementation shall explicitly define a behavior, but two conforming implementations need not have the same behavior when the number of elements in the result and operand types does not match.
+The implementation may define the result to contain all, some or none of the original bits in whatever order it chooses.
+It is an error to use the <code>as_type&lt;T&gt;</code> operator to reinterpret data to a type of a different number of bytes.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="examples-2">3.3.3. Examples</h4>
+<div class="sect4">
+<h5 id="example-1-2">Example 1</h5>
+<div class="paragraph">
+<p>Examples of reinterpreting data types using <code>as_type&lt;&gt;</code> function.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_reinterpret&gt;
+using namespace cl;
+
+kernel void Foo() {
+       float f = 1.0f;
+       uint u = as_type&lt;uint&gt;(f);      // Legal. Contains:  0x3f800000
+
+       float4 f = float4(1.0f, 2.0f, 3.0f, 4.0f);
+       // Legal. Contains:
+       // int4(0x3f800000, 0x40000000, 0x40400000, 0x40800000)
+       int4 i = as_type&lt;int4&gt;(f);
+
+       int i;
+       // Legal. Result is implementation-defined.
+       short2 j = as_type&lt;short2&gt;(i);
+
+       int4 i;
+       // Legal. Result is implementation-defined.
+       short8 j = as_type&lt;short8&gt;(i);
+
+       float4 f;
+       // Error.  Result and operand have different sizes
+       double4 g = as_type&lt;double4&gt;(f);
+
+       float4 f;
+       // Legal. g.xyz will have same values as f.xyz.  g.w is
+       // undefined
+       float3 g = as_type&lt;float3&gt;(f);
+}</code></pre>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="address-spaces-library">3.4. Address Spaces Library</h3>
+<div class="paragraph">
+<p>Unlike OpenCL C, OpenCL C++ does not require the address space qualifiers to allocate storage from global, local and constant memory pool.
+The same functionality is provided using the storage and pointer classes.
+These new types are designed to avoid many programming issues and it is recommended to use them for the static and program scope variables even if it is not required.</p>
+</div>
+<div class="sect3">
+<h4 id="header-opencl_memory-synopsis">3.4.1. Header &lt;opencl_memory&gt; Synopsis</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+enum class mem_fence
+{
+    local,
+    global,
+    image
+};
+
+inline mem_fence operator ~(mem_fence flags);
+inline mem_fence operator &amp;(mem_fence LHS, mem_fence RHS);
+inline mem_fence operator |(mem_fence LHS, mem_fence RHS);
+inline mem_fence operator ^(mem_fence LHS, mem_fence RHS);
+
+// address space pointer classes
+template&lt;class T&gt;
+class global_ptr;
+
+template&lt;class T&gt;
+class local_ptr;
+
+template&lt;class T&gt;
+class private_ptr;
+
+template&lt;class T&gt;
+class constant_ptr;
+
+template&lt;class T&gt;
+using global = see 'global class' section;
+
+template&lt;class T&gt;
+using local = see 'local class' section;
+
+template&lt;class T&gt;
+using priv = see 'priv class' section;
+
+template&lt;class T&gt;
+using constant = see 'constant class' section;
+
+// address space query functions
+template&lt;class T&gt;
+mem_fence get_mem_fence(T *ptr);
+
+// address space cast functions
+template&lt;class T&gt;
+T dynamic_asptr_cast(T *ptr) noexcept;
+
+template &lt;class T, class U&gt;
+local_ptr&lt;T&gt; static_asptr_cast(local_ptr&lt;U&gt; const&amp; ptr) noexcept;
+template &lt;class T, class U&gt;
+global_ptr&lt;T&gt; static_asptr_cast(global_ptr&lt;U&gt; const&amp; ptr) noexcept;
+template &lt;class T, class U&gt;
+constant_ptr&lt;T&gt; static_asptr_cast(constant_ptr&lt;U&gt; const&amp; ptr) noexcept;
+template &lt;class T, class U&gt;
+private_ptr&lt;T&gt; static_asptr_cast(private_ptr&lt;U&gt; const&amp; ptr) noexcept;
+
+template &lt;class T, class U&gt;
+local_ptr&lt;T&gt; reinterpret_asptr_cast(local_ptr&lt;U&gt; const&amp; ptr) noexcept;
+template &lt;class T, class U&gt;
+global_ptr&lt;T&gt; reinterpret_asptr_cast(global_ptr&lt;U&gt; const&amp; ptr) noexcept;
+template &lt;class T, class U&gt;
+constant_ptr&lt;T&gt; reinterpret_asptr_cast(constant_ptr&lt;U&gt; const&amp; ptr) noexcept;
+template &lt;class T, class U&gt;
+private_ptr&lt;T&gt; reinterpret_asptr_cast(private_ptr&lt;U&gt; const&amp; ptr) noexcept;
+
+template &lt;class T&gt;
+T* addressof(T&amp; t) noexcept;
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="explicit-address-space-storage-classes">3.4.2. Explicit address space storage classes</h4>
+<div class="paragraph">
+<p>The explicit address space storage classes described in this section are designed to allocate memory in one of the named address spaces: global, local, constant or private.</p>
+</div>
+<div class="sect4">
+<h5 id="global-class">global class</h5>
+<div class="paragraph">
+<p>The variables declared using <code>global&lt;T&gt;</code> class refer to memory objects allocated from the global memory pool (see the <a href="#global"><em>Global Memory Pool</em></a> section).
+The global storage class can only be used to declare variables at program, function and class scope.
+The variables at function and class scope must be declared with <code>static</code> specifier.</p>
+</div>
+<div class="paragraph">
+<p>If <code>T</code> is a fundamental or an array type, the <code>global</code> class should meet the following requirements:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>no user provide default constructor</p>
+</li>
+<li>
+<p>default copy and move constructors</p>
+</li>
+<li>
+<p>default copy and move assignment operators</p>
+</li>
+<li>
+<p>address-of operators that return a generic <code>T</code> pointer (<code>T*</code>)</p>
+</li>
+<li>
+<p>conversion operators to a generic <code>T</code> lvalue reference type (<code>T&amp;</code>)</p>
+</li>
+<li>
+<p>assignment <code>const T&amp;</code> operator</p>
+</li>
+<li>
+<p><code>ptr()</code> methods that return a <code>global_ptr&lt;T&gt;</code> pointer class</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If <code>T</code> is a class type, the <code>global</code> class should provide the following interface:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>the same public interface as <code>T</code> type including constructors and assignment operators address-of operators that return a generic <code>T</code> pointer (<code>T*</code>)</p>
+</li>
+<li>
+<p>conversion operators to a generic <code>T</code> lvalue reference type (<code>T&amp;</code>)</p>
+</li>
+<li>
+<p><code>ptr()</code> methods that return a <code>global_ptr&lt;T&gt;</code> pointer class</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect4">
+<h5 id="local-class">local class</h5>
+<div class="paragraph">
+<p>The variables declared using <code>local&lt;T&gt;</code> class refer to memory objects allocated from the local memory pool (see the <a href="#local"><em>Local Memory Pool</em></a> section).
+The local storage class can only be used to declare variables at program, kernel and class scope.
+The variables at class scope must be declared with <code>static</code> specifier.</p>
+</div>
+<div class="paragraph">
+<p>If <code>T</code> is a fundamental or an array type, the <code>local</code> class should meet the following requirements:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>no user provide default constructor</p>
+</li>
+<li>
+<p>default copy and move constructors</p>
+</li>
+<li>
+<p>default copy and move assignment operators</p>
+</li>
+<li>
+<p>address-of operators that return a generic <code>T</code> pointer (<code>T*</code>)</p>
+</li>
+<li>
+<p>conversion operators to a generic <code>T</code> lvalue reference type (<code>T&amp;</code>)</p>
+</li>
+<li>
+<p>assignment <code>const T&amp;</code> operator</p>
+</li>
+<li>
+<p><code>ptr()</code> methods that return a <code>local_ptr&lt;T&gt;</code> pointer class</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If <code>T</code> is a class type, the <code>local</code> class should provide the following interface:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>the same public interface as <code>T</code> type including constructors
+and assignment operators</p>
+</li>
+<li>
+<p>address-of operators that return a generic <code>T</code> pointer (<code>T*</code>)</p>
+</li>
+<li>
+<p>conversion operators to a generic <code>T</code> lvalue reference type (<code>T&amp;</code>)</p>
+</li>
+<li>
+<p><code>ptr()</code> methods that return a <code>local_ptr&lt;T&gt;</code> pointer class</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect4">
+<h5 id="priv-class">priv class</h5>
+<div class="paragraph">
+<p>The variables declared using the <code>priv&lt;T&gt;</code> class refer to memory objects allocated from the private memory pool.</p>
+</div>
+<div class="paragraph">
+<p>The <code>priv</code> storage class cannot be used to declare variables in the program scope, with <code>static</code> specifier or <code>extern</code> specifier.</p>
+</div>
+<div class="paragraph">
+<p>If <code>T</code> is a fundamental or an array type, the <code>priv</code> class should meet the following requirements:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>no user provide default constructor</p>
+</li>
+<li>
+<p>default copy and move constructors</p>
+</li>
+<li>
+<p>default copy and move assignment operators</p>
+</li>
+<li>
+<p>address-of operators that return a generic <code>T</code> pointer (<code>T*</code>)</p>
+</li>
+<li>
+<p>conversion operators to a generic <code>T</code> lvalue reference type (<code>T&amp;</code>)</p>
+</li>
+<li>
+<p>assignment const <code>T&amp;</code> operator</p>
+</li>
+<li>
+<p><code>ptr()</code> methods that return a <code>private_ptr&lt;T&gt;</code> pointer class</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If <code>T</code> is a class type, the <code>priv</code> class should provide the following interface:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>the same public interface as <code>T</code> type including constructors and assignment operators</p>
+</li>
+<li>
+<p>address-of operators that return a generic <code>T</code> pointer (<code>T*</code>)</p>
+</li>
+<li>
+<p>conversion operators to a generic <code>T</code> lvalue reference type (<code>T&amp;</code>)</p>
+</li>
+<li>
+<p><code>ptr()</code> methods that return a <code>private_ptr&lt;T&gt;</code> pointer class</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect4">
+<h5 id="constant-class">constant class</h5>
+<div class="paragraph">
+<p>The variables declared using the <code>constant&lt;T&gt;</code> class refer to memory objects allocated from the global memory pool and which are accessed inside a kernel(s) as read-only variables.
+The constant storage class can only be used to declare variables at program, kernel and class scope.
+The variables at class scope must be declared with <code>static</code> specifier.</p>
+</div>
+<div class="paragraph">
+<p>The <code>T</code> type must meet the following requirements:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>T</code> must be constructible at compile time</p>
+</li>
+<li>
+<p><code>T</code> cannot have any user defined constructors, destructors, methods and operators</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If <code>T</code> is a fundamental, array or class type, the <code>constant</code> class should meet the following requirements:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>no user provide default constructor</p>
+</li>
+<li>
+<p>default copy and move constructors</p>
+</li>
+<li>
+<p>copy and move assignment operators deleted</p>
+</li>
+<li>
+<p>address-of operators that return a <code>constant_ptr&lt;T&gt;</code> pointer class</p>
+</li>
+<li>
+<p><code>ptr()</code> methods that return a <code>constant_ptr&lt;T&gt;</code> pointer class</p>
+</li>
+<li>
+<p>conversion operators to a constant <code>T</code> lvalue reference type (<code>add_constant_t&lt;T&gt;&amp;</code>)</p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="explicit-address-space-pointer-classes">3.4.3. Explicit address space pointer classes</h4>
+<div class="paragraph">
+<p>The explicit address space pointer classes are just like pointers: they can be converted to and from pointers with compatible address spaces, qualifiers and types.
+Assignment or casting between explicit pointer types of incompatible address spaces is illegal.</p>
+</div>
+<div class="paragraph">
+<p>All named address spaces are incompatible with all other address spaces, but local, global and private pointers can be converted to standard C++ pointers.</p>
+</div>
+<div class="sect4">
+<h5 id="global_ptr-class">global_ptr class</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+template &lt;class T&gt; class global_ptr
+{
+public:
+    //types:
+    typedef T element_type;
+    typedef ptrdiff_t difference_type;
+    typedef add_global_t&lt;T&gt;&amp; reference;
+    typedef const add_global_t&lt;T&gt;&amp; const_reference;
+    typedef add_global_t&lt;T&gt;* pointer;
+    typedef const add_global_t&lt;T&gt;* const_pointer;
+
+    //constructors:
+    constexpr global_ptr() noexcept;
+    explicit global_ptr(pointer p) noexcept;
+    global_ptr(const global_ptr &amp;r) noexcept;
+    global_ptr(global_ptr &amp;&amp;r) noexcept;
+    constexpr global_ptr(nullptr_t) noexcept;
+
+    //assignment:
+    global_ptr &amp;operator=(const global_ptr &amp;r) noexcept;
+    global_ptr &amp;operator=(global_ptr &amp;&amp;r) noexcept;
+    global_ptr &amp;operator=(pointer r) noexcept;
+    global_ptr &amp;operator=(nullptr_t) noexcept;
+
+    //observers:
+    add_lvalue_reference_t&lt;add_global_t&lt;T&gt;&gt; operator*() const noexcept;
+    pointer operator-&gt;() const noexcept;
+    pointer get() const noexcept;
+    explicit operator bool() const noexcept;
+
+    //modifiers:
+    pointer release() noexcept;
+    void reset(pointer p = pointer()) noexcept;
+    void swap(global_ptr&amp; r) noexcept;
+
+    global_ptr &amp;operator++() noexcept;
+    global_ptr operator++(int) noexcept;
+    global_ptr &amp;operator--() noexcept;
+    global_ptr operator--(int) noexcept;
+    global_ptr &amp;operator+=(difference_type r) noexcept;
+    global_ptr &amp;operator-=(difference_type r) noexcept;
+    global_ptr operator+(difference_type r) noexcept;
+    global_ptr operator-(difference_type r) noexcept;
+};
+
+template &lt;class T&gt; class global_ptr&lt;T[]&gt;
+{
+public:
+    //types:
+    typedef T element_type;
+    typedef ptrdiff_t difference_type;
+    typedef add_global_t&lt;T&gt;&amp; reference;
+    typedef const add_global_t&lt;T&gt;&amp; const_reference;
+    typedef add_global_t&lt;T&gt;* pointer;
+    typedef const add_global_t&lt;T&gt;* const_pointer;
+
+    //constructors:
+    constexpr global_ptr() noexcept;
+    explicit global_ptr(pointer p) noexcept;
+    global_ptr(const global_ptr &amp;r) noexcept;
+    global_ptr(global_ptr &amp;&amp;r) noexcept;
+    constexpr global_ptr(nullptr_t) noexcept;
+
+    //assignment:
+    global_ptr &amp;operator=(const global_ptr &amp;r) noexcept;
+    global_ptr &amp;operator=(global_ptr &amp;&amp;r) noexcept;
+    global_ptr &amp;operator=(pointer r) noexcept;
+    global_ptr &amp;operator=(nullptr_t) noexcept;
+
+    //observers:
+    reference operator[](size_t pos) const noexcept;
+    pointer get() const noexcept;
+    explicit operator bool() const noexcept;
+
+    //modifiers:
+    pointer release()noexcept;
+    void reset(pointer p) noexcept;
+    void reset(nullptr_t p = nullptr) noexcept;
+    void swap(global_ptr&amp; r) noexcept;
+
+    global_ptr &amp;operator++() noexcept;
+    global_ptr operator++(int) noexcept;
+    global_ptr &amp;operator--() noexcept;
+    global_ptr operator--(int) noexcept;
+    global_ptr &amp;operator+=(difference_type r) noexcept;
+    global_ptr &amp;operator-=(difference_type r) noexcept;
+    global_ptr operator+(difference_type r) noexcept;
+    global_ptr operator-(difference_type r) noexcept;
+};
+
+template&lt;class T, class U&gt;
+bool operator==(const global_ptr&lt;T&gt; &amp;a, const global_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator!=(const global_ptr&lt;T&gt; &amp;a, const global_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator&lt;(const global_ptr&lt;T&gt; &amp;a, const global_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator&gt;(const global_ptr&lt;T&gt; &amp;a, const global_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator&lt;=(const global_ptr&lt;T&gt; &amp;a, const global_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator&gt;=(const global_ptr&lt;T&gt; &amp;a, const global_ptr&lt;U&gt; &amp;b) noexcept;
+
+template&lt;class T&gt;
+bool operator==(const global_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+template&lt;class T&gt;
+bool operator==(nullptr_t, const global_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator!=(const global_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+template&lt;class T&gt;
+bool operator!=(nullptr_t, const global_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&lt;(const global_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+template&lt;class T&gt;
+bool operator&lt;(nullptr_t, const global_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&gt;(const global_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+template&lt;class T&gt;
+bool operator&gt;(nullptr_t, const global_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&lt;=(const global_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+template&lt;class T&gt;
+bool operator&lt;=(nullptr_t, const global_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&gt;=(const global_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+template&lt;class T&gt;
+bool operator&gt;=(nullptr_t, const global_ptr&lt;T&gt; &amp;x) noexcept;
+
+template&lt;class T&gt;
+void swap(global_ptr&lt;T&gt;&amp; a, global_ptr&lt;T&gt;&amp; b) noexcept;
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="local_ptr-class">local_ptr class</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+template &lt;class T&gt; class local_ptr
+{
+public:
+    struct size_type
+    {
+        explicit constexpr size_type(size_t size);
+        operator size_t();
+    };
+
+    //types:
+    typedef T element_type;
+    typedef ptrdiff_t difference_type;
+    typedef add_local_t&lt;T&gt;&amp; reference;
+    typedef const add_local_t&lt;T&gt;&amp; const_reference;
+    typedef add_local_t&lt;T&gt;* pointer;
+    typedef const add_local_t&lt;T&gt;* const_pointer;
+
+    //constructors:
+    constexpr local_ptr() noexcept;
+    explicit local_ptr(pointer p) noexcept;
+    local_ptr(const local_ptr &amp;r) noexcept;
+    local_ptr(local_ptr &amp;&amp;r) noexcept;
+    constexpr local_ptr(nullptr_t) noexcept;
+
+    //assignment:
+    local_ptr &amp;operator=(const local_ptr &amp;r) noexcept;
+    local_ptr &amp;operator=(local_ptr &amp;&amp;r) noexcept;
+    local_ptr &amp;operator=(pointer r) noexcept;
+    local_ptr &amp;operator=(nullptr_t) noexcept;
+
+    //observers:
+    add_lvalue_reference_t&lt;add_local_t&lt;T&gt;&gt; operator*() const noexcept;
+    pointer operator-&gt;() const noexcept;
+    pointer get() const noexcept;
+    explicit operator bool() const noexcept;
+
+    //modifiers:
+    pointer release() noexcept;
+    void reset(pointer p = pointer()) noexcept;
+    void swap(local_ptr&amp; r) noexcept;
+
+    local_ptr &amp;operator++() noexcept;
+    local_ptr operator++(int) noexcept;
+    local_ptr &amp;operator--() noexcept;
+    local_ptr operator--(int) noexcept;
+    local_ptr &amp;operator+=(difference_type r) noexcept;
+    local_ptr &amp;operator-=(difference_type r) noexcept;
+    local_ptr operator+(difference_type r) noexcept;
+    local_ptr operator-(difference_type r) noexcept;
+};
+
+template &lt;class T&gt; class local_ptr&lt;T[]&gt;
+{
+public:
+    //types:
+    typedef T element_type;
+    typedef ptrdiff_t difference_type;
+    typedef add_local_t&lt;T&gt;&amp; reference;
+    typedef const add_local_t&lt;T&gt;&amp; const_reference;
+    typedef add_local_t&lt;T&gt;* pointer;
+    typedef const add_local_t&lt;T&gt;* const_pointer;
+
+    //constructors:
+    constexpr local_ptr() noexcept;
+    explicit local_ptr(pointer p) noexcept;
+    local_ptr(const local_ptr &amp;r) noexcept;
+    local_ptr(local_ptr &amp;&amp;r) noexcept;
+    constexpr local_ptr(nullptr_t) noexcept;
+
+    //assignment:
+    local_ptr &amp;operator=(const local_ptr &amp;r) noexcept;
+    local_ptr &amp;operator=(local_ptr &amp;&amp;r) noexcept;
+    local_ptr &amp;operator=(pointer r) noexcept;
+    local_ptr &amp;operator=(nullptr_t) noexcept;
+
+    //observers:
+    reference operator[](size_t pos) const noexcept;
+    pointer get() const noexcept;
+    explicit operator bool() const noexcept;
+
+    //modifiers:
+    pointer release()noexcept;
+    void reset(pointer p) noexcept;
+    void reset(nullptr_t p = nullptr) noexcept;
+    void swap(local_ptr&amp; r) noexcept;
+
+    local_ptr &amp;operator++() noexcept;
+    local_ptr operator++(int) noexcept;
+    local_ptr &amp;operator--() noexcept;
+    local_ptr operator--(int) noexcept;
+    local_ptr &amp;operator+=(difference_type r) noexcept;
+    local_ptr &amp;operator-=(difference_type r) noexcept;
+    local_ptr operator+(difference_type r) noexcept;
+    local_ptr operator-(difference_type r) noexcept;
+};
+
+template&lt;class T, class U&gt;
+bool operator==(const local_ptr&lt;T&gt; &amp;a, const local_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator!=(const local_ptr&lt;T&gt; &amp;a, const local_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator&lt;(const local_ptr&lt;T&gt; &amp;a, const local_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator&gt;(const local_ptr&lt;T&gt; &amp;a, const local_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator&lt;=(const local_ptr&lt;T&gt; &amp;a, const local_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator&gt;=(const local_ptr&lt;T&gt; &amp;a, const local_ptr&lt;U&gt; &amp;b) noexcept;
+
+template&lt;class T&gt;
+bool operator==(const local_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+template&lt;class T&gt;
+bool operator==(nullptr_t, const local_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator!=(const local_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+template&lt;class T&gt;
+bool operator!=(nullptr_t, const local_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&lt;(const local_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+template&lt;class T&gt;
+bool operator&lt;(nullptr_t, const local_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&gt;(const local_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+template&lt;class T&gt;
+bool operator&gt;(nullptr_t, const local_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&lt;=(const local_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+template&lt;class T&gt;
+bool operator&lt;=(nullptr_t, const local_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&gt;=(const local_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+template&lt;class T&gt;
+bool operator&gt;=(nullptr_t, const local_ptr&lt;T&gt; &amp;x) noexcept;
+
+template&lt;class T&gt;
+void swap(local_ptr&lt;T&gt;&amp; a, local_ptr&lt;T&gt;&amp; b) noexcept;
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="private_ptr-class">private_ptr class</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+template &lt;class T&gt; class private_ptr
+{
+public:
+    //types:
+    typedef T element_type;
+    typedef ptrdiff_t difference_type;
+    typedef add_private_t&lt;T&gt;&amp; reference;
+    typedef const add_private_t&lt;T&gt;&amp; const_reference;
+    typedef add_private_t&lt;T&gt;* pointer;
+    typedef const add_private_t&lt;T&gt;* const_pointer;
+
+    //constructors:
+    constexpr private_ptr() noexcept;
+    explicit private_ptr(pointer p) noexcept;
+    private_ptr(const private_ptr &amp;r) noexcept;
+    private_ptr(private_ptr &amp;&amp;r) noexcept;
+    constexpr private_ptr(nullptr_t) noexcept;
+
+    //assignment:
+    private_ptr &amp;operator=(const private_ptr &amp;r) noexcept;
+    private_ptr &amp;operator=(private_ptr &amp;&amp;r) noexcept;
+    private_ptr &amp;operator=(pointer r) noexcept;
+    private_ptr &amp;operator=(nullptr_t) noexcept;
+
+    //observers:
+    add_lvalue_reference_t&lt;add_private_t&lt;T&gt;&gt; operator*() const noexcept;
+    pointer operator-&gt;() const noexcept;
+    pointer get() const noexcept;
+    explicit operator bool() const noexcept;
+
+    //modifiers:
+    pointer release() noexcept;
+    void reset(pointer p = pointer()) noexcept;
+    void swap(private_ptr&amp; r) noexcept;
+
+    private_ptr &amp;operator++() noexcept;
+    private_ptr operator++(int) noexcept;
+    private_ptr &amp;operator--() noexcept;
+    private_ptr operator--(int) noexcept;
+    private_ptr &amp;operator+=(difference_type r) noexcept;
+    private_ptr &amp;operator-=(difference_type r) noexcept;
+    private_ptr operator+(difference_type r) noexcept;
+    private_ptr operator-(difference_type r) noexcept;
+};
+
+template &lt;class T&gt; class private_ptr&lt;T[]&gt; {
+public:
+    //types:
+    typedef T element_type;
+    typedef ptrdiff_t difference_type;
+    typedef add_private_t&lt;T&gt;&amp; reference;
+    typedef const add_private_t&lt;T&gt;&amp; const_reference;
+    typedef add_private_t&lt;T&gt;* pointer;
+    typedef const add_private_t&lt;T&gt;* const_pointer;
+
+    //constructors:
+    constexpr private_ptr() noexcept;
+    explicit private_ptr(pointer p) noexcept;
+    private_ptr(const private_ptr &amp;r) noexcept;
+    private_ptr(private_ptr &amp;&amp;r) noexcept;
+    constexpr private_ptr(nullptr_t) noexcept;
+
+    //assignment:
+    private_ptr &amp;operator=(const private_ptr &amp;r) noexcept;
+    private_ptr &amp;operator=(private_ptr &amp;&amp;r) noexcept;
+    private_ptr &amp;operator=(pointer r) noexcept;
+    private_ptr &amp;operator=(nullptr_t) noexcept;
+
+    //observers:
+    reference operator[](size_t pos) const noexcept;
+    pointer get() const noexcept;
+    explicit operator bool() const noexcept;
+
+    //modifiers:
+    pointer release()noexcept;
+    void reset(pointer p) noexcept;
+    void reset(nullptr_t p = nullptr) noexcept;
+    void swap(private_ptr&amp; r) noexcept;
+
+    private_ptr &amp;operator++() noexcept;
+    private_ptr operator++(int) noexcept;
+    private_ptr &amp;operator--() noexcept;
+    private_ptr operator--(int) noexcept;
+    private_ptr &amp;operator+=(difference_type r) noexcept;
+    private_ptr &amp;operator-=(difference_type r) noexcept;
+    private_ptr operator+(difference_type r) noexcept;
+    private_ptr operator-(difference_type r) noexcept;
+};
+
+template&lt;class T, class U&gt;
+bool operator==(const private_ptr&lt;T&gt; &amp;a, const private_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator!=(const private_ptr&lt;T&gt; &amp;a, const private_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator&lt;(const private_ptr&lt;T&gt; &amp;a, const private_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator&gt;(const private_ptr&lt;T&gt; &amp;a, const private_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator&lt;=(const private_ptr&lt;T&gt; &amp;a, const private_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator&gt;=(const private_ptr&lt;T&gt; &amp;a, const private_ptr&lt;U&gt; &amp;b) noexcept;
+
+template&lt;class T&gt;
+bool operator==(const private_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+template&lt;class T&gt;
+bool operator==(nullptr_t, const private_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator!=(const private_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+template&lt;class T&gt;
+bool operator!=(nullptr_t, const private_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&lt;(const private_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+template&lt;class T&gt;
+bool operator&lt;(nullptr_t, const private_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&gt;(const private_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+template&lt;class T&gt;
+bool operator&gt;(nullptr_t, const private_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&lt;=(const private_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+template&lt;class T&gt;
+bool operator&lt;=(nullptr_t, const private_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&gt;=(const private_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+template&lt;class T&gt;
+bool operator&gt;=(nullptr_t, const private_ptr&lt;T&gt; &amp;x) noexcept;
+
+template&lt;class T&gt;
+void swap(private_ptr&lt;T&gt;&amp; a, private_ptr&lt;T&gt;&amp; b) noexcept;
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="constant_ptr-class">constant_ptr class</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+template &lt;class T&gt; class constant_ptr
+{
+public:
+    //types:
+    typedef T element_type;
+    typedef ptrdiff_t difference_type;
+    typedef add_constant_t&lt;T&gt;&amp; reference;
+    typedef const add_constant_t&lt;T&gt;&amp; const_reference;
+    typedef add_constant_t&lt;T&gt;* pointer;
+    typedef const add_constant_t&lt;T&gt;* const_pointer;
+
+    //constructors:
+    constexpr constant_ptr() noexcept;
+    explicit constant_ptr(pointer p) noexcept;
+    constant_ptr(const constant_ptr &amp;r) noexcept;
+    constant_ptr(constant_ptr &amp;&amp;r) noexcept;
+    constexpr constant_ptr(nullptr_t) noexcept;
+
+    //assignment:
+    constant_ptr &amp;operator=(const constant_ptr &amp;r) noexcept;
+    constant_ptr &amp;operator=(constant_ptr &amp;&amp;r) noexcept;
+    constant_ptr &amp;operator=(pointer r) noexcept;
+    constant_ptr &amp;operator=(nullptr_t) noexcept;
+
+    //observers:
+    add_lvalue_reference_t&lt;add_constant_t&lt;T&gt;&gt; operator*() const noexcept;
+    pointer operator-&gt;() const noexcept;
+    pointer get() const noexcept;
+    explicit operator bool() const noexcept;
+
+    //modifiers:
+    pointer release() noexcept;
+    void reset(pointer p = pointer()) noexcept;
+    void swap(constant_ptr&amp; r) noexcept;
+
+    constant_ptr &amp;operator++() noexcept;
+    constant_ptr operator++(int) noexcept;
+    constant_ptr &amp;operator--() noexcept;
+    constant_ptr operator--(int) noexcept;
+    constant_ptr &amp;operator+=(difference_type r) noexcept;
+    constant_ptr &amp;operator-=(difference_type r) noexcept;
+    constant_ptr operator+(difference_type r) noexcept;
+    constant_ptr operator-(difference_type r) noexcept;
+};
+
+template &lt;class T&gt; class constant_ptr&lt;T[]&gt;
+{
+public:
+    //types:
+    typedef T element_type;
+    typedef ptrdiff_t difference_type;
+    typedef add_constant_t&lt;T&gt;&amp; reference;
+    typedef const add_constant_t&lt;T&gt;&amp; const_reference;
+    typedef add_constant_t&lt;T&gt;* pointer;
+    typedef const add_constant_t&lt;T&gt;* const_pointer;
+
+    //constructors:
+    constexpr constant_ptr() noexcept;
+    explicit constant_ptr(pointer p) noexcept;
+    constant_ptr(const constant_ptr &amp;r) noexcept;
+    constant_ptr(constant_ptr &amp;&amp;r) noexcept;
+    constexpr constant_ptr(nullptr_t) noexcept;
+
+    //assignment:
+    constant_ptr &amp;operator=(const constant_ptr &amp;r) noexcept;
+    constant_ptr &amp;operator=(constant_ptr &amp;&amp;r) noexcept;
+    constant_ptr &amp;operator=(pointer r) noexcept;
+    constant_ptr &amp;operator=(nullptr_t) noexcept;
+
+    //observers:
+    reference operator[](size_t pos) const noexcept;
+    pointer get() const noexcept;
+    explicit operator bool() const noexcept;
+
+    //modifiers:
+    pointer release()noexcept;
+    void reset(pointer p) noexcept;
+    void reset(nullptr_t p = nullptr) noexcept;
+    void swap(constant_ptr&amp; r) noexcept;
+
+    constant_ptr &amp;operator++() noexcept;
+    constant_ptr operator++(int) noexcept;
+    constant_ptr &amp;operator--() noexcept;
+    constant_ptr operator--(int) noexcept;
+    constant_ptr &amp;operator+=(difference_type r) noexcept;
+    constant_ptr &amp;operator-=(difference_type r) noexcept;
+    constant_ptr operator+(difference_type r) noexcept;
+    constant_ptr operator-(difference_type r) noexcept;
+};
+
+template&lt;class T, class U&gt;
+bool operator==(const constant_ptr&lt;T&gt; &amp;a, const constant_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator!=(const constant_ptr&lt;T&gt; &amp;a, const constant_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator&lt;(const constant_ptr&lt;T&gt; &amp;a, const constant_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator&gt;(const constant_ptr&lt;T&gt; &amp;a, const constant_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator&lt;=(const constant_ptr&lt;T&gt; &amp;a, const constant_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator&gt;=(const constant_ptr&lt;T&gt; &amp;a, const constant_ptr&lt;U&gt; &amp;b) noexcept;
+
+template&lt;class T&gt;
+bool operator==(const constant_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+template&lt;class T&gt;
+bool operator==(nullptr_t, const constant_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator!=(const constant_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+template&lt;class T&gt;
+bool operator!=(nullptr_t, const constant_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&lt;(const constant_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+template&lt;class T&gt;
+bool operator&lt;(nullptr_t, const constant_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&gt;(const constant_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+template&lt;class T&gt;
+bool operator&gt;(nullptr_t, const constant_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&lt;=(const constant_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+template&lt;class T&gt;
+bool operator&lt;=(nullptr_t, const constant_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&gt;=(const constant_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+template&lt;class T&gt;
+bool operator&gt;=(nullptr_t, const constant_ptr&lt;T&gt; &amp;x) noexcept;
+
+template&lt;class T&gt;
+void swap(constant_ptr&lt;T&gt;&amp; a, constant_ptr&lt;T&gt;&amp; b) noexcept;
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="constructors">Constructors</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>constexpr global_ptr() noexcept;
+constexpr local_ptr() noexcept;
+constexpr private_ptr() noexcept;
+constexpr constant_ptr() noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Constructs an object which points to nothing.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>explicit global_ptr(pointer p) noexcept;
+explicit local_ptr(pointer p) noexcept;
+explicit private_ptr(pointer p) noexcept;
+explicit constant_ptr(pointer p) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Constructs an object which points to <code>p</code>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>global_ptr(const global_ptr &amp;) noexcept;
+local_ptr(const local_ptr &amp;) noexcept;
+private_ptr(const private_ptr &amp;) noexcept;
+constant_ptr(const constant_ptr &amp;) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Copy constructor.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>global_ptr(global_ptr &amp;&amp;r) noexcept;
+local_ptr(local_ptr &amp;&amp;r) noexcept;
+private_ptr(private_ptr &amp;&amp;r) noexcept;
+constant_ptr(constant_ptr &amp;&amp;r) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Move constructor.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>constexpr global_ptr(nullptr_t) noexcept;
+constexpr local_ptr(nullptr_t) noexcept;
+constexpr private_ptr(nullptr_t) noexcept;
+constexpr constant_ptr(nullptr_t) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Constructs an object initialized with <code>nullptr</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="assignment-operators">Assignment operators</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>global_ptr &amp;operator=(const global_ptr &amp;r) noexcept;
+local_ptr &amp;operator=(const local_ptr &amp;r) noexcept;
+private_ptr &amp;operator=(const private_ptr &amp;r) noexcept;
+constant_ptr &amp;operator=(const constant_ptr &amp;r) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Copy assignment operator</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>global_ptr &amp;operator=(global_ptr &amp;&amp;r) noexcept;
+local_ptr &amp;operator=(local_ptr &amp;&amp;r) noexcept;
+private_ptr &amp;operator=(private_ptr &amp;&amp;r) noexcept;
+constant_ptr &amp;operator=(constant_ptr &amp;&amp;r) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Move assignment operator</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>global_ptr &amp;operator=(pointer r) noexcept;
+local_ptr &amp;operator=(pointer r) noexcept;
+private_ptr &amp;operator=(pointer r) noexcept;
+constant_ptr &amp;operator=(pointer r) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Assigns <code>r</code> pointer to the stored pointer</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>global_ptr &amp;operator=(nullptr_t) noexcept;
+local_ptr &amp;operator=(nullptr_t) noexcept;
+private_ptr &amp;operator=(nullptr_t) noexcept;
+constant_ptr &amp;operator=(nullptr_t) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Assigns <code>nullptr</code> to the stored pointer</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="observers">Observers</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>add_lvalue_reference_t&lt;add_global_t&lt;T&gt;&gt; operator*() const noexcept;
+add_lvalue_reference_t&lt;add_local_t&lt;T&gt;&gt; operator*() const noexcept;
+add_lvalue_reference_t&lt;add_private_t&lt;T&gt;&gt; operator*() const noexcept;
+add_lvalue_reference_t&lt;add_constant_t&lt;T&gt;&gt; operator*() const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>*get()</code>. It is only defined in single object version of the explicit address space pointer class.
+The result of this operator is undefined if <code>get() == nullptr</code>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>pointer operator-&gt;() const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>get()</code>. It is only defined in single object version of the explicit address space pointer class.
+The result of this operator is undefined if <code>get() == nullptr</code>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>reference operator[](size_t pos) const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>get()[pos]</code>. The subscript operator is only defined in specialized <code>global_ptr&lt;T[]&gt;</code>, <code>local_ptr&lt;T[]&gt;</code>, <code>private_ptr&lt;T[]&gt;</code> and <code>constant_ptr&lt;T[]&gt;</code> version for array types.
+The result of this operator is undefined if <code>pos &gt;=</code> the number of elements in the array to which the stored pointer points.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>pointer get() const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the stored pointer.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>explicit operator bool() const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>get() != nullptr</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="modifiers">Modifiers</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>pointer release() noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Assigns <code>nullptr</code> to the stored pointer and returns the value <code>get()</code> had at the start of the call to release.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>void reset(pointer p = pointer()) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Assigned <code>p</code> to the stored pointer.
+It is only defined in single object version of the explicit address space pointer class</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>void reset(pointer p) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Assigned <code>p</code> to the stored pointer.
+It is only defined in specialized <code>global_ptr&lt;T[]&gt;</code>, <code>local_ptr&lt;T[]&gt;</code>, <code>private_ptr&lt;T[]&gt;</code> and <code>constant_ptr&lt;T[]&gt;</code> version for array types.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>void reset(nullptr_t p = nullptr) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Equivalent to <code>reset(pointer())</code>.
+It is only defined in specialized <code>global_ptr&lt;T[]&gt;</code>, <code>local_ptr&lt;T[]&gt;</code>, <code>private_ptr&lt;T[]&gt;</code> and <code>constant_ptr&lt;T[]&gt;</code> version for array types.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>void swap(global_ptr&amp; r) noexcept;
+void swap(local_ptr&amp; r) noexcept;
+void swap(private_ptr&amp; r) noexcept;
+void swap(constant_ptr&amp; r) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Invokes swap on the stored pointers.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>global_ptr &amp;operator++() noexcept;
+local_ptr &amp;operator++() noexcept;
+private_ptr &amp;operator++() noexcept;
+constant_ptr &amp;operator++() noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Prefix increment operator.
+Increments the stored pointer by one.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>global_ptr operator++(int) noexcept;
+local_ptr operator++(int) noexcept;
+private_ptr operator++(int) noexcept;
+constant_ptr operator++(int) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Postfix increment operator.
+Increments the stored pointer by one.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>global_ptr &amp;operator--() noexcept;
+local_ptr &amp;operator--() noexcept;
+private_ptr &amp;operator--() noexcept;
+constant_ptr &amp;operator--() noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Prefix decrement operator.
+Decrements the stored pointer by one.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>global_ptr operator--(int) noexcept;
+local_ptr operator--(int) noexcept;
+private_ptr operator--(int) noexcept;
+constant_ptr operator--(int) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Postfix decrement operator.
+Decrements the stored pointer by one.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>global_ptr &amp;operator+=(difference_type r) noexcept;
+local_ptr &amp;operator+=(difference_type r) noexcept;
+private_ptr &amp;operator+=(difference_type r) noexcept;
+constant_ptr &amp;operator+=(difference_type r) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Adds <code>r</code> to the stored pointer and returns <code>*this</code>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>global_ptr &amp;operator-=(difference_type r) noexcept;
+local_ptr &amp;operator-=(difference_type r) noexcept;
+private_ptr &amp;operator-=(difference_type r) noexcept;
+constant_ptr &amp;operator-=(difference_type r) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Subtracts <code>r</code> to the stored pointer and returns <code>*this</code>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>global_ptr operator+(difference_type r) noexcept;
+local_ptr operator+(difference_type r) noexcept;
+private_ptr operator+(difference_type r) noexcept;
+constant_ptr operator+(difference_type r) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Adds <code>r</code> to the stored pointer and returns the value <code>*this</code> has at the start of <code>operator+</code>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>global_ptr operator-(difference_type r) noexcept;
+local_ptr operator-(difference_type r) noexcept;
+private_ptr operator-(difference_type r) noexcept;
+constant_ptr operator-(difference_type r) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Subtracts <code>r</code> to the stored pointer and returns the value <code>*this</code> has at the start of <code>operator-</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="non-member-functions">Non-member functions</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template&lt;class T, class U&gt;
+bool operator==(const global_ptr&lt;T&gt; &amp;a, const global_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator==(const local_ptr&lt;T&gt; &amp;a, const local_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator==(const private_ptr&lt;T&gt; &amp;a, const private_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator==(const constant_ptr&lt;T&gt; &amp;a, const constant_ptr&lt;U&gt; &amp;b) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Comparison <code>operator==</code> for the explicit address space pointer classes.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template&lt;class T&gt;
+bool operator==(nullptr_t, const global_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator==(const global_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+
+template&lt;class T&gt;
+bool operator==(nullptr_t, const local_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator==(const local_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+
+template&lt;class T&gt;
+bool operator==(nullptr_t, const private_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator==(const private_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+
+template&lt;class T&gt;
+bool operator==(nullptr_t, const constant_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator==(const constant_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Comparison <code>operator==</code> for the explicit address space pointer classes with a <code>nullptr_t</code>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template&lt;class T, class U&gt;
+bool operator!=(const global_ptr&lt;T&gt; &amp;a, const global_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator!=(const local_ptr&lt;T&gt; &amp;a, const local_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator!=(const private_ptr&lt;T&gt; &amp;a, const private_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator!=(const constant_ptr&lt;T&gt; &amp;a, const constant_ptr&lt;U&gt; &amp;b) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Comparison <code>operator!=</code> for the explicit address space pointer classes.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template&lt;class T&gt;
+bool operator!=(nullptr_t, const global_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator!=(const global_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+
+template&lt;class T&gt;
+bool operator!=(nullptr_t, const local_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator!=(const local_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+
+template&lt;class T&gt;
+bool operator!=(nullptr_t, const private_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator!=(const private_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+
+template&lt;class T&gt;
+bool operator!=(nullptr_t, const constant_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator!=(const constant_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Comparison <code>operator!=</code> for the explicit address space pointer classes with a <code>nullptr_t</code>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template&lt;class T, class U&gt;
+bool operator&lt;(const global_ptr&lt;T&gt; &amp;a, const global_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator&lt;(const local_ptr&lt;T&gt; &amp;a, const local_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator&lt;(const private_ptr&lt;T&gt; &amp;a, const private_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator&lt;(const constant_ptr&lt;T&gt; &amp;a, const constant_ptr&lt;U&gt; &amp;b) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Comparison <code>operator&lt;</code> for the explicit address space pointer classes.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template&lt;class T&gt;
+bool operator&lt;(nullptr_t, const global_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&lt;(const global_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+
+template&lt;class T&gt;
+bool operator&lt;(nullptr_t, const local_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&lt;(const local_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+
+template&lt;class T&gt;
+bool operator&lt;(nullptr_t, const private_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&lt;(const private_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+
+template&lt;class T&gt;
+bool operator&lt;(nullptr_t, const constant_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&lt;(const constant_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Comparison <code>operator&lt;</code> for the explicit address space pointer classes with a <code>nullptr_t</code>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template&lt;class T, class U&gt;
+bool operator&gt;(const global_ptr&lt;T&gt; &amp;a, const global_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator&gt;(const local_ptr&lt;T&gt; &amp;a, const local_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator&gt;(const private_ptr&lt;T&gt; &amp;a, const private_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator&gt;(const constant_ptr&lt;T&gt; &amp;a, const constant_ptr&lt;U&gt; &amp;b) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Comparison <code>operator&gt;</code> for the explicit address space pointer classes.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template&lt;class T&gt;
+bool operator&gt;(nullptr_t, const global_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&gt;(const global_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+
+template&lt;class T&gt;
+bool operator&gt;(nullptr_t, const local_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&gt;(const local_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+
+template&lt;class T&gt;
+bool operator&gt;(nullptr_t, const private_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&gt;(const private_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+
+template&lt;class T&gt;
+bool operator&gt;(nullptr_t, const constant_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&gt;(const constant_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Comparison <code>operator&gt;</code> for the explicit address space pointer classes with a <code>nullptr_t</code>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template&lt;class T, class U&gt;
+bool operator&lt;=(const global_ptr&lt;T&gt; &amp;a, const global_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator&lt;=(const local_ptr&lt;T&gt; &amp;a, const local_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator&lt;=(const private_ptr&lt;T&gt; &amp;a, const private_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator&lt;=(const constant_ptr&lt;T&gt; &amp;a, const constant_ptr&lt;U&gt; &amp;b) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Comparison <code>operator&lt;=</code> for the explicit address space pointer classes.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template&lt;class T&gt;
+bool operator&lt;=(nullptr_t, const global_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&lt;=(const global_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+
+template&lt;class T&gt;
+bool operator&lt;=(nullptr_t, const local_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&lt;=(const local_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+
+template&lt;class T&gt;
+bool operator&lt;=(nullptr_t, const private_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&lt;=(const private_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+
+template&lt;class T&gt;
+bool operator&lt;=(nullptr_t, const constant_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&lt;=(const constant_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Comparison <code>operator&lt;=</code> for the explicit address space pointer classes with a <code>nullptr_t</code>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template&lt;class T, class U&gt;
+bool operator&gt;=(const global_ptr&lt;T&gt; &amp;a, const global_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator&gt;=(const local_ptr&lt;T&gt; &amp;a, const local_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator&gt;=(const private_ptr&lt;T&gt; &amp;a, const private_ptr&lt;U&gt; &amp;b) noexcept;
+template&lt;class T, class U&gt;
+bool operator&gt;=(const constant_ptr&lt;T&gt; &amp;a, const constant_ptr&lt;U&gt; &amp;b) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Comparison <code>operator&gt;=</code> for the explicit address space pointer classes.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template&lt;class T&gt;
+bool operator&gt;=(nullptr_t, const global_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&gt;=(const global_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+
+template&lt;class T&gt;
+bool operator&gt;=(nullptr_t, const local_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&gt;=(const local_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+
+template&lt;class T&gt;
+bool operator&gt;=(nullptr_t, const private_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&gt;=(const private_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;
+
+template&lt;class T&gt;
+bool operator&gt;=(nullptr_t, const constant_ptr&lt;T&gt; &amp;x) noexcept;
+template&lt;class T&gt;
+bool operator&gt;=(const constant_ptr&lt;T&gt; &amp;x, nullptr_t) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Comparison <code>operator&gt;=</code> for the explicit address space pointer classes with a <code>nullptr_t</code>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template&lt;class T&gt;
+void swap(global_ptr&lt;T&gt;&amp; a, global_ptr&lt;T&gt;&amp; b) noexcept;
+template&lt;class T&gt;
+void swap(local_ptr&lt;T&gt;&amp; a, local_ptr&lt;T&gt;&amp; b) noexcept;
+template&lt;class T&gt;
+void swap(private_ptr&lt;T&gt;&amp; a, private_ptr&lt;T&gt;&amp; b) noexcept;
+template&lt;class T&gt;
+void swap(constant_ptr&lt;T&gt;&amp; a, constant_ptr&lt;T&gt;&amp; b) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Calls <code>a.swap(b)</code></p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="other-functions">3.4.4. Other functions</h4>
+<div class="paragraph">
+<p>The OpenCL C++ address space library implements the address space query and cast functions.
+The cast function that allows to explicitly convert from a pointer in the generic address space to a pointer in the global, local and private address space.</p>
+</div>
+<div class="sect4">
+<h5 id="get_mem_fence">get_mem_fence</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template &lt;class T&gt;
+mem_fence get_mem_fence (T *ptr);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the <code>mem_fence</code> value for <code>ptr</code>.
+<code>ptr</code> must be the generic pointer and it cannot be the explicit address space pointer (<code>global_ptr&lt;&gt;</code>, <code>local_ptr&lt;&gt;</code>, <code>private_ptr&lt;&gt;</code> and <code>constant_ptr&lt;&gt;</code>) or pointer to address space storage class (<code>global&lt;&gt;*</code>, <code>local&lt;&gt;*</code>, <code>priv&lt;&gt;*</code> and <code>constant&lt;&gt;*</code>).</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="dynamic_asptr_cast">dynamic_asptr_cast</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template&lt;class T, class U&gt;
+T dynamic_asptr_cast(U *ptr);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns a pointer that points to a region in the address space pointer class specified in <code>T</code> if <code>dynamic_asptr_cast</code> can cast <code>ptr</code> to the specified address space.
+Otherwise it returns <code>nullptr</code>.
+Only <code>global_ptr&lt;U&gt;</code>, <code>local_ptr&lt;U&gt;</code> and <code>private_ptr&lt;U&gt;</code> are valid <code>T</code> template arguments.
+<code>ptr</code> must be the generic pointer and it cannot be the explicit address space pointer (<code>global_ptr&lt;&gt;</code>, <code>local_ptr&lt;&gt;</code>, <code>private_ptr&lt;&gt;</code> and <code>constant_ptr&lt;&gt;</code>) or pointer to address space storage class (<code>global&lt;&gt;*</code>, <code>local&lt;&gt;*</code>, <code>priv&lt;&gt;*</code> and <code>constant&lt;&gt;*</code>).</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="static_asptr_cast">static_asptr_cast</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template &lt;class T, class U&gt;
+local_ptr&lt;T&gt; static_asptr_cast(local_ptr&lt;U&gt; const&amp; ptr) noexcept;
+template &lt;class T, class U&gt;
+global_ptr&lt;T&gt; static_asptr_cast(global_ptr&lt;U&gt; const&amp; ptr) noexcept;
+template &lt;class T, class U&gt;
+constant_ptr&lt;T&gt; static_asptr_cast(constant_ptr&lt;U&gt; const&amp; ptr) noexcept;
+template &lt;class T, class U&gt;
+private_ptr&lt;T&gt; static_asptr_cast(private_ptr&lt;U&gt; const&amp; ptr) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The expression <code>static_cast(r.get())</code> shall be well formed.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="reinterpret_asptr_cast">reinterpret_asptr_cast</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template &lt;class T, class U&gt;
+local_ptr&lt;T&gt; reinterpret_asptr_cast(local_ptr&lt;U&gt; const&amp; ptr) noexcept;
+template &lt;class T, class U&gt;
+global_ptr&lt;T&gt; reinterpret_asptr_cast(global_ptr&lt;U&gt; const&amp; ptr) noexcept;
+template &lt;class T, class U&gt;
+constant_ptr&lt;T&gt; reinterpret_asptr_cast(constant_ptr&lt;U&gt; const&amp; ptr) noexcept;
+template &lt;class T, class U&gt;
+private_ptr&lt;T&gt; reinterpret_asptr_cast(private_ptr&lt;U&gt; const&amp; ptr) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The expression <code>reinterpret_cast(r.get())</code> shall be well formed.</p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="restrictions-2">3.4.5. Restrictions</h4>
+<div class="paragraph">
+<p>1.
+The objects allocated using <code>global</code>, <code>local</code> and <code>constant</code> storage classes can be passed to a function only by reference or pointer</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_memory&gt;
+#include &lt;opencl_array&gt;
+using namespace cl;
+
+kernel void foo(global&lt;array&lt;int, 5&gt;&gt; val) {
+    // Error: variable in the global
+    //        address space passed by value
+    //...
+}
+
+kernel void bar(global&lt;array&lt;int, 5&gt;&gt; &amp;val) { // OK
+    //...
+}
+
+kernel void foobar(global_ptr&lt;int&gt; val) { // OK
+    //...
+}
+
+kernel void barfoo(global_ptr&lt;int[]&gt; val) { // OK
+    //...
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>2.
+The <code>global</code>, <code>local</code>, <code>priv</code> and <code>constant</code> storage classes cannot be used as a return type of function</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_memory&gt;
+#include &lt;opencl_array&gt;
+using namespace cl;
+
+global&lt;array&lt;int, 5&gt;&gt; programVar;
+
+global&lt;array&lt;int, 5&gt;&gt; foo() { // error: variable in the global
+                             // address space returned by value
+    return programVar;
+}
+
+global&lt;array&lt;int, 5&gt;&gt; &amp;bar() { // OK
+    return programVar;
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>3.
+The <code>global</code>, <code>local</code> and <code>constant</code> storage classes cannot be used to declare class members unless <code>static</code> keyword is used</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_memory&gt;
+#include &lt;opencl_array&gt;
+using namespace cl;
+
+struct Foo {
+    global&lt;int&gt; a; // error: class members cannot be qualified
+                   // with address space
+    local&lt;array&lt;int, 5&gt;&gt; b; // error: class members cannot be
+                           // qualified with address space
+
+    static global&lt;int&gt; c; // OK
+    static local&lt;array&lt;int, 5&gt;&gt; d; // OK
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>4.
+The <code>global</code> storage class cannot be used to declare variables at function scope unless <code>static</code> keyword is used</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_memory&gt;
+using namespace cl;
+
+kernel void foo() {
+    global&lt;int&gt; b; // error
+    static global&lt;int&gt; b; // OK
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>5.
+The <code>local</code> variables can be declared only at kernel function scope, program scope and with <code>static</code> keyword</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_memory&gt;
+#include &lt;opencl_array&gt;
+using namespace cl;
+
+// An array of 5 ints allocated in
+// local address space.
+local&lt;array&lt;int, 5&gt;&gt; a = { 10 }; // OK: program scope local
+                                 // variable
+
+kernel void foo() {
+    // A single int allocated in
+    // local address space
+    local&lt;int&gt; b{1}; // OK
+    static local&lt;int&gt; d{1}; // OK
+
+    if(get_local_id(0) == 0) {
+        // example of variable in local address space
+        // but not declared at __kernel function scope.
+        local&lt;int&gt; c{2}; // not allowed
+  }
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>6.
+The objects allocated using <code>global</code> storage class must be initialized with the constant expression arguments</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_memory&gt;
+#include &lt;opencl_work_item&gt;
+using namespace cl;
+
+kernel void foo() {
+    int a = get_local_id(0);
+    static global&lt;int&gt; b{a}; // undefined behavior
+    static global&lt;int&gt; c{0}; // OK
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>7.
+The constructors of objects allocated using <code>constant</code> storage class must be constant expression</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_memory&gt;
+#include &lt;opencl_work_item&gt;
+using namespace cl;
+
+constant&lt;int&gt; b{0}; // OK
+
+kernel void foo() {
+    int a = get_local_id(0);
+    static constant&lt;int&gt; b{a}; // undefined behavior
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>8.
+Constant variables must be initialized</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_memory&gt;
+using namespace cl;
+
+constant&lt;int&gt; a{0}; // OK
+constant&lt;int&gt; b; // error: constant variable must be initialized
+
+kernel void foo() {
+    static constant&lt;int&gt; c{0}; // OK
+    static constant&lt;int&gt; d; // error: constant variable must be initialized
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>9.
+The <code>priv</code> storage class cannot be used to declare variables in the program scope or with <code>static</code> specifier.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_memory&gt;
+using namespace cl;
+
+priv&lt;int&gt; a{0}; // error: priv variable in program scope
+
+kernel void foo() {
+    static priv&lt;int&gt; c{0}; // error: priv variable with static specifier
+    priv&lt;int&gt; d; // OK
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>10.
+<code>T</code> type used in <code>constant</code> storage class cannot have any user defined constructors, destructors, operators and methods</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_memory&gt;
+using namespace cl;
+
+struct bar {
+    int get() { return 10; }
+};
+
+kernel void foo() {
+    constant&lt;bar&gt; a;
+    int b = a.get() // undefined behavior
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>11.
+<code>T</code> type used in <code>global</code>, <code>local</code>, <code>priv</code> and <code>constant</code> storage class cannot be sealed class</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_memory&gt;
+using namespace cl;
+
+struct bar final { };
+
+kernel void foo() {
+    local&lt;bar&gt; a; // error: bar is marked as final
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>12.
+Using work-group barriers or relying on a specific work-item to be executed in constructors and destructors of global and local objects can result in undefined behavior</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_memory&gt;
+#include &lt;opencl_synchronization&gt;
+using namespace cl;
+
+struct Foo {
+    Foo() {
+        work_group_barrier(mem_fence::local); // not allowed
+    }
+
+    ~Foo() {
+        if(get_local_id(0) != 5) { // not allowed
+            while(1) {}
+        }
+    }
+};
+
+kernel void bar() {
+    local&lt;Foo&gt; a;
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>13.
+All local (address-space) variable declarations in kernel-scope shall be declared before any explicit return statement.
+Declaring local variable after return statement may cause undefined behavior.
+Implementation is encouraged to generate at least a warning in such cases.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="examples-3">3.4.6. Examples</h4>
+<div class="sect4">
+<h5 id="example-1-3">Example 1</h5>
+<div class="paragraph">
+<p>Example of passing an explicit address space storage object to a kernel.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_memory&gt;
+using namespace cl;
+
+kernel void foo(global&lt;int&gt; *arg) {
+    //...
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="example-2-2">Example 2</h5>
+<div class="paragraph">
+<p>Example of passing an explicit address space pointer object to a kernel.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_memory&gt;
+using namespace cl;
+
+kernel void foo(global_ptr&lt;int&gt; arg) {
+    //...
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="example-3-1">Example 3</h5>
+<div class="paragraph">
+<p>Example of casting a generic pointer to an explicit address space pointer object.
+This is the runtime operation and the <code>dynamic_asptr_cast</code> can fail.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_memory&gt;
+using namespace cl;
+
+kernel void foo(global_ptr&lt;int&gt; arg) {
+    int *ptr = arg;
+    auto globalPtr = dynamic_asptr_cast&lt;global_ptr&lt;int&gt;&gt;(ptr);
+    if(globalPtr)
+    {
+        //...
+    }
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="example-4">Example 4</h5>
+<div class="paragraph">
+<p>Example of using an array with an explicit address space storage class.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_memory&gt;
+#include &lt;opencl_array&gt;
+#include &lt;opencl_work_item&gt;
+using namespace cl;
+
+kernel void foo() {
+    local&lt;array&lt;int, 2&gt;&gt; localArray;
+    if(get_local_id(0) == 0) {
+        for(auto it = localArray.begin(); it != localArray.end(); ++it)
+            *it = 0;
+    }
+    work_group_barrier(mem_fence::local);
+    localArray[0] += 1;
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="example-5">Example 5</h5>
+<div class="paragraph">
+<p>Example of using a fundamental type with an explicit address space storage class.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_memory&gt;
+#include &lt;opencl_work_item&gt;
+using namespace cl;
+
+kernel void foo() {
+    local&lt;int&gt; a;
+    if(get_local_id(0) == 0)
+        a = 1;
+
+    work_group_barrier(mem_fence::local);
+    if(get_local_id(0) == 1)
+        a += 1;
+}</code></pre>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="specialization-constants-library">3.5. Specialization Constants Library</h3>
+<div class="paragraph">
+<p>The specialization constants are objects that will not have known constant values until after initial generation of a SPIR-V module.
+Such objects are called specialization constants.
+Application might provide values for the specialization constants that will be used when SPIR-V program is built.</p>
+</div>
+<div class="sect3">
+<h4 id="header-opencl_spec_constant-synopsis">3.5.1. Header &lt;opencl_spec_constant&gt; Synopsis</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+template&lt;class T, unsigned int ID&gt;
+struct spec_constant
+{
+    spec_constant() = delete;
+    spec_constant(const spec_constant &amp;) = default;
+    spec_constant(spec_constant&amp;&amp;) = default;
+
+    constexpr spec_constant(const T&amp; value);
+
+    spec_constant&amp; operator=(const spec_constant&amp;) = delete;
+    spec_constant&amp; operator=(spec_constant&amp;&amp;) = delete;
+
+    const T&amp; get() const noexcept;
+
+    operator const T&amp;() const noexcept;
+};
+
+template&lt;class T, unsigned int ID&gt;
+const T&amp; get(const spec_constant&lt;T, ID&gt; &amp;r) noexcept;
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="spec_constant-class-methods-and-get-function">3.5.2. spec_constant class methods and get function</h4>
+<div class="sect4">
+<h5 id="spec_constantspec_constant">spec_constant::spec_constant</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>constexpr spec_constant(const T&amp; value);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Constructor of spec_constant class.
+The value parameter is a default value of the specialization constant that will be used if a value is not set by the host API.
+It must be a literal value.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="get">get</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>const T&amp; get() const noexcept;
+
+operator const T&amp;() const noexcept;
+
+template&lt;class T, unsigned int ID&gt;
+const T&amp; get(const spec_constant&lt;T, ID&gt; &amp;r) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Return a value of specialization constant.
+If an object is not specialized from the host, the default value will be returned.</p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="requirements-2">3.5.3. Requirements</h4>
+<div class="paragraph">
+<p>Specialization constant variables cannot be defined <code>constexpr</code>.</p>
+</div>
+<div class="sect4">
+<h5 id="data-1">Data</h5>
+<div class="paragraph">
+<p>Template parameter <code>T</code> in spec_constant class template denotes the data type of specialization constant.
+The type <code>T</code> must be integral or floating point type.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="id">ID</h5>
+<div class="paragraph">
+<p>Template parameter <code>ID</code> in spec_constant class template denotes an unique ID of the specialization constant that can be used to set a value from the host API.
+The value of <code>ID</code> must be unique within this compilation unit and across any other SPIR-V modules that it is linked with.</p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="examples-9">3.5.4. Examples</h4>
+<div class="sect4">
+<h5 id="example-1-9">Example 1</h5>
+<div class="paragraph">
+<p>Example of using the specialization constant in the kernel.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_spec_constant&gt;
+cl::spec_constant&lt;int, 1&gt; spec1{ 255 };
+constexpr cl::spec_constant&lt;int, 2&gt; spec2{ 255 }; // error, constexpr specialization
+                                                  // constant variables are not allowed
+
+kernel void myKernel()
+{
+  if(cl::get(spec1) == 255)
+  {
+       // do something if a default value is used
+  }
+  else
+  {
+    // do something if the spec constant was specialized by the host
+  }
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="example-2-7">Example 2</h5>
+<div class="paragraph">
+<p>Example of specializing one of the dimensions in <code>cl::required_work_group_size</code> attribute.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_spec_constant&gt;
+cl::spec_constant&lt;int, 1&gt; spec1{ 512 };
+
+[[cl::required_work_group_size(spec1, 1, 1)]]
+kernel void myKernel()
+{
+   //...
+}</code></pre>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="half-wrapper-library">3.6. Half Wrapper Library</h3>
+<div class="paragraph">
+<p>The OpenCL C++ programming language implements a wrapper class for the built-in half data type (see the <a href="#builtin-half-data-type"><em>Built-in Half Data Type</em></a> section).
+The class methods perform implicit <code>vload_half</code> and <code>vstore_half</code> operations from the <a href="#vector-data-load-and-store-functions"><em>Vector Data Load and Store Functions</em></a> section.</p>
+</div>
+<div class="sect3">
+<h4 id="header-opencl_half-synopsis">3.6.1. Header &lt;opencl_half&gt; Synopsis</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl {
+struct fp16
+{
+    fp16() = default;
+    fp16(const fp16 &amp;) = default;
+    fp16(fp16 &amp;&amp;) = default;
+    fp16 &amp;operator=(const fp16 &amp;) = default;
+    fp16 &amp;operator=(fp16 &amp;&amp;) = default;
+
+    explicit operator bool() const noexcept;
+
+#ifdef cl_khr_fp16
+    fp16(half r) noexcept;
+    fp16 &amp;operator=(half r) noexcept;
+    operator half() const noexcept;
+#endif
+
+    fp16(float r) noexcept;
+    fp16 &amp;operator=(float r) noexcept;
+    operator float() const noexcept;
+
+#ifdef cl_khr_fp64
+    fp16(double r) noexcept;
+    fp16 &amp;operator=(double r) noexcept;
+    operator double() const noexcept;
+#endif
+
+    fp16 &amp;operator++() noexcept;
+    fp16 operator++(int) noexcept;
+    fp16 &amp;operator--() noexcept;
+    fp16 operator--(int) noexcept;
+    fp16 &amp;operator+=(const fp16 &amp;r) noexcept;
+    fp16 &amp;operator-=(const fp16 &amp;r) noexcept;
+    fp16 &amp;operator*=(const fp16 &amp;r) noexcept;
+    fp16 &amp;operator/=(const fp16 &amp;r) noexcept;
+};
+
+bool operator==(const fp16&amp; lhs, const fp16&amp; rhs) noexcept;
+bool operator!=(const fp16&amp; lhs, const fp16&amp; rhs) noexcept;
+bool operator&lt; (const fp16&amp; lhs, const fp16&amp; rhs) noexcept;
+bool operator&gt; (const fp16&amp; lhs, const fp16&amp; rhs) noexcept;
+bool operator&lt;=(const fp16&amp; lhs, const fp16&amp; rhs) noexcept;
+bool operator&gt;=(const fp16&amp; lhs, const fp16&amp; rhs) noexcept;
+fp16 operator+(const fp16&amp; lhs, const fp16&amp; rhs) noexcept;
+fp16 operator-(const fp16&amp; lhs, const fp16&amp; rhs) noexcept;
+fp16 operator*(const fp16&amp; lhs, const fp16&amp; rhs) noexcept;
+fp16 operator/(const fp16&amp; lhs, const fp16&amp; rhs) noexcept;
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="constructors-1">3.6.2. Constructors</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>fp16(const half &amp;r) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Constructs an object with a half built-in type.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>fp16(const float &amp;r) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Constructs an object with a float built-in type.
+If the <strong>cl_khr_fp16</strong> extension is not supported, <code>vstore_half</code> built-in function is called with the default rounding mode.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>fp16(const double &amp;r) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Constructs an object with a double built-in type.
+If the <strong>cl_khr_fp16</strong> extension is not supported, <code>vstore_half</code> built-in function is called with the default rounding mode.
+The constructor is only present if the double precision support is enabled.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="assignment-operators-1">3.6.3. Assignment operators</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>fp16 &amp;operator=(const half &amp;r) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Assigns r to the stored half type.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>fp16 &amp;operator=(const float &amp;r) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Assigns r to the stored half type.
+If the <strong>cl_khr_fp16</strong> extension is not supported, <code>vstore_half</code> built-in function is called with the default rounding mode.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>fp16 &amp;operator=(const double &amp;r) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Assigns r to the stored half type.
+If the <strong>cl_khr_fp16</strong> extension is not supported, <code>vstore_half</code> built-in function is called with the default rounding mode.
+The operator is only present if the double precision support is enabled.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="conversion-operators">3.6.4. Conversion operators</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>explicit operator bool() const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>m != 0.0h</code>.
+If the <strong>cl_khr_fp16</strong> extension is not supported, <code>vload_half</code> built-in function is called.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>operator half() const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Conversion operator to the built-in half type.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>operator float() const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Conversion operator.
+If the <strong>cl_khr_fp16</strong> extension is not supported, <code>vload_half</code> built-in function is called.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>operator double() const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Conversion operator.
+If the <strong>cl_khr_fp16</strong> extension is not supported, <code>vload_half</code> built-in function is called.
+The operator is only present if the double precision support is enabled.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="arithmetic-operations">3.6.5. Arithmetic operations</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>fp16 &amp;operator++() noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Pre-increment operator.
+If the <strong>cl_khr_fp16</strong> extension is not supported, <code>vload_half</code> and <code>vstore_half</code> built-in functions are called.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>fp16 operator++(int) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Post-increment operator.
+If the <strong>cl_khr_fp16</strong> extension is not supported, <code>vload_half</code> and <code>vstore_half</code> built-in functions are called.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>fp16 &amp;operator--() noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Pre-decrement operator.
+If the <strong>cl_khr_fp16</strong> extension is not supported, <code>vload_half</code> and <code>vstore_half</code> built-in functions are called.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>fp16 operator--(int) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Pre-decrement operator.
+If the <strong>cl_khr_fp16</strong> extension is not supported, <code>vload_half</code> and <code>vstore_half</code> built-in functions are called.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>fp16 &amp;operator+=(const fp16 &amp;r) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Addition operator.
+If the <strong>cl_khr_fp16</strong> extension is not supported, <code>vload_half</code> and <code>vstore_half</code> built-in functions are called.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>fp16 &amp;operator-=(const fp16 &amp;r) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Subtract operator.
+If the <strong>cl_khr_fp16</strong> extension is not supported, <code>vload_half</code> and <code>vstore_half</code> built-in functions are called.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>fp16 &amp;operator*=(const fp16 &amp;r) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Multiplication operator.
+If the <strong>cl_khr_fp16</strong> extension is not supported, <code>vload_half</code> and <code>vstore_half</code> built-in functions are called.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>fp16 &amp;operator/=(const fp16 &amp;r) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Division operator.
+If the <strong>cl_khr_fp16</strong> extension is not supported, <code>vload_half</code> and <code>vstore_half</code> built-in functions are called.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="non-member-functions-1">3.6.6. Non-member functions</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>bool operator==(const fp16&amp; lhs, const fp16&amp; rhs) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Comparison operator ==.
+If the <strong>cl_khr_fp16</strong> extension is not supported, <code>vload_half</code> built-in function is called.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>bool operator!=(const fp16&amp; lhs, const fp16&amp; rhs) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Comparison operator !=.
+If the <strong>cl_khr_fp16</strong> extension is not supported, <code>vload_half</code> built-in function is called.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>bool operator&lt; (const fp16&amp; lhs, const fp16&amp; rhs) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Comparison operator &lt;.
+If the <strong>cl_khr_fp16</strong> extension is not supported, <code>vload_half</code> built-in function is called.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>bool operator&gt; (const fp16&amp; lhs, const fp16&amp; rhs) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Comparison operator &gt;.
+If the <strong>cl_khr_fp16</strong> extension is not supported, <code>vload_half</code> built-in function is called.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>bool operator&lt;=(const fp16&amp; lhs, const fp16&amp; rhs) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Comparison operator &#8656;.
+If the <strong>cl_khr_fp16</strong> extension is not supported, <code>vload_half</code> built-in function is called.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>bool operator&gt;=(const fp16&amp; lhs, const fp16&amp; rhs) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Comparison operator &gt;=.
+If the <strong>cl_khr_fp16</strong> extension is not supported, <code>vload_half</code> built-in function is called.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>fp16 operator+(const fp16&amp; lhs, const fp16&amp; rhs) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Addition operator.
+If the <strong>cl_khr_fp16</strong> extension is not supported, <code>vload_half</code> and <code>vstore_half</code> built-in functions are called.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>fp16 operator-(const fp16&amp; lhs, const fp16&amp; rhs) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Subtract operator.
+If the <strong>cl_khr_fp16</strong> extension is not supported, <code>vload_half</code> and <code>vstore_half</code> built-in functions are called.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>fp16 operator*(const fp16&amp; lhs, const fp16&amp; rhs) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Multiplication operator.
+If the <strong>cl_khr_fp16</strong> extension is not supported, <code>vload_half</code> and <code>vstore_half</code> built-in functions are called.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>fp16 operator/(const fp16&amp; lhs, const fp16&amp; rhs) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Division operator.
+If the <strong>cl_khr_fp16</strong> extension is not supported, <code>vload_half</code> and <code>vstore_half</code> built-in functions are called.</p>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="vector-wrapper-library">3.7. Vector Wrapper Library</h3>
+<div class="paragraph">
+<p>The OpenCL C++ programming language implements a vector wrapper type that works efficiently on the OpenCL devices.
+The vector class supports methods that allow construction of a new vector from a swizzled set of component elements or from a built-in vector type.
+The vector class can be converted to a corresponding built-in vector type.</p>
+</div>
+<div class="paragraph">
+<p>The <code>Size</code> parameter can be one of: 2, 3, 4, 8 or 16.
+Any other value should produce a compilation failure.
+The element type parameter <code>T</code>, must be one of the basic scalar types defined in <a href="#device_builtin_scalar_data_types">Device built-in scalar data types</a> table except void type.</p>
+</div>
+<div class="sect3">
+<h4 id="header-opencl_vec-synopsis">3.7.1. Header &lt;opencl_vec&gt; Synopsis</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl {
+static constexpr size_t undef_channel = static_cast&lt;size_t&gt;(-1);
+enum class channel : size_t { r = 0, g = 1, b = 2, a = 3, x = 0, y = 1, z = 2, w = 3, undef = undef_channel };
+
+template&lt;class T, size_t Size&gt;
+struct vec
+{
+    using element_type = T;
+    using vector_type = make_vector_t&lt;T, Size&gt;;
+    static constexpr size_t size = Size;
+
+    vec( ) = default;
+    vec(const vec &amp;) = default;
+    vec(vec &amp;&amp;) = default;
+
+    vec(const vector_type &amp;r) noexcept;
+    vec(vector_type &amp;&amp;r) noexcept;
+
+    template &lt;class... Params&gt;
+    vec(Params... params) noexcept;
+
+    vec&amp; operator=(const vec &amp;) = default;
+    vec&amp; operator=(vec &amp;&amp;) = default;
+
+    vec&amp; operator=(const vector_type &amp;r) noexcept;
+    vec&amp; operator=(vector_type &amp;&amp;r) noexcept;
+
+    operator vector_type() const noexcept;
+
+    vec&amp; operator++() noexcept;
+    vec&amp; operator++(int) noexcept;
+    vec&amp; operator--() noexcept;
+    vec&amp; operator--(int) noexcept;
+    vec&amp; operator+=(const vec &amp;r) noexcept;
+    vec&amp; operator+=(const element_type &amp;r) noexcept;
+    vec&amp; operator-=(const vec &amp;r) noexcept;
+    vec&amp; operator-=(const element_type &amp;r) noexcept;
+    vec&amp; operator*=(const vec &amp;r) noexcept;
+    vec&amp; operator*=(const element_type &amp;r) noexcept;
+    vec&amp; operator/=(const vec &amp;r) noexcept;
+    vec&amp; operator/=(const element_type &amp;r) noexcept;
+    vec&amp; operator%=(const vec &amp;r) noexcept;
+    vec&amp; operator%=(const element_type &amp;r) noexcept;
+
+    template &lt;size_t... Sizes&gt;
+    auto swizzle() noexcept;
+
+    template &lt;size_t... Sizes&gt;
+    auto swizzle() const noexcept;
+
+#ifdef SIMPLE_SWIZZLES
+    auto x() noexcept;
+...
+    auto xyzw() noexcept;
+...
+    auto zzzz() noexcept;
+#endif
+};
+
+template &lt;size_t... Swizzle, class Vec&gt;
+auto swizzle(Vec&amp; v);
+template &lt;channel... Swizzle, class Vec&gt;
+auto swizzle(Vec&amp; v);
+
+template&lt;class T, size_t Size&gt;
+make_vector_t&lt;bool, Size&gt; operator==(const vec&lt;T, Size&gt; &amp;lhs,
+                                     const vec&lt;T, Size&gt; &amp;rhs) noexcept;
+template&lt;class T, size_t Size&gt;
+make_vector_t&lt;bool, Size&gt; operator!=(const vec&lt;T, Size&gt; &amp;lhs,
+                                     const vec&lt;T, Size&gt; &amp;rhs) noexcept;
+template&lt;class T, size_t Size&gt;
+make_vector_t&lt;bool, Size&gt; operator&lt;(const vec&lt;T, Size&gt; &amp;lhs,
+                                    const vec&lt;T, Size&gt; &amp;rhs) noexcept;
+template&lt;class T, size_t Size&gt;
+make_vector_t&lt;bool, Size&gt; operator&gt;(const vec&lt;T, Size&gt; &amp;lhs,
+                                    const vec&lt;T, Size&gt; &amp;rhs) noexcept;
+template&lt;class T, size_t Size&gt;
+make_vector_t&lt;bool, Size&gt; operator&lt;=(const vec&lt;T, Size&gt; &amp;lhs,
+                                     const vec&lt;T, Size&gt; &amp;rhs) noexcept;
+template&lt;class T, size_t Size&gt;
+make_vector_t&lt;bool, Size&gt; operator&gt;=(const vec&lt;T, Size&gt; &amp;lhs,
+                                     const vec&lt;T, Size&gt; &amp;rhs) noexcept;
+template&lt;class T, size_t Size&gt;
+vec&lt;T, Size&gt; operator+(const vec&lt;T, Size&gt; &amp;lhs,
+                       const vec&lt;T, Size&gt; &amp;rhs) noexcept;
+template&lt;class T, size_t Size&gt;
+vec&lt;T, Size&gt; operator+(const vec&lt;T, Size&gt; &amp;lhs, const T &amp;rhs) noexcept;
+template&lt;class T, size_t Size&gt;
+vec&lt;T, Size&gt; operator+(const T &amp;lhs, const vec&lt;T, Size&gt; &amp;rhs) noexcept;
+template&lt;class T, size_t Size&gt;
+vec&lt;T, Size&gt; operator-(const vec&lt;T, Size&gt; &amp;lhs,
+                       const vec&lt;T, Size&gt; &amp;rhs) noexcept;
+template&lt;class T, size_t Size&gt;
+vec&lt;T, Size&gt; operator-(const vec&lt;T, Size&gt; &amp;lhs, const T &amp;rhs) noexcept;
+template&lt;class T, size_t Size&gt;
+vec&lt;T, Size&gt; operator-(const T &amp;lhs, const vec&lt;T, Size&gt; &amp;rhs) noexcept;
+template&lt;class T, size_t Size&gt;
+vec&lt;T, Size&gt; operator*(const vec&lt;T, Size&gt; &amp;lhs,
+                       const vec&lt;T, Size&gt; &amp;rhs) noexcept;
+template&lt;class T, size_t Size&gt;
+vec&lt;T, Size&gt; operator*(const vec&lt;T, Size&gt; &amp;lhs, const T &amp;rhs) noexcept;
+template&lt;class T, size_t Size&gt;
+vec&lt;T, Size&gt; operator*(const T &amp;lhs, const vec&lt;T, Size&gt; &amp;rhs) noexcept;
+template&lt;class T, size_t Size&gt;
+vec&lt;T, Size&gt; operator/(const vec&lt;T, Size&gt; &amp;lhs,
+                       const vec&lt;T, Size&gt; &amp;rhs) noexcept;
+template&lt;class T, size_t Size&gt;
+vec&lt;T, Size&gt; operator/(const vec&lt;T, Size&gt; &amp;lhs, const T &amp;rhs) noexcept;
+template&lt;class T, size_t Size&gt;
+vec&lt;T, Size&gt; operator/(const T &amp;lhs, const vec&lt;T, Size&gt; &amp;rhs) noexcept;
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="constructors-2">3.7.2. Constructors</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>vec(const vector_type &amp;r) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Copy constructor.
+Constructs an object with the corresponding built-in vector type.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>vec(vector_type &amp;&amp;r) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Move constructor.
+Constructs an object with the corresponding built-in vector type.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template &lt;class... Params&gt;
+vec(Params... params) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Constructs a vector object from a swizzled set of component elements.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="assignment-operators-2">3.7.3. Assignment operators</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>vec&amp; operator=(const vector_type &amp;r) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Copy assignment operator.
+The operator assigns a corresponding built-in vector type.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>vec&amp; operator=(vector_type &amp;&amp;r) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Move assignment operator.
+The operator assigns a corresponding built-in vector type.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="conversion-operators-1">3.7.4. Conversion operators</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>operator vector_type() const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Conversion operator.
+The operator converts from the vector wrapper class to a corresponding built-in vector type.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="arithmetic-operations-1">3.7.5. Arithmetic operations</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>vec&amp; operator++() noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Pre-increment operator.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>vec&amp; operator++(int) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Post-increment operator.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>vec&amp; operator--() noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Pre-decrement operator.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>vec&amp; operator--(int) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Post-decrement operator.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>vec&amp; operator+=(const vec &amp;r) noexcept;
+vec&amp; operator+=(const element_type &amp;r) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Add each element of <code>r</code> to the respective element of the current vector in-place.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>vec&amp; operator-=(const vec &amp;r) noexcept;
+vec&amp; operator-=(const element_type &amp;r) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Subtract each element of <code>r</code> from the respective element of the current vector in-place.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>vec&amp; operator*=(const vec &amp;r) noexcept;
+vec&amp; operator*=(const element_type &amp;r) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Multiply each element of <code>r</code> by the respective element of the current vector in-place.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>vec&amp; operator/=(const vec &amp;r) noexcept;
+vec&amp; operator/=(const element_type &amp;r) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Divide each element of the current vector in-place by the respective element of <code>r</code>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>vec&amp; operator%=(const vec &amp;r) noexcept;
+vec&amp; operator%=(const element_type &amp;r) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Remainder of each element of the current vector in-place by the respective element of <code>r</code>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="swizzle-methods">3.7.6. Swizzle methods</h4>
+<div class="paragraph">
+<p>All swizzle methods return a temporary object representing a swizzled set of the original vector&#8217;s member elements.
+The swizzled vector may be used as a source (rvalue) and destination (lvalue).
+In order to enable the r-value and lvalue swizzling to work, this returns an intermediate swizzled-vector class, which can be implicitly converted to a vector (rvalue evaluation) or assigned to.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template &lt;size_t... Sizes&gt;
+auto swizzle() noexcept;
+
+template &lt;size_t... Sizes&gt;
+auto swizzle() const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns a vector swizzle.
+The number of template parameters specified in <code>Sizes</code> must be from <code>1</code> to <code>Size</code>.
+<code>Sizes</code> parameters must be channel values: <code>channel::r</code>, <code>channel::b</code>, <code>&#8230;&#8203;</code>.
+Swizzle letters may be repeated or re-ordered.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>auto x() noexcept;
+...
+auto xyzw() noexcept;
+...
+auto zzzz() noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns a swizzle.
+These swizzle methods are only generated if the user defined the <code>SIMPLE_SWIZZLES</code> macro before including <em>opencl_vec</em> header.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="non-member-functions-2">3.7.7. Non-member functions</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template &lt;size_t... Swizzle, class Vec&gt;
+auto swizzle(Vec&amp; v);
+
+template &lt;channel... Swizzle, class Vec&gt;
+auto swizzle(Vec&amp; v);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns a vector swizzle.
+The number of template parameters specified in <code>Sizes</code> must be from <code>1</code> to <code>Size</code>.
+<code>Sizes</code> parameters must be channel values: <code>channel::r</code>, <code>channel::b</code>, <code>&#8230;&#8203;</code> .
+Swizzle letters may be repeated or re-ordered.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template&lt;class T, size_t Size&gt;
+make_vector_t&lt;bool, Size&gt; operator==(const vec&lt;T, Size&gt; &amp;lhs,
+                                     const vec&lt;T, Size&gt; &amp;rhs) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Return <code>true</code> if all elements of <code>rhs</code> compare equal to the respective element of <code>lhs</code>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template&lt;class T, size_t Size&gt;
+make_vector_t&lt;bool, Size&gt; operator!=(const vec&lt;T, Size&gt; &amp;lhs,
+                                     const vec&lt;T, Size&gt; &amp;rhs) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Return <code>true</code> if any one element of <code>rhs</code> does not compare equal to the respective element of <code>lhs</code>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template&lt;class T, size_t Size&gt;
+make_vector_t&lt;bool, Size&gt; operator&lt;(const vec&lt;T, Size&gt; &amp;lhs,
+                                    const vec&lt;T, Size&gt; &amp;rhs) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Return <code>true</code> if all elements of <code>lhs</code> are less than the respective element of <code>rhs</code>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template&lt;class T, size_t Size&gt;
+make_vector_t&lt;bool, Size&gt; operator&gt;(const vec&lt;T, Size&gt; &amp;lhs,
+                                    const vec&lt;T, Size&gt; &amp;rhs) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Return <code>true</code> if all elements of <code>lhs</code> are greater than the respective element of <code>rhs</code>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template&lt;class T, size_t Size&gt;
+make_vector_t&lt;bool, Size&gt; operator&lt;=(const vec&lt;T, Size&gt; &amp;lhs,
+                                     const vec&lt;T, Size&gt; &amp;rhs) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Return <code>true</code> if all elements of <code>lhs</code> are less than or equal to the respective element of <code>rhs</code>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template&lt;class T, size_t Size&gt;
+make_vector_t&lt;bool, Size&gt; operator&gt;=(const vec&lt;T, Size&gt; &amp;lhs,
+                                     const vec&lt;T, Size&gt; &amp;rhs) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Return <code>true</code> if all elements of <code>lhs</code> are greater than or equal to the respective element of <code>rhs</code>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template&lt;class T, size_t Size&gt;
+vec&lt;T, Size&gt; operator+(const vec&lt;T, Size&gt; &amp;lhs,
+                       const vec&lt;T, Size&gt; &amp;rhs) noexcept;
+
+template&lt;class T, size_t Size&gt;
+vec&lt;T, Size&gt; operator+(const vec&lt;T, Size&gt; &amp;lhs, const T &amp;rhs) noexcept;
+
+template&lt;class T, size_t Size&gt;
+vec&lt;T, Size&gt; operator+(const T &amp;lhs, const vec&lt;T, Size&gt; &amp;rhs) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Add each element of <code>rhs</code> to the respective element of <code>lhs</code>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template&lt;class T, size_t Size&gt;
+vec&lt;T, Size&gt; operator-(const vec&lt;T, Size&gt; &amp;lhs,
+                       const vec&lt;T, Size&gt; &amp;rhs) noexcept;
+template&lt;class T, size_t Size&gt;
+vec&lt;T, Size&gt; operator-(const vec&lt;T, Size&gt; &amp;lhs, const T &amp;rhs) noexcept;
+template&lt;class T, size_t Size&gt;
+vec&lt;T, Size&gt; operator-(const T &amp;lhs, const vec&lt;T, Size&gt; &amp;rhs) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Subtract each element of <code>rhs</code> from the respective element of <code>lhs</code>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template&lt;class T, size_t Size&gt;
+vec&lt;T, Size&gt; operator*(const vec&lt;T, Size&gt; &amp;lhs,
+                       const vec&lt;T, Size&gt; &amp;rhs) noexcept;
+template&lt;class T, size_t Size&gt;
+vec&lt;T, Size&gt; operator*(const vec&lt;T, Size&gt; &amp;lhs, const T &amp;rhs) noexcept;
+template&lt;class T, size_t Size&gt;
+vec&lt;T, Size&gt; operator*(const T &amp;lhs, const vec&lt;T, Size&gt; &amp;rhs) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Multiply each element of <code>rhs</code> by the respective element of <code>lhs</code>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template&lt;class T, size_t Size&gt;
+vec&lt;T, Size&gt; operator/(const vec&lt;T, Size&gt; &amp;lhs,
+                       const vec&lt;T, Size&gt; &amp;rhs) noexcept;
+template&lt;class T, size_t Size&gt;
+vec&lt;T, Size&gt; operator/(const vec&lt;T, Size&gt; &amp;lhs, const T &amp;rhs) noexcept;
+template&lt;class T, size_t Size&gt;
+vec&lt;T, Size&gt; operator/(const T &amp;lhs, const vec&lt;T, Size&gt; &amp;rhs) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Divide each element of <code>lhs</code> by the respective element of the <code>rhs</code>.</p>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="range-library">3.8. Range Library</h3>
+<div class="paragraph">
+<p>OpenCL C++ implements small library that contains useful utilities to manipulate iterator ranges.</p>
+</div>
+<div class="sect3">
+<h4 id="header-opencl_range-synopsis">3.8.1. Header &lt;opencl_range&gt; Synopsis</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+template &lt;class It&gt;
+struct range_type
+{
+    constexpr range_type(It&amp; it) noexcept;
+    constexpr range_type(It&amp; it, difference_type end) noexcept;
+    constexpr range_type(It&amp; it, difference_type begin,
+                         difference_type end) noexcept;
+
+    constexpr auto begin( ) noexcept;
+    constexpr auto end( ) noexcept;
+};
+
+template &lt;class It&gt;
+constexpr auto range(It&amp; it) noexcept;
+
+template &lt;class It&gt;
+constexpr auto range(It&amp; it, difference_type end) noexcept;
+
+template &lt;class It&gt;
+constexpr auto range(It&amp; it, difference_type begin,
+                     difference_type end) noexcept;
+
+// difference_type is It::difference_type if present ptrdiff_t otherwise.
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="range-type">3.8.2. Range type</h4>
+<div class="paragraph">
+<p>Range type represents a given range over iterable type.
+Depending on constructor used:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>constexpr range_type(It&amp; it) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Represents range from <code>begin(it)</code> to <code>end(it)</code>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>constexpr range_type(It&amp; it, difference_type end) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Represents range from <code>begin(it)</code> to <code>begin(it)+end</code>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>constexpr range_type(It&amp; it, difference_type begin,
+                     difference_type end) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Represents range from <code>begin(it)+begin</code> to <code>begin(it)+end</code>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="range-function">3.8.3. Range function</h4>
+<div class="paragraph">
+<p>range function is present in three overloads matching <code>range_type</code> constructors.
+It is a factory function building <code>range_type</code>.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+This function main purpose is enabling the use of range based for loops on built-in vectors.
+</td>
+</tr>
+</table>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="vector-utilities-library">3.9. Vector Utilities Library</h3>
+<div class="paragraph">
+<p>OpenCL C++ implements vector utilities library that contains multiple helper classes to help working with built-in vectors.</p>
+</div>
+<div class="sect3">
+<h4 id="header-opencl_vector_utility-synopsis">3.9.1. Header &lt;opencl_vector_utility&gt; Synopsis</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+template &lt;size_t Channel, class Vec&gt;
+constexpr remove_attrs_t&lt;vector_element_t&lt;Vec&gt;&gt; get(Vec &amp; vector) noexcept;
+
+template &lt;size_t Channel, class Vec&gt;
+constexpr void set(Vec &amp; vector,
+                   remove_attrs_t&lt;vector_element_t&lt;Vec&gt;&gt; value) noexcept;
+
+template &lt;class Vec&gt;
+struct channel_ref
+{
+    using type = remove_attrs_t&lt;vector_element_t&lt;Vec&gt;&gt;;
+
+    constexpr operator type( ) noexcept;
+    constexpr channel_ref&amp; operator=(type value) noexcept;
+    constexpr channel_ref&amp; operator +=(type value) noexcept;
+    constexpr friend type operator +(channel_ref lhs, type rhs) noexcept;
+    constexpr channel_ref&amp; operator -=(type value) noexcept;
+    constexpr friend type operator -(channel_ref lhs, type rhs) noexcept;
+    constexpr channel_ref&amp; operator *=(type value) noexcept;
+    constexpr friend type operator *(channel_ref lhs, type rhs) noexcept;
+    constexpr channel_ref&amp; operator /=(type value) noexcept;
+    constexpr friend type operator /(channel_ref lhs, type rhs) noexcept;
+    constexpr channel_ref&amp; operator %=(type value) noexcept;
+    constexpr friend type operator %(channel_ref lhs, type rhs) noexcept;
+    constexpr channel_ref&amp; operator ^=(type value) noexcept;
+    constexpr friend type operator ^(channel_ref lhs, type rhs) noexcept;
+    constexpr channel_ref&amp; operator &amp;=(type value) noexcept;
+    constexpr friend type operator &amp;(channel_ref lhs, type rhs) noexcept;
+    constexpr channel_ref&amp; operator |=(type value) noexcept;
+    constexpr friend type operator |(channel_ref lhs, type rhs) noexcept;
+    constexpr channel_ref&amp; operator++( ) noexcept;
+    constexpr channel_ref operator++(int) noexcept;
+    constexpr channel_ref&amp; operator--( ) noexcept;
+    constexpr channel_ref operator--(int) noexcept;
+};
+
+template &lt;&gt;
+struct channel_ref&lt;floating_point_vector&gt;
+{
+    using type = remove_attrs_t&lt;vector_element_t&lt;Vec&gt;&gt;;
+
+    constexpr operator type( ) noexcept;
+    constexpr channel_ref&amp; operator=(type value) noexcept;
+    constexpr channel_ref&amp; operator +=(type value) noexcept;
+    constexpr friend type operator +(channel_ref lhs, type rhs) noexcept;
+    constexpr channel_ref&amp; operator -=(type value) noexcept;
+    constexpr friend type operator -(channel_ref lhs, type rhs) noexcept;
+    constexpr channel_ref&amp; operator *=(type value) noexcept;
+    constexpr friend type operator *(channel_ref lhs, type rhs) noexcept;
+    constexpr channel_ref&amp; operator /=(type value) noexcept;
+    constexpr friend type operator /(channel_ref lhs, type rhs) noexcept;
+    constexpr channel_ref&amp; operator++( ) noexcept;
+    constexpr channel_ref&amp; operator++(int) noexcept;
+    constexpr channel_ref&amp; operator--( ) noexcept;
+    constexpr channel_ref&amp; operator--(int) noexcept;
+};
+
+template &lt;&gt;
+struct channel_ref&lt;boolean_vector&gt;
+{
+    using type = remove_attrs_t&lt;vector_element_t&lt;Vec&gt;&gt;;
+
+    constexpr operator type( ) noexcept;
+    constexpr channel_ref&amp; operator=(type value) noexcept;
+    constexpr channel_ref&amp; operator +=(type value) noexcept;
+    constexpr friend type operator +(channel_ref lhs, type rhs) noexcept;
+    constexpr channel_ref&amp; operator -=(type value) noexcept;
+    constexpr friend type operator -(channel_ref lhs, type rhs) noexcept;
+    constexpr channel_ref&amp; operator *=(type value) noexcept;
+    constexpr friend type operator *(channel_ref lhs, type rhs) noexcept;
+    constexpr channel_ref&amp; operator /=(type value) noexcept;
+    constexpr friend type operator /(channel_ref lhs, type rhs) noexcept;
+    constexpr channel_ref&amp; operator %=(type value) noexcept;
+    constexpr friend type operator %(channel_ref lhs, type rhs) noexcept;
+    constexpr channel_ref&amp; operator ^=(type value) noexcept;
+    constexpr friend type operator ^(channel_ref lhs, type rhs) noexcept;
+    constexpr channel_ref&amp; operator &amp;=(type value) noexcept;
+    constexpr friend type operator &amp;(channel_ref lhs, type rhs) noexcept;
+    constexpr channel_ref&amp; operator |=(type value) noexcept;
+    constexpr friend type operator |(channel_ref lhs, type rhs) noexcept;
+    constexpr channel_ref&amp; operator++( ) noexcept;
+    constexpr channel_ref&amp; operator++(int) noexcept;
+};
+
+template &lt;class Vec&gt;
+struct channel_ptr
+{
+    constexpr channel_ptr( ) noexcept;
+    constexpr channel_ptr(const channel_ref&lt;Vec&gt;&amp; ref) noexcept;
+    constexpr channel_ptr(const channel_ptr&amp;) noexcept = default;
+    constexpr channel_ptr(channel_ptr&amp;&amp;) noexcept = default;
+    constexpr channel_ptr&amp; operator=(const channel_ptr&amp;) noexcept = default;
+    constexpr channel_ptr&amp; operator=(channel_ptr&amp;&amp;) noexcept = default;
+
+    using type = remove_attrs_t&lt;vector_element_t&lt;Vec&gt;&gt;;
+
+    constexpr channel_ref&lt;Vec&gt;&amp; operator*( ) noexcept;
+};
+
+template &lt;class Vec&gt;
+struct vector_iterator : iterator&lt;random_access_iterator_tag,
+                          remove_attrs_t&lt;vector_element_t&lt;remove_attrs_t&lt;Vec&gt;&gt;&gt;,
+                          ptrdiff_t,
+                          channel_ptr&lt;remove_attrs_t&lt;Vec&gt;&gt;,
+                          channel_ref&lt;remove_attrs_t&lt;Vec&gt;&gt;&gt;
+{
+    using type = remove_attrs_t&lt;Vec&gt;;
+
+    constexpr vector_iterator(type &amp; vector, size_t offset) noexcept;
+    constexpr vector_iterator( ) noexcept = default;
+    constexpr vector_iterator(const vector_iterator&amp;) noexcept = default;
+    constexpr vector_iterator(vector_iterator&amp;&amp;) noexcept = default;
+    constexpr vector_iterator&amp; operator=(
+                                     const vector_iterator&amp;) noexcept = default;
+    constexpr vector_iterator&amp; operator=(vector_iterator&amp;&amp;) noexcept = default;
+
+    constexpr vector_iterator&amp; operator+=(difference_type value) noexcept;
+    constexpr friend vector_iterator operator+(const vector_iterator&amp; lhs,
+                                               difference_type rhs) noexcept;
+    constexpr friend vector_iterator operator+(difference_type lhs,
+                                           const vector_iterator&amp; rhs) noexcept;
+    constexpr vector_iterator&amp; operator-=(difference_type value) noexcept;
+    constexpr friend vector_iterator operator-(const vector_iterator&amp; lhs,
+                                                  difference_type rhs) noexcept;
+
+    constexpr vector_iterator operator++(int) noexcept;
+    constexpr vector_iterator&amp; operator++( ) noexcept;
+    constexpr vector_iterator operator--(int) noexcept;
+    constexpr vector_iterator&amp; operator--( ) noexcept;
+
+    friend constexpr bool operator ==(const vector_iterator&amp; lhs,
+                                      const vector_iterator&amp; rhs) noexcept;
+    friend constexpr bool operator !=(const vector_iterator&amp; lhs,
+                                      const vector_iterator&amp; rhs) noexcept;
+    friend constexpr bool operator &lt;(const vector_iterator&amp; lhs,
+                                     const vector_iterator&amp; rhs) noexcept;
+    friend constexpr bool operator &lt;=(const vector_iterator&amp; lhs,
+                                      const vector_iterator&amp; rhs) noexcept;
+    friend constexpr bool operator &gt;(const vector_iterator&amp; lhs,
+                                     const vector_iterator&amp; rhs) noexcept;
+    friend constexpr bool operator &gt;=(const vector_iterator&amp; lhs,
+                                      const vector_iterator&amp; rhs) noexcept;
+
+    constexpr reference operator[ ](difference_type value) noexcept;
+    constexpr reference operator*( ) noexcept;
+
+    constexpr pointer operator-&gt;( ) noexcept;
+};
+
+template &lt;class Vec, class = enable_if_t&lt;is_vector_type&lt;Vec&gt;::value, void&gt;&gt;
+constexpr channel_ref&lt;Vec&gt; index(Vec&amp; vector, size_t channel) noexcept;
+
+template &lt;class Vec, class = enable_if_t&lt;is_vector_type&lt;Vec&gt;::value, void&gt;&gt;
+constexpr vector_iterator&lt;Vec&gt; begin(Vec &amp; vector) noexcept;
+
+template &lt;class Vec, class = enable_if_t&lt;is_vector_type&lt;Vec&gt;::value, void&gt;&gt;
+constexpr vector_iterator&lt;Vec&gt; end(Vec &amp; vector) noexcept;
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="vector-iterator">3.9.2. Vector iterator</h4>
+<div class="paragraph">
+<p>Vector iterator is a random access iterator that allows runtime iteration over vector channels.
+Meets all the requirements for random access iterator.
+Iterating outside of vector bounds is an undefined behavior.</p>
+</div>
+<div class="paragraph">
+<p>The library also exposes non member begin and end functions for vectors.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+Due to the usage of argument-dependent lookup in range based for loops this functions are not available, and the new range adapter has to be used
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p>There is also an <code>index</code> function present in the library that allows runtime numerical indexing of channels.
+It returns a channel reference to a given channel number.
+Indexing out of vector bounds results in undefined behavior.</p>
+</div>
+<div class="paragraph">
+<p>The following example will present simple template function computing sum of channels of a given vector:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template&lt;class V&gt;
+auto sum(const V&amp; v) {
+    vector_element_t&lt;V&gt; temp = 0;
+    for(auto e : range(v)) {
+        temp += e;
+    }
+    return temp;
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="channel-reference-and-channel-pointer">3.9.3. Channel reference and channel pointer</h4>
+<div class="paragraph">
+<p><code>channel_ref</code> and <code>channel_ptr</code> classes provide lightweight reference and pointer wrappers for vector channels.
+This is required due to the fact that vector channels can be moved across memory during execution so direct physical addressing is impossible.
+Reference wrapper provides a set of binary operators (depending on vector channel type).</p>
+</div>
+<div class="paragraph">
+<p>The following example will present a simple usage of channel reference to set first channel of given vector to 0:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template &lt;class V&gt;
+void fun(V&amp; v) {
+    channel_ref&lt;V&gt; r = *begin(v);
+    r = 0;
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="get-and-set-functions">3.9.4. Get and set functions</h4>
+<div class="paragraph">
+<p>Get and set functions allow compile time numerical indexing of channels to substitute for normal swizzling.
+Indexing out of vector range generates a compile error.
+Get function returns a copy of channel value.</p>
+</div>
+<div class="paragraph">
+<p>The following example will present how get and set functions can be used to duplicate the value of the first channel of given vector:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template &lt;class V&gt;
+void fun(V&amp; v) {
+    auto c = get&lt; 0 &gt;(v);
+    set&lt; 0 &gt;(v, 2*c);
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="examples-8">3.9.5. Examples</h4>
+<div class="sect4">
+<h5 id="example-1-8">Example 1</h5>
+<div class="paragraph">
+<p>Example of using built-in vector iterators.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_vector_utility&gt;
+#include &lt;opencl_range&gt;
+using namespace cl;
+
+kernel void foo() {
+    int8 v_i8;
+    auto iter_begin = begin(v_i8);
+    auto iter_end = end(v_i8);
+
+    iter_begin = iter_end;
+
+    int a = 0;
+    a = *iter_begin;
+    a = iter_begin[0];
+
+    iter_begin++;
+    iter_begin+=1;
+    iter_begin = iter_begin + 1;
+
+    iter_begin--;
+    iter_begin-=1;
+    iter_begin = iter_begin - 1;
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="example-2-6">Example 2</h5>
+<div class="paragraph">
+<p>Example of iterating though built-in vector channels and using range library.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_vector_utility&gt;
+#include &lt;opencl_range&gt;
+
+kernel void foo() {
+    int16 a;
+
+    for (auto it = cl::begin(a); it != cl::end(a); it++) {
+        int b = *it;
+        *it = 2;
+    }
+
+    for (auto c : cl::range(a,3,6)) {
+        int b = c;
+        c = 2;
+    }
+}</code></pre>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="marker-types">3.10. Marker Types</h3>
+<div class="paragraph">
+<p>Some types in OpenCL C++ are considered marker types.
+These types are special in the manner that their usages need to be tracked by the compiler.
+This results in the following set of restrictions that marker types have to follow:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Marker types have the default constructor deleted.</p>
+</li>
+<li>
+<p>Marker types have all default copy and move assignment operators deleted.</p>
+</li>
+<li>
+<p>Marker types have address-of operator deleted.</p>
+</li>
+<li>
+<p>Marker types cannot be used in divergent control flow. It can result in undefined behavior.</p>
+</li>
+<li>
+<p>Size of marker types is undefined.</p>
+</li>
+</ul>
+</div>
+<div class="sect3">
+<h4 id="header-opencl_marker-synopsis">3.10.1. Header &lt;opencl_marker&gt; Synopsis</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+struct marker_type;
+
+template&lt;class T&gt;
+struct is_marker_type;
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="marker_type-class">3.10.2. marker_type class</h4>
+<div class="paragraph">
+<p>All special OpenCL C++ types must use the <code>marker_type</code> class as a base class.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="is_marker_type-type-trait">3.10.3. is_marker_type type trait</h4>
+<div class="paragraph">
+<p><code>is_marker_type</code> type trait provides compile-time check if the base of a class is <code>marker_type</code>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+template&lt;class T&gt;
+struct is_marker_type : integral_constant &lt;bool, is_base_of&lt;marker_type, T&gt;::value&gt; { };
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="examples">3.10.4. Examples</h4>
+<div class="sect4">
+<h5 id="example-1">Example 1</h5>
+<div class="paragraph">
+<p>The examples of invalid use of <code>marker types</code>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_image&gt;
+#include &lt;opencl_work_item&gt;
+using namespace cl;
+
+float4 bar(image1d&lt;float4&gt; img) {
+    return img.read({get_global_id(0), get_global_id(1)});
+}
+
+kernel void foo(image1d&lt;float4&gt; img1, image1d&lt;float4&gt; img2) {
+    image1d&lt;float4&gt; img3; //error: marker type cannot be declared
+                          //       in the kernel
+    img1 = img2; //error: marker type cannot be assigned
+    image1d&lt;float4&gt; *imgPtr = &amp;img1; //error: taking address of
+                                     //       marker type
+
+    size_t s = sizeof(img1); //undefined behavior: size of marker
+                             //               type is not defined
+
+    float4 val = bar(get_global_id(0) ? img1: img2);
+                          //undefined behavior: divergent control flow
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="example-2">Example 2</h5>
+<div class="paragraph">
+<p>The examples of how to use <code>is_marker_type</code> trait.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_image&gt;
+using namespace cl;
+
+kernel void foo(image1d&lt;float4&gt; img) {
+  static_assert(is_marker_type&lt;decltype(img)&gt;(), "");
+}</code></pre>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="images-and-samplers-library">3.11. Images and Samplers Library</h3>
+<div class="paragraph">
+<p>This section describes the image and sampler types and functions that can be used to read from and/or write to an image.
+<code>image1d</code>, <code>image1d_buffer</code>, <code>image1d_array</code>, <code>image2d</code>, <code>image2d_array</code>, <code>image3d</code>, <code>image2d_depth</code>, <code>image2d_array_depth</code>, <code>image2d_ms</code>, <code>image2d_array_ms</code>, <code>image2d_depth_ms</code>, <code>image2d_array_depth_ms</code> <a id="ftnref13"></a> <a href="#ftn13">[13]</a> and <code>sampler</code> follow the rules for marker types (see the <a href="#marker-types"><em>Marker Types</em></a> section).
+The image and sampler types can only be used if the device support images i.e. <code>CL_DEVICE_IMAGE_SUPPORT</code> as described in table 4.3 in OpenCL 2.2 specification is <code>CL_TRUE</code>.</p>
+</div>
+<div class="sect3">
+<h4 id="image-and-sampler-host-types">3.11.1. Image and Sampler Host Types</h4>
+<div class="paragraph">
+<p>The below table describes the OpenCL image and sampler data types and the corresponding data type available to the application:</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 10. Host image and sampler types</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Type in OpenCL C++</strong></th>
+<th class="tableblock halign-left valign-top"><strong>API type for application</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl::image1d</code>,<br>
+  <code>cl::image1d_buffer</code>,<br>
+  <code>cl::image1d_array</code>,<br>
+  <code>cl::image2d</code>,<br>
+  <code>cl::image2d_array</code>,<br>
+  <code>cl::image3d</code>,<br>
+  <code>cl::image2d_depth</code>,<br>
+  <code>cl::image2d_array_depth</code>,<br>
+  <code>cl::image2d_ms</code>,<br>
+  <code>cl::image2d_array_ms</code>,<br>
+  <code>cl::image2d_depth_ms</code>,<br>
+  <code>cl::image2d_array_depth_ms</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_image</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl::sampler</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_sampler</code></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="header-opencl_image-synopsis">3.11.2. Header &lt;opencl_image&gt; Synopsis</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+enum class image_access;
+enum class image_channel_type;
+enum class image_channel_order;
+enum class addressing_mode;
+enum class normalized_coordinates;
+enum class filtering_mode;
+
+struct sampler;
+
+template &lt;addressing_mode A, normalized_coordinates C, filtering_mode F&gt;
+constexpr sampler make_sampler();
+
+template &lt;class T, image_access A, image_dim Dim, bool Depth, bool Array,
+          bool MS&gt;
+struct image;
+
+template &lt;class T, image_access A = image_access::read&gt;
+using image1d = image&lt;T, A, image_dim::image_1d, false, false, false&gt;;
+
+template &lt;class T, image_access A = image_access::read&gt;
+using image1d_buffer = image&lt;T, A, image_dim::image_buffer, false, false,
+                             false&gt;;
+
+template &lt;class T, image_access A = image_access::read&gt;
+using image1d_array = image&lt;T, A, image_dim::image_1d, false, true, false&gt;;
+
+template &lt;class T, image_access A = image_access::read&gt;
+using image2d = image&lt;T, A, image_dim::image_2d, false, false, false&gt;;
+
+template &lt;class T, image_access A = image_access::read&gt;
+using image2d_depth = image&lt;T, A, image_dim::image_2d, true, false, false&gt;;
+
+template &lt;class T, image_access A = image_access::read&gt;
+using image2d_array = image&lt;T, A, image_dim::image_2d, false, true, false&gt;;
+
+template &lt;class T, image_access A = image_access::read&gt;
+using image3d = image&lt;T, A, image_dim::image_3d, false, false, false&gt;;
+
+template &lt;class T, image_access A = image_access::read&gt;
+using image2d_array_depth = image&lt;T, A, image_dim:: image_2d, true, true,
+                                  false&gt;;
+
+#if defined(cl_khr_gl_msaa_sharing) &amp;&amp; defined(cl_khr_gl_depth_images)
+template &lt;class T, image_access A = image_access::read&gt;
+using image2d_ms = image&lt;T, A, image_dim::image_2d, false, false, true&gt;;
+
+template &lt;class T, image_access A = image_access::read&gt;
+using image2d_array_ms = image&lt;T, A, image_dim::image_2d, false, true, true&gt;;
+
+template &lt;class T, image_access A = image_access::read&gt;
+using image2d_depth_ms = image&lt;T, A, image_dim::image_2d, true, false, true&gt;;
+
+template &lt;class T, image_access A = image_access::read&gt;
+using image2d_array_depth_ms = image&lt;T, A, image_dim::image_2d, true, true,
+                                     true&gt;;
+#endif
+
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Where <code>T</code> is the type of value returned when reading or sampling from given image or the type of color used to write to image.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="image-class">3.11.3. image class</h4>
+<div class="paragraph">
+<p>Every image type has the following set of publicly available members and typedefs:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template &lt;class T, image_access A, image_dim Dim, bool Depth, bool Array,
+          bool MS&gt;
+struct image: marker_type
+{
+    static constexpr image_dim dimension = Dim;
+    static constexpr size_t dimension_num = image_dim_num&lt;Dim&gt;::value;
+    static constexpr size_t image_size = dimension_num + (Array? 1: 0);
+    static constexpr image_access access = A;
+    static constexpr bool is_array = Array;
+    static constexpr bool is_depth = Depth;
+#if defined(cl_khr_gl_msaa_sharing) &amp;&amp; defined(cl_khr_gl_depth_images)
+    static constexpr bool is_ms = MS;
+#else
+    static constexpr bool is_ms = false;
+#endif
+    typedef element_type T;
+    typedef integer_coord make_vector_t&lt;int, image_size&gt;;
+    typedef float_coord make_vector_t&lt;float, image_size&gt;;
+
+#ifdef cl_khr_mipmap_image
+    typedef gradient_coord make_vector_t&lt;float, dimension_num&gt;;
+#endif
+
+    struct pixel;
+
+    image() = delete;
+    image(const image&amp;) = default;
+    image(image&amp;&amp;) = default;
+
+    image&amp; operator=(const image&amp;) = delete;
+    image&amp; operator=(image&amp;&amp;) = delete;
+    image* operator&amp;() = delete;
+};</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="image-element-types">3.11.4. Image element types</h4>
+<div class="paragraph">
+<p>We can classify images into four categories: depth images which have the <code>Depth</code> template parameter set to <code>true</code>, multi-sample depth images which have the <code>Depth</code> and <code>MS</code> template parameters set to <code>true</code>, multi-sample which have the <code>MS</code> template parameter set to <code>true</code>, and the normal images which have the <code>Depth</code> and <code>MS</code> template parameters set to <code>false</code>.</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>For non-multisample depth images the only valid element types are: <code>float</code> and <code>half</code> <a id="ftnref14"></a> <a href="#ftn4">[4]</a></p>
+</li>
+<li>
+<p>For normal images the only valid element types are: <code>float4</code>, <code>half4</code> <a href="#ftn4">[4]</a>, <code>int4</code> and <code>uint4</code></p>
+</li>
+<li>
+<p>For multi-sample 2D and multi-sample 2D array images the only valid element types are: <code>float4</code>, <code>int4</code> and <code>uint4</code></p>
+</li>
+<li>
+<p>For multi-sample 2D depth and multi-sample 2D array depth images the only valid element type is: <code>float</code></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Image type with invalid pixel type is ill formed.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="image-dimension">3.11.5. Image dimension</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+enum class image_dim
+{
+    image_1d,
+    image_2d,
+    image_3d,
+    image_buffer
+};
+
+template &lt;image_dim Dim&gt;
+struct image_dim_num;
+
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Image types present different set of methods depending on their dimensionality and arrayness.</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Images of dimension 1 (<code>image_dim::image_1d</code> and <code>image_dim::buffer</code>) have method:</p>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int width() const noexcept;</code></pre>
+</div>
+</div>
+</li>
+<li>
+<p>Images of dimension 2 (<code>image_dim::image_2d</code>)  have all methods of 1 dimensional images and</p>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int height() const noexcept;</code></pre>
+</div>
+</div>
+</li>
+<li>
+<p>Images of dimension 3 (<code>image_dim::image_3d</code>) have all methods of 2 dimensional images and</p>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int depth() const noexcept;</code></pre>
+</div>
+</div>
+</li>
+<li>
+<p>Arrayed images have additional method</p>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int array_size() const noexcept;</code></pre>
+</div>
+</div>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If the <strong>cl_khr_mipmap_image</strong> or <strong>cl_khr_mipmap_image_writes</strong> extension is enabled, then the following methods are also present:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Images of dimension 1 (<code>image_dim::image_1d</code> and <code>image_dim::buffer</code>) have method:</p>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int width(int lod) const noexcept;</code></pre>
+</div>
+</div>
+</li>
+<li>
+<p>Images of dimension 2 (<code>image_dim::image_2d</code>) have all methods of 1 dimensional images and</p>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int height(int lod) const noexcept;</code></pre>
+</div>
+</div>
+</li>
+<li>
+<p>Images of dimension 3 (<code>image_dim::image_3d</code>) have all methods of 2 dimensional images and</p>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int depth(int lod) const noexcept;</code></pre>
+</div>
+</div>
+</li>
+<li>
+<p>Arrayed images have additional method</p>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int array_size(int lod) const noexcept;</code></pre>
+</div>
+</div>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If the <strong>cl_khr_gl_msaa_sharing</strong> and <strong>cl_khr_gl_depth_images</strong> extensions are enabled, then the following methods are also present:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Images of dimension 2D (<code>image_dim::image_2d</code>) have method:</p>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int num_samples() const noexcept;</code></pre>
+</div>
+</div>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The following table describes the <code>image_dim_num</code> trait that return a number of dimensions based on <code>image_dim</code> parameter.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 11. Image_dim_num trait</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Template</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Value</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>template &lt;image_dim Dim&gt; struct image_dim_num;</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">If <code>Dim</code> is <code>image_dim::image_1d</code> or <code>image_dim::image_buffer</code>, image dimension is 1.<br>
+  If <code>Dim</code> is <code>image_dim::image_2d</code>, image dimension is 2.<br>
+  If <code>Dim</code> is <code>image_dim::image_3d</code>, image dimension is 3.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="image-access">3.11.6. Image access</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+enum class image_access
+{
+    sample,
+    read,
+    write,
+    read_write
+};
+
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The non-multisample image template class specializations present different set of methods based on their access parameter.</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Images specified with <code>image_access::read</code> provide additional methods:</p>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>element_type image::read(integer_coord coord) const noexcept;
+
+pixel image::operator[](integer_coord coord) const noexcept;
+
+element_type image::pixel::operator element_type() const noexcept;</code></pre>
+</div>
+</div>
+</li>
+<li>
+<p>Images specified with <code>image_access::write</code> provide additional method:</p>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>void image::write(integer_coord coord, element_type color) noexcept;
+
+image::pixel image::operator[](integer_coord coord) noexcept;
+
+image::pixel &amp; image::pixel::operator=(element_type color) noexcept;</code></pre>
+</div>
+</div>
+</li>
+<li>
+<p>Images specified with <code>image_access::read_write</code> provide additional methods:</p>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>element_type image::read(integer_coord coord) const noexcept;
+
+void image::write(integer_coord coord, element_type color) noexcept;
+
+image::pixel image::operator[](integer_coord coord) noexcept;
+
+element_type image::pixel::operator element_type() const noexcept;
+
+image::pixel &amp; image::pixel::operator=(element_type color) noexcept;</code></pre>
+</div>
+</div>
+</li>
+<li>
+<p>Images specified with <code>image_access::sample</code> provide additional methods:</p>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>element_type image::read(integer_coord coord) const noexcept;
+
+element_type image::sample(const sampler &amp;s,
+                           integer_coord coord) const noexcept;
+
+element_type image::sample(const sampler &amp;s, float_coord coord) const noexcept;
+
+image::pixel image::operator[](integer_coord coord) const noexcept;
+
+element_type image::pixel::operator element_type() const noexcept;</code></pre>
+</div>
+</div>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If the <strong>cl_khr_mipmap_image</strong> extension is enabled the following methods are added to the non-multisample image types:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Images specified with <code>image_access::sample</code> provide additional methods:</p>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>element_type image::sample(const sampler &amp;s, float_coord coord,
+                           float lod) const noexcept;
+
+element_type image::sample(const sampler &amp;s, float_coord coord,
+                           gradient_coord gradient_x,
+                           gradient_coord gradient_y) const noexcept;</code></pre>
+</div>
+</div>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If the <strong>cl_khr_mipmap_image_writes</strong> extension is enabled the following methods are added to the non-multisample image types:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Images specified with <code>image_access::write</code> provide additional method:</p>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>void image::write(integer_coord coord, element_type color, int lod) noexcept;</code></pre>
+</div>
+</div>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If the <strong>cl_khr_gl_msaa_sharing</strong> and <strong>cl_khr_gl_depth_images</strong> extensions are enabled and the multisample image type is used, the following method is available:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>The multisample images specified with <code>image_access::read</code> provide method:</p>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>element_type image::read(integer_coord coord, int sample) noexcept;</code></pre>
+</div>
+</div>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="common-image-methods">3.11.7. Common image methods</h4>
+<div class="paragraph">
+<p>Each image type implements a set of common methods:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>image_channel_type image::data_type() const noexcept;
+image_channel_order image::order() const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>If the <strong>cl_khr_mipmap_image</strong> or <strong>cl_khr_mipmap_image_writes</strong> extension is enabled, then the following method is also present in the non-multisample image types:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int image::miplevels() const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>where <code>image_channel_type</code> and <code>image_channel_order</code> are defined as follows:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+enum class image_channel_type
+{
+    snorm_int8,
+    snorm_int16,
+    unorm_int8,
+    unorm_int16,
+    unorm_int24,
+    unorm_short_565,
+    unorm_short_555,
+    unorm_int_101010,
+    unorm_int_101010_2,
+    signed_int8,
+    signed_int16,
+    signed_int32,
+    unsigned_int8,
+    unsigned_int16,
+    unsigned_int32,
+    fp16,
+    fp32
+};
+
+enum class image_channel_order
+{
+    a,
+    r,
+    rx,
+    rg,
+    rgx,
+    ra,
+    rgb,
+    rgbx,
+    rgba,
+    argb,
+    bgra,
+    intensity,
+    luminance,
+    abgr,
+    depth,
+    depth_stencil,
+    srgb,
+    srgbx,
+    srgba,
+    sbgra
+};
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="other-image-methods">3.11.8. Other image methods</h4>
+<div class="sect4">
+<h5 id="imagesample">image::sample</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>element_type image::sample(const sampler &amp;s, float_coord coord) const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Reads a color value from the non-multisample image using sampler and floating point coordinates.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>element_type image::sample(const sampler &amp;s, integer_coord coord) const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Reads a color value from non-multisample image using sampler and integer coordinates.</p>
+</div>
+<div class="paragraph">
+<p>A sampler must use filter mode set to <code>filtering_mode::nearest</code>, normalized coordinates and addressing mode set to <code>addressing_mode::clamp_to_edge</code>, <code>addressing_mode::clamp</code>, <code>addressing_mode::none</code>, otherwise the values returned are undefined.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>element_type image::sample(const sampler &amp;s, float_coord coord, float lod) const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Reads a color value from non-multisample image using sampler and floating point coordinates in the mip-level specified by <code>lod</code>.</p>
+</div>
+<div class="paragraph">
+<p>Method is present for non-multisample images if the <strong>cl_khr_mipmap_image</strong> extension is enabled.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>element_type image::sample(const sampler &amp;s, float_coord coord,
+                           gradient_coord gradient_x,
+                           gradient_coord gradient_y) const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Use the gradients to compute the lod and coordinate <code>coord</code> to do an element lookup in the mip-level specified by the computed lod.</p>
+</div>
+<div class="paragraph">
+<p>Method is present if the <strong>cl_khr_mipmap_image</strong> extension is enabled.</p>
+</div>
+<div class="paragraph">
+<p>Based on the parameters with which image was created on host side the
+function will return different ranges of values</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>returns floating-point values in the range [0.0, 1.0] for image objects created with <code>image_channel_type</code> set to one of the pre-defined packed formats or <code>image_channel_type::unorm_int8</code> or <code>image_channel_type::unorm_int16</code>.</p>
+</li>
+<li>
+<p>returns floating-point values in the range [-1.0, 1.0] for image objects created with <code>image_channel_type::snorm_int8</code> or <code>image_channel_type::snorm_int16</code>.</p>
+</li>
+<li>
+<p>returns floating-point values for image objects created with <code>image_channel_type::float16</code> or <code>image_channel_type::float32</code>.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Values returned by <code>image::sample</code> where <code>T</code> is a floating-point type for image objects with <code>image_channel_type</code> values not specified in the description above are undefined.</p>
+</div>
+<div class="paragraph">
+<p>The <code>image::sample</code> functions that take an image object where <code>T</code> is a signed integer type can only be used with image objects created with:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>image_channel_type::sint8</code>,</p>
+</li>
+<li>
+<p><code>image_channel_type::sint16</code> and</p>
+</li>
+<li>
+<p><code>image_channel_type::sint32</code>.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If the <code>image_channel_type</code> is not one of the above values, the values returned by <code>image::sample</code> are undefined.</p>
+</div>
+<div class="paragraph">
+<p>The <code>image::sample</code> functions that take an image object where <code>T</code> is an unsigned integer type can only be used with image objects created with:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>image_channel_type::uint8</code>,</p>
+</li>
+<li>
+<p><code>image_channel_type::uint16</code> and</p>
+</li>
+<li>
+<p><code>image_channel_type::uint32</code>.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If the <code>image_channel_type</code> is not one of the above values, the values returned by <code>image::sample</code> are undefined.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="imageread">image::read</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>element_type image::read(integer_coord coord) const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Reads a color value from non-multisample image without sampler and integral coordinates.
+If the <strong>cl_khr_mipmap_image</strong> extension is present, may also perform reads from mipmap layer 0.</p>
+</div>
+<div class="paragraph">
+<p>The image read function behaves exactly as the corresponding image sample function using a sampler
+that has filter mode set to <code>filtering_mode::nearest</code>, normalized coordinates set to
+<code>normalized_coordinates::unnormalized</code> and addressing mode set to  <code>addressing_mode::none</code>.
+There is one execption for cases where the image sample type is <code>image_channel_type::fp32</code>.
+In this exceptional case, when channel data values are denormalized, the image read function may return
+the denormalized data, while the sample function may flush denormalized channel data values to zero.
+The coordinates must be between 0 and image size in that dimension non inclusive.</p>
+</div>
+<div class="paragraph">
+<p>Based on the parameters with which image was created on host side the function will return different ranges of values</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>returns floating-point values in the range [0.0, 1.0] for image objects created with <code>image_channel_type</code> set to one of the pre-defined packed formats or <code>image_channel_type::unorm_int8</code> or <code>image_channel_type::unorm_int16</code>.</p>
+</li>
+<li>
+<p>returns floating-point values in the range [-1.0, 1.0] for image objects created with <code>image_channel_type::snorm_int8</code> or <code>image_channel_type::snorm_int16</code>.</p>
+</li>
+<li>
+<p>returns floating-point values for image objects created with <code>image_channel_type::float16</code> or <code>image_channel_type::float32</code>.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Values returned by <code>image::read</code> where <code>T</code> is a floating-point type for image objects with <code>image_channel_type</code> values not specified in the description above are undefined.</p>
+</div>
+<div class="paragraph">
+<p>The <code>image::read</code> functions that take an image object where <code>T</code> is a signed integer type can only be used with image objects created with:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>image_channel_type::sint8</code>,</p>
+</li>
+<li>
+<p><code>image_channel_type::sint16</code> and</p>
+</li>
+<li>
+<p><code>image_channel_type::sint32</code>.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If the <code>image_channel_type</code> is not one of the above values, the values returned by <code>image::read</code> are undefined.</p>
+</div>
+<div class="paragraph">
+<p>The <code>image::read</code> functions that take an image object where <code>T</code> is an unsigned integer type can only be used with image objects created with <code>image_channel_type</code> set to one of the following values:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>image_channel_type::uint8</code>,</p>
+</li>
+<li>
+<p><code>image_channel_type::uint16</code> and</p>
+</li>
+<li>
+<p><code>image_channel_type::uint32</code>.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If the <code>image_channel_type</code> is not one of the above values, the values returned by <code>image::read</code> are undefined.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>element_type image::read(integer_coord coord, int sample) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Use the coordinate and sample to do an element lookup in the image object.
+Method is only available in the MSAA image types, and if the <strong>cl_khr_gl_msaa_sharing</strong> and <strong>cl_khr_gl_depth_images</strong> extensions are enabled.</p>
+</div>
+<div class="paragraph">
+<p>When a multisample image is accessed in a kernel, the access takes one vector of integers describing which pixel to fetch and an integer corresponding to the sample numbers describing which sample within the pixel to fetch.
+<code>sample</code> identifies the sample position in the multi-sample image.</p>
+</div>
+<div class="paragraph">
+<p>For best performance, we recommend that sample be a literal value so it is known at compile time and the OpenCL compiler can perform appropriate optimizations for multisample reads on the device.</p>
+</div>
+<div class="paragraph">
+<p>No standard sampling instructions are allowed on the multisample image.
+Accessing a coordinate outside the image and/or a sample that is outside the number of samples associated with each pixel in the image is undefined.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="imagewrite">image::write</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>void image::write(integer_coord coord, element_type color) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Writes a color value to location specified by coordinates from non-multisample image.
+If the <strong>cl_khr_mipmap_image_writes</strong> extension is present, may also perform writes to mipmap layer 0.
+The coordinates must be between 0 and image size in that dimension non inclusive.</p>
+</div>
+<div class="paragraph">
+<p>Based on the parameters with which image was created on host side the function will perform appropriate data format conversions before writing a color value.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>void image::write(integer_coord coord, element_type color, int lod) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Writes a color value to location specified by coordinates and lod from mipmap image.
+The coordinates must be between 0 and image size in that dimension non inclusive.</p>
+</div>
+<div class="paragraph">
+<p>Method is present if the <strong>cl_khr_mipmap_image</strong> extension is enabled.</p>
+</div>
+<div class="paragraph">
+<p>Based on the parameters with which image was created on host side the function will perform appropriate data format conversions before writing a color value.</p>
+</div>
+<div class="paragraph">
+<p>The <code>image::write</code> functions that take an image object where <code>T</code> is a floating-point type can only be used with image objects created with <code>image_channel_type</code> set to one of the pre-defined packed formats or set to:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>image_channel_type::snorm_int8</code></p>
+</li>
+<li>
+<p><code>image_channel_type::unorm_int8</code></p>
+</li>
+<li>
+<p><code>image_channel_type::snorm_int16</code></p>
+</li>
+<li>
+<p><code>image_channel_type::unorm_int16</code></p>
+</li>
+<li>
+<p><code>image_channel_type::float16</code></p>
+</li>
+<li>
+<p><code>image_channel_type::float32</code></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The <code>image::write</code> functions that take an image object where <code>T</code> is a signed integer type can only be used with image objects created with:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>image_channel_type::sint8</code></p>
+</li>
+<li>
+<p><code>image_channel_type::sint16</code></p>
+</li>
+<li>
+<p><code>image_channel_type::sint32</code></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The <code>image::write</code> functions that take an image object where <code>T</code> is an unsigned integer type can only be used with image objects created with:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>image_channel_type::uint8</code></p>
+</li>
+<li>
+<p><code>image_channel_type::uint16</code></p>
+</li>
+<li>
+<p><code>image_channel_type::uint32</code></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The behavior of <code>image::write</code> for image objects created with
+<code>image_channel_type</code> values not specified in the description above is undefined.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="imageoperator">\image::operator[]</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>pixel operator[](integer_coord coord) noexcept;
+
+pixel operator[](integer_coord coord) const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Creates a pixel which can be used to read or/and write operation(s).
+It depends on image_access specified in the image.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+The pixel stores a reference to image and coordinates.
+This operation can consume more private memory than <code>image::read</code> and <code>image::write</code> methods.
+It can also negatively impact performance.
+</td>
+</tr>
+</table>
+</div>
+</div>
+<div class="sect4">
+<h5 id="imagepixeloperator-element_type">image::pixel::operator element_type</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>element_type pixel::operator element_type() const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Reads a color value from non-multisample image without sampler and integral coordinates specified in pixel.
+If the <strong>cl_khr_mipmap_image</strong> extension is present, may also perform reads from mipmap layer 0.</p>
+</div>
+<div class="paragraph">
+<p>This function is similar to <code>image::read</code> method.
+Please refer to description of this method for more details.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="imagepixeloperator">image::pixel::operator=</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>pixel &amp; pixel::operator=(element_type color) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Writes a color value to location specified by coordinates in pixel from non-multisample image.
+If the <strong>cl_khr_mipmap_image_writes</strong> extension is present, may also perform writes to mipmap layer 0.
+The coordinates specified in pixel must be between 0 and image size in that dimension non inclusive.</p>
+</div>
+<div class="paragraph">
+<p>Based on the parameters with which image was created on host side the function will perform appropriate data format conversions before writing a color value.</p>
+</div>
+<div class="paragraph">
+<p>This function is similar to <code>image::write</code> method.
+Please refer to description of this method for more details.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="imagewidth">image::width</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int width() const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns width of the image.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int width(int lod) const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns width of the mip-level specified by <code>lod</code>.</p>
+</div>
+<div class="paragraph">
+<p>Method is present in the non-multisample image types if the <strong>cl_khr_mipmap_image</strong> extension is enabled.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="imageheight">image::height</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int height() const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns height of the image.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int height(int lod) const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns height of the mip-level specified by <code>lod</code>.</p>
+</div>
+<div class="paragraph">
+<p>Method is present in the non-multisample image types if the <strong>cl_khr_mipmap_image</strong> extension is enabled.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="imagedepth">image::depth</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int depth() const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns depth of the image.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int depth(int lod) const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns depth of the mip-level specified by <code>lod</code>.</p>
+</div>
+<div class="paragraph">
+<p>Method is present in the non-multisample image types if the <strong>cl_khr_mipmap_image</strong> extension is enabled.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="imagearray_size">image::array_size</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int array_size() const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns size of the image array.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int array_size(int lod) const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns size of the image array specified by <code>lod</code>.</p>
+</div>
+<div class="paragraph">
+<p>Method is present in the non-multisample image types if the <strong>cl_khr_mipmap_image</strong> extension is enabled.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="imagesize">image::size</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>integer_coord size() const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns appropriately sized vector, or scalar for 1 dimensional images, containing all image dimensions followed by array size.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="imagedata_type">image::data_type</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>image_channel_type image::data_type() const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns format of the image as specified upon its creation on host side.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="imageorder">image::order</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>image_channel_order image::order() const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns channel order of the image as specified upon its creation on host side.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="imagemiplevels">image::miplevels</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int miplevels() const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns number of mipmaps of image.
+Method is present if the <strong>cl_khr_mipmap_image</strong> or <strong>cl_khr_mipmap_image_writes</strong> extension is enabled.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="imagenum_samples">image::num_samples</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int num_samples() const noexcept;</code></pre>
+</div>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="sampler">3.11.9. Sampler</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+struct sampler: marker_type
+{
+    sampler() = delete;
+    sampler(const sampler&amp;) = default;
+    sampler(sampler&amp;&amp;) = default;
+
+    sampler&amp; operator=(const sampler&amp;) = delete;
+    sampler&amp; operator=(sampler&amp;&amp;) = delete;
+    sampler* operator&amp;() = delete;
+
+};
+
+template &lt;addressing_mode A, normalized_coordinates C, filtering_mode F&gt;
+constexpr sampler make_sampler();
+
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>There are only two ways of acquiring a sampler inside of a kernel. One is to pass it as a kernel parameter from host using <code>clSetKernelArg</code>, the other one is to create one using make_sampler function in the kernel code. <code>make_sampler</code> function has three template parameters specifying behavior of sampler. Once acquired sampler can only be passed by reference as all other marker types. The sampler objects at non-program scope must be declared with static specifier.</p>
+</div>
+<div class="paragraph">
+<p>The maximum number of samplers that can be declared in a kernel can be queried using the <code>CL_DEVICE_MAX_SAMPLERS</code> token in <code>clGetDeviceInfo</code>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="sampler-modes">3.11.10. Sampler Modes</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+enum class addressing_mode
+{
+    mirrored_repeat,
+    repeat,
+    clamp_to_edge,
+    clamp,
+    none
+};
+
+enum class normalized_coordinates
+{
+    normalized,
+    unnormalized
+};
+
+enum class filtering_mode
+{
+    nearest,
+    linear
+};
+
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The following tables describe the inline sampler parameters and their behavior.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 12. Addressing modes</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Addressing mode</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>mirrored_repeat</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Out of range coordinates will be flipped at every integer junction. This addressing mode can only be used with normalized coordinates. If normalized coordinates are not used, this addressing mode may generate image coordinates that are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>repeat</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Out of range image coordinates are wrapped to the valid range. This addressing mode can only be used with normalized coordinates. If normalized coordinates are not used, this addressing mode may generate image coordinates that are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>clamp_to_edge</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Out of range image coordinates are clamped to the extent.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>clamp</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Out of range image coordinates will return a border color.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>none</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">For this addressing mode the programmer guarantees that the image coordinates used to sample elements of the image refer to a location inside the image; otherwise the results are undefined.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>For 1D and 2D image arrays, the addressing mode applies only to the <em>x</em> and (<em>x, y</em>) coordinates.  The addressing mode for the coordinate which specifies the array index is always clamp_to_edge.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 13. Normalized coordinates</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Normalized Coordinate Values</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>normalized</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Specifies whether the <em>x</em>, <em>y</em> and <em>z</em> coordinates are passed in as normalized values.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>unnormalized</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Specifies whether the <em>x</em>, <em>y</em> and <em>z</em> coordinates are passed in as unnormalized values.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>Sampling from an image with samplers that differ in specification of coordinates normalization result in undefined behavior.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 14. Coordinate filtering modes</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Filtering mode</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>nearest</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Chooses a color of nearest pixel.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>linear</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Performs a linear sampling of adjacent pixels.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>Refer to <em>section 4.2</em> in the OpenCL API specification for a description of these filter modes.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="determining-the-border-color-or-value">3.11.11. Determining the border color or value</h4>
+<div class="paragraph">
+<p>If <code>&lt;addressing mode&gt;</code> in sampler is clamp, then out-of-range image coordinates return the border color. The border color selected depends on the image channel order and can be one of the following values:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>If the image channel order is <code>image_channel_order::a</code>, <code>image_channel_order::intensity</code>, <code>image_channel_order::rx</code>, <code>image_channel_order::ra</code>, <code>image_channel_order::rgx</code>, <code>image_channel_order::rgbx</code>, <code>image_channel_order::srgbx</code>, <code>image_channel_order::argb</code>, <code>image_channel_order::bgra</code>, <code>image_channel_order::abgr</code>, <code>image_channel_order::rgba</code>, <code>image_channel_order::srgba</code> or <code>image_channel_order::sbgra</code>, the border color is (0.0f, 0.0f, 0.0f, 0.0f).</p>
+</li>
+<li>
+<p>If the image channel order is <code>image_channel_order::r</code>, <code>image_channel_order::rg</code>, <code>image_channel_order::rgb</code>, or <code>image_channel_order::luminance</code>, the border color is (0.0f, 0.0f, 0.0f, 1.0f).</p>
+</li>
+<li>
+<p>If the image channel order is <code>image_channel_order::depth</code>, the border value is 0.0f.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="srgb-images">3.11.12. sRGB Images</h4>
+<div class="paragraph">
+<p>The built-in image read functions perform sRGB to linear RGB conversions if the image is an sRGB image. Writes to sRGB images from a kernel is an optional extension. The <strong>cl_khr_srgb_image_writes</strong> extension will be reported in the <code>CL_DEVICE_EXTENSIONS</code> string if a device supports writing to sRGB images using <code>image::write</code>. <code>clGetSupportedImageFormats</code> will return the supported sRGB images if <code>CL_MEM_READ_WRITE</code> or <code>CL_MEM_WRITE_ONLY</code> is specified in <code>flags</code> argument and the device supports writing to an sRGB image. If the <strong>cl_khr_srgb_image_writes</strong> extension is supported and has been enabled, the built-in image write functions perform the linear to sRGB conversion.</p>
+</div>
+<div class="paragraph">
+<p>Only the R, G and B components are converted from linear to sRGB and vice-versa. The alpha component is returned as is.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="reading-and-writing-to-the-same-image-in-a-kernel">3.11.13. Reading and writing to the same image in a kernel</h4>
+<div class="paragraph">
+<p>To read and write to the same image in a kernel, the image must be declared with the <code>image_access::read_write</code>. Only sampler-less reads and write functions can be called on an image declared with the <code>image_access::read_write</code> access qualifier. Calling the <code>image::sample</code> functions on an image declared with the <code>image_access::read_write</code> will result in a compilation error.</p>
+</div>
+<div class="paragraph">
+<p>The <code>atomic_fence</code> function from the <a href="#fences"><em>Atomic Fences</em></a> section can be used to make sure that writes are visible to later reads by the same work-item. Without use of the <code>atomic_fence</code> function, write-read coherence on image objects is not guaranteed: if a work-item reads from an image to which it has previously written without an intervening atomic_fence, it is not guaranteed that those previous writes are visible to the work-item. Only a scope of <code>memory_order_acq_rel</code> is valid for <code>atomic_fence</code> when passed the <code>mem_fence::image</code> flag.  If multiple work-items are writing to and reading from multiple locations in an image, the <code>work_group_barrier</code> from the <a href="#synchronization-functions"><em>Synchronization Functions</em></a> section should be used.</p>
+</div>
+<div class="paragraph">
+<p>Consider the following example:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_work_item&gt;
+#include &lt;opencl_atomic&gt;
+#include &lt;opencl_image&gt;
+using namespace cl;
+
+kernel void foo(image2d&lt;float4, image_access::read_write&gt; img, ... ) {
+    int2 coord;
+    coord.x = (int)get_global_id(0);
+    coord.y = (int)get_global_id(1);
+
+    float4 clr = img.read(coord);
+    //...
+    img.write(coord, clr);
+
+    // required to ensure that following read from image at
+    // location coord returns the latest color value.
+    atomic_fence(mem_fence::image,
+     memory_order_acq_rel,
+     memory_scope_work_item);
+
+    float4 clr_new = img.read(coord);
+    //...
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="mapping-image-channels-to-color-values-returned-by-imagesample-imageread-and-color-values-passed-to-imagewrite-to-image-channels">3.11.14. Mapping image channels to color values returned by image::sample, image::read and color values passed to image::write to image channels</h4>
+<div class="paragraph">
+<p>The following table describes the mapping of the number of channels of an image element to the appropriate components in the <code>float4</code>, <code>int4</code> or <code>uint4</code> vector data type for the color values returned by <code>image::sample</code>, <code>image::read</code> or supplied to <code>image::write</code>. The unmapped components will be set to 0.0 for red, green and blue channels and will be set to 1.0 for the alpha channel.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 15. Image channel mappings</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Image Channel Order</strong></th>
+<th class="tableblock halign-left valign-top"><strong>float4, int4 or uint4 components of channel data</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">r, rx</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">(r, 0.0, 0.0, 1.0)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">a</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">(0.0, 0.0, 0.0, a)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">rg, rgx</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">(r, g, 0.0, 1.0)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">ra</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">(r, 0.0, 0.0, a)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">rgb, rgbx, srgb, srgbx</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">(r, g, b, 1.0)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">rgba, bgra, argb, abgr, srgba, sbgra</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">(r, g, b, a)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">intensity</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">(I, I, I, I)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">luminance</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">(L, L, L, 1.0)</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>For <code>image_channel_order::depth</code> images, a scalar value is returned by <code>image::sample</code>, <code>image::read</code> or supplied to <code>image::write</code>.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+A kernel that uses a sampler with the clamp addressing mode with multiple images may result in additional samplers being used internally by an implementation. If the same sampler is used with multiple images called via <code>image::sample</code>, then it is possible that an implementation may need to allocate an additional sampler to handle the different border color values that may be needed depending on the image formats being used.  The implementation allocated samplers will count against the maximum sampler values supported by the device and given by <code>CL_DEVICE_MAX_SAMPLERS</code>. Enqueuing a kernel that requires more samplers than the implementation can support will result in a <code>CL_OUT_OF_RESOURCES</code> error being returned.
+</td>
+</tr>
+</table>
+</div>
+</div>
+<div class="sect3">
+<h4 id="restrictions-4">3.11.15. Restrictions</h4>
+<div class="ulist">
+<ul>
+<li>
+<p>The image and sampler types cannot be used with variables declared inside a class or union field, a pointer type, an array, global variables declared at program scope or the return type of a function.</p>
+</li>
+<li>
+<p>The image and sampler types cannot be used with the <code>global</code>, <code>local</code>, <code>priv</code> and <code>constant</code> address space storage classes (see the <a href="#explicit-address-space-storage-classes"><em>Explicit address space storage classes</em></a> section).</p>
+</li>
+<li>
+<p>The values returned by applying the <code>sizeof</code> operator to the image and sampler types are implementation-defined.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="examples-5">3.11.16. Examples</h4>
+<div class="sect4">
+<h5 id="example-1-5">Example 1</h5>
+<div class="paragraph">
+<p>The example how to use an image object with sampler-less reads.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_image&gt;
+#include &lt;opencl_work_item&gt;
+using namespace cl;
+
+kernel void foo(image2d&lt;float4, image_access::read&gt; img) {
+    int2 coord;
+    coord.x = get_global_id(0);
+    coord.y = get_global_id(1);
+
+    float4 val = img.read(coord);
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="example-2-3">Example 2</h5>
+<div class="paragraph">
+<p>The example how to use an image object with <code>image_access::read_write</code> access and <code>atomic_fence</code> function.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_image&gt;
+#include &lt;opencl_atomic&gt;
+#include &lt;opencl_work_item&gt;
+using namespace cl;
+
+kernel void foo(image2d&lt;float4, image_access::read_write&gt; img) {
+    int2 coord;
+    coord.x = get_global_id(0);
+    coord.y = get_global_id(1);
+
+    float4 val1{0.5f};
+    img[coord] = val1;
+
+    atomic_fence(mem_fence::image, memory_order_acq_rel,
+                 memory_scope_work_item);
+
+    float4 val2 = img[coord];
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="example-3-2">Example 3</h5>
+<div class="paragraph">
+<p>The example how to use an image object with sampler passed by a kernel argument.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_image&gt;
+#include &lt;opencl_work_item&gt;
+using namespace cl;
+
+kernel void foo(image2d&lt;float4, image_access::sample&gt; img, sampler s) {
+    int2 coord;
+    coord.x = get_global_id(0);
+    coord.y = get_global_id(1);
+
+    float4 val = img.sample(s, coord);
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="example-4-1">Example 4</h5>
+<div class="paragraph">
+<p>The example how to use an image object with sampler declared at program scope.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_image&gt;
+#include &lt;opencl_work_item&gt;
+using namespace cl;
+
+sampler s = make_sampler&lt;addressing_mode::clamp,
+                         normalized_coordinates::unnormalized,
+                         filtering_mode::nearest&gt;();
+
+kernel void foo(image2d&lt;float4, image_access::sample&gt; img) {
+    int2 coord;
+    coord.x = get_global_id(0);
+    coord.y = get_global_id(1);
+
+    float4 val = img.sample(s, coord);
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="example-5-1">Example 5</h5>
+<div class="paragraph">
+<p>The example how to use an image object with sampler declared at non-program scope.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_image&gt;
+#include &lt;opencl_work_item&gt;
+using namespace cl;
+
+kernel void foo(image2d&lt;float4, image_access::sample&gt; img) {
+    int2 coord;
+    coord.x = get_global_id(0);
+    coord.y = get_global_id(1);
+
+    static sampler s = make_sampler&lt;addressing_mode::clamp,
+                                    normalized_coordinates::unnormalized,
+                                    filtering_mode::nearest&gt;();
+
+    float4 val = img.sample(s, coord);
+}</code></pre>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="pipes-library">3.12. Pipes Library</h3>
+<div class="paragraph">
+<p>Header <em>&lt;opencl_pipe&gt;</em> defines <code>pipe</code> and <code>pipe_storage</code> template classes.
+<code>pipe</code> and <code>pipe_storage</code> can be used as a communication channel between kernels.
+<code>pipe</code>, <code>reservation</code> and <code>pipe_storage</code>  template classes follow all the rules for marker types as specified in the <a href="#marker-types"><em>Marker Types</em></a> section.</p>
+</div>
+<div class="sect3">
+<h4 id="pipe-host-type">3.12.1. Pipe Host Type</h4>
+<div class="paragraph">
+<p>The below describes the OpenCL pipe data type and the corresponding data type available to the application:</p>
+</div>
+<table id="host_pipe_type" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 16. Host pipe type</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Type in OpenCL C++</strong></th>
+<th class="tableblock halign-left valign-top"><strong>API type for application</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl::pipe</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_pipe</code></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="header-opencl_pipe-synopsis">3.12.2. Header &lt;opencl_pipe&gt; Synopsis</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+enum class pipe_access { read, write };
+
+template &lt;class T, pipe_access Access = pipe_access::read&gt;
+struct pipe;
+
+template &lt;class T, size_t N&gt;
+struct pipe_storage;
+
+template&lt;pipe_access Access = pipe_access::read, class T, size_t N&gt;
+pipe&lt;T, Access&gt; make_pipe(const pipe_storage&lt;T, N&gt;&amp; ps);
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="pipe-class-specializations">3.12.3. pipe class specializations</h4>
+<div class="paragraph">
+<p><code>pipe</code> class has two distinct specializations depending on <code>pipe_access</code> parameter defined as follows:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+template &lt;class T, pipe_access Access = pipe_access::read&gt;
+struct pipe: marker_type
+{
+    typedef T element_type;
+    static constexpr pipe_access access = Access;
+
+    template&lt;memory_scope S&gt;
+    struct reservation: marker_type
+    {
+        reservation() = delete;
+        reservation(const reservation&amp;) = default;
+        reservation(reservation&amp;&amp;) = default;
+
+        reservation&amp; operator=(const reservation&amp;) = delete;
+        reservation&amp; operator=(reservation&amp;&amp;) = delete;
+        reservation* operator&amp;() = delete;
+
+        bool is_valid() const noexcept;
+        bool read(uint index, T&amp; ref) const noexcept;
+        void commit() noexcept;
+
+        explicit operator bool() const noexcept;
+    };
+
+    pipe() = delete;
+    pipe(const pipe&amp;) = default;
+    pipe(pipe&amp;&amp;) = default;
+
+    pipe&amp; operator=(const pipe&amp;) = delete;
+    pipe&amp; operator=(pipe&amp;&amp;) = delete;
+    pipe* operator&amp;() = delete;
+
+    bool read(T&amp; ref) const noexcept;
+    reservation&lt;memory_scope_work_item&gt; reserve(
+                                               uint num_packets) const noexcept;
+    reservation&lt;memory_scope_work_group&gt; work_group_reserve(
+                                               uint num_packets) const noexcept;
+    reservation&lt;memory_scope_sub_group&gt; sub_group_reserve(
+                                               uint num_packets) const noexcept;
+
+    uint num_packets() const noexcept;
+    uint max_packets() const noexcept;
+};
+
+template &lt;class T&gt;
+struct pipe&lt;T, pipe_access::write&gt;: marker_type
+{
+    typedef T element_type;
+    static constexpr pipe_access access = pipe_access::write;
+
+    template&lt;memory_scope S&gt;
+    struct reservation: marker_type
+    {
+        reservation() = delete;
+        reservation(const reservation &amp;) = default;
+        reservation(reservation &amp;&amp;) = default;
+
+        reservation&amp; operator=(const reservation &amp;) noexcept = delete;
+        reservation&amp; operator=(reservation &amp;&amp;) noexcept = delete;
+        reservation* operator&amp;() = delete;
+
+        bool is_valid() const noexcept;
+        bool write(uint index, const T&amp; ref) noexcept;
+        void commit() noexcept;
+
+        explicit operator bool() const noexcept;
+    };
+
+    pipe() = delete;
+    pipe(const pipe&amp;) = default;
+    pipe(pipe&amp;&amp;) = default;
+
+    pipe&amp; operator=(const pipe&amp;) = delete;
+    pipe&amp; operator=(pipe&amp;&amp;) = delete;
+    pipe* operator&amp;() = delete;
+
+    bool write(const T&amp; ref) noexcept;
+    reservation&lt;memory_scope_work_item&gt; reserve(uint num_packets) noexcept;
+    reservation&lt;memory_scope_work_group&gt; work_group_reserve(
+                                                     uint num_packets) noexcept;
+    reservation&lt;memory_scope_sub_group&gt; sub_group_reserve(
+                                                     uint num_packets) noexcept;
+
+    uint num_packets() const noexcept;
+    uint max_packets() const noexcept;
+};
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="pipe-class-methods">3.12.4. pipe class methods</h4>
+<div class="sect4">
+<h5 id="piperead">pipe::read</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>bool read(T&amp; ref) const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Read packet from pipe into <code>ref</code>.</p>
+</div>
+<div class="paragraph">
+<p>Returns <code>true</code> if read is successful and <code>false</code> if the pipe is empty.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="pipewrite">pipe::write</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>bool write(const T&amp; ref) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Write packet specified by <code>ref</code> to pipe.
+Returns <code>true</code> if write is successful and <code>false</code> if the pipe is full.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="pipereserve">pipe::reserve</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>reservation reserve(uint num_packets) const noexcept;
+
+reservation reserve(uint num_packets) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Reserve <code>num_packets</code> entries for reading/writing from/to pipe.
+Returns a valid reservation if the reservation is successful.</p>
+</div>
+<div class="paragraph">
+<p>The reserved pipe entries are referred to by indices that go from <code>0 &#8230;&#8203; num_packets - 1</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="pipework_group_reserve">pipe::work_group_reserve</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>reservation work_group_reserve(uint num_packets) const noexcept;
+
+reservation work_group_reserve(uint num_packets) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Reserve <code>num_packets</code> entries for reading/writing from/to pipe.
+Returns a valid reservation if the reservation is successful.</p>
+</div>
+<div class="paragraph">
+<p>The reserved pipe entries are referred to by indices that go from <code>0 &#8230;&#8203; num_packets - 1</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="pipesub_group_reserve">pipe::sub_group_reserve</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>reservation sub_group_reserve(uint num_packets) const noexcept;
+
+reservation sub_group_reserve(uint num_packets) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Reserve <code>num_packets</code> entries for reading/writing from/to pipe.
+Returns a valid reservation if the reservation is successful.</p>
+</div>
+<div class="paragraph">
+<p>The reserved pipe entries are referred to by indices that go from <code>0 &#8230;&#8203; num_packets - 1</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="pipenum_packets">pipe::num_packets</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>uint num_packets() const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the current number of packets that have been written to the pipe, but have not yet been read from the pipe.
+The number of available entries in a pipe is a dynamic value.
+The value returned should be considered immediately stale.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="pipemax_packets">pipe::max_packets</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>uint max_packets() const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the maximum number of packets specified when pipe was created.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="pipereservationread">pipe::reservation::read</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>bool pipe::reservation::read(uint index, T&amp; ref) const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Read packet from the reserved area of the pipe referred to by <code>index</code> into <code>ref</code>.</p>
+</div>
+<div class="paragraph">
+<p>The reserved pipe entries are referred to by indices that go from <code>0 &#8230;&#8203; num_packets - 1</code>.</p>
+</div>
+<div class="paragraph">
+<p>Returns <code>true</code> if read is successful and <code>false</code> otherwise.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="pipereservationwrite">pipe::reservation::write</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>bool pipe::reservation::write(uint index, const T&amp; ref) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Write packet specified by <code>ref</code> to the reserved area of the pipe referred to by <code>index</code>.</p>
+</div>
+<div class="paragraph">
+<p>The reserved pipe entries are referred to by indices that go from <code>0 &#8230;&#8203; num_packets - 1</code>.</p>
+</div>
+<div class="paragraph">
+<p>Returns <code>true</code> if write is successful and <code>false</code> otherwise.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="pipereservationcommit">pipe::reservation::commit</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>void pipe::reservation::commit() const noexcept;
+
+void pipe::reservation::commit() noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Indicates that all reads/writes to <code>num_packets</code> associated with reservation are completed.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="pipereservationis_valid">pipe::reservation::is_valid</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>bool pipe::reservation::is_valid();</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Return <code>true</code> if reservation is a valid reservation and <code>false</code> otherwise.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="pipereservationoperator-bool">pipe::reservation::operator bool</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>explicit pipe::reservation::operator bool() const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Return <code>true</code> if reservation is a valid reservation and <code>false</code> otherwise.</p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="pipe_storage-class">3.12.5. pipe_storage class</h4>
+<div class="paragraph">
+<p>The lifetime of <code>pipe_storage</code> objects is the same as a program where they were declared.
+The variables of such type are not shared across devices.</p>
+</div>
+<div class="paragraph">
+<p><code>N</code> in the <code>pipe_storage</code> template class specifies the maximum number of packets which can be held by an object.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+template&lt;class T, size_t N&gt;
+struct pipe_storage: marker_type
+{
+    pipe_storage();
+    pipe_storage(const pipe_storage&amp;) = default;
+    pipe_storage(pipe_storage&amp;&amp;) = default;
+
+    pipe_storage&amp; operator=(const pipe_storage&amp;) = delete;
+    pipe_storage&amp; operator=(pipe_storage&amp;&amp;) = delete;
+    pipe_storage* operator&amp;() = delete;
+
+    template&lt;pipe_access Access = pipe_access::read&gt;
+    pipe&lt;T, Access&gt; get() const noexcept
+};
+
+template&lt;pipe_access Access = pipe_access::read, class T, size_t N&gt;
+pipe&lt;T, Access&gt; make_pipe(const pipe_storage&lt;T, N&gt;&amp; ps);
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="pipe_storage-class-methods-and-make_pipe-function">3.12.6. pipe_storage class methods and make_pipe function</h4>
+<div class="sect4">
+<h5 id="pipe_storageget">pipe_storage::get</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template&lt;pipe_access Access = pipe_access::read&gt;
+pipe&lt;T, Access&gt; get() noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Constructs a read only or write only pipe from <code>pipe_storage</code> object.
+One kernel can have only one pipe accessor associated with one <code>pipe_storage</code> object.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="make_pipe">make_pipe</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template&lt;pipe_access Access = pipe_access::read, class T, size_t N&gt;
+pipe&lt;T, Access&gt; make_pipe(const pipe_storage&lt;T, N&gt;&amp; ps);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Constructs a read only or write only pipe from <code>pipe_storage</code> object.
+One kernel can have only one pipe accessor associated with one <code>pipe_storage</code> object.</p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="operations-ordering-using-reservations">3.12.7. Operations ordering using reservations</h4>
+<div class="paragraph">
+<p>The <code>reservation::read</code> and <code>reservation::write</code> pipe functions can be used to read from or write to a packet index.
+These functions can be used to read from or write to a packet index one or multiple times.
+If a packet index that is reserved for writing is not written to using the <code>reservation::write</code> method, the contents of that packet in the pipe are undefined.
+<code>reservation::commit</code> remove the entries reserved for reading from the pipe.
+<code>reservation::commit</code> ensures that the entries reserved for writing are all added in-order as one contiguous set of packets to the pipe.</p>
+</div>
+<div class="paragraph">
+<p>There can only be <code>CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS</code> (refer to <em>Table 4.3</em>) reservations active (i.e. reservations that have been reserved but not committed) per work-item or work-group for a pipe in a kernel executing on a device.</p>
+</div>
+<div class="paragraph">
+<p>Work-item based reservations made by a work-item are ordered in the pipe as they are ordered in the program.
+Reservations made by different work-items that belong to the same work-group can be ordered using the work-group barrier function.
+The order of work-item based reservations that belong to different work-groups is implementation defined.</p>
+</div>
+<div class="paragraph">
+<p>Work-group based reservations made by a work-group are ordered in the pipe as they are ordered in the program.
+The order of work-group based reservations by different work-groups is implementation defined.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="requirements">3.12.8. Requirements</h4>
+<div class="sect4">
+<h5 id="data">Data</h5>
+<div class="paragraph">
+<p>Template parameter <code>T</code> in <code>pipe</code> and <code>pipe_storage</code> class template denotes the data type stored in pipe.
+The type <code>T</code> must be a POD type i.e. satisfy <code>is_pod&lt;T&gt;::value == true</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="work-group-operations">Work-group operations</h5>
+<div class="paragraph">
+<p>All work-group specific functions must be encountered by all work items in a work-group executing the kernel with the same argument values, otherwise the behavior is undefined.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="sub-group-operations">Sub-group operations</h5>
+<div class="paragraph">
+<p>All sub-group specific functions must be encountered by all work items in a sub-group executing the kernel with the same argument values, otherwise the behavior is undefined.</p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="restrictions-5">3.12.9. Restrictions</h4>
+<div class="sect4">
+<h5 id="pipe">pipe</h5>
+<div class="ulist">
+<ul>
+<li>
+<p>The <code>pipe</code> type cannot be used with variables declared inside a class or union field, a pointer type, an array, global variables declared at program scope or the return type of a function.</p>
+</li>
+<li>
+<p>A kernel cannot read from and write to the same pipe object.</p>
+</li>
+<li>
+<p>The <code>pipe</code> type cannot be used with the <code>global</code>, <code>local</code>, <code>priv</code> and <code>constant</code> address space storage classes (see the <a href="#explicit-address-space-storage-classes"><em>Explicit address space storage classes</em></a> section).</p>
+</li>
+<li>
+<p>The value returned by applying the <code>sizeof</code> operator to the <code>pipe</code> type is implementation-defined.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect4">
+<h5 id="reservation">reservation</h5>
+<div class="ulist">
+<ul>
+<li>
+<p>The <code>reservation</code> type cannot be used with variables declared inside a class or union field, a pointer type, an array, global variables declared at program scope or the return type of a function.</p>
+</li>
+<li>
+<p>The <code>reservation</code> type cannot be used with the <code>global</code>, <code>local</code>, <code>priv</code> and <code>constant</code> address space storage classes (see the <a href="#explicit-address-space-storage-classes"><em>Explicit address space storage classes</em></a> section).</p>
+</li>
+<li>
+<p>The value returned by applying the <code>sizeof</code> operator to the <code>reservation</code> type is implementation-defined.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The following behavior is undefined:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>A kernel calls <code>reservation::read</code> or <code>reservation::write</code> with a valid reservation but with an index that is not a value from <code>0 &#8230;&#8203; num_packets - 1</code> specified to the corresponding call to <code>pipe::reserve</code>, <code>pipe::work_group_reserve</code> or <code>pipe::sub_group_reserve</code>.</p>
+</li>
+<li>
+<p>A kernel calls <code>reservation::read</code> or <code>reservation::write</code> with a reservation that has already been committed (i.e. a <code>reservation::commit</code> with this reservation has already been called).</p>
+</li>
+<li>
+<p>The contents of the reserved data packets in the pipe are undefined if the kernel does not call <code>reservation::write</code> for all entries that were reserved by the corresponding call to <code>pipe::reserve</code>, <code>pipe::work_group_reserve</code> or <code>pipe::sub_group_reserve</code>.</p>
+</li>
+<li>
+<p>Calls to <code>reservation::read</code> and <code>reservation::commit</code> or <code>reservation::write</code> and <code>reservation::commit</code> for a given reservation must be called by the same kernel that made the reservation using <code>pipe::reserve</code>, <code>pipe::work_group_reserve</code> or <code>pipe::sub_group_reserve</code>. The reservation cannot be passed to another kernel including child kernels.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect4">
+<h5 id="pipe_storage">pipe_storage</h5>
+<div class="ulist">
+<ul>
+<li>
+<p>Variables of type <code>pipe_storage</code> can only be declared at program scope or with the static specifier.</p>
+</li>
+<li>
+<p>The <code>pipe_storage</code> type cannot be used as a class or union field, a pointer type, an array or the return type of a function.</p>
+</li>
+<li>
+<p>The <code>pipe_storage</code> type cannot be used with the <code>global</code>, <code>local</code>, <code>priv</code> and <code>constant</code> address space storage classes (see the <a href="#explicit-address-space-storage-classes"><em>Explicit address space storage classes</em></a> section).</p>
+</li>
+<li>
+<p>The value returned by applying the <code>sizeof</code> operator to the <code>pipe_storage</code> type is implementation-defined.</p>
+</li>
+<li>
+<p>Variables of type <code>pipe</code> created from <code>pipe_storage</code> can only be declared inside a kernel function at kernel scope.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The following behavior is undefined:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>A kernel cannot contain more than one <code>pipe</code> accessor made from one <code>pipe_storage</code> object. Otherwise behavior is undefined.</p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="examples-6">3.12.10. Examples</h4>
+<div class="sect4">
+<h5 id="example-1-6">Example 1</h5>
+<div class="paragraph">
+<p>Example of reading from a pipe object.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_pipe&gt;
+using namespace cl;
+
+kernel void reader(pipe&lt;int&gt; p) {
+    int val;
+    if(p.read(val)) {
+        //...
+    }
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="example-2-4">Example 2</h5>
+<div class="paragraph">
+<p>Example of writing to a pipe object.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_pipe&gt;
+using namespace cl;
+
+kernel void writer(pipe&lt;int, pipe_access::write&gt; p) {
+    //...
+    int val;
+    if(p.write(val)) {
+        //...
+    }
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="example-3-3">Example 3</h5>
+<div class="paragraph">
+<p>Example of reading from a pipe object using reservations.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_pipe&gt;
+using namespace cl;
+
+kernel void reader(pipe&lt;int, pipe_access::read&gt; p) {
+    int val;
+    auto rid = p.reserve(1);
+    if(rid.read(0, val)) {
+        //...
+    }
+    rid.commit();
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="example-4-2">Example 4</h5>
+<div class="paragraph">
+<p>Example of using a pipe_storage object and how to create the pipe objects/accessors from it.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_pipe&gt;
+
+cl::pipe_storage &lt;int, 100&gt; myProgramPipe0;
+
+kernel void producer() {
+    cl::pipe&lt;int, cl::pipe_access::write&gt; p =
+   myProgramPipe0.get&lt;cl::pipe_access::write&gt;();
+    //...
+    p.write(...);
+}
+
+kernel void consumer() {
+    cl::pipe&lt;int, cl::pipe_access::read&gt; p =
+  myProgramPipe0.get&lt;cl::pipe_access::read&gt;();
+    if(p.read(...)) {
+        //...
+    }
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="example-5-2">Example 5</h5>
+<div class="paragraph">
+<p>Example of using more than one pipe_storage object.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_pipe&gt;
+using namespace cl;
+
+pipe_storage&lt;int2, 20&gt; myProgramPipe2;
+pipe_storage&lt;float, 40&gt; myProgramPipe3;
+
+kernel void input() {
+    auto p = make_pipe&lt;pipe_access::write&gt;(myProgramPipe2);
+    //...
+    p.write(...);
+}
+
+kernel void processor() {
+    auto p_in = make_pipe&lt;pipe_access::read&gt;(myProgramPipe2);
+    auto p_out = make_pipe&lt;pipe_access::write&gt;(myProgramPipe3);
+    ...
+    if(p_in.read(...)) {
+        //...
+    }
+    p_out.write(...);
+}
+
+kernel void output() {
+    auto p = make_pipe&lt;pipe_access::read&gt;(myProgramPipe3);
+    if(p.read(...)) {
+        //...
+    }
+}</code></pre>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="device-enqueue-library">3.13. Device Enqueue Library</h3>
+<div class="paragraph">
+<p>OpenCL C++ device enqueue functionality allows a kernel to enqueue the same device, without host interaction.
+A kernel may enqueue code represented by lambda syntax, and control execution order with event dependencies including user events and markers.
+<code>device_queue</code> follows all the rules for marker types as specified in the <a href="#marker-types"><em>Marker Types</em></a> section.</p>
+</div>
+<div class="sect3">
+<h4 id="queue-host-type">3.13.1. Queue Host Type</h4>
+<div class="paragraph">
+<p>The below table describes the OpenCL queue data type and the corresponding data type available to the application:</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 17. Host queue type</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Type in OpenCL C++</strong></th>
+<th class="tableblock halign-left valign-top"><strong>API type for application</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl::device_queue</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cl_queue</code></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="header-opencl_device_queue-synopsis">3.13.2. Header &lt;opencl_device_queue&gt; Synopsis</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+enum class enqueue_status;
+enum class enqueue_policy;
+enum class event_status;
+enum class event_profiling_info;
+
+struct event
+{
+    event();
+    event(const event&amp;) = default;
+    event(event&amp;) = default;
+
+    event&amp; operator=(const event&amp;) = default;
+    event&amp; operator=(event&amp;&amp;) = default;
+
+    bool is_valid() const noexcept;
+    void retain() noexcept;
+    void release() noexcept;
+
+    explicit operator bool() const noexcept;
+
+    void set_status(event_status status) noexcept;
+    void profiling_info(event_profiling_info name,
+                        global_ptr&lt;long&gt; value) noexcept;
+};
+
+event make_user_event();
+
+struct ndrange
+{
+    explicit ndrange(size_t global_work_size) noexcept;
+    ndrange(size_t global_work_size,
+            size_t local_work_size) noexcept;
+    ndrange(size_t global_work_offset,
+            size_t global_work_size,
+            size_t local_work_size) noexcept;
+
+    template &lt;size_t N&gt;
+    ndrange(const size_t (&amp;global_work_size)[N]) noexcept;
+    template &lt;size_t N&gt;
+    ndrange(const size_t (&amp;global_work_size)[N],
+            const size_t (&amp;local_work_size)[N]) noexcept;
+    template &lt;size_t N&gt;
+    ndrange(const size_t (&amp;global_work_offset)[N],
+            const size_t (&amp;global_work_size)[N],
+            const size_t (&amp;local_work_size)[N]) noexcept;
+};
+
+struct device_queue: marker_type
+{
+    device_queue() noexcept = delete;
+    device_queue(const device_queue&amp;) = default;
+    device_queue(device_queue&amp;&amp;) = default;
+
+    device_queue&amp; operator=(const device_queue&amp;) = delete;
+    device_queue&amp; operator=(device_queue&amp;&amp;) = delete;
+    device_queue* operator&amp;() = delete;
+
+    template &lt;class Fun, class... Args&gt;
+    enqueue_status enqueue_kernel(enqueue_policy flag,
+                                  const ndrange &amp;ndrange,
+                                  Fun fun,
+                                  Args... args) noexcept;
+
+    template &lt;class Fun, class... Args&gt;
+    enqueue_status enqueue_kernel(enqueue_policy flag,
+                                  uint num_events_in_wait_list,
+                                  const event *event_wait_list,
+                                  event *event_ret,
+                                  const ndrange &amp;ndrange,
+                                  Fun fun,
+                                  Args... args) noexcept;
+
+    enqueue_status enqueue_marker(uint num_events_in_wait_list,
+                                  const event *event_wait_list,
+                                  event *event_ret) noexcept;
+};
+
+device_queue get_default_device_queue();
+
+template &lt;class Fun, class... Args&gt;
+uint get_kernel_work_group_size(Fun fun, Args... args);
+template &lt;class Fun, class... Args&gt;
+uint get_kernel_preferred_work_group_size_multiple(Fun fun,
+                                                   Args... args);
+template &lt;class Fun, class... Args&gt;
+uint get_kernel_sub_group_count_for_ndrange(const ndrange &amp;ndrange,
+                                            Fun fun,
+                                            Args... args);
+template &lt;class Fun, class... Args&gt;
+uint get_kernel_max_sub_group_size_for_ndrange(const ndrange &amp;ndrange,
+                                               Fun fun,
+                                               Args... args);
+template &lt;class Fun, class... Args&gt;
+uint get_kernel_local_size_for_sub_group_count(uint num_sub_groups,
+                                               Fun fun,
+                                               Args... args);
+template &lt;class Fun, class... Args&gt;
+uint get_kernel_max_num_sub_groups(Fun fun, Args... args);
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="device_queue-class-methods">3.13.3. device_queue class methods</h4>
+<div class="paragraph">
+<p><code>device_queue</code> object represents work queue of the device.
+Device queue meets all requirements of the marker types as in the <a href="#marker-types"><em>Marker Types</em></a> section.</p>
+</div>
+<div class="sect4">
+<h5 id="enqueue_kernel">device_queue::enqueue_kernel</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template &lt;class Fun, class... Args&gt;
+enqueue_status enqueue_kernel(enqueue_policy policy,
+                              const ndrange &amp;ndrange,
+                              Fun fun,
+                              Args... args) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>This method allows to enqueue functor or lambda <code>fun</code> on the device with specified <code>policy</code> over the specified <code>ndrange</code>.</p>
+</div>
+<div class="paragraph">
+<p><code>args</code> are the arguments that will be passed to <code>fun</code> when kernel will be enqueued with the exception for <code>local_ptr</code> parameters.
+For local pointers user must supply the size of local memory that will be allocated using <code>local_ptr&lt;T&gt;::size_type\{num elements}</code>.
+Please see examples how to use <code>enqueue_kernel</code> are in the <a href="#examples-7"><em>Examples</em></a> section.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template &lt;class Fun, class... Args&gt;
+enqueue_status enqueue_kernel(enqueue_policy policy,
+                              uint num_events_in_wait_list,
+                              const event *event_wait_list,
+                              event *event_ret,
+                              const ndrange &amp;ndrange,
+                              Fun fun,
+                              Args... args) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>This method enqueues functor or lambda <code>fun</code> in the same way as the overload above with the exception for the passed event list.
+If an event is returned, <code>enqueue_kernel</code> performs an implicit retain on the returned event.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="enqueue_marker">device_queue::enqueue_marker</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>enqueue_status enqueue_marker(uint num_events_in_wait_list,
+                              const event *event_wait_list,
+                              event *event_ret) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>This method enqueues a marker to device queue.
+The marker command waits for a list of events specified by <code>event_wait_list</code> to complete before the marker completes.
+<code>event_ret</code> must not be <code>nullptr</code> as otherwise this is a no-op.</p>
+</div>
+<div class="paragraph">
+<p>If an event is returned, <code>enqueue_marker</code> performs an implicit retain on the returned event.</p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="event-class-methods">3.13.4. event class methods</h4>
+<div class="sect4">
+<h5 id="is_valid">event::is_valid</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>bool is_valid() const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>true</code> if event object is a valid event.
+Otherwise returns <code>false</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="operator-bool">event::operator bool</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>explicit operator bool() const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>true</code> if event object is a valid event.
+Otherwise returns <code>false</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="retain">event::retain</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>void retain() noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Increments the event reference count.
+Event must be an event returned by <code>enqueue_kernel</code> or <code>enqueue_marker</code> or a user event.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="release">event::release</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>void release() noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Decrements the event reference count.
+The event object is deleted once the event reference count is zero, the specific command identified by this event has completed (or terminated) and there are no commands in any device command queue that require a wait for this event to complete.
+Event must be an event returned by <code>enqueue_kernel</code>, <code>enqueue_marker</code> or a user event.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="set_status">event::set_status</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>void set_status(event_status status) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Sets the execution status of a user event.
+Event must be a user event.
+<code>status</code> can be either <code>event_status::complete</code> or <code>event_status::error</code> value indicating an error.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="profiling_info">event::profiling_info</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>void profiling_info(event_profiling_info name,
+                    global_ptr&lt;long&gt; value) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Captures the profiling information for functions that are enqueued as commands.
+The specific function being referred to is: <code>enqueue_kernel</code>.
+These enqueued commands are identified by unique event objects.
+The profiling information will be available in <code>value</code> once the command identified by event has completed.
+Event must be an event returned by <code>enqueue_kernel</code>.</p>
+</div>
+<div class="paragraph">
+<p><code>name</code> identifies which profiling information is to be queried and can be:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>event_profiling_info::exec_time</code></p>
+<div class="paragraph">
+<p><code>value</code> is a pointer to two 64-bit values.</p>
+</div>
+<div class="paragraph">
+<p>The first 64-bit value describes the elapsed time <code>CL_PROFILING_COMMAND_END - CL_PROFILING_COMMAND_START</code> for the command identified by event in nanoseconds.</p>
+</div>
+<div class="paragraph">
+<p>The second 64-bit value describes the elapsed time <code>CL_PROFILING_COMMAND_COMPLETE - CL_PROFILING_COMMAND_START</code> for the command identified by event in nanoseconds.</p>
+</div>
+</li>
+</ul>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+<code>profiling_info</code> when called multiple times for the same event is undefined.
+</td>
+</tr>
+</table>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="other-operations">3.13.5. Other operations</h4>
+<div class="sect4">
+<h5 id="get_default_device_queue">get_default_device_queue</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>device_queue get_default_device_queue();</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the default device queue.
+If a default device queue has not been created, <code>device_queue::is_valid()</code> will return <code>false</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="make_user_event">make_user_event</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>event make_user_event();</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Creates a user event.
+Returns the user event.
+The execution status of the user event created is set to <code>event_status::submitted</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="get_kernel_work_group_size">get_kernel_work_group_size</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template &lt;class Fun, class... Args&gt;
+uint get_kernel_work_group_size(Fun fun, Args... args);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>This provides a mechanism to query the maximum work-group size that can be used to execute a functor on the current device.</p>
+</div>
+<div class="paragraph">
+<p><code>fun</code> specifies the functor representing the kernel code that would be enqueued.</p>
+</div>
+<div class="paragraph">
+<p><code>args</code> are the arguments that will be passed to <code>fun</code> when kernel will be enqueued with the exception for <code>local_ptr</code> parameters.
+For local pointers user must supply the size of local memory that will be allocated.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="get_kernel_preferred_work_group_size_multiple">get_kernel_preferred_work_group_size_multiple</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template &lt;class Fun, class... Args&gt;
+uint get_kernel_preferred_work_group_size_multiple(Fun fun,
+                                                   Args... args);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the preferred multiple of work-group size for launch.
+This is a performance hint.
+Specifying a work-group size that is not a multiple of the value returned by this query as the value of the local work size argument to enqueue will not fail to enqueue the functor for execution unless the work-group size specified is larger than the device maximum.</p>
+</div>
+<div class="paragraph">
+<p><code>fun</code> specifies the functor representing the kernel code that would be enqueued.</p>
+</div>
+<div class="paragraph">
+<p><code>args</code> are the arguments that will be passed to <code>fun</code> when kernel will be enqueued with the exception for <code>local_ptr</code> parameters.
+For local pointers user must supply the size of local memory that will be allocated.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="get_kernel_sub_group_count_for_ndrange">get_kernel_sub_group_count_for_ndrange</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template &lt;class Fun, class... Args&gt;
+uint get_kernel_sub_group_count_for_ndrange(const ndrange &amp;ndrange,
+                                            Fun fun,
+                                            Args... args);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the number of sub-groups in each work-group of the dispatch (except for the last in cases where the global size does not divide cleanly into work-groups) given the combination of the passed ndrange and functor.</p>
+</div>
+<div class="paragraph">
+<p><code>fun</code> specifies the functor representing the kernel code that would be enqueued.</p>
+</div>
+<div class="paragraph">
+<p><code>args</code> are the arguments that will be passed to <code>fun</code> when kernel will be enqueued with the exception for <code>local_ptr</code> parameters.
+For local pointers user must supply the size of local memory that will be allocated.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="get_kernel_max_sub_group_size_for_ndrange">get_kernel_max_sub_group_size_for_ndrange</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template &lt;class Fun, class... Args&gt;
+uint get_kernel_max_sub_group_size_for_ndrange(const ndrange &amp;ndrange,
+                                               Fun fun,
+                                               Args... args);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the maximum sub-group size for a functor.</p>
+</div>
+<div class="paragraph">
+<p><code>fun</code> specifies the functor representing the kernel code that would be enqueued.</p>
+</div>
+<div class="paragraph">
+<p><code>args</code> are the arguments that will be passed to <code>fun</code> when kernel will be enqueued with the exception for <code>local_ptr</code> parameters.
+For local pointers user must supply the size of local memory that will be allocated.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="get_kernel_local_size_for_sub_group_count">get_kernel_local_size_for_sub_group_count</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template &lt;class Fun, class... Args&gt;
+uint get_kernel_local_size_for_sub_group_count(uint num_sub_groups,
+                                               Fun fun,
+                                               Args... args);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns a valid local size that would produce the requested number of sub-groups such that each sub-group is complete with no partial sub-groups.</p>
+</div>
+<div class="paragraph">
+<p><code>fun</code> specifies the functor representing the kernel code that would be enqueued.</p>
+</div>
+<div class="paragraph">
+<p><code>args</code> are the arguments that will be passed to <code>fun</code> when kernel will be enqueued with the exception for <code>local_ptr</code> parameters.
+For local pointers user must supply the size of local memory that will be allocated.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="get_kernel_max_num_sub_groups">get_kernel_max_num_sub_groups</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template &lt;class Fun, class... Args&gt;
+uint get_kernel_max_num_sub_groups(Fun fun, Args... args);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Provides a mechanism to query the maximum number of sub-groups that can be used to execute the passed functor on the current device.</p>
+</div>
+<div class="paragraph">
+<p><code>fun</code> specifies the functor representing the kernel code that would be enqueued.</p>
+</div>
+<div class="paragraph">
+<p><code>args</code> are the arguments that will be passed to <code>fun</code> when kernel will be enqueued with the exception for <code>local_ptr</code> parameters.
+For local pointers user must supply the size of local memory that will be allocated.</p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="ndrange">3.13.6. ndrange</h4>
+<div class="paragraph">
+<p><code>ndrange</code> type is used to represent the size of the enqueued workload.
+The dimension of the workload ranges from 1 to 3.
+User can specify global work size, local work size and global work offset.
+Unspecified parameters are defaulted to 0.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="enqueue-policy">3.13.7. Enqueue policy</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>enum class enqueue_policy
+{
+    no_wait,
+    wait_kernel,
+    wait_work_group
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Enqueue policy enumerable is used to specify launch policy of enqueued kernel.
+It is defined as follows:</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 18. Enqueue policy</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Policy</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>no_wait</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Indicates that the enqueued kernels do not need to wait for the parent kernel to finish execution before they begin execution.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>wait_kernel</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Indicates that all work-items of the parent kernel must finish executing and all immediate <a id="ftnref14"></a> <a href="#ftn14">[14]</a> side effects committed before the enqueued child kernel may begin execution.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>wait_work_group</code> <a id="ftnref15"></a> <a href="#ftn15">[15]</a></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Indicates that the enqueued kernels wait only for the work-group that enqueued the kernels to finish before they begin execution.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="enqueue-status">3.13.8. Enqueue status</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>enum class enqueue_status
+{
+    success,
+    failure,
+    invalid_queue,
+    invalid_ndrange,
+    invalid_event_wait_list,
+    queue_full,
+    invalid_arg_size,
+    event_allocation_failure,
+    out_of_resources
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The <code>enqueue_kernel</code> and <code>enqueue_marker</code> methods return <code>enqueue_status::success</code> if the command is enqueued successfully and return <code>enqueue_status::failure</code> otherwise.
+If the <em>-g</em> compile option is specified in compiler options passed to <code>clBuildProgram</code>, the other errors may be returned instead of <code>enqueue_status::failure</code> to indicate why <code>enqueue_kernel</code> or <code>enqueue_marker</code> failed.
+Enqueue status is defined as follows:</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 19. Enqueue status</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Status</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>success</code></p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>failure</code></p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>invalid_queue</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>queue</em> is not a valid device queue.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>invalid_ndrange</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">If <code>ndrange</code> is not a valid ND-range descriptor or if the program was compiled with <em>-cl-uniform-work-group-size</em> and the local work size is specified in <code>ndrange</code> but the global work size specified in <code>ndrange</code> is not a multiple of the local work size.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>invalid_event_wait_list</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">If <code>event_wait_list</code> is <code>nullptr</code> and <code>num_events_in_wait_list</code> &gt; 0, or if <code>event_wait_list</code> is not <code>nullptr</code> and <code>num_events_in_wait_list</code> is 0, or if <code>event</code> objects in <code>event_wait_list</code> are not valid events.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>queue_full</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">If <em>queue</em> is full.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>invalid_arg_size</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">If size of local memory arguments is 0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>event_allocation_failure</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">If <code>event_ret</code> is not <code>nullptr</code> and an event could not be allocated.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>out_of_resources</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">If there is a failure to queue the kernel in <em>queue</em> because of insufficient resources needed to execute the kernel.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="event-status">3.13.9. Event status</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>enum class event_status
+{
+    submitted,
+    complete,
+    error,
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Event status enumerable is used to set a user event status.
+It is defined as follows:</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 20. Event status</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Status</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>submitted</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Initial status of a user event</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>complete</code></p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>error</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Status indicating an error</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="determining-when-a-parent-kernel-has-finished-execution">3.13.10. Determining when a parent kernel has finished execution</h4>
+<div class="paragraph">
+<p>A parent kernel&#8217;s execution status is considered to be complete when it and all its child kernels have finished execution.
+The execution status of a parent kernel will be <code>event_status::complete</code> if this kernel and all its child kernels finish execution successfully.
+The execution status of the kernel will be <code>event_status::error</code> if it or any of its child kernels encounter an error, or are abnormally terminated.</p>
+</div>
+<div class="paragraph">
+<p>For example, assume that the host enqueues a kernel <code>k</code> for execution on a device.
+Kernel <code>k</code> when executing on the device enqueues kernels <code>A</code> and <code>B</code> to a device queue(s).
+The <code>enqueue_kernel</code> call to enqueue kernel <code>B</code> specifies the event associated with kernel <code>A</code> in the <code>event_wait_list</code> argument i.e. wait for kernel <code>A</code> to finish execution before kernel <code>B</code> can begin execution.
+Let&#8217;s assume kernel <code>A</code> enqueues kernels <code>X</code>, <code>Y</code> and <code>Z</code>.
+Kernel <code>A</code> is considered to have finished execution i.e. its execution status is <code>event_status::complete</code> only after <code>A</code> and the kernels <code>A</code> enqueued (and any kernels these enqueued kernels enqueue and so on) have finished execution.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="event-profiling-info">3.13.11. Event profiling info</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>enum class event_profiling_info
+{
+    exec_time,
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Event profiling info enumerable is used to determine the outcome of <code>event::profiling_info</code> function.
+It is defined as follows:</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 21. Event profiling info</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Status</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>exec_time</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Identifies profiling information to be queried.
+  If specified, the two 64-bit values are returned</p>
+<p class="tableblock">  The first 64-bit value describes the elapsed time: <code>CL_PROFILING_COMMAND_END - CL_PROFILING_COMMAND_START</code> for the command identified by event in nanoseconds.</p>
+<p class="tableblock">  The second 64-bit value describes the elapsed time <code>CL_PROFILING_COMMAND_COMPLETE - CL_PROFILING_COMMAND_START</code> for the command identified by event in nanoseconds.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="requirements-1">3.13.12. Requirements</h4>
+<div class="paragraph">
+<p>Functor and lambda objects passed to <code>enqueue_kernel</code> method of device queue has to follow specific restrictions:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>It has to be trivially copyable.</p>
+</li>
+<li>
+<p>It has to be trivially copy constructible.</p>
+</li>
+<li>
+<p>It has to be trivially destructible.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Code enqueuing function objects that do not meet this criteria is ill-formed.</p>
+</div>
+<div class="sect4">
+<h5 id="pointers-references-and-marker-types">Pointers, references and marker types</h5>
+<div class="paragraph">
+<p>Functors that are enqueued cannot have any reference and pointer fields, nor can have fields of marker types.
+If object containing such fields is enqueued the behavior is undefined.</p>
+</div>
+<div class="paragraph">
+<p>The same restrictions apply to <em>capture-list</em> variables in lambda.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+This requirements are caused by the fact that kernel may be enqueued after parent kernel terminated all pointers and references will be invalidated by then.
+</td>
+</tr>
+</table>
+</div>
+</div>
+<div class="sect4">
+<h5 id="events">Events</h5>
+<div class="paragraph">
+<p>Events can be used to identify commands enqueued to a command-queue from the host.
+These events created by the OpenCL runtime can only be used on the host i.e. as events passed in <code>event_wait_list</code> argument to various <code>clEnqueue</code>* APIs or runtime APIs that take events as arguments such as <code>clRetainEvent</code>, <code>clReleaseEvent</code>, <code>clGetEventProfilingInfo</code>.</p>
+</div>
+<div class="paragraph">
+<p>Similarly, events can be used to identify commands enqueued to a device queue (from a kernel).
+These event objects cannot be passed to the host or used by OpenCL runtime APIs such as the <code>clEnqueue</code>* APIs or runtime APIs that take event arguments.</p>
+</div>
+<div class="paragraph">
+<p><code>clRetainEvent</code> and <code>clReleaseEvent</code> will return <code>CL_INVALID_OPERATION</code> if event specified is an event that refers to any kernel enqueued to a device queue using <code>enqueue_kernel</code> or <code>enqueue_marker</code> or is a user event created by <code>make_user_event</code>.</p>
+</div>
+<div class="paragraph">
+<p>Similarly, <code>clSetUserEventStatus</code> can only be used to set the execution status of events created using <code>clCreateUserEvent</code>.
+User events created on the device can be set using <code>event::set_status</code> method.</p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="restrictions-6">3.13.13. Restrictions</h4>
+<div class="ulist">
+<ul>
+<li>
+<p>The <code>device_queue</code> type cannot be used with variables declared inside a class or union field, a pointer type, an array, global variables declared at program scope or the return type of a function.</p>
+</li>
+<li>
+<p>The <code>event</code> type cannot be used with variables declared inside a class or union field, global variables declared at program scope or the return type of a function.</p>
+</li>
+<li>
+<p>The <code>event</code> and <code>device_queue</code> type cannot be used with the <code>global</code>, <code>local</code>, <code>priv</code> and <code>constant</code> address space storage classes (see the <a href="#explicit-address-space-storage-classes"><em>Explicit address space storage classes</em></a> section).</p>
+</li>
+<li>
+<p>The values returned by applying the <code>sizeof</code> operator to the <code>device_queue</code> and <code>event</code> types is implementation-defined.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="examples-7">3.13.14. Examples</h4>
+<div class="sect4">
+<h5 id="example-1-7">Example 1</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_device_queue&gt;
+#include &lt;opencl_work_item&gt;
+using namespace cl;
+
+kernel void foo() {
+    auto q = get_default_device_queue();
+    q.enqueue_kernel(enqueue_policy::no_wait,
+                     ndrange( 1 ),
+                     [](){ uint tid = get_global_id(0); } );
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="example-2-5">Example 2</h5>
+<div class="paragraph">
+<p>Example of using the explicit local pointer class with <code>enqueue_kernel</code> method.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_device_queue&gt;
+#include &lt;opencl_work_item&gt;
+using namespace cl;
+
+kernel void foo(device_queue q) {
+    auto lambda = [](local_ptr&lt;ushort16&gt; p) { uint tid = get_global_id(0); };
+    q.enqueue_kernel(enqueue_policy::no_wait,
+                     ndrange{1},
+                     lambda,
+                     local_ptr&lt;ushort16&gt;::size_type{1});
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="example-3-4">Example 3</h5>
+<div class="paragraph">
+<p>Example of enqueuing a functor to a <code>device_queue</code> object.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_device_queue&gt;
+#include &lt;opencl_work_item&gt;
+using namespace cl;
+
+struct Lambda {
+    template &lt;typename T&gt;
+    void operator ()(T t) const { uint tid = get_global_id(0); }
+};
+
+kernel void foo(device_queue q) {
+    auto lambda = Lambda{};
+    q.enqueue_kernel(enqueue_policy::no_wait,
+                     ndrange{1},
+                     lambda,
+                     local_ptr&lt;ushort16&gt;::size_type{1});
+}</code></pre>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="work-item-functions">3.14. Work-Item Functions</h3>
+<div class="paragraph">
+<p>This section describes the library of work-item functions that can be used to query the number of dimensions, the global and local work size specified to <code>clEnqueueNDRangeKernel</code>, and the global and local identifier of each work-item when this kernel is being executed on a device.</p>
+</div>
+<div class="sect3">
+<h4 id="header-opencl_work_item-synopsis">3.14.1. Header &lt;opencl_work_item&gt; Synopsis</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+uint get_work_dim();
+size_t get_global_size(uint dimindx);
+size_t get_global_id(uint dimindx);
+size_t get_local_size(uint dimindx);
+size_t get_enqueued_local_size(uint dimindx);
+size_t get_local_id(uint dimindx);
+size_t get_num_groups(uint dimindx);
+size_t get_group_id(uint dimindx);
+size_t get_global_offset(uint dimindx);
+size_t get_global_linear_id();
+size_t get_local_linear_id();
+size_t get_sub_group_size();
+size_t get_max_sub_group_size();
+size_t get_num_sub_groups();
+size_t get_enqueued_num_sub_groups();
+size_t get_sub_group_id();
+size_t get_sub_group_local_id();
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="work-item-operations">3.14.2. Work item operations</h4>
+<div class="sect4">
+<h5 id="get_work_dim">get_work_dim</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>uint get_work_dim()</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the number of dimensions in use.
+This is the value given to the <code>work_dim</code> argument specified in <code>clEnqueueNDRangeKernel</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="get_global_size">get_global_size</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>size_t get_global_size(uint dimindx)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the number of global work-items specified for dimension identified by <code>dimindx</code>.
+This value is given by the <code>global_work_size</code> argument to <code>clEnqueueNDRangeKernel</code>.
+Valid values of <code>dimindx</code> are <code>0</code> to <code>get_work_dim()-1</code>.
+For other values of <code>dimindx</code>, <code>get_global_size()</code> returns <code>1</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="get_global_id">get_global_id</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>size_t get_global_id(uint dimindx)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the unique global work-item ID value for dimension identified by <code>dimindx</code>.
+The global work-item ID specifies the work-item ID based on the number of global work-items specified to execute the kernel.
+Valid values of <code>dimindx</code> are <code>0</code> to <code>get_work_dim()-1</code>.
+For other values of <code>dimindx</code>, <code>get_global_id()</code> returns <code>0</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="get_local_size">get_local_size</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>size_t get_local_size(uint dimindx)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the number of local work-items specified in dimension identified by <code>dimindx</code>.
+This value is at most the value given by the <code>local_work_size</code> argument to <code>clEnqueueNDRangeKernel</code> if <code>local_work_size</code> is not <code>NULL</code>; otherwise the OpenCL implementation chooses an appropriate <code>local_work_size</code> value which is returned by this function.
+If the kernel is executed with a non-uniform work-group size <a id="ftnref19"></a> <a href="#ftn19">[19]</a>, calls to this built-in from some work-groups may return different values than calls to this built-in from other work-groups.</p>
+</div>
+<div class="paragraph">
+<p>Valid values of <code>dimindx</code> are <code>0</code> to <code>get_work_dim()-1</code>.
+For other values of <code>dimindx</code>, <code>get_local_size()</code> returns <code>1</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="get_enqueued_local_size">get_enqueued_local_size</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>size_t get_enqueued_local_size(uint dimindx)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the same value as that returned by <code>get_local_size(dimindx)</code> if the kernel is executed with a uniform work-group size.</p>
+</div>
+<div class="paragraph">
+<p>If the kernel is executed with a non-uniform work-group size, returns the number of local work-items in each of the work-groups that make up the uniform region of the global range in the dimension identified by <code>dimindx</code>.
+If the <code>local_work_size</code> argument to <code>clEnqueueNDRangeKernel</code> is not <code>NULL</code>, this value will match the value specified in <code>local_work_size[dimindx]</code>.
+If <code>local_work_size</code> is <code>NULL</code>, this value will match the local size that the implementation determined would be most efficient at implementing the uniform region of the global range.</p>
+</div>
+<div class="paragraph">
+<p>Valid values of <code>dimindx</code> are <code>0</code> to <code>get_work_dim()-1</code>.
+For other values of <code>dimindx</code>, <code>get_enqueued_local_size()</code> returns <code>1</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="get_local_id">get_local_id</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>size_t get_local_id(uint dimindx)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the unique local work-item ID i.e. a work-item within a specific work-group for dimension identified by <code>dimindx</code>.
+Valid values of <code>dimindx</code> are <code>0</code> to <code>get_work_dim()-1</code>.
+For other values of <code>dimindx</code>, <code>get_local_id()</code> returns <code>0</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="get_num_groups">get_num_groups</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>size_t get_num_groups(uint dimindx)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the number of work-groups that will execute a kernel for dimension identified by <code>dimindx</code>.
+Valid values of <code>dimindx</code> are <code>0</code> to <code>get_work_dim()-1</code>.
+For other values of <code>dimindx</code>, <code>get_num_groups()</code> returns <code>1</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="get_group_id">get_group_id</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>size_t get_group_id(uint dimindx)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><code>get_group_id</code> returns the work-group ID which is a number from <code>0 &#8230;&#8203; get_num_groups(dimindx)-1</code>.
+Valid values of <code>dimindx</code> are <code>0</code> to <code>get_work_dim()-1</code>.
+For other values, <code>get_group_id()</code> returns <code>0</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="get_global_offset">get_global_offset</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>size_t get_global_offset(uint dimindx)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><code>get_global_offset</code> returns the offset values specified in <code>global_work_offset</code> argument to <code>clEnqueueNDRangeKernel</code>.
+Valid values of <code>dimindx</code> are <code>0</code> to <code>get_work_dim()-1</code>.
+For other values, <code>get_global_offset()</code> returns <code>0</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="get_global_linear_id">get_global_linear_id</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>size_t get_global_linear_id()</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the work-items 1-dimensional global ID.</p>
+</div>
+<div class="paragraph">
+<p>For 1D work-groups, it is computed as:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>get_global_id(0) - get_global_offset(0)</code></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For 2D work-groups, it is computed as:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>( get_global_id(1) - get_global_offset(1)) * get_global_size(0) + (get_global_id(0) - get_global_offset(0) )</code></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For 3D work-groups, it is computed as:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>( (get_global_id(2) - get_global_offset(2) ) * get_global_size(1) * get_global_size(0)) + ( (get_global_id(1) - get_global_offset(1) ) * get_global_size (0) ) + ( get_global_id(0) - get_global_offset(0) )</code>.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect4">
+<h5 id="get_local_linear_id">get_local_linear_id</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>size_t get_local_linear_id()</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the work-items 1-dimensional local ID.</p>
+</div>
+<div class="paragraph">
+<p>For 1D work-groups, it is the same value as:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>get_local_id(0)</code></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For 2D work-groups, it is computed as:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>get_local_id(1) * get_local_size(0) + get_local_id(0)</code></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For 3D work-groups, it is computed as:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>(get_local_id(2) * get_local_size(1) * get_local_size(0)) + (get_local_id(1) * get_local_size(0)) + get_local_id(0)</code></p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect4">
+<h5 id="get_sub_group_size">get_sub_group_size</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>size_t get_sub_group_size()</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the number of work-items in the sub-group.
+This value is no more than the maximum sub-group size and is implementation-defined based on a combination of the compiled kernel and the dispatch dimensions.
+This will be a constant value for the lifetime of the sub-group.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="get_max_sub_group_size">get_max_sub_group_size</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>size_t get_max_sub_group_size()</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the maximum size of a sub-group within the dispatch.
+This value will be invariant for a given set of dispatch dimensions and a kernel object compiled for a given device.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="get_num_sub_groups">get_num_sub_groups</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>size_t get_num_sub_groups()</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the number of sub-groups that the current work-group is divided into.</p>
+</div>
+<div class="paragraph">
+<p>This number will be constant for the duration of a work-group&#8217;s execution.
+If the kernel is executed with a non-uniform work-group size <a href="#ftn17">[17]</a> values for any dimension, calls to this built-in from some work-groups may return different values than calls to this built-in from other work-groups.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="get_enqueued_num_sub_groups">get_enqueued_num_sub_groups</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>size_t get_enqueued_num_sub_groups()</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the same value as that returned by <code>get_num_sub_groups()</code> if the kernel is executed with a uniform work-group size.</p>
+</div>
+<div class="paragraph">
+<p>If the kernel is executed with a non-uniform work-group size, returns the number of sub groups in each of the work groups that make up the uniform region of the global range.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="get_sub_group_id">get_sub_group_id</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>size_t get_sub_group_id()</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><code>get_sub_group_id()</code> returns the sub-group ID which is a number from <code>0 &#8230;&#8203; get_num_sub_groups()-1</code>.</p>
+</div>
+<div class="paragraph">
+<p>For <code>clEnqueueTask</code>, this returns <code>0</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="get_sub_group_local_id">get_sub_group_local_id</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>size_t get_sub_group_local_id()</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the unique work-item ID within the current sub-group.
+The mapping from <code>get_local_id(dimindx)</code> to <code>get_sub_group_local_id()</code> will be invariant for the lifetime of the work-group.</p>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="work-group-functions">3.15. Work-group Functions</h3>
+<div class="paragraph">
+<p>The OpenCL C++ library implements the following functions that operate on a work-group level.
+These built-in functions must be encountered by all work-items in a work-group executing the kernel.</p>
+</div>
+<div class="paragraph">
+<p>Here <code>gentype</code> matches: <code>int</code>, <code>uint</code>, <code>long</code>, <code>ulong</code>, <code>float</code>, <code>half</code> <a id="ftnref4"></a> <a href="#ftn4">[4]</a> or <code>double</code> <a id="ftnref18"></a> <a href="#ftn18">[18]</a>.</p>
+</div>
+<div class="sect3">
+<h4 id="header-opencl_work_group-synopsis">3.15.1. Header &lt;opencl_work_group&gt; Synopsis</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+enum class work_group_op { add, min, max };
+
+//logical operations
+bool work_group_all(bool predicate);
+bool work_group_any(bool predicate);
+bool sub_group_all(bool predicate);
+bool sub_group_any(bool predicate);
+
+//broadcast functions
+int work_group_broadcast(int a, size_t local_id);
+uint work_group_broadcast(uint a, size_t local_id);
+long work_group_broadcast(long a, size_t local_id);
+ulong work_group_broadcast(ulong a, size_t local_id);
+float work_group_broadcast(float a, size_t local_id);
+#ifdef cl_khr_fp16
+half work_group_broadcast(half a, size_t local_id);
+#endif
+#ifdef cl_khr_fp64
+double work_group_broadcast(double a, size_t local_id);
+#endif
+
+int work_group_broadcast(int a, size_t local_id_x, size_t local_id_y);
+uint work_group_broadcast(uint a, size_t local_id_x, size_t local_id_y);
+long work_group_broadcast(long a, size_t local_id_x, size_t local_id_y);
+ulong work_group_broadcast(ulong a, size_t local_id_x, size_t local_id_y);
+float work_group_broadcast(float a, size_t local_id_x, size_t local_id_y);
+#ifdef cl_khr_fp16
+half work_group_broadcast(half a, size_t local_id_x, size_t local_id_y);
+#endif
+#ifdef cl_khr_fp64
+double work_group_broadcast(double a, size_t local_id_x, size_t local_id_y);
+#endif
+
+int work_group_broadcast(int a, size_t local_id_x, size_t local_id_y,
+                         size_t local_id_z);
+uint work_group_broadcast(uint a, size_t local_id_x, size_t local_id_y,
+                          size_t local_id_z);
+long work_group_broadcast(long a, size_t local_id_x, size_t local_id_y,
+                          size_t local_id_z);
+ulong work_group_broadcast(ulong a, size_t local_id_x, size_t local_id_y,
+                           size_t local_id_z);
+float work_group_broadcast(float a, size_t local_id_x, size_t local_id_y,
+                           size_t local_id_z);
+#ifdef cl_khr_fp16
+half work_group_broadcast(half a, size_t local_id_x, size_t local_id_y,
+                          size_t local_id_z);
+#endif
+#ifdef cl_khr_fp64
+double work_group_broadcast(double a, size_t local_id_x, size_t local_id_y,
+                            size_t local_id_z);
+#endif
+
+int sub_group_broadcast(int a, size_t sub_group_local_id);
+uint sub_group_broadcast(uint a, size_t sub_group_local_id);
+long sub_group_broadcast(long a, size_t sub_group_local_id);
+ulong sub_group_broadcast(ulong a, size_t sub_group_local_id);
+float sub_group_broadcast(float a, size_t sub_group_local_id);
+#ifdef cl_khr_fp16
+half sub_group_broadcast(half a, size_t sub_group_local_id);
+#endif
+#ifdef cl_khr_fp64
+double sub_group_broadcast(double a, size_t sub_group_local_id);
+#endif
+
+//numeric operations
+template &lt;work_group_op op&gt; int work_group_reduce(int x);
+template &lt;work_group_op op&gt; uint work_group_reduce(uint x);
+template &lt;work_group_op op&gt; long work_group_reduce(long x);
+template &lt;work_group_op op&gt; ulong work_group_reduce(ulong x);
+template &lt;work_group_op op&gt; float work_group_reduce(float x);
+#ifdef cl_khr_fp16
+template &lt;work_group_op op&gt; half work_group_reduce(half x);
+#endif
+#ifdef cl_khr_fp64
+template &lt;work_group_op op&gt; double work_group_reduce(double x);
+#endif
+
+template &lt;work_group_op op&gt; int work_group_scan_exclusive(int x);
+template &lt;work_group_op op&gt; uint work_group_scan_exclusive(uint x);
+template &lt;work_group_op op&gt; long work_group_scan_exclusive(long x);
+template &lt;work_group_op op&gt; ulong work_group_scan_exclusive(ulong x);
+template &lt;work_group_op op&gt; float work_group_scan_exclusive(float x);
+#ifdef cl_khr_fp16
+template &lt;work_group_op op&gt; half work_group_scan_exclusive(half x);
+#endif
+#ifdef cl_khr_fp64
+template &lt;work_group_op op&gt; double work_group_scan_exclusive(double x);
+#endif
+
+template &lt;work_group_op op&gt; int work_group_scan_inclusive(int x);
+template &lt;work_group_op op&gt; uint work_group_scan_inclusive(uint x);
+template &lt;work_group_op op&gt; long work_group_scan_inclusive(long x);
+template &lt;work_group_op op&gt; ulong work_group_scan_inclusive(ulong x);
+template &lt;work_group_op op&gt; float work_group_scan_inclusive(float x);
+#ifdef cl_khr_fp16
+template &lt;work_group_op op&gt; half work_group_scan_inclusive(half x);
+#endif
+#ifdef cl_khr_fp64
+template &lt;work_group_op op&gt; double work_group_scan_inclusive(double x);
+#endif
+
+template &lt;work_group_op op&gt; int sub_group_reduce(int x);
+template &lt;work_group_op op&gt; uint sub_group_reduce(uint x);
+template &lt;work_group_op op&gt; long sub_group_reduce(long x);
+template &lt;work_group_op op&gt; ulong sub_group_reduce(ulong x);
+template &lt;work_group_op op&gt; float sub_group_reduce(float x);
+#ifdef cl_khr_fp16
+template &lt;work_group_op op&gt; half sub_group_reduce(half x);
+#endif
+#ifdef cl_khr_fp64
+template &lt;work_group_op op&gt; double sub_group_reduce(double x);
+#endif
+
+template &lt;work_group_op op&gt; int sub_group_scan_exclusive(int x);
+template &lt;work_group_op op&gt; uint sub_group_scan_exclusive(uint x);
+template &lt;work_group_op op&gt; long sub_group_scan_exclusive(long x);
+template &lt;work_group_op op&gt; ulong sub_group_scan_exclusive(ulong x);
+template &lt;work_group_op op&gt; float sub_group_scan_exclusive(float x);
+#ifdef cl_khr_fp16
+template &lt;work_group_op op&gt; half sub_group_scan_exclusive(half x);
+#endif
+#ifdef cl_khr_fp64
+template &lt;work_group_op op&gt; double sub_group_scan_exclusive(double x);
+#endif
+
+template &lt;work_group_op op&gt; int sub_group_scan_inclusive(int x);
+template &lt;work_group_op op&gt; uint sub_group_scan_inclusive(uint x);
+template &lt;work_group_op op&gt; long sub_group_scan_inclusive(long x);
+template &lt;work_group_op op&gt; ulong sub_group_scan_inclusive(ulong x);
+template &lt;work_group_op op&gt; float sub_group_scan_inclusive(float x);
+#ifdef cl_khr_fp16
+template &lt;work_group_op op&gt; half sub_group_scan_inclusive(half x);
+#endif
+#ifdef cl_khr_fp64
+template &lt;work_group_op op&gt; double sub_group_scan_inclusive(double x);
+#endif
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="logical-operations">3.15.2. Logical operations</h4>
+<div class="sect4">
+<h5 id="work_group_all">work_group_all</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>bool work_group_all(bool predicate)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Evaluates <code>predicate</code> for all work-items in the work-group and returns <code>true</code> if <code>predicate</code> evaluates to <code>true</code> for all work-items in the work-group.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="work_group_any">work_group_any</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>bool work_group_any(bool predicate)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Evaluates <code>predicate</code> for all work-items in the work-group and returns <code>true</code> if <code>predicate</code> evaluates to <code>true</code> for any work-items in the work-group.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="sub_group_all">sub_group_all</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>bool sub_group_all(bool predicate)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Evaluates <code>predicate</code> for all work-items in the sub-group and returns <code>true</code> value if <code>predicate</code> evaluates to <code>true</code> for all work-items in the sub-group.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="sub_group_any">sub_group_any</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>bool sub_group_any(bool predicate)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Evaluates <code>predicate</code> for all work-items in the sub-group and returns <code>true</code> value if <code>predicate</code> evaluates to <code>true</code> for any work-items in the sub-group.</p>
+</div>
+<div class="paragraph">
+<p>Example:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_work_item&gt;
+#include &lt;opencl_work_group&gt;
+using namespace cl;
+
+kernel void foo(int *p) {
+    //...
+    bool check = work_group_all(p[get_local_id(0)] == 0);
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>In this case <code>work_group_all</code> would return <code>true</code> for all work-items in work-group if all elements in <code>p</code>, in range specified by work-group&#8217;s size, are <code>true</code>.</p>
+</div>
+<div class="paragraph">
+<p>One could achieve similar result by using analogical call to <code>work_group_any</code>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_work_item&gt;
+#include &lt;opencl_work_group&gt;
+using namespace cl;
+
+kernel void foo(int *p) {
+    //...
+    bool check = !work_group_any(p[get_local_id(0)] != 0);
+}</code></pre>
+</div>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="broadcast-functions">3.15.3. Broadcast functions</h4>
+<div class="sect4">
+<h5 id="work_group_broadcast">work_group_broadcast</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype work_group_broadcast(gentype a,
+                             size_t local_id);
+
+gentype work_group_broadcast(gentype a,
+                             size_t local_id_x,
+                             size_t local_id_y);
+
+gentype work_group_broadcast(gentype a,
+                                            size_t local_id_x,
+                                            size_t local_id_y,
+                                            size_t local_id_z);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Broadcast the value of <code>a</code> for work-item identified by <code>local_id</code> to all work-items in the work-group.</p>
+</div>
+<div class="paragraph">
+<p><code>local_id</code> must be the same value for all work-items in the work-group.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="sub_group_broadcast">sub_group_broadcast</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype sub_group_broadcast(gentype a,
+                                           size_t sub_group_local_id);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Broadcast the value of <code>a</code> for work-item identified by <code>sub_group_local_id</code> (value returned by <code>get_sub_group_local_id</code>) to all work-items in the sub-group.</p>
+</div>
+<div class="paragraph">
+<p><code>sub_group_local_id</code> must be the same value for all work-items in the sub-group.</p>
+</div>
+<div class="paragraph">
+<p>Example:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_work_item&gt;
+#include &lt;opencl_work_group&gt;
+using namespace cl;
+
+kernel void foo(int *p) {
+   //...
+   int broadcasted_value = work_group_broadcast(p[get_local_id(0)], 0);
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Here we are broadcasting value passed to <code>work_group_broadcast</code> function by work-item with <code>local_id = 0</code> (which is <code>p[0]</code>).
+This function will return <code>p[0]</code> for all callers.
+Please note that <code>local_id</code> must be the same for all work-items, therefore something like this is invalid:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_work_item&gt;
+#include &lt;opencl_work_group&gt;
+using namespace cl;
+
+kernel void foo(int *p) {
+    //...
+    int broadcasted_value =
+      work_group_broadcast(p[get_local_id(0)], get_local_id(0));
+                    //invalid: second argument has different value
+                    // for different work-items in work-group
+}</code></pre>
+</div>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="numeric-operations">3.15.4. Numeric operations</h4>
+<div class="sect4">
+<h5 id="work_group_reduce">work_group_reduce</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template &lt;work_group_op op&gt;
+gentype work_group_reduce(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Return result of reduction operation specified by <code>op</code> for all values of <code>x</code> specified by work-items in a work-group.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="work_group_scan_exclusive">work_group_scan_exclusive</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template &lt;work_group_op op&gt;
+gentype work_group_scan_exclusive(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Do an exclusive scan operation specified by <code>op</code> of all values specified by work-items in the work-group.
+The scan results are returned for each work-item.</p>
+</div>
+<div class="paragraph">
+<p>The scan order is defined by increasing 1D linear global ID within the work-group.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="work_group_scan_inclusive">work_group_scan_inclusive</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template &lt;work_group_op op&gt;
+gentype work_group_scan_inclusive(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Do an inclusive scan operation specified by <code>op</code> of all values specified by work-items in the work-group.
+The scan results are returned for each work-item.</p>
+</div>
+<div class="paragraph">
+<p>The scan order is defined by increasing 1D linear global ID within the work-group.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="sub_group_reduce">sub_group_reduce</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template &lt;work_group_op op&gt;
+gentype sub_group_reduce(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Return result of reduction operation specified by <code>op</code> for all values of <code>x</code> specified by work-items in a sub-group.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="sub_group_scan_exclusive">sub_group_scan_exclusive</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template &lt;work_group_op op&gt;
+gentype sub_group_scan_exclusive(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Do an exclusive scan operation specified by <code>op</code> of all values specified by work-items in a sub-group.
+The scan results are returned for each work-item.</p>
+</div>
+<div class="paragraph">
+<p>The scan order is defined by increasing 1D linear global ID within the sub-group.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="sub_group_scan_inclusive">sub_group_scan_inclusive</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template &lt;work_group_op op&gt;
+gentype sub_group_scan_inclusive(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Do an inclusive scan operation specified by <code>op</code> of all values specified by work-items in a sub-group.
+The scan results are returned for each work-item.</p>
+</div>
+<div class="paragraph">
+<p>The scan order is defined by increasing 1D linear global ID within the sub-group.</p>
+</div>
+<div class="paragraph">
+<p>The inclusive scan operation takes a binary operator <code>op</code> with an identity I and n (where n is the size of the work-group) elements [a<sub>0</sub>, a<sub>1</sub>, &#8230;&#8203; a<sub>n-1</sub>] and returns [a<sub>0</sub>, (a<sub>0</sub> <em>op</em> a<sub>1</sub>), &#8230;&#8203; (a<sub>0</sub> <em>op</em> a<sub>1</sub> <em>op</em> &#8230;&#8203; <em>op</em> a<sub>n-1</sub>)].
+If <code>op</code> is <code>work_group_op::add</code>, the identity I is 0.
+If <code>op</code> is <code>work_group_op::min</code>, the identity I is <code>INT_MAX</code>, <code>UINT_MAX</code>, <code>LONG_MAX</code>, <code>ULONG_MAX</code>, for <code>int</code>, <code>uint</code>, <code>long</code>, <code>ulong</code> types and is <code>+INF</code> for floating-point types.
+Similarly if <code>op</code> is <code>work_group_op::max</code>, the identity I is <code>INT_MIN</code>, <code>0</code>, <code>LONG_MIN</code>, <code>0</code> and <code>-INF</code>.</p>
+</div>
+<div class="paragraph">
+<p>Consider the following example:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_work_item&gt;
+#include &lt;opencl_work_group&gt;
+using namespace cl;
+
+void foo(int *p)
+{
+    ...
+    int prefix_sum_val =
+               work_group_scan_inclusive&lt;work_group_op::add&gt;(
+    p[get_local_id(0)]);
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>For the example above, let&#8217;s assume that the work-group size is 8 and p points to the following elements [3 1 7 0 4 1 6 3].
+Work-item 0 calls <code>work_group_scan_inclusive&lt;work_group_op::add&gt;</code> with 3 and returns 3.
+Work-item 1 calls <code>work_group_scan_inclusive&lt;work_group_op::add&gt;</code> with 1 and returns 4.
+The full set of values returned by <code>work_group_scan_inclusive&lt;work_group_op::add&gt;</code> for work-items 0 &#8230;&#8203; 7 is [3 4 11 11 15 16 22 25].</p>
+</div>
+<div class="paragraph">
+<p>The exclusive scan operation takes a binary associative operator <code>op</code> with an identity I and n (where n is the size of the work-group) elements [a<sub>0</sub>, a<sub>1</sub>, &#8230;&#8203; a<sub>n-1</sub>] and returns [I, a<sub>0</sub>, (a<sub>0</sub> <em>op</em> a<sub>1</sub>), &#8230;&#8203; (a<sub>0</sub> <em>op</em> a<sub>1</sub> <em>op</em> &#8230;&#8203; <em>op</em> a<sub>n-2</sub>)].
+For the example above, the exclusive scan add operation on the ordered set [3 1 7 0 4 1 6 3] would return [0 3 4 11 11 15 16 22].</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+The order of floating-point operations is not guaranteed for the <code>work_group_reduce&lt;op&gt;</code>, <code>work_group_scan_inclusive&lt;op&gt;</code> and <code>work_group_scan_exclusive&lt;op&gt;</code> built-in functions that operate on <code>half</code>, <code>float</code> and <code>double</code> data types.
+The order of these floating-point operations is also non-deterministic for a given work-group.
+</td>
+</tr>
+</table>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="synchronization-functions">3.16. Synchronization Functions</h3>
+<div class="paragraph">
+<p>The OpenCL C++ library implements the following synchronization functions.</p>
+</div>
+<div class="sect3">
+<h4 id="header-opencl_synchronization-synopsis">3.16.1. Header &lt;opencl_synchronization&gt; Synopsis</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+void work_group_barrier(mem_fence flags,
+                        memory_scope scope = memory_scope_work_group);
+void sub_group_barrier(mem_fence flags,
+                       memory_scope scope = memory_scope_work_group);
+
+#ifdef cl_khr_subgroup_named_barrier
+struct work_group_named_barrier: marker_type
+{
+    work_group_named_barrier(uint sub_group_count);
+    work_group_named_barrier() = delete;
+    work_group_named_barrier(const work_group_named_barrier&amp;) = default;
+    work_group_named_barrier(work_group_named_barrier&amp;&amp;) = default;
+
+    work_group_named_barrier&amp; operator=(
+                                      const work_group_named_barrier&amp;) = delete;
+    work_group_named_barrier&amp; operator=(work_group_named_barrier&amp;&amp;) = delete;
+    work_group_named_barrier* operator&amp;() = delete;
+
+    void wait(mem_fence flags,
+              memory_scope scope = memory_scope_work_group) const noexcept;
+};
+
+#endif
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="synchronization-operations">3.16.2. Synchronization operations</h4>
+<div class="sect4">
+<h5 id="work_group_barrier">work_group_barrier</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>void work_group_barrier(mem_fence flags,
+                        memory_scope scope  = memory_scope_work_group);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>All work-items in a work-group executing the kernel on a processor must execute this function before any are allowed to continue execution beyond the <code>work_group_barrier</code>.
+This function must be encountered by all work-items in a work-group executing the kernel.
+These rules apply to ND-ranges implemented with uniform and non-uniform work-groups.</p>
+</div>
+<div class="paragraph">
+<p>If <code>work_group_barrier</code> is inside a conditional statement, then all work-items must enter the conditional if any work-item enters the conditional statement and executes the <code>work_group_barrier</code>.</p>
+</div>
+<div class="paragraph">
+<p>If <code>work_group_barrier</code> is inside a loop, all work-items must execute the <code>work_group_barrier</code> for each iteration of the loop before any are allowed to continue execution beyond the <code>work_group_barrier</code>.</p>
+</div>
+<div class="paragraph">
+<p>The <code>scope</code> argument specifies whether the memory accesses of work-items in the work-group to memory address space(s) identified by <code>flags</code> become visible to all work-items in the work-group, the device or all SVM devices.</p>
+</div>
+<div class="paragraph">
+<p>The <code>work_group_barrier</code> function can also be used to specify which memory operations i.e. to global memory, local memory or images become visible to the appropriate memory scope identified by <code>scope</code>.
+The <code>flags</code> argument specifies the memory address spaces.
+This is a bitfield and can be set to 0 or a combination of the following values ORed together.
+When these flags are ORed together the <code>work_group_barrier</code> acts as a combined barrier for all address spaces specified by the flags ordering memory accesses both within and across the specified address spaces.</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>mem_fence::local</code> - The <code>work_group_barrier</code> function will ensure that all local memory accesses become visible to all work-items in the work-group.
+Note that the value of <code>scope</code> is ignored as the memory scope is always <code>memory_scope_work_group</code>.</p>
+</li>
+<li>
+<p><code>mem_fence::global</code> - The <code>work_group_barrier</code> function ensure that all global memory accesses become visible to the appropriate scope as given by <code>scope</code>.</p>
+</li>
+<li>
+<p><code>mem_fence::image</code> - The <code>work_group_barrier</code> function will ensure that all image memory accesses become visible to the appropriate scope as given by <code>scope</code>.
+The value of <code>scope</code> must be <code>memory_scope_work_group</code> or <code>memory_scope_device</code>.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p><code>mem_fence::image</code> cannot be used together with <code>mem_fence::local</code> or <code>mem_fence::global</code>.</p>
+</div>
+<div class="paragraph">
+<p>The values of <code>flags</code> and <code>scope</code> must be the same for all work-items in the work-group.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="sub_group_barrier">sub_group_barrier</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>void sub_group_barrier(mem_fence flags,
+                       memory_scope scope = memory_scope_work_group);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>All work-items in a sub-group executing the kernel on a processor must execute this function before any are allowed to continue execution beyond the sub-group barrier.
+This function must be encountered by all work-items in a sub-group executing the kernel.
+These rules apply to ND-ranges implemented with uniform and non-uniform work-groups.</p>
+</div>
+<div class="paragraph">
+<p>If <code>sub_group_barrier</code> is inside a conditional statement, then all work-items within the sub-group must enter the conditional if any work-item in the sub-group enters the conditional statement and executes the <code>sub_group_barrier</code>.</p>
+</div>
+<div class="paragraph">
+<p>If <code>sub_group_barrier</code> is inside a loop, all work-items within the sub-group must execute the <code>sub_group_barrier</code> for each iteration of the loop before any are allowed to continue execution beyond the <code>sub_group_barrier</code>.</p>
+</div>
+<div class="paragraph">
+<p>The <code>sub_group_barrier</code> function also queues a memory fence (reads and writes) to ensure correct ordering of memory operations to local or global memory.</p>
+</div>
+<div class="paragraph">
+<p>The <code>flags</code> argument specifies the memory address spaces.
+This is a bitfield and can be set to 0 or a combination of the following values ORed together.
+When these flags are ORed together the <code>sub_group_barrier</code> acts as a combined barrier for all address spaces specified by the flags ordering memory accesses both within and across the specified address spaces.</p>
+</div>
+<div class="paragraph">
+<p><code>mem_fence::local</code> - The <code>sub_group_barrier</code> function will ensure that all local memory accesses become visible to all work-items in the sub-group.
+Note that the value of <code>scope</code> is ignored as the memory scope is always <code>memory_scope_work_group</code>.</p>
+</div>
+<div class="paragraph">
+<p><code>mem_fence::global</code> - The <code>sub_group_barrier</code> function ensure that all global memory accesses become visible to the appropriate scope as given by <code>scope</code>.</p>
+</div>
+<div class="paragraph">
+<p><code>mem_fence::image</code> - The <code>sub_group_barrier</code> function will ensure that all image memory accesses become visible to the appropriate scope as given by <code>scope</code>.
+The value of <code>scope</code> must be <code>memory_scope_work_group</code> or <code>memory_scope_device</code>.</p>
+</div>
+<div class="paragraph">
+<p><code>mem_fence::image</code> cannot be used together with <code>mem_fence::local</code> or <code>mem_fence::global</code>.</p>
+</div>
+<div class="paragraph">
+<p>The values of <code>flags</code> and <code>scope</code> must be the same for all work-items in the sub-group.</p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="named-barriers">3.16.3. Named barriers</h4>
+<div class="paragraph">
+<p>This section describes the optional <strong>cl_khr_sub_group_named_barrier</strong> extension which exposes the ability to perform barrier synchronization on flexible portions of an execution domain.</p>
+</div>
+<div class="paragraph">
+<p>If the <strong>cl_khr_sub_group_named_barrier</strong> extension is supported by a device, an application that wants to use it will need to define the <code>cl_khr_sub_group_named_barrier</code> macro before including the OpenCL C++ standard library headers or using the <em>-D</em> compiler option (<a href="#preprocessor_options"><em>Preprocessor options</em></a> section).</p>
+</div>
+<div class="paragraph">
+<p>An implementation shall support at least 8 named barriers per work-group.
+The exact maximum number can be queried using <code>clGetDeviceInfo</code> with <code>CL_DEVICE_MAX_NAMED_BARRIER_COUNT_KHR</code> from the OpenCL 2.2 Extension Specification.</p>
+</div>
+<div class="paragraph">
+<p>Restrictions:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>The <code>work_group_named_barrier</code> type cannot be used with variables declared inside a class or union field, a pointer type, an array, global variables declared at program scope or the return type of a function.</p>
+</li>
+<li>
+<p>The <code>work_group_named_barrier</code> type cannot be used with the <code>global</code>, <code>priv</code> and <code>constant</code> address space storage classes (see the the <a href="#explicit-address-space-storage-classes"><em>Explicit address space storage classes</em></a> section).</p>
+</li>
+<li>
+<p>The value returned by applying the <code>sizeof</code> operator to the <code>work_group_named_barrier</code> type is implementation-defined.</p>
+</li>
+</ul>
+</div>
+<div class="sect4">
+<h5 id="work_group_named_barrier">work_group_named_barrier</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>work_group_named_barrier(uint sub_group_count);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Initialize a new named barrier object to synchronize <code>sub_group_count</code> sub-groups in the current work-group.
+Construction of a named-barrier object is a work-group operation and hence must be called uniformly across the work-group.
+<code>sub_group_count</code> must be uniform across the work-group.</p>
+</div>
+<div class="paragraph">
+<p>Named barrier objects can be reconstructed and assigned to underlying entities by the compiler, or reused.
+Reused barriers will always be the same size and act in phases such that when each participating sub-group has waited the wait count is set to 0 and the entire process can start again.
+The internal wait count will cycle through the range from <code>0</code> to <code>sub_group_count</code> in each phase of use of the barrier.</p>
+</div>
+<div class="paragraph">
+<p>Named barrier objects can only be constructed within kernels, not within arbitrary functions.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="wait">wait</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>void wait(mem_fence flags,
+          memory_scope scope = memory_scope_work_group) const noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>All work-items in a sub-group executing the kernel on a processor must execute this method before any are allowed to continue execution beyond the barrier.
+This function must be encountered by all work-items in a sub-group executing the kernel.</p>
+</div>
+<div class="paragraph">
+<p>These rules apply to ND-ranges implemented with uniform and non-uniform work-groups.</p>
+</div>
+<div class="paragraph">
+<p>If <code>wait</code> is called inside a conditional statement, then all work-items within the sub-group must enter the conditional if any work-item in the sub-group enters the conditional statement and executes the call to wait.</p>
+</div>
+<div class="paragraph">
+<p>If <code>wait</code> is called inside a loop, all work-items within the sub-group must execute the wait operation for each iteration of the loop before any are allowed to continue execution beyond the call to wait.
+The wait function causes the entire sub-group to wait until <code>sub_group_count</code> sub-groups have waited on the named barrier, where <code>sub_group_count</code> is the initialization value passed to the call to the constructor of the named barrier.
+Once the wait count equals <code>sub_group_count</code>, any sub-groups waiting at the named barrier will be released and the barrier&#8217;s wait count reset to 0.</p>
+</div>
+<div class="paragraph">
+<p>The <code>flags</code> argument specifies the memory address spaces.
+This is a bitfield and can be set to 0 or a combination of the following values ORed together.
+When these flags are ORed together the wait acts as a combined wait operation for all address spaces specified by the flags ordering memory accesses both within and across the specified address spaces.</p>
+</div>
+<div class="paragraph">
+<p><code>mem_fence::local</code> - The wait function will ensure that all local memory accesses become visible to all work-items in the sub-group.
+Note that the value of <code>scope</code> is ignored as the memory scope is always <code>memory_scope_work_group</code>.</p>
+</div>
+<div class="paragraph">
+<p><code>mem_fence::global</code> - The wait function ensure that all global memory accesses become visible to the appropriate scope as given by <code>scope</code>.</p>
+</div>
+<div class="paragraph">
+<p><code>mem_fence::image</code> cannot be specified as a flag for this function.</p>
+</div>
+<div class="paragraph">
+<p>The values of <code>flags</code> and <code>scope</code> must be the same for all work-items in the sub-group.</p>
+</div>
+<div class="paragraph">
+<p>The below example shows how to use the named barriers:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_memory&gt;
+#include &lt;opencl_synchronization&gt;
+#include &lt;opencl_work_item&gt;
+
+using namespace cl;
+
+void aFunction(work_group_named_barrier &amp;b) {
+    while(...) {
+        // Do something in first set
+        b.wait(mem_fence::global);
+    }
+}
+
+kernel void aKernel() {
+    // Initialize a set of named barriers
+    local&lt;work_group_named_barrier&gt; a(4);
+    local&lt;work_group_named_barrier&gt; b(2);
+    local&lt;work_group_named_barrier&gt; c(2);
+
+    if(get_sub_group_id() &lt; 4) {
+        a.wait(mem_fence::local);
+        if(get_sub_group_id() &lt; 2) {
+            // Pass one of the named barriers to a function by reference
+            // Barrier cannot be constructed in a non-kernel function
+            aFunction(b);
+        } else {
+            // Do something else
+            c.wait(mem_fence::local);
+            // Continue
+        }
+
+        // Wait a second time on the first barrier
+        a.wait(mem_fence::global);
+    }
+
+
+    // Back to work-group uniform control flow,
+    // we can synchronize the entire group if necessary
+    work_group_barrier(mem_fence::global);
+}</code></pre>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="common-functions">3.17. Common Functions</h3>
+<div class="paragraph">
+<p>This section describes the OpenCL C++ library common functions that take scalar or vector arguments.
+Vector versions of common functions operate component-wise.
+Descriptions are always per-component.</p>
+</div>
+<div class="paragraph">
+<p>The built-in common functions are implemented using the round to nearest even rounding mode.</p>
+</div>
+<div class="paragraph">
+<p>Here <code>gentype</code> matches: <code>half<em>n</em></code> <a id="ftnref4"></a> <a href="#ftn4">[4]</a>, <code>float<em>n</em></code> or <code>double<em>n</em></code> <a id="ftnref18"></a> <a href="#ftn18">[18]</a></p>
+</div>
+<div class="sect3">
+<h4 id="header-opencl_common-synopsis">3.17.1. Header &lt;opencl_common&gt; Synopsis</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+#ifdef cl_khr_fp16
+halfn clamp(halfn x, halfn min, halfn max);
+halfn degrees(halfn t);
+halfn max(halfn x, halfn y);
+halfn min(halfn x, halfn y);
+halfn mix(halfn x, halfn y, halfn a);
+halfn radians(halfn t);
+halfn step(halfn edge, halfn x);
+halfn smoothstep(halfn edge0, halfn edge1, halfn x);
+halfn sign(halfn t);
+#endif
+
+#ifdef cl_khr_fp64
+doublen clamp(doublen x, doublen min, doublen max);
+doublen degrees(doublen t);
+doublen max(doublen x, doublen y);
+doublen min(doublen x, doublen y);
+doublen mix(doublen x, doublen y, doublen a);
+doublen radians(doublen t);
+doublen step(doublen edge, doublen x);
+doublen smoothstep(doublen edge0, doublen edge1, doublen x);
+doublen sign(doublen t);
+#endif
+
+floatn clamp(floatn x, floatn min, floatn max);
+floatn degrees(floatn t);
+floatn max(floatn x, floatn y);
+floatn min(floatn x, floatn y);
+floatn mix(floatn x, floatn y, floatn a);
+floatn radians(floatn t);
+floatn step(floatn edge, floatn x);
+floatn smoothstep(floatn edge0, floatn edge1, floatn x);
+floatn sign(floatn t);
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="common-operations">3.17.2. Common operations</h4>
+<div class="sect4">
+<h5 id="clamp-1">clamp</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype clamp(gentype x, gentype minval, gentype maxval);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>fmin(fmax(x, minval), maxval)</code>.</p>
+</div>
+<div class="paragraph">
+<p>Results are undefined if <code>minval &gt; maxval</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="degrees">degrees</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype degrees(gentype radians);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Converts radians to degrees, i.e. <code>(180 / π) * radians</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="max-1">max</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype max(gentype x, gentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>y</code> if <code>x &lt; y</code>, otherwise it returns <code>x</code>.
+If <code>x</code> or <code>y</code> are <code>infinite</code> or <code>NaN</code>, the return values are undefined.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="min-1">min</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype min(gentype x, gentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>y</code> if <code>y &lt; x</code>, otherwise it returns <code>x</code>.
+If <code>x</code> or <code>y</code> are <code>infinite</code> or <code>NaN</code>, the return values are undefined.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="mix">mix</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype mix(gentype x, gentype y, gentype a);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the linear blend of <code>x</code> and <code>y</code> implemented as:</p>
+</div>
+<div class="paragraph">
+<p><code>x + (y - x) * a</code></p>
+</div>
+<div class="paragraph">
+<p><code>a</code> must be a value in the range 0.0 &#8230;&#8203; 1.0.
+If <code>a</code> is not in the range 0.0 &#8230;&#8203; 1.0, the return values are undefined.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="radians">radians</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype radians(gentype degrees);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Converts degrees to radians, i.e. <code>(π / 180) * degrees</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="step">step</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype step(gentype edge, gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>0.0</code> if <code>x &lt; edge</code>, otherwise it returns <code>1.0</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="smoothstep">smoothstep</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype smoothstep(gentype edge0, gentype edge1, gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>0.0</code> if <code>x &lt;= edge0</code> and <code>1.0</code> if <code>x &gt;= edge1</code> and performs smooth Hermite interpolation between <code>0</code> and <code>1</code> when <code>edge0 &lt; x &lt; edge1</code>.
+This is useful in cases where you would want a threshold function with a smooth transition.</p>
+</div>
+<div class="paragraph">
+<p>This is equivalent to:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype t;
+t = clamp((x - edge0) / (edge1 - edge0), 0, 1);
+return t * t * (3 - 2 * t);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Results are undefined if <code>edge0 &gt;= edge1</code> or if <code>x</code>, <code>edge0</code> or <code>edge1</code> is a <code>NaN</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="sign">sign</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype sign(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>1.0</code> if <code>x &gt; 0</code>, <code>-0.0</code> if <code>x = -0.0</code>, <code>+0.0</code> if <code>x = 0.0</code>, or <code>-1.0</code> if <code>x &lt; 0</code>.
+Returns <code>0.0</code> if <code>x</code> is a <code>NaN</code>.</p>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="geometric-functions">3.18. Geometric Functions</h3>
+<div class="paragraph">
+<p>This section describes the OpenCL C++ library geometric functions that take scalar or vector arguments.
+Vector versions of geometric functions operate component-wise.
+Descriptions are always per-component.
+The geometric functions are implemented using the round to nearest even rounding mode.</p>
+</div>
+<div class="paragraph">
+<p><code>float<em>n</em></code> is <code>float</code>, <code>float2</code>, <code>float3</code> or <code>float4</code>.</p>
+</div>
+<div class="paragraph">
+<p><code>half<em>n</em></code> <a id="ftnref4"></a> <a href="#ftn4">[4]</a> is <code>half</code>, <code>half2</code>, <code>half3</code> or <code>half4</code>.</p>
+</div>
+<div class="paragraph">
+<p><code>double<em>n</em></code> <a id="ftnref18"></a> <a href="#ftn18">[18]</a> is <code>double</code>, <code>double2</code>, <code>double3</code> or <code>double4</code>.</p>
+</div>
+<div class="sect3">
+<h4 id="header-opencl_geometric-synopsis">3.18.1. Header &lt;opencl_geometric&gt; Synopsis</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+#ifdef cl_khr_fp16
+half3 cross(half3 p0, half3 p1);
+half4 cross(half4 p0, half4 p1);
+half dot(half p0, half p1);
+half dot(half2 p0, half2 p1);
+half dot(half3 p0, half3 p1);
+half dot(half4 p0, half4 p1);
+half distance(half p0, half p1);
+half distance(half2 p0, half2 p1);
+half distance(half3 p0, half3 p1;
+half distance(half4 p0, half4 p1);
+half length(half t);
+half length(half2 t);
+half length(half3 t);
+half length(half4 t);
+half normalize(half t);
+half2 normalize(half2 t);
+half3 normalize(half3 t);
+half4 normalize(half4 t);
+#endif
+
+#ifdef cl_khr_fp64
+double3 cross(double3 p0, double3 p1);
+double4 cross(double4 p0, double4 p1);
+double dot(double p0, double p1);
+double dot(double2 p0, double2 p1);
+double dot(double3 p0, double3 p1);
+double dot(double4 p0, double4 p1);
+double distance(double p0, double p1);
+double distance(double2 p0, double2 p1);
+double distance(double3 p0, double3 p1);
+double distance(double4 p0, double4 p1);
+double length(double t);
+double length(double2 t);
+double length(double3 t);
+double length(double4 t);
+double normalize(double t);
+double2 normalize(double2 t);
+double3 normalize(double3 t);
+double4 normalize(double4 t);
+#endif
+
+float3 cross(float3 p0, float3 p1);
+float4 cross(float4 p0, float4 p1);
+float dot(float p0, float p1);
+float dot(float2 p0, float2 p1);
+float dot(float3 p0, float3 p1);
+float dot(float4 p0, float4 p1);
+float distance(float p0, float p1);
+float distance(float2 p0, float2 p1);
+float distance(float3 p0, float3 p1);
+float distance(float4 p0, float4 p1);
+float length(float t);
+float length(float2 t);
+float length(float3 t);
+float length(float4 t);
+float normalize(float t);
+float2 normalize(float2 t);
+float3 normalize(float3 t);
+float4 normalize(float4 t);
+
+float fast_distance(float p0, float p1);
+float fast_distance(float2 p0, float2 p1);
+float fast_distance(float3 p0, float3 p1);
+float fast_distance(float4 p0, float4 p1);
+float fast_length(float t);
+float fast_length(float2 t);
+float fast_length(float3 t);
+float fast_length(float4 t);
+float fast_normalize(float t);
+float2 fast_normalize(float2 t);
+float3 fast_normalize(float3 t);
+float4 fast_normalize(float4 t);
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="geometric-operations">3.18.2. Geometric operations</h4>
+<div class="sect4">
+<h5 id="cross">cross</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>float4 cross(float4 p0, float4 p1);
+float3 cross(float3 p0, float3 p1);
+double4 cross(double4 p0, double4 p1);
+double3 cross(double3 p0, double3 p1);
+half4 cross(half4 p0, half4 p1);
+half3 cross(half3 p0, half3 p1);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the cross product of <code>p0.xyz</code> and <code>p1.xyz</code>.
+The <code>w</code> component of <code>float4</code> result returned will be <code>0.0</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="dot">dot</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>float dot(floatn p0, floatn p1);
+double dot(doublen p0, doublen p1);
+half dot(halfn p0, halfn p1);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute dot product.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="distance">distance</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>float distance(floatn p0, floatn p1);
+double distance(doublen p0, doublen p1);
+half distance(halfn p0, halfn p1);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the distance between <code>p0</code> and <code>p1</code>.</p>
+</div>
+<div class="paragraph">
+<p>This is calculated as <code>length(p0 - p1)</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="length">length</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>float length(floatn p);
+double length(doublen p);
+half length(halfn p);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Return the length of vector <code>p</code>, i.e.,
+\(\sqrt{p.x^2 + p.y^2 + \ldots}\)</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="normalize">normalize</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn normalize(floatn p);
+doublen normalize(doublen p);
+halfn normalize(halfn p);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns a vector in the same direction as <code>p</code> but with a length of <code>1</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="fast_distance">fast_distance</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>float fast_distance(floatn p0, floatn p1);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>fast_length(p0 - p1)</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="fast_length">fast_length</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>float fast_length(floatn p);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the length of vector <code>p</code> computed as:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>half_sqrt(p.x^2 + p.y^2 + ...)</code></pre>
+</div>
+</div>
+</div>
+<div class="sect4">
+<h5 id="fast_normalize">fast_normalize</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn fast_normalize(floatn p);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns a vector in the same direction as <code>p</code> but with a length of 1.
+<code>fast_normalize</code> is computed as:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>p * half_rsqrt(p.x^2 + p.y^2 + ...)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The result shall be within 8192 ulps error from the infinitely precise result of</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>if (all(p == 0.0f))
+ result = p;
+else
+ result = p / sqrt(p.x^2 + p.y^2 + ... );</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>with the following exceptions:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>If the sum of squares is greater than <code>FLT_MAX</code> then the value of the floating-point values in the result vector are undefined.</p>
+</li>
+<li>
+<p>If the sum of squares is less than <code>FLT_MIN</code> then the implementation may return back <code>p</code>.</p>
+</li>
+<li>
+<p>If the device is in &#8220;denorms are flushed to zero&#8221; mode, individual operand elements with magnitude less than <code>sqrt(FLT_MIN)</code> may be flushed to zero before proceeding with the calculation.</p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="math-functions">3.19. Math Functions</h3>
+<div class="paragraph">
+<p>,The list of the OpenCL C++ library math functions is described in <a href="#trigonometric-functions"><em>Trigonometric functions</em></a>, <a href="#logarithmic-functions"><em>Logarithmic functions</em></a>, <a href="#exponential-functions"><em>Exponential functions</em></a>, <a href="#floating-point-functions"><em>Floating-point functions</em></a>, <a href="#comparison-functions"><em>Comparison functions</em></a>, and <a href="#other-functions-1"><em>Other functions</em></a> sections.</p>
+</div>
+<div class="paragraph">
+<p>The built-in math functions are categorized into the following:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>A list of built-in functions that have scalar or vector argument versions.</p>
+</li>
+<li>
+<p>A list of built-in functions that only take scalar float arguments.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The vector versions of the math functions operate component-wise.
+The description is per-component.</p>
+</div>
+<div class="paragraph">
+<p>The built-in math functions are not affected by the prevailing rounding mode in the calling environment, and always return the same value as they would if called with the round to nearest even rounding mode.</p>
+</div>
+<div class="paragraph">
+<p>Here <code>gentype</code> matches: <code>half<em>n</em></code> <a id="ftnref4"></a> <a href="#ftn4">[4]</a>, <code>float<em>n</em></code> or <code>double<em>n</em></code> <a id="ftnref18"></a> <a href="#ftn18">[18]</a></p>
+</div>
+<div class="sect3">
+<h4 id="header-opencl_math-synopsis">3.19.1. Header &lt;opencl_math&gt; Synopsis</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+//trigonometric functions
+gentype acos(gentype x);
+gentype acosh(gentype x);
+gentype acospi(gentype x);
+gentype asin(gentype x);
+gentype asinh(gentype x);
+gentype asinpi(gentype x);
+gentype atan(gentype x);
+gentype atanh(gentype x);
+gentype atanpi(gentype x);
+gentype atan2(gentype y, gentype x);
+gentype atan2pi(gentype y, gentype x);
+gentype cos(gentype x);
+gentype cosh(gentype x);
+gentype cospi(gentype x);
+gentype sin(gentype x);
+gentype sincos(gentype x, gentype * cosval);
+gentype sinh(gentype x);
+gentype sinpi(gentype x);
+gentype tan(gentype x);
+gentype tanh(gentype x);
+gentype tanpi(gentype x);
+
+//power functions
+gentype cbrt(gentype x);
+gentype pow(gentype x, gentype y);
+gentype pown(gentype x, intn y);
+gentype powr(gentype x, gentype y);
+gentype rootn(gentype x, intn y);
+gentype rsqrt(gentype x);
+gentype sqrt(gentype x);
+
+//logarithmic functions
+intn ilogb(gentype x);
+gentype lgamma(gentype x);
+gentype lgamma_r(gentype x, intn* signp);
+gentype log(gentype x);
+gentype logb(gentype x);
+gentype log2(gentype x);
+gentype log10(gentype x);
+gentype log1p(gentype x);
+
+//exponential functions
+gentype exp(gentype x);
+gentype expm1(gentype x);
+gentype exp2(gentype x);
+gentype exp10(gentype x);
+gentype ldexp(gentype x, intn k);
+
+//floating-point functions
+gentype ceil(gentype x);
+gentype copysign(gentype x, gentype y);
+gentype floor(gentype x);
+gentype fma(gentype a, gentype b, gentype c);
+gentype fmod(gentype x, gentype y);
+gentype fract(gentype x, gentype* iptr);
+gentype frexp(gentype x, intn* exp);
+gentype modf(gentype x, gentype* iptr);
+#ifdef cl_khr_fp16
+halfn nan(ushortn nancode);
+#endif
+floatn nan(uintn nancode);
+#ifdef cl_khr_fp64
+doublen nan(ulong nancode);
+#endif
+gentype nextafter(gentype x, gentype y);
+gentype remainder(gentype x, gentype y);
+gentype remquo(gentype x, gentype y, intn* quo);
+gentype rint(gentype x);
+gentype round(gentype x);
+gentype trunc(gentype x);
+
+//comparison functions
+gentype fdim(gentype x, gentype y);
+gentype fmax(gentype x, gentype y);
+gentype fmin(gentype x, gentype y);
+gentype maxmag(gentype x, gentype y);
+gentype minmag(gentype x, gentype y);
+
+//other functions
+gentype erf(gentype x);
+gentype erfc(gentype x);
+gentype fabs(gentype x);
+gentype hypot(gentype x, gentype y);
+gentype mad(gentype a, gentype b, gentype c);
+gentype tgamma(gentype x);
+
+//native functions
+namespace native
+{
+floatn cos(floatn x);
+floatn exp(floatn x);
+floatn exp2(floatn x);
+floatn exp10(floatn x);
+floatn log(floatn x);
+floatn log2(floatn x);
+floatn log10(floatn x);
+floatn recip(floatn x);
+floatn rsqrt(floatn x);
+floatn sin(floatn x);
+floatn sqrt(floatn x);
+floatn tan(floatn x);
+floatn divide(floatn x, floatn y);
+floatn powr(floatn x, floatn y);
+
+}
+
+//half_math functions
+namespace half_math
+{
+floatn cos(floatn x);
+floatn exp(floatn x);
+floatn exp2(floatn x);
+floatn exp10(floatn x);
+floatn log(floatn x);
+floatn log2(floatn x);
+floatn log10(floatn x);
+floatn recip(floatn x);
+floatn rsqrt(floatn x);
+floatn sin(floatn x);
+floatn sqrt(floatn x);
+floatn tan(floatn x);
+floatn divide(floatn x, floatn y);
+floatn powr(floatn x, floatn y);
+
+}
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="trigonometric-functions">3.19.2. Trigonometric functions</h4>
+<div class="sect4">
+<h5 id="acos">acos</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype acos(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Arc cosine function.
+Returns an angle in radians.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="acosh">acosh</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype acosh(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Inverse hyperbolic cosine.
+Returns an angle in radians.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="acospi">acospi</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype acospi(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute acos(<code>x</code>) / π.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="asin">asin</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype asin(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Arc sine function.
+Returns an angle in radians.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="asinh">asinh</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype asinh(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Inverse hyperbolic sine.
+Returns an angle in radians.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="asinpi">asinpi</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype asinpi(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute asin(<code>x</code>) / π.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="atan">atan</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype atan(gentype y_over_x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Arc tangent function.
+Returns an angle in radians.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="atan2">atan2</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype atan2(gentype y, gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Arc tangent of <code>y / x</code>.
+Returns an angle in radians.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="atanh">atanh</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype atanh(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Hyperbolic arc tangent.
+Returns an angle in radians.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="atanpi">atanpi</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype atanpi(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute atan(<code>x</code>) / π.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="atan2pi">atan2pi</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype atan2pi(gentype y, gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute atan2(<code>y</code>, <code>x</code>) / π.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="cos">cos</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype cos(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute cosine, where <code>x</code> is an angle in radians.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="cosh">cosh</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype cosh(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute hyperbolic consine, where <code>x</code> is an angle in radians.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="cospi">cospi</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype cospi(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute cos(π x).</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="sin">sin</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype sin(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute sine, where <code>x</code> is an angle in radians.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="sincos">sincos</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype sincos(gentype x, gentype *cosval);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute sine and cosine of <code>x</code>.
+The computed sine is the return value and computed cosine is returned in <code>cosval</code>, where <code>x</code> is an angle in radians</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="sinh">sinh</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype sinh(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute hyperbolic sine, where <code>x</code> is an angle in radians</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="sinpi">sinpi</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype sinpi(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute sin(π <code>x</code>).</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="tan">tan</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype tan(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute tangent, where <code>x</code> is an angle in radians.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="tanh">tanh</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype tanh(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute hyperbolic tangent, where <code>x</code> is an angle in radians.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="tanpi">tanpi</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype tanpi(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute tan(π <code>x</code>).</p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="power-functions">3.19.3. Power function</h4>
+<div class="sect4">
+<h5 id="cbrt">cbrt</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype cbrt(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute cube-root.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="pow">pow</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype pow(gentype x, gentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute <code>x</code> to the power <code>y</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="pown">pown</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn pown(gentype x, intn y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute <code>x</code> to the power <code>y</code>, where <code>y</code> is an integer.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="powr">powr</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype powr(gentype x, gentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute <code>x</code> to the power <code>y</code>, where <code>x</code> is <code>&gt;= 0</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="rootn">rootn</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype powr(gentype x, gentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute <code>x</code> to the power <code>1/y</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="rsqrt">rsqrt</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype rsqrt(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute inverse square root.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="sqrt">sqrt</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype sqrt(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute square root.</p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="logarithmic-functions">3.19.4. Logarithmic functions</h4>
+<div class="sect4">
+<h5 id="ilogb">ilogb</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>intn ilogb(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Return the exponent as an integer value.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="lgamma">lgamma</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype lgamma(gentype x);
+
+gentype lgamma_r(gentype x, intn *signp);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Log gamma function.
+Returns the natural logarithm of the absolute value of the gamma function.
+The sign of the gamma function is returned in the signp argument of <code>lgamma_r</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="log">log</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype log(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute natural logarithm.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="log2">log2</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype log2(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute a base 2 logarithm.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="log10">log10</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype log10(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute a base 10 logarithm.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="log1p">log1p</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype log1p(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute log<sub>e</sub>(1.0 + x).</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="logb">logb</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype logb(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute the exponent of <code>x</code>, which is the integral part of log<sub>r</sub>|<code>x</code>|.</p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="exponential-functions">3.19.5. Exponential functions</h4>
+<div class="sect4">
+<h5 id="exp">exp</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype exp(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute the base e exponential of <code>x</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="exp2">exp2</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype exp2(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Exponential base 2 function.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="exp10">exp10</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype exp10(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Exponential base 10 function.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="expm1">expm1</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype expm1(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute e<sup>x</sup>- 1.0.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="ldexp">ldexp</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype ldexp(gentype x, intn k);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Multiply <code>x</code> by 2 to the power <code>k</code>.</p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="floating-point-functions">3.19.6. Floating-point functions</h4>
+<div class="sect4">
+<h5 id="ceil">ceil</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype ceil(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Round to integral value using the round to positive infinity rounding mode.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="copysign">copysign</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype copysign(gentype x, gentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns x with its sign changed to match the sign of y.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="floor">floor</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype floor(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Round to integral value using the round to negative infinity rounding mode.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="fma">fma</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype fma(gentype a, gentype b, gentype c);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the correctly rounded floating-point representation of the sum of <code>c</code> with the infinitely precise product of <code>a</code> and <code>b</code>.
+Rounding of intermediate products shall not occur.
+Edge case behavior is per the IEEE 754-2008 standard.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="fmod">fmod</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype fmod(gentype x, gentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Modulus. Returns <code>x - y * trunc (x/y)</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="fract">fract</h5>
+<div class="paragraph">
+<p><code>fract</code> <a id="ftnref20"></a> <a href="#ftn20">[20]</a>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype fract(gentype x, gentype *iptr);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>fmin(x - floor(x), 0x1.fffffep-1f)</code>.</p>
+</div>
+<div class="paragraph">
+<p><code>floor(x)</code> is returned in <code>iptr</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="frexp">frexp</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype frexp(gentype x, intn *exp);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Extract mantissa and exponent from <code>x</code>.
+For each component the mantissa returned is a half with magnitude in the interval [1/2, 1) or 0.
+Each component of <code>x</code> equals mantissa returned <code>* 2<sup>exp</sup></code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="modf">modf</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype modf(gentype x, gentype *iptr);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Decompose a floating-point number.
+The modf function breaks the argument <code>x</code> into integral and fractional parts, each of which has the same sign as the argument.
+It stores the integral part in the object pointed to by <code>iptr</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="nan">nan</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn nan(uintn nancode);
+doublen nan(ulongn nancode);
+halfn nan(ushortn nancode);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns a quiet <code>NaN</code>.
+The nancode may be placed in the significand of the resulting <code>NaN</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="nextafter">nextafter</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype nextafter(gentype x, gentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Computes the next representable single-precision floating-point value following <code>x</code> in the direction of <code>y</code>.
+Thus, if <code>y</code> is less than <code>x</code>.
+<code>nextafter()</code> returns the largest representable floating-point number less than <code>x</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="remainder">remainder</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype remainder(gentype x, gentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute the value <code>r</code> such that <code>r = x - n*y</code>, where <code>n</code> is the integer nearest the exact value of <code>x/y</code>.
+If there are two integers closest to <code>x/y</code>, <code>n</code> shall be the even one.
+If <code>r</code> is zero, it is given the same sign as <code>x</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="remquo">remquo</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype remquo(gentype x, gentype y, intn *quo);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The remquo function computes the value <code>r</code> such that <code>r = x - k*y</code>, where <code>k</code> is the integer nearest the exact value of <code>x/y</code>.
+If there are two integers closest to <code>x/y</code>, <code>k</code> shall be the even one.
+If <code>r</code> is zero, it is given the same sign as <code>x</code>.
+This is the same value that is returned by the remainder function.
+<code>remquo</code> also calculates at least the seven lower bits of the integral quotient <code>x/y</code>, and gives that value the same sign as <code>x/y</code>.
+It stores this signed value in the object pointed to by <code>quo</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="rint">rint</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype rint(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Round to integral value (using round to nearest even rounding mode) in floating-point format.
+Refer to the <a href="#rounding-modes"><em>Rounding Modes</em></a> section for description of rounding modes.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="round">round</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype round(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Return the integral value nearest to <code>x</code> rounding halfway cases away from zero, regardless of the current rounding direction.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="trunc">trunc</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype trunc(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Round to integral value using the round to zero rounding mode.</p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="comparison-functions">3.19.7. Comparison functions</h4>
+<div class="sect4">
+<h5 id="fdim">fdim</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype fdim(gentype x, gentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><code>x - y</code> if <code>x &gt; y</code>, <code>+0</code> if <code>x</code> is less than or equal to <code>y</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="fmax">fmax</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype fmax(gentype x, gentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>y</code> if <code>x &lt; y</code>, otherwise it returns <code>x</code>.
+If one argument is a <code>NaN</code>, <code>fmax()</code> returns the other argument.
+If both arguments are NaNs, <code>fmax()</code> returns a <code>NaN</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="fmin">fmin</h5>
+<div class="paragraph">
+<p><code>fmin</code> <a id="ftnref21"></a> <a href="#ftn21">[21]</a>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype fmin(gentype x, gentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>y</code> if <code>y &lt; x</code>, otherwise it returns <code>x</code>.
+If one argument is a NaN, <code>fmin()</code> returns the other argument.
+If both arguments are NaNs, <code>fmin()</code> returns a <code>NaN</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="fmod-1">fmod</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype fmod(gentype x, gentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Modulus.
+Returns <code>x - y * trunc (x/y)</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="maxmag">maxmag</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype maxmag(gentype x, gentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>x</code> if <code>|x| &gt; |y|</code>, <code>y</code> if <code>|y| &gt; |x|</code>, otherwise <code>fmax(x, y)</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="minmag">minmag</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype minmag(gentype x, gentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>x</code> if <code>|x| &lt; |y|</code>, <code>y</code> if <code>|y| &lt; |x|</code>, otherwise <code>fmin(x, y)</code>.</p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="other-functions-1">3.19.8. Other functions</h4>
+<div class="sect4">
+<h5 id="erfc">erfc</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype erfc(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Complementary error function.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="erf">erf</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype erf(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Error function encountered in integrating the <a href="http://mathworld.wolfram.com/NormalDistribution.html">normal distribution</a>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="fabs">fabs</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype fabs(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute absolute value of a floating-point number.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="hypot">hypot</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype hypot(gentype x, gentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute the value of the square root of <code>x<sup>2</sup> + y<sup>2</sup></code> without undue overflow or underflow.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="mad">mad</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype mad(gentype a, gentype b, gentype c);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><code>mad</code> computes <code>a * b + c</code>.
+The function may compute <code>a * b + c</code> with reduced accuracy
+    in the embedded profile.  See the SPIR-V OpenCL environment specification
+    for details. On some hardware the mad instruction may provide better
+    performance than expanded computation of <code>a * b + c</code>. <a id="ftnref22"></a> <a href="#ftn22">[22]</a></p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="tgamma">tgamma</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype tgamma(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute the gamma function.</p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="native-functions">3.19.9. Native functions</h4>
+<div class="paragraph">
+<p>This section describes the following functions:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>A subset of functions from previous sections that are defined in the <code>cl::native_math</code> namespace.
+These functions may map to one or more native device instructions and will typically have better performance compared to the corresponding functions (without the native_math namespace) described in the <a href="#trigonometric-functions"><em>Trigonometric functions</em></a>, <a href="#logarithmic-functions"><em>Logarithmic functions</em></a>, <a href="#exponential-functions"><em>Exponential functions</em></a>, <a href="#floating-point-functions"><em>Floating-point functions</em></a>, <a href="#comparison-functions"><em>Comparison functions</em></a> and <a href="#other-functions-1"><em>Other functions</em></a> sections.
+The accuracy (and in some cases the input range(s)) of these functions is implementation-defined.</p>
+</li>
+<li>
+<p>Native functions for following basic operations: divide and reciprocal.</p>
+</li>
+<li>
+<p>Support for denormal values is implementation-defined for native functions.</p>
+</li>
+</ul>
+</div>
+<div class="sect4">
+<h5 id="native_mathcos">native_math::cos</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn native_math::cos(floatn x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute cosine over an implementation-defined range, where <code>x</code> is an angle in radians.
+The maximum error is implementation-defined.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="native_mathdivide">native_math::divide</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn native_math::divide(floatn x, floatn y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute <code>x / y</code> over an implementation-defined range.
+The maximum error is implementation-defined.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="native_mathexp">native_math::exp</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn native_math::exp(floatn x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute the base e exponential of <code>x</code> over an implementation-defined range.
+The maximum error is implementation-defined.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="native_mathexp2">native_math::exp2</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn native_math::exp2(floatn x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute the base 2 exponential of <code>x</code> over an implementation-defined range.
+The maximum error is implementation-defined.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="native_mathexp10">native_math::exp10</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn native_math::exp10(floatn x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute the base 10 exponential of <code>x</code> over an implementation-defined range.
+The maximum error is implementation-defined.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="native_mathlog">native_math::log</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn native_math::log(floatn x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute natural logarithm over an implementation-defined range.
+The maximum error is implementation-defined.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="native_mathlog2">native_math::log2</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn native_math::log2(floatn x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute a base 2 logarithm over an implementation-defined range.
+The maximum error is implementation-defined.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="native_mathlog10">native_math::log10</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn native_math::log10(floatn x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute a base 10 logarithm over an implementation-defined range.
+The maximum error is implementation-defined.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="native_mathpowr">native_math::powr</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn native_math::powr(floatn x, floatn y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute <code>x</code> to the power <code>y</code>, where <code>x</code> is <code>&gt;= 0</code>.
+The range of <code>x</code> and <code>y</code> are implementation-defined.
+The maximum error is implementation-defined.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="native_mathrecip">native_math::recip</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn native_math::recip(floatn x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute reciprocal over an implementation-defined range.
+The maximum error is implementation-defined.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="native_mathrsqrt">native_math::rsqrt</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn native_math::rsqrt(floatn x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute inverse square root over an implementation-defined range.
+The maximum error is implementation-defined.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="native_mathsin">native_math::sin</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn native_math::sin(floatn x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute sine over an implementation-defined range, where <code>x</code> is an angle in radians.
+The maximum error is implementation-defined.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="native_mathsqrt">native_math::sqrt</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn native_math::sqrt(floatn x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute square root over an implementation-defined range.
+The maximum error is implementation-defined.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="native_mathtan">native_math::tan</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn native_math::tan(floatn x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute tangent over an implementation-defined range, where <code>x</code> is an angle in radians.
+The maximum error is implementation-defined.</p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="half-functions">3.19.10. Half functions</h4>
+<div class="paragraph">
+<p>This section describes the following functions:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>A subset of functions from previous sections that are defined in the <code>cl::half_math</code> namespace.
+These functions are implemented with a minimum of 10-bits of accuracy i.e. an ULP value &lt;= 8192 ulp.</p>
+</li>
+<li>
+<p>half functions for following basic operations: divide and reciprocal.</p>
+</li>
+<li>
+<p>Support for denormal values is optional for half_math:: functions. The <code>half_math::</code> functions may return any result allowed by the <a href="#edge-case-behavior-in-flush-to-zero-mode"><em>Edge Case Behavior in Flush To Zero Mode</em></a> section, even when <code>-cl-denorms-are-zero</code> is not in force.</p>
+</li>
+</ul>
+</div>
+<div class="sect4">
+<h5 id="half_mathcos">half_math::cos</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn half_math::cos(floatn x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute cosine.
+<code>x</code> is an angle in radians and it must be in the range -2<sup>16</sup> &#8230;&#8203; +2<sup>16</sup>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="half_mathdivide">half_math::divide</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn half_math::divide(floatn x, floatn y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute <code>x / y</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="half_mathexp">half_math::exp</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn half_math::exp(floatn x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute the base e exponential of <code>x</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="half_mathexp2">half_math::exp2</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn half_math::exp2(floatn x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute the base 2 exponential of <code>x</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="half_mathexp10">half_math::exp10</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn half_math::exp10(floatn x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute the base 10 exponential of <code>x</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="half_mathlog">half_math::log</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn half_math::log(floatn x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute natural logarithm.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="half_mathlog2">half_math::log2</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn half_math::log2(floatn x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute a base 2 logarithm.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="half_mathlog10">half_math::log10</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn half_math::log10(floatn x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute a base 10 logarithm.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="half_mathpowr">half_math::powr</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn half_math::powr(floatn x, floatn y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute <code>x</code> to the power <code>y</code>, where <code>x</code> is <code>&gt;= 0</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="half_mathrecip">half_math::recip</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn half_math::recip(floatn x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute reciprocal.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="half_mathrsqrt">half_math::rsqrt</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn half_math::rsqrt(floatn x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute inverse square root.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="half_mathsin">half_math::sin</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn half_math::sin(floatn x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute sine.
+<code>x</code> is an angle in radians and it must be in the range -2<sup>16</sup> &#8230;&#8203; +2<sup>16</sup>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="half_mathsqrt">half_math::sqrt</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn half_math::sqrt(floatn x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute square root.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="half_mathtan">half_math::tan</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>floatn half_math::tan(floatn x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compute tangent.
+<code>x</code> is an angle in radians and it must be in the range -2<sup>16</sup> &#8230;&#8203; +2<sup>16</sup>.</p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="floating-point-pragmas">3.19.11. Floating-point pragmas</h4>
+<div class="paragraph">
+<p>The <code>FP_CONTRACT</code> pragma can be used to allow (if the state is on) or disallow (if the state is off) the implementation to contract expressions.
+Each pragma can occur either outside external declarations or preceding all explicit declarations and statements inside a compound statement.
+When outside external declarations, the pragma takes effect from its occurrence until another <code>FP_CONTRACT</code> pragma is encountered, or until the end of the translation unit.
+When inside a compound statement, the pragma takes effect from its occurrence until another <code>FP_CONTRACT</code> pragma is encountered (including within a nested compound statement), or until the end of the compound statement; at the end of a compound statement the state for the pragma is restored to its condition just before the compound statement.
+If this pragma is used in any other context, the behavior is undefined.</p>
+</div>
+<div class="paragraph">
+<p>The pragma definition to set <code>FP_CONTRACT</code> is:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#pragma OPENCL FP_CONTRACT on-off-switch
+                          // on-off-switch is one of: ON, OFF or DEFAULT.</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The <code>DEFAULT</code> value is <code>ON</code>.</p>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="integer-functions">3.20. Integer Functions</h3>
+<div class="paragraph">
+<p>This section describes the OpenCL C++ library integer functions that take scalar or vector arguments.
+Vector versions of integer functions operate component-wise.
+Descriptions are always per-component.</p>
+</div>
+<div class="paragraph">
+<p>Here <code>gentype</code> matches: <code>char<em>n</em></code>, <code>uchar<em>n</em></code>, <code>short<em>n</em></code>, <code>ushort<em>n</em></code>, <code>int<em>n</em></code>, <code>uint<em>n</em></code>, <code>long<em>n</em></code> and <code>ulong<em>n</em></code>.</p>
+</div>
+<div class="sect3">
+<h4 id="header-opencl_integer-synopsis">3.20.1. Header &lt;opencl_integer&gt; Synopsis</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+//bitwise functions
+gentype clz(gentype x);
+gentype ctz(gentype x);
+gentype popcount(gentype x);
+gentype rotate(gentype v, gentype i);
+
+shortn upsample(charn hi, ucharn lo);
+ushortn upsample(ucharn hi, ucharn lo);
+intn upsample(shortn hi, ushortn lo);
+uintn upsample(ushortn hi, ushortn lo);
+longn upsample(intn hi, uintn lo);
+ulongn upsample(uintn hi, uintn lo);
+
+//numeric functions
+ugentype abs(gentype x);
+ugentype abs_diff(gentype x, gentype y);
+gentype  add_sat(gentype x, gentype y);
+gentype  hadd(gentype x, gentype y);
+gentype  rhadd(gentype x, gentype y);
+gentype  clamp(gentype x, gentype minval, gentype maxval);
+gentype  clamp(gentype x, sgentype minval, sgentype maxval);
+gentype  mad_hi(gentype a, gentype b, gentype c);
+gentype  mad_sat(gentype a, gentype b, gentype c);
+gentype  max(gentype x, gentype y);
+gentype  max(gentype x, sgentype y);
+gentype  min(gentype x, gentype y);
+gentype  min(gentype x, sgentype y);
+gentype  mul_hi(gentype x, gentype y);
+gentype  sub_sat(gentype x, gentype y);
+
+//24-bits functions
+intn mad24(intn x, intn y, intn z);
+uintn mad24(uintn x, uintn y, uintn z);
+intn mul24(intn x, intn y);
+uintn mul24(uintn x, uintn y);
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="bitwise-operations">3.20.2. Bitwise operations</h4>
+<div class="sect4">
+<h5 id="clz">clz</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype clz(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the number of leading 0-bits in <code>x</code>, starting at the most significant bit position.
+If <code>x</code> is <code>0</code>, returns the size in bits of the type of <code>x</code> or component type of <code>x</code>, if <code>x</code> is a vector.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="ctz">ctz</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype ctz(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the count of trailing 0-bits in <code>x</code>.
+If <code>x</code> is <code>0</code>, returns the size in bits of the type of <code>x</code> or component type of <code>x</code>, if <code>x</code> is a vector.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="rotate">rotate</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype rotate(gentype v, gentype i);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>For each element in <code>v</code>, the bits are shifted left by the number of bits given by the corresponding element in <code>i</code> (subject to usual shift modulo rules described in the <a href="#expressions"><em>Expressions</em></a> section).
+Bits shifted off the left side of the element are shifted back in from the right.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="upsample">upsample</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>shortn upsample(charn hi, ucharn lo);
+ushortn upsample(ucharn hi, ucharn lo);
+
+intn upsample(shortn hi, ushortn lo);
+uintn upsample(ushortn hi, ushortn lo);
+
+longn upsample(intn hi, uintn lo);
+ulongn upsample(uintn hi, uintn lo);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><code>result[i] = ((short)hi[i] &lt;&lt; 8) | lo[i]</code></p>
+</div>
+<div class="paragraph">
+<p><code>result[i] = ((ushort)hi[i] &lt;&lt; 8) | lo[i]</code></p>
+</div>
+<div class="paragraph">
+<p><code>result[i] = ((int)hi[i] &lt;&lt; 16) | lo[i]</code></p>
+</div>
+<div class="paragraph">
+<p><code>result[i] = ((uint)hi[i] &lt;&lt; 16) | lo[i]</code></p>
+</div>
+<div class="paragraph">
+<p><code>result[i] = ((long)hi[i] &lt;&lt; 32) | lo[i]</code></p>
+</div>
+<div class="paragraph">
+<p><code>result[i] = ((ulong)hi[i] &lt;&lt; 32) | lo[i]</code></p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="popcount">popcount</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype popcount(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the number of non-zero bits in <code>x</code>.</p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="numeric-functions">3.20.3. Numeric functions</h4>
+<div class="sect4">
+<h5 id="abs">abs</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>ugentype abs(gentype x);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>|x|</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="abs_diff">abs_diff</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>ugentype abs_diff(gentype x, gentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>|x - y|</code> without modulo overflow.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="add_sat">add_sat</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype add_sat(gentype x, gentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>x + y</code> and saturates the result.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="hadd">hadd</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype hadd(gentype x, gentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>(x + y) &gt;&gt; 1</code>.
+The intermediate sum does not modulo overflow.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="rhadd">rhadd</h5>
+<div class="paragraph">
+<p><code>rhadd</code> <a id="ftnref23"></a> <a href="#ftn23">[23]</a>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype rhadd(gentype x, gentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>(x + y + 1) &gt;&gt; 1</code>.
+The intermediate sum does not modulo overflow.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="clamp">clamp</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype clamp(gentype x, gentype minval, gentype maxval);
+gentype clamp(gentype x, sgentype minval, sgentype maxval);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>min(max(x, minval), maxval)</code>.</p>
+</div>
+<div class="paragraph">
+<p>Results are undefined if <code>minval &gt; maxval</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="mad_hi">mad_hi</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype mad_hi(gentype a, gentype b, gentype c);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>mul_hi(a, b) + c</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="mad_sat">mad_sat</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype mad_sat(gentype a, gentype b, gentype c);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>a * b + c</code> and saturates the result.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="max">max</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype max(gentype x, gentype y);
+gentype max(gentype x, sgentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>y</code> if <code>x &lt; y</code>, otherwise it returns <code>x</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="min">min</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype min(gentype x, gentype y);
+gentype min(gentype x, sgentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>y</code> if <code>y &lt; x</code>, otherwise it returns <code>x</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="mul_hi">mul_hi</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype mul_hi(gentype x, gentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Computes <code>x * y</code> and returns the high half of the product of <code>x</code> and <code>y</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="sub_sat">sub_sat</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype sub_sat(gentype x, gentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>x - y</code> and saturates the result.</p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="bits-operations">3.20.4. 24-bits operations</h4>
+<div class="paragraph">
+<p>In this section fast integer functions are described that can be used for optimizing performance of kernels.</p>
+</div>
+<div class="sect4">
+<h5 id="mad24">mad24</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>intn mad24(intn x, intn y, intn z);
+uintn mad24(uintn x, uintn y, uintn z);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Multiply two 24-bit integer values <code>x</code> and <code>y</code> and add the 32-bit integer result to the 32-bit integer <code>z</code>.
+Refer to definition of mul24 to see how the 24-bit integer multiplication is performed.</p>
+</div>
+<div id="mul24" class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>intn mul24(intn x, intn y);
+uintn mul24(uintn x, uintn y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Multiply two 24-bit integer values <code>x</code> and <code>y</code>.
+<code>x</code> and <code>y</code> are 32-bit integers but only the low 24-bits are used to perform the multiplication.
+<code>mul24</code> should only be used when values in <code>x</code> and <code>y</code> are in the range [-2<sup>23</sup>, 2<sup>23</sup>-1] if <code>x</code> and <code>y</code> are signed integers and in the range [0, 2<sup>24</sup>-1] if <code>x</code> and <code>y</code> are unsigned integers.
+If <code>x</code> and <code>y</code> are not in this range, the multiplication result is implementation-defined.</p>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="relational-functions">3.21. Relational Functions</h3>
+<div class="paragraph">
+<p>The relational and equality operators (<code>&lt;</code>, <code>&lt;=</code>, <code>&gt;</code>, <code>&gt;=</code>, <code>!=</code>, <code>==</code>) can be used with scalar and vector built-in types and produce a scalar or vector boolean result respectively as described in the <a href="#expressions"><em>Expressions</em></a> section.</p>
+</div>
+<div class="paragraph">
+<p>Here <code>gentype</code> matches: <code>char<em>n</em></code>, <code>uchar<em>n</em></code>, <code>short<em>n</em></code>, <code>ushort<em>n</em></code>, <code>int<em>n</em></code>, <code>uint<em>n</em></code>, <code>long<em>n</em></code>, <code>ulong<em>n</em></code>, <code>half<em>n</em></code> <a id="ftnref4"></a> <a href="#ftn4">[4]</a>, <code>float<em>n</em></code> and <code>double<em>n</em></code> <a id="ftnref18"></a> <a href="#ftn18">[18]</a>.</p>
+</div>
+<div class="paragraph">
+<p>The relational functions <code>isequal</code>, <code>isgreater</code>, <code>isgreaterequal</code>, <code>isless</code>, <code>islessequal</code>, and <code>islessgreater</code> always return <code>false</code> if either argument is not a number (NaN).
+<code>isnotequal</code> returns <code>true</code> if one or both arguments are not a number (NaN).</p>
+</div>
+<div class="sect3">
+<h4 id="header-opencl_relational-synopsis">3.21.1. Header &lt;opencl_relational&gt; Synopsis</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+#ifdef cl_khr_fp16
+booln isequal(halfn x, halfn y);
+booln isnotequal(halfn x, halfn y);
+booln isgreater(halfn x, halfn y);
+booln isgreaterequal(halfn x, halfn y);
+booln isless(halfn x, halfn y);
+booln islessequal(halfn x, halfn y);
+booln islessgreater(halfn x, halfn y);
+booln isordered(halfn x, halfn y);
+booln isunordered(halfn x, halfn y);
+booln isfinite(halfn t);
+booln isinf(halfn t);
+booln isnan(halfn t);
+booln isnormal(halfn t);
+booln signbit(halfn t);
+
+#endif
+
+#ifdef cl_khr_fp64
+booln isequal(doublen x, doublen y);
+booln isnotequal(doublen x, doublen y);
+booln isgreater(doublen x, doublen y);
+booln isgreaterequal(doublen x, doublen y);
+booln isless(doublen x, doublen y);
+booln islessequal(doublen x, doublen y);
+booln islessgreater(doublen x, doublen y);
+booln isordered(doublen x, doublen y);
+booln isunordered(doublen x, doublen y);
+booln isfinite(doublen t);
+booln isinf(doublen t);
+booln isnan(doublen t);
+booln isnormal(doublen t);
+booln signbit(doublen t);
+
+#endif //cl_khr_fp64
+
+booln isequal(floatn x, floatn y);
+booln isnotequal(floatn x, floatn y);
+booln isgreater(floatn x, floatn y);
+booln isgreaterequal(floatn x, floatn y);
+booln isless(floatn x, floatn y);
+booln islessequal(floatn x, floatn y);
+booln islessgreater(floatn x, floatn y);
+booln isordered(floatn x, floatn y);
+booln isunordered(floatn x, floatn y);
+booln isfinite(floatn t);
+booln isinf(floatn t);
+booln isnan(floatn t);
+booln isnormal(floatn t);
+booln signbit(floatn t);
+
+bool any(booln t);
+bool all(booln t);
+
+gentype bitselect(gentype a, gentype b, gentype c);
+gentype select(gentype a, gentype b, booln c);
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="comparison-operations">3.21.2. Comparison operations</h4>
+<div class="sect4">
+<h5 id="isequal">isequal</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>booln isequal(gentype x, gentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the component-wise compare of <code>x == y</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="isnotequal">isnotequal</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>booln isnotequal(gentype x, gentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the component-wise compare of <code>x != y</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="isgreater">isgreater</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>booln isgreater(gentype x, gentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the component-wise compare of <code>x &gt; y</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="isgreaterequal">isgreaterequal</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>booln isgreaterequal(gentype x, gentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the component-wise compare of <code>x &gt;= y</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="isless">isless</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>booln isless(gentype x, gentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the component-wise compare of <code>x &lt; y</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="islessequal">islessequal</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>booln islessequal(gentype x, gentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the component-wise compare of <code>x &lt;= y</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="islessgreater">islessgreater</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>booln islessgreater(gentype x, gentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns the component-wise compare of <code>(x &lt; y) || (x &gt; y)</code>.</p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="test-operations">3.21.3. Test operations</h4>
+<div class="sect4">
+<h5 id="isfinite">isfinite</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>booln isfinite(gentype t);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Test for finite value.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="isinf">isinf</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>booln isinf(gentype t);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Test for infinity value (positive or negative) .</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="isnan">isnan</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>booln isnan(gentype t);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Test for a NaN.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="isnormal">isnormal</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>booln isnormal(gentype t);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Test for a normal value.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="isordered">isordered</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>booln isordered(gentype x, gentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Test if arguments are ordered.
+<code>isordered()</code> takes arguments <code>x</code> and <code>y</code>, and returns the result of <code>isequal(x, x) &amp;&amp; isequal(y, y)</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="isunordered">isunordered</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>booln isunordered(gentype x, gentype y);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Test if arguments are unordered.
+<code>isunordered()</code> takes arguments <code>x</code> and <code>y</code>, returning <code>true</code> if <code>x</code> or <code>y</code> is NaN, and <code>false</code> otherwise.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="signbit">signbit</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>booln signbit(gentype t);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Test for sign bit.
+Returns a <code>true</code> if the sign bit in the float is set else returns <code>false</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="any">any</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>bool any(booln t);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>true</code> if any component of <code>t</code> is <code>true</code>; otherwise returns <code>false</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="all">all</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>bool all(booln t);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returns <code>true</code> if all components of <code>t</code> are <code>true</code>; otherwise returns <code>false</code>.</p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="select-operations">3.21.4. Select operations</h4>
+<div class="sect4">
+<h5 id="bitselect">bitselect</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype bitselect(gentype a, gentype b, gentype c);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Each bit of the result is the corresponding bit of <code>a</code> if the corresponding bit of <code>c</code> is <code>0</code>.
+Otherwise it is the corresponding bit of <code>b</code>.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="select">select</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype select(gentype a, gentype b, booln c);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>For each component of a vector type,</p>
+</div>
+<div class="paragraph">
+<p><code>result[i] = c[i] ? b[i] : a[i]</code>.</p>
+</div>
+<div class="paragraph">
+<p>For a scalar type,  <code>result = c ? b : a</code>.</p>
+</div>
+<div class="paragraph">
+<p><code>booln</code> must have the same number of elements as <code>gentype</code>.</p>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="vector-data-load-and-store-functions">3.22. Vector Data Load and Store Functions</h3>
+<div class="paragraph">
+<p>Functions described in this section allow user to read and write vector types from a pointer to memory.
+The results of these functions are undefined if the address being read from or written to is not correctly aligned as described in following subsections.</p>
+</div>
+<div class="paragraph">
+<p>Here <code>gentype</code> matches: <code>char<em>n</em></code>, <code>uchar<em>n</em></code>, <code>short<em>n</em></code>, <code>ushort<em>n</em></code>, <code>int<em>n</em></code>, <code>uint<em>n</em></code>, <code>long<em>n</em></code>, <code>ulong<em>n</em></code>, <code>half<em>n</em></code> <a id="ftnref4"></a> <a href="#ftn4">[4]</a>, <code>float<em>n</em></code> and <code>double<em>n</em></code> <a id="ftnref18"></a> <a href="#ftn18">[18]</a>.</p>
+</div>
+<div class="sect3">
+<h4 id="header-opencl_vector_load_store">3.22.1. Header &lt;opencl_vector_load_store&gt; Synopsis</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+//basic load &amp; store
+template &lt;size_t N, class T&gt;
+make_vector_t&lt;T, N&gt; vload(size_t offset, const T* p);
+
+template &lt;size_t N, class T&gt;
+make_vector_t&lt;T, N&gt; vload(size_t offset, const constant_ptr&lt;T&gt; p);
+
+template &lt;class T&gt;
+void vstore(T data, size_t offset, vector_element_t&lt;T&gt;* p);
+
+//half load &amp; store
+template &lt;size_t N&gt;
+make_vector_t&lt;float, N&gt; vload_half(size_t offset, const half* p);
+
+template &lt;size_t N&gt;
+make_vector_t&lt;float, N&gt; vload_half(size_t offset, const constant_ptr&lt;half&gt; p);
+
+template &lt;rounding_mode rmode = rounding_mode::rte, class T&gt;
+void vstore_half(T data, size_t offset, half* p);
+
+//half array load &amp; store
+template &lt;size_t N&gt;
+make_vector_t&lt;float, N&gt; vloada_half(size_t offset, const half* p);
+
+template &lt;size_t N&gt;
+make_vector_t&lt;float, N&gt; vloada_half(size_t offset, const constant_ptr&lt;half&gt; p);
+
+template &lt;rounding_mode rmode = rounding_mode::rte, class T&gt;
+void vstorea_half(T data, size_t offset, half* p);
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="basic-load-store">3.22.2. Basic load &amp; store</h4>
+<div class="sect4">
+<h5 id="vload">vload</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template &lt;size_t N, class T&gt;
+make_vector_t&lt;T, N&gt; vload(size_t offset, const T* p);
+
+template &lt;size_t N, class T&gt;
+make_vector_t&lt;T, N&gt; vload(size_t offset, const constant_ptr&lt;T&gt; p);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Return <code>sizeof(make_vector_t&lt;T, N&gt;)</code> bytes of data read from address <code>(p + (offset * n))</code>.</p>
+</div>
+<div class="paragraph">
+<p>Requirements:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>The address computed as <code>(p+(offset*n))</code> must be 8-bit aligned if <code>T</code> is <code>char</code>, or <code>uchar</code>; 16-bit aligned if <code>T</code> is <code>short</code>, <code>ushort</code>, or <code>half</code> <a href="#ftn4">[4]</a>; 32-bit aligned if <code>T</code> is <code>int</code>, <code>uint</code>, or <code>float</code>; and 64-bit aligned if <code>T</code> is <code>long</code>, <code>ulong</code>, or <code>double</code> <a href="#ftn18">[18]</a>.</p>
+</li>
+<li>
+<p><code>vload</code> function is only defined for n = 2, 3, 4, 8, 16.</p>
+</li>
+<li>
+<p><code>half</code> version is only defined if the <strong>cl_khr_fp16</strong> extension is supported.</p>
+</li>
+<li>
+<p><code>double</code> version is only defined if double precision is supported.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect4">
+<h5 id="vstore">vstore</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template &lt;class T&gt;
+void vstore(T data, size_t offset, vector_element_t&lt;T&gt;* p);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Write <code>sizeof(T)</code> bytes given by data to address <code>(p+(offset*n))</code>.</p>
+</div>
+<div class="paragraph">
+<p>Requirements:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>The address computed as <code>(p+(offset*n))</code> must be 8-bit aligned if <code>T</code> is <code>char</code>, or <code>uchar</code>; 16-bit aligned if <code>T</code> is <code>short</code>, <code>ushort</code>, or <code>half</code> <a href="#ftn4">[4]</a>; 32-bit aligned if <code>T</code> is <code>int</code>, <code>uint</code>, or <code>float</code>; and 64-bit aligned if <code>T</code> is <code>long</code>, <code>ulong</code>, or <code>double</code> <a href="#ftn18">[18]</a>.</p>
+</li>
+<li>
+<p><code>vstore</code> function is only defined for n = 2, 3, 4, 8, 16.</p>
+</li>
+<li>
+<p><code>half</code> version is only defined if the <strong>cl_khr_fp16</strong> extension is supported.</p>
+</li>
+<li>
+<p><code>double</code> version is only defined if double precision is supported.</p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="half-vload-vstore">3.22.3. half vload &amp; vstore</h4>
+<div class="sect4">
+<h5 id="vload_half">vload_half</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template &lt;size_t N&gt;
+make_vector_t&lt;float, N&gt; vload_half(size_t offset, const half* p);
+
+template &lt;size_t N&gt;
+make_vector_t&lt;float, N&gt; vload_half(size_t offset, const constant_ptr&lt;half&gt; p);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Read <code>sizeof(halfn)</code> bytes of data from address <code>(p+(offset*n))</code>.
+The data read is interpreted as a <code>halfn</code> value.
+The <code>halfn</code> value read is converted to a <code>float</code> value and the <code>floatn</code> value is returned.</p>
+</div>
+<div class="paragraph">
+<p>Requirements:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>The read address computed as <code>(p+(offset*n))</code> must be 16-bit aligned.</p>
+</li>
+<li>
+<p><code>vload_half</code> function is only defined for n = 1, 2, 3, 4, 8, 16.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect4">
+<h5 id="vstore_half">vstore_half</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template &lt;rounding_mode rmode = rounding_mode::rte, class T&gt;
+void vstore_half(T data, size_t offset, half* p);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The <code>T</code> value given by data is first converted to a <code>halfn</code> value using the appropriate rounding mode.
+The <code>half</code> value is then written to address computed as <code>(p+offset)</code>.</p>
+</div>
+<div class="paragraph">
+<p>Requirements:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>The address computed as <code>(p+offset)</code> must be 16-bit aligned.</p>
+</li>
+<li>
+<p><code>T</code> can be <code>floatn</code> or <code>doublen</code> <a href="#ftn18">[18]</a>.</p>
+</li>
+<li>
+<p><code>double</code> version is only defined if double precision is supported.</p>
+</li>
+<li>
+<p><code>vstore_half</code> function is only defined for n = 1, 2, 3, 4, 8, 16.</p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="half-array-vload-vstore">3.22.4. half array vload &amp; vstore</h4>
+<div class="sect4">
+<h5 id="vloada_half">vloada_half</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template &lt;size_t N&gt;
+make_vector_t&lt;float, N&gt; vloada_half(size_t offset, const half* p);
+
+template &lt;size_t N&gt;
+make_vector_t&lt;float, N&gt; vloada_half(size_t offset, const constant_ptr&lt;half&gt; p);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>For <code>N</code> = 2, 4, 8 and 16 read <code>sizeof(halfn)</code> bytes of data from address <code>(p+(offset*n))</code>.
+The data read is interpreted as a <code>halfn</code> value.
+The <code>halfn</code> value read is converted to a <code>floatn</code> value and the <code>floatn</code> value is returned.</p>
+</div>
+<div class="paragraph">
+<p>Requirements:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>The address computed as <code>(p+(offset*n))</code> must be aligned to <code>sizeof(halfn)</code> bytes.</p>
+</li>
+<li>
+<p>For n = 3, <code>vloada_half</code> reads a <code>half3</code> from address <code>(p+(offset*4))</code> and returns a <code>float3</code>.
+The address computed as <code>(p+(offset*4))</code> must be aligned to <code>sizeof(half)*4</code> bytes.</p>
+</li>
+<li>
+<p><code>vloada_half</code> function is only defined for <code>N</code> = 2, 3, 4, 8, 16.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect4">
+<h5 id="vstorea_half">vstorea_half</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>template &lt;rounding_mode rmode = rounding_mode::rte, class T&gt;
+void vstorea_half(T data, size_t offset, half* p);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The <code>T</code> value is converted to a <code>halfn</code> value using the appropriate rounding mode.
+For n = 2, 4, 8 or 16, the halfn value is written to the address computed as <code>(p+(offset*n))</code>.
+For n = 3, the <code>half3</code> value is written to the address computed as <code>(p+(offset*4))</code>.
+The address computed as <code>(p+(offset*4))</code> must be aligned to <code>sizeof(half)*4</code> bytes.</p>
+</div>
+<div class="paragraph">
+<p>Requirements:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>The address computed as <code>(p+(offset* n))</code> must be aligned to <code>sizeof(halfn)</code> bytes.</p>
+</li>
+<li>
+<p>For n = 3, the address computed as <code>(p+(offset*4))</code> must be aligned to <code>sizeof(half)*4</code> bytes.</p>
+</li>
+<li>
+<p><code>T</code> can be <code>floatn</code> or <code>doublen</code> <a href="#ftn18">[18]</a>.</p>
+</li>
+<li>
+<p><code>double</code> version is only defined if double precision is supported.</p>
+</li>
+<li>
+<p><code>vstorea_half</code> function is only defined for n = 2, 3, 4, 8, 16.</p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="printf">3.23. printf</h3>
+<div class="paragraph">
+<p>The OpenCL C++ programming language implements the <code>printf</code> <a id="ftnref24"></a> <a href="#ftn24">[24]</a> function.
+This function is defined in header <em>&lt;opencl_printf&gt;</em>.</p>
+</div>
+<div class="sect3">
+<h4 id="header-opencl_printf-synopsis">3.23.1. Header &lt;opencl_printf&gt; Synopsis</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+int printf(const char *format, ...);
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="printf-function">3.23.2. printf function</h4>
+<div class="sect4">
+<h5 id="printf-1">printf</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int printf(const char *format, ...);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The <code>printf</code> built-in function writes output to an implementation-defined stream such as stdout under control of the string pointed to by <code>format</code> that specifies how subsequent arguments are converted for output.
+If there are insufficient arguments for the format, the behavior is undefined.
+If the format is exhausted while arguments remain, the excess arguments are evaluated (as always) but are otherwise ignored.
+The <code>printf</code> function returns when the end of the format string is encountered.</p>
+</div>
+<div class="paragraph">
+<p><code>printf</code> returns 0 if it was executed successfully and -1 otherwise.</p>
+</div>
+<div class="paragraph">
+<p>Limitations:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Format must be known at compile time; otherwise it will be a compile time error.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect4">
+<h5 id="printf-output-synchronization">printf output synchronization</h5>
+<div class="paragraph">
+<p>When the event that is associated with a particular kernel invocation is completed, the output of all <code>printf()</code> calls executed by this kernel invocation is flushed to the implementation-defined output stream.
+Calling <code>clFinish</code> on a host command queue flushes all pending output by <code>printf</code> in previously enqueued and completed commands to the implementation-defined output stream.
+In the case that <code>printf</code> is executed from multiple work-items concurrently, there is no guarantee of ordering with respect to written data.
+For example, it is valid for the output of a work-item with a global id (0,0,1) to appear intermixed with the output of a work-item with a global id (0,0,4) and so on.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="printf-format-string">printf format string</h5>
+<div class="paragraph">
+<p>The format shall be a character sequence, beginning and ending in its initial shift state.
+The format is composed of zero or more directives: ordinary characters (not <strong>%</strong>), which are copied unchanged to the output stream; and conversion specifications, each of which results in fetching zero or more subsequent arguments, converting them, if applicable, according to the corresponding conversion specifier, and then writing the result to the output stream.
+The format is in the <code>constant</code> address space and must be resolvable at compile time i.e. cannot be dynamically created by the executing program, itself.</p>
+</div>
+<div class="paragraph">
+<p>Each conversion specification is introduced by the character <strong>%</strong>.
+After the <strong>%</strong>, the following appear in sequence:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Zero or more <em>flags</em> (in any order) that modify the meaning of the conversion specification.</p>
+</li>
+<li>
+<p>An optional minimum <em>field width</em>.
+If the converted value has fewer characters than the field width, it is padded with spaces (by default) on the left (or right, if the left adjustment flag, described later, has been given) to the field width.
+The field width takes the form of a nonnegative decimal integer. <a id="ftnref25"></a> <a href="#ftn25">[25]</a></p>
+</li>
+<li>
+<p>An optional <em>precision</em> that gives the minimum number of digits to appear for the <em>d</em>, <em>i</em>, <em>o</em>, <em>u</em>, <em>x</em>, and <em>X</em> conversions, the number of digits to appear after the decimal-point character for <em>a</em>, <em>A</em>, <em>e</em>, <em>E</em>, <em>f</em>, and <em>F</em> conversions, the maximum number of significant digits for the <em>g</em> and <em>G</em> conversions, or the maximum number of bytes to be written for <em>s</em> conversions.
+The precision takes the form of a period (.) followed by an optional decimal integer; if only the period is specified, the precision is taken as zero.
+If a precision appears with any other conversion specifier, the behavior is undefined.</p>
+</li>
+<li>
+<p>An optional <em>vector specifier</em>.</p>
+</li>
+<li>
+<p>A <em>length modifier</em> that specifies the size of the argument.
+The <em>length modifier</em> is required with a vector specifier and together specifies the vector type.
+Implicit conversions between vector types are disallowed (as per the <a href="#implicit-type-conversions"><em>Implicit Type Conversions</em></a> section).
+If the <em>vector specifier</em> is not specified, the <em>length modifier</em> is optional.</p>
+</li>
+<li>
+<p>A <em>conversion specifier</em> character that specifies the type of conversion to be applied.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The flag characters and their meanings are:</p>
+</div>
+<div class="hdlist">
+<table>
+<tr>
+<td class="hdlist1">
+<em>-</em>
+</td>
+<td class="hdlist2">
+<p>The result of the conversion is left-justified within the field.
+(It is right-justified if this flag is not specified.)</p>
+</td>
+</tr>
+<tr>
+<td class="hdlist1">
+<em>+</em>
+</td>
+<td class="hdlist2">
+<p>The result of a signed conversion always begins with a plus or minus sign.
+(It begins with a sign only when a negative value is converted if this flag is not specified.) <a id="ftnref26"></a> <a href="#ftn26">[26]</a></p>
+</td>
+</tr>
+<tr>
+<td class="hdlist1">
+<em>space</em>
+</td>
+<td class="hdlist2">
+<p>If the first character of a signed conversion is not a sign, or if a signed conversion results in no characters, a space is prefixed to the result.
+If the <em>space</em> and <em>+</em> flags both appear, the <em>space</em> flag is ignored.</p>
+</td>
+</tr>
+<tr>
+<td class="hdlist1">
+<em>#</em>
+</td>
+<td class="hdlist2">
+<p>The result is converted to an "alternative form".
+For <em>o</em> conversion, it increases the precision, if and only if necessary, to force the first digit of the result to be a zero (if the value and precision are both 0, a single 0 is printed).
+For <em>x</em> (or <em>X</em>) conversion, a nonzero result has <strong>0x</strong> (or <strong>0X</strong>) prefixed to it.
+For <em>a</em>, <em>A</em>, <em>e</em>, <em>E</em>, <em>f</em>, <em>F</em>, <em>g</em> and <em>G</em> conversions, the result of converting a floating-point number always contains a decimal-point character, even if no digits follow it.
+(Normally, a decimal-point character appears in the result of these conversions only if a digit follows it.) For <em>g</em> and <em>G</em> conversions, trailing zeros are <em>not</em> removed from the result.
+For other conversions, the behavior is undefined.</p>
+</td>
+</tr>
+<tr>
+<td class="hdlist1">
+<em>0</em>
+</td>
+<td class="hdlist2">
+<p>For <em>d</em>, <em>i</em>, <em>o</em>, <em>u</em>, <em>x</em>, <em>X</em>, <em>a</em>, <em>A</em>, <em>e</em>, <em>E</em>, <em>f</em>, <em>F</em>, <em>g</em> and <em>G</em> conversions, leading zeros (following any indication of sign or base) are used to pad to the field width rather than performing space padding, except when converting an infinity or NaN.
+If the <em>0</em> and <em>-</em> flags both appear, the <em>0</em> flag is ignored.
+For <em>d</em>, <em>i</em>, <em>o</em>, <em>u</em>, <em>x</em>, and <em>X</em> conversions, if a precision is specified, the <em>0</em> flag is ignored.
+For other conversions, the behavior is undefined.</p>
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p>The vector specifier and its meaning is:</p>
+</div>
+<div class="hdlist">
+<table>
+<tr>
+<td class="hdlist1">
+<em>vn</em>
+</td>
+<td class="hdlist2">
+<p>Specifies that a following <em>a</em>, <em>A</em>, <em>e</em>, <em>E</em>, <em>f</em>, <em>F</em>, <em>g</em>, <em>G</em>, <em>d</em>, <em>i</em>, <em>o</em>, <em>u</em>, <em>x</em> or <em>X</em> conversion specifier applies to a vector argument, where <em>n</em> is the size of the vector and must be 2, 3, 4, 8 or 16.</p>
+<div class="paragraph">
+<p>The vector value is displayed in the following general form:</p>
+</div>
+<div class="paragraph">
+<p>value1 <em>C</em> value2 <em>C</em> &#8230;&#8203; <em>C</em> value<em>n</em></p>
+</div>
+<div class="paragraph">
+<p>where <em>C</em> is a separator character.
+The value for this separator character is a comma.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p>If the vector specifier is not used, the length modifiers and their meanings are:</p>
+</div>
+<div class="hdlist">
+<table>
+<tr>
+<td class="hdlist1">
+<em>hh</em>
+</td>
+<td class="hdlist2">
+<p>Specifies that a following <em>d</em>, <em>i</em>, <em>o</em>, <em>u</em>, <em>x</em>, or <em>X</em> conversion specifier applies to a <code>char</code> or <code>uchar</code> argument (the argument will have been promoted according to the integer promotions, but its value shall be converted to <code>char</code> or <code>uchar</code> before printing).</p>
+</td>
+</tr>
+<tr>
+<td class="hdlist1">
+<em>h</em>
+</td>
+<td class="hdlist2">
+<p>Specifies that a following <em>d</em>, <em>i</em>, <em>o</em>, <em>u</em>, <em>x</em> or <em>X</em> conversion specifier applies to a <code>short</code> or <code>ushort</code> argument (the argument will have been promoted according to the integer promotions, but its value shall be converted to <code>short</code> or <code>ushort</code> before printing).</p>
+</td>
+</tr>
+<tr>
+<td class="hdlist1">
+<em>l</em> (ell)
+</td>
+<td class="hdlist2">
+<p>Specifies that a following <em>d</em>, <em>i</em>, <em>o</em>, <em>u</em>, <em>x</em> or <em>X</em> conversion specifier applies to a <code>long</code> or <code>ulong</code> argument.
+The <em>l</em> modifier is supported by the full profile.
+For the embedded profile, the <em>l</em> modifier is supported only if 64-bit integers are supported by the device.</p>
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p>If the vector specifier is used, the length modifiers and their meanings are:</p>
+</div>
+<div class="hdlist">
+<table>
+<tr>
+<td class="hdlist1">
+<em>hh</em>
+</td>
+<td class="hdlist2">
+<p>Specifies that a following <em>d</em>, <em>i</em>, <em>o</em>, <em>u</em>, <em>x</em> or <em>X</em> conversion specifier applies to a <code>char<em>n</em></code> or <code>uchar<em>n</em></code> argument (the argument will not be promoted).</p>
+</td>
+</tr>
+<tr>
+<td class="hdlist1">
+<em>h</em>
+</td>
+<td class="hdlist2">
+<p>Specifies that a following <em>d</em>, <em>i</em>, <em>o</em>, <em>u</em>, <em>x</em> or <em>X</em> conversion specifier applies to a <code>short<em>n</em></code> or <code>ushort<em>n</em></code> argument (the argument will not be promoted); that a following <em>a</em>, <em>A</em>, <em>e</em>, <em>E</em>, <em>f</em>, <em>F</em>, <em>g</em> or <em>G</em> conversion specifier applies to a <code>half<em>n</em></code> argument.</p>
+</td>
+</tr>
+<tr>
+<td class="hdlist1">
+<em>hl</em>
+</td>
+<td class="hdlist2">
+<p>This modifier can only be used with the vector specifier.
+Specifies that a following <em>d</em>, <em>i</em>, <em>o</em>, <em>u</em>, <em>x</em> or <em>X</em> conversion specifier applies to an <code>int<em>n</em></code> or <code>uint<em>n</em></code> argument; that a following <em>a</em>, <em>A</em>, <em>e</em>, <em>E</em>, <em>f</em>, <em>F</em>, <em>g</em> or <em>G</em> conversion specifier applies to a <code>float<em>n</em></code> argument.</p>
+</td>
+</tr>
+<tr>
+<td class="hdlist1">
+<em>l</em> (ell)
+</td>
+<td class="hdlist2">
+<p>Specifies that a following <em>d</em>, <em>i</em>, <em>o</em>, <em>u</em>, <em>x</em> or <em>X</em> conversion specifier applies to a <code>long<em>n</em></code> or <code>ulong<em>n</em></code> argument; that a following <em>a</em>, <em>A</em>, <em>e</em>, <em>E</em>, <em>f</em>, <em>F</em>, <em>g</em> or <em>G</em> conversion specifier applies to a <code>double<em>n</em></code> argument.
+The <em>l</em> modifier is supported by the full profile.
+For the embedded profile, the <em>l</em> modifier is supported only if 64-bit integers or double-precision floating-point are supported by the device.</p>
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p>If a vector specifier appears without a length modifier, the behavior is undefined.
+The vector data type described by the vector specifier and length modifier must match the data type of the argument; otherwise the behavior is undefined.</p>
+</div>
+<div class="paragraph">
+<p>If a length modifier appears with any conversion specifier other than as specified above, the behavior is undefined.</p>
+</div>
+<div class="paragraph">
+<p>The conversion specifiers and their meanings are:</p>
+</div>
+<div class="hdlist">
+<table>
+<tr>
+<td class="hdlist1">
+<em>d</em>,&#160;<em>i</em>
+</td>
+<td class="hdlist2">
+<p>The <code>int</code>, <code>char<em>n</em></code>, <code>short<em>n</em></code>, <code>int<em>n</em></code> or <code>long<em>n</em></code> argument is converted to signed decimal in the style <em>[-]dddd</em>.
+The precision specifies the minimum number of digits to appear; if the value being converted can be represented in fewer digits, it is expanded with leading zeros.
+The default precision is 1. The result of converting a zero value with a precision of zero is no characters.</p>
+</td>
+</tr>
+<tr>
+<td class="hdlist1">
+<em>o</em>,&#160;<em>u</em>, <em>x</em>,&#160;<em>X</em>
+</td>
+<td class="hdlist2">
+<p>The <code>uint</code>, <code>uchar<em>n</em></code>, <code>ushort<em>n</em></code>, <code>uint<em>n</em></code> or <code>ulong<em>n</em></code> argument is converted to unsigned octal (<em>o</em>), unsigned decimal (<em>u</em>), or unsigned hexadecimal notation (<em>x</em> or <em>X</em>) in the style <em>dddd</em>; the letters <strong>abcdef</strong> are used for <em>x</em> conversion and the letters <strong>ABCDEF</strong> for <em>X</em> conversion.
+The precision specifies the minimum number of digits to appear; if the value being converted can be represented in fewer digits, it is expanded with leading zeros.
+The default precision is 1.
+The result of converting a zero value with a precision of zero is no characters.</p>
+</td>
+</tr>
+<tr>
+<td class="hdlist1">
+<em>f</em>,&#160;<em>F</em>
+</td>
+<td class="hdlist2">
+<p>A <code>double</code>, <code>half<em>n</em></code>, <code>float<em>n</em></code> or <code>double<em>n</em></code> argument representing a floating-point number is converted to decimal notation in the style <em>[-]ddd</em><strong>.</strong><em>ddd</em>, where the number of digits after the decimal-point character is equal to the precision specification.
+If the precision is missing, it is taken as 6; if the precision is zero and the <em>#</em> flag is not specified, no decimal-point character appears.
+If a decimal-point character appears, at least one digit appears before it.
+The value is rounded to the appropriate number of digits.
+A <code>double</code>, <code>half<em>n</em></code>, <code>float<em>n</em></code> or <code>double<em>n</em></code> argument representing an infinity is converted in one of the styles <em>[-]</em><strong>inf</strong> or <em>[-]</em><strong>infinity</strong> - which style is implementation-defined.
+A <code>double</code>, <code>half<em>n</em></code>, <code>float<em>n</em></code> or <code>double<em>n</em></code> argument representing a NaN is converted in one of the styles <em>[-]</em><strong>nan</strong> or <em>[-]</em><strong>nan</strong>(<em>n-char-sequence</em>) - which style, and the meaning of any <em>n-char-sequence</em>, is implementation-defined.
+The <em>F</em> conversion specifier produces <strong>INF</strong>, <strong>INFINITY</strong>, or <strong>NAN</strong> instead of <strong>inf</strong>, <strong>infinity</strong>, or <strong>nan</strong>, respectively. <a id="ftnref27"></a> <a href="#ftn27">[27]</a></p>
+</td>
+</tr>
+<tr>
+<td class="hdlist1">
+<em>e</em>,&#160;<em>E</em>
+</td>
+<td class="hdlist2">
+<p>A <code>double</code>, <code>half<em>n</em></code>, <code>float<em>n</em></code> or <code>double<em>n</em></code> argument representing a floating-point number is converted in the style <em>[-]d</em><strong>.</strong><em>ddd</em><strong>e</strong><em>±dd</em>, where there is one digit (which is nonzero if the argument is nonzero) before the decimal-point character and the number of digits after it is equal to the precision; if the precision is missing, it is taken as 6; if the precision is zero and the <em>#</em> flag is not specified, no decimal-point character appears.
+The value is rounded to the appropriate number of digits.
+The <em>E</em> conversion specifier produces a number with <strong>E</strong> instead of <strong>e</strong> introducing the exponent.
+The exponent always contains at least two digits, and only as many more digits as necessary to represent the exponent.
+If the value is zero, the exponent is zero.
+A <code>double</code>, <code>half<em>n</em></code>, <code>float<em>n</em></code> or <code>double<em>n</em></code> argument representing an infinity or NaN is converted in the style of an <em>f</em> or <em>F</em> conversion specifier.</p>
+</td>
+</tr>
+<tr>
+<td class="hdlist1">
+<em>g</em>,&#160;<em>G</em>
+</td>
+<td class="hdlist2">
+<p>A <code>double</code>, <code>half<em>n</em></code>, <code>float<em>n</em></code> or <code>double<em>n</em></code> argument representing a floating-point number is converted in style <em>f</em> or <em>e</em> (or in style <em>F</em> or <em>E</em> in the case of a <em>G</em> conversion specifier), depending on the value converted and the precision.
+Let <em>P</em> equal the precision if nonzero, 6 if the precision is omitted, or 1 if the precision is zero.
+Then, if a conversion with style <em>E</em> would have an exponent of <em>X</em>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>if <em>P &gt; X ≥ -4, the conversion is with style _f</em> (or <em>F</em>) and precision <em>P - (X + 1)</em>.</p>
+</li>
+<li>
+<p>otherwise, the conversion is with style <em>e</em> (or <em>E</em>) and precision <em>P - 1</em>.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Finally, unless the <em>#</em> flag is used, any trailing zeros are removed from the fractional portion of the result and the decimal-point character is removed if there is no fractional portion remaining.
+A <code>double</code>, <code>half<em>n</em></code>, <code>float<em>n</em></code> or <code>double<em>n</em></code> argument representing an infinity or NaN is converted in the style of an <em>f</em> or <em>F</em> conversion specifier.</p>
+</div>
+</td>
+</tr>
+<tr>
+<td class="hdlist1">
+<em>a</em>,&#160;<em>A</em>
+</td>
+<td class="hdlist2">
+<p>A <code>double</code>, <code>half<em>n</em></code>, <code>float<em>n</em></code> or <code>double<em>n</em></code> argument representing a floating-point number is converted in the style <em>[-]</em><strong>0x</strong><em>h</em><strong>.</strong><em>hhhh</em><strong>p</strong><em>±d</em>, where there is one hexadecimal digit (which is nonzero if the argument is a normalized floating-point number and is otherwise unspecified) before the decimal-point character <a id="ftnref28"></a> <a href="#ftn28">[28]</a> and the number of hexadecimal digits after it is equal to the precision; if the precision is missing, then the precision is sufficient for an exact representation of the value; if the precision is zero and the <em>#</em> flag is not specified, no decimal point character appears.
+The letters <strong>abcdef</strong> are used for <em>a</em> conversion and the letters <strong>ABCDEF</strong> for <em>A</em> conversion.
+The <em>A</em> conversion specifier produces a number with <strong>X</strong> and <strong>P</strong> instead of <strong>x</strong> and <strong>p</strong>.
+The exponent always contains at least one digit, and only as many more digits as necessary to represent the decimal exponent of 2.
+If the value is zero, the exponent is zero.
+A <code>double</code>, <code>half<em>n</em></code>, <code>float<em>n</em></code> or <code>double<em>n</em></code> argument representing an infinity or NaN is converted in the style of an <em>f</em> or <em>F</em> conversion specifier.</p>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+The conversion specifiers <em>e</em>, <em>E</em>, <em>g</em>, <em>G</em>, <em>a</em>, <em>A</em> convert a <code>float</code> or <code>half</code> argument that is a scalar type to a <code>double</code> only if the <code>double</code> data type is supported.
+If the <code>double</code> data type is not supported, the argument will be a <code>float</code> instead of a <code>double</code> and the <code>half</code> type will be converted to a <code>float</code>.
+</td>
+</tr>
+</table>
+</div>
+</td>
+</tr>
+<tr>
+<td class="hdlist1">
+<em>c</em>
+</td>
+<td class="hdlist2">
+<p>The <code>int</code> argument is converted to an <code>uchar</code> and the resulting character is written.</p>
+</td>
+</tr>
+<tr>
+<td class="hdlist1">
+<em>s</em>
+</td>
+<td class="hdlist2">
+<p>The argument shall be a literal string. <a id="ftnref29"></a> <a href="#ftn29">[29]</a>
+Characters from the literal string array are written up to (but not including) the terminating null character.
+If the precision is specified, no more than that many bytes are written.
+If the precision is not specified or is greater than the size of the array, the array shall contain a null character.</p>
+</td>
+</tr>
+<tr>
+<td class="hdlist1">
+<em>p</em>
+</td>
+<td class="hdlist2">
+<p>The argument shall be a pointer to <code>void</code>.
+The pointer can refer to a memory region in the global, constant, local, private or generic address space.
+The value of the pointer is converted to a sequence of printing characters in an implementation-defined manner.</p>
+</td>
+</tr>
+<tr>
+<td class="hdlist1">
+<em>%</em>
+</td>
+<td class="hdlist2">
+<p>A <strong>%</strong> character is written.
+No argument is converted. The complete conversion specification shall be <strong>%%</strong>.</p>
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p>If a conversion specification is invalid, the behavior is undefined.
+If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.</p>
+</div>
+<div class="paragraph">
+<p>In no case does a nonexistent or small field width cause truncation of a field; if the result of a conversion is wider than the field width, the field is expanded to contain the conversion result.</p>
+</div>
+<div class="paragraph">
+<p>For <em>a</em> and <em>A</em> conversions, the value is correctly rounded to a hexadecimal floating number with the given precision.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>float4  f = float4(1.0f, 2.0f, 3.0f, 4.0f);
+uchar4 uc = uchar4(0xFA, 0xFB, 0xFC, 0xFD);
+
+printf("f4 = %2.2v4hlf\n", f);
+printf("uc = %#v4hhx\n", uc);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The above two <code>printf</code> calls print the following:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>f4 = 1.00,2.00,3.00,4.00
+uc = 0xfa,0xfb,0xfc,0xfd</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>A few examples of valid use cases of <code>printf</code> for the conversion specifier <em>s</em> are given below.
+The argument value must be a pointer to a literal string.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_printf&gt;
+
+kernel void my_kernel( ... )
+{
+    cl::printf("%s\n", "this is a test string\n");
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>A few examples of invalid use cases of <code>printf</code> for the conversion specifier <em>s</em> are given below:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_printf&gt;
+
+kernel void my_kernel(char *s, ... )
+{
+    cl::printf("%s\n", s);
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>A few examples of invalid use cases of <code>printf</code> where data types given by the vector specifier and length modifier do not match the argument type are given below:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_printf&gt;
+using namespace cl;
+
+kernel void my_kernel( ... )
+{
+    uint2 ui = uint2(0x12345678, 0x87654321);
+    printf("unsigned short value = (%#v2hx)\n", ui);
+    printf("unsigned char value = (%#v2hhx)\n", ui);
+}</code></pre>
+</div>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="differences-between-opencl-c-and-c14-printf">3.23.3. Differences between OpenCL C++ and C++14 printf</h4>
+<div class="ulist">
+<ul>
+<li>
+<p>The <em>l</em> modifier followed by a <em>c</em> conversion specifier or <em>s</em> conversion specifier is not supported by OpenCL C++.</p>
+</li>
+<li>
+<p>The <em>ll</em>, <em>j</em>, <em>z</em>, <em>t</em>, and <em>L</em> length modifiers are not supported by OpenCL C++ but are reserved.</p>
+</li>
+<li>
+<p>The <em>n</em> conversion specifier is not supported by OpenCL C++ but is reserved.</p>
+</li>
+<li>
+<p>OpenCL C++ adds the optional <em>vn</em> vector specifier to support printing of vector types.</p>
+</li>
+<li>
+<p>The conversion specifiers <em>f</em>, <em>F</em>, <em>e</em>, <em>E</em>, <em>g</em>, <em>G</em>, <em>a</em>, <em>A</em> convert a float argument to a double only if the double data type is supported.
+Refer to the description of <code>CL_DEVICE_DOUBLE_FP_CONFIG</code> in <em>table 4.3</em>.
+If the double data type is not supported, the argument will be a float instead of a double.</p>
+</li>
+<li>
+<p>For the embedded profile, the <em>l</em> length modifier is supported only if 64-bit integers are supported.</p>
+</li>
+<li>
+<p>In OpenCL C++, <code>printf</code> returns 0 if it was executed successfully and -1 otherwise vs. C++14 where <code>printf</code> returns the number of characters printed or a negative value if an output or encoding error occurred.</p>
+</li>
+<li>
+<p>In OpenCL C++, the conversion specifier <em>s</em> can only be used for arguments that are literal strings.</p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="atomic-operations-library">3.24. Atomic Operations Library</h3>
+<div class="paragraph">
+<p>The OpenCL C++ programming language implements a subset of the C++14 atomics (refer to <em>chapter 29</em> of the C++14 specification) and synchronization operations.
+These operations play a special role in making assignments in one work-item visible to another.
+Please note that this chapter only presents synopsis of the atomics library and differences from C++14 specification.</p>
+</div>
+<div class="sect3">
+<h4 id="header-opencl_atomic-synopsis">3.24.1. Header &lt;opencl_atomic&gt; Synopsis</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+enum memory_order;
+enum memory_scope;
+
+template&lt;class T&gt; struct atomic;
+// specialization for scalar types T that satisfy cl::is_integral&lt;T&gt;
+template&lt;&gt; struct atomic&lt;integral&gt;;
+template&lt;class T&gt; struct atomic&lt;T*&gt;;
+
+using atomic_int = atomic&lt;int&gt;;
+using atomic_uint = atomic&lt;unsigned int&gt;;
+#if defined(cl_khr_int64_base_atomics) &amp;&amp; defined(cl_khr_int64_extended_atomics)
+using atomic_long = atomic&lt;long&gt;;
+using atomic_ulong = atomic&lt;unsigned long&gt;;
+#endif
+using atomic_float = atomic&lt;float&gt;;
+#if defined(cl_khr_fp64) &amp;&amp;
+    defined(cl_khr_int64_base_atomics) &amp;&amp;
+    defined(cl_khr_int64_extended_atomics)
+using atomic_double = atomic&lt;double&gt;;
+#endif
+#if (defined(cl_khr_int64_base_atomics) &amp;&amp;
+     defined(cl_khr_int64_extended_atomics) &amp;&amp;
+     __INTPTR_WIDTH__ == 64) ||
+    __INTPTR_WIDTH__ == 32
+using atomic_intptr_t = atomic&lt;intptr_t&gt;;
+using atomic_uintptr_t = atomic&lt;uintptr_t&gt;;
+#endif
+#if (defined(cl_khr_int64_base_atomics) &amp;&amp;
+     defined(cl_khr_int64_extended_atomics) &amp;&amp;
+     __SIZE_WIDTH__ == 64) ||
+    __SIZE_WIDTH__ == 32
+using atomic_size_t = atomic&lt;size_t&gt;;
+#endif
+#if (defined(cl_khr_int64_base_atomics) &amp;&amp;
+     defined(cl_khr_int64_extended_atomics) &amp;&amp;
+     __PTRDIFF_WIDTH__ == 64) ||
+    __PTRDIFF_WIDTH__ == 32
+using atomic_ptrdiff_t = atomic&lt;ptrdiff_t&gt;;
+#endif
+
+// Please note that all operations taking memory_order as a parameter have,
+// in addition to cpp14 specification, additional parameter for memory_scope
+template &lt;class T&gt;
+bool atomic_is_lock_free(const volatile atomic&lt;T&gt;*) noexcept;
+template &lt;class T&gt;
+bool atomic_is_lock_free(const atomic&lt;T&gt;*) noexcept;
+template &lt;class T&gt;
+void atomic_init(volatile atomic&lt;T&gt;*, T) noexcept;
+template &lt;class T&gt;
+void atomic_init(atomic&lt;T&gt;*, T) noexcept;
+template &lt;class T&gt;
+void atomic_store(volatile atomic&lt;T&gt;*, T) noexcept;
+template &lt;class T&gt;
+void atomic_store(atomic&lt;T&gt;*, T) noexcept;
+template &lt;class T&gt;
+void atomic_store_explicit(volatile atomic&lt;T&gt;*, T, memory_order,
+                           memory_scope) noexcept;
+template &lt;class T&gt;
+void atomic_store_explicit(atomic&lt;T&gt;*, T, memory_order,
+                           memory_scope) noexcept;
+template &lt;class T&gt;
+T atomic_load(const volatile atomic&lt;T&gt;*) noexcept;
+template &lt;class T&gt;
+T atomic_load(const atomic&lt;T&gt;*) noexcept;
+template &lt;class T&gt;
+T atomic_load_explicit(const volatile atomic&lt;T&gt;*, memory_order,
+                       memory_scope) noexcept;
+template &lt;class T&gt;
+T atomic_load_explicit(const atomic&lt;T&gt;*, memory_order, memory_scope) noexcept;
+template &lt;class T&gt;
+T atomic_exchange(volatile atomic&lt;T&gt;*, T) noexcept;
+template &lt;class T&gt;
+T atomic_exchange(atomic&lt;T&gt;*, T) noexcept;
+template &lt;class T&gt;
+T atomic_exchange_explicit(volatile atomic&lt;T&gt;*, T, memory_order,
+                           memory_scope) noexcept;
+template &lt;class T&gt;
+T atomic_exchange_explicit(atomic&lt;T&gt;*, T, memory_order, memory_scope) noexcept;
+template &lt;class T&gt;
+bool atomic_compare_exchange_weak(volatile atomic&lt;T&gt;*, T*, T) noexcept;
+template &lt;class T&gt;
+bool atomic_compare_exchange_weak(atomic&lt;T&gt;*, T*, T) noexcept;
+template &lt;class T&gt;
+bool atomic_compare_exchange_strong(volatile atomic&lt;T&gt;*, T*, T) noexcept;
+template &lt;class T&gt;
+bool atomic_compare_exchange_strong(atomic&lt;T&gt;*, T*, T) noexcept;
+template &lt;class T&gt;
+bool atomic_compare_exchange_weak_explicit(volatile atomic&lt;T&gt;*, T*, T,
+                                           memory_order, memory_order,
+                                           memory_scope) noexcept;
+template &lt;class T&gt;
+bool atomic_compare_exchange_weak_explicit(atomic&lt;T&gt;*, T*, T, memory_order,
+                                           memory_order, memory_scope) noexcept;
+template &lt;class T&gt;
+bool atomic_compare_exchange_strong_explicit(volatile atomic&lt;T&gt;*, T*, T,
+                                             memory_order, memory_order,
+                                             memory_scope) noexcept;
+template &lt;class T&gt;
+bool atomic_compare_exchange_strong_explicit(atomic&lt;T&gt;*, T*, T,
+                                             memory_order, memory_order,
+                                             memory_scope) noexcept;
+
+// Please note that all operations taking memory_order as a parameter have
+// additional overloads, in addition to cpp14 specification, taking both
+// memory_order and memory_scope parameters.
+template &lt;class T&gt;
+T atomic_fetch_add(volatile atomic&lt;T&gt;*, T) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_add(atomic&lt;T&gt;*, T) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_add_explicit(volatile atomic&lt;T&gt;*, T, memory_order,
+                            memory_scope) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_add_explicit(atomic&lt;T&gt;*, T, memory_order, memory_scope) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_sub(volatile atomic&lt;T&gt;*, T) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_sub(atomic&lt;T&gt;*, T) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_sub_explicit(volatile atomic&lt;T&gt;*, T, memory_order,
+                            memory_scope) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_sub_explicit(atomic&lt;T&gt;*, T, memory_order, memory_scope) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_and(volatile atomic&lt;T&gt;*, T) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_and(atomic&lt;T&gt;*, T) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_and_explicit(volatile atomic&lt;T&gt;*, T, memory_order,
+                            memory_scope) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_and_explicit(atomic&lt;T&gt;*, T, memory_order, memory_scope) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_or(volatile atomic&lt;T&gt;*, T) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_or(atomic&lt;T&gt;*, T) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_or_explicit(volatile atomic&lt;T&gt;*, T, memory_order,
+                           memory_scope) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_or_explicit(atomic&lt;T&gt;*, T, memory_order, memory_scope) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_xor(volatile atomic&lt;T&gt;*, T) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_xor(atomic&lt;T&gt;*, T) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_xor_explicit(volatile atomic&lt;T&gt;*, T, memory_order,
+                            memory_scope) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_xor_explicit(atomic&lt;T&gt;*, T, memory_order, memory_scope) noexcept;
+//OpenCL specific min/max atomics:
+T atomic_fetch_min(volatile atomic&lt;T&gt;*, T) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_min(atomic&lt;T&gt;*, T) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_min_explicit(volatile atomic&lt;T&gt;*, T, memory_order,
+                            memory_scope) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_min_explicit(atomic&lt;T&gt;*, T, memory_order, memory_scope) noexcept;
+T atomic_fetch_max(volatile atomic&lt;T&gt;*, T) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_max(atomic&lt;T&gt;*, T) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_max_explicit(volatile atomic&lt;T&gt;*, T, memory_order,
+                            memory_scope) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_max_explicit(atomic&lt;T&gt;*, T, memory_order, memory_scope) noexcept;
+
+template &lt;class T&gt;
+void atomic_store(atomic&lt;T&gt;* object, T value) noexcept;
+template &lt;class T&gt;
+void atomic_store(volatile atomic&lt;T&gt;* object, T value) noexcept;
+template &lt;class T&gt;
+void atomic_store_explicit(atomic&lt;T&gt;* object, T value, memory_order,
+                           memory_scope) noexcept;
+template &lt;class T&gt;
+void atomic_store_explicit(volatile atomic&lt;T&gt;* object, T value, memory_order,
+                           memory_scope) noexcept;
+
+template &lt;class T&gt;
+T atomic_load(atomic&lt;T&gt;* object) noexcept;
+template &lt;class T&gt;
+T atomic_load(volatile atomic&lt;T&gt;* object) noexcept;
+template &lt;class T&gt;
+T atomic_load_explicit(atomic&lt;T&gt;* object, memory_order, memory_scope) noexcept;
+template &lt;class T&gt;
+T atomic_load_explicit(volatile atomic&lt;T&gt;* object, memory_order,
+                       memory_scope) noexcept;
+
+template &lt;class T&gt;
+T atomic_exchange(atomic&lt;T&gt;* object, T value) noexcept;
+template &lt;class T&gt;
+T atomic_exchange(volatile atomic&lt;T&gt;* object, T value) noexcept;
+template &lt;class T&gt;
+T atomic_exchange_explicit(atomic&lt;T&gt;* object, T value, memory_order,
+                           memory_scope) noexcept;
+template &lt;class T&gt;
+T atomic_exchange_explicit(volatile atomic&lt;T&gt;* object, T value, memory_order,
+                           memory_scope) noexcept;
+
+template &lt;class T&gt;
+bool atomic_compare_exchange_strong(atomic&lt;T&gt;* object, T* expected,
+                                    T desired) noexcept;
+template &lt;class T&gt;
+bool atomic_compare_exchange_strong(volatile atomic&lt;T&gt;* object, T* expected,
+                                    T desired) noexcept;
+template &lt;class T&gt;
+bool atomic_compare_exchange_strong_explicit(atomic&lt;T&gt;* object, T* expected,
+                                             T desired, memory_order,
+                                             memory_scope) noexcept;
+template &lt;class T&gt;
+bool atomic_compare_exchange_strong_explicit(volatile atomic&lt;T&gt;* object,
+                                             T* expected, T desired,
+                                             memory_order,
+                                             memory_scope) noexcept;
+template &lt;class T&gt;
+bool atomic_compare_exchange_weak(atomic&lt;T&gt;* object, T* expected,
+                                  T desired) noexcept;
+template &lt;class T&gt;
+bool atomic_compare_exchange_weak(volatile atomic&lt;T&gt;* object, T* expected,
+                                  T desired) noexcept;
+template &lt;class T&gt;
+bool atomic_compare_exchange_weak_explicit(atomic&lt;T&gt;* object, T* expected,
+                                           T desired, memory_order,
+                                           memory_scope) noexcept;
+template &lt;class T&gt;
+bool atomic_compare_exchange_weak_explicit(volatile atomic&lt;T&gt;* object,
+                                           T* expected, T desired,
+                                           memory_order, memory_scope) noexcept;
+
+template &lt;class T&gt;
+T atomic_fetch_add(atomic&lt;T&gt;* object, T value) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_add(volatile atomic&lt;T&gt;* object, T value) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_add_explicit(atomic&lt;T&gt;* object, T value, memory_order,
+                            memory_scope) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_add_explicit(volatile atomic&lt;T&gt;* object, T value, memory_order,
+                            memory_scope) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_and(atomic&lt;T&gt;* object, T value) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_and(volatile atomic&lt;T&gt;* object, T value) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_and_explicit(atomic&lt;T&gt;* object, T value, memory_order,
+                            memory_scope) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_and_explicit(volatile atomic&lt;T&gt;* object, T value, memory_order,
+                            memory_scope) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_or(atomic&lt;T&gt;* object, T value) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_or(volatile atomic&lt;T&gt;* object, T value) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_or_explicit(atomic&lt;T&gt;* object, T value, memory_order,
+                           memory_scope) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_or_explicit(volatile atomic&lt;T&gt;* object, T value, memory_order,
+                           memory_scope) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_sub(atomic&lt;T&gt;* object, T value) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_sub(volatile atomic&lt;T&gt;* object, T value) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_sub_explicit(atomic&lt;T&gt;* object, T value, memory_order,
+                            memory_scope) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_sub_explicit(volatile atomic&lt;T&gt;* object, T value, memory_order,
+                            memory_scope) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_xor(atomic&lt;T&gt;* object, T value) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_xor(volatile atomic&lt;T&gt;* object, T value) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_xor_explicit(atomic&lt;T&gt;* object, T value, memory_order,
+                            memory_scope) noexcept;
+template &lt;class T&gt;
+T atomic_fetch_xor_explicit(volatile atomic&lt;T&gt;* object, T value, memory_order,
+                            memory_scope) noexcept;
+
+#if (defined(cl_khr_int64_base_atomics) &amp;&amp;
+     defined(cl_khr_int64_extended_atomics) &amp;&amp;
+     __SIZE_WIDTH__ == 64) ||
+    __SIZE_WIDTH__ == 32
+template &lt;class T&gt;
+T* atomic_fetch_add(atomic&lt;T*&gt;* object, ptrdiff_t value) noexcept;
+template &lt;class T&gt;
+T* atomic_fetch_add(volatile atomic&lt;T*&gt;* object, ptrdiff_t value) noexcept;
+template &lt;class T&gt;
+T* atomic_fetch_add_explicit(atomic&lt;T*&gt;* object, ptrdiff_t value, memory_order,
+                             memory_scope) noexcept;
+template &lt;class T&gt;
+T* atomic_fetch_add_explicit(volatile atomic&lt;T*&gt;* object, ptrdiff_t value,
+                             memory_order, memory_scope) noexcept;
+template &lt;class T&gt;
+T* atomic_fetch_and(atomic&lt;T*&gt;* object, ptrdiff_t value) noexcept;
+template &lt;class T&gt;
+T* atomic_fetch_and(volatile atomic&lt;T*&gt;* object, ptrdiff_t value) noexcept;
+template &lt;class T&gt;
+T* atomic_fetch_and_explicit(atomic&lt;T*&gt;* object, ptrdiff_t value, memory_order,
+                             memory_scope) noexcept;
+template &lt;class T&gt;
+T* atomic_fetch_and_explicit(volatile atomic&lt;T*&gt;* object, ptrdiff_t value,
+                             memory_order, memory_scope) noexcept;
+template &lt;class T&gt;
+T* atomic_fetch_or(atomic&lt;T*&gt;* object, ptrdiff_t value) noexcept;
+template &lt;class T&gt;
+T* atomic_fetch_or(volatile atomic&lt;T*&gt;* object, ptrdiff_t value) noexcept;
+template &lt;class T&gt;
+T* atomic_fetch_or_explicit(atomic&lt;T*&gt;* object, ptrdiff_t value, memory_order,
+                            memory_scope) noexcept;
+template &lt;class T&gt;
+T* atomic_fetch_or_explicit(volatile atomic&lt;T*&gt;* object, ptrdiff_t value,
+                            memory_order, memory_scope) noexcept;
+template &lt;class T&gt;
+T* atomic_fetch_sub(atomic&lt;T*&gt;* object, ptrdiff_t value) noexcept;
+template &lt;class T&gt;
+T* atomic_fetch_sub(volatile atomic&lt;T*&gt;* object, ptrdiff_t value) noexcept;
+template &lt;class T&gt;
+T* atomic_fetch_sub_explicit(atomic&lt;T*&gt;* object, ptrdiff_t value, memory_order,
+                             memory_scope) noexcept;
+template &lt;class T&gt;
+T* atomic_fetch_sub_explicit(volatile atomic&lt;T*&gt;* object, ptrdiff_t value,
+                             memory_order, memory_scope) noexcept;
+template &lt;class T&gt;
+T* atomic_fetch_xor(atomic&lt;T*&gt;* object, ptrdiff_t value) noexcept;
+template &lt;class T&gt;
+T* atomic_fetch_xor(volatile atomic&lt;T*&gt;* object, ptrdiff_t value) noexcept;
+template &lt;class T&gt;
+T* atomic_fetch_xor_explicit(atomic&lt;T*&gt;* object, ptrdiff_t value, memory_order,
+                             memory_scope) noexcept;
+template &lt;class T&gt;
+T* atomic_fetch_xor_explicit(volatile atomic&lt;T*&gt;* object, ptrdiff_t value,
+                             memory_order, memory_scope) noexcept;
+#endif
+
+void atomic_fence(mem_fence flags, memory_order order,
+                  memory_scope scope) noexcept;
+
+#define ATOMIC_VAR_INIT(value) as described in cpp14 specification [atomics.types.operations]
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="order-and-scope">3.24.2. Order and scope</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+enum memory_order
+{
+    memory_order_relaxed,
+    memory_order_acquire,
+    memory_order_release,
+    memory_order_acq_rel,
+    memory_order_seq_cst
+};
+
+enum memory_scope
+{
+    memory_scope_all_svm_devices,
+    memory_scope_device,
+    memory_scope_work_group,
+    memory_scope_sub_group,
+    memory_scope_work_item
+};
+
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>An enumeration <code>memory_order</code> is described in section [atomics.order] of C++14 specification. <a id="ftnref7"></a> <a href="#ftn7">[7]</a></p>
+</div>
+<div class="paragraph">
+<p>The enumerated type <code>memory_scope</code> specifies whether the memory ordering constraints given by <code>memory_order</code> apply to work-items in a work-group or work-items of a kernel(s) executing on the device or across devices (in the case of shared virtual memory). Its enumeration constants are as follows:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>memory_scope_work_item</code> <a id="ftnref8"></a> <a href="#ftn8">[8]</a></p>
+</li>
+<li>
+<p><code>memory_scope_sub_group</code></p>
+</li>
+<li>
+<p><code>memory_scope_work_group</code></p>
+</li>
+<li>
+<p><code>memory_scope_device</code></p>
+</li>
+<li>
+<p><code>memory_scope_all_svm_devices</code></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The memory scope should only be used when performing atomic operations to global memory.
+Atomic operations to local memory only guarantee memory ordering in the work-group not across work-groups and therefore ignore the <code>memory_scope</code> value.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+With fine-grained system SVM, sharing happens at the granularity of individual loads and stores anywhere in host memory.
+Memory consistency is always guaranteed at synchronization points, but to obtain finer control over consistency, the OpenCL atomics functions may be used to ensure that the updates to individual data values made by
+one unit of execution are visible to other execution units.
+In particular, when a host thread needs fine control over the consistency of memory that is shared with one or more OpenCL devices, it must use atomic and fence operations that are compatible with the C++14 atomic operations <a id="ftnref9"></a> <a href="#ftn9">[9]</a>.
+</td>
+</tr>
+</table>
+</div>
+</div>
+<div class="sect3">
+<h4 id="atomic-lock-free-property">3.24.3. Atomic lock-free property</h4>
+<div class="paragraph">
+<p>OpenCL C++ requires all atomic types to be lock free.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="atomic-types">3.24.4. Atomic types</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+
+template &lt;class T&gt;
+struct atomic
+{
+    bool is_lock_free() const volatile noexcept;
+    bool is_lock_free() const noexcept;
+    void store(T, memory_order = memory_order_seq_cst,
+               memory_scope = memory_scope_device) volatile noexcept;
+    void store(T, memory_order = memory_order_seq_cst,
+               memory_scope = memory_scope_device) noexcept;
+    T load(memory_order = memory_order_seq_cst,
+           memory_scope = memory_scope_device) const volatile noexcept;
+    T load(memory_order = memory_order_seq_cst,
+           memory_scope = memory_scope_device) const noexcept;
+    operator T() const volatile noexcept;
+    operator T() const noexcept;
+    T exchange(T, memory_order = memory_order_seq_cst,
+               memory_scope = memory_scope_device) volatile noexcept;
+    T exchange(T, memory_order = memory_order_seq_cst,
+               memory_scope = memory_scope_device) noexcept;
+    bool compare_exchange_weak(T&amp;, T, memory_order,
+                               memory_order, memory_scope) volatile noexcept;
+    bool compare_exchange_weak(T&amp;, T, memory_order,
+                               memory_order, memory_scope) noexcept;
+    bool compare_exchange_strong(T&amp;, T, memory_order,
+                                 memory_order, memory_scope) volatile noexcept;
+    bool compare_exchange_strong(T&amp;, T, memory_order,
+                                 memory_order, memory_scope) noexcept;
+    bool compare_exchange_weak(T&amp;, T, memory_order = memory_order_seq_cst,
+                          memory_scope = memory_scope_device) volatile noexcept;
+    bool compare_exchange_weak(T&amp;, T, memory_order = memory_order_seq_cst,
+                               memory_scope = memory_scope_device) noexcept;
+    bool compare_exchange_strong(T&amp;, T, memory_order = memory_order_seq_cst,
+                          memory_scope = memory_scope_device) volatile noexcept;
+    bool compare_exchange_strong(T&amp;, T, memory_order = memory_order_seq_cst,
+                                 memory_scope = memory_scope_device) noexcept;
+    atomic() noexcept = default;
+    constexpr atomic(T) noexcept;
+    atomic(const atomic&amp;) = delete;
+    atomic&amp; operator=(const atomic&amp;) = delete;
+    atomic&amp; operator=(const atomic&amp;) volatile = delete;
+    T operator=(T) volatile noexcept;
+    T operator=(T) noexcept;
+};
+
+template &lt;&gt;
+struct atomic&lt;integral&gt;
+{
+    bool is_lock_free() const volatile noexcept;
+    bool is_lock_free() const noexcept;
+    void store(integral, memory_order = memory_order_seq_cst,
+               memory_scope = memory_scope_device) volatile noexcept;
+    void store(integral, memory_order = memory_order_seq_cst,
+               memory_scope = memory_scope_device) noexcept;
+    integral load(memory_order = memory_order_seq_cst,
+                  memory_scope = memory_scope_device) const volatile noexcept;
+    integral load(memory_order = memory_order_seq_cst,
+                  memory_scope = memory_scope_device) const noexcept;
+    operator integral() const volatile noexcept;
+    operator integral() const noexcept;
+    integral exchange(integral, memory_order = memory_order_seq_cst,
+                      memory_scope = memory_scope_device) volatile noexcept;
+    integral exchange(integral, memory_order = memory_order_seq_cst,
+                      memory_scope = memory_scope_device) noexcept;
+    bool compare_exchange_weak(integral&amp;, integral, memory_order,
+                               memory_order, memory_scope) volatile noexcept;
+    bool compare_exchange_weak(integral&amp;, integral, memory_order, memory_order,
+                               memory_scope) noexcept;
+    bool compare_exchange_strong(integral&amp;, integral, memory_order,
+                                 memory_order, memory_scope) volatile noexcept;
+    bool compare_exchange_strong(integral&amp;, integral, memory_order,
+                                 memory_order, memory_scope) noexcept;
+    bool compare_exchange_weak(integral&amp;, integral,
+                          memory_order = memory_order_seq_cst,
+                          memory_scope = memory_scope_device) volatile noexcept;
+    bool compare_exchange_weak(integral&amp;, integral,
+                               memory_order = memory_order_seq_cst,
+                               memory_scope = memory_scope_device) noexcept;
+    bool compare_exchange_strong(integral&amp;, integral,
+                          memory_order = memory_order_seq_cst,
+                          memory_scope = memory_scope_device) volatile noexcept;
+    bool compare_exchange_strong(integral&amp;, integral,
+                                 memory_order = memory_order_seq_cst,
+                                 memory_scope = memory_scope_device) noexcept;
+    integral fetch_add(integral, memory_order = memory_order_seq_cst,
+                       memory_scope = memory_scope_device) volatile noexcept;
+    integral fetch_add(integral, memory_order = memory_order_seq_cst,
+                       memory_scope = memory_scope_device) noexcept;
+    integral fetch_sub(integral, memory_order = memory_order_seq_cst,
+                       memory_scope = memory_scope_device) volatile noexcept;
+    integral fetch_sub(integral, memory_order = memory_order_seq_cst,
+                       memory_scope = memory_scope_device) noexcept;
+    integral fetch_and(integral, memory_order = memory_order_seq_cst,
+                       memory_scope = memory_scope_device) volatile noexcept;
+    integral fetch_and(integral, memory_order = memory_order_seq_cst,
+                       memory_scope = memory_scope_device) noexcept;
+    integral fetch_or(integral, memory_order = memory_order_seq_cst,
+                      memory_scope = memory_scope_device) volatile noexcept;
+    integral fetch_or(integral, memory_order = memory_order_seq_cst,
+                      memory_scope = memory_scope_device) noexcept;
+    integral fetch_xor(integral, memory_order = memory_order_seq_cst,
+                       memory_scope = memory_scope_device) volatile noexcept;
+    integral fetch_xor(integral, memory_order = memory_order_seq_cst,
+                       memory_scope = memory_scope_device) noexcept;
+    integral fetch_min(integral, memory_order = memory_order_seq_cst,
+                       memory_scope = memory_scope_device) volatile noexcept;
+    integral fetch_min(integral, memory_order = memory_order_seq_cst,
+                       memory_scope = memory_scope_device) noexcept;
+    integral fetch_max(integral, memory_order = memory_order_seq_cst,
+                       memory_scope = memory_scope_device) volatile noexcept;
+    integral fetch_max(integral, memory_order = memory_order_seq_cst,
+                       memory_scope = memory_scope_device) noexcept;
+    atomic() noexcept = default;
+    constexpr atomic(integral) noexcept;
+    atomic(const atomic&amp;) = delete;
+    atomic&amp; operator=(const atomic&amp;) = delete;
+    atomic&amp; operator=(const atomic&amp;) volatile = delete;
+    integral operator=(integral) volatile noexcept;
+    integral operator=(integral) noexcept;
+    integral operator++(int) volatile noexcept;
+    integral operator++(int) noexcept;
+    integral operator--(int) volatile noexcept;
+    integral operator--(int) noexcept;
+    integral operator++() volatile noexcept;
+    integral operator++() noexcept;
+    integral operator--() volatile noexcept;
+    integral operator--() noexcept;
+    integral operator+=(integral) volatile noexcept;
+    integral operator+=(integral) noexcept;
+    integral operator-=(integral) volatile noexcept;
+    integral operator-=(integral) noexcept;
+    integral operator&amp;=(integral) volatile noexcept;
+    integral operator&amp;=(integral) noexcept;
+    integral operator|=(integral) volatile noexcept;
+    integral operator|=(integral) noexcept;
+    integral operator^=(integral) volatile noexcept;
+    integral operator^=(integral) noexcept;
+};
+
+#if (defined(cl_khr_int64_base_atomics) &amp;&amp;
+     defined(cl_khr_int64_extended_atomics) &amp;&amp;
+     __SIZE_WIDTH__ == 64) ||
+    __SIZE_WIDTH__ == 32
+template &lt;class T&gt;
+struct atomic&lt;T*&gt;
+{
+    bool is_lock_free() const volatile noexcept;
+    bool is_lock_free() const noexcept;
+    void store(T*, memory_order = memory_order_seq_cst,
+               memory_scope = memory_scope_device) volatile noexcept;
+    void store(T*, memory_order = memory_order_seq_cst,
+               memory_scope = memory_scope_device) noexcept;
+    T* load(memory_order = memory_order_seq_cst,
+            memory_scope = memory_scope_device) const volatile noexcept;
+    T* load(memory_order = memory_order_seq_cst,
+            memory_scope = memory_scope_device) const noexcept;
+    operator T*() const volatile noexcept;
+    operator T*() const noexcept;
+    T* exchange(T*, memory_order = memory_order_seq_cst,
+                memory_scope = memory_scope_device) volatile noexcept;
+    T* exchange(T*, memory_order = memory_order_seq_cst,
+                memory_scope = memory_scope_device) noexcept;
+    bool compare_exchange_weak(T*&amp;, T*, memory_order,
+                               memory_order, memory_scope) volatile noexcept;
+    bool compare_exchange_weak(T*&amp;, T*, memory_order,
+                               memory_order, memory_scope) noexcept;
+    bool compare_exchange_strong(T*&amp;, T*, memory_order,
+                                 memory_order, memory_scope) volatile noexcept;
+    bool compare_exchange_strong(T*&amp;, T*, memory_order,
+                                 memory_order, memory_scope) noexcept;
+    bool compare_exchange_weak(T*&amp;, T*, memory_order = memory_order_seq_cst,
+                          memory_scope = memory_scope_device) volatile noexcept;
+    bool compare_exchange_weak(T*&amp;, T*, memory_order = memory_order_seq_cst,
+                               memory_scope = memory_scope_device) noexcept;
+    bool compare_exchange_strong(T*&amp;, T*, memory_order = memory_order_seq_cst,
+                          memory_scope = memory_scope_device) volatile noexcept;
+    bool compare_exchange_strong(T*&amp;, T*, memory_order = memory_order_seq_cst,
+                                 memory_scope = memory_scope_device) noexcept;
+    T* fetch_add(ptrdiff_t, memory_order = memory_order_seq_cst,
+                 memory_scope = memory_scope_device) volatile noexcept;
+    T* fetch_add(ptrdiff_t, memory_order = memory_order_seq_cst,
+                 memory_scope = memory_scope_device) noexcept;
+    T* fetch_sub(ptrdiff_t, memory_order = memory_order_seq_cst,
+                 memory_scope = memory_scope_device) volatile noexcept;
+    T* fetch_sub(ptrdiff_t, memory_order = memory_order_seq_cst,
+                 memory_scope = memory_scope_device) noexcept;
+    atomic() noexcept = default;
+    constexpr atomic(T*) noexcept;
+    atomic(const atomic&amp;) = delete;
+    atomic&amp; operator=(const atomic&amp;) = delete;
+    atomic&amp; operator=(const atomic&amp;) volatile = delete;
+    T* operator=(T*) volatile noexcept;
+    T* operator=(T*) noexcept;
+    T* operator++(int) volatile noexcept;
+    T* operator++(int) noexcept;
+    T* operator--(int) volatile noexcept;
+    T* operator--(int) noexcept;
+    T* operator++() volatile noexcept;
+    T* operator++() noexcept;
+    T* operator--() volatile noexcept;
+    T* operator--() noexcept;
+    T* operator+=(ptrdiff_t) volatile noexcept;
+    T* operator+=(ptrdiff_t) noexcept;
+    T* operator-=(ptrdiff_t) volatile noexcept;
+    T* operator-=(ptrdiff_t) noexcept;
+};
+#endif
+
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The <em>opencl_atomic</em> header defines general specialization for class template <code>atomic&lt;T&gt;</code>.</p>
+</div>
+<div class="paragraph">
+<p>There are explicit specializations for integral types.
+Each of these specializations provides set of extra operators suitable for integral types.</p>
+</div>
+<div class="paragraph">
+<p>There is an explicit specialization of the atomic template for pointer types.</p>
+</div>
+<div class="paragraph">
+<p>All atomic classes have deleted copy constructor and deleted copy assignment operators.</p>
+</div>
+<div class="paragraph">
+<p>There are several typedefs for atomic types specified as follows:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+using atomic_int = atomic&lt;int&gt;;
+using atomic_uint = atomic&lt;uint&gt;;
+#if defined(cl_khr_int64_base_atomics) &amp;&amp; defined(cl_khr_int64_extended_atomics)
+using atomic_long = atomic&lt;long&gt;;
+using atomic_ulong = atomic&lt;ulong&gt;;
+#endif
+using atomic_float = atomic&lt;float&gt;;
+#if defined(cl_khr_fp64) &amp;&amp;
+    defined(cl_khr_int64_base_atomics) &amp;&amp;
+    defined(cl_khr_int64_extended_atomics)
+using atomic_double = atomic&lt;double&gt;;
+#endif
+#if (defined(cl_khr_int64_base_atomics) &amp;&amp;
+     defined(cl_khr_int64_extended_atomics) &amp;&amp;
+     __INTPTR_WIDTH__ == 64) ||
+    __INTPTR_WIDTH__ == 32
+using atomic_intptr_t = atomic&lt;intptr_t&gt;;
+using atomic_uintptr_t = atomic&lt;uintptr_t&gt;;
+#endif
+#if (defined(cl_khr_int64_base_atomics) &amp;&amp;
+     defined(cl_khr_int64_extended_atomics) &amp;&amp;
+     __SIZE_WIDTH__ == 64) ||
+    __SIZE_WIDTH__ == 32
+using atomic_size_t = atomic&lt;size_t&gt;;
+#endif
+#if (defined(cl_khr_int64_base_atomics) &amp;&amp;
+     defined(cl_khr_int64_extended_atomics) &amp;&amp;
+     __PTRDIFF_WIDTH__ == 64) ||
+    __PTRDIFF_WIDTH__ == 32
+using atomic_ptrdiff_t = atomic&lt;ptrdiff_t&gt;;
+#endif
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="flag-type-and-operations">3.24.5. Flag type and operations</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+struct atomic_flag
+{
+    bool test_and_set(memory_order = memory_order_seq_cst,
+                      memory_scope = memory_scope_device) volatile noexcept;
+    bool test_and_set(memory_order = memory_order_seq_cst,
+                      memory_scope = memory_scope_device) noexcept;
+    void clear(memory_order = memory_order_seq_cst,
+               memory_scope = memory_scope_device) volatile noexcept;
+    void clear(memory_order = memory_order_seq_cst,
+               memory_scope = memory_scope_device) noexcept;
+    atomic_flag() noexcept = default;
+    atomic_flag(const atomic_flag&amp;) = delete;
+    atomic_flag&amp; operator=(const atomic_flag&amp;) = delete;
+    atomic_flag&amp; operator=(const atomic_flag&amp;) volatile = delete;
+};
+
+bool atomic_flag_test_and_set(volatile atomic_flag*) noexcept;
+bool atomic_flag_test_and_set(atomic_flag*) noexcept;
+bool atomic_flag_test_and_set_explicit(volatile atomic_flag*, memory_order,
+                                       memory_scope) noexcept;
+bool atomic_flag_test_and_set_explicit(atomic_flag*, memory_order,
+                                       memory_scope) noexcept;
+void atomic_flag_clear(volatile atomic_flag*) noexcept;
+void atomic_flag_clear(atomic_flag*) noexcept;
+void atomic_flag_clear_explicit(volatile atomic_flag*, memory_order,
+                                memory_scope) noexcept;
+void atomic_flag_clear_explicit(atomic_flag*, memory_order,
+                                memory_scope) noexcept;
+
+#define ATOMIC_FLAG_INIT as described in cpp14 specification [atomics.flag]
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="fences">3.24.6. Fences</h4>
+<div class="sect4">
+<h5 id="atomic_fence">atomic_fence</h5>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>void atomic_fence(mem_fence flags, memory_order order, memory_scope scope) noexcept;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Orders loads or/and stores of a work-item executing a kernel.</p>
+</div>
+<div class="paragraph">
+<p><code>flags</code> must be set to <code>mem_fence::global</code>, <code>mem_fence::local</code>, <code>mem_fence::image</code> or a combination of these values ORed together; otherwise the behavior is undefined.
+The behavior of calling <code>atomic_fence</code> with <code>mem_fence::global</code> and <code>mem_fence::local</code> ORed together is equivalent to calling <code>atomic_fence</code> individually for each of the fence values set in <code>flags</code>.
+<code>mem_fence::image</code> cannot be specified ORed with <code>mem_fence::global</code> and <code>mem_fence::local</code>.</p>
+</div>
+<div class="paragraph">
+<p>Depending on the value of order, this operation:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Has no effects, if <code>order == memory_order_relaxed</code>.</p>
+</li>
+<li>
+<p>Is an acquire fence, if <code>order == memory_order_acquire</code>.</p>
+</li>
+<li>
+<p>Is a release fence, if <code>order == memory_order_release</code>.</p>
+</li>
+<li>
+<p>Is both an acquire fence and a release fence, if <code>order == memory_order_acq_rel</code>.</p>
+</li>
+<li>
+<p>Is a sequentially consistent acquire and release fence, if <code>order == memory_order_seq_cst</code>.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For images declared with the <code>image_access::read_write</code>, the <code>atomic_fence</code> must be called to make sure that writes to the image by a work-item become visible to that work-item on subsequent reads to that image by that work-item.
+Only a scope of <code>memory_order_acq_rel</code> is valid for <code>atomic_fence</code> when passed the <code>mem_fence::image</code> flag.</p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="bit-atomics">3.24.7. 64-bit Atomics</h4>
+<div class="paragraph">
+<p>The optional extensions <strong>cl_khr_int64_base_atomics</strong> and <strong>cl_khr_int64_extended_atomics</strong> implement atomic operations on 64-bit signed and unsigned integers to locations in global and local memory.</p>
+</div>
+<div class="paragraph">
+<p>An application that wants to use 64-bit atomic types will need to define <code>cl_khr_int64_base_atomics</code> and <code>cl_khr_int64_extended_atomics</code> macros in the code before including the OpenCL C++ standard library headers or using <em>-D</em> compiler option (see the <a href="#preprocessor_options"><em>Preprocessor options</em></a> section).</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="restrictions-3">3.24.8. Restrictions</h4>
+<div class="ulist">
+<ul>
+<li>
+<p>The generic <code>atomic&lt;T&gt;</code> class template is only available if <code>T</code> is <code>int</code>, <code>uint</code>, <code>long</code>, <code>ulong</code> <a id="ftnref10"></a> <a href="#ftn10">[10]</a>, <code>float</code>, <code>double</code> <a id="ftnref11"></a> <a href="#ftn11">[11]</a>, <code>intptr_t</code> <a id="ftnref12"></a> <a href="#ftn12">[12]</a>, <code>uintptr_t</code>, <code>size_t</code>, <code>ptrdiff_t</code>.</p>
+</li>
+<li>
+<p>The <code>atomic_bool</code>, <code>atomic_char</code>, <code>atomic_uchar</code>, <code>atomic_short</code>, <code>atomic_ushort</code>, <code>atomic_intmax_t</code> and <code>atomic_uintmax_t</code> types are not supported by OpenCL C++.</p>
+</li>
+<li>
+<p>OpenCL C++ requires that the built-in atomic functions on atomic types are lock-free.</p>
+</li>
+<li>
+<p>The atomic data types cannot be declared inside a kernel or non-kernel function unless they are declared as <code>static</code> keyword or in <code>local&lt;T&gt;</code> and <code>global&lt;T&gt;</code> containers.</p>
+</li>
+<li>
+<p>The atomic operations on the private memory can result in undefined behavior.</p>
+</li>
+<li>
+<p><code>memory_order_consume</code> is not supported by OpenCL C++.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="examples-4">3.24.9. Examples</h4>
+<div class="sect4">
+<h5 id="example-1-4">Example 1</h5>
+<div class="paragraph">
+<p>Examples of using atomic with and without an explicit address space
+storage class.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#include &lt;opencl_memory&gt;
+#include &lt;opencl_atomic&gt;
+using namespace cl;
+
+atomic&lt;int&gt; a; // OK: atomic in the global memory
+local&lt;atomic&lt;int&gt;&gt; b; // OK: atomic in the local memory
+global&lt;atomic&lt;int&gt;&gt; c; // OK: atomic in the global memory
+
+kernel void foo() {
+    static global&lt;atomic&lt;int&gt;&gt; d; // OK: atomic in the global memory
+    atomic&lt;global&lt;int&gt;&gt; e; // error: class members cannot be
+                           //        in address space
+    local&lt;atomic&lt;int&gt;&gt; f; // OK: atomic in the local memory
+    static atomic&lt;int&gt; g; // OK: atomic in the global memory
+    atomic&lt;int&gt; h; // undefined behavior
+}</code></pre>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="array-library">3.25. Array Library</h3>
+<div class="paragraph">
+<p>OpenCL C++ implements part of array library (<em>chapter 23.3.2</em>, <em>[array]</em>) from the C++14 standard.</p>
+</div>
+<div class="paragraph">
+<p>For the detailed description please refer to C++14 standard.</p>
+</div>
+<div class="sect3">
+<h4 id="header-opencl_array-synopsis">3.25.1. Header &lt;opencl_array&gt; Synopsis</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+template&lt;class T, size_t N&gt;
+struct array
+{
+    //types:
+    typedef T value_type;
+    typedef size_t size_type;
+    typedef ptrdiff_t difference_type;
+    typedef T&amp; reference;
+    typedef const T&amp; const_reference;
+    typedef implementation-defined iterator;
+    typedef implementation-defined const_iterator;
+    typedef T* pointer;
+    typedef const T* const_pointer;
+    typedef cl::reverse_iterator&lt;iterator&gt; reverse_iterator;
+    typedef cl::reverse_iterator&lt;const_iterator&gt; const_reverse_iterator;
+
+    value_type __elems[N]; // exposition only
+
+    // no explicit construct/copy/destroy for aggregate type
+
+    // iterators:
+    iterator begin() noexcept;
+    const_iterator begin() const noexcept;
+    iterator end() noexcept;
+    const_iterator end() const noexcept;
+
+    reverse_iterator rbegin() noexcept;
+    const_reverse_iterator rbegin() const noexcept;
+    reverse_iterator rend() noexcept;
+    const_reverse_iterator rend() const;
+
+    const_iterator cbegin() const noexcept;
+    const_iterator cend() const noexcept;
+    const_reverse_iterator crbegin() const noexcept;
+    const_reverse_iterator crend() const noexcept;
+
+    // capacity:
+    constexpr size_type size() const noexcept;
+    constexpr size_type max_size() const noexcept;
+    constexpr bool empty() const noexcept;
+
+    // element access:
+    reference operator[](size_type n) noexcept;
+    const_reference operator[](size_type n) const noexcept;
+    reference front() noexcept;
+    const_reference front() const noexcept;
+    reference back() noexcept;
+    const_reference back() const noexcept;
+
+    pointer data();
+    const_pointer data() const noexcept;
+};
+
+template &lt;class T&gt; class tuple_size;
+template &lt;size_t I, class T&gt; class tuple_element;
+
+template &lt;class T, size_t N&gt;
+struct tuple_size&lt;array&lt;T, N&gt;&gt;;
+
+template &lt;size_t I, class T, size_t N&gt;
+struct tuple_element&lt;I, array&lt;T, N&gt;&gt;;
+
+template &lt;size_t I, class T, size_t N&gt;
+constexpr T&amp; get(array&lt;T, N&gt;&amp; a) noexcept;
+template &lt;size_t I, class T, size_t N&gt;
+constexpr T&amp;&amp; get(array&lt;T, N&gt;&amp;&amp; a) noexcept;
+template &lt;size_t I, class T, size_t N&gt;
+constexpr const T&amp; get(const array&lt;T, N&gt;&amp; a) noexcept;
+
+}</code></pre>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="limits-library">3.26. Limits Library</h3>
+<div class="paragraph">
+<p>OpenCL C++ standard library implements modified version of the numeric limits library described in chapter <em>18.3 [support.limits]</em> of C++14 standard.</p>
+</div>
+<div class="sect3">
+<h4 id="header-opencl_limits-synopsis">3.26.1. Header &lt;opencl_limits&gt; Synopsis</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+
+template&lt;class T&gt; class numeric_limits;
+
+enum float_round_style;
+enum float_denorm_style;
+
+#define CHAR_BIT    8
+#define CHAR_MAX    SCHAR_MAX
+#define CHAR_MIN    SCHAR_MIN
+#define INT_MAX     2147483647
+#define INT_MIN     (-2147483647 - 1)
+#define LONG_MAX    0x7fffffffffffffffL
+#define LONG_MIN    (-0x7fffffffffffffffL - 1)
+#define SCHAR_MAX   127
+#define SCHAR_MIN   (-127 - 1)
+#define SHRT_MAX    32767
+#define SHRT_MIN    (-32767 - 1)
+#define UCHAR_MAX   255
+#define USHRT_MAX   65535
+#define UINT_MAX    0xffffffff
+#define ULONG_MAX   0xffffffffffffffffUL
+
+template&lt;&gt; class numeric_limits&lt;bool&gt;;
+template&lt;&gt; class numeric_limits&lt;bool2&gt;;
+template&lt;&gt; class numeric_limits&lt;bool3&gt;;
+template&lt;&gt; class numeric_limits&lt;bool4&gt;;
+template&lt;&gt; class numeric_limits&lt;bool8&gt;;
+template&lt;&gt; class numeric_limits&lt;bool16&gt;;
+template&lt;&gt; class numeric_limits&lt;char&gt;;
+template&lt;&gt; class numeric_limits&lt;char2&gt;;
+template&lt;&gt; class numeric_limits&lt;char3&gt;;
+template&lt;&gt; class numeric_limits&lt;char4&gt;;
+template&lt;&gt; class numeric_limits&lt;char8&gt;;
+template&lt;&gt; class numeric_limits&lt;char16&gt;;
+template&lt;&gt; class numeric_limits&lt;uchar&gt;;
+template&lt;&gt; class numeric_limits&lt;uchar2&gt;;
+template&lt;&gt; class numeric_limits&lt;uchar3&gt;;
+template&lt;&gt; class numeric_limits&lt;uchar4&gt;;
+template&lt;&gt; class numeric_limits&lt;uchar8&gt;;
+template&lt;&gt; class numeric_limits&lt;uchar16&gt;;
+template&lt;&gt; class numeric_limits&lt;short&gt;;
+template&lt;&gt; class numeric_limits&lt;short2&gt;;
+template&lt;&gt; class numeric_limits&lt;short3&gt;;
+template&lt;&gt; class numeric_limits&lt;short4&gt;;
+template&lt;&gt; class numeric_limits&lt;short8&gt;;
+template&lt;&gt; class numeric_limits&lt;short16&gt;;
+template&lt;&gt; class numeric_limits&lt;ushort&gt;;
+template&lt;&gt; class numeric_limits&lt;ushort2&gt;;
+template&lt;&gt; class numeric_limits&lt;ushort3&gt;;
+template&lt;&gt; class numeric_limits&lt;ushort4&gt;;
+template&lt;&gt; class numeric_limits&lt;ushort8&gt;;
+template&lt;&gt; class numeric_limits&lt;ushort16&gt;;
+template&lt;&gt; class numeric_limits&lt;int&gt;;
+template&lt;&gt; class numeric_limits&lt;int2&gt;;
+template&lt;&gt; class numeric_limits&lt;int3&gt;;
+template&lt;&gt; class numeric_limits&lt;int4&gt;;
+template&lt;&gt; class numeric_limits&lt;int8&gt;;
+template&lt;&gt; class numeric_limits&lt;int16&gt;;
+template&lt;&gt; class numeric_limits&lt;uint&gt;;
+template&lt;&gt; class numeric_limits&lt;uint2&gt;;
+template&lt;&gt; class numeric_limits&lt;uint3&gt;;
+template&lt;&gt; class numeric_limits&lt;uint4&gt;;
+template&lt;&gt; class numeric_limits&lt;uint8&gt;;
+template&lt;&gt; class numeric_limits&lt;uint16&gt;;
+template&lt;&gt; class numeric_limits&lt;long&gt;;
+template&lt;&gt; class numeric_limits&lt;long2&gt;;
+template&lt;&gt; class numeric_limits&lt;long3&gt;;
+template&lt;&gt; class numeric_limits&lt;long4&gt;;
+template&lt;&gt; class numeric_limits&lt;long8&gt;;
+template&lt;&gt; class numeric_limits&lt;long16&gt;;
+template&lt;&gt; class numeric_limits&lt;ulong&gt;;
+template&lt;&gt; class numeric_limits&lt;ulong2&gt;;
+template&lt;&gt; class numeric_limits&lt;ulong3&gt;;
+template&lt;&gt; class numeric_limits&lt;ulong4&gt;;
+template&lt;&gt; class numeric_limits&lt;ulong8&gt;;
+template&lt;&gt; class numeric_limits&lt;ulong16&gt;;
+
+#ifdef cl_khr_fp16
+#define HALF_DIG        3
+#define HALF_MANT_DIG   11
+#define HALF_MAX_10_EXP +4
+#define HALF_MAX_EXP    +16
+#define HALF_MIN_10_EXP -4
+#define HALF_MIN_EXP    -13
+#define HALF_RADIX      2
+#define HALF_MAX        0x1.ffcp15h
+#define HALF_MIN        0x1.0p-14h
+#define HALF_EPSILON    0x1.0p-10h
+
+template&lt;&gt; class numeric_limits&lt;half&gt;;
+#endif
+
+#define FLT_DIG         6
+#define FLT_MANT_DIG    24
+#define FLT_MAX_10_EXP  +38
+#define FLT_MAX_EXP     +128
+#define FLT_MIN_10_EXP  -37
+#define FLT_MIN_EXP     -125
+#define FLT_RADIX       2
+#define FLT_MAX         0x1.fffffep127f
+#define FLT_MIN         0x1.0p-126f
+#define FLT_EPSILON     0x1.0p-23f
+template&lt;&gt; class numeric_limits&lt;float&gt;;
+
+#ifdef cl_khr_fp64
+#define DBL_DIG         15
+#define DBL_MANT_DIG    53
+#define DBL_MAX_10_EXP  +308
+#define DBL_MAX_EXP     +1024
+#define DBL_MIN_10_EXP  -307
+#define DBL_MIN_EXP     -1021
+#define DBL_MAX         0x1.fffffffffffffp1023
+#define DBL_MIN         0x1.0p-1022
+#define DBL_EPSILON     0x1.0p-52
+
+template&lt;&gt; class numeric_limits&lt;double&gt;;
+#endif
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="class-numeric_limits">3.26.2. Class numeric_limits</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+template&lt;class T&gt;
+class numeric_limits
+{
+public:
+  static constexpr bool is_specialized = false;
+  static constexpr T min() noexcept { return T(); }
+  static constexpr T max() noexcept { return T(); }
+  static constexpr T lowest() noexcept { return T(); }
+  static constexpr int digits = 0;
+  static constexpr int digits10 = 0;
+  static constexpr int max_digits10 = 0;
+  static constexpr bool is_signed = false;
+  static constexpr bool is_integer = false;
+  static constexpr bool is_exact = false;
+  static constexpr int radix = 0;
+  static constexpr T epsilon() noexcept { return T(); }
+  static constexpr T round_error() noexcept { return T(); }
+  static constexpr int min_exponent = 0;
+  static constexpr int min_exponent10 = 0;
+  static constexpr int max_exponent = 0;
+  static constexpr int max_exponent10 = 0;
+  static constexpr bool has_infinity = false;
+  static constexpr bool has_quiet_NaN = false;
+  static constexpr bool has_signaling_NaN = false;
+  static constexpr float_denorm_style has_denorm = denorm_absent;
+  static constexpr bool has_denorm_loss = false;
+  static constexpr T infinity() noexcept { return T(); }
+  static constexpr T quiet_NaN() noexcept { return T(); }
+  static constexpr T signaling_NaN() noexcept { return T(); }
+  static constexpr T denorm_min() noexcept { return T(); }
+  static constexpr bool is_iec559 = false;
+  static constexpr bool is_bounded = false;
+  static constexpr bool is_modulo = false;
+  static constexpr bool traps = false;
+  static constexpr bool tinyness_before = false;
+  static constexpr float_round_style round_style = round_toward_zero;
+  static constexpr bool is_scalar = false;
+  static constexpr bool is_vector = false;
+};
+
+template&lt;class T&gt; class numeric_limits&lt;const T&gt;;
+template&lt;class T&gt; class numeric_limits&lt;volatile T&gt;;
+template&lt;class T&gt; class numeric_limits&lt;const volatile T&gt;;
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="has_denorm-numeric_limits-class-member">3.26.3. has_denorm numeric_limits class member</h4>
+<div class="paragraph">
+<p><code>has_denorm</code> class member value depends on a macro:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>HAS_SINGLE_FP_DENORM</code> for type <code>float</code>.</p>
+</li>
+<li>
+<p><code>HAS_HALF_FP_DENORM</code> for type <code>half</code>.</p>
+</li>
+<li>
+<p><code>HAS_DOUBLE_FP_DENORM</code> for type <code>double</code>.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If a macro is defined, <code>has_denorm</code> is set to <code>denorm_present</code>.
+Otherwise it is <code>denorm_absent</code>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="floating-point-macros-and-limits">3.26.4. Floating-point macros and limits</h4>
+<div class="paragraph">
+<p>The macro names given in the following list must use the values specified.
+These constant expressions are suitable for use in <code>#if</code> preprocessing directives.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#define FLT_DIG         6
+#define FLT_MANT_DIG    24
+#define FLT_MAX_10_EXP  +38
+#define FLT_MAX_EXP     +128
+#define FLT_MIN_10_EXP  -37
+#define FLT_MIN_EXP     -125
+#define FLT_RADIX       2
+#define FLT_MAX         0x1.fffffep127f
+#define FLT_MIN         0x1.0p-126f
+#define FLT_EPSILON     0x1.0p-23f</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The following table describes the built-in macro names given above in the OpenCL C++ library and the corresponding macro names available to the application.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 22. Float Built-in Macros</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Macro in OpenCL C++</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Macro for application</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>FLT_DIG</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_FLT_DIG</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>FLT_MANT_DIG</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_FLT_MANT_DIG</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>FLT_MAX_10_EXP</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_FLT_MAX_10_EXP</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>FLT_MAX_EXP</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_FLT_MAX_EXP</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>FLT_MIN_10_EXP</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_FLT_MIN_10_EXP</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>FLT_MIN_EXP</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_FLT_MIN_EXP</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>FLT_RADIX</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_FLT_RADIX</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>FLT_MAX</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_FLT_MAX</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>FLT_MIN</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_FLT_MIN</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>FLT_EPSILSON</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_FLT_EPSILON</code></p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>The following macros shall expand to integer constant expressions whose values are returned by <code>ilogb(x)</code> if <code>x</code> is zero or NaN, respectively.
+The value of <code>FP_ILOGB0</code> shall be either <code>INT_MIN</code> or <code>INT_MAX</code>. The value of <code>FP_ILOGBNAN</code> shall be either <code>INT_MAX</code> or <code>INT_MIN</code>.</p>
+</div>
+<div class="paragraph">
+<p>If double precision is supported by the device, the following macros and constants are available:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#define DBL_DIG         15
+#define DBL_MANT_DIG    53
+#define DBL_MAX_10_EXP  +308
+#define DBL_MAX_EXP     +1024
+#define DBL_MIN_10_EXP  -307
+#define DBL_MIN_EXP     -1021
+#define DBL_MAX         0x1.fffffffffffffp1023
+#define DBL_MIN         0x1.0p-1022
+#define DBL_EPSILON     0x1.0p-52</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The macro names given in the following list must use the values specified.
+These constant expressions are suitable for use in <code>#if</code> preprocessing directives.</p>
+</div>
+<div class="paragraph">
+<p>The following table describes the built-in macro names given above in the OpenCL C++ library and the corresponding macro names available to the application.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 23. Double Built-in Macros</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Macro in OpenCL cpp</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Macro for application</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>DBL_DIG</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_DBL_DIG</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>DBL_MANT_DIG</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_DBL_MANT_DIG</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>DBL_MAX_10_EXP</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_DBL_MAX_10_EXP</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>DBL_MAX_EXP</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_DBL_MAX_EXP</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>DBL_MIN_10_EXP</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_DBL_MIN_10_EXP</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>DBL_MIN_EXP</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_DBL_MIN_EXP</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>DBL_MAX</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_DBL_MAX</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>DBL_MIN</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_DBL_MIN</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>DBL_EPSILSON</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_DBL_EPSILON</code></p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>If half precision arithmetic operations are supported, the following macros and constants for half precision floating-point are available:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#define HALF_DIG        3
+#define HALF_MANT_DIG   11
+#define HALF_MAX_10_EXP +4
+#define HALF_MAX_EXP    +16
+#define HALF_MIN_10_EXP -4
+#define HALF_MIN_EXP    -13
+#define HALF_RADIX      2
+#define HALF_MAX        0x1.ffcp15h
+#define HALF_MIN        0x1.0p-14h
+#define HALF_EPSILON    0x1.0p-10h</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The macro names given in the following list must use the values specified.
+These constant expressions are suitable for use in <code>#if</code> preprocessing directives.</p>
+</div>
+<div class="paragraph">
+<p>The following table describes the built-in macro names given above in the OpenCL C++ library and the corresponding macro names available to the application.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 24. Half Built-in Macros</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Macro in OpenCL cpp</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Macro for application</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>HALF_DIG</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_HALF_DIG</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>HALF_MANT_DIG</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_HALF_MANT_DIG</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>HALF_MAX_10_EXP</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_HALF_MAX_10_EXP</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>HALF_MAX_EXP</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_HALF_MAX_EXP</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>HALF_MIN_10_EXP</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_HALF_MIN_10_EXP</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>HALF_MIN_EXP</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_HALF_MIN_EXP</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>HALF_RADIX</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_HALF_RADIX</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>HALF_MAX</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_HALF_MAX</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>HALF_MIN</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_HALF_MIN</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>HALF_EPSILSON</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_HALF_EPSILON</code></p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>The following symbolic constants are available.
+Their values are of type float and are accurate within the precision of a single precision floating-point number.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 25. Float Symbolic Constants</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Constant Name</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>MAXFLOAT</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of maximum non-infinite single-precision floating-point number.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>HUGE_VALF</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A positive float constant expression. <code>HUGE_VALF</code> evaluates to +infinity.
+  Used as an error value returned by the built-in math functions.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>INFINITY</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A constant expression of type float representing positive or unsigned infinity.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>NAN</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A constant expression of type float representing a quiet NaN.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>If double precision is supported by the device, the following symbolic constant will also be available:</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 26. Double Symbolic Constants</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Constant Name</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>HUGE_VAL</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A positive double constant expression.
+  <code>HUGE_VAL</code> evaluates to +infinity.
+  Used as an error value returned by the built-in math functions.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="integer-macros-and-limits">3.26.5. Integer macros and limits</h4>
+<div class="paragraph">
+<p>The macro names given in the following list must use the values specified.
+The values shall all be constant expressions suitable for use in <code>#if</code> preprocessing directives.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#define CHAR_BIT    8
+#define CHAR_MAX    SCHAR_MAX
+#define CHAR_MIN    SCHAR_MIN
+#define INT_MAX     2147483647
+#define INT_MIN     (-2147483647 - 1)
+#define LONG_MAX    0x7fffffffffffffffL
+#define LONG_MIN    (-0x7fffffffffffffffL - 1)
+#define SCHAR_MAX   127
+#define SCHAR_MIN   (-127 - 1)
+#define SHRT_MAX    32767
+#define SHRT_MIN    (-32767 - 1)
+#define UCHAR_MAX   255
+#define USHRT_MAX   65535
+#define UINT_MAX    0xffffffff
+#define ULONG_MAX   0xffffffffffffffffUL</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The following table describes the built-in macro names given above in the OpenCL C++ library and the corresponding macro names available to the application.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 27. Integer built-in macros</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Macro in OpenCL cpp</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Macro for application</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CHAR_BIT</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_CHAR_BIT</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CHAR_MAX</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_CHAR_MAX</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CHAR_MIN</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_CHAR_MIN</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>INT_MAX</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_INT_MAX</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>INT_MIN</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_INT_MIN</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>LONG_MAX</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_LONG_MAX</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>LONG_MIN</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_LONG_MIN</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>SCHAR_MAX</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_SCHAR_MAX</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>SCHAR_MIN</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_SCHAR_MIN</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>SHRT_MAX</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_SHRT_MAX</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>SHRT_MIN</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_SHRT_MIN</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>UCHAR_MAX</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_UCHAR_MAX</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>USHRT_MAX</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_USHRT_MAX</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>UINT_MAX</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_UINT_MAX</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>ULONG_MAX</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_ULONG_MAX</code></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+<div class="sect2">
+<h3 id="math-constants-library">3.27. Math Constants Library</h3>
+<div class="paragraph">
+<p>OpenCL C++ implements math constant library.
+The purpose of this library is to provide the commonly used constants for half, float and double data types.</p>
+</div>
+<div class="sect3">
+<h4 id="header-opencl_math_constants-synopsis">3.27.1. Header &lt;opencl_math_constants&gt; Synopsis</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+template&lt;class T&gt; class math_constants;
+
+#ifdef cl_khr_fp16
+#define M_E_H           see below
+#define M_LOG2E_H       see below
+#define M_LOG10E_H      see below
+#define M_LN2_H         see below
+#define M_LN10_H        see below
+#define M_PI_H          see below
+#define M_PI_2_H        see below
+#define M_PI_4_H        see below
+#define M_1_PI_H        see below
+#define M_2_PI_H        see below
+#define M_2_SQRTPI_H    see below
+#define M_SQRT2_H       see below
+#define M_SQRT1_2_H     see below
+
+template&lt;&gt; class math_constants&lt;half&gt;;
+template&lt;&gt; class math_constants&lt;half2&gt;;
+template&lt;&gt; class math_constants&lt;half3&gt;;
+template&lt;&gt; class math_constants&lt;half4&gt;;
+template&lt;&gt; class math_constants&lt;half8&gt;;
+template&lt;&gt; class math_constants&lt;half16&gt;;
+#endif
+
+#define M_E_F           see below
+#define M_LOG2E_F       see below
+#define M_LOG10E_F      see below
+#define M_LN2_F         see below
+#define M_LN10_F        see below
+#define M_PI_F          see below
+#define M_PI_2_F        see below
+#define M_PI_4_F        see below
+#define M_1_PI_F        see below
+#define M_2_PI_F        see below
+#define M_2_SQRTPI_F    see below
+#define M_SQRT2_F       see below
+#define M_SQRT1_2_F     see below
+
+template&lt;&gt; class math_constants&lt;float&gt;;
+template&lt;&gt; class math_constants&lt;float2&gt;;
+template&lt;&gt; class math_constants&lt;float3&gt;;
+template&lt;&gt; class math_constants&lt;float4&gt;;
+template&lt;&gt; class math_constants&lt;float8&gt;;
+template&lt;&gt; class math_constants&lt;float16&gt;;
+
+#ifdef cl_khr_fp64
+#define M_E         see below
+#define M_LOG2E     see below
+#define M_LOG10E    see below
+#define M_LN2       see below
+#define M_LN10      see below
+#define M_PI        see below
+#define M_PI_2      see below
+#define M_PI_4      see below
+#define M_1_PI      see below
+#define M_2_PI      see below
+#define M_2_SQRTPI  see below
+#define M_SQRT2     see below
+#define M_SQRT1_2   see below
+
+template&lt;&gt; class math_constants&lt;double&gt;;
+template&lt;&gt; class math_constants&lt;double2&gt;;
+template&lt;&gt; class math_constants&lt;double3&gt;;
+template&lt;&gt; class math_constants&lt;double4&gt;;
+template&lt;&gt; class math_constants&lt;double8&gt;;
+template&lt;&gt; class math_constants&lt;double16&gt;;
+#endif
+
+template&lt;class T&gt;
+constexpr T e_v = math_constants&lt;T&gt;::e();
+template&lt;class T&gt;
+constexpr T log2e_v = math_constants&lt;T&gt;::log2e();
+template&lt;class T&gt;
+constexpr T log10e_v = math_constants&lt;T&gt;::log10e();
+template&lt;class T&gt;
+constexpr T ln2_v = math_constants&lt;T&gt;::ln2();
+template&lt;class T&gt;
+constexpr T ln10_v = math_constants&lt;T&gt;::ln10();
+template&lt;class T&gt;
+constexpr T pi_v = math_constants&lt;T&gt;::pi();
+template&lt;class T&gt;
+constexpr T pi_2_v = math_constants&lt;T&gt;::pi_2();
+template&lt;class T&gt;
+constexpr T pi_4_v = math_constants&lt;T&gt;::pi_4();
+template&lt;class T&gt;
+constexpr T one_pi_v = math_constants&lt;T&gt;::one_pi();
+template&lt;class T&gt;
+constexpr T two_pi_v = math_constants&lt;T&gt;::two_pi();
+template&lt;class T&gt;
+constexpr T two_sqrtpi_v = math_constants&lt;T&gt;::two_sqrtpi();
+template&lt;class T&gt;
+constexpr T sqrt2_v = math_constants&lt;T&gt;::sqrt2();
+template&lt;class T&gt;
+constexpr T sqrt1_2_v = math_constants&lt;T&gt;::sqrt1_2();
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="class-math_constants">3.27.2. Class math_constants</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+template&lt;class T&gt;
+class math_constants
+{
+public:
+  static constexpr T e() noexcept { return T(); }
+  static constexpr T log2e() noexcept { return T(); }
+  static constexpr T log10e() noexcept { return T(); }
+  static constexpr T ln2() noexcept { return T(); }
+  static constexpr T ln10() noexcept { return T(); }
+  static constexpr T pi() noexcept { return T(); }
+  static constexpr T pi_2() noexcept { return T(); }
+  static constexpr T pi_4() noexcept { return T(); }
+  static constexpr T one_pi() noexcept { return T(); }
+  static constexpr T two_pi() noexcept { return T(); }
+  static constexpr T two_sqrtpi() noexcept { return T(); }
+  static constexpr T sqrt2() noexcept { return T(); }
+  static constexpr T sqrt1_2() noexcept { return T(); }
+};
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="half-constants">3.27.3. Half Constants</h4>
+<div class="paragraph">
+<p>The following constants are also available.
+They are of type <code>half</code> and are accurate within the precision of the <code>half</code> type.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 28. Half Constants</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Constant</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>e</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of e</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>log2e</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of log<sub>2</sub>e</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>log10e</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of log<sub>10</sub>e</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>ln2</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of log<sub>e</sub>2</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>ln10</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of log<sub>e</sub>10</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>pi</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of π</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>pi_2</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of π / 2</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>pi_4</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of π / 4</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>one_pi</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of 1 / π</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>two_pi</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of 2 / π</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>two_sqrtpi</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of 2 / √π</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>sqrt2</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of √2</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>sqrt1_2</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of 1 / √2</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="float-constants">3.27.4. Float Constants</h4>
+<div class="paragraph">
+<p>The following constants are also available.
+They are of type <code>float</code> and are accurate within the precision of the <code>float</code> type.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 29. Float Constants</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Constant</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>e</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of e</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>log2e</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of log<sub>2</sub>e</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>log10e</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of log<sub>10</sub>e</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>ln2</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of log<sub>e</sub>2</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>ln10</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of log<sub>e</sub>10</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>pi</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of π</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>pi_2</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of π / 2</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>pi_4</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of π / 4</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>one_pi</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of 1 / π</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>two_pi</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of 2 / π</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>two_sqrtpi</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of 2 / √π</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>sqrt2</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of √2</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>sqrt1_2</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of 1 / √2</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="double-constants">3.27.5. Double Constants</h4>
+<div class="paragraph">
+<p>The following constants are also available.
+They are of type <code>double</code> and are accurate within the precision of the <code>double</code> type.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 30. Double Constants</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Constant</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>e</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of e</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>log2e</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of log<sub>2</sub>e</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>log10e</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of log<sub>10</sub>e</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>ln2</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of log<sub>e</sub>2</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>ln10</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of log<sub>e</sub>10</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>pi</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of π</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>pi_2</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of π / 2</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>pi_4</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of π / 4</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>one_pi</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of 1 / π</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>two_pi</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of 2 / π</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>two_sqrtpi</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of 2 / √π</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>sqrt2</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of √2</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>sqrt1_2</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of 1 / √2</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+<div class="sect2">
+<h3 id="tuple-library">3.28. Tuple Library</h3>
+<div class="paragraph">
+<p>OpenCL C++ standard library implements most of the tuples described in <em>chapter 20.4 [tuple]</em> of C++14 standard.</p>
+</div>
+<div class="paragraph">
+<p>The following parts of tuple library are not supported:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>allocator related traits (C++14 standard, <em>section 20.4.2.8</em>)</p>
+</li>
+</ul>
+</div>
+<div class="sect3">
+<h4 id="header-opencl_tuple-synopsis">3.28.1. Header &lt;opencl_tuple&gt; Synopsis</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+// class template tuple:
+template &lt;class... Types&gt; class tuple;
+
+// tuple creation functions:
+const unspecified ignore;
+template &lt;class... Types&gt;
+constexpr tuple&lt;VTypes ...&gt; make_tuple(Types&amp;&amp;...);
+template &lt;class... Types&gt;
+constexpr tuple&lt;Types&amp;&amp;...&gt; forward_as_tuple(Types&amp;&amp;...) noexcept;
+template&lt;class... Types&gt;
+constexpr tuple&lt;Types&amp;...&gt; tie(Types&amp;...) noexcept;
+template &lt;class... Tuples&gt;
+constexpr tuple&lt;Ctypes ...&gt; tuple_cat(Tuples&amp;&amp;...);
+
+//  tuple helper classes:
+template &lt;class T&gt; class tuple_size; // undefined
+template &lt;class T&gt; class tuple_size&lt;const T&gt;;
+template &lt;class T&gt; class tuple_size&lt;volatile T&gt;;
+template &lt;class T&gt; class tuple_size&lt;const volatile T&gt;;
+template &lt;class... Types&gt; class tuple_size&lt;tuple&lt;Types...&gt; &gt;;
+template &lt;size_t I, class T&gt; class tuple_element; // undefined
+template &lt;size_t I, class T&gt; class tuple_element&lt;I, const T&gt;;
+template &lt;size_t I, class T&gt; class tuple_element&lt;I, volatile T&gt;;
+template &lt;size_t I, class T&gt; class tuple_element&lt;I, const volatile T&gt;;
+template &lt;size_t I, class... Types&gt; class tuple_element&lt;I, tuple&lt;Types...&gt; &gt;;
+template &lt;size_t I, class T&gt;
+using tuple_element_t = typename tuple_element&lt;I, T&gt;::type;
+
+// element access:
+template &lt;size_t I, class... Types&gt;
+constexpr tuple_element_t&lt;I, tuple&lt;Types...&gt;&gt;&amp;
+get(tuple&lt;Types...&gt;&amp;) noexcept;
+template &lt;size_t I, class... Types&gt;
+constexpr tuple_element_t&lt;I, tuple&lt;Types...&gt;&gt;&amp;&amp;
+get(tuple&lt;Types...&gt;&amp;&amp;) noexcept;
+template &lt;size_t I, class... Types&gt;
+constexpr const tuple_element_t&lt;I, tuple&lt;Types...&gt;&gt;&amp;
+get(const tuple&lt;Types...&gt;&amp;) noexcept;
+template &lt;class T, class... Types&gt;
+constexpr T&amp; get(tuple&lt;Types...&gt;&amp; t) noexcept;
+template &lt;class T, class... Types&gt;
+constexpr T&amp;&amp; get(tuple&lt;Types...&gt;&amp;&amp; t) noexcept;
+template &lt;class T, class... Types&gt;
+constexpr const T&amp; get(const tuple&lt;Types...&gt;&amp; t) noexcept;
+
+// relational operators:
+template&lt;class... TTypes, class... UTypes&gt;
+constexpr bool operator==(const tuple&lt;TTypes...&gt;&amp;, const tuple&lt;UTypes...&gt;&amp;);
+template&lt;class... TTypes, class... UTypes&gt;
+constexpr bool operator&lt;(const tuple&lt;TTypes...&gt;&amp;, const tuple&lt;UTypes...&gt;&amp;);
+template&lt;class... TTypes, class... UTypes&gt;
+constexpr bool operator!=(const tuple&lt;TTypes...&gt;&amp;, const tuple&lt;UTypes...&gt;&amp;);
+template&lt;class... TTypes, class... UTypes&gt;
+constexpr bool operator&gt;(const tuple&lt;TTypes...&gt;&amp;, const tuple&lt;UTypes...&gt;&amp;);
+template&lt;class... TTypes, class... UTypes&gt;
+constexpr bool operator&lt;=(const tuple&lt;TTypes...&gt;&amp;, const tuple&lt;UTypes...&gt;&amp;);
+template&lt;class... TTypes, class... UTypes&gt;
+constexpr bool operator&gt;=(const tuple&lt;TTypes...&gt;&amp;, const tuple&lt;UTypes...&gt;&amp;);
+
+// specialized algorithms:
+template &lt;class... Types&gt;
+void swap(tuple&lt;Types...&gt;&amp; x, tuple&lt;Types...&gt;&amp; y) noexcept(see cpp14 standard);
+
+}</code></pre>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="type-traits-library">3.29. Type Traits Library</h3>
+<div class="paragraph">
+<p>OpenCL C++ supports type traits defined in C++14 specification with following changes:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>the <a href="#unary-type-traits"><em>Unary Type Traits</em></a> section describes additions and changes to <em>UnaryTypeTraits</em>.</p>
+</li>
+<li>
+<p>the <a href="#binary-type-traits"><em>Binary type traits</em></a> section describes additions and changes to <em>BinaryTypeTraits</em>.</p>
+</li>
+<li>
+<p>the <a href="#transformation-traits"><em>Transformation traits</em></a> section describes additions and changes to <em>TransformationTraits</em>.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>This section specifies only OpenCL specific type traits and modifications.
+All C++ type traits are described in <em>chapter 20.10 [meta]</em> of C++14 standard.</p>
+</div>
+<div class="sect3">
+<h4 id="header-opencl_type_traits-synopsis">3.29.1. Header &lt;opencl_type_traits&gt; Synopsis</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+// helper class:
+template &lt;class T, T v&gt; struct integral_constant;
+typedef integral_constant&lt;bool, true&gt; true_type;
+typedef integral_constant&lt;bool, false&gt; false_type;
+
+// primary type categories:
+template &lt;class T&gt; struct is_void;
+template &lt;class T&gt; struct is_null_pointer;
+template &lt;class T&gt; struct is_integral;
+template &lt;class T&gt; struct is_floating_point;
+template &lt;class T&gt; struct is_array;
+template &lt;class T&gt; struct is_pointer;
+template &lt;class T&gt; struct is_lvalue_reference;
+template &lt;class T&gt; struct is_rvalue_reference;
+template &lt;class T&gt; struct is_member_object_pointer;
+template &lt;class T&gt; struct is_member_function_pointer;
+template &lt;class T&gt; struct is_enum;
+template &lt;class T&gt; struct is_union;
+template &lt;class T&gt; struct is_class;
+template &lt;class T&gt; struct is_function;
+
+// composite type categories:
+template &lt;class T&gt; struct is_reference;
+template &lt;class T&gt; struct is_arithmetic;
+template &lt;class T&gt; struct is_fundamental;
+template &lt;class T&gt; struct is_object;
+template &lt;class T&gt; struct is_scalar;
+template &lt;class T&gt; struct is_compound;
+template &lt;class T&gt; struct is_member_pointer;
+
+// type properties:
+template &lt;class T&gt; struct is_const;
+template &lt;class T&gt; struct is_volatile;
+template &lt;class T&gt; struct is_private;
+template &lt;class T&gt; struct is_local;
+template &lt;class T&gt; struct is_global;
+template &lt;class T&gt; struct is_constant;
+template &lt;class T&gt; struct is_generic;
+template &lt;class T&gt; struct is_vector;
+template &lt;class T&gt; struct is_trivial;
+template &lt;class T&gt; struct is_trivially_copyable;
+template &lt;class T&gt; struct is_standard_layout;
+template &lt;class T&gt; struct is_pod;
+template &lt;class T&gt; struct is_literal_type;
+template &lt;class T&gt; struct is_empty;
+template &lt;class T&gt; struct is_polymorphic;
+template &lt;class T&gt; struct is_abstract;
+template &lt;class T&gt; struct is_final;
+template &lt;class T&gt; struct is_signed;
+template &lt;class T&gt; struct is_unsigned;
+template &lt;class T, class... Args&gt; struct is_constructible;
+template &lt;class T&gt; struct is_default_constructible;
+template &lt;class T&gt; struct is_copy_constructible;
+template &lt;class T&gt; struct is_move_constructible;
+template &lt;class T, class U&gt; struct is_assignable;
+template &lt;class T&gt; struct is_copy_assignable;
+template &lt;class T&gt; struct is_move_assignable;
+template &lt;class T&gt; struct is_destructible;
+template &lt;class T, class... Args&gt; struct is_trivially_constructible;
+template &lt;class T&gt; struct is_trivially_default_constructible;
+template &lt;class T&gt; struct is_trivially_copy_constructible;
+template &lt;class T&gt; struct is_trivially_move_constructible;
+template &lt;class T, class U&gt; struct is_trivially_assignable;
+template &lt;class T&gt; struct is_trivially_copy_assignable;
+template &lt;class T&gt; struct is_trivially_move_assignable;
+template &lt;class T&gt; struct is_trivially_destructible;
+template &lt;class T, class... Args&gt; struct is_nothrow_constructible;
+template &lt;class T&gt; struct is_nothrow_default_constructible;
+template &lt;class T&gt; struct is_nothrow_copy_constructible;
+template &lt;class T&gt; struct is_nothrow_move_constructible;
+template &lt;class T, class U&gt; struct is_nothrow_assignable;
+template &lt;class T&gt; struct is_nothrow_copy_assignable;
+template &lt;class T&gt; struct is_nothrow_move_assignable;
+template &lt;class T&gt; struct is_nothrow_destructible;
+template &lt;class T&gt; struct has_virtual_destructor;
+
+// type property queries:
+template &lt;class T&gt; struct alignment_of;
+template &lt;class T&gt; struct rank;
+template &lt;class T, unsigned I = 0&gt; struct extent;
+// type relations:
+template &lt;class T, class U&gt; struct is_same;
+template &lt;class Base, class Derived&gt; struct is_base_of;
+template &lt;class From, class To&gt; struct is_convertible;
+
+// const-volatile modifications:
+template &lt;class T&gt; struct remove_const;
+template &lt;class T&gt; struct remove_volatile;
+template &lt;class T&gt; struct remove_cv;
+template &lt;class T&gt; struct add_const;
+template &lt;class T&gt; struct add_volatile;
+template &lt;class T&gt; struct add_cv;
+template &lt;class T&gt;
+using remove_const_t = typename remove_const&lt;T&gt;::type;
+template &lt;class T&gt;
+using remove_volatile_t = typename remove_volatile&lt;T&gt;::type;
+template &lt;class T&gt;
+using remove_cv_t = typename remove_cv&lt;T&gt;::type;
+template &lt;class T&gt;
+using add_const_t = typename add_const&lt;T&gt;::type;
+template &lt;class T&gt;
+using add_volatile_t = typename add_volatile&lt;T&gt;::type;
+template &lt;class T&gt;
+using add_cv_t = typename add_cv&lt;T&gt;::type;
+
+// as modifications
+template &lt;class T&gt; struct remove_constant;
+template &lt;class T&gt; struct remove_local;
+template &lt;class T&gt; struct remove_global;
+template &lt;class T&gt; struct remove_private;
+template &lt;class T&gt; struct remove_generic;
+template &lt;class T&gt; struct remove_as;
+template &lt;class T&gt; struct remove_attrs;
+template &lt;class T&gt; struct add_constant;
+template &lt;class T&gt; struct add_local;
+template &lt;class T&gt; struct add_global;
+template &lt;class T&gt; struct add_private;
+template &lt;class T&gt; struct add_generic;
+template &lt;class T&gt;
+using remove_constant_t = typename remove_constant&lt;T&gt;::type;
+template &lt;class T&gt;
+using remove_local_t = typename remove_local&lt;T&gt;::type;
+template &lt;class T&gt;
+using remove_global_t = typename remove_global&lt;T&gt;::type;
+template &lt;class T&gt;
+using remove_private_t = typename remove_private&lt;T&gt;::type;
+template &lt;class T&gt;
+using remove_generic_t = typename remove_generic&lt;T&gt;::type;
+template &lt;class T&gt;
+using remove_as_t = typename remove_as&lt;T&gt;::type;
+template &lt;class T&gt;
+using remove_attrs_t = typename remove_attrs&lt;T&gt;::type;
+template &lt;class T&gt;
+using add_constant_t = typename add_constant&lt;T&gt;::type;
+template &lt;class T&gt;
+using add_local_t = typename add_local&lt;T&gt;::type;
+template &lt;class T&gt;
+using add_global_t = typename add_global&lt;T&gt;::type;
+template &lt;class T&gt;
+using add_private_t = typename add_private&lt;T&gt;::type;
+template &lt;class T&gt;
+using add_generic_t = typename add_generic&lt;T&gt;::type;
+
+// reference modifications:
+template &lt;class T&gt; struct remove_reference;
+template &lt;class T&gt; struct add_lvalue_reference;
+template &lt;class T&gt; struct add_rvalue_reference;
+template &lt;class T&gt;
+using remove_reference_t = typename remove_reference&lt;T&gt;::type;
+template &lt;class T&gt;
+using add_lvalue_reference_t = typename add_lvalue_reference&lt;T&gt;::type;
+template &lt;class T&gt;
+using add_rvalue_reference_t = typename add_rvalue_reference&lt;T&gt;::type;
+
+// sign modifications:
+template &lt;class T&gt; struct make_signed;
+template &lt;class T&gt; struct make_unsigned;
+template &lt;class T&gt;
+using make_signed_t = typename make_signed&lt;T&gt;::type;
+template &lt;class T&gt;
+using make_unsigned_t = typename make_unsigned&lt;T&gt;::type;
+
+// array modifications:
+template &lt;class T&gt; struct remove_extent;
+template &lt;class T&gt; struct remove_all_extents;
+template &lt;class T&gt;
+using remove_extent_t = typename remove_extent&lt;T&gt;::type;
+template &lt;class T&gt;
+using remove_all_extents_t = typename remove_all_extents&lt;T&gt;::type;
+
+// pointer modifications:
+template &lt;class T&gt; struct remove_pointer;
+template &lt;class T&gt; struct add_pointer;
+template &lt;class T&gt;
+using remove_pointer_t = typename remove_pointer&lt;T&gt;::type;
+template &lt;class T&gt;
+using add_pointer_t = typename add_pointer&lt;T&gt;::type;
+
+// built-in vector queries
+template &lt;class T&gt; struct is_vector_type;
+template &lt;class T&gt; struct vector_size;
+
+// built-in vector modifications
+template &lt;class T&gt; struct vector_element;
+template &lt;class T, uint DIM&gt; struct make_vector;
+template &lt;class T&gt;
+using vector_element_t = typename vector_element&lt;T&gt;::type;
+template &lt;class T, uint DIM&gt;
+using make_vector_t = typename make_vector&lt;T,DIM&gt;::type;
+
+// other transformations:
+template &lt;cl::size_t Len,
+cl::size_t Align = default-alignment&gt;
+struct aligned_storage;
+template &lt;cl::size_t Len, class... Types&gt; struct aligned_union;
+template &lt;class T&gt; struct decay;
+template &lt;bool, class T = void&gt; struct enable_if;
+template &lt;bool, class T, class F&gt; struct conditional;
+template &lt;class... T&gt; struct common_type;
+template &lt;class T&gt; struct underlying_type;
+template &lt;class&gt; class result_of; // not defined
+template &lt;class F, class... ArgTypes&gt; class result_of&lt;F(ArgTypes...)&gt;;
+template &lt;cl::size_t Len,
+cl::size_t Align = default-alignment &gt;
+using aligned_storage_t = typename aligned_storage&lt;Len,Align&gt;::type;
+template &lt;cl::size_t Len, class... Types&gt;
+using aligned_union_t = typename aligned_union&lt;Len,Types...&gt;::type;
+template &lt;class T&gt;
+using decay_t = typename decay&lt;T&gt;::type;
+template &lt;bool b, class T = void&gt;
+using enable_if_t = typename enable_if&lt;b,T&gt;::type;
+template &lt;bool b, class T, class F&gt;
+using conditional_t = typename conditional&lt;b,T,F&gt;::type;
+template &lt;class... T&gt;
+using common_type_t = typename common_type&lt;T...&gt;::type;
+template &lt;class T&gt;
+using underlying_type_t = typename underlying_type&lt;T&gt;::type;
+template &lt;class T&gt;
+using result_of_t = typename result_of&lt;T&gt;::type;
+template &lt;class...&gt;
+using void_t = void;
+
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="unary-type-traits">3.29.2. Unary Type Traits</h4>
+<div class="sect4">
+<h5 id="additional-type-property-predicates">Additional type property predicates</h5>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 31. Additional type property predicates</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Template</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Condition</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>template &lt;class T&gt; struct is_private;</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation defined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>template &lt;class T&gt; struct is_local;</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation defined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>template &lt;class T&gt; struct is_global;</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation defined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>template &lt;class T&gt; struct is_constant;</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation defined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>template &lt;class T&gt; struct is_generic;</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation defined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>template &lt;class T&gt; struct is_vector;</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>T</code> is built-in vector type.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect4">
+<h5 id="additional-type-property-queries">Additional type property queries</h5>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 32. Additional type property queries</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Template</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Value</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>template &lt;class T&gt; struct vector_size;</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">If <code>T</code> names a built-in vector type, an integer value representing number of <code>T</code>'s components; otherwise <code>1</code>.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+<div class="sect3">
+<h4 id="binary-type-traits">3.29.3. Binary type traits</h4>
+<div class="sect4">
+<h5 id="changed-relationships-traits">Changed relationships traits</h5>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 33. Changed relationship traits</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Template</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Condition</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>template &lt;class T, class U&gt; struct is_same;</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>T</code> and <code>U</code> name the same type with the same <em>cv qualifications</em>.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+<div class="sect3">
+<h4 id="transformation-traits">3.29.4. Transformation traits</h4>
+<div class="sect4">
+<h5 id="address-space-and-vector-modifications">Address space and vector modifications</h5>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 34. Address space and vector traits</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Template</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Comments</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>template &lt;class T&gt; Xstruct remove_private;</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation defined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>template &lt;class T&gt; Xstruct remove_local;</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation defined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>template &lt;class T&gt; Xstruct remove_global;</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation defined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>template &lt;class T&gt; Xstruct remove_constant;</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation defined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>template &lt;class T&gt; Xstruct remove_generic;</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation defined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>template &lt;class T&gt; Xstruct remove_as;</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation defined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>template &lt;class T&gt; Xstruct remove_attrs;</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation defined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>template &lt;class T&gt; Xstruct add_private;</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation defined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>template &lt;class T&gt; Xstruct add_local;</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation defined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>template &lt;class T&gt; Xstruct add_global;</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation defined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>template &lt;class T&gt; Xstruct add_constant;</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation defined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>template &lt;class T&gt; Xstruct add_generic;</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation defined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>template &lt;class T&gt; Xstruct vector_element;</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">If <code>T</code> is a built-in vector type, member typedef <code>T</code> shall name type of <code>T</code>'s component; otherwise it shall name <code>T</code>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>template &lt;class T, size_t Dim&gt; struct make_vector;</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">If type <code>U</code> exists and names a built-in vector type with <code>Dim</code> components of type <code>T</code>, member typedef type shall name <code>U</code>; otherwise it shall name <code>T</code>.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="iterator-library">3.30. Iterator Library</h3>
+<div class="paragraph">
+<p>OpenCL C++ implements part of iterator library (<em>chapter 24, [iterators]</em>) from the C++14 standard.
+Primitives (C++14 standard, <em>section 24.4</em>), iterator operations (C++14 standard, <em>section 24.4.4,</em>), predefined iterators (C++14 standard, <em>section 24.5</em>) and range access (C++14 standard, <em>section 24.7</em>) are supported.</p>
+</div>
+<div class="paragraph">
+<p>For the detailed description please refer to C++14 standard.</p>
+</div>
+<div class="sect3">
+<h4 id="header-opencl_iterator-synopsis">3.30.1. Header &lt;opencl_iterator&gt; Synopsis</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+// primitives:
+template&lt;class Iterator&gt; struct iterator_traits;
+template&lt;class T&gt; struct iterator_traits&lt;T*&gt;;
+template&lt;class Category, class T, class Distance = ptrdiff_t,
+class Pointer = T*, class Reference = T&amp;&gt; struct iterator;
+
+struct input_iterator_tag { };
+struct output_iterator_tag { };
+struct forward_iterator_tag: public input_iterator_tag { };
+struct bidirectional_iterator_tag: public forward_iterator_tag { };
+struct random_access_iterator_tag: public bidirectional_iterator_tag { };
+
+// iterator operations:
+template &lt;class InputIterator, class Distance&gt;
+void advance(InputIterator&amp; i, Distance n);
+template &lt;class InputIterator&gt;
+typename iterator_traits&lt;InputIterator&gt;::difference_type
+distance(InputIterator first, InputIterator last);
+template &lt;class ForwardIterator&gt;
+ForwardIterator next(ForwardIterator x,
+typename std::iterator_traits&lt;ForwardIterator&gt;::difference_type n = 1);
+template &lt;class BidirectionalIterator&gt;
+BidirectionalIterator prev(BidirectionalIterator x,
+typename std::iterator_traits&lt;BidirectionalIterator&gt;::difference_type n = 1);
+
+// predefined iterators:
+template &lt;class Iterator&gt; class reverse_iterator;
+template &lt;class Iterator1, class Iterator2&gt;
+bool operator==(
+const reverse_iterator&lt;Iterator1&gt;&amp; x,
+const reverse_iterator&lt;Iterator2&gt;&amp; y);
+template &lt;class Iterator1, class Iterator2&gt;
+bool operator&lt;(
+const reverse_iterator&lt;Iterator1&gt;&amp; x,
+const reverse_iterator&lt;Iterator2&gt;&amp; y);
+template &lt;class Iterator1, class Iterator2&gt;
+bool operator!=(
+const reverse_iterator&lt;Iterator1&gt;&amp; x,
+const reverse_iterator&lt;Iterator2&gt;&amp; y);
+template &lt;class Iterator1, class Iterator2&gt;
+bool operator&gt;(
+const reverse_iterator&lt;Iterator1&gt;&amp; x,
+const reverse_iterator&lt;Iterator2&gt;&amp; y);
+template &lt;class Iterator1, class Iterator2&gt;
+bool operator&gt;=(
+const reverse_iterator&lt;Iterator1&gt;&amp; x,
+const reverse_iterator&lt;Iterator2&gt;&amp; y);
+template &lt;class Iterator1, class Iterator2&gt;
+bool operator&lt;=(
+const reverse_iterator&lt;Iterator1&gt;&amp; x,
+const reverse_iterator&lt;Iterator2&gt;&amp; y);
+template &lt;class Iterator1, class Iterator2&gt;
+auto operator-(
+const reverse_iterator&lt;Iterator1&gt;&amp; x,
+const reverse_iterator&lt;Iterator2&gt;&amp; y) -&gt;decltype(y.base() - x.base());
+template &lt;class Iterator&gt;
+reverse_iterator&lt;Iterator&gt;
+operator+(typename reverse_iterator&lt;Iterator&gt;::difference_type n,
+          const reverse_iterator&lt;Iterator&gt;&amp; x);
+template &lt;class Iterator&gt;
+reverse_iterator&lt;Iterator&gt; make_reverse_iterator(Iterator i);
+template &lt;class Container&gt; class back_insert_iterator;
+template &lt;class Container&gt;
+back_insert_iterator&lt;Container&gt; back_inserter(Container&amp; x);
+template &lt;class Container&gt; class front_insert_iterator;
+template &lt;class Container&gt;
+front_insert_iterator&lt;Container&gt; front_inserter(Container&amp; x);
+template &lt;class Container&gt; class insert_iterator;
+template &lt;class Container&gt;
+insert_iterator&lt;Container&gt; inserter(Container&amp; x,
+                                    typename Container::iterator i);
+template &lt;class Iterator&gt; class move_iterator;
+template &lt;class Iterator1, class Iterator2&gt;
+bool operator==(
+const move_iterator&lt;Iterator1&gt;&amp; x, const move_iterator&lt;Iterator2&gt;&amp; y);
+template &lt;class Iterator1, class Iterator2&gt;
+bool operator!=(
+const move_iterator&lt;Iterator1&gt;&amp; x, const move_iterator&lt;Iterator2&gt;&amp; y);
+template &lt;class Iterator1, class Iterator2&gt;
+bool operator&lt;(
+const move_iterator&lt;Iterator1&gt;&amp; x, const move_iterator&lt;Iterator2&gt;&amp; y);
+template &lt;class Iterator1, class Iterator2&gt;
+bool operator&lt;=(
+const move_iterator&lt;Iterator1&gt;&amp; x, const move_iterator&lt;Iterator2&gt;&amp; y);
+template &lt;class Iterator1, class Iterator2&gt;
+bool operator&gt;(
+const move_iterator&lt;Iterator1&gt;&amp; x, const move_iterator&lt;Iterator2&gt;&amp; y);
+template &lt;class Iterator1, class Iterator2&gt;
+bool operator&gt;=(
+const move_iterator&lt;Iterator1&gt;&amp; x, const move_iterator&lt;Iterator2&gt;&amp; y);
+template &lt;class Iterator1, class Iterator2&gt;
+auto operator-(
+const move_iterator&lt;Iterator1&gt;&amp; x,
+const move_iterator&lt;Iterator2&gt;&amp; y) -&gt; decltype(x.base() - y.base());
+template &lt;class Iterator&gt;
+move_iterator&lt;Iterator&gt; operator+(
+                            typename move_iterator&lt;Iterator&gt;::difference_type n,
+                            const move_iterator&lt;Iterator&gt;&amp; x);
+template &lt;class Iterator&gt;
+move_iterator&lt;Iterator&gt; make_move_iterator(Iterator i);
+
+// range access:
+template &lt;class C&gt; auto begin(C&amp; c) -&gt; decltype(c.begin());
+template &lt;class C&gt; auto begin(const C&amp; c) -&gt; decltype(c.begin());
+template &lt;class C&gt; auto end(C&amp; c) -&gt; decltype(c.end());
+template &lt;class C&gt; auto end(const C&amp; c) -&gt; decltype(c.end());
+template &lt;class T, size_t N&gt; constexpr T* begin(T (&amp;array)[N]) noexcept;
+template &lt;class T, size_t N&gt; constexpr T* end(T (&amp;array)[N]) noexcept;
+template &lt;class C&gt;
+constexpr auto cbegin(const C&amp; c) noexcept(noexcept(std::begin(c)))
+-&gt; decltype(std::begin(c));
+template &lt;class C&gt;
+constexpr auto cend(const C&amp; c) noexcept(noexcept(std::end(c)))
+-&gt; decltype(std::end(c));
+template &lt;class C&gt; auto rbegin(C&amp; c) -&gt; decltype(c.rbegin());
+template &lt;class C&gt; auto rbegin(const C&amp; c) -&gt; decltype(c.rbegin());
+template &lt;class C&gt; auto rend(C&amp; c) -&gt; decltype(c.rend());
+template &lt;class C&gt; auto rend(const C&amp; c) -&gt; decltype(c.rend());
+template &lt;class T, size_t N&gt; reverse_iterator&lt;T*&gt; rbegin(T (&amp;array)[N]);
+template &lt;class T, size_t N&gt; reverse_iterator&lt;T*&gt; rend(T (&amp;array)[N]);
+template &lt;class E&gt; reverse_iterator&lt;const E*&gt; rbegin(initializer_list&lt;E&gt; il);
+template &lt;class E&gt; reverse_iterator&lt;const E*&gt; rend(initializer_list&lt;E&gt; il);
+template &lt;class C&gt; auto crbegin(const C&amp; c) -&gt; decltype(std::rbegin(c));
+template &lt;class C&gt; auto crend(const C&amp; c) -&gt; decltype(std::rend(c));
+
+}</code></pre>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="general-utilities-library">3.31. General Utilities Library</h3>
+<div class="paragraph">
+<p>OpenCL C++ implements part of utility library (<em>chapter 20.2, [utilities]</em>) from the C++14 standard.</p>
+</div>
+<div class="paragraph">
+<p>For the detailed description please refer to C++14 standard.</p>
+</div>
+<div class="sect3">
+<h4 id="header-opencl_utility-synopsis">3.31.1. Header &lt;opencl_utility&gt; Synopsis</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>namespace cl
+{
+template&lt;class T&gt;
+add_rvalue_reference_t&lt;T&gt; declval( );
+
+template &lt;class T&gt;
+constexpr T&amp;&amp; forward(typename remove_reference_t&amp; t) noexcept;
+template &lt;class T&gt;
+constexpr T&amp;&amp; forward(typename remove_reference_t&amp;&amp; t) noexcept;
+template &lt;class T&gt;
+constexpr typename remove_reference_t&amp;&amp; move(T&amp;&amp; t) noexcept;
+
+template&lt;class T&gt;
+void swap(T&amp; a, T&amp; b) noexcept;
+
+template &lt;class T&gt;
+  constexpr conditional_t&lt;
+  !is_nothrow_move_constructible&lt;T&gt;::value &amp;&amp; is_copy_constructible&lt;T&gt;::value,
+  const T&amp;, T&amp;&amp;&gt; move_if_noexcept(T&amp; x) noexcept;
+
+}</code></pre>
+</div>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="opencl-numerical-compliance">4. OpenCL Numerical Compliance</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>This section describes features of the C++14 and IEEE 754 standards that must be supported by all OpenCL compliant devices.</p>
+</div>
+<div class="paragraph">
+<p>This section describes the functionality that must be supported by all OpenCL devices for single precision floating-point numbers.
+Currently, only single precision and half precision floating-point is a requirement.
+Double precision floating-point is an optional feature.</p>
+</div>
+<div class="sect2">
+<h3 id="rounding-modes-1">4.1. Rounding Modes</h3>
+<div class="paragraph">
+<p>Floating-point calculations may be carried out internally with extra precision and then rounded to fit into the destination type.
+IEEE 754 defines four possible rounding modes:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Round to nearest even.</p>
+</li>
+<li>
+<p>Round toward +infinity.</p>
+</li>
+<li>
+<p>Round toward -infinity.</p>
+</li>
+<li>
+<p>Round toward zero.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p><em>Round to nearest even</em> is currently the only rounding mode required <a id="ftnref30"></a> <a href="#ftn30">[30]</a> by the OpenCL specification for single precision and double precision operations and is therefore the default rounding mode.
+In addition, only static selection of rounding mode is supported.
+Static and dynamic selection of rounding mode is not supported.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="inf-nan-and-denormalized-numbers">4.2. INF, NaN and Denormalized Numbers</h3>
+<div class="paragraph">
+<p>INF and NaNs must be supported.
+Support for signaling NaNs is not required.</p>
+</div>
+<div class="paragraph">
+<p>Support for denormalized numbers with single precision floating-point is optional.
+Denormalized single precision floating-point numbers passed as input or produced as the output of single precision floating-point operations such as add, sub, mul, divide, and the functions defined in <a href="#math-functions">Math Functions</a>, <a href="#common-functions">Common Functions</a> and <a href="#geometric-functions">Geometric Functions</a> may be flushed to zero.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="floating-point-exceptions">4.3. Floating-Point Exceptions</h3>
+<div class="paragraph">
+<p>Floating-point exceptions are disabled in OpenCL.
+The result of a floating-point exception must match the IEEE 754 spec for the exceptions not enabled case.
+Whether and when the implementation sets floating-point flags or raises floating-point exceptions is implementation-defined.
+This standard provides no method for querying, clearing or setting floating-point flags or trapping raised exceptions.
+Due to non-performance, non-portability of trap mechanisms and the impracticality of servicing precise exceptions in a vector context (especially on heterogeneous hardware), such features are discouraged.</p>
+</div>
+<div class="paragraph">
+<p>Implementations that nevertheless support such operations through an extension to the standard shall initialize with all exception flags cleared and the exception masks set so that exceptions raised by arithmetic operations do not trigger a trap to be taken.
+If the underlying work is reused by the implementation, the implementation is however not responsible for reclearing the flags or resetting exception masks to default values before entering the kernel.
+That is to say that kernels that do not inspect flags or enable traps are licensed to expect that their arithmetic will not trigger a trap.
+Those kernels that do examine flags or enable traps are responsible for clearing flag state and disabling all traps before returning control to the implementation.
+Whether or when the underlying work-item (and accompanying global floating-point state if any) is reused is implementation-defined.</p>
+</div>
+<div class="paragraph">
+<p>The expressions math_errorhandling and MATH_ERREXCEPT are reserved for use by this standard, but not defined.
+Implementations that extend this specification with support for floating-point exceptions shall define <code>math_errorhandling</code> and <code>MATH_ERREXCEPT</code> per ISO / IEC 9899 : TC2.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="relative-error-as-ulps">4.4. Relative Error as ULPs</h3>
+<div class="paragraph">
+<p>In this section we discuss the maximum relative error defined as ulp (units in the last place).
+Addition, subtraction, multiplication, fused multiply-add and conversion between integer and a single precision floating-point format are IEEE 754 compliant and are therefore correctly rounded.
+Conversion between floating-point formats and explicit conversions specified in the <a href="#conversions-library"><em>Conversions Library</em></a> section must be correctly rounded.</p>
+</div>
+<div class="paragraph">
+<p>The ULP is defined as follows:</p>
+</div>
+<div class="paragraph">
+<p>If x is a real number that lies between two finite consecutive floating-point numbers a and b, without being equal to one of them, then ulp(x) = |b - a|, otherwise ulp(x) is the distance between the two non-equal finite floating-point numbers nearest x.
+Moreover, ulp(NaN) is NaN.</p>
+</div>
+<div class="paragraph">
+<p><em>Attribution: This definition was taken with consent from Jean-Michel Muller with slight clarification for behavior at zero.
+Refer to <a href="ftp://ftp.inria.fr/INRIA/publication/publi-pdf/RR/RR-5504.pdf" class="bare">ftp://ftp.inria.fr/INRIA/publication/publi-pdf/RR/RR-5504.pdf</a></em></p>
+</div>
+<div class="paragraph">
+<p><a href="#ulp_values_for_single_precision_builtin_math_functions">ULP values for single precision built-in math functions</a> <a id="ftnref31"></a> <a href="#ftn31">[31]</a> table describes the minimum accuracy of single precision floating-point arithmetic operations given as ULP values.
+The reference value used to compute the ULP value of an arithmetic operation is the infinitely precise result.</p>
+</div>
+<table id="ulp_values_for_single_precision_builtin_math_functions" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 35. ULP values for single precision built-in math functions</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Function</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Min Accuracy - ULP values <a id="ftnref32"></a> <a href="#ftn32">[32]</a></strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>x</em> + <em>y</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>x</em> - <em>y</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>x</em> * <em>y</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">1.0  / <em>x</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2.5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>x</em> / <em>y</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2.5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">acos</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">acospi</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">asin</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">asinpi</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">atan</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">atan2</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 6 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">atanpi</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">atan2pi</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 6 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">acosh</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">asinh</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">atanh</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cbrt</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">ceil</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">copysign</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cos</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cosh</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cospi</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">erfc</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">erf</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">exp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">exp2</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">exp10</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">expm1</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">fabs</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">fdim</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">floor</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">fma</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">fmax</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">fmin</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">fmod</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">fract</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">frexp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">hypot</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">ilogb</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">ldexp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">log</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">log2</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">log10</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">log1p</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">logb</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">mad</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented either as a correctly rounded fma or as a multiply followed by an add both of which are correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">maxmag</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">minmag</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">modf</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">nan</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">nextafter</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">pow(x, y)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">pown(x, y)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">powr(x, y)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">remainder</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">remquo</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">rint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">rootn</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">round</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">rsqrt</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">sin</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">sincos</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp for sine and cosine values</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">sinh</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">sinpi</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">sqrt</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">tan</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">tanh</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">tanpi</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 6 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">tgamma</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">trunc</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">native_math::cos</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">native_math::divide</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">native_math::exp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">native_math::exp2</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">native_math::exp10</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">native_math::log</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">native_math::log2</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">native_math::log10</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">native_math::powr</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">native_math::recip</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">native_math::rsqrt</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">native_math::sin</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">native_math::sqrt</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">native_math::tan</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p><a href="#ulp_values_for_single_precision_builtin_math_functions_for_embedded_profile">ULP values for single precision builtin math functions for embedded profile</a> table describes the minimum accuracy of single precision floating-point arithmetic operations given as ULP values for the embedded profile.
+The reference value used to compute the ULP value of an arithmetic operation is the infinitely precise result.</p>
+</div>
+<table id="ulp_values_for_single_precision_builtin_math_functions_for_embedded_profile" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 36. ULP values for single precision built-in math functions for embedded profile</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Function</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Min Accuracy - ULP values <a href="#ftn32">[32]</a></strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>x</em> + <em>y</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>x</em> - <em>y</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>x</em> * <em>y</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">1.0  / <em>x</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>x</em> / <em>y</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">acos</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">acospi</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">asin</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">asinpi</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">atan</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">atan2</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 6 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">atanpi</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">atan2pi</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 6 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">acosh</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">asinh</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">atanh</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cbrt</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">ceil</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">copysign</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cos</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cosh</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cospi</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">erfc</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">erf</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">exp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">exp2</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">exp10</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">expm1</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">fabs</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">fdim</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">floor</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">fma</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">fmax</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">fmin</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">fmod</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">fract</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">frexp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">hypot</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">ilogb</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">ldexp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">log</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">log2</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">log10</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">log1p</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">logb</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">mad</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Any value allowed (infinite ulp)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">maxmag</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">minmag</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">modf</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">nan</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">nextafter</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">pow(x, y)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">pown(x, y)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">powr(x, y)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">remainder</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">remquo</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">rint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">rootn</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">round</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">rsqrt</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">sin</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">sincos</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp for sine and cosine values</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">sinh</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">sinpi</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">sqrt</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">tan</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">tanh</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">tanpi</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 6 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">tgamma</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">trunc</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half_cos</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half_divide</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half_exp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half_exp2</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half_exp10</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half_log</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half_log2</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half_log10</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half_powr</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half_recip</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half_rsqrt</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half_sin</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half_sqrt</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half_tan</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">native_math::cos</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">native_math::divide</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">native_math::exp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">native_math::exp2</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">native_math::exp10</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">native_math::log</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">native_math::log2</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">native_math::log10</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">native_math::powr</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">native_math::recip</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">native_math::rsqrt</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">native_math::sin</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">native_math::sqrt</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">native_math::tan</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p><a href="#ulp_values_for_single_precision_builtin_math_functions_with_fast_relaxed_math">ULP values for single precision built-in math functions with unsafe math optimizations</a> table describes the minimum accuracy of commonly used single precision floating-point arithmetic operations given as ULP values if the <em>-cl-unsafe-math-optimizations</em> compiler option is specified when compiling or building an OpenCL program.
+For derived implementations, the operations used in the derivation may themselves be relaxed according to <a href="#ulp_values_for_single_precision_builtin_math_functions_with_fast_relaxed_math">ULP values for single precision built-in math functions with unsafe math optimizations</a> table.
+The minimum accuracy of math functions not defined in <a href="#ulp_values_for_single_precision_builtin_math_functions_with_fast_relaxed_math">ULP values for single precision built-in math functions with unsafe math optimizations</a> table when the <em>-cl-unsafe-math-optimizations</em> compiler option is specified is as defined in <a href="#ulp_values_for_single_precision_builtin_math_functions">ULP values for single precision built-in math functions</a> table when operating in the full profile, and as defined in <a href="#ulp_values_for_single_precision_builtin_math_functions_for_embedded_profile">ULP values for single precision built-in math functions for embedded profile</a> table when operating in the embedded profile.
+The reference value used to compute the ULP value of an arithmetic operation is the infinitely precise result.</p>
+</div>
+<table id="ulp_values_for_single_precision_builtin_math_functions_with_fast_relaxed_math" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 37. ULP values for single precision built-in math functions with unsafe math optimizations in the full and embedded profiles</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Function</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Min Accuracy - ULP values <a href="#ftn32">[32]</a></strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">1.0  / x</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2.5 ulp for x in the domain of 2<sup>-126</sup> to 2<sup>126</sup> for the full profile, and &lt;= 3 ulp for the embedded profile.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">x / y</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2.5 ulp for x in the domain of 2<sup>-62</sup> to 2<sup>62</sup> and <em>y</em> in the domain of 2<sup>-62</sup> to 2<sup>62</sup> for the full profile, and &lt;= 3 ulp for the embedded profile.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">acos(x)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4096 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">acospi(x)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented as acos(x) * M_PI_F.
+  For non-derived implementations, the error is &lt;= 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">asin(x)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4096 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">asinpi(x)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented as asin(x) * M_PI_F.
+  For non-derived implementations, the error is &lt;= 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">atan(x)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4096 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">atan2(y, x)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented as atan(y/x) for x &gt; 0, atan(y/x) + M_PI_F for x &lt; 0 and y &gt; 0 and atan(y/x) - M_PI_F for x &lt; 0 and y &lt; 0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">atanpi(x)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented as atan(x) * M_1_PI_F.
+  For non-derived implementations, the error is &lt;= 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">atan2pi(y, x)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented as atan2(y, x) * M_1_PI_F.
+  For non-derived implementations, the error is &lt;= 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">acosh(x)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented as log( x + sqrt(x*x - 1) ).</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">asinh(x)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented as log( x + sqrt(x*x + 1) ).</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">atanh(x)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Defined for x in the domain (-1, 1). For x in [-2<sup>-10</sup>, 2<sup>-10</sup>], implemented as x.
+  For x outside of [-2<sup>-10</sup>, 2<sup>-10</sup>], implemented as 0.5f * log( (1.0f + x) / (1.0f - x) ).
+  For non-derived implementations, the error is &lt;= 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cbrt(x)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented as rootn(x, 3).
+  For non-derived implementations, the error is &lt;= 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cos(x)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">For x in the domain [-π, π], the maximum absolute error is &lt;= 2<sup>-11</sup> and larger otherwise.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cosh(x)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Defined for x in the domain [-88, 88] and implemented as 0.5f * ( exp(x) + exp(-x) ).
+  For non-derived implementations, the error is &lt;= 8192 ULP.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cospi(x)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">For x in the domain [-1, 1], the maximum absolute error is &lt;= 2<sup>-11</sup> and larger otherwise.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">exp(x)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 + floor( fabs(2 * x) ) ulp for the full profile, and &lt;= 4 ulp for the embedded profile.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">exp2(x)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 + floor( fabs(2 * x) ) ulp for the full profile, and &lt;= 4 ulp for the embedded profile.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">exp10(x)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Derived implementations implement this as exp2( x * log2(10) ).
+  For non-derived implementations, the error is &lt;= 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">expm1(x)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Derived implementations implement this as exp(x) - 1.
+  For non-derived implementations, the error is &lt;= 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">log(x)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">For x in the domain [0.5, 2] the maximum absolute error is &lt;= 2<sup>-21</sup>; otherwise the maximum error is &lt;=3 ulp for the full profile and &lt;= 4 ulp for the embedded profile</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">log2(x)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">For x in the domain [0.5, 2] the maximum absolute error is &lt;= 2<sup>-21</sup>; otherwise the maximum error is &lt;=3 ulp for the full profile and &lt;= 4 ulp for the embedded profile</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">log10(x)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">For x in the domain [0.5, 2] the maximum absolute error is &lt;= 2<sup>-21</sup>; otherwise the maximum error is &lt;=3 ulp for the full profile and &lt;= 4 ulp for the embedded profile</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">log1p(x)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Derived implementations implement this as log(x + 1).
+  For non-derived implementations, the error is &lt;= 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">pow(x, y)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Undefined for x = 0 and y = 0.
+  Undefined for x &lt; 0 and non-integer y.
+  Undefined for x &lt; 0 and y outside the domain [-2<sup>24</sup>, 2<sup>24</sup>].
+  For x &gt; 0 or x &lt; 0 and even y, derived implementations implement this as exp2( y * log2(x) ).
+  For x &lt; 0 and odd y, derived implementations implement this as -exp2( y * log2(fabs(x) ) <a id="ftnref33"></a> <a href="#ftn33">[33]</a>.
+  For x == 0 and nonzero y, derived implementations return zero.
+  For non-derived implementations, the error is &lt;= 8192 ULP.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">pown(x, y)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Defined only for integer values of y.
+  Undefined for x = 0 and y = 0.
+  For x &gt;= 0 or x &lt; 0 and even y, derived implementations implement this as exp2( y * log2(x) ).
+  For x &lt; 0 and odd y, derived implementations implement this as -exp2( y * log2( fabs(x) ) ).
+  For non-derived implementations, the error is &lt;= 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">powr(x, y)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Defined only for x &gt;= 0.
+  Undefined for x = 0 and y = 0.
+  Derived implementations implement this as exp2( y * log2(x) ).
+  For non-derived implementations, the error is &lt;= 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">rootn(x, y)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Defined for x &gt; 0 when y is non-zero, derived implementations implement this case as exp2( log2(x) / y ). Defined for x &lt; 0 when y is odd, derived implementations implement this case as -exp2( log2(-x) / y ).
+  Defined for x = +/-0 when y &gt; 0, derived implementations will return +0 in this case.
+  For non-derived implementations, the error is &lt;= 8192 ULP.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">sin(x)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">For x in the domain [-π, π], the maximum absolute error is &lt;= 2<sup>-11</sup> and larger otherwise.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">sincos(x)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">ulp values as defined for sin(x) and cos(x).</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">sinh(x)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Defined for x in the domain [-88, 88].
+  For x in [-2<sup>-10</sup>, 2<sup>-10</sup>], derived implementations implement as x.
+  For x outside of [-2<sup>-10</sup>, 2<sup>-10</sup>], derived implement as 0.5f * ( exp(x) - exp(-x) ).
+  For non-derived implementations, the error is &lt;= 8192 ULP.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">sinpi(x)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">For x in the domain [-1, 1], the maximum absolute error is &lt;= 2<sup>-11</sup> and larger otherwise.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">tan(x)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Derived implementations implement this as sin(x) * ( 1.0f / cos(x) ).
+  For non-derived implementations, the error is &lt;= 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">tanh</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Defined for x in the domain [-88, 88].
+  For x in [-2<sup>-10</sup>, 2<sup>-10</sup>], derived implementations implement as x.
+  For x outside of [-2<sup>-10</sup>, 2<sup>-10</sup>], derived implementations implement as ( exp(x) - exp(-x) ) / ( exp(x) + exp(-x) ).
+  For non-derived implementations, the error is &lt;= 8192 ULP.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">tanpi(x)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Derived implementations implement this as tan(x * M_PI_F).
+  For non-derived implementations, the error is &lt;= 8192 ulp for x in the domain [-1, 1].</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">x * y + z</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented either as a correctly rounded fma or as a multiply and an add both of which are correctly rounded.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p><a href="#ulp_values_for_double_precision_builtin_math_functions">ULP values for double precision built-in math functions</a> table describes the minimum accuracy of double precision floating-point arithmetic operations given as ULP values.
+The reference value used to compute the ULP value of an arithmetic operation is the infinitely precise result.</p>
+</div>
+<table id="ulp_values_for_double_precision_builtin_math_functions" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 38. ULP values for double precision built-in math functions</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Function</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Min Accuracy - ULP values <a href="#ftn32">[32]</a></strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">x + y</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">x - y</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">x * y</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">1.0  / x</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">x / y</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">acos</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">acospi</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">asin</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">asinpi</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">atan</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">atan2</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 6 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">atanpi</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">atan2pi</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 6 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">acosh</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">asinh</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">atanh</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cbrt</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">ceil</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">copysign</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cos</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cosh</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cospi</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">erfc</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">erf</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">exp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">exp2</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">exp10</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">expm1</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">fabs</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">fdim</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">floor</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">fma</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">fmax</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">fmin</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">fmod</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">fract</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">frexp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">hypot</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">ilogb</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">ldexp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">log</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">log2</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">log10</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">log1p</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">logb</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">mad</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented either as a correctly rounded fma or as a multiply followed by an add both of which are correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">maxmag</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">minmag</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">modf</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">nan</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">nextafter</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">pow(x, y)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">pown(x, y)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">powr(x, y)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">remainder</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">remquo</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">rint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">rootn</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">round</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">rsqrt</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">sin</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">sincos</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp for sine and cosine values</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">sinh</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">sinpi</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">sqrt</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">tan</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">tanh</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">tanpi</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 6 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">tgamma</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">trunc</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p><a href="#ulp_values_for_half_precision_builtin_math_functions">ULP values for half precision built-in math functions</a> table describes the minimum accuracy of half precision floating-point arithmetic operations given as ULP values.
+The reference value used to compute the ULP value of an arithmetic operation is the infinitely precise result.</p>
+</div>
+<table id="ulp_values_for_half_precision_builtin_math_functions" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 39. ULP values for half precision built-in math functions</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Function</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Min Accuracy - ULP values <a href="#ftn32">[32]</a></strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">x + y</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">x - y</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">x * y</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">1.0 / x</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">x / y</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">acos</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">acospi</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">asin</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">asinpi</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">atan</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">atan2</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">atanpi</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">atan2pi</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">acosh</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">asinh</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">atanh</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cbrt</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">ceil</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">copysign</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cos</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cosh</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cospi</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">erfc</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">erf</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">exp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">exp2</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">exp10</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">expm1</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">fabs</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">fdim</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">floor</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">fma</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">fmax</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">fmin</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">fmod</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">fract</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">frexp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">hypot</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">ilogb</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">ldexp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">log</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">log2</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">log10</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">log1p</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">logb</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">mad</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented either as a correctly rounded fma or as a multiply followed by an add both of which are correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">maxmag</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">minmag</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">modf</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">nan</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">nextafter</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">pow(x, y)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">pown(x, y)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">powr(x, y)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">remainder</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">remquo</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">rint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">rootn</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">round</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">rsqrt</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 1 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">sin</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">sincos</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp for sine and cosine values</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">sinh</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">sinpi</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">sqrt</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">tan</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">tanh</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">tanpi</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">tgamma</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">trunc</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect2">
+<h3 id="edge-case-behavior">4.5. Edge Case Behavior</h3>
+<div class="paragraph">
+<p>The edge case behavior of the math functions (see the <a href="#math-functions"><em>Math Functions</em></a> section) shall conform to sections F.9 and G.6 of ISO/IEC 9899:TC 2, except where noted below in the <a href="#additional-requirements-beyond-isoiec-9899tc2"><em>Additional Requirements Beyond ISO/IEC 9899:TC2</em></a> section.</p>
+</div>
+<div class="sect3">
+<h4 id="additional-requirements-beyond-isoiec-9899tc2">4.5.1. Additional Requirements Beyond ISO/IEC 9899:TC2</h4>
+<div class="paragraph">
+<p>Functions that return a NaN with more than one NaN operand shall return one of the NaN operands.
+Functions that return a NaN operand may silence the NaN if it is a signaling NaN.
+A non-signaling NaN shall be converted to a non-signaling NaN.
+A signaling NaN shall be converted to a NaN, and should be converted to a non-signaling NaN.
+How the rest of the NaN payload bits or the sign of NaN is converted is undefined.</p>
+</div>
+<div class="paragraph">
+<p>The usual allowances for rounding error (see the <a href="#relative-error-as-ulps"><em>Relative Error as ULPs</em></a> section) or flushing behavior (see the <a href="#edge-case-behavior-in-flush-to-zero-mode"><em>Edge Case Behavior in Flush To Zero Mode</em></a> section) shall not apply for those values for which <em>section F.9</em> of ISO/IEC 9899:,TC2, or the <a href="#additional-requirements-beyond-isoiec-9899tc2"><em>Additional Requirements Beyond ISO/IEC 9899:TC2</em></a> and the <a href="#edge-case-behavior-in-flush-to-zero-mode"><em>Edge Case Behavior in Flush To Zero Mode</em></a> sections below (and similar sections for other floating-point precisions) prescribe a result (e.g. ceil( -1 &lt; x &lt; 0 ) returns -0).
+Those values shall produce exactly the prescribed answers, and no other.
+Where the ± symbol is used, the sign shall be preserved.
+For example, sin(±0) = ±0 shall be interpreted to mean sin(+0) is +0 and sin(-0) is -0.</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>acospi( 1 ) = +0.</p>
+</li>
+<li>
+<p>acospi( x ) returns a NaN for | x | &gt; 1.</p>
+</li>
+<li>
+<p>asinpi( ±0 ) = ±0.</p>
+</li>
+<li>
+<p>asinpi( x ) returns a NaN for | x | &gt; 1.</p>
+</li>
+<li>
+<p>atanpi( ±0 ) = ±0.</p>
+</li>
+<li>
+<p>atanpi ( ±∞ ) = ±0.5.</p>
+</li>
+<li>
+<p>atan2pi ( ±0, -0 ) = ±1.</p>
+</li>
+<li>
+<p>atan2pi ( ±0, +0 ) = ±0.</p>
+</li>
+<li>
+<p>atan2pi ( ±0, x ) returns ±1 for x &lt; 0.</p>
+</li>
+<li>
+<p>atan2pi ( ±0, x) returns ±0 for x &gt; 0.</p>
+</li>
+<li>
+<p>atan2pi ( y, ±0 ) returns -0.5 for y &lt; 0.</p>
+</li>
+<li>
+<p>atan2pi ( y, ±0 ) returns 0.5 for y &gt; 0.</p>
+</li>
+<li>
+<p>atan2pi ( ±y, -∞ ) returns ±1 for finite y &gt; 0.</p>
+</li>
+<li>
+<p>atan2pi ( ±y, +∞ ) returns ±0 for finite y &gt; 0.</p>
+</li>
+<li>
+<p>atan2pi ( ±∞, x ) returns ±0.5 for finite x.</p>
+</li>
+<li>
+<p>atan2pi ( ±∞, -∞ ) returns ±0.75.</p>
+</li>
+<li>
+<p>atan2pi ( ±∞, +∞ ) returns ±0.25.</p>
+</li>
+<li>
+<p>ceil( -1 &lt; x &lt; 0 ) returns -0.</p>
+</li>
+<li>
+<p>cospi( ±0 ) returns 1</p>
+</li>
+<li>
+<p>cospi( n + 0.5 ) is +0 for any integer n where n + 0.5 is representable.</p>
+</li>
+<li>
+<p>cospi( ±∞ ) returns a NaN.</p>
+</li>
+<li>
+<p>exp10( ±0 ) returns 1.</p>
+</li>
+<li>
+<p>exp10( -∞ ) returns +0.</p>
+</li>
+<li>
+<p>exp10( +∞ ) returns +∞.</p>
+</li>
+<li>
+<p>distance( x, y ) calculates the distance from x to y without overflow or extraordinary precision loss due to underflow.</p>
+</li>
+<li>
+<p>fdim( any, NaN ) returns NaN.</p>
+</li>
+<li>
+<p>fdim( NaN, any ) returns NaN.</p>
+</li>
+<li>
+<p>fmod( ±0, NaN ) returns NaN.</p>
+</li>
+<li>
+<p>frexp( ±∞, exp ) returns ±∞ and stores 0 in exp.</p>
+</li>
+<li>
+<p>frexp( NaN, exp ) returns the NaN and stores 0 in exp.</p>
+</li>
+<li>
+<p>fract( x, iptr) shall not return a value greater than or equal to 1.0, and shall not return a value less than 0.</p>
+</li>
+<li>
+<p>fract( +0, iptr ) returns +0 and +0 in iptr.</p>
+</li>
+<li>
+<p>fract( -0, iptr ) returns -0 and -0 in iptr.</p>
+</li>
+<li>
+<p>fract( +inf, iptr ) returns +0 and +inf in iptr.</p>
+</li>
+<li>
+<p>fract( -inf, iptr ) returns -0 and -inf in iptr.</p>
+</li>
+<li>
+<p>fract( NaN, iptr ) returns the NaN and NaN in iptr.</p>
+</li>
+<li>
+<p>length calculates the length of a vector without overflow or extraordinary precision loss due to underflow.</p>
+</li>
+<li>
+<p>lgamma_r( x, signp ) returns 0 in signp if x is zero or a negative integer.</p>
+</li>
+<li>
+<p>nextafter( -0, y &gt; 0 ) returns smallest positive denormal value.</p>
+</li>
+<li>
+<p>nextafter( +0, y &lt; 0 ) returns smallest negative denormal value.</p>
+</li>
+<li>
+<p>normalize shall reduce the vector to unit length, pointing in the same direction without overflow or extraordinary precision loss due to underflow.</p>
+</li>
+<li>
+<p>normalize( v ) returns v if all elements of v are zero.</p>
+</li>
+<li>
+<p>normalize( v ) returns a vector full of NaNs if any element is a NaN.</p>
+</li>
+<li>
+<p>normalize( v ) for which any element in v is infinite shall proceed as if the elements in v were replaced as follows:</p>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>for( i = 0; i &lt; sizeof(v) / sizeof(v[0] ); i++ )
+    v[i] = isinf(v[i] )  ?  copysign(1.0, v[i]) : 0.0 * v [i];</code></pre>
+</div>
+</div>
+</li>
+<li>
+<p>pow( ±0, -∞ ) returns +∞</p>
+</li>
+<li>
+<p>pown( x, 0 ) is 1 for any x, even zero, NaN or infinity.</p>
+</li>
+<li>
+<p>pown( ±0, n ) is ±∞ for odd n &lt; 0.</p>
+</li>
+<li>
+<p>pown( ±0, n ) is +∞ for even n &lt; 0.</p>
+</li>
+<li>
+<p>pown( ±0, n ) is +0 for even n &gt; 0.</p>
+</li>
+<li>
+<p>pown( ±0, n ) is ±0 for odd n &gt; 0.</p>
+</li>
+<li>
+<p>powr( x, ±0 ) is 1 for finite x &gt; 0.</p>
+</li>
+<li>
+<p>powr( ±0, y ) is +∞ for finite y &lt; 0.</p>
+</li>
+<li>
+<p>powr( ±0, -∞) is +∞.</p>
+</li>
+<li>
+<p>powr( ±0, y ) is +0 for y &gt; 0.</p>
+</li>
+<li>
+<p>powr( +1, y ) is 1 for finite y.</p>
+</li>
+<li>
+<p>powr( x, y ) returns NaN for x &lt; 0.</p>
+</li>
+<li>
+<p>powr( ±0, ±0 ) returns NaN.</p>
+</li>
+<li>
+<p>powr( +∞, ±0 ) returns NaN.</p>
+</li>
+<li>
+<p>powr( +1, ±∞ ) returns NaN.</p>
+</li>
+<li>
+<p>powr( x, NaN ) returns the NaN for x &gt;= 0.</p>
+</li>
+<li>
+<p>powr( NaN, y ) returns the NaN.</p>
+</li>
+<li>
+<p>rint( -0.5 &lt;= x &lt; 0 ) returns -0.</p>
+</li>
+<li>
+<p>remquo(x, y, &amp;quo) returns a NaN and 0 in quo if x is ±∞, or if y is 0 and the other argument is non-NaN or if either argument is a NaN.</p>
+</li>
+<li>
+<p>rootn( ±0, n ) is ±∞ for odd n &lt; 0.</p>
+</li>
+<li>
+<p>rootn( ±0, n ) is +∞ for even n &lt; 0.</p>
+</li>
+<li>
+<p>rootn( ±0, n ) is +0 for even n &gt; 0.</p>
+</li>
+<li>
+<p>rootn( ±0, n ) is ±0 for odd n &gt; 0.</p>
+</li>
+<li>
+<p>rootn( x, n ) returns a NaN for x &lt; 0 and n is even.</p>
+</li>
+<li>
+<p>rootn( x, 0 ) returns a NaN.</p>
+</li>
+<li>
+<p>round( -0.5 &lt; x &lt; 0 ) returns -0.</p>
+</li>
+<li>
+<p>sinpi( ±0 ) returns ±0.</p>
+</li>
+<li>
+<p>sinpi( +n) returns +0 for positive integers n.</p>
+</li>
+<li>
+<p>sinpi( -n ) returns -0 for negative integers n.</p>
+</li>
+<li>
+<p>sinpi( ±∞ ) returns a NaN.</p>
+</li>
+<li>
+<p>tanpi( ±0 ) returns ±0.</p>
+</li>
+<li>
+<p>tanpi( ±∞ ) returns a NaN.</p>
+</li>
+<li>
+<p>tanpi( n ) is copysign( 0.0, n ) for even integers n.</p>
+</li>
+<li>
+<p>tanpi( n ) is copysign( 0.0, - n) for odd integers n.</p>
+</li>
+<li>
+<p>tanpi( n + 0.5 ) for even integer n is +∞ where n + 0.5 is representable.</p>
+</li>
+<li>
+<p>tanpi( n + 0.5 ) for odd integer n is -∞ where n + 0.5 is representable.</p>
+</li>
+<li>
+<p>trunc( -1 &lt; x &lt; 0 ) returns -0.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="changes-to-isoiec-9899-tc2-behavior">4.5.2. Changes to ISO/IEC 9899: TC2 Behavior</h4>
+<div class="paragraph">
+<p><code>modf</code> behaves as though implemented by:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype modf( gentype value, gentype *iptr )
+{
+    *iptr = trunc( value );
+    return copysign( isinf( value ) ? 0.0 : value - *iptr, value );
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>rint always rounds according to round to nearest even rounding mode even if the caller is in some other rounding mode.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="edge-case-behavior-in-flush-to-zero-mode">4.5.3. Edge Case Behavior in Flush To Zero Mode</h4>
+<div class="paragraph">
+<p>If denormals are flushed to zero, then a function may return one of four results:</p>
+</div>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>Any conforming result for non-flush-to-zero mode.</p>
+</li>
+<li>
+<p>If the result given by 1. is a sub-normal before rounding, it may be flushed to zero.</p>
+</li>
+<li>
+<p>Any non-flushed conforming result for the function if one or more of its sub-normal operands are flushed to zero.</p>
+</li>
+<li>
+<p>If the result of 3. is a sub-normal before rounding, the result may be flushed to zero.</p>
+</li>
+</ol>
+</div>
+<div class="paragraph">
+<p>In each of the above cases, if an operand or result is flushed to zero, the sign of the zero is undefined.</p>
+</div>
+<div class="paragraph">
+<p>If subnormals are flushed to zero, a device may choose to conform to the following edge cases for nextafter instead of those listed in the <a href="#additional-requirements-beyond-isoiec-9899tc2"><em>Additional Requirements Beyond ISO/IEC 9899:TC2</em></a> section:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>nextafter ( +smallest normal, y &lt; +smallest normal ) = +0.</p>
+</li>
+<li>
+<p>nextafter ( -smallest normal, y &gt; -smallest normal ) = -0.</p>
+</li>
+<li>
+<p>nextafter ( -0, y &gt; 0 ) returns smallest positive normal value.</p>
+</li>
+<li>
+<p>nextafter ( +0, y &lt; 0 ) returns smallest negative normal value.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For clarity, subnormals or denormals are defined to be the set of representable numbers in the range 0 &lt; x &lt; <code>TYPE_MIN</code> and <code>-TYPE_MIN</code> &lt; x &lt; -0.
+They do not include ±0.
+A non-zero number is said to be sub-normal before rounding if after normalization, its radix-2 exponent is less than <code>(TYPE_MIN_EXP - 1)</code>. <a id="ftnref35"></a> <a href="#ftn35">[35]</a></p>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="image-addressing-and-filtering">5. Image Addressing and Filtering</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>Let w<sub>t</sub>, h<sub>t</sub> and d<sub>t</sub> be the width, height (or image array size for a 1D image array) and depth (or image array size for a 2D image array) of the image in pixels.
+Let coord.xy also referred to as (s,t) or coord.xyz also referred to as (s,t,r) be the coordinates specified to <code>image::read</code>.
+The sampler specified in <code>image::read</code> is used to determine how to sample the image and return an appropriate color.</p>
+</div>
+<div class="sect2">
+<h3 id="image-coordinates">5.1. Image Coordinates</h3>
+<div class="paragraph">
+<p>This affects the interpretation of image coordinates.
+If image coordinates specified to <code>image::read</code> are normalized (as specified in the sampler), the s,t, and r coordinate values are multiplied by w<sub>t</sub>, h<sub>t,</sub> and d<sub>t</sub> respectively to generate the unnormalized coordinate values.
+For image arrays, the image array coordinate (i.e. t if it is a 1D image array or r if it is a 2D image array) specified to <code>image::read</code> must always be the unnormalized image coordinate value.</p>
+</div>
+<div class="paragraph">
+<p>Let (u,v,w) represent the unnormalized image coordinate values.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="addressing-and-filter-modes">5.2. Addressing and Filter Modes</h3>
+<div class="paragraph">
+<p>We first describe how the addressing and filter modes are applied to generate the appropriate sample locations to read from the image if the addressing mode is not <code>addressing_mode::repeat</code> nor <code>addressing_mode::mirrored_repeat</code>.</p>
+</div>
+<div class="paragraph">
+<p>After generating the image coordinate (u,v,w) we apply the appropriate addressing and filter mode to generate the appropriate sample locations to read from the image.</p>
+</div>
+<div class="paragraph">
+<p>If values in (u,v,w) are INF or NaN, the behavior of <code>image::read</code> is undefined.</p>
+</div>
+<div class="sect3">
+<h4 id="filtering_modenearest">5.2.1. filtering_mode::nearest</h4>
+<div class="paragraph">
+<p>When filter mode is <code>filtering_mode::nearest</code>, the image element in the image that is nearest (in Manhattan distance) to that specified by (u,v,w) is obtained.
+This means the image element at location (i,j,k) becomes the image element value, where</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[\begin{array}{rcl}
+i &amp;=&amp; address\_mode((int)floor(u))\\
+j &amp;=&amp; address\_mode((int)floor(v))\\
+k &amp;=&amp; address\_mode((int)floor(w))
+\end{array}\]
+</div>
+</div>
+<div class="paragraph">
+<p>For a 3D image, the image element at location (i, j, k) becomes the color value.
+For a 2D image, the image element at location (i, j) becomes the color value.</p>
+</div>
+<div class="paragraph">
+<p>The below table describes the <code>address_mode</code> function.</p>
+</div>
+<table id="addressing_modes_to_generate_texel_location" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 40. Addressing modes to generate texel location</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Addressing Mode</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Result of address_mode(coord)</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><div><div class="paragraph">
+<p><code>clamp_to_edge</code></p>
+</div></div></td>
+<td class="tableblock halign-left valign-top"><div><div class="paragraph">
+<p>clamp (coord, 0, size - 1)</p>
+</div></div></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><div><div class="paragraph">
+<p><code>clamp</code></p>
+</div></div></td>
+<td class="tableblock halign-left valign-top"><div><div class="paragraph">
+<p>clamp (coord, -1, size)</p>
+</div></div></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><div><div class="paragraph">
+<p><code>none</code></p>
+</div></div></td>
+<td class="tableblock halign-left valign-top"><div><div class="paragraph">
+<p>Coord</p>
+</div></div></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>The size term in <a href="#addressing_modes_to_generate_texel_location">Addressing modes to generate texel location</a> table is w<sub>t</sub> for u, h<sub>t</sub> for v and d<sub>t</sub> for w.</p>
+</div>
+<div class="paragraph">
+<p>The clamp function used in <a href="#addressing_modes_to_generate_texel_location">Addressing modes to generate texel location</a> table is defined as:</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1"></dt>
+<dd>
+<p>\(clamp(a, b, c) = return (a &lt; b) ? b : ((a &gt; c) ? c : a)\)</p>
+</dd>
+</dl>
+</div>
+<div class="paragraph">
+<p>If the selected texel location (i,j,k) refers to a location outside the image, the border color is used as the color value for this texel.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="filtering_modelinear">5.2.2. filtering_mode::linear</h4>
+<div class="paragraph">
+<p>When filter mode is <code>filtering_mode::linear</code>, a 2 x 2 square of image elements for a 2D image or a 2 x 2 x 2 cube of image elements for a 3D image is selected.
+This 2 x 2 square or 2 x 2 x 2 cube is obtained as follows.</p>
+</div>
+<div class="paragraph">
+<p>Let</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[\begin{aligned}
+i0 &amp; = address\_mode((int)floor(u - 0.5))\\
+j0 &amp; = address\_mode((int)floor(v - 0.5))\\
+k0 &amp; = address\_mode((int)floor(w - 0.5))\\
+i1 &amp; = address\_mode((int)floor(u - 0.5) + 1)\\
+j1 &amp; = address\_mode((int)floor(v - 0.5) + 1)\\
+k1 &amp; = address\_mode((int)floor(w - 0.5) + 1)\\
+a  &amp; = frac(u - 0.5)\\
+b  &amp; = frac(v - 0.5)\\
+c  &amp; = frac(w - 0.5)
+\end{aligned}\]
+</div>
+</div>
+<div class="paragraph">
+<p>where frac(x) denotes the fractional part of x and is computed as x - floor(x).</p>
+</div>
+<div class="paragraph">
+<p>For a 3D image, the image element value is found as</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[\begin{array}{rcl}
+T &amp;=&amp; (1 - a) * (1 - b) * (1 - c) * T_{i0j0k0}\\
+  &amp; &amp; {} + a * (1 - b) * (1 - c) * T_{i1j0k0}\\
+  &amp; &amp; {} + (1 - a) * b * (1 - c) * T_{i0j1k0}\\
+  &amp; &amp; {} + a * b * (1 - c) * T_{i1j1k0}\\
+  &amp; &amp; {} + (1 - a) * (1 - b) * c * T_{i0j0k1}\\
+  &amp; &amp; {} + a * (1 - b) * c * T_{i1j0k1}\\
+  &amp; &amp; {} + (1 - a) * b * c * T_{i0j1k1}\\
+  &amp; &amp; {} + a * b * c * T_{i1j1k1}
+\end{array}\]
+</div>
+</div>
+<div class="paragraph">
+<p>where T<sub>ijk</sub> is the image element at location (i,j,k) in the 3D image.</p>
+</div>
+<div class="paragraph">
+<p>For a 2D image, the image element value is found as</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[\begin{array}{rcl}
+T &amp;=&amp; (1 - a) * (1 - b) * T_{i0j0}\\
+  &amp; &amp; {} + a * (1 - b) * T_{i1j0}\\
+  &amp; &amp; {} + (1 - a) * b * T_{i0j1}\\
+  &amp; &amp; {} + a * b * T_{i1j1}
+\end{array}\]
+</div>
+</div>
+<div class="paragraph">
+<p>where T<sub>ij</sub> is the image element at location (i,j) in the 2D image.</p>
+</div>
+<div class="paragraph">
+<p>If any of the selected T<sub>ijk</sub> or T<sub>ij</sub> in the above equations refers to a location outside the image, the border color is used as the color value for T<sub>ijk</sub> or T<sub>ij</sub>.</p>
+</div>
+<div class="paragraph">
+<p>If the image channel type is <code>CL_FLOAT</code> or <code>CL_HALF_FLOAT</code> and any of the image elements T<sub>ijk</sub> or T<sub>ij</sub> is INF or NaN, the behavior of the built-in image read function is undefined.</p>
+</div>
+<div class="paragraph">
+<p>We now discuss how the addressing and filter modes are applied to generate the appropriate sample locations to read from the image if the addressing mode is <code>addressing_mode::repeat</code>.</p>
+</div>
+<div class="paragraph">
+<p>If values in (s,t,r) are INF or NaN, the behavior of the built-in image read functions is undefined.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="filtering_modenearest-1">5.2.3. filtering_mode::nearest</h4>
+<div class="paragraph">
+<p>When filter mode is <code>filtering_mode::nearest</code>, the image element at location (i,j,k) becomes the image element value, with i, j and k computed as</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[\begin{array}{l}
+u = (s - floor(s)) * w_t\\
+i = (int)floor(u)\\
+if\ (i &gt; w_t - 1)\\
+\qquad i = i - w_t\\
+v = (t - floor(t)) * h_t\\
+j = (int)floor(v)\\
+if\ (j &gt; h_t - 1)\\
+\qquad j = j - h_t\\
+w = (r - floor(r)) * d_t\\
+k = (int)floor(w)\\
+if\ (k &gt; d_t - 1)\\
+\qquad k = k - d_t
+\end{array}\]
+</div>
+</div>
+<div class="paragraph">
+<p>For a 3D image, the image element at location (i, j, k) becomes the color value.
+For a 2D image, the image element at location (i, j) becomes the color value.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="filtering_modelinear-1">5.2.4. filtering_mode::linear</h4>
+<div class="paragraph">
+<p>When filter mode is <code>filtering_mode::linear</code>, a 2 x 2 square of image elements for a 2D image or a 2 x 2 x 2 cube of image elements for a 3D image is selected.
+This 2 x 2 square or 2 x 2 x 2 cube is obtained as follows.</p>
+</div>
+<div class="paragraph">
+<p>Let</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[\begin{array}{l}
+u = (s - floor(s)) * w_t\\
+i0 = (int)floor(u - 0.5)\\
+i1 = i0 + 1\\
+if (i0 &lt; 0)\\
+i0 = w_t + i0\\
+if\ (i1 &gt; w_t - 1)\\
+\qquad i1 = i1 - w_t\\
+v = (t - floor(t)) * h_t\\
+j0 = (int)floor(v - 0.5)\\
+j1 = j0 + 1\\
+if (j0 &lt; 0)\\
+j0 = h_t + j0\\
+if\ (j1 &gt; h_t - 1)\\
+\qquad j1 = j1 - h_t\\
+w = (r - floor(r)) * d_t\\
+k0 = (int)floor(w - 0.5)\\
+k1 = k0 + 1\\
+if (k0 &lt; 0)\\
+\qquad k0 = d_t + k0\\
+if\ (k1 &gt; d_t - 1)\\
+\qquad k1 = k1 - d_t\\
+a = frac(u - 0.5)\\
+b = frac(v - 0.5)\\
+c = frac(w - 0.5)
+\end{array}\]
+</div>
+</div>
+<div class="paragraph">
+<p>where frac(x) denotes the fractional part of x and is computed as x - floor(x).</p>
+</div>
+<div class="paragraph">
+<p>For a 3D image, the image element value is found as</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[\begin{array}{rcl}
+T &amp;=&amp; (1 - a) * (1 - b) * (1 - c) * T_{i0j0k0}\\
+  &amp; &amp; {} + a * (1 - b) * (1 - c) * T_{i1j0k0}\\
+  &amp; &amp; {} + (1 - a) * b * (1 - c) * T_{i0j1k0}\\
+  &amp; &amp; {} + a * b * (1 - c) * T_{i1j1k0}\\
+  &amp; &amp; {} + (1 - a) * (1 - b) * c * T_{i0j0k1}\\
+  &amp; &amp; {} + a * (1 - b) * c * T_{i1j0k1}\\
+  &amp; &amp; {} + (1 - a) * b * c * T_{i0j1k1}\\
+  &amp; &amp; {} + a * b * c * T_{i1j1k1}
+\end{array}\]
+</div>
+</div>
+<div class="paragraph">
+<p>where T<sub>ijk</sub> is the image element at location (i,j,k) in the 3D image.</p>
+</div>
+<div class="paragraph">
+<p>For a 2D image, the image element value is found as</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[\begin{array}{rcl}
+T &amp;=&amp; (1 - a) * (1 - b) * T_{i0j0}\\
+  &amp; &amp; {} + a * (1 - b) * T_{i1j0}\\
+  &amp; &amp; {} + (1 - a) * b * T_{i0j1}\\
+  &amp; &amp; {} + a * b * T_{i1j1}
+\end{array}\]
+</div>
+</div>
+<div class="paragraph">
+<p>where T<sub>ij</sub> is the image element at location (i,j) in the 2D image.</p>
+</div>
+<div class="paragraph">
+<p>If the image channel type is <code>CL_FLOAT</code> or <code>CL_HALF_FLOAT</code> and any of the image elements T<sub>ijk</sub> or T<sub>ij</sub> is INF or NaN, the behavior of the built-in image read function is undefined.</p>
+</div>
+<div class="paragraph">
+<p>We now discuss how the addressing and filter modes are applied to generate the appropriate sample locations to read from the image if the addressing mode is <code>addressing_mode::repeat</code>.
+The <code>addressing_mode::mirrored_repeat</code> addressing mode causes the image to be read as if it is tiled at every integer seam with the interpretation of the image data flipped at each integer crossing.
+For example, the (s,t,r) coordinates between 2 and 3 are addressed into the image as coordinates from 1 down to 0.
+If values in (s,t,r) are INF or NaN, the behavior of the built-in image read functions is undefined.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="filtering_modenearest-2">5.2.5. filtering_mode::nearest</h4>
+<div class="paragraph">
+<p>When filter mode is <code>filtering_mode::nearest</code>, the image element at location (i,j,k) becomes the image element value, with i,j and k computed as</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[\begin{array}{rcl}
+s' &amp;=&amp; 2.0f * rint(0.5f * s)\\
+s' &amp;=&amp; fabs(s - s')\\
+u  &amp;=&amp; s' * w_t\\
+i  &amp;=&amp; (int)floor(u)\\
+i  &amp;=&amp; min(i, w_t - 1)\\
+t' &amp;=&amp; 2.0f * rint(0.5f * t)\\
+t' &amp;=&amp; fabs(t - t')\\
+v  &amp;=&amp; t' * h_t\\
+j  &amp;=&amp; (int)floor(v)\\
+j  &amp;=&amp; min(j, h_t - 1)\\
+r' &amp;=&amp; 2.0f * rint(0.5f * r)\\
+r' &amp;=&amp; fabs(r - r')\\
+w  &amp;=&amp; r' * d_t\\
+k  &amp;=&amp; (int)floor(w)\\
+k  &amp;=&amp; min(k, d_t - 1)
+\end{array}\]
+</div>
+</div>
+<div class="paragraph">
+<p>For a 3D image, the image element at location (i, j, k) becomes the color value.
+For a 2D image, the image element at location (i, j) becomes the color value.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="filtering_modelinear-2">5.2.6. filtering_mode::linear</h4>
+<div class="paragraph">
+<p>When filter mode is <code>filtering_mode::linear</code>, a 2 x 2 square of image elements for a 2D image or a 2 x 2 x 2 cube of image elements for a 3D image is selected.
+This 2 x 2 square or 2 x 2 x 2 cube is obtained as follows.</p>
+</div>
+<div class="paragraph">
+<p>Let</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[\begin{array}{rcl}
+s' &amp;=&amp; 2.0f * rint(0.5f * s)\\
+s' &amp;=&amp; fabs(s - s')\\
+u  &amp;=&amp; s' * w_t\\
+i0 &amp;=&amp; (int)floor(u - 0.5f)\\
+i1 &amp;=&amp; i0 + 1\\
+i0 &amp;=&amp; max(i0, 0)\\
+i1 &amp;=&amp; min(i1, w_t - 1)\\
+t' &amp;=&amp; 2.0f * rint(0.5f * t)\\
+t' &amp;=&amp; fabs(t - t')\\
+v  &amp;=&amp; t' * h_t\\
+j0 &amp;=&amp; (int)floor(v - 0.5f)\\
+j1 &amp;=&amp; j0 + 1\\
+j0 &amp;=&amp; max(j0, 0)\\
+j1 &amp;=&amp; min(j1, h_t - 1)\\
+r' &amp;=&amp; 2.0f * rint(0.5f * r)\\
+r' &amp;=&amp; fabs(r - r')\\
+w  &amp;=&amp; r' * d_t\\
+k0 &amp;=&amp; (int)floor(w - 0.5f)\\
+k1 &amp;=&amp; k0 + 1\\
+k0 &amp;=&amp; max(k0, 0)\\
+k1 &amp;=&amp; min(k1, d_t - 1)\\
+a  &amp;=&amp; frac(u - 0.5)\\
+b  &amp;=&amp; frac(v - 0.5)\\
+c  &amp;=&amp; frac(w - 0.5)
+\end{array}\]
+</div>
+</div>
+<div class="paragraph">
+<p>where frac(x) denotes the fractional part of x and is computed as x - floor(x).</p>
+</div>
+<div class="paragraph">
+<p>For a 3D image, the image element value is found as</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[\begin{array}{rcl}
+T &amp;=&amp; (1 - a) * (1 - b) * (1 - c) * T_{i0j0k0}\\
+  &amp; &amp; {} + a * (1 - b) * (1 - c) * T_{i1j0k0}\\
+  &amp; &amp; {} + (1 - a) * b * (1 - c) * T_{i0j1k0}\\
+  &amp; &amp; {} + a * b * (1 - c) * T_{i1j1k0}\\
+  &amp; &amp; {} + (1 - a) * (1 - b) * c * T_{i0j0k1}\\
+  &amp; &amp; {} + a * (1 - b) * c * T_{i1j0k1}\\
+  &amp; &amp; {} + (1 - a) * b * c * T_{i0j1k1}\\
+  &amp; &amp; {} + a * b * c * T_{i1j1k1}
+\end{array}\]
+</div>
+</div>
+<div class="paragraph">
+<p>where T<sub>ijk</sub> is the image element at location (i,j,k) in the 3D image.</p>
+</div>
+<div class="paragraph">
+<p>For a 2D image, the image element value is found as</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[\begin{array}{rcl}
+T &amp;=&amp; (1 - a) * (1 - b) * T_{i0j0}\\
+  &amp; &amp; {} + a * (1 - b) * T_{i1j0}\\
+  &amp; &amp; {} + (1 - a) * b * T_{i0j1}\\
+  &amp; &amp; {} + a * b * T_{i1j1}
+\end{array}\]
+</div>
+</div>
+<div class="paragraph">
+<p>where T<sub>ij</sub> is the image element at location (i,j) in the 2D image.</p>
+</div>
+<div class="paragraph">
+<p>For a 1D image, the image element value is found as</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[T = (1 - a) * T_i0 + a * T_i1\]
+</div>
+</div>
+<div class="paragraph">
+<p>where T<sub>i</sub> is the image element at location (i) in the 1D image.</p>
+</div>
+<div class="paragraph">
+<p>If the image channel type is <code>CL_FLOAT</code> or <code>CL_HALF_FLOAT</code> and any of the image elements T<sub>ijk</sub> or T<sub>ij</sub> is INF or NaN, the behavior of the built-in image read function is undefined.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-note" title="Note"></i>
+</td>
+<td class="content">
+If the sampler is specified as using unnormalized coordinates (floating-point or integer coordinates), filter mode set to <code>filtering_mode::nearest</code> and addressing mode set to one of the following modes - <code>addressing_mode::none</code>, <code>addressing_mode::clamp_to_edge</code> or <code>addressing_mode::clamp</code>, the location of the image element in the image given by (i, j, k) will be computed without any loss of precision.
+For all other sampler combinations of normalized or unnormalized coordinates, filter and addressing modes, the relative error or precision of the addressing mode calculations and the image filter operation are not defined by this revision of the OpenCL specification.
+To ensure a minimum precision of image addressing and filter calculations across any OpenCL device, for these sampler combinations, developers should unnormalize the image coordinate in the kernel and implement the linear filter in the kernel with appropriate calls to <code>image::read</code> with a sampler that uses unnormalized coordinates, filter mode set to <code>filtering_mode::nearest</code>, addressing mode set to <code>addressing_mode::none</code>, <code>addressing_mode::clamp_to_edge</code> or <code>addressing_mode::clamp</code> and finally performing the interpolation of color values read from the image to generate the filtered color value.
+</td>
+</tr>
+</table>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="conversion-rules">5.3. Conversion Rules</h3>
+<div class="paragraph">
+<p>In this section we discuss conversion rules that are applied when reading and writing images in a kernel.</p>
+</div>
+<div class="sect3">
+<h4 id="conversion-rules-for-normalized-integer-channel-data-types">5.3.1. Conversion rules for normalized integer</h4>
+<div class="paragraph">
+<p>In this section we discuss converting normalized integer channel data types to half-precision and single-precision floating-point values and vice-versa.</p>
+</div>
+<div class="sect4">
+<h5 id="converting-normalized-integer-channel-data-types-to-half-precision-floating-point-values">Converting normalized integer channel data types to half precision floating-point values</h5>
+<div class="paragraph">
+<p>For images created with image channel data type of <code>CL_UNORM_INT8</code> and <code>CL_UNORM_INT16</code>, <code>image::read</code> will convert the channel values from an 8-bit or 16-bit unsigned integer to normalized half precision floating-point values in the range [0.0h &#8230;&#8203; 1.0h].</p>
+</div>
+<div class="paragraph">
+<p>For images created with image channel data type of <code>CL_SNORM_INT8</code> and <code>CL_SNORM_INT16</code>, <code>image::read</code> will convert the channel values from an 8-bit or 16-bit signed integer to normalized half precision floating-point values in the range [-1.0h &#8230;&#8203; 1.0h].</p>
+</div>
+<div class="paragraph">
+<p>These conversions are performed as follows:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>CL_UNORM_INT8</code> (8-bit unsigned integer) &#8594; <code>half</code></p>
+<div class="stemblock">
+<div class="content">
+\[normalized\_half\_value(x)=round\_to\_half(\frac{x}{255})\]
+</div>
+</div>
+</li>
+<li>
+<p><code>CL_UNORM_INT_101010</code> (10-bit unsigned integer) &#8594; <code>half</code></p>
+<div class="stemblock">
+<div class="content">
+\[normalized\_half\_value(x)=round\_to\_half(\frac{x}{1023})\]
+</div>
+</div>
+</li>
+<li>
+<p><code>CL_UNORM_INT16</code> (16-bit unsigned integer) &#8594; <code>half</code></p>
+<div class="stemblock">
+<div class="content">
+\[normalized\_half\_value(x)=round\_to\_half(\frac{x}{65535})\]
+</div>
+</div>
+</li>
+<li>
+<p><code>CL_SNORM_INT8</code> (8-bit signed integer) &#8594; <code>half</code></p>
+<div class="stemblock">
+<div class="content">
+\[normalized\_half\_value(x)=max(-1.0h, round\_to\_half(\frac{x}{127}))\]
+</div>
+</div>
+</li>
+<li>
+<p><code>CL_SNORM_INT16</code> (16-bit signed integer) &#8594; <code>half</code></p>
+<div class="stemblock">
+<div class="content">
+\[normalized\_half\_value(x)=max(-1.0h, round\_to\_half(\frac{x}{32767}))\]
+</div>
+</div>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The precision of the above conversions is &lt;= 1.5 ulp except for the following cases.</p>
+</div>
+<div class="paragraph">
+<p>For <code>CL_UNORM_INT8</code>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>0 must convert to 0.0h and</p>
+</li>
+<li>
+<p>255 must convert to 1.0h</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For <code>CL_UNORM_INT_101010</code>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>0 must convert to 0.0h and</p>
+</li>
+<li>
+<p>1023 must convert to 1.0h</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For <code>CL_UNORM_INT16</code>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>0 must convert to 0.0h and</p>
+</li>
+<li>
+<p>65535 must convert to 1.0h</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For <code>CL_SNORM_INT8</code>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>-128 and -127 must convert to -1.0h,</p>
+</li>
+<li>
+<p>0 must convert to 0.0h and</p>
+</li>
+<li>
+<p>127 must convert to 1.0h</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For <code>CL_SNORM_INT16</code>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>-32768 and -32767 must convert to -1.0h,</p>
+</li>
+<li>
+<p>0 must convert to 0.0h and</p>
+</li>
+<li>
+<p>32767 must convert to 1.0h</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect4">
+<h5 id="converting-half-precision-floating-point-values-to-normalized-integer-channel-data-types">Converting half precision floating-point values to normalized integer channel data types</h5>
+<div class="paragraph">
+<p>For images created with image channel data type of <code>CL_UNORM_INT8</code> and <code>CL_UNORM_INT16</code>, <code>image::write</code> will convert the half precision floating-point color value to an 8-bit or 16-bit unsigned integer.</p>
+</div>
+<div class="paragraph">
+<p>For images created with image channel data type of <code>CL_SNORM_INT8</code> and <code>CL_SNORM_INT16</code>, <code>image::write</code> will convert the half precision floating-point color value to an 8-bit or 16-bit signed integer.</p>
+</div>
+<div class="paragraph">
+<p>OpenCL implementations may choose to approximate the rounding mode used in the conversions described below.
+When approximate rounding is used instead of the preferred rounding, the result of the conversion must satisfy the bound given below.</p>
+</div>
+<div class="paragraph">
+<p>The conversions from half precision floating-point values to normalized integer values are performed is as follows:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>half</code> &#8594; <code>CL_UNORM_INT8</code> (8-bit unsigned integer)</p>
+<div class="stemblock">
+<div class="content">
+\[\begin{aligned}
+f(x)=max(0,min(255,255 \times x))\\
+\\
+f_{preferred}(x) =
+\begin{cases}
+ round\_to\_nearest\_even\_uint8(f(x)) &amp; x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; x = \infty \text{ or } x = NaN
+\end{cases}\\
+f_{approx}(x) =
+\begin{cases}
+ round\_to\_impl\_uint8(f(x)) &amp; x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; x = \infty \text{ or } x = NaN
+\end{cases}\\
+\\
+|f(x) - f_{approx}(x)|\leq 0.6, x \neq \infty \text{ and } x \neq NaN
+\end{aligned}\]
+</div>
+</div>
+</li>
+<li>
+<p><code>half</code> &#8594; <code>CL_UNORM_INT16</code> (16-bit unsigned integer)</p>
+<div class="stemblock">
+<div class="content">
+\[\begin{aligned}
+f(x)=max(0,min(65535,65535 \times x))\\
+\\
+f_{preferred}(x) =
+\begin{cases}
+ round\_to\_nearest\_even\_uint16(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+f_{approx}(x) =
+\begin{cases}
+ round\_to\_impl\_uint16(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+\\
+|f(x) - f_{approx}(x)|\leq 0.6, x \neq \infty \text{ and } x \neq NaN
+\end{aligned}\]
+</div>
+</div>
+</li>
+<li>
+<p><code>half</code> &#8594; <code>CL_SNORM_INT8</code> (8-bit signed integer)</p>
+<div class="stemblock">
+<div class="content">
+\[\begin{aligned}
+f(x)=max(-128,min(127,127 \times x))\\
+\\
+f_{preferred}(x) =
+\begin{cases}
+ round\_to\_nearest\_even\_uint8(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+f_{approx}(x) =
+\begin{cases}
+ round\_to\_impl\_uint8(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+\\
+|f(x) - f_{approx}(x)|\leq 0.6, x \neq \infty \text{ and } x \neq NaN
+\end{aligned}\]
+</div>
+</div>
+</li>
+<li>
+<p><code>half</code> &#8594; <code>CL_SNORM_INT16</code> (16-bit signed integer)</p>
+<div class="stemblock">
+<div class="content">
+\[\begin{aligned}
+f(x)=max(-32768,min(32767,32767 \times x))\\
+\\
+f_{preferred}(x) =
+\begin{cases}
+ round\_to\_nearest\_even\_uint16(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+f_{approx}(x) =
+\begin{cases}
+ round\_to\_impl\_uint16(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+\\
+|f(x) - f_{approx}(x)|\leq 0.6, x \neq \infty \text{ and } x \neq NaN
+\end{aligned}\]
+</div>
+</div>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect4">
+<h5 id="converting-normalized-integer-channel-data-types-to-floating-point-values">Converting normalized integer channel data types to floating-point values</h5>
+<div class="paragraph">
+<p>For images created with image channel data type of <code>CL_UNORM_INT8</code> and <code>CL_UNORM_INT16</code>, <code>image::read</code> will convert the channel values from an 8-bit or 16-bit unsigned integer to normalized floating-point values in the range [0.0f &#8230;&#8203; 1.0f].</p>
+</div>
+<div class="paragraph">
+<p>For images created with image channel data type of <code>CL_SNORM_INT8</code> and <code>CL_SNORM_INT16</code>, <code>image::read</code> will convert the channel values from an 8-bit or 16-bit signed integer to normalized floating-point values in the range [-1.0f &#8230;&#8203; 1.0f].</p>
+</div>
+<div class="paragraph">
+<p>These conversions are performed as follows:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>CL_UNORM_INT8</code> (8-bit unsigned integer) &#8594; <code>float</code></p>
+<div class="stemblock">
+<div class="content">
+\[normalized\_float\_value(x)=round\_to\_float(\frac{x}{255})\]
+</div>
+</div>
+</li>
+<li>
+<p><code>CL_UNORM_INT_101010</code> (10-bit unsigned integer) &#8594; <code>float</code></p>
+<div class="stemblock">
+<div class="content">
+\[normalized\_float\_value(x)=round\_to\_float(\frac{x}{1023})\]
+</div>
+</div>
+</li>
+<li>
+<p><code>CL_UNORM_INT16</code> (16-bit unsigned integer) &#8594; <code>float</code></p>
+<div class="stemblock">
+<div class="content">
+\[normalized\_float\_value(x)=round\_to\_float(\frac{x}{65535})\]
+</div>
+</div>
+</li>
+<li>
+<p><code>CL_SNORM_INT8</code> (8-bit signed integer) &#8594; <code>float</code></p>
+<div class="stemblock">
+<div class="content">
+\[normalized\_float\_value(x)=max(-1.0f, round\_to\_float(\frac{x}{127}))\]
+</div>
+</div>
+</li>
+<li>
+<p><code>CL_SNORM_INT16</code> (16-bit signed integer) &#8594; <code>float</code></p>
+<div class="stemblock">
+<div class="content">
+\[normalized\_float\_value(x)=max(-1.0f, round\_to\_float(\frac{x}{32767}))\]
+</div>
+</div>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The precision of the above conversions is &lt;= 1.5 ulp except for the following cases.</p>
+</div>
+<div class="paragraph">
+<p>For <code>CL_UNORM_INT8</code>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>0 must convert to 0.0f and</p>
+</li>
+<li>
+<p>255 must convert to 1.0f</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For <code>CL_UNORM_INT_101010</code>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>0 must convert to 0.0f and</p>
+</li>
+<li>
+<p>1023 must convert to 1.0f</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For <code>CL_UNORM_INT16</code>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>0 must convert to 0.0f and</p>
+</li>
+<li>
+<p>65535 must convert to 1.0f</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For <code>CL_SNORM_INT8</code>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>-128 and -127 must convert to -1.0f,</p>
+</li>
+<li>
+<p>0 must convert to 0.0f and</p>
+</li>
+<li>
+<p>127 must convert to 1.0f</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For <code>CL_SNORM_INT16</code>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>-32768 and -32767 must convert to -1.0f,</p>
+</li>
+<li>
+<p>0 must convert to 0.0f and</p>
+</li>
+<li>
+<p>32767 must convert to 1.0f</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect4">
+<h5 id="converting-floating-point-values-to-normalized-integer-channel-data-types">Converting floating-point values to normalized integer channel data types</h5>
+<div class="paragraph">
+<p>For images created with image channel data type of <code>CL_UNORM_INT8</code> and <code>CL_UNORM_INT16</code>, <code>image::write</code> will convert the floating-point color value to an 8-bit or 16-bit unsigned integer.</p>
+</div>
+<div class="paragraph">
+<p>For images created with image channel data type of <code>CL_SNORM_INT8</code> and <code>CL_SNORM_INT16</code>, <code>image::write</code> will convert the floating-point color value to an 8-bit or 16-bit signed integer.</p>
+</div>
+<div class="paragraph">
+<p>OpenCL implementations may choose to approximate the rounding mode used in the conversions described below.
+When approximate rounding is used instead of the preferred rounding, the result of the conversion must satisfy the bound given below.</p>
+</div>
+<div class="paragraph">
+<p>The conversions from half precision floating-point values to normalized integer values are performed is as follows:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>float</code> &#8594; <code>CL_UNORM_INT8</code> (8-bit unsigned integer)</p>
+<div class="stemblock">
+<div class="content">
+\[\begin{aligned}
+f(x)=max(0,min(255,255 \times x))\\
+\\
+f_{preferred}(x) =
+\begin{cases}
+ round\_to\_nearest\_even\_uint8(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+f_{approx}(x) =
+\begin{cases}
+ round\_to\_impl\_uint8(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+\\
+|f(x) - f_{approx}(x)|\leq 0.6, x \neq \infty \text{ and } x \neq NaN
+\end{aligned}\]
+</div>
+</div>
+</li>
+<li>
+<p><code>float</code> &#8594; <code>CL_UNORM_INT_101010</code> (10-bit unsigned integer)</p>
+<div class="stemblock">
+<div class="content">
+\[\begin{aligned}
+f(x)=max(0,min(1023,1023 \times x))\\
+\\
+f_{preferred}(x) =
+\begin{cases}
+ round\_to\_nearest\_even\_uint10(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+f_{approx}(x) =
+\begin{cases}
+ round\_to\_impl\_uint10(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+\\
+|f(x) - f_{approx}(x)|\leq 0.6, x \neq \infty \text{ and } x \neq NaN
+\end{aligned}\]
+</div>
+</div>
+</li>
+<li>
+<p><code>float</code> &#8594; <code>CL_UNORM_INT16</code> (16-bit unsigned integer)</p>
+<div class="stemblock">
+<div class="content">
+\[\begin{aligned}
+f(x)=max(0,min(65535,65535 \times x))\\
+\\
+f_{preferred}(x) =
+\begin{cases}
+ round\_to\_nearest\_even\_uint16(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+f_{approx}(x) =
+\begin{cases}
+ round\_to\_impl\_uint16(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+\\
+|f(x) - f_{approx}(x)|\leq 0.6, x \neq \infty \text{ and } x \neq NaN
+\end{aligned}\]
+</div>
+</div>
+</li>
+<li>
+<p><code>float</code> &#8594; <code>CL_SNORM_INT8</code> (8-bit signed integer)</p>
+<div class="stemblock">
+<div class="content">
+\[\begin{aligned}
+f(x)=max(-128,min(127,127 \times x))\\
+\\
+f_{preferred}(x) =
+\begin{cases}
+ round\_to\_nearest\_even\_uint8(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+f_{approx}(x) =
+\begin{cases}
+ round\_to\_impl\_uint8(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+\\
+|f(x) - f_{approx}(x)|\leq 0.6, x \neq \infty \text{ and } x \neq NaN
+\end{aligned}\]
+</div>
+</div>
+</li>
+<li>
+<p><code>float</code> &#8594; <code>CL_SNORM_INT16</code> (16-bit signed integer)</p>
+<div class="stemblock">
+<div class="content">
+\[\begin{aligned}
+f(x)=max(-32768,min(32767,32767 \times x))\\
+\\
+f_{preferred}(x) =
+\begin{cases}
+ round\_to\_nearest\_even\_uint16(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+f_{approx}(x) =
+\begin{cases}
+ round\_to\_impl\_uint16(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+\\
+|f(x) - f_{approx}(x)|\leq 0.6, x \neq \infty \text{ and } x \neq NaN
+\end{aligned}\]
+</div>
+</div>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="conversion-rules-for-half-precision-floating-point-channel-data-type">5.3.2. Conversion rules for half precision floating-point channel data type</h4>
+<div class="paragraph">
+<p>For images created with a channel data type of <code>CL_HALF_FLOAT</code>, the conversions of half to float and half to half are lossless (as described in the <a href="#builtin-half-data-type"><em>Built-in Half Data Type</em></a> section).
+Conversions from float to half round the mantissa using the round to nearest even or round to zero rounding mode.
+Denormalized numbers for the half data type which may be generated when converting a float to a half  may be flushed to zero.
+A float NaN must be converted to an appropriate NaN in the half type.
+A float INF must be converted to an appropriate INF in the half type.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="conversion-rules-for-floating-point-channel-data-type">5.3.3. Conversion rules for floating-point channel data type</h4>
+<div class="paragraph">
+<p>The following rules apply for reading and writing images created with channel data type of <code>CL_FLOAT</code>.</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>NaNs may be converted to a NaN value(s) supported by the device.</p>
+</li>
+<li>
+<p>Denorms can be flushed to zero.</p>
+</li>
+<li>
+<p>All other values must be preserved.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="conversion-rules-for-signed-and-unsigned-8-bit-16-bit-and-32-bit-integer-channel-data-types">5.3.4. Conversion rules for signed and unsigned 8-bit, 16-bit and 32-bit integer channel data types</h4>
+<div class="paragraph">
+<p>Calls to <code>image::read</code> with channel data type values of <code>CL_SIGNED_INT8</code>, <code>CL_SIGNED_INT16</code> and <code>CL_SIGNED_INT32</code> return the unmodified integer values stored in the image at specified location.</p>
+</div>
+<div class="paragraph">
+<p>Calls to <code>image::read</code> with channel data type values of <code>CL_UNSIGNED_INT8</code>, <code>CL_UNSIGNED_INT16</code> and <code>CL_UNSIGNED_INT32</code> return the unmodified integer values stored in the image at specified location.</p>
+</div>
+<div class="paragraph">
+<p>Calls to <code>image::write</code> will perform one of the following conversions:</p>
+</div>
+<div class="paragraph">
+<p>32 bit signed integer &#8594; 8-bit signed integer</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>convert_cast&lt;char,saturate::on&gt;(i)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>32 bit signed integer &#8594; 16-bit signed integer</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>convert_cast&lt;short,saturate::on&gt;(i)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>32 bit signed integer &#8594; 32-bit signed integer</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>no conversion is performed</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Calls to image::write will perform one of the following conversions:</p>
+</div>
+<div class="paragraph">
+<p>32 bit unsigned integer &#8594; 8-bit unsigned integer</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>convert_cast&lt;uchar,saturate::on&gt;(i)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>32 bit unsigned integer &#8594; 16-bit unsigned integer</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>convert_cast&lt;ushort,saturate::on&gt;(i)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>32 bit unsigned integer &#8594; 32-bit unsigned integer</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>no conversion is performed</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The conversions described in this section must be correctly saturated.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="conversion-rules-for-srgba-and-sbgra-images">5.3.5. Conversion rules for sRGBA and sBGRA images</h4>
+<div class="paragraph">
+<p>Standard RGB data, which roughly displays colors in a linear ramp of luminosity levels such that an average observer, under average viewing conditions, can view them as perceptually equal steps on an average display.
+All 0&#8217;s maps to 0.0f, and all 1&#8217;s maps to 1.0f.
+The sequence of unsigned integer encodings between all 0&#8217;s and all 1&#8217;s represent a nonlinear progression in the floating-point interpretation of the numbers between 0.0f to 1.0f.
+For more detail, see the <a href="#sRGB-spec">SRGB color standard</a>.</p>
+</div>
+<div class="paragraph">
+<p>Conversion from sRGB space is automatically done by image::read built-in functions if the image channel order is one of the sRGB values described above.
+When reading from an sRGB image, the conversion from sRGB to linear RGB is performed before the filter specified in the sampler specified to image::sample is applied.
+If the format has an alpha channel, the alpha data is stored in linear color space.
+Conversion to sRGB space is automatically done by image::write built-in functions if the image channel order is one of the sRGB values described above and the device supports writing to sRGB images.</p>
+</div>
+<div class="paragraph">
+<p>If the format has an alpha channel, the alpha data is stored in linear color space.</p>
+</div>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>The following process is used by image::read and image::sample to convert a normalized 8-bit unsigned integer sRGB color value x to a floating-point linear RGB color value y:</p>
+<div class="olist loweralpha">
+<ol class="loweralpha" type="a">
+<li>
+<p>Convert a normalized 8-bit unsigned integer sRGB value x to a floating-point sRGB value r as per rules described in the <a href="#converting-floating-point-values-to-normalized-integer-channel-data-types"><em>Converting floating-point values to normalized integer channel data types</em></a> section.</p>
+<div class="stemblock">
+<div class="content">
+\[r=normalized\_float\_value(x)\]
+</div>
+</div>
+</li>
+<li>
+<p>Convert a floating-point sRGB value r to a floating-point linear RGB color value y:</p>
+<div class="stemblock">
+<div class="content">
+\[\begin{aligned}
+c_{linear}(x) =
+\begin{cases}
+ \frac{r}{12.92} &amp; \quad r \geq 0 \text{ and } r \leq 0.04045\\[1em]
+ (\frac{r + 0.055}{1.055})^{2.4} &amp; \quad r &gt; 0.04045 \text{ and } \leq 1
+\end{cases}\\
+\\
+y = c_{linear}(r)
+\end{aligned}\]
+</div>
+</div>
+</li>
+</ol>
+</div>
+</li>
+<li>
+<p>The following process is used by <code>image::write</code> to convert a linear RGB floating-point color value y to a normalized 8-bit unsigned integer sRGB value x:</p>
+<div class="olist loweralpha">
+<ol class="loweralpha" type="a">
+<li>
+<p>Convert a floating-point linear RGB value y to a normalized floating point sRGB value r:</p>
+<div class="stemblock">
+<div class="content">
+\[\begin{aligned}
+c_{linear}(x) =
+\begin{cases}
+ 0 &amp; \quad y \geq NaN \text{ or } y &lt; 0\\
+ 12.92 \times y &amp; \quad y \geq 0 \text{ and } y &lt; 0.0031308\\
+ 1.055 \times y^{(\frac{1}{2.4})} &amp; \quad y \geq 0.0031308 \text{ and } y \leq 1\\
+ 1 &amp; \quad y &gt; 1
+\end{cases}\\
+\\
+r = c_{sRGB}(y)
+\end{aligned}\]
+</div>
+</div>
+</li>
+<li>
+<p>Convert a normalized floating-point sRGB value r to a normalized 8-bit unsigned integer sRGB value x as per rules described in <a href="#converting-normalized-integer-channel-data-types-to-half-precision-floating-point-values">Converting normalized integer channel data types to half precision floating-point values</a> section.</p>
+<div class="stemblock">
+<div class="content">
+\[\begin{aligned}
+g(r) =
+\begin{cases}
+ f_{preferred}(r) &amp; \quad \text{if rounding mode is round to even}\\
+ f_{approx}(r) &amp; \quad \text{if implementation-defined rounding mode}
+\end{cases}\\
+\\
+x = g(r)
+\end{aligned}\]
+</div>
+</div>
+</li>
+</ol>
+</div>
+</li>
+</ol>
+</div>
+<div class="paragraph">
+<p>The accuracy required of using <code>image::read</code> and <code>image::sample</code> to convert a normalized 8-bit unsigned integer sRGB color value x to a floating-point linear RGB color value y is given by:</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[|x-255 \times c_{sRGB}(y)|\leq 0.5\]
+</div>
+</div>
+<div class="paragraph">
+<p>The accuracy required of using <code>image::write</code> to convert a linear RGB floating-point color value y to a normalized 8-bit unsigned integer sRGB value x is given by:</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[|x-255 \times c_{sRGB}(y)|\leq 0.6\]
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="selecting-an-image-from-an-image-array">5.4. Selecting an Image from an Image Array</h3>
+<div class="paragraph">
+<p>Let (u,v,w)  represent the unnormalized image coordinate values for reading from and/or writing to a 2D image in a 2D image array.</p>
+</div>
+<div class="paragraph">
+<p>When read using a sampler, the 2D image layer selected is computed as:</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[layer = clamp(rint(w), 0, d_t - 1)\]
+</div>
+</div>
+<div class="paragraph">
+<p>otherwise the layer selected is computed as:</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[layer = w\]
+</div>
+</div>
+<div class="paragraph">
+<p>(since w is already an integer) and the result is undefined if w is not one of the integers 0, 1, &#8230;&#8203; d<sub>t</sub> - 1.</p>
+</div>
+<div class="paragraph">
+<p>Let (u,v)  represent the unnormalized image coordinate values for reading from and/or writing to a 1D image in a 1D image array.</p>
+</div>
+<div class="paragraph">
+<p>When read using a sampler, the 1D image layer selected is computed as:</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[layer = clamp(rint(v), 0, h_t - 1)\]
+</div>
+</div>
+<div class="paragraph">
+<p>otherwise the layer selected is computed as:</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[layer = v\]
+</div>
+</div>
+<div class="paragraph">
+<p>(since v is already an integer) and the result is undefined if v is not one of the integers 0, 1, &#8230;&#8203; h<sub>t</sub> - 1.</p>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="compiler_options">6. Compiler options</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>The compiler options are categorized as preprocessor options, options for controlling the OpenCL C++ version, options that control FP16 and FP64 support.
+This specification defines a standard set of options that must be supported by the compiler when building program executables online or offline from OpenCL C++ to an IL.
+These may be extended by a set of vendor or platform specific options.</p>
+</div>
+<div class="sect2">
+<h3 id="preprocessor_options">6.1. Preprocessor options</h3>
+<div class="paragraph">
+<p>These options control the OpenCL C++ preprocessor which is run on each program source before actual compilation.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>-D name</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Predefine name as a macro, with definition 1.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>-D name=definition</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The contents of definition are tokenized and processed as if they appeared during translation phase three in a <code>#define</code> directive.
+In particular, the definition will be truncated by embedded newline characters.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="options-controlling_the-opencl_c_version">6.2. Options Controlling the OpenCL C++ version</h3>
+<div class="paragraph">
+<p>The following option controls the version of OpenCL C++ that the compiler accepts.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>-cl-std=</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Determine the OpenCL C++ language version to use.
+A value for this option must be provided.
+Valid values are:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>c++ - Support all OpenCL C++ programs that use the OpenCL C++ language features defined in the <a href="#openclcpp-programming-language"><em>OpenCL C++ Programming Language</em></a> section.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect2">
+<h3 id="fp16_and_fp64_options">6.3. Double and half-precision floating-point options</h3>
+<div class="paragraph">
+<p>The following option controls the double and half floating-point support that the compiler accepts.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>-cl-fp16-enable</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>This option enables full half data type support.
+The option defines <code>cl_khr_fp16</code> macro.
+The default is disabled.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>-cl-fp64-enable</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>This option enables double data type support.
+The option defines <code>cl_khr_fp64</code> macro.
+The default is disabled.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="other_options">6.4. Other options</h3>
+<div class="listingblock">
+<div class="content">
+<pre>-cl-zero-init-local-mem-vars</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>This option enables software zero-initialization of variables allocated in local memory.</p>
+</div>
+<div style="page-break-after: always;"></div>
+<hr>
+<div id="ftn2" class="paragraph">
+<p><a href="#ftnref2">[2]</a> The <code>double</code> data type is an optional type that is supported if <code>CL_DEVICE_DOUBLE_FP_CONFIG</code> in table 4.3 for a device is not zero.</p>
+</div>
+<div id="ftn3" class="paragraph">
+<p><a href="#ftnref3">[3]</a> The question mark ? in numerical selector refers to special undefined component of vector; reading from it results in undefined value, writing to it is discarded.</p>
+</div>
+<div id="ftn4" class="paragraph">
+<p><a href="#ftnref4">[4]</a> Only if the <strong>cl_khr_fp16</strong> extension is enabled and has been supported</p>
+</div>
+<div id="ftn5" class="paragraph">
+<p><a href="#ftnref5">[5]</a> For conversions to floating-point format, when a finite source value exceeds the maximum representable finite floating-point destination value, the rounding mode will affect whether the result is the maximum finite floating-point value or infinity of same sign as the source value, per IEEE-754 rules for rounding.</p>
+</div>
+<div id="ftn6" class="paragraph">
+<p><a href="#ftnref6">[6]</a> The <code>as_type&lt;T&gt;</code> function is intended to reflect the organization of data in register.
+The <code>as_type&lt;T&gt;</code> construct is intended to compile to no instructions on devices that use a shared register file designed to operate on both the operand and result types.
+Note that while differences in memory organization are expected to largely be limited to those arising from endianness, the register based representation may also differ due to size of the element in register.
+(For example, an architecture may load a char into a 32-bit register, or a char vector into a SIMD vector register with fixed 32-bit element size.)
+If the element count does not match, then the implementation should pick a data representation that most closely matches what would happen if an appropriate result type operator was applied to a register containing data of the source type.
+So, for example if an implementation stores all single precision data as double in register, it should implement <code>as_type&lt;int&gt;(float)</code> by first downconverting the double to single precision and then (if necessary) moving the single precision bits to a register suitable for operating on integer data.
+If data stored in different address spaces do not have the same endianness, then the "dominant endianness" of the device should prevail.</p>
+</div>
+<div id="ftn7" class="paragraph">
+<p><a href="#ftnref7">[7]</a> <code>memory_order_consume</code> is not supported in OpenCL C++</p>
+</div>
+<div id="ftn8" class="paragraph">
+<p><a href="#ftnref8">[8]</a> This value for <code>memory_scope</code> can only be used with <code>atomic_fence</code> with flags set to <code>mem_fence::image</code>.</p>
+</div>
+<div id="ftn9" class="paragraph">
+<p><a href="#ftnref9">[9]</a> We can&#8217;t require C++14 atomics since host programs can be implemented in other programming languages and versions of C or C++, but we do require that the host programs use atomics and that those atomics be compatible with those in C++14.</p>
+</div>
+<div id="ftn10" class="paragraph">
+<p><a href="#ftnref10">[10]</a> The <code>atomic_long</code> and <code>atomic_ulong</code> types are supported if the <strong>cl_khr_int64_base_atomics</strong> and <strong>cl_khr_int64_extended_atomics</strong> extensions are supported and have been enabled.</p>
+</div>
+<div id="ftn11" class="paragraph">
+<p><a href="#ftnref11">[11]</a> The <code>atomic_double</code> type is only supported if double precision is supported and the <strong>cl_khr_int64_base_atomics</strong> and <strong>cl_khr_int64_extended_atomics</strong> extensions are supported and have been enabled.</p>
+</div>
+<div id="ftn12" class="paragraph">
+<p><a href="#ftnref12">[12]</a> If the device address space is 64-bits, the data types <code>atomic_intptr_t</code>, <code>atomic_uintptr_t</code>, <code>atomic_size_t</code> and <code>atomic_ptrdiff_t</code> are supported only if the <strong>cl_khr_int64_base_atomics</strong> and <strong>cl_khr_int64_extended_atomics</strong> extensions are supported and have been enabled.</p>
+</div>
+<div id="ftn13" class="paragraph">
+<p><a href="#ftnref13">[13]</a> The <code>*_ms</code> types are supported only if the *cl_khr_gl_msaa_sharing* and <strong>cl_khr_gl_depth_images</strong> extensions are supported and have been enabled.</p>
+</div>
+<div id="ftn14" class="paragraph">
+<p><a href="#ftnref14">[14]</a> Immediate meaning not side effects resulting from child kernels. The side effects would include stores to global memory and pipe reads and writes.</p>
+</div>
+<div id="ftn15" class="paragraph">
+<p><a href="#ftnref15">[15]</a> This acts as a memory synchronization point between work-items in a work-group and child kernels enqueued by work-items in the work-group.</p>
+</div>
+<div id="ftn17" class="paragraph">
+<p><a href="#ftnref17">[17]</a> i.e. the <code>global_work_size</code> values specified to <code>clEnqueueNDRangeKernel</code> are not evenly divisible by the <code>local_work_size</code> values for each dimension.</p>
+</div>
+<div id="ftn18" class="paragraph">
+<p><a href="#ftnref18">[18]</a> Only if double precision is supported and has been enabled.</p>
+</div>
+<div id="ftn19" class="paragraph">
+<p><a href="#ftnref19">[19]</a> Refer to the <a href="#order-and-scope"><em>Memory order and scope</em></a> section for description of <code>memory_scope</code>.</p>
+</div>
+<div id="ftn20" class="paragraph">
+<p><a href="#ftnref20">[20]</a> The <code>min()</code> operator is there to prevent <code>fract(-small)</code> from returning 1.0.
+It returns the largest positive floating-point number less than 1.0.</p>
+</div>
+<div id="ftn21" class="paragraph">
+<p><a href="#ftnref21">[21]</a> fmin and fmax behave as defined by C++14 and may not match the IEEE 754-2008 definition for minNum and maxNum with regard to signaling NaNs.
+Specifically, signaling NaNs may behave as quiet NaNs.</p>
+</div>
+<div id="ftn22" class="paragraph">
+<p><a href="#ftnref22">[22]</a> The user is cautioned that for some usages, e.g. <code>mad(a, b, -a*b)</code>, the definition of <code>mad()</code> in the embedded profile is loose enough that almost any result is allowed from <code>mad()</code> for some values of <code>a</code> and <code>b</code>.</p>
+</div>
+<div id="ftn23" class="paragraph">
+<p><a href="#ftnref23">[23]</a> Frequently vector operations need n + 1 bits temporarily to calculate a result.
+The rhadd instruction gives you an extra bit without needing to upsample and downsample. This can be a profound performance win.</p>
+</div>
+<div id="ftn24" class="paragraph">
+<p><a href="#ftnref24">[24]</a> The primary purpose of the printf function is to help in debugging OpenCL kernels.</p>
+</div>
+<div id="ftn25" class="paragraph">
+<p><a href="#ftnref25">[25]</a> Note that <em>0</em> is taken as a flag, not as the beginning of a field width.</p>
+</div>
+<div id="ftn26" class="paragraph">
+<p><a href="#ftnref26">[26]</a> The results of all floating conversions of a negative zero, and of negative values that round to zero, include a minus sign.</p>
+</div>
+<div id="ftn27" class="paragraph">
+<p><a href="#ftnref27">[27]</a> When applied to infinite and NaN values, the -, +, and space flag characters have their usual meaning; the # and <em>0</em> flag characters have no effect.</p>
+</div>
+<div id="ftn28" class="paragraph">
+<p><a href="#ftnref28">[28]</a> Binary implementations can choose the hexadecimal digit to the left of the decimal-point character so that subsequent digits align to nibble (4-bit) boundaries.</p>
+</div>
+<div id="ftn29" class="paragraph">
+<p><a href="#ftnref29">[29]</a> No special provisions are made for multibyte characters.
+The behavior of printf with the <em>s</em> conversion specifier is undefined if the argument value is not a pointer to a literal string.</p>
+</div>
+<div id="ftn30" class="paragraph">
+<p><a href="#ftnref30">[30]</a> Except for the embedded profile whether either round to zero or round to nearest rounding mode may be supported for single precision floating-point.</p>
+</div>
+<div id="ftn31" class="paragraph">
+<p><a href="#ftnref31">[31]</a> The ULP values for built-in math functions <code>lgamma</code> and <code>lgamma_r</code> is currently undefined.</p>
+</div>
+<div id="ftn32" class="paragraph">
+<p><a href="#ftnref32">[32]</a> 0 ulp is used for math functions that do not require rounding.</p>
+</div>
+<div id="ftn33" class="paragraph">
+<p><a href="#ftnref33">[33]</a> On some implementations, <code>powr()</code> or <code>pown()</code> may perform faster than <code>pow()</code>.
+If <code>x</code> is known to be <code>&gt;= 0</code>, consider using <code>powr()</code> in place of <code>pow()</code>, or if <code>y</code> is known to be an integer, consider using <code>pown()</code> in place of <code>pow()</code>.</p>
+</div>
+<div id="ftn35" class="paragraph">
+<p><a href="#ftnref35">[35]</a> Here <code>TYPE_MIN</code> and <code>TYPE_MIN_EXP</code> should be substituted by constants appropriate to the floating-point type under consideration, such as <code>FLT_MIN</code> and <code>FLT_MIN_EXP</code> for float.</p>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div id="footer">
+<div id="footer-text">
+Version 2.2-7<br>
+Last updated 2018-05-07 12:41:34 BST
+</div>
+</div>
+
+
+</body>
+</html>
\ No newline at end of file
diff --git a/specs/2.2/html/OpenCL_Env.html b/specs/2.2/html/OpenCL_Env.html
new file mode 100644
index 0000000..b610b8e
--- /dev/null
+++ b/specs/2.2/html/OpenCL_Env.html
@@ -0,0 +1,6566 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<meta name="generator" content="Asciidoctor 1.5.6.1">
+<meta name="author" content="Khronos OpenCL Working Group">
+<title>The OpenCL&#8482; SPIR-V Environment Specification</title>
+<style>
+/*! normalize.css v2.1.2 | MIT License | git.io/normalize */
+/* ========================================================================== HTML5 display definitions ========================================================================== */
+/** Correct `block` display not defined in IE 8/9. */
+article, aside, details, figcaption, figure, footer, header, hgroup, main, nav, section, summary { display: block; }
+
+/** Correct `inline-block` display not defined in IE 8/9. */
+audio, canvas, video { display: inline-block; }
+
+/** Prevent modern browsers from displaying `audio` without controls. Remove excess height in iOS 5 devices. */
+audio:not([controls]) { display: none; height: 0; }
+
+/** Address `[hidden]` styling not present in IE 8/9. Hide the `template` element in IE, Safari, and Firefox < 22. */
+[hidden], template { display: none; }
+
+script { display: none !important; }
+
+/* ========================================================================== Base ========================================================================== */
+/** 1. Set default font family to sans-serif. 2. Prevent iOS text size adjust after orientation change, without disabling user zoom. */
+html { font-family: sans-serif; /* 1 */ -ms-text-size-adjust: 100%; /* 2 */ -webkit-text-size-adjust: 100%; /* 2 */ }
+
+/** Remove default margin. */
+body { margin: 0; }
+
+/* ========================================================================== Links ========================================================================== */
+/** Remove the gray background color from active links in IE 10. */
+a { background: transparent; }
+
+/** Address `outline` inconsistency between Chrome and other browsers. */
+a:focus { outline: thin dotted; }
+
+/** Improve readability when focused and also mouse hovered in all browsers. */
+a:active, a:hover { outline: 0; }
+
+/* ========================================================================== Typography ========================================================================== */
+/** Address variable `h1` font-size and margin within `section` and `article` contexts in Firefox 4+, Safari 5, and Chrome. */
+h1 { font-size: 2em; margin: 0.67em 0; }
+
+/** Address styling not present in IE 8/9, Safari 5, and Chrome. */
+abbr[title] { border-bottom: 1px dotted; }
+
+/** Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome. */
+b, strong { font-weight: bold; }
+
+/** Address styling not present in Safari 5 and Chrome. */
+dfn { font-style: italic; }
+
+/** Address differences between Firefox and other browsers. */
+hr { -moz-box-sizing: content-box; box-sizing: content-box; height: 0; }
+
+/** Address styling not present in IE 8/9. */
+mark { background: #ff0; color: #000; }
+
+/** Correct font family set oddly in Safari 5 and Chrome. */
+code, kbd, pre, samp { font-family: monospace, serif; font-size: 1em; }
+
+/** Improve readability of pre-formatted text in all browsers. */
+pre { white-space: pre-wrap; }
+
+/** Set consistent quote types. */
+q { quotes: "\201C" "\201D" "\2018" "\2019"; }
+
+/** Address inconsistent and variable font size in all browsers. */
+small { font-size: 80%; }
+
+/** Prevent `sub` and `sup` affecting `line-height` in all browsers. */
+sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }
+
+sup { top: -0.5em; }
+
+sub { bottom: -0.25em; }
+
+/* ========================================================================== Embedded content ========================================================================== */
+/** Remove border when inside `a` element in IE 8/9. */
+img { border: 0; }
+
+/** Correct overflow displayed oddly in IE 9. */
+svg:not(:root) { overflow: hidden; }
+
+/* ========================================================================== Figures ========================================================================== */
+/** Address margin not present in IE 8/9 and Safari 5. */
+figure { margin: 0; }
+
+/* ========================================================================== Forms ========================================================================== */
+/** Define consistent border, margin, and padding. */
+fieldset { border: 1px solid #c0c0c0; margin: 0 2px; padding: 0.35em 0.625em 0.75em; }
+
+/** 1. Correct `color` not being inherited in IE 8/9. 2. Remove padding so people aren't caught out if they zero out fieldsets. */
+legend { border: 0; /* 1 */ padding: 0; /* 2 */ }
+
+/** 1. Correct font family not being inherited in all browsers. 2. Correct font size not being inherited in all browsers. 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome. */
+button, input, select, textarea { font-family: inherit; /* 1 */ font-size: 100%; /* 2 */ margin: 0; /* 3 */ }
+
+/** Address Firefox 4+ setting `line-height` on `input` using `!important` in the UA stylesheet. */
+button, input { line-height: normal; }
+
+/** Address inconsistent `text-transform` inheritance for `button` and `select`. All other form control elements do not inherit `text-transform` values. Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+. Correct `select` style inheritance in Firefox 4+ and Opera. */
+button, select { text-transform: none; }
+
+/** 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` and `video` controls. 2. Correct inability to style clickable `input` types in iOS. 3. Improve usability and consistency of cursor style between image-type `input` and others. */
+button, html input[type="button"], input[type="reset"], input[type="submit"] { -webkit-appearance: button; /* 2 */ cursor: pointer; /* 3 */ }
+
+/** Re-set default cursor for disabled elements. */
+button[disabled], html input[disabled] { cursor: default; }
+
+/** 1. Address box sizing set to `content-box` in IE 8/9. 2. Remove excess padding in IE 8/9. */
+input[type="checkbox"], input[type="radio"] { box-sizing: border-box; /* 1 */ padding: 0; /* 2 */ }
+
+/** 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome (include `-moz` to future-proof). */
+input[type="search"] { -webkit-appearance: textfield; /* 1 */ -moz-box-sizing: content-box; -webkit-box-sizing: content-box; /* 2 */ box-sizing: content-box; }
+
+/** Remove inner padding and search cancel button in Safari 5 and Chrome on OS X. */
+input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; }
+
+/** Remove inner padding and border in Firefox 4+. */
+button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; }
+
+/** 1. Remove default vertical scrollbar in IE 8/9. 2. Improve readability and alignment in all browsers. */
+textarea { overflow: auto; /* 1 */ vertical-align: top; /* 2 */ }
+
+/* ========================================================================== Tables ========================================================================== */
+/** Remove most spacing between table cells. */
+table { border-collapse: collapse; border-spacing: 0; }
+
+meta.foundation-mq-small { font-family: "only screen and (min-width: 768px)"; width: 768px; }
+
+meta.foundation-mq-medium { font-family: "only screen and (min-width:1280px)"; width: 1280px; }
+
+meta.foundation-mq-large { font-family: "only screen and (min-width:1440px)"; width: 1440px; }
+
+*, *:before, *:after { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; }
+
+html, body { font-size: 100%; }
+
+body { background: white; color: #222222; padding: 0; margin: 0; font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; font-weight: normal; font-style: normal; line-height: 1; position: relative; cursor: auto; }
+
+a:hover { cursor: pointer; }
+
+img, object, embed { max-width: 100%; height: auto; }
+
+object, embed { height: 100%; }
+
+img { -ms-interpolation-mode: bicubic; }
+
+#map_canvas img, #map_canvas embed, #map_canvas object, .map_canvas img, .map_canvas embed, .map_canvas object { max-width: none !important; }
+
+.left { float: left !important; }
+
+.right { float: right !important; }
+
+.text-left { text-align: left !important; }
+
+.text-right { text-align: right !important; }
+
+.text-center { text-align: center !important; }
+
+.text-justify { text-align: justify !important; }
+
+.hide { display: none; }
+
+.antialiased { -webkit-font-smoothing: antialiased; }
+
+img { display: inline-block; vertical-align: middle; }
+
+textarea { height: auto; min-height: 50px; }
+
+select { width: 100%; }
+
+object, svg { display: inline-block; vertical-align: middle; }
+
+.center { margin-left: auto; margin-right: auto; }
+
+.spread { width: 100%; }
+
+p.lead, .paragraph.lead > p, #preamble > .sectionbody > .paragraph:first-of-type p { font-size: 1.21875em; line-height: 1.6; }
+
+.subheader, .admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { line-height: 1.4; color: black; font-weight: 300; margin-top: 0.2em; margin-bottom: 0.5em; }
+
+/* Typography resets */
+div, dl, dt, dd, ul, ol, li, h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6, pre, form, p, blockquote, th, td { margin: 0; padding: 0; direction: ltr; }
+
+/* Default Link Styles */
+a { color: #0068b0; text-decoration: none; line-height: inherit; }
+a:hover, a:focus { color: #333333; }
+a img { border: none; }
+
+/* Default paragraph styles */
+p { font-family: Noto, sans-serif; font-weight: normal; font-size: 1em; line-height: 1.6; margin-bottom: 0.75em; text-rendering: optimizeLegibility; }
+p aside { font-size: 0.875em; line-height: 1.35; font-style: italic; }
+
+/* Default header styles */
+h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { font-family: Noto, sans-serif; font-weight: normal; font-style: normal; color: black; text-rendering: optimizeLegibility; margin-top: 0.5em; margin-bottom: 0.5em; line-height: 1.2125em; }
+h1 small, h2 small, h3 small, #toctitle small, .sidebarblock > .content > .title small, h4 small, h5 small, h6 small { font-size: 60%; color: #4d4d4d; line-height: 0; }
+
+h1 { font-size: 2.125em; }
+
+h2 { font-size: 1.6875em; }
+
+h3, #toctitle, .sidebarblock > .content > .title { font-size: 1.375em; }
+
+h4 { font-size: 1.125em; }
+
+h5 { font-size: 1.125em; }
+
+h6 { font-size: 1em; }
+
+hr { border: solid #dddddd; border-width: 1px 0 0; clear: both; margin: 1.25em 0 1.1875em; height: 0; }
+
+/* Helpful Typography Defaults */
+em, i { font-style: italic; line-height: inherit; }
+
+strong, b { font-weight: bold; line-height: inherit; }
+
+small { font-size: 60%; line-height: inherit; }
+
+code { font-family: Consolas, "Liberation Mono", Courier, monospace; font-weight: normal; color: #264357; }
+
+/* Lists */
+ul, ol, dl { font-size: 1em; line-height: 1.6; margin-bottom: 0.75em; list-style-position: outside; font-family: Noto, sans-serif; }
+
+ul, ol { margin-left: 1.5em; }
+ul.no-bullet, ol.no-bullet { margin-left: 1.5em; }
+
+/* Unordered Lists */
+ul li ul, ul li ol { margin-left: 1.25em; margin-bottom: 0; font-size: 1em; /* Override nested font-size change */ }
+ul.square li ul, ul.circle li ul, ul.disc li ul { list-style: inherit; }
+ul.square { list-style-type: square; }
+ul.circle { list-style-type: circle; }
+ul.disc { list-style-type: disc; }
+ul.no-bullet { list-style: none; }
+
+/* Ordered Lists */
+ol li ul, ol li ol { margin-left: 1.25em; margin-bottom: 0; }
+
+/* Definition Lists */
+dl dt { margin-bottom: 0.3em; font-weight: bold; }
+dl dd { margin-bottom: 0.75em; }
+
+/* Abbreviations */
+abbr, acronym { text-transform: uppercase; font-size: 90%; color: black; border-bottom: 1px dotted #dddddd; cursor: help; }
+
+abbr { text-transform: none; }
+
+/* Blockquotes */
+blockquote { margin: 0 0 0.75em; padding: 0.5625em 1.25em 0 1.1875em; border-left: 1px solid #dddddd; }
+blockquote cite { display: block; font-size: 0.8125em; color: #5e93b8; }
+blockquote cite:before { content: "\2014 \0020"; }
+blockquote cite a, blockquote cite a:visited { color: #5e93b8; }
+
+blockquote, blockquote p { line-height: 1.6; color: #333333; }
+
+/* Microformats */
+.vcard { display: inline-block; margin: 0 0 1.25em 0; border: 1px solid #dddddd; padding: 0.625em 0.75em; }
+.vcard li { margin: 0; display: block; }
+.vcard .fn { font-weight: bold; font-size: 0.9375em; }
+
+.vevent .summary { font-weight: bold; }
+.vevent abbr { cursor: auto; text-decoration: none; font-weight: bold; border: none; padding: 0 0.0625em; }
+
+@media only screen and (min-width: 768px) { h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { line-height: 1.4; }
+  h1 { font-size: 2.75em; }
+  h2 { font-size: 2.3125em; }
+  h3, #toctitle, .sidebarblock > .content > .title { font-size: 1.6875em; }
+  h4 { font-size: 1.4375em; } }
+/* Tables */
+table { background: white; margin-bottom: 1.25em; border: solid 1px #d8d8ce; }
+table thead, table tfoot { background: -webkit-linear-gradient(top, #add386, #90b66a); font-weight: bold; }
+table thead tr th, table thead tr td, table tfoot tr th, table tfoot tr td { padding: 0.5em 0.625em 0.625em; font-size: inherit; color: white; text-align: left; }
+table tr th, table tr td { padding: 0.5625em 0.625em; font-size: inherit; color: #6d6e71; }
+table tr.even, table tr.alt, table tr:nth-of-type(even) { background: #edf2f2; }
+table thead tr th, table tfoot tr th, table tbody tr td, table tr td, table tfoot tr td { display: table-cell; line-height: 1.4; }
+
+body { -moz-osx-font-smoothing: grayscale; -webkit-font-smoothing: antialiased; tab-size: 4; }
+
+h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { line-height: 1.4; }
+
+a:hover, a:focus { text-decoration: underline; }
+
+.clearfix:before, .clearfix:after, .float-group:before, .float-group:after { content: " "; display: table; }
+.clearfix:after, .float-group:after { clear: both; }
+
+*:not(pre) > code { font-size: inherit; font-style: normal !important; letter-spacing: 0; padding: 0; background-color: white; -webkit-border-radius: 0; border-radius: 0; line-height: inherit; word-wrap: break-word; }
+*:not(pre) > code.nobreak { word-wrap: normal; }
+*:not(pre) > code.nowrap { white-space: nowrap; }
+
+pre, pre > code { line-height: 1.6; color: #264357; font-family: Consolas, "Liberation Mono", Courier, monospace; font-weight: normal; }
+
+em em { font-style: normal; }
+
+strong strong { font-weight: normal; }
+
+.keyseq { color: #333333; }
+
+kbd { font-family: Consolas, "Liberation Mono", Courier, monospace; display: inline-block; color: black; font-size: 0.65em; line-height: 1.45; background-color: #f7f7f7; border: 1px solid #ccc; -webkit-border-radius: 3px; border-radius: 3px; -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 0.1em white inset; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 0.1em white inset; margin: 0 0.15em; padding: 0.2em 0.5em; vertical-align: middle; position: relative; top: -0.1em; white-space: nowrap; }
+
+.keyseq kbd:first-child { margin-left: 0; }
+
+.keyseq kbd:last-child { margin-right: 0; }
+
+.menuseq, .menuref { color: #000; }
+
+.menuseq b:not(.caret), .menuref { font-weight: inherit; }
+
+.menuseq { word-spacing: -0.02em; }
+.menuseq b.caret { font-size: 1.25em; line-height: 0.8; }
+.menuseq i.caret { font-weight: bold; text-align: center; width: 0.45em; }
+
+b.button:before, b.button:after { position: relative; top: -1px; font-weight: normal; }
+
+b.button:before { content: "["; padding: 0 3px 0 2px; }
+
+b.button:after { content: "]"; padding: 0 2px 0 3px; }
+
+#header, #content, #footnotes, #footer { width: 100%; margin-left: auto; margin-right: auto; margin-top: 0; margin-bottom: 0; max-width: 62.5em; *zoom: 1; position: relative; padding-left: 1.5em; padding-right: 1.5em; }
+#header:before, #header:after, #content:before, #content:after, #footnotes:before, #footnotes:after, #footer:before, #footer:after { content: " "; display: table; }
+#header:after, #content:after, #footnotes:after, #footer:after { clear: both; }
+
+#content { margin-top: 1.25em; }
+
+#content:before { content: none; }
+
+#header > h1:first-child { color: black; margin-top: 2.25rem; margin-bottom: 0; }
+#header > h1:first-child + #toc { margin-top: 8px; border-top: 1px solid #dddddd; }
+#header > h1:only-child, body.toc2 #header > h1:nth-last-child(2) { border-bottom: 1px solid #dddddd; padding-bottom: 8px; }
+#header .details { border-bottom: 1px solid #dddddd; line-height: 1.45; padding-top: 0.25em; padding-bottom: 0.25em; padding-left: 0.25em; color: #5e93b8; display: -ms-flexbox; display: -webkit-flex; display: flex; -ms-flex-flow: row wrap; -webkit-flex-flow: row wrap; flex-flow: row wrap; }
+#header .details span:first-child { margin-left: -0.125em; }
+#header .details span.email a { color: #333333; }
+#header .details br { display: none; }
+#header .details br + span:before { content: "\00a0\2013\00a0"; }
+#header .details br + span.author:before { content: "\00a0\22c5\00a0"; color: #333333; }
+#header .details br + span#revremark:before { content: "\00a0|\00a0"; }
+#header #revnumber { text-transform: capitalize; }
+#header #revnumber:after { content: "\00a0"; }
+
+#content > h1:first-child:not([class]) { color: black; border-bottom: 1px solid #dddddd; padding-bottom: 8px; margin-top: 0; padding-top: 1rem; margin-bottom: 1.25rem; }
+
+#toc { border-bottom: 0 solid #dddddd; padding-bottom: 0.5em; }
+#toc > ul { margin-left: 0.125em; }
+#toc ul.sectlevel0 > li > a { font-style: italic; }
+#toc ul.sectlevel0 ul.sectlevel1 { margin: 0.5em 0; }
+#toc ul { font-family: Noto, sans-serif; list-style-type: none; }
+#toc li { line-height: 1.3334; margin-top: 0.3334em; }
+#toc a { text-decoration: none; }
+#toc a:active { text-decoration: underline; }
+
+#toctitle { color: black; font-size: 1.2em; }
+
+@media only screen and (min-width: 768px) { #toctitle { font-size: 1.375em; }
+  body.toc2 { padding-left: 15em; padding-right: 0; }
+  #toc.toc2 { margin-top: 0 !important; background-color: white; position: fixed; width: 15em; left: 0; top: 0; border-right: 1px solid #dddddd; border-top-width: 0 !important; border-bottom-width: 0 !important; z-index: 1000; padding: 1.25em 1em; height: 100%; overflow: auto; }
+  #toc.toc2 #toctitle { margin-top: 0; margin-bottom: 0.8rem; font-size: 1.2em; }
+  #toc.toc2 > ul { font-size: 0.9em; margin-bottom: 0; }
+  #toc.toc2 ul ul { margin-left: 0; padding-left: 1em; }
+  #toc.toc2 ul.sectlevel0 ul.sectlevel1 { padding-left: 0; margin-top: 0.5em; margin-bottom: 0.5em; }
+  body.toc2.toc-right { padding-left: 0; padding-right: 15em; }
+  body.toc2.toc-right #toc.toc2 { border-right-width: 0; border-left: 1px solid #dddddd; left: auto; right: 0; } }
+@media only screen and (min-width: 1280px) { body.toc2 { padding-left: 20em; padding-right: 0; }
+  #toc.toc2 { width: 20em; }
+  #toc.toc2 #toctitle { font-size: 1.375em; }
+  #toc.toc2 > ul { font-size: 0.95em; }
+  #toc.toc2 ul ul { padding-left: 1.25em; }
+  body.toc2.toc-right { padding-left: 0; padding-right: 20em; } }
+#content #toc { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 0; border-radius: 0; }
+#content #toc > :first-child { margin-top: 0; }
+#content #toc > :last-child { margin-bottom: 0; }
+
+#footer { max-width: 100%; background-color: none; padding: 1.25em; }
+
+#footer-text { color: black; line-height: 1.44; }
+
+#content { margin-bottom: 0.625em; }
+
+.sect1 { padding-bottom: 0.625em; }
+
+@media only screen and (min-width: 768px) { #content { margin-bottom: 1.25em; }
+  .sect1 { padding-bottom: 1.25em; } }
+.sect1:last-child { padding-bottom: 0; }
+
+.sect1 + .sect1 { border-top: 0 solid #dddddd; }
+
+#content h1 > a.anchor, h2 > a.anchor, h3 > a.anchor, #toctitle > a.anchor, .sidebarblock > .content > .title > a.anchor, h4 > a.anchor, h5 > a.anchor, h6 > a.anchor { position: absolute; z-index: 1001; width: 1.5ex; margin-left: -1.5ex; display: block; text-decoration: none !important; visibility: hidden; text-align: center; font-weight: normal; }
+#content h1 > a.anchor:before, h2 > a.anchor:before, h3 > a.anchor:before, #toctitle > a.anchor:before, .sidebarblock > .content > .title > a.anchor:before, h4 > a.anchor:before, h5 > a.anchor:before, h6 > a.anchor:before { content: "\00A7"; font-size: 0.85em; display: block; padding-top: 0.1em; }
+#content h1:hover > a.anchor, #content h1 > a.anchor:hover, h2:hover > a.anchor, h2 > a.anchor:hover, h3:hover > a.anchor, #toctitle:hover > a.anchor, .sidebarblock > .content > .title:hover > a.anchor, h3 > a.anchor:hover, #toctitle > a.anchor:hover, .sidebarblock > .content > .title > a.anchor:hover, h4:hover > a.anchor, h4 > a.anchor:hover, h5:hover > a.anchor, h5 > a.anchor:hover, h6:hover > a.anchor, h6 > a.anchor:hover { visibility: visible; }
+#content h1 > a.link, h2 > a.link, h3 > a.link, #toctitle > a.link, .sidebarblock > .content > .title > a.link, h4 > a.link, h5 > a.link, h6 > a.link { color: black; text-decoration: none; }
+#content h1 > a.link:hover, h2 > a.link:hover, h3 > a.link:hover, #toctitle > a.link:hover, .sidebarblock > .content > .title > a.link:hover, h4 > a.link:hover, h5 > a.link:hover, h6 > a.link:hover { color: black; }
+
+.audioblock, .imageblock, .literalblock, .listingblock, .stemblock, .videoblock { margin-bottom: 1.25em; }
+
+.admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { text-rendering: optimizeLegibility; text-align: left; }
+
+table.tableblock > caption.title { white-space: nowrap; overflow: visible; max-width: 0; }
+
+.paragraph.lead > p, #preamble > .sectionbody > .paragraph:first-of-type p { color: black; }
+
+table.tableblock #preamble > .sectionbody > .paragraph:first-of-type p { font-size: inherit; }
+
+.admonitionblock > table { border-collapse: separate; border: 0; background: none; width: 100%; }
+.admonitionblock > table td.icon { text-align: center; width: 80px; }
+.admonitionblock > table td.icon img { max-width: initial; }
+.admonitionblock > table td.icon .title { font-weight: bold; font-family: Noto, sans-serif; text-transform: uppercase; }
+.admonitionblock > table td.content { padding-left: 1.125em; padding-right: 1.25em; border-left: 1px solid #dddddd; color: #5e93b8; }
+.admonitionblock > table td.content > :last-child > :last-child { margin-bottom: 0; }
+
+.exampleblock > .content { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 0; border-radius: 0; }
+.exampleblock > .content > :first-child { margin-top: 0; }
+.exampleblock > .content > :last-child { margin-bottom: 0; }
+
+.sidebarblock { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 0; border-radius: 0; }
+.sidebarblock > :first-child { margin-top: 0; }
+.sidebarblock > :last-child { margin-bottom: 0; }
+.sidebarblock > .content > .title { color: black; margin-top: 0; }
+
+.exampleblock > .content > :last-child > :last-child, .exampleblock > .content .olist > ol > li:last-child > :last-child, .exampleblock > .content .ulist > ul > li:last-child > :last-child, .exampleblock > .content .qlist > ol > li:last-child > :last-child, .sidebarblock > .content > :last-child > :last-child, .sidebarblock > .content .olist > ol > li:last-child > :last-child, .sidebarblock > .content .ulist > ul > li:last-child > :last-child, .sidebarblock > .content .qlist > ol > li:last-child > :last-child { margin-bottom: 0; }
+
+.literalblock pre, .listingblock pre:not(.highlight), .listingblock pre[class="highlight"], .listingblock pre[class^="highlight "], .listingblock pre.CodeRay, .listingblock pre.prettyprint { background: #eeeeee; }
+.sidebarblock .literalblock pre, .sidebarblock .listingblock pre:not(.highlight), .sidebarblock .listingblock pre[class="highlight"], .sidebarblock .listingblock pre[class^="highlight "], .sidebarblock .listingblock pre.CodeRay, .sidebarblock .listingblock pre.prettyprint { background: #f2f1f1; }
+
+.literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { border: 1px hidden #666666; -webkit-border-radius: 0; border-radius: 0; word-wrap: break-word; padding: 1.25em 1.5625em 1.125em 1.5625em; font-size: 0.8125em; }
+.literalblock pre.nowrap, .literalblock pre[class].nowrap, .listingblock pre.nowrap, .listingblock pre[class].nowrap { overflow-x: auto; white-space: pre; word-wrap: normal; }
+@media only screen and (min-width: 768px) { .literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { font-size: 0.90625em; } }
+@media only screen and (min-width: 1280px) { .literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { font-size: 1em; } }
+
+.literalblock.output pre { color: #eeeeee; background-color: #264357; }
+
+.listingblock pre.highlightjs { padding: 0; }
+.listingblock pre.highlightjs > code { padding: 1.25em 1.5625em 1.125em 1.5625em; -webkit-border-radius: 0; border-radius: 0; }
+
+.listingblock > .content { position: relative; }
+
+.listingblock code[data-lang]:before { display: none; content: attr(data-lang); position: absolute; font-size: 0.75em; top: 0.425rem; right: 0.5rem; line-height: 1; text-transform: uppercase; color: #999; }
+
+.listingblock:hover code[data-lang]:before { display: block; }
+
+.listingblock.terminal pre .command:before { content: attr(data-prompt); padding-right: 0.5em; color: #999; }
+
+.listingblock.terminal pre .command:not([data-prompt]):before { content: "$"; }
+
+table.pyhltable { border-collapse: separate; border: 0; margin-bottom: 0; background: none; }
+
+table.pyhltable td { vertical-align: top; padding-top: 0; padding-bottom: 0; line-height: 1.6; }
+
+table.pyhltable td.code { padding-left: .75em; padding-right: 0; }
+
+pre.pygments .lineno, table.pyhltable td:not(.code) { color: #999; padding-left: 0; padding-right: .5em; border-right: 1px solid #dddddd; }
+
+pre.pygments .lineno { display: inline-block; margin-right: .25em; }
+
+table.pyhltable .linenodiv { background: none !important; padding-right: 0 !important; }
+
+.quoteblock { margin: 0 1em 0.75em 1.5em; display: table; }
+.quoteblock > .title { margin-left: -1.5em; margin-bottom: 0.75em; }
+.quoteblock blockquote, .quoteblock blockquote p { color: #333333; font-size: 1.15rem; line-height: 1.75; word-spacing: 0.1em; letter-spacing: 0; font-style: italic; text-align: justify; }
+.quoteblock blockquote { margin: 0; padding: 0; border: 0; }
+.quoteblock blockquote:before { content: "\201c"; float: left; font-size: 2.75em; font-weight: bold; line-height: 0.6em; margin-left: -0.6em; color: black; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); }
+.quoteblock blockquote > .paragraph:last-child p { margin-bottom: 0; }
+.quoteblock .attribution { margin-top: 0.5em; margin-right: 0.5ex; text-align: right; }
+.quoteblock .quoteblock { margin-left: 0; margin-right: 0; padding: 0.5em 0; border-left: 3px solid #5e93b8; }
+.quoteblock .quoteblock blockquote { padding: 0 0 0 0.75em; }
+.quoteblock .quoteblock blockquote:before { display: none; }
+
+.verseblock { margin: 0 1em 0.75em 1em; }
+.verseblock pre { font-family: "Open Sans", "DejaVu Sans", sans; font-size: 1.15rem; color: #333333; font-weight: 300; text-rendering: optimizeLegibility; }
+.verseblock pre strong { font-weight: 400; }
+.verseblock .attribution { margin-top: 1.25rem; margin-left: 0.5ex; }
+
+.quoteblock .attribution, .verseblock .attribution { font-size: 0.8125em; line-height: 1.45; font-style: italic; }
+.quoteblock .attribution br, .verseblock .attribution br { display: none; }
+.quoteblock .attribution cite, .verseblock .attribution cite { display: block; letter-spacing: -0.025em; color: #5e93b8; }
+
+.quoteblock.abstract { margin: 0 0 0.75em 0; display: block; }
+.quoteblock.abstract blockquote, .quoteblock.abstract blockquote p { text-align: left; word-spacing: 0; }
+.quoteblock.abstract blockquote:before, .quoteblock.abstract blockquote p:first-of-type:before { display: none; }
+
+table.tableblock { max-width: 100%; border-collapse: separate; }
+table.tableblock td > .paragraph:last-child p > p:last-child, table.tableblock th > p:last-child, table.tableblock td > p:last-child { margin-bottom: 0; }
+
+table.tableblock, th.tableblock, td.tableblock { border: 0 solid #d8d8ce; }
+
+table.grid-all > thead > tr > .tableblock, table.grid-all > tbody > tr > .tableblock { border-width: 0 1px 1px 0; }
+
+table.grid-all > tfoot > tr > .tableblock { border-width: 1px 1px 0 0; }
+
+table.grid-cols > * > tr > .tableblock { border-width: 0 1px 0 0; }
+
+table.grid-rows > thead > tr > .tableblock, table.grid-rows > tbody > tr > .tableblock { border-width: 0 0 1px 0; }
+
+table.grid-rows > tfoot > tr > .tableblock { border-width: 1px 0 0 0; }
+
+table.grid-all > * > tr > .tableblock:last-child, table.grid-cols > * > tr > .tableblock:last-child { border-right-width: 0; }
+
+table.grid-all > tbody > tr:last-child > .tableblock, table.grid-all > thead:last-child > tr > .tableblock, table.grid-rows > tbody > tr:last-child > .tableblock, table.grid-rows > thead:last-child > tr > .tableblock { border-bottom-width: 0; }
+
+table.frame-all { border-width: 1px; }
+
+table.frame-sides { border-width: 0 1px; }
+
+table.frame-topbot { border-width: 1px 0; }
+
+th.halign-left, td.halign-left { text-align: left; }
+
+th.halign-right, td.halign-right { text-align: right; }
+
+th.halign-center, td.halign-center { text-align: center; }
+
+th.valign-top, td.valign-top { vertical-align: top; }
+
+th.valign-bottom, td.valign-bottom { vertical-align: bottom; }
+
+th.valign-middle, td.valign-middle { vertical-align: middle; }
+
+table thead th, table tfoot th { font-weight: bold; }
+
+tbody tr th { display: table-cell; line-height: 1.4; background: -webkit-linear-gradient(top, #add386, #90b66a); }
+
+tbody tr th, tbody tr th p, tfoot tr th, tfoot tr th p { color: white; font-weight: bold; }
+
+p.tableblock > code:only-child { background: none; padding: 0; }
+
+p.tableblock { font-size: 1em; }
+
+td > div.verse { white-space: pre; }
+
+ol { margin-left: 1.75em; }
+
+ul li ol { margin-left: 1.5em; }
+
+dl dd { margin-left: 1.125em; }
+
+dl dd:last-child, dl dd:last-child > :last-child { margin-bottom: 0; }
+
+ol > li p, ul > li p, ul dd, ol dd, .olist .olist, .ulist .ulist, .ulist .olist, .olist .ulist { margin-bottom: 0.375em; }
+
+ul.checklist, ul.none, ol.none, ul.no-bullet, ol.no-bullet, ol.unnumbered, ul.unstyled, ol.unstyled { list-style-type: none; }
+
+ul.no-bullet, ol.no-bullet, ol.unnumbered { margin-left: 0.625em; }
+
+ul.unstyled, ol.unstyled { margin-left: 0; }
+
+ul.checklist { margin-left: 0.625em; }
+
+ul.checklist li > p:first-child > .fa-square-o:first-child, ul.checklist li > p:first-child > .fa-check-square-o:first-child { width: 1.25em; font-size: 0.8em; position: relative; bottom: 0.125em; }
+
+ul.checklist li > p:first-child > input[type="checkbox"]:first-child { margin-right: 0.25em; }
+
+ul.inline { display: -ms-flexbox; display: -webkit-box; display: flex; -ms-flex-flow: row wrap; -webkit-flex-flow: row wrap; flex-flow: row wrap; list-style: none; margin: 0 0 0.375em -0.75em; }
+
+ul.inline > li { margin-left: 0.75em; }
+
+.unstyled dl dt { font-weight: normal; font-style: normal; }
+
+ol.arabic { list-style-type: decimal; }
+
+ol.decimal { list-style-type: decimal-leading-zero; }
+
+ol.loweralpha { list-style-type: lower-alpha; }
+
+ol.upperalpha { list-style-type: upper-alpha; }
+
+ol.lowerroman { list-style-type: lower-roman; }
+
+ol.upperroman { list-style-type: upper-roman; }
+
+ol.lowergreek { list-style-type: lower-greek; }
+
+.hdlist > table, .colist > table { border: 0; background: none; }
+.hdlist > table > tbody > tr, .colist > table > tbody > tr { background: none; }
+
+td.hdlist1, td.hdlist2 { vertical-align: top; padding: 0 0.625em; }
+
+td.hdlist1 { font-weight: bold; padding-bottom: 0.75em; }
+
+.literalblock + .colist, .listingblock + .colist { margin-top: -0.5em; }
+
+.colist > table tr > td:first-of-type { padding: 0.4em 0.75em 0 0.75em; line-height: 1; vertical-align: top; }
+.colist > table tr > td:first-of-type img { max-width: initial; }
+.colist > table tr > td:last-of-type { padding: 0.25em 0; }
+
+.thumb, .th { line-height: 0; display: inline-block; border: solid 4px white; -webkit-box-shadow: 0 0 0 1px #dddddd; box-shadow: 0 0 0 1px #dddddd; }
+
+.imageblock.left, .imageblock[style*="float: left"] { margin: 0.25em 0.625em 1.25em 0; }
+.imageblock.right, .imageblock[style*="float: right"] { margin: 0.25em 0 1.25em 0.625em; }
+.imageblock > .title { margin-bottom: 0; }
+.imageblock.thumb, .imageblock.th { border-width: 6px; }
+.imageblock.thumb > .title, .imageblock.th > .title { padding: 0 0.125em; }
+
+.image.left, .image.right { margin-top: 0.25em; margin-bottom: 0.25em; display: inline-block; line-height: 0; }
+.image.left { margin-right: 0.625em; }
+.image.right { margin-left: 0.625em; }
+
+a.image { text-decoration: none; display: inline-block; }
+a.image object { pointer-events: none; }
+
+sup.footnote, sup.footnoteref { font-size: 0.875em; position: static; vertical-align: super; }
+sup.footnote a, sup.footnoteref a { text-decoration: none; }
+sup.footnote a:active, sup.footnoteref a:active { text-decoration: underline; }
+
+#footnotes { padding-top: 0.75em; padding-bottom: 0.75em; margin-bottom: 0.625em; }
+#footnotes hr { width: 20%; min-width: 6.25em; margin: -0.25em 0 0.75em 0; border-width: 1px 0 0 0; }
+#footnotes .footnote { padding: 0 0.375em 0 0.225em; line-height: 1.3334; font-size: 0.875em; margin-left: 1.2em; margin-bottom: 0.2em; }
+#footnotes .footnote a:first-of-type { font-weight: bold; text-decoration: none; margin-left: -1.05em; }
+#footnotes .footnote:last-of-type { margin-bottom: 0; }
+#content #footnotes { margin-top: -0.625em; margin-bottom: 0; padding: 0.75em 0; }
+
+.gist .file-data > table { border: 0; background: #fff; width: 100%; margin-bottom: 0; }
+.gist .file-data > table td.line-data { width: 99%; }
+
+div.unbreakable { page-break-inside: avoid; }
+
+.big { font-size: larger; }
+
+.small { font-size: smaller; }
+
+.underline { text-decoration: underline; }
+
+.overline { text-decoration: overline; }
+
+.line-through { text-decoration: line-through; }
+
+.aqua { color: #00bfbf; }
+
+.aqua-background { background-color: #00fafa; }
+
+.black { color: black; }
+
+.black-background { background-color: black; }
+
+.blue { color: #0000bf; }
+
+.blue-background { background-color: #0000fa; }
+
+.fuchsia { color: #bf00bf; }
+
+.fuchsia-background { background-color: #fa00fa; }
+
+.gray { color: #606060; }
+
+.gray-background { background-color: #7d7d7d; }
+
+.green { color: #006000; }
+
+.green-background { background-color: #007d00; }
+
+.lime { color: #00bf00; }
+
+.lime-background { background-color: #00fa00; }
+
+.maroon { color: #600000; }
+
+.maroon-background { background-color: #7d0000; }
+
+.navy { color: #000060; }
+
+.navy-background { background-color: #00007d; }
+
+.olive { color: #606000; }
+
+.olive-background { background-color: #7d7d00; }
+
+.purple { color: #600060; }
+
+.purple-background { background-color: #7d007d; }
+
+.red { color: #bf0000; }
+
+.red-background { background-color: #fa0000; }
+
+.silver { color: #909090; }
+
+.silver-background { background-color: #bcbcbc; }
+
+.teal { color: #006060; }
+
+.teal-background { background-color: #007d7d; }
+
+.white { color: #bfbfbf; }
+
+.white-background { background-color: #fafafa; }
+
+.yellow { color: #bfbf00; }
+
+.yellow-background { background-color: #fafa00; }
+
+span.icon > .fa { cursor: default; }
+a span.icon > .fa { cursor: inherit; }
+
+.admonitionblock td.icon [class^="fa icon-"] { font-size: 2.5em; text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5); cursor: default; }
+.admonitionblock td.icon .icon-note:before { content: "\f05a"; color: #29475c; }
+.admonitionblock td.icon .icon-tip:before { content: "\f0eb"; text-shadow: 1px 1px 2px rgba(155, 155, 0, 0.8); color: #111; }
+.admonitionblock td.icon .icon-warning:before { content: "\f071"; color: #bf6900; }
+.admonitionblock td.icon .icon-caution:before { content: "\f06d"; color: #bf3400; }
+.admonitionblock td.icon .icon-important:before { content: "\f06a"; color: #bf0000; }
+
+.conum[data-value] { display: inline-block; color: #fff !important; background-color: black; -webkit-border-radius: 100px; border-radius: 100px; text-align: center; font-size: 0.75em; width: 1.67em; height: 1.67em; line-height: 1.67em; font-family: "Open Sans", "DejaVu Sans", sans-serif; font-style: normal; font-weight: bold; }
+.conum[data-value] * { color: #fff !important; }
+.conum[data-value] + b { display: none; }
+.conum[data-value]:after { content: attr(data-value); }
+pre .conum[data-value] { position: relative; top: -0.125em; }
+
+b.conum * { color: inherit !important; }
+
+.conum:not([data-value]):empty { display: none; }
+
+h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { border-bottom: 1px solid #dddddd; }
+
+.sect1 { padding-bottom: 0; }
+
+#toctitle { color: #00406F; font-weight: normal; margin-top: 1.5em; }
+
+.sidebarblock { border-color: #aaa; }
+
+code { -webkit-border-radius: 4px; border-radius: 4px; }
+
+p.tableblock.header { color: #6d6e71; }
+
+.literalblock pre, .listingblock pre { background: #eeeeee; }
+
+</style>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css">
+<style>
+/* Stylesheet for CodeRay to match GitHub theme | MIT License | http://foundation.zurb.com */
+/*pre.CodeRay {background-color:#f7f7f8;}*/
+.CodeRay .line-numbers{border-right:1px solid #d8d8d8;padding:0 0.5em 0 .25em}
+.CodeRay span.line-numbers{display:inline-block;margin-right:.5em;color:rgba(0,0,0,.3)}
+.CodeRay .line-numbers strong{color:rgba(0,0,0,.4)}
+table.CodeRay{border-collapse:separate;border-spacing:0;margin-bottom:0;border:0;background:none}
+table.CodeRay td{vertical-align: top;line-height:1.45}
+table.CodeRay td.line-numbers{text-align:right}
+table.CodeRay td.line-numbers>pre{padding:0;color:rgba(0,0,0,.3)}
+table.CodeRay td.code{padding:0 0 0 .5em}
+table.CodeRay td.code>pre{padding:0}
+.CodeRay .debug{color:#fff !important;background:#000080 !important}
+.CodeRay .annotation{color:#007}
+.CodeRay .attribute-name{color:#000080}
+.CodeRay .attribute-value{color:#700}
+.CodeRay .binary{color:#509}
+.CodeRay .comment{color:#998;font-style:italic}
+.CodeRay .char{color:#04d}
+.CodeRay .char .content{color:#04d}
+.CodeRay .char .delimiter{color:#039}
+.CodeRay .class{color:#458;font-weight:bold}
+.CodeRay .complex{color:#a08}
+.CodeRay .constant,.CodeRay .predefined-constant{color:#008080}
+.CodeRay .color{color:#099}
+.CodeRay .class-variable{color:#369}
+.CodeRay .decorator{color:#b0b}
+.CodeRay .definition{color:#099}
+.CodeRay .delimiter{color:#000}
+.CodeRay .doc{color:#970}
+.CodeRay .doctype{color:#34b}
+.CodeRay .doc-string{color:#d42}
+.CodeRay .escape{color:#666}
+.CodeRay .entity{color:#800}
+.CodeRay .error{color:#808}
+.CodeRay .exception{color:inherit}
+.CodeRay .filename{color:#099}
+.CodeRay .function{color:#900;font-weight:bold}
+.CodeRay .global-variable{color:#008080}
+.CodeRay .hex{color:#058}
+.CodeRay .integer,.CodeRay .float{color:#099}
+.CodeRay .include{color:#555}
+.CodeRay .inline{color:#000}
+.CodeRay .inline .inline{background:#ccc}
+.CodeRay .inline .inline .inline{background:#bbb}
+.CodeRay .inline .inline-delimiter{color:#d14}
+.CodeRay .inline-delimiter{color:#d14}
+.CodeRay .important{color:#555;font-weight:bold}
+.CodeRay .interpreted{color:#b2b}
+.CodeRay .instance-variable{color:#008080}
+.CodeRay .label{color:#970}
+.CodeRay .local-variable{color:#963}
+.CodeRay .octal{color:#40e}
+.CodeRay .predefined{color:#369}
+.CodeRay .preprocessor{color:#579}
+.CodeRay .pseudo-class{color:#555}
+.CodeRay .directive{font-weight:bold}
+.CodeRay .type{font-weight:bold}
+.CodeRay .predefined-type{color:inherit}
+.CodeRay .reserved,.CodeRay .keyword {color:#000;font-weight:bold}
+.CodeRay .key{color:#808}
+.CodeRay .key .delimiter{color:#606}
+.CodeRay .key .char{color:#80f}
+.CodeRay .value{color:#088}
+.CodeRay .regexp .delimiter{color:#808}
+.CodeRay .regexp .content{color:#808}
+.CodeRay .regexp .modifier{color:#808}
+.CodeRay .regexp .char{color:#d14}
+.CodeRay .regexp .function{color:#404;font-weight:bold}
+.CodeRay .string{color:#d20}
+.CodeRay .string .string .string{background:#ffd0d0}
+.CodeRay .string .content{color:#d14}
+.CodeRay .string .char{color:#d14}
+.CodeRay .string .delimiter{color:#d14}
+.CodeRay .shell{color:#d14}
+.CodeRay .shell .delimiter{color:#d14}
+.CodeRay .symbol{color:#990073}
+.CodeRay .symbol .content{color:#a60}
+.CodeRay .symbol .delimiter{color:#630}
+.CodeRay .tag{color:#008080}
+.CodeRay .tag-special{color:#d70}
+.CodeRay .variable{color:#036}
+.CodeRay .insert{background:#afa}
+.CodeRay .delete{background:#faa}
+.CodeRay .change{color:#aaf;background:#007}
+.CodeRay .head{color:#f8f;background:#505}
+.CodeRay .insert .insert{color:#080}
+.CodeRay .delete .delete{color:#800}
+.CodeRay .change .change{color:#66f}
+.CodeRay .head .head{color:#f4f}
+</style>
+<link rel="stylesheet" href="../katex/katex.min.css">
+<script src="../katex/katex.min.js"></script>
+<script src="../katex/contrib/auto-render.min.js"></script>
+    <!-- Use KaTeX to render math once document is loaded, see
+         https://github.com/Khan/KaTeX/tree/master/contrib/auto-render -->
+<script>
+    document.addEventListener("DOMContentLoaded", function () {
+        renderMathInElement(
+            document.body,
+            {
+                delimiters: [
+                    { left: "$$", right: "$$", display: true},
+                    { left: "\\[", right: "\\]", display: true},
+                    { left: "$", right: "$", display: false},
+                    { left: "\\(", right: "\\)", display: false}
+                ]
+            }
+        );
+    });
+</script></head>
+<body class="book toc2 toc-left" style="max-width: 100;">
+<div id="header">
+<h1>The OpenCL<sup>&#8482;</sup> SPIR-V Environment Specification</h1>
+<div class="details">
+<span id="author" class="author">Khronos OpenCL Working Group</span><br>
+<span id="revnumber">version 2.2-7,</span>
+<span id="revdate">Sat, 12 May 2018 13:21:27 +0000</span>
+<br><span id="revremark">from git branch: master commit: ab6da3001e9eeafaa36c18888ca7eb4ebb9768af</span>
+</div>
+<div id="toc" class="toc2">
+<div id="toctitle">Table of Contents</div>
+<ul class="sectlevel1">
+<li><a href="#introduction">1. Introduction</a></li>
+<li><a href="#consumption">2. SPIR-V Consumption</a>
+<ul class="sectlevel2">
+<li><a href="#_validation_rules">2.1. Validation Rules</a></li>
+<li><a href="#_source_language_encoding">2.2. Source Language Encoding</a></li>
+<li><a href="#_numerical_type_formats">2.3. Numerical Type Formats</a></li>
+<li><a href="#_supported_types">2.4. Supported Types</a></li>
+<li><a href="#_image_channel_order_mapping">2.5. Image Channel Order Mapping</a></li>
+<li><a href="#_image_channel_data_type_mapping">2.6. Image Channel Data Type Mapping</a></li>
+<li><a href="#_kernels">2.7. Kernels</a></li>
+<li><a href="#_kernel_return_types">2.8. Kernel Return Types</a></li>
+<li><a href="#_kernel_arguments">2.9. Kernel Arguments</a></li>
+</ul>
+</li>
+<li><a href="#opencl2_2">3. OpenCL 2.2</a>
+<ul class="sectlevel2">
+<li><a href="#_full_profile">3.1. Full Profile</a></li>
+<li><a href="#_embedded_profile">3.2. Embedded Profile</a></li>
+<li><a href="#_validation_rules_2">3.3. Validation Rules</a></li>
+</ul>
+</li>
+<li><a href="#opencl2_1">4. OpenCL 2.1</a>
+<ul class="sectlevel2">
+<li><a href="#_full_profile_2">4.1. Full Profile</a></li>
+<li><a href="#_embedded_profile_2">4.2. Embedded Profile</a></li>
+<li><a href="#_validation_rules_3">4.3. Validation Rules</a></li>
+</ul>
+</li>
+<li><a href="#opencl2_0">5. OpenCL 2.0</a>
+<ul class="sectlevel2">
+<li><a href="#_full_profile_3">5.1. Full Profile</a></li>
+<li><a href="#_embedded_profile_3">5.2. Embedded Profile</a></li>
+<li><a href="#_validation_rules_4">5.3. Validation Rules</a></li>
+</ul>
+</li>
+<li><a href="#opencl1_2">6. OpenCL 1.2</a>
+<ul class="sectlevel2">
+<li><a href="#_full_profile_4">6.1. Full Profile</a></li>
+<li><a href="#_embedded_profile_4">6.2. Embedded Profile</a></li>
+<li><a href="#_validation_rules_5">6.3. Validation Rules</a></li>
+</ul>
+</li>
+<li><a href="#opencl_extensions">7. OpenCL Extensions</a>
+<ul class="sectlevel2">
+<li><a href="#_declaring_spir_v_extensions">7.1. Declaring SPIR-V Extensions</a></li>
+<li><a href="#_full_and_embedded_profile_extensions">7.2. Full and Embedded Profile Extensions</a></li>
+<li><a href="#_embedded_profile_extensions">7.3. Embedded Profile Extensions</a></li>
+</ul>
+</li>
+<li><a href="#numerical_compliance">8. OpenCL Numerical Compliance</a>
+<ul class="sectlevel2">
+<li><a href="#_rounding_modes">8.1. Rounding Modes</a></li>
+<li><a href="#_rounding_modes_for_conversions">8.2. Rounding Modes for Conversions</a></li>
+<li><a href="#_out_of_range_conversions">8.3. Out-of-Range Conversions</a></li>
+<li><a href="#_inf_nan_and_denormalized_numbers">8.4. INF, NaN, and Denormalized Numbers</a></li>
+<li><a href="#_floating_point_exceptions">8.5. Floating-Point Exceptions</a></li>
+<li><a href="#relative-error-as-ulps">8.6. Relative Error as ULPs</a></li>
+<li><a href="#_edge_case_behavior">8.7. Edge Case Behavior</a></li>
+</ul>
+</li>
+<li><a href="#image_addressing_and_filtering">9. Image Addressing and Filtering</a>
+<ul class="sectlevel2">
+<li><a href="#image-coordinates">9.1. Image Coordinates</a></li>
+<li><a href="#addressing-and-filter-modes">9.2. Addressing and Filter Modes</a></li>
+<li><a href="#precision-of-addressing-and-filter-modes">9.3. Precision of Addressing and Filter Modes</a></li>
+<li><a href="#conversion-rules">9.4. Conversion Rules</a></li>
+<li><a href="#selecting-an-image-from-an-image-array">9.5. Selecting an Image from an Image Array</a></li>
+<li><a href="#_data_format_for_reading_and_writing_images">9.6. Data Format for Reading and Writing Images</a></li>
+<li><a href="#_sampled_and_sampler_less_reads">9.7. Sampled and Sampler-less Reads</a></li>
+</ul>
+</li>
+<li><a href="#references">10. Normative References</a></li>
+</ul>
+</div>
+</div>
+<div id="content">
+<div id="preamble">
+<div class="sectionbody">
+<div class="paragraph">
+<p>Copyright 2008-2018 The Khronos Group.</p>
+</div>
+<div class="paragraph">
+<p>This specification is protected by copyright laws and contains material proprietary
+to the Khronos Group, Inc. Except as described by these terms, it or any components
+may not be reproduced, republished, distributed, transmitted, displayed, broadcast
+or otherwise exploited in any manner without the express prior written permission
+of Khronos Group.</p>
+</div>
+<div class="paragraph">
+<p>Khronos Group grants a conditional copyright license to use and reproduce the
+unmodified specification for any purpose, without fee or royalty, EXCEPT no licenses
+to any patent, trademark or other intellectual property rights are granted under
+these terms. Parties desiring to implement the specification and make use of
+Khronos trademarks in relation to that implementation, and receive reciprocal patent
+license protection under the Khronos IP Policy must become Adopters and confirm the
+implementation as conformant under the process defined by Khronos for this
+specification; see <a href="https://www.khronos.org/adopters" class="bare">https://www.khronos.org/adopters</a>.</p>
+</div>
+<div class="paragraph">
+<p>Khronos Group makes no, and expressly disclaims any, representations or warranties,
+express or implied, regarding this specification, including, without limitation:
+merchantability, fitness for a particular purpose, non-infringement of any
+intellectual property, correctness, accuracy, completeness, timeliness, and
+reliability. Under no circumstances will the Khronos Group, or any of its Promoters,
+Contributors or Members, or their respective partners, officers, directors,
+employees, agents or representatives be liable for any damages, whether direct,
+indirect, special or consequential damages for lost revenues, lost profits, or
+otherwise, arising from or in connection with these materials.</p>
+</div>
+<div class="paragraph">
+<p>Vulkan is a registered trademark and Khronos, OpenXR, SPIR, SPIR-V, SYCL, WebGL,
+WebCL, OpenVX, OpenVG, EGL, COLLADA, glTF, NNEF, OpenKODE, OpenKCAM, StreamInput,
+OpenWF, OpenSL ES, OpenMAX, OpenMAX AL, OpenMAX IL, OpenMAX DL, OpenML and DevU are
+trademarks of the Khronos Group Inc. ASTC is a trademark of ARM Holdings PLC,
+OpenCL is a trademark of Apple Inc. and OpenGL and OpenML are registered trademarks
+and the OpenGL ES and OpenGL SC logos are trademarks of Silicon Graphics
+International used under license by Khronos. All other product names, trademarks,
+and/or company names are used solely for identification and belong to their
+respective owners.</p>
+</div>
+<div style="page-break-after: always;"></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="introduction">1. Introduction</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p><a href="#opencl-spec"><strong>OpenCL</strong></a> (Open Computing Language) is an open royalty-free
+standard for general purpose parallel programming across CPUs, GPUs, and
+other processors, giving software developers portable and efficient access
+to the power of these heterogeneous processing platforms.</p>
+</div>
+<div class="paragraph">
+<p>Parallel programs in OpenCL may be written in the <a href="#opencl-c-spec">OpenCL C</a>
+source language, or may compiled from OpenCL C, <a href="#opencl-cpp-spec">OpenCL
+C++</a>, or other source languages into SPIR-V modules.</p>
+</div>
+<div class="paragraph">
+<p>All SPIR-V intermediate binary modules are consumed by environments, such as
+an API, a specific version of an API, or an implementation of an API.
+The environment describes required support for some SPIR-V capabilities,
+additional semantics for some SPIR-V instructions, and additional validation
+rules a module must adhere to in order to be considered valid.</p>
+</div>
+<div class="paragraph">
+<p>This document describes the environment for implementations of the OpenCL
+API.
+It is written for compiler developers who are generating SPIR-V modules to
+be consumed by the OpenCL API, for implementors of the OpenCL API who are
+consuming SPIR-V modules, and by software developers who are using SPIR-V
+modules with the OpenCL API.</p>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="consumption">2. SPIR-V Consumption</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>This section describes common properties of all OpenCL environments.
+Subsequent sections describe environments for specific versions of OpenCL,
+and how an environment may additionally be modified via OpenCL or SPIR-V
+extensions.</p>
+</div>
+<div class="paragraph">
+<p>A SPIR-V module passed to an OpenCL environment is interpreted as a series
+of 32-bit words in host endianness, with literal strings packed as described
+in the SPIR-V specification.
+The first few words of the SPIR-V module must be a magic number and a SPIR-V
+version number, as described in the SPIR-V specification.</p>
+</div>
+<div class="sect2">
+<h3 id="_validation_rules">2.1. Validation Rules</h3>
+<div class="paragraph">
+<p>The following are a list of validation rules that apply to SPIR-V modules
+executing in all OpenCL environments:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>The <em>Execution Model</em> declared in <strong>OpEntryPoint</strong> must be <strong>Kernel</strong>.</p>
+</li>
+<li>
+<p>The <em>Addressing Model</em> declared in <strong>OpMemoryModel</strong> must be either
+<strong>Physical32</strong> or <strong>Physical64</strong>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>Modules indicating a <strong>Physical32</strong> <em>Addressing Model</em> are valid for
+OpenCL devices reporting <code>32</code> for <code>CL_DEVICE_ADDRESS_BITS</code>.</p>
+</li>
+<li>
+<p>Modules indicating a <strong>Physical64</strong> <em>Addressing Model</em> are valid for
+OpenCL devices reporting <code>64</code> for <code>CL_DEVICE_ADDRESS_BITS</code>.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p>The <em>Memory Model</em> declared in <strong>OpMemoryModel</strong> must be <strong>OpenCL</strong>.</p>
+</li>
+<li>
+<p>For all <strong>OpTypeInt</strong> integer type-declaration instructions:</p>
+<div class="ulist">
+<ul>
+<li>
+<p><em>Signedness</em> must be 0, indicating no signedness semantics.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p>For all <strong>OpTypeImage</strong> type-declaration instructions:</p>
+<div class="ulist">
+<ul>
+<li>
+<p><em>Sampled Type</em> must be <strong>OpTypeVoid</strong>.</p>
+</li>
+<li>
+<p><em>Sampled</em> must be 0, indicating that the image usage will be known at
+run time, not at compile time.</p>
+</li>
+<li>
+<p><em>MS</em> must be 0, indicating single-sampled content.</p>
+</li>
+<li>
+<p><em>Arrayed</em> may only be set to 1, indicating arrayed content, when <em>Dim</em>
+is set to <strong>1D</strong> or <strong>2D</strong>.</p>
+</li>
+<li>
+<p><em>Image Format</em> must be <strong>Unknown</strong>, indicating that the image does not
+have a specified format.</p>
+</li>
+<li>
+<p>The optional image <em>Access Qualifier</em> must be present.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p>The image write instruction <strong>OpImageWrite</strong> must not include any optional
+<em>Image Operands</em>.</p>
+</li>
+<li>
+<p>The image read instructions <strong>OpImageRead</strong>, <strong>OpImageFetch</strong>, and
+<strong>OpImageSampleExplicitLod</strong> must not include the optional <em>Image Operand</em>
+<strong>ConstOffset</strong>.</p>
+</li>
+<li>
+<p>For all <strong>Atomic Instructions</strong>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>Only 32-bit integer types are supported for the <em>Result Type</em> and/or
+type of <em>Value</em>.</p>
+</li>
+<li>
+<p>The <em>Pointer</em> operand must be a pointer to the <strong>Function</strong>, <strong>Workgroup</strong>,
+or <strong>CrossWorkGroup</strong> <em>Storage Classes</em>.  Note that an <strong>Atomic Instruction</strong>
+on a pointer to the <strong>Function</strong> <em>Storage Class</em> is valid, but does not
+have defined behavior.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p>Recursion is not supported.
+The static function call graph for an entry point must not contain
+cycles.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_source_language_encoding">2.2. Source Language Encoding</h3>
+<div class="paragraph">
+<p>If a SPIR-V module represents a program written in OpenCL C, then the
+<em>Source Language</em> operand for the <strong>OpSource</strong> instruction should be
+<strong>OpenCL_C</strong>, and the 32-bit literal language <em>Version</em> should describe the
+version of OpenCL C, encoded MSB to LSB as:</p>
+</div>
+<div class="literalblock">
+<div class="content">
+<pre>0 | Major Number | Minor Number | Revision Number (optional)</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Hence, OpenCL C 1.2 would be encoded as <code>0x00010200</code>, and OpenCL C 2.0 as
+<code>0x00020000</code>.</p>
+</div>
+<div class="paragraph">
+<p>If a SPIR-V module represents a program written in OpenCL C++, then the
+<em>Source Language</em> operand for the <strong>OpSource</strong> instruction should be
+<strong>OpenCL_CPP</strong>, and the 32-bit literal language <em>Version</em> should describe the
+version of OpenCL C++, encoded similarly.
+Hence, OpenCL C++ 2.2 would be encoded as <code>0x00020200</code>.</p>
+</div>
+<div class="paragraph">
+<p>The source language version is purely informational and has no semantic
+meaning.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_numerical_type_formats">2.3. Numerical Type Formats</h3>
+<div class="paragraph">
+<p>For all OpenCL environments, floating-point types are represented and stored
+using <a href="#ieee-754-spec">IEEE-754</a> semantics.
+All integer formats are represented and stored using 2&#8217;s-complement format.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_supported_types">2.4. Supported Types</h3>
+<div class="paragraph">
+<p>The following types are supported by OpenCL environments.
+Note that some types may require additional capabilities, and may not be
+supported by all OpenCL environments.</p>
+</div>
+<div class="paragraph">
+<p>OpenCL environments support arrays declared using <strong>OpTypeArray</strong>, structs
+declared using <strong>OpTypeStruct</strong>, functions declared using <strong>OpTypeFunction</strong>,
+and pointers declared using <strong>OpTypePointer</strong>.</p>
+</div>
+<div class="sect3">
+<h4 id="_basic_scalar_and_vector_types">2.4.1. Basic Scalar and Vector Types</h4>
+<div class="paragraph">
+<p><strong>OpTypeVoid</strong> is supported.</p>
+</div>
+<div class="paragraph">
+<p>The following scalar types are supported by OpenCL environments:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>OpTypeBool</strong></p>
+</li>
+<li>
+<p><strong>OpTypeInt</strong>, with <em>Width</em> equal to 8, 16, 32, or 64, and with
+<em>Signedness</em> equal to zero, indicating no signedness semantics.</p>
+</li>
+<li>
+<p><strong>OpTypeFloat</strong>, with <em>Width</em> equal to 16, 32, or 64.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>OpenCL environments support vector types declared using <strong>OpTypeVector</strong>.
+The vector <em>Component Type</em> may be any of the scalar types described
+above.
+Supported vector <em>Component Counts</em> are 2, 3, 4, 8, or 16.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_image_related_data_types">2.4.2. Image-Related Data Types</h4>
+<div class="paragraph">
+<p>The following table describes the <strong>OpTypeImage</strong> image types supported by
+OpenCL environments:</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 1. Image Types</caption>
+<colgroup>
+<col style="width: 16.6666%;">
+<col style="width: 16.6666%;">
+<col style="width: 16.6666%;">
+<col style="width: 50.0002%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>Dim</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>Depth</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>Arrayed</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>1D</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>0</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>0</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 1D image.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>1D</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>0</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>1</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 1D image array.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>2D</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>0</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>0</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 2D image.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>2D</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>1</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>0</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 2D depth image.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>2D</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>0</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>1</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 2D image array.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>2D</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>1</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>1</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 2D depth image array.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>3D</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>0</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>0</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 3D image.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Buffer</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>0</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>0</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 1D buffer image.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p><strong>OpTypeSampler</strong> may be used to declare sampler types in OpenCL environments.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_other_data_types">2.4.3. Other Data Types</h4>
+<div class="paragraph">
+<p>The following table describes other data types that may be used in an
+OpenCL environment:</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 2. Other Data Types</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Type</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpTypeEvent</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">OpenCL event type.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpTypeDeviceEvent</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">OpenCL device-side event type.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpTypePipe</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">OpenCL pipe type</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpTypeReserveId</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">OpenCL pipe reservation identifier.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpTypeQueue</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">OpenCL device-side command queue.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_image_channel_order_mapping">2.5. Image Channel Order Mapping</h3>
+<div class="paragraph">
+<p>The following table describes how the results of the SPIR-V
+<strong>OpImageQueryOrder</strong> instruction correspond to the OpenCL host API image
+channel orders.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 3. Image Channel Order mapping</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>SPIR-V Image Channel Order</strong></th>
+<th class="tableblock halign-left valign-top"><strong>OpenCL Image Channel Order</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>R</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_R</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>A</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_A</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>RG</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_RG</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>RA</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_RA</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>RGB</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_RGB</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>RGBA</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_RGBA</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>BGRA</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_BGRA</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>ARGB</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_ARGB</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>Intensity</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_INTENSITY</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>Luminance</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_LUMINANCE</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>Rx</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_Rx</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>RGx</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_RGx</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>RGBx</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_RGBx</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>Depth</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_DEPTH</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>DepthStencil</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_DEPTH_STENCIL</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>sRGB</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_sRGB</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>sRGBA</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_sRGBA</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>sBGRA</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_sBGRA</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>sRGBx</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_sRGBx</code></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect2">
+<h3 id="_image_channel_data_type_mapping">2.6. Image Channel Data Type Mapping</h3>
+<div class="paragraph">
+<p>The following table describes how the results of the SPIR-V
+<strong>OpImageQueryFormat</strong> instruction correspond to the OpenCL host API image
+channel data types.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 4. Image Channel Data Type mapping</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>SPIR-V Image Channel Data Type</strong></th>
+<th class="tableblock halign-left valign-top"><strong>OpenCL Image Channel Data Type</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>SnormInt8</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_SNORM_INT8</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>SnormInt16</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_SNORM_INT16</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>UnormInt8</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_UNORM_INT8</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>UnormInt16</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_UNORM_INT16</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>UnormInt24</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_UNORM_INT24</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>UnormShort565</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_UNORM_SHORT_565</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>UnormShort555</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_UNORM_SHORT_555</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>UnormInt101010</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_UNORM_INT_101010</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>SignedInt8</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_SIGNED_INT8</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>SignedInt16</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_SIGNED_INT16</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>SignedInt32</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_SIGNED_INT32</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>UnsignedInt8</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_UNSIGNED_INT8</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>UnsignedInt16</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_UNSIGNED_INT16</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>UnsignedInt32</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_UNSIGNED_INT32</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>HalfFloat</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_HALF_FLOAT</code></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>Float</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CL_FLOAT</code></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect2">
+<h3 id="_kernels">2.7. Kernels</h3>
+<div class="paragraph">
+<p>An <strong>OpFunction</strong> in a SPIR-V module that is identified with <strong>OpEntryPoint</strong>
+defines an OpenCL kernel that may be invoked using the OpenCL host API
+enqueue kernel interfaces.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_kernel_return_types">2.8. Kernel Return Types</h3>
+<div class="paragraph">
+<p>The <em>Result Type</em> for an <strong>OpFunction</strong> identified with <strong>OpEntryPoint</strong> must be
+<strong>OpTypeVoid</strong>.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_kernel_arguments">2.9. Kernel Arguments</h3>
+<div class="paragraph">
+<p>An <strong>OpFunctionParameter</strong> for an <strong>OpFunction</strong> that is identified with
+<strong>OpEntryPoint</strong> defines an OpenCL kernel argument.
+Allowed types for OpenCL kernel arguments are:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>OpTypeInt</strong></p>
+</li>
+<li>
+<p><strong>OpTypeFloat</strong></p>
+</li>
+<li>
+<p><strong>OpTypeStruct</strong></p>
+</li>
+<li>
+<p><strong>OpTypeVector</strong></p>
+</li>
+<li>
+<p><strong>OpTypePointer</strong></p>
+</li>
+<li>
+<p><strong>OpTypeSampler</strong></p>
+</li>
+<li>
+<p><strong>OpTypeImage</strong></p>
+</li>
+<li>
+<p><strong>OpTypePipe</strong></p>
+</li>
+<li>
+<p><strong>OpTypeQueue</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For <strong>OpTypeInt</strong> parameters, supported <em>Widths</em> are 8, 16, 32, and 64, and
+must have no signedness semantics.</p>
+</div>
+<div class="paragraph">
+<p>For <strong>OpTypeFloat</strong> parameters, <em>Width</em> must be 32.</p>
+</div>
+<div class="paragraph">
+<p>For <strong>OpTypeStruct</strong> parameters, supported structure <em>Member Types</em> are:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>OpTypeInt</strong></p>
+</li>
+<li>
+<p><strong>OpTypeFloat</strong></p>
+</li>
+<li>
+<p><strong>OpTypeStruct</strong></p>
+</li>
+<li>
+<p><strong>OpTypeVector</strong></p>
+</li>
+<li>
+<p><strong>OpTypePointer</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For <strong>OpTypePointer</strong> parameters, supported <em>Storage Classes</em> are:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>CrossWorkgroup</strong></p>
+</li>
+<li>
+<p><strong>Workgroup</strong></p>
+</li>
+<li>
+<p><strong>UniformConstant</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>OpenCL kernel argument types must have a representation in the OpenCL host
+API.</p>
+</div>
+<div class="paragraph">
+<p>Environments that support extensions or optional features may allow
+additional types in an entry point&#8217;s parameter list.</p>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="opencl2_2">3. OpenCL 2.2</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>An OpenCL 2.2 environment must accept SPIR-V 1.0, 1.1, and 1.2 modules.</p>
+</div>
+<div class="sect2">
+<h3 id="_full_profile">3.1. Full Profile</h3>
+<div class="paragraph">
+<p>An OpenCL 2.2 Full Profile environment is guaranteed to support the
+following SPIR-V capabilities:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>Address</strong></p>
+</li>
+<li>
+<p><strong>DeviceEnqueue</strong></p>
+</li>
+<li>
+<p><strong>Float16Buffer</strong></p>
+</li>
+<li>
+<p><strong>GenericPointer</strong></p>
+</li>
+<li>
+<p><strong>Groups</strong></p>
+</li>
+<li>
+<p><strong>Int64</strong></p>
+</li>
+<li>
+<p><strong>Int16</strong></p>
+</li>
+<li>
+<p><strong>Int8</strong></p>
+</li>
+<li>
+<p><strong>Kernel</strong></p>
+</li>
+<li>
+<p><strong>Linkage</strong></p>
+</li>
+<li>
+<p><strong>Pipes</strong></p>
+</li>
+<li>
+<p><strong>Vector16</strong></p>
+</li>
+<li>
+<p><strong>SubgroupDispatch</strong></p>
+</li>
+<li>
+<p><strong>PipeStorage</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The following capabilities may be optionally supported:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>ImageBasic</strong>, if <code>CL_DEVICE_IMAGE_SUPPORT</code> is <code>CL_TRUE</code></p>
+</li>
+<li>
+<p><strong>Float64</strong>, if the device supports double precision floating-point</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If <strong>ImageBasic</strong> is supported then the following capabilities must also be
+supported:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>ImageReadWrite</strong></p>
+</li>
+<li>
+<p><strong>LiteralSampler</strong></p>
+</li>
+<li>
+<p><strong>Sampled1D</strong></p>
+</li>
+<li>
+<p><strong>Image1D</strong></p>
+</li>
+<li>
+<p><strong>SampledBuffer</strong></p>
+</li>
+<li>
+<p><strong>ImageBuffer</strong></p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_embedded_profile">3.2. Embedded Profile</h3>
+<div class="paragraph">
+<p>An OpenCL 2.2 Embedded Profile environment is guaranteed to support the
+following SPIR-V capabilities:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>Address</strong></p>
+</li>
+<li>
+<p><strong>DeviceEnqueue</strong></p>
+</li>
+<li>
+<p><strong>Float16Buffer</strong></p>
+</li>
+<li>
+<p><strong>GenericPointer</strong></p>
+</li>
+<li>
+<p><strong>Groups</strong></p>
+</li>
+<li>
+<p><strong>Int16</strong></p>
+</li>
+<li>
+<p><strong>Int8</strong></p>
+</li>
+<li>
+<p><strong>Kernel</strong></p>
+</li>
+<li>
+<p><strong>Linkage</strong></p>
+</li>
+<li>
+<p><strong>Pipes</strong></p>
+</li>
+<li>
+<p><strong>Vector16</strong></p>
+</li>
+<li>
+<p><strong>SubgroupDispatch</strong></p>
+</li>
+<li>
+<p><strong>PipeStorage</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Furthermore, the following capabilities may optionally be supported:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>ImageBasic</strong>, if <code>CL_DEVICE_IMAGE_SUPPORT</code> is <code>CL_TRUE</code></p>
+</li>
+<li>
+<p><strong>Float64</strong>, if the device supports double precision floating-point</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If <strong>ImageBasic</strong> is supported then the following capabilities must also be
+supported:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>ImageReadWrite</strong></p>
+</li>
+<li>
+<p><strong>LiteralSampler</strong></p>
+</li>
+<li>
+<p><strong>Sampled1D</strong></p>
+</li>
+<li>
+<p><strong>Image1D</strong></p>
+</li>
+<li>
+<p><strong>SampledBuffer</strong></p>
+</li>
+<li>
+<p><strong>ImageBuffer</strong></p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_validation_rules_2">3.3. Validation Rules</h3>
+<div class="paragraph">
+<p>The following are a list of validation rules for SPIR-V modules executing in
+an OpenCL 2.2 environment:</p>
+</div>
+<div class="paragraph">
+<p><em>Scope</em> for <em>Execution</em> is generally limited to:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>Workgroup</strong></p>
+</li>
+<li>
+<p><strong>Subgroup</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p><em>Scope</em> for <em>Memory</em> is generally limited to:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>CrossDevice</strong></p>
+</li>
+<li>
+<p><strong>Device</strong></p>
+</li>
+<li>
+<p><strong>Workgroup</strong></p>
+</li>
+<li>
+<p><strong>Invocation</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p><em>Scope</em> for <em>Execution</em> for the <strong>OpGroupAsyncCopy</strong> and <strong>OpGroupWaitEvents</strong>
+instructions is specifically limited to:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>Workgroup</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The <em>Pointer</em> operand to all <strong>Atomic Instructions</strong> may additionally be a
+pointer to the <strong>Generic</strong> <em>Storage Class</em>, however behavior is still
+undefined if the <strong>Generic</strong> pointer represents a pointer to the <strong>Function</strong>
+<em>Storage Class</em>.</p>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="opencl2_1">4. OpenCL 2.1</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>An OpenCL 2.1 environment must accept SPIR-V 1.0 modules.</p>
+</div>
+<div class="sect2">
+<h3 id="_full_profile_2">4.1. Full Profile</h3>
+<div class="paragraph">
+<p>An OpenCL 2.1 Full Profile environment is guaranteed to support the
+following SPIR-V capabilities:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>Address</strong></p>
+</li>
+<li>
+<p><strong>DeviceEnqueue</strong></p>
+</li>
+<li>
+<p><strong>Float16Buffer</strong></p>
+</li>
+<li>
+<p><strong>GenericPointer</strong></p>
+</li>
+<li>
+<p><strong>Groups</strong></p>
+</li>
+<li>
+<p><strong>Int64</strong></p>
+</li>
+<li>
+<p><strong>Int16</strong></p>
+</li>
+<li>
+<p><strong>Int8</strong></p>
+</li>
+<li>
+<p><strong>Kernel</strong></p>
+</li>
+<li>
+<p><strong>Linkage</strong></p>
+</li>
+<li>
+<p><strong>Pipes</strong></p>
+</li>
+<li>
+<p><strong>Vector16</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The following capabilities may be optionally supported:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>ImageBasic</strong>, if <code>CL_DEVICE_IMAGE_SUPPORT</code> is <code>CL_TRUE</code></p>
+</li>
+<li>
+<p><strong>Float64</strong>, if the device supports double precision floating-point</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If <strong>ImageBasic</strong> is supported then the following capabilities must also be
+supported:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>ImageReadWrite</strong></p>
+</li>
+<li>
+<p><strong>LiteralSampler</strong></p>
+</li>
+<li>
+<p><strong>Sampled1D</strong></p>
+</li>
+<li>
+<p><strong>Image1D</strong></p>
+</li>
+<li>
+<p><strong>SampledBuffer</strong></p>
+</li>
+<li>
+<p><strong>ImageBuffer</strong></p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_embedded_profile_2">4.2. Embedded Profile</h3>
+<div class="paragraph">
+<p>An OpenCL 2.1 Embedded Profile environment is guaranteed to support the
+following SPIR-V capabilities:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>Address</strong></p>
+</li>
+<li>
+<p><strong>DeviceEnqueue</strong></p>
+</li>
+<li>
+<p><strong>Float16Buffer</strong></p>
+</li>
+<li>
+<p><strong>GenericPointer</strong></p>
+</li>
+<li>
+<p><strong>Groups</strong></p>
+</li>
+<li>
+<p><strong>Int16</strong></p>
+</li>
+<li>
+<p><strong>Int8</strong></p>
+</li>
+<li>
+<p><strong>Kernel</strong></p>
+</li>
+<li>
+<p><strong>Linkage</strong></p>
+</li>
+<li>
+<p><strong>Pipes</strong></p>
+</li>
+<li>
+<p><strong>Vector16</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Furthermore, the following capabilities may optionally be supported:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>ImageBasic</strong>, if <code>CL_DEVICE_IMAGE_SUPPORT</code> is <code>CL_TRUE</code></p>
+</li>
+<li>
+<p><strong>Float64</strong>, if the device supports double precision floating-point</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If <strong>ImageBasic</strong> is supported then the following capabilities must also be
+supported:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>ImageReadWrite</strong></p>
+</li>
+<li>
+<p><strong>LiteralSampler</strong></p>
+</li>
+<li>
+<p><strong>Sampled1D</strong></p>
+</li>
+<li>
+<p><strong>Image1D</strong></p>
+</li>
+<li>
+<p><strong>SampledBuffer</strong></p>
+</li>
+<li>
+<p><strong>ImageBuffer</strong></p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_validation_rules_3">4.3. Validation Rules</h3>
+<div class="paragraph">
+<p>The following are a list of validation rules for SPIR-V modules executing in
+an OpenCL 2.1 environment:</p>
+</div>
+<div class="paragraph">
+<p><em>Scope</em> for <em>Execution</em> is generally limited to:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>Workgroup</strong></p>
+</li>
+<li>
+<p><strong>Subgroup</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p><em>Scope</em> for <em>Memory</em> is generally limited to:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>CrossDevice</strong></p>
+</li>
+<li>
+<p><strong>Device</strong></p>
+</li>
+<li>
+<p><strong>Workgroup</strong></p>
+</li>
+<li>
+<p><strong>Invocation</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p><em>Scope</em> for <em>Execution</em> for the <strong>OpGroupAsyncCopy</strong> and <strong>OpGroupWaitEvents</strong>
+instructions is specifically limited to:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>Workgroup</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The <em>Pointer</em> operand to all <strong>Atomic Instructions</strong> may additionally be a
+pointer to the <strong>Generic</strong> <em>Storage Class</em>, however behavior is still
+undefined if the <strong>Generic</strong> pointer represents a pointer to the <strong>Function</strong>
+<em>Storage Class</em>.</p>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="opencl2_0">5. OpenCL 2.0</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>An OpenCL 2.0 environment must accept SPIR-V 1.0 modules if it includes the
+optional extension <code>cl_khr_il_program</code> in the host API
+<code>CL_PLATFORM_EXTENSIONS</code> or <code>CL_DEVICE_EXTENSIONS</code> string.</p>
+</div>
+<div class="sect2">
+<h3 id="_full_profile_3">5.1. Full Profile</h3>
+<div class="paragraph">
+<p>An OpenCL 2.0 Full Profile environment is guaranteed to support the
+following SPIR-V capabilities:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>Address</strong></p>
+</li>
+<li>
+<p><strong>DeviceEnqueue</strong></p>
+</li>
+<li>
+<p><strong>Float16Buffer</strong></p>
+</li>
+<li>
+<p><strong>GenericPointer</strong></p>
+</li>
+<li>
+<p><strong>Groups</strong></p>
+</li>
+<li>
+<p><strong>Int64</strong></p>
+</li>
+<li>
+<p><strong>Int16</strong></p>
+</li>
+<li>
+<p><strong>Int8</strong></p>
+</li>
+<li>
+<p><strong>Kernel</strong></p>
+</li>
+<li>
+<p><strong>Linkage</strong></p>
+</li>
+<li>
+<p><strong>Pipes</strong></p>
+</li>
+<li>
+<p><strong>Vector16</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The following capabilities may be optionally supported:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>ImageBasic</strong>, if <code>CL_DEVICE_IMAGE_SUPPORT</code> is <code>CL_TRUE</code></p>
+</li>
+<li>
+<p><strong>Float64</strong>, if the device supports double precision floating-point</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If <strong>ImageBasic</strong> is supported then the following capabilities must also be
+supported:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>ImageReadWrite</strong></p>
+</li>
+<li>
+<p><strong>LiteralSampler</strong></p>
+</li>
+<li>
+<p><strong>Sampled1D</strong></p>
+</li>
+<li>
+<p><strong>Image1D</strong></p>
+</li>
+<li>
+<p><strong>SampledBuffer</strong></p>
+</li>
+<li>
+<p><strong>ImageBuffer</strong></p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_embedded_profile_3">5.2. Embedded Profile</h3>
+<div class="paragraph">
+<p>An OpenCL 2.0 Embedded Profile environment is guaranteed to support the
+following SPIR-V capabilities:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>Address</strong></p>
+</li>
+<li>
+<p><strong>DeviceEnqueue</strong></p>
+</li>
+<li>
+<p><strong>Float16Buffer</strong></p>
+</li>
+<li>
+<p><strong>GenericPointer</strong></p>
+</li>
+<li>
+<p><strong>Groups</strong></p>
+</li>
+<li>
+<p><strong>Int16</strong></p>
+</li>
+<li>
+<p><strong>Int8</strong></p>
+</li>
+<li>
+<p><strong>Kernel</strong></p>
+</li>
+<li>
+<p><strong>Linkage</strong></p>
+</li>
+<li>
+<p><strong>Pipes</strong></p>
+</li>
+<li>
+<p><strong>Vector16</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Furthermore, the following capabilities may optionally be supported:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>ImageBasic</strong>, if <code>CL_DEVICE_IMAGE_SUPPORT</code> is <code>CL_TRUE</code></p>
+</li>
+<li>
+<p><strong>Float64</strong>, if the device supports double precision floating-point</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If <strong>ImageBasic</strong> is supported then the following capabilities must also be
+supported:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>ImageReadWrite</strong></p>
+</li>
+<li>
+<p><strong>LiteralSampler</strong></p>
+</li>
+<li>
+<p><strong>Sampled1D</strong></p>
+</li>
+<li>
+<p><strong>Image1D</strong></p>
+</li>
+<li>
+<p><strong>SampledBuffer</strong></p>
+</li>
+<li>
+<p><strong>ImageBuffer</strong></p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_validation_rules_4">5.3. Validation Rules</h3>
+<div class="paragraph">
+<p>The following are a list of validation rules for SPIR-V modules executing in
+an OpenCL 2.0 environment:</p>
+</div>
+<div class="paragraph">
+<p><em>Scope</em> for <em>Execution</em> is generally limited to:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>Workgroup</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p><em>Scope</em> for <em>Memory</em> is generally limited to:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>CrossDevice</strong></p>
+</li>
+<li>
+<p><strong>Device</strong></p>
+</li>
+<li>
+<p><strong>Workgroup</strong></p>
+</li>
+<li>
+<p><strong>Invocation</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The <em>Pointer</em> operand to all <strong>Atomic Instructions</strong> may additionally be a
+pointer to the <strong>Generic</strong> <em>Storage Class</em>, however behavior is still
+undefined if the <strong>Generic</strong> pointer represents a pointer to the <strong>Function</strong>
+<em>Storage Class</em>.</p>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="opencl1_2">6. OpenCL 1.2</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>An OpenCL 1.2 environment must accept SPIR-V 1.0 modules if it includes the
+optional extension <code>cl_khr_il_program</code> in the host API
+<code>CL_PLATFORM_EXTENSIONS</code> or <code>CL_DEVICE_EXTENSIONS</code> string.</p>
+</div>
+<div class="sect2">
+<h3 id="_full_profile_4">6.1. Full Profile</h3>
+<div class="paragraph">
+<p>An OpenCL 1.2 Full Profile environment is guaranteed to support the
+following SPIR-V capabilities:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>Address</strong></p>
+</li>
+<li>
+<p><strong>Float16Buffer</strong></p>
+</li>
+<li>
+<p><strong>Groups</strong></p>
+</li>
+<li>
+<p><strong>Int64</strong></p>
+</li>
+<li>
+<p><strong>Int16</strong></p>
+</li>
+<li>
+<p><strong>Int8</strong></p>
+</li>
+<li>
+<p><strong>Kernel</strong></p>
+</li>
+<li>
+<p><strong>Linkage</strong></p>
+</li>
+<li>
+<p><strong>Vector16</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The following capabilities may be optionally supported:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>ImageBasic</strong>, if <code>CL_DEVICE_IMAGE_SUPPORT</code> is <code>CL_TRUE</code></p>
+</li>
+<li>
+<p><strong>Float64</strong>, if the device supports double precision floating-point</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If <strong>ImageBasic</strong> is supported then the following capabilities must also be
+supported:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>LiteralSampler</strong></p>
+</li>
+<li>
+<p><strong>Sampled1D</strong></p>
+</li>
+<li>
+<p><strong>Image1D</strong></p>
+</li>
+<li>
+<p><strong>SampledBuffer</strong></p>
+</li>
+<li>
+<p><strong>ImageBuffer</strong></p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_embedded_profile_4">6.2. Embedded Profile</h3>
+<div class="paragraph">
+<p>An OpenCL 1.2 Embedded Profile environment is guaranteed to support the
+following SPIR-V capabilities:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>Address</strong></p>
+</li>
+<li>
+<p><strong>Float16Buffer</strong></p>
+</li>
+<li>
+<p><strong>Groups</strong></p>
+</li>
+<li>
+<p><strong>Int16</strong></p>
+</li>
+<li>
+<p><strong>Int8</strong></p>
+</li>
+<li>
+<p><strong>Kernel</strong></p>
+</li>
+<li>
+<p><strong>Linkage</strong></p>
+</li>
+<li>
+<p><strong>Pipes</strong></p>
+</li>
+<li>
+<p><strong>Vector16</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The following capabilities may be optionally supported:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>ImageBasic</strong>, if <code>CL_DEVICE_IMAGE_SUPPORT</code> is <code>CL_TRUE</code></p>
+</li>
+<li>
+<p><strong>Float64</strong>, if the device supports double precision floating-point</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If <strong>ImageBasic</strong> is supported then the following capabilities must also be
+supported:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>LiteralSampler</strong></p>
+</li>
+<li>
+<p><strong>Sampled1D</strong></p>
+</li>
+<li>
+<p><strong>Image1D</strong></p>
+</li>
+<li>
+<p><strong>SampledBuffer</strong></p>
+</li>
+<li>
+<p><strong>ImageBuffer</strong></p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_validation_rules_5">6.3. Validation Rules</h3>
+<div class="paragraph">
+<p>The following are a list of validation rules for SPIR-V modules executing in
+an OpenCL 1.2 environment:</p>
+</div>
+<div class="paragraph">
+<p><em>Scope</em> for <em>Execution</em> is generally limited to:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>Workgroup</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p><em>Scope</em> for <em>Memory</em> is generally limited to:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>CrossDevice</strong></p>
+</li>
+<li>
+<p><strong>Device</strong></p>
+</li>
+<li>
+<p><strong>Workgroup</strong></p>
+</li>
+<li>
+<p><strong>Invocation</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The following <strong>Group Instructions</strong> are not supported:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>OpGroupAll</strong></p>
+</li>
+<li>
+<p><strong>OpGroupAny</strong></p>
+</li>
+<li>
+<p><strong>OpGroupBroadcast</strong></p>
+</li>
+<li>
+<p><strong>OpGroupIAdd</strong></p>
+</li>
+<li>
+<p><strong>OpGroupFAdd</strong></p>
+</li>
+<li>
+<p><strong>OpGroupFMin</strong></p>
+</li>
+<li>
+<p><strong>OpGroupUMin</strong></p>
+</li>
+<li>
+<p><strong>OpGroupSMin</strong></p>
+</li>
+<li>
+<p><strong>OpGroupFMax</strong></p>
+</li>
+<li>
+<p><strong>OpGroupUMax</strong></p>
+</li>
+<li>
+<p><strong>OpGroupSMax</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For the <strong>Barrier Instructions</strong> <strong>OpControlBarrier</strong> and <strong>OpMemoryBarrier</strong>, the
+<em>Scope</em> for execution must be <strong>Workgroup</strong>, the <em>Scope</em> for memory must be
+<strong>Workgroup</strong>, and the <em>Memory Semantics</em> must be <strong>SequentiallyConsistent</strong>.</p>
+</div>
+<div class="paragraph">
+<p>For the <strong>Atomic Instructions</strong>, the <em>Scope</em> must be <strong>Device</strong>, and the <em>Memory
+Semantics</em> must be <strong>Relaxed</strong>.</p>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="opencl_extensions">7. OpenCL Extensions</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>An OpenCL environment may be modified by <a href="#opencl-extension-spec">OpenCL
+extensions</a>.  For example, some OpenCL extensions may require support
+for support for additional SPIR-V capabilities or instructions, or by
+relaxing SPIR-V restrictions.
+Some OpenCL extensions may modify the OpenCL environment by requiring
+consumption of a SPIR-V module that uses a SPIR-V extension.  In this case,
+the implementation will include the OpenCL extension in the host API
+<code>CL_PLATFORM_EXTENSIONS</code> or <code>CL_DEVICE_EXTENSIONS</code> string, but not the
+corresponding SPIR-V extension.</p>
+</div>
+<div class="paragraph">
+<p>This section describes how the OpenCL environment is modified by Khronos
+(<code>khr</code>) OpenCL extensions.  Other OpenCL extensions, such as multi-vendor
+(<code>ext</code>) extensions or vendor-specific extensions, describe how they modify
+the OpenCL environment in their individual extension specifications.  The
+Khronos OpenCL extensions require no corresponding SPIR-V extensions.</p>
+</div>
+<div class="sect2">
+<h3 id="_declaring_spir_v_extensions">7.1. Declaring SPIR-V Extensions</h3>
+<div class="paragraph">
+<p>A SPIR-V module declares use of a SPIR-V extension using <strong>OpExtension</strong> and
+the name of the SPIR-V extension.  For example:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>OpExtension "SPV_KHR_extension_name"</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Only use of SPIR-V extensions may be declared in a SPIR-V module using
+<strong>OpExtension</strong>; there is never a need to declare use of an OpenCL extension
+in a SPIR-V module using <strong>OpExtension</strong>.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_full_and_embedded_profile_extensions">7.2. Full and Embedded Profile Extensions</h3>
+<div class="sect3">
+<h4 id="_code_cl_khr_3d_image_writes_code">7.2.1. <code>cl_khr_3d_image_writes</code></h4>
+<div class="paragraph">
+<p>If the OpenCL environment supports the extension <code>cl_khr_3d_image_writes</code>,
+then the environment must accept <em>Image</em> operands to <strong>OpImageWrite</strong> that
+are declared with with dimensionality <em>Dim</em> equal to <strong>3D</strong>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_code_cl_khr_depth_images_code">7.2.2. <code>cl_khr_depth_images</code></h4>
+<div class="paragraph">
+<p>If the OpenCL environment supports the extension <code>cl_khr_depth_images</code>,
+then the environment must accept modules that declare 2D depth image types
+using <strong>OpTypeImage</strong> with dimensionality <em>Dim</em> equal to <strong>2D</strong> and <em>Depth</em>
+equal to  1, indicating a depth image.  2D depth images may optionally be
+<em>Arrayed</em>, if supported.</p>
+</div>
+<div class="paragraph">
+<p>Additionally, the following Image Channel Orders may be returned by
+<strong>OpImageQueryOrder</strong>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>Depth</strong></p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_code_cl_khr_device_enqueue_local_arg_types_code">7.2.3. <code>cl_khr_device_enqueue_local_arg_types</code></h4>
+<div class="paragraph">
+<p>If the OpenCL environment supports the extension
+<code>cl_khr_device_enqueue_local_arg_types</code>, then then environment will allow
+<em>Invoke</em> functions to be passed to <strong>OpEnqueueKernel</strong> with <strong>Workgroup</strong>
+memory pointer parameters of any type.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_code_cl_khr_fp16_code">7.2.4. <code>cl_khr_fp16</code></h4>
+<div class="paragraph">
+<p>If the OpenCL environment supports the extension <code>cl_khr_fp16</code>, then the
+environment must accept modules that declare the following SPIR-V
+capabilities:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>Float16</strong></p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_code_cl_khr_fp64_code">7.2.5. <code>cl_khr_fp64</code></h4>
+<div class="paragraph">
+<p>If the OpenCL environment supports the extension <code>cl_khr_fp64</code>, then the
+environment must accept modules that declare the following SPIR-V
+capabilities:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>Float64</strong></p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_code_cl_khr_gl_depth_images_code">7.2.6. <code>cl_khr_gl_depth_images</code></h4>
+<div class="paragraph">
+<p>If the OpenCL environment supports the extension <code>cl_khr_gl_depth_images</code>,
+then the following Image Channel Orders may additionally be returned by
+<strong>OpImageQueryOrder</strong>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>DepthStencil</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Also, the following Image Channel Data Types may additionally be returned by
+<strong>OpImageQueryFormat</strong>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>UnormInt24</strong></p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_code_cl_khr_gl_msaa_sharing_code">7.2.7. <code>cl_khr_gl_msaa_sharing</code></h4>
+<div class="paragraph">
+<p>If the OpenCL environment supports the extension <code>cl_khr_gl_msaa_sharing</code>,
+then the environment must accept modules that declare 2D multi-sampled
+image types using <strong>OpTypeImage</strong> with dimensionality <em>Dim</em> equal to <strong>2D</strong> and
+<em>MS</em> equal to 1, indicating multi-sampled content.  2D multi-sampled images
+may optionally be <em>Arrayed</em> or <em>Depth</em> images, if supported.</p>
+</div>
+<div class="paragraph">
+<p>The 2D multi-sampled images may be used with the following instructions:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>OpImageRead</strong></p>
+</li>
+<li>
+<p><strong>OpImageQuerySizeLod</strong></p>
+</li>
+<li>
+<p><strong>OpImageQueryFormat</strong></p>
+</li>
+<li>
+<p><strong>OpImageQueryOrder</strong></p>
+</li>
+<li>
+<p><strong>OpImageQuerySamples</strong></p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_code_cl_khr_int64_base_atomics_code_and_code_cl_khr_int64_extended_atomics_code">7.2.8. <code>cl_khr_int64_base_atomics</code> and <code>cl_khr_int64_extended_atomics</code></h4>
+<div class="paragraph">
+<p>If the OpenCL environment supports the extension <code>cl_khr_int64_base_atomics</code>
+or <code>cl_khr_int64_extended_atomics</code>, then the environment must support 64-bit
+integer operands for all of the SPIR-V <strong>Atomic Instructions</strong>.</p>
+</div>
+<div class="paragraph">
+<p>When the <strong>WorkgroupMemory</strong> <em>Memory Semantic</em> is used the <em>Scope</em> must be
+<strong>Workgroup</strong>.</p>
+</div>
+<div class="paragraph">
+<p>Note: OpenCL environments that consume SPIR-V must support both
+<code>cl_khr_int64_base_atomics</code> and <code>cl_khr_int64_extended_atomics</code> or neither
+of these extensions.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_code_cl_khr_mipmap_image_code">7.2.9. <code>cl_khr_mipmap_image</code></h4>
+<div class="paragraph">
+<p>If the OpenCL environment supports the extension <code>cl_khr_mipmap_image</code>,
+then the environment must accept non-zero optional <strong>Lod</strong> <em>Image Operands</em>
+for the following instructions:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>OpImageSampleExplicitLod</strong></p>
+</li>
+<li>
+<p><strong>OpImageFetch</strong></p>
+</li>
+<li>
+<p><strong>OpImageRead</strong></p>
+</li>
+<li>
+<p><strong>OpImageQuerySizeLod</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Note: Implementations that support <code>cl_khr_mipmap_image</code> are not guaranteed
+to support the <strong>ImageMipmap</strong> capability, since this extension does not
+require non-zero optional <strong>Lod</strong> <em>Image Operands</em> for <strong>OpImageWrite</strong>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_code_cl_khr_mipmap_image_writes_code">7.2.10. <code>cl_khr_mipmap_image_writes</code></h4>
+<div class="paragraph">
+<p>If the OpenCL environment supports the extension <code>cl_khr_mipmap_image_writes</code>,
+then the environment must accept non-zero optional <strong>Lod</strong> <em>Image Operands</em>
+for the following instructions:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>OpImageWrite</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Note: An implementation that supports <code>cl_khr_mipmap_image_writes</code> must also
+support <code>cl_khr_mipmap_image</code>, and support for both extensions does
+guarantee support for the <strong>ImageMipmap</strong> capability.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_code_cl_khr_subgroups_code">7.2.11. <code>cl_khr_subgroups</code></h4>
+<div class="paragraph">
+<p>If the OpenCL environment supports the extension <code>cl_khr_subgroups</code>, then
+the environment will generally allows the scope for <em>Execution</em> to include:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>Subgroup</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>However, the <em>Scope</em> for <em>Execution</em> for the <strong>OpGroupAsyncCopy</strong> and
+<strong>OpGroupWaitEvents</strong> instructions still is limited to:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>Workgroup</strong></p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_code_cl_khr_subgroup_named_barrier_code">7.2.12. <code>cl_khr_subgroup_named_barrier</code></h4>
+<div class="paragraph">
+<p>If the OpenCL environment supports the extension
+<code>cl_khr_subgroup_named_barrier</code>, then the environment must accept modules
+that declare the following SPIR-V capabilities:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>NamedBarrier</strong></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_embedded_profile_extensions">7.3. Embedded Profile Extensions</h3>
+<div class="sect3">
+<h4 id="_code_cles_khr_int64_code">7.3.1. <code>cles_khr_int64</code></h4>
+<div class="paragraph">
+<p>If the OpenCL environment supports the extension <code>cles_khr_int64</code>, then the
+environment must accept modules that declare the following SPIR-V
+capabilities:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>Int64</strong></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="numerical_compliance">8. OpenCL Numerical Compliance</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>This section describes features of the <a href="#cpp14-spec">C++14</a> and
+<a href="#ieee-754-spec">IEEE-754</a> standards that must be supported by all OpenCL
+compliant devices.</p>
+</div>
+<div class="paragraph">
+<p>This section describes the functionality that must be supported by all
+OpenCL devices for single precision floating-point numbers.
+Currently, only single precision floating-point is a requirement.
+Half precision floating-point is an optional feature indicated by the
+<strong>Float16</strong> capability.
+Double precision floating-point is also an optional feature indicated by the
+<strong>Float64</strong> capability.</p>
+</div>
+<div class="sect2">
+<h3 id="_rounding_modes">8.1. Rounding Modes</h3>
+<div class="paragraph">
+<p>Floating-point calculations may be carried out internally with extra
+precision and then rounded to fit into the destination type.
+IEEE 754 defines four possible rounding modes:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><em>Round to nearest even</em></p>
+</li>
+<li>
+<p><em>Round toward +infinity</em></p>
+</li>
+<li>
+<p><em>Round toward -infinity</em></p>
+</li>
+<li>
+<p><em>Round toward zero</em></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The complete set of rounding modes supported by the device are described by
+the <code>CL_DEVICE_SINGLE_FP_CONFIG</code>, <code>CL_DEVICE_HALF_FP_CONFIG</code>, and
+<code>CL_DEVICE_DOUBLE_FP_CONFIG</code> device queries.</p>
+</div>
+<div class="paragraph">
+<p>For double precision operations, <em>Round to nearest even</em> is a required
+rounding mode, and is therefore the default rounding mode for double
+precision operations.</p>
+</div>
+<div class="paragraph">
+<p>For single precision operations, devices supporting the full profile must
+support <em>Round to nearest even</em>, therefore for full profile devices this is
+the default rounding mode for single precision operations.
+Devices supporting the embedded profile may support either <em>Round to nearest
+even</em> or <em>Round toward zero</em> as the default rounding mode for single
+precision operations.</p>
+</div>
+<div class="paragraph">
+<p>For half precision operations, devices may support either <em>Round to nearest
+even</em> or <em>Round toward zero</em> as the default rounding mode for half precision
+operations.</p>
+</div>
+<div class="paragraph">
+<p>Only static selection of rounding mode is supported.
+Dynamically reconfiguring the rounding mode as specified by the IEEE 754
+spec is not supported.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_rounding_modes_for_conversions">8.2. Rounding Modes for Conversions</h3>
+<div class="paragraph">
+<p>Results of the following conversion instructions may include an optional
+<strong>FPRoundingMode</strong> decoration:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>OpConvertFToU</strong></p>
+</li>
+<li>
+<p><strong>OpConvertFToS</strong></p>
+</li>
+<li>
+<p><strong>OpConvertSToF</strong></p>
+</li>
+<li>
+<p><strong>OpConvertUToF</strong></p>
+</li>
+<li>
+<p><strong>OpFConvert</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The <strong>FPRoundingMode</strong> decoration may not be added to results of any other
+instruction.</p>
+</div>
+<div class="paragraph">
+<p>If no rounding mode is specified explicitly via an <strong>FPRoundingMode</strong>
+decoration, then the default rounding mode for conversion operations is:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><em>Round to nearest even</em>, for conversions to floating-point types.</p>
+</li>
+<li>
+<p><em>Round toward zero</em>, for conversions from floating-point to integer types.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_out_of_range_conversions">8.3. Out-of-Range Conversions</h3>
+<div class="paragraph">
+<p>When a conversion operand is either greater than the greatest representable
+destination value or less than the least representable destination value,
+it is said to be out-of-range.</p>
+</div>
+<div class="paragraph">
+<p>Converting an out-of-range integer to an integer type without a
+<strong>SaturatedConversion</strong> decoration follows <a href="#C99-spec">C99</a>/<a href="#cpp14-spec">C++14</a> conversion rules.</p>
+</div>
+<div class="paragraph">
+<p>Converting an out-of-range floating point number to an integer type without
+a <strong>SaturatedConversion</strong> decoration is implementation-defined.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_inf_nan_and_denormalized_numbers">8.4. INF, NaN, and Denormalized Numbers</h3>
+<div class="paragraph">
+<p>INFs and NaNs must be supported.
+Support for signaling NaNs is not required.</p>
+</div>
+<div class="paragraph">
+<p>Support for denormalized numbers with single precision and half precision
+floating-point is optional.
+Denormalized single precision or half precision floating-point numbers
+passed as the input or produced as the output of single precision or half
+precision floating-point operations may be flushed to zero.
+Support for denormalized numbers is required for double precision
+floating-point.</p>
+</div>
+<div class="paragraph">
+<p>Support for INFs, NaNs, and denormalized numbers is described by the
+<code>CL_FP_DENORM</code> and <code>CL_FP_INF_NAN</code> bits in the <code>CL_DEVICE_SINGLE_FP_CONFIG</code>,
+<code>CL_DEVICE_HALF_FP_CONFIG</code>, and <code>CL_DEVICE_DOUBLE_FP_CONFIG</code> device queries.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_floating_point_exceptions">8.5. Floating-Point Exceptions</h3>
+<div class="paragraph">
+<p>Floating-point exceptions are disabled in OpenCL.
+The result of a floating-point exception must match the IEEE 754 spec for
+the exceptions-not-enabled case.
+Whether and when the implementation sets floating-point flags or raises
+floating-point exceptions is implementation-defined.</p>
+</div>
+<div class="paragraph">
+<p>This standard provides no method for querying, clearing or setting
+floating-point flags or trapping raised exceptions.
+Due to non-performance, non-portability of trap mechanisms, and the
+impracticality of servicing precise exceptions in a vector context
+(especially on heterogeneous hardware), such features are discouraged.</p>
+</div>
+<div class="paragraph">
+<p>Implementations that nevertheless support such operations through an
+extension to the standard shall initialize with all exception flags cleared
+and the exception masks set so that exceptions raised by arithmetic
+operations do not trigger a trap to be taken.
+If the underlying work is reused by the implementation, the implementation
+is however not responsible for re-clearing the flags or resetting exception
+masks to default values before entering the kernel.
+That is to say that kernels that do not inspect flags or enable traps are
+licensed to expect that their arithmetic will not trigger a trap.
+Those kernels that do examine flags or enable traps are responsible for
+clearing flag state and disabling all traps before returning control to the
+implementation.
+Whether or when the underlying work-item (and accompanying global
+floating-point state if any) is reused is implementation-defined.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="relative-error-as-ulps">8.6. Relative Error as ULPs</h3>
+<div class="paragraph">
+<p>In this section we discuss the maximum relative error defined as ulp (units
+in the last place).
+Addition, subtraction, multiplication, fused multiply-add, and conversion
+between integer and a single precision floating-point format are IEEE 754
+compliant and are therefore correctly rounded.
+Conversion between floating-point formats and explicit conversions must be
+correctly rounded.</p>
+</div>
+<div class="paragraph">
+<p>The ULP is defined as follows:</p>
+</div>
+<div class="quoteblock">
+<blockquote>
+<div class="paragraph">
+<p>If x is a real number that lies between two finite consecutive
+floating-point numbers a and b, without being equal to one of them, then
+ulp(x) = |b - a|, otherwise ulp(x) is the distance between the two non-equal
+finite floating-point numbers nearest x.
+Moreover, ulp(NaN) is NaN.</p>
+</div>
+</blockquote>
+</div>
+<div class="paragraph">
+<p>Attribution: This definition was taken with consent from Jean-Michel Muller
+with slight clarification for behavior at zero.  Refer to: <a href="#ulp-definition">On the definition of ulp(x)</a>.</p>
+</div>
+<div class="paragraph">
+<p>0 ULP is used for math functions that do not require rounding.
+The reference value used to compute the ULP value is the infinitely precise
+result.</p>
+</div>
+<div class="sect3">
+<h4 id="_ulp_values_for_math_instructions_full_profile">8.6.1. ULP Values for Math Instructions - Full Profile</h4>
+<div class="paragraph">
+<p>The ULP Values for Math Instructions table below describes the minimum
+accuracy of floating-point math arithmetic instructions for full profile
+devices given as ULP values.</p>
+</div>
+<table id="ulp_values_for_math_instructions" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 5. ULP Values for Math Instructions - Full Profile</caption>
+<colgroup>
+<col style="width: 31%;">
+<col style="width: 23%;">
+<col style="width: 23%;">
+<col style="width: 23%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>SPIR-V Instruction</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Minimum Accuracy - Float64</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Minimum Accuracy - Float32</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Minimum Accuracy - Float16</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpFAdd</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpFSub</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpFMul</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpFDiv</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2.5 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>acos</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>acosh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>acospi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>asin</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>asinh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>asinpi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>atan</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>atanh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>atanpi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>atan2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 6 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 6 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>atan2pi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 6 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 6 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>cbrt</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>ceil</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>copysign</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>cos</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>cosh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>cospi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>erfc</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>erf</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>exp</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>exp2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>exp10</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>expm1</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>fabs</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>fdim</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>floor</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>fma</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>fmax</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>fmin</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>fmod</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>fract</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>frexp</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>hypot</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>ilogb</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>ldexp</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>lgamma</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>lgamma_r</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>log</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>log2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>log10</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>log1p</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>logb</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>mad</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented either as a correctly rounded fma, or as a multiply followed
+  by an add, both of which are correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented either as a correctly rounded fma, or as a multiply followed
+  by an add, both of which are correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented either as a correctly rounded fma, or as a multiply followed
+  by an add, both of which are correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>maxmag</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>minmag</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>modf</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>nan</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>nextafter</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>pow</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>pown</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>powr</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>remainder</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>remquo</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp for the remainder, at least the lower 7 bits of the integral quotient</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp for the remainder, at least the lower 7 bits of the integral quotient</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp for the remainder, at least the lower 7 bits of the integral quotient</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>rint</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>rootn</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>round</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>rsqrt</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 1 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>sin</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>sincos</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp for sine and cosine values</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp for sine and cosine values</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp for sine and cosine values</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>sinh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>sinpi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>sqrt</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>tan</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>tanh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>tanpi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 6 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 6 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>tgamma</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>trunc</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>half_cos</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>half_divide</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>half_exp</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>half_exp2</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>half_exp10</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>half_log</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>half_log2</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>half_log10</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>half_powr</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>half_recip</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>half_rsqrt</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>half_sin</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>half_sqrt</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>half_tan</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>native_cos</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>native_divide</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>native_exp</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>native_exp2</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>native_exp10</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>native_log</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>native_log2</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>native_log10</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>native_powr</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>native_recip</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>native_rsqrt</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>native_sin</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>native_sqrt</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>native_tan</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_ulp_values_for_math_instructions_embedded_profile">8.6.2. ULP Values for Math Instructions - Embedded Profile</h4>
+<div class="paragraph">
+<p>The ULP Values for Math instructions for Embedded Profile table below
+describes the minimum accuracy of floating-point math arithmetic operations
+given as ULP values for the embedded profile.</p>
+</div>
+<table id="ulp_values_for_math_instructions_for_embedded_profile" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 6. ULP Values for Math Instructions - Embedded Profile</caption>
+<colgroup>
+<col style="width: 31%;">
+<col style="width: 23%;">
+<col style="width: 23%;">
+<col style="width: 23%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>SPIR-V Instruction</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Minimum Accuracy - Float64</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Minimum Accuracy - Float32</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Minimum Accuracy - Float16</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpFAdd</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpFSub</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpFMul</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpFDiv</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 1 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>acos</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>acosh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>acospi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>asin</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>asinh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>asinpi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>atan</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>atanh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>atanpi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>atan2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 6 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 6 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>atan2pi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 6 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 6 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>cbrt</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>ceil</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>copysign</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>cos</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>cosh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>cospi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>erfc</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>erf</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>exp</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>exp2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>exp10</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>expm1</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>fabs</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>fdim</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>floor</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>fma</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>fmax</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>fmin</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>fmod</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>fract</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>frexp</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>hypot</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>ilogb</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>ldexp</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>lgamma</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>lgamma_r</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>log</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>log2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>log10</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>log1p</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>logb</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>mad</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemention-defined</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemention-defined</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemention-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>maxmag</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>minmag</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>modf</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>nan</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>nextafter</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>pow</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>pown</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>powr</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>remainder</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>remquo</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp for the remainder, at least the lower 7 bits of the integral quotient</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp for the remainder, at least the lower 7 bits of the integral quotient</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp for the remainder, at least the lower 7 bits of the integral quotient</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>rint</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>rootn</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>round</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>rsqrt</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 1 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>sin</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>sincos</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp for sine and cosine values</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp for sine and cosine values</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp for sine and cosine values</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>sinh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>sinpi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>sqrt</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 1 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>tan</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>tanh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>tanpi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 6 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 6 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>tgamma</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 16 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>trunc</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>half_cos</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>half_divide</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>half_exp</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>half_exp2</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>half_exp10</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>half_log</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>half_log2</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>half_log10</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>half_powr</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>half_recip</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>half_rsqrt</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>half_sin</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>half_sqrt</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>half_tan</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 8192 ulp</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>native_cos</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>native_divide</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>native_exp</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>native_exp2</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>native_exp10</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>native_log</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>native_log2</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>native_log10</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>native_powr</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>native_recip</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>native_rsqrt</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>native_sin</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>native_sqrt</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>native_tan</strong></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_ulp_values_for_math_instructions_unsafe_math_optimizations_enabled">8.6.3. ULP Values for Math Instructions - Unsafe Math Optimizations Enabled</h4>
+<div class="paragraph">
+<p>The ULP Values for Math Instructions with Unsafe Math Optimizations table below
+describes the minimum accuracy of commonly used single precision
+floating-point math arithmetic instructions given as ULP values if the
+<em>-cl-unsafe-math-optimizations</em> compiler option is specified when compiling or
+building the OpenCL program.</p>
+</div>
+<div class="paragraph">
+<p>For derived implementations, the operations used in the derivation may
+themselves be relaxed according to the ULP Values for Math Instructions with
+Unsafe Math Optimizations table.</p>
+</div>
+<div class="paragraph">
+<p>The minimum accuracy of math functions not defined in the ULP Values for
+Math Instructions with Unsafe Math Optimizations table when the
+<em>-cl-unsafe-math-optimizations</em> compiler option is specified is as defined in the
+<a href="#ulp_values_for_math_instructions">ULP Values for Math Instructions for Full
+Profile</a> table when operating in the full profile, and as defined in the
+<a href="#ulp_values_for_math_instructions_for_embedded_profile">ULP Values for Math
+instructions for Embedded Profile</a> table when operating in the embedded
+profile.</p>
+</div>
+<table id="ulp_values_for_math_instructions_with_fast_relaxed_math" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 7. ULP Values for Single Precision Math Instructions with <em>-cl-unsafe-math-optimizations</em></caption>
+<colgroup>
+<col style="width: 30%;">
+<col style="width: 70%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>SPIR-V Instruction</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Minimum Accuracy</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpFDiv</strong> for 1.0 / <em>x</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2.5 ulp for x in the domain of 2<sup>-126</sup> to 2<sup>126</sup> for the full profile,
+  and &lt;= 3 ulp for the embedded profile.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpFDiv</strong> for <em>x</em> / <em>y</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2.5 ulp for x in the domain of 2<sup>-62</sup> to 2<sup>62</sup> and <em>y</em> in the domain
+  of 2<sup>-62</sup> to 2<sup>62</sup> for the full profile, and &lt;= 3 ulp for the embedded
+  profile.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>acos</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4096 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>acosh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented as log( x + sqrt(x*x - 1) ).</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>acospi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented as acos(x) * M_PI_F.
+  For non-derived implementations, the error is &lt;= 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>asin</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4096 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>asinh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented as log( x + sqrt(x*x + 1) ).</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>asinpi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented as asin(x) * M_PI_F.
+  For non-derived implementations, the error is &lt;= 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>atan</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4096 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>atanh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Defined for x in the domain (-1, 1).
+  For x in [-2<sup>-10</sup>, 2<sup>-10</sup>], implemented as x.
+  For x outside of [-2<sup>-10</sup>, 2<sup>-10</sup>], implemented as 0.5f * log( (1.0f + x)
+  / (1.0f - x) ).
+  For non-derived implementations, the error is &lt;= 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>atanpi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented as atan(x) * M_1_PI_F.
+  For non-derived implementations, the error is &lt;= 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>atan2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented as atan(y/x) for x &gt; 0, atan(y/x) + M_PI_F for x &lt; 0 and y &gt;
+  0, and atan(y/x) - M_PI_F for x &lt; 0 and y &lt; 0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>atan2pi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented as atan2(y, x) * M_1_PI_F.
+  For non-derived implementations, the error is &lt;= 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>cbrt</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented as rootn(x, 3).
+  For non-derived implementations, the error is &lt;= 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>cos</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">For x in the domain [-π, π], the maximum absolute error is &lt;=
+  2<sup>-11</sup> and larger otherwise.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>cosh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Defined for x in the domain [-∞, ∞] and implemented as 0.5f * (
+  exp(x) + exp(-x) ).
+  For non-derived implementations, the error is &lt;= 8192 ULP.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>cospi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">For x in the domain [-1, 1], the maximum absolute error is &lt;= 2<sup>-11</sup> and
+  larger otherwise.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>exp</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 + floor( fabs(2 * x) ) ulp for the full profile, and &lt;= 4 ulp for
+  the embedded profile.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>exp2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 + floor( fabs(2 * x) ) ulp for the full profile, and &lt;= 4 ulp for
+  the embedded profile.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>exp10</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Derived implementations implement this as exp2( x * log2(10) ).
+  For non-derived implementations, the error is &lt;= 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>expm1</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Derived implementations implement this as exp(x) - 1.
+  For non-derived implementations, the error is &lt;= 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>log</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">For x in the domain [0.5, 2] the maximum absolute error is &lt;= 2<sup>-21</sup>;
+  otherwise the maximum error is &lt;=3 ulp for the full profile and &lt;= 4 ulp
+  for the embedded profile</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>log2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">For x in the domain [0.5, 2] the maximum absolute error is &lt;= 2<sup>-21</sup>;
+  otherwise the maximum error is &lt;=3 ulp for the full profile and &lt;= 4 ulp
+  for the embedded profile</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>log10</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">For x in the domain [0.5, 2] the maximum absolute error is &lt;= 2<sup>-21</sup>;
+  otherwise the maximum error is &lt;=3 ulp for the full profile and &lt;= 4 ulp
+  for the embedded profile</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>log1p</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Derived implementations implement this as log(x + 1).
+  For non-derived implementations, the error is &lt;= 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>pow</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Undefined for x = 0 and y = 0.
+  Undefined for x &lt; 0 and non-integer y.
+  Undefined for x &lt; 0 and y outside the domain [-2<sup>24</sup>, 2<sup>24</sup>].
+  For x &gt; 0 or x &lt; 0 and even y, derived implementations implement this as
+  exp2( y * log2(x) ).
+  For x &lt; 0 and odd y, derived implementations implement this as -exp2( y *
+  log2(fabs(x) ).
+  For x == 0 and nonzero y, derived implementations return zero.
+  For non-derived implementations, the error is &lt;= 8192 ULP.</p>
+<p class="tableblock">  On some implementations, powr() or pown() may perform faster
+  than pow().
+  If x is known to be &gt;= 0, consider using powr() in place of pow(),
+  or if y is known to be an integer, consider using pown() in place of
+  pow().</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>pown</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Defined only for integer values of y.
+  Undefined for x = 0 and y = 0.
+  For x &gt;= 0 or x &lt; 0 and even y, derived implementations implement this as
+  exp2( y * log2(x) ).
+  For x &lt; 0 and odd y, derived implementations implement this as -exp2( y *
+  log2( fabs(x) ) ).
+  For non-derived implementations, the error is &lt;= 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>powr</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Defined only for x &gt;= 0.
+  Undefined for x = 0 and y = 0.
+  Derived implementations implement this as exp2( y * log2(x) ).
+  For non-derived implementations, the error is &lt;= 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>rootn</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Defined for x &gt; 0 when y is non-zero, derived implementations implement
+  this case as exp2( log2(x) / y ).
+  Defined for x &lt; 0 when y is odd, derived implementations implement this
+  case as -exp2( log2(-x) / y ).
+  Defined for x = +/-0 when y &gt; 0, derived implementations will return +0 in
+  this case.
+  For non-derived implementations, the error is &lt;= 8192 ULP.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>sin</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">For x in the domain [-π, π], the maximum absolute error is &lt;=
+  2<sup>-11</sup> and larger otherwise.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>sincos</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">ulp values as defined for sin(x) and cos(x).</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>sinh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Defined for x in the domain [-∞, ∞].
+  For x in [-2<sup>-10</sup>, 2<sup>-10</sup>], derived implementations implement as x.
+  For x outside of [-2<sup>-10</sup>, 2<sup>-10</sup>], derived implement as 0.5f * ( exp(x) -
+  exp(-x) ).
+  For non-derived implementations, the error is &lt;= 8192 ULP.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>sinpi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">For x in the domain [-1, 1], the maximum absolute error is &lt;= 2<sup>-11</sup> and
+  larger otherwise.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>tan</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Derived implementations implement this as sin(x) * ( 1.0f / cos(x) ).
+  For non-derived implementations, the error is &lt;= 8192 ulp.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>tanh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Defined for x in the domain [-∞, ∞].
+  For x in [-2<sup>-10</sup>, 2<sup>-10</sup>], derived implementations implement as x.
+  For x outside of [-2<sup>-10</sup>, 2<sup>-10</sup>], derived implementations implement as
+  (exp(x) - exp(-x)) / (exp(x) + exp(-x)).
+  For non-derived implementations, the error is &lt;= 8192 ULP.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpExtInst</strong> <strong>tanpi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Derived implementations implement this as tan(x * M_PI_F).
+  For non-derived implementations, the error is &lt;= 8192 ulp for x in the
+  domain [-1, 1].</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpFMul</strong> and <strong>OpFAdd</strong>,<br>
+  for <em>x</em> * <em>y</em> + <em>z</em></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implemented either as a correctly rounded fma or as a multiply and an add
+  both of which are correctly rounded.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_edge_case_behavior">8.7. Edge Case Behavior</h3>
+<div class="paragraph">
+<p>The edge case behavior of the math functions shall conform to sections F.9
+and G.6 of ISO/IEC 9899:TC 2, except where noted below in the
+<em><a href="#additional-requirements-beyond-isoiec-9899tc2">Additional Requirements
+Beyond ISO/IEC 9899:TC2</a> section</em>.</p>
+</div>
+<div class="sect3">
+<h4 id="additional-requirements-beyond-isoiec-9899tc2">8.7.1. Additional Requirements Beyond ISO/IEC 9899:TC2</h4>
+<div class="paragraph">
+<p>Functions that return a NaN with more than one NaN operand shall return one
+of the NaN operands.
+Functions that return a NaN operand may silence the NaN if it is a signaling
+NaN.
+A non-signaling NaN shall be converted to a non-signaling NaN.
+A signaling NaN shall be converted to a NaN, and should be converted to a
+non-signaling NaN.
+How the rest of the NaN payload bits or the sign of NaN is converted is
+undefined.</p>
+</div>
+<div class="paragraph">
+<p>The usual allowances for rounding error (<em><a href="#relative-error-as-ulps">Relative
+Error as ULPs</a> section</em>) or flushing behavior
+(<em><a href="#edge-case-behavior-in-flush-to-zero-mode">Edge Case Behavior in Flush To
+Zero Mode</a> section</em>) shall not apply for those values for which <em>section
+F.9</em> of ISO/IEC 9899:,TC2, or
+<em><a href="#additional-requirements-beyond-isoiec-9899tc2">Additional Requirements
+Beyond ISO/IEC 9899:TC2</a></em> and
+<em><a href="#edge-case-behavior-in-flush-to-zero-mode">Edge Case Behavior in Flush To
+Zero Mode</a> sections</em> below (and similar sections for other floating-point
+precisions) prescribe a result (e.g. ceil( -1 &lt; x &lt; 0 ) returns -0).
+Those values shall produce exactly the prescribed answers, and no other.
+Where the ± symbol is used, the sign shall be preserved.
+For example, sin(±0) = ±0 shall be interpreted to mean sin(+0)
+is +0 and sin(-0) is -0.</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>OpExtInst</strong> <strong>acospi</strong>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>acospi( 1 ) = +0.</p>
+</li>
+<li>
+<p>acospi( x ) returns a NaN for | x | &gt; 1.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><strong>OpExtInst</strong> <strong>asinpi</strong>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>asinpi( ±0 ) = ±0.</p>
+</li>
+<li>
+<p>asinpi( x ) returns a NaN for | x | &gt; 1.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><strong>OpExtInst</strong> <strong>atanpi</strong>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>atanpi( ±0 ) = ±0.</p>
+</li>
+<li>
+<p>atanpi ( ±∞ ) = ±0.5.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><strong>OpExtInst</strong> <strong>atan2pi</strong>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>atan2pi ( ±0, -0 ) = ±1.</p>
+</li>
+<li>
+<p>atan2pi ( ±0, +0 ) = ± 0.</p>
+</li>
+<li>
+<p>atan2pi ( ±0, x ) returns ± 1 for x &lt; 0.</p>
+</li>
+<li>
+<p>atan2pi ( ±0, x) returns ± 0 for x &gt; 0.</p>
+</li>
+<li>
+<p>atan2pi ( y, ±0 ) returns -0.5 for y &lt; 0.</p>
+</li>
+<li>
+<p>atan2pi ( y, ±0 ) returns 0.5 for y &gt; 0.</p>
+</li>
+<li>
+<p>atan2pi ( ±y, -∞ ) returns ± 1 for finite y &gt; 0.</p>
+</li>
+<li>
+<p>atan2pi ( ±y, +∞ ) returns ± 0 for finite y &gt; 0.</p>
+</li>
+<li>
+<p>atan2pi ( ±∞, x ) returns ± 0.5 for finite x.</p>
+</li>
+<li>
+<p>atan2pi (±∞, -∞ ) returns ±0.75.</p>
+</li>
+<li>
+<p>atan2pi (±∞, +∞ ) returns ±0.25.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><strong>OpExtInst</strong> <strong>ceil</strong>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>ceil( -1 &lt; x &lt; 0 ) returns -0.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><strong>OpExtInst</strong> <strong>cospi</strong>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>cospi( ±0 ) returns 1</p>
+</li>
+<li>
+<p>cospi( n + 0.5 ) is +0 for any integer n where n + 0.5 is
+representable.</p>
+</li>
+<li>
+<p>cospi( ±∞ ) returns a NaN.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><strong>OpExtInst</strong> <strong>exp10</strong>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>exp10( ±0 ) returns 1.</p>
+</li>
+<li>
+<p>exp10( -∞ ) returns +0.</p>
+</li>
+<li>
+<p>exp10( +∞ ) returns +∞.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><strong>OpExtInst</strong> <strong>distance</strong>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>distance(x, y) calculates the distance from x to y without overflow or
+extraordinary precision loss due to underflow.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><strong>OpExtInst</strong> <strong>fdim</strong>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>fdim( any, NaN ) returns NaN.</p>
+</li>
+<li>
+<p>fdim( NaN, any ) returns NaN.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><strong>OpExtInst</strong> <strong>fmod</strong>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>fmod( ±0, NaN ) returns NaN.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><strong>OpExtInst</strong> <strong>fract</strong>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>fract( x, iptr) shall not return a value greater than or equal to 1.0,
+and shall not return a value less than 0.</p>
+</li>
+<li>
+<p>fract( +0, iptr ) returns +0 and +0 in iptr.</p>
+</li>
+<li>
+<p>fract( -0, iptr ) returns -0 and -0 in iptr.</p>
+</li>
+<li>
+<p>fract( +inf, iptr ) returns +0 and +inf in iptr.</p>
+</li>
+<li>
+<p>fract( -inf, iptr ) returns -0 and -inf in iptr.</p>
+</li>
+<li>
+<p>fract( NaN, iptr ) returns the NaN and NaN in iptr.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><strong>OpExtInst</strong> <strong>frexp</strong>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>frexp( ±∞, exp ) returns ±∞ and stores 0 in exp.</p>
+</li>
+<li>
+<p>frexp( NaN, exp ) returns the NaN and stores 0 in exp.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><strong>OpExtInst</strong> <strong>length</strong>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>length calculates the length of a vector without overflow or
+extraordinary precision loss due to underflow.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><strong>OpExtInst</strong> <strong>lgamma_r</strong>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>lgamma_r( x, signp ) returns 0 in signp if x is zero or a negative
+integer.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><strong>OpExtInst</strong> <strong>nextafter</strong>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>nextafter( -0, y &gt; 0 ) returns smallest positive denormal value.</p>
+</li>
+<li>
+<p>nextafter( +0, y &lt; 0 ) returns smallest negative denormal value.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><strong>OpExtInst</strong> <strong>normalize</strong>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>normalize shall reduce the vector to unit length, pointing in the same
+direction without overflow or extraordinary precision loss due to
+underflow.</p>
+</li>
+<li>
+<p>normalize( v ) returns v if all elements of v are zero.</p>
+</li>
+<li>
+<p>normalize( v ) returns a vector full of NaNs if any element is a NaN.</p>
+</li>
+<li>
+<p>normalize( v ) for which any element in v is infinite shall proceed as
+if the elements in v were replaced as follows:</p>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>for( i = 0; i &lt; sizeof(v) / sizeof(v[0] ); i++ )
+    v[i] = isinf(v[i] )  ?  copysign(1.0, v[i]) : 0.0 * v [i];</code></pre>
+</div>
+</div>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><strong>OpExtInst</strong> <strong>pow</strong>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>pow( ±0, -∞ ) returns +∞</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><strong>OpExtInst</strong> <strong>pown</strong>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>pown( x, 0 ) is 1 for any x, even zero, NaN or infinity.</p>
+</li>
+<li>
+<p>pown( ±0, n ) is ±∞ for odd n &lt; 0.</p>
+</li>
+<li>
+<p>pown( ±0, n ) is +∞ for even n &lt; 0.</p>
+</li>
+<li>
+<p>pown( ±0, n ) is +0 for even n &gt; 0.</p>
+</li>
+<li>
+<p>pown( ±0, n ) is ±0 for odd n &gt; 0.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><strong>OpExtInst</strong> <strong>powr</strong>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>powr( x, ±0 ) is 1 for finite x &gt; 0.</p>
+</li>
+<li>
+<p>powr( ±0, y ) is +∞ for finite y &lt; 0.</p>
+</li>
+<li>
+<p>powr( ±0, -∞) is +∞.</p>
+</li>
+<li>
+<p>powr( ±0, y ) is +0 for y &gt; 0.</p>
+</li>
+<li>
+<p>powr( +1, y ) is 1 for finite y.</p>
+</li>
+<li>
+<p>powr( x, y ) returns NaN for x &lt; 0.</p>
+</li>
+<li>
+<p>powr( ±0, ±0 ) returns NaN.</p>
+</li>
+<li>
+<p>powr( +∞, ±0 ) returns NaN.</p>
+</li>
+<li>
+<p>powr( +1, ±∞ ) returns NaN.</p>
+</li>
+<li>
+<p>powr( x, NaN ) returns the NaN for x &gt;= 0.</p>
+</li>
+<li>
+<p>powr( NaN, y ) returns the NaN.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><strong>OpExtInst</strong> <strong>rint</strong>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>rint( -0.5 &lt;= x &lt; 0 ) returns -0.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><strong>OpExtInst</strong> <strong>remquo</strong>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>remquo(x, y, &amp;quo) returns a NaN and 0 in quo if x is ±∞, or
+if y is 0 and the other argument is non-NaN or if either argument is a
+NaN.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><strong>OpExtInst</strong> <strong>rootn</strong>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>rootn( ±0, n ) is ±∞ for odd n &lt; 0.</p>
+</li>
+<li>
+<p>rootn( ±0, n ) is +∞ for even n &lt; 0.</p>
+</li>
+<li>
+<p>rootn( ±0, n ) is +0 for even n &gt; 0.</p>
+</li>
+<li>
+<p>rootn( ±0, n ) is ±0 for odd n &gt; 0.</p>
+</li>
+<li>
+<p>rootn( x, n ) returns a NaN for x &lt; 0 and n is even.</p>
+</li>
+<li>
+<p>rootn( x, 0 ) returns a NaN.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><strong>OpExtInst</strong> <strong>round</strong>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>round( -0.5 &lt; x &lt; 0 ) returns -0.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><strong>OpExtInst</strong> <strong>sinpi</strong>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>sinpi( ±0 ) returns ±0.</p>
+</li>
+<li>
+<p>sinpi( +n) returns +0 for positive integers n.</p>
+</li>
+<li>
+<p>sinpi( -n ) returns -0 for negative integers n.</p>
+</li>
+<li>
+<p>sinpi( ±∞ ) returns a NaN.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><strong>OpExtInst</strong> <strong>tanpi</strong>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>tanpi( ±0 ) returns ±0.</p>
+</li>
+<li>
+<p>tanpi( ±∞ ) returns a NaN.</p>
+</li>
+<li>
+<p>tanpi( n ) is copysign( 0.0, n ) for even integers n.</p>
+</li>
+<li>
+<p>tanpi( n ) is copysign( 0.0, - n) for odd integers n.</p>
+</li>
+<li>
+<p>tanpi( n + 0.5 ) for even integer n is +∞ where n + 0.5 is
+representable.</p>
+</li>
+<li>
+<p>tanpi( n + 0.5 ) for odd integer n is -∞ where n + 0.5 is
+representable.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><strong>OpExtInst</strong> <strong>trunc</strong>:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>trunc( -1 &lt; x &lt; 0 ) returns -0.</p>
+</li>
+</ul>
+</div>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="changes-to-isoiec-9899-tc2-behavior">8.7.2. Changes to ISO/IEC 9899: TC2 Behavior</h4>
+<div class="paragraph">
+<p><strong>OpExtInst</strong> <strong>modf</strong> behaves as though implemented by:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>gentype modf( gentype value, gentype *iptr )
+{
+    *iptr = trunc( value );
+    return copysign( isinf( value ) ? 0.0 : value - *iptr, value );
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><strong>OpExtInst</strong> <strong>rint</strong> always rounds according to round to nearest even rounding
+mode even if the caller is in some other rounding mode.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="edge-case-behavior-in-flush-to-zero-mode">8.7.3. Edge Case Behavior in Flush To Zero Mode</h4>
+<div class="paragraph">
+<p>If denormals are flushed to zero, then a function may return one of four
+results:</p>
+</div>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>Any conforming result for non-flush-to-zero mode.</p>
+</li>
+<li>
+<p>If the result given by 1 is a sub-normal before rounding, it may be
+flushed to zero.</p>
+</li>
+<li>
+<p>Any non-flushed conforming result for the function if one or more of its
+sub-normal operands are flushed to zero.</p>
+</li>
+<li>
+<p>If the result of 3 is a sub-normal before rounding, the result may be
+flushed to zero.</p>
+</li>
+</ol>
+</div>
+<div class="paragraph">
+<p>In each of the above cases, if an operand or result is flushed to zero, the
+sign of the zero is undefined.</p>
+</div>
+<div class="paragraph">
+<p>If subnormals are flushed to zero, a device may choose to conform to the
+following edge cases for <strong>OpExtInst</strong> <strong>nextafter</strong> instead of those listed in
+<em><a href="#additional-requirements-beyond-isoiec-9899tc2">Additional Requirements
+Beyond ISO/IEC 9899:TC2</a> section</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>nextafter ( +smallest normal, y &lt; +smallest normal ) = +0.</p>
+</li>
+<li>
+<p>nextafter ( -smallest normal, y &gt; -smallest normal ) = -0.</p>
+</li>
+<li>
+<p>nextafter ( -0, y &gt; 0 ) returns smallest positive normal value.</p>
+</li>
+<li>
+<p>nextafter ( +0, y &lt; 0 ) returns smallest negative normal value.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For clarity, subnormals or denormals are defined to be the set of
+representable numbers in the range 0 &lt; x &lt; TYPE_MIN and -TYPE_MIN &lt; x &lt; -0.
+They do not include ±0.
+A non-zero number is said to be sub-normal before rounding if, after
+normalization, its radix-2 exponent is less than (TYPE_MIN_EXP - 1).
+<sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnote_1" title="View footnote.">1</a>]</sup></p>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="image_addressing_and_filtering">9. Image Addressing and Filtering</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>This section describes how image operations behave in an OpenCL environment.</p>
+</div>
+<div class="sect2">
+<h3 id="image-coordinates">9.1. Image Coordinates</h3>
+<div class="paragraph">
+<p>Let <code>w<sub>t</sub></code>, <code>h<sub>t</sub></code> and <code>d<sub>t</sub></code> be the width, height (or image array size for a 1D image array) and depth (or image array size for a 2D image array) of the image in pixels.
+Let <code>coord.xy</code> (also referred to as <code>(s,t)</code>) or <code>coord.xyz</code> (also referred to as <code>(s,t,r)</code>) be the coordinates specified to an image read instruction (such as <strong>OpImageRead</strong>) or an image write instruction (such as <strong>OpImageWrite</strong>).</p>
+</div>
+<div class="paragraph">
+<p>If image coordinates specified to an image read instruction are normalized (as specified in the sampler), the <code>s</code>, <code>t</code>, and <code>r</code> coordinate values are multiplied by <code>w<sub>t</sub></code>, <code>h<sub>t</sub></code> and <code>d<sub>t</sub></code> respectively to generate the unnormalized coordinate values.
+For image arrays, the image array coordinate (i.e. <code>t</code> if it is a 1D image array or <code>r</code> if it is a 2D image array) specified to the image read instruction must always be the unnormalized image coordinate value.</p>
+</div>
+<div class="paragraph">
+<p>Image coordinates specified to an image write instruction are always unnormalized image coordinate values.</p>
+</div>
+<div class="paragraph">
+<p>Let <code>(u,v,w)</code> represent the unnormalized image coordinate values.</p>
+</div>
+<div class="paragraph">
+<p>If values in <code>(s,t,r)</code> or <code>(u,v,w)</code> are INF or NaN, the behavior of the image read instruction or image write instruction is undefined.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="addressing-and-filter-modes">9.2. Addressing and Filter Modes</h3>
+<div class="paragraph">
+<p>After generating the image coordinate <code>(u,v,w)</code> we apply the appropriate addressing and filter mode to generate the appropriate sample locations to read from the image.</p>
+</div>
+<div class="sect3">
+<h4 id="clamp-addressing">9.2.1. Clamp and None Addressing Modes</h4>
+<div class="paragraph">
+<p>We first describe how the addressing and filter modes are applied to generate the appropriate sample locations to read from the image if the addressing mode is <code>CL_ADDRESS_CLAMP</code>, <code>CL_ADDRESS_CLAMP_TO_EDGE</code>, or <code>CL_ADDRESS_NONE</code>.</p>
+</div>
+<div class="sect4">
+<h5 id="clamp-nearest_filtering">Nearest Filtering</h5>
+<div class="paragraph">
+<p>When the filter mode is <code>CL_FILTER_NEAREST</code>, the result of the image read instruction is the image element that is nearest (in Manhattan distance) to the image element location <code>(i,j,k)</code>.
+The image element location <code>(i,j,k)</code> is computed as:</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[\begin{aligned}
+i &amp; = address\_mode((int)floor(u))\\
+j &amp; = address\_mode((int)floor(v))\\
+k &amp; = address\_mode((int)floor(w))
+\end{aligned}\]
+</div>
+</div>
+<div class="paragraph">
+<p>For a 3D image, the image element at location <code>(i,j,k)</code> becomes the color value.
+For a 2D image, the image element at location <code>(i,j)</code> becomes the color value.</p>
+</div>
+<div class="paragraph">
+<p>The below table describes the <code>address_mode</code> function.</p>
+</div>
+<table id="addressing_modes_to_generate_texel_location" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 8. Addressing Modes to Generate Texel Location</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Addressing Mode</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Result of <em>address_mode(coord)</em></strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><div><div class="paragraph">
+<p><code>CL_ADDRESS_CLAMP</code></p>
+</div></div></td>
+<td class="tableblock halign-left valign-top"><div><div class="paragraph">
+<p><em>clamp (coord, -1, size)</em></p>
+</div></div></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><div><div class="paragraph">
+<p><code>CL_ADDRESS_CLAMP_TO_EDGE</code></p>
+</div></div></td>
+<td class="tableblock halign-left valign-top"><div><div class="paragraph">
+<p><em>clamp (coord, 0, size - 1)</em></p>
+</div></div></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><div><div class="paragraph">
+<p><code>CL_ADDRESS_NONE</code></p>
+</div></div></td>
+<td class="tableblock halign-left valign-top"><div><div class="paragraph">
+<p><em>coord</em></p>
+</div></div></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>The size term in the table above is <code>w<sub>t</sub></code> for u, <code>h<sub>t</sub></code> for v and <code>d<sub>t</sub></code> for w.</p>
+</div>
+<div class="paragraph">
+<p>The clamp function used in the table above is defined as:</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[\begin{aligned}
+clamp(a, b, c) &amp; = return (a &lt; b) ? b : ((a &gt; c) ? c : a)
+\end{aligned}\]
+</div>
+</div>
+<div class="paragraph">
+<p>If the addressing mode is <code>CL_ADDRESS_CLAMP</code> or <code>CL_ADDRESS_CLAMP_TO_EDGE</code>, and the selected texel location <code>(i,j,k)</code> refers to a location outside the image, the border color is used as the color value for the texel.</p>
+</div>
+<div class="paragraph">
+<p>Otherwise, if the addressing mode is <code>CL_ADDRESS_NONE</code> and the selected texel location <code>(i,j,k)</code> refers to a location outside the image, the color value for the texel is undefined.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="clamp-linear-filtering">Linear Filtering</h5>
+<div class="paragraph">
+<p>When the filter mode is <code>CL_FILTER_LINEAR</code>, a 2 x 2 square of image elements (for a 2D image) or a 2 x 2 x 2 cube of image elements (for a 3D image is selected).
+This 2 x 2 square or 2 x 2 x 2 cube is obtained as follows.</p>
+</div>
+<div class="paragraph">
+<p>Let:</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[\begin{aligned}
+i0 &amp; = address\_mode((int)floor(u - 0.5))\\
+j0 &amp; = address\_mode((int)floor(v - 0.5))\\
+k0 &amp; = address\_mode((int)floor(w - 0.5))\\
+i1 &amp; = address\_mode((int)floor(u - 0.5) + 1)\\
+j1 &amp; = address\_mode((int)floor(v - 0.5) + 1)\\
+k1 &amp; = address\_mode((int)floor(w - 0.5) + 1)\\
+a  &amp; = frac(u - 0.5)\\
+b  &amp; = frac(v - 0.5)\\
+c  &amp; = frac(w - 0.5)
+\end{aligned}\]
+</div>
+</div>
+<div class="paragraph">
+<p>The frac function determines the fractional part of x and is computed as:</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[\begin{aligned}
+frac(x) &amp; = x - floor(x)
+\end{aligned}\]
+</div>
+</div>
+<div class="paragraph">
+<p>For a 3D image, the color value is computed as:</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[\begin{array}{rcl}
+T &amp;=&amp; (1 - a) \times (1 - b) \times (1 - c) \times T_{i0j0k0}\\
+  &amp; &amp; {} + a \times (1 - b) \times (1 - c) \times T_{i1j0k0}\\
+  &amp; &amp; {} + (1 - a) \times b \times (1 - c) \times T_{i0j1k0}\\
+  &amp; &amp; {} + a \times b \times (1 - c) \times T_{i1j1k0}\\
+  &amp; &amp; {} + (1 - a) \times (1 - b) \times c \times T_{i0j0k1}\\
+  &amp; &amp; {} + a \times (1 - b) \times c \times T_{i1j0k1}\\
+  &amp; &amp; {} + (1 - a) \times b \times c \times T_{i0j1k1}\\
+  &amp; &amp; {} + a \times b \times c \times T_{i1j1k1}
+\end{array}\]
+</div>
+</div>
+<div class="paragraph">
+<p>where <code>T<sub>ijk</sub></code> is the image element at location <code>(i,j,k)</code> in the 3D image.</p>
+</div>
+<div class="paragraph">
+<p>For a 2D image, the color value is computed as:</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[\begin{array}{rcl}
+T &amp;=&amp; (1 - a) \times (1 - b) \times T_{i0j0}\\
+  &amp; &amp; {} + a \times (1 - b) \times T_{i1j0}\\
+  &amp; &amp; {} + (1 - a) \times b \times T_{i0j1}\\
+  &amp; &amp; {} + a \times b \times T_{i1j1}
+\end{array}\]
+</div>
+</div>
+<div class="paragraph">
+<p>where <code>T<sub>ij</sub></code> is the image element at location <code>(i,j)</code> in the 2D image.</p>
+</div>
+<div class="paragraph">
+<p>If the addressing mode is <code>CL_ADDRESS_CLAMP</code> or <code>CL_ADDRESS_CLAMP_TO_EDGE</code>, and any of the selected <code>T<sub>ijk</sub></code> or <code>T<sub>ij</sub></code> refers to a location outside the image, the border color is used as the image element.</p>
+</div>
+<div class="paragraph">
+<p>Otherwise, if the addressing mode is <code>CL_ADDRESS_NONE</code>, and any of the selected <code>T<sub>ijk</sub></code> or <code>T<sub>ij</sub></code> refers to a location outside the image, the color value is undefined.</p>
+</div>
+<div class="paragraph">
+<p>If the image channel type is <code>CL_FLOAT</code> or <code>CL_HALF_FLOAT</code>, and any of the image elements <code>T<sub>ijk</sub></code> or <code>T<sub>ij</sub></code> is INF or NaN, the color value is undefined.</p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="repeat-addressing">9.2.2. Repeat Addressing Mode</h4>
+<div class="paragraph">
+<p>We now discuss how the addressing and filter modes are applied to generate the appropriate sample locations to read from the image if the addressing mode is <code>CL_ADDRESS_REPEAT</code>.</p>
+</div>
+<div class="sect4">
+<h5 id="repeat-nearest-filtering">Nearest Filtering</h5>
+<div class="paragraph">
+<p>When filter mode is <code>CL_FILTER_NEAREST</code>, the result of the image read instruction is the image element that is nearest (in Manhattan distance) to the image element location <code>(i,j,k)</code>.
+The image element location <code>(i,j,k)</code> is computed as:</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[\begin{array}{l}
+u = (s - floor(s)) \times w_t\\
+i = (int)floor(u)\\
+if\ (i &gt; w_t - 1)\\
+\qquad i = i - w_t\\
+v = (t - floor(t)) \times h_t\\
+j = (int)floor(v)\\
+if\ (j &gt; h_t - 1)\\
+\qquad j = j - h_t\\
+w = (r - floor(r)) \times d_t\\
+k = (int)floor(w)\\
+if\ (k &gt; d_t - 1)\\
+\qquad k = k - d_t
+\end{array}\]
+</div>
+</div>
+<div class="paragraph">
+<p>For a 3D image, the image element at location (i, j, k) becomes the color value.
+For a 2D image, the image element at location (i, j) becomes the color value.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="repeat-linear-filtering">Linear Filtering</h5>
+<div class="paragraph">
+<p>When filter mode is <code>CL_FILTER_LINEAR</code>, a 2 x 2 square of image elements for a 2D image or a 2 x 2 x 2 cube of image elements for a 3D image is selected.
+This 2 x 2 square or 2 x 2 x 2 cube is obtained as follows.</p>
+</div>
+<div class="paragraph">
+<p>Let</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[\begin{array}{l}
+u = (s - floor(s)) \times w_t\\
+i0 = (int)floor(u - 0.5)\\
+i1 = i0 + 1\\
+if (i0 &lt; 0)\\
+i0 = w_t + i0\\
+if\ (i1 &gt; w_t - 1)\\
+\qquad i1 = i1 - w_t\\
+v = (t - floor(t)) \times h_t\\
+j0 = (int)floor(v - 0.5)\\
+j1 = j0 + 1\\
+if (j0 &lt; 0)\\
+j0 = h_t + j0\\
+if\ (j1 &gt; h_t - 1)\\
+\qquad j1 = j1 - h_t\\
+w = (r - floor(r)) \times d_t\\
+k0 = (int)floor(w - 0.5)\\
+k1 = k0 + 1\\
+if (k0 &lt; 0)\\
+\qquad k0 = d_t + k0\\
+if\ (k1 &gt; d_t - 1)\\
+\qquad k1 = k1 - d_t\\
+a = frac(u - 0.5)\\
+b = frac(v - 0.5)\\
+c = frac(w - 0.5)
+\end{array}\]
+</div>
+</div>
+<div class="paragraph">
+<p>For a 3D image, the color value is computed as:</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[\begin{array}{rcl}
+T &amp;=&amp; (1 - a) \times (1 - b) \times (1 - c) \times T_{i0j0k0}\\
+  &amp; &amp; {} + a \times (1 - b) \times (1 - c) \times T_{i1j0k0}\\
+  &amp; &amp; {} + (1 - a) \times b \times (1 - c) \times T_{i0j1k0}\\
+  &amp; &amp; {} + a \times b \times (1 - c) \times T_{i1j1k0}\\
+  &amp; &amp; {} + (1 - a) \times (1 - b) \times c \times T_{i0j0k1}\\
+  &amp; &amp; {} + a \times (1 - b) \times c \times T_{i1j0k1}\\
+  &amp; &amp; {} + (1 - a) \times b \times c \times T_{i0j1k1}\\
+  &amp; &amp; {} + a \times b \times c \times T_{i1j1k1}
+\end{array}\]
+</div>
+</div>
+<div class="paragraph">
+<p>where <code>T<sub>ijk</sub></code> is the image element at location <code>(i,j,k)</code> in the 3D image.</p>
+</div>
+<div class="paragraph">
+<p>For a 2D image, the color value is computed as:</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[\begin{array}{rcl}
+T &amp;=&amp;(1 - a) \times (1 - b) \times T_{i0j0}\\
+  &amp; &amp; {} + a \times (1 - b) \times T_{i1j0}\\
+  &amp; &amp; {} + (1 - a) \times b \times T_{i0j1}\\
+  &amp; &amp; {} + a \times b \times T_{i1j1}
+\end{array}\]
+</div>
+</div>
+<div class="paragraph">
+<p>where <code>T<sub>ij</sub></code> is the image element at location <code>(i,j)</code> in the 2D image.</p>
+</div>
+<div class="paragraph">
+<p>If the image channel type is <code>CL_FLOAT</code> or <code>CL_HALF_FLOAT</code>, and any of the image elements <code>T<sub>ijk</sub></code> or <code>T<sub>ij</sub></code> is INF or NaN, the color value is undefined.</p>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="mirrored-repeat-addressing">9.2.3. Mirrored Repeat Addressing Mode</h4>
+<div class="paragraph">
+<p>We now discuss how the addressing and filter modes are applied to generate the appropriate sample locations to read from the image if the addressing mode is <code>CL_ADDRESS_MIRRORED_REPEAT</code>.
+The <code>CL_ADDRESS_MIRRORED_REPEAT</code> addressing mode causes the image to be read as if it is tiled at every integer seam, with the interpretation of the image data flipped at each integer crossing.</p>
+</div>
+<div class="sect4">
+<h5 id="mirrored-repeat-nearest-filtering">Nearest Filtering</h5>
+<div class="paragraph">
+<p>When filter mode is <code>CL_FILTER_NEAREST</code>, the result of the image read instruction is the image element that is nearest (in Manhattan distance) to the image element location <code>(i,j,k)</code>.
+The image element location <code>(i,j,k)</code> is computed as:</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[\begin{array}{rcl}
+s' &amp;=&amp; 2.0f \times rint(0.5f \times s)\\
+s` &amp;=&amp; fabs(s - s`)\\
+u  &amp;=&amp; s' \times w_t\\
+i  &amp;=&amp; (int)floor(u)\\
+i  &amp;=&amp; min(i, w_t - 1)\\
+t' &amp;=&amp; 2.0f \times rint(0.5f \times t)\\
+t` &amp;=&amp; fabs(t - t`)\\
+v  &amp;=&amp; t' \times h_t\\
+j  &amp;=&amp; (int)floor(v)\\
+j  &amp;=&amp; min(j, h_t - 1)\\
+r' &amp;=&amp; 2.0f \times rint(0.5f \times r)\\
+r` &amp;=&amp; fabs(r - r`)\\
+w  &amp;=&amp; r' \times d_t\\
+k  &amp;=&amp; (int)floor(w)\\
+k  &amp;=&amp; min(k, d_t - 1)
+\end{array}\]
+</div>
+</div>
+<div class="paragraph">
+<p>For a 3D image, the image element at location (i, j, k) becomes the color value.
+For a 2D image, the image element at location (i, j) becomes the color value.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="mirrored-repeat-linear-filtering">Linear Filtering</h5>
+<div class="paragraph">
+<p>When filter mode is <code>CL_FILTER_LINEAR</code>, a 2 x 2 square of image elements for a 2D image or a 2 x 2 x 2 cube of image elements for a 3D image is selected.
+This 2 x 2 square or 2 x 2 x 2 cube is obtained as follows.</p>
+</div>
+<div class="paragraph">
+<p>Let</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[\begin{array}{rcl}
+s' &amp;=&amp; 2.0f \times rint(0.5f \times s)\\
+s` &amp;=&amp; fabs(s - s`)\\
+u  &amp;=&amp; s' \times w_t\\
+i0 &amp;=&amp; (int)floor(u - 0.5f)\\
+i1 &amp;=&amp; i0 + 1\\
+i0 &amp;=&amp; max(i0, 0)\\
+i1 &amp;=&amp; min(i1, w_t - 1)\\
+t' &amp;=&amp; 2.0f \times rint(0.5f \times t)\\
+t` &amp;=&amp; fabs(t - t`)\\
+v  &amp;=&amp; t' \times h_t\\
+j0 &amp;=&amp; (int)floor(v - 0.5f)\\
+j1 &amp;=&amp; j0 + 1\\
+j0 &amp;=&amp; max(j0, 0)\\
+j1 &amp;=&amp; min(j1, h_t - 1)\\
+r' &amp;=&amp; 2.0f \times rint(0.5f \times r)\\
+r` &amp;=&amp; fabs(r - r`)\\
+w  &amp;=&amp; r' \times d_t\\
+k0 &amp;=&amp; (int)floor(w - 0.5f)\\
+k1 &amp;=&amp; k0 + 1\\
+k0 &amp;=&amp; max(k0, 0)\\
+k1 &amp;=&amp; min(k1, d_t - 1)\\
+a  &amp;=&amp; frac(u - 0.5)\\
+b  &amp;=&amp; frac(v - 0.5)\\
+c  &amp;=&amp; frac(w - 0.5)
+\end{array}\]
+</div>
+</div>
+<div class="paragraph">
+<p>For a 3D image, the color value is computed as:</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[\begin{array}{rcl}
+T &amp;=&amp; (1 - a) \times (1 - b) \times (1 - c) \times T_{i0j0k0}\\
+  &amp; &amp; {} + a \times (1 - b) \times (1 - c) \times T_{i1j0k0}\\
+  &amp; &amp; {} + (1 - a) \times b \times (1 - c) \times T_{i0j1k0}\\
+  &amp; &amp; {} + a \times b \times (1 - c) \times T_{i1j1k0}\\
+  &amp; &amp; {} + (1 - a) \times (1 - b) \times c \times T_{i0j0k1}\\
+  &amp; &amp; {} + a \times (1 - b) \times c \times T_{i1j0k1}\\
+  &amp; &amp; {} + (1 - a) \times b \times c \times T_{i0j1k1}\\
+  &amp; &amp; {} + a \times b \times c \times T_{i1j1k1}
+\end{array}\]
+</div>
+</div>
+<div class="paragraph">
+<p>where <code>T<sub>ijk</sub></code> is the image element at location <code>(i,j,k)</code> in the 3D image.</p>
+</div>
+<div class="paragraph">
+<p>For a 2D image, the color value is computed as:</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[\begin{array}{rcl}
+T &amp;=&amp; (1 - a) \times (1 - b) \times T_{i0j0}\\
+  &amp; &amp; {} + a \times (1 - b) \times T_{i1j0}\\
+  &amp; &amp; {} + (1 - a) \times b \times T_{i0j1}\\
+  &amp; &amp; {} + a \times b \times T_{i1j1}
+\end{array}\]
+</div>
+</div>
+<div class="paragraph">
+<p>where <code>T<sub>ij</sub></code> is the image element at location <code>(i,j)</code> in the 2D image.</p>
+</div>
+<div class="paragraph">
+<p>For a 1D image, the color value is computed as:</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[\begin{array}{rcl}
+T &amp;=&amp; (1 - a) \times T_i0 + a \times T_i1
+\end{array}\]
+</div>
+</div>
+<div class="paragraph">
+<p>where <code>T<sub>i</sub></code> is the image element at location <code>(i)</code> in the 1D image.</p>
+</div>
+<div class="paragraph">
+<p>If the image channel type is <code>CL_FLOAT</code> or <code>CL_HALF_FLOAT</code> and any of the image elements <code>T<sub>ijk</sub></code> or <code>T<sub>ij</sub></code> is INF or NaN, the color value is undefined.</p>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="precision-of-addressing-and-filter-modes">9.3. Precision of Addressing and Filter Modes</h3>
+<div class="paragraph">
+<p>If the sampler is specified as using unnormalized coordinates (floating-point or integer coordinates), filter mode set to <code>CL_FILTER_NEAREST</code> and addressing mode set to one of the following modes - <code>CL_ADDRESS_CLAMP</code>, <code>CL_ADDRESS_CLAMP_TO_EDGE</code> or <code>CL_ADDRESS_NONE</code> - the location of the image element in the image given by <code>(i,j,k)</code> will be computed without any loss of precision.</p>
+</div>
+<div class="paragraph">
+<p>For all other sampler combinations of normalized or unnormalized coordinates, filter modes, and addressing modes, the relative error or precision of the addressing mode calculations and the image filter operation are not defined.
+To ensure precision of image addressing and filter calculations across any OpenCL device for these sampler combinations, developers may unnormalize the image coordinate in the kernel, and then implement the linear filter in the kernel with appropriate read image instructions with a sampler that uses unnormalized coordinates, filter mode set to <code>CL_FILTER_NEAREST</code>, addressing mode set to <code>CL_ADDRESS_CLAMP</code>, <code>CL_ADDRESS_CLAMP_TO_EDGE</code> or <code>CL_ADDRESS_NONE</code>, and finally performing the interpolation of color values read from the image to generate the filtered color value.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="conversion-rules">9.4. Conversion Rules</h3>
+<div class="paragraph">
+<p>In this section we discuss conversion rules that are applied when reading and writing images in a kernel.</p>
+</div>
+<div class="sect3">
+<h4 id="conversion-rules-for-normalized-integer-channel-data-types">9.4.1. Conversion Rules for Normalized Integer Channel Data Types</h4>
+<div class="paragraph">
+<p>In this section we discuss converting normalized integer channel data types to half-precision and single-precision floating-point values and vice-versa.</p>
+</div>
+<div class="sect4">
+<h5 id="converting-normalized-integer-channel-data-types-to-half-precision-floating-point-values">Converting Normalized Integer Channel Data Types to Half Precision Floating-point Values</h5>
+<div class="paragraph">
+<p>For images created with image channel data type of <code>CL_UNORM_INT8</code> and <code>CL_UNORM_INT16</code>, image read instructions will convert the channel values from an 8-bit or 16-bit unsigned integer to normalized half precision floating-point values in the range [0.0h &#8230;&#8203; 1.0h].</p>
+</div>
+<div class="paragraph">
+<p>For images created with image channel data type of <code>CL_SNORM_INT8</code> and <code>CL_SNORM_INT16</code>, image read instructions will convert the channel values from an 8-bit or 16-bit signed integer to normalized half precision floating-point values in the range [-1.0h &#8230;&#8203; 1.0h].</p>
+</div>
+<div class="paragraph">
+<p>These conversions are performed as follows:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>CL_UNORM_INT8</code> (8-bit unsigned integer) &#8594; <code>half</code></p>
+<div class="stemblock">
+<div class="content">
+\[normalized\_half\_value(x)=round\_to\_half(\frac{x}{255})\]
+</div>
+</div>
+</li>
+<li>
+<p><code>CL_UNORM_INT_101010</code> (10-bit unsigned integer) &#8594; <code>half</code></p>
+<div class="stemblock">
+<div class="content">
+\[normalized\_half\_value(x)=round\_to\_half(\frac{x}{1023})\]
+</div>
+</div>
+</li>
+<li>
+<p><code>CL_UNORM_INT16</code> (16-bit unsigned integer) &#8594; <code>half</code></p>
+<div class="stemblock">
+<div class="content">
+\[normalized\_half\_value(x)=round\_to\_half(\frac{x}{65535})\]
+</div>
+</div>
+</li>
+<li>
+<p><code>CL_SNORM_INT8</code> (8-bit signed integer) &#8594; <code>half</code></p>
+<div class="stemblock">
+<div class="content">
+\[normalized\_half\_value(x)=max(-1.0h, round\_to\_half(\frac{x}{127}))\]
+</div>
+</div>
+</li>
+<li>
+<p><code>CL_SNORM_INT16</code> (16-bit signed integer) &#8594; <code>half</code></p>
+<div class="stemblock">
+<div class="content">
+\[normalized\_half\_value(x)=max(-1.0h, round\_to\_half(\frac{x}{32767}))\]
+</div>
+</div>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The precision of the above conversions is &lt;= 1.5 ulp except for the following cases:</p>
+</div>
+<div class="paragraph">
+<p>For <code>CL_UNORM_INT8</code>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>0 must convert to 0.0h, and</p>
+</li>
+<li>
+<p>255 must convert to 1.0h</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For <code>CL_UNORM_INT_101010</code>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>0 must convert to 0.0h, and</p>
+</li>
+<li>
+<p>1023 must convert to 1.0h</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For <code>CL_UNORM_INT16</code>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>0 must convert to 0.0h, and</p>
+</li>
+<li>
+<p>65535 must convert to 1.0h</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For <code>CL_SNORM_INT8</code>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>-128 and -127 must convert to -1.0h,</p>
+</li>
+<li>
+<p>0 must convert to 0.0h, and</p>
+</li>
+<li>
+<p>127 must convert to 1.0h</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For <code>CL_SNORM_INT16</code>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>-32768 and -32767 must convert to -1.0h,</p>
+</li>
+<li>
+<p>0 must convert to 0.0h, and</p>
+</li>
+<li>
+<p>32767 must convert to 1.0h</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect4">
+<h5 id="converting-half-precision-floating-point-values-to-normalized-integer-channel-data-types">Converting Half Precision Floating-point Values to Normalized Integer Channel Data Types</h5>
+<div class="paragraph">
+<p>For images created with image channel data type of <code>CL_UNORM_INT8</code> and <code>CL_UNORM_INT16</code>, image write instructions will convert the half precision floating-point color value to an 8-bit or 16-bit unsigned integer.</p>
+</div>
+<div class="paragraph">
+<p>For images created with image channel data type of <code>CL_SNORM_INT8</code> and <code>CL_SNORM_INT16</code>, image write instructions will convert the half precision floating-point color value to an 8-bit or 16-bit signed integer.</p>
+</div>
+<div class="paragraph">
+<p>OpenCL implementations may choose to approximate the rounding mode used in the conversions described below.
+When approximate rounding is used instead of the preferred rounding, the result of the conversion must satisfy the bound given below.</p>
+</div>
+<div class="paragraph">
+<p>The conversions from half precision floating-point values to normalized integer values are performed is as follows:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>half</code> &#8594; <code>CL_UNORM_INT8</code> (8-bit unsigned integer)</p>
+<div class="stemblock">
+<div class="content">
+\[\begin{aligned}
+&amp; f(x)=max(0,min(255,255 \times x))\\
+\\
+&amp; f_{preferred}(x) =
+\begin{cases}
+ round\_to\_nearest\_even\_uint8(f(x)) &amp; x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; x = \infty \text{ or } x = NaN
+\end{cases}\\
+&amp; f_{approx}(x) =
+\begin{cases}
+ round\_to\_impl\_uint8(f(x)) &amp; x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; x = \infty \text{ or } x = NaN
+\end{cases}\\
+\\
+&amp; |f(x) - f_{approx}(x)|\leq 0.6, x \neq \infty \text{ and } x \neq NaN
+\end{aligned}\]
+</div>
+</div>
+</li>
+<li>
+<p><code>half</code> &#8594; <code>CL_UNORM_INT16</code> (16-bit unsigned integer)</p>
+<div class="stemblock">
+<div class="content">
+\[\begin{aligned}
+&amp; f(x)=max(0,min(65535,65535 \times x))\\
+\\
+&amp; f_{preferred}(x) =
+\begin{cases}
+ round\_to\_nearest\_even\_uint16(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+&amp; f_{approx}(x) =
+\begin{cases}
+ round\_to\_impl\_uint16(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+\\
+&amp; |f(x) - f_{approx}(x)|\leq 0.6, x \neq \infty \text{ and } x \neq NaN
+\end{aligned}\]
+</div>
+</div>
+</li>
+<li>
+<p><code>half</code> &#8594; <code>CL_SNORM_INT8</code> (8-bit signed integer)</p>
+<div class="stemblock">
+<div class="content">
+\[\begin{aligned}
+&amp; f(x)=max(-128,min(127,127 \times x))\\
+\\
+&amp; f_{preferred}(x) =
+\begin{cases}
+ round\_to\_nearest\_even\_int8(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+&amp; f_{approx}(x) =
+\begin{cases}
+ round\_to\_impl\_int8(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+\\
+&amp; |f(x) - f_{approx}(x)|\leq 0.6, x \neq \infty \text{ and } x \neq NaN
+\end{aligned}\]
+</div>
+</div>
+</li>
+<li>
+<p><code>half</code> &#8594; <code>CL_SNORM_INT16</code> (16-bit signed integer)</p>
+<div class="stemblock">
+<div class="content">
+\[\begin{aligned}
+&amp; f(x)=max(-32768,min(32767,32767 \times x))\\
+\\
+&amp; f_{preferred}(x) =
+\begin{cases}
+ round\_to\_nearest\_even\_int16(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+&amp; f_{approx}(x) =
+\begin{cases}
+ round\_to\_impl\_int16(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+\\
+&amp; |f(x) - f_{approx}(x)|\leq 0.6, x \neq \infty \text{ and } x \neq NaN
+\end{aligned}\]
+</div>
+</div>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect4">
+<h5 id="converting-normalized-integer-channel-data-types-to-floating-point-values">Converting Normalized Integer Channel Data Types to Floating-point Values</h5>
+<div class="paragraph">
+<p>For images created with image channel data type of <code>CL_UNORM_INT8</code> and <code>CL_UNORM_INT16</code>, image read instructions will convert the channel values from an 8-bit or 16-bit unsigned integer to normalized floating-point values in the range [0.0f &#8230;&#8203; 1.0f].</p>
+</div>
+<div class="paragraph">
+<p>For images created with image channel data type of <code>CL_SNORM_INT8</code> and <code>CL_SNORM_INT16</code>, image read instructions will convert the channel values from an 8-bit or 16-bit signed integer to normalized floating-point values in the range [-1.0f &#8230;&#8203; 1.0f].</p>
+</div>
+<div class="paragraph">
+<p>These conversions are performed as follows:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>CL_UNORM_INT8</code> (8-bit unsigned integer) &#8594; <code>float</code></p>
+<div class="stemblock">
+<div class="content">
+\[normalized\_float\_value(x)=round\_to\_float(\frac{x}{255})\]
+</div>
+</div>
+</li>
+<li>
+<p><code>CL_UNORM_INT_101010</code> (10-bit unsigned integer) &#8594; <code>float</code></p>
+<div class="stemblock">
+<div class="content">
+\[normalized\_float\_value(x)=round\_to\_float(\frac{x}{1023})\]
+</div>
+</div>
+</li>
+<li>
+<p><code>CL_UNORM_INT16</code> (16-bit unsigned integer) &#8594; <code>float</code></p>
+<div class="stemblock">
+<div class="content">
+\[normalized\_float\_value(x)=round\_to\_float(\frac{x}{65535})\]
+</div>
+</div>
+</li>
+<li>
+<p><code>CL_SNORM_INT8</code> (8-bit signed integer) &#8594; <code>float</code></p>
+<div class="stemblock">
+<div class="content">
+\[normalized\_float\_value(x)=max(-1.0f, round\_to\_float(\frac{x}{127}))\]
+</div>
+</div>
+</li>
+<li>
+<p><code>CL_SNORM_INT16</code> (16-bit signed integer) &#8594; <code>float</code></p>
+<div class="stemblock">
+<div class="content">
+\[normalized\_float\_value(x)=max(-1.0f, round\_to\_float(\frac{x}{32767}))\]
+</div>
+</div>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The precision of the above conversions is &lt;= 1.5 ulp except for the following cases.</p>
+</div>
+<div class="paragraph">
+<p>For <code>CL_UNORM_INT8</code>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>0 must convert to 0.0f, and</p>
+</li>
+<li>
+<p>255 must convert to 1.0f</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For <code>CL_UNORM_INT_101010</code>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>0 must convert to 0.0f, and</p>
+</li>
+<li>
+<p>1023 must convert to 1.0f</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For <code>CL_UNORM_INT16</code>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>0 must convert to 0.0f, and</p>
+</li>
+<li>
+<p>65535 must convert to 1.0f</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For <code>CL_SNORM_INT8</code>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>-128 and -127 must convert to -1.0f,</p>
+</li>
+<li>
+<p>0 must convert to 0.0f, and</p>
+</li>
+<li>
+<p>127 must convert to 1.0f</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>For <code>CL_SNORM_INT16</code>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>-32768 and -32767 must convert to -1.0f,</p>
+</li>
+<li>
+<p>0 must convert to 0.0f, and</p>
+</li>
+<li>
+<p>32767 must convert to 1.0f</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect4">
+<h5 id="converting-floating-point-values-to-normalized-integer-channel-data-types">Converting Floating-point Values to Normalized Integer Channel Data Types</h5>
+<div class="paragraph">
+<p>For images created with image channel data type of <code>CL_UNORM_INT8</code> and <code>CL_UNORM_INT16</code>, image write instructions will convert the floating-point color value to an 8-bit or 16-bit unsigned integer.</p>
+</div>
+<div class="paragraph">
+<p>For images created with image channel data type of <code>CL_SNORM_INT8</code> and <code>CL_SNORM_INT16</code>, image write instructions will convert the floating-point color value to an 8-bit or 16-bit signed integer.</p>
+</div>
+<div class="paragraph">
+<p>OpenCL implementations may choose to approximate the rounding mode used in the conversions described below.
+When approximate rounding is used instead of the preferred rounding, the result of the conversion must satisfy the bound given below.</p>
+</div>
+<div class="paragraph">
+<p>The conversions from half precision floating-point values to normalized integer values are performed is as follows:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>float</code> &#8594; <code>CL_UNORM_INT8</code> (8-bit unsigned integer)</p>
+<div class="stemblock">
+<div class="content">
+\[\begin{aligned}
+&amp; f(x)=max(0,min(255,255 \times x))\\
+\\
+&amp; f_{preferred}(x) =
+\begin{cases}
+ round\_to\_nearest\_even\_uint8(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+&amp; f_{approx}(x) =
+\begin{cases}
+ round\_to\_impl\_uint8(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+\\
+&amp; |f(x) - f_{approx}(x)|\leq 0.6, x \neq \infty \text{ and } x \neq NaN
+\end{aligned}\]
+</div>
+</div>
+</li>
+<li>
+<p><code>float</code> &#8594; <code>CL_UNORM_INT_101010</code> (10-bit unsigned integer)</p>
+<div class="stemblock">
+<div class="content">
+\[\begin{aligned}
+&amp; f(x)=max(0,min(1023,1023 \times x))\\
+\\
+&amp; f_{preferred}(x) =
+\begin{cases}
+ round\_to\_nearest\_even\_uint10(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+&amp; f_{approx}(x) =
+\begin{cases}
+ round\_to\_impl\_uint10(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+\\
+&amp; |f(x) - f_{approx}(x)|\leq 0.6, x \neq \infty \text{ and } x \neq NaN
+\end{aligned}\]
+</div>
+</div>
+</li>
+<li>
+<p><code>float</code> &#8594; <code>CL_UNORM_INT16</code> (16-bit unsigned integer)</p>
+<div class="stemblock">
+<div class="content">
+\[\begin{aligned}
+&amp; f(x)=max(0,min(65535,65535 \times x))\\
+\\
+&amp; f_{preferred}(x) =
+\begin{cases}
+ round\_to\_nearest\_even\_uint16(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+&amp; f_{approx}(x) =
+\begin{cases}
+ round\_to\_impl\_uint16(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+\\
+&amp; |f(x) - f_{approx}(x)|\leq 0.6, x \neq \infty \text{ and } x \neq NaN
+\end{aligned}\]
+</div>
+</div>
+</li>
+<li>
+<p><code>float</code> &#8594; <code>CL_SNORM_INT8</code> (8-bit signed integer)</p>
+<div class="stemblock">
+<div class="content">
+\[\begin{aligned}
+&amp; f(x)=max(-128,min(127,127 \times x))\\
+\\
+&amp; f_{preferred}(x) =
+\begin{cases}
+ round\_to\_nearest\_even\_uint8(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+&amp; f_{approx}(x) =
+\begin{cases}
+ round\_to\_impl\_uint8(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+\\
+&amp; |f(x) - f_{approx}(x)|\leq 0.6, x \neq \infty \text{ and } x \neq NaN
+\end{aligned}\]
+</div>
+</div>
+</li>
+<li>
+<p><code>float</code> &#8594; <code>CL_SNORM_INT16</code> (16-bit signed integer)</p>
+<div class="stemblock">
+<div class="content">
+\[\begin{aligned}
+&amp; f(x)=max(-32768,min(32767,32767 \times x))\\
+\\
+&amp; f_{preferred}(x) =
+\begin{cases}
+ round\_to\_nearest\_even\_uint16(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+&amp; f_{approx}(x) =
+\begin{cases}
+ round\_to\_impl\_uint16(f(x)) &amp; \quad x \neq \infty \text{ and } x \neq NaN\\
+ \text{implementation-defined} &amp; \quad x = \infty \text{ or } x = NaN
+\end{cases}\\
+\\
+&amp; |f(x) - f_{approx}(x)|\leq 0.6, x \neq \infty \text{ and } x \neq NaN
+\end{aligned}\]
+</div>
+</div>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="conversion-rules-for-half-precision-floating-point-channel-data-type">9.4.2. Conversion Rules for Half Precision Floating-point Channel Data Type</h4>
+<div class="paragraph">
+<p>For images created with a channel data type of <code>CL_HALF_FLOAT</code>, the conversions of half to float and half to half are lossless.
+Conversions from float to half round the mantissa using the round to nearest even or round to zero rounding mode.
+Denormalized numbers for the half data type which may be generated when converting a float to a half may be flushed to zero.
+A float NaN must be converted to an appropriate NaN in the half type.
+A float INF must be converted to an appropriate INF in the half type.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="conversion-rules-for-floating-point-channel-data-type">9.4.3. Conversion Rules for Floating-point Channel Data Type</h4>
+<div class="paragraph">
+<p>The following rules apply for reading and writing images created with channel data type of <code>CL_FLOAT</code>.</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>NaNs may be converted to a NaN value(s) supported by the device.</p>
+</li>
+<li>
+<p>Denorms can be flushed to zero.</p>
+</li>
+<li>
+<p>All other values must be preserved.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="conversion-rules-for-signed-and-unsigned-8-bit-16-bit-and-32-bit-integer-channel-data-types">9.4.4. Conversion Rules for Signed and Unsigned 8-bit, 16-bit and 32-bit Integer Channel Data Types</h4>
+<div class="paragraph">
+<p>For images created with image channel data type of <code>CL_SIGNED_INT8</code>, <code>CL_SIGNED_INT16</code> and <code>CL_SIGNED_INT32</code>, image read instructions will return the unmodified integer values stored in the image at specified location.</p>
+</div>
+<div class="paragraph">
+<p>Likewise, for images created with image channel data type of <code>CL_UNSIGNED_INT8</code>, <code>CL_UNSIGNED_INT16</code> and <code>CL_UNSIGNED_INT32</code>, image read instructions will return the unmodified unsigned integer values stored in the image at specified location.</p>
+</div>
+<div class="paragraph">
+<p>Image write instructions will perform one of the following conversions:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>32 bit signed integer &#8594; <code>CL_SIGNED_INT8</code> (8-bit signed integer):</p>
+<div class="stemblock">
+<div class="content">
+\[int8\_value(x) = clamp(x, -128, 127)\]
+</div>
+</div>
+</li>
+<li>
+<p>32 bit signed integer &#8594; <code>CL_SIGNED_INT16</code> (16-bit signed integer):</p>
+<div class="stemblock">
+<div class="content">
+\[int16\_value(x) = clamp(x, -32768, 32767)\]
+</div>
+</div>
+</li>
+<li>
+<p>32 bit signed integer &#8594; <code>CL_SIGNED_INT32</code> (32-bit signed integer):</p>
+<div class="stemblock">
+<div class="content">
+\[int32\_value(x) = x \quad \text{(no conversion)}\]
+</div>
+</div>
+</li>
+<li>
+<p>32 bit unsigned integer &#8594; <code>CL_UNSIGNED_INT8</code> (8-bit unsigned integer):</p>
+<div class="stemblock">
+<div class="content">
+\[uint8\_value(x) = clamp(x, 0, 255)\]
+</div>
+</div>
+</li>
+<li>
+<p>32 bit unsigned integer &#8594; <code>CL_UNSIGNED_INT16</code> (16-bit unsigned integer):</p>
+<div class="stemblock">
+<div class="content">
+\[uint16\_value(x) = clamp(x, 0, 65535)\]
+</div>
+</div>
+</li>
+<li>
+<p>32 bit unsigned integer &#8594; <code>CL_UNSIGNED_INT32</code> (32-bit unsigned integer):</p>
+<div class="stemblock">
+<div class="content">
+\[uint32\_value(x) = x \quad \text{(no conversion)}\]
+</div>
+</div>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The conversions described in this section must be correctly saturated.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="conversion-rules-for-srgba-and-sbgra-images">9.4.5. Conversion Rules for sRGBA and sBGRA Images</h4>
+<div class="paragraph">
+<p>Standard RGB data, which roughly displays colors in a linear ramp of luminosity levels such that an average observer, under average viewing conditions, can view them as perceptually equal steps on an average display.
+All 0`s maps to 0.0f, and all 1`s maps to 1.0f.
+The sequence of unsigned integer encodings between all 0`s and all 1`s represent a nonlinear progression in the floating-point interpretation of the numbers between 0.0f to 1.0f.
+For more detail, see the <a href="#sRGB-spec">SRGB color standard</a>.</p>
+</div>
+<div class="paragraph">
+<p>Conversion from sRGB space is automatically done the image read instruction if the image channel order is one of the sRGB values described above.
+When reading from an sRGB image, the conversion from sRGB to linear RGB is performed before filtering is applied.
+If the format has an alpha channel, the alpha data is stored in linear color space.
+Conversion to sRGB space is automatically done by the image write instruction if the image channel order is one of the sRGB values described above and the device supports writing to sRGB images.</p>
+</div>
+<div class="paragraph">
+<p>If the format has an alpha channel, the alpha data is stored in linear color space.</p>
+</div>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>The following process is used by image read instructions to convert a normalized 8-bit unsigned integer sRGB color value x to a floating-point linear RGB color value y:</p>
+<div class="olist loweralpha">
+<ol class="loweralpha" type="a">
+<li>
+<p>Convert a normalized 8-bit unsigned integer sRGB value x to a floating-point sRGB value r as per rules described in <a href="#converting-normalized-integer-channel-data-types-to-floating-point-values">Converting Normalized Integer Channel Data Types to Floating-point Values</a> section.</p>
+<div class="stemblock">
+<div class="content">
+\[r=normalized\_float\_value(x)\]
+</div>
+</div>
+</li>
+<li>
+<p>Convert a floating-point sRGB value r to a floating-point linear RGB color value y:</p>
+<div class="stemblock">
+<div class="content">
+\[\begin{aligned}
+&amp; c_{linear}(x) =
+\begin{cases}
+ \frac{r}{12.92} &amp; \quad r \geq 0 \text{ and } r \leq 0.04045\\
+ (\frac{r + 0.055}{1.055})^{2.4} &amp; \quad r &gt; 0.04045 \text{ and } \leq 1
+\end{cases}\\
+\\
+&amp; y = c_{linear}(r)
+\end{aligned}\]
+</div>
+</div>
+</li>
+</ol>
+</div>
+</li>
+<li>
+<p>The following process is used by image write instructions to convert a linear RGB floating-point color value y to a normalized 8-bit unsigned integer sRGB value x:</p>
+<div class="olist loweralpha">
+<ol class="loweralpha" type="a">
+<li>
+<p>Convert a floating-point linear RGB value y to a normalized floating point sRGB value r:</p>
+<div class="stemblock">
+<div class="content">
+\[\begin{aligned}
+&amp; c_{linear}(x) =
+\begin{cases}
+ 0 &amp; \quad y \geq NaN \text{ or } y &lt; 0\\
+ 12.92 \times y &amp; \quad y \geq 0 \text{ and } y &lt; 0.0031308\\
+ 1.055 \times y^{(\frac{1}{2.4})} &amp; \quad y \geq 0.0031308 \text{ and } y \leq 1\\
+ 1 &amp; \quad y &gt; 1
+\end{cases}\\
+\\
+&amp; r = c_{sRGB}(y)
+\end{aligned}\]
+</div>
+</div>
+</li>
+<li>
+<p>Convert a normalized floating-point sRGB value r to a normalized 8-bit unsigned integer sRGB value x as per rules described in <a href="#converting-floating-point-values-to-normalized-integer-channel-data-types">Converting Floating-point Values to Normalized Integer Channel Data Types</a> section.</p>
+<div class="stemblock">
+<div class="content">
+\[\begin{aligned}
+&amp; g(r) =
+\begin{cases}
+ f_{preferred}(r) &amp; \quad \text{if rounding mode is round to even}\\
+ f_{approx}(r) &amp; \quad \text{if implementation-defined rounding mode}
+\end{cases}\\
+\\
+&amp; x = g(r)
+\end{aligned}\]
+</div>
+</div>
+</li>
+</ol>
+</div>
+</li>
+</ol>
+</div>
+<div class="paragraph">
+<p>The accuracy required when converting a normalized 8-bit unsigned integer sRGB color value x to a floating-point linear RGB color value y is given by:</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[|x-255 \times c_{sRGB}(y)|\leq 0.5\]
+</div>
+</div>
+<div class="paragraph">
+<p>The accuracy required when converting a linear RGB floating-point color value y to a normalized 8-bit unsigned integer sRGB value x is given by:</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[|x-255 \times c_{sRGB}(y)|\leq 0.6\]
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="selecting-an-image-from-an-image-array">9.5. Selecting an Image from an Image Array</h3>
+<div class="paragraph">
+<p>Let <code>(u,v,w)</code> represent the unnormalized image coordinate values for reading from and/or writing to a 2D image in a 2D image array.</p>
+</div>
+<div class="paragraph">
+<p>When read using a sampler, the 2D image layer selected is computed as:</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[layer = clamp(rint(w), 0, d_t - 1)\]
+</div>
+</div>
+<div class="paragraph">
+<p>otherwise the layer selected is computed as:</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[layer = w\]
+</div>
+</div>
+<div class="paragraph">
+<p>(since w is already an integer) and the result is undefined if w is not one of the integers 0, 1, &#8230;&#8203; <code>d<sub>t</sub></code> - 1.</p>
+</div>
+<div class="paragraph">
+<p>Let <code>(u,v)</code> represent the unnormalized image coordinate values for reading from and/or writing to a 1D image in a 1D image array.</p>
+</div>
+<div class="paragraph">
+<p>When read using a sampler, the 1D image layer selected is computed as:</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[layer = clamp(rint(v), 0, h_t - 1)\]
+</div>
+</div>
+<div class="paragraph">
+<p>otherwise the layer selected is computed as:</p>
+</div>
+<div class="stemblock">
+<div class="content">
+\[layer = v\]
+</div>
+</div>
+<div class="paragraph">
+<p>(since v is already an integer) and the result is undefined if v is not one of the integers 0, 1, &#8230;&#8203; <code>h<sub>t</sub></code> - 1.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_data_format_for_reading_and_writing_images">9.6. Data Format for Reading and Writing Images</h3>
+<div class="paragraph">
+<p>This section describes how image element data is returned by an
+image read instruction or passed as the <em>Texel</em> data that is
+written by an image write instruction:</p>
+</div>
+<div class="paragraph">
+<p>For the following image channel orders, the data is a four
+component vector type:</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 9. <em>Mapping Image Data to Vector Components</em></caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Image Channel Order</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Components</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>R</code>, <code>Rx</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">(R, 0, 0, 1)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>A</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">(0, 0, 0, A)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>RG</code>, <code>RGx</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">(R, G, 0, 1)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>RGB</code>, <code>RGBx</code>, <code>sRGB</code>, <code>sRGBx</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">(R, G, B, 1)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>RGBA</code>, <code>BGRA</code>, <code>ARGB</code>, <code>ABGR</code>, <code>sRGBA</code>, <code>sBGRA</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">(R, G, B, A)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>Intensity</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">(I, I, I, I)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>Luminance</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">(L, L, L, 1)</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>For the following image channel orders, the data is a scalar type:</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 10. <em>Scalar Image Data</em></caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Image Channel Order</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Scalar Value</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>Depth</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">D</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>DepthStencil</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">D</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>The following table describes the mapping from image channel data type
+to the data vector component type or scalar type:</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 11. <em>Image Data Types</em></caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Image Channel Order</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Data Type</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>SnormInt8</code>,
+<code>SnormInt16</code>,<br>
+<code>UnormInt8</code>,
+<code>UnormInt16</code>,<br>
+<code>UnormShort565</code>,
+<code>UnormShort555</code>,<br>
+<code>UnormInt101010</code>,
+<code>UnormInt101010_2</code>,<br>
+<code>UnormInt24</code>,<br>
+<code>HalfFloat</code>,<br>
+<code>Float</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpTypeFloat</strong>, with <em>Width</em> equal to 16 or 32.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><code>SignedInt8</code>,
+<code>SignedInt16</code>,
+<code>SignedInt32</code>,<br>
+<code>UnsignedInt8</code>,
+<code>UnsignedInt16</code>,
+<code>UnsignedInt32</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>OpTypeInt</strong>, with <em>Width</em> equal to 32.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect2">
+<h3 id="_sampled_and_sampler_less_reads">9.7. Sampled and Sampler-less Reads</h3>
+<div class="paragraph">
+<p>SPIR-V instructions that read from an image without a sampler (such as <strong>OpImageRead</strong>) behave exactly the same as the corresponding image read instruction with a sampler that has <em>Sampler Filter Mode</em> set to <strong>Nearest</strong>, <strong>Non-Normalized</strong> coordinates, and <em>Sampler Addressing Mode</em> set to <strong>None</strong>.</p>
+</div>
+<div class="paragraph">
+<p>There is one exception for cases where the image being read has <em>Image Format</em> equal to a floating-point type (such as <strong>R32f</strong>).
+In this exceptional case, when channel data values are denormalized, the non-sampler image read instruction may return the denormalized data, while the sampler image read instruction may flush denormalized channel data values to zero.
+The coordinates must be between 0 and image size in that dimension, non inclusive.</p>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="references">10. Normative References</h2>
+<div class="sectionbody">
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p><a id="ieee-754-spec"></a><em>IEEE Standard for Floating-Point Arithmetic</em>, IEEE Std 754-2008,
+<a href="http://dx.doi.org/10.1109/IEEESTD.2008.4610935" class="bare">http://dx.doi.org/10.1109/IEEESTD.2008.4610935</a> , August, 2008.</p>
+</li>
+<li>
+<p><a id="C99-spec"></a> &#8220;ISO/IEC 9899:1999 - Programming Languages - C&#8221;, with
+technical corrigenda TC1 and TC2,
+<a href="https://www.iso.org/standard/29237.html" class="bare">https://www.iso.org/standard/29237.html</a> .</p>
+</li>
+<li>
+<p><a id="cpp14-spec"></a> &#8220;ISO/IEC 14882:2014 - Information technology - Programming
+languages - C++&#8221;, <a href="https://www.iso.org/standard/64029.html" class="bare">https://www.iso.org/standard/64029.html</a> .</p>
+</li>
+<li>
+<p><a id="opencl-spec"></a> &#8220;The OpenCL Specification, Version 2.2&#8221;,
+<a href="https://www.khronos.org/registry/OpenCL/" class="bare">https://www.khronos.org/registry/OpenCL/</a> .</p>
+</li>
+<li>
+<p><a id="opencl-c-spec"></a> &#8220;The OpenCL C Specification, Version 2.0&#8221;,
+<a href="https://www.khronos.org/registry/OpenCL/" class="bare">https://www.khronos.org/registry/OpenCL/</a> .</p>
+</li>
+<li>
+<p><a id="opencl-cpp-spec"></a> &#8220;The OpenCL C++ 1.0 Specification&#8221;,
+<a href="https://www.khronos.org/registry/OpenCL/" class="bare">https://www.khronos.org/registry/OpenCL/</a> .</p>
+</li>
+<li>
+<p><a id="opencl-extension-spec"></a> &#8220;The OpenCL Extension Specification, Version
+2.2&#8221;, <a href="https://www.khronos.org/registry/OpenCL/" class="bare">https://www.khronos.org/registry/OpenCL/</a> .</p>
+</li>
+<li>
+<p><a id="spirv-spec"></a> &#8220;SPIR-V Specification, Version 1.2, Unified&#8221;,
+<a href="https://www.khronos.org/registry/spir-v/" class="bare">https://www.khronos.org/registry/spir-v/</a> .</p>
+</li>
+<li>
+<p><a id="ulp-definition"></a> Jean-Michel Muller. <em>On the definition of ulp(x)</em>.
+RR-5504, INRIA. 2005, pp.16. &lt;inria-00070503&gt;</p>
+</li>
+<li>
+<p><a id="sRGB-spec"></a> &#8220;IEC 61966-2-1:1999 Multimedia systems and equipment -
+Colour measurement and management - Part 2-1: Colour management -
+Default RGB colour space - sRGB&#8221;,
+<a href="https://webstore.iec.ch/publication/6169" class="bare">https://webstore.iec.ch/publication/6169</a> .</p>
+</li>
+</ol>
+</div>
+</div>
+</div>
+</div>
+<div id="footnotes">
+<hr>
+<div class="footnote" id="_footnote_1">
+<a href="#_footnoteref_1">1</a>. Here <code>TYPE_MIN</code> and <code>TYPE_MIN_EXP</code> should be substituted by constants appropriate to the floating-point type under consideration, such as <code>FLT_MIN</code> and <code>FLT_MIN_EXP</code> for float.
+</div>
+</div>
+<div id="footer">
+<div id="footer-text">
+Version 2.2-7<br>
+Last updated 2018-05-07 12:41:34 BST
+</div>
+</div>
+
+
+</body>
+</html>
\ No newline at end of file
diff --git a/specs/2.2/html/OpenCL_Ext.html b/specs/2.2/html/OpenCL_Ext.html
new file mode 100644
index 0000000..062d769
--- /dev/null
+++ b/specs/2.2/html/OpenCL_Ext.html
@@ -0,0 +1,11814 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<meta name="generator" content="Asciidoctor 1.5.6.1">
+<meta name="author" content="Khronos OpenCL Working Group">
+<title>The OpenCL Extension Specification</title>
+<style>
+/*! normalize.css v2.1.2 | MIT License | git.io/normalize */
+/* ========================================================================== HTML5 display definitions ========================================================================== */
+/** Correct `block` display not defined in IE 8/9. */
+article, aside, details, figcaption, figure, footer, header, hgroup, main, nav, section, summary { display: block; }
+
+/** Correct `inline-block` display not defined in IE 8/9. */
+audio, canvas, video { display: inline-block; }
+
+/** Prevent modern browsers from displaying `audio` without controls. Remove excess height in iOS 5 devices. */
+audio:not([controls]) { display: none; height: 0; }
+
+/** Address `[hidden]` styling not present in IE 8/9. Hide the `template` element in IE, Safari, and Firefox < 22. */
+[hidden], template { display: none; }
+
+script { display: none !important; }
+
+/* ========================================================================== Base ========================================================================== */
+/** 1. Set default font family to sans-serif. 2. Prevent iOS text size adjust after orientation change, without disabling user zoom. */
+html { font-family: sans-serif; /* 1 */ -ms-text-size-adjust: 100%; /* 2 */ -webkit-text-size-adjust: 100%; /* 2 */ }
+
+/** Remove default margin. */
+body { margin: 0; }
+
+/* ========================================================================== Links ========================================================================== */
+/** Remove the gray background color from active links in IE 10. */
+a { background: transparent; }
+
+/** Address `outline` inconsistency between Chrome and other browsers. */
+a:focus { outline: thin dotted; }
+
+/** Improve readability when focused and also mouse hovered in all browsers. */
+a:active, a:hover { outline: 0; }
+
+/* ========================================================================== Typography ========================================================================== */
+/** Address variable `h1` font-size and margin within `section` and `article` contexts in Firefox 4+, Safari 5, and Chrome. */
+h1 { font-size: 2em; margin: 0.67em 0; }
+
+/** Address styling not present in IE 8/9, Safari 5, and Chrome. */
+abbr[title] { border-bottom: 1px dotted; }
+
+/** Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome. */
+b, strong { font-weight: bold; }
+
+/** Address styling not present in Safari 5 and Chrome. */
+dfn { font-style: italic; }
+
+/** Address differences between Firefox and other browsers. */
+hr { -moz-box-sizing: content-box; box-sizing: content-box; height: 0; }
+
+/** Address styling not present in IE 8/9. */
+mark { background: #ff0; color: #000; }
+
+/** Correct font family set oddly in Safari 5 and Chrome. */
+code, kbd, pre, samp { font-family: monospace, serif; font-size: 1em; }
+
+/** Improve readability of pre-formatted text in all browsers. */
+pre { white-space: pre-wrap; }
+
+/** Set consistent quote types. */
+q { quotes: "\201C" "\201D" "\2018" "\2019"; }
+
+/** Address inconsistent and variable font size in all browsers. */
+small { font-size: 80%; }
+
+/** Prevent `sub` and `sup` affecting `line-height` in all browsers. */
+sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }
+
+sup { top: -0.5em; }
+
+sub { bottom: -0.25em; }
+
+/* ========================================================================== Embedded content ========================================================================== */
+/** Remove border when inside `a` element in IE 8/9. */
+img { border: 0; }
+
+/** Correct overflow displayed oddly in IE 9. */
+svg:not(:root) { overflow: hidden; }
+
+/* ========================================================================== Figures ========================================================================== */
+/** Address margin not present in IE 8/9 and Safari 5. */
+figure { margin: 0; }
+
+/* ========================================================================== Forms ========================================================================== */
+/** Define consistent border, margin, and padding. */
+fieldset { border: 1px solid #c0c0c0; margin: 0 2px; padding: 0.35em 0.625em 0.75em; }
+
+/** 1. Correct `color` not being inherited in IE 8/9. 2. Remove padding so people aren't caught out if they zero out fieldsets. */
+legend { border: 0; /* 1 */ padding: 0; /* 2 */ }
+
+/** 1. Correct font family not being inherited in all browsers. 2. Correct font size not being inherited in all browsers. 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome. */
+button, input, select, textarea { font-family: inherit; /* 1 */ font-size: 100%; /* 2 */ margin: 0; /* 3 */ }
+
+/** Address Firefox 4+ setting `line-height` on `input` using `!important` in the UA stylesheet. */
+button, input { line-height: normal; }
+
+/** Address inconsistent `text-transform` inheritance for `button` and `select`. All other form control elements do not inherit `text-transform` values. Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+. Correct `select` style inheritance in Firefox 4+ and Opera. */
+button, select { text-transform: none; }
+
+/** 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` and `video` controls. 2. Correct inability to style clickable `input` types in iOS. 3. Improve usability and consistency of cursor style between image-type `input` and others. */
+button, html input[type="button"], input[type="reset"], input[type="submit"] { -webkit-appearance: button; /* 2 */ cursor: pointer; /* 3 */ }
+
+/** Re-set default cursor for disabled elements. */
+button[disabled], html input[disabled] { cursor: default; }
+
+/** 1. Address box sizing set to `content-box` in IE 8/9. 2. Remove excess padding in IE 8/9. */
+input[type="checkbox"], input[type="radio"] { box-sizing: border-box; /* 1 */ padding: 0; /* 2 */ }
+
+/** 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome (include `-moz` to future-proof). */
+input[type="search"] { -webkit-appearance: textfield; /* 1 */ -moz-box-sizing: content-box; -webkit-box-sizing: content-box; /* 2 */ box-sizing: content-box; }
+
+/** Remove inner padding and search cancel button in Safari 5 and Chrome on OS X. */
+input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; }
+
+/** Remove inner padding and border in Firefox 4+. */
+button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; }
+
+/** 1. Remove default vertical scrollbar in IE 8/9. 2. Improve readability and alignment in all browsers. */
+textarea { overflow: auto; /* 1 */ vertical-align: top; /* 2 */ }
+
+/* ========================================================================== Tables ========================================================================== */
+/** Remove most spacing between table cells. */
+table { border-collapse: collapse; border-spacing: 0; }
+
+meta.foundation-mq-small { font-family: "only screen and (min-width: 768px)"; width: 768px; }
+
+meta.foundation-mq-medium { font-family: "only screen and (min-width:1280px)"; width: 1280px; }
+
+meta.foundation-mq-large { font-family: "only screen and (min-width:1440px)"; width: 1440px; }
+
+*, *:before, *:after { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; }
+
+html, body { font-size: 100%; }
+
+body { background: white; color: #222222; padding: 0; margin: 0; font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; font-weight: normal; font-style: normal; line-height: 1; position: relative; cursor: auto; }
+
+a:hover { cursor: pointer; }
+
+img, object, embed { max-width: 100%; height: auto; }
+
+object, embed { height: 100%; }
+
+img { -ms-interpolation-mode: bicubic; }
+
+#map_canvas img, #map_canvas embed, #map_canvas object, .map_canvas img, .map_canvas embed, .map_canvas object { max-width: none !important; }
+
+.left { float: left !important; }
+
+.right { float: right !important; }
+
+.text-left { text-align: left !important; }
+
+.text-right { text-align: right !important; }
+
+.text-center { text-align: center !important; }
+
+.text-justify { text-align: justify !important; }
+
+.hide { display: none; }
+
+.antialiased { -webkit-font-smoothing: antialiased; }
+
+img { display: inline-block; vertical-align: middle; }
+
+textarea { height: auto; min-height: 50px; }
+
+select { width: 100%; }
+
+object, svg { display: inline-block; vertical-align: middle; }
+
+.center { margin-left: auto; margin-right: auto; }
+
+.spread { width: 100%; }
+
+p.lead, .paragraph.lead > p, #preamble > .sectionbody > .paragraph:first-of-type p { font-size: 1.21875em; line-height: 1.6; }
+
+.subheader, .admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { line-height: 1.4; color: black; font-weight: 300; margin-top: 0.2em; margin-bottom: 0.5em; }
+
+/* Typography resets */
+div, dl, dt, dd, ul, ol, li, h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6, pre, form, p, blockquote, th, td { margin: 0; padding: 0; direction: ltr; }
+
+/* Default Link Styles */
+a { color: #0068b0; text-decoration: none; line-height: inherit; }
+a:hover, a:focus { color: #333333; }
+a img { border: none; }
+
+/* Default paragraph styles */
+p { font-family: Noto, sans-serif; font-weight: normal; font-size: 1em; line-height: 1.6; margin-bottom: 0.75em; text-rendering: optimizeLegibility; }
+p aside { font-size: 0.875em; line-height: 1.35; font-style: italic; }
+
+/* Default header styles */
+h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { font-family: Noto, sans-serif; font-weight: normal; font-style: normal; color: black; text-rendering: optimizeLegibility; margin-top: 0.5em; margin-bottom: 0.5em; line-height: 1.2125em; }
+h1 small, h2 small, h3 small, #toctitle small, .sidebarblock > .content > .title small, h4 small, h5 small, h6 small { font-size: 60%; color: #4d4d4d; line-height: 0; }
+
+h1 { font-size: 2.125em; }
+
+h2 { font-size: 1.6875em; }
+
+h3, #toctitle, .sidebarblock > .content > .title { font-size: 1.375em; }
+
+h4 { font-size: 1.125em; }
+
+h5 { font-size: 1.125em; }
+
+h6 { font-size: 1em; }
+
+hr { border: solid #dddddd; border-width: 1px 0 0; clear: both; margin: 1.25em 0 1.1875em; height: 0; }
+
+/* Helpful Typography Defaults */
+em, i { font-style: italic; line-height: inherit; }
+
+strong, b { font-weight: bold; line-height: inherit; }
+
+small { font-size: 60%; line-height: inherit; }
+
+code { font-family: Consolas, "Liberation Mono", Courier, monospace; font-weight: normal; color: #264357; }
+
+/* Lists */
+ul, ol, dl { font-size: 1em; line-height: 1.6; margin-bottom: 0.75em; list-style-position: outside; font-family: Noto, sans-serif; }
+
+ul, ol { margin-left: 1.5em; }
+ul.no-bullet, ol.no-bullet { margin-left: 1.5em; }
+
+/* Unordered Lists */
+ul li ul, ul li ol { margin-left: 1.25em; margin-bottom: 0; font-size: 1em; /* Override nested font-size change */ }
+ul.square li ul, ul.circle li ul, ul.disc li ul { list-style: inherit; }
+ul.square { list-style-type: square; }
+ul.circle { list-style-type: circle; }
+ul.disc { list-style-type: disc; }
+ul.no-bullet { list-style: none; }
+
+/* Ordered Lists */
+ol li ul, ol li ol { margin-left: 1.25em; margin-bottom: 0; }
+
+/* Definition Lists */
+dl dt { margin-bottom: 0.3em; font-weight: bold; }
+dl dd { margin-bottom: 0.75em; }
+
+/* Abbreviations */
+abbr, acronym { text-transform: uppercase; font-size: 90%; color: black; border-bottom: 1px dotted #dddddd; cursor: help; }
+
+abbr { text-transform: none; }
+
+/* Blockquotes */
+blockquote { margin: 0 0 0.75em; padding: 0.5625em 1.25em 0 1.1875em; border-left: 1px solid #dddddd; }
+blockquote cite { display: block; font-size: 0.8125em; color: #5e93b8; }
+blockquote cite:before { content: "\2014 \0020"; }
+blockquote cite a, blockquote cite a:visited { color: #5e93b8; }
+
+blockquote, blockquote p { line-height: 1.6; color: #333333; }
+
+/* Microformats */
+.vcard { display: inline-block; margin: 0 0 1.25em 0; border: 1px solid #dddddd; padding: 0.625em 0.75em; }
+.vcard li { margin: 0; display: block; }
+.vcard .fn { font-weight: bold; font-size: 0.9375em; }
+
+.vevent .summary { font-weight: bold; }
+.vevent abbr { cursor: auto; text-decoration: none; font-weight: bold; border: none; padding: 0 0.0625em; }
+
+@media only screen and (min-width: 768px) { h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { line-height: 1.4; }
+  h1 { font-size: 2.75em; }
+  h2 { font-size: 2.3125em; }
+  h3, #toctitle, .sidebarblock > .content > .title { font-size: 1.6875em; }
+  h4 { font-size: 1.4375em; } }
+/* Tables */
+table { background: white; margin-bottom: 1.25em; border: solid 1px #d8d8ce; }
+table thead, table tfoot { background: -webkit-linear-gradient(top, #add386, #90b66a); font-weight: bold; }
+table thead tr th, table thead tr td, table tfoot tr th, table tfoot tr td { padding: 0.5em 0.625em 0.625em; font-size: inherit; color: white; text-align: left; }
+table tr th, table tr td { padding: 0.5625em 0.625em; font-size: inherit; color: #6d6e71; }
+table tr.even, table tr.alt, table tr:nth-of-type(even) { background: #edf2f2; }
+table thead tr th, table tfoot tr th, table tbody tr td, table tr td, table tfoot tr td { display: table-cell; line-height: 1.4; }
+
+body { -moz-osx-font-smoothing: grayscale; -webkit-font-smoothing: antialiased; tab-size: 4; }
+
+h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { line-height: 1.4; }
+
+a:hover, a:focus { text-decoration: underline; }
+
+.clearfix:before, .clearfix:after, .float-group:before, .float-group:after { content: " "; display: table; }
+.clearfix:after, .float-group:after { clear: both; }
+
+*:not(pre) > code { font-size: inherit; font-style: normal !important; letter-spacing: 0; padding: 0; background-color: white; -webkit-border-radius: 0; border-radius: 0; line-height: inherit; word-wrap: break-word; }
+*:not(pre) > code.nobreak { word-wrap: normal; }
+*:not(pre) > code.nowrap { white-space: nowrap; }
+
+pre, pre > code { line-height: 1.6; color: #264357; font-family: Consolas, "Liberation Mono", Courier, monospace; font-weight: normal; }
+
+em em { font-style: normal; }
+
+strong strong { font-weight: normal; }
+
+.keyseq { color: #333333; }
+
+kbd { font-family: Consolas, "Liberation Mono", Courier, monospace; display: inline-block; color: black; font-size: 0.65em; line-height: 1.45; background-color: #f7f7f7; border: 1px solid #ccc; -webkit-border-radius: 3px; border-radius: 3px; -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 0.1em white inset; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 0.1em white inset; margin: 0 0.15em; padding: 0.2em 0.5em; vertical-align: middle; position: relative; top: -0.1em; white-space: nowrap; }
+
+.keyseq kbd:first-child { margin-left: 0; }
+
+.keyseq kbd:last-child { margin-right: 0; }
+
+.menuseq, .menuref { color: #000; }
+
+.menuseq b:not(.caret), .menuref { font-weight: inherit; }
+
+.menuseq { word-spacing: -0.02em; }
+.menuseq b.caret { font-size: 1.25em; line-height: 0.8; }
+.menuseq i.caret { font-weight: bold; text-align: center; width: 0.45em; }
+
+b.button:before, b.button:after { position: relative; top: -1px; font-weight: normal; }
+
+b.button:before { content: "["; padding: 0 3px 0 2px; }
+
+b.button:after { content: "]"; padding: 0 2px 0 3px; }
+
+#header, #content, #footnotes, #footer { width: 100%; margin-left: auto; margin-right: auto; margin-top: 0; margin-bottom: 0; max-width: 62.5em; *zoom: 1; position: relative; padding-left: 1.5em; padding-right: 1.5em; }
+#header:before, #header:after, #content:before, #content:after, #footnotes:before, #footnotes:after, #footer:before, #footer:after { content: " "; display: table; }
+#header:after, #content:after, #footnotes:after, #footer:after { clear: both; }
+
+#content { margin-top: 1.25em; }
+
+#content:before { content: none; }
+
+#header > h1:first-child { color: black; margin-top: 2.25rem; margin-bottom: 0; }
+#header > h1:first-child + #toc { margin-top: 8px; border-top: 1px solid #dddddd; }
+#header > h1:only-child, body.toc2 #header > h1:nth-last-child(2) { border-bottom: 1px solid #dddddd; padding-bottom: 8px; }
+#header .details { border-bottom: 1px solid #dddddd; line-height: 1.45; padding-top: 0.25em; padding-bottom: 0.25em; padding-left: 0.25em; color: #5e93b8; display: -ms-flexbox; display: -webkit-flex; display: flex; -ms-flex-flow: row wrap; -webkit-flex-flow: row wrap; flex-flow: row wrap; }
+#header .details span:first-child { margin-left: -0.125em; }
+#header .details span.email a { color: #333333; }
+#header .details br { display: none; }
+#header .details br + span:before { content: "\00a0\2013\00a0"; }
+#header .details br + span.author:before { content: "\00a0\22c5\00a0"; color: #333333; }
+#header .details br + span#revremark:before { content: "\00a0|\00a0"; }
+#header #revnumber { text-transform: capitalize; }
+#header #revnumber:after { content: "\00a0"; }
+
+#content > h1:first-child:not([class]) { color: black; border-bottom: 1px solid #dddddd; padding-bottom: 8px; margin-top: 0; padding-top: 1rem; margin-bottom: 1.25rem; }
+
+#toc { border-bottom: 0 solid #dddddd; padding-bottom: 0.5em; }
+#toc > ul { margin-left: 0.125em; }
+#toc ul.sectlevel0 > li > a { font-style: italic; }
+#toc ul.sectlevel0 ul.sectlevel1 { margin: 0.5em 0; }
+#toc ul { font-family: Noto, sans-serif; list-style-type: none; }
+#toc li { line-height: 1.3334; margin-top: 0.3334em; }
+#toc a { text-decoration: none; }
+#toc a:active { text-decoration: underline; }
+
+#toctitle { color: black; font-size: 1.2em; }
+
+@media only screen and (min-width: 768px) { #toctitle { font-size: 1.375em; }
+  body.toc2 { padding-left: 15em; padding-right: 0; }
+  #toc.toc2 { margin-top: 0 !important; background-color: white; position: fixed; width: 15em; left: 0; top: 0; border-right: 1px solid #dddddd; border-top-width: 0 !important; border-bottom-width: 0 !important; z-index: 1000; padding: 1.25em 1em; height: 100%; overflow: auto; }
+  #toc.toc2 #toctitle { margin-top: 0; margin-bottom: 0.8rem; font-size: 1.2em; }
+  #toc.toc2 > ul { font-size: 0.9em; margin-bottom: 0; }
+  #toc.toc2 ul ul { margin-left: 0; padding-left: 1em; }
+  #toc.toc2 ul.sectlevel0 ul.sectlevel1 { padding-left: 0; margin-top: 0.5em; margin-bottom: 0.5em; }
+  body.toc2.toc-right { padding-left: 0; padding-right: 15em; }
+  body.toc2.toc-right #toc.toc2 { border-right-width: 0; border-left: 1px solid #dddddd; left: auto; right: 0; } }
+@media only screen and (min-width: 1280px) { body.toc2 { padding-left: 20em; padding-right: 0; }
+  #toc.toc2 { width: 20em; }
+  #toc.toc2 #toctitle { font-size: 1.375em; }
+  #toc.toc2 > ul { font-size: 0.95em; }
+  #toc.toc2 ul ul { padding-left: 1.25em; }
+  body.toc2.toc-right { padding-left: 0; padding-right: 20em; } }
+#content #toc { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 0; border-radius: 0; }
+#content #toc > :first-child { margin-top: 0; }
+#content #toc > :last-child { margin-bottom: 0; }
+
+#footer { max-width: 100%; background-color: none; padding: 1.25em; }
+
+#footer-text { color: black; line-height: 1.44; }
+
+#content { margin-bottom: 0.625em; }
+
+.sect1 { padding-bottom: 0.625em; }
+
+@media only screen and (min-width: 768px) { #content { margin-bottom: 1.25em; }
+  .sect1 { padding-bottom: 1.25em; } }
+.sect1:last-child { padding-bottom: 0; }
+
+.sect1 + .sect1 { border-top: 0 solid #dddddd; }
+
+#content h1 > a.anchor, h2 > a.anchor, h3 > a.anchor, #toctitle > a.anchor, .sidebarblock > .content > .title > a.anchor, h4 > a.anchor, h5 > a.anchor, h6 > a.anchor { position: absolute; z-index: 1001; width: 1.5ex; margin-left: -1.5ex; display: block; text-decoration: none !important; visibility: hidden; text-align: center; font-weight: normal; }
+#content h1 > a.anchor:before, h2 > a.anchor:before, h3 > a.anchor:before, #toctitle > a.anchor:before, .sidebarblock > .content > .title > a.anchor:before, h4 > a.anchor:before, h5 > a.anchor:before, h6 > a.anchor:before { content: "\00A7"; font-size: 0.85em; display: block; padding-top: 0.1em; }
+#content h1:hover > a.anchor, #content h1 > a.anchor:hover, h2:hover > a.anchor, h2 > a.anchor:hover, h3:hover > a.anchor, #toctitle:hover > a.anchor, .sidebarblock > .content > .title:hover > a.anchor, h3 > a.anchor:hover, #toctitle > a.anchor:hover, .sidebarblock > .content > .title > a.anchor:hover, h4:hover > a.anchor, h4 > a.anchor:hover, h5:hover > a.anchor, h5 > a.anchor:hover, h6:hover > a.anchor, h6 > a.anchor:hover { visibility: visible; }
+#content h1 > a.link, h2 > a.link, h3 > a.link, #toctitle > a.link, .sidebarblock > .content > .title > a.link, h4 > a.link, h5 > a.link, h6 > a.link { color: black; text-decoration: none; }
+#content h1 > a.link:hover, h2 > a.link:hover, h3 > a.link:hover, #toctitle > a.link:hover, .sidebarblock > .content > .title > a.link:hover, h4 > a.link:hover, h5 > a.link:hover, h6 > a.link:hover { color: black; }
+
+.audioblock, .imageblock, .literalblock, .listingblock, .stemblock, .videoblock { margin-bottom: 1.25em; }
+
+.admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { text-rendering: optimizeLegibility; text-align: left; }
+
+table.tableblock > caption.title { white-space: nowrap; overflow: visible; max-width: 0; }
+
+.paragraph.lead > p, #preamble > .sectionbody > .paragraph:first-of-type p { color: black; }
+
+table.tableblock #preamble > .sectionbody > .paragraph:first-of-type p { font-size: inherit; }
+
+.admonitionblock > table { border-collapse: separate; border: 0; background: none; width: 100%; }
+.admonitionblock > table td.icon { text-align: center; width: 80px; }
+.admonitionblock > table td.icon img { max-width: initial; }
+.admonitionblock > table td.icon .title { font-weight: bold; font-family: Noto, sans-serif; text-transform: uppercase; }
+.admonitionblock > table td.content { padding-left: 1.125em; padding-right: 1.25em; border-left: 1px solid #dddddd; color: #5e93b8; }
+.admonitionblock > table td.content > :last-child > :last-child { margin-bottom: 0; }
+
+.exampleblock > .content { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 0; border-radius: 0; }
+.exampleblock > .content > :first-child { margin-top: 0; }
+.exampleblock > .content > :last-child { margin-bottom: 0; }
+
+.sidebarblock { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 0; border-radius: 0; }
+.sidebarblock > :first-child { margin-top: 0; }
+.sidebarblock > :last-child { margin-bottom: 0; }
+.sidebarblock > .content > .title { color: black; margin-top: 0; }
+
+.exampleblock > .content > :last-child > :last-child, .exampleblock > .content .olist > ol > li:last-child > :last-child, .exampleblock > .content .ulist > ul > li:last-child > :last-child, .exampleblock > .content .qlist > ol > li:last-child > :last-child, .sidebarblock > .content > :last-child > :last-child, .sidebarblock > .content .olist > ol > li:last-child > :last-child, .sidebarblock > .content .ulist > ul > li:last-child > :last-child, .sidebarblock > .content .qlist > ol > li:last-child > :last-child { margin-bottom: 0; }
+
+.literalblock pre, .listingblock pre:not(.highlight), .listingblock pre[class="highlight"], .listingblock pre[class^="highlight "], .listingblock pre.CodeRay, .listingblock pre.prettyprint { background: #eeeeee; }
+.sidebarblock .literalblock pre, .sidebarblock .listingblock pre:not(.highlight), .sidebarblock .listingblock pre[class="highlight"], .sidebarblock .listingblock pre[class^="highlight "], .sidebarblock .listingblock pre.CodeRay, .sidebarblock .listingblock pre.prettyprint { background: #f2f1f1; }
+
+.literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { border: 1px hidden #666666; -webkit-border-radius: 0; border-radius: 0; word-wrap: break-word; padding: 1.25em 1.5625em 1.125em 1.5625em; font-size: 0.8125em; }
+.literalblock pre.nowrap, .literalblock pre[class].nowrap, .listingblock pre.nowrap, .listingblock pre[class].nowrap { overflow-x: auto; white-space: pre; word-wrap: normal; }
+@media only screen and (min-width: 768px) { .literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { font-size: 0.90625em; } }
+@media only screen and (min-width: 1280px) { .literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { font-size: 1em; } }
+
+.literalblock.output pre { color: #eeeeee; background-color: #264357; }
+
+.listingblock pre.highlightjs { padding: 0; }
+.listingblock pre.highlightjs > code { padding: 1.25em 1.5625em 1.125em 1.5625em; -webkit-border-radius: 0; border-radius: 0; }
+
+.listingblock > .content { position: relative; }
+
+.listingblock code[data-lang]:before { display: none; content: attr(data-lang); position: absolute; font-size: 0.75em; top: 0.425rem; right: 0.5rem; line-height: 1; text-transform: uppercase; color: #999; }
+
+.listingblock:hover code[data-lang]:before { display: block; }
+
+.listingblock.terminal pre .command:before { content: attr(data-prompt); padding-right: 0.5em; color: #999; }
+
+.listingblock.terminal pre .command:not([data-prompt]):before { content: "$"; }
+
+table.pyhltable { border-collapse: separate; border: 0; margin-bottom: 0; background: none; }
+
+table.pyhltable td { vertical-align: top; padding-top: 0; padding-bottom: 0; line-height: 1.6; }
+
+table.pyhltable td.code { padding-left: .75em; padding-right: 0; }
+
+pre.pygments .lineno, table.pyhltable td:not(.code) { color: #999; padding-left: 0; padding-right: .5em; border-right: 1px solid #dddddd; }
+
+pre.pygments .lineno { display: inline-block; margin-right: .25em; }
+
+table.pyhltable .linenodiv { background: none !important; padding-right: 0 !important; }
+
+.quoteblock { margin: 0 1em 0.75em 1.5em; display: table; }
+.quoteblock > .title { margin-left: -1.5em; margin-bottom: 0.75em; }
+.quoteblock blockquote, .quoteblock blockquote p { color: #333333; font-size: 1.15rem; line-height: 1.75; word-spacing: 0.1em; letter-spacing: 0; font-style: italic; text-align: justify; }
+.quoteblock blockquote { margin: 0; padding: 0; border: 0; }
+.quoteblock blockquote:before { content: "\201c"; float: left; font-size: 2.75em; font-weight: bold; line-height: 0.6em; margin-left: -0.6em; color: black; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); }
+.quoteblock blockquote > .paragraph:last-child p { margin-bottom: 0; }
+.quoteblock .attribution { margin-top: 0.5em; margin-right: 0.5ex; text-align: right; }
+.quoteblock .quoteblock { margin-left: 0; margin-right: 0; padding: 0.5em 0; border-left: 3px solid #5e93b8; }
+.quoteblock .quoteblock blockquote { padding: 0 0 0 0.75em; }
+.quoteblock .quoteblock blockquote:before { display: none; }
+
+.verseblock { margin: 0 1em 0.75em 1em; }
+.verseblock pre { font-family: "Open Sans", "DejaVu Sans", sans; font-size: 1.15rem; color: #333333; font-weight: 300; text-rendering: optimizeLegibility; }
+.verseblock pre strong { font-weight: 400; }
+.verseblock .attribution { margin-top: 1.25rem; margin-left: 0.5ex; }
+
+.quoteblock .attribution, .verseblock .attribution { font-size: 0.8125em; line-height: 1.45; font-style: italic; }
+.quoteblock .attribution br, .verseblock .attribution br { display: none; }
+.quoteblock .attribution cite, .verseblock .attribution cite { display: block; letter-spacing: -0.025em; color: #5e93b8; }
+
+.quoteblock.abstract { margin: 0 0 0.75em 0; display: block; }
+.quoteblock.abstract blockquote, .quoteblock.abstract blockquote p { text-align: left; word-spacing: 0; }
+.quoteblock.abstract blockquote:before, .quoteblock.abstract blockquote p:first-of-type:before { display: none; }
+
+table.tableblock { max-width: 100%; border-collapse: separate; }
+table.tableblock td > .paragraph:last-child p > p:last-child, table.tableblock th > p:last-child, table.tableblock td > p:last-child { margin-bottom: 0; }
+
+table.tableblock, th.tableblock, td.tableblock { border: 0 solid #d8d8ce; }
+
+table.grid-all > thead > tr > .tableblock, table.grid-all > tbody > tr > .tableblock { border-width: 0 1px 1px 0; }
+
+table.grid-all > tfoot > tr > .tableblock { border-width: 1px 1px 0 0; }
+
+table.grid-cols > * > tr > .tableblock { border-width: 0 1px 0 0; }
+
+table.grid-rows > thead > tr > .tableblock, table.grid-rows > tbody > tr > .tableblock { border-width: 0 0 1px 0; }
+
+table.grid-rows > tfoot > tr > .tableblock { border-width: 1px 0 0 0; }
+
+table.grid-all > * > tr > .tableblock:last-child, table.grid-cols > * > tr > .tableblock:last-child { border-right-width: 0; }
+
+table.grid-all > tbody > tr:last-child > .tableblock, table.grid-all > thead:last-child > tr > .tableblock, table.grid-rows > tbody > tr:last-child > .tableblock, table.grid-rows > thead:last-child > tr > .tableblock { border-bottom-width: 0; }
+
+table.frame-all { border-width: 1px; }
+
+table.frame-sides { border-width: 0 1px; }
+
+table.frame-topbot { border-width: 1px 0; }
+
+th.halign-left, td.halign-left { text-align: left; }
+
+th.halign-right, td.halign-right { text-align: right; }
+
+th.halign-center, td.halign-center { text-align: center; }
+
+th.valign-top, td.valign-top { vertical-align: top; }
+
+th.valign-bottom, td.valign-bottom { vertical-align: bottom; }
+
+th.valign-middle, td.valign-middle { vertical-align: middle; }
+
+table thead th, table tfoot th { font-weight: bold; }
+
+tbody tr th { display: table-cell; line-height: 1.4; background: -webkit-linear-gradient(top, #add386, #90b66a); }
+
+tbody tr th, tbody tr th p, tfoot tr th, tfoot tr th p { color: white; font-weight: bold; }
+
+p.tableblock > code:only-child { background: none; padding: 0; }
+
+p.tableblock { font-size: 1em; }
+
+td > div.verse { white-space: pre; }
+
+ol { margin-left: 1.75em; }
+
+ul li ol { margin-left: 1.5em; }
+
+dl dd { margin-left: 1.125em; }
+
+dl dd:last-child, dl dd:last-child > :last-child { margin-bottom: 0; }
+
+ol > li p, ul > li p, ul dd, ol dd, .olist .olist, .ulist .ulist, .ulist .olist, .olist .ulist { margin-bottom: 0.375em; }
+
+ul.checklist, ul.none, ol.none, ul.no-bullet, ol.no-bullet, ol.unnumbered, ul.unstyled, ol.unstyled { list-style-type: none; }
+
+ul.no-bullet, ol.no-bullet, ol.unnumbered { margin-left: 0.625em; }
+
+ul.unstyled, ol.unstyled { margin-left: 0; }
+
+ul.checklist { margin-left: 0.625em; }
+
+ul.checklist li > p:first-child > .fa-square-o:first-child, ul.checklist li > p:first-child > .fa-check-square-o:first-child { width: 1.25em; font-size: 0.8em; position: relative; bottom: 0.125em; }
+
+ul.checklist li > p:first-child > input[type="checkbox"]:first-child { margin-right: 0.25em; }
+
+ul.inline { display: -ms-flexbox; display: -webkit-box; display: flex; -ms-flex-flow: row wrap; -webkit-flex-flow: row wrap; flex-flow: row wrap; list-style: none; margin: 0 0 0.375em -0.75em; }
+
+ul.inline > li { margin-left: 0.75em; }
+
+.unstyled dl dt { font-weight: normal; font-style: normal; }
+
+ol.arabic { list-style-type: decimal; }
+
+ol.decimal { list-style-type: decimal-leading-zero; }
+
+ol.loweralpha { list-style-type: lower-alpha; }
+
+ol.upperalpha { list-style-type: upper-alpha; }
+
+ol.lowerroman { list-style-type: lower-roman; }
+
+ol.upperroman { list-style-type: upper-roman; }
+
+ol.lowergreek { list-style-type: lower-greek; }
+
+.hdlist > table, .colist > table { border: 0; background: none; }
+.hdlist > table > tbody > tr, .colist > table > tbody > tr { background: none; }
+
+td.hdlist1, td.hdlist2 { vertical-align: top; padding: 0 0.625em; }
+
+td.hdlist1 { font-weight: bold; padding-bottom: 0.75em; }
+
+.literalblock + .colist, .listingblock + .colist { margin-top: -0.5em; }
+
+.colist > table tr > td:first-of-type { padding: 0.4em 0.75em 0 0.75em; line-height: 1; vertical-align: top; }
+.colist > table tr > td:first-of-type img { max-width: initial; }
+.colist > table tr > td:last-of-type { padding: 0.25em 0; }
+
+.thumb, .th { line-height: 0; display: inline-block; border: solid 4px white; -webkit-box-shadow: 0 0 0 1px #dddddd; box-shadow: 0 0 0 1px #dddddd; }
+
+.imageblock.left, .imageblock[style*="float: left"] { margin: 0.25em 0.625em 1.25em 0; }
+.imageblock.right, .imageblock[style*="float: right"] { margin: 0.25em 0 1.25em 0.625em; }
+.imageblock > .title { margin-bottom: 0; }
+.imageblock.thumb, .imageblock.th { border-width: 6px; }
+.imageblock.thumb > .title, .imageblock.th > .title { padding: 0 0.125em; }
+
+.image.left, .image.right { margin-top: 0.25em; margin-bottom: 0.25em; display: inline-block; line-height: 0; }
+.image.left { margin-right: 0.625em; }
+.image.right { margin-left: 0.625em; }
+
+a.image { text-decoration: none; display: inline-block; }
+a.image object { pointer-events: none; }
+
+sup.footnote, sup.footnoteref { font-size: 0.875em; position: static; vertical-align: super; }
+sup.footnote a, sup.footnoteref a { text-decoration: none; }
+sup.footnote a:active, sup.footnoteref a:active { text-decoration: underline; }
+
+#footnotes { padding-top: 0.75em; padding-bottom: 0.75em; margin-bottom: 0.625em; }
+#footnotes hr { width: 20%; min-width: 6.25em; margin: -0.25em 0 0.75em 0; border-width: 1px 0 0 0; }
+#footnotes .footnote { padding: 0 0.375em 0 0.225em; line-height: 1.3334; font-size: 0.875em; margin-left: 1.2em; margin-bottom: 0.2em; }
+#footnotes .footnote a:first-of-type { font-weight: bold; text-decoration: none; margin-left: -1.05em; }
+#footnotes .footnote:last-of-type { margin-bottom: 0; }
+#content #footnotes { margin-top: -0.625em; margin-bottom: 0; padding: 0.75em 0; }
+
+.gist .file-data > table { border: 0; background: #fff; width: 100%; margin-bottom: 0; }
+.gist .file-data > table td.line-data { width: 99%; }
+
+div.unbreakable { page-break-inside: avoid; }
+
+.big { font-size: larger; }
+
+.small { font-size: smaller; }
+
+.underline { text-decoration: underline; }
+
+.overline { text-decoration: overline; }
+
+.line-through { text-decoration: line-through; }
+
+.aqua { color: #00bfbf; }
+
+.aqua-background { background-color: #00fafa; }
+
+.black { color: black; }
+
+.black-background { background-color: black; }
+
+.blue { color: #0000bf; }
+
+.blue-background { background-color: #0000fa; }
+
+.fuchsia { color: #bf00bf; }
+
+.fuchsia-background { background-color: #fa00fa; }
+
+.gray { color: #606060; }
+
+.gray-background { background-color: #7d7d7d; }
+
+.green { color: #006000; }
+
+.green-background { background-color: #007d00; }
+
+.lime { color: #00bf00; }
+
+.lime-background { background-color: #00fa00; }
+
+.maroon { color: #600000; }
+
+.maroon-background { background-color: #7d0000; }
+
+.navy { color: #000060; }
+
+.navy-background { background-color: #00007d; }
+
+.olive { color: #606000; }
+
+.olive-background { background-color: #7d7d00; }
+
+.purple { color: #600060; }
+
+.purple-background { background-color: #7d007d; }
+
+.red { color: #bf0000; }
+
+.red-background { background-color: #fa0000; }
+
+.silver { color: #909090; }
+
+.silver-background { background-color: #bcbcbc; }
+
+.teal { color: #006060; }
+
+.teal-background { background-color: #007d7d; }
+
+.white { color: #bfbfbf; }
+
+.white-background { background-color: #fafafa; }
+
+.yellow { color: #bfbf00; }
+
+.yellow-background { background-color: #fafa00; }
+
+span.icon > .fa { cursor: default; }
+a span.icon > .fa { cursor: inherit; }
+
+.admonitionblock td.icon [class^="fa icon-"] { font-size: 2.5em; text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5); cursor: default; }
+.admonitionblock td.icon .icon-note:before { content: "\f05a"; color: #29475c; }
+.admonitionblock td.icon .icon-tip:before { content: "\f0eb"; text-shadow: 1px 1px 2px rgba(155, 155, 0, 0.8); color: #111; }
+.admonitionblock td.icon .icon-warning:before { content: "\f071"; color: #bf6900; }
+.admonitionblock td.icon .icon-caution:before { content: "\f06d"; color: #bf3400; }
+.admonitionblock td.icon .icon-important:before { content: "\f06a"; color: #bf0000; }
+
+.conum[data-value] { display: inline-block; color: #fff !important; background-color: black; -webkit-border-radius: 100px; border-radius: 100px; text-align: center; font-size: 0.75em; width: 1.67em; height: 1.67em; line-height: 1.67em; font-family: "Open Sans", "DejaVu Sans", sans-serif; font-style: normal; font-weight: bold; }
+.conum[data-value] * { color: #fff !important; }
+.conum[data-value] + b { display: none; }
+.conum[data-value]:after { content: attr(data-value); }
+pre .conum[data-value] { position: relative; top: -0.125em; }
+
+b.conum * { color: inherit !important; }
+
+.conum:not([data-value]):empty { display: none; }
+
+h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { border-bottom: 1px solid #dddddd; }
+
+.sect1 { padding-bottom: 0; }
+
+#toctitle { color: #00406F; font-weight: normal; margin-top: 1.5em; }
+
+.sidebarblock { border-color: #aaa; }
+
+code { -webkit-border-radius: 4px; border-radius: 4px; }
+
+p.tableblock.header { color: #6d6e71; }
+
+.literalblock pre, .listingblock pre { background: #eeeeee; }
+
+</style>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css">
+<style>
+/* Stylesheet for CodeRay to match GitHub theme | MIT License | http://foundation.zurb.com */
+/*pre.CodeRay {background-color:#f7f7f8;}*/
+.CodeRay .line-numbers{border-right:1px solid #d8d8d8;padding:0 0.5em 0 .25em}
+.CodeRay span.line-numbers{display:inline-block;margin-right:.5em;color:rgba(0,0,0,.3)}
+.CodeRay .line-numbers strong{color:rgba(0,0,0,.4)}
+table.CodeRay{border-collapse:separate;border-spacing:0;margin-bottom:0;border:0;background:none}
+table.CodeRay td{vertical-align: top;line-height:1.45}
+table.CodeRay td.line-numbers{text-align:right}
+table.CodeRay td.line-numbers>pre{padding:0;color:rgba(0,0,0,.3)}
+table.CodeRay td.code{padding:0 0 0 .5em}
+table.CodeRay td.code>pre{padding:0}
+.CodeRay .debug{color:#fff !important;background:#000080 !important}
+.CodeRay .annotation{color:#007}
+.CodeRay .attribute-name{color:#000080}
+.CodeRay .attribute-value{color:#700}
+.CodeRay .binary{color:#509}
+.CodeRay .comment{color:#998;font-style:italic}
+.CodeRay .char{color:#04d}
+.CodeRay .char .content{color:#04d}
+.CodeRay .char .delimiter{color:#039}
+.CodeRay .class{color:#458;font-weight:bold}
+.CodeRay .complex{color:#a08}
+.CodeRay .constant,.CodeRay .predefined-constant{color:#008080}
+.CodeRay .color{color:#099}
+.CodeRay .class-variable{color:#369}
+.CodeRay .decorator{color:#b0b}
+.CodeRay .definition{color:#099}
+.CodeRay .delimiter{color:#000}
+.CodeRay .doc{color:#970}
+.CodeRay .doctype{color:#34b}
+.CodeRay .doc-string{color:#d42}
+.CodeRay .escape{color:#666}
+.CodeRay .entity{color:#800}
+.CodeRay .error{color:#808}
+.CodeRay .exception{color:inherit}
+.CodeRay .filename{color:#099}
+.CodeRay .function{color:#900;font-weight:bold}
+.CodeRay .global-variable{color:#008080}
+.CodeRay .hex{color:#058}
+.CodeRay .integer,.CodeRay .float{color:#099}
+.CodeRay .include{color:#555}
+.CodeRay .inline{color:#000}
+.CodeRay .inline .inline{background:#ccc}
+.CodeRay .inline .inline .inline{background:#bbb}
+.CodeRay .inline .inline-delimiter{color:#d14}
+.CodeRay .inline-delimiter{color:#d14}
+.CodeRay .important{color:#555;font-weight:bold}
+.CodeRay .interpreted{color:#b2b}
+.CodeRay .instance-variable{color:#008080}
+.CodeRay .label{color:#970}
+.CodeRay .local-variable{color:#963}
+.CodeRay .octal{color:#40e}
+.CodeRay .predefined{color:#369}
+.CodeRay .preprocessor{color:#579}
+.CodeRay .pseudo-class{color:#555}
+.CodeRay .directive{font-weight:bold}
+.CodeRay .type{font-weight:bold}
+.CodeRay .predefined-type{color:inherit}
+.CodeRay .reserved,.CodeRay .keyword {color:#000;font-weight:bold}
+.CodeRay .key{color:#808}
+.CodeRay .key .delimiter{color:#606}
+.CodeRay .key .char{color:#80f}
+.CodeRay .value{color:#088}
+.CodeRay .regexp .delimiter{color:#808}
+.CodeRay .regexp .content{color:#808}
+.CodeRay .regexp .modifier{color:#808}
+.CodeRay .regexp .char{color:#d14}
+.CodeRay .regexp .function{color:#404;font-weight:bold}
+.CodeRay .string{color:#d20}
+.CodeRay .string .string .string{background:#ffd0d0}
+.CodeRay .string .content{color:#d14}
+.CodeRay .string .char{color:#d14}
+.CodeRay .string .delimiter{color:#d14}
+.CodeRay .shell{color:#d14}
+.CodeRay .shell .delimiter{color:#d14}
+.CodeRay .symbol{color:#990073}
+.CodeRay .symbol .content{color:#a60}
+.CodeRay .symbol .delimiter{color:#630}
+.CodeRay .tag{color:#008080}
+.CodeRay .tag-special{color:#d70}
+.CodeRay .variable{color:#036}
+.CodeRay .insert{background:#afa}
+.CodeRay .delete{background:#faa}
+.CodeRay .change{color:#aaf;background:#007}
+.CodeRay .head{color:#f8f;background:#505}
+.CodeRay .insert .insert{color:#080}
+.CodeRay .delete .delete{color:#800}
+.CodeRay .change .change{color:#66f}
+.CodeRay .head .head{color:#f4f}
+</style>
+<link rel="stylesheet" href="../katex/katex.min.css">
+<script src="../katex/katex.min.js"></script>
+<script src="../katex/contrib/auto-render.min.js"></script>
+    <!-- Use KaTeX to render math once document is loaded, see
+         https://github.com/Khan/KaTeX/tree/master/contrib/auto-render -->
+<script>
+    document.addEventListener("DOMContentLoaded", function () {
+        renderMathInElement(
+            document.body,
+            {
+                delimiters: [
+                    { left: "$$", right: "$$", display: true},
+                    { left: "\\[", right: "\\]", display: true},
+                    { left: "$", right: "$", display: false},
+                    { left: "\\(", right: "\\)", display: false}
+                ]
+            }
+        );
+    });
+</script></head>
+<body class="book toc2 toc-left" style="max-width: 100;">
+<div id="header">
+<h1>The OpenCL Extension Specification</h1>
+<div class="details">
+<span id="author" class="author">Khronos OpenCL Working Group</span><br>
+<span id="revnumber">version 2.2-7,</span>
+<span id="revdate">Sat, 12 May 2018 13:21:27 +0000</span>
+<br><span id="revremark">from git branch: master commit: ab6da3001e9eeafaa36c18888ca7eb4ebb9768af</span>
+</div>
+<div id="toc" class="toc2">
+<div id="toctitle">Table of Contents</div>
+<ul class="sectlevel1">
+<li><a href="#optional-extensions">1. Optional Extensions</a></li>
+<li><a href="#cl_khr_fp16">2. Half Precision Floating-Point</a></li>
+<li><a href="#cl_khr_gl_sharing">3. Creating an OpenCL Context from an OpenGL Context or Share Group</a></li>
+<li><a href="#cl_khr_gl_sharing__memobjs">4. Creating OpenCL Memory Objects from OpenGL Objects</a></li>
+<li><a href="#cl_khr_gl_event-creating">5. Creating OpenCL Event Objects from OpenGL Sync Objects</a></li>
+<li><a href="#cl_khr_dx9_media_sharing">6. Creating OpenCL Memory Objects from DirectX 9 Media Surfaces</a></li>
+<li><a href="#cl_khr_d3d10_sharing">7. Creating OpenCL Memory Objects from Direct3D 10 Buffers and Textures</a></li>
+<li><a href="#cl_khr_d3d11_sharing">8. Creating OpenCL Memory Objects from Direct3D 11 Buffers and Textures</a></li>
+<li><a href="#cl_khr_gl_depth_images">9. Sharing OpenGL and OpenGL ES Depth and Depth-Stencil Images</a></li>
+<li><a href="#cl_khr_gl_msaa_sharing">10. Creating OpenCL Memory Obejcts from OpenGL MSAA Textures</a></li>
+<li><a href="#cl_khr_initialize_memory">11. Local and Private Memory Initialization</a></li>
+<li><a href="#cl_khr_terminate_context">12. Terminating OpenCL contexts</a></li>
+<li><a href="#cl_khr_spir">13. SPIR 1.2 Binaries</a></li>
+<li><a href="#cl_khr_icd-opencl">14. OpenCL Installable Client Driver (ICD)</a></li>
+<li><a href="#cl_khr_subgroups">15. Subgroups</a></li>
+<li><a href="#cl_khr_mipmap_image">16. Mipmaps</a></li>
+<li><a href="#cl_khr_egl_image">17. Creating OpenCL Memory Objects from EGL Images</a></li>
+<li><a href="#cl_khr_egl_event">18. Creating OpenCL Event Objects from EGL Sync Objects</a></li>
+<li><a href="#cl_khr_priority_hints">19. Priority Hints</a></li>
+<li><a href="#cl_khr_throttle_hints">20. Throttle Hints</a></li>
+<li><a href="#cl_khr_subgroup_named_barrier">21. Named Barriers for Subgroups</a></li>
+<li><a href="#_summary_of_changes_from_opencl_2_1">Appendix A: Summary of Changes from OpenCL 2.1</a></li>
+</ul>
+</div>
+</div>
+<div id="content">
+<div id="preamble">
+<div class="sectionbody">
+<div class="paragraph">
+<p>Copyright 2008-2018 The Khronos Group.</p>
+</div>
+<div class="paragraph">
+<p>This specification is protected by copyright laws and contains material proprietary
+to the Khronos Group, Inc. Except as described by these terms, it or any components
+may not be reproduced, republished, distributed, transmitted, displayed, broadcast
+or otherwise exploited in any manner without the express prior written permission
+of Khronos Group.</p>
+</div>
+<div class="paragraph">
+<p>Khronos Group grants a conditional copyright license to use and reproduce the
+unmodified specification for any purpose, without fee or royalty, EXCEPT no licenses
+to any patent, trademark or other intellectual property rights are granted under
+these terms. Parties desiring to implement the specification and make use of
+Khronos trademarks in relation to that implementation, and receive reciprocal patent
+license protection under the Khronos IP Policy must become Adopters and confirm the
+implementation as conformant under the process defined by Khronos for this
+specification; see <a href="https://www.khronos.org/adopters" class="bare">https://www.khronos.org/adopters</a>.</p>
+</div>
+<div class="paragraph">
+<p>Khronos Group makes no, and expressly disclaims any, representations or warranties,
+express or implied, regarding this specification, including, without limitation:
+merchantability, fitness for a particular purpose, non-infringement of any
+intellectual property, correctness, accuracy, completeness, timeliness, and
+reliability. Under no circumstances will the Khronos Group, or any of its Promoters,
+Contributors or Members, or their respective partners, officers, directors,
+employees, agents or representatives be liable for any damages, whether direct,
+indirect, special or consequential damages for lost revenues, lost profits, or
+otherwise, arising from or in connection with these materials.</p>
+</div>
+<div class="paragraph">
+<p>Vulkan is a registered trademark and Khronos, OpenXR, SPIR, SPIR-V, SYCL, WebGL,
+WebCL, OpenVX, OpenVG, EGL, COLLADA, glTF, NNEF, OpenKODE, OpenKCAM, StreamInput,
+OpenWF, OpenSL ES, OpenMAX, OpenMAX AL, OpenMAX IL, OpenMAX DL, OpenML and DevU are
+trademarks of the Khronos Group Inc. ASTC is a trademark of ARM Holdings PLC,
+OpenCL is a trademark of Apple Inc. and OpenGL and OpenML are registered trademarks
+and the OpenGL ES and OpenGL SC logos are trademarks of Silicon Graphics
+International used under license by Khronos. All other product names, trademarks,
+and/or company names are used solely for identification and belong to their
+respective owners.</p>
+</div>
+<div style="page-break-after: always;"></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="optional-extensions">1. Optional Extensions</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>This document describes the list of optional features supported by OpenCL
+2.2.
+Optional extensions may be supported by some OpenCL devices.
+Optional extensions are not required to be supported by a conformant OpenCL
+implementation, but are expected to be widely available; they define
+functionality that is likely to move into the required feature set in a
+future revision of the OpenCL specification.
+A brief description of how OpenCL extensions are defined is provided below.</p>
+</div>
+<div class="paragraph">
+<p>For OpenCL extensions approved by the OpenCL working group, the following
+naming conventions are used:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>A unique <em>name string</em> of the form <code>"<strong>cl_khr_&lt;<em>name</em>&gt;</strong>"</code> is associated
+with each extension.
+If the extension is supported by an implementation, this string will be
+present in the implementation&#8217;s CL_PLATFORM_EXTENSIONS string or
+CL_DEVICE_EXTENSIONS string.</p>
+</li>
+<li>
+<p>All API functions defined by the extension will have names of the form
+<strong>cl&lt;<em>function_name</em>&gt;KHR</strong>.</p>
+</li>
+<li>
+<p>All enumerants defined by the extension will have names of the form
+<strong>CL_&lt;<em>enum_name</em>&gt;_KHR.</strong></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>OpenCL extensions approved by the OpenCL working group can be <em>promoted</em> to
+required core features in later revisions of OpenCL.
+When this occurs, the extension specifications are merged into the core
+specification.
+Functions and enumerants that are part of such promoted extensions will have
+the <strong>KHR</strong> affix removed.
+OpenCL implementations of such later revisions must also export the name
+strings of promoted extensions in the CL_PLATFORM_EXTENSIONS or
+CL_DEVICE_EXTENSIONS string, and support the <strong>KHR</strong>-affixed versions of
+functions and enumerants as a transition aid.</p>
+</div>
+<div class="paragraph">
+<p>For vendor extensions, the following naming conventions are used:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>A unique <em>name string</em> of the form <code>"<strong>cl_&lt;<em>vendor_name</em>&gt;_&lt;<em>name&gt;</em></strong>"</code>
+is associated with each extension.
+If the extension is supported by an implementation, this string will be
+present in the implementation&#8217;s CL_PLATFORM_EXTENSIONS string or
+CL_DEVICE_EXTENSIONS string.</p>
+</li>
+<li>
+<p>All API functions defined by the vendor extension will have names of the
+form <strong>cl&lt;<em>function_name</em>&gt;&lt;<em>vendor_name</em>&gt;</strong>.</p>
+</li>
+<li>
+<p>All enumerants defined by the vendor extension will have names of the
+form <strong>CL_&lt;<em>enum_name</em>&gt;_&lt;<em>vendor_name</em>&gt;.</strong></p>
+</li>
+</ul>
+</div>
+<div class="sect2">
+<h3 id="compiler-directives-for-optional-extensions">1.1. Compiler Directives for Optional Extensions</h3>
+<div class="paragraph">
+<p>The <strong>#pragma OPENCL EXTENSION</strong> directive controls the behavior of the OpenCL
+compiler with respect to extensions.
+The <strong>#pragma OPENCL EXTENSION</strong> directive is defined as:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#pragma OPENCL EXTENSION &lt;extension_name&gt; : &lt;behavior&gt;
+#pragma OPENCL EXTENSION all : &lt;behavior&gt;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>where <em>extension_name</em> is the name of the extension.
+The <em>extension_name</em> will have names of the form <strong>cl_khr_&lt;<em>name</em>&gt;</strong> for an
+extension approved by the OpenCL working group and will have names of the
+form <strong>cl_&lt;<em>vendor_name</em>&gt;_&lt;<em>name</em>&gt;</strong> for vendor extensions.
+The token <strong>all</strong> means that the behavior applies to all extensions supported
+by the compiler.
+The <em>behavior</em> can be set to one of the following values given by the table
+below.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 25%;">
+<col style="width: 75%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>behavior</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>enable</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Behave as specified by the extension <em>extension_name</em>.</p>
+<p class="tableblock">  Report an error on the <strong><code>#pragma OPENCL EXTENSION</code></strong> if the
+  <em>extension_name</em> is not supported, or if <strong>all</strong> is specified.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>disable</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Behave (including issuing errors and warnings) as if the extension
+  <em>extension_name</em> is not part of the language definition.</p>
+<p class="tableblock">  If <strong>all</strong> is specified, then behavior must revert back to that of the
+  non-extended core version of the language being compiled to.</p>
+<p class="tableblock">  Warn on the <strong><code>#pragma OPENCL EXTENSION</code></strong> if the extension <em>extension_name</em>
+  is not supported.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>The <strong><code>#pragma OPENCL EXTENSION</code></strong> directive is a simple, low-level mechanism
+to set the behavior for each extension.
+It does not define policies such as which combinations are appropriate;
+those must be defined elsewhere.
+The order of directives matter in setting the behavior for each extension.
+Directives that occur later override those seen earlier.
+The <strong>all</strong> variant sets the behavior for all extensions, overriding all
+previously issued extension directives, but only if the <em>behavior</em> is set to
+<strong>disable</strong>.</p>
+</div>
+<div class="paragraph">
+<p>The initial state of the compiler is as if the directive</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#pragma OPENCL EXTENSION all : disable</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>was issued, telling the compiler that all error and warning reporting must
+be done according to this specification, ignoring any extensions.</p>
+</div>
+<div class="paragraph">
+<p>Every extension which affects the OpenCL language semantics, syntax or adds
+built-in functions to the language must create a preprocessor <code>#define</code> that
+matches the extension name string.
+This <code>#define</code> would be available in the language if and only if the
+extension is supported on a given implementation.</p>
+</div>
+<div class="paragraph">
+<p><strong>Example</strong>:</p>
+</div>
+<div class="paragraph">
+<p>An extension which adds the extension string <code>"cl_khr_3d_image_writes"</code>
+should also add a preprocessor <code>#define</code> called <strong><code>cl_khr_3d_image_writes</code></strong>.
+A kernel can now use this preprocessor <code>#define</code> to do something like:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#ifdef cl_khr_3d_image_writes
+    // do something using the extension
+#else
+    // do something else or #error!
+#endif</code></pre>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="getting-opencl-api-extension-function-pointers">1.2. Getting OpenCL API Extension Function Pointers</h3>
+<div class="paragraph">
+<p>The function
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>void clGetExtensionFunctionAddressForPlatform(cl_platform_id platform,
+                                              const char *funcname)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>returns the address of the extension function named by <em>funcname</em> for a
+given <em>platform</em> The pointer returned should be cast to a function pointer
+type matching the extension function&#8217;s definition defined in the appropriate
+extension specification and header file.
+A return value of <code>NULL</code> indicates that the specified function does not
+exist for the implementation or <em>platform</em> is not a valid platform.
+A non-<code>NULL</code> return value for <strong>clGetExtensionFunctionAddressForPlatform</strong>
+does not guarantee that an extension function is actually supported by the
+platform.
+The application must also make a corresponding query using
+<strong>clGetPlatformInfo</strong>(platform, CL_PLATFORM_EXTENSIONS, &#8230;&#8203;) or
+<strong>clGetDeviceInfo</strong>(device, CL_DEVICE_EXTENSIONS, &#8230;&#8203;) to determine if an
+extension is supported by the OpenCL implementation.</p>
+</div>
+<div class="paragraph">
+<p>Since there is no way to qualify the query with a
+device, the function pointer returned must work for all implementations of
+that extension on different devices for a platform.
+The behavior of calling a device extension function on a device not
+supporting that extension is undefined.</p>
+</div>
+<div class="paragraph">
+<p><strong>clGetExtensionFunctionAddressForPlatform</strong> may not be be used to query for core
+(non-extension) functions in OpenCL.
+For extension functions that may be queried using
+<strong>clGetExtensionFunctionAddressForPlatform</strong>, implementations may also choose to
+export those functions statically from the object libraries
+implementing those functions, however, portable applications cannot rely on
+this behavior.</p>
+</div>
+<div class="paragraph">
+<p>Function pointer typedefs must be declared for all extensions that add API
+entrypoints.
+These typedefs are a required part of the extension interface, to be
+provided in an appropriate header (such as cl_ext.h if the extension is an
+OpenCL extension, or cl_gl_ext.h if the extension is an OpenCL / OpenGL
+sharing extension).</p>
+</div>
+<div class="paragraph">
+<p>The following convention must be followed for all extensions affecting the
+host API:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#ifndef extension_name
+#define extension_name 1
+
+// all data typedefs, token #defines, prototypes, and
+// function pointer typedefs for this extension
+
+// function pointer typedefs must use the
+// following naming convention
+
+typedef CL_API_ENTRY return_type
+            (CL_API_CALL *clExtensionFunctionNameTAG_fn)(...);
+
+#endif // _extension_name_</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>where <code>TAG</code> can be <code>KHR</code>, <code>EXT</code> or <code>vendor-specific</code>.</p>
+</div>
+<div class="paragraph">
+<p>Consider, for example, the <strong>cl_khr_gl_sharing</strong> extension.
+This extension would add the following to cl_gl_ext.h:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#ifndef cl_khr_gl_sharing
+#define cl_khr_gl_sharing 1
+
+// all data typedefs, token #defines, prototypes, and
+// function pointer typedefs for this extension
+#define CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR -1000
+#define CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR 0x2006
+#define CL_DEVICES_FOR_GL_CONTEXT_KHR 0x2007
+#define CL_GL_CONTEXT_KHR 0x2008
+#define CL_EGL_DISPLAY_KHR 0x2009
+#define CL_GLX_DISPLAY_KHR 0x200A
+#define CL_WGL_HDC_KHR 0x200B
+#define CL_CGL_SHAREGROUP_KHR 0x200C
+
+// function pointer typedefs must use the
+// following naming convention
+typedef CL_API_ENTRY cl_int
+        (CL_API_CALL *clGetGLContextInfoKHR_fn)(
+            const cl_context_properties * /* properties */,
+            cl_gl_context_info /* param_name */,
+            size_t /* param_value_size */,
+            void * /* param_value */,
+            size_t * /*param_value_size_ret*/);
+
+#endif // cl_khr_gl_sharing</code></pre>
+</div>
+</div>
+<div style="page-break-after: always;"></div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="cl_khr_fp16">2. Half Precision Floating-Point</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>This section describes the <strong>cl_khr_fp16</strong> extension.
+This extension adds support for half scalar and vector types as built-in
+types that can be used for arithmetic operations, conversions etc.</p>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_fp16-additions-to-chapter-6-of-the-opencl-2.0-specification">2.1. Additions to Chapter 6 of the OpenCL 2.0 C Specification</h3>
+<div class="paragraph">
+<p>The list of built-in scalar, and vector data types defined in <em>tables 6.1</em>,
+and <em>6.2</em> are extended to include the following:</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 25%;">
+<col style="width: 75%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Type</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 2-component half-precision floating-point vector.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half3</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 3-component half-precision floating-point vector.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half4</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 4-component half-precision floating-point vector.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half8</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 8-component half-precision floating-point vector.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half16</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 16-component half-precision floating-point vector.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>The built-in vector data types for <code>halfn</code> are also declared as appropriate
+types in the OpenCL API (and header files) that can be used by an
+application.
+The following table describes the built-in vector data types for <code>halfn</code> as
+defined in the OpenCL C programming language and the corresponding data type
+available to the application:</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Type in OpenCL Language</strong></th>
+<th class="tableblock halign-left valign-top"><strong>API type for application</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cl_half2</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half3</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cl_half3</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half4</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cl_half4</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half8</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cl_half8</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>half16</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cl_half16</strong></p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>The relational, equality, logical and logical unary operators described in
+<em>section 6.3</em> can be used with <code>half</code> scalar and <code>halfn</code> vector types and
+shall produce a scalar <code>int</code> and vector <code>shortn</code> result respectively.</p>
+</div>
+<div class="paragraph">
+<p>The OpenCL compiler accepts an h and H suffix on floating point literals,
+indicating the literal is typed as a half.</p>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_fp16-conversions">2.1.1. Conversions</h4>
+<div class="paragraph">
+<p>The implicit conversion rules specified in <em>section 6.2.1</em> now include the
+<code>half</code> scalar and <code>halfn</code> vector data types.</p>
+</div>
+<div class="paragraph">
+<p>The explicit casts described in <em>section 6.2.2</em> are extended to take a
+<code>half</code> scalar data type and a <code>halfn</code> vector data type.</p>
+</div>
+<div class="paragraph">
+<p>The explicit conversion functions described in <em>section 6.2.3</em> are extended
+to take a <code>half</code> scalar data type and a <code>halfn</code> vector data type.</p>
+</div>
+<div class="paragraph">
+<p>The <code>as_typen()</code> function for re-interpreting types as described in <em>section
+6.2.4.2</em> is extended to allow conversion-free casts between <code>shortn</code>,
+<code>ushortn</code>, and <code>halfn</code> scalar and vector data types.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_fp16-math-functions">2.1.2. Math Functions</h4>
+<div class="paragraph">
+<p>The built-in math functions defined in <em>table 6.8</em> (also listed below) are
+extended to include appropriate versions of functions that take <code>half</code>, and
+<code>half{2|3|4|8|16}</code> as arguments and return values.
+<code>gentype</code> now also includes <code>half</code>, <code>half2</code>, <code>half3</code>, <code>half4</code>, <code>half8</code>, and
+<code>half16</code>.</p>
+</div>
+<div class="paragraph">
+<p>For any specific use of a function, the actual type has to be the same for
+all arguments and the return type.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 1. <em>Half Precision Built-in Math Functions</em></caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Function</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>acos</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Arc cosine function.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>acosh</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Inverse hyperbolic cosine.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>acospi</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute <strong>acos</strong> (<em>x</em>) / π.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>asin</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Arc sine function.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>asinh</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Inverse hyperbolic sine.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>asinpi</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute <strong>asin</strong> (<em>x</em>) / π.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>atan</strong> (gentype <em>y_over_x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Arc tangent function.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>atan2</strong> (gentype <em>y</em>, gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Arc tangent of <em>y</em> / <em>x</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>atanh</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Hyperbolic arc tangent.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>atanpi</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute <strong>atan</strong> (<em>x</em>) / π.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>atan2pi</strong> (gentype <em>y</em>, gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute <strong>atan2</strong> (<em>y</em>, <em>x</em>) / π.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>cbrt</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute cube-root.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>ceil</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Round to integral value using the round to positive infinity rounding
+  mode.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>copysign</strong> (gentype <em>x</em>, gentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <em>x</em> with its sign changed to match the sign of <em>y</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>cos</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute cosine.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>cosh</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute hyperbolic consine.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>cospi</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute <strong>cos</strong> (π <em>x</em>).</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>erfc</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Complementary error function.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>erf</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Error function encountered in integrating the normal distribution.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>exp</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute the base- e exponential of <em>x</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>exp2</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Exponential base 2 function.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>exp10</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Exponential base 10 function.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>expm1</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute <em>e<sup>x</sup></em>- 1.0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>fabs</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute absolute value of a floating-point number.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>fdim</strong> (gentype <em>x</em>, gentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><em>x</em> - <em>y</em> if <em>x</em> &gt; <em>y</em>, +0 if x is less than or equal to y.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>floor</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Round to integral value using the round to negative infinity rounding
+  mode.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>fma</strong> (gentype <em>a</em>, gentype <em>b</em>, gentype <em>c</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the correctly rounded floating-point representation of the sum of
+  <em>c</em> with the infinitely precise product of <em>a</em> and <em>b</em>.
+  Rounding of intermediate products shall not occur.
+  Edge case behavior is per the IEEE 754-2008.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>fmax</strong> (gentype x, gentype y)<br>
+  gentype <strong>fmax</strong> (gentype <em>x</em>, half <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <em>y</em> if <em>x</em> &lt; <em>y</em>, otherwise it returns <em>x</em>.
+  If one argument is a NaN, <strong>fmax()</strong> returns the other argument.
+  If both arguments are NaNs, <strong>fmax()</strong> returns a NaN.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>fmin</strong> (gentype <em>x</em>, gentype <em>y</em>)<br>
+  gentype <strong>fmin</strong> (gentype <em>x</em>, half <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <em>y</em> if <em>y</em> &lt; <em>x</em>, otherwise it returns <em>x</em>.
+  If one argument is a NaN, <strong>fmin()</strong> returns the other argument.
+  If both arguments are NaNs, <strong>fmin()</strong> returns a NaN.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>fmod</strong> (gentype <em>x</em>, gentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Modulus.
+  Returns <em>x</em> - <em>y</em> * <strong>trunc</strong> (<em>x</em>/<em>y</em>) .</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>fract</strong> (gentype <em>x</em>, gentype *<em>iptr</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <strong>fmin</strong>( <em>x</em> - <strong>floor</strong> (<em>x</em>), 0x1.ffcp-1f ).</p>
+<p class="tableblock">  <strong>floor</strong>(x) is returned in <em>iptr</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half<em>n</em> <strong>frexp</strong> (half<em>n</em> <em>x</em>, int<em>n</em> *exp)<br>
+  half <strong>frexp</strong> (half <em>x</em>, int *exp)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Extract mantissa and exponent from <em>x</em>.
+  For each component the mantissa returned is a float with magnitude in the
+  interval [1/2, 1) or 0.
+  Each component of <em>x</em> equals mantissa returned * 2<em><sup>exp</sup></em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>hypot</strong> (gentype <em>x</em>, gentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute the value of the square root of <em>x</em><sup>2</sup>+ <em>y</em><sup>2</sup> without undue
+  overflow or underflow.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int<em>n</em> <strong>ilogb</strong> (half<em>n</em> <em>x</em>)<br>
+  int <strong>ilogb</strong> (half <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the exponent as an integer value.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half<em>n</em> <strong>ldexp</strong> (half<em>n</em> <em>x</em>, int<em>n</em> <em>k</em>)<br>
+  half<em>n</em> <strong>ldexp</strong> (half<em>n</em> <em>x</em>, int <em>k</em>)<br>
+  half <strong>ldexp</strong> (half <em>x</em>, int <em>k</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Multiply <em>x</em> by 2 to the power <em>k</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>lgamma</strong> (gentype <em>x</em>)<br>
+  half<em>n</em> <strong>lgamma_r</strong> (half<em>n</em> <em>x</em>, int<em>n</em> *<em>signp</em>)<br>
+  half <strong>lgamma_r</strong> (half <em>x</em>, int *<em>signp</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Log gamma function.
+  Returns the natural logarithm of the absolute value of the gamma function.
+  The sign of the gamma function is returned in the <em>signp</em> argument of
+  <strong>lgamma_r</strong>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>log</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute natural logarithm.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>log2</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute a base 2 logarithm.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>log10</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute a base 10 logarithm.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>log1p</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute log<sub>e</sub>(1.0 + <em>x</em>) .</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>logb</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute the exponent of <em>x</em>, which is the integral part of
+  log<em><sub>r</sub></em>|<em>x</em>|.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>mad</strong> (gentype <em>a</em>, gentype <em>b</em>, gentype <em>c</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mad</strong> computes <em>a</em> * <em>b</em> + <em>c</em>.
+  The function may compute <em>a</em> * <em>b</em> + <em>c</em> with reduced accuracy
+  in the embedded profile.  See the SPIR-V OpenCL environment specification
+  for details. On some hardware the mad instruction may provide better
+  performance than expanded computation of <em>a</em> * <em>b</em> + <em>c</em>.</p>
+<p class="tableblock">  Note: For some usages, e.g. <strong>mad</strong>(a, b, -a*b), the half precision
+  definition of <strong>mad</strong>() is loose enough that almost any result is allowed
+  from <strong>mad</strong>() for some values of a and b.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>maxmag</strong> (gentype <em>x</em>, gentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <em>x</em> if |<em>x</em>| &gt; |<em>y</em>|, <em>y</em> if |<em>y</em>| &gt; |<em>x</em>|, otherwise
+  <strong>fmax</strong>(<em>x</em>, <em>y</em>).</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>minmag</strong> (gentype <em>x</em>, gentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <em>x</em> if |<em>x</em>| &lt; |<em>y</em>|, <em>y</em> if |<em>y</em>| &lt; |<em>x</em>|, otherwise
+  <strong>fmin</strong>(<em>x</em>, <em>y</em>).</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>modf</strong> (gentype <em>x</em>, gentype *<em>iptr</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Decompose a floating-point number.
+  The <strong>modf</strong> function breaks the argument <em>x</em> into integral and fractional
+  parts, each of which has the same sign as the argument.
+  It stores the integral part in the object pointed to by <em>iptr</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half<em>n</em> <strong>nan</strong> (ushort<em>n</em> <em>nancode</em>)<br>
+  half <strong>nan</strong> (ushort <em>nancode</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns a quiet NaN.
+  The <em>nancode</em> may be placed in the significand of the resulting NaN.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>nextafter</strong> (gentype <em>x</em>, gentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Computes the next representable half-precision floating-point value
+  following <em>x</em> in the direction of <em>y</em>.
+  Thus, if <em>y</em> is less than <em>x</em>, <strong>nextafter</strong>() returns the largest
+  representable floating-point number less than <em>x</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>pow</strong> (gentype <em>x</em>, gentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute <em>x</em> to the power <em>y</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half<em>n</em> <strong>pown</strong> (half<em>n</em> <em>x</em>, int<em>n</em> <em>y</em>)<br>
+  half <strong>pown</strong> (half <em>x</em>, int <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute <em>x</em> to the power <em>y</em>, where <em>y</em> is an integer.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>powr</strong> (gentype <em>x</em>, gentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute <em>x</em> to the power <em>y</em>, where <em>x</em> is &gt;= 0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>remainder</strong> (gentype <em>x</em>, gentype <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute the value <em>r</em> such that <em>r</em> = <em>x</em> - <em>n</em>*<em>y</em>, where <em>n</em> is the
+  integer nearest the exact value of <em>x</em>/<em>y</em>.
+  If there are two integers closest to <em>x</em>/<em>y</em>, <em>n</em> shall be the even one.
+  If <em>r</em> is zero, it is given the same sign as <em>x</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half<em>n</em> <strong>remquo</strong> (half<em>n</em> <em>x</em>, half<em>n</em> <em>y</em>, int<em>n</em> *<em>quo</em>)<br>
+  half <strong>remquo</strong> (half <em>x</em>, half <em>y</em>, int *<em>quo</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The <strong>remquo</strong> function computes the value r such that <em>r</em> = <em>x</em> - <em>k</em>*<em>y</em>,
+  where <em>k</em> is the integer nearest the exact value of <em>x</em>/<em>y</em>.
+  If there are two integers closest to <em>x</em>/<em>y</em>, <em>k</em> shall be the even one.
+  If <em>r</em> is zero, it is given the same sign as <em>x</em>.
+  This is the same value that is returned by the <strong>remainder</strong> function.
+  <strong>remquo</strong> also calculates the lower seven bits of the integral quotient
+  <em>x</em>/<em>y</em>, and gives that value the same sign as <em>x</em>/<em>y</em>.
+  It stores this signed value in the object pointed to by <em>quo</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>rint</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Round to integral value (using round to nearest even rounding mode) in
+  floating-point format.
+  Refer to section 7.1 for description of rounding modes.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half<em>n</em> <strong>rootn</strong> (half<em>n</em> <em>x</em>, int<em>n</em> <em>y</em>)<br>
+  half <strong>rootn</strong> (half <em>x</em>, int <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute <em>x</em> to the power 1/<em>y</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>round</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the integral value nearest to <em>x</em> rounding halfway cases away from
+  zero, regardless of the current rounding direction.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>rsqrt</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute inverse square root.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>sin</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute sine.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>sincos</strong> (gentype <em>x</em>, gentype *<em>cosval</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute sine and cosine of x.
+  The computed sine is the return value and computed cosine is returned in
+  <em>cosval</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>sinh</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute hyperbolic sine.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>sinpi</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute <strong>sin</strong> (π <em>x</em>).</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>sqrt</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute square root.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>tan</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute tangent.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>tanh</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute hyperbolic tangent.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>tanpi</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute <strong>tan</strong> (π <em>x</em>).</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>tgamma</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute the gamma function.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>trunc</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Round to integral value using the round to zero rounding mode.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>The <strong>FP_FAST_FMA_HALF</strong> macro indicates whether the <strong>fma()</strong> family of
+functions are fast compared with direct code for half precision
+floating-point.
+If defined, the <strong>FP_FAST_FMA_HALF</strong> macro shall indicate that the <strong>fma()</strong>
+function generally executes about as fast as, or faster than, a multiply and
+an add of <strong>half</strong> operands</p>
+</div>
+<div class="paragraph">
+<p>The macro names given in the following list must use the values specified.
+These constant expressions are suitable for use in #if preprocessing
+directives.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>#define HALF_DIG            3
+#define HALF_MANT_DIG       11
+#define HALF_MAX_10_EXP     +4
+#define HALF_MAX_EXP        +16
+#define HALF_MIN_10_EXP     -4
+#define HALF_MIN_EXP        -13
+#define HALF_RADIX          2
+#define HALF_MAX            0x1.ffcp15h
+#define HALF_MIN            0x1.0p-14h
+#define HALF_EPSILON        0x1.0p-10h</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The following table describes the built-in macro names given above in the
+OpenCL C programming language and the corresponding macro names available to
+the application.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Macro in OpenCL Language</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Macro for application</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>HALF_DIG</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_HALF_DIG</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>HALF_MANT_DIG</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_HALF_MANT_DIG</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>HALF_MAX_10_EXP</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_HALF_MAX_10_EXP</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>HALF_MAX_EXP</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_HALF_MAX_EXP</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>HALF_MIN_10_EXP</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_HALF_MIN_10_EXP</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>HALF_MIN_EXP</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_HALF_MIN_EXP</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>HALF_RADIX</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_HALF_RADIX</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>HALF_MAX</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_HALF_MAX</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>HALF_MIN</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_HALF_MIN</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>HALF_EPSILSON</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_HALF_EPSILON</strong></p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>The following constants are also available.
+They are of type <code>half</code> and are accurate within the precision of the <code>half</code>
+type.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Constant</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>M_E_H</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of e</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>M_LOG2E_H</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of log<sub>2</sub>e</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>M_LOG10E_H</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of log<sub>10</sub>e</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>M_LN2_H</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of log<sub>e</sub>2</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>M_LN10_H</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of log<sub>e</sub>10</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>M_PI_H</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of π</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>M_PI_2_H</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of π / 2</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>M_PI_4_H</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of π / 4</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>M_1_PI_H</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of 1 / π</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>M_2_PI_H</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of 2 / π</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>M_2_SQRTPI_H</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of 2 / √π</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>M_SQRT2_H</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of √2</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>M_SQRT1_2_H</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Value of 1 / √2</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_fp16-common-functions">2.1.3. Common Functions</h4>
+<div class="paragraph">
+<p>The built-in common functions defined in <em>table 6.12</em> (also listed below)
+are extended to include appropriate versions of functions that take <code>half</code>,
+and <code>half{2|3|4|8|16}</code> as arguments and return values.
+gentype now also includes <code>half</code>, <code>half2</code>, <code>half3</code>, <code>half4</code>, <code>half8</code> and
+<code>half16</code>.
+These are described below.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 2. <em>Half Precision Built-in Common Functions</em></caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Function</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>clamp</strong> (<br>
+  gentype <em>x</em>, gentype <em>minval</em>, gentype <em>maxval</em>)</p>
+<p class="tableblock">  gentype <strong>clamp</strong> (<br>
+  gentype <em>x</em>, half <em>minval</em>, half <em>maxval</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <strong>min</strong>(<strong>max</strong>(<em>x</em>, <em>minval</em>), <em>maxval</em>).</p>
+<p class="tableblock">  Results are undefined if <em>minval</em> &gt; <em>maxval</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>degrees</strong> (gentype <em>radians</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Converts <em>radians</em> to degrees,<br>
+  i.e. (180 / π) * <em>radians</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>max</strong> (gentype <em>x</em>, gentype <em>y</em>)<br>
+  gentype <strong>max</strong> (gentype <em>x</em>, half <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <em>y</em> if <em>x</em> &lt; <em>y</em>, otherwise it returns <em>x</em>.
+  If <em>x</em> and <em>y</em> are infinite or NaN, the return values are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>min</strong> (gentype <em>x</em>, gentype <em>y</em>)<br>
+  gentype <strong>min</strong> (gentype <em>x</em>, half <em>y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <em>y</em> if <em>y</em> &lt; <em>x</em>, otherwise it returns <em>x</em>.
+  If <em>x</em> and <em>y</em> are infinite or NaN, the return values are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>mix</strong> (gentype <em>x</em>, gentype <em>y</em>, gentype <em>a</em>)<br>
+  gentype <strong>mix</strong> (gentype <em>x</em>, gentype <em>y</em>, half <em>a</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the linear blend of <em>x</em> and <em>y</em> implemented as:</p>
+<p class="tableblock">  <em>x</em> + (<em>y</em> - <em>x)</em> * <em>a</em></p>
+<p class="tableblock">  <em>a</em> must be a value in the range 0.0 &#8230;&#8203; 1.0.
+  If <em>a</em> is not in the range 0.0 &#8230;&#8203; 1.0, the return values are undefined.</p>
+<p class="tableblock">  Note: The half precision <strong>mix</strong> function can be implemented using contractions such as <strong>mad</strong> or <strong>fma</strong>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>radians</strong> (gentype <em>degrees</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Converts <em>degrees</em> to radians, i.e. (π / 180) * <em>degrees</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>step</strong> (gentype <em>edge</em>, gentype <em>x</em>)<br>
+  gentype <strong>step</strong> (half <em>edge</em>, gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns 0.0 if <em>x</em> &lt; <em>edge</em>, otherwise it returns 1.0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>smoothstep</strong> (<br>
+  gentype <em>edge0</em>, gentype <em>edge1</em>, gentype <em>x</em>)</p>
+<p class="tableblock">  gentype <strong>smoothstep</strong> (<br>
+  half <em>edge0</em>, half <em>edge1</em>, gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns 0.0 if <em>x</em> &lt;= <em>edge0</em> and 1.0 if <em>x</em> &gt;= <em>edge1</em> and performs
+  smooth Hermite interpolation between 0 and 1 when <em>edge0</em> &lt; <em>x</em> &lt; <em>edge1</em>.
+  This is useful in cases where you would want a threshold function with a
+  smooth transition.</p>
+<p class="tableblock">  This is equivalent to:</p>
+<p class="tableblock">  gentype <em>t</em>;<br>
+  <em>t</em> = clamp ((<em>x</em> - <em>edge0</em>) / (<em>edge1</em> - <em>edge0</em>), 0, 1);<br>
+  return <em>t</em> * <em>t</em> * (3 - 2 * <em>t</em>);<br></p>
+<p class="tableblock">  Results are undefined if <em>edge0</em> &gt;= <em>edge1</em>.</p>
+<p class="tableblock">  Note: The half precision <strong>smoothstep</strong> function can be implemented using contractions such as <strong>mad</strong> or <strong>fma</strong>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>sign</strong> (gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns 1.0 if <em>x</em> &gt; 0, -0.0 if <em>x</em> = -0.0, +0.0 if <em>x</em> = +0.0, or -1.0 if
+  <em>x</em> &lt; 0.
+  Returns 0.0 if <em>x</em> is a NaN.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_fp16-geometric-functions">2.1.4. Geometric Functions</h4>
+<div class="paragraph">
+<p>The built-in geometric functions defined in <em>table 6.13</em> (also listed below)
+are extended to include appropriate versions of functions that take <code>half</code>,
+and <code>half{2|3|4}</code> as arguments and return values.
+gentype now also includes <code>half</code>, <code>half2</code>, <code>half3</code> and <code>half4</code>.
+These are described below.</p>
+</div>
+<div class="paragraph">
+<p>Note: The half precision geometric functions can be implemented using
+contractions such as <strong>mad</strong> or <strong>fma</strong>.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 3. <em>Half Precision Built-in Geometric Functions</em></caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Function</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half4 <strong>cross</strong> (half4 <em>p0</em>, half4 <em>p1</em>)<br>
+  half3 <strong>cross</strong> (half3 <em>p0</em>, half3 <em>p1</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the cross product of <em>p0.xyz</em> and <em>p1.xyz</em>.
+  The <em>w</em> component of the result will be 0.0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half <strong>dot</strong> (gentype <em>p0</em>, gentype <em>p1</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Compute the dot product of <em>p0</em> and <em>p1</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half <strong>distance</strong> (gentype <em>p0</em>, gentype <em>p1</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the distance between <em>p0</em> and <em>p1</em>.
+  This is calculated as <strong>length</strong>(<em>p0</em> - <em>p1</em>).</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half <strong>length</strong> (gentype <em>p</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the length of vector x, i.e.,<br>
+  sqrt( <em>p.x</em><sup>2</sup> + <em>p.y</em><sup>2</sup> + &#8230;&#8203; )</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>normalize</strong> (gentype <em>p</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns a vector in the same direction as <em>p</em> but with a length of 1.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_fp16-relational-functions">2.1.5. Relational Functions</h4>
+<div class="paragraph">
+<p>The scalar and vector relational functions described in <em>table 6.14</em> are
+extended to include versions that take <code>half</code>, <code>half2</code>, <code>half3</code>, <code>half4</code>,
+<code>half8</code> and <code>half16</code> as arguments.</p>
+</div>
+<div class="paragraph">
+<p>The relational and equality operators (&lt;, &lt;=, &gt;, &gt;=, !=, ==) can be used
+with <code>halfn</code> vector types and shall produce a vector <code>shortn</code> result as
+described in <em>section 6.3</em>.</p>
+</div>
+<div class="paragraph">
+<p>The functions <strong>isequal</strong>, <strong>isnotequal</strong>, <strong>isgreater</strong>, <strong>isgreaterequal</strong>,
+<strong>isless</strong>, <strong>islessequal</strong>, <strong>islessgreater</strong>, <strong>isfinite</strong>, <strong>isinf</strong>, <strong>isnan</strong>,
+<strong>isnormal</strong>, <strong>isordered</strong>, <strong>isunordered</strong> and <strong>signbit</strong> shall return a 0 if the
+specified relation is <em>false</em> and a 1 if the specified relation is true for
+scalar argument types.
+These functions shall return a 0 if the specified relation is <em>false</em> and a
+-1 (i.e. all bits set) if the specified relation is <em>true</em> for vector
+argument types.</p>
+</div>
+<div class="paragraph">
+<p>The relational functions <strong>isequal</strong>, <strong>isgreater</strong>, <strong>isgreaterequal</strong>, <strong>isless</strong>,
+<strong>islessequal</strong>, and <strong>islessgreater</strong> always return 0 if either argument is not
+a number (NaN).
+<strong>isnotequal</strong> returns 1 if one or both arguments are not a number (NaN) and
+the argument type is a scalar and returns -1 if one or both arguments are
+not a number (NaN) and the argument type is a vector.</p>
+</div>
+<div class="paragraph">
+<p>The functions described in <em>table 6.14</em> are extended to include the <code>halfn</code>
+vector types.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 4. <em>Half Precision Relational Functions</em></caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Function</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>isequal</strong> (half <em>x</em>, half <em>y</em>)<br>
+  short<em>n</em> <strong>isequal</strong> (half<em>n x</em>, half<em>n y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the component-wise compare of <em>x</em> == <em>y</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>isnotequal</strong> (half <em>x</em>, half <em>y</em>)<br>
+  short<em>n</em> <strong>isnotequal</strong> (half<em>n x</em>, half<em>n y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the component-wise compare of <em>x</em> != <em>y</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>isgreater</strong> (half <em>x</em>, half <em>y</em>)<br>
+  short<em>n</em> <strong>isgreater</strong> (half<em>n x</em>, half<em>n y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the component-wise compare of <em>x</em> &gt; <em>y</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>isgreaterequal</strong> (half <em>x</em>, half <em>y</em>)<br>
+  short<em>n</em> <strong>isgreaterequal</strong> (half<em>n x</em>, half<em>n y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the component-wise compare of <em>x</em> &gt;= <em>y</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>isless</strong> (half <em>x</em>, half <em>y</em>)<br>
+  short<em>n</em> <strong>isless</strong> (half<em>n x</em>, half<em>n y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the component-wise compare of <em>x</em> &lt; <em>y</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>islessequal</strong> (half <em>x</em>, half <em>y</em>)<br>
+  short<em>n</em> <strong>islessequal</strong> (half<em>n x</em>, half<em>n y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the component-wise compare of <em>x</em> &lt;= <em>y</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>islessgreater</strong> (half <em>x</em>, half <em>y</em>)<br>
+  short<em>n</em> <strong>islessgreater</strong> (half<em>n x</em>, half<em>n y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the component-wise compare of (<em>x</em> &lt; <em>y</em>) || (<em>x</em> &gt; <em>y</em>) .</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>isfinite</strong> (half)<br>
+  short<em>n</em> <strong>isfinite</strong> (half<em>n</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Test for finite value.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>isinf</strong> (half)<br>
+  short<em>n</em> <strong>isinf</strong> (half<em>n</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Test for infinity value (positive or negative) .</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>isnan</strong> (half)<br>
+  short<em>n</em> <strong>isnan</strong> (half<em>n</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Test for a NaN.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>isnormal</strong> (half)<br>
+  short<em>n</em> <strong>isnormal</strong> (half<em>n</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Test for a normal value.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>isordered</strong> (half <em>x</em>, half <em>y</em>)<br>
+  short<em>n</em> <strong>isordered</strong> (half<em>n x</em>, half<em>n y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Test if arguments are ordered.
+  <strong>isordered</strong>() takes arguments <em>x</em> and <em>y</em>, and returns the result
+  <strong>isequal</strong>(<em>x</em>, <em>x</em>) &amp;&amp; <strong>isequal</strong>(<em>y</em>, <em>y</em>).</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>isunordered</strong> (half <em>x</em>, half <em>y</em>)<br>
+  short<em>n</em> <strong>isunordered</strong> (half<em>n x</em>, half<em>n y</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Test if arguments are unordered.
+  <strong>isunordered</strong>() takes arguments <em>x</em> and <em>y</em>, returning non-zero if <em>x</em> or
+  <em>y</em> is a NaN, and zero otherwise.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>signbit</strong> (half)<br>
+  short<em>n</em> <strong>signbit</strong> (half<em>n</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Test for sign bit.
+  The scalar version of the function returns a 1 if the sign bit in the half
+  is set else returns 0.
+  The vector version of the function returns the following for each
+  component in half<em>n</em>: -1 (i.e all bits set) if the sign bit in the half
+  is set else returns 0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half<em>n</em> <strong>bitselect</strong> (half<em>n a</em>, half<em>n b</em>, half<em>n c</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Each bit of the result is the corresponding bit of <em>a</em> if the
+  corresponding bit of <em>c</em> is 0.
+  Otherwise it is the corresponding bit of <em>b</em>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half<em>n</em> <strong>select</strong> (half<em>n a</em>, half<em>n b</em>, short<em>n</em> <em>c</em>)<br>
+  half<em>n</em> <strong>select</strong> (half<em>n a</em>, half<em>n b</em>, ushort<em>n</em> <em>c</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">For each component,<br>
+  <em>result[i]</em> = if MSB of <em>c[i]</em> is set ? <em>b[i]</em> : <em>a[i]</em>.<br></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_fp16-vector-data-load-and-store-functions">2.1.6. Vector Data Load and Store Functions</h4>
+<div class="paragraph">
+<p>The vector data load (<strong>vload<em>n</em></strong>) and store (<strong>vstore<em>n</em></strong>) functions
+described in <em>table 6.14</em> (also listed below) are extended to include
+versions that read from or write to half scalar or vector values.
+The generic type <code>gentype</code> is extended to include <code>half</code>.
+The generic type <code>gentypen</code> is extended to include <code>half</code>, <code>half2</code>, <code>half3</code>,
+<code>half4</code>, <code>half8</code>, and <code>half16</code>.</p>
+</div>
+<div class="paragraph">
+<p>Note: <strong>vload3</strong> reads <em>x</em>, <em>y</em>, <em>z</em> components from address
+(<em>p</em> + (<em>offset</em> * 3)) into a 3-component vector and <strong>vstore3</strong> writes <em>x</em>, <em>y</em>, <em>z</em>
+components from a 3-component vector to address (<em>p</em> + (<em>offset</em> * 3)).</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 5. <em>Half Precision Vector Data Load and Store Functions</em></caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Function</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype<em>n</em> <strong>vload<em>n</em></strong><br>
+  (size_t <em>offset</em>, const gentype *<em>p</em>)</p>
+<p class="tableblock">  gentype<em>n</em> <strong>vload<em>n</em></strong><br>
+  (size_t <em>offset</em>, const __constant gentype *<em>p</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return sizeof (gentype<em>n</em>) bytes of data read from address
+  (<em>p</em> + (<em>offset * n</em>)).
+  The read address computed as (<em>p</em> + (<em>offset * n</em>)) must be 16-bit
+  aligned.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>vstore<em>n</em></strong> (<br>
+  gentype<em>n</em> <em>data</em>, size_t <em>offset</em>, gentype *<em>p</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Write sizeof (gentype<em>n</em>) bytes given by <em>data</em> to address
+  (<em>p</em> + (<em>offset * n</em>)).
+  The write address computed as (<em>p</em> + (<em>offset * n</em>)) must be 16-bit
+  aligned.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_fp16-async-copies-from-global-to-local-memory-local-to-global-memory-and-prefetch">2.1.7. Async Copies from Global to Local Memory, Local to Global Memory, and Prefetch</h4>
+<div class="paragraph">
+<p>The OpenCL C programming language implements the following functions that
+provide asynchronous copies between global and local memory and a prefetch
+from global memory.</p>
+</div>
+<div class="paragraph">
+<p>The generic type <code>gentype</code> is extended to include <code>half</code>, <code>half2</code>, <code>half3</code>,
+<code>half4</code>, <code>half8</code>, and <code>half16</code>.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 6. <em>Half Precision Built-in Async Copy and Prefetch Functions</em></caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Function</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">event_t <strong>async_work_group_copy</strong> (<br>
+  __local gentype *<em>dst</em>,<br>
+  const __global gentype *<em>src</em>,<br>
+  size_t <em>num_gentypes</em>, event_t <em>event</em>)</p>
+<p class="tableblock">  event_t <strong>async_work_group_copy</strong> (<br>
+  __global gentype <em>*dst</em>,<br>
+  const __local gentype *<em>src</em>,<br>
+  size_t <em>num_gentypes</em>, event_t <em>event</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Perform an async copy of <em>num_gentypes</em> gentype elements from <em>src</em> to
+  <em>dst</em>.
+  The async copy is performed by all work-items in a work-group and this
+  built-in function must therefore be encountered by all work-items in a
+  work-group executing the kernel with the same argument values; otherwise
+  the results are undefined.</p>
+<p class="tableblock">  Returns an event object that can be used by <strong>wait_group_events</strong> to wait
+  for the async copy to finish.
+  The <em>event</em> argument can also be used to associate the
+  <strong>async_work_group_copy</strong> with a previous async copy allowing an event to be
+  shared by multiple async copies; otherwise <em>event</em> should be zero.</p>
+<p class="tableblock">  If <em>event</em> argument is not zero, the event object supplied in <em>event</em>
+  argument will be returned.</p>
+<p class="tableblock">  This function does not perform any implicit synchronization of source data
+  such as using a <strong>barrier</strong> before performing the copy.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">event_t <strong>async_work_group_strided_copy</strong> (<br>
+  __local gentype <em>*dst</em>,<br>
+  const __global gentype *<em>src</em>,<br>
+  size_t <em>num_gentypes</em>,<br>
+  size_t <em>src_stride</em>, event_t <em>event</em>)</p>
+<p class="tableblock">  event_t <strong>async_work_group_strided_copy</strong> (<br>
+  __global gentype <em>*dst</em>,<br>
+  const __local gentype *<em>src</em>,<br>
+  size_t <em>num_gentypes</em>,<br>
+  size_t <em>dst_stride</em>, event_t <em>event</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Perform an async gather of <em>num_gentypes</em> gentype elements from <em>src</em> to
+  <em>dst</em>.
+  The <em>src_stride</em> is the stride in elements for each gentype element read
+  from <em>src</em>.
+  The async gather is performed by all work-items in a work-group and this
+  built-in function must therefore be encountered by all work-items in a
+  work-group executing the kernel with the same argument values; otherwise
+  the results are undefined.</p>
+<p class="tableblock">  Returns an event object that can be used by <strong>wait_group_events</strong> to wait
+  for the async copy to finish.
+  The <em>event</em> argument can also be used to associate the
+  <strong>async_work_group_strided_copy</strong> with a previous async copy allowing an
+  event to be shared by multiple async copies; otherwise <em>event</em> should be
+  zero.</p>
+<p class="tableblock">  If <em>event</em> argument is not zero, the event object supplied in <em>event</em>
+  argument will be returned.</p>
+<p class="tableblock">  This function does not perform any implicit synchronization of source data
+  such as using a <strong>barrier</strong> before performing the copy.</p>
+<p class="tableblock">  The behavior of <strong>async_work_group_strided_copy</strong> is undefined if
+  <em>src_stride</em> or <em>dst_stride</em> is 0, or if the <em>src_stride</em> or <em>dst_stride</em>
+  values cause the <em>src</em> or <em>dst</em> pointers to exceed the upper bounds of the
+  address space during the copy.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>wait_group_events</strong> (<br>
+  int <em>num_events</em>, event_t *<em>event_list</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Wait for events that identify the <strong>async_work_group_copy</strong> operations to
+  complete.
+  The event objects specified in <em>event_list</em> will be released after the
+  wait is performed.</p>
+<p class="tableblock">  This function must be encountered by all work-items in a work-group
+  executing the kernel with the same <em>num_events</em> and event objects
+  specified in <em>event_list</em>; otherwise the results are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>prefetch</strong> (<br>
+  const __global gentype *<em>p</em>, size_t <em>num_gentypes</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Prefetch <em>num_gentypes</em> * sizeof(gentype) bytes into the global cache.
+  The prefetch instruction is applied to a work-item in a work-group and
+  does not affect the functional behavior of the kernel.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_fp16-image-read-and-write-functions">2.1.8. Image Read and Write Functions</h4>
+<div class="paragraph">
+<p>The image read and write functions defined in <em>tables 6.23</em>, <em>6.24</em> and
+<em>6.25</em> are extended to support image color values that are a <code>half</code> type.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_built_in_image_read_functions">2.1.9. Built-in Image Read Functions</h4>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 7. <em>Half Precision Built-in Image Read Functions</em></caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Function</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half4 <strong>read_imageh</strong> (<br>
+  read_only image2d_t <em>image</em>,<br>
+  sampler_t <em>sampler</em>,<br>
+  int2 <em>coord</em>)</p>
+<p class="tableblock">  half4 <strong>read_imageh</strong> (<br>
+  read_only image2d_t <em>image</em>,<br>
+  sampler_t <em>sampler</em>,<br>
+  float2 <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use the coordinate <em>(coord.x, coord.y)</em> to do an element lookup in the 2D
+  image object specified by <em>image</em>.</p>
+<p class="tableblock">  <strong>read_imageh</strong> returns half precision floating-point values in the range
+  [0.0 &#8230;&#8203; 1.0] for image objects created with <em>image_channel_data_type</em> set
+  to one of the pre-defined packed formats, CL_UNORM_INT8, or
+  CL_UNORM_INT16.</p>
+<p class="tableblock">  <strong>read_imageh</strong> returns half precision floating-point values in the range
+  [-1.0 &#8230;&#8203; 1.0] for image objects created with <em>image_channel_data_type</em>
+  set to CL_SNORM_INT8, or CL_SNORM_INT16.</p>
+<p class="tableblock">  <strong>read_imageh</strong> returns half precision floating-point values for image
+  objects created with <em>image_channel_data_type</em> set to CL_HALF_FLOAT.</p>
+<p class="tableblock">  The <strong>read_imageh</strong> calls that take integer coordinates must use a sampler
+  with filter mode set to CLK_FILTER_NEAREST, normalized coordinates set to
+  CLK_NORMALIZED_COORDS_FALSE and addressing mode set to
+  CLK_ADDRESS_CLAMP_TO_EDGE, CLK_ADDRESS_CLAMP or CLK_ADDRESS_NONE;
+  otherwise the values returned are undefined.</p>
+<p class="tableblock">  Values returned by <strong>read_imageh</strong> for image objects with
+  <em>image_channel_data_type</em> values not specified in the description above
+  are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half4 <strong>read_imageh</strong> (<br>
+  read_only image3d_t <em>image</em>,<br>
+  sampler_t <em>sampler</em>,<br>
+  int4 <em>coord</em> )</p>
+<p class="tableblock">  half4 <strong>read_imageh</strong> (<br>
+  read_only image3d_t <em>image</em>,<br>
+  sampler_t <em>sampler</em>,<br>
+  float4 <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use the coordinate <em>(coord.x</em>, <em>coord.y</em>, <em>coord.z)</em> to do an
+  elementlookup in the 3D image object specified by <em>image</em>. <em>coord.w</em> is
+  ignored.</p>
+<p class="tableblock">  <strong>read_imageh</strong> returns half precision floating-point values in the range
+  [0.0 &#8230;&#8203; 1.0] for image objects created with <em>image_channel_data_type</em> set
+  to one of the pre-defined packed formats or CL_UNORM_INT8, or
+  CL_UNORM_INT16.</p>
+<p class="tableblock">  <strong>read_imageh</strong> returns half precision floating-point values in the range
+  [-1.0 &#8230;&#8203; 1.0] for image objects created with <em>image_channel_data_type</em>
+  set to CL_SNORM_INT8, or CL_SNORM_INT16.</p>
+<p class="tableblock">  <strong>read_imageh</strong>returns half precision floating-point values for image
+  objects created with <em>image_channel_data_type</em> set to CL_HALF_FLOAT.</p>
+<p class="tableblock">  The <strong>read_imageh</strong> calls that take integer coordinates must use a sampler
+  with filter mode set to CLK_FILTER_NEAREST, normalized coordinates set to
+  CLK_NORMALIZED_COORDS_FALSE and addressing mode set to
+  CLK_ADDRESS_CLAMP_TO_EDGE, CLK_ADDRESS_CLAMP or CLK_ADDRESS_NONE;
+  otherwise the values returned are undefined.</p>
+<p class="tableblock">  Values returned by <strong>read_imageh</strong> for image objects with
+  <em>image_channel_data_type</em> values not specified in the description are
+  undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half4 <strong>read_imageh</strong> (<br>
+  read_only image2d_array_t <em>image</em>,<br>
+  sampler_t <em>sampler</em>,<br>
+  int4 <em>coord</em>)</p>
+<p class="tableblock">  half4 <strong>read_imageh</strong> (<br>
+  read_only image2d_array_t <em>image</em>,<br>
+  sampler_t <em>sampler</em>,<br>
+  float4 <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use <em>coord.xy</em> to do an element lookup in the 2D image identified by
+  <em>coord.z</em> in the 2D image array specified by <em>image</em>.</p>
+<p class="tableblock">  <strong>read_imageh</strong> returns half precision floating-point values in the range
+  [0.0 &#8230;&#8203; 1.0] for image objects created with image_channel_data_type set
+  to one of the pre-defined packed formats or CL_UNORM_INT8, or
+  CL_UNORM_INT16.</p>
+<p class="tableblock">  <strong>read_imageh</strong> returns half precision floating-point values in the range
+  [-1.0 &#8230;&#8203; 1.0] for image objects created with image_channel_data_type set
+  to CL_SNORM_INT8, or CL_SNORM_INT16.</p>
+<p class="tableblock">  <strong>read_imageh</strong> returns half precision floating-point values for image
+  objects created with image_channel_data_type set to CL_HALF_FLOAT.</p>
+<p class="tableblock">  The <strong>read_imageh</strong> calls that take integer coordinates must use a sampler
+  with filter mode set to CLK_FILTER_NEAREST, normalized coordinates set to
+  CLK_NORMALIZED_COORDS_FALSE and addressing mode set to
+  CLK_ADDRESS_CLAMP_TO_EDGE, CLK_ADDRESS_CLAMP or CLK_ADDRESS_NONE;
+  otherwise the values returned are undefined.</p>
+<p class="tableblock">  Values returned by <strong>read_imageh</strong> for image objects with
+  image_channel_data_type values not specified in the description above are
+  undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half4 <strong>read_imageh</strong> (<br>
+  read_only image1d_t <em>image</em>,<br>
+  sampler_t <em>sampler</em>,<br>
+  int <em>coord</em>)</p>
+<p class="tableblock">  half4 <strong>read_imageh</strong> (<br>
+  read_only image1d_t <em>image</em>,<br>
+  sampler_t <em>sampler</em>,<br>
+  float <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use <em>coord</em> to do an element lookup in the 1D image object specified by
+  <em>image</em>.</p>
+<p class="tableblock">  <strong>read_imageh</strong> returns half precision floating-point values in the range
+  [0.0 &#8230;&#8203; 1.0] for image objects created with <em>image_channel_data_type</em> set
+  to one of the pre-defined packed formats or CL_UNORM_INT8, or
+  CL_UNORM_INT16.</p>
+<p class="tableblock">  <strong>read_imageh</strong> returns half precision floating-point values in the range
+  [-1.0 &#8230;&#8203; 1.0] for image objects created with <em>image_channel_data_type</em>
+  set to CL_SNORM_INT8, or CL_SNORM_INT16.</p>
+<p class="tableblock">  <strong>read_imageh</strong> returns half precision floating-point values for image
+  objects created with <em>image_channel_data_type</em> set to CL_HALF_FLOAT.</p>
+<p class="tableblock">  The <strong>read_imageh</strong> calls that take integer coordinates must use a sampler
+  with filter mode set to CLK_FILTER_NEAREST, normalized coordinates set to
+  CLK_NORMALIZED_COORDS_FALSE and addressing mode set to
+  CLK_ADDRESS_CLAMP_TO_EDGE, CLK_ADDRESS_CLAMP or CLK_ADDRESS_NONE;
+  otherwise the values returned are undefined.</p>
+<p class="tableblock">  Values returned by <strong>read_imageh</strong> for image objects with
+  <em>image_channel_data_type</em> values not specified in the description above
+  are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half4 <strong>read_imageh</strong> (<br>
+  read_only image1d_array_t <em>image</em>,<br>
+  sampler_t <em>sampler</em>,<br>
+  int2 <em>coord</em>)</p>
+<p class="tableblock">  half4 <strong>read_imageh</strong> (<br>
+  read_only image1d_array_t <em>image</em>,<br>
+  sampler_t <em>sampler</em>,<br>
+  float2 <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use <em>coord.x</em> to do an element lookup in the 1D image identified by
+  <em>coord.y</em> in the 1D image array specified by <em>image</em>.</p>
+<p class="tableblock">  <strong>read_imageh</strong> returns half precision floating-point values in the range
+  [0.0 &#8230;&#8203; 1.0] for image objects created with image_channel_data_type set
+  to one of the pre-defined packed formats or CL_UNORM_INT8, or
+  CL_UNORM_INT16.</p>
+<p class="tableblock">  <strong>read_imageh</strong> returns half precision floating-point values in the range
+  [-1.0 &#8230;&#8203; 1.0] for image objects created with image_channel_data_type set
+  to CL_SNORM_INT8, or CL_SNORM_INT16.</p>
+<p class="tableblock">  <strong>read_imageh</strong> returns half precision floating-point values for image
+  objects created with image_channel_data_type set to CL_HALF_FLOAT.</p>
+<p class="tableblock">  The <strong>read_imageh</strong> calls that take integer coordinates must use a sampler
+  with filter mode set to CLK_FILTER_NEAREST, normalized coordinates set to
+  CLK_NORMALIZED_COORDS_FALSE and addressing mode set to
+  CLK_ADDRESS_CLAMP_TO_EDGE, CLK_ADDRESS_CLAMP or CLK_ADDRESS_NONE;
+  otherwise the values returned are undefined.</p>
+<p class="tableblock">  Values returned by <strong>read_imageh</strong> for image objects with
+  image_channel_data_type values not specified in the description above are
+  undefined.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_built_in_image_sampler_less_read_functions">2.1.10. Built-in Image Sampler-less Read Functions</h4>
+<div class="paragraph">
+<p><em>aQual</em> in Table 6.24 refers to one of the access qualifiers.
+For sampler-less read functions this may be <em>read_only</em> or <em>read_write</em>.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 8. <em>Half Precision Built-in Image Sampler-less Read Functions</em></caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Function</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half4 <strong>read_imageh</strong> (<br>
+  <em>aQual</em> image2d_t <em>image</em>,<br>
+  int2 <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use the coordinate <em>(coord.x, coord.y)</em> to do an element lookup in the 2D
+  image object specified by <em>image</em>.</p>
+<p class="tableblock">  <strong>read_imageh</strong> returns half precision floating-point values in the range
+  [0.0 &#8230;&#8203; 1.0] for image objects created with <em>image_channel_data_type</em> set
+  to one of the pre-defined packed formats or CL_UNORM_INT8, or
+  CL_UNORM_INT16.</p>
+<p class="tableblock">  <strong>read_imageh</strong> returns half precision floating-point values in the range
+  [-1.0 &#8230;&#8203; 1.0] for image objects created with <em>image_channel_data_type</em>
+  set to CL_SNORM_INT8, or CL_SNORM_INT16.</p>
+<p class="tableblock">  <strong>read_imageh</strong> returns half precision floating-point values for image
+  objects created with <em>image_channel_data_type</em> set to CL_HALF_FLOAT.</p>
+<p class="tableblock">  Values returned by <strong>read_imageh</strong> for image objects with
+  <em>image_channel_data_type</em> values not specified in the description above
+  are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half4 <strong>read_imageh</strong> (<br>
+  <em>aQual</em> image3d_t <em>image</em>,<br>
+  int4 <em>coord</em> )</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use the coordinate <em>(coord.x</em>, <em>coord.y</em>, <em>coord.z)</em> to do an element
+  lookup in the 3D image object specified by <em>image</em>. <em>coord.w</em> is ignored.</p>
+<p class="tableblock">  <strong>read_imageh</strong> returns half precision floating-point values in the range
+  [0.0 &#8230;&#8203; 1.0] for image objects created with <em>image_channel_data_type</em> set
+  to one of the pre-defined packed formats or CL_UNORM_INT8, or
+  CL_UNORM_INT16.</p>
+<p class="tableblock">  <strong>read_imageh</strong> returns half precision floating-point values in the range
+  [-1.0 &#8230;&#8203; 1.0] for image objects created with <em>image_channel_data_type</em>
+  set to CL_SNORM_INT8, or CL_SNORM_INT16.</p>
+<p class="tableblock">  <strong>read_imageh</strong> returns half precision floating-point values for image
+  objects created with <em>image_channel_data_type</em> set to CL_HALF_FLOAT.</p>
+<p class="tableblock">  Values returned by <strong>read_imageh</strong> for image objects with
+  <em>image_channel_data_type</em> values not specified in the description are
+  undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half4 <strong>read_imageh</strong> (<br>
+  <em>aQual</em> image2d_array_t <em>image</em>,<br>
+  int4 <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use <em>coord.xy</em> to do an element lookup in the 2D image identified by
+  <em>coord.z</em> in the 2D image array specified by <em>image</em>.</p>
+<p class="tableblock">  <strong>read_imageh</strong> returns half precision floating-point values in the range
+  [0.0 &#8230;&#8203; 1.0] for image objects created with <em>image_channel_data_type</em> set
+  to one of the pre-defined packed formats or CL_UNORM_INT8, or
+  CL_UNORM_INT16.</p>
+<p class="tableblock">  <strong>read_imageh</strong> returns half precision floating-point values in the range
+  [-1.0 &#8230;&#8203; 1.0] for image objects created with <em>image_channel_data_type</em>
+  set to CL_SNORM_INT8, or CL_SNORM_INT16.</p>
+<p class="tableblock">  <strong>read_imageh</strong> returns half precision floating-point values for image
+  objects created with <em>image_channel_data_type</em> set to CL_HALF_FLOAT.</p>
+<p class="tableblock">  Values returned by <strong>read_imageh</strong> for image objects with
+  <em>image_channel_data_type</em> values not specified in the description above
+  are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half4 <strong>read_imageh</strong> (<br>
+  <em>aQual</em> image1d_t <em>image</em>,<br>
+  int <em>coord</em>)</p>
+<p class="tableblock">  half4 <strong>read_imageh</strong> (<br>
+  <em>aQual</em> image1d_buffer_t <em>image</em>,<br>
+  int <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use <em>coord</em> to do an element lookup in the 1D image or 1D image buffer
+  object specified by <em>image</em>.</p>
+<p class="tableblock">  <strong>read_imageh</strong> returns half precision floating-point values in the range
+  [0.0 &#8230;&#8203; 1.0] for image objects created with <em>image_channel_data_type</em> set
+  to one of the pre-defined packed formats or CL_UNORM_INT8, or
+  CL_UNORM_INT16.</p>
+<p class="tableblock">  <strong>read_imageh</strong> returns half precision floating-point values in the range
+  [-1.0 &#8230;&#8203; 1.0] for image objects created with <em>image_channel_data_type</em>
+  set to CL_SNORM_INT8, or CL_SNORM_INT16.</p>
+<p class="tableblock">  <strong>read_imageh</strong> returns half precision floating-point values for image
+  objects created with <em>image_channel_data_type</em> set to CL_HALF_FLOAT.</p>
+<p class="tableblock">  Values returned by <strong>read_imageh</strong> for image objects with
+  <em>image_channel_data_type</em> values not specified in the description above
+  are undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">half4 <strong>read_imageh</strong> (<br>
+  <em>aQual</em> image1d_array_t <em>image</em>,<br>
+  int2 <em>coord</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Use <em>coord.x</em> to do an element lookup in the 2D image identified by
+  <em>coord.y</em> in the 2D image array specified by <em>image</em>.</p>
+<p class="tableblock">  <strong>read_imageh</strong> returns half precision floating-point values in the range
+  [0.0 &#8230;&#8203; 1.0] for image objects created with <em>image_channel_data_type</em> set
+  to one of the pre-defined packed formats or CL_UNORM_INT8, or
+  CL_UNORM_INT16.</p>
+<p class="tableblock">  <strong>read_imageh</strong> returns half precision floating-point values in the range
+  [-1.0 &#8230;&#8203; 1.0] for image objects created with <em>image_channel_data_type</em>
+  set to CL_SNORM_INT8, or CL_SNORM_INT16.</p>
+<p class="tableblock">  <strong>read_imageh</strong> returns half precision floating-point values for image
+  objects created with <em>image_channel_data_type</em> set to CL_HALF_FLOAT.</p>
+<p class="tableblock">  Values returned by <strong>read_imageh</strong> for image objects with
+  <em>image_channel_data_type</em> values not specified in the description above
+  are undefined.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_built_in_image_write_functions">2.1.11. Built-in Image Write Functions</h4>
+<div class="paragraph">
+<p><em>aQual</em> in Table 6.25 refers to one of the access qualifiers.
+For write functions this may be <em>write_only</em> or <em>read_write</em>.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 9. <em>Half Precision Built-in Image Write Functions</em></caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Function</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>write_imageh</strong> (<br>
+  <em>aQual</em> image2d_t <em>image</em>,<br>
+  int2 <em>coord</em>,<br>
+  half4 <em>color</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Write <em>color</em> value to location specified by <em>coord.xy</em> in the 2D image
+  specified by <em>image</em>.</p>
+<p class="tableblock">  Appropriate data format conversion to the specified image format is done
+  before writing the color value. <em>x</em> &amp; <em>y</em> are considered to be
+  unnormalized coordinates and must be in the range 0 &#8230;&#8203; width - 1, and 0
+  &#8230;&#8203; height - 1.</p>
+<p class="tableblock">  <strong>write_imageh</strong> can only be used with image objects created with
+  <em>image_channel_data_type</em> set to one of the pre-defined packed formats or
+  set to CL_SNORM_INT8, CL_UNORM_INT8, CL_SNORM_INT16, CL_UNORM_INT16 or
+  CL_HALF_FLOAT.</p>
+<p class="tableblock">  The behavior of <strong>write_imageh</strong> for image objects created with
+  <em>image_channel_data_type</em> values not specified in the description above or
+  with (<em>x</em>, <em>y</em>) coordinate values that are not in the range (0 &#8230;&#8203; width -
+  1, 0 &#8230;&#8203; height - 1) respectively, is undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>write_imageh</strong> (<br>
+  <em>aQual</em> image2d_array_t <em>image</em>,<br>
+  int4 <em>coord</em>,<br>
+  half4 <em>color</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Write <em>color</em> value to location specified by <em>coord.xy</em> in the 2D image
+  identified by <em>coord.z</em> in the 2D image array specified by <em>image</em>.</p>
+<p class="tableblock">  Appropriate data format conversion to the specified image format is done
+  before writing the color value. <em>coord.x</em>, <em>coord.y</em> and <em>coord.z</em> are
+  considered to be unnormalized coordinates and must be in the range 0 &#8230;&#8203;
+  image width - 1, 0 &#8230;&#8203; image height - 1 and 0 &#8230;&#8203; image number of layers -
+  1.</p>
+<p class="tableblock">  <strong>write_imageh</strong> can only be used with image objects created with
+  <em>image_channel_data_type</em> set to one of the pre-defined packed formats or
+  set to CL_SNORM_INT8, CL_UNORM_INT8, CL_SNORM_INT16, CL_UNORM_INT16 or
+  CL_HALF_FLOAT.</p>
+<p class="tableblock">  The behavior of <strong>write_imageh</strong> for image objects created with
+  <em>image_channel_data_type</em> values not specified in the description above or
+  with (<em>x</em>, <em>y, z</em>) coordinate values that are not in the range (0 &#8230;&#8203;
+  image width - 1, 0 &#8230;&#8203; image height - 1, 0 &#8230;&#8203; image number of layers -
+  1), respectively, is undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>write_imageh</strong> (<br>
+  <em>aQual</em> image1d_t <em>image</em>,<br>
+  int <em>coord</em>,<br>
+  half4 <em>color</em>)</p>
+<p class="tableblock">  void <strong>write_imageh</strong> (<br>
+  <em>aQual</em> image1d_buffer_t <em>image</em>,<br>
+  int <em>coord</em>,<br>
+  half4 <em>color</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Write <em>color</em> value to location specified by <em>coord</em> in the 1D image or 1D
+  image buffer object specified by <em>image</em>.
+  Appropriate data format conversion to the specified image format is done
+  before writing the color value.
+  <em>coord</em> is considered to be unnormalized coordinates and must be in the
+  range 0 &#8230;&#8203; image width - 1.</p>
+<p class="tableblock">  <strong>write_imageh</strong> can only be used with image objects created with
+  <em>image_channel_data_type</em> set to one of the pre-defined packed formats or
+  set to CL_SNORM_INT8, CL_UNORM_INT8, CL_SNORM_INT16, CL_UNORM_INT16 or
+  CL_HALF_FLOAT.
+  Appropriate data format conversion will be done to convert channel data
+  from a floating-point value to actual data format in which the channels
+  are stored.</p>
+<p class="tableblock">  The behavior of <strong>write_imageh</strong> for image objects created with
+  <em>image_channel_data_type</em> values not specified in the description above or
+  with coordinate values that is not in the range (0 &#8230;&#8203; image width - 1),
+  is undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>write_imageh</strong> (<br>
+  <em>aQual</em> image1d_array_t <em>image</em>,<br>
+  int2 <em>coord</em>,<br>
+  half4 <em>color</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Write <em>color</em> value to location specified by <em>coord.x</em> in the 1D image
+  identified by <em>coord.y</em> in the 1D image array specified by <em>image</em>.
+  Appropriate data format conversion to the specified image format is done
+  before writing the color value. <em>coord.x</em> and <em>coord.y</em> are considered to
+  be unnormalized coordinates and must be in the range 0 &#8230;&#8203; image width - 1
+  and 0 &#8230;&#8203; image number of layers - 1.</p>
+<p class="tableblock">  <strong>write_imageh</strong> can only be used with image objects created with
+  <em>image_channel_data_type</em> set to one of the pre-defined packed formats or
+  set to CL_SNORM_INT8, CL_UNORM_INT8, CL_SNORM_INT16, CL_UNORM_INT16 or
+  CL_HALF_FLOAT.
+  Appropriate data format conversion will be done to convert channel data
+  from a floating-point value to actual data format in which the channels
+  are stored.</p>
+<p class="tableblock">  The behavior of <strong>write_imageh</strong> for image objects created with
+  <em>image_channel_data_type</em> values not specified in the description above or
+  with (<em>x</em>, <em>y</em>) coordinate values that are not in the range (0 &#8230;&#8203; image
+  width - 1, 0 &#8230;&#8203; image number of layers - 1), respectively, is undefined.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>write_imageh</strong> (<br>
+  <em>aQual</em> image3d_t <em>image</em>,<br>
+  int4 <em>coord</em>,<br>
+  half4 <em>color</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Write color value to location specified by coord.xyz in the 3D image
+  object specified by <em>image</em>.</p>
+<p class="tableblock">  Appropriate data format conversion to the specified image format is done
+  before writing the color value.
+  coord.x, coord.y and coord.z are considered to be unnormalized coordinates
+  and must be in the range 0 &#8230;&#8203; image width - 1, 0 &#8230;&#8203; image height - 1 and
+  0 &#8230;&#8203; image depth - 1.</p>
+<p class="tableblock">  <strong>write_imageh</strong> can only be used with image objects created with
+  image_channel_data_type set to one of the pre-defined packed formats or
+  set to CL_SNORM_INT8, CL_UNORM_INT8, CL_SNORM_INT16, CL_UNORM_INT16 or
+  CL_HALF_FLOAT.</p>
+<p class="tableblock">  The behavior of <strong>write_imageh</strong> for image objects created with
+  image_channel_data_type values not specified in the description above or
+  with (x, y, z) coordinate values that are not in the range (0 &#8230;&#8203; image
+  width - 1, 0 &#8230;&#8203; image height - 1, 0 &#8230;&#8203; image depth - 1), respectively,
+  is undefined.</p>
+<p class="tableblock">  Note: This built-in function is only available if the
+  cl_khr_3d_image_writes extension is also supported by the device.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_fp16-ieee754-compliance">2.1.12. IEEE754 Compliance</h4>
+<div class="paragraph">
+<p>The following table entry describes the additions to <em>table 4.3,</em> which
+allows applications to query the configuration information using
+<strong>clGetDeviceInfo</strong> for an OpenCL device that supports half precision
+floating-point.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 25%;">
+<col style="width: 25%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Op-code</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Return Type</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_HALF_FP_CONFIG</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_device_fp_config</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Describes half precision floating-point capability of the OpenCL device.
+  This is a bit-field that describes one or more of the following values:</p>
+<p class="tableblock">  CL_FP_DENORM&#8201;&#8212;&#8201;denorms are supported</p>
+<p class="tableblock">  CL_FP_INF_NAN&#8201;&#8212;&#8201;INF and NaNs are supported</p>
+<p class="tableblock">  CL_FP_ROUND_TO_NEAREST&#8201;&#8212;&#8201;round to nearest even rounding mode supported</p>
+<p class="tableblock">  CL_FP_ROUND_TO_ZERO&#8201;&#8212;&#8201;round to zero rounding mode supported</p>
+<p class="tableblock">  CL_FP_ROUND_TO_INF&#8201;&#8212;&#8201;round to positive and negative infinity rounding
+  modes supported</p>
+<p class="tableblock">  CP_FP_FMA&#8201;&#8212;&#8201;IEEE754-2008 fused multiply-add is supported</p>
+<p class="tableblock">  CL_FP_SOFT_FLOAT&#8201;&#8212;&#8201;Basic floating-point operations (such as addition,
+  subtraction, multiplication) are implemented in software.</p>
+<p class="tableblock">  The required minimum half precision floating-point capability as
+  implemented by this extension is:</p>
+<p class="tableblock">  CL_FP_ROUND_TO_ZERO, or CL_FP_ROUND_TO_NEAREST | CL_FP_INF_NAN.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_fp16-rounding-modes">2.1.13. Rounding Modes</h4>
+<div class="paragraph">
+<p>If CL_FP_ROUND_TO_NEAREST is supported, the default rounding mode for
+half-precision floating-point operations will be round to nearest even;
+otherwise the default rounding mode will be round to zero.</p>
+</div>
+<div class="paragraph">
+<p>Conversions to half floating point format must be correctly rounded using
+the indicated <code>convert</code> operator rounding mode or the default rounding mode
+for half-precision floating-point operations if no rounding mode is
+specified by the operator, or a C-style cast is used.</p>
+</div>
+<div class="paragraph">
+<p>Conversions from half to integer format shall correctly round using the
+indicated <code>convert</code> operator rounding mode, or towards zero if no rounding
+mode is specified by the operator or a C-style cast is used.
+All conversions from half to floating point formats are exact.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_fp16-relative-error-as-ulps">2.1.14. Relative Error as ULPs</h4>
+<div class="paragraph">
+<p>In this section we discuss the maximum relative error defined as <em>ulp</em>
+(units in the last place).</p>
+</div>
+<div class="paragraph">
+<p>Addition, subtraction, multiplication, fused multiply-add operations on half
+types are required to be correctly rounded using the default rounding mode
+for half-precision floating-point operations.</p>
+</div>
+<div class="paragraph">
+<p>The following table describes the minimum accuracy of half precision
+floating-point arithmetic operations given as ULP values.
+0 ULP is used for math functions that do not require rounding.
+The reference value used to compute the ULP value of an arithmetic operation
+is the infinitely precise result.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 10. <em>ULP Values for Half Precision Floating-Point Arithmetic Operations</em></caption>
+<colgroup>
+<col style="width: 33.3333%;">
+<col style="width: 33.3333%;">
+<col style="width: 33.3334%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Function</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Min Accuracy - Full Profile</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Min Accuracy - Embedded Profile</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong><em>x</em> + <em>y</em></strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong><em>x</em> - <em>y</em></strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong><em>x</em> * <em>y</em></strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>1.0 / <em>x</em></strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 1 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong><em>x</em> / <em>y</em></strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 1 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>acos</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>acosh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>acospi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>asin</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>asinh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>asinpi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>atan</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>atanh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>atanpi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>atan2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>atan2pi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cbrt</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ceil</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>copysign</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cos</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cosh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cospi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>erfc</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>erf</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>exp</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>exp2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>exp10</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>expm1</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>fabs</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>fdim</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>floor</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>fma</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>fmax</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>fmin</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>fmod</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>fract</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>frexp</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>hypot</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ilogb</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ldexp</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>log</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>log2</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>log10</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>log1p</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>logb</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mad</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-defined</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>maxmag</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>minmag</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>modf</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>nan</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>nextafter</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>pow(x, y)</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>pown(x, y)</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>powr(x, y)</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>remainder</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>remquo</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp for the remainder, at least the lower 7 bits of the integral quotient</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0 ulp for the remainder, at least the lower 7 bits of the integral quotient</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>rint</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>rootn</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 5 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>round</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>rsqrt</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;=1 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;=1 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sin</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sincos</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp for sine and cosine values</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp for sine and cosine values</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sinh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sinpi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sqrt</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 1 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>tan</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>tanh</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>tanpi</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 2 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 3 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>tgamma</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;= 4 ulp</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>trunc</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>Note: <em>Implementations may perform floating-point operations on</em> <code>half</code>
+<em>scalar or vector data types by converting the</em> <code>half</code> <em>values to single
+precision floating-point values and performing the operation in single
+precision floating-point.
+In this case, the implementation will use the</em> <code>half</code> <em>scalar or vector data
+type as a storage only format</em>.</p>
+</div>
+<div style="page-break-after: always;"></div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="cl_khr_gl_sharing">3. Creating an OpenCL Context from an OpenGL Context or Share Group</h2>
+<div class="sectionbody">
+<div class="sect2">
+<h3 id="cl_khr_gl_sharing-overview">3.1. Overview</h3>
+<div class="paragraph">
+<p>This section describes the <strong>cl_khr_gl_sharing</strong> extension.
+The section <a href="#cl_khr_gl_sharing__memobjs">Creating OpenCL Memory Objects from
+OpenGL Objects</a> defines how to share data with texture and buffer objects
+in a parallel OpenGL implementation, but does not define how the association
+between an OpenCL context and an OpenGL context or share group is
+established.
+This extension defines optional attributes to OpenCL context creation
+routines which associate a OpenGL context or share group object with a newly
+created OpenCL context.</p>
+</div>
+<div class="paragraph">
+<p>An OpenGL implementation supporting buffer objects and sharing of texture
+and buffer object images with OpenCL is required by this extension.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_gl_sharing-new-procedures-and-functions">3.2. New Procedures and Functions</h3>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_int clGetGLContextInfoKHR(const cl_context_properties *properties,
+                             cl_gl_context_info param_name,
+                             size_t param_value_size,
+                             void *param_value,
+                             size_t *param_value_size_ret);</code></pre>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_gl_sharing-new-tokens">3.3. New Tokens</h3>
+<div class="paragraph">
+<p>Returned by <strong>clCreateContext</strong>, <strong>clCreateContextFromType</strong>, and
+<strong>clGetGLContextInfoKHR</strong> when an invalid OpenGL context or share group object
+handle is specified in <em>properties</em>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR      -1000</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Accepted as the <em>param_name</em> argument of <strong>clGetGLContextInfoKHR</strong>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR        0x2006
+CL_DEVICES_FOR_GL_CONTEXT_KHR               0x2007</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Accepted as an attribute name in the <em>properties</em> argument of
+<strong>clCreateContext</strong> and <strong>clCreateContextFromType</strong>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_GL_CONTEXT_KHR                           0x2008
+CL_EGL_DISPLAY_KHR                          0x2009
+CL_GLX_DISPLAY_KHR                          0x200A
+CL_WGL_HDC_KHR                              0x200B
+CL_CGL_SHAREGROUP_KHR                       0x200C</pre>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_gl_sharing-additions-to-chapter-4">3.4. Additions to Chapter 4 of the OpenCL 2.2 Specification</h3>
+<div class="paragraph">
+<p>In <em>section 4.4</em>, replace the description of <em>properties</em> under
+<strong>clCreateContext</strong> with:</p>
+</div>
+<div class="paragraph">
+<p>"`<em>properties</em> points to an attribute list, which is a array of ordered
+&lt;attribute name, value&gt; pairs terminated with zero.
+If an attribute is not specified in <em>properties</em>, then its default value
+(listed in <em>table 4.5</em>) is used (it is said to be specified implicitly).
+If <em>properties</em> is <code>NULL</code> or empty (points to a list whose first value is
+zero), all attributes take on their default values.</p>
+</div>
+<div class="paragraph">
+<p>Attributes control sharing of OpenCL memory objects with OpenGL buffer,
+texture, and renderbuffer objects.
+Depending on the platform-specific API used to bind OpenGL contexts to the
+window system, the following attributes may be set to identify an OpenGL
+context:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>When the CGL binding API is supported, the attribute
+CL_CGL_SHAREGROUP_KHR should be set to a CGLShareGroup handle to a CGL
+share group object.</p>
+</li>
+<li>
+<p>When the EGL binding API is supported, the attribute CL_GL_CONTEXT_KHR
+should be set to an EGLContext handle to an OpenGL ES or OpenGL context,
+and the attribute CL_EGL_DISPLAY_KHR should be set to the EGLDisplay
+handle of the display used to create the OpenGL ES or OpenGL context.</p>
+</li>
+<li>
+<p>When the GLX binding API is supported, the attribute CL_GL_CONTEXT_KHR
+should be set to a GLXContext handle to an OpenGL context, and the
+attribute CL_GLX_DISPLAY_KHR should be set to the Display handle of the
+X Window System display used to create the OpenGL context.</p>
+</li>
+<li>
+<p>When the WGL binding API is supported, the attribute CL_GL_CONTEXT_KHR
+should be set to an HGLRC handle to an OpenGL context, and the attribute
+CL_WGL_HDC_KHR should be set to the HDC handle of the display used to
+create the OpenGL context.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Memory objects created in the context so specified may be shared with the
+specified OpenGL or OpenGL ES context (as well as with any other OpenGL
+contexts on the share list of that context, according to the description of
+sharing in the GLX 1.4 and EGL 1.4 specifications, and the WGL documentation
+for OpenGL implementations on Microsoft Windows), or with the explicitly
+identified OpenGL share group for CGL.
+If no OpenGL or OpenGL ES context or share group is specified in the
+attribute list, then memory objects may not be shared, and calling any of
+the commands described in <a href="#cl_khr_gl_sharing__memobjs">Creating OpenCL
+Memory Objects from OpenGL Objects</a> will result in a
+CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR error.`"</p>
+</div>
+<div class="paragraph">
+<p>OpenCL / OpenGL sharing does not support the CL_CONTEXT_INTEROP_USER_SYNC
+property defined in <em>table 4.5</em>.
+Specifying this property when creating a context with OpenCL / OpenGL
+sharing will return an appropriate error.</p>
+</div>
+<div class="paragraph">
+<p>Add to <em>table 4.5</em>:</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 11. <em>OpenGL Sharing Context Creation Attributes</em></caption>
+<colgroup>
+<col style="width: 33.3333%;">
+<col style="width: 33.3333%;">
+<col style="width: 33.3334%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Attribute Name</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Allowed Values</strong>
+
+  <strong>(Default value is in bold)</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_GL_CONTEXT_KHR</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>0</strong>, OpenGL context handle</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">OpenGL context to associated the OpenCL context with</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_CGL_SHAREGROUP_KHR</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>0</strong>, CGL share group handle</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CGL share group to associate the OpenCL context with</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_EGL_DISPLAY_KHR</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>EGL_NO_DISPLAY</strong>, EGLDisplay handle</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">EGLDisplay an OpenGL context was created with respect to</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_GLX_DISPLAY_KHR</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>None</strong>, X handle</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">X Display an OpenGL context was created with respect to</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_WGL_HDC_KHR</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>0</strong>, HDC handle</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">HDC an OpenGL context was created with respect to</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>Replace the first error in the list for <strong>clCreateContext</strong> with:</p>
+</div>
+<div class="paragraph">
+<p>"`<em>errcode_ret</em> returns CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR if a context
+was specified by any of the following means:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>A context was specified for an EGL-based OpenGL ES or OpenGL
+implementation by setting the attributes CL_GL_CONTEXT_KHR and
+CL_EGL_DISPLAY_KHR.</p>
+</li>
+<li>
+<p>A context was specified for a GLX-based OpenGL implementation by setting
+the attributes CL_GL_CONTEXT_KHR and CL_GLX_DISPLAY_KHR.</p>
+</li>
+<li>
+<p>A context was specified for a WGL-based OpenGL implementation by setting
+the attributes CL_GL_CONTEXT_KHR and CL_WGL_HDC_KHR</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>and any of the following conditions hold:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>The specified display and context attributes do not identify a valid
+OpenGL or OpenGL ES context.</p>
+</li>
+<li>
+<p>The specified context does not support buffer and renderbuffer objects.</p>
+</li>
+<li>
+<p>The specified context is not compatible with the OpenCL context being
+created (for example, it exists in a physically distinct address space,
+such as another hardware device; or it does not support sharing data
+with OpenCL due to implementation restrictions).</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p><em>errcode_ret</em> returns CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR if a share
+group was specified for a CGL-based OpenGL implementation by setting the
+attribute CL_CGL_SHAREGROUP_KHR, and the specified share group does not
+identify a valid CGL share group object.</p>
+</div>
+<div class="paragraph">
+<p><em>errcode_ret</em> returns CL_INVALID_OPERATION if a context was specified as
+described above and any of the following conditions hold:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>A context or share group object was specified for one of CGL, EGL, GLX,
+or WGL and the OpenGL implementation does not support that window-system
+binding API.</p>
+</li>
+<li>
+<p>More than one of the attributes CL_CGL_SHAREGROUP_KHR,
+CL_EGL_DISPLAY_KHR, CL_GLX_DISPLAY_KHR, and CL_WGL_HDC_KHR is set to a
+non-default value.</p>
+</li>
+<li>
+<p>Both of the attributes CL_CGL_SHAREGROUP_KHR and CL_GL_CONTEXT_KHR are
+set to non-default values.</p>
+</li>
+<li>
+<p>Any of the devices specified in the <em>devices</em> argument cannot support
+OpenCL objects which share the data store of an OpenGL object.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p><em>errcode_ret</em> returns CL_INVALID_PROPERTY if an attribute name other than
+those specified in <em>table 4.5</em> or if CL_CONTEXT_INTEROP_USER_SYNC is
+specified in <em>properties</em>.`"</p>
+</div>
+<div class="paragraph">
+<p>Replace the description of <em>properties</em> under <strong>clCreateContextFromType</strong>
+with:</p>
+</div>
+<div class="paragraph">
+<p>&#8220;_properties_ points to an attribute list whose format and valid contents
+are identical to the <strong>properties</strong> argument of <strong>clCreateContext</strong>.&#8221;</p>
+</div>
+<div class="paragraph">
+<p>Replace the first error in the list for <strong>clCreateContextFromType</strong> with the
+same two new errors described above for <strong>clCreateContext</strong>.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_gl_sharing-additions-to-chapter-5">3.5. Additions to Chapter 5 of the OpenCL 2.2 Specification</h3>
+<div class="paragraph">
+<p>Add a new section to describe the new API for querying OpenCL devices that
+support sharing with OpenGL:</p>
+</div>
+<div class="paragraph">
+<p>"`OpenCL device(s) corresponding to an OpenGL context may be queried.
+Such a device may not always exist (for example, if an OpenGL context is
+specified on a GPU not supporting OpenCL command queues, but which does
+support shared CL/GL objects), and if it does exist, may change over time.
+When such a device does exist, acquiring and releasing shared CL/GL objects
+may be faster on a command queue corresponding to this device than on
+command queues corresponding to other devices available to an OpenCL
+context.</p>
+</div>
+<div class="paragraph">
+<p>To query the currently corresponding device, use the function
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_int clGetGLContextInfoKHR(const cl_context_properties *properties,
+                             cl_gl_context_info param_name,
+                             size_t param_value_size,
+                             void *param_value,
+                             size_t *param_value_size_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><em>properties</em> points to an attribute list whose format and valid contents are
+identical to the <em>properties</em> argument of <strong>clCreateContext</strong>.
+<em>properties</em> must identify a single valid GL context or GL share group
+object.</p>
+</div>
+<div class="paragraph">
+<p><em>param_name</em> is a constant that specifies the device types to query, and
+must be one of the values shown in the table below.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value</em> is a pointer to memory where the result of the query is
+returned as described in the table below.
+If <em>param_value</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size</em> specifies the size in bytes of memory pointed to by
+<em>param_value</em>.
+This size must be greater than or equal to the size of the return type
+described in the table below.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size_ret</em> returns the actual size in bytes of data being
+queried by <em>param_value</em>.
+If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<table id="cl_khr_gl_sharing-clGetGLContextInfoKHR-table" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 12. <em>Supported Device Types for</em> <strong>clGetGLContextInfoKHR</strong></caption>
+<colgroup>
+<col style="width: 40%;">
+<col style="width: 20%;">
+<col style="width: 40%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>param_name</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Return Type</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Information returned in param_value</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cl_device_id</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return the OpenCL device currently associated with the specified OpenGL
+  context.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEVICES_FOR_GL_CONTEXT_KHR</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cl_device_id[]</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return all OpenCL devices which may be associated with the specified
+  OpenGL context.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p><strong>clGetGLContextInfoKHR</strong> returns CL_SUCCESS if the function is executed
+successfully.
+If no device(s) exist corresponding to <em>param_name</em>, the call will not fail,
+but the value of <em>param_value_size_ret</em> will be zero.</p>
+</div>
+<div class="paragraph">
+<p><strong>clGetGLContextInfoKHR</strong> returns CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR if a
+context was specified by any of the following means:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>A context was specified for an EGL-based OpenGL ES or OpenGL
+implementation by setting the attributes CL_GL_CONTEXT_KHR and
+CL_EGL_DISPLAY_KHR.</p>
+</li>
+<li>
+<p>A context was specified for a GLX-based OpenGL implementation by setting
+the attributes CL_GL_CONTEXT_KHR and CL_GLX_DISPLAY_KHR.</p>
+</li>
+<li>
+<p>A context was specified for a WGL-based OpenGL implementation by setting
+the attributes CL_GL_CONTEXT_KHR and CL_WGL_HDC_KHR.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>and any of the following conditions hold:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>The specified display and context attributes do not identify a valid
+OpenGL or OpenGL ES context.</p>
+</li>
+<li>
+<p>The specified context does not support buffer and renderbuffer objects.</p>
+</li>
+<li>
+<p>The specified context is not compatible with the OpenCL context being
+created (for example, it exists in a physically distinct address space,
+such as another hardware device; or it does not support sharing data
+with OpenCL due to implementation restrictions).</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p><strong>clGetGLContextInfoKHR</strong> returns CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR if a
+share group was specified for a CGL-based OpenGL implementation by setting
+the attribute CL_CGL_SHAREGROUP_KHR, and the specified share group does not
+identify a valid CGL share group object.</p>
+</div>
+<div class="paragraph">
+<p><strong>clGetGLContextInfoKHR</strong> returns CL_INVALID_OPERATION if a context was
+specified as described above and any of the following conditions hold:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>A context or share group object was specified for one of CGL, EGL, GLX,
+or WGL and the OpenGL implementation does not support that window-system
+binding API.</p>
+</li>
+<li>
+<p>More than one of the attributes CL_CGL_SHAREGROUP_KHR,
+CL_EGL_DISPLAY_KHR, CL_GLX_DISPLAY_KHR, and CL_WGL_HDC_KHR is set to a
+non-default value.</p>
+</li>
+<li>
+<p>Both of the attributes CL_CGL_SHAREGROUP_KHR and CL_GL_CONTEXT_KHR are
+set to non-default values.</p>
+</li>
+<li>
+<p>Any of the devices specified in the &lt;devices&gt; argument cannot support
+OpenCL objects which share the data store of an OpenGL object.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p><strong>clGetGLContextInfoKHR</strong> returns CL_INVALID_VALUE if an attribute name other
+than those specified in <em>table 4.5</em> is specified in <em>properties</em>.</p>
+</div>
+<div class="paragraph">
+<p>Additionally, <strong>clGetGLContextInfoKHR</strong> returns CL_INVALID_VALUE if
+<em>param_name</em> is not one of the values listed in the table
+<a href="#cl_khr_gl_sharing-clGetGLContextInfoKHR-table"><em>GL context information that
+can be queried with</em> <strong>clGetGLContextInfoKHR</strong></a>, or if the size in bytes
+specified by <em>param_value_size</em> is less than the size of the return type
+shown in the table and <em>param_value</em> is not a <code>NULL</code> value;
+CL_OUT_OF_RESOURCES if there is a failure to allocate resources required by
+the OpenCL implementation on the device; or CL_OUT_OF_HOST_MEMORY if there
+is a failure to allocate resources required by the OpenCL implementation on
+the host.`"</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_gl_sharing-issues">3.6. Issues</h3>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>How should the OpenGL context be identified when creating an associated
+OpenCL context?</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>RESOLVED: by using a (display,context handle) attribute pair to identify an
+arbitrary OpenGL or OpenGL ES context with respect to one of the
+window-system binding layers EGL, GLX, or WGL, or a share group handle to
+identify a CGL share group.
+If a context is specified, it need not be current to the thread calling
+clCreateContext*.</p>
+</div>
+<div class="paragraph">
+<p>A previously suggested approach would use a single boolean attribute
+CL_USE_GL_CONTEXT_KHR to allow creating a context associated with the
+currently bound OpenGL context.
+This may still be implemented as a separate extension, and might allow more
+efficient acquire/release behavior in the special case where they are being
+executed in the same thread as the bound GL context used to create the CL
+context.</p>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p>What should the format of an attribute list be?</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>After considerable discussion, we think we can live with a list of
+&lt;attribute name,value&gt; pairs terminated by zero.
+The list is passed as 'cl_context_properties *<em>properties'</em>, where
+cl_context_properties is typedefed to be 'intptr_t' in cl.h.</p>
+</div>
+<div class="paragraph">
+<p>This effectively allows encoding all scalar integer, pointer, and handle
+values in the host API into the argument list and is analogous to the
+structure and type of EGL attribute lists.
+<code>NULL</code> attribute lists are also allowed.
+Again as for EGL, any attributes not explicitly passed in the list will take
+on a defined default value that does something reasonable.</p>
+</div>
+<div class="paragraph">
+<p>Experience with EGL, GLX, and WGL has shown attribute lists to be a
+sufficiently flexible and general mechanism to serve the needs of management
+calls such as context creation.
+It is not completely general (encoding floating-point and non-scalar
+attribute values is not straightforward), and other approaches were
+suggested such as opaque attribute lists with getter/setter methods, or
+arrays of varadic structures.</p>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p>What&#8217;s the behavior of an associated OpenGL or OpenCL context when using
+resources defined by the other associated context, and that context is
+destroyed?</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>RESOLVED: OpenCL objects place a reference on the data store underlying the
+corresponding GL object when they&#8217;re created.
+The GL name corresponding to that data store may be deleted, but the data
+store itself remains so long as any CL object has a reference to it.
+However, destroying all GL contexts in the share group corresponding to a CL
+context results in implementation-dependent behavior when using a
+corresponding CL object, up to and including program termination.</p>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p>How about sharing with D3D?</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>Sharing between D3D and OpenCL should use the same attribute list mechanism,
+though obviously with different parameters, and be exposed as a similar
+parallel OpenCL extension.
+There may be an interaction between that extension and this one since it&#8217;s
+not yet clear if it will be possible to create a CL context simultaneously
+sharing GL and D3D objects.</p>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p>Under what conditions will context creation fail due to sharing?</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>RESOLVED: Several cross-platform failure conditions are described (GL
+context or CGL share group doesn&#8217;t exist, GL context doesn&#8217;t support types
+of GL objects, GL context implementation doesn&#8217;t allow sharing), but
+additional failures may result due to implementation-dependent reasons and
+should be added to this extension as such failures are discovered.
+Sharing between OpenCL and OpenGL requires integration at the driver
+internals level.</p>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p>What command queues can <strong>clEnqueueAcquire/ReleaseGLObjects</strong> be placed
+on?</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>RESOLVED: All command queues.
+This restriction is enforced at context creation time.
+If any device passed to context creation cannot support shared CL/GL
+objects, context creation will fail with a CL_INVALID_OPERATION error.</p>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p>How can applications determine which command queue to place an
+Acquire/Release on?</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>RESOLVED: The <strong>clGetGLContextInfoKHR</strong> returns either the CL device currently
+corresponding to a specified GL context (typically the display it&#8217;s running
+on), or a list of all the CL devices the specified context might run on
+(potentially useful in multiheaded / &#8220;virtual screen&#8221; environments).
+This command is not simply placed in <a href="#cl_khr_gl_sharing__memobjs">Creating
+OpenCL Memory Objects from OpenGL Objects</a> because it relies on the same
+property-list method of specifying a GL context introduced by this
+extension.</p>
+</div>
+<div class="paragraph">
+<p>If no devices are returned, it means that the GL context exists on an older
+GPU not capable of running OpenCL, but still capable of sharing objects
+between GL running on that GPU and CL running elsewhere.</p>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p>What is the meaning of the CL_DEVICES_FOR_GL_CONTEXT_KHR query?</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>RESOLVED: The list of all CL devices that may ever be associated with a
+specific GL context.
+On platforms such as MacOS X, the &#8220;virtual screen&#8221; concept allows multiple
+GPUs to back a single virtual display.
+Similar functionality might be implemented on other windowing systems, such
+as a transparent heterogenous multiheaded X server.
+Therefore the exact meaning of this query is interpreted relative to the
+binding layer API in use.</p>
+</div>
+</div>
+</div>
+</li>
+</ol>
+</div>
+<div style="page-break-after: always;"></div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="cl_khr_gl_sharing__memobjs">4. Creating OpenCL Memory Objects from OpenGL Objects</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>This section describes OpenCL functions that allow applications to use
+OpenGL buffer, texture and renderbuffer objects as OpenCL memory objects.
+This allows efficient sharing of data between OpenCL and OpenGL.
+The OpenCL API may be used to execute kernels that read and/or write memory
+objects that are also OpenGL objects.</p>
+</div>
+<div class="paragraph">
+<p>An OpenCL image object may be created from an OpenGL texture or renderbuffer
+object.
+An OpenCL buffer object may be created from an OpenGL buffer object.</p>
+</div>
+<div class="paragraph">
+<p>OpenCL memory objects may be created from OpenGL objects if and only if the
+OpenCL context has been created from an OpenGL share group object or
+context.
+OpenGL share groups and contexts are created using platform specific APIs
+such as EGL, CGL, WGL, and GLX.
+On MacOS X, an OpenCL context may be created from an OpenGL share group
+object using the OpenCL platform extension <strong>cl_apple_gl_sharing</strong>.
+On other platforms including Microsoft Windows, Linux/Unix, and others, an
+OpenCL context may be created from an OpenGL context using the extension
+<strong>cl_khr_gl_sharing</strong>.
+Refer to the platform documentation for your OpenCL implementation, or visit
+the Khronos Registry at <a href="http://www.khronos.org/registry/cl/" class="bare">http://www.khronos.org/registry/cl/</a> for more
+information.</p>
+</div>
+<div class="paragraph">
+<p>Any supported OpenGL object defined within the GL share group object, or the
+share group associated with the GL context from which the OpenCL context is
+created, may be shared, with the exception of the default OpenGL objects
+(i.e. objects named zero), which may not be shared.</p>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_gl_sharing__memobjs-lifetime-of-shared-objects">4.1. Lifetime of Shared Objects</h3>
+<div class="paragraph">
+<p>An OpenCL memory object created from an OpenGL object (hereinafter refered
+to as a &#8220;shared CL/GL object&#8221;) remains valid as long as the corresponding
+GL object has not been deleted.
+If the GL object is deleted through the GL API (e.g. <strong>glDeleteBuffers</strong>,
+<strong>glDeleteTextures,</strong> or <strong>glDeleteRenderbuffers</strong>), subsequent use of the CL
+buffer or image object will result in undefined behavior, including but not
+limited to possible CL errors and data corruption, but may not result in
+program termination.</p>
+</div>
+<div class="paragraph">
+<p>The CL context and corresponding command-queues are dependent on the
+existence of the GL share group object, or the share group associated with
+the GL context from which the CL context is created.
+If the GL share group object or all GL contexts in the share group are
+destroyed, any use of the CL context or command-queue(s) will result in
+undefined behavior, which may include program termination.
+Applications should destroy the CL command-queue(s) and CL context before
+destroying the corresponding GL share group or contexts</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_gl_sharing__memobjs-cl-buffer-objects-from-gl-buffer-objects">4.2. OpenCL Buffer Objects from OpenGL Buffer Objects</h3>
+<div class="paragraph">
+<p>The function
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_mem clCreateFromGLBuffer(cl_context context,
+                            cl_mem_flags flags,
+                            GLuint bufobj,
+                            cl_int *errcode_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>creates an OpenCL buffer object from an OpenGL buffer object.</p>
+</div>
+<div class="paragraph">
+<p><em>context</em> is a valid OpenCL context created from an OpenGL context.</p>
+</div>
+<div class="paragraph">
+<p><em>flags</em> is a bit-field that is used to specify usage information.
+Refer to <em>table 5.3</em> for a description of <em>flags</em>.
+Only CL_MEM_READ_ONLY, CL_MEM_WRITE_ONLY and CL_MEM_READ_WRITE values
+specified in <em>table 5.3</em> can be used.</p>
+</div>
+<div class="paragraph">
+<p><em>bufobj</em> is the name of a GL buffer object.
+The data store of the GL buffer object must have have been previously
+created by calling <strong>glBufferData</strong>, although its contents need not be
+initialized.
+The size of the data store will be used to determine the size of the CL
+buffer object.</p>
+</div>
+<div class="paragraph">
+<p><em>errcode_ret</em> will return an appropriate error code as described below.
+If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p>
+</div>
+<div class="paragraph">
+<p><strong>clCreateFromGLBuffer</strong> returns a valid non-zero OpenCL buffer object and
+<em>errcode_ret</em> is set to CL_SUCCESS if the buffer object is created
+successfully.
+Otherwise, it returns a <code>NULL</code> value with one of the following error values
+returned in <em>errcode_ret</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context or was not
+created from a GL context.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if values specified in <em>flags</em> are not valid.</p>
+</li>
+<li>
+<p>CL_INVALID_GL_OBJECT if <em>bufobj</em> is not a GL buffer object or is a GL
+buffer object but does not have an existing data store or the size of
+the buffer is 0.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The size of the GL buffer object data store at the time
+<strong>clCreateFromGLBuffer</strong> is called will be used as the size of buffer object
+returned by <strong>clCreateFromGLBuffer</strong>.
+If the state of a GL buffer object is modified through the GL API (e.g.
+<strong>glBufferData</strong>) while there exists a corresponding CL buffer object,
+subsequent use of the CL buffer object will result in undefined behavior.</p>
+</div>
+<div class="paragraph">
+<p>The <strong>clRetainMemObject</strong> and <strong>clReleaseMemObject</strong> functions can be used to
+retain and release the buffer object.</p>
+</div>
+<div class="paragraph">
+<p>The CL buffer object created using clCreateFromGLBuffer can also be used to
+create a CL 1D image buffer object.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_gl_sharing__memobjs-cl-image-objects-from-gl-textures">4.3. OpenCL Image Objects from OpenGL Textures</h3>
+<div class="paragraph">
+<p>The function
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_mem clCreateFromGLTexture(cl_context context,
+                             cl_mem_flags flags,
+                             GLenum texture_target,
+                             GLint miplevel,
+                             GLuint texture,
+                             cl_int *errcode_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>creates the following:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>an OpenCL 2D image object from an OpenGL 2D texture object or a single
+face of an OpenGL cubemap texture object,</p>
+</li>
+<li>
+<p>an OpenCL 2D image array object from an OpenGL 2D texture array object,</p>
+</li>
+<li>
+<p>an OpenCL 1D image object from an OpenGL 1D texture object,</p>
+</li>
+<li>
+<p>an OpenCL 1D image buffer object from an OpenGL texture buffer object,</p>
+</li>
+<li>
+<p>an OpenCL 1D image array object from an OpenGL 1D texture array object,</p>
+</li>
+<li>
+<p>an OpenCL 3D image object from an OpenGL 3D texture object.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p><em>context</em> is a valid OpenCL context created from an OpenGL context.</p>
+</div>
+<div class="paragraph">
+<p><em>flags</em> is a bit-field that is used to specify usage information.
+Refer to <em>table 5.3</em> for a description of <em>flags</em>.
+Only CL_MEM_READ_ONLY, CL_MEM_WRITE_ONLY and CL_MEM_READ_WRITE values
+specified in <em>table 5.3</em> may be used.</p>
+</div>
+<div class="paragraph">
+<p><em>texture_target</em> must be one of GL_TEXTURE_1D, GL_TEXTURE_1D_ARRAY,
+GL_TEXTURE_BUFFER, GL_TEXTURE_2D, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_3D,
+GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
+GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
+GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, or
+GL_TEXTURE_RECTANGLE (Note: CL_TEXTURE_RECTANGLE requires OpenGL 3.1.
+Alternatively, GL_TEXTURE_RECTANGLE_ARB may be specified if the OpenGL
+extension <strong>GL_ARB_texture_rectangle</strong> is supported.).
+<em>texture_target</em> is used only to define the image type of <em>texture</em>.
+No reference to a bound GL texture object is made or implied by this
+parameter.</p>
+</div>
+<div class="paragraph">
+<p><em>miplevel</em> is the mipmap level to be used.
+If <em>texture_target</em> is GL_TEXTURE_BUFFER, <em>miplevel</em> must be 0.
+Note: Implementations may return CL_INVALID_OPERATION for miplevel
+values &gt; 0.</p>
+</div>
+<div class="paragraph">
+<p><em>texture</em> is the name of a GL 1D, 2D, 3D, 1D array, 2D array, cubemap,
+rectangle or buffer texture object.
+The texture object must be a complete texture as per OpenGL rules on texture
+completeness.
+The <em>texture</em> format and dimensions defined by OpenGL for the specified
+<em>miplevel</em> of the texture will be used to create the OpenCL image memory
+object.
+Only GL texture objects with an internal format that maps to appropriate
+image channel order and data type specified in <em>tables 5.5</em> and <em>5.6</em> may be
+used to create the OpenCL image memory object.</p>
+</div>
+<div class="paragraph">
+<p><em>errcode_ret</em> will return an appropriate error code as described below.
+If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p>
+</div>
+<div class="paragraph">
+<p><strong>clCreateFromGLTexture</strong> returns a valid non-zero OpenCL image object and
+<em>errcode_ret</em> is set to CL_SUCCESS if the image object is created
+successfully.
+Otherwise, it returns a <code>NULL</code> value with one of the following error values
+returned in <em>errcode_ret</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context or was not
+created from a GL context.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if values specified in <em>flags</em> are not valid or if
+value specified in <em>texture_target</em> is not one of the values specified
+in the description of <em>texture_target</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_MIP_LEVEL if <em>miplevel</em> is less than the value of
+<em>level<sub>base</sub></em> (for OpenGL implementations) or zero (for OpenGL ES
+implementations); or greater than the value of <em>q</em> (for both OpenGL and
+OpenGL ES).
+<em>level<sub>base</sub></em> and <em>q</em> are defined for the texture in <em>section 3.8.10</em>
+(Texture Completeness) of the OpenGL 2.1 specification and <em>section
+3.7.10</em> of the OpenGL ES 2.0.</p>
+</li>
+<li>
+<p>CL_INVALID_MIP_LEVEL if <em>miplevel</em> is greather than zero and the OpenGL
+implementation does not support creating from non-zero mipmap levels.</p>
+</li>
+<li>
+<p>CL_INVALID_GL_OBJECT if <em>texture</em> is not a GL texture object whose type
+matches <em>texture_target</em>, if the specified <em>miplevel</em> of <em>texture</em> is
+not defined, or if the width or height of the specified <em>miplevel</em> is
+zero or if the GL texture object is incomplete.</p>
+</li>
+<li>
+<p>CL_INVALID_IMAGE_FORMAT_DESCRIPTOR if the OpenGL texture internal format
+does not map to a supported OpenCL image format.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if <em>texture</em> is a GL texture object created with a
+border width value greater than zero.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If the state of a GL texture object is modified through the GL API (e.g.
+<strong>glTexImage2D</strong>, <strong>glTexImage3D</strong> or the values of the texture parameters
+GL_TEXTURE_BASE_LEVEL or GL_TEXTURE_MAX_LEVEL are modified) while there
+exists a corresponding CL image object, subsequent use of the CL image
+object will result in undefined behavior.</p>
+</div>
+<div class="paragraph">
+<p>The <strong>clRetainMemObject</strong> and <strong>clReleaseMemObject</strong> functions can be used to
+retain and release the image objects.</p>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_gl_sharing__memobjs-list-of-opengl-and-corresponding-opencl-image-formats">4.3.1. List of OpenGL and corresponding OpenCL Image Formats</h4>
+<div class="paragraph">
+<p>The table below describes the list of OpenGL texture internal formats and
+the corresponding OpenCL image formats.
+If a OpenGL texture object with an internal format from the table below is
+successfully created by OpenGL, then there is guaranteed to be a mapping to
+one of the corresponding OpenCL image format(s) in that table.
+Texture objects created with other OpenGL internal formats may (but are not
+guaranteed to) have a mapping to an OpenCL image format; if such mappings
+exist, they are guaranteed to preserve all color components, data types, and
+at least the number of bits/component actually allocated by OpenGL for that
+format.</p>
+</div>
+<table id="cl_khr_gl_sharing__memobjs-mapping-of-image-formats" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 13. <em>OpenGL internal formats and corresponding OpenCL internal formats</em></caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>GL internal format</strong></th>
+<th class="tableblock halign-left valign-top"><strong>CL image format</strong>
+
+  <strong>(channel order, channel data type)</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_RGBA8</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_UNORM_INT8 or</p>
+<p class="tableblock">CL_BGRA, CL_UNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_SRGB8_ALPHA8</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_sRGBA, CL_UNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_UNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_BGRA, CL_UNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_RGBA8I, GL_RGBA8I_EXT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_SIGNED_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_RGBA16I, GL_RGBA16I_EXT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_SIGNED_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_RGBA32I, GL_RGBA32I_EXT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_SIGNED_INT32</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_RGBA8UI, GL_RGBA8UI_EXT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_UNSIGNED_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_RGBA16UI, GL_RGBA16UI_EXT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_UNSIGNED_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_RGBA32UI, GL_RGBA32UI_EXT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_UNSIGNED_INT32</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_RGBA8_SNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_SNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_RGBA16</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_UNORM_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_RGBA16_SNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_SNORM_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_RGBA16F, GL_RGBA16F_ARB</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_HALF_FLOAT</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_RGBA32F, GL_RGBA32F_ARB</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_FLOAT</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_R8</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_UNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_R8_SNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_SNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_R16</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_UNORM_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_R16_SNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_SNORM_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_R16F</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_HALF_FLOAT</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_R32F</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_FLOAT</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_R8I</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_SIGNED_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_R16I</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_SIGNED_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_R32I</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_SIGNED_INT32</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_R8UI</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_UNSIGNED_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_R16UI</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_UNSIGNED_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_R32UI</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_UNSIGNED_INT32</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_RG8</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_UNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_RG8_SNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_SNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_RG16</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_UNORM_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_RG16_SNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_SNORM_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_RG16F</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_HALF_FLOAT</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_RG32F</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_FLOAT</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_RG8I</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_SIGNED_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_RG16I</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_SIGNED_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_RG32I</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_SIGNED_INT32</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_RG8UI</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_UNSIGNED_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_RG16UI</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_UNSIGNED_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_RG32UI</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_UNSIGNED_INT32</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_gl_sharing__memobjs-cl-image-objects-from-gl-renderbuffers">4.4. OpenCL Image Objects from OpenGL Renderbuffers</h3>
+<div class="paragraph">
+<p>The function
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_mem clCreateFromGLRenderbuffer(cl_context context,
+                                  cl_mem_flags flags,
+                                  GLuint renderbuffer,
+                                  cl_int *errcode_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>creates an OpenCL 2D image object from an OpenGL renderbuffer object.</p>
+</div>
+<div class="paragraph">
+<p><em>context</em> is a valid OpenCL context created from an OpenGL context.</p>
+</div>
+<div class="paragraph">
+<p><em>flags</em> is a bit-field that is used to specify usage information.
+Refer to <em>table 5.3</em> for a description of <em>flags</em>.
+Only CL_MEM_READ_ONLY, CL_MEM_WRITE_ONLY and CL_MEM_READ_WRITE values
+specified in <em>table 5.3</em> can be used.</p>
+</div>
+<div class="paragraph">
+<p><em>renderbuffer</em> is the name of a GL renderbuffer object.
+The renderbuffer storage must be specified before the image object can be
+created.
+The <em>renderbuffer</em> format and dimensions defined by OpenGL will be used to
+create the 2D image object.
+Only GL renderbuffers with internal formats that maps to appropriate image
+channel order and data type specified in <em>tables 5.5</em> and <em>5.6</em> can be used
+to create the 2D image object.</p>
+</div>
+<div class="paragraph">
+<p><em>errcode_ret</em> will return an appropriate error code as described below.
+If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p>
+</div>
+<div class="paragraph">
+<p><strong>clCreateFromGLRenderbuffer</strong> returns a valid non-zero OpenCL image object
+and <em>errcode_ret</em> is set to CL_SUCCESS if the image object is created
+successfully.
+Otherwise, it returns a <code>NULL</code> value with one of the following error values
+returned in <em>errcode_ret</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context or was not
+created from a GL context.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if values specified in <em>flags</em> are not valid.</p>
+</li>
+<li>
+<p>CL_INVALID_GL_OBJECT if <em>renderbuffer</em> is not a GL renderbuffer object
+or if the width or height of <em>renderbuffer</em> is zero.</p>
+</li>
+<li>
+<p>CL_INVALID_IMAGE_FORMAT_DESCRIPTOR if the OpenGL renderbuffer internal
+format does not map to a supported OpenCL image format.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if <em>renderbuffer</em> is a multi-sample GL renderbuffer
+object.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If the state of a GL renderbuffer object is modified through the GL API
+(i.e. changes to the dimensions or format used to represent pixels of the GL
+renderbuffer using appropriate GL API calls such as <strong>glRenderbufferStorage</strong>)
+while there exists a corresponding CL image object, subsequent use of the CL
+image object will result in undefined behavior.</p>
+</div>
+<div class="paragraph">
+<p>The <strong>clRetainMemObject</strong> and <strong>clReleaseMemObject</strong> functions can be used to
+retain and release the image objects.</p>
+</div>
+<div class="paragraph">
+<p>The table <a href="#cl_khr_gl_sharing__memobjs-mapping-of-image-formats"><em>OpenGL
+internal formats and corresponding OpenCL internal formats</em></a> describes the
+list of OpenGL renderbuffer internal formats and the corresponding OpenCL
+image formats.
+If an OpenGL renderbuffer object with an internal format from the table is
+successfully created by OpenGL, then there is guaranteed to be a mapping to
+one of the corresponding OpenCL image format(s) in that table.
+Renderbuffer objects created with other OpenGL internal formats may (but are
+not guaranteed to) have a mapping to an OpenCL image format; if such
+mappings exist, they are guaranteed to preserve all color components, data
+types, and at least the number of bits/component actually allocated by
+OpenGL for that format.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_gl_sharing__memobjs-querying-gl-object-information-from-a-cl-memory-object">4.5. Querying OpenGL object information from an OpenCL memory object</h3>
+<div class="paragraph">
+<p>The OpenGL object used to create the OpenCL memory object and information
+about the object type i.e. whether it is a texture, renderbuffer or buffer
+object can be queried using the following function.
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_int clGetGLObjectInfo(cl_mem memobj,
+                         cl_gl_object_type *gl_object_type,
+                         GLuint *gl_object_name)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><em>gl_object_type</em> returns the type of GL object attached to <em>memobj</em> and can
+be CL_GL_OBJECT_BUFFER, CL_GL_OBJECT_TEXTURE2D, CL_GL_OBJECT_TEXTURE3D,
+CL_GL_OBJECT_TEXTURE2D_ARRAY, CL_GL_OBJECT_TEXTURE1D,
+CL_GL_OBJECT_TEXTURE1D_ARRAY, CL_GL_OBJECT_TEXTURE_BUFFER, or
+CL_GL_OBJECT_RENDERBUFFER.
+If <em>gl_object_type</em> is <code>NULL</code>, it is ignored</p>
+</div>
+<div class="paragraph">
+<p><em>gl_object_name</em> returns the GL object name used to create <em>memobj</em>.
+If <em>gl_object_name</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<div class="paragraph">
+<p><strong>clGetGLObjectInfo</strong> returns CL_SUCCESS if the call was executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_MEM_OBJECT if <em>memobj</em> is not a valid OpenCL memory object.</p>
+</li>
+<li>
+<p>CL_INVALID_GL_OBJECT if there is no GL object associated with <em>memobj</em>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_int clGetGLTextureInfo(cl_mem memobj,
+                          cl_gl_texture_info param_name,
+                          size_t param_value_size,
+                          void *param_value,
+                          size_t *param_value_size_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>returns additional information about the GL texture object associated with
+<em>memobj</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>param_name</em> specifies what additional information about the GL texture
+object associated with <em>memobj</em> to query.
+The list of supported <em>param_name</em> types and the information returned in
+<em>param_value</em> by <strong>clGetGLTextureInfo</strong> is described in the table below.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value</em> is a pointer to memory where the result being queried is
+returned.
+If <em>param_value</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size</em> is used to specify the size in bytes of memory pointed to
+by <em>param_value</em>.
+This size must be &gt;= size of return type as described in the table below.</p>
+</div>
+<div class="paragraph">
+<p><em>param_value_size_ret</em> returns the actual size in bytes of data copied to
+<em>param_value</em>.
+If <em>param_value_size_ret</em> is <code>NULL</code>, it is ignored.</p>
+</div>
+<table id="cl_khr_gl_sharing__memobjs-clGetGLTextureInfo-queries" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 14. <em>OpenGL texture info that may be queried with</em> <strong>clGetGLTextureInfo</strong></caption>
+<colgroup>
+<col style="width: 33.3333%;">
+<col style="width: 33.3333%;">
+<col style="width: 33.3334%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_gl_texture_info</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Return Type</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Info. returned in <em>param_value</em></strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_GL_TEXTURE_TARGET</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GLenum</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The <em>texture_target</em> argument specified in <strong>clCreateFromGLTexture</strong>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_GL_MIPMAP_LEVEL</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GLint</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The <em>miplevel</em> argument specified in <strong>clCreateFromGLTexture</strong>.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p><strong>clGetGLTextureInfo</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_MEM_OBJECT if <em>memobj</em> is not a valid OpenCL memory object.</p>
+</li>
+<li>
+<p>CL_INVALID_GL_OBJECT if there is no GL texture object associated with
+<em>memobj</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>param_name</em> is not valid, or if size in bytes
+specified by <em>param_value_size</em> is less than the size of the return type
+as described in the table above and <em>param_value</em> is not <code>NULL</code>, or if
+<em>param_value</em> and <em>param_value_size_ret</em> are <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_gl_sharing__memobjs-sharing-memory-objects-that-map-to-gl-objects-between-gl-and-cl-contexts">4.6. Sharing memory objects that map to GL objects between GL and CL contexts</h3>
+<div class="paragraph">
+<p>The function
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_int  clEnqueueAcquireGLObjects(cl_command_queue command_queue,
+                                  cl_uint num_objects,
+                                  const cl_mem *mem_objects,
+                                  cl_uint num_events_in_wait_list,
+                                  const cl_event *event_wait_list,
+                                  cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>is used to acquire OpenCL memory objects that have been created from OpenGL
+objects.
+These objects need to be acquired before they can be used by any OpenCL
+commands queued to a command-queue.
+The OpenGL objects are acquired by the OpenCL context associated with
+<em>command_queue</em> and can therefore be used by all command-queues associated
+with the OpenCL context.</p>
+</div>
+<div class="paragraph">
+<p><em>command_queue</em> is a valid command-queue.
+All devices used to create the OpenCL context associated with
+<em>command_queue</em> must support acquiring shared CL/GL objects.
+This constraint is enforced at context creation time.</p>
+</div>
+<div class="paragraph">
+<p><em>num_objects</em> is the number of memory objects to be acquired in
+<em>mem_objects</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>mem_objects</em> is a pointer to a list of CL memory objects that correspond to
+GL objects.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before this particular command can be executed.
+If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait
+on any event to complete.
+If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> act as synchronization points.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> returns an event object that identifies this command and can be used
+to query or queue a wait for the command to complete.
+<em>event</em> can be <code>NULL</code> in which case it will not be possible for the
+application to query the status of this command or queue a wait for this
+command to complete.
+If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the
+<em>event</em> argument should not refer to an element of the <em>event_wait_list</em>
+array.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueAcquireGLObjects</strong> returns CL_SUCCESS if the function is executed
+successfully.
+If <em>num_objects</em> is 0 and <em>mem_objects</em> is <code>NULL</code> the function does nothing
+and returns CL_SUCCESS.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_VALUE if <em>num_objects</em> is zero and <em>mem_objects</em> is not a
+<code>NULL</code> value or if <em>num_objects</em> &gt; 0 and <em>mem_objects</em> is <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_MEM_OBJECT if memory objects in <em>mem_objects</em> are not valid
+OpenCL memory objects.</p>
+</li>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if context associated with <em>command_queue</em> was not
+created from an OpenGL context</p>
+</li>
+<li>
+<p>CL_INVALID_GL_OBJECT if memory objects in <em>mem_objects</em> have not been
+created from a GL object(s).</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_int clEnqueueReleaseGLObjects(cl_command_queue command_queue,
+                                 cl_uint num_objects,
+                                 const cl_mem *mem_objects,
+                                 cl_uint num_events_in_wait_list,
+                                 const cl_event *event_wait_list,
+                                 cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>is used to release OpenCL memory objects that have been created from OpenGL
+objects.
+These objects need to be released before they can be used by OpenGL.
+The OpenGL objects are released by the OpenCL context associated with
+<em>command_queue</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>num_objects</em> is the number of memory objects to be released in
+<em>mem_objects</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>mem_objects</em> is a pointer to a list of CL memory objects that correspond to
+GL objects.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before this command can be executed.
+If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait
+on any event to complete.
+If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event_wait_list</em> act as synchronization points.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> returns an event object that identifies this particular read / write
+command and can be used to query or queue a wait for the command to
+complete.
+<em>event</em> can be`NULL` in which case it will not be possible for the
+application to query the status of this command or queue a wait for this
+command to complete.
+If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the
+<em>event</em> argument should not refer to an element of the <em>event_wait_list</em>
+array.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueReleaseGLObjects</strong> returns CL_SUCCESS if the function is executed
+successfully.
+If <em>num_objects</em> is 0 and <em>mem_objects</em> is <code>NULL</code> the function does nothing
+and returns CL_SUCCESS.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_VALUE if <em>num_objects</em> is zero and <em>mem_objects</em> is not a
+<code>NULL</code> value or if <em>num_objects</em> &gt; 0 and <em>mem_objects</em> is <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_MEM_OBJECT if memory objects in <em>mem_objects</em> are not valid
+OpenCL memory objects.</p>
+</li>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if context associated with <em>command_queue</em> was not
+created from an OpenGL context</p>
+</li>
+<li>
+<p>CL_INVALID_GL_OBJECT if memory objects in <em>mem_objects</em> have not been
+created from a GL object(s).</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_gl_sharing__memobjs-synchronizing-opencl-and-opengl-access-to-shared-objects">4.6.1. Synchronizing OpenCL and OpenGL Access to Shared Objects</h4>
+<div class="paragraph">
+<p>In order to ensure data integrity, the application is responsible for
+synchronizing access to shared CL/GL objects by their respective APIs.
+Failure to provide such synchronization may result in race conditions and
+other undefined behavior including non-portability between implementations.</p>
+</div>
+<div class="paragraph">
+<p>Prior to calling <strong>clEnqueueAcquireGLObjects</strong>, the application must ensure
+that any pending GL operations which access the objects specified in
+<em>mem_objects</em> have completed.
+This may be accomplished portably by issuing and waiting for completion of a
+<strong>glFinish</strong> command on all GL contexts with pending references to these
+objects.
+Implementations may offer more efficient synchronization methods; for
+example on some platforms calling <strong>glFlush</strong> may be sufficient, or
+synchronization may be implicit within a thread, or there may be
+vendor-specific extensions that enable placing a fence in the GL command
+stream and waiting for completion of that fence in the CL command queue.
+Note that no synchronization methods other than <strong>glFinish</strong> are portable
+between OpenGL implementations at this time.</p>
+</div>
+<div class="paragraph">
+<p>Similarly, after calling <strong>clEnqueueReleaseGLObjects</strong>, the application is
+responsible for ensuring that any pending OpenCL operations which access the
+objects specified in <em>mem_objects</em> have completed prior to executing
+subsequent GL commands which reference these objects.
+This may be accomplished portably by calling <strong>clWaitForEvents</strong> with the
+event object returned by <strong>clEnqueueReleaseGLObjects,</strong> or by calling
+<strong>clFinish</strong>.
+As above, some implementations may offer more efficient methods.</p>
+</div>
+<div class="paragraph">
+<p>The application is responsible for maintaining the proper order of
+operations if the CL and GL contexts are in separate threads.</p>
+</div>
+<div class="paragraph">
+<p>If a GL context is bound to a thread other than the one in which
+<strong>clEnqueueReleaseGLObjects</strong> is called, changes to any of the objects in
+<em>mem_objects</em> may not be visible to that context without additional steps
+being taken by the application.
+For an OpenGL 3.1 (or later) context, the requirements are described in
+Appendix D (&#8220;Shared Objects and Multiple Contexts&#8221;) of the OpenGL 3.1
+Specification.
+For prior versions of OpenGL, the requirements are implementation-dependent.</p>
+</div>
+<div class="paragraph">
+<p>Attempting to access the data store of an OpenGL object after it has been
+acquired by OpenCL and before it has been released will result in undefined
+behavior.
+Similarly, attempting to access a shared CL/GL object from OpenCL before it
+has been acquired by the OpenCL command queue, or after it has been
+released, will result in undefined behavior.</p>
+</div>
+<div style="page-break-after: always;"></div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="cl_khr_gl_event-creating">5. Creating OpenCL Event Objects from OpenGL Sync Objects</h2>
+<div class="sectionbody">
+<div class="sect2">
+<h3 id="cl_khr_gl_event-overview">5.1. Overview</h3>
+<div class="paragraph">
+<p>This section describes the <strong>cl_khr_gl_event</strong> extension.
+This extension allows creating OpenCL event objects linked to OpenGL fence
+sync objects, potentially improving efficiency of sharing images and buffers
+between the two APIs.
+The companion <strong>GL_ARB_cl_event</strong> extension provides the complementary
+functionality of creating an OpenGL sync object from an OpenCL event object.</p>
+</div>
+<div class="paragraph">
+<p>In addition, this extension modifies the behavior of
+<strong>clEnqueueAcquireGLObjects</strong> and <strong>clEnqueueReleaseGLObjects</strong> to implicitly
+guarantee synchronization with an OpenGL context bound in the same thread as
+the OpenCL context.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_gl_event-new-procedures-and-functions">5.2. New Procedures and Functions</h3>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_event clCreateEventFromGLsyncKHR(cl_context context,
+                                    GLsync sync,
+                                    cl_int *errcode_ret);</code></pre>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_gl_event-new-tokens">5.3. New Tokens</h3>
+<div class="paragraph">
+<p>Returned by <strong>clGetEventInfo</strong> when <em>param_name</em> is CL_EVENT_COMMAND_TYPE:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_COMMAND_GL_FENCE_SYNC_OBJECT_KHR 0x200D</pre>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_gl_event-additions-to-chapter-5">5.4. Additions to Chapter 5 of the OpenCL 2.2 Specification</h3>
+<div class="paragraph">
+<p>Add following to the fourth paragraph of <em>section 5.11</em> (prior to the
+description of <strong>clWaitForEvents</strong>):</p>
+</div>
+<div class="paragraph">
+<p>&#8220;Event objects can also be used to reflect the status of an OpenGL sync
+object.
+The sync object in turn refers to a fence command executing in an OpenGL
+command stream.
+This provides another method of coordinating sharing of buffers and images
+between OpenGL and OpenCL.&#8221;</p>
+</div>
+<div class="paragraph">
+<p>Add CL_COMMAND_GL_FENCE_SYNC_OBJECT_KHR to the valid <em>param_value</em> values
+returned by <strong>clGetEventInfo</strong> for <em>param_name</em> CL_EVENT_COMMAND_TYPE (in the
+third row and third column of <em>table 5.22</em>).</p>
+</div>
+<div class="paragraph">
+<p>Add new <em>subsection 5.11.1</em>:</p>
+</div>
+<div class="paragraph">
+<p>"`<strong>5.11.1 Linking Event Objects to OpenGL Synchronization Objects</strong></p>
+</div>
+<div class="paragraph">
+<p>An event object may be created by linking to an OpenGL <strong>sync object</strong>.
+Completion of such an event object is equivalent to waiting for completion
+of the fence command associated with the linked GL sync object.</p>
+</div>
+<div class="paragraph">
+<p>The function
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_event clCreateEventFromGLsyncKHR(cl_context context,
+                                    GLsync sync,
+                                    cl_int *errcode_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>creates a linked event object.</p>
+</div>
+<div class="paragraph">
+<p><em>context</em> is a valid OpenCL context created from an OpenGL context or share
+group, using the <strong>cl_khr_gl_sharing</strong> extension.</p>
+</div>
+<div class="paragraph">
+<p><em>sync</em> is the name of a sync object in the GL share group associated with
+<em>context</em>.</p>
+</div>
+<div class="paragraph">
+<p><strong>clCreateEventFromGLsyncKHR</strong> returns a valid OpenCL event object and
+<em>errcode_ret</em> is set to CL_SUCCESS if the event object is created
+successfully.
+Otherwise, it returns a <code>NULL</code> value with one of the following error values
+returned in <em>errcode_ret</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context, or was not
+created from a GL context.</p>
+</li>
+<li>
+<p>CL_INVALID_GL_OBJECT if <em>sync</em> is not the name of a sync object in the
+GL share group associated with <em>context</em>.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The parameters of an event object linked to a GL sync object will return the
+following values when queried with <strong>clGetEventInfo</strong>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>The CL_EVENT_COMMAND_QUEUE of a linked event is <code>NULL</code>, because the
+event is not associated with any OpenCL command queue.</p>
+</li>
+<li>
+<p>The CL_EVENT_COMMAND_TYPE of a linked event is
+CL_COMMAND_GL_FENCE_SYNC_OBJECT_KHR, indicating that the event is
+associated with a GL sync object, rather than an OpenCL command.</p>
+</li>
+<li>
+<p>The CL_EVENT_COMMAND_EXECUTION_STATUS of a linked event is either
+CL_SUBMITTED, indicating that the fence command associated with the sync
+object has not yet completed, or CL_COMPLETE, indicating that the fence
+command has completed.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p><strong>clCreateEventFromGLsyncKHR</strong> performs an implicit <strong>clRetainEvent</strong> on the
+returned event object.
+Creating a linked event object also places a reference on the linked GL sync
+object.
+When the event object is deleted, the reference will be removed from the GL
+sync object.</p>
+</div>
+<div class="paragraph">
+<p>Events returned from <strong>clCreateEventFromGLsyncKHR</strong> can be used in the
+<em>event_wait_list</em> argument to <strong>clEnqueueAcquireGLObjects</strong> and CL APIs that
+take a cl_event as an argument but do not enqueue commands.
+Passing such events to any other CL API that enqueues commands will generate
+a CL_INVALID_EVENT error.`"</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_gl_event-additions-to-extension-specification">5.5. Additions to the OpenCL Extension Specification</h3>
+<div class="paragraph">
+<p>Add following the paragraph describing parameter <em>event</em> to
+<strong>clEnqueueAcquireGLObjects</strong>:</p>
+</div>
+<div class="paragraph">
+<p>"`If an OpenGL context is bound to the current thread, then any OpenGL
+commands which</p>
+</div>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>affect or access the contents of a memory object listed in the
+<em>mem_objects</em> list, and</p>
+</li>
+<li>
+<p>were issued on that OpenGL context prior to the call to
+<strong>clEnqueueAcquireGLObjects</strong></p>
+</li>
+</ol>
+</div>
+<div class="paragraph">
+<p>will complete before execution of any OpenCL commands following the
+<strong>clEnqueueAcquireGLObjects</strong> which affect or access any of those memory
+objects.
+If a non-<code>NULL</code> <em>event</em> object is returned, it will report completion only
+after completion of such OpenGL commands.`"</p>
+</div>
+<div class="paragraph">
+<p>Add following the paragraph describing parameter <em>event</em> to
+<strong>clEnqueueReleaseGLObjects</strong>:</p>
+</div>
+<div class="paragraph">
+<p>"`If an OpenGL context is bound to the current thread, then then any OpenGL
+commands which</p>
+</div>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>affect or access the contents of the memory objects listed in the
+<em>mem_objects</em> list, and</p>
+</li>
+<li>
+<p>are issued on that context after the call to <strong>clEnqueueReleaseGLObjects</strong></p>
+</li>
+</ol>
+</div>
+<div class="paragraph">
+<p>will not execute until after execution of any OpenCL commands preceding the</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueReleaseGLObjects</strong> which affect or access any of those memory
+objects.
+If a non-<code>NULL</code> <em>event</em> object is returned, it will report completion before
+execution of such OpenGL commands.`"</p>
+</div>
+<div class="paragraph">
+<p>Replace the second paragraph of
+<a href="#cl_khr_gl_sharing__memobjs-synchronizing-opencl-and-opengl-access-to-shared-objects">Synchronizing OpenCL and OpenGL Access to Shared Objects</a> with:</p>
+</div>
+<div class="paragraph">
+<p>"`Prior to calling <strong>clEnqueueAcquireGLObjects</strong>, the application must ensure
+that any pending OpenGL operations which access the objects specified in
+<em>mem_objects</em> have completed.</p>
+</div>
+<div class="paragraph">
+<p>If the <strong>cl_khr_gl_event</strong> extension is supported, then the OpenCL
+implementation will ensure that any such pending OpenGL operations are
+complete for an OpenGL context bound to the same thread as the OpenCL
+context.
+This is referred to as <em>implicit synchronization</em>.</p>
+</div>
+<div class="paragraph">
+<p>If the <strong>cl_khr_gl_event</strong> extension is supported and the OpenGL context in
+question supports fence sync objects, completion of OpenGL commands may also
+be determined by placing a GL fence command after those commands using
+<strong>glFenceSync</strong>, creating an event from the resulting GL sync object using
+<strong>clCreateEventFromGLsyncKHR</strong>, and determining completion of that event
+object via <strong>clEnqueueAcquireGLObjects</strong>.
+This method may be considerably more efficient than calling <strong>glFinish</strong>, and
+is referred to as <em>explicit synchronization</em>.
+Explicit synchronization is most useful when an OpenGL context bound to
+another thread is accessing the memory objects.</p>
+</div>
+<div class="paragraph">
+<p>If the <strong>cl_khr_gl_event</strong> extension is not supported, completion of OpenGL
+commands may be determined by issuing and waiting for completion of a
+<strong>glFinish</strong> command on all OpenGL contexts with pending references to these
+objects.
+Some implementations may offer other efficient synchronization methods.
+If such methods exist they will be described in platform-specific
+documentation.</p>
+</div>
+<div class="paragraph">
+<p>Note that no synchronization method other than <strong>glFinish</strong> is portable
+between all OpenGL implementations and all OpenCL implementations.
+While this is the only way to ensure completion that is portable to all
+platforms, <strong>glFinish</strong> is an expensive operation and its use should be
+avoided if the <strong>cl_khr_gl_event</strong> extension is supported on a platform.`"</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_gl_event-issues">5.6. Issues</h3>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>How are references between CL events and GL syncs handled?</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>PROPOSED: The linked CL event places a single reference on the GL sync
+object.
+That reference is removed when the CL event is deleted.
+A more expensive alternative would be to reflect changes in the CL event
+reference count through to the GL sync.</p>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p>How are linkages to synchronization primitives in other APIs handled?</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>UNRESOLVED.
+We will at least want to have a way to link events to EGL sync objects.
+There is probably no analogous DX concept.
+There would be an entry point for each type of synchronization primitive to
+be linked to, such as clCreateEventFromEGLSyncKHR.</p>
+</div>
+<div class="paragraph">
+<p>An alternative is a generic clCreateEventFromExternalEvent taking an
+attribute list.
+The attribute list would include information defining the type of the
+external primitive and additional information (GL sync object handle, EGL
+display and sync object handle, etc.) specific to that type.
+This allows a single entry point to be reused.</p>
+</div>
+<div class="paragraph">
+<p>These will probably be separate extensions following the API proposed here.</p>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p>Should the CL_EVENT_COMMAND_TYPE correspond to the type of command
+(fence) or the type of the linked sync object?</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>PROPOSED: To the type of the linked sync object.</p>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p>Should we support both explicit and implicit synchronization?</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>PROPOSED: Yes.
+Implicit synchronization is suitable when GL and CL are executing in the
+same application thread.
+Explicit synchronization is suitable when they are executing in different
+threads but the expense of glFinish is too high.</p>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p>Should this be a platform or device extension?</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>PROPOSED: Platform extension.
+This may result in considerable under-the-hood work to implement the
+sync&#8594;event semantics using only the public GL API, however, when multiple
+drivers and devices with different GL support levels coexist in the same
+runtime.</p>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p>Where can events generated from GL syncs be usable?</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>PROPOSED: Only with clEnqueueAcquireGLObjects, and attempting to use such an
+event elsewhere will generate an error.
+There is no apparent use case for using such events elsewhere, and possibly
+some cost to supporting it, balanced by the cost of checking the source of
+events in all other commands accepting them as parameters.</p>
+</div>
+</div>
+</div>
+</li>
+</ol>
+</div>
+<div style="page-break-after: always;"></div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="cl_khr_dx9_media_sharing">6. Creating OpenCL Memory Objects from DirectX 9 Media Surfaces</h2>
+<div class="sectionbody">
+<div class="sect2">
+<h3 id="cl_khr_dx9_media_sharing-overview">6.1. Overview</h3>
+<div class="paragraph">
+<p>This section describes the <strong>cl_khr_dx9_media_sharing</strong> extension.
+The goal of this extension is to allow applications to use media surfaces as
+OpenCL memory objects.
+This allows efficient sharing of data between OpenCL and selected adapter
+APIs (only DX9 for now).
+If this extension is supported, an OpenCL image object can be created from a
+media surface and the OpenCL API can be used to execute kernels that read
+and/or write memory objects that are media surfaces.
+Note that OpenCL memory objects may be created from the adapter media
+surface if and only if the OpenCL context has been created from that
+adapter.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_dx9_media_sharing-new-procedures-and-functions">6.2. New Procedures and Functions</h3>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_int clGetDeviceIDsFromDX9MediaAdapterKHR(
+                                    cl_platform_id platform,
+                                    cl_uint num_media_adapters,
+                                    cl_dx9_media_adapter_type_khr *media_adapters_type,
+                                    void *media_adapters,
+                                    cl_dx9_media_adapter_set_khr media_adapter_set,
+                                    cl_uint num_entries,
+                                    cl_device_id *devices,
+                                    cl_int *num_devices)
+
+cl_mem clCreateFromDX9MediaSurfaceKHR(cl_context context,
+                                      cl_mem_flags flags,
+                                      cl_dx9_media_adapter_type_khr adapter_type,
+                                      void *surface_info,
+                                      cl_uint plane,
+                                      cl_int *errcode_ret)
+
+cl_int clEnqueueAcquireDX9MediaSurfacesKHR(cl_command_queue command_queue,
+                                           cl_uint num_objects,
+                                           const cl_mem *mem_objects,
+                                           cl_uint num_events_in_wait_list,
+                                           const cl_event *event_wait_list,
+                                           cl_event *event)
+
+cl_int clEnqueueReleaseDX9MediaSurfacesKHR(cl_command_queue command_queue,
+                                           cl_uint num_objects,
+                                           const cl_mem *mem_objects,
+                                           cl_uint num_events_in_wait_list,
+                                           const cl_event *event_wait_list,
+                                           cl_event *event)</code></pre>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_dx9_media_sharing-new-tokens">6.3. New Tokens</h3>
+<div class="paragraph">
+<p>Accepted by the <em>media_adapter_type</em> parameter of
+<strong>clGetDeviceIDsFromDX9MediaAdapterKHR</strong>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_ADAPTER_D3D9_KHR         0x2020
+CL_ADAPTER_D3D9EX_KHR       0x2021
+CL_ADAPTER_DXVA_KHR         0x2022</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Accepted by the <em>media_adapter_set</em> parameter of
+<strong>clGetDeviceIDsFromDX9MediaAdapterKHR</strong>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR  0x2023
+CL_ALL_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR        0x2024</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Accepted as a property name in the <em>properties</em> parameter of
+<strong>clCreateContext</strong> and <strong>clCreateContextFromType</strong>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_CONTEXT_ADAPTER_D3D9_KHR     0x2025
+CL_CONTEXT_ADAPTER_D3D9EX_KHR   0x2026
+CL_CONTEXT_ADAPTER_DXVA_KHR     0x2027</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Accepted as the property being queried in the <em>param_name</em> parameter of
+<strong>clGetMemObjectInfo</strong>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_MEM_DX9_MEDIA_ADAPTER_TYPE_KHR   0x2028
+CL_MEM_DX9_MEDIA_SURFACE_INFO_KHR   0x2029</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Accepted as the property being queried in the <em>param_name</em> parameter of
+<strong>clGetImageInfo</strong>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_IMAGE_DX9_MEDIA_PLANE_KHR    0x202A</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returned in the <em>param_value</em> parameter of <strong>clGetEventInfo</strong> when
+<em>param_name</em> is CL_EVENT_COMMAND_TYPE:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_COMMAND_ACQUIRE_DX9_MEDIA_SURFACES_KHR   0x202B
+CL_COMMAND_RELEASE_DX9_MEDIA_SURFACES_KHR   0x202C</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returned by <strong>clCreateContext</strong> and <strong>clCreateContextFromType</strong> if the media
+adapter specified for interoperability is not compatible with the devices
+against which the context is to be created:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_INVALID_DX9_MEDIA_ADAPTER_KHR    -1010</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returned by <strong>clCreateFromDX9MediaSurfaceKHR</strong> when <em>adapter_type</em> is set to a
+media adapter and the <em>surface_info</em> does not reference a media surface of
+the required type, or if <em>adapter_type</em> is set to a media adapter type and
+<em>surface_info</em> does not contain a valid reference to a media surface on that
+adapter, by <strong>clGetMemObjectInfo</strong> when <em>param_name</em> is a surface or handle
+when the image was not created from an appropriate media surface, and from
+<strong>clGetImageInfo</strong> when <em>param_name</em> is CL IMAGE_DX9_MEDIA_PLANE KHR and image
+was not created from an appropriate media surface.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_INVALID_DX9_MEDIA_SURFACE_KHR    -1011</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returned by <strong>clEnqueueAcquireDX9MediaSurfacesKHR</strong> when any of <em>mem_objects</em>
+are currently acquired by OpenCL</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_DX9_MEDIA_SURFACE_ALREADY_ACQUIRED_KHR   -1012</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returned by <strong>clEnqueueReleaseDX9MediaSurfacesKHR</strong> when any of <em>mem_objects</em>
+are not currently acquired by OpenCL</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_DX9_MEDIA_SURFACE_NOT_ACQUIRED_KHR   -1013</pre>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_dx9_media_sharing-additions-to-chapter-4">6.4. Additions to Chapter 4 of the OpenCL 2.2 Specification</h3>
+<div class="paragraph">
+<p>In <em>section 4.4</em>, replace the description of <em>properties</em> under
+<strong>clCreateContext</strong> with:</p>
+</div>
+<div class="paragraph">
+<p>&#8220;_properties_ specifies a list of context property names and their
+corresponding values.
+Each property is followed immediately by the corresponding desired value.
+The list is terminated with zero.
+If a property is not specified in <em>properties</em>, then its default value
+(listed in <em>table 4.5</em>) is used (it is said to be specified implicitly).
+If <em>properties</em> is <code>NULL</code> or empty (points to a list whose first value is
+zero), all attributes take on their default values.&#8221;</p>
+</div>
+<div class="paragraph">
+<p>Add the following to <em>table 4.5</em>:</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 33.3333%;">
+<col style="width: 33.3333%;">
+<col style="width: 33.3334%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_context_properties enum</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Property value</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_CONTEXT_ADAPTER_D3D9_KHR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">IDirect3DDevice9 *</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Specifies an IDirect3DDevice9 to use for D3D9 interop.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_CONTEXT_ADAPTER_D3D9EX_KHR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">IDirect3DDeviceEx*</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Specifies an IDirect3DDevice9Ex to use for D3D9 interop.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_CONTEXT_ADAPTER_DXVA_KHR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">IDXVAHD_Device *</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Specifies an IDXVAHD_Device to use for DXVA interop.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>Add to the list of errors for <strong>clCreateContext</strong>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_ADAPTER_KHR if any of the values of the properties
+CL_CONTEXT_ADAPTER_D3D9_KHR, CL_CONTEXT_ADAPTER_D3D9EX_KHR or
+CL_CONTEXT_ADAPTER_DXVA_KHR is non-<code>NULL</code> and does not specify a valid
+media adapter with which the <em>cl_device_ids</em> against which this context
+is to be created may interoperate.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Add to the list of errors for <strong>clCreateContextFromType</strong> the same new errors
+described above for <strong>clCreateContext</strong>.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_dx9_media_sharing-additions-to-chapter-5">6.5. Additions to Chapter 5 of the OpenCL 2.2 Specification</h3>
+<div class="paragraph">
+<p>Add to the list of errors for <strong>clGetMemObjectInfo</strong>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_DX9_MEDIA_SURFACE_KHR if <em>param_name</em> is
+CL_MEM_DX9_MEDIA_SURFACE_INFO_KHR and <em>memobj</em> was not created by the
+function <strong>clCreateFromDX9MediaSurfaceKHR</strong> from a Direct3D9 surface.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Extend <em>table 5.12</em> to include the following entry:</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 33.3333%;">
+<col style="width: 33.3333%;">
+<col style="width: 33.3334%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_mem_info</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Return type</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Info. returned in <em>param_value</em></strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_DX9_MEDIA_ADAPTER_TYPE_KHR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cl_dx9_media_adapter_type_khr</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the <em>cl_dx9_media_adapter_type_khr</em> argument value specified when
+  <em>memobj</em> is created using <strong>clCreateFromDX9MediaSurfaceKHR</strong>.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_DX9_MEDIA_SURFACE_INFO_KHR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cl_dx9_surface_info_khr</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the <em>cl_dx9_surface_info_khr</em> argument value specified when
+  <em>memobj</em> is created using <strong>clCreateFromDX9MediaSurfaceKHR</strong>.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>Add to the list of errors for <strong>clGetImageInfo</strong>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_DX9_MEDIA_SURFACE_KHR if <em>param_name</em> is
+CL_IMAGE_DX9_MEDIA_PLANE_KHR and <em>image</em> was not created by the function
+<strong>clCreateFromDX9MediaSurfaceKHR</strong>.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Extend <em>table 5.9</em> to include the following entry.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 33.3333%;">
+<col style="width: 33.3333%;">
+<col style="width: 33.3334%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_image_info</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Return type</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Info. returned in <em>param_value</em></strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_IMAGE_DX9_MEDIA_PLANE_KHR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cl_uint</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the <em>plane</em> argument value specified when <em>memobj</em> is created
+  using <strong>clCreateFromDX9MediaSurfaceKHR</strong>.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>Add to <em>table 5.22</em> in the <strong>Info returned in param_value</strong> column for
+<em>cl_event_info</em> = CL_EVENT_COMMAND_TYPE:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_COMMAND_ACQUIRE_DX9_MEDIA_SURFACES_KHR
+CL_COMMAND_RELEASE_DX9_MEDIA_SURFACES_KHR</pre>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_dx9_media_sharing-sharing-media-surfaces-with-opencl">6.6. Sharing Media Surfaces with OpenCL</h3>
+<div class="paragraph">
+<p>This section discusses OpenCL functions that allow applications to use media
+surfaces as OpenCL memory objects.
+This allows efficient sharing of data between OpenCL and media surface APIs.
+The OpenCL API may be used to execute kernels that read and/or write memory
+objects that are also media surfaces.
+An OpenCL image object may be created from a media surface.
+OpenCL memory objects may be created from media surfaces if and only if the
+OpenCL context has been created from a media adapter.</p>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_dx9_media_sharing-querying-opencl-devices-corresponding-to-media-adapters">6.6.1. Querying OpenCL Devices corresponding to Media Adapters</h4>
+<div class="paragraph">
+<p>Media adapters are an abstraction associated with devices that provide media
+capabilities.</p>
+</div>
+<div class="paragraph">
+<p>The function
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_int clGetDeviceIDsFromDX9MediaAdapterKHR(
+                                    cl_platform_id platform,
+                                    cl_uint num_media_adapters,
+                                    cl_dx9_media_adapter_type_khr *media_adapters_type,
+                                    void *media_adapters,
+                                    cl_dx9_media_adapter_set_khr media_adapter_set,
+                                    cl_uint num_entries,
+                                    cl_device_id *devices,
+                                    cl_int *num_devices)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>queries a media adapter for any associated OpenCL devices.
+Adapters with associated OpenCL devices can enable media surface sharing
+between the two.</p>
+</div>
+<div class="paragraph">
+<p><em>platform</em> refers to the platform ID returned by <strong>clGetPlatformIDs</strong>.</p>
+</div>
+<div class="paragraph">
+<p><em>num_media_adapters</em> specifies the number of media adapters.</p>
+</div>
+<div class="paragraph">
+<p><em>media_adapters_type</em> is an array of <em>num_media_adapters</em> entries.
+Each entry specifies the type of media adapter and must be one of the values
+described in the table below.</p>
+</div>
+<table id="cl_khr_dx9_media_sharing-media-adapter-types" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 15. <em>cl_dx9_media_adapter_type_khr values</em></caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_dx9_media_adapter_type_khr</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Type of media adapters</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_ADAPTER_D3D9_KHR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">IDirect3DDevice9 *</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_ADAPTER_D3D9EX_KHR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">IDirect3DDevice9Ex *</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_ADAPTER_DXVA_KHR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">IDXVAHD_Device *</p></td>
+</tr>
+</tbody>
+</table>
+<table id="cl_khr_dx9_media_sharing-media-adapter-sets" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 16. <em>cl_dx9_media_adapter_set_khr values</em></caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_dx9_media_adapter_set_khr</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The preferred OpenCL devices associated with the media adapter.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_ALL_DEVICES_FOR_MEDIA_DX9_ADAPTER_KHR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">All OpenCL devices that may interoperate with the media adapter</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p><em>media_adapters</em> is an array of <em>num_media_adapters</em> entries.
+Each entry specifies the actual adapter whose type is specified by
+<em>media_adapter_type</em>.
+The <em>media_adapters</em> must be one of the types described in the table
+<a href="#cl_khr_dx9_media_sharing-media-adapter-types"><em>cl_dx9_media_adapter_type_khr
+values</em></a>.
+<em>media_adapter_set</em> specifies the set of adapters to return and must be one
+of the values described in the table
+&lt;&lt;[[cl_khr_dx9_media_sharing-media-adapter-sets,<em>cl_dx9_media_adapter_set_khr
+values</em>&gt;&gt;.</p>
+</div>
+<div class="paragraph">
+<p><em>num_entries</em> is the number of cl_device_id entries that can be added to
+<em>devices</em>.
+If <em>devices</em> is not <code>NULL</code>, the <em>num_entries</em> must be greater than zero.</p>
+</div>
+<div class="paragraph">
+<p><em>devices</em> returns a list of OpenCL devices found that support the list of
+media adapters specified.
+The cl_device_id values returned in <em>devices</em> can be used to identify a
+specific OpenCL device.
+If <em>devices</em> argument is <code>NULL</code>, this argument is ignored.
+The number of OpenCL devices returned is the minimum of the value specified
+by <em>num_entries</em> or the number of OpenCL devices whose type matches
+<em>device_type</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>num_devices</em> returns the number of OpenCL devices.
+If <em>num_devices</em> is <code>NULL</code>, this argument is ignored.</p>
+</div>
+<div class="paragraph">
+<p><strong>clGetDeviceIDsFromDX9MediaAdapterKHR</strong> returns CL_SUCCESS if the function is
+executed successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_PLATFORM if <em>platform</em> is not a valid platform.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>num_media_adapters</em> is zero or if
+<em>media_adapters_type</em> is <code>NULL</code> or if <em>media_adapters</em> is <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if any of the entries in <em>media_adapters_type</em> or
+<em>media_adapters</em> is not a valid value.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>media_adapter_set</em> is not a valid value.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>num_entries</em> is equal to zero and <em>devices</em> is not
+<code>NULL</code> or if both <em>num_devices</em> and <em>devices</em> are <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_DEVICE_NOT_FOUND if no OpenCL devices that correspond to adapters
+specified in <em>media_adapters</em> and <em>media_adapters_type</em> were found.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_dx9_media_sharing-creating-media-resources-as-opencl-image-objects">6.6.2. Creating Media Resources as OpenCL Image Objects</h4>
+<div class="paragraph">
+<p>The function
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_mem clCreateFromDX9MediaSurfaceKHR(cl_context context,
+                                      cl_mem_flags flags,
+                                      cl_dx9_media_adapter_type_khr adapter_type,
+                                      void *surface_info,
+                                      cl_uint plane,
+                                      cl_int *errcode_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>creates an OpenCL image object from a media surface.</p>
+</div>
+<div class="paragraph">
+<p><em>context</em> is a valid OpenCL context created from a media adapter.</p>
+</div>
+<div class="paragraph">
+<p>flags is a bit-field that is used to specify usage information.
+Refer to <em>table 5.3</em> for a description of flags.
+Only CL_MEM_READ_ONLY, CL_MEM_WRITE_ONLY and CL_MEM_READ_WRITE values
+specified in <em>table 5.3</em> can be used.</p>
+</div>
+<div class="paragraph">
+<p><em>adapter_type</em> is a value from enumeration of supported adapters described
+in the table
+<a href="#cl_khr_dx9_media_sharing-media-adapter-types"><em>cl_dx9_media_adapter_type_khr
+values</em></a>.
+The type of <em>surface_info</em> is determined by the adapter type.
+The implementation does not need to support all adapter types.
+This approach provides flexibility to support additional adapter types in
+the future.
+Supported adapter types are CL_ADAPTER_D3D9_KHR, CL_ADAPTER_D3D9EX_KHR and
+CL_ADAPTER_DXVA_KHR.</p>
+</div>
+<div class="paragraph">
+<p>If <em>adapter_type</em> is CL_ADAPTER_D3D9_KHR, CL_ADAPTER_D3D9EX_KHR and
+CL_ADAPTER_DXVA_KHR, the <em>surface_info</em> points to the following structure:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>typedef struct _cl_dx9_surface_info_khr
+{
+    IDirect3DSurface9 *resource;
+    HANDLE shared_handle;
+} cl_dx9_surface_info_khr;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>For DX9 surfaces, we need both the handle to the resource and the resource
+itself to have a sufficient amount of information to eliminate a copy of the
+surface for sharing in cases where this is possible.
+Elimination of the copy is driver dependent.
+<em>shared_handle</em> may be <code>NULL</code> and this may result in sub-optimal
+performance.</p>
+</div>
+<div class="paragraph">
+<p><em>surface_info</em> is a pointer to one of the structures defined in the
+<em>adapter_type</em> description above passed in as a void *.</p>
+</div>
+<div class="paragraph">
+<p><em>plane</em> is the plane of resource to share for planar surface formats.
+For planar formats, we use the plane parameter to obtain a handle to thie
+specific plane (Y, U or V for example).
+For non-planar formats used by media, <em>plane</em> must be 0.</p>
+</div>
+<div class="paragraph">
+<p><em>errcode_ret</em> will return an appropriate error code.
+If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p>
+</div>
+<div class="paragraph">
+<p><strong>clCreateFromDX9MediaSurfaceKHR</strong> returns a valid non-zero 2D image object
+and <em>errcode_ret</em> is set to CL_SUCCESS if the 2D image object is created
+successfully.
+Otherwise it returns a <code>NULL</code> value with one of the following error values
+returned in <em>errcode_ret</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if values specified in <em>flags</em> are not valid or if
+<em>plane</em> is not a valid plane of <em>resource</em> specified in <em>surface_info</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_DX9_MEDIA_SURFACE_KHR if <em>resource</em> specified in
+<em>surface_info</em> is not a valid resource or is not associated with
+<em>adapter_type</em> (e.g., <em>adapter_type</em> is set to CL_ADAPTER_D3D9_KHR and
+<em>resource</em> is not a Direct3D 9 surface created in D3DPOOL_DEFAULT).</p>
+</li>
+<li>
+<p>CL_INVALID_DX9_MEDIA_SURFACE_KHR if <em>shared_handle</em> specified in
+<em>surface_info</em> is not <code>NULL</code> or a valid handle value.</p>
+</li>
+<li>
+<p>CL_INVALID_IMAGE_FORMAT_DESCRIPTOR if the texture format of <em>resource</em>
+is not listed in <a href="#cl_khr_dx9_media_sharing-fourcc-image-formats"><em>YUV
+FourCC codes and corresponding OpenCL image format</em></a> or
+<a href="#cl_khr_dx9_media_sharing-d3d-image-formats"><em>Direct3D formats and
+corresponding OpenCL image formats</em></a>.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if there are no devices in <em>context</em> that support
+<em>adapter_type</em>.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The width and height of the returned OpenCL 2D image object are determined
+by the width and height of the plane of resource.
+The channel type and order of the returned image object is determined by the
+format and plane of resource and are described in the table
+<a href="#cl_khr_dx9_media_sharing-fourcc-image-formats"><em>YUV FourCC codes and
+corresponding OpenCL image format</em></a> or
+<a href="#cl_khr_dx9_media_sharing-d3d-image-formats"><em>Direct3D formats and
+corresponding OpenCL image formats</em></a>.</p>
+</div>
+<div class="paragraph">
+<p>This call will increment the internal media surface count on <em>resource</em>.
+The internal media surface reference count on <em>resource</em> will be decremented
+when the OpenCL reference count on the returned OpenCL memory object drops
+to zero.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_dx9_media_sharing-querying-media-surface-properties-of-memory-objects-created-from-media-surfaces">6.6.3. Querying Media Surface Properties of Memory Objects created from Media Surfaces</h4>
+<div class="paragraph">
+<p>Properties of media surface objects may be queried using
+<strong>clGetMemObjectInfo</strong> and <strong>clGetImageInfo</strong> with <em>param_name</em>
+CL_MEM_DX9_MEDIA_ADAPTER_TYPE_KHR, CL_MEM_DX9_MEDIA_SURFACE_INFO_KHR and
+CL_IMAGE_DX9_MEDIA_PLANE_KHR as described in <em>sections 5.4.3</em> and <em>5.3.6</em>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_dx9_media_sharing-sharing-memory-objects-created-from-media-surfaces-between-a-media-adapter-and-opencl">6.6.4. Sharing Memory Objects created from Media Surfaces between a Media Adapter and OpenCL</h4>
+<div class="paragraph">
+<p>The function
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_int clEnqueueAcquireDX9MediaSurfacesKHR(cl_command_queue command_queue,
+                                           cl_uint num_objects,
+                                           const cl_mem *mem_objects,
+                                           cl_uint num_events_in_wait_list,
+                                           const cl_event *event_wait_list,
+                                           cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>is used to acquire OpenCL memory objects that have been created from a media
+surface.
+The media surfaces are acquired by the OpenCL context associated with
+<em>command_queue</em> and can therefore be used by all command-queues associated
+with the OpenCL context.</p>
+</div>
+<div class="paragraph">
+<p>OpenCL memory objects created from media surfaces must be acquired before
+they can be used by any OpenCL commands queued to a command-queue.
+If an OpenCL memory object created from a media surface is used while it is
+not currently acquired by OpenCL, the call attempting to use that OpenCL
+memory object will return CL_DX9_MEDIA_SURFACE_NOT_ACQUIRED_KHR.</p>
+</div>
+<div class="paragraph">
+<p>If CL_CONTEXT_INTEROP_USER_SYNC is not specified as CL_TRUE during context
+creation, <strong>clEnqueueAcquireDX9MediaSurfacesKHR</strong> provides the synchronization
+guarantee that any media adapter API calls involving the interop device(s)
+used in the OpenCL context made before <strong>clEnqueueAcquireDX9MediaSurfacesKHR</strong>
+is called will complete executing before <em>event</em> reports completion and
+before the execution of any subsequent OpenCL work issued in <em>command_queue</em>
+begins.
+If the context was created with properties specifying
+CL_CONTEXT_INTEROP_USER_SYNC as CL_TRUE, the user is responsible for
+guaranteeing that any media adapter API calls involving the interop
+device(s) used in the OpenCL context made before
+<strong>clEnqueueAcquireDX9MediaSurfacesKHR</strong> is called have completed before
+calling <strong>clEnqueueAcquireDX9MediaSurfacesKHR</strong> <strong>.</strong></p>
+</div>
+<div class="paragraph">
+<p><em>command_queue</em> is a valid command-queue.</p>
+</div>
+<div class="paragraph">
+<p><em>num_objects</em> is the number of memory objects to be acquired in
+<em>mem_objects</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>mem_objects</em> is a pointer to a list of OpenCL memory objects that were
+created from media surfaces.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before this particular command can be executed.
+If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait
+on any event to complete.
+If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event_wait_list</em> act as synchronization points.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> returns an event object that identifies this particular command and
+can be used to query or queue a wait for this particular command to
+complete.
+<em>event</em> can be <code>NULL</code> in which case it will not be possible for the
+application to query the status of this command or queue a wait for this
+command to complete.
+If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the
+<em>event</em> argument should not refer to an element of the <em>event_wait_list</em>
+array.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueAcquireDX9MediaSurfacesKHR</strong> returns CL_SUCCESS if the function is
+executed successfully.
+If <em>num_objects</em> is 0 and <em>mem_objects</em> is <code>NULL</code> then the function does
+nothing and returns CL_SUCCESS.
+Otherwise it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_VALUE if <em>num_objects</em> is zero and <em>mem_objects</em> is not a
+<code>NULL</code> value or if <em>num_objects</em> &gt; 0 and <em>mem_objects</em> is <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_MEM_OBJECT if memory objects in <em>mem_objects</em> are not valid
+OpenCL memory objects or if memory objects in <em>mem_objects</em> have not
+been created from media surfaces.</p>
+</li>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if context associated with <em>command_queue</em> was not
+created from a device that can share the media surface referenced by
+<em>mem_objects</em>.</p>
+</li>
+<li>
+<p>CL_DX9_MEDIA_SURFACE_ALREADY_ACQUIRED_KHR if memory objects in
+<em>mem_objects</em> have previously been acquired using
+<strong>clEnqueueAcquireDX9MediaSurfacesKHR</strong> but have not been released using
+<strong>clEnqueueReleaseDX9MediaSurfacesKHR</strong>.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_int clEnqueueReleaseDX9MediaSurfacesKHR(cl_command_queue command_queue,
+                                           cl_uint num_objects,
+                                           const cl_mem *mem_objects,
+                                           cl_uint num_events_in_wait_list,
+                                           const cl_event *event_wait_list,
+                                           cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>is used to release OpenCL memory objects that have been created from media
+surfaces.
+The media surfaces are released by the OpenCL context associated with
+<em>command_queue</em>.</p>
+</div>
+<div class="paragraph">
+<p>OpenCL memory objects created from media surfaces which have been acquired
+by OpenCL must be released by OpenCL before they may be accessed by the
+media adapter API.
+Accessing a media surface while its corresponding OpenCL memory object is
+acquired is in error and will result in undefined behavior, including but
+not limited to possible OpenCL errors, data corruption, and program
+termination.</p>
+</div>
+<div class="paragraph">
+<p>If CL_CONTEXT_INTEROP_USER_SYNC is not specified as CL_TRUE during context
+creation, <strong>clEnqueueReleaseDX9MediaSurfacesKHR</strong> provides the synchronization
+guarantee that any calls to media adapter APIs involving the interop
+device(s) used in the OpenCL context made after the call to
+<strong>clEnqueueReleaseDX9MediaSurfacesKHR</strong> will not start executing until after
+all events in <em>event_wait_list</em> are complete and all work already submitted
+to <em>command_queue</em> completes execution.
+If the context was created with properties specifying
+CL_CONTEXT_INTEROP_USER_SYNC as CL_TRUE, the user is responsible for
+guaranteeing that any media adapter API calls involving the interop
+device(s) used in the OpenCL context made after
+<strong>clEnqueueReleaseDX9MediaSurfacesKHR</strong> will not start executing until after
+event returned by <strong>clEnqueueReleaseDX9MediaSurfacesKHR</strong> reports completion.</p>
+</div>
+<div class="paragraph">
+<p><em>num_objects</em> is the number of memory objects to be released in
+<em>mem_objects</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>mem_objects</em> is a pointer to a list of OpenCL memory objects that were
+created from media surfaces.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before this particular command can be executed.
+If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait
+on any event to complete.
+If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event</em> returns an event object that identifies this
+particular command and can be used to query or queue a wait for this
+particular command to complete.
+<em>event</em> can be <code>NULL</code> in which case it will not be possible for the
+application to query the status of this command or queue a wait for this
+command to complete.
+If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the
+<em>event</em> argument should not refer to an element of the <em>event_wait_list</em>
+array.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueReleaseDX9MediaSurfaceKHR</strong> returns CL_SUCCESS if the function is
+executed successfully.
+If <em>num_objects</em> is 0 and &lt;<em>mem_objects</em>&gt; is <code>NULL</code> the function does
+nothing and returns CL_SUCCESS.
+Otherwise it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_VALUE if <em>num_objects</em> is zero and <em>mem_objects</em> is not a
+<code>NULL</code> value or if <em>num_objects</em> &gt; 0 and <em>mem_objects</em> is <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_MEM_OBJECT if memory objects in <em>mem_objects</em> are not valid
+OpenCL memory objects or if memory objects in <em>mem_objects</em> have not
+been created from valid media surfaces.</p>
+</li>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if context associated with <em>command_queue</em> was not
+created from a media object.</p>
+</li>
+<li>
+<p>CL_DX9_MEDIA_SURFACE_NOT_ACQUIRED_KHR if memory objects in <em>mem_objects</em>
+have not previously been acquired using
+<strong>clEnqueueAcquireDX9MediaSurfacesKHR</strong>, or have been released using
+<strong>clEnqueueReleaseDX9MediaSurfacesKHR</strong> since the last time that they were
+acquired.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em>&gt; is 0, or if event objects in
+<em>event_wait_list</em> are not valid events.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_dx9_media_sharing-surface-formats-for-media-surface-sharing">6.6.5. Surface formats for Media Surface Sharing</h4>
+<div class="paragraph">
+<p>This section includes the D3D surface formats that are supported when the
+adapter type is one of the Direct 3D lineage .
+Using a D3D surface format not listed here is an error.
+To extend the use of this extension to support media adapters beyond
+DirectX9 tables similar to the ones in this section will need to be defined
+for the surface formats supported by the new media adapter.
+All implementations that support this extension are required to support the
+NV12 surface format, the other surface formats supported are the same
+surface formats that the adapter you are sharing with supports as long as
+they are listed in the table
+<a href="#cl_khr_dx9_media_sharing-fourcc-image-formats"><em>YUV FourCC codes and
+corresponding OpenCL image format</em></a> or in the table
+<a href="#cl_khr_dx9_media_sharing-d3d-image-formats"><em>Direct3D formats and
+corresponding OpenCL image formats</em></a>.</p>
+</div>
+<table id="cl_khr_dx9_media_sharing-fourcc-image-formats" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 17. <em>YUV FourCC codes and corresponding OpenCL image format</em></caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>FOUR CC code</strong></th>
+<th class="tableblock halign-left valign-top"><strong>CL image format</strong>
+
+<strong>(channel order, channel data type)</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">FOURCC('N','V','1','2'), Plane 0</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_UNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">FOURCC('N','V','1','2'), Plane 1</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_UNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">FOURCC('Y','V','1','2'), Plane 0</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_UNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">FOURCC('Y','V','1','2'), Plane 1</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_UNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">FOURCC('Y','V','1','2'), Plane 2</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_UNORM_INT8</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>In the table <a href="#cl_khr_dx9_media_sharing-fourcc-image-formats"><em>YUV FourCC
+codes and corresponding OpenCL image format</em></a> above, NV12 Plane 0
+corresponds to the luminance (Y) channel and Plane 1 corresponds to the UV
+channels.
+The YV12 Plane 0 corresponds to the Y channel, Plane 1 corresponds to the V
+channel and Plane 2 corresponds to the U channel.
+Note that the YUV formats map to CL_R and CL_RG but do not perform any YUV
+to RGB conversion and vice-versa.</p>
+</div>
+<table id="cl_khr_dx9_media_sharing-d3d-image-formats" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 18. <em>Direct3D formats and corresponding OpenCL image formats</em></caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>D3D format</strong></th>
+<th class="tableblock halign-left valign-top"><strong>CL image format</strong><br>
+<strong>(channel order, channel data type)</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">D3DFMT_R32F</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_FLOAT</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">D3DFMT_R16F</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_HALF_FLOAT</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">D3DFMT_L16</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_UNORM_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">D3DFMT_A8</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_A, CL_UNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">D3DFMT_L8</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_UNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">D3DFMT_G32R32F</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_FLOAT</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">D3DFMT_G16R16F</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_HALF_FLOAT</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">D3DFMT_G16R16</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_UNORM_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">D3DFMT_A8L8</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_UNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">D3DFMT_A32B32G32R32F</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_FLOAT</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">D3DFMT_A16B16G16R16F</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_HALF_FLOAT</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">D3DFMT_A16B16G16R16</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_UNORM_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">D3DFMT_A8B8G8R8</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_UNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">D3DFMT_X8B8G8R8</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_UNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">D3DFMT_A8R8G8B8</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_BGRA, CL_UNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">D3DFMT_X8R8G8B8</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_BGRA, CL_UNORM_INT8</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>Note: The D3D9 format names in the table above seem to imply that the
+order of the color channels are switched relative to OpenCL but this is
+not the case.
+For example, the layout of channels for each pixel for D3DFMT_A32FB32FG32FR32F
+is the same as CL_RGBA, CL_FLOAT.</p>
+</div>
+<div style="page-break-after: always;"></div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="cl_khr_d3d10_sharing">7. Creating OpenCL Memory Objects from Direct3D 10 Buffers and Textures</h2>
+<div class="sectionbody">
+<div class="sect2">
+<h3 id="cl_khr_d3d10_sharing-overview">7.1. Overview</h3>
+<div class="paragraph">
+<p>This section describes the <strong>cl_khr_d3d10_sharing</strong> extension.
+The goal of this extension is to provide interoperability between OpenCL and
+Direct3D 10.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_d3d10_sharing-new-procedures-and-functions">7.2. New Procedures and Functions</h3>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_int clGetDeviceIDsFromD3D10KHR(cl_platform_id platform,
+                                  cl_d3d10_device_source_khr d3d_device_source,
+                                  void *d3d_object,
+                                  cl_d3d10_device_set_khr d3d_device_set,
+                                  cl_uint num_entries,
+                                  cl_device_id *devices,
+                                  cl_uint *num_devices)
+
+cl_mem clCreateFromD3D10BufferKHR(cl_context context,
+                                  cl_mem_flags flags,
+                                  ID3D10Buffer *resource,
+                                  cl_int *errcode_ret)
+
+cl_mem clCreateFromD3D10Texture2DKHR(cl_context context,
+                                     cl_mem_flags flags,
+                                     ID3D10Texture2D *resource,
+                                     UINT subresource,
+                                     cl_int *errcode_ret)
+
+cl_mem clCreateFromD3D10Texture3DKHR(cl_context context,
+                                     cl_mem_flags flags,
+                                     ID3D10Texture3D *resource,
+                                     UINT subresource,
+                                     cl_int *errcode_ret)
+
+cl_int clEnqueueAcquireD3D10ObjectsKHR(cl_command_queue command_queue,
+                                       cl_uint num_objects,
+                                       const cl_mem *mem_objects,
+                                       cl_uint num_events_in_wait_list,
+                                       const cl_event *event_wait_list,
+                                       cl_event *event)
+
+cl_int clEnqueueReleaseD3D10ObjectsKHR(cl_command_queue command_queue,
+                                       cl_uint num_objects,
+                                       const cl_mem *mem_objects,
+                                       cl_uint num_events_in_wait_list,
+                                       const cl_event *event_wait_list,
+                                       cl_event *event)</code></pre>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_d3d10_sharing-new-tokens">7.3. New Tokens</h3>
+<div class="paragraph">
+<p>Accepted as a Direct3D 10 device source in the <em>d3d_device_source</em> parameter
+of <strong>clGetDeviceIDsFromD3D10KHR</strong>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_D3D10_DEVICE_KHR                 0x4010
+CL_D3D10_DXGI_ADAPTER_KHR           0x4011</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Accepted as a set of Direct3D 10 devices in the <em>d3d_device_set</em> parameter
+of <strong>clGetDeviceIDsFromD3D10KHR</strong>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_PREFERRED_DEVICES_FOR_D3D10_KHR  0x4012
+CL_ALL_DEVICES_FOR_D3D10_KHR        0x4013</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Accepted as a property name in the <em>properties</em> parameter of
+<strong>clCreateContext</strong> and <strong>clCreateContextFromType</strong>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_CONTEXT_D3D10_DEVICE_KHR         0x4014</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Accepted as a property name in the <em>param_name</em> parameter of
+<strong>clGetContextInfo</strong>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_CONTEXT_D3D10_PREFER_SHARED_RESOURCES_KHR    0x402C</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Accepted as the property being queried in the <em>param_name</em> parameter of
+<strong>clGetMemObjectInfo</strong>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_MEM_D3D10_RESOURCE_KHR           0x4015</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Accepted as the property being queried in the <em>param_name</em> parameter of
+<strong>clGetImageInfo</strong>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_IMAGE_D3D10_SUBRESOURCE_KHR      0x4016</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returned in the <em>param_value</em> parameter of <strong>clGetEventInfo</strong> when
+<em>param_name</em> is CL_EVENT_COMMAND_TYPE:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_COMMAND_ACQUIRE_D3D10_OBJECTS_KHR    0x4017
+CL_COMMAND_RELEASE_D3D10_OBJECTS_KHR    0x4018</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returned by <strong>clCreateContext</strong> and <strong>clCreateContextFromType</strong> if the Direct3D
+10 device specified for interoperability is not compatible with the devices
+against which the context is to be created:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_INVALID_D3D10_DEVICE_KHR         -1002</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returned by <strong>clCreateFromD3D10BufferKHR</strong> when <em>resource</em> is not a Direct3D
+10 buffer object, and by <strong>clCreateFromD3D10Texture2DKHR</strong> and
+<strong>clCreateFromD3D10Texture3DKHR</strong> when <em>resource</em> is not a Direct3D 10 texture
+object:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_INVALID_D3D10_RESOURCE_KHR       -1003</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returned by <strong>clEnqueueAcquireD3D10ObjectsKHR</strong> when any of <em>mem_objects</em> are
+currently acquired by OpenCL:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_D3D10_RESOURCE_ALREADY_ACQUIRED_KHR  -1004</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returned by <strong>clEnqueueReleaseD3D10ObjectsKHR</strong> when any of <em>mem_objects</em> are
+not currently acquired by OpenCL:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_D3D10_RESOURCE_NOT_ACQUIRED_KHR  -1005</pre>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_d3d10_sharing-additions-to-chapter-4">7.4. Additions to Chapter 4 of the OpenCL 2.2 Specification</h3>
+<div class="paragraph">
+<p>In <em>section 4.4</em>, replace the description of <em>properties</em> under
+<strong>clCreateContext</strong> with:</p>
+</div>
+<div class="paragraph">
+<p>&#8220;_properties_ specifies a list of context property names and their
+corresponding values.
+Each property is followed immediately by the corresponding desired value.
+The list is terminated with zero.
+If a property is not specified in <em>properties</em>, then its default value
+(listed in <em>table 4.5</em>) is used (it is said to be specified implicitly).
+If <em>properties</em> is <code>NULL</code> or empty (points to a list whose first value is
+zero), all attributes take on their default values.&#8221;</p>
+</div>
+<div class="paragraph">
+<p>Add the following to <em>table 4.5</em>:</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 40%;">
+<col style="width: 20%;">
+<col style="width: 40%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_context_properties enum</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Property value</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_CONTEXT_D3D10_DEVICE_KHR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">ID3D10Device *</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Specifies the ID3D10Device * to use for Direct3D 10 interoperability.
+  The default value is <code>NULL</code>.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>Add to the list of errors for <strong>clCreateContext</strong>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_D3D10_DEVICE_KHR if the value of the property
+CL_CONTEXT_D3D10_DEVICE_KHR is non-<code>NULL</code> and does not specify a valid
+Direct3D 10 device with which the <em>cl_device_ids</em> against which this
+context is to be created may interoperate.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if Direct3D 10 interoperability is specified by
+setting CL_INVALID_D3D10_DEVICE_KHR to a non-<code>NULL</code> value, and
+interoperability with another graphics API is also specified.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Add to the list of errors for <strong>clCreateContextFromType</strong> the same new errors
+described above for <strong>clCreateContext</strong>.</p>
+</div>
+<div class="paragraph">
+<p>Add the following row to <em>table 4.6</em>:</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 40%;">
+<col style="width: 20%;">
+<col style="width: 40%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_context_info</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Return Type</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Information returned in param_value</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_CONTEXT_D3D10_PREFER_SHARED_RESOURCES_KHR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cl_bool</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns CL_TRUE if Direct3D 10 resources created as shared by setting
+  <em>MiscFlags</em> to include D3D10_RESOURCE_MISC_SHARED will perform faster when
+  shared with OpenCL, compared with resources which have not set this flag.
+  Otherwise returns CL_FALSE.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_d3d10_sharing-additions-to-chapter-5">7.5. Additions to Chapter 5 of the OpenCL 2.2 Specification</h3>
+<div class="paragraph">
+<p>Add to the list of errors for <strong>clGetMemObjectInfo</strong>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_D3D10_RESOURCE_KHR if <em>param_name</em> is
+CL_MEM_D3D10_RESOURCE_KHR and <em>memobj</em> was not created by the function
+<strong>clCreateFromD3D10BufferKHR</strong>, <strong>clCreateFromD3D10Texture2DKHR</strong>, or
+<strong>clCreateFromD3D10Texture3DKHR</strong>.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Extend <em>table 5.12</em> to include the following entry.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 40%;">
+<col style="width: 20%;">
+<col style="width: 40%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_mem_info</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Return type</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Info. returned in <em>param_value</em></strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_D3D10_RESOURCE_KHR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">ID3D10Resource *</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">If <em>memobj</em> was created using <strong>clCreateFromD3D10BufferKHR</strong>,
+  <strong>clCreateFromD3D10Texture2DKHR</strong>, or <strong>clCreateFromD3D10Texture3DKHR</strong>,
+  returns the <em>resource</em> argument specified when <em>memobj</em> was created.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>Add to the list of errors for <strong>clGetImageInfo</strong>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_D3D10_RESOURCE_KHR if <em>param_name</em> is
+CL_MEM_D3D10_SUBRESOURCE_KHR and <em>image</em> was not created by the function
+<strong>clCreateFromD3D10Texture2DKHR</strong>, or <strong>clCreateFromD3D10Texture3DKHR</strong>.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Extend <em>table 5.9</em> to include the following entry.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 40%;">
+<col style="width: 20%;">
+<col style="width: 40%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_image_info</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Return type</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Info. returned in <em>param_value</em></strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_D3D10_SUBRESOURCE_KHR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">UINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">If <em>image</em> was created using <strong>clCreateFromD3D10Texture2DKHR</strong>, or
+  <strong>clCreateFromD3D10Texture3DKHR</strong>, returns the <em>subresource</em> argument
+  specified when <em>image</em> was created.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>Add to <em>table 5.22</em> in the <strong>Info returned in &lt;param_value&gt;</strong> column for
+<em>cl_event_info</em> = CL_EVENT_COMMAND_TYPE:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_COMMAND_ACQUIRE_D3D10_OBJECTS_KHR
+CL_COMMAND_RELEASE_D3D10_OBJECTS_KHR</pre>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_d3d10_sharing-sharing-memory-objects-with-direct3d-10-resources">7.6. Sharing Memory Objects with Direct3D 10 Resources</h3>
+<div class="paragraph">
+<p>This section discusses OpenCL functions that allow applications to use
+Direct3D 10 resources as OpenCL memory objects.
+This allows efficient sharing of data between OpenCL and Direct3D 10.
+The OpenCL API may be used to execute kernels that read and/or write memory
+objects that are also Direct3D 10 resources.
+An OpenCL image object may be created from a Direct3D 10 texture resource.
+An OpenCL buffer object may be created from a Direct3D 10 buffer resource.
+OpenCL memory objects may be created from Direct3D 10 objects if and only if
+the OpenCL context has been created from a Direct3D 10 device.</p>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_d3d10_sharing-querying-opencl-devices-corresponding-to-direct3d-10-devices">7.6.1. Querying OpenCL Devices Corresponding to Direct3D 10 Devices</h4>
+<div class="paragraph">
+<p>The OpenCL devices corresponding to a Direct3D 10 device may be queried.
+The OpenCL devices corresponding to a DXGI adapter may also be queried.
+The OpenCL devices corresponding to a Direct3D 10 device will be a subset of
+the OpenCL devices corresponding to the DXGI adapter against which the
+Direct3D 10 device was created.</p>
+</div>
+<div class="paragraph">
+<p>The OpenCL devices corresponding to a Direct3D 10 device or a DXGI device
+may be queried using the function
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_int clGetDeviceIDsFromD3D10KHR(cl_platform_id platform,
+                                  cl_d3d10_device_source_khr d3d_device_source,
+                                  void *d3d_object,
+                                  cl_d3d10_device_set_khr d3d_device_set,
+                                  cl_uint num_entries,
+                                  cl_device_id *devices,
+                                  cl_uint *num_devices)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><em>platform</em> refers to the platform ID returned by <strong>clGetPlatformIDs</strong>.</p>
+</div>
+<div class="paragraph">
+<p><em>d3d_device_source</em> specifies the type of <em>d3d_object</em>, and must be one of
+the values shown in the table below.</p>
+</div>
+<div class="paragraph">
+<p><em>d3d_object</em> specifies the object whose corresponding OpenCL devices are
+being queried.
+The type of <em>d3d_object</em> must be as specified in the table below.</p>
+</div>
+<div class="paragraph">
+<p><em>d3d_device_set</em> specifies the set of devices to return, and must be one of
+the values shown in the table below.</p>
+</div>
+<div class="paragraph">
+<p><em>num_entries</em> is the number of cl_device_id entries that can be added to
+<em>devices</em>.
+If <em>devices</em> is not <code>NULL</code> then <em>num_entries</em> must be greater than zero.</p>
+</div>
+<div class="paragraph">
+<p><em>devices</em> returns a list of OpenCL devices found.
+The cl_device_id values returned in <em>devices</em> can be used to identify a
+specific OpenCL device.
+If <em>devices</em> is <code>NULL</code>, this argument is ignored.
+The number of OpenCL devices returned is the minimum of the value specified
+by <em>num_entries</em> and the number of OpenCL devices corresponding to
+<em>d3d_object</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>num_devices</em> returns the number of OpenCL devices available that correspond
+to <em>d3d_object</em>.
+If <em>num_devices</em> is <code>NULL</code>, this argument is ignored.</p>
+</div>
+<div class="paragraph">
+<p><strong>clGetDeviceIDsFromD3D10KHR</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise it may return</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_PLATFORM if <em>platform</em> is not a valid platform.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>d3d_device_source</em> is not a valid value,
+<em>d3d_device_set</em> is not a valid value, <em>num_entries</em> is equal to zero
+and <em>devices</em> is not <code>NULL</code>, or if both <em>num_devices</em> and <em>devices</em> are
+<code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_DEVICE_NOT_FOUND if no OpenCL devices that correspond to <em>d3d_object</em>
+were found.</p>
+</li>
+</ul>
+</div>
+<table id="cl_khr_d3d10_sharing-clGetDeviceIDsFromD3D10KHR-object-type" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 19. <em>Direct3D 10 object types that may be used by</em> <strong>clGetDeviceIDsFromD3D10KHR</strong></caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_d3d_device_source_khr</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Type of <em>d3d_object</em></strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_D3D10_DEVICE_KHR</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">ID3D10Device *</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_D3D10_DXGI_ADAPTER_KHR</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">IDXGIAdapter *</p></td>
+</tr>
+</tbody>
+</table>
+<table id="cl_khr_d3d10_sharing-clGetDeviceIDsFromD3D10KHR-devices" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 20. <em>Sets of devices queriable using</em> <strong>clGetDeviceIDsFromD3D10KHR</strong></caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_d3d_device_set_khr</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Devices returned in <em>devices</em></strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_PREFERRED_DEVICES_FOR_D3D10_KHR</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The preferred OpenCL devices associated with the specified Direct3D
+  object.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_ALL_DEVICES_FOR_D3D10_KHR</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">All OpenCL devices which may interoperate with the specified Direct3D
+  object.
+  Performance of sharing data on these devices may be considerably less than
+  on the preferred devices.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_d3d10_sharing-lifetime-of-shared-objects">7.6.2. Lifetime of Shared Objects</h4>
+<div class="paragraph">
+<p>An OpenCL memory object created from a Direct3D 10 resource remains valid as
+long as the corresponding Direct3D 10 resource has not been deleted.
+If the Direct3D 10 resource is deleted through the Direct3D 10 API,
+subsequent use of the OpenCL memory object will result in undefined
+behavior, including but not limited to possible OpenCL errors, data
+corruption, and program termination.</p>
+</div>
+<div class="paragraph">
+<p>The successful creation of a cl_context against a Direct3D 10 device
+specified via the context create parameter CL_CONTEXT_D3D10_DEVICE_KHR will
+increment the internal Direct3D reference count on the specified Direct3D 10
+device.
+The internal Direct3D reference count on that Direct3D 10 device will be
+decremented when the OpenCL reference count on the returned OpenCL context
+drops to zero.</p>
+</div>
+<div class="paragraph">
+<p>The OpenCL context and corresponding command-queues are dependent on the
+existence of the Direct3D 10 device from which the OpenCL context was
+created.
+If the Direct3D 10 device is deleted through the Direct3D 10 API, subsequent
+use of the OpenCL context will result in undefined behavior, including but
+not limited to possible OpenCL errors, data corruption, and program
+termination.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_d3d10_sharing-sharing-direct3d-10-buffer-resources-as-opencl-buffer-objects">7.6.3. Sharing Direct3D 10 Buffer Resources as OpenCL Buffer Objects</h4>
+<div class="paragraph">
+<p>The function
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_mem clCreateFromD3D10BufferKHR(cl_context context,
+                                  cl_mem_flags flags,
+                                  ID3D10Buffer *resource,
+                                  cl_int *errcode_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>creates an OpenCL buffer object from a Direct3D 10 buffer.</p>
+</div>
+<div class="paragraph">
+<p><em>context</em> is a valid OpenCL context created from a Direct3D 10 device.</p>
+</div>
+<div class="paragraph">
+<p><em>flags</em> is a bit-field that is used to specify usage information.
+Refer to <em>table 5.3</em> for a description of <em>flags</em>.
+Only CL_MEM_READ_ONLY, CL_MEM_WRITE_ONLY and CL_MEM_READ_WRITE values
+specified in <em>table 5.3</em> can be used.</p>
+</div>
+<div class="paragraph">
+<p><em>resource</em> is a pointer to the Direct3D 10 buffer to share.</p>
+</div>
+<div class="paragraph">
+<p><em>errcode_ret</em> will return an appropriate error code.
+If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p>
+</div>
+<div class="paragraph">
+<p><strong>clCreateFromD3D10BufferKHR</strong> returns a valid non-zero OpenCL buffer object
+and <em>errcode_ret</em> is set to CL_SUCCESS if the buffer object is created
+successfully.
+Otherwise, it returns a <code>NULL</code> value with one of the following error values
+returned in <em>errcode_ret</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if values specified in <em>flags</em> are not valid.</p>
+</li>
+<li>
+<p>CL_INVALID_D3D10_RESOURCE_KHR if <em>resource</em> is not a Direct3D 10 buffer
+resource, if <em>resource</em> was created with the D3D10_USAGE flag
+D3D10_USAGE_IMMUTABLE, if a cl_mem from <em>resource</em> has already been
+created using <strong>clCreateFromD3D10BufferKHR</strong>, or if <em>context</em> was not
+created against the same Direct3D 10 device from which <em>resource</em> was
+created.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The size of the returned OpenCL buffer object is the same as the size of
+<em>resource</em>.
+This call will increment the internal Direct3D reference count on
+<em>resource</em>.
+The internal Direct3D reference count on <em>resource</em> will be decremented when
+the OpenCL reference count on the returned OpenCL memory object drops to
+zero.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_d3d10_sharing-sharing-direct3d-10-texture-and-resources-as-opencl-image-objects">7.6.4. Sharing Direct3D 10 Texture and Resources as OpenCL Image Objects</h4>
+<div class="paragraph">
+<p>The function
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_mem clCreateFromD3D10Texture2DKHR(cl_context context,
+                                     cl_mem_flags flags,
+                                     ID3D10Texture2D *resource,
+                                     UINT subresource,
+                                     cl_int *errcode_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>creates an OpenCL 2D image object from a subresource of a Direct3D 10 2D
+texture.</p>
+</div>
+<div class="paragraph">
+<p><em>context</em> is a valid OpenCL context created from a Direct3D 10 device.</p>
+</div>
+<div class="paragraph">
+<p><em>flags</em> is a bit-field that is used to specify usage information.
+Refer to <em>table 5.3</em> for a description of <em>flags</em>.
+Only CL_MEM_READ_ONLY, CL_MEM_WRITE_ONLY and CL_MEM_READ_WRITE values
+specified in <em>table 5.3</em> can be used.</p>
+</div>
+<div class="paragraph">
+<p><em>resource</em> is a pointer to the Direct3D 10 2D texture to share.</p>
+</div>
+<div class="paragraph">
+<p><em>subresource</em> is the subresource of <em>resource</em> to share.</p>
+</div>
+<div class="paragraph">
+<p><em>errcode_ret</em> will return an appropriate error code.
+If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p>
+</div>
+<div class="paragraph">
+<p><strong>clCreateFromD3D10Texture2DKHR</strong> returns a valid non-zero OpenCL image object
+and <em>errcode_ret</em> is set to CL_SUCCESS if the image object is created
+successfully.
+Otherwise, it returns a <code>NULL</code> value with one of the following error values
+returned in <em>errcode_ret</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if values specified in <em>flags</em> are not valid or if
+<em>subresource</em> is not a valid subresource index for <em>resource</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_D3D10_RESOURCE_KHR if <em>resource</em> is not a Direct3D 10 texture
+resource, if <em>resource</em> was created with the D3D10_USAGE flag
+D3D10_USAGE_IMMUTABLE, if <em>resource</em> is a multisampled texture, if a
+cl_mem from subresource <em>subresource</em> of <em>resource</em> has already been
+created using <strong>clCreateFromD3D10Texture2DKHR</strong>, or if <em>context</em> was not
+created against the same Direct3D 10 device from which <em>resource</em> was
+created.</p>
+</li>
+<li>
+<p>CL_INVALID_IMAGE_FORMAT_DESCRIPTOR if the Direct3D 10 texture format of
+<em>resource</em> is not listed in the table
+<a href="#cl_khr_d3d10_sharing-mapping-of-image-formats"><em>Direct3D 10 formats and
+corresponding OpenCL image formats</em></a> or if the Direct3D 10 texture
+format of <em>resource</em> does not map to a supported OpenCL image format.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The width and height of the returned OpenCL 2D image object are determined
+by the width and height of subresource <em>subresource</em> of <em>resource</em>.
+The channel type and order of the returned OpenCL 2D image object is
+determined by the format of <em>resource</em> by the table
+<a href="#cl_khr_d3d10_sharing-mapping-of-image-formats"><em>Direct3D 10 formats and
+corresponding OpenCL image formats</em></a>.</p>
+</div>
+<div class="paragraph">
+<p>This call will increment the internal Direct3D reference count on
+<em>resource</em>.
+The internal Direct3D reference count on <em>resource</em> will be decremented when
+the OpenCL reference count on the returned OpenCL memory object drops to
+zero.</p>
+</div>
+<div class="paragraph">
+<p>The function
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_mem clCreateFromD3D10Texture3DKHR(cl_context context,
+                                     cl_mem_flags flags,
+                                     ID3D10Texture3D *resource,
+                                     UINT subresource,
+                                     cl_int *errcode_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>creates an OpenCL 3D image object from a subresource of a Direct3D 10 3D
+texture.</p>
+</div>
+<div class="paragraph">
+<p><em>context</em> is a valid OpenCL context created from a Direct3D 10 device.</p>
+</div>
+<div class="paragraph">
+<p><em>flags</em> is a bit-field that is used to specify usage information.
+Refer to table 5.3 for a description of <em>flags</em>.
+Only CL_MEM_READ_ONLY, CL_MEM_WRITE_ONLY and CL_MEM_READ_WRITE values
+specified in <em>table 5.3</em> can be used.</p>
+</div>
+<div class="paragraph">
+<p><em>resource</em> is a pointer to the Direct3D 10 3D texture to share.</p>
+</div>
+<div class="paragraph">
+<p><em>subresource</em> is the subresource of <em>resource</em> to share.</p>
+</div>
+<div class="paragraph">
+<p><em>errcode_ret</em> will return an appropriate error code.
+If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p>
+</div>
+<div class="paragraph">
+<p><strong>clCreateFromD3D10Texture3DKHR</strong> returns a valid non-zero OpenCL image object
+and <em>errcode_ret</em> is set to CL_SUCCESS if the image object is created
+successfully.
+Otherwise, it returns a <code>NULL</code> value with one of the following error values
+returned in <em>errcode_ret</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if values specified in <em>flags</em> are not valid or if
+<em>subresource</em> is not a valid subresource index for <em>resource</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_D3D10_RESOURCE_KHR if <em>resource</em> is not a Direct3D 10 texture
+resource, if <em>resource</em> was created with the D3D10_USAGE flag
+D3D10_USAGE_IMMUTABLE, if <em>resource</em> is a multisampled texture, if a
+cl_mem from subresource <em>subresource</em> of <em>resource</em> has already been
+created using <strong>clCreateFromD3D10Texture3DKHR</strong>, or if <em>context</em> was not
+created against the same Direct3D 10 device from which <em>resource</em> was
+created.</p>
+</li>
+<li>
+<p>CL_INVALID_IMAGE_FORMAT_DESCRIPTOR if the Direct3D 10 texture format of
+<em>resource</em> is not listed in the table
+<a href="#cl_khr_d3d10_sharing-mapping-of-image-formats"><em>Direct3D 10 formats and
+corresponding OpenCL image formats</em></a> or if the Direct3D 10 texture
+format of <em>resource</em> does not map to a supported OpenCL image format.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The width, height and depth of the returned OpenCL 3D image object are
+determined by the width, height and depth of subresource <em>subresource</em> of
+<em>resource</em>.
+The channel type and order of the returned OpenCL 3D image object is
+determined by the format of <em>resource</em> by the table
+<a href="#cl_khr_d3d10_sharing-mapping-of-image-formats"><em>Direct3D 10 formats and
+corresponding OpenCL image formats</em></a>.</p>
+</div>
+<div class="paragraph">
+<p>This call will increment the internal Direct3D reference count on
+<em>resource</em>.
+The internal Direct3D reference count on <em>resource</em> will be decremented when
+the OpenCL reference count on the returned OpenCL memory object drops to
+zero.</p>
+</div>
+<table id="cl_khr_d3d10_sharing-mapping-of-image-formats" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 21. <em>Direct3D 10 formats and corresponding OpenCL image formats</em></caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>DXGI format</strong></th>
+<th class="tableblock halign-left valign-top"><strong>CL image format</strong>
+
+<strong>(channel order, channel data type)</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R32G32B32A32_FLOAT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_FLOAT</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R32G32B32A32_UINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_UNSIGNED_INT32</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R32G32B32A32_SINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_SIGNED_INT32</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R16G16B16A16_FLOAT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_HALF_FLOAT</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R16G16B16A16_UNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_UNORM_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R16G16B16A16_UINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_UNSIGNED_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R16G16B16A16_SNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_SNORM_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R16G16B16A16_SINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_SIGNED_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_B8G8R8A8_UNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_BGRA, CL_UNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R8G8B8A8_UNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_UNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R8G8B8A8_UINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_UNSIGNED_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R8G8B8A8_SNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_SNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R8G8B8A8_SINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_SIGNED_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R32G32_FLOAT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_FLOAT</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R32G32_UINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_UNSIGNED_INT32</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R32G32_SINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_SIGNED_INT32</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R16G16_FLOAT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_HALF_FLOAT</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R16G16_UNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_UNORM_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R16G16_UINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_UNSIGNED_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R16G16_SNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_SNORM_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R16G16_SINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_SIGNED_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R8G8_UNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_UNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R8G8_UINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_UNSIGNED_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R8G8_SNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_SNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R8G8_SINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_SIGNED_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R32_FLOAT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_FLOAT</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R32_UINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_UNSIGNED_INT32</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R32_SINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_SIGNED_INT32</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R16_FLOAT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_HALF_FLOAT</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R16_UNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_UNORM_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R16_UINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_UNSIGNED_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R16_SNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_SNORM_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R16_SINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_SIGNED_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R8_UNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_UNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R8_UINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_UNSIGNED_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R8_SNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_SNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R8_SINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_SIGNED_INT8</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_d3d10_sharing-querying-direct3d-properties-of-memory-objects-created-from-direct3d-10-resources">7.6.5. Querying Direct3D properties of memory objects created from Direct3D 10 resources</h4>
+<div class="paragraph">
+<p>Properties of Direct3D 10 objects may be queried using <strong>clGetMemObjectInfo</strong>
+and <strong>clGetImageInfo</strong> with <em>param_name</em> CL_MEM_D3D10_RESOURCE_KHR and</p>
+</div>
+<div class="paragraph">
+<p>CL_IMAGE_D3D10_SUBRESOURCE_KHR respectively as described in <em>sections 5.4.3</em>
+and <em>5.3.6</em>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_d3d10_sharing-sharing-memory-objects-created-from-direct3d-10-resources-between-direct3d-10-and-opencl-contexts">7.6.6. Sharing memory objects created from Direct3D 10 resources between Direct3D 10 and OpenCL contexts</h4>
+<div class="paragraph">
+<p>The function
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_int clEnqueueAcquireD3D10ObjectsKHR(cl_command_queue command_queue,
+                                       cl_uint num_objects,
+                                       const cl_mem *mem_objects,
+                                       cl_uint num_events_in_wait_list,
+                                       const cl_event *event_wait_list,
+                                       cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>is used to acquire OpenCL memory objects that have been created from
+Direct3D 10 resources.
+The Direct3D 10 objects are acquired by the OpenCL context associated with
+<em>command_queue</em> and can therefore be used by all command-queues associated
+with the OpenCL context.</p>
+</div>
+<div class="paragraph">
+<p>OpenCL memory objects created from Direct3D 10 resources must be acquired
+before they can be used by any OpenCL commands queued to a command-queue.
+If an OpenCL memory object created from a Direct3D 10 resource is used while
+it is not currently acquired by OpenCL, the call attempting to use that
+OpenCL memory object will return CL_D3D10_RESOURCE_NOT_ACQUIRED_KHR.</p>
+</div>
+<div class="paragraph">
+<p>If CL_CONTEXT_INTEROP_USER_SYNC is not specified as CL_TRUE during context
+creation, <strong>clEnqueueAcquireD3D10ObjectsKHR</strong> provides the synchronization
+guarantee that any Direct3D 10 calls involving the interop device(s) used in
+the OpenCL context made before <strong>clEnqueueAcquireD3D10ObjectsKHR</strong> is called
+will complete executing before <em>event</em> reports completion and before the
+execution of any subsequent OpenCL work issued in <em>command_queue</em> begins.
+If the context was created with properties specifying
+CL_CONTEXT_INTEROP_USER_SYNC as CL_TRUE, the user is responsible for
+guaranteeing that any Direct3D 10 calls involving the interop device(s) used
+in the OpenCL context made before <strong>clEnqueueAcquireD3D10ObjectsKHR</strong> is
+called have completed before calling <strong>clEnqueueAcquireD3D10ObjectsKHR.</strong></p>
+</div>
+<div class="paragraph">
+<p><em>command_queue</em> is a valid command-queue.</p>
+</div>
+<div class="paragraph">
+<p><em>num_objects</em> is the number of memory objects to be acquired in
+<em>mem_objects</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>mem_objects</em> is a pointer to a list of OpenCL memory objects that were
+created from Direct3D 10 resources.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before this particular command can be executed.
+If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait
+on any event to complete.
+If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event_wait_list</em> act as synchronization points.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> returns an event object that identifies this particular command and
+can be used to query or queue a wait for this particular command to
+complete.
+<em>event</em> can be <code>NULL</code> in which case it will not be possible for the
+application to query the status of this command or queue a wait for this
+command to complete.
+If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the
+<em>event</em> argument should not refer to an element of the <em>event_wait_list</em>
+array.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueAcquireD3D10ObjectsKHR</strong> returns CL_SUCCESS if the function is
+executed successfully.
+If <em>num_objects</em> is 0 and <em>mem_objects</em> is <code>NULL</code> then the function does
+nothing and returns CL_SUCCESS.
+Otherwise it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_VALUE if <em>num_objects</em> is zero and <em>mem_objects</em> is not a
+<code>NULL</code> value or if <em>num_objects</em> &gt; 0 and <em>mem_objects</em> is <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_MEM_OBJECT if memory objects in <em>mem_objects</em> are not valid
+OpenCL memory objects or if memory objects in <em>mem_objects</em> have not
+been created from Direct3D 10 resources.</p>
+</li>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if context associated with <em>command_queue</em> was not
+created from an Direct3D 10 context.</p>
+</li>
+<li>
+<p>CL_D3D10_RESOURCE_ALREADY_ACQUIRED_KHR if memory objects in
+<em>mem_objects</em> have previously been acquired using
+<strong>clEnqueueAcquireD3D10ObjectsKHR</strong> but have not been released using
+<strong>clEnqueueReleaseD3D10ObjectsKHR</strong>.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_int clEnqueueReleaseD3D10ObjectsKHR(cl_command_queue command_queue,
+                                       cl_uint num_objects,
+                                       const cl_mem *mem_objects,
+                                       cl_uint num_events_in_wait_list,
+                                       const cl_event *event_wait_list,
+                                       cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>is used to release OpenCL memory objects that have been created from
+Direct3D 10 resources.
+The Direct3D 10 objects are released by the OpenCL context associated with
+<em>command_queue</em>.</p>
+</div>
+<div class="paragraph">
+<p>OpenCL memory objects created from Direct3D 10 resources which have been
+acquired by OpenCL must be released by OpenCL before they may be accessed by
+Direct3D 10.
+Accessing a Direct3D 10 resource while its corresponding OpenCL memory
+object is acquired is in error and will result in undefined behavior,
+including but not limited to possible OpenCL errors, data corruption, and
+program termination.</p>
+</div>
+<div class="paragraph">
+<p>If CL_CONTEXT_INTEROP_USER_SYNC is not specified as CL_TRUE during context
+creation, <strong>clEnqueueReleaseD3D10ObjectsKHR</strong> provides the synchronization
+guarantee that any calls to Direct3D 10 calls involving the interop
+device(s) used in the OpenCL context made after the call to
+<strong>clEnqueueReleaseD3D10ObjectsKHR</strong> will not start executing until after all
+events in <em>event_wait_list</em> are complete and all work already submitted to
+<em>command_queue</em> completes execution.
+If the context was created with properties specifying
+CL_CONTEXT_INTEROP_USER_SYNC as CL_TRUE, the user is responsible for
+guaranteeing that any Direct3D 10 calls involving the interop device(s) used
+in the OpenCL context made after <strong>clEnqueueReleaseD3D10ObjectsKHR</strong> will not
+start executing until after event returned by
+<strong>clEnqueueReleaseD3D10ObjectsKHR</strong> reports completion.</p>
+</div>
+<div class="paragraph">
+<p><em>num_objects</em> is the number of memory objects to be released in
+<em>mem_objects</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>mem_objects</em> is a pointer to a list of OpenCL memory objects that were
+created from Direct3D 10 resources.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before this particular command can be executed.
+If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait
+on any event to complete.
+If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event</em> returns an event object that identifies this
+particular command and can be used to query or queue a wait for this
+particular command to complete.
+<em>event</em> can be <code>NULL</code> in which case it will not be possible for the
+application to query the status of this command or queue a wait for this
+command to complete.
+If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the
+<em>event</em> argument should not refer to an element of the <em>event_wait_list</em>
+array.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueReleaseD3D10ObjectsKHR</strong> returns CL_SUCCESS if the function is
+executed successfully.
+If <em>num_objects</em> is 0 and <em>mem_objects</em> is <code>NULL</code> the function does nothing
+and returns CL_SUCCESS.
+Otherwise it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_VALUE if <em>num_objects</em> is zero and <em>mem_objects</em> is not a
+<code>NULL</code> value or if <em>num_objects</em> &gt; 0 and <em>mem_objects</em> is <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_MEM_OBJECT if memory objects in <em>mem_objects</em> are not valid
+OpenCL memory objects or if memory objects in <em>mem_objects</em> have not
+been created from Direct3D 10 resources.</p>
+</li>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if context associated with <em>command_queue</em> was not
+created from a Direct3D 10 device.</p>
+</li>
+<li>
+<p>CL_D3D10_RESOURCE_NOT_ACQUIRED_KHR if memory objects in <em>mem_objects</em>
+have not previously been acquired using
+<strong>clEnqueueAcquireD3D10ObjectsKHR</strong>, or have been released using
+<strong>clEnqueueReleaseD3D10ObjectsKHR</strong> since the last time that they were
+acquired.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em>&gt; is 0, or if event objects in
+<em>event_wait_list</em> are not valid events.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_d3d10_sharing-issues">7.7. Issues</h3>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>Should this extension be KHR or EXT?</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>PROPOSED: KHR.
+If this extension is to be approved by Khronos then it should be KHR,
+otherwise EXT.
+Not all platforms can support this extension, but that is also true of
+OpenGL interop.</p>
+</div>
+<div class="paragraph">
+<p>RESOLVED: KHR.</p>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p>Requiring SharedHandle on ID3D10Resource</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>Requiring this can largely simplify things at the DDI level and make some
+implementations faster.
+However, the DirectX spec only defines the shared handle for a subset of the
+resources we would like to support:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>D3D10_RESOURCE_MISC_SHARED - Enables the sharing of resource data between
+two or more Direct3D devices.
+The only resources that can be shared are 2D non-mipmapped textures.</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>PROPOSED A: Add wording to the spec about some implementations needing the
+resource setup as shared:</p>
+</div>
+<div class="paragraph">
+<p>&#8220;Some implementations may require the resource to be shared on the D3D10
+side of the API&#8221;</p>
+</div>
+<div class="paragraph">
+<p>If we do that, do we need another enum to describe this failure case?</p>
+</div>
+<div class="paragraph">
+<p>PROPOSED B: Require that all implementations support both shared and
+non-shared resources.
+The restrictions prohibiting multisample textures and the flag
+D3D10_USAGE_IMMUTABLE guarantee software access to all shareable resources.</p>
+</div>
+<div class="paragraph">
+<p>RESOLVED: Require that implementations support both
+D3D10_RESOURCE_MISC_SHARED being set and not set.
+Add the query for CL_CONTEXT_D3D10_PREFER_SHARED_RESOURCES_KHR to determine
+on a per-context basis which method will be faster.</p>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p>Texture1D support</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>There is not a matching CL type, so do we want to support this and map to
+buffer or Texture2D? If so the command might correspond to the 2D / 3D
+versions:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_mem clCreateFromD3D10Texture1D(cl_context context,
+                                  cl_mem_flags flags,
+                                  ID3D10Texture2D *resource,
+                                  UINT subresource,
+                                  cl_int *errcode_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>RESOLVED: We will not add support for ID3D10Texture1D objects unless a
+corresponding OpenCL 1D Image type is created.</p>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p>CL/D3D10 queries</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>The GL interop has clGetGLObjectInfo and clGetGLTextureInfo.
+It is unclear if these are needed on the D3D10 interop side since the D3D10
+spec makes these queries trivial on the D3D10 object itself.
+Also, not all of the sematics of the GL call map across.</p>
+</div>
+<div class="paragraph">
+<p>PROPOSED: Add the <strong>clGetMemObjectInfo</strong> and <strong>clGetImageInfo</strong> parameter names
+CL_MEM_D3D10_RESOURCE_KHR and CL_IMAGE_D3D10_SUBRESOURCE_KHR to query the
+D3D10 resource from which a cl_mem was created.
+From this data, any D3D10 side information may be queried using the D3D10
+API.</p>
+</div>
+<div class="paragraph">
+<p>RESOLVED: We will use <strong>clGetMemObjectInfo</strong> and <strong>clGetImageInfo</strong> to access
+this information.</p>
+</div>
+</div>
+</div>
+</li>
+</ol>
+</div>
+<div style="page-break-after: always;"></div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="cl_khr_d3d11_sharing">8. Creating OpenCL Memory Objects from Direct3D 11 Buffers and Textures</h2>
+<div class="sectionbody">
+<div class="sect2">
+<h3 id="cl_khr_d3d11_sharing-overview">8.1. Overview</h3>
+<div class="paragraph">
+<p>This section describes the <strong>cl_khr_d3d11_sharing</strong> extension.
+The goal of this extension is to provide interoperability between OpenCL and
+Direct3D 11.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_d3d11_sharing-new-procedures-and-functions">8.2. New Procedures and Functions</h3>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_int clGetDeviceIDsFromD3D11KHR(cl_platform_id platform,
+                                  cl_d3d11_device_source_khr d3d_device_source,
+                                  void *d3d_object,
+                                  cl_d3d11_device_set_khr d3d_device_set,
+                                  cl_uint num_entries,
+                                  cl_device_id *devices,
+                                  cl_uint *num_devices)
+
+cl_mem clCreateFromD3D11BufferKHR(cl_context context,
+                                  cl_mem_flags flags,
+                                  ID3D11Buffer *resource,
+                                  cl_int *errcode_ret)
+
+cl_mem clCreateFromD3D11Texture2DKHR(cl_context context,
+                                     cl_mem_flags flags,
+                                     ID3D11Texture2D *resource,
+                                     UINT subresource,
+                                     cl_int *errcode_ret)
+
+cl_mem clCreateFromD3D11Texture3DKHR(cl_context context,
+                                     cl_mem_flags flags,
+                                     ID3D11Texture3D *resource,
+                                     UINT subresource,
+                                     cl_int *errcode_ret)
+
+cl_int clEnqueueAcquireD3D11ObjectsKHR(cl_command_queue command_queue,
+                                       cl_uint num_objects,
+                                       const cl_mem *mem_objects,
+                                       cl_uint num_events_in_wait_list,
+                                       const cl_event *event_wait_list,
+                                       cl_event *event)
+
+cl_int clEnqueueReleaseD3D11ObjectsKHR(cl_command_queue command_queue,
+                                       cl_uint num_objects,
+                                       const cl_mem *mem_objects,
+                                       cl_uint num_events_in_wait_list,
+                                       const cl_event *event_wait_list,
+                                       cl_event *event)</code></pre>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_d3d11_sharing-new-tokens">8.3. New Tokens</h3>
+<div class="paragraph">
+<p>Accepted as a Direct3D 11 device source in the <em>d3d_device_source</em> parameter
+of <strong>clGetDeviceIDsFromD3D11KHR</strong>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_D3D11_DEVICE_KHR                 0x4019
+CL_D3D11_DXGI_ADAPTER_KHR           0x401A</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Accepted as a set of Direct3D 11 devices in the _d3d_device_set_parameter of
+<strong>clGetDeviceIDsFromD3D11KHR</strong>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_PREFERRED_DEVICES_FOR_D3D11_KHR  0x401B
+CL_ALL_DEVICES_FOR_D3D11_KHR        0x401C</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Accepted as a property name in the <em>properties</em> parameter of
+<strong>clCreateContext</strong> and <strong>clCreateContextFromType</strong>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_CONTEXT_D3D11_DEVICE_KHR         0x401D</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Accepted as a property name in the <em>param_name</em> parameter of
+<strong>clGetContextInfo</strong>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_CONTEXT_D3D11_PREFER_SHARED_RESOURCES_KHR    0x402D</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Accepted as the property being queried in the <em>param_name</em> parameter of
+<strong>clGetMemObjectInfo</strong>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_MEM_D3D11_RESOURCE_KHR           0x401E</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Accepted as the property being queried in the <em>param_name</em> parameter of
+<strong>clGetImageInfo</strong>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_IMAGE_D3D11_SUBRESOURCE_KHR      0x401F</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returned in the <em>param_value</em> parameter of <strong>clGetEventInfo</strong> when
+<em>param_name</em> is CL_EVENT_COMMAND_TYPE:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_COMMAND_ACQUIRE_D3D11_OBJECTS_KHR    0x4020
+CL_COMMAND_RELEASE_D3D11_OBJECTS_KHR    0x4021</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returned by <strong>clCreateContext</strong> and <strong>clCreateContextFromType</strong> if the Direct3D
+11 device specified for interoperability is not compatible with the devices
+against which the context is to be created:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_INVALID_D3D11_DEVICE_KHR         -1006</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returned by <strong>clCreateFromD3D11BufferKHR</strong> when <em>resource</em> is not a Direct3D
+11 buffer object, and by <strong>clCreateFromD3D11Texture2DKHR</strong> and
+<strong>clCreateFromD3D11Texture3DKHR</strong> when <em>resource</em> is not a Direct3D 11 texture
+object.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_INVALID_D3D11_RESOURCE_KHR       -1007</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returned by <strong>clEnqueueAcquireD3D11ObjectsKHR</strong> when any of <em>mem_objects</em> are
+currently acquired by OpenCL</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_D3D11_RESOURCE_ALREADY_ACQUIRED_KHR  -1008</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returned by <strong>clEnqueueReleaseD3D11ObjectsKHR</strong> when any of <em>mem_objects</em> are
+not currently acquired by OpenCL</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_D3D11_RESOURCE_NOT_ACQUIRED_KHR  -1009</pre>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_d3d11_sharing-additions-to-chapter-4">8.4. Additions to Chapter 4 of the OpenCL 2.2 Specification</h3>
+<div class="paragraph">
+<p>In <em>section 4.4</em>, replace the description of <em>properties</em> under
+<strong>clCreateContext</strong> with:</p>
+</div>
+<div class="paragraph">
+<p>&#8220;_properties_ specifies a list of context property names and their
+corresponding values.
+Each property is followed immediately by the corresponding desired value.
+The list is terminated with zero.
+If a property is not specified in <em>properties</em>, then its default value
+(listed in <em>table 4.5</em>) is used (it is said to be specified implicitly).
+If <em>properties</em> is <code>NULL</code> or empty (points to a list whose first value is
+zero), all attributes take on their default values.&#8221;</p>
+</div>
+<div class="paragraph">
+<p>Add the following to <em>table 4.5</em>:</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 40%;">
+<col style="width: 20%;">
+<col style="width: 40%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_context_properties enum</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Property value</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_CONTEXT_D3D11_DEVICE_KHR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">ID3D11Device *</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Specifies the ID3D11Device * to use for Direct3D 11 interoperability.</p>
+<p class="tableblock">  The default value is <code>NULL</code>.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>Add to the list of errors for <strong>clCreateContext</strong>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_D3D11_DEVICE_KHR if the value of the property
+CL_CONTEXT_D3D11_DEVICE_KHR is non-<code>NULL</code> and does not specify a valid
+Direct3D 11 device with which the <em>cl_device_ids</em> against which this
+context is to be created may interoperate.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if Direct3D 11 interoperability is specified by
+setting CL_INVALID_D3D11_DEVICE_KHR to a non-<code>NULL</code> value, and
+interoperability with another graphics API is also specified.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Add to the list of errors for <strong>clCreateContextFromType</strong> the same new errors
+described above for <strong>clCreateContext</strong>.</p>
+</div>
+<div class="paragraph">
+<p>Add the following row to <em>table 4.6</em>:</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 40%;">
+<col style="width: 20%;">
+<col style="width: 40%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_context_info</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Return Type</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Information returned in param_value</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_CONTEXT_D3D11_PREFER_SHARED_RESOURCES_KHR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cl_bool</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns CL_TRUE if Direct3D 11 resources created as shared by setting
+  <em>MiscFlags</em> to include D3D11_RESOURCE_MISC_SHARED will perform faster when
+  shared with OpenCL, compared with resources which have not set this flag.
+  Otherwise returns CL_FALSE.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_d3d11_sharing-additions-to-chapter-5">8.5. Additions to Chapter 5 of the OpenCL 2.2 Specification</h3>
+<div class="paragraph">
+<p>Add to the list of errors for <strong>clGetMemObjectInfo</strong>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_D3D11_RESOURCE_KHR if <em>param_name</em> is
+CL_MEM_D3D11_RESOURCE_KHR and <em>memobj</em> was not created by the function
+<strong>clCreateFromD3D11BufferKHR</strong>, <strong>clCreateFromD3D11Texture2DKHR</strong>, or
+<strong>clCreateFromD3D11Texture3DKHR</strong>.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Extend <em>table 5.12</em> to include the following entry.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 40%;">
+<col style="width: 20%;">
+<col style="width: 40%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_mem_info</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Return type</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Info. returned in <em>param_value</em></strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_D3D11_RESOURCE_KHR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">ID3D11Resource *</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">If <em>memobj</em> was created using <strong>clCreateFromD3D11BufferKHR</strong>,
+  <strong>clCreateFromD3D11Texture2DKHR</strong>, or <strong>clCreateFromD3D11Texture3DKHR</strong>,
+  returns the <em>resource</em> argument specified when <em>memobj</em> was created.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>Add to the list of errors for <strong>clGetImageInfo</strong>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_D3D11_RESOURCE_KHR if <em>param_name</em> is
+CL_MEM_D3D11_SUBRESOURCE_KHR and <em>image</em> was not created by the function
+<strong>clCreateFromD3D11Texture2DKHR</strong>, or <strong>clCreateFromD3D11Texture3DKHR</strong>.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Extend <em>table 5.9</em> to include the following entry.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 40%;">
+<col style="width: 20%;">
+<col style="width: 40%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_image_info</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Return type</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Info. returned in <em>param_value</em></strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_MEM_D3D11_SUBRESOURCE_KHR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">UINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">If <em>image</em> was created using <strong>clCreateFromD3D11Texture2DKHR</strong>, or
+  <strong>clCreateFromD3D11Texture3DKHR</strong>, returns the <em>subresource</em> argument
+  specified when <em>image</em> was created.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>Add to <em>table 5.22</em> in the <strong>Info returned in param_value</strong> column for
+<em>cl_event_info</em> = CL_EVENT_COMMAND_TYPE:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_COMMAND_ACQUIRE_D3D11_OBJECTS_KHR
+CL_COMMAND_RELEASE_D3D11_OBJECTS_KHR</pre>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_d3d11_sharing-sharing-memory-objects-with-direct3d-11-resources">8.6. Sharing Memory Objects with Direct3D 11 Resources</h3>
+<div class="paragraph">
+<p>This section discusses OpenCL functions that allow applications to use
+Direct3D 11 resources as OpenCL memory objects.
+This allows efficient sharing of data between OpenCL and Direct3D 11.
+The OpenCL API may be used to execute kernels that read and/or write memory
+objects that are also Direct3D 11 resources.
+An OpenCL image object may be created from a Direct3D 11 texture resource.
+An OpenCL buffer object may be created from a Direct3D 11 buffer resource.
+OpenCL memory objects may be created from Direct3D 11 objects if and only if
+the OpenCL context has been created from a Direct3D 11 device.</p>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_d3d11_sharing-querying-opencl-devices-corresponding-to-direct3d-11-devices">8.6.1. Querying OpenCL Devices Corresponding to Direct3D 11 Devices</h4>
+<div class="paragraph">
+<p>The OpenCL devices corresponding to a Direct3D 11 device may be queried.
+The OpenCL devices corresponding to a DXGI adapter may also be queried.
+The OpenCL devices corresponding to a Direct3D 11 device will be a subset of
+the OpenCL devices corresponding to the DXGI adapter against which the
+Direct3D 11 device was created.</p>
+</div>
+<div class="paragraph">
+<p>The OpenCL devices corresponding to a Direct3D 11 device or a DXGI device
+may be queried using the function
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_int clGetDeviceIDsFromD3D11KHR(cl_platform_id platform,
+                                  cl_d3d11_device_source_khr d3d_device_source,
+                                  void *d3d_object,
+                                  cl_d3d11_device_set_khr d3d_device_set,
+                                  cl_uint num_entries,
+                                  cl_device_id *devices,
+                                  cl_uint *num_devices)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><em>platform</em> refers to the platform ID returned by <strong>clGetPlatformIDs</strong>.</p>
+</div>
+<div class="paragraph">
+<p><em>d3d_device_source</em> specifies the type of <em>d3d_object</em>, and must be one of
+the values shown in the table below.</p>
+</div>
+<div class="paragraph">
+<p><em>d3d_object</em> specifies the object whose corresponding OpenCL devices are
+being queried.
+The type of <em>d3d_object</em> must be as specified in the table below.</p>
+</div>
+<div class="paragraph">
+<p><em>d3d_device_set</em> specifies the set of devices to return, and must be one of
+the values shown in the table below.</p>
+</div>
+<div class="paragraph">
+<p><em>num_entries</em> is the number of cl_device_id entries that can be added to
+<em>devices</em>.
+If <em>devices</em> is not <code>NULL</code> then <em>num_entries</em> must be greater than zero.</p>
+</div>
+<div class="paragraph">
+<p><em>devices</em> returns a list of OpenCL devices found.
+The cl_device_id values returned in <em>devices</em> can be used to identify a
+specific OpenCL device.
+If <em>devices</em> is <code>NULL</code>, this argument is ignored.
+The number of OpenCL devices returned is the minimum of the value specified
+by <em>num_entries</em> and the number of OpenCL devices corresponding to
+<em>d3d_object</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>num_devices</em> returns the number of OpenCL devices available that correspond
+to <em>d3d_object</em>.
+If <em>num_devices</em> is <code>NULL</code>, this argument is ignored.</p>
+</div>
+<div class="paragraph">
+<p><strong>clGetDeviceIDsFromD3D10KHR</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise it may return</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_PLATFORM if <em>platform</em> is not a valid platform.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>d3d_device_source</em> is not a valid value,
+<em>d3d_device_set</em> is not a valid value, <em>num_entries</em> is equal to zero
+and <em>devices</em> is not <code>NULL</code>, or if both <em>num_devices</em> and <em>devices</em> are
+<code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_DEVICE_NOT_FOUND if no OpenCL devices that correspond to <em>d3d_object</em>
+were found.</p>
+</li>
+</ul>
+</div>
+<table id="cl_khr_d3d11_sharing-clGetDeviceIDsFromD3D11KHR-object-type" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 22. <em>Direct3D 11 object types that may be used by</em> <strong>clGetDeviceIDsFromD3D11KHR</strong></caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_d3d_device_source_khr</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Type of <em>d3d_object</em></strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_D3D11_DEVICE_KHR</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">ID3D11Device *</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_D3D11_DXGI_ADAPTER_KHR</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">IDXGIAdapter *</p></td>
+</tr>
+</tbody>
+</table>
+<table id="cl_khr_d3d11_sharing-clGetDeviceIDsFromD3D10KHR-devices" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 23. <em>Sets of devices queriable using</em> <strong>clGetDeviceIDsFromD3D11KHR</strong></caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_d3d_device_set_khr</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Devices returned in <em>devices</em></strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_PREFERRED_DEVICES_FOR_D3D11_KHR</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The preferred OpenCL devices associated with the specified Direct3D
+  object.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_ALL_DEVICES_FOR_D3D11_KHR</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">All OpenCL devices which may interoperate with the specified Direct3D
+  object.
+  Performance of sharing data on these devices may be considerably less than
+  on the preferred devices.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_d3d11_sharing-lifetime-of-shared-objects">8.6.2. Lifetime of Shared Objects</h4>
+<div class="paragraph">
+<p>An OpenCL memory object created from a Direct3D 11 resource remains valid as
+long as the corresponding Direct3D 11 resource has not been deleted.
+If the Direct3D 11 resource is deleted through the Direct3D 11 API,
+subsequent use of the OpenCL memory object will result in undefined
+behavior, including but not limited to possible OpenCL errors, data
+corruption, and program termination.</p>
+</div>
+<div class="paragraph">
+<p>The successful creation of a cl_context against a Direct3D 11 device
+specified via the context create parameter CL_CONTEXT_D3D11_DEVICE_KHR will
+increment the internal Direct3D reference count on the specified Direct3D 11
+device.
+The internal Direct3D reference count on that Direct3D 11 device will be
+decremented when the OpenCL reference count on the returned OpenCL context
+drops to zero.</p>
+</div>
+<div class="paragraph">
+<p>The OpenCL context and corresponding command-queues are dependent on the
+existence of the Direct3D 11 device from which the OpenCL context was
+created.
+If the Direct3D 11 device is deleted through the Direct3D 11 API, subsequent
+use of the OpenCL context will result in undefined behavior, including but
+not limited to possible OpenCL errors, data corruption, and program
+termination.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_d3d11_sharing-sharing-direct3d-11-buffer-resources-as-opencl-buffer-objects">8.6.3. Sharing Direct3D 11 Buffer Resources as OpenCL Buffer Objects</h4>
+<div class="paragraph">
+<p>The function
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_mem clCreateFromD3D11BufferKHR(cl_context context,
+                                  cl_mem_flags flags,
+                                  ID3D11Buffer *resource,
+                                  cl_int *errcode_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>creates an OpenCL buffer object from a Direct3D 11 buffer.</p>
+</div>
+<div class="paragraph">
+<p><em>context</em> is a valid OpenCL context created from a Direct3D 11 device.</p>
+</div>
+<div class="paragraph">
+<p><em>flags</em> is a bit-field that is used to specify usage information.
+Refer to table 5.3 for a description of <em>flags</em>.
+Only CL_MEM_READ_ONLY, CL_MEM_WRITE_ONLY and CL_MEM_READ_WRITE values
+specified in <em>table 5.3</em> can be used.</p>
+</div>
+<div class="paragraph">
+<p><em>resource</em> is a pointer to the Direct3D 11 buffer to share.</p>
+</div>
+<div class="paragraph">
+<p><em>errcode_ret</em> will return an appropriate error code.
+If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p>
+</div>
+<div class="paragraph">
+<p><strong>clCreateFromD3D11BufferKHR</strong> returns a valid non-zero OpenCL buffer object
+and <em>errcode_ret</em> is set to CL_SUCCESS if the buffer object is created
+successfully.
+Otherwise, it returns a <code>NULL</code> value with one of the following error values
+returned in <em>errcode_ret</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if values specified in <em>flags</em> are not valid.</p>
+</li>
+<li>
+<p>CL_INVALID_D3D11_RESOURCE_KHR if <em>resource</em> is not a Direct3D 11 buffer
+resource, if <em>resource</em> was created with the D3D11_USAGE flag
+D3D11_USAGE_IMMUTABLE, if a cl_mem from <em>resource</em> has already been
+created using <strong>clCreateFromD3D11BufferKHR</strong>, or if <em>context</em> was not
+created against the same Direct3D 11 device from which <em>resource</em> was
+created.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The size of the returned OpenCL buffer object is the same as the size of
+<em>resource</em>.
+This call will increment the internal Direct3D reference count on
+<em>resource</em>.
+The internal Direct3D reference count on <em>resource</em> will be decremented when
+the OpenCL reference count on the returned OpenCL memory object drops to
+zero.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_d3d11_sharing-sharing-direct3d-11-texture-and-resources-as-opencl-image-objects">8.6.4. Sharing Direct3D 11 Texture and Resources as OpenCL Image Objects</h4>
+<div class="paragraph">
+<p>The function
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_mem clCreateFromD3D11Texture2DKHR(cl_context context,
+                                     cl_mem_flags flags,
+                                     ID3D11Texture2D *resource,
+                                     UINT subresource,
+                                     cl_int *errcode_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>creates an OpenCL 2D image object from a subresource of a Direct3D 11 2D
+texture.</p>
+</div>
+<div class="paragraph">
+<p><em>context</em> is a valid OpenCL context created from a Direct3D 11 device.</p>
+</div>
+<div class="paragraph">
+<p><em>flags</em> is a bit-field that is used to specify usage information.
+Refer to <em>table 5.3</em> for a description of <em>flags</em>.
+Only CL_MEM_READ_ONLY, CL_MEM_WRITE_ONLY and CL_MEM_READ_WRITE values
+specified in <em>table 5.3</em> can be used.</p>
+</div>
+<div class="paragraph">
+<p><em>resource</em> is a pointer to the Direct3D 11 2D texture to share.</p>
+</div>
+<div class="paragraph">
+<p><em>subresource</em> is the subresource of <em>resource</em> to share.</p>
+</div>
+<div class="paragraph">
+<p><em>errcode_ret</em> will return an appropriate error code.
+If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p>
+</div>
+<div class="paragraph">
+<p><strong>clCreateFromD3D11Texture2DKHR</strong> returns a valid non-zero OpenCL image object
+and <em>errcode_ret</em> is set to CL_SUCCESS if the image object is created
+successfully.
+Otherwise, it returns a <code>NULL</code> value with one of the following error values
+returned in <em>errcode_ret</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if values specified in <em>flags</em> are not valid or if
+<em>subresource</em> is not a valid subresource index for <em>resource</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_D3D11_RESOURCE_KHR if <em>resource</em> is not a Direct3D 11 texture
+resource, if <em>resource</em> was created with the D3D11_USAGE flag
+D3D11_USAGE_IMMUTABLE, if <em>resource</em> is a multisampled texture, if a
+cl_mem from subresource <em>subresource</em> of <em>resource</em> has already been
+created using <strong>clCreateFromD3D11Texture2DKHR</strong>, or if <em>context</em> was not
+created against the same Direct3D 10 device from which <em>resource</em> was
+created.</p>
+</li>
+<li>
+<p>CL_INVALID_IMAGE_FORMAT_DESCRIPTOR if the Direct3D 11 texture format of
+<em>resource</em> is not listed in the table
+<a href="#cl_khr_d3d11_sharing-mapping-of-image-formats"><em>Direct3D 11 formats and
+corresponding OpenCL image formats</em></a> or if the Direct3D 11 texture
+format of <em>resource</em> does not map to a supported OpenCL image format.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The width and height of the returned OpenCL 2D image object are determined
+by the width and height of subresource <em>subresource</em> of <em>resource</em>.
+The channel type and order of the returned OpenCL 2D image object is
+determined by the format of <em>resource</em> by the table
+<a href="#cl_khr_d3d11_sharing-mapping-of-image-formats"><em>Direct3D 11 formats and
+corresponding OpenCL image formats</em></a>.</p>
+</div>
+<div class="paragraph">
+<p>This call will increment the internal Direct3D reference count on
+<em>resource</em>.
+The internal Direct3D reference count on <em>resource</em> will be decremented when
+the OpenCL reference count on the returned OpenCL memory object drops to
+zero.</p>
+</div>
+<div class="paragraph">
+<p>The function
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_mem clCreateFromD3D11Texture3DKHR(cl_context context,
+                                     cl_mem_flags flags,
+                                     ID3D11Texture3D *resource,
+                                     UINT subresource,
+                                     cl_int *errcode_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>creates an OpenCL 3D image object from a subresource of a Direct3D 11 3D
+texture.</p>
+</div>
+<div class="paragraph">
+<p><em>context</em> is a valid OpenCL context created from a Direct3D 11 device.</p>
+</div>
+<div class="paragraph">
+<p><em>flags</em> is a bit-field that is used to specify usage information.
+Refer to <em>table 5.3</em> for a description of <em>flags</em>.
+Only CL_MEM_READ_ONLY, CL_MEM_WRITE_ONLY and CL_MEM_READ_WRITE values
+specified in <em>table 5.3</em> can be used.</p>
+</div>
+<div class="paragraph">
+<p><em>resource</em> is a pointer to the Direct3D 11 3D texture to share.</p>
+</div>
+<div class="paragraph">
+<p><em>subresource</em> is the subresource of <em>resource</em> to share.</p>
+</div>
+<div class="paragraph">
+<p><em>errcode_ret</em> will return an appropriate error code.
+If <em>errcode_ret</em> is <code>NULL</code>, no error code is returned.</p>
+</div>
+<div class="paragraph">
+<p><strong>clCreateFromD3D11Texture3DKHR</strong> returns a valid non-zero OpenCL image object
+and <em>errcode_ret</em> is set to CL_SUCCESS if the image object is created
+successfully.
+Otherwise, it returns a <code>NULL</code> value with one of the following error values
+returned in <em>errcode_ret</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if values specified in <em>flags</em> are not valid or if
+<em>subresource</em> is not a valid subresource index for <em>resource</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_D3D11_RESOURCE_KHR if <em>resource</em> is not a Direct3D 11 texture
+resource, if <em>resource</em> was created with the D3D11_USAGE flag
+D3D11_USAGE_IMMUTABLE, if <em>resource</em> is a multisampled texture, if a
+cl_mem from subresource <em>subresource</em> of <em>resource</em> has already been
+created using <strong>clCreateFromD3D11Texture3DKHR</strong>, or if <em>context</em> was not
+created against the same Direct3D 11 device from which <em>resource</em> was
+created.</p>
+</li>
+<li>
+<p>CL_INVALID_IMAGE_FORMAT_DESCRIPTOR if the Direct3D 11 texture format of
+<em>resource</em> is not listed in the table
+<a href="#cl_khr_d3d11_sharing-mapping-of-image-formats"><em>Direct3D 11 formats and
+corresponding OpenCL image formats</em></a> or if the Direct3D 11 texture
+format of <em>resource</em> does not map to a supported OpenCL image format.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The width, height and depth of the returned OpenCL 3D image object are
+determined by the width, height and depth of subresource <em>subresource</em> of
+<em>resource</em>.
+The channel type and order of the returned OpenCL 3D image object is
+determined by the format of <em>resource</em> by the table
+<a href="#cl_khr_d3d11_sharing-mapping-of-image-formats"><em>Direct3D 11 formats and
+corresponding OpenCL image formats</em></a>.</p>
+</div>
+<div class="paragraph">
+<p>This call will increment the internal Direct3D reference count on
+<em>resource</em>.
+The internal Direct3D reference count on <em>resource</em> will be decremented when
+the OpenCL reference count on the returned OpenCL memory object drops to
+zero.</p>
+</div>
+<table id="cl_khr_d3d11_sharing-mapping-of-image-formats" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 24. <em>Direct3D 11 formats and corresponding OpenCL image formats</em></caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>DXGI format</strong></th>
+<th class="tableblock halign-left valign-top"><strong>CL image format</strong>
+
+<strong>(channel order, channel data type)</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R32G32B32A32_FLOAT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_FLOAT</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R32G32B32A32_UINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_UNSIGNED_INT32</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R32G32B32A32_SINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_SIGNED_INT32</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R16G16B16A16_FLOAT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_HALF_FLOAT</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R16G16B16A16_UNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_UNORM_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R16G16B16A16_UINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_UNSIGNED_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R16G16B16A16_SNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_SNORM_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R16G16B16A16_SINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_SIGNED_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_B8G8R8A8_UNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_BGRA, CL_UNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R8G8B8A8_UNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_UNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R8G8B8A8_UINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_UNSIGNED_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R8G8B8A8_SNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_SNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R8G8B8A8_SINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RGBA, CL_SIGNED_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R32G32_FLOAT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_FLOAT</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R32G32_UINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_UNSIGNED_INT32</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R32G32_SINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_SIGNED_INT32</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R16G16_FLOAT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_HALF_FLOAT</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R16G16_UNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_UNORM_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R16G16_UINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_UNSIGNED_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R16G16_SNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_SNORM_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R16G16_SINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_SIGNED_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R8G8_UNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_UNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R8G8_UINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_UNSIGNED_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R8G8_SNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_SNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R8G8_SINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_RG, CL_SIGNED_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R32_FLOAT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_FLOAT</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R32_UINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_UNSIGNED_INT32</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R32_SINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_SIGNED_INT32</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R16_FLOAT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_HALF_FLOAT</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R16_UNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_UNORM_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R16_UINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_UNSIGNED_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R16_SNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_SNORM_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R16_SINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_SIGNED_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R8_UNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_UNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R8_UINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_UNSIGNED_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R8_SNORM</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_SNORM_INT8</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">DXGI_FORMAT_R8_SINT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_R, CL_SIGNED_INT8</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_d3d11_sharing-querying-direct3d-properties-of-memory-objects-created-from-direct3d-11-resources">8.6.5. Querying Direct3D properties of memory objects created from Direct3D 11 resources</h4>
+<div class="paragraph">
+<p>Properties of Direct3D 11 objects may be queried using <strong>clGetMemObjectInfo</strong>
+and <strong>clGetImageInfo</strong> with <em>param_name</em> CL_MEM_D3D11_RESOURCE_KHR and</p>
+</div>
+<div class="paragraph">
+<p>CL_IMAGE_D3D11_SUBRESOURCE_KHR respectively as described in <em>sections 5.4.3</em>
+and <em>5.3.6</em>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_d3d11_sharing-sharing-memory-objects-created-from-direct3d-11-resources-between-direct3d-11-and-opencl-contexts">8.6.6. Sharing memory objects created from Direct3D 11 resources between Direct3D 11 and OpenCL contexts</h4>
+<div class="paragraph">
+<p>The function
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_int clEnqueueAcquireD3D11ObjectsKHR(cl_command_queue command_queue,
+                                       cl_uint num_objects,
+                                       const cl_mem *mem_objects,
+                                       cl_uint num_events_in_wait_list,
+                                       const cl_event *event_wait_list,
+                                       cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>is used to acquire OpenCL memory objects that have been created from
+Direct3D 11 resources.
+The Direct3D 11 objects are acquired by the OpenCL context associated with
+<em>command_queue</em> and can therefore be used by all command-queues associated
+with the OpenCL context.</p>
+</div>
+<div class="paragraph">
+<p>OpenCL memory objects created from Direct3D 11 resources must be acquired
+before they can be used by any OpenCL commands queued to a command-queue.
+If an OpenCL memory object created from a Direct3D 11 resource is used while
+it is not currently acquired by OpenCL, the call attempting to use that
+OpenCL memory object will return CL_D3D11_RESOURCE_NOT_ACQUIRED_KHR.</p>
+</div>
+<div class="paragraph">
+<p>If CL_CONTEXT_INTEROP_USER_SYNC is not specified as CL_TRUE during context
+creation, <strong>clEnqueueAcquireD3D11ObjectsKHR</strong> provides the synchronization
+guarantee that any Direct3D 11 calls involving the interop device(s) used in
+the OpenCL context made before <strong>clEnqueueAcquireD3D11ObjectsKHR</strong> is called
+will complete executing before <em>event</em> reports completion and before the
+execution of any subsequent OpenCL work issued in <em>command_queue</em> begins.
+If the context was created with properties specifying
+CL_CONTEXT_INTEROP_USER_SYNC as CL_TRUE, the user is responsible for
+guaranteeing that any Direct3D 11 calls involving the interop device(s) used
+in the OpenCL context made before <strong>clEnqueueAcquireD3D11ObjectsKHR</strong> is
+called have completed before calling <strong>clEnqueueAcquireD3D11ObjectsKHR.</strong></p>
+</div>
+<div class="paragraph">
+<p><em>command_queue</em> is a valid command-queue.</p>
+</div>
+<div class="paragraph">
+<p><em>num_objects</em> is the number of memory objects to be acquired in
+<em>mem_objects</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>mem_objects</em> is a pointer to a list of OpenCL memory objects that were
+created from Direct3D 11 resources.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before this particular command can be executed.
+If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait
+on any event to complete.
+If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event_wait_list</em> act as synchronization points.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> returns an event object that identifies this particular command and
+can be used to query or queue a wait for this particular command to
+complete.
+<em>event</em> can be <code>NULL</code> in which case it will not be possible for the
+application to query the status of this command or queue a wait for this
+command to complete.
+If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the
+<em>event</em> argument should not refer to an element of the <em>event_wait_list</em>
+array.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueAcquireD3D11ObjectsKHR</strong> returns CL_SUCCESS if the function is
+executed successfully.
+If <em>num_objects</em> is 0 and <em>mem_objects</em> is <code>NULL</code> then the function does
+nothing and returns CL_SUCCESS.
+Otherwise it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_VALUE if <em>num_objects</em> is zero and <em>mem_objects</em> is not a
+<code>NULL</code> value or if <em>num_objects</em> &gt; 0 and <em>mem_objects</em> is <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_MEM_OBJECT if memory objects in <em>mem_objects</em> are not valid
+OpenCL memory objects or if memory objects in <em>mem_objects</em> have not
+been created from Direct3D 11 resources.</p>
+</li>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if context associated with <em>command_queue</em> was not
+created from an Direct3D 11 context.</p>
+</li>
+<li>
+<p>CL_D3D11_RESOURCE_ALREADY_ACQUIRED_KHR if memory objects in
+<em>mem_objects</em> have previously been acquired using
+<strong>clEnqueueAcquireD3D11ObjectsKHR</strong> but have not been released using
+<strong>clEnqueueReleaseD3D11ObjectsKHR</strong>.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_int clEnqueueReleaseD3D11ObjectsKHR(cl_command_queue command_queue,
+                                       cl_uint num_objects,
+                                       const cl_mem *mem_objects,
+                                       cl_uint num_events_in_wait_list,
+                                       const cl_event *event_wait_list,
+                                       cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>is used to release OpenCL memory objects that have been created from
+Direct3D 11 resources.
+The Direct3D 11 objects are released by the OpenCL context associated with
+<em>command_queue</em>.</p>
+</div>
+<div class="paragraph">
+<p>OpenCL memory objects created from Direct3D 11 resources which have been
+acquired by OpenCL must be released by OpenCL before they may be accessed by
+Direct3D 11.
+Accessing a Direct3D 11 resource while its corresponding OpenCL memory
+object is acquired is in error and will result in undefined behavior,
+including but not limited to possible OpenCL errors, data corruption, and
+program termination.</p>
+</div>
+<div class="paragraph">
+<p>If CL_CONTEXT_INTEROP_USER_SYNC is not specified as CL_TRUE during context
+creation, <strong>clEnqueueReleaseD3D11ObjectsKHR</strong> provides the synchronization
+guarantee that any calls to Direct3D 11 calls involving the interop
+device(s) used in the OpenCL context made after the call to
+<strong>clEnqueueReleaseD3D11ObjectsKHR</strong> will not start executing until after all
+events in <em>event_wait_list</em> are complete and all work already submitted to
+<em>command_queue</em> completes execution.
+If the context was created with properties specifying
+CL_CONTEXT_INTEROP_USER_SYNC as CL_TRUE, the user is responsible for
+guaranteeing that any Direct3D 11 calls involving the interop device(s) used
+in the OpenCL context made after <strong>clEnqueueReleaseD3D11ObjectsKHR</strong> will not
+start executing until after event returned by
+<strong>clEnqueueReleaseD3D11ObjectsKHR</strong> reports completion.</p>
+</div>
+<div class="paragraph">
+<p><em>num_objects</em> is the number of memory objects to be released in
+<em>mem_objects</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>mem_objects</em> is a pointer to a list of OpenCL memory objects that were
+created from Direct3D 11 resources.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before this particular command can be executed.
+If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait
+on any event to complete.
+If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event</em> returns an event object that identifies this
+particular command and can be used to query or queue a wait for this
+particular command to complete.
+<em>event</em> can be <code>NULL</code> in which case it will not be possible for the
+application to query the status of this command or queue a wait for this
+command to complete.
+If the <em>event_wait_list</em> and the <em>event</em> arguments are not <code>NULL</code>, the
+<em>event</em> argument should not refer to an element of the <em>event_wait_list</em>
+array.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueReleaseD3D11ObjectsKHR</strong> returns CL_SUCCESS if the function is
+executed successfully.
+If <em>num_objects</em> is 0 and <em>mem_objects</em> is <code>NULL</code> the function does nothing
+and returns CL_SUCCESS.
+Otherwise it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_VALUE if <em>num_objects</em> is zero and <em>mem_objects</em> is not a
+<code>NULL</code> value or if <em>num_objects</em> &gt; 0 and <em>mem_objects</em> is <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_MEM_OBJECT if memory objects in <em>mem_objects</em> are not valid
+OpenCL memory objects or if memory objects in <em>mem_objects</em> have not
+been created from Direct3D 11 resources.</p>
+</li>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_CONTEXT if context associated with <em>command_queue</em> was not
+created from a Direct3D 11 device.</p>
+</li>
+<li>
+<p>CL_D3D11_RESOURCE_NOT_ACQUIRED_KHR if memory objects in <em>mem_objects</em>
+have not previously been acquired using
+<strong>clEnqueueAcquireD3D11ObjectsKHR</strong>, or have been released using
+<strong>clEnqueueReleaseD3D11ObjectsKHR</strong> since the last time that they were
+acquired.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em>&gt; is 0, or if event objects in
+<em>event_wait_list</em> are not valid events.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div style="page-break-after: always;"></div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="cl_khr_gl_depth_images">9. Sharing OpenGL and OpenGL ES Depth and Depth-Stencil Images</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>This section describes the <strong>cl_khr_gl_depth_images</strong> extension.
+The <strong>cl_khr_gl_depth_images</strong> extends OpenCL / OpenGL sharing (the
+cl_khr_gl_sharing_extension) defined in
+<a href="#cl_khr_gl_sharing__memobjs">Creating OpenCL Memory Objects from OpenGL
+Objects</a> to allow an OpenCL image to be created from an OpenGL depth or
+depth-stencil texture.</p>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_gl_depth_images-additions-to-chapter-5">9.1. Additions to Chapter 5 of the OpenCL 2.2 Specification</h3>
+<div class="paragraph">
+<p>The <strong>cl_khr_gl_depth_images</strong> extension extends OpenCL / OpenGL sharing by
+allowing an OpenCL depth image to be created from an OpenGL depth or
+depth-stencil texture.
+Depth images with an image channel order of CL_DEPTH_STENCIL can only be
+created using the <strong>clCreateFromGLTexture</strong> API.</p>
+</div>
+<div class="paragraph">
+<p>This extension adds the following new image format for depth-stencil images
+to <em>table 5.6 and 5.7</em> of the OpenCL 2.2 specification.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 100%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Enum values that can be specified in channel_order</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEPTH_STENCIL</strong>.
+  This format can only be used if channel data type = CL_UNORM_INT24 or
+  CL_FLOAT.</p></td>
+</tr>
+</tbody>
+</table>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Image Channel Data Type</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_UNORM_INT24</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Each channel component is a normalized unsigned 24-bit integer value</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_FLOAT</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Each channel component is a single precision floating-point value</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>This extension adds the following new image format to the minimum list of
+supported image formats described in <em>tables 5.8.a</em> and <em>5.8.b</em>.</p>
+</div>
+<table id="cl_khr_gl_depth_images-required-image-formats" class="tableblock frame-all grid-all spread">
+<caption class="title">Table 25. <em>Required Image Formats for</em> <strong>cl_khr_gl_depth_images</strong></caption>
+<colgroup>
+<col style="width: 25%;">
+<col style="width: 25%;">
+<col style="width: 25%;">
+<col style="width: 25%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>num_channels</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>channel_order</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>channel_data_type</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>read / write</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">1</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEPTH_STENCIL</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_UNORM_INT24<br>
+  CL_FLOAT</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">read only</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>For the image format given by channel order of CL_DEPTH_STENCIL and channel
+data type of CL_UNORM_INT24, the depth is stored as an unsigned normalized
+24-bit value.</p>
+</div>
+<div class="paragraph">
+<p>For the image format given by channel order of CL DEPTH_STENCIL and channel
+data type of CL_FLOAT, each pixel is two 32-bit values.
+The depth is stored as a single precision floating-point value followed by
+the stencil which is stored as a 8-bit integer value.</p>
+</div>
+<div class="paragraph">
+<p>The stencil value cannot be read or written using the <strong>read_imagef</strong> and
+<strong>write_imagef</strong> built-in functions in an OpenCL kernel.</p>
+</div>
+<div class="paragraph">
+<p>Depth image objects with an image channel order equal to CL_DEPTH_STENCIL
+cannot be used as arguments to clEnqueueReadImage, clEnqueueWriteImage,
+clEnqueueCopyImage, clEnqueueCopyImageToBuffer, clEnqueueCopyBufferToImage,
+clEnqueueMapImage and clEnqueueFillImage and will return a
+CL_INVALID_OPERATION error.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_gl_depth_images-additions-to-extension-specification">9.2. Additions to the OpenCL Extension Specification</h3>
+<div class="paragraph">
+<p>The following new image formats are added to the table of
+<a href="#cl_khr_gl_sharing__memobjs-mapping-of-image-formats">OpenGL internal
+formats and corresponding OpenCL internal formats</a> in the OpenCL extension
+specification.
+If an OpenGL texture object with an internal format in this table is
+successfully created by OpenGL, then there is guaranteed to be a mapping to
+one of the corresponding OpenCL image format(s) in that table.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>GL internal format</strong></th>
+<th class="tableblock halign-left valign-top"><strong>CL image format</strong>
+
+  <strong>(channel order, channel data type)</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_DEPTH_COMPONENT32F</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEPTH, CL_FLOAT</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_DEPTH_COMPONENT16</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEPTH, CL_UNORM_INT16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_DEPTH24_STENCIL8</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEPTH_STENCIL, CL_UNORM_INT24</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GL_DEPTH32F_STENCIL8</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_DEPTH_STENCIL, CL_FLOAT</p></td>
+</tr>
+</tbody>
+</table>
+<div style="page-break-after: always;"></div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="cl_khr_gl_msaa_sharing">10. Creating OpenCL Memory Obejcts from OpenGL MSAA Textures</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>This extension extends the OpenCL / OpenGL sharing (the
+cl_khr_gl_sharing_extension) defined in
+<a href="#cl_khr_gl_sharing__memobjs">Creating OpenCL Memory Objects from OpenGL
+Objects</a> to allow an OpenCL image to be created from an OpenGL
+multi-sampled (a.k.a.
+MSAA) texture (color or depth).</p>
+</div>
+<div class="paragraph">
+<p>This extension name is <strong>cl_khr_gl_msaa_sharing</strong>.
+This extension requires <strong>cl_khr_gl_depth_images</strong>.</p>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_gl_msaa_sharing-additions-to-extension-specification">10.1. Additions to the OpenCL Extension Specification</h3>
+<div class="paragraph">
+<p>Allow <em>texture_target</em> argument to <strong>clCreateFromGLTexture</strong> to be
+GL_TEXTURE_2D_MULTISAMPLE or GL_TEXTURE_2D_MULTISAMPLE_ARRAY.</p>
+</div>
+<div class="paragraph">
+<p>If <em>texture_target</em> is GL_TEXTURE_2D_MULTISAMPLE, <strong>clCreateFromGLTexture</strong>
+creates an OpenCL 2D multi-sample image object from an OpenGL 2D
+multi-sample texture.</p>
+</div>
+<div class="paragraph">
+<p>If <em>texture_target</em> is GL_TEXTURE_2D_MULTISAMPLE_ARRAY,
+<strong>clCreateFromGLTexture</strong> creates an OpenCL 2D multi-sample array image object
+from an OpenGL 2D multi-sample texture.</p>
+</div>
+<div class="paragraph">
+<p>Multi-sample OpenCL image objects can only be read from a kernel.
+Multi-sample OpenCL image objects cannot be used as arguments to
+clEnqueueReadImage , clEnqueueWriteImage, clEnqueueCopyImage,
+clEnqueueCopyImageToBuffer, clEnqueueCopyBufferToImage, clEnqueueMapImage
+and clEnqueueFillImage and will return a CL_INVALID_OPERATION error.</p>
+</div>
+<div class="paragraph">
+<p><strong>Add the following entry to the table describing
+<a href="#cl_khr_gl_sharing__memobjs-clGetGLTextureInfo-queries">OpenGL texture info
+that may be queried with clGetGLTextureInfo</a>:</strong></p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 33.3333%;">
+<col style="width: 33.3333%;">
+<col style="width: 33.3334%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_gl_texture_info</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Return Type</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Info. returned in <em>param_value</em></strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_GL_NUM_SAMPLES</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">GLsizei</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The <em>samples</em> argument passed to <strong>glTexImage2DMultisample</strong> or
+  <strong>glTexImage3DMultisample</strong>.</p>
+<p class="tableblock">  If <em>image</em> is not a MSAA texture, 1 is returned.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_gl_msaa_sharing-additions-to-chapter-5">10.2. Additions to Chapter 5 of the OpenCL 2.2 Specification</h3>
+<div class="paragraph">
+<p>The formats described in tables 5.8.a and 5.8.b of the OpenCL 2.2
+specification and the additional formats described in
+<a href="#cl_khr_gl_depth_images-required-image-formats">required image formats for
+cl_khr_gl_depth_images</a> also support OpenCL images created from a OpenGL
+multi-sampled color or depth texture.</p>
+</div>
+<div class="paragraph">
+<p><strong>Update text that describes arg value argument to clSetKernelArg with the
+following:</strong></p>
+</div>
+<div class="paragraph">
+<p>&#8220;If the argument is a multi-sample 2D image, the <em>arg_value</em> entry must be
+a pointer to a multi-sample image object.
+If the argument is a multi-sample 2D depth image, the <em>arg_value</em> entry must
+be a pointer to a multisample depth image object.
+If the argument is a multi-sample 2D image array, the <em>arg_value</em> entry must
+be a pointer to a multi-sample image array object.
+If the argument is a multi-sample 2D depth image array, the <em>arg_value</em>
+entry must be a pointer to a multi-sample depth image array object.&#8221;</p>
+</div>
+<div class="paragraph">
+<p><strong>Updated error code text for clSetKernelArg is:</strong></p>
+</div>
+<div class="paragraph">
+<p><strong>Add the following text:</strong></p>
+</div>
+<div class="paragraph">
+<p>&#8220;CL_INVALID_MEM_OBJECT for an argument declared to be a multi-sample image,
+multi-sample image array, multi-sample depth image or a multi-sample depth
+image array and the argument value specified in <em>arg_value</em> does not follow
+the rules described above for a depth memory object or memory array object
+argument.&#8221;</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_gl_msaa_sharing-additions-to-chapter-6">10.3. Additions to Chapter 6 of the OpenCL 2.2 Specification</h3>
+<div class="paragraph">
+<p><strong>Add the following new data types to <em>table 6.3</em> in <em>section 6.1.3</em> of the
+OpenCL 2.2 specification:</strong></p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Type</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>image2d_msaa_t</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 2D multi-sample color image.
+  Refer to <em>section 6.13.14</em> for a detailed description of the built-in
+  functions that use this type.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>image2d_array_msaa_t</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 2D multi-sample color image array.
+  Refer to <em>section 6.13.14</em> for a detailed description of the built-in
+  functions that use this type.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>image2d_msaa_depth_t</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 2D multi-sample depth image.
+  Refer to <em>section 6.13.14</em> for a detailed description of the built-in
+  functions that use this type.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>image2d_array_msaa_depth_t</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A 2D multi-sample depth image array.
+  Refer to <em>section 6.13.14</em> for a detailed description of the built-in
+  functions that use this type.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p><strong>Add the following built-in functions to section 6.13.14.3&#8201;&#8212;&#8201;BuiltIn Image
+Sampler-less Read Functions:</strong></p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>float4 read_imagef(
+    image2d_msaa_t image,
+    int2 coord,
+    int sample)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Use the coordinate <em>(coord.x, coord.y)</em> and <em>sample</em> to do an element lookup
+in the 2D image object specified by <em>image</em>.</p>
+</div>
+<div class="paragraph">
+<p><strong>read_imagef</strong> returns floating-point values in the range [0.0 &#8230;&#8203; 1.0] for
+image objects created with <em>image_channel_data_type</em> set to one of the
+pre-defined packed formats or CL_UNORM_INT8, or CL_UNORM_INT16.</p>
+</div>
+<div class="paragraph">
+<p><strong>read_imagef</strong> returns floating-point values in the range [-1.0 &#8230;&#8203; 1.0] for
+image objects created with <em>image_channel_data_type</em> set to CL_SNORM_INT8,
+or CL_SNORM_INT16.</p>
+</div>
+<div class="paragraph">
+<p><strong>read_imagef</strong> returns floating-point values for image objects created with
+<em>image_channel_data_type</em> set to CL_HALF_FLOAT or CL_FLOAT.</p>
+</div>
+<div class="paragraph">
+<p>Values returned by <strong>read_imagef</strong> for image objects with
+<em>image_channel_data_type</em> values not specified in the description above are
+undefined.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int4 read_imagei(image2d_msaa_t image,
+                 int2 coord,
+                 int sample)
+
+uint4 read_imageui(image2d_msaa_t image,
+                   int2 coord,
+                   int sample)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Use the coordinate <em>(coord.x, coord.y)</em> and <em>sample</em> to do an element lookup
+in the 2D image object specified by <em>image</em>.</p>
+</div>
+<div class="paragraph">
+<p><strong>read_imagei</strong> and <strong>read_imageui</strong> return unnormalized signed integer and
+unsigned integer values respectively.
+Each channel will be stored in a 32-bit integer.</p>
+</div>
+<div class="paragraph">
+<p><strong>read_imagei</strong> can only be used with image objects created with
+<em>image_channel_data_type</em> set to one of the following values:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_SIGNED_INT8,</p>
+</li>
+<li>
+<p>CL_SIGNED_INT16, and</p>
+</li>
+<li>
+<p>CL_SIGNED_INT32.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If the <em>image_channel_data_type</em> is not one of the above values, the values
+returned by <strong>read_imagei</strong> are undefined.</p>
+</div>
+<div class="paragraph">
+<p><strong>read_imageui</strong> can only be used with image objects created with
+<em>image_channel_data_type</em> set to one of the following values:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_UNSIGNED_INT8,</p>
+</li>
+<li>
+<p>CL_UNSIGNED_INT16, and</p>
+</li>
+<li>
+<p>CL_UNSIGNED_INT32.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If the <em>image_channel_data_type</em> is not one of the above values, the values
+returned by <strong>read_imageui</strong> are undefined.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>float4 read_imagef(image2d_array_msaa_t image,
+                   int4 coord,
+                   int sample)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Use <em>coord.xy</em> and <em>sample</em> to do an element lookup in the 2D image
+identified by <em>coord.z</em> in the 2D image array specified by <em>image</em>.</p>
+</div>
+<div class="paragraph">
+<p><strong>read_imagef</strong> returns floating-point values in the range [0.0 &#8230;&#8203; 1.0] for
+image objects created with <em>image_channel_data_type</em> set to one of the
+pre-defined packed formats or CL_UNORM_INT8, or CL_UNORM_INT16.</p>
+</div>
+<div class="paragraph">
+<p><strong>read_imagef</strong> returns floating-point values in the range [-1.0 &#8230;&#8203; 1.0] for
+image objects created with <em>image_channel_data_type</em> set to CL_SNORM_INT8,
+or CL_SNORM_INT16.</p>
+</div>
+<div class="paragraph">
+<p><strong>read_imagef</strong> returns floating-point values for image objects created with
+<em>image_channel_data_type</em> set to CL_HALF_FLOAT or CL_FLOAT.</p>
+</div>
+<div class="paragraph">
+<p>Values returned by <strong>read_imagef</strong> for image objects with
+<em>image_channel_data_type</em> values not specified in the description above are
+undefined.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int4 read_imagei(image2d_array_msaa_t image,
+                 int4 coord,
+                 int sample)
+
+uint4 read_imageui(image2d_array_msaa_t image,
+                   int4 coord,
+                   int sample)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Use <em>coord.xy</em> and <em>sample</em> to do an element lookup in the 2D image
+identified by <em>coord.z</em> in the 2D image array specified by <em>image</em>.</p>
+</div>
+<div class="paragraph">
+<p><strong>read_imagei</strong> and <strong>read_imageui</strong> return unnormalized signed integer and
+unsigned integer values respectively.
+Each channel will be stored in a 32-bit integer.</p>
+</div>
+<div class="paragraph">
+<p><strong>read_imagei</strong> can only be used with image objects created with
+<em>image_channel_data_type</em> set to one of the following values:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_SIGNED_INT8,</p>
+</li>
+<li>
+<p>CL_SIGNED_INT16, and</p>
+</li>
+<li>
+<p>CL_SIGNED_INT32.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If the <em>image_channel_data_type</em> is not one of the above values, the values
+returned by <strong>read_imagei</strong> are undefined.</p>
+</div>
+<div class="paragraph">
+<p><strong>read_imageui</strong> can only be used with image objects created with
+<em>image_channel_data_type</em> set to one of the following values:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_UNSIGNED_INT8,</p>
+</li>
+<li>
+<p>CL_UNSIGNED_INT16, and</p>
+</li>
+<li>
+<p>CL_UNSIGNED_INT32.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If the <em>image_channel_data_type</em> is not one of the above values, the values
+returned by <strong>read_imageui</strong> are undefined.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>float read_imagef(image2d_msaa_depth_t image,
+                  int2 coord,
+                  int sample)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Use the coordinate <em>(coord.x, coord.y)</em> and <em>sample</em> to do an element lookup
+in the 2D depth image object specified by <em>image</em>.</p>
+</div>
+<div class="paragraph">
+<p><strong>read_imagef</strong> returns a floating-point value in the range [0.0 &#8230;&#8203; 1.0] for
+depth image objects created with <em>image_channel_data_type</em> set to
+CL_UNORM_INT16 or CL_UNORM_INT24.</p>
+</div>
+<div class="paragraph">
+<p><strong>read_imagef</strong> returns a floating-point value for depth image objects created
+with <em>image_channel_data_type</em> set to CL_FLOAT.</p>
+</div>
+<div class="paragraph">
+<p>Values returned by <strong>read_imagef</strong> for image objects with
+<em>image_channel_data_type</em> values not specified in the description above are
+undefined.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>float read_imagef(image2d_array_msaaa_depth_t image,
+                  int4 coord,
+                  int sample)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Use <em>coord.xy</em> and <em>sample</em> to do an element lookup in the 2D image
+identified by <em>coord.z</em> in the 2D depth image array specified by <em>image</em>.</p>
+</div>
+<div class="paragraph">
+<p><strong>read_imagef</strong> returns a floating-point value in the range [0.0 &#8230;&#8203; 1.0] for
+depth image objects created with <em>image_channel_data_type</em> set to
+CL_UNORM_INT16 or CL_UNORM_INT24.</p>
+</div>
+<div class="paragraph">
+<p><strong>read_imagef</strong> returns a floating-point value for depth image objects created
+with <em>image_channel_data_type</em> set to CL_FLOAT.</p>
+</div>
+<div class="paragraph">
+<p>Values returned by <strong>read_imagef</strong> for image objects with
+<em>image_channel_data_type</em> values not specified in the description above are
+undefined.</p>
+</div>
+<div class="paragraph">
+<p>Note: When a multisample image is accessed in a kernel, the access takes one
+vector of integers describing which pixel to fetch and an integer
+corresponding to the sample numbers describing which sample within the pixel
+to fetch.
+sample identifies the sample position in the multi-sample image.</p>
+</div>
+<div class="paragraph">
+<p><strong>For best performance, we recommend that <em>sample</em> be a literal value so it
+is known at compile time and the OpenCL compiler can perform appropriate
+optimizations for multi-sample reads on the device</strong>.</p>
+</div>
+<div class="paragraph">
+<p>No standard sampling instructions are allowed on the multisample image.
+Accessing a coordinate outside the image and/or a sample that is outside the
+number of samples associated with each pixel in the image is undefined</p>
+</div>
+<div class="paragraph">
+<p><strong>Add the following built-in functions to section 6.13.14.5&#8201;&#8212;&#8201;BuiltIn Image
+Query Functions:</strong></p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int get_image_width(image2d_msaa_t image)
+
+int get_image_width(image2d_array_msaa_t image)
+
+int get_image_width(image2d_msaa_depth_t image)
+
+int get_image_width(image2d_array_msaa_depth_t image)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Return the image width in pixels.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int get_image_height(image2d_msaa_t image)
+
+int get_image_height(image2d_array_msaa_t image)
+
+int get_image_height(image2d_msaa_depth_t image)
+
+int get_image_height(image2d_array_msaa_depth_t image)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Return the image height in pixels.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int get_image_channel_data_type(image2d_msaa_t image)
+
+int get_image_channel_data_type(image2d_array_msaa_t image)
+
+int get_image_channel_data_type(image2d_msaa_depth_t image)
+
+int get_image_channel_data_type(image2d_array_msaa_depth_t image)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Return the channel data type.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int get_image_channel_order(image2d_msaa_t image)
+
+int get_image_channel_order(image2d_array_msaa_t image)
+
+int get_image_channel_order(image2d_msaa_depth_t image)
+
+int get_image_channel_order(image2d_array_msaa_depth_t image)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Return the image channel order.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int2 get_image_dim(image2d_msaa_t image)
+
+int2 get_image_dim(image2d_array_msaa_t image)
+
+int2 get_image_dim(image2d_msaa_depth_t image)
+
+int2 get_image_dim(image2d_array_msaa_depth_t image)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Return the 2D image width and height as an int2 type.
+The width is returned in the <em>x</em> component, and the height in the <em>y</em>
+component.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>size_t get_image_array_size(image2d_array_msaa_depth_t image)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Return the number of images in the 2D image array.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>int get_image_num_samples(image2d_msaa_t image)
+
+int get_image_num_samples(image2d_array_msaa_t image)
+
+int get_image_num_samples(image2d_msaa_depth_t image)
+
+int get_image_num_samples(image2d_array_msaa_depth_t image)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Return the number of samples in the 2D MSAA image</p>
+</div>
+<div style="page-break-after: always;"></div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="cl_khr_initialize_memory">11. Local and Private Memory Initialization</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>Memory is allocated in various forms in OpenCL both explicitly (global
+memory) or implicitly (local, private memory).
+This allocation so far does not provide a straightforward mechanism to
+initialize the memory on allocation.
+In other words what is lacking is the equivalent of calloc for the currently
+supported malloc like capability.
+This functionality is useful for a variety of reasons including ease of
+debugging, application controlled limiting of visibility to previous
+contents of memory and in some cases, optimization</p>
+</div>
+<div class="paragraph">
+<p>This extension adds support for initializing local and private memory before
+a kernel begins execution.
+This extension name is <strong>cl_khr_initialize_memory</strong>.</p>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_initialize_memory-additions-to-chapter-4">11.1. Additions to Chapter 4 of the OpenCL 2.2 Specification</h3>
+<div class="paragraph">
+<p>Add a new context property to <em>table 4.5</em> in <em>section 4.4</em>.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 33.3333%;">
+<col style="width: 22.2222%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_context_properties enum</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Property value</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_CONTEXT_MEMORY_INITIALIZE_KHR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_context_memory_initialize_khr</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Describes which memory types for the context must be initialized.
+  This is a bit-field, where the following values are currently supported:</p>
+<p class="tableblock">  CL_CONTEXT_MEMORY_INITIALIZE_LOCAL_KHR&#8201;&#8212;&#8201;Initialize local memory to
+  zeros.</p>
+<p class="tableblock">  CL_CONTEXT_MEMORY_INITIALIZE_PRIVATE_KHR&#8201;&#8212;&#8201;Initialize private memory to
+  zeros.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_initialize_memory-additions-to-chapter-6">11.2. Additions to Chapter 6 of the OpenCL 2.2 Specification</h3>
+<div class="paragraph">
+<p>Updates to <em>section 6.9</em>&#8201;&#8212;&#8201;Restrictions</p>
+</div>
+<div class="paragraph">
+<p>If the context is created with CL CONTEXT MEMORY INITIALIZE KHR, appropriate
+memory locations as specified by the bit-field is initialized with zeroes,
+prior to the start of execution of any kernel.
+The driver chooses when, prior to kernel execution, the initialization of
+local and/or private memory is performed.
+The only requirement is there should be no values set from outside the
+context, which can be read during a kernel execution.</p>
+</div>
+<div style="page-break-after: always;"></div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="cl_khr_terminate_context">12. Terminating OpenCL contexts</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>Today, OpenCL provides an API to release a context.
+This operation is done only after all queues, memory object, programs and
+kernels are released, which in turn might wait for all ongoing operations to
+complete.
+However, there are cases in which a fast release is required, or release
+operation cannot be done, as commands are stuck in mid execution.
+An example of the first case can be program termination due to exception, or
+quick shutdown due to low power.
+Examples of the second case are when a kernel is running too long, or gets
+stuck, or it may result from user action which makes the results of the
+computation unnecessary.</p>
+</div>
+<div class="paragraph">
+<p>In many cases, the driver or the device is capable of speeding up the
+closure of ongoing operations when the results are no longer required in a
+much more expedient manner than waiting for all previously enqueued
+operations to finish.</p>
+</div>
+<div class="paragraph">
+<p>This extension implements a new query to check whether a device can
+terminate an OpenCL context and adds an API to terminate a context.</p>
+</div>
+<div class="paragraph">
+<p>The extension name is <strong>cl_khr_terminate_context</strong>.</p>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_terminate_context-additions-to-chapter-4">12.1. Additions to Chapter 4 of the OpenCL 2.2 Specification</h3>
+<div class="paragraph">
+<p>Add a new device property to <em>table 4.3</em> in <em>section 4.2</em>.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 33.3333%;">
+<col style="width: 22.2222%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_device_info</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Return Type</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_TERMINATE_CAPABILITY_KHR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cl_device_terminate_capability_khr</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Describes the termination capability of the OpenCL device.
+  This is a bit-field, where the following values are currently supported:</p>
+<p class="tableblock">  CL_DEVICE_TERMINATE_CAPABILITY_CONTEXT_KHR - Indicates that context
+  termination is supported.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>Add a new context property to <em>table 4.5</em> in <em>section 4.4</em>.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 33.3333%;">
+<col style="width: 22.2222%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_context_properties enum</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Property value</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_CONTEXT_TERMINATE_KHR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cl_bool</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Specifies whether the context can be terminated.
+  The default value is CL_FALSE.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>CL_CONTEXT_TERMINATE_KHR can be specified in the context properties only if
+all devices associated with the context support the ability to support
+context termination (i.e. CL_DEVICE_TERMINATE_CAPABILITY_CONTEXT_KHR is set
+for CL_DEVICE_TERMINATE_CAPABILITY_KHR).
+Otherwise, context creation fails with error code of CL_INVALID_PROPERTY.</p>
+</div>
+<div class="paragraph">
+<p>The new function
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_int clTerminateContextKHR(cl context context)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>terminates all pending work associated with the context and renders all data
+owned by the context invalid.
+It is the responsibility of the application to release all objects
+associated with the context being terminated.</p>
+</div>
+<div class="paragraph">
+<p>When a context is terminated:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>The execution status of enqueued commands will be CL_TERMINATED_KHR.
+Event objects can be queried using <strong>clGetEventInfo</strong>.
+Event callbacks can be registered and registered event callbacks will be
+called with <em>event_command_exec_status</em> set to CL_TERMINATED_KHR.
+<strong>clWaitForEvents</strong> will return as immediately for commands associated
+with event objects specified in event_list.
+The status of user events can be set.
+Event objects can be retained and released.
+<strong>clGetEventProfilingInfo</strong> returns CL_PROFILING_INFO_NOT_AVAILABLE.</p>
+</li>
+<li>
+<p>The context is considered to be terminated.
+A callback function registered when the context was created will be
+called.
+Only queries, retain and release operations can be performed on the
+context.
+All other APIs that use a context as an argument will return
+CL_CONTEXT_TERMINATED_KHR.</p>
+</li>
+<li>
+<p>The contents of the memory regions of the memory objects is undefined.
+Queries, registering a destructor callback, retain and release
+operations can be performed on the memory objects.</p>
+</li>
+<li>
+<p>Once a context has been terminated, all OpenCL API calls that create
+objects or enqueue commands will return CL_CONTEXT_TERMINATED_KHR.
+APIs that release OpenCL objects will continue to operate as though
+<strong>clTerminateContextKHR</strong> was not called.</p>
+</li>
+<li>
+<p>The behavior of callbacks will remain unchanged, and will report
+appropriate error, if executing after termination of context.
+This behavior is similar to enqueued commands, after the command queue
+has become invalid.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p><strong>clTerminateContextKHR</strong> returns CL_SUCCESS if the function is executed
+successfully.
+Otherwise, it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_CONTEXT if <em>context</em> is not a valid OpenCL context.</p>
+</li>
+<li>
+<p>CL_CONTEXT_TERMINATED_KHR if <em>context</em> has already been terminated.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if <em>context</em> was not created with
+CL_CONTEXT_TERMNATE_KHR set to CL_TRUE.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>An implementation that supports this extension must be able to terminate
+commands currently executing on devices or queued across all command-queues
+associated with the context that is being terminated.
+The implementation cannot implement this extension by waiting for currently
+executing (or queued) commands to finish execution on devices associated
+with this context (i.e. doing a <strong>clFinish</strong>).</p>
+</div>
+<div style="page-break-after: always;"></div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="cl_khr_spir">13. SPIR 1.2 Binaries</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>This extension adds the ability to create an OpenCL program object from a
+Standard Portable Intermediate Representation (SPIR) instance.
+A SPIR instance is a vendor-neutral non-source representation for OpenCL C
+programs.</p>
+</div>
+<div class="paragraph">
+<p>The extension name is <strong>cl_khr_spir</strong>.
+This extension has been superseded by the SPIR-V intermediate
+representation, which became a core feature in OpenCL 2.1.</p>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_spir-additions-to-chapter-4">13.1. Additions to Chapter 4 of the OpenCL 2.2 Specification</h3>
+<div class="paragraph">
+<p><strong>Add a new device property to <em>table 4.3</em> in <em>section 4.2</em>:</strong></p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 28.5714%;">
+<col style="width: 14.2857%;">
+<col style="width: 57.1429%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_device_info</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Return Type</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_SPIR_VERSIONS</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A space separated list of SPIR versions supported by the device.</p>
+<p class="tableblock">  For example, returning <code>"1.2"</code> in this query implies that SPIR version 1.2
+  is supported by the implementation.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_spir-additions-to-chapter-5">13.2. Additions to Chapter 5 of the OpenCL 2.2 Specification</h3>
+<div class="paragraph">
+<p><strong>Additions to <em>section 5.8.1</em>&#8201;&#8212;&#8201;Creating Program Objects:</strong></p>
+</div>
+<div class="paragraph">
+<p>&#8220;<strong>clCreateProgramWithBinary</strong> can be used to load a SPIR binary.
+Once a program object has been created from a SPIR binary, <strong>clBuildProgram</strong>
+can be called to build a program executable or <strong>clCompileProgram</strong> can be
+called to compile the SPIR binary.&#8221;</p>
+</div>
+<div class="paragraph">
+<p>Modify the CL_PROGRAM_BINARY_TYPE entry in <em>table 5.14</em>
+(<strong>clGetProgramBuildInfo</strong>) to add a potential value
+CL_PROGRAM_BINARY_TYPE_INTERMEDIATE:</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 28.5714%;">
+<col style="width: 14.2857%;">
+<col style="width: 57.1429%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_program_build_info</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Return Type</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Info. returned in <em>param_value</em></strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PROGRAM_BINARY_TYPE</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cl_program_binary_type</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_PROGRAM_BINARY_TYPE_INTERMEDIATE&#8201;&#8212;&#8201;An intermediate (non-source)
+  representation for the program is loaded as a binary.
+  The program must be further processed with <strong>clCompileProgram</strong> or
+  <strong>clBuildProgram</strong>.</p>
+<p class="tableblock">  If processed with <strong>clCompileProgram</strong>, the result will be a binary of type
+  CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT or CL_PROGRAM_BINARY_TYPE_LIBRARY.
+  If processed with <strong>clBuildProgram</strong>, the result will be a binary of type
+  CL_PROGRAM_BINARY_TYPE_EXECUTABLE.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p><strong>Additions to <em>section 5.8.4</em>&#8201;&#8212;&#8201;Compiler Options:</strong></p>
+</div>
+<div class="paragraph">
+<p>&#8220;The compile option <strong>-x spir</strong> must be specified to indicate that the binary
+is in SPIR format, and the compile option <strong>-spir-std</strong> must be used to
+specify the version of the SPIR specification that describes the format and
+meaning of the binary.
+For example, if the binary is as described in SPIR version 1.2, then
+<strong>-spir-std=1.2</strong> must be specified.
+Failing to specify these compile options may result in implementation
+defined behavior.&#8221;</p>
+</div>
+<div class="paragraph">
+<p><strong>Additions to <em>section 5.9.3</em>&#8201;&#8212;&#8201;Kernel Object Queries:</strong></p>
+</div>
+<div class="paragraph">
+<p>Modify following text in clGetKernelArgInfo from:</p>
+</div>
+<div class="paragraph">
+<p>&#8220;Kernel argument information is only available if the program object
+associated with <em>kernel</em> is created with <strong>clCreateProgramWithSource</strong> and the
+program executable is built with the -cl-kernel-arg-info option specified in
+<em>options</em> argument to <strong>clBuildProgram</strong> or <strong>clCompileProgram</strong>.&#8221;</p>
+</div>
+<div class="paragraph">
+<p>to:</p>
+</div>
+<div class="paragraph">
+<p>&#8220;Kernel argument information is only available if the program object
+associated with <em>kernel</em> is created with <strong>clCreateProgramWithSource</strong> and the
+program executable is built with the -cl-kernel-arg-info option specified in
+<em>options</em> argument to <strong>clBuildProgram</strong> or <strong>clCompileProgram</strong>, or if the
+program object associated with <em>kernel</em> is created with
+<strong>clCreateProgramWithBinary</strong> and the program executable is built with the
+-cl-kernel-arg-info and --x spir options specified in <em>options</em> argument to
+<strong>clBuildProgram</strong> or <strong>clCompileProgram</strong>.&#8221;</p>
+</div>
+<div style="page-break-after: always;"></div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="cl_khr_icd-opencl">14. OpenCL Installable Client Driver (ICD)</h2>
+<div class="sectionbody">
+<div class="sect2">
+<h3 id="cl_khr_icd-overview">14.1. Overview</h3>
+<div class="paragraph">
+<p>This section describes a platform extension which defines a simple mechanism
+through which the Khronos OpenCL installable client driver loader (ICD
+Loader) may expose multiple separate vendor installable client drivers
+(Vendor ICDs) for OpenCL.
+An application written against the ICD Loader will be able to access all
+cl_platform_ids exposed by all vendor implementations with the ICD Loader
+acting as a demultiplexor.</p>
+</div>
+<div class="paragraph">
+<p>This is a platform extension, so if this extension is supported by an
+implementation, the string <strong>cl_khr_icd</strong> will be present in the
+<code>CL_PLATFORM_EXTENSIONS</code> string.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_icd-inferring-vendors-from-function-call-arguments">14.2. Inferring Vendors from Function Call Arguments</h3>
+<div class="paragraph">
+<p>At every OpenCL function call, the ICD Loader infers the vendor ICD function
+to call from the arguments to the function.
+An object is said to be ICD compatible if it is of the following structure:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>struct _cl_&lt;object&gt;
+{
+    struct _cl_icd_dispatch *dispatch;
+    // ... remainder of internal data
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>&lt;object&gt; is one of platform_id, device_id, context, command_queue, mem,
+program, kernel, event, or sampler.</p>
+</div>
+<div class="paragraph">
+<p>The structure <code>_cl_icd_dispatch</code> is a function pointer dispatch table which
+is used to direct calls to a particular vendor implementation.
+All objects created from ICD compatible objects must be ICD compatible.</p>
+</div>
+<div class="paragraph">
+<p>The order of the functions in <code>_cl_icd_dispatch</code> is determined by the ICD
+Loader&#8217;s source.
+The ICD Loader&#8217;s source&#8217;s <code>_cl_icd_dispatch</code> table is to be appended to
+only.</p>
+</div>
+<div class="paragraph">
+<p>Functions which do not have an argument from which the vendor implementation
+may be inferred have been deprecated and may be ignored.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_icd-icd-data">14.3. ICD Data</h3>
+<div class="paragraph">
+<p>A Vendor ICD is defined by two pieces of data:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>The Vendor ICD library specifies a library which contains the OpenCL
+entry points for the vendor&#8217;s OpenCL implementation.
+The vendor ICD&#8217;s library file name should include the vendor name, or a
+vendor-specific implementation identifier.</p>
+</li>
+<li>
+<p>The Vendor ICD extension suffix is a short string which specifies the
+default suffix for extensions implemented only by that vendor.
+The vendor suffix string is optional.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_icd-icd-loader-vendor-enumeration-on-windows">14.4. ICD Loader Vendor Enumeration on Windows</h3>
+<div class="paragraph">
+<p>To enumerate Vendor ICDs on Windows, the ICD Loader will first
+scan for REG_SZ string values in the "Display Adapter" and
+"Software Components" HKR registry keys.  The exact registry
+keys to scan should be obtained via PnP Configuration Manager
+APIs, but will look like:</p>
+</div>
+<div class="paragraph">
+<p>For 64-bit ICDs:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>HKLM\SYSTEM\CurrentControlSet\Control\Class\
+{Display Adapter GUID}\{Instance ID}\OpenCLDriverName, or
+
+HKLM\SYSTEM\CurrentControlSet\Control\Class\
+{Software Component GUID}\{Instance ID}\OpenCLDriverName</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>For 32-bit ICDs:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>HKLM\SYSTEM\CurrentControlSet\Control\Class\
+{Display Adapter GUID}\{Instance ID}\OpenCLDriverNameWoW, or
+
+HKLM\SYSTEM\CurrentControlSet\Control\Class\
+{Software Component GUID}\{Instance ID}\OpenCLDriverNameWoW</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>These registry values contain the path to the Vendor ICD library.
+For example, if the registry contains the value:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>[HKLM\SYSTEM\CurrentControlSet\Control\Class\{GUID}\{Instance}]
+"OpenCLDriverName"="c:\\vendor a\\vndra_ocl.dll"</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Then the ICD Loader will open the Vendor ICD library:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>c:\vendor a\vndra_ocl.dll</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The ICD Loader will also scan for REG_DWORD values in the registry
+key:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>HKLM\SOFTWARE\Khronos\OpenCL\Vendors</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>For each registry value in this key which has data set to 0, the
+ICD Loader will open the Vendor ICD library specified by the name
+of the registry value.</p>
+</div>
+<div class="paragraph">
+<p>For example, if the registry contains the value:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>[HKLM\SOFTWARE\Khronos\OpenCL\Vendors]
+"c:\\vendor a\\vndra_ocl.dll"=dword:00000000</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Then the ICD will open the Vendor ICD library:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>c:\vendor a\vndra_ocl.dll</pre>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_icd-icd-loader-vendor-enumeration-on-linux">14.5. ICD Loader Vendor Enumeration on Linux</h3>
+<div class="paragraph">
+<p>To enumerate vendor ICDs on Linux, the ICD Loader scans the files in the
+path <code>/etc/OpenCL/vendors</code>.
+For each file in this path, the ICD Loader opens the file as a text file.
+The expected format for the file is a single line of text which specifies
+the Vendor ICD&#8217;s library.
+The ICD Loader will attempt to open that file as a shared object using
+dlopen().
+Note that the library specified may be an absolute path or just a file name.</p>
+</div>
+<div class="paragraph">
+<p>For example, if the following file exists</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>/etc/OpenCL/vendors/VendorA.icd</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>and contains the text</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>libVendorAOpenCL.so</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>then the ICD Loader will load the library <code>libVendorAOpenCL.so</code>.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_icd-icd-loader-vendor-enumeration-on-android">14.6. ICD Loader Vendor Enumeration on Android</h3>
+<div class="paragraph">
+<p>To enumerate vendor ICDs on Android, the ICD Loader scans the files in the
+path <code>/system/vendor/Khronos/OpenCL/vendors</code>.
+For each file in this path, the ICD Loader opens the file as a text file.
+The expected format for the file is a single line of text which specifies
+the Vendor ICD&#8217;s library.
+The ICD Loader will attempt to open that file as a shared object using
+dlopen().
+Note that the library specified may be an absolute path or just a file name.</p>
+</div>
+<div class="paragraph">
+<p>For example, if the following file exists</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>/system/vendor/Khronos/OpenCL/vendors/VendorA.icd</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>and contains the text</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>libVendorAOpenCL.so</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>then the ICD Loader will load the library <code>libVendorAOpenCL.so</code>.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_icd-adding-a-vendor-library">14.7. Adding a Vendor Library</h3>
+<div class="paragraph">
+<p>Upon successfully loading a Vendor ICD&#8217;s library, the ICD Loader queries the
+following functions from the library: <strong>clIcdGetPlatformIDsKHR</strong>,
+<strong>clGetPlatformInfo</strong>, and <strong>clGetExtensionFunctionAddress</strong> (note:
+<strong>clGetExtensionFunctionAddress</strong> has been deprecated, but is still required
+for the ICD loader).
+If any of these functions are not present then the ICD Loader will close and
+ignore the library.</p>
+</div>
+<div class="paragraph">
+<p>Next the ICD Loader queries available ICD-enabled platforms in the library
+using <strong>clIcdGetPlatformIDsKHR</strong>.
+For each of these platforms, the ICD Loader queries the platform&#8217;s extension
+string to verify that <strong>cl_khr_icd</strong> is supported, then queries the platform&#8217;s
+Vendor ICD extension suffix using <strong>clGetPlatformInfo</strong> with the value
+CL_PLATFORM_ICD_SUFFIX_KHR.</p>
+</div>
+<div class="paragraph">
+<p>If any of these steps fail, the ICD Loader will ignore the Vendor ICD and
+continue on to the next.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_icd-new-procedures-and-functions">14.8. New Procedures and Functions</h3>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_int clIcdGetPlatformIDsKHR(cl_uint num_entries,
+                              cl_platform_id *platforms,
+                              cl_uint *num_platforms);</code></pre>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_icd-new-tokens">14.9. New Tokens</h3>
+<div class="paragraph">
+<p>Accepted as <em>param_name</em> to the function <strong>clGetPlatformInfo</strong>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_PLATFORM_ICD_SUFFIX_KHR  0x0920</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returned by <strong>clGetPlatformIDs</strong> when no platforms are found:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_PLATFORM_NOT_FOUND_KHR   -1001</pre>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_icd-additions-to-chapter-4">14.10. Additions to Chapter 4 of the OpenCL 2.2 Specification</h3>
+<div class="paragraph">
+<p>In <em>section 4.1</em>, replace the description of the return values of
+<strong>clGetPlatformIDs</strong> with:</p>
+</div>
+<div class="paragraph">
+<p>"clGetPlatformIDs* returns CL_SUCCESS if the function is executed
+successfully and there are a non zero number of platforms available.
+It returns CL_PLATFORM_NOT_FOUND_KHR if zero platforms are available.
+It returns CL_INVALID_VALUE if <em>num_entries</em> is equal to zero and
+<em>platforms</em> is not <code>NULL</code> or if both <em>num_platforms</em> and <em>platforms</em> are
+<code>NULL</code>."</p>
+</div>
+<div class="paragraph">
+<p>In <em>section 4.1</em>, add the following after the description of
+<strong>clGetPlatformIDs</strong>:</p>
+</div>
+<div class="paragraph">
+<p>"The list of platforms accessible through the Khronos ICD Loader can be
+obtained using the following function:
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_int clIcdGetPlatformIDsKHR(cl_uint num_entries,
+                              cl_platform_id *platforms,
+                              cl_uint *num_platforms);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p><em>num_entries</em> is the number of cl_platform_id entries that can be added to
+<em>platforms</em>.
+If <em>platforms</em> is not <code>NULL</code>, then <em>num_entries</em> must be greater than zero.</p>
+</div>
+<div class="paragraph">
+<p><em>platforms</em> returns a list of OpenCL platforms available for access through
+the Khronos ICD Loader.
+The cl_platform_id values returned in <em>platforms</em> are ICD compatible and can
+be used to identify a specific OpenCL platform.
+If the <em>platforms</em> argument is <code>NULL</code>, then this argument is ignored.
+The number of OpenCL platforms returned is the minimum of the value
+specified by <em>num_entries</em> or the number of OpenCL platforms available.</p>
+</div>
+<div class="paragraph">
+<p><em>num_platforms</em> returns the number of OpenCL platforms available.
+If <em>num_platforms</em> is <code>NULL</code>, then this argument is ignored.</p>
+</div>
+<div class="paragraph">
+<p><strong>clIcdGetPlatformIDsKHR</strong> returns CL_SUCCESS if the function is executed
+successfully and there are a non zero number of platforms available.
+It returns CL_PLATFORM_NOT_FOUND_KHR if zero platforms are available.
+It returns CL_INVALID_VALUE if <em>num_entries</em> is equal to zero and
+<em>platforms</em> is not <code>NULL</code> or if both <em>num_platforms</em> and <em>platforms</em> are
+<code>NULL</code>."</p>
+</div>
+<div class="paragraph">
+<p>Add the following to <em>table 4.1</em>:</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 40%;">
+<col style="width: 20%;">
+<col style="width: 40%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_platform_info enum</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Return Type</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_PLATFORM_ICD_SUFFIX_KHR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">char[]</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The function name suffix used to identify extension functions to be
+  directed to this platform by the ICD Loader.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_icd-source-code">14.11. Source Code</h3>
+<div class="paragraph">
+<p>The official source for the ICD loader is available on github, at:</p>
+</div>
+<div class="paragraph">
+<p><a href="https://github.com/KhronosGroup/OpenCL-ICD-Loader" class="bare">https://github.com/KhronosGroup/OpenCL-ICD-Loader</a></p>
+</div>
+<div class="paragraph">
+<p>The complete <code>_cl_icd_dispatch</code> structure is defined in the header
+<strong>icd_dispatch.h</strong>, which is available as a part of the source code.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_icd-issues">14.12. Issues</h3>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>Some OpenCL functions do not take an object argument from which their
+vendor library may be identified (e.g, clUnloadCompiler), how will they
+be handled?</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>RESOLVED: Such functions will be a noop for all calls through the ICD.</p>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p>How are OpenCL extension to be handled?</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>RESOLVED: OpenCL extension functions may be added to the ICD as soon as they
+are implemented by any vendor.
+The suffix mechanism provides access for vendor extensions which are not yet
+added to the ICD.</p>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p>How will the ICD handle a <code>NULL</code> cl_platform_id?</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>RESOLVED: The ICD will by default choose the first enumerated platform as
+the <code>NULL</code> platform.
+The user can override this default by setting an environment variable
+OPENCL_ICD_DEFAULT_PLATFORM to the desired platform index.
+The API calls that deal with platforms will return CL_INVALID_PLATFORM if
+the index is not between zero and (number of platforms - 1), both inclusive.</p>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p>There exists no mechanism to unload the ICD, should there be one?</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>RESOLVED: As there is no standard mechanism for unloading a vendor
+implementation, do not add one for the ICD.</p>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p>How will the ICD loader handle <code>NULL</code> objects passed to the OpenCL
+functions?</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>RESOLVED: The ICD loader will check for <code>NULL</code> objects passed to the OpenCL
+functions without trying to dereference the <code>NULL</code> objects for obtaining the
+ICD dispatch table.
+On detecting a <code>NULL</code> object it will return one of the CL_INVALID_* error
+values corresponding to the object in question.</p>
+</div>
+</div>
+</div>
+</li>
+</ol>
+</div>
+<div style="page-break-after: always;"></div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="cl_khr_subgroups">15. Subgroups</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>This section describes the <strong>cl_khr_subgroups</strong> extension.</p>
+</div>
+<div class="paragraph">
+<p>This extension adds support for implementation-controlled groups of work
+items, known as subgroups.
+Subgroups behave similarly to work groups and have their own sets of
+builtins and synchronization primitives, but subgroups within a work group
+are independent, may make forward progress with respect to each other, and
+may map to optimized hardware structures where that makes sense.</p>
+</div>
+<div class="paragraph">
+<p>Subgroups became a core feature in OpenCL 2.1, so this section only
+describes changes to the OpenCL 2.0 C specification.
+Please refer to the OpenCL API specification for descriptions of the
+subgroups APIs, to the SPIR-V specification for information about using
+subgroups in the SPIR-V intermediate representation, and to the OpenCL C++
+specification for descriptions of OpenCL C++ subgroup built-in functions.</p>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_subgroups-additions-to-chapter-6-of-the-opencl-2.0-specification">15.1. Additions to Chapter 6 of the OpenCL 2.0 C Specification</h3>
+<div class="sect3">
+<h4 id="cl_khr_subgroups-additions-to-section-6.13.1-work-item-functions">15.1.1. Additions to section 6.13.1&#8201;&#8212;&#8201;Work Item Functions</h4>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Function</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><div><div class="paragraph">
+<p>uint <strong>get_sub_group_size</strong> ()</p>
+</div></div></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the number of work items in the subgroup.
+  This value is no more than the maximum subgroup size and is
+  implementation-defined based on a combination of the compiled kernel and
+  the dispatch dimensions.
+  This will be a constant value for the lifetime of the subgroup.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><div><div class="paragraph">
+<p>uint <strong>get_max_sub_group_size</strong> ()</p>
+</div></div></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the maximum size of a subgroup within the dispatch.
+  This value will be invariant for a given set of dispatch dimensions and a
+  kernel object compiled for a given device.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><div><div class="paragraph">
+<p>uint <strong>get_num_sub_groups</strong> ()</p>
+</div></div></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the number of subgroups that the current work group is divided
+  into.</p>
+<p class="tableblock">  This number will be constant for the duration of a work group&#8217;s execution.
+  If the kernel is executed with a non-uniform work group size
+  (i.e. the global_work_size values specified to <strong>clEnqueueNDRangeKernel</strong>
+  are not evenly divisible by the local_work_size values for any dimension,
+  calls to this built-in from some work groups may return different values
+  than calls to this built-in from other work groups.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><div><div class="paragraph">
+<p>uint <strong>get_enqueued_num_sub_groups</strong> ()</p>
+</div></div></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the same value as that returned by <strong>get_num_sub_groups</strong> if the
+  kernel is executed with a uniform work group size.</p>
+<p class="tableblock">  If the kernel is executed with a non-uniform work group size, returns the
+  number of subgroups in each of the work groups that make up the uniform
+  region of the global range.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><div><div class="paragraph">
+<p>uint <strong>get_sub_group_id</strong> ()</p>
+</div></div></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>get_sub_group_id</strong> returns the subgroup ID which is a number from 0 ..
+  <strong>get_num_sub_groups</strong>() - 1.</p>
+<p class="tableblock">  For <strong>clEnqueueTask</strong>, this returns 0.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><div><div class="paragraph">
+<p>uint <strong>get_sub_group_local_id</strong> ()</p>
+</div></div></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the unique work item ID within the current subgroup.
+  The mapping from <strong>get_local_id</strong>(<em>dimindx</em>) to <strong>get_sub_group_local_id</strong>
+  will be invariant for the lifetime of the work group.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_subgroups-additions-to-section-6.13.8-synchronization-functions">15.1.2. Additions to section 6.13.8&#8201;&#8212;&#8201;Synchronization Functions</h4>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Function</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>sub_group_barrier</strong> (<br>
+  cl_mem_fence_flags <em>flags</em>)</p>
+<p class="tableblock">  void <strong>sub_group_barrier</strong> (<br>
+  cl_mem_fence_flags <em>flags</em>, memory_scope <em>scope</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">All work items in a subgroup executing the kernel on a processor must
+  execute this function before any are allowed to continue execution beyond
+  the subgroup barrier.
+  This function must be encountered by all work items in a subgroup
+  executing the kernel.
+  These rules apply to ND-ranges implemented with uniform and non-uniform
+  work groups.</p>
+<p class="tableblock">  If <strong>subgroup_barrier</strong> is inside a conditional statement, then all work
+  items within the subgroup must enter the conditional if any work item in
+  the subgroup enters the conditional statement and executes the
+  subgroup_barrier.</p>
+<p class="tableblock">  If <strong>subgroup_barrier</strong> is inside a loop, all work items within the subgroup
+  must execute the subgroup_barrier for each iteration of the loop before
+  any are allowed to continue execution beyond the subgroup_barrier.</p>
+<p class="tableblock">  The <strong>subgroup_barrier</strong> function also queues a memory fence (reads and
+  writes) to ensure correct ordering of memory operations to local or global
+  memory.</p>
+<p class="tableblock">  The flags argument specifies the memory address space and can be set to a
+  combination of the following values:</p>
+<p class="tableblock">  CLK_LOCAL_MEM_FENCE - The <strong>subgroup_barrier</strong> function will either flush
+  any variables stored in local memory or queue a memory fence to ensure
+  correct ordering of memory operations to local memory.</p>
+<p class="tableblock">  CLK_GLOBAL_MEM_FENCE&#8201;&#8212;&#8201;The <strong>subgroup_barrier</strong> function will queue a
+  memory fence to ensure correct ordering of memory operations to global
+  memory.
+  This can be useful when work items, for example, write to buffer objects
+  and then want to read the updated data from these buffer objects.</p>
+<p class="tableblock">  CLK_IMAGE_MEM_FENCE&#8201;&#8212;&#8201;The <strong>subgroup_barrier</strong> function will queue a memory
+  fence to ensure correct ordering of memory operations to image objects.
+  This can be useful when work items, for example, write to image objects
+  and then want to read the updated data from these image objects.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_subgroups-additions-to-section-6.13.11-atomic-functions">15.1.3. Additions to section 6.13.11&#8201;&#8212;&#8201;Atomic Functions</h4>
+<div class="paragraph">
+<p>Add the following new value to the enumerated type <code>memory_scope</code> defined in
+<em>section 6.13.11.4</em>.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>memory_scope_sub_group</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The <code>memory_scope_sub_group</code> specifies that the memory ordering constraints
+given by <code>memory_order</code> apply to work items in a subgroup.
+This memory scope can be used when performing atomic operations to global or
+local memory.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_subgroups-additions-to-section-6.13.15-work-group-functions">15.1.4. Additions to section 6.13.15&#8201;&#8212;&#8201;Work Group Functions</h4>
+<div class="paragraph">
+<p>The OpenCL C programming language implements the following built-in
+functions that operate on a subgroup level.
+These built-in functions must be encountered by all work items in a subgroup
+executing the kernel.
+We use the generic type name <code>gentype</code> to indicate the built-in data types
+<code>half</code> (only if the <strong>cl_khr_fp16</strong> extension is supported), <code>int</code>,
+<code>uint</code>, <code>long</code>, <code>ulong</code>, <code>float</code> or <code>double</code> (only if double
+precision is supported) as the type for the arguments.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Function</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>sub_group_all</strong> (int <em>predicate</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Evaluates <em>predicate</em> for all work items in the subgroup and returns a
+  non-zero value if <em>predicate</em> evaluates to non-zero for all work items in
+  the subgroup.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>sub_group_any</strong> (int <em>predicate</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Evaluates <em>predicate</em> for all work items in the subgroup and returns a
+  non-zero value if <em>predicate</em> evaluates to non-zero for any work items in
+  the subgroup.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>sub_group_broadcast</strong> (<br>
+  gentype <em>x</em>, uint <em>sub_group_local_id</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Broadcast the value of <em>x</em> for work item identified by
+  <em>sub_group_local_id</em> (value returned by <strong>get_sub_group_local_id</strong>) to all
+  work items in the subgroup.</p>
+<p class="tableblock">  <em>sub_group_local_id</em> must be the same value for all work items in the
+  subgroup.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>sub_group_reduce_&lt;op&gt;</strong> (<br>
+  gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Return result of reduction operation specified by <strong>&lt;op&gt;</strong> for all values of
+  <em>x</em> specified by work items in a subgroup.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>sub_group_scan_exclusive_&lt;op&gt;</strong> (<br>
+  gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Do an exclusive scan operation specified by <strong>&lt;op&gt;</strong> of all values specified
+  by work items in a subgroup.
+  The scan results are returned for each work item.</p>
+<p class="tableblock">  The scan order is defined by increasing 1D linear global ID within the
+  subgroup.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">gentype <strong>sub_group_scan_inclusive_&lt;op&gt;</strong> (<br>
+  gentype <em>x</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Do an inclusive scan operation specified by <strong>&lt;op&gt;</strong> of all values specified
+  by work items in a subgroup.
+  The scan results are returned for each work item.</p>
+<p class="tableblock">  The scan order is defined by increasing 1D linear global ID within the
+  subgroup.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_subgroups-additions-to-section-6.13.16-pipe-functions">15.1.5. Additions to section 6.13.16&#8201;&#8212;&#8201;Pipe Functions</h4>
+<div class="paragraph">
+<p>The OpenCL C programming language implements the following built-in pipe
+functions that operate at a subgroup level.
+These built-in functions must be encountered by all work items in a subgroup
+executing the kernel with the same argument values; otherwise the behavior
+is undefined.
+We use the generic type name <code>gentype</code> to indicate the built-in OpenCL C
+scalar or vector integer or floating-point data types or any user defined
+type built from these scalar and vector data types can be used as the type
+for the arguments to the pipe functions listed in <em>table 6.29</em>.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Function</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">reserve_id_t <strong>sub_group_reserve_read_pipe</strong> (<br>
+  read_only pipe gentype <em>pipe</em>,<br>
+  uint <em>num_packets</em>)</p>
+<p class="tableblock">  reserve_id_t <strong>sub_group_reserve_write_pipe</strong> (<br>
+  write_only pipe gentype <em>pipe</em>,<br>
+  uint <em>num_packets</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Reserve <em>num_packets</em> entries for reading from or writing to <em>pipe</em>.
+  Returns a valid non-zero reservation ID if the reservation is successful
+  and 0 otherwise.</p>
+<p class="tableblock">  The reserved pipe entries are referred to by indices that go from 0 &#8230;&#8203;
+  <em>num_packets</em> - 1.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>sub_group_commit_read_pipe</strong> (<br>
+  read_only pipe gentype <em>pipe</em>,<br>
+  reserve_id_t <em>reserve_id</em>)</p>
+<p class="tableblock">  void <strong>sub_group_commit_write_pipe</strong> (<br>
+  write_only pipe gentype <em>pipe</em>,<br>
+  reserve_id_t <em>reserve_id</em>)</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Indicates that all reads and writes to <em>num_packets</em> associated with
+  reservation <em>reserve_id</em> are completed.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>Note: Reservations made by a subgroup are ordered in the pipe as they are
+ordered in the program.
+Reservations made by different subgroups that belong to the same work group
+can be ordered using subgroup synchronization.
+The order of subgroup based reservations that belong to different work
+groups is implementation defined.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_subgroups-additions-to-section-6.13.17.6-enqueuing-kernels-kernel-query-functions">15.1.6. Additions to section 6.13.17.6&#8201;&#8212;&#8201;Enqueuing Kernels (Kernel Query Functions)</h4>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 55.5555%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>Built-in Function</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">uint <strong>get_kernel_sub_group_count_for_ndrange</strong> (<br>
+  const ndrange_t <em>ndrange</em>,<br>
+  void (^block)(void));</p>
+<p class="tableblock">  uint <strong>get_kernel_sub_group_count_for_ndrange</strong> (<br>
+  const ndrange_t <em>ndrange</em>,<br>
+  void (^block)(local void *, &#8230;&#8203;));</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the number of subgroups in each work group of the dispatch (except
+  for the last in cases where the global size does not divide cleanly into
+  work groups) given the combination of the passed ndrange and block.</p>
+<p class="tableblock">  <em>block</em> specifies the block to be enqueued.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">uint <strong>get_kernel_max_sub_group_size_for_ndrange</strong> (<br>
+  const ndrange_t <em>ndrange</em>,<br>
+  void (^block)(void));<br></p>
+<p class="tableblock">  uint <strong>get_kernel_max_sub_group_size_for_ndrange</strong> (<br>
+  const ndrange_t <em>ndrange</em>,<br>
+  void (^block)(local void *, &#8230;&#8203;));</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the maximum subgroup size for a block.</p></td>
+</tr>
+</tbody>
+</table>
+<div style="page-break-after: always;"></div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="cl_khr_mipmap_image">16. Mipmaps</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>This section describes OpenCL support for mipmaps.</p>
+</div>
+<div class="paragraph">
+<p>There are two optional mipmap extensions.
+The <strong>cl_khr_mipmap_image</strong> extension adds the ability to create a mip-mapped
+image, enqueue commands to read/write/copy/map/unmap a region of a mipmapped
+image, and built-in functions that can be used to read a mip-mapped image in
+an OpenCL C program.
+The <strong>cl_khr_mipmap_image_writes</strong> extension adds built-in functions that can
+be used to write a mip-mapped image in an OpenCL C program.
+If the <strong>cl_khr_mipmap_image_writes</strong> extension is supported by the OpenCL
+device, the <strong>cl_khr_mipmap_image</strong> extension must also be supported.</p>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_mipmap_image-additions-to-chapter-5">16.1. Additions to Chapter 5 of the OpenCL 2.2 Specification</h3>
+<div class="sect3">
+<h4 id="cl_khr_mipmap_image-additions-to-section-5.3">16.1.1. Additions to section 5.3&#8201;&#8212;&#8201;Image Objects</h4>
+<div class="paragraph">
+<p>A mip-mapped 1D image, 1D image array, 2D image, 2D image array or 3D image
+is created by specifying <em>num_mip_levels</em> to be a value greater than one in
+the <em>cl_image_desc</em> passed to <strong>clCreateImage</strong>.
+The dimensions of a mip-mapped image can be a power of two or a non-power of
+two.
+Each successively smaller mipmap level is half the size of the previous
+level.
+If this half value is a fractional value, it is rounded down to the nearest
+integer.</p>
+</div>
+<div class="paragraph">
+<p><strong>Restrictions</strong></p>
+</div>
+<div class="paragraph">
+<p>The following restrictions apply when mip-mapped images are created with
+<strong>clCreateImage</strong>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_MEM_USE_HOST_PTR or CL_MEM_COPY_HOST_PTR cannot be specified if a
+mip-mapped image is created.</p>
+</li>
+<li>
+<p>The <em>host_ptr</em> argument to <strong>clCreateImage</strong> must be a <code>NULL</code> value.</p>
+</li>
+<li>
+<p>Mip-mapped images cannot be created for CL_MEM_OBJECT_IMAGE1D_BUFFER
+images, depth images or multi-sampled (i.e. msaa) images.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Calls to <strong>clEnqueueReadImage</strong>, <strong>clEnqueueWriteImage</strong> and <strong>clEnqueueMapImage</strong>
+can be used to read from or write to a specific mip-level of a mip-mapped
+image.
+If image argument is a 1D image, <em>origin</em>[1] specifies the mip-level to use.
+If image argument is a 1D image array, <em>origin</em>[2] specifies the mip-level
+to use.
+If image argument is a 2D image, <em>origin</em>[2] specifies the mip-level to use.
+If image argument is a 2D image array or a 3D image, <em>origin</em>[3] specifies
+the mip-level to use.</p>
+</div>
+<div class="paragraph">
+<p>Calls to <strong>clEnqueueCopyImage</strong>, <strong>clEnqueueCopyImageToBuffer</strong> and
+<strong>clEnqueueCopyBufferToImage</strong> can also be used to copy from and to a specific
+mip-level of a mip-mapped image.
+If <em>src_image</em> argument is a 1D image, <em>src_origin</em>[1] specifies the
+mip-level to use.
+If <em>src_image</em> argument is a 1D image array, <em>src_origin</em>[2] specifies the
+mip-level to use.
+If <em>src_image</em> argument is a 2D image, <em>src_origin</em>[2] specifies the
+mip-level to use.
+If <em>src_image</em> argument is a 2D image array or a 3D image, <em>src_origin</em>[3]
+specifies the mip-level to use.
+If <em>dst_image</em> argument is a 1D image, <em>dst_origin</em>[1] specifies the
+mip-level to use.
+If <em>dst_image</em> argument is a 1D image array, <em>dst_origin</em>[2] specifies the
+mip-level to use.
+If <em>dst_image</em> argument is a 2D image, <em>dst_origin</em>[2] specifies the
+mip-level to use.
+If <em>dst_image</em> argument is a 2D image array or a 3D image, <em>dst_origin</em>[3]
+specifies the mip-level to use.</p>
+</div>
+<div class="paragraph">
+<p>If the mip level specified is not a valid value, these functions return the
+error CL_INVALID_MIP_LEVEL.</p>
+</div>
+<div class="paragraph">
+<p>Calls to clEnqueueFillImage can be used to write to a specific mip-level of
+a mip-mapped image.
+If image argument is a 1D image, origin[1] specifies the mip-level to use.
+If image argument is a 1D image array, origin[2] specifies the mip-level to
+use.
+If image argument is a 2D image, origin[2] specifies the mip-level to use.
+If image argument is a 2D image array or a 3D image, origin[3] specifies the
+mip-level to use.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_mipmap_image-additions-to-section-5.7">16.1.2. Additions to section 5.7&#8201;&#8212;&#8201;Sampler Objects</h4>
+<div class="paragraph">
+<p>Add the following sampler properties <em>to table 5.14</em> that can be specified
+when a sampler object is created using <strong>clCreateSamplerWithProperties</strong>.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 16.6666%;">
+<col style="width: 33.3334%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_sampler_properties enum</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Property Value</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Default Value</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SAMPLER_MIP_FILTER_MODE_KHR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_filter_mode</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">CL_FILTER_NEAREST</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SAMPLER_LOD_MIN_KHR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_float</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">0.0f</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_SAMPLER_LOD_MAX_KHR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cl_float</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">MAXFLOAT</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>Note: The sampler properties CL_SAMPLER_MIP_FILTER_MODE_KHR,
+CL_SAMPLER_LOD_MIN_KHR and CL_SAMPLER_LOD_MAX_KHR cannot be specified with
+any samplers initialized in the OpenCL program source.
+Only the default values for these properties will be used.
+To create a sampler with specific values for these properties, a sampler
+object must be created with <strong>clCreateSamplerWithProperties</strong> and passed as an
+argument to a kernel.</p>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_mipmap_image-additions-to-creating-opencl-memory-objects-from-opengl-objects">16.2. Additions to <a href="#cl_khr_gl_sharing__memobjs">Creating OpenCL Memory Objects from OpenGL Objects</a></h3>
+<div class="paragraph">
+<p>If both the <strong><code>cl_khr_mipmap_image</code></strong> and <strong><code>cl_khr_gl_sharing</code></strong> extensions are
+supported by the OpenCL device, the <strong><code>cl_khr_gl_sharing</code></strong> extension may also
+be used to create a mipmapped OpenCL image from a mipmapped OpenGL texture.</p>
+</div>
+<div class="paragraph">
+<p>To create a mipmapped OpenCL image from a mipmapped OpenGL texture, pass a
+negative value as the <em>miplevel</em> argument to <strong>clCreateFromGLTexture</strong>.
+If <em>miplevel</em> is a negative value then an OpenCL mipmapped image object is
+created from a mipmapped OpenGL texture object, instead of an OpenCL image
+object for a specific miplevel of the OpenGL texture.</p>
+</div>
+<div class="paragraph">
+<p>Note: For a detailed description of how the level of detail is computed,
+please refer to <em>section 3.9.7</em> of the OpenGL 3.0 specification.</p>
+</div>
+<div style="page-break-after: always;"></div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="cl_khr_egl_image">17. Creating OpenCL Memory Objects from EGL Images</h2>
+<div class="sectionbody">
+<div class="sect2">
+<h3 id="cl_khr_egl_image-overview">17.1. Overview</h3>
+<div class="paragraph">
+<p>This section describes the <strong>cl_khr_egl_image</strong> extension.
+This extension provides a mechanism to creating OpenCL memory objects from
+from EGLImages.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_egl_image-new-procedures-and-functions">17.2. New Procedures and Functions</h3>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_mem clCreateFromEGLImageKHR(cl_context context,
+                               CLeglDisplayKHR display,
+                               CLeglImageKHR image,
+                               cl_mem_flags flags,
+                               const cl_egl_image_properties_khr *properties,
+                               cl_int *errcode_ret);
+
+cl_int clEnqueueAcquireEGLObjectsKHR(cl_command_queue command_queue,
+                                     cl_uint num_objects,
+                                     const cl_mem *mem_objects,
+                                     cl_uint num_events_in_wait_list,
+                                     const cl_event *event_wait_list,
+                                     cl_event *event)
+
+cl_int clEnqueueReleaseEGLObjectsKHR(cl_command_queue command_queue,
+                                     cl_uint num_objects,
+                                     const cl_mem *mem_objects,
+                                     cl_uint num_events_in_wait_list,
+                                     const cl_event *event_wait_list,
+                                     cl_event *event)</code></pre>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_egl_image-new-tokens">17.3. New Tokens</h3>
+<div class="paragraph">
+<p>New error codes:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_EGL_RESOURCE_NOT_ACQUIRED_KHR    -1092
+CL_INVALID_EGL_OBJECT_KHR           -1093</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>New command types:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_COMMAND_ACQUIRE_EGL_OBJECTS_KHR  0x202D
+CL_COMMAND_RELEASE_EGL_OBJECTS_KHR  0x202E</pre>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_egl_image-additions-to-chapter-5">17.4. Additions to Chapter 5 of the OpenCL 2.2 Specification</h3>
+<div class="paragraph">
+<p>In section 5.2.4, add the following text after the paragraph defining
+clCreateImage:</p>
+</div>
+<div class="paragraph">
+<p>"`The function
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_mem clCreateFromEGLImageKHR(cl_context context,
+                               CLeglDisplayKHR display,
+                               CLeglImageKHR image,
+                               cl_mem_flags flags,
+                               const cl_egl_image_properties_khr *properties,
+                               cl_int *errcode_ret);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>creates an EGLImage target of type cl_mem from the EGLImage source provided
+as <em>image</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>display</em> should be of type EGLDisplay, cast into the type CLeglDisplayKHR.</p>
+</div>
+<div class="paragraph">
+<p><em>image</em> should be of type EGLImageKHR, cast into the type CLeglImageKHR.
+Assuming no errors are generated in this function, the resulting image
+object will be an EGLImage target of the specified EGLImage <em>image</em>.
+The resulting cl_mem is an image object which may be used normally by all
+OpenCL operations.
+This maps to an image2d_t type in OpenCL kernel code.</p>
+</div>
+<div class="paragraph">
+<p><em>flags</em> is a bit-field that is used to specify usage information about the
+memory object being created.</p>
+</div>
+<div class="paragraph">
+<p>The possible values for <em>flags</em> are: CL_MEM_READ_ONLY, CL_MEM_WRITE_ONLY and
+CL_MEM _READ_WRITE.</p>
+</div>
+<div class="paragraph">
+<p>For OpenCL 1.2 <em>flags</em> also accepts: CL_MEM_HOST_WRITE_ONLY,
+CL_MEM_HOST_READ_ONLY or CL_MEM_HOST_NO_ACCESS.</p>
+</div>
+<div class="paragraph">
+<p>This extension only requires support for CL_MEM _READ_ONLY, and for OpenCL
+1.2 CL_MEM_HOST_NO_ACCESS.
+For OpenCL 1.1, a CL_INVALID_OPERATION will be returned for images which do
+not support host mapping.</p>
+</div>
+<div class="paragraph">
+<p>If the value passed in <em>flags</em> is not supported by the OpenCL implementation
+it will return CL_INVALID_VALUE.
+The accepted <em>flags</em> may be dependent upon the texture format used.</p>
+</div>
+<div class="paragraph">
+<p><em>properties</em> specifies a list of property names and their corresponding
+values.
+Each property name is immediately followed by the corresponding desired
+value.
+The list is terminated with 0.
+No properties are currently supported with this version of the extension.
+<em>properties</em> can be <code>NULL</code>.</p>
+</div>
+<div class="paragraph">
+<p><strong>clCreateFromEGLImageKHR</strong> returns a valid non-zero OpenCL image object and
+<em>errcode_ret</em> is set to CL_SUCCESS if the image object is created
+successfully.
+Otherwise, it returns a <code>NULL</code> value with one of the following error values
+returned in <em>errcode_ret</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_CONTEXT if <em>context</em> is not a valid OpenCL context.</p>
+</li>
+<li>
+<p>CL_INVALID_VALUE if <em>properties</em> contains invalid values, if <em>display</em>
+is not a valid display object or if <em>flags</em> are not in the set defined
+above.</p>
+</li>
+<li>
+<p>CL_INVALID_EGL_OBJECT_KHR if <em>image</em> is not a valid EGLImage object.</p>
+</li>
+<li>
+<p>CL_IMAGE_FORMAT_NOT_SUPPORTED if the OpenCL implementation is not able
+to create a cl_mem compatible with the provided CLeglImageKHR for an
+implementation-dependent reason (this could be caused by, but not
+limited to, reasons such as unsupported texture formats, etc).</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_INVALID_OPERATION if there are no devices in <em>context</em> that support
+images (i.e. CL_DEVICE_IMAGE_SUPPORT specified in table 4.3 is CL_FALSE)
+or if the flags passed are not supported for that image type.`"</p>
+</li>
+</ul>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_egl_image-lifetime-of-shared-objects">17.4.1. Lifetime of Shared Objects</h4>
+<div class="paragraph">
+<p>An OpenCL memory object created from an EGL image remains valid according to
+the lifetime behavior as described in EGL_KHR_image_base.</p>
+</div>
+<div class="paragraph">
+<p>&#8220;Any EGLImage siblings exist in any client API context&#8221;</p>
+</div>
+<div class="paragraph">
+<p>For OpenCL this means that while the application retains a reference on the
+cl_mem (the EGL sibling), the image remains valid.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_egl_image-synchronizing-opengl-and-egl-access-to-shared-objects">17.4.2. Synchronizing OpenCL and EGL Access to Shared Objects</h4>
+<div class="paragraph">
+<p>In order to ensure data integrity, the application is responsible for
+synchronizing access to shared CL/EGL objects by their respective APIs.
+Failure to provide such synchronization may result in race conditions and
+other undefined behavior including non-portability between implementations.</p>
+</div>
+<div class="paragraph">
+<p>Prior to calling clEnqueueAcquireEGLObjectsKHR, the application must ensure
+that any pending operations which access the objects specified in
+mem_objects have completed.
+This may be accomplished in a portable way by ceasing all client operations
+on the resource, and issuing and waiting for completion of a glFinish
+command on all GL contexts with pending references to these objects.
+Implementations may offer more efficient synchronization methods, such as
+synchronization primitives or fence operations.</p>
+</div>
+<div class="paragraph">
+<p>Similarly, after calling clEnqueueReleaseEGLImageObjects, the application is
+responsible for ensuring that any pending OpenCL operations which access the
+objects specified in mem_objects have completed prior to executing
+subsequent commands in other APIs which reference these objects.
+This may be accomplished in a portable way by calling clWaitForEvents with
+the event object returned by clEnqueueReleaseGLObjects, or by calling
+clFinish.
+As above, some implementations may offer more efficient methods.</p>
+</div>
+<div class="paragraph">
+<p>Attempting to access the data store of an EGLImage object after it has been
+acquired by OpenCL and before it has been released will result in undefined
+behavior.
+Similarly, attempting to access a shared EGLImage object from OpenCL before
+it has been acquired by the OpenCL command queue or after it has been
+released, will result in undefined behavior.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="cl_khr_egl_image-sharing-memory-objects-created-from-egl-resources-between-egldisplays-and-opencl-contexts">17.4.3. Sharing memory objects created from EGL resources between EGLDisplays and OpenCL contexts</h4>
+<div class="paragraph">
+<p>The function
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_int clEnqueueAcquireEGLObjectsKHR(cl_command_queue command_queue,
+                                     cl_uint num_objects,
+                                     const cl_mem *mem_objects,
+                                     cl_uint num_events_in_wait_list,
+                                     const cl_event *event_wait_list,
+                                     cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>is used to acquire OpenCL memory objects that have been created from EGL
+resources.
+The EGL objects are acquired by the OpenCL context associated with
+<em>command_queue</em> and can therefore be used by all command-queues associated
+with the OpenCL context.</p>
+</div>
+<div class="paragraph">
+<p>OpenCL memory objects created from EGL resources must be acquired before
+they can be used by any OpenCL commands queued to a command-queue.
+If an OpenCL memory object created from a EGL resource is used while it is
+not currently acquired by OpenCL, the call attempting to use that OpenCL
+memory object will return CL_EGL_RESOURCE_NOT_ACQUIRED_KHR.</p>
+</div>
+<div class="paragraph">
+<p><em>command_queue</em> is a valid command-queue.</p>
+</div>
+<div class="paragraph">
+<p><em>num_objects</em> is the number of memory objects to be acquired in
+<em>mem_objects</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>mem_objects</em> is a pointer to a list of OpenCL memory objects that were
+created from EGL resources, within the context associate with command_queue.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before this particular command can be executed.
+If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait
+on any event to complete.
+If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event_wait_list</em> act as synchronization points.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> returns an event object that identifies this particular command and
+can be used to query or queue a wait for this particular command to
+complete.
+<em>event</em> can be <code>NULL</code> in which case it will not be possible for the
+application to query the status of this command or queue a wait for this
+command to complete.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueAcquireEGLObjectsKHR</strong> returns CL_SUCCESS if the function is
+executed successfully.
+If <em>num_objects</em> is 0 and <em>mem_objects</em> is <code>NULL</code> then the function does
+nothing and returns CL_SUCCESS.
+Otherwise it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_VALUE if <em>num_objects</em> is zero and <em>mem_objects</em> is not a
+<code>NULL</code> value or if num_objects &gt; 0 and mem_objects is <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_MEM_OBJECT if memory objects in <em>mem_objects</em> are not valid
+OpenCL memory objects in the context associated with <em>command_queue</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_EGL_OBJECT_KHR if memory objects in <em>mem_objects</em> have not
+been created from EGL resources.</p>
+</li>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The function
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_int clEnqueueReleaseEGLObjectsKHR(cl_command_queue command_queue,
+                                     cl_uint num_objects,
+                                     const cl_mem *mem_objects,
+                                     cl_uint num_events_in_wait_list,
+                                     const cl_event *event_wait_list,
+                                     cl_event *event)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>is used to release OpenCL memory objects that have been created from EGL
+resources.
+The EGL objects are released by the OpenCL context associated with
+&lt;command_queue&gt;.</p>
+</div>
+<div class="paragraph">
+<p>OpenCL memory objects created from EGL resources which have been acquired by
+OpenCL must be released by OpenCL before they may be accessed by EGL or by
+EGL client APIs.
+Accessing a EGL resource while its corresponding OpenCL memory object is
+acquired is in error and will result in undefined behavior, including but
+not limited to possible OpenCL errors, data corruption, and program
+termination.</p>
+</div>
+<div class="paragraph">
+<p><em>command_queue</em> is a valid command-queue.</p>
+</div>
+<div class="paragraph">
+<p><em>num_objects</em> is the number of memory objects to be acquired in
+<em>mem_objects</em>.</p>
+</div>
+<div class="paragraph">
+<p><em>mem_objects</em> is a pointer to a list of OpenCL memory objects that were
+created from EGL resources, within the context associate with command_queue.</p>
+</div>
+<div class="paragraph">
+<p><em>event_wait_list</em> and <em>num_events_in_wait_list</em> specify events that need to
+complete before this particular command can be executed.
+If <em>event_wait_list</em> is <code>NULL</code>, then this particular command does not wait
+on any event to complete.
+If <em>event_wait_list</em> is <code>NULL</code>, <em>num_events_in_wait_list</em> must be 0.
+If <em>event_wait_list</em> is not <code>NULL</code>, the list of events pointed to by
+<em>event_wait_list</em> must be valid and <em>num_events_in_wait_list</em> must be
+greater than 0.
+The events specified in <em>event_wait_list</em> act as synchronization points.</p>
+</div>
+<div class="paragraph">
+<p><em>event</em> returns an event object that identifies this particular command and
+can be used to query or queue a wait for this particular command to
+complete.
+<em>event</em> can be <code>NULL</code> in which case it will not be possible for the
+application to query the status of this command or queue a wait for this
+command to complete.</p>
+</div>
+<div class="paragraph">
+<p><strong>clEnqueueReleaseEGLObjectsKHR</strong> returns CL_SUCCESS if the function is
+executed successfully.
+If <em>num_objects</em> is 0 and <em>mem_objects</em> is <code>NULL</code> then the function does
+nothing and returns CL_SUCCESS.
+Otherwise it returns one of the following errors:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_VALUE if <em>num_objects</em> is zero and <em>mem_objects</em> is not a
+<code>NULL</code> value or if num_objects &gt; 0 and mem_objects is <code>NULL</code>.</p>
+</li>
+<li>
+<p>CL_INVALID_MEM_OBJECT if memory objects in <em>mem_objects</em> are not valid
+OpenCL memory objects in the context associated with <em>command_queue</em>.</p>
+</li>
+<li>
+<p>CL_INVALID_EGL_OBJECT_KHR if memory objects in <em>mem_objects</em> have not
+been created from EGL resources.</p>
+</li>
+<li>
+<p>CL_INVALID_COMMAND_QUEUE if <em>command_queue</em> is not a valid
+command-queue.</p>
+</li>
+<li>
+<p>CL_INVALID_EVENT_WAIT_LIST if <em>event_wait_list</em> is <code>NULL</code> and
+<em>num_events_in_wait_list</em> &gt; 0, or <em>event_wait_list</em> is not <code>NULL</code> and
+<em>num_events_in_wait_list</em> is 0, or if event objects in <em>event_wait_list</em>
+are not valid events.</p>
+</li>
+<li>
+<p>CL_OUT_OF_RESOURCES if there is a failure to allocate resources required
+by the OpenCL implementation on the device.</p>
+</li>
+<li>
+<p>CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources
+required by the OpenCL implementation on the host.</p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_egl_image-issues">17.5. Issues</h3>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>This extension does not support reference counting of the images, so the
+onus is on the application to behave sensibly and not release the
+underlying cl_mem object while the EGLImage is still being used.</p>
+</li>
+<li>
+<p>In order to ensure data integrity, the application is responsible for
+synchronizing access to shared CL/EGL image objects by their respective
+APIs.
+Failure to provide such synchronization may result in race conditions
+and other undefined behavior.
+This may be accomplished by calling clWaitForEvents with the event
+objects returned by any OpenCL commands which use the shared image
+object or by calling clFinish.</p>
+</li>
+<li>
+<p>Currently CL_MEM_READ_ONLY is the only supported flag for <em>flags</em>.</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>RESOLVED: Implementation will now return an error if writing to a shared
+object that is not supported rather than disallowing it entirely.</p>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p>Currently restricted to 2D image objects.</p>
+</li>
+<li>
+<p>What should happen for YUV color-space conversion, multi plane images,
+and chroma-siting, and channel mapping?</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>RESOLVED: YUV is no longer explicitly described in this extension.
+Before this removal the behavior was dependent on the platform.
+This extension explicitly leaves the YUV layout to the platform and EGLImage
+source extension (i.e. is implementation specific).
+Colorspace conversion must be applied by the application using a color
+conversion matrix.</p>
+</div>
+<div class="paragraph">
+<p>The expected extension path if YUV color-space conversion is to be supported
+is to introduce a YUV image type and provide overloaded versions of the
+read_image built-in functions.</p>
+</div>
+<div class="paragraph">
+<p>Getting image information for a YUV image should return the original image
+size (non quantized size) when all of Y U and V are present in the image.
+If the planes have been separated then the actual dimensionality of the
+separated plane should be reported.
+For example with YUV 4:2:0 (NV12) with a YUV image of 256x256, the Y only
+image would return 256x256 whereas the UV only image would return 128x128.</p>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p>Should an attribute list be used instead?</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>RESOLVED: function has been changed to use an attribute list.</p>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p>What should happen for EGLImage extensions which introduce formats
+without a mapping to an OpenCL image channel data type or channel order?</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>RESOLVED: This extension does not define those formats.
+It is expected that as additional EGL extensions are added to create EGL
+images from other sources, an extension to CL will be introduced where
+needed to represent those image types.</p>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p>What are the guarantees to synchronization behavior provided by the
+implementation?</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>The basic portable form of synchronization is to use a clFinish, as is the
+case for GL interop.
+In addition implementations which support the synchronization extensions
+cl_khr_egl_event and EGL_KHR_cl_event can interoperate more efficiently as
+described in those extensions.</p>
+</div>
+</div>
+</div>
+</li>
+</ol>
+</div>
+<div style="page-break-after: always;"></div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="cl_khr_egl_event">18. Creating OpenCL Event Objects from EGL Sync Objects</h2>
+<div class="sectionbody">
+<div class="sect2">
+<h3 id="cl_khr_egl_event-overview">18.1. Overview</h3>
+<div class="paragraph">
+<p>This section describes the <strong>cl_khr_egl_event</strong> extension.
+This extension allows creating OpenCL event objects linked to EGL fence sync
+objects, potentially improving efficiency of sharing images and buffers
+between the two APIs.
+The companion <strong>EGL_KHR_cl_event</strong> extension provides the complementary
+functionality of creating an EGL sync object from an OpenCL event object.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_egl_event-new-procedures-and-functions">18.2. New Procedures and Functions</h3>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_event clCreateEventFromEGLSyncKHR(cl_context context,
+                                     CLeglSyncKHR sync,
+                                     CLeglDisplayKHR display,
+                                     cl_int *errcode_ret);</code></pre>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_egl_event-new-tokens">18.3. New Tokens</h3>
+<div class="paragraph">
+<p>Returned by clCreateEventFromEGLSyncKHR if <em>sync</em> is not a valid EGLSyncKHR
+handle created with respect to EGLDisplay <em>display</em>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_INVALID_EGL_OBJECT_KHR               -1093</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Returned by <strong>clGetEventInfo</strong> when <em>param_name</em> is CL_EVENT_COMMAND_TYPE:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>CL_COMMAND_EGL_FENCE_SYNC_OBJECT_KHR    0x202F</pre>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_egl_event-additions-to-chapter-5">18.4. Additions to Chapter 5 of the OpenCL 2.2 Specification</h3>
+<div class="paragraph">
+<p>Add following to the fourth paragraph of <em>section 5.11</em> (prior to the
+description of <strong>clWaitForEvents</strong>):</p>
+</div>
+<div class="paragraph">
+<p>&#8220;Event objects can also be used to reflect the status of an EGL fence sync
+object.
+The sync object in turn refers to a fence command executing in an EGL client
+API command stream.
+This provides another method of coordinating sharing of EGL / EGL client API
+objects with OpenCL.
+Completion of EGL / EGL client API commands may be determined by placing an
+EGL fence command after commands using eglCreateSyncKHR, creating an event
+from the resulting EGL sync object using clCreateEventFromEGLSyncKHR and
+then specifying it in the <em>event_wait_list</em> of a clEnqueueAcquire***
+command.
+This method may be considerably more efficient than calling operations like
+glFinish, and is referred to as <em>explicit synchronization</em>.
+The application is responsible for ensuring the command stream associated
+with the EGL fence is flushed to ensure the CL queue is submitted to the
+device.
+Explicit synchronization is most useful when an EGL client API context bound
+to another thread is accessing the memory objects.&#8221;</p>
+</div>
+<div class="paragraph">
+<p>Add CL_COMMAND_EGL_FENCE_SYNC_OBJECT_KHR to the valid <em>param_value</em> values
+returned by <strong>clGetEventInfo</strong> for <em>param_name</em> CL_EVENT_COMMAND_TYPE (in the
+third row and third column of <em>table 5.22</em>).</p>
+</div>
+<div class="paragraph">
+<p>Add new <em>subsection 5.11.2</em>:</p>
+</div>
+<div class="paragraph">
+<p>"`<strong>5.11.2 Linking Event Objects to EGL Synchronization Objects</strong></p>
+</div>
+<div class="paragraph">
+<p>An event object may be created by linking to an EGL <strong>sync object</strong>.
+Completion of such an event object is equivalent to waiting for completion
+of the fence command associated with the linked EGL sync object.</p>
+</div>
+<div class="paragraph">
+<p>The function
+</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="CodeRay highlight"><code>cl_event clCreateEventFromEGLSyncKHR(cl_context context,
+                                     CLeglSyncKHR sync,
+                                     CLeglDisplayKHR display,
+                                     cl_int *errcode_ret)</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>creates a linked event object.</p>
+</div>
+<div class="paragraph">
+<p><em>context</em> is a valid OpenCL context created from an OpenGL context or share
+group, using the <strong>cl_khr_gl_sharing</strong> extension.</p>
+</div>
+<div class="paragraph">
+<p><em>sync</em> is the name of a sync object of type EGL_SYNC_FENCE_KHR created with
+respect to EGLDisplay <em>display</em>.</p>
+</div>
+<div class="paragraph">
+<p><strong>clCreateEventFromEGLSyncKHR</strong> returns a valid OpenCL event object and
+<em>errcode_ret</em> is set to CL_SUCCESS if the event object is created
+successfully.
+Otherwise, it returns a <code>NULL</code> value with one of the following error values
+returned in <em>errcode_ret</em>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>CL_INVALID_CONTEXT if <em>context</em> is not a valid context, or was not
+created from a GL context.</p>
+</li>
+<li>
+<p>CL_INVALID_EGL_OBJECT_KHR if <em>sync</em> is not a valid EGLSyncKHR object of
+type EGL_SYNC_FENCE_KHR created with respect to EGLDisplay <em>display</em>.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>The parameters of an event object linked to an EGL sync object will return
+the following values when queried with <strong>clGetEventInfo</strong>:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>The CL_EVENT_COMMAND_QUEUE of a linked event is <code>NULL</code>, because the
+event is not associated with any OpenCL command queue.</p>
+</li>
+<li>
+<p>The CL_EVENT_COMMAND_TYPE of a linked event is
+CL_COMMAND_EGL_FENCE_SYNC_OBJECT_KHR, indicating that the event is
+associated with a EGL sync object, rather than an OpenCL command.</p>
+</li>
+<li>
+<p>The CL_EVENT_COMMAND_EXECUTION_STATUS of a linked event is either
+CL_SUBMITTED, indicating that the fence command associated with the sync
+object has not yet completed, or CL_COMPLETE, indicating that the fence
+command has completed.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p><strong>clCreateEventFromEGLSyncKHR</strong> performs an implicit <strong>clRetainEvent</strong> on the
+returned event object.
+Creating a linked event object also places a reference on the linked EGL
+sync object.
+When the event object is deleted, the reference will be removed from the EGL
+sync object.</p>
+</div>
+<div class="paragraph">
+<p>Events returned from <strong>clCreateEventFromEGLSyncKHR</strong> may only be consumed by
+<strong>clEnqueueAcquire</strong>*** commands.
+Passing such events to any other CL API that enqueues commands will generate
+a CL_INVALID_EVENT error.`"</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_egl_event-additions-to-extension-specification">18.5. Additions to the OpenCL Extension Specification</h3>
+<div class="paragraph">
+<p>Replace the second paragraph of
+<a href="#cl_khr_gl_sharing__memobjs-synchronizing-opencl-and-opengl-access-to-shared-objects">Synchronizing OpenCL and OpenGL Access to Shared Objects</a> with:</p>
+</div>
+<div class="paragraph">
+<p>"`Prior to calling <strong>clEnqueueAcquireGLObjects</strong>, the application must ensure
+that any pending EGL or EGL client API operations which access the objects
+specified in <em>mem_objects</em> have completed.</p>
+</div>
+<div class="paragraph">
+<p>If the <strong>cl_khr_egl_event</strong> extension is supported and the EGL context in
+question supports fence sync objects, <em>explicit synchronization</em> can be
+achieved as set out in <em>section 5.7.1</em>.</p>
+</div>
+<div class="paragraph">
+<p>If the <strong>cl_khr_egl_event</strong> extension is not supported, completion of EGL
+client API commands may be determined by issuing and waiting for completion
+of commands such as glFinish or vgFinish on all client API contexts with
+pending references to these objects.
+Some implementations may offer other efficient synchronization methods.
+If such methods exist they will be described in platform-specific
+documentation.</p>
+</div>
+<div class="paragraph">
+<p>Note that no synchronization methods other than glFinish and vgFinish are
+portable between all EGL client API implementations and all OpenCL
+implementations.
+While this is the only way to ensure completion that is portable to all
+platforms, these are expensive operation and their use should be avoided if
+the cl_khr_egl_event extension is supported on a platform.`"</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_egl_event-issues">18.6. Issues</h3>
+<div class="paragraph">
+<p>Most issues are shared with <strong>cl_khr_gl_event</strong> and are resolved as described
+in that extension.</p>
+</div>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>Should we support implicit synchronization?</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>RESOLVED: No, as this may be very difficult since the synchronization would
+not be with EGL, it would be with currently bound EGL client APIs.
+It would be necessary to know which client APIs might be bound, to validate
+that they&#8217;re associated with the EGLDisplay associated with the OpenCL
+context, and to reach into each such context.</p>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p>Do we need to have typedefs to use EGL handles in OpenCL?</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>RESOLVED Using typedefs for EGL handles.</p>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p>Should we restrict which CL APIs can be used with this cl_event?</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>RESOLVED Use is limited to clEnqueueAcquire*** calls only.</p>
+</div>
+</div>
+</div>
+</li>
+<li>
+<p>What is the desired behaviour for this extension when EGLSyncKHR is of a
+type other than EGL_SYNC_FENCE_KHR?</p>
+<div class="openblock">
+<div class="content">
+<div class="paragraph">
+<p>RESOLVED This extension only requires support for EGL_SYNC_FENCE_KHR.
+Support of other types is an implementation choice, and will result in
+CL_INVALID_EGL_OBJECT_KHR if unsupported.</p>
+</div>
+</div>
+</div>
+</li>
+</ol>
+</div>
+<div style="page-break-after: always;"></div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="cl_khr_priority_hints">19. Priority Hints</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>This section describes the <strong>cl_khr_priority_hints</strong> extension.
+This extension adds priority hints for OpenCL, but does not specify the
+scheduling behavior or minimum guarantees.
+It is expected that the the user guides associated with each implementation
+which supports this extension will describe the scheduling behavior
+guarantees.</p>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_priority_hints-host-side-api-modifications">19.1. Host-side API modifications</h3>
+<div class="paragraph">
+<p>The function <strong><code>clCreateCommandQueueWithProperties</code></strong> (Section 5.1) is
+extended to support a priority value as part of the <em>properties</em> argument.</p>
+</div>
+<div class="paragraph">
+<p>The priority property applies to OpenCL command queues that belong to the
+same OpenCL context.</p>
+</div>
+<div class="paragraph">
+<p>The properties field accepts the <code>CL_QUEUE_PRIORITY_KHR</code> property, with a
+value of type cl_queue_priority_khr, which can be one of:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>CL_QUEUE_PRIORITY_HIGH_KHR</code></p>
+</li>
+<li>
+<p><code>CL_QUEUE_PRIORITY_MED_KHR</code></p>
+</li>
+<li>
+<p><code>CL_QUEUE_PRIORITY_LOW_KHR</code></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If <code>CL_QUEUE_PRIORITY_KHR</code> is not specified then the default priority is
+<code>CL_QUEUE_PRIORITY_MED_KHR</code>.</p>
+</div>
+<div class="paragraph">
+<p>To the error section for <strong><code>clCreateCommandQueueWithProperties</code></strong>, the
+following is added:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>CL_INVALID_QUEUE_PROPERTIES</code> if the <code>CL_QUEUE_PRIORITY_KHR</code> property is
+specified and the queue is a <code>CL_QUEUE_ON_DEVICE</code>.</p>
+</li>
+</ul>
+</div>
+<div style="page-break-after: always;"></div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="cl_khr_throttle_hints">20. Throttle Hints</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>This section describes the <strong>cl_khr_throttle_hints</strong> extension.
+This extension adds throttle hints for OpenCL, but does not specify the
+throttling behavior or minimum guarantees.
+It is expected that the user guide associated with each implementation which
+supports this extension will describe the throttling behavior guarantees.</p>
+</div>
+<div class="paragraph">
+<p>Note that the throttle hint is orthogonal to functionality defined in
+<strong>cl_khr_priority_hints</strong> extension.
+For example, a task may have high priority (<code>CL_QUEUE_PRIORITY_HIGH_KHR</code>)
+but should at the same time be executed at an optimized throttle setting
+(<code>CL_QUEUE_THROTTLE_LOW</code>).</p>
+</div>
+<div class="sect2">
+<h3 id="cl_khr_throttle_hints-host-side-api-modifications">20.1. Host-side API modifications</h3>
+<div class="paragraph">
+<p>The function <strong><code>clCreateCommandQueueWithProperties</code></strong> (Section 5.1) is
+extended to support a new <code>CL_QUEUE_THROTTLE_KHR</code> value as part of the
+<em>properties</em> argument.</p>
+</div>
+<div class="paragraph">
+<p>The properties field accepts the following values:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>CL_QUEUE_THROTTLE_HIGH_KHR</code> (full throttle, i.e., OK to consume more
+energy)</p>
+</li>
+<li>
+<p><code>CL_QUEUE_THROTTLE_MED_KHR</code> (normal throttle)</p>
+</li>
+<li>
+<p><code>CL_QUEUE_THROTTLE_LOW_KHR</code> (optimized/lowest energy consumption)</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If <code>CL_QUEUE_THROTTLE_KHR</code> is not specified then the default priority is
+<code>CL_QUEUE_THROTTLE_MED_KHR</code>.</p>
+</div>
+<div class="paragraph">
+<p>To the error section for <strong><code>clCreateCommandQueueWithProperties</code></strong>, the
+following is added:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>CL_INVALID_QUEUE_PROPERTIES</code> if the <code>CL_QUEUE_THROTTLE_KHR</code> property is
+specified and the queue is a <code>CL_QUEUE_ON_DEVICE</code>.</p>
+</li>
+</ul>
+</div>
+<div style="page-break-after: always;"></div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="cl_khr_subgroup_named_barrier">21. Named Barriers for Subgroups</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>This section describes the <strong>cl_khr_subgroup_named_barrier</strong> extension.
+This extension adds barrier operations that cover subsets of an OpenCL
+work-group.
+Only the OpenCL API changes are described in this section.
+Please refer to the SPIR-V specification for information about using
+subgroups named barriers in the SPIR-V intermediate representation, and to
+the OpenCL C++ specification for descriptions of the subgroup named
+barrier built-in functions in the OpenCL C++ kernel language.</p>
+</div>
+<div class="paragraph">
+<p>Add to <em>table 4.3</em>:</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 33.3333%;">
+<col style="width: 16.6666%;">
+<col style="width: 50.0001%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top"><strong>cl_device_info</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Return Type</strong></th>
+<th class="tableblock halign-left valign-top"><strong>Description</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>CL_DEVICE_MAX_NAMED_BARRIER_COUNT_KHR</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>cl_uint</strong></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Maximum number of named barriers in a work-group for any given
+  kernel-instance running on the device.
+  The minimum value is 8.</p></td>
+</tr>
+</tbody>
+</table>
+<div style="page-break-after: always;"></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_summary_of_changes_from_opencl_2_1">Appendix A: Summary of Changes from OpenCL 2.1</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>The following features are added to OpenCL 2.2:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>The OpenCL 2.2 KHR extension <strong>cl_khr_subgroup_named_barrier</strong> has been
+added.</p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+</div>
+<div id="footer">
+<div id="footer-text">
+Version 2.2-7<br>
+Last updated 2018-05-12 14:11:33 BST
+</div>
+</div>
+
+
+</body>
+</html>
\ No newline at end of file
diff --git a/specs/2.2/html/OpenCL_ICD_Installation.html b/specs/2.2/html/OpenCL_ICD_Installation.html
new file mode 100644
index 0000000..676da61
--- /dev/null
+++ b/specs/2.2/html/OpenCL_ICD_Installation.html
@@ -0,0 +1,1130 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<meta name="generator" content="Asciidoctor 1.5.6.1">
+<meta name="author" content="Khronos OpenCL Working Group">
+<title>OpenCL ICD Installation Guidelines</title>
+<style>
+/*! normalize.css v2.1.2 | MIT License | git.io/normalize */
+/* ========================================================================== HTML5 display definitions ========================================================================== */
+/** Correct `block` display not defined in IE 8/9. */
+article, aside, details, figcaption, figure, footer, header, hgroup, main, nav, section, summary { display: block; }
+
+/** Correct `inline-block` display not defined in IE 8/9. */
+audio, canvas, video { display: inline-block; }
+
+/** Prevent modern browsers from displaying `audio` without controls. Remove excess height in iOS 5 devices. */
+audio:not([controls]) { display: none; height: 0; }
+
+/** Address `[hidden]` styling not present in IE 8/9. Hide the `template` element in IE, Safari, and Firefox < 22. */
+[hidden], template { display: none; }
+
+script { display: none !important; }
+
+/* ========================================================================== Base ========================================================================== */
+/** 1. Set default font family to sans-serif. 2. Prevent iOS text size adjust after orientation change, without disabling user zoom. */
+html { font-family: sans-serif; /* 1 */ -ms-text-size-adjust: 100%; /* 2 */ -webkit-text-size-adjust: 100%; /* 2 */ }
+
+/** Remove default margin. */
+body { margin: 0; }
+
+/* ========================================================================== Links ========================================================================== */
+/** Remove the gray background color from active links in IE 10. */
+a { background: transparent; }
+
+/** Address `outline` inconsistency between Chrome and other browsers. */
+a:focus { outline: thin dotted; }
+
+/** Improve readability when focused and also mouse hovered in all browsers. */
+a:active, a:hover { outline: 0; }
+
+/* ========================================================================== Typography ========================================================================== */
+/** Address variable `h1` font-size and margin within `section` and `article` contexts in Firefox 4+, Safari 5, and Chrome. */
+h1 { font-size: 2em; margin: 0.67em 0; }
+
+/** Address styling not present in IE 8/9, Safari 5, and Chrome. */
+abbr[title] { border-bottom: 1px dotted; }
+
+/** Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome. */
+b, strong { font-weight: bold; }
+
+/** Address styling not present in Safari 5 and Chrome. */
+dfn { font-style: italic; }
+
+/** Address differences between Firefox and other browsers. */
+hr { -moz-box-sizing: content-box; box-sizing: content-box; height: 0; }
+
+/** Address styling not present in IE 8/9. */
+mark { background: #ff0; color: #000; }
+
+/** Correct font family set oddly in Safari 5 and Chrome. */
+code, kbd, pre, samp { font-family: monospace, serif; font-size: 1em; }
+
+/** Improve readability of pre-formatted text in all browsers. */
+pre { white-space: pre-wrap; }
+
+/** Set consistent quote types. */
+q { quotes: "\201C" "\201D" "\2018" "\2019"; }
+
+/** Address inconsistent and variable font size in all browsers. */
+small { font-size: 80%; }
+
+/** Prevent `sub` and `sup` affecting `line-height` in all browsers. */
+sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }
+
+sup { top: -0.5em; }
+
+sub { bottom: -0.25em; }
+
+/* ========================================================================== Embedded content ========================================================================== */
+/** Remove border when inside `a` element in IE 8/9. */
+img { border: 0; }
+
+/** Correct overflow displayed oddly in IE 9. */
+svg:not(:root) { overflow: hidden; }
+
+/* ========================================================================== Figures ========================================================================== */
+/** Address margin not present in IE 8/9 and Safari 5. */
+figure { margin: 0; }
+
+/* ========================================================================== Forms ========================================================================== */
+/** Define consistent border, margin, and padding. */
+fieldset { border: 1px solid #c0c0c0; margin: 0 2px; padding: 0.35em 0.625em 0.75em; }
+
+/** 1. Correct `color` not being inherited in IE 8/9. 2. Remove padding so people aren't caught out if they zero out fieldsets. */
+legend { border: 0; /* 1 */ padding: 0; /* 2 */ }
+
+/** 1. Correct font family not being inherited in all browsers. 2. Correct font size not being inherited in all browsers. 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome. */
+button, input, select, textarea { font-family: inherit; /* 1 */ font-size: 100%; /* 2 */ margin: 0; /* 3 */ }
+
+/** Address Firefox 4+ setting `line-height` on `input` using `!important` in the UA stylesheet. */
+button, input { line-height: normal; }
+
+/** Address inconsistent `text-transform` inheritance for `button` and `select`. All other form control elements do not inherit `text-transform` values. Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+. Correct `select` style inheritance in Firefox 4+ and Opera. */
+button, select { text-transform: none; }
+
+/** 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` and `video` controls. 2. Correct inability to style clickable `input` types in iOS. 3. Improve usability and consistency of cursor style between image-type `input` and others. */
+button, html input[type="button"], input[type="reset"], input[type="submit"] { -webkit-appearance: button; /* 2 */ cursor: pointer; /* 3 */ }
+
+/** Re-set default cursor for disabled elements. */
+button[disabled], html input[disabled] { cursor: default; }
+
+/** 1. Address box sizing set to `content-box` in IE 8/9. 2. Remove excess padding in IE 8/9. */
+input[type="checkbox"], input[type="radio"] { box-sizing: border-box; /* 1 */ padding: 0; /* 2 */ }
+
+/** 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome (include `-moz` to future-proof). */
+input[type="search"] { -webkit-appearance: textfield; /* 1 */ -moz-box-sizing: content-box; -webkit-box-sizing: content-box; /* 2 */ box-sizing: content-box; }
+
+/** Remove inner padding and search cancel button in Safari 5 and Chrome on OS X. */
+input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; }
+
+/** Remove inner padding and border in Firefox 4+. */
+button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; }
+
+/** 1. Remove default vertical scrollbar in IE 8/9. 2. Improve readability and alignment in all browsers. */
+textarea { overflow: auto; /* 1 */ vertical-align: top; /* 2 */ }
+
+/* ========================================================================== Tables ========================================================================== */
+/** Remove most spacing between table cells. */
+table { border-collapse: collapse; border-spacing: 0; }
+
+meta.foundation-mq-small { font-family: "only screen and (min-width: 768px)"; width: 768px; }
+
+meta.foundation-mq-medium { font-family: "only screen and (min-width:1280px)"; width: 1280px; }
+
+meta.foundation-mq-large { font-family: "only screen and (min-width:1440px)"; width: 1440px; }
+
+*, *:before, *:after { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; }
+
+html, body { font-size: 100%; }
+
+body { background: white; color: #222222; padding: 0; margin: 0; font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; font-weight: normal; font-style: normal; line-height: 1; position: relative; cursor: auto; }
+
+a:hover { cursor: pointer; }
+
+img, object, embed { max-width: 100%; height: auto; }
+
+object, embed { height: 100%; }
+
+img { -ms-interpolation-mode: bicubic; }
+
+#map_canvas img, #map_canvas embed, #map_canvas object, .map_canvas img, .map_canvas embed, .map_canvas object { max-width: none !important; }
+
+.left { float: left !important; }
+
+.right { float: right !important; }
+
+.text-left { text-align: left !important; }
+
+.text-right { text-align: right !important; }
+
+.text-center { text-align: center !important; }
+
+.text-justify { text-align: justify !important; }
+
+.hide { display: none; }
+
+.antialiased { -webkit-font-smoothing: antialiased; }
+
+img { display: inline-block; vertical-align: middle; }
+
+textarea { height: auto; min-height: 50px; }
+
+select { width: 100%; }
+
+object, svg { display: inline-block; vertical-align: middle; }
+
+.center { margin-left: auto; margin-right: auto; }
+
+.spread { width: 100%; }
+
+p.lead, .paragraph.lead > p, #preamble > .sectionbody > .paragraph:first-of-type p { font-size: 1.21875em; line-height: 1.6; }
+
+.subheader, .admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { line-height: 1.4; color: black; font-weight: 300; margin-top: 0.2em; margin-bottom: 0.5em; }
+
+/* Typography resets */
+div, dl, dt, dd, ul, ol, li, h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6, pre, form, p, blockquote, th, td { margin: 0; padding: 0; direction: ltr; }
+
+/* Default Link Styles */
+a { color: #0068b0; text-decoration: none; line-height: inherit; }
+a:hover, a:focus { color: #333333; }
+a img { border: none; }
+
+/* Default paragraph styles */
+p { font-family: Noto, sans-serif; font-weight: normal; font-size: 1em; line-height: 1.6; margin-bottom: 0.75em; text-rendering: optimizeLegibility; }
+p aside { font-size: 0.875em; line-height: 1.35; font-style: italic; }
+
+/* Default header styles */
+h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { font-family: Noto, sans-serif; font-weight: normal; font-style: normal; color: black; text-rendering: optimizeLegibility; margin-top: 0.5em; margin-bottom: 0.5em; line-height: 1.2125em; }
+h1 small, h2 small, h3 small, #toctitle small, .sidebarblock > .content > .title small, h4 small, h5 small, h6 small { font-size: 60%; color: #4d4d4d; line-height: 0; }
+
+h1 { font-size: 2.125em; }
+
+h2 { font-size: 1.6875em; }
+
+h3, #toctitle, .sidebarblock > .content > .title { font-size: 1.375em; }
+
+h4 { font-size: 1.125em; }
+
+h5 { font-size: 1.125em; }
+
+h6 { font-size: 1em; }
+
+hr { border: solid #dddddd; border-width: 1px 0 0; clear: both; margin: 1.25em 0 1.1875em; height: 0; }
+
+/* Helpful Typography Defaults */
+em, i { font-style: italic; line-height: inherit; }
+
+strong, b { font-weight: bold; line-height: inherit; }
+
+small { font-size: 60%; line-height: inherit; }
+
+code { font-family: Consolas, "Liberation Mono", Courier, monospace; font-weight: normal; color: #264357; }
+
+/* Lists */
+ul, ol, dl { font-size: 1em; line-height: 1.6; margin-bottom: 0.75em; list-style-position: outside; font-family: Noto, sans-serif; }
+
+ul, ol { margin-left: 1.5em; }
+ul.no-bullet, ol.no-bullet { margin-left: 1.5em; }
+
+/* Unordered Lists */
+ul li ul, ul li ol { margin-left: 1.25em; margin-bottom: 0; font-size: 1em; /* Override nested font-size change */ }
+ul.square li ul, ul.circle li ul, ul.disc li ul { list-style: inherit; }
+ul.square { list-style-type: square; }
+ul.circle { list-style-type: circle; }
+ul.disc { list-style-type: disc; }
+ul.no-bullet { list-style: none; }
+
+/* Ordered Lists */
+ol li ul, ol li ol { margin-left: 1.25em; margin-bottom: 0; }
+
+/* Definition Lists */
+dl dt { margin-bottom: 0.3em; font-weight: bold; }
+dl dd { margin-bottom: 0.75em; }
+
+/* Abbreviations */
+abbr, acronym { text-transform: uppercase; font-size: 90%; color: black; border-bottom: 1px dotted #dddddd; cursor: help; }
+
+abbr { text-transform: none; }
+
+/* Blockquotes */
+blockquote { margin: 0 0 0.75em; padding: 0.5625em 1.25em 0 1.1875em; border-left: 1px solid #dddddd; }
+blockquote cite { display: block; font-size: 0.8125em; color: #5e93b8; }
+blockquote cite:before { content: "\2014 \0020"; }
+blockquote cite a, blockquote cite a:visited { color: #5e93b8; }
+
+blockquote, blockquote p { line-height: 1.6; color: #333333; }
+
+/* Microformats */
+.vcard { display: inline-block; margin: 0 0 1.25em 0; border: 1px solid #dddddd; padding: 0.625em 0.75em; }
+.vcard li { margin: 0; display: block; }
+.vcard .fn { font-weight: bold; font-size: 0.9375em; }
+
+.vevent .summary { font-weight: bold; }
+.vevent abbr { cursor: auto; text-decoration: none; font-weight: bold; border: none; padding: 0 0.0625em; }
+
+@media only screen and (min-width: 768px) { h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { line-height: 1.4; }
+  h1 { font-size: 2.75em; }
+  h2 { font-size: 2.3125em; }
+  h3, #toctitle, .sidebarblock > .content > .title { font-size: 1.6875em; }
+  h4 { font-size: 1.4375em; } }
+/* Tables */
+table { background: white; margin-bottom: 1.25em; border: solid 1px #d8d8ce; }
+table thead, table tfoot { background: -webkit-linear-gradient(top, #add386, #90b66a); font-weight: bold; }
+table thead tr th, table thead tr td, table tfoot tr th, table tfoot tr td { padding: 0.5em 0.625em 0.625em; font-size: inherit; color: white; text-align: left; }
+table tr th, table tr td { padding: 0.5625em 0.625em; font-size: inherit; color: #6d6e71; }
+table tr.even, table tr.alt, table tr:nth-of-type(even) { background: #edf2f2; }
+table thead tr th, table tfoot tr th, table tbody tr td, table tr td, table tfoot tr td { display: table-cell; line-height: 1.4; }
+
+body { -moz-osx-font-smoothing: grayscale; -webkit-font-smoothing: antialiased; tab-size: 4; }
+
+h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { line-height: 1.4; }
+
+a:hover, a:focus { text-decoration: underline; }
+
+.clearfix:before, .clearfix:after, .float-group:before, .float-group:after { content: " "; display: table; }
+.clearfix:after, .float-group:after { clear: both; }
+
+*:not(pre) > code { font-size: inherit; font-style: normal !important; letter-spacing: 0; padding: 0; background-color: white; -webkit-border-radius: 0; border-radius: 0; line-height: inherit; word-wrap: break-word; }
+*:not(pre) > code.nobreak { word-wrap: normal; }
+*:not(pre) > code.nowrap { white-space: nowrap; }
+
+pre, pre > code { line-height: 1.6; color: #264357; font-family: Consolas, "Liberation Mono", Courier, monospace; font-weight: normal; }
+
+em em { font-style: normal; }
+
+strong strong { font-weight: normal; }
+
+.keyseq { color: #333333; }
+
+kbd { font-family: Consolas, "Liberation Mono", Courier, monospace; display: inline-block; color: black; font-size: 0.65em; line-height: 1.45; background-color: #f7f7f7; border: 1px solid #ccc; -webkit-border-radius: 3px; border-radius: 3px; -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 0.1em white inset; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 0.1em white inset; margin: 0 0.15em; padding: 0.2em 0.5em; vertical-align: middle; position: relative; top: -0.1em; white-space: nowrap; }
+
+.keyseq kbd:first-child { margin-left: 0; }
+
+.keyseq kbd:last-child { margin-right: 0; }
+
+.menuseq, .menuref { color: #000; }
+
+.menuseq b:not(.caret), .menuref { font-weight: inherit; }
+
+.menuseq { word-spacing: -0.02em; }
+.menuseq b.caret { font-size: 1.25em; line-height: 0.8; }
+.menuseq i.caret { font-weight: bold; text-align: center; width: 0.45em; }
+
+b.button:before, b.button:after { position: relative; top: -1px; font-weight: normal; }
+
+b.button:before { content: "["; padding: 0 3px 0 2px; }
+
+b.button:after { content: "]"; padding: 0 2px 0 3px; }
+
+#header, #content, #footnotes, #footer { width: 100%; margin-left: auto; margin-right: auto; margin-top: 0; margin-bottom: 0; max-width: 62.5em; *zoom: 1; position: relative; padding-left: 1.5em; padding-right: 1.5em; }
+#header:before, #header:after, #content:before, #content:after, #footnotes:before, #footnotes:after, #footer:before, #footer:after { content: " "; display: table; }
+#header:after, #content:after, #footnotes:after, #footer:after { clear: both; }
+
+#content { margin-top: 1.25em; }
+
+#content:before { content: none; }
+
+#header > h1:first-child { color: black; margin-top: 2.25rem; margin-bottom: 0; }
+#header > h1:first-child + #toc { margin-top: 8px; border-top: 1px solid #dddddd; }
+#header > h1:only-child, body.toc2 #header > h1:nth-last-child(2) { border-bottom: 1px solid #dddddd; padding-bottom: 8px; }
+#header .details { border-bottom: 1px solid #dddddd; line-height: 1.45; padding-top: 0.25em; padding-bottom: 0.25em; padding-left: 0.25em; color: #5e93b8; display: -ms-flexbox; display: -webkit-flex; display: flex; -ms-flex-flow: row wrap; -webkit-flex-flow: row wrap; flex-flow: row wrap; }
+#header .details span:first-child { margin-left: -0.125em; }
+#header .details span.email a { color: #333333; }
+#header .details br { display: none; }
+#header .details br + span:before { content: "\00a0\2013\00a0"; }
+#header .details br + span.author:before { content: "\00a0\22c5\00a0"; color: #333333; }
+#header .details br + span#revremark:before { content: "\00a0|\00a0"; }
+#header #revnumber { text-transform: capitalize; }
+#header #revnumber:after { content: "\00a0"; }
+
+#content > h1:first-child:not([class]) { color: black; border-bottom: 1px solid #dddddd; padding-bottom: 8px; margin-top: 0; padding-top: 1rem; margin-bottom: 1.25rem; }
+
+#toc { border-bottom: 0 solid #dddddd; padding-bottom: 0.5em; }
+#toc > ul { margin-left: 0.125em; }
+#toc ul.sectlevel0 > li > a { font-style: italic; }
+#toc ul.sectlevel0 ul.sectlevel1 { margin: 0.5em 0; }
+#toc ul { font-family: Noto, sans-serif; list-style-type: none; }
+#toc li { line-height: 1.3334; margin-top: 0.3334em; }
+#toc a { text-decoration: none; }
+#toc a:active { text-decoration: underline; }
+
+#toctitle { color: black; font-size: 1.2em; }
+
+@media only screen and (min-width: 768px) { #toctitle { font-size: 1.375em; }
+  body.toc2 { padding-left: 15em; padding-right: 0; }
+  #toc.toc2 { margin-top: 0 !important; background-color: white; position: fixed; width: 15em; left: 0; top: 0; border-right: 1px solid #dddddd; border-top-width: 0 !important; border-bottom-width: 0 !important; z-index: 1000; padding: 1.25em 1em; height: 100%; overflow: auto; }
+  #toc.toc2 #toctitle { margin-top: 0; margin-bottom: 0.8rem; font-size: 1.2em; }
+  #toc.toc2 > ul { font-size: 0.9em; margin-bottom: 0; }
+  #toc.toc2 ul ul { margin-left: 0; padding-left: 1em; }
+  #toc.toc2 ul.sectlevel0 ul.sectlevel1 { padding-left: 0; margin-top: 0.5em; margin-bottom: 0.5em; }
+  body.toc2.toc-right { padding-left: 0; padding-right: 15em; }
+  body.toc2.toc-right #toc.toc2 { border-right-width: 0; border-left: 1px solid #dddddd; left: auto; right: 0; } }
+@media only screen and (min-width: 1280px) { body.toc2 { padding-left: 20em; padding-right: 0; }
+  #toc.toc2 { width: 20em; }
+  #toc.toc2 #toctitle { font-size: 1.375em; }
+  #toc.toc2 > ul { font-size: 0.95em; }
+  #toc.toc2 ul ul { padding-left: 1.25em; }
+  body.toc2.toc-right { padding-left: 0; padding-right: 20em; } }
+#content #toc { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 0; border-radius: 0; }
+#content #toc > :first-child { margin-top: 0; }
+#content #toc > :last-child { margin-bottom: 0; }
+
+#footer { max-width: 100%; background-color: none; padding: 1.25em; }
+
+#footer-text { color: black; line-height: 1.44; }
+
+#content { margin-bottom: 0.625em; }
+
+.sect1 { padding-bottom: 0.625em; }
+
+@media only screen and (min-width: 768px) { #content { margin-bottom: 1.25em; }
+  .sect1 { padding-bottom: 1.25em; } }
+.sect1:last-child { padding-bottom: 0; }
+
+.sect1 + .sect1 { border-top: 0 solid #dddddd; }
+
+#content h1 > a.anchor, h2 > a.anchor, h3 > a.anchor, #toctitle > a.anchor, .sidebarblock > .content > .title > a.anchor, h4 > a.anchor, h5 > a.anchor, h6 > a.anchor { position: absolute; z-index: 1001; width: 1.5ex; margin-left: -1.5ex; display: block; text-decoration: none !important; visibility: hidden; text-align: center; font-weight: normal; }
+#content h1 > a.anchor:before, h2 > a.anchor:before, h3 > a.anchor:before, #toctitle > a.anchor:before, .sidebarblock > .content > .title > a.anchor:before, h4 > a.anchor:before, h5 > a.anchor:before, h6 > a.anchor:before { content: "\00A7"; font-size: 0.85em; display: block; padding-top: 0.1em; }
+#content h1:hover > a.anchor, #content h1 > a.anchor:hover, h2:hover > a.anchor, h2 > a.anchor:hover, h3:hover > a.anchor, #toctitle:hover > a.anchor, .sidebarblock > .content > .title:hover > a.anchor, h3 > a.anchor:hover, #toctitle > a.anchor:hover, .sidebarblock > .content > .title > a.anchor:hover, h4:hover > a.anchor, h4 > a.anchor:hover, h5:hover > a.anchor, h5 > a.anchor:hover, h6:hover > a.anchor, h6 > a.anchor:hover { visibility: visible; }
+#content h1 > a.link, h2 > a.link, h3 > a.link, #toctitle > a.link, .sidebarblock > .content > .title > a.link, h4 > a.link, h5 > a.link, h6 > a.link { color: black; text-decoration: none; }
+#content h1 > a.link:hover, h2 > a.link:hover, h3 > a.link:hover, #toctitle > a.link:hover, .sidebarblock > .content > .title > a.link:hover, h4 > a.link:hover, h5 > a.link:hover, h6 > a.link:hover { color: black; }
+
+.audioblock, .imageblock, .literalblock, .listingblock, .stemblock, .videoblock { margin-bottom: 1.25em; }
+
+.admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { text-rendering: optimizeLegibility; text-align: left; }
+
+table.tableblock > caption.title { white-space: nowrap; overflow: visible; max-width: 0; }
+
+.paragraph.lead > p, #preamble > .sectionbody > .paragraph:first-of-type p { color: black; }
+
+table.tableblock #preamble > .sectionbody > .paragraph:first-of-type p { font-size: inherit; }
+
+.admonitionblock > table { border-collapse: separate; border: 0; background: none; width: 100%; }
+.admonitionblock > table td.icon { text-align: center; width: 80px; }
+.admonitionblock > table td.icon img { max-width: initial; }
+.admonitionblock > table td.icon .title { font-weight: bold; font-family: Noto, sans-serif; text-transform: uppercase; }
+.admonitionblock > table td.content { padding-left: 1.125em; padding-right: 1.25em; border-left: 1px solid #dddddd; color: #5e93b8; }
+.admonitionblock > table td.content > :last-child > :last-child { margin-bottom: 0; }
+
+.exampleblock > .content { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 0; border-radius: 0; }
+.exampleblock > .content > :first-child { margin-top: 0; }
+.exampleblock > .content > :last-child { margin-bottom: 0; }
+
+.sidebarblock { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 0; border-radius: 0; }
+.sidebarblock > :first-child { margin-top: 0; }
+.sidebarblock > :last-child { margin-bottom: 0; }
+.sidebarblock > .content > .title { color: black; margin-top: 0; }
+
+.exampleblock > .content > :last-child > :last-child, .exampleblock > .content .olist > ol > li:last-child > :last-child, .exampleblock > .content .ulist > ul > li:last-child > :last-child, .exampleblock > .content .qlist > ol > li:last-child > :last-child, .sidebarblock > .content > :last-child > :last-child, .sidebarblock > .content .olist > ol > li:last-child > :last-child, .sidebarblock > .content .ulist > ul > li:last-child > :last-child, .sidebarblock > .content .qlist > ol > li:last-child > :last-child { margin-bottom: 0; }
+
+.literalblock pre, .listingblock pre:not(.highlight), .listingblock pre[class="highlight"], .listingblock pre[class^="highlight "], .listingblock pre.CodeRay, .listingblock pre.prettyprint { background: #eeeeee; }
+.sidebarblock .literalblock pre, .sidebarblock .listingblock pre:not(.highlight), .sidebarblock .listingblock pre[class="highlight"], .sidebarblock .listingblock pre[class^="highlight "], .sidebarblock .listingblock pre.CodeRay, .sidebarblock .listingblock pre.prettyprint { background: #f2f1f1; }
+
+.literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { border: 1px hidden #666666; -webkit-border-radius: 0; border-radius: 0; word-wrap: break-word; padding: 1.25em 1.5625em 1.125em 1.5625em; font-size: 0.8125em; }
+.literalblock pre.nowrap, .literalblock pre[class].nowrap, .listingblock pre.nowrap, .listingblock pre[class].nowrap { overflow-x: auto; white-space: pre; word-wrap: normal; }
+@media only screen and (min-width: 768px) { .literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { font-size: 0.90625em; } }
+@media only screen and (min-width: 1280px) { .literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { font-size: 1em; } }
+
+.literalblock.output pre { color: #eeeeee; background-color: #264357; }
+
+.listingblock pre.highlightjs { padding: 0; }
+.listingblock pre.highlightjs > code { padding: 1.25em 1.5625em 1.125em 1.5625em; -webkit-border-radius: 0; border-radius: 0; }
+
+.listingblock > .content { position: relative; }
+
+.listingblock code[data-lang]:before { display: none; content: attr(data-lang); position: absolute; font-size: 0.75em; top: 0.425rem; right: 0.5rem; line-height: 1; text-transform: uppercase; color: #999; }
+
+.listingblock:hover code[data-lang]:before { display: block; }
+
+.listingblock.terminal pre .command:before { content: attr(data-prompt); padding-right: 0.5em; color: #999; }
+
+.listingblock.terminal pre .command:not([data-prompt]):before { content: "$"; }
+
+table.pyhltable { border-collapse: separate; border: 0; margin-bottom: 0; background: none; }
+
+table.pyhltable td { vertical-align: top; padding-top: 0; padding-bottom: 0; line-height: 1.6; }
+
+table.pyhltable td.code { padding-left: .75em; padding-right: 0; }
+
+pre.pygments .lineno, table.pyhltable td:not(.code) { color: #999; padding-left: 0; padding-right: .5em; border-right: 1px solid #dddddd; }
+
+pre.pygments .lineno { display: inline-block; margin-right: .25em; }
+
+table.pyhltable .linenodiv { background: none !important; padding-right: 0 !important; }
+
+.quoteblock { margin: 0 1em 0.75em 1.5em; display: table; }
+.quoteblock > .title { margin-left: -1.5em; margin-bottom: 0.75em; }
+.quoteblock blockquote, .quoteblock blockquote p { color: #333333; font-size: 1.15rem; line-height: 1.75; word-spacing: 0.1em; letter-spacing: 0; font-style: italic; text-align: justify; }
+.quoteblock blockquote { margin: 0; padding: 0; border: 0; }
+.quoteblock blockquote:before { content: "\201c"; float: left; font-size: 2.75em; font-weight: bold; line-height: 0.6em; margin-left: -0.6em; color: black; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); }
+.quoteblock blockquote > .paragraph:last-child p { margin-bottom: 0; }
+.quoteblock .attribution { margin-top: 0.5em; margin-right: 0.5ex; text-align: right; }
+.quoteblock .quoteblock { margin-left: 0; margin-right: 0; padding: 0.5em 0; border-left: 3px solid #5e93b8; }
+.quoteblock .quoteblock blockquote { padding: 0 0 0 0.75em; }
+.quoteblock .quoteblock blockquote:before { display: none; }
+
+.verseblock { margin: 0 1em 0.75em 1em; }
+.verseblock pre { font-family: "Open Sans", "DejaVu Sans", sans; font-size: 1.15rem; color: #333333; font-weight: 300; text-rendering: optimizeLegibility; }
+.verseblock pre strong { font-weight: 400; }
+.verseblock .attribution { margin-top: 1.25rem; margin-left: 0.5ex; }
+
+.quoteblock .attribution, .verseblock .attribution { font-size: 0.8125em; line-height: 1.45; font-style: italic; }
+.quoteblock .attribution br, .verseblock .attribution br { display: none; }
+.quoteblock .attribution cite, .verseblock .attribution cite { display: block; letter-spacing: -0.025em; color: #5e93b8; }
+
+.quoteblock.abstract { margin: 0 0 0.75em 0; display: block; }
+.quoteblock.abstract blockquote, .quoteblock.abstract blockquote p { text-align: left; word-spacing: 0; }
+.quoteblock.abstract blockquote:before, .quoteblock.abstract blockquote p:first-of-type:before { display: none; }
+
+table.tableblock { max-width: 100%; border-collapse: separate; }
+table.tableblock td > .paragraph:last-child p > p:last-child, table.tableblock th > p:last-child, table.tableblock td > p:last-child { margin-bottom: 0; }
+
+table.tableblock, th.tableblock, td.tableblock { border: 0 solid #d8d8ce; }
+
+table.grid-all > thead > tr > .tableblock, table.grid-all > tbody > tr > .tableblock { border-width: 0 1px 1px 0; }
+
+table.grid-all > tfoot > tr > .tableblock { border-width: 1px 1px 0 0; }
+
+table.grid-cols > * > tr > .tableblock { border-width: 0 1px 0 0; }
+
+table.grid-rows > thead > tr > .tableblock, table.grid-rows > tbody > tr > .tableblock { border-width: 0 0 1px 0; }
+
+table.grid-rows > tfoot > tr > .tableblock { border-width: 1px 0 0 0; }
+
+table.grid-all > * > tr > .tableblock:last-child, table.grid-cols > * > tr > .tableblock:last-child { border-right-width: 0; }
+
+table.grid-all > tbody > tr:last-child > .tableblock, table.grid-all > thead:last-child > tr > .tableblock, table.grid-rows > tbody > tr:last-child > .tableblock, table.grid-rows > thead:last-child > tr > .tableblock { border-bottom-width: 0; }
+
+table.frame-all { border-width: 1px; }
+
+table.frame-sides { border-width: 0 1px; }
+
+table.frame-topbot { border-width: 1px 0; }
+
+th.halign-left, td.halign-left { text-align: left; }
+
+th.halign-right, td.halign-right { text-align: right; }
+
+th.halign-center, td.halign-center { text-align: center; }
+
+th.valign-top, td.valign-top { vertical-align: top; }
+
+th.valign-bottom, td.valign-bottom { vertical-align: bottom; }
+
+th.valign-middle, td.valign-middle { vertical-align: middle; }
+
+table thead th, table tfoot th { font-weight: bold; }
+
+tbody tr th { display: table-cell; line-height: 1.4; background: -webkit-linear-gradient(top, #add386, #90b66a); }
+
+tbody tr th, tbody tr th p, tfoot tr th, tfoot tr th p { color: white; font-weight: bold; }
+
+p.tableblock > code:only-child { background: none; padding: 0; }
+
+p.tableblock { font-size: 1em; }
+
+td > div.verse { white-space: pre; }
+
+ol { margin-left: 1.75em; }
+
+ul li ol { margin-left: 1.5em; }
+
+dl dd { margin-left: 1.125em; }
+
+dl dd:last-child, dl dd:last-child > :last-child { margin-bottom: 0; }
+
+ol > li p, ul > li p, ul dd, ol dd, .olist .olist, .ulist .ulist, .ulist .olist, .olist .ulist { margin-bottom: 0.375em; }
+
+ul.checklist, ul.none, ol.none, ul.no-bullet, ol.no-bullet, ol.unnumbered, ul.unstyled, ol.unstyled { list-style-type: none; }
+
+ul.no-bullet, ol.no-bullet, ol.unnumbered { margin-left: 0.625em; }
+
+ul.unstyled, ol.unstyled { margin-left: 0; }
+
+ul.checklist { margin-left: 0.625em; }
+
+ul.checklist li > p:first-child > .fa-square-o:first-child, ul.checklist li > p:first-child > .fa-check-square-o:first-child { width: 1.25em; font-size: 0.8em; position: relative; bottom: 0.125em; }
+
+ul.checklist li > p:first-child > input[type="checkbox"]:first-child { margin-right: 0.25em; }
+
+ul.inline { display: -ms-flexbox; display: -webkit-box; display: flex; -ms-flex-flow: row wrap; -webkit-flex-flow: row wrap; flex-flow: row wrap; list-style: none; margin: 0 0 0.375em -0.75em; }
+
+ul.inline > li { margin-left: 0.75em; }
+
+.unstyled dl dt { font-weight: normal; font-style: normal; }
+
+ol.arabic { list-style-type: decimal; }
+
+ol.decimal { list-style-type: decimal-leading-zero; }
+
+ol.loweralpha { list-style-type: lower-alpha; }
+
+ol.upperalpha { list-style-type: upper-alpha; }
+
+ol.lowerroman { list-style-type: lower-roman; }
+
+ol.upperroman { list-style-type: upper-roman; }
+
+ol.lowergreek { list-style-type: lower-greek; }
+
+.hdlist > table, .colist > table { border: 0; background: none; }
+.hdlist > table > tbody > tr, .colist > table > tbody > tr { background: none; }
+
+td.hdlist1, td.hdlist2 { vertical-align: top; padding: 0 0.625em; }
+
+td.hdlist1 { font-weight: bold; padding-bottom: 0.75em; }
+
+.literalblock + .colist, .listingblock + .colist { margin-top: -0.5em; }
+
+.colist > table tr > td:first-of-type { padding: 0.4em 0.75em 0 0.75em; line-height: 1; vertical-align: top; }
+.colist > table tr > td:first-of-type img { max-width: initial; }
+.colist > table tr > td:last-of-type { padding: 0.25em 0; }
+
+.thumb, .th { line-height: 0; display: inline-block; border: solid 4px white; -webkit-box-shadow: 0 0 0 1px #dddddd; box-shadow: 0 0 0 1px #dddddd; }
+
+.imageblock.left, .imageblock[style*="float: left"] { margin: 0.25em 0.625em 1.25em 0; }
+.imageblock.right, .imageblock[style*="float: right"] { margin: 0.25em 0 1.25em 0.625em; }
+.imageblock > .title { margin-bottom: 0; }
+.imageblock.thumb, .imageblock.th { border-width: 6px; }
+.imageblock.thumb > .title, .imageblock.th > .title { padding: 0 0.125em; }
+
+.image.left, .image.right { margin-top: 0.25em; margin-bottom: 0.25em; display: inline-block; line-height: 0; }
+.image.left { margin-right: 0.625em; }
+.image.right { margin-left: 0.625em; }
+
+a.image { text-decoration: none; display: inline-block; }
+a.image object { pointer-events: none; }
+
+sup.footnote, sup.footnoteref { font-size: 0.875em; position: static; vertical-align: super; }
+sup.footnote a, sup.footnoteref a { text-decoration: none; }
+sup.footnote a:active, sup.footnoteref a:active { text-decoration: underline; }
+
+#footnotes { padding-top: 0.75em; padding-bottom: 0.75em; margin-bottom: 0.625em; }
+#footnotes hr { width: 20%; min-width: 6.25em; margin: -0.25em 0 0.75em 0; border-width: 1px 0 0 0; }
+#footnotes .footnote { padding: 0 0.375em 0 0.225em; line-height: 1.3334; font-size: 0.875em; margin-left: 1.2em; margin-bottom: 0.2em; }
+#footnotes .footnote a:first-of-type { font-weight: bold; text-decoration: none; margin-left: -1.05em; }
+#footnotes .footnote:last-of-type { margin-bottom: 0; }
+#content #footnotes { margin-top: -0.625em; margin-bottom: 0; padding: 0.75em 0; }
+
+.gist .file-data > table { border: 0; background: #fff; width: 100%; margin-bottom: 0; }
+.gist .file-data > table td.line-data { width: 99%; }
+
+div.unbreakable { page-break-inside: avoid; }
+
+.big { font-size: larger; }
+
+.small { font-size: smaller; }
+
+.underline { text-decoration: underline; }
+
+.overline { text-decoration: overline; }
+
+.line-through { text-decoration: line-through; }
+
+.aqua { color: #00bfbf; }
+
+.aqua-background { background-color: #00fafa; }
+
+.black { color: black; }
+
+.black-background { background-color: black; }
+
+.blue { color: #0000bf; }
+
+.blue-background { background-color: #0000fa; }
+
+.fuchsia { color: #bf00bf; }
+
+.fuchsia-background { background-color: #fa00fa; }
+
+.gray { color: #606060; }
+
+.gray-background { background-color: #7d7d7d; }
+
+.green { color: #006000; }
+
+.green-background { background-color: #007d00; }
+
+.lime { color: #00bf00; }
+
+.lime-background { background-color: #00fa00; }
+
+.maroon { color: #600000; }
+
+.maroon-background { background-color: #7d0000; }
+
+.navy { color: #000060; }
+
+.navy-background { background-color: #00007d; }
+
+.olive { color: #606000; }
+
+.olive-background { background-color: #7d7d00; }
+
+.purple { color: #600060; }
+
+.purple-background { background-color: #7d007d; }
+
+.red { color: #bf0000; }
+
+.red-background { background-color: #fa0000; }
+
+.silver { color: #909090; }
+
+.silver-background { background-color: #bcbcbc; }
+
+.teal { color: #006060; }
+
+.teal-background { background-color: #007d7d; }
+
+.white { color: #bfbfbf; }
+
+.white-background { background-color: #fafafa; }
+
+.yellow { color: #bfbf00; }
+
+.yellow-background { background-color: #fafa00; }
+
+span.icon > .fa { cursor: default; }
+a span.icon > .fa { cursor: inherit; }
+
+.admonitionblock td.icon [class^="fa icon-"] { font-size: 2.5em; text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5); cursor: default; }
+.admonitionblock td.icon .icon-note:before { content: "\f05a"; color: #29475c; }
+.admonitionblock td.icon .icon-tip:before { content: "\f0eb"; text-shadow: 1px 1px 2px rgba(155, 155, 0, 0.8); color: #111; }
+.admonitionblock td.icon .icon-warning:before { content: "\f071"; color: #bf6900; }
+.admonitionblock td.icon .icon-caution:before { content: "\f06d"; color: #bf3400; }
+.admonitionblock td.icon .icon-important:before { content: "\f06a"; color: #bf0000; }
+
+.conum[data-value] { display: inline-block; color: #fff !important; background-color: black; -webkit-border-radius: 100px; border-radius: 100px; text-align: center; font-size: 0.75em; width: 1.67em; height: 1.67em; line-height: 1.67em; font-family: "Open Sans", "DejaVu Sans", sans-serif; font-style: normal; font-weight: bold; }
+.conum[data-value] * { color: #fff !important; }
+.conum[data-value] + b { display: none; }
+.conum[data-value]:after { content: attr(data-value); }
+pre .conum[data-value] { position: relative; top: -0.125em; }
+
+b.conum * { color: inherit !important; }
+
+.conum:not([data-value]):empty { display: none; }
+
+h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { border-bottom: 1px solid #dddddd; }
+
+.sect1 { padding-bottom: 0; }
+
+#toctitle { color: #00406F; font-weight: normal; margin-top: 1.5em; }
+
+.sidebarblock { border-color: #aaa; }
+
+code { -webkit-border-radius: 4px; border-radius: 4px; }
+
+p.tableblock.header { color: #6d6e71; }
+
+.literalblock pre, .listingblock pre { background: #eeeeee; }
+
+</style>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css">
+<style>
+/* Stylesheet for CodeRay to match GitHub theme | MIT License | http://foundation.zurb.com */
+/*pre.CodeRay {background-color:#f7f7f8;}*/
+.CodeRay .line-numbers{border-right:1px solid #d8d8d8;padding:0 0.5em 0 .25em}
+.CodeRay span.line-numbers{display:inline-block;margin-right:.5em;color:rgba(0,0,0,.3)}
+.CodeRay .line-numbers strong{color:rgba(0,0,0,.4)}
+table.CodeRay{border-collapse:separate;border-spacing:0;margin-bottom:0;border:0;background:none}
+table.CodeRay td{vertical-align: top;line-height:1.45}
+table.CodeRay td.line-numbers{text-align:right}
+table.CodeRay td.line-numbers>pre{padding:0;color:rgba(0,0,0,.3)}
+table.CodeRay td.code{padding:0 0 0 .5em}
+table.CodeRay td.code>pre{padding:0}
+.CodeRay .debug{color:#fff !important;background:#000080 !important}
+.CodeRay .annotation{color:#007}
+.CodeRay .attribute-name{color:#000080}
+.CodeRay .attribute-value{color:#700}
+.CodeRay .binary{color:#509}
+.CodeRay .comment{color:#998;font-style:italic}
+.CodeRay .char{color:#04d}
+.CodeRay .char .content{color:#04d}
+.CodeRay .char .delimiter{color:#039}
+.CodeRay .class{color:#458;font-weight:bold}
+.CodeRay .complex{color:#a08}
+.CodeRay .constant,.CodeRay .predefined-constant{color:#008080}
+.CodeRay .color{color:#099}
+.CodeRay .class-variable{color:#369}
+.CodeRay .decorator{color:#b0b}
+.CodeRay .definition{color:#099}
+.CodeRay .delimiter{color:#000}
+.CodeRay .doc{color:#970}
+.CodeRay .doctype{color:#34b}
+.CodeRay .doc-string{color:#d42}
+.CodeRay .escape{color:#666}
+.CodeRay .entity{color:#800}
+.CodeRay .error{color:#808}
+.CodeRay .exception{color:inherit}
+.CodeRay .filename{color:#099}
+.CodeRay .function{color:#900;font-weight:bold}
+.CodeRay .global-variable{color:#008080}
+.CodeRay .hex{color:#058}
+.CodeRay .integer,.CodeRay .float{color:#099}
+.CodeRay .include{color:#555}
+.CodeRay .inline{color:#000}
+.CodeRay .inline .inline{background:#ccc}
+.CodeRay .inline .inline .inline{background:#bbb}
+.CodeRay .inline .inline-delimiter{color:#d14}
+.CodeRay .inline-delimiter{color:#d14}
+.CodeRay .important{color:#555;font-weight:bold}
+.CodeRay .interpreted{color:#b2b}
+.CodeRay .instance-variable{color:#008080}
+.CodeRay .label{color:#970}
+.CodeRay .local-variable{color:#963}
+.CodeRay .octal{color:#40e}
+.CodeRay .predefined{color:#369}
+.CodeRay .preprocessor{color:#579}
+.CodeRay .pseudo-class{color:#555}
+.CodeRay .directive{font-weight:bold}
+.CodeRay .type{font-weight:bold}
+.CodeRay .predefined-type{color:inherit}
+.CodeRay .reserved,.CodeRay .keyword {color:#000;font-weight:bold}
+.CodeRay .key{color:#808}
+.CodeRay .key .delimiter{color:#606}
+.CodeRay .key .char{color:#80f}
+.CodeRay .value{color:#088}
+.CodeRay .regexp .delimiter{color:#808}
+.CodeRay .regexp .content{color:#808}
+.CodeRay .regexp .modifier{color:#808}
+.CodeRay .regexp .char{color:#d14}
+.CodeRay .regexp .function{color:#404;font-weight:bold}
+.CodeRay .string{color:#d20}
+.CodeRay .string .string .string{background:#ffd0d0}
+.CodeRay .string .content{color:#d14}
+.CodeRay .string .char{color:#d14}
+.CodeRay .string .delimiter{color:#d14}
+.CodeRay .shell{color:#d14}
+.CodeRay .shell .delimiter{color:#d14}
+.CodeRay .symbol{color:#990073}
+.CodeRay .symbol .content{color:#a60}
+.CodeRay .symbol .delimiter{color:#630}
+.CodeRay .tag{color:#008080}
+.CodeRay .tag-special{color:#d70}
+.CodeRay .variable{color:#036}
+.CodeRay .insert{background:#afa}
+.CodeRay .delete{background:#faa}
+.CodeRay .change{color:#aaf;background:#007}
+.CodeRay .head{color:#f8f;background:#505}
+.CodeRay .insert .insert{color:#080}
+.CodeRay .delete .delete{color:#800}
+.CodeRay .change .change{color:#66f}
+.CodeRay .head .head{color:#f4f}
+</style>
+<link rel="stylesheet" href="../katex/katex.min.css">
+<script src="../katex/katex.min.js"></script>
+<script src="../katex/contrib/auto-render.min.js"></script>
+    <!-- Use KaTeX to render math once document is loaded, see
+         https://github.com/Khan/KaTeX/tree/master/contrib/auto-render -->
+<script>
+    document.addEventListener("DOMContentLoaded", function () {
+        renderMathInElement(
+            document.body,
+            {
+                delimiters: [
+                    { left: "$$", right: "$$", display: true},
+                    { left: "\\[", right: "\\]", display: true},
+                    { left: "$", right: "$", display: false},
+                    { left: "\\(", right: "\\)", display: false}
+                ]
+            }
+        );
+    });
+</script></head>
+<body class="book toc2 toc-left" style="max-width: 100;">
+<div id="header">
+<h1>OpenCL ICD Installation Guidelines</h1>
+<div class="details">
+<span id="author" class="author">Khronos OpenCL Working Group</span><br>
+<span id="revnumber">version 2.2-7,</span>
+<span id="revdate">Sat, 12 May 2018 13:21:29 +0000</span>
+<br><span id="revremark">from git branch: master commit: ab6da3001e9eeafaa36c18888ca7eb4ebb9768af</span>
+</div>
+<div id="toc" class="toc2">
+<div id="toctitle">Table of Contents</div>
+<ul class="sectlevel1">
+<li><a href="#_introduction">1. Introduction</a></li>
+<li><a href="#_general_guidelines">2. General Guidelines</a>
+<ul class="sectlevel2">
+<li><a href="#_compatibility_with_non_icd_implementations">2.1. Compatibility With Non-ICD implementations</a></li>
+</ul>
+</li>
+<li><a href="#_windows_icd_installation_and_uninstallation">3. Windows ICD Installation and Uninstallation</a>
+<ul class="sectlevel2">
+<li><a href="#_windows_icd_installation">3.1. Windows ICD Installation</a></li>
+<li><a href="#_windows_icd_uninstallation">3.2. Windows ICD Uninstallation</a></li>
+<li><a href="#_opencl_dll_versioning">3.3. OpenCL.dll Versioning</a></li>
+</ul>
+</li>
+<li><a href="#_android_icd_installation">4. Android ICD Installation</a>
+<ul class="sectlevel2">
+<li><a href="#_target_device_filesystem">4.1. Target Device Filesystem</a></li>
+<li><a href="#_android_sdk_ndk">4.2. Android SDK/NDK</a></li>
+</ul>
+</li>
+</ul>
+</div>
+</div>
+<div id="content">
+<div id="preamble">
+<div class="sectionbody">
+<div class="paragraph">
+<p>Copyright 2008-2018 The Khronos Group.</p>
+</div>
+<div class="paragraph">
+<p>This specification is protected by copyright laws and contains material proprietary
+to the Khronos Group, Inc. Except as described by these terms, it or any components
+may not be reproduced, republished, distributed, transmitted, displayed, broadcast
+or otherwise exploited in any manner without the express prior written permission
+of Khronos Group.</p>
+</div>
+<div class="paragraph">
+<p>Khronos Group grants a conditional copyright license to use and reproduce the
+unmodified specification for any purpose, without fee or royalty, EXCEPT no licenses
+to any patent, trademark or other intellectual property rights are granted under
+these terms. Parties desiring to implement the specification and make use of
+Khronos trademarks in relation to that implementation, and receive reciprocal patent
+license protection under the Khronos IP Policy must become Adopters and confirm the
+implementation as conformant under the process defined by Khronos for this
+specification; see <a href="https://www.khronos.org/adopters" class="bare">https://www.khronos.org/adopters</a>.</p>
+</div>
+<div class="paragraph">
+<p>Khronos Group makes no, and expressly disclaims any, representations or warranties,
+express or implied, regarding this specification, including, without limitation:
+merchantability, fitness for a particular purpose, non-infringement of any
+intellectual property, correctness, accuracy, completeness, timeliness, and
+reliability. Under no circumstances will the Khronos Group, or any of its Promoters,
+Contributors or Members, or their respective partners, officers, directors,
+employees, agents or representatives be liable for any damages, whether direct,
+indirect, special or consequential damages for lost revenues, lost profits, or
+otherwise, arising from or in connection with these materials.</p>
+</div>
+<div class="paragraph">
+<p>Vulkan is a registered trademark and Khronos, OpenXR, SPIR, SPIR-V, SYCL, WebGL,
+WebCL, OpenVX, OpenVG, EGL, COLLADA, glTF, NNEF, OpenKODE, OpenKCAM, StreamInput,
+OpenWF, OpenSL ES, OpenMAX, OpenMAX AL, OpenMAX IL, OpenMAX DL, OpenML and DevU are
+trademarks of the Khronos Group Inc. ASTC is a trademark of ARM Holdings PLC,
+OpenCL is a trademark of Apple Inc. and OpenGL and OpenML are registered trademarks
+and the OpenGL ES and OpenGL SC logos are trademarks of Silicon Graphics
+International used under license by Khronos. All other product names, trademarks,
+and/or company names are used solely for identification and belong to their
+respective owners.</p>
+</div>
+<div style="page-break-after: always;"></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_introduction">1. Introduction</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>The OpenCL Installable Client Driver (ICD) is a mechanism to allow OpenCL implementations from multiple vendors to coexist on a system. A vendor OpenCL implementation is an OpenCL Installable Client Driver if it implements the extension <code>cl_khr_icd</code>, which is described in the OpenCL extension registry:</p>
+</div>
+<div class="paragraph">
+<p><a href="https://www.khronos.org/registry/OpenCL/extensions/khr/cl_khr_icd.txt" class="bare">https://www.khronos.org/registry/OpenCL/extensions/khr/cl_khr_icd.txt</a></p>
+</div>
+<div class="paragraph">
+<p>The ICD loader library is a shared resource that discovers and enumerates all OpenCL ICDs. It will typically be installed by an installer from one of the vendors.</p>
+</div>
+<div class="paragraph">
+<p>In order to prevent conflicts between vendor installers it is necessary to have strict guidelines for installation and uninstallation of the ICD loader library and associated system configuration.</p>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_general_guidelines">2. General Guidelines</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>Vendor installers MUST install and uninstall their ICD-compliant implementations in such a way that the installer:</p>
+</div>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>Installs its own ICD loader library if and only if the existing ICD loader library is older than the one being installed.</p>
+</li>
+<li>
+<p>Does not remove ICD loader library at uninstall if other implementations exist.</p>
+</li>
+<li>
+<p>Does not cause existing installations to become inoperable or unusable in any way. This includes, but is not limited to, WHQL and similar signed package certification check failures.</p>
+</li>
+<li>
+<p>Does not manipulate the vendor enumeration order within the ICD loader library except to add (or remove) the new vendor implementation.</p>
+</li>
+</ol>
+</div>
+<div class="sect2">
+<h3 id="_compatibility_with_non_icd_implementations">2.1. Compatibility With Non-ICD implementations</h3>
+<div class="paragraph">
+<p>Because the ICD loader library and a non-ICD OpenCL implementation are likely to share the same library file name, behavior is undefined if the ICD loader library is installed on a system with an existing non-ICD OpenCL implementation, or if a non-ICD OpenCL implementation is installed on a system with an existing ICD loader library. In particular, in this scenario the non-ICD OpenCL implementation, or the ICD OpenCL implementation, or both, may cease to function correctly.</p>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_windows_icd_installation_and_uninstallation">3. Windows ICD Installation and Uninstallation</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>On Windows, the ICD loader library is <code>OpenCL.dll</code>.</p>
+</div>
+<div class="paragraph">
+<p>In general, Windows Vendor installers MUST follow the guidelines described here:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><a href="https://msdn.microsoft.com/en-us/library/ms954376.aspx" class="bare">https://msdn.microsoft.com/en-us/library/ms954376.aspx</a></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If the Windows Vendor installer is using the <em>Windows Installer</em> then many of the steps below will happen automatically.</p>
+</div>
+<div class="sect2">
+<h3 id="_windows_icd_installation">3.1. Windows ICD Installation</h3>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>Vendor MAY include <code>OpenCL.dll</code> file in its vendor package.</p>
+</li>
+<li>
+<p>IF Vendor includes <code>OpenCL.dll</code> in the manifest of the signed vendor package, then Vendor MUST NOT include <code>OpenCL.dll</code> in the manifest of the signed vendor package to map to either of the following paths:</p>
+<div class="olist loweralpha">
+<ol class="loweralpha" type="a">
+<li>
+<p><code>%WINDIR%\system32\OpenCL.dll</code></p>
+</li>
+<li>
+<p><code>%WINDIR%\SysWOW64\OpenCL.dll</code></p>
+</li>
+</ol>
+</div>
+<div class="paragraph">
+<p>Vendor MAY include <code>OpenCL.dll</code> in the manifest of a signed package provided that a vendor specific directory is used, such as <code>%PROGRAMFILES%\&lt;vendor&gt;\OpenCL</code>.</p>
+</div>
+</li>
+<li>
+<p>Vendor MUST check for existing OpenCL installations before installing <code>OpenCL.dll</code>.</p>
+<div class="olist loweralpha">
+<ol class="loweralpha" type="a">
+<li>
+<p>Vendor SHALL check the version of <code>OpenCL.dll</code> located in</p>
+<div class="olist lowerroman">
+<ol class="lowerroman" type="i">
+<li>
+<p><code>%WINDIR%\System32\</code></p>
+</li>
+<li>
+<p><code>%WINDIR%\SysWOW64\</code></p>
+</li>
+</ol>
+</div>
+</li>
+<li>
+<p>IF <code>OpenCL.dll</code> is not present, install ICD in 3.a.i and/or 3.a.ii as appropriate.</p>
+</li>
+<li>
+<p>IF version of installed <code>OpenCL.dll</code> &lt; vendor <code>OpenCL.dll</code> version, then replace the installed <code>OpenCL.dll</code> in 3.a.i and/or 3.a.ii as appropriate.</p>
+</li>
+<li>
+<p>IF version of installed <code>OpenCL.dll</code> &gt;= vendor <code>OpenCL.dll</code> version, then vendor MUST NOT modify the installed <code>OpenCL.dll</code>.</p>
+</li>
+</ol>
+</div>
+<div class="paragraph">
+<p>Versioning of <code>OpenCL.dll</code> is described in a later section.</p>
+</div>
+</li>
+<li>
+<p>Vendor MUST accurately increment the reference count for <code>OpenCL.dll</code>.</p>
+<div class="olist loweralpha">
+<ol class="loweralpha" type="a">
+<li>
+<p>IF Vendor does not use the Windows Installer, the Vendor installer MUST increment the reference count under the registry key:</p>
+<div class="literalblock">
+<div class="content">
+<pre>HKLM\SOFTWARE\Microsoft\Windows\Current Version\SharedDLLs</pre>
+</div>
+</div>
+</li>
+</ol>
+</div>
+</li>
+</ol>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_windows_icd_uninstallation">3.2. Windows ICD Uninstallation</h3>
+<div class="paragraph">
+<p>Uninstalling <code>OpenCL.dll</code> should be straightforward since it is reference counted as a shared component.</p>
+</div>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>Vendor MUST accurately decrement the reference count for <code>OpenCL.dll</code> and delete it when the reference count reaches zero.</p>
+</li>
+</ol>
+</div>
+<div class="paragraph">
+<p>Note that older installers that do not comply with these guidelines may not check the reference count when uninstalling and hence may erroneously uninstall <code>OpenCL.dll</code> while it is still in use by another OpenCL implementation.  If this occurs, reinstalling the other OpenCL implementation will usually fix the issue.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_opencl_dll_versioning">3.3. OpenCL.dll Versioning</h3>
+<div class="paragraph">
+<p>The <code>OpenCL.dll</code> has a FileVersion string of the form “x.y.z.0”. The parts <strong><em>x</em></strong> and <strong><em>y</em></strong> denote the OpenCL major and minor version (2.2 at the time of writing this document). The third part <strong><em>z</em></strong> is a revision number which will be incremented for every change made to the ICD loader sources.</p>
+</div>
+<div class="paragraph">
+<p>For same version of OpenCL, higher <strong><em>z</em></strong> value means a later revision. For different versions of OpenCL a higher OpenCL version means a later revision, irrespective of the value of <strong><em>z</em></strong>.</p>
+</div>
+<div class="paragraph">
+<p>If a given OpenCL.dll file does not have a valid FileVersion string or if the FileVersion string is absent then the version should be considered to be "0.0.0.0".</p>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_android_icd_installation">4. Android ICD Installation</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>On Android, the ICD loader library is <code>libOpenCL.so</code>.</p>
+</div>
+<div class="sect2">
+<h3 id="_target_device_filesystem">4.1. Target Device Filesystem</h3>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>Vendor MUST install <code>libOpenCL.so</code> to reside directly within the directory <code>/vendor/lib/</code> which is one of the paths searched by the dynamic loader on an Android system.</p>
+</li>
+</ol>
+</div>
+<div class="paragraph">
+<p>Usually an Android system will have a single-vendor OpenCL installation, so the need to overwrite <code>libOpenCL.so</code> should not arise.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_android_sdk_ndk">4.2. Android SDK/NDK</h3>
+<div class="paragraph">
+<p>Vendors should package the <code>libOpenCL.so</code> stub for linking to user applications in their Android SDK/NDK and either configure the default environment, or provide instructions for configuring the build environment, or both.</p>
+</div>
+<div class="paragraph">
+<p>Typically a vendor should put <code>libOpenCL.so</code> inside a directory within the Android SDK/NDK package provided by the vendor for application development on the vendor’s device. The path to this directory should be added to LIBPATH in the default environment of the IDE (e.g. Eclipse) and other build configurations (e.g. Makefiles) in the SDK/NDK. The path should also be mentioned in the vendor documentation to allow application developers to write their own Makefiles or other build systems.</p>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div id="footer">
+<div id="footer-text">
+Version 2.2-7<br>
+Last updated 2018-05-03 23:50:18 BST
+</div>
+</div>
+
+
+</body>
+</html>
\ No newline at end of file
diff --git a/specs/2.2/katex/README.md b/specs/2.2/katex/README.md
new file mode 100644
index 0000000..5f8caa8
--- /dev/null
+++ b/specs/2.2/katex/README.md
@@ -0,0 +1,68 @@
+# [<img src="https://khan.github.io/KaTeX/katex-logo.svg" width="130" alt="KaTeX">](https://khan.github.io/KaTeX/) [![Build Status](https://travis-ci.org/Khan/KaTeX.svg?branch=master)](https://travis-ci.org/Khan/KaTeX)
+
+[![Join the chat at https://gitter.im/Khan/KaTeX](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Khan/KaTeX?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+
+KaTeX is a fast, easy-to-use JavaScript library for TeX math rendering on the web.
+
+ * **Fast:** KaTeX renders its math synchronously and doesn't need to reflow the page. See how it compares to a competitor in [this speed test](http://jsperf.com/katex-vs-mathjax/).
+ * **Print quality:** KaTeX’s layout is based on Donald Knuth’s TeX, the gold standard for math typesetting.
+ * **Self contained:** KaTeX has no dependencies and can easily be bundled with your website resources.
+ * **Server side rendering:** KaTeX produces the same output regardless of browser or environment, so you can pre-render expressions using Node.js and send them as plain HTML.
+
+KaTeX supports all major browsers, including Chrome, Safari, Firefox, Opera, and IE 8 - IE 11.  A list of supported  commands can be on the [wiki](https://github.com/Khan/KaTeX/wiki/Function-Support-in-KaTeX).
+
+## Usage
+
+You can [download KaTeX](https://github.com/khan/katex/releases) and host it on your server or include the `katex.min.js` and `katex.min.css` files on your page directly from a CDN:
+
+```html
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.6.0/katex.min.css">
+<script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.6.0/katex.min.js"></script>
+```
+
+#### In-browser rendering
+
+Call `katex.render` with a TeX expression and a DOM element to render into:
+
+```js
+katex.render("c = \\pm\\sqrt{a^2 + b^2}", element);
+```
+
+If KaTeX can't parse the expression, it throws a `katex.ParseError` error.
+
+#### Server side rendering or rendering to a string
+
+To generate HTML on the server or to generate an HTML string of the rendered math, you can use `katex.renderToString`:
+
+```js
+var html = katex.renderToString("c = \\pm\\sqrt{a^2 + b^2}");
+// '<span class="katex">...</span>'
+```
+
+Make sure to include the CSS and font files, but there is no need to include the JavaScript. Like `render`, `renderToString` throws if it can't parse the expression.
+
+#### Rendering options
+
+You can provide an object of options as the last argument to `katex.render` and `katex.renderToString`. Available options are:
+
+- `displayMode`: `boolean`. If `true` the math will be rendered in display mode, which will put the math in display style (so `\int` and `\sum` are large, for example), and will center the math on the page on its own line. If `false` the math will be rendered in inline mode. (default: `false`)
+- `throwOnError`: `boolean`. If `true`, KaTeX will throw a `ParseError` when it encounters an unsupported command. If `false`, KaTeX will render the unsupported command as text in the color given by `errorColor`. (default: `true`)
+- `errorColor`: `string`. A color string given in the format `"#XXX"` or `"#XXXXXX"`. This option determines the color which unsupported commands are rendered in. (default: `#cc0000`)
+
+For example:
+
+```js
+katex.render("c = \\pm\\sqrt{a^2 + b^2}", element, { displayMode: true });
+```
+
+#### Automatic rendering of math on a page
+
+Math on the page can be automatically rendered using the auto-render extension. See [the Auto-render README](contrib/auto-render/README.md) for more information.
+
+## Contributing
+
+See [CONTRIBUTING.md](CONTRIBUTING.md)
+
+## License
+
+KaTeX is licensed under the [MIT License](http://opensource.org/licenses/MIT).
diff --git a/specs/2.2/katex/contrib/auto-render.min.js b/specs/2.2/katex/contrib/auto-render.min.js
new file mode 100644
index 0000000..30cc312
--- /dev/null
+++ b/specs/2.2/katex/contrib/auto-render.min.js
@@ -0,0 +1 @@
+(function(e){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=e()}else if(typeof define==="function"&&define.amd){define([],e)}else{var t;if(typeof window!=="undefined"){t=window}else if(typeof global!=="undefined"){t=global}else if(typeof self!=="undefined"){t=self}else{t=this}t.renderMathInElement=e()}})(function(){var e,t,r;return function n(e,t,r){function a(o,l){if(!t[o]){if(!e[o]){var f=typeof require=="function"&&require;if(!l&&f)return f(o,!0);if(i)return i(o,!0);var d=new Error("Cannot find module '"+o+"'");throw d.code="MODULE_NOT_FOUND",d}var s=t[o]={exports:{}};e[o][0].call(s.exports,function(t){var r=e[o][1][t];return a(r?r:t)},s,s.exports,n,e,t,r)}return t[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)a(r[o]);return a}({1:[function(e,t,r){var n=e("./splitAtDelimiters");var a=function(e,t){var r=[{type:"text",data:e}];for(var a=0;a<t.length;a++){var i=t[a];r=n(r,i.left,i.right,i.display||false)}return r};var i=function(e,t){var r=a(e,t);var n=document.createDocumentFragment();for(var i=0;i<r.length;i++){if(r[i].type==="text"){n.appendChild(document.createTextNode(r[i].data))}else{var o=document.createElement("span");var l=r[i].data;try{katex.render(l,o,{displayMode:r[i].display})}catch(f){if(!(f instanceof katex.ParseError)){throw f}console.error("KaTeX auto-render: Failed to parse `"+r[i].data+"` with ",f);n.appendChild(document.createTextNode(r[i].rawData));continue}n.appendChild(o)}}return n};var o=function(e,t,r){for(var n=0;n<e.childNodes.length;n++){var a=e.childNodes[n];if(a.nodeType===3){var l=i(a.textContent,t);n+=l.childNodes.length-1;e.replaceChild(l,a)}else if(a.nodeType===1){var f=r.indexOf(a.nodeName.toLowerCase())===-1;if(f){o(a,t,r)}}}};var l={delimiters:[{left:"$$",right:"$$",display:true},{left:"\\[",right:"\\]",display:true},{left:"\\(",right:"\\)",display:false}],ignoredTags:["script","noscript","style","textarea","pre","code"]};var f=function(e){var t;var r;for(var n=1,a=arguments.length;n<a;n++){t=arguments[n];for(r in t){if(Object.prototype.hasOwnProperty.call(t,r)){e[r]=t[r]}}}return e};var d=function(e,t){if(!e){throw new Error("No element provided to render")}t=f({},l,t);o(e,t.delimiters,t.ignoredTags)};t.exports=d},{"./splitAtDelimiters":2}],2:[function(e,t,r){var n=function(e,t,r){var n=r;var a=0;var i=e.length;while(n<t.length){var o=t[n];if(a<=0&&t.slice(n,n+i)===e){return n}else if(o==="\\"){n++}else if(o==="{"){a++}else if(o==="}"){a--}n++}return-1};var a=function(e,t,r,a){var i=[];for(var o=0;o<e.length;o++){if(e[o].type==="text"){var l=e[o].data;var f=true;var d=0;var s;s=l.indexOf(t);if(s!==-1){d=s;i.push({type:"text",data:l.slice(0,d)});f=false}while(true){if(f){s=l.indexOf(t,d);if(s===-1){break}i.push({type:"text",data:l.slice(d,s)});d=s}else{s=n(r,l,d+t.length);if(s===-1){break}i.push({type:"math",data:l.slice(d+t.length,s),rawData:l.slice(d,s+r.length),display:a});d=s+r.length}f=!f}i.push({type:"text",data:l.slice(d)})}else{i.push(e[o])}}return i};t.exports=a},{}]},{},[1])(1)});
diff --git a/specs/2.2/katex/fonts/KaTeX_AMS-Regular.eot b/specs/2.2/katex/fonts/KaTeX_AMS-Regular.eot
new file mode 100644
index 0000000..784276a
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_AMS-Regular.eot
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_AMS-Regular.ttf b/specs/2.2/katex/fonts/KaTeX_AMS-Regular.ttf
new file mode 100644
index 0000000..6f1e0be
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_AMS-Regular.ttf
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_AMS-Regular.woff b/specs/2.2/katex/fonts/KaTeX_AMS-Regular.woff
new file mode 100644
index 0000000..4dded47
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_AMS-Regular.woff
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_AMS-Regular.woff2 b/specs/2.2/katex/fonts/KaTeX_AMS-Regular.woff2
new file mode 100644
index 0000000..ea81079
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_AMS-Regular.woff2
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Caligraphic-Bold.eot b/specs/2.2/katex/fonts/KaTeX_Caligraphic-Bold.eot
new file mode 100644
index 0000000..1a0db0c
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Caligraphic-Bold.eot
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Caligraphic-Bold.ttf b/specs/2.2/katex/fonts/KaTeX_Caligraphic-Bold.ttf
new file mode 100644
index 0000000..b94907d
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Caligraphic-Bold.ttf
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Caligraphic-Bold.woff b/specs/2.2/katex/fonts/KaTeX_Caligraphic-Bold.woff
new file mode 100644
index 0000000..799fa81
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Caligraphic-Bold.woff
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Caligraphic-Bold.woff2 b/specs/2.2/katex/fonts/KaTeX_Caligraphic-Bold.woff2
new file mode 100644
index 0000000..73bb542
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Caligraphic-Bold.woff2
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Caligraphic-Regular.eot b/specs/2.2/katex/fonts/KaTeX_Caligraphic-Regular.eot
new file mode 100644
index 0000000..6cc83d0
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Caligraphic-Regular.eot
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Caligraphic-Regular.ttf b/specs/2.2/katex/fonts/KaTeX_Caligraphic-Regular.ttf
new file mode 100644
index 0000000..cf51e20
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Caligraphic-Regular.ttf
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Caligraphic-Regular.woff b/specs/2.2/katex/fonts/KaTeX_Caligraphic-Regular.woff
new file mode 100644
index 0000000..f5e5c62
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Caligraphic-Regular.woff
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Caligraphic-Regular.woff2 b/specs/2.2/katex/fonts/KaTeX_Caligraphic-Regular.woff2
new file mode 100644
index 0000000..dd76d34
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Caligraphic-Regular.woff2
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Fraktur-Bold.eot b/specs/2.2/katex/fonts/KaTeX_Fraktur-Bold.eot
new file mode 100644
index 0000000..1960b10
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Fraktur-Bold.eot
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Fraktur-Bold.ttf b/specs/2.2/katex/fonts/KaTeX_Fraktur-Bold.ttf
new file mode 100644
index 0000000..7b0790f
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Fraktur-Bold.ttf
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Fraktur-Bold.woff b/specs/2.2/katex/fonts/KaTeX_Fraktur-Bold.woff
new file mode 100644
index 0000000..dc32571
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Fraktur-Bold.woff
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Fraktur-Bold.woff2 b/specs/2.2/katex/fonts/KaTeX_Fraktur-Bold.woff2
new file mode 100644
index 0000000..fdc4292
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Fraktur-Bold.woff2
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Fraktur-Regular.eot b/specs/2.2/katex/fonts/KaTeX_Fraktur-Regular.eot
new file mode 100644
index 0000000..e4e7379
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Fraktur-Regular.eot
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Fraktur-Regular.ttf b/specs/2.2/katex/fonts/KaTeX_Fraktur-Regular.ttf
new file mode 100644
index 0000000..063bc02
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Fraktur-Regular.ttf
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Fraktur-Regular.woff b/specs/2.2/katex/fonts/KaTeX_Fraktur-Regular.woff
new file mode 100644
index 0000000..c4b18d8
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Fraktur-Regular.woff
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Fraktur-Regular.woff2 b/specs/2.2/katex/fonts/KaTeX_Fraktur-Regular.woff2
new file mode 100644
index 0000000..4318d93
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Fraktur-Regular.woff2
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Main-Bold.eot b/specs/2.2/katex/fonts/KaTeX_Main-Bold.eot
new file mode 100644
index 0000000..80fbd02
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Main-Bold.eot
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Main-Bold.ttf b/specs/2.2/katex/fonts/KaTeX_Main-Bold.ttf
new file mode 100644
index 0000000..8e10722
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Main-Bold.ttf
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Main-Bold.woff b/specs/2.2/katex/fonts/KaTeX_Main-Bold.woff
new file mode 100644
index 0000000..43b361a
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Main-Bold.woff
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Main-Bold.woff2 b/specs/2.2/katex/fonts/KaTeX_Main-Bold.woff2
new file mode 100644
index 0000000..af57a96
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Main-Bold.woff2
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Main-Italic.eot b/specs/2.2/katex/fonts/KaTeX_Main-Italic.eot
new file mode 100644
index 0000000..fc77016
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Main-Italic.eot
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Main-Italic.ttf b/specs/2.2/katex/fonts/KaTeX_Main-Italic.ttf
new file mode 100644
index 0000000..d124495
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Main-Italic.ttf
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Main-Italic.woff b/specs/2.2/katex/fonts/KaTeX_Main-Italic.woff
new file mode 100644
index 0000000..e623236
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Main-Italic.woff
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Main-Italic.woff2 b/specs/2.2/katex/fonts/KaTeX_Main-Italic.woff2
new file mode 100644
index 0000000..944e974
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Main-Italic.woff2
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Main-Regular.eot b/specs/2.2/katex/fonts/KaTeX_Main-Regular.eot
new file mode 100644
index 0000000..dc60c09
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Main-Regular.eot
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Main-Regular.ttf b/specs/2.2/katex/fonts/KaTeX_Main-Regular.ttf
new file mode 100644
index 0000000..da5797f
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Main-Regular.ttf
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Main-Regular.woff b/specs/2.2/katex/fonts/KaTeX_Main-Regular.woff
new file mode 100644
index 0000000..37db672
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Main-Regular.woff
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Main-Regular.woff2 b/specs/2.2/katex/fonts/KaTeX_Main-Regular.woff2
new file mode 100644
index 0000000..4882042
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Main-Regular.woff2
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Math-BoldItalic.eot b/specs/2.2/katex/fonts/KaTeX_Math-BoldItalic.eot
new file mode 100644
index 0000000..52c8b8c
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Math-BoldItalic.eot
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Math-BoldItalic.ttf b/specs/2.2/katex/fonts/KaTeX_Math-BoldItalic.ttf
new file mode 100644
index 0000000..a8b527c
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Math-BoldItalic.ttf
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Math-BoldItalic.woff b/specs/2.2/katex/fonts/KaTeX_Math-BoldItalic.woff
new file mode 100644
index 0000000..8940e0b
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Math-BoldItalic.woff
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Math-BoldItalic.woff2 b/specs/2.2/katex/fonts/KaTeX_Math-BoldItalic.woff2
new file mode 100644
index 0000000..15cf56d
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Math-BoldItalic.woff2
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Math-Italic.eot b/specs/2.2/katex/fonts/KaTeX_Math-Italic.eot
new file mode 100644
index 0000000..64c8992
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Math-Italic.eot
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Math-Italic.ttf b/specs/2.2/katex/fonts/KaTeX_Math-Italic.ttf
new file mode 100644
index 0000000..06f39d3
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Math-Italic.ttf
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Math-Italic.woff b/specs/2.2/katex/fonts/KaTeX_Math-Italic.woff
new file mode 100644
index 0000000..cf3b4b7
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Math-Italic.woff
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Math-Italic.woff2 b/specs/2.2/katex/fonts/KaTeX_Math-Italic.woff2
new file mode 100644
index 0000000..5f8c4bf
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Math-Italic.woff2
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Math-Regular.eot b/specs/2.2/katex/fonts/KaTeX_Math-Regular.eot
new file mode 100644
index 0000000..5521e6a
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Math-Regular.eot
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Math-Regular.ttf b/specs/2.2/katex/fonts/KaTeX_Math-Regular.ttf
new file mode 100644
index 0000000..7312708
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Math-Regular.ttf
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Math-Regular.woff b/specs/2.2/katex/fonts/KaTeX_Math-Regular.woff
new file mode 100644
index 0000000..0e2ebdf
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Math-Regular.woff
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Math-Regular.woff2 b/specs/2.2/katex/fonts/KaTeX_Math-Regular.woff2
new file mode 100644
index 0000000..ebe3d02
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Math-Regular.woff2
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_SansSerif-Bold.eot b/specs/2.2/katex/fonts/KaTeX_SansSerif-Bold.eot
new file mode 100644
index 0000000..1660e76
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_SansSerif-Bold.eot
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_SansSerif-Bold.ttf b/specs/2.2/katex/fonts/KaTeX_SansSerif-Bold.ttf
new file mode 100644
index 0000000..dbeb7b9
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_SansSerif-Bold.ttf
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_SansSerif-Bold.woff b/specs/2.2/katex/fonts/KaTeX_SansSerif-Bold.woff
new file mode 100644
index 0000000..8f144a8
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_SansSerif-Bold.woff
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_SansSerif-Bold.woff2 b/specs/2.2/katex/fonts/KaTeX_SansSerif-Bold.woff2
new file mode 100644
index 0000000..329e855
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_SansSerif-Bold.woff2
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_SansSerif-Italic.eot b/specs/2.2/katex/fonts/KaTeX_SansSerif-Italic.eot
new file mode 100644
index 0000000..289ae3f
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_SansSerif-Italic.eot
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_SansSerif-Italic.ttf b/specs/2.2/katex/fonts/KaTeX_SansSerif-Italic.ttf
new file mode 100644
index 0000000..b3a2f38
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_SansSerif-Italic.ttf
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_SansSerif-Italic.woff b/specs/2.2/katex/fonts/KaTeX_SansSerif-Italic.woff
new file mode 100644
index 0000000..bddf7ea
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_SansSerif-Italic.woff
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_SansSerif-Italic.woff2 b/specs/2.2/katex/fonts/KaTeX_SansSerif-Italic.woff2
new file mode 100644
index 0000000..5fa767b
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_SansSerif-Italic.woff2
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_SansSerif-Regular.eot b/specs/2.2/katex/fonts/KaTeX_SansSerif-Regular.eot
new file mode 100644
index 0000000..1b38b98
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_SansSerif-Regular.eot
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_SansSerif-Regular.ttf b/specs/2.2/katex/fonts/KaTeX_SansSerif-Regular.ttf
new file mode 100644
index 0000000..e4712f8
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_SansSerif-Regular.ttf
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_SansSerif-Regular.woff b/specs/2.2/katex/fonts/KaTeX_SansSerif-Regular.woff
new file mode 100644
index 0000000..33be368
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_SansSerif-Regular.woff
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_SansSerif-Regular.woff2 b/specs/2.2/katex/fonts/KaTeX_SansSerif-Regular.woff2
new file mode 100644
index 0000000..4fcb2e2
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_SansSerif-Regular.woff2
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Script-Regular.eot b/specs/2.2/katex/fonts/KaTeX_Script-Regular.eot
new file mode 100644
index 0000000..7870d7f
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Script-Regular.eot
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Script-Regular.ttf b/specs/2.2/katex/fonts/KaTeX_Script-Regular.ttf
new file mode 100644
index 0000000..da4d113
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Script-Regular.ttf
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Script-Regular.woff b/specs/2.2/katex/fonts/KaTeX_Script-Regular.woff
new file mode 100644
index 0000000..d6ae79f
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Script-Regular.woff
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Script-Regular.woff2 b/specs/2.2/katex/fonts/KaTeX_Script-Regular.woff2
new file mode 100644
index 0000000..1b43deb
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Script-Regular.woff2
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Size1-Regular.eot b/specs/2.2/katex/fonts/KaTeX_Size1-Regular.eot
new file mode 100644
index 0000000..29950f9
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Size1-Regular.eot
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Size1-Regular.ttf b/specs/2.2/katex/fonts/KaTeX_Size1-Regular.ttf
new file mode 100644
index 0000000..194466a
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Size1-Regular.ttf
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Size1-Regular.woff b/specs/2.2/katex/fonts/KaTeX_Size1-Regular.woff
new file mode 100644
index 0000000..237f271
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Size1-Regular.woff
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Size1-Regular.woff2 b/specs/2.2/katex/fonts/KaTeX_Size1-Regular.woff2
new file mode 100644
index 0000000..39b6f8f
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Size1-Regular.woff2
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Size2-Regular.eot b/specs/2.2/katex/fonts/KaTeX_Size2-Regular.eot
new file mode 100644
index 0000000..b8b0536
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Size2-Regular.eot
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Size2-Regular.ttf b/specs/2.2/katex/fonts/KaTeX_Size2-Regular.ttf
new file mode 100644
index 0000000..b41b66a
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Size2-Regular.ttf
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Size2-Regular.woff b/specs/2.2/katex/fonts/KaTeX_Size2-Regular.woff
new file mode 100644
index 0000000..4a30558
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Size2-Regular.woff
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Size2-Regular.woff2 b/specs/2.2/katex/fonts/KaTeX_Size2-Regular.woff2
new file mode 100644
index 0000000..3facec1
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Size2-Regular.woff2
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Size3-Regular.eot b/specs/2.2/katex/fonts/KaTeX_Size3-Regular.eot
new file mode 100644
index 0000000..576b864
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Size3-Regular.eot
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Size3-Regular.ttf b/specs/2.2/katex/fonts/KaTeX_Size3-Regular.ttf
new file mode 100644
index 0000000..790ddbb
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Size3-Regular.ttf
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Size3-Regular.woff b/specs/2.2/katex/fonts/KaTeX_Size3-Regular.woff
new file mode 100644
index 0000000..3a6d062
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Size3-Regular.woff
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Size3-Regular.woff2 b/specs/2.2/katex/fonts/KaTeX_Size3-Regular.woff2
new file mode 100644
index 0000000..2cffafe
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Size3-Regular.woff2
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Size4-Regular.eot b/specs/2.2/katex/fonts/KaTeX_Size4-Regular.eot
new file mode 100644
index 0000000..c2b045f
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Size4-Regular.eot
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Size4-Regular.ttf b/specs/2.2/katex/fonts/KaTeX_Size4-Regular.ttf
new file mode 100644
index 0000000..ce660aa
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Size4-Regular.ttf
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Size4-Regular.woff b/specs/2.2/katex/fonts/KaTeX_Size4-Regular.woff
new file mode 100644
index 0000000..7826c6c
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Size4-Regular.woff
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Size4-Regular.woff2 b/specs/2.2/katex/fonts/KaTeX_Size4-Regular.woff2
new file mode 100644
index 0000000..c921898
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Size4-Regular.woff2
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Typewriter-Regular.eot b/specs/2.2/katex/fonts/KaTeX_Typewriter-Regular.eot
new file mode 100644
index 0000000..4c178f4
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Typewriter-Regular.eot
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Typewriter-Regular.ttf b/specs/2.2/katex/fonts/KaTeX_Typewriter-Regular.ttf
new file mode 100644
index 0000000..b0427ad
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Typewriter-Regular.ttf
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Typewriter-Regular.woff b/specs/2.2/katex/fonts/KaTeX_Typewriter-Regular.woff
new file mode 100644
index 0000000..78e9904
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Typewriter-Regular.woff
Binary files differ
diff --git a/specs/2.2/katex/fonts/KaTeX_Typewriter-Regular.woff2 b/specs/2.2/katex/fonts/KaTeX_Typewriter-Regular.woff2
new file mode 100644
index 0000000..618de99
--- /dev/null
+++ b/specs/2.2/katex/fonts/KaTeX_Typewriter-Regular.woff2
Binary files differ
diff --git a/specs/2.2/katex/katex.css b/specs/2.2/katex/katex.css
new file mode 100644
index 0000000..ef0aa62
--- /dev/null
+++ b/specs/2.2/katex/katex.css
@@ -0,0 +1,976 @@
+@font-face {
+  font-family: 'KaTeX_AMS';
+  src: url('fonts/KaTeX_AMS-Regular.eot');
+  src: url('fonts/KaTeX_AMS-Regular.eot#iefix') format('embedded-opentype'), url('fonts/KaTeX_AMS-Regular.woff2') format('woff2'), url('fonts/KaTeX_AMS-Regular.woff') format('woff'), url('fonts/KaTeX_AMS-Regular.ttf') format('truetype');
+  font-weight: normal;
+  font-style: normal;
+}
+@font-face {
+  font-family: 'KaTeX_Caligraphic';
+  src: url('fonts/KaTeX_Caligraphic-Bold.eot');
+  src: url('fonts/KaTeX_Caligraphic-Bold.eot#iefix') format('embedded-opentype'), url('fonts/KaTeX_Caligraphic-Bold.woff2') format('woff2'), url('fonts/KaTeX_Caligraphic-Bold.woff') format('woff'), url('fonts/KaTeX_Caligraphic-Bold.ttf') format('truetype');
+  font-weight: bold;
+  font-style: normal;
+}
+@font-face {
+  font-family: 'KaTeX_Caligraphic';
+  src: url('fonts/KaTeX_Caligraphic-Regular.eot');
+  src: url('fonts/KaTeX_Caligraphic-Regular.eot#iefix') format('embedded-opentype'), url('fonts/KaTeX_Caligraphic-Regular.woff2') format('woff2'), url('fonts/KaTeX_Caligraphic-Regular.woff') format('woff'), url('fonts/KaTeX_Caligraphic-Regular.ttf') format('truetype');
+  font-weight: normal;
+  font-style: normal;
+}
+@font-face {
+  font-family: 'KaTeX_Fraktur';
+  src: url('fonts/KaTeX_Fraktur-Bold.eot');
+  src: url('fonts/KaTeX_Fraktur-Bold.eot#iefix') format('embedded-opentype'), url('fonts/KaTeX_Fraktur-Bold.woff2') format('woff2'), url('fonts/KaTeX_Fraktur-Bold.woff') format('woff'), url('fonts/KaTeX_Fraktur-Bold.ttf') format('truetype');
+  font-weight: bold;
+  font-style: normal;
+}
+@font-face {
+  font-family: 'KaTeX_Fraktur';
+  src: url('fonts/KaTeX_Fraktur-Regular.eot');
+  src: url('fonts/KaTeX_Fraktur-Regular.eot#iefix') format('embedded-opentype'), url('fonts/KaTeX_Fraktur-Regular.woff2') format('woff2'), url('fonts/KaTeX_Fraktur-Regular.woff') format('woff'), url('fonts/KaTeX_Fraktur-Regular.ttf') format('truetype');
+  font-weight: normal;
+  font-style: normal;
+}
+@font-face {
+  font-family: 'KaTeX_Main';
+  src: url('fonts/KaTeX_Main-Bold.eot');
+  src: url('fonts/KaTeX_Main-Bold.eot#iefix') format('embedded-opentype'), url('fonts/KaTeX_Main-Bold.woff2') format('woff2'), url('fonts/KaTeX_Main-Bold.woff') format('woff'), url('fonts/KaTeX_Main-Bold.ttf') format('truetype');
+  font-weight: bold;
+  font-style: normal;
+}
+@font-face {
+  font-family: 'KaTeX_Main';
+  src: url('fonts/KaTeX_Main-Italic.eot');
+  src: url('fonts/KaTeX_Main-Italic.eot#iefix') format('embedded-opentype'), url('fonts/KaTeX_Main-Italic.woff2') format('woff2'), url('fonts/KaTeX_Main-Italic.woff') format('woff'), url('fonts/KaTeX_Main-Italic.ttf') format('truetype');
+  font-weight: normal;
+  font-style: italic;
+}
+@font-face {
+  font-family: 'KaTeX_Main';
+  src: url('fonts/KaTeX_Main-Regular.eot');
+  src: url('fonts/KaTeX_Main-Regular.eot#iefix') format('embedded-opentype'), url('fonts/KaTeX_Main-Regular.woff2') format('woff2'), url('fonts/KaTeX_Main-Regular.woff') format('woff'), url('fonts/KaTeX_Main-Regular.ttf') format('truetype');
+  font-weight: normal;
+  font-style: normal;
+}
+@font-face {
+  font-family: 'KaTeX_Math';
+  src: url('fonts/KaTeX_Math-Italic.eot');
+  src: url('fonts/KaTeX_Math-Italic.eot#iefix') format('embedded-opentype'), url('fonts/KaTeX_Math-Italic.woff2') format('woff2'), url('fonts/KaTeX_Math-Italic.woff') format('woff'), url('fonts/KaTeX_Math-Italic.ttf') format('truetype');
+  font-weight: normal;
+  font-style: italic;
+}
+@font-face {
+  font-family: 'KaTeX_SansSerif';
+  src: url('fonts/KaTeX_SansSerif-Regular.eot');
+  src: url('fonts/KaTeX_SansSerif-Regular.eot#iefix') format('embedded-opentype'), url('fonts/KaTeX_SansSerif-Regular.woff2') format('woff2'), url('fonts/KaTeX_SansSerif-Regular.woff') format('woff'), url('fonts/KaTeX_SansSerif-Regular.ttf') format('truetype');
+  font-weight: normal;
+  font-style: normal;
+}
+@font-face {
+  font-family: 'KaTeX_Script';
+  src: url('fonts/KaTeX_Script-Regular.eot');
+  src: url('fonts/KaTeX_Script-Regular.eot#iefix') format('embedded-opentype'), url('fonts/KaTeX_Script-Regular.woff2') format('woff2'), url('fonts/KaTeX_Script-Regular.woff') format('woff'), url('fonts/KaTeX_Script-Regular.ttf') format('truetype');
+  font-weight: normal;
+  font-style: normal;
+}
+@font-face {
+  font-family: 'KaTeX_Size1';
+  src: url('fonts/KaTeX_Size1-Regular.eot');
+  src: url('fonts/KaTeX_Size1-Regular.eot#iefix') format('embedded-opentype'), url('fonts/KaTeX_Size1-Regular.woff2') format('woff2'), url('fonts/KaTeX_Size1-Regular.woff') format('woff'), url('fonts/KaTeX_Size1-Regular.ttf') format('truetype');
+  font-weight: normal;
+  font-style: normal;
+}
+@font-face {
+  font-family: 'KaTeX_Size2';
+  src: url('fonts/KaTeX_Size2-Regular.eot');
+  src: url('fonts/KaTeX_Size2-Regular.eot#iefix') format('embedded-opentype'), url('fonts/KaTeX_Size2-Regular.woff2') format('woff2'), url('fonts/KaTeX_Size2-Regular.woff') format('woff'), url('fonts/KaTeX_Size2-Regular.ttf') format('truetype');
+  font-weight: normal;
+  font-style: normal;
+}
+@font-face {
+  font-family: 'KaTeX_Size3';
+  src: url('fonts/KaTeX_Size3-Regular.eot');
+  src: url('fonts/KaTeX_Size3-Regular.eot#iefix') format('embedded-opentype'), url('fonts/KaTeX_Size3-Regular.woff2') format('woff2'), url('fonts/KaTeX_Size3-Regular.woff') format('woff'), url('fonts/KaTeX_Size3-Regular.ttf') format('truetype');
+  font-weight: normal;
+  font-style: normal;
+}
+@font-face {
+  font-family: 'KaTeX_Size4';
+  src: url('fonts/KaTeX_Size4-Regular.eot');
+  src: url('fonts/KaTeX_Size4-Regular.eot#iefix') format('embedded-opentype'), url('fonts/KaTeX_Size4-Regular.woff2') format('woff2'), url('fonts/KaTeX_Size4-Regular.woff') format('woff'), url('fonts/KaTeX_Size4-Regular.ttf') format('truetype');
+  font-weight: normal;
+  font-style: normal;
+}
+@font-face {
+  font-family: 'KaTeX_Typewriter';
+  src: url('fonts/KaTeX_Typewriter-Regular.eot');
+  src: url('fonts/KaTeX_Typewriter-Regular.eot#iefix') format('embedded-opentype'), url('fonts/KaTeX_Typewriter-Regular.woff2') format('woff2'), url('fonts/KaTeX_Typewriter-Regular.woff') format('woff'), url('fonts/KaTeX_Typewriter-Regular.ttf') format('truetype');
+  font-weight: normal;
+  font-style: normal;
+}
+.katex-display {
+  display: block;
+  margin: 1em 0;
+  text-align: center;
+}
+.katex-display > .katex {
+  display: inline-block;
+  text-align: initial;
+}
+.katex {
+  font: normal 1.21em KaTeX_Main, Times New Roman, serif;
+  line-height: 1.2;
+  white-space: nowrap;
+  text-indent: 0;
+}
+.katex .katex-html {
+  display: inline-block;
+}
+.katex .katex-mathml {
+  position: absolute;
+  clip: rect(1px, 1px, 1px, 1px);
+  padding: 0;
+  border: 0;
+  height: 1px;
+  width: 1px;
+  overflow: hidden;
+}
+.katex .base {
+  display: inline-block;
+}
+.katex .strut {
+  display: inline-block;
+}
+.katex .mathrm {
+  font-style: normal;
+}
+.katex .textit {
+  font-style: italic;
+}
+.katex .mathit {
+  font-family: KaTeX_Math;
+  font-style: italic;
+}
+.katex .mathbf {
+  font-family: KaTeX_Main;
+  font-weight: bold;
+}
+.katex .amsrm {
+  font-family: KaTeX_AMS;
+}
+.katex .mathbb {
+  font-family: KaTeX_AMS;
+}
+.katex .mathcal {
+  font-family: KaTeX_Caligraphic;
+}
+.katex .mathfrak {
+  font-family: KaTeX_Fraktur;
+}
+.katex .mathtt {
+  font-family: KaTeX_Typewriter;
+}
+.katex .mathscr {
+  font-family: KaTeX_Script;
+}
+.katex .mathsf {
+  font-family: KaTeX_SansSerif;
+}
+.katex .mainit {
+  font-family: KaTeX_Main;
+  font-style: italic;
+}
+.katex .mord + .mop {
+  margin-left: 0.16667em;
+}
+.katex .mord + .mbin {
+  margin-left: 0.22222em;
+}
+.katex .mord + .mrel {
+  margin-left: 0.27778em;
+}
+.katex .mord + .minner {
+  margin-left: 0.16667em;
+}
+.katex .mop + .mord {
+  margin-left: 0.16667em;
+}
+.katex .mop + .mop {
+  margin-left: 0.16667em;
+}
+.katex .mop + .mrel {
+  margin-left: 0.27778em;
+}
+.katex .mop + .minner {
+  margin-left: 0.16667em;
+}
+.katex .mbin + .mord {
+  margin-left: 0.22222em;
+}
+.katex .mbin + .mop {
+  margin-left: 0.22222em;
+}
+.katex .mbin + .mopen {
+  margin-left: 0.22222em;
+}
+.katex .mbin + .minner {
+  margin-left: 0.22222em;
+}
+.katex .mrel + .mord {
+  margin-left: 0.27778em;
+}
+.katex .mrel + .mop {
+  margin-left: 0.27778em;
+}
+.katex .mrel + .mopen {
+  margin-left: 0.27778em;
+}
+.katex .mrel + .minner {
+  margin-left: 0.27778em;
+}
+.katex .mclose + .mop {
+  margin-left: 0.16667em;
+}
+.katex .mclose + .mbin {
+  margin-left: 0.22222em;
+}
+.katex .mclose + .mrel {
+  margin-left: 0.27778em;
+}
+.katex .mclose + .minner {
+  margin-left: 0.16667em;
+}
+.katex .mpunct + .mord {
+  margin-left: 0.16667em;
+}
+.katex .mpunct + .mop {
+  margin-left: 0.16667em;
+}
+.katex .mpunct + .mrel {
+  margin-left: 0.16667em;
+}
+.katex .mpunct + .mopen {
+  margin-left: 0.16667em;
+}
+.katex .mpunct + .mclose {
+  margin-left: 0.16667em;
+}
+.katex .mpunct + .mpunct {
+  margin-left: 0.16667em;
+}
+.katex .mpunct + .minner {
+  margin-left: 0.16667em;
+}
+.katex .minner + .mord {
+  margin-left: 0.16667em;
+}
+.katex .minner + .mop {
+  margin-left: 0.16667em;
+}
+.katex .minner + .mbin {
+  margin-left: 0.22222em;
+}
+.katex .minner + .mrel {
+  margin-left: 0.27778em;
+}
+.katex .minner + .mopen {
+  margin-left: 0.16667em;
+}
+.katex .minner + .mpunct {
+  margin-left: 0.16667em;
+}
+.katex .minner + .minner {
+  margin-left: 0.16667em;
+}
+.katex .mord.mtight {
+  margin-left: 0;
+}
+.katex .mop.mtight {
+  margin-left: 0;
+}
+.katex .mbin.mtight {
+  margin-left: 0;
+}
+.katex .mrel.mtight {
+  margin-left: 0;
+}
+.katex .mopen.mtight {
+  margin-left: 0;
+}
+.katex .mclose.mtight {
+  margin-left: 0;
+}
+.katex .mpunct.mtight {
+  margin-left: 0;
+}
+.katex .minner.mtight {
+  margin-left: 0;
+}
+.katex .mord + .mop.mtight {
+  margin-left: 0.16667em;
+}
+.katex .mop + .mord.mtight {
+  margin-left: 0.16667em;
+}
+.katex .mop + .mop.mtight {
+  margin-left: 0.16667em;
+}
+.katex .mclose + .mop.mtight {
+  margin-left: 0.16667em;
+}
+.katex .minner + .mop.mtight {
+  margin-left: 0.16667em;
+}
+.katex .reset-textstyle.textstyle {
+  font-size: 1em;
+}
+.katex .reset-textstyle.scriptstyle {
+  font-size: 0.7em;
+}
+.katex .reset-textstyle.scriptscriptstyle {
+  font-size: 0.5em;
+}
+.katex .reset-scriptstyle.textstyle {
+  font-size: 1.42857em;
+}
+.katex .reset-scriptstyle.scriptstyle {
+  font-size: 1em;
+}
+.katex .reset-scriptstyle.scriptscriptstyle {
+  font-size: 0.71429em;
+}
+.katex .reset-scriptscriptstyle.textstyle {
+  font-size: 2em;
+}
+.katex .reset-scriptscriptstyle.scriptstyle {
+  font-size: 1.4em;
+}
+.katex .reset-scriptscriptstyle.scriptscriptstyle {
+  font-size: 1em;
+}
+.katex .style-wrap {
+  position: relative;
+}
+.katex .vlist {
+  display: inline-block;
+}
+.katex .vlist > span {
+  display: block;
+  height: 0;
+  position: relative;
+}
+.katex .vlist > span > span {
+  display: inline-block;
+}
+.katex .vlist .baseline-fix {
+  display: inline-table;
+  table-layout: fixed;
+}
+.katex .msupsub {
+  text-align: left;
+}
+.katex .mfrac > span > span {
+  text-align: center;
+}
+.katex .mfrac .frac-line {
+  width: 100%;
+}
+.katex .mfrac .frac-line:before {
+  border-bottom-style: solid;
+  border-bottom-width: 1px;
+  content: "";
+  display: block;
+}
+.katex .mfrac .frac-line:after {
+  border-bottom-style: solid;
+  border-bottom-width: 0.04em;
+  content: "";
+  display: block;
+  margin-top: -1px;
+}
+.katex .mspace {
+  display: inline-block;
+}
+.katex .mspace.negativethinspace {
+  margin-left: -0.16667em;
+}
+.katex .mspace.thinspace {
+  width: 0.16667em;
+}
+.katex .mspace.negativemediumspace {
+  margin-left: -0.22222em;
+}
+.katex .mspace.mediumspace {
+  width: 0.22222em;
+}
+.katex .mspace.thickspace {
+  width: 0.27778em;
+}
+.katex .mspace.sixmuspace {
+  width: 0.333333em;
+}
+.katex .mspace.eightmuspace {
+  width: 0.444444em;
+}
+.katex .mspace.enspace {
+  width: 0.5em;
+}
+.katex .mspace.twelvemuspace {
+  width: 0.666667em;
+}
+.katex .mspace.quad {
+  width: 1em;
+}
+.katex .mspace.qquad {
+  width: 2em;
+}
+.katex .llap,
+.katex .rlap {
+  width: 0;
+  position: relative;
+}
+.katex .llap > .inner,
+.katex .rlap > .inner {
+  position: absolute;
+}
+.katex .llap > .fix,
+.katex .rlap > .fix {
+  display: inline-block;
+}
+.katex .llap > .inner {
+  right: 0;
+}
+.katex .rlap > .inner {
+  left: 0;
+}
+.katex .katex-logo .a {
+  font-size: 0.75em;
+  margin-left: -0.32em;
+  position: relative;
+  top: -0.2em;
+}
+.katex .katex-logo .t {
+  margin-left: -0.23em;
+}
+.katex .katex-logo .e {
+  margin-left: -0.1667em;
+  position: relative;
+  top: 0.2155em;
+}
+.katex .katex-logo .x {
+  margin-left: -0.125em;
+}
+.katex .rule {
+  display: inline-block;
+  border: solid 0;
+  position: relative;
+}
+.katex .overline .overline-line,
+.katex .underline .underline-line {
+  width: 100%;
+}
+.katex .overline .overline-line:before,
+.katex .underline .underline-line:before {
+  border-bottom-style: solid;
+  border-bottom-width: 1px;
+  content: "";
+  display: block;
+}
+.katex .overline .overline-line:after,
+.katex .underline .underline-line:after {
+  border-bottom-style: solid;
+  border-bottom-width: 0.04em;
+  content: "";
+  display: block;
+  margin-top: -1px;
+}
+.katex .sqrt > .sqrt-sign {
+  position: relative;
+}
+.katex .sqrt .sqrt-line {
+  width: 100%;
+}
+.katex .sqrt .sqrt-line:before {
+  border-bottom-style: solid;
+  border-bottom-width: 1px;
+  content: "";
+  display: block;
+}
+.katex .sqrt .sqrt-line:after {
+  border-bottom-style: solid;
+  border-bottom-width: 0.04em;
+  content: "";
+  display: block;
+  margin-top: -1px;
+}
+.katex .sqrt > .root {
+  margin-left: 0.27777778em;
+  margin-right: -0.55555556em;
+}
+.katex .sizing,
+.katex .fontsize-ensurer {
+  display: inline-block;
+}
+.katex .sizing.reset-size1.size1,
+.katex .fontsize-ensurer.reset-size1.size1 {
+  font-size: 1em;
+}
+.katex .sizing.reset-size1.size2,
+.katex .fontsize-ensurer.reset-size1.size2 {
+  font-size: 1.4em;
+}
+.katex .sizing.reset-size1.size3,
+.katex .fontsize-ensurer.reset-size1.size3 {
+  font-size: 1.6em;
+}
+.katex .sizing.reset-size1.size4,
+.katex .fontsize-ensurer.reset-size1.size4 {
+  font-size: 1.8em;
+}
+.katex .sizing.reset-size1.size5,
+.katex .fontsize-ensurer.reset-size1.size5 {
+  font-size: 2em;
+}
+.katex .sizing.reset-size1.size6,
+.katex .fontsize-ensurer.reset-size1.size6 {
+  font-size: 2.4em;
+}
+.katex .sizing.reset-size1.size7,
+.katex .fontsize-ensurer.reset-size1.size7 {
+  font-size: 2.88em;
+}
+.katex .sizing.reset-size1.size8,
+.katex .fontsize-ensurer.reset-size1.size8 {
+  font-size: 3.46em;
+}
+.katex .sizing.reset-size1.size9,
+.katex .fontsize-ensurer.reset-size1.size9 {
+  font-size: 4.14em;
+}
+.katex .sizing.reset-size1.size10,
+.katex .fontsize-ensurer.reset-size1.size10 {
+  font-size: 4.98em;
+}
+.katex .sizing.reset-size2.size1,
+.katex .fontsize-ensurer.reset-size2.size1 {
+  font-size: 0.71428571em;
+}
+.katex .sizing.reset-size2.size2,
+.katex .fontsize-ensurer.reset-size2.size2 {
+  font-size: 1em;
+}
+.katex .sizing.reset-size2.size3,
+.katex .fontsize-ensurer.reset-size2.size3 {
+  font-size: 1.14285714em;
+}
+.katex .sizing.reset-size2.size4,
+.katex .fontsize-ensurer.reset-size2.size4 {
+  font-size: 1.28571429em;
+}
+.katex .sizing.reset-size2.size5,
+.katex .fontsize-ensurer.reset-size2.size5 {
+  font-size: 1.42857143em;
+}
+.katex .sizing.reset-size2.size6,
+.katex .fontsize-ensurer.reset-size2.size6 {
+  font-size: 1.71428571em;
+}
+.katex .sizing.reset-size2.size7,
+.katex .fontsize-ensurer.reset-size2.size7 {
+  font-size: 2.05714286em;
+}
+.katex .sizing.reset-size2.size8,
+.katex .fontsize-ensurer.reset-size2.size8 {
+  font-size: 2.47142857em;
+}
+.katex .sizing.reset-size2.size9,
+.katex .fontsize-ensurer.reset-size2.size9 {
+  font-size: 2.95714286em;
+}
+.katex .sizing.reset-size2.size10,
+.katex .fontsize-ensurer.reset-size2.size10 {
+  font-size: 3.55714286em;
+}
+.katex .sizing.reset-size3.size1,
+.katex .fontsize-ensurer.reset-size3.size1 {
+  font-size: 0.625em;
+}
+.katex .sizing.reset-size3.size2,
+.katex .fontsize-ensurer.reset-size3.size2 {
+  font-size: 0.875em;
+}
+.katex .sizing.reset-size3.size3,
+.katex .fontsize-ensurer.reset-size3.size3 {
+  font-size: 1em;
+}
+.katex .sizing.reset-size3.size4,
+.katex .fontsize-ensurer.reset-size3.size4 {
+  font-size: 1.125em;
+}
+.katex .sizing.reset-size3.size5,
+.katex .fontsize-ensurer.reset-size3.size5 {
+  font-size: 1.25em;
+}
+.katex .sizing.reset-size3.size6,
+.katex .fontsize-ensurer.reset-size3.size6 {
+  font-size: 1.5em;
+}
+.katex .sizing.reset-size3.size7,
+.katex .fontsize-ensurer.reset-size3.size7 {
+  font-size: 1.8em;
+}
+.katex .sizing.reset-size3.size8,
+.katex .fontsize-ensurer.reset-size3.size8 {
+  font-size: 2.1625em;
+}
+.katex .sizing.reset-size3.size9,
+.katex .fontsize-ensurer.reset-size3.size9 {
+  font-size: 2.5875em;
+}
+.katex .sizing.reset-size3.size10,
+.katex .fontsize-ensurer.reset-size3.size10 {
+  font-size: 3.1125em;
+}
+.katex .sizing.reset-size4.size1,
+.katex .fontsize-ensurer.reset-size4.size1 {
+  font-size: 0.55555556em;
+}
+.katex .sizing.reset-size4.size2,
+.katex .fontsize-ensurer.reset-size4.size2 {
+  font-size: 0.77777778em;
+}
+.katex .sizing.reset-size4.size3,
+.katex .fontsize-ensurer.reset-size4.size3 {
+  font-size: 0.88888889em;
+}
+.katex .sizing.reset-size4.size4,
+.katex .fontsize-ensurer.reset-size4.size4 {
+  font-size: 1em;
+}
+.katex .sizing.reset-size4.size5,
+.katex .fontsize-ensurer.reset-size4.size5 {
+  font-size: 1.11111111em;
+}
+.katex .sizing.reset-size4.size6,
+.katex .fontsize-ensurer.reset-size4.size6 {
+  font-size: 1.33333333em;
+}
+.katex .sizing.reset-size4.size7,
+.katex .fontsize-ensurer.reset-size4.size7 {
+  font-size: 1.6em;
+}
+.katex .sizing.reset-size4.size8,
+.katex .fontsize-ensurer.reset-size4.size8 {
+  font-size: 1.92222222em;
+}
+.katex .sizing.reset-size4.size9,
+.katex .fontsize-ensurer.reset-size4.size9 {
+  font-size: 2.3em;
+}
+.katex .sizing.reset-size4.size10,
+.katex .fontsize-ensurer.reset-size4.size10 {
+  font-size: 2.76666667em;
+}
+.katex .sizing.reset-size5.size1,
+.katex .fontsize-ensurer.reset-size5.size1 {
+  font-size: 0.5em;
+}
+.katex .sizing.reset-size5.size2,
+.katex .fontsize-ensurer.reset-size5.size2 {
+  font-size: 0.7em;
+}
+.katex .sizing.reset-size5.size3,
+.katex .fontsize-ensurer.reset-size5.size3 {
+  font-size: 0.8em;
+}
+.katex .sizing.reset-size5.size4,
+.katex .fontsize-ensurer.reset-size5.size4 {
+  font-size: 0.9em;
+}
+.katex .sizing.reset-size5.size5,
+.katex .fontsize-ensurer.reset-size5.size5 {
+  font-size: 1em;
+}
+.katex .sizing.reset-size5.size6,
+.katex .fontsize-ensurer.reset-size5.size6 {
+  font-size: 1.2em;
+}
+.katex .sizing.reset-size5.size7,
+.katex .fontsize-ensurer.reset-size5.size7 {
+  font-size: 1.44em;
+}
+.katex .sizing.reset-size5.size8,
+.katex .fontsize-ensurer.reset-size5.size8 {
+  font-size: 1.73em;
+}
+.katex .sizing.reset-size5.size9,
+.katex .fontsize-ensurer.reset-size5.size9 {
+  font-size: 2.07em;
+}
+.katex .sizing.reset-size5.size10,
+.katex .fontsize-ensurer.reset-size5.size10 {
+  font-size: 2.49em;
+}
+.katex .sizing.reset-size6.size1,
+.katex .fontsize-ensurer.reset-size6.size1 {
+  font-size: 0.41666667em;
+}
+.katex .sizing.reset-size6.size2,
+.katex .fontsize-ensurer.reset-size6.size2 {
+  font-size: 0.58333333em;
+}
+.katex .sizing.reset-size6.size3,
+.katex .fontsize-ensurer.reset-size6.size3 {
+  font-size: 0.66666667em;
+}
+.katex .sizing.reset-size6.size4,
+.katex .fontsize-ensurer.reset-size6.size4 {
+  font-size: 0.75em;
+}
+.katex .sizing.reset-size6.size5,
+.katex .fontsize-ensurer.reset-size6.size5 {
+  font-size: 0.83333333em;
+}
+.katex .sizing.reset-size6.size6,
+.katex .fontsize-ensurer.reset-size6.size6 {
+  font-size: 1em;
+}
+.katex .sizing.reset-size6.size7,
+.katex .fontsize-ensurer.reset-size6.size7 {
+  font-size: 1.2em;
+}
+.katex .sizing.reset-size6.size8,
+.katex .fontsize-ensurer.reset-size6.size8 {
+  font-size: 1.44166667em;
+}
+.katex .sizing.reset-size6.size9,
+.katex .fontsize-ensurer.reset-size6.size9 {
+  font-size: 1.725em;
+}
+.katex .sizing.reset-size6.size10,
+.katex .fontsize-ensurer.reset-size6.size10 {
+  font-size: 2.075em;
+}
+.katex .sizing.reset-size7.size1,
+.katex .fontsize-ensurer.reset-size7.size1 {
+  font-size: 0.34722222em;
+}
+.katex .sizing.reset-size7.size2,
+.katex .fontsize-ensurer.reset-size7.size2 {
+  font-size: 0.48611111em;
+}
+.katex .sizing.reset-size7.size3,
+.katex .fontsize-ensurer.reset-size7.size3 {
+  font-size: 0.55555556em;
+}
+.katex .sizing.reset-size7.size4,
+.katex .fontsize-ensurer.reset-size7.size4 {
+  font-size: 0.625em;
+}
+.katex .sizing.reset-size7.size5,
+.katex .fontsize-ensurer.reset-size7.size5 {
+  font-size: 0.69444444em;
+}
+.katex .sizing.reset-size7.size6,
+.katex .fontsize-ensurer.reset-size7.size6 {
+  font-size: 0.83333333em;
+}
+.katex .sizing.reset-size7.size7,
+.katex .fontsize-ensurer.reset-size7.size7 {
+  font-size: 1em;
+}
+.katex .sizing.reset-size7.size8,
+.katex .fontsize-ensurer.reset-size7.size8 {
+  font-size: 1.20138889em;
+}
+.katex .sizing.reset-size7.size9,
+.katex .fontsize-ensurer.reset-size7.size9 {
+  font-size: 1.4375em;
+}
+.katex .sizing.reset-size7.size10,
+.katex .fontsize-ensurer.reset-size7.size10 {
+  font-size: 1.72916667em;
+}
+.katex .sizing.reset-size8.size1,
+.katex .fontsize-ensurer.reset-size8.size1 {
+  font-size: 0.28901734em;
+}
+.katex .sizing.reset-size8.size2,
+.katex .fontsize-ensurer.reset-size8.size2 {
+  font-size: 0.40462428em;
+}
+.katex .sizing.reset-size8.size3,
+.katex .fontsize-ensurer.reset-size8.size3 {
+  font-size: 0.46242775em;
+}
+.katex .sizing.reset-size8.size4,
+.katex .fontsize-ensurer.reset-size8.size4 {
+  font-size: 0.52023121em;
+}
+.katex .sizing.reset-size8.size5,
+.katex .fontsize-ensurer.reset-size8.size5 {
+  font-size: 0.57803468em;
+}
+.katex .sizing.reset-size8.size6,
+.katex .fontsize-ensurer.reset-size8.size6 {
+  font-size: 0.69364162em;
+}
+.katex .sizing.reset-size8.size7,
+.katex .fontsize-ensurer.reset-size8.size7 {
+  font-size: 0.83236994em;
+}
+.katex .sizing.reset-size8.size8,
+.katex .fontsize-ensurer.reset-size8.size8 {
+  font-size: 1em;
+}
+.katex .sizing.reset-size8.size9,
+.katex .fontsize-ensurer.reset-size8.size9 {
+  font-size: 1.19653179em;
+}
+.katex .sizing.reset-size8.size10,
+.katex .fontsize-ensurer.reset-size8.size10 {
+  font-size: 1.43930636em;
+}
+.katex .sizing.reset-size9.size1,
+.katex .fontsize-ensurer.reset-size9.size1 {
+  font-size: 0.24154589em;
+}
+.katex .sizing.reset-size9.size2,
+.katex .fontsize-ensurer.reset-size9.size2 {
+  font-size: 0.33816425em;
+}
+.katex .sizing.reset-size9.size3,
+.katex .fontsize-ensurer.reset-size9.size3 {
+  font-size: 0.38647343em;
+}
+.katex .sizing.reset-size9.size4,
+.katex .fontsize-ensurer.reset-size9.size4 {
+  font-size: 0.43478261em;
+}
+.katex .sizing.reset-size9.size5,
+.katex .fontsize-ensurer.reset-size9.size5 {
+  font-size: 0.48309179em;
+}
+.katex .sizing.reset-size9.size6,
+.katex .fontsize-ensurer.reset-size9.size6 {
+  font-size: 0.57971014em;
+}
+.katex .sizing.reset-size9.size7,
+.katex .fontsize-ensurer.reset-size9.size7 {
+  font-size: 0.69565217em;
+}
+.katex .sizing.reset-size9.size8,
+.katex .fontsize-ensurer.reset-size9.size8 {
+  font-size: 0.83574879em;
+}
+.katex .sizing.reset-size9.size9,
+.katex .fontsize-ensurer.reset-size9.size9 {
+  font-size: 1em;
+}
+.katex .sizing.reset-size9.size10,
+.katex .fontsize-ensurer.reset-size9.size10 {
+  font-size: 1.20289855em;
+}
+.katex .sizing.reset-size10.size1,
+.katex .fontsize-ensurer.reset-size10.size1 {
+  font-size: 0.20080321em;
+}
+.katex .sizing.reset-size10.size2,
+.katex .fontsize-ensurer.reset-size10.size2 {
+  font-size: 0.2811245em;
+}
+.katex .sizing.reset-size10.size3,
+.katex .fontsize-ensurer.reset-size10.size3 {
+  font-size: 0.32128514em;
+}
+.katex .sizing.reset-size10.size4,
+.katex .fontsize-ensurer.reset-size10.size4 {
+  font-size: 0.36144578em;
+}
+.katex .sizing.reset-size10.size5,
+.katex .fontsize-ensurer.reset-size10.size5 {
+  font-size: 0.40160643em;
+}
+.katex .sizing.reset-size10.size6,
+.katex .fontsize-ensurer.reset-size10.size6 {
+  font-size: 0.48192771em;
+}
+.katex .sizing.reset-size10.size7,
+.katex .fontsize-ensurer.reset-size10.size7 {
+  font-size: 0.57831325em;
+}
+.katex .sizing.reset-size10.size8,
+.katex .fontsize-ensurer.reset-size10.size8 {
+  font-size: 0.69477912em;
+}
+.katex .sizing.reset-size10.size9,
+.katex .fontsize-ensurer.reset-size10.size9 {
+  font-size: 0.8313253em;
+}
+.katex .sizing.reset-size10.size10,
+.katex .fontsize-ensurer.reset-size10.size10 {
+  font-size: 1em;
+}
+.katex .delimsizing.size1 {
+  font-family: KaTeX_Size1;
+}
+.katex .delimsizing.size2 {
+  font-family: KaTeX_Size2;
+}
+.katex .delimsizing.size3 {
+  font-family: KaTeX_Size3;
+}
+.katex .delimsizing.size4 {
+  font-family: KaTeX_Size4;
+}
+.katex .delimsizing.mult .delim-size1 > span {
+  font-family: KaTeX_Size1;
+}
+.katex .delimsizing.mult .delim-size4 > span {
+  font-family: KaTeX_Size4;
+}
+.katex .nulldelimiter {
+  display: inline-block;
+  width: 0.12em;
+}
+.katex .op-symbol {
+  position: relative;
+}
+.katex .op-symbol.small-op {
+  font-family: KaTeX_Size1;
+}
+.katex .op-symbol.large-op {
+  font-family: KaTeX_Size2;
+}
+.katex .op-limits > .vlist > span {
+  text-align: center;
+}
+.katex .accent > .vlist > span {
+  text-align: center;
+}
+.katex .accent .accent-body > span {
+  width: 0;
+}
+.katex .accent .accent-body.accent-vec > span {
+  position: relative;
+  left: 0.326em;
+}
+.katex .mtable .vertical-separator {
+  display: inline-block;
+  margin: 0 -0.025em;
+  border-right: 0.05em solid black;
+}
+.katex .mtable .arraycolsep {
+  display: inline-block;
+}
+.katex .mtable .col-align-c > .vlist {
+  text-align: center;
+}
+.katex .mtable .col-align-l > .vlist {
+  text-align: left;
+}
+.katex .mtable .col-align-r > .vlist {
+  text-align: right;
+}
diff --git a/specs/2.2/katex/katex.js b/specs/2.2/katex/katex.js
new file mode 100644
index 0000000..e104be9
--- /dev/null
+++ b/specs/2.2/katex/katex.js
@@ -0,0 +1,9075 @@
+(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.katex = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
+/* eslint no-console:0 */
+/**
+ * This is the main entry point for KaTeX. Here, we expose functions for
+ * rendering expressions either to DOM nodes or to markup strings.
+ *
+ * We also expose the ParseError class to check if errors thrown from KaTeX are
+ * errors in the expression, or errors in javascript handling.
+ */
+
+var ParseError = require("./src/ParseError");
+var Settings = require("./src/Settings");
+
+var buildTree = require("./src/buildTree");
+var parseTree = require("./src/parseTree");
+var utils = require("./src/utils");
+
+/**
+ * Parse and build an expression, and place that expression in the DOM node
+ * given.
+ */
+var render = function(expression, baseNode, options) {
+    utils.clearNode(baseNode);
+
+    var settings = new Settings(options);
+
+    var tree = parseTree(expression, settings);
+    var node = buildTree(tree, expression, settings).toNode();
+
+    baseNode.appendChild(node);
+};
+
+// KaTeX's styles don't work properly in quirks mode. Print out an error, and
+// disable rendering.
+if (typeof document !== "undefined") {
+    if (document.compatMode !== "CSS1Compat") {
+        typeof console !== "undefined" && console.warn(
+            "Warning: KaTeX doesn't work in quirks mode. Make sure your " +
+                "website has a suitable doctype.");
+
+        render = function() {
+            throw new ParseError("KaTeX doesn't work in quirks mode.");
+        };
+    }
+}
+
+/**
+ * Parse and build an expression, and return the markup for that.
+ */
+var renderToString = function(expression, options) {
+    var settings = new Settings(options);
+
+    var tree = parseTree(expression, settings);
+    return buildTree(tree, expression, settings).toMarkup();
+};
+
+/**
+ * Parse an expression and return the parse tree.
+ */
+var generateParseTree = function(expression, options) {
+    var settings = new Settings(options);
+    return parseTree(expression, settings);
+};
+
+module.exports = {
+    render: render,
+    renderToString: renderToString,
+    /**
+     * NOTE: This method is not currently recommended for public use.
+     * The internal tree representation is unstable and is very likely
+     * to change. Use at your own risk.
+     */
+    __parse: generateParseTree,
+    ParseError: ParseError
+};
+
+},{"./src/ParseError":6,"./src/Settings":8,"./src/buildTree":13,"./src/parseTree":22,"./src/utils":25}],2:[function(require,module,exports){
+/** @flow */
+
+"use strict";
+
+function getRelocatable(re) {
+  // In the future, this could use a WeakMap instead of an expando.
+  if (!re.__matchAtRelocatable) {
+    // Disjunctions are the lowest-precedence operator, so we can make any
+    // pattern match the empty string by appending `|()` to it:
+    // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-patterns
+    var source = re.source + "|()";
+
+    // We always make the new regex global.
+    var flags = "g" + (re.ignoreCase ? "i" : "") + (re.multiline ? "m" : "") + (re.unicode ? "u" : "")
+    // sticky (/.../y) doesn't make sense in conjunction with our relocation
+    // logic, so we ignore it here.
+    ;
+
+    re.__matchAtRelocatable = new RegExp(source, flags);
+  }
+  return re.__matchAtRelocatable;
+}
+
+function matchAt(re, str, pos) {
+  if (re.global || re.sticky) {
+    throw new Error("matchAt(...): Only non-global regexes are supported");
+  }
+  var reloc = getRelocatable(re);
+  reloc.lastIndex = pos;
+  var match = reloc.exec(str);
+  // Last capturing group is our sentinel that indicates whether the regex
+  // matched at the given location.
+  if (match[match.length - 1] == null) {
+    // Original regex matched.
+    match.length = match.length - 1;
+    return match;
+  } else {
+    return null;
+  }
+}
+
+module.exports = matchAt;
+},{}],3:[function(require,module,exports){
+/**
+ * The Lexer class handles tokenizing the input in various ways. Since our
+ * parser expects us to be able to backtrack, the lexer allows lexing from any
+ * given starting point.
+ *
+ * Its main exposed function is the `lex` function, which takes a position to
+ * lex from and a type of token to lex. It defers to the appropriate `_innerLex`
+ * function.
+ *
+ * The various `_innerLex` functions perform the actual lexing of different
+ * kinds.
+ */
+
+var matchAt = require("match-at");
+
+var ParseError = require("./ParseError");
+
+// The main lexer class
+function Lexer(input) {
+    this.input = input;
+    this.pos = 0;
+}
+
+/**
+ * The resulting token returned from `lex`.
+ *
+ * It consists of the token text plus some position information.
+ * The position information is essentially a range in an input string,
+ * but instead of referencing the bare input string, we refer to the lexer.
+ * That way it is possible to attach extra metadata to the input string,
+ * like for example a file name or similar.
+ *
+ * The position information (all three parameters) is optional,
+ * so it is OK to construct synthetic tokens if appropriate.
+ * Not providing available position information may lead to
+ * degraded error reporting, though.
+ *
+ * @param {string}  text   the text of this token
+ * @param {number=} start  the start offset, zero-based inclusive
+ * @param {number=} end    the end offset, zero-based exclusive
+ * @param {Lexer=}  lexer  the lexer which in turn holds the input string
+ */
+function Token(text, start, end, lexer) {
+    this.text = text;
+    this.start = start;
+    this.end = end;
+    this.lexer = lexer;
+}
+
+/**
+ * Given a pair of tokens (this and endToken), compute a “Token” encompassing
+ * the whole input range enclosed by these two.
+ *
+ * @param {Token}  endToken  last token of the range, inclusive
+ * @param {string} text      the text of the newly constructed token
+ */
+Token.prototype.range = function(endToken, text) {
+    if (endToken.lexer !== this.lexer) {
+        return new Token(text); // sorry, no position information available
+    }
+    return new Token(text, this.start, endToken.end, this.lexer);
+};
+
+/* The following tokenRegex
+ * - matches typical whitespace (but not NBSP etc.) using its first group
+ * - does not match any control character \x00-\x1f except whitespace
+ * - does not match a bare backslash
+ * - matches any ASCII character except those just mentioned
+ * - does not match the BMP private use area \uE000-\uF8FF
+ * - does not match bare surrogate code units
+ * - matches any BMP character except for those just described
+ * - matches any valid Unicode surrogate pair
+ * - matches a backslash followed by one or more letters
+ * - matches a backslash followed by any BMP character, including newline
+ * Just because the Lexer matches something doesn't mean it's valid input:
+ * If there is no matching function or symbol definition, the Parser will
+ * still reject the input.
+ */
+var tokenRegex = new RegExp(
+    "([ \r\n\t]+)|" +                                 // whitespace
+    "([!-\\[\\]-\u2027\u202A-\uD7FF\uF900-\uFFFF]" +  // single codepoint
+    "|[\uD800-\uDBFF][\uDC00-\uDFFF]" +               // surrogate pair
+    "|\\\\(?:[a-zA-Z]+|[^\uD800-\uDFFF])" +           // function name
+    ")"
+);
+
+/**
+ * This function lexes a single token.
+ */
+Lexer.prototype.lex = function() {
+    var input = this.input;
+    var pos = this.pos;
+    if (pos === input.length) {
+        return new Token("EOF", pos, pos, this);
+    }
+    var match = matchAt(tokenRegex, input, pos);
+    if (match === null) {
+        throw new ParseError(
+            "Unexpected character: '" + input[pos] + "'",
+            new Token(input[pos], pos, pos + 1, this));
+    }
+    var text = match[2] || " ";
+    var start = this.pos;
+    this.pos += match[0].length;
+    var end = this.pos;
+    return new Token(text, start, end, this);
+};
+
+module.exports = Lexer;
+
+},{"./ParseError":6,"match-at":2}],4:[function(require,module,exports){
+/**
+ * This file contains the “gullet” where macros are expanded
+ * until only non-macro tokens remain.
+ */
+
+var Lexer = require("./Lexer");
+
+function MacroExpander(input, macros) {
+    this.lexer = new Lexer(input);
+    this.macros = macros;
+    this.stack = []; // contains tokens in REVERSE order
+    this.discardedWhiteSpace = [];
+}
+
+/**
+ * Recursively expand first token, then return first non-expandable token.
+ */
+MacroExpander.prototype.nextToken = function() {
+    for (;;) {
+        if (this.stack.length === 0) {
+            this.stack.push(this.lexer.lex());
+        }
+        var topToken = this.stack.pop();
+        var name = topToken.text;
+        if (!(name.charAt(0) === "\\" && this.macros.hasOwnProperty(name))) {
+            return topToken;
+        }
+        var expansion = this.macros[name];
+        if (typeof expansion === "string") {
+            var bodyLexer = new Lexer(expansion);
+            expansion = [];
+            var tok = bodyLexer.lex();
+            while (tok.text !== "EOF") {
+                expansion.push(tok);
+                tok = bodyLexer.lex();
+            }
+            expansion.reverse(); // to fit in with stack using push and pop
+            this.macros[name] = expansion;
+        }
+        this.stack = this.stack.concat(expansion);
+    }
+};
+
+MacroExpander.prototype.get = function(ignoreSpace) {
+    this.discardedWhiteSpace = [];
+    var token = this.nextToken();
+    if (ignoreSpace) {
+        while (token.text === " ") {
+            this.discardedWhiteSpace.push(token);
+            token = this.nextToken();
+        }
+    }
+    return token;
+};
+
+/**
+ * Undo the effect of the preceding call to the get method.
+ * A call to this method MUST be immediately preceded and immediately followed
+ * by a call to get.  Only used during mode switching, i.e. after one token
+ * was got in the old mode but should get got again in a new mode
+ * with possibly different whitespace handling.
+ */
+MacroExpander.prototype.unget = function(token) {
+    this.stack.push(token);
+    while (this.discardedWhiteSpace.length !== 0) {
+        this.stack.push(this.discardedWhiteSpace.pop());
+    }
+};
+
+module.exports = MacroExpander;
+
+},{"./Lexer":3}],5:[function(require,module,exports){
+/**
+ * This file contains information about the options that the Parser carries
+ * around with it while parsing. Data is held in an `Options` object, and when
+ * recursing, a new `Options` object can be created with the `.with*` and
+ * `.reset` functions.
+ */
+
+/**
+ * This is the main options class. It contains the style, size, color, and font
+ * of the current parse level. It also contains the style and size of the parent
+ * parse level, so size changes can be handled efficiently.
+ *
+ * Each of the `.with*` and `.reset` functions passes its current style and size
+ * as the parentStyle and parentSize of the new options class, so parent
+ * handling is taken care of automatically.
+ */
+function Options(data) {
+    this.style = data.style;
+    this.color = data.color;
+    this.size = data.size;
+    this.phantom = data.phantom;
+    this.font = data.font;
+
+    if (data.parentStyle === undefined) {
+        this.parentStyle = data.style;
+    } else {
+        this.parentStyle = data.parentStyle;
+    }
+
+    if (data.parentSize === undefined) {
+        this.parentSize = data.size;
+    } else {
+        this.parentSize = data.parentSize;
+    }
+}
+
+/**
+ * Returns a new options object with the same properties as "this".  Properties
+ * from "extension" will be copied to the new options object.
+ */
+Options.prototype.extend = function(extension) {
+    var data = {
+        style: this.style,
+        size: this.size,
+        color: this.color,
+        parentStyle: this.style,
+        parentSize: this.size,
+        phantom: this.phantom,
+        font: this.font
+    };
+
+    for (var key in extension) {
+        if (extension.hasOwnProperty(key)) {
+            data[key] = extension[key];
+        }
+    }
+
+    return new Options(data);
+};
+
+/**
+ * Create a new options object with the given style.
+ */
+Options.prototype.withStyle = function(style) {
+    return this.extend({
+        style: style
+    });
+};
+
+/**
+ * Create a new options object with the given size.
+ */
+Options.prototype.withSize = function(size) {
+    return this.extend({
+        size: size
+    });
+};
+
+/**
+ * Create a new options object with the given color.
+ */
+Options.prototype.withColor = function(color) {
+    return this.extend({
+        color: color
+    });
+};
+
+/**
+ * Create a new options object with "phantom" set to true.
+ */
+Options.prototype.withPhantom = function() {
+    return this.extend({
+        phantom: true
+    });
+};
+
+/**
+ * Create a new options objects with the give font.
+ */
+Options.prototype.withFont = function(font) {
+    return this.extend({
+        font: font || this.font
+    });
+};
+
+/**
+ * Create a new options object with the same style, size, and color. This is
+ * used so that parent style and size changes are handled correctly.
+ */
+Options.prototype.reset = function() {
+    return this.extend({});
+};
+
+/**
+ * A map of color names to CSS colors.
+ * TODO(emily): Remove this when we have real macros
+ */
+var colorMap = {
+    "katex-blue": "#6495ed",
+    "katex-orange": "#ffa500",
+    "katex-pink": "#ff00af",
+    "katex-red": "#df0030",
+    "katex-green": "#28ae7b",
+    "katex-gray": "gray",
+    "katex-purple": "#9d38bd",
+    "katex-blueA": "#ccfaff",
+    "katex-blueB": "#80f6ff",
+    "katex-blueC": "#63d9ea",
+    "katex-blueD": "#11accd",
+    "katex-blueE": "#0c7f99",
+    "katex-tealA": "#94fff5",
+    "katex-tealB": "#26edd5",
+    "katex-tealC": "#01d1c1",
+    "katex-tealD": "#01a995",
+    "katex-tealE": "#208170",
+    "katex-greenA": "#b6ffb0",
+    "katex-greenB": "#8af281",
+    "katex-greenC": "#74cf70",
+    "katex-greenD": "#1fab54",
+    "katex-greenE": "#0d923f",
+    "katex-goldA": "#ffd0a9",
+    "katex-goldB": "#ffbb71",
+    "katex-goldC": "#ff9c39",
+    "katex-goldD": "#e07d10",
+    "katex-goldE": "#a75a05",
+    "katex-redA": "#fca9a9",
+    "katex-redB": "#ff8482",
+    "katex-redC": "#f9685d",
+    "katex-redD": "#e84d39",
+    "katex-redE": "#bc2612",
+    "katex-maroonA": "#ffbde0",
+    "katex-maroonB": "#ff92c6",
+    "katex-maroonC": "#ed5fa6",
+    "katex-maroonD": "#ca337c",
+    "katex-maroonE": "#9e034e",
+    "katex-purpleA": "#ddd7ff",
+    "katex-purpleB": "#c6b9fc",
+    "katex-purpleC": "#aa87ff",
+    "katex-purpleD": "#7854ab",
+    "katex-purpleE": "#543b78",
+    "katex-mintA": "#f5f9e8",
+    "katex-mintB": "#edf2df",
+    "katex-mintC": "#e0e5cc",
+    "katex-grayA": "#f6f7f7",
+    "katex-grayB": "#f0f1f2",
+    "katex-grayC": "#e3e5e6",
+    "katex-grayD": "#d6d8da",
+    "katex-grayE": "#babec2",
+    "katex-grayF": "#888d93",
+    "katex-grayG": "#626569",
+    "katex-grayH": "#3b3e40",
+    "katex-grayI": "#21242c",
+    "katex-kaBlue": "#314453",
+    "katex-kaGreen": "#71B307"
+};
+
+/**
+ * Gets the CSS color of the current options object, accounting for the
+ * `colorMap`.
+ */
+Options.prototype.getColor = function() {
+    if (this.phantom) {
+        return "transparent";
+    } else {
+        return colorMap[this.color] || this.color;
+    }
+};
+
+module.exports = Options;
+
+},{}],6:[function(require,module,exports){
+/**
+ * This is the ParseError class, which is the main error thrown by KaTeX
+ * functions when something has gone wrong. This is used to distinguish internal
+ * errors from errors in the expression that the user provided.
+ *
+ * If possible, a caller should provide a Token or ParseNode with information
+ * about where in the source string the problem occurred.
+ *
+ * @param {string} message  The error message
+ * @param {(Token|ParseNode)=} token  An object providing position information
+ */
+function ParseError(message, token) {
+    var error = "KaTeX parse error: " + message;
+    var start;
+    var end;
+
+    if (token && token.lexer && token.start <= token.end) {
+        // If we have the input and a position, make the error a bit fancier
+
+        // Get the input
+        var input = token.lexer.input;
+
+        // Prepend some information
+        start = token.start;
+        end = token.end;
+        if (start === input.length) {
+            error += " at end of input: ";
+        } else {
+            error += " at position " + (start + 1) + ": ";
+        }
+
+        // Underline token in question using combining underscores
+        var underlined = input.slice(start, end).replace(/[^]/g, "$&\u0332");
+
+        // Extract some context from the input and add it to the error
+        var left;
+        if (start > 15) {
+            left = "…" + input.slice(start - 15, start);
+        } else {
+            left = input.slice(0, start);
+        }
+        var right;
+        if (end + 15 < input.length) {
+            right = input.slice(end, end + 15) + "…";
+        } else {
+            right = input.slice(end);
+        }
+        error += left + underlined + right;
+    }
+
+    // Some hackery to make ParseError a prototype of Error
+    // See http://stackoverflow.com/a/8460753
+    var self = new Error(error);
+    self.name = "ParseError";
+    self.__proto__ = ParseError.prototype;
+
+    self.position = start;
+    return self;
+}
+
+// More hackery
+ParseError.prototype.__proto__ = Error.prototype;
+
+module.exports = ParseError;
+
+},{}],7:[function(require,module,exports){
+/* eslint no-constant-condition:0 */
+var functions = require("./functions");
+var environments = require("./environments");
+var MacroExpander = require("./MacroExpander");
+var symbols = require("./symbols");
+var utils = require("./utils");
+var cjkRegex = require("./unicodeRegexes").cjkRegex;
+
+var parseData = require("./parseData");
+var ParseError = require("./ParseError");
+
+/**
+ * This file contains the parser used to parse out a TeX expression from the
+ * input. Since TeX isn't context-free, standard parsers don't work particularly
+ * well.
+ *
+ * The strategy of this parser is as such:
+ *
+ * The main functions (the `.parse...` ones) take a position in the current
+ * parse string to parse tokens from. The lexer (found in Lexer.js, stored at
+ * this.lexer) also supports pulling out tokens at arbitrary places. When
+ * individual tokens are needed at a position, the lexer is called to pull out a
+ * token, which is then used.
+ *
+ * The parser has a property called "mode" indicating the mode that
+ * the parser is currently in. Currently it has to be one of "math" or
+ * "text", which denotes whether the current environment is a math-y
+ * one or a text-y one (e.g. inside \text). Currently, this serves to
+ * limit the functions which can be used in text mode.
+ *
+ * The main functions then return an object which contains the useful data that
+ * was parsed at its given point, and a new position at the end of the parsed
+ * data. The main functions can call each other and continue the parsing by
+ * using the returned position as a new starting point.
+ *
+ * There are also extra `.handle...` functions, which pull out some reused
+ * functionality into self-contained functions.
+ *
+ * The earlier functions return ParseNodes.
+ * The later functions (which are called deeper in the parse) sometimes return
+ * ParseFuncOrArgument, which contain a ParseNode as well as some data about
+ * whether the parsed object is a function which is missing some arguments, or a
+ * standalone object which can be used as an argument to another function.
+ */
+
+/**
+ * Main Parser class
+ */
+function Parser(input, settings) {
+    // Create a new macro expander (gullet) and (indirectly via that) also a
+    // new lexer (mouth) for this parser (stomach, in the language of TeX)
+    this.gullet = new MacroExpander(input, settings.macros);
+    // Store the settings for use in parsing
+    this.settings = settings;
+    // Count leftright depth (for \middle errors)
+    this.leftrightDepth = 0;
+}
+
+var ParseNode = parseData.ParseNode;
+
+/**
+ * An initial function (without its arguments), or an argument to a function.
+ * The `result` argument should be a ParseNode.
+ */
+function ParseFuncOrArgument(result, isFunction, token) {
+    this.result = result;
+    // Is this a function (i.e. is it something defined in functions.js)?
+    this.isFunction = isFunction;
+    this.token = token;
+}
+
+/**
+ * Checks a result to make sure it has the right type, and throws an
+ * appropriate error otherwise.
+ *
+ * @param {boolean=} consume whether to consume the expected token,
+ *                           defaults to true
+ */
+Parser.prototype.expect = function(text, consume) {
+    if (this.nextToken.text !== text) {
+        throw new ParseError(
+            "Expected '" + text + "', got '" + this.nextToken.text + "'",
+            this.nextToken
+        );
+    }
+    if (consume !== false) {
+        this.consume();
+    }
+};
+
+/**
+ * Considers the current look ahead token as consumed,
+ * and fetches the one after that as the new look ahead.
+ */
+Parser.prototype.consume = function() {
+    this.nextToken = this.gullet.get(this.mode === "math");
+};
+
+Parser.prototype.switchMode = function(newMode) {
+    this.gullet.unget(this.nextToken);
+    this.mode = newMode;
+    this.consume();
+};
+
+/**
+ * Main parsing function, which parses an entire input.
+ *
+ * @return {?Array.<ParseNode>}
+ */
+Parser.prototype.parse = function() {
+    // Try to parse the input
+    this.mode = "math";
+    this.consume();
+    var parse = this.parseInput();
+    return parse;
+};
+
+/**
+ * Parses an entire input tree.
+ */
+Parser.prototype.parseInput = function() {
+    // Parse an expression
+    var expression = this.parseExpression(false);
+    // If we succeeded, make sure there's an EOF at the end
+    this.expect("EOF", false);
+    return expression;
+};
+
+var endOfExpression = ["}", "\\end", "\\right", "&", "\\\\", "\\cr"];
+
+/**
+ * Parses an "expression", which is a list of atoms.
+ *
+ * @param {boolean} breakOnInfix  Should the parsing stop when we hit infix
+ *                  nodes? This happens when functions have higher precendence
+ *                  than infix nodes in implicit parses.
+ *
+ * @param {?string} breakOnTokenText  The text of the token that the expression
+ *                  should end with, or `null` if something else should end the
+ *                  expression.
+ *
+ * @return {ParseNode}
+ */
+Parser.prototype.parseExpression = function(breakOnInfix, breakOnTokenText) {
+    var body = [];
+    // Keep adding atoms to the body until we can't parse any more atoms (either
+    // we reached the end, a }, or a \right)
+    while (true) {
+        var lex = this.nextToken;
+        if (endOfExpression.indexOf(lex.text) !== -1) {
+            break;
+        }
+        if (breakOnTokenText && lex.text === breakOnTokenText) {
+            break;
+        }
+        if (breakOnInfix && functions[lex.text] && functions[lex.text].infix) {
+            break;
+        }
+        var atom = this.parseAtom();
+        if (!atom) {
+            if (!this.settings.throwOnError && lex.text[0] === "\\") {
+                var errorNode = this.handleUnsupportedCmd();
+                body.push(errorNode);
+                continue;
+            }
+
+            break;
+        }
+        body.push(atom);
+    }
+    return this.handleInfixNodes(body);
+};
+
+/**
+ * Rewrites infix operators such as \over with corresponding commands such
+ * as \frac.
+ *
+ * There can only be one infix operator per group.  If there's more than one
+ * then the expression is ambiguous.  This can be resolved by adding {}.
+ *
+ * @returns {Array}
+ */
+Parser.prototype.handleInfixNodes = function(body) {
+    var overIndex = -1;
+    var funcName;
+
+    for (var i = 0; i < body.length; i++) {
+        var node = body[i];
+        if (node.type === "infix") {
+            if (overIndex !== -1) {
+                throw new ParseError(
+                    "only one infix operator per group",
+                    node.value.token);
+            }
+            overIndex = i;
+            funcName = node.value.replaceWith;
+        }
+    }
+
+    if (overIndex !== -1) {
+        var numerNode;
+        var denomNode;
+
+        var numerBody = body.slice(0, overIndex);
+        var denomBody = body.slice(overIndex + 1);
+
+        if (numerBody.length === 1 && numerBody[0].type === "ordgroup") {
+            numerNode = numerBody[0];
+        } else {
+            numerNode = new ParseNode("ordgroup", numerBody, this.mode);
+        }
+
+        if (denomBody.length === 1 && denomBody[0].type === "ordgroup") {
+            denomNode = denomBody[0];
+        } else {
+            denomNode = new ParseNode("ordgroup", denomBody, this.mode);
+        }
+
+        var value = this.callFunction(
+            funcName, [numerNode, denomNode], null);
+        return [new ParseNode(value.type, value, this.mode)];
+    } else {
+        return body;
+    }
+};
+
+// The greediness of a superscript or subscript
+var SUPSUB_GREEDINESS = 1;
+
+/**
+ * Handle a subscript or superscript with nice errors.
+ */
+Parser.prototype.handleSupSubscript = function(name) {
+    var symbolToken = this.nextToken;
+    var symbol = symbolToken.text;
+    this.consume();
+    var group = this.parseGroup();
+
+    if (!group) {
+        if (!this.settings.throwOnError && this.nextToken.text[0] === "\\") {
+            return this.handleUnsupportedCmd();
+        } else {
+            throw new ParseError(
+                "Expected group after '" + symbol + "'",
+                symbolToken
+            );
+        }
+    } else if (group.isFunction) {
+        // ^ and _ have a greediness, so handle interactions with functions'
+        // greediness
+        var funcGreediness = functions[group.result].greediness;
+        if (funcGreediness > SUPSUB_GREEDINESS) {
+            return this.parseFunction(group);
+        } else {
+            throw new ParseError(
+                "Got function '" + group.result + "' with no arguments " +
+                    "as " + name, symbolToken);
+        }
+    } else {
+        return group.result;
+    }
+};
+
+/**
+ * Converts the textual input of an unsupported command into a text node
+ * contained within a color node whose color is determined by errorColor
+ */
+Parser.prototype.handleUnsupportedCmd = function() {
+    var text = this.nextToken.text;
+    var textordArray = [];
+
+    for (var i = 0; i < text.length; i++) {
+        textordArray.push(new ParseNode("textord", text[i], "text"));
+    }
+
+    var textNode = new ParseNode(
+        "text",
+        {
+            body: textordArray,
+            type: "text"
+        },
+        this.mode);
+
+    var colorNode = new ParseNode(
+        "color",
+        {
+            color: this.settings.errorColor,
+            value: [textNode],
+            type: "color"
+        },
+        this.mode);
+
+    this.consume();
+    return colorNode;
+};
+
+/**
+ * Parses a group with optional super/subscripts.
+ *
+ * @return {?ParseNode}
+ */
+Parser.prototype.parseAtom = function() {
+    // The body of an atom is an implicit group, so that things like
+    // \left(x\right)^2 work correctly.
+    var base = this.parseImplicitGroup();
+
+    // In text mode, we don't have superscripts or subscripts
+    if (this.mode === "text") {
+        return base;
+    }
+
+    // Note that base may be empty (i.e. null) at this point.
+
+    var superscript;
+    var subscript;
+    while (true) {
+        // Lex the first token
+        var lex = this.nextToken;
+
+        if (lex.text === "\\limits" || lex.text === "\\nolimits") {
+            // We got a limit control
+            if (!base || base.type !== "op") {
+                throw new ParseError(
+                    "Limit controls must follow a math operator",
+                    lex);
+            } else {
+                var limits = lex.text === "\\limits";
+                base.value.limits = limits;
+                base.value.alwaysHandleSupSub = true;
+            }
+            this.consume();
+        } else if (lex.text === "^") {
+            // We got a superscript start
+            if (superscript) {
+                throw new ParseError("Double superscript", lex);
+            }
+            superscript = this.handleSupSubscript("superscript");
+        } else if (lex.text === "_") {
+            // We got a subscript start
+            if (subscript) {
+                throw new ParseError("Double subscript", lex);
+            }
+            subscript = this.handleSupSubscript("subscript");
+        } else if (lex.text === "'") {
+            // We got a prime
+            var prime = new ParseNode("textord", "\\prime", this.mode);
+
+            // Many primes can be grouped together, so we handle this here
+            var primes = [prime];
+            this.consume();
+            // Keep lexing tokens until we get something that's not a prime
+            while (this.nextToken.text === "'") {
+                // For each one, add another prime to the list
+                primes.push(prime);
+                this.consume();
+            }
+            // Put them into an ordgroup as the superscript
+            superscript = new ParseNode("ordgroup", primes, this.mode);
+        } else {
+            // If it wasn't ^, _, or ', stop parsing super/subscripts
+            break;
+        }
+    }
+
+    if (superscript || subscript) {
+        // If we got either a superscript or subscript, create a supsub
+        return new ParseNode("supsub", {
+            base: base,
+            sup: superscript,
+            sub: subscript
+        }, this.mode);
+    } else {
+        // Otherwise return the original body
+        return base;
+    }
+};
+
+// A list of the size-changing functions, for use in parseImplicitGroup
+var sizeFuncs = [
+    "\\tiny", "\\scriptsize", "\\footnotesize", "\\small", "\\normalsize",
+    "\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge"
+];
+
+// A list of the style-changing functions, for use in parseImplicitGroup
+var styleFuncs = [
+    "\\displaystyle", "\\textstyle", "\\scriptstyle", "\\scriptscriptstyle"
+];
+
+/**
+ * Parses an implicit group, which is a group that starts at the end of a
+ * specified, and ends right before a higher explicit group ends, or at EOL. It
+ * is used for functions that appear to affect the current style, like \Large or
+ * \textrm, where instead of keeping a style we just pretend that there is an
+ * implicit grouping after it until the end of the group. E.g.
+ *   small text {\Large large text} small text again
+ * It is also used for \left and \right to get the correct grouping.
+ *
+ * @return {?ParseNode}
+ */
+Parser.prototype.parseImplicitGroup = function() {
+    var start = this.parseSymbol();
+
+    if (start == null) {
+        // If we didn't get anything we handle, fall back to parseFunction
+        return this.parseFunction();
+    }
+
+    var func = start.result;
+    var body;
+
+    if (func === "\\left") {
+        // If we see a left:
+        // Parse the entire left function (including the delimiter)
+        var left = this.parseFunction(start);
+        // Parse out the implicit body
+        ++this.leftrightDepth;
+        body = this.parseExpression(false);
+        --this.leftrightDepth;
+        // Check the next token
+        this.expect("\\right", false);
+        var right = this.parseFunction();
+        return new ParseNode("leftright", {
+            body: body,
+            left: left.value.value,
+            right: right.value.value
+        }, this.mode);
+    } else if (func === "\\begin") {
+        // begin...end is similar to left...right
+        var begin = this.parseFunction(start);
+        var envName = begin.value.name;
+        if (!environments.hasOwnProperty(envName)) {
+            throw new ParseError(
+                "No such environment: " + envName, begin.value.nameGroup);
+        }
+        // Build the environment object. Arguments and other information will
+        // be made available to the begin and end methods using properties.
+        var env = environments[envName];
+        var args = this.parseArguments("\\begin{" + envName + "}", env);
+        var context = {
+            mode: this.mode,
+            envName: envName,
+            parser: this,
+            positions: args.pop()
+        };
+        var result = env.handler(context, args);
+        this.expect("\\end", false);
+        var endNameToken = this.nextToken;
+        var end = this.parseFunction();
+        if (end.value.name !== envName) {
+            throw new ParseError(
+                "Mismatch: \\begin{" + envName + "} matched " +
+                "by \\end{" + end.value.name + "}",
+                endNameToken);
+        }
+        result.position = end.position;
+        return result;
+    } else if (utils.contains(sizeFuncs, func)) {
+        // If we see a sizing function, parse out the implict body
+        body = this.parseExpression(false);
+        return new ParseNode("sizing", {
+            // Figure out what size to use based on the list of functions above
+            size: "size" + (utils.indexOf(sizeFuncs, func) + 1),
+            value: body
+        }, this.mode);
+    } else if (utils.contains(styleFuncs, func)) {
+        // If we see a styling function, parse out the implict body
+        body = this.parseExpression(true);
+        return new ParseNode("styling", {
+            // Figure out what style to use by pulling out the style from
+            // the function name
+            style: func.slice(1, func.length - 5),
+            value: body
+        }, this.mode);
+    } else {
+        // Defer to parseFunction if it's not a function we handle
+        return this.parseFunction(start);
+    }
+};
+
+/**
+ * Parses an entire function, including its base and all of its arguments.
+ * The base might either have been parsed already, in which case
+ * it is provided as an argument, or it's the next group in the input.
+ *
+ * @param {ParseFuncOrArgument=} baseGroup optional as described above
+ * @return {?ParseNode}
+ */
+Parser.prototype.parseFunction = function(baseGroup) {
+    if (!baseGroup) {
+        baseGroup = this.parseGroup();
+    }
+
+    if (baseGroup) {
+        if (baseGroup.isFunction) {
+            var func = baseGroup.result;
+            var funcData = functions[func];
+            if (this.mode === "text" && !funcData.allowedInText) {
+                throw new ParseError(
+                    "Can't use function '" + func + "' in text mode",
+                    baseGroup.token);
+            }
+
+            var args = this.parseArguments(func, funcData);
+            var token = baseGroup.token;
+            var result = this.callFunction(func, args, args.pop(), token);
+            return new ParseNode(result.type, result, this.mode);
+        } else {
+            return baseGroup.result;
+        }
+    } else {
+        return null;
+    }
+};
+
+/**
+ * Call a function handler with a suitable context and arguments.
+ */
+Parser.prototype.callFunction = function(name, args, positions, token) {
+    var context = {
+        funcName: name,
+        parser: this,
+        positions: positions,
+        token: token
+    };
+    return functions[name].handler(context, args);
+};
+
+/**
+ * Parses the arguments of a function or environment
+ *
+ * @param {string} func  "\name" or "\begin{name}"
+ * @param {{numArgs:number,numOptionalArgs:number|undefined}} funcData
+ * @return the array of arguments, with the list of positions as last element
+ */
+Parser.prototype.parseArguments = function(func, funcData) {
+    var totalArgs = funcData.numArgs + funcData.numOptionalArgs;
+    if (totalArgs === 0) {
+        return [[this.pos]];
+    }
+
+    var baseGreediness = funcData.greediness;
+    var positions = [this.pos];
+    var args = [];
+
+    for (var i = 0; i < totalArgs; i++) {
+        var nextToken = this.nextToken;
+        var argType = funcData.argTypes && funcData.argTypes[i];
+        var arg;
+        if (i < funcData.numOptionalArgs) {
+            if (argType) {
+                arg = this.parseGroupOfType(argType, true);
+            } else {
+                arg = this.parseGroup(true);
+            }
+            if (!arg) {
+                args.push(null);
+                positions.push(this.pos);
+                continue;
+            }
+        } else {
+            if (argType) {
+                arg = this.parseGroupOfType(argType);
+            } else {
+                arg = this.parseGroup();
+            }
+            if (!arg) {
+                if (!this.settings.throwOnError &&
+                    this.nextToken.text[0] === "\\") {
+                    arg = new ParseFuncOrArgument(
+                        this.handleUnsupportedCmd(this.nextToken.text),
+                        false);
+                } else {
+                    throw new ParseError(
+                        "Expected group after '" + func + "'", nextToken);
+                }
+            }
+        }
+        var argNode;
+        if (arg.isFunction) {
+            var argGreediness =
+                functions[arg.result].greediness;
+            if (argGreediness > baseGreediness) {
+                argNode = this.parseFunction(arg);
+            } else {
+                throw new ParseError(
+                    "Got function '" + arg.result + "' as " +
+                    "argument to '" + func + "'", nextToken);
+            }
+        } else {
+            argNode = arg.result;
+        }
+        args.push(argNode);
+        positions.push(this.pos);
+    }
+
+    args.push(positions);
+
+    return args;
+};
+
+
+/**
+ * Parses a group when the mode is changing.
+ *
+ * @return {?ParseFuncOrArgument}
+ */
+Parser.prototype.parseGroupOfType = function(innerMode, optional) {
+    var outerMode = this.mode;
+    // Handle `original` argTypes
+    if (innerMode === "original") {
+        innerMode = outerMode;
+    }
+
+    if (innerMode === "color") {
+        return this.parseColorGroup(optional);
+    }
+    if (innerMode === "size") {
+        return this.parseSizeGroup(optional);
+    }
+
+    this.switchMode(innerMode);
+    if (innerMode === "text") {
+        // text mode is special because it should ignore the whitespace before
+        // it
+        while (this.nextToken.text === " ") {
+            this.consume();
+        }
+    }
+    // By the time we get here, innerMode is one of "text" or "math".
+    // We switch the mode of the parser, recurse, then restore the old mode.
+    var res = this.parseGroup(optional);
+    this.switchMode(outerMode);
+    return res;
+};
+
+/**
+ * Parses a group, essentially returning the string formed by the
+ * brace-enclosed tokens plus some position information.
+ *
+ * @param {string} modeName  Used to describe the mode in error messages
+ * @param {boolean=} optional  Whether the group is optional or required
+ */
+Parser.prototype.parseStringGroup = function(modeName, optional) {
+    if (optional && this.nextToken.text !== "[") {
+        return null;
+    }
+    var outerMode = this.mode;
+    this.mode = "text";
+    this.expect(optional ? "[" : "{");
+    var str = "";
+    var firstToken = this.nextToken;
+    var lastToken = firstToken;
+    while (this.nextToken.text !== (optional ? "]" : "}")) {
+        if (this.nextToken.text === "EOF") {
+            throw new ParseError(
+                "Unexpected end of input in " + modeName,
+                firstToken.range(this.nextToken, str));
+        }
+        lastToken = this.nextToken;
+        str += lastToken.text;
+        this.consume();
+    }
+    this.mode = outerMode;
+    this.expect(optional ? "]" : "}");
+    return firstToken.range(lastToken, str);
+};
+
+/**
+ * Parses a regex-delimited group: the largest sequence of tokens
+ * whose concatenated strings match `regex`. Returns the string
+ * formed by the tokens plus some position information.
+ *
+ * @param {RegExp} regex
+ * @param {string} modeName  Used to describe the mode in error messages
+ */
+Parser.prototype.parseRegexGroup = function(regex, modeName) {
+    var outerMode = this.mode;
+    this.mode = "text";
+    var firstToken = this.nextToken;
+    var lastToken = firstToken;
+    var str = "";
+    while (this.nextToken.text !== "EOF"
+           && regex.test(str + this.nextToken.text)) {
+        lastToken = this.nextToken;
+        str += lastToken.text;
+        this.consume();
+    }
+    if (str === "") {
+        throw new ParseError(
+            "Invalid " + modeName + ": '" + firstToken.text + "'",
+            firstToken);
+    }
+    this.mode = outerMode;
+    return firstToken.range(lastToken, str);
+};
+
+/**
+ * Parses a color description.
+ */
+Parser.prototype.parseColorGroup = function(optional) {
+    var res = this.parseStringGroup("color", optional);
+    if (!res) {
+        return null;
+    }
+    var match = (/^(#[a-z0-9]+|[a-z]+)$/i).exec(res.text);
+    if (!match) {
+        throw new ParseError("Invalid color: '" + res.text + "'", res);
+    }
+    return new ParseFuncOrArgument(
+        new ParseNode("color", match[0], this.mode),
+        false);
+};
+
+/**
+ * Parses a size specification, consisting of magnitude and unit.
+ */
+Parser.prototype.parseSizeGroup = function(optional) {
+    var res;
+    if (!optional && this.nextToken.text !== "{") {
+        res = this.parseRegexGroup(
+            /^[-+]? *(?:$|\d+|\d+\.\d*|\.\d*) *[a-z]{0,2}$/, "size");
+    } else {
+        res = this.parseStringGroup("size", optional);
+    }
+    if (!res) {
+        return null;
+    }
+    var match = (/([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/).exec(res.text);
+    if (!match) {
+        throw new ParseError("Invalid size: '" + res.text + "'", res);
+    }
+    var data = {
+        number: +(match[1] + match[2]), // sign + magnitude, cast to number
+        unit: match[3]
+    };
+    if (data.unit !== "em" && data.unit !== "ex" && data.unit !== "mu") {
+        throw new ParseError("Invalid unit: '" + data.unit + "'", res);
+    }
+    return new ParseFuncOrArgument(
+        new ParseNode("color", data, this.mode),
+        false);
+};
+
+/**
+ * If the argument is false or absent, this parses an ordinary group,
+ * which is either a single nucleus (like "x") or an expression
+ * in braces (like "{x+y}").
+ * If the argument is true, it parses either a bracket-delimited expression
+ * (like "[x+y]") or returns null to indicate the absence of a
+ * bracket-enclosed group.
+ *
+ * @param {boolean=} optional  Whether the group is optional or required
+ * @return {?ParseFuncOrArgument}
+ */
+Parser.prototype.parseGroup = function(optional) {
+    var firstToken = this.nextToken;
+    // Try to parse an open brace
+    if (this.nextToken.text === (optional ? "[" : "{")) {
+        // If we get a brace, parse an expression
+        this.consume();
+        var expression = this.parseExpression(false, optional ? "]" : null);
+        var lastToken = this.nextToken;
+        // Make sure we get a close brace
+        this.expect(optional ? "]" : "}");
+        if (this.mode === "text") {
+            this.formLigatures(expression);
+        }
+        return new ParseFuncOrArgument(
+            new ParseNode("ordgroup", expression, this.mode,
+                          firstToken, lastToken),
+            false);
+    } else {
+        // Otherwise, just return a nucleus, or nothing for an optional group
+        return optional ? null : this.parseSymbol();
+    }
+};
+
+/**
+ * Form ligature-like combinations of characters for text mode.
+ * This includes inputs like "--", "---", "``" and "''".
+ * The result will simply replace multiple textord nodes with a single
+ * character in each value by a single textord node having multiple
+ * characters in its value.  The representation is still ASCII source.
+ *
+ * @param {Array.<ParseNode>} group  the nodes of this group,
+ *                                   list will be moified in place
+ */
+Parser.prototype.formLigatures = function(group) {
+    var i;
+    var n = group.length - 1;
+    for (i = 0; i < n; ++i) {
+        var a = group[i];
+        var v = a.value;
+        if (v === "-" && group[i + 1].value === "-") {
+            if (i + 1 < n && group[i + 2].value === "-") {
+                group.splice(i, 3, new ParseNode(
+                    "textord", "---", "text", a, group[i + 2]));
+                n -= 2;
+            } else {
+                group.splice(i, 2, new ParseNode(
+                    "textord", "--", "text", a, group[i + 1]));
+                n -= 1;
+            }
+        }
+        if ((v === "'" || v === "`") && group[i + 1].value === v) {
+            group.splice(i, 2, new ParseNode(
+                "textord", v + v, "text", a, group[i + 1]));
+            n -= 1;
+        }
+    }
+};
+
+/**
+ * Parse a single symbol out of the string. Here, we handle both the functions
+ * we have defined, as well as the single character symbols
+ *
+ * @return {?ParseFuncOrArgument}
+ */
+Parser.prototype.parseSymbol = function() {
+    var nucleus = this.nextToken;
+
+    if (functions[nucleus.text]) {
+        this.consume();
+        // If there exists a function with this name, we return the function and
+        // say that it is a function.
+        return new ParseFuncOrArgument(
+            nucleus.text,
+            true, nucleus);
+    } else if (symbols[this.mode][nucleus.text]) {
+        this.consume();
+        // Otherwise if this is a no-argument function, find the type it
+        // corresponds to in the symbols map
+        return new ParseFuncOrArgument(
+            new ParseNode(symbols[this.mode][nucleus.text].group,
+                          nucleus.text, this.mode, nucleus),
+            false, nucleus);
+    } else if (this.mode === "text" && cjkRegex.test(nucleus.text)) {
+        this.consume();
+        return new ParseFuncOrArgument(
+            new ParseNode("textord", nucleus.text, this.mode, nucleus),
+            false, nucleus);
+    } else {
+        return null;
+    }
+};
+
+Parser.prototype.ParseNode = ParseNode;
+
+module.exports = Parser;
+
+},{"./MacroExpander":4,"./ParseError":6,"./environments":16,"./functions":19,"./parseData":21,"./symbols":23,"./unicodeRegexes":24,"./utils":25}],8:[function(require,module,exports){
+/**
+ * This is a module for storing settings passed into KaTeX. It correctly handles
+ * default settings.
+ */
+
+/**
+ * Helper function for getting a default value if the value is undefined
+ */
+function get(option, defaultValue) {
+    return option === undefined ? defaultValue : option;
+}
+
+/**
+ * The main Settings object
+ *
+ * The current options stored are:
+ *  - displayMode: Whether the expression should be typeset by default in
+ *                 textstyle or displaystyle (default false)
+ */
+function Settings(options) {
+    // allow null options
+    options = options || {};
+    this.displayMode = get(options.displayMode, false);
+    this.throwOnError = get(options.throwOnError, true);
+    this.errorColor = get(options.errorColor, "#cc0000");
+    this.macros = options.macros || {};
+}
+
+module.exports = Settings;
+
+},{}],9:[function(require,module,exports){
+/**
+ * This file contains information and classes for the various kinds of styles
+ * used in TeX. It provides a generic `Style` class, which holds information
+ * about a specific style. It then provides instances of all the different kinds
+ * of styles possible, and provides functions to move between them and get
+ * information about them.
+ */
+
+var sigmas = require("./fontMetrics.js").sigmas;
+
+var metrics = [{}, {}, {}];
+var i;
+for (var key in sigmas) {
+    if (sigmas.hasOwnProperty(key)) {
+        for (i = 0; i < 3; i++) {
+            metrics[i][key] = sigmas[key][i];
+        }
+    }
+}
+for (i = 0; i < 3; i++) {
+    metrics[i].emPerEx = sigmas.xHeight[i] / sigmas.quad[i];
+}
+
+/**
+ * The main style class. Contains a unique id for the style, a size (which is
+ * the same for cramped and uncramped version of a style), a cramped flag, and a
+ * size multiplier, which gives the size difference between a style and
+ * textstyle.
+ */
+function Style(id, size, multiplier, cramped) {
+    this.id = id;
+    this.size = size;
+    this.cramped = cramped;
+    this.sizeMultiplier = multiplier;
+    this.metrics = metrics[size > 0 ? size - 1 : 0];
+}
+
+/**
+ * Get the style of a superscript given a base in the current style.
+ */
+Style.prototype.sup = function() {
+    return styles[sup[this.id]];
+};
+
+/**
+ * Get the style of a subscript given a base in the current style.
+ */
+Style.prototype.sub = function() {
+    return styles[sub[this.id]];
+};
+
+/**
+ * Get the style of a fraction numerator given the fraction in the current
+ * style.
+ */
+Style.prototype.fracNum = function() {
+    return styles[fracNum[this.id]];
+};
+
+/**
+ * Get the style of a fraction denominator given the fraction in the current
+ * style.
+ */
+Style.prototype.fracDen = function() {
+    return styles[fracDen[this.id]];
+};
+
+/**
+ * Get the cramped version of a style (in particular, cramping a cramped style
+ * doesn't change the style).
+ */
+Style.prototype.cramp = function() {
+    return styles[cramp[this.id]];
+};
+
+/**
+ * HTML class name, like "displaystyle cramped"
+ */
+Style.prototype.cls = function() {
+    return sizeNames[this.size] + (this.cramped ? " cramped" : " uncramped");
+};
+
+/**
+ * HTML Reset class name, like "reset-textstyle"
+ */
+Style.prototype.reset = function() {
+    return resetNames[this.size];
+};
+
+/**
+ * Return if this style is tightly spaced (scriptstyle/scriptscriptstyle)
+ */
+Style.prototype.isTight = function() {
+    return this.size >= 2;
+};
+
+// IDs of the different styles
+var D = 0;
+var Dc = 1;
+var T = 2;
+var Tc = 3;
+var S = 4;
+var Sc = 5;
+var SS = 6;
+var SSc = 7;
+
+// String names for the different sizes
+var sizeNames = [
+    "displaystyle textstyle",
+    "textstyle",
+    "scriptstyle",
+    "scriptscriptstyle"
+];
+
+// Reset names for the different sizes
+var resetNames = [
+    "reset-textstyle",
+    "reset-textstyle",
+    "reset-scriptstyle",
+    "reset-scriptscriptstyle"
+];
+
+// Instances of the different styles
+var styles = [
+    new Style(D, 0, 1.0, false),
+    new Style(Dc, 0, 1.0, true),
+    new Style(T, 1, 1.0, false),
+    new Style(Tc, 1, 1.0, true),
+    new Style(S, 2, 0.7, false),
+    new Style(Sc, 2, 0.7, true),
+    new Style(SS, 3, 0.5, false),
+    new Style(SSc, 3, 0.5, true)
+];
+
+// Lookup tables for switching from one style to another
+var sup = [S, Sc, S, Sc, SS, SSc, SS, SSc];
+var sub = [Sc, Sc, Sc, Sc, SSc, SSc, SSc, SSc];
+var fracNum = [T, Tc, S, Sc, SS, SSc, SS, SSc];
+var fracDen = [Tc, Tc, Sc, Sc, SSc, SSc, SSc, SSc];
+var cramp = [Dc, Dc, Tc, Tc, Sc, Sc, SSc, SSc];
+
+// We only export some of the styles. Also, we don't export the `Style` class so
+// no more styles can be generated.
+module.exports = {
+    DISPLAY: styles[D],
+    TEXT: styles[T],
+    SCRIPT: styles[S],
+    SCRIPTSCRIPT: styles[SS]
+};
+
+},{"./fontMetrics.js":17}],10:[function(require,module,exports){
+/* eslint no-console:0 */
+/**
+ * This module contains general functions that can be used for building
+ * different kinds of domTree nodes in a consistent manner.
+ */
+
+var domTree = require("./domTree");
+var fontMetrics = require("./fontMetrics");
+var symbols = require("./symbols");
+var utils = require("./utils");
+
+var greekCapitals = [
+    "\\Gamma",
+    "\\Delta",
+    "\\Theta",
+    "\\Lambda",
+    "\\Xi",
+    "\\Pi",
+    "\\Sigma",
+    "\\Upsilon",
+    "\\Phi",
+    "\\Psi",
+    "\\Omega"
+];
+
+// The following have to be loaded from Main-Italic font, using class mainit
+var mainitLetters = [
+    "\u0131",   // dotless i, \imath
+    "\u0237",   // dotless j, \jmath
+    "\u00a3"   // \pounds
+];
+
+/**
+ * Makes a symbolNode after translation via the list of symbols in symbols.js.
+ * Correctly pulls out metrics for the character, and optionally takes a list of
+ * classes to be attached to the node.
+ *
+ * TODO: make argument order closer to makeSpan
+ * TODO: add a separate argument for math class (e.g. `mop`, `mbin`), which
+ * should if present come first in `classes`.
+ */
+var makeSymbol = function(value, fontFamily, mode, options, classes) {
+    // Replace the value with its replaced value from symbol.js
+    if (symbols[mode][value] && symbols[mode][value].replace) {
+        value = symbols[mode][value].replace;
+    }
+
+    var metrics = fontMetrics.getCharacterMetrics(value, fontFamily);
+
+    var symbolNode;
+    if (metrics) {
+        var italic = metrics.italic;
+        if (mode === "text") {
+            italic = 0;
+        }
+        symbolNode = new domTree.symbolNode(
+            value, metrics.height, metrics.depth, italic, metrics.skew,
+            classes);
+    } else {
+        // TODO(emily): Figure out a good way to only print this in development
+        typeof console !== "undefined" && console.warn(
+            "No character metrics for '" + value + "' in style '" +
+                fontFamily + "'");
+        symbolNode = new domTree.symbolNode(value, 0, 0, 0, 0, classes);
+    }
+
+    if (options) {
+        if (options.style.isTight()) {
+            symbolNode.classes.push("mtight");
+        }
+        if (options.getColor()) {
+            symbolNode.style.color = options.getColor();
+        }
+    }
+
+    return symbolNode;
+};
+
+/**
+ * Makes a symbol in Main-Regular or AMS-Regular.
+ * Used for rel, bin, open, close, inner, and punct.
+ */
+var mathsym = function(value, mode, options, classes) {
+    // Decide what font to render the symbol in by its entry in the symbols
+    // table.
+    // Have a special case for when the value = \ because the \ is used as a
+    // textord in unsupported command errors but cannot be parsed as a regular
+    // text ordinal and is therefore not present as a symbol in the symbols
+    // table for text
+    if (value === "\\" || symbols[mode][value].font === "main") {
+        return makeSymbol(value, "Main-Regular", mode, options, classes);
+    } else {
+        return makeSymbol(
+            value, "AMS-Regular", mode, options, classes.concat(["amsrm"]));
+    }
+};
+
+/**
+ * Makes a symbol in the default font for mathords and textords.
+ */
+var mathDefault = function(value, mode, options, classes, type) {
+    if (type === "mathord") {
+        return mathit(value, mode, options, classes);
+    } else if (type === "textord") {
+        return makeSymbol(
+            value, "Main-Regular", mode, options, classes.concat(["mathrm"]));
+    } else {
+        throw new Error("unexpected type: " + type + " in mathDefault");
+    }
+};
+
+/**
+ * Makes a symbol in the italic math font.
+ */
+var mathit = function(value, mode, options, classes) {
+    if (/[0-9]/.test(value.charAt(0)) ||
+            // glyphs for \imath and \jmath do not exist in Math-Italic so we
+            // need to use Main-Italic instead
+            utils.contains(mainitLetters, value) ||
+            utils.contains(greekCapitals, value)) {
+        return makeSymbol(
+            value, "Main-Italic", mode, options, classes.concat(["mainit"]));
+    } else {
+        return makeSymbol(
+            value, "Math-Italic", mode, options, classes.concat(["mathit"]));
+    }
+};
+
+/**
+ * Makes either a mathord or textord in the correct font and color.
+ */
+var makeOrd = function(group, options, type) {
+    var mode = group.mode;
+    var value = group.value;
+    if (symbols[mode][value] && symbols[mode][value].replace) {
+        value = symbols[mode][value].replace;
+    }
+
+    var classes = ["mord"];
+
+    var font = options.font;
+    if (font) {
+        if (font === "mathit" || utils.contains(mainitLetters, value)) {
+            return mathit(value, mode, options, classes);
+        } else {
+            var fontName = fontMap[font].fontName;
+            if (fontMetrics.getCharacterMetrics(value, fontName)) {
+                return makeSymbol(
+                    value, fontName, mode, options, classes.concat([font]));
+            } else {
+                return mathDefault(value, mode, options, classes, type);
+            }
+        }
+    } else {
+        return mathDefault(value, mode, options, classes, type);
+    }
+};
+
+/**
+ * Calculate the height, depth, and maxFontSize of an element based on its
+ * children.
+ */
+var sizeElementFromChildren = function(elem) {
+    var height = 0;
+    var depth = 0;
+    var maxFontSize = 0;
+
+    if (elem.children) {
+        for (var i = 0; i < elem.children.length; i++) {
+            if (elem.children[i].height > height) {
+                height = elem.children[i].height;
+            }
+            if (elem.children[i].depth > depth) {
+                depth = elem.children[i].depth;
+            }
+            if (elem.children[i].maxFontSize > maxFontSize) {
+                maxFontSize = elem.children[i].maxFontSize;
+            }
+        }
+    }
+
+    elem.height = height;
+    elem.depth = depth;
+    elem.maxFontSize = maxFontSize;
+};
+
+/**
+ * Makes a span with the given list of classes, list of children, and options.
+ *
+ * TODO: Ensure that `options` is always provided (currently some call sites
+ * don't pass it).
+ * TODO: add a separate argument for math class (e.g. `mop`, `mbin`), which
+ * should if present come first in `classes`.
+ */
+var makeSpan = function(classes, children, options) {
+    var span = new domTree.span(classes, children, options);
+
+    sizeElementFromChildren(span);
+
+    return span;
+};
+
+/**
+ * Prepends the given children to the given span, updating height, depth, and
+ * maxFontSize.
+ */
+var prependChildren = function(span, children) {
+    span.children = children.concat(span.children);
+
+    sizeElementFromChildren(span);
+};
+
+/**
+ * Makes a document fragment with the given list of children.
+ */
+var makeFragment = function(children) {
+    var fragment = new domTree.documentFragment(children);
+
+    sizeElementFromChildren(fragment);
+
+    return fragment;
+};
+
+/**
+ * Makes an element placed in each of the vlist elements to ensure that each
+ * element has the same max font size. To do this, we create a zero-width space
+ * with the correct font size.
+ */
+var makeFontSizer = function(options, fontSize) {
+    var fontSizeInner = makeSpan([], [new domTree.symbolNode("\u200b")]);
+    fontSizeInner.style.fontSize =
+        (fontSize / options.style.sizeMultiplier) + "em";
+
+    var fontSizer = makeSpan(
+        ["fontsize-ensurer", "reset-" + options.size, "size5"],
+        [fontSizeInner]);
+
+    return fontSizer;
+};
+
+/**
+ * Makes a vertical list by stacking elements and kerns on top of each other.
+ * Allows for many different ways of specifying the positioning method.
+ *
+ * Arguments:
+ *  - children: A list of child or kern nodes to be stacked on top of each other
+ *              (i.e. the first element will be at the bottom, and the last at
+ *              the top). Element nodes are specified as
+ *                {type: "elem", elem: node}
+ *              while kern nodes are specified as
+ *                {type: "kern", size: size}
+ *  - positionType: The method by which the vlist should be positioned. Valid
+ *                  values are:
+ *                   - "individualShift": The children list only contains elem
+ *                                        nodes, and each node contains an extra
+ *                                        "shift" value of how much it should be
+ *                                        shifted (note that shifting is always
+ *                                        moving downwards). positionData is
+ *                                        ignored.
+ *                   - "top": The positionData specifies the topmost point of
+ *                            the vlist (note this is expected to be a height,
+ *                            so positive values move up)
+ *                   - "bottom": The positionData specifies the bottommost point
+ *                               of the vlist (note this is expected to be a
+ *                               depth, so positive values move down
+ *                   - "shift": The vlist will be positioned such that its
+ *                              baseline is positionData away from the baseline
+ *                              of the first child. Positive values move
+ *                              downwards.
+ *                   - "firstBaseline": The vlist will be positioned such that
+ *                                      its baseline is aligned with the
+ *                                      baseline of the first child.
+ *                                      positionData is ignored. (this is
+ *                                      equivalent to "shift" with
+ *                                      positionData=0)
+ *  - positionData: Data used in different ways depending on positionType
+ *  - options: An Options object
+ *
+ */
+var makeVList = function(children, positionType, positionData, options) {
+    var depth;
+    var currPos;
+    var i;
+    if (positionType === "individualShift") {
+        var oldChildren = children;
+        children = [oldChildren[0]];
+
+        // Add in kerns to the list of children to get each element to be
+        // shifted to the correct specified shift
+        depth = -oldChildren[0].shift - oldChildren[0].elem.depth;
+        currPos = depth;
+        for (i = 1; i < oldChildren.length; i++) {
+            var diff = -oldChildren[i].shift - currPos -
+                oldChildren[i].elem.depth;
+            var size = diff -
+                (oldChildren[i - 1].elem.height +
+                 oldChildren[i - 1].elem.depth);
+
+            currPos = currPos + diff;
+
+            children.push({type: "kern", size: size});
+            children.push(oldChildren[i]);
+        }
+    } else if (positionType === "top") {
+        // We always start at the bottom, so calculate the bottom by adding up
+        // all the sizes
+        var bottom = positionData;
+        for (i = 0; i < children.length; i++) {
+            if (children[i].type === "kern") {
+                bottom -= children[i].size;
+            } else {
+                bottom -= children[i].elem.height + children[i].elem.depth;
+            }
+        }
+        depth = bottom;
+    } else if (positionType === "bottom") {
+        depth = -positionData;
+    } else if (positionType === "shift") {
+        depth = -children[0].elem.depth - positionData;
+    } else if (positionType === "firstBaseline") {
+        depth = -children[0].elem.depth;
+    } else {
+        depth = 0;
+    }
+
+    // Make the fontSizer
+    var maxFontSize = 0;
+    for (i = 0; i < children.length; i++) {
+        if (children[i].type === "elem") {
+            maxFontSize = Math.max(maxFontSize, children[i].elem.maxFontSize);
+        }
+    }
+    var fontSizer = makeFontSizer(options, maxFontSize);
+
+    // Create a new list of actual children at the correct offsets
+    var realChildren = [];
+    currPos = depth;
+    for (i = 0; i < children.length; i++) {
+        if (children[i].type === "kern") {
+            currPos += children[i].size;
+        } else {
+            var child = children[i].elem;
+
+            var shift = -child.depth - currPos;
+            currPos += child.height + child.depth;
+
+            var childWrap = makeSpan([], [fontSizer, child]);
+            childWrap.height -= shift;
+            childWrap.depth += shift;
+            childWrap.style.top = shift + "em";
+
+            realChildren.push(childWrap);
+        }
+    }
+
+    // Add in an element at the end with no offset to fix the calculation of
+    // baselines in some browsers (namely IE, sometimes safari)
+    var baselineFix = makeSpan(
+        ["baseline-fix"], [fontSizer, new domTree.symbolNode("\u200b")]);
+    realChildren.push(baselineFix);
+
+    var vlist = makeSpan(["vlist"], realChildren);
+    // Fix the final height and depth, in case there were kerns at the ends
+    // since the makeSpan calculation won't take that in to account.
+    vlist.height = Math.max(currPos, vlist.height);
+    vlist.depth = Math.max(-depth, vlist.depth);
+    return vlist;
+};
+
+// A table of size -> font size for the different sizing functions
+var sizingMultiplier = {
+    size1: 0.5,
+    size2: 0.7,
+    size3: 0.8,
+    size4: 0.9,
+    size5: 1.0,
+    size6: 1.2,
+    size7: 1.44,
+    size8: 1.73,
+    size9: 2.07,
+    size10: 2.49
+};
+
+// A map of spacing functions to their attributes, like size and corresponding
+// CSS class
+var spacingFunctions = {
+    "\\qquad": {
+        size: "2em",
+        className: "qquad"
+    },
+    "\\quad": {
+        size: "1em",
+        className: "quad"
+    },
+    "\\enspace": {
+        size: "0.5em",
+        className: "enspace"
+    },
+    "\\;": {
+        size: "0.277778em",
+        className: "thickspace"
+    },
+    "\\:": {
+        size: "0.22222em",
+        className: "mediumspace"
+    },
+    "\\,": {
+        size: "0.16667em",
+        className: "thinspace"
+    },
+    "\\!": {
+        size: "-0.16667em",
+        className: "negativethinspace"
+    }
+};
+
+/**
+ * Maps TeX font commands to objects containing:
+ * - variant: string used for "mathvariant" attribute in buildMathML.js
+ * - fontName: the "style" parameter to fontMetrics.getCharacterMetrics
+ */
+// A map between tex font commands an MathML mathvariant attribute values
+var fontMap = {
+    // styles
+    "mathbf": {
+        variant: "bold",
+        fontName: "Main-Bold"
+    },
+    "mathrm": {
+        variant: "normal",
+        fontName: "Main-Regular"
+    },
+    "textit": {
+        variant: "italic",
+        fontName: "Main-Italic"
+    },
+
+    // "mathit" is missing because it requires the use of two fonts: Main-Italic
+    // and Math-Italic.  This is handled by a special case in makeOrd which ends
+    // up calling mathit.
+
+    // families
+    "mathbb": {
+        variant: "double-struck",
+        fontName: "AMS-Regular"
+    },
+    "mathcal": {
+        variant: "script",
+        fontName: "Caligraphic-Regular"
+    },
+    "mathfrak": {
+        variant: "fraktur",
+        fontName: "Fraktur-Regular"
+    },
+    "mathscr": {
+        variant: "script",
+        fontName: "Script-Regular"
+    },
+    "mathsf": {
+        variant: "sans-serif",
+        fontName: "SansSerif-Regular"
+    },
+    "mathtt": {
+        variant: "monospace",
+        fontName: "Typewriter-Regular"
+    }
+};
+
+module.exports = {
+    fontMap: fontMap,
+    makeSymbol: makeSymbol,
+    mathsym: mathsym,
+    makeSpan: makeSpan,
+    makeFragment: makeFragment,
+    makeVList: makeVList,
+    makeOrd: makeOrd,
+    prependChildren: prependChildren,
+    sizingMultiplier: sizingMultiplier,
+    spacingFunctions: spacingFunctions
+};
+
+},{"./domTree":15,"./fontMetrics":17,"./symbols":23,"./utils":25}],11:[function(require,module,exports){
+/* eslint no-console:0 */
+/**
+ * This file does the main work of building a domTree structure from a parse
+ * tree. The entry point is the `buildHTML` function, which takes a parse tree.
+ * Then, the buildExpression, buildGroup, and various groupTypes functions are
+ * called, to produce a final HTML tree.
+ */
+
+var ParseError = require("./ParseError");
+var Style = require("./Style");
+
+var buildCommon = require("./buildCommon");
+var delimiter = require("./delimiter");
+var domTree = require("./domTree");
+var fontMetrics = require("./fontMetrics");
+var utils = require("./utils");
+
+var makeSpan = buildCommon.makeSpan;
+
+var isSpace = function(node) {
+    return node instanceof domTree.span && node.classes[0] === "mspace";
+};
+
+// Binary atoms (first class `mbin`) change into ordinary atoms (`mord`)
+// depending on their surroundings. See TeXbook pg. 442-446, Rules 5 and 6,
+// and the text before Rule 19.
+
+var isBin = function(node) {
+    return node && node.classes[0] === "mbin";
+};
+
+var isBinLeftCanceller = function(node, isRealGroup) {
+    // TODO: This code assumes that a node's math class is the first element
+    // of its `classes` array. A later cleanup should ensure this, for
+    // instance by changing the signature of `makeSpan`.
+    if (node) {
+        return utils.contains(["mbin", "mopen", "mrel", "mop", "mpunct"],
+                              node.classes[0]);
+    } else {
+        return isRealGroup;
+    }
+};
+
+var isBinRightCanceller = function(node, isRealGroup) {
+    if (node) {
+        return utils.contains(["mrel", "mclose", "mpunct"], node.classes[0]);
+    } else {
+        return isRealGroup;
+    }
+};
+
+/**
+ * Take a list of nodes, build them in order, and return a list of the built
+ * nodes. documentFragments are flattened into their contents, so the
+ * returned list contains no fragments. `isRealGroup` is true if `expression`
+ * is a real group (no atoms will be added on either side), as opposed to
+ * a partial group (e.g. one created by \color).
+ */
+var buildExpression = function(expression, options, isRealGroup) {
+    // Parse expressions into `groups`.
+    var groups = [];
+    for (var i = 0; i < expression.length; i++) {
+        var group = expression[i];
+        var output = buildGroup(group, options);
+        if (output instanceof domTree.documentFragment) {
+            Array.prototype.push.apply(groups, output.children);
+        } else {
+            groups.push(output);
+        }
+    }
+    // At this point `groups` consists entirely of `symbolNode`s and `span`s.
+
+    // Explicit spaces (e.g., \;, \,) should be ignored with respect to atom
+    // spacing (e.g., "add thick space between mord and mrel"). Since CSS
+    // adjacency rules implement atom spacing, spaces should be invisible to
+    // CSS. So we splice them out of `groups` and into the atoms themselves.
+    var spaces = null;
+    for (i = 0; i < groups.length; i++) {
+        if (isSpace(groups[i])) {
+            spaces = spaces || [];
+            spaces.push(groups[i]);
+            groups.splice(i, 1);
+            i--;
+        } else if (spaces) {
+            if (groups[i] instanceof domTree.symbolNode) {
+                groups[i] = makeSpan([].concat(groups[i].classes), [groups[i]]);
+            }
+            buildCommon.prependChildren(groups[i], spaces);
+            spaces = null;
+        }
+    }
+    if (spaces) {
+        Array.prototype.push.apply(groups, spaces);
+    }
+
+    // Binary operators change to ordinary symbols in some contexts.
+    for (i = 0; i < groups.length; i++) {
+        if (isBin(groups[i])
+            && (isBinLeftCanceller(groups[i - 1], isRealGroup)
+                || isBinRightCanceller(groups[i + 1], isRealGroup))) {
+            groups[i].classes[0] = "mord";
+        }
+    }
+
+    return groups;
+};
+
+// Return math atom class (mclass) of a domTree.
+var getTypeOfDomTree = function(node) {
+    if (node instanceof domTree.documentFragment) {
+        if (node.children.length) {
+            return getTypeOfDomTree(
+                node.children[node.children.length - 1]);
+        }
+    } else {
+        if (utils.contains(["mord", "mop", "mbin", "mrel", "mopen", "mclose",
+            "mpunct", "minner"], node.classes[0])) {
+            return node.classes[0];
+        }
+    }
+    return null;
+};
+
+/**
+ * Sometimes, groups perform special rules when they have superscripts or
+ * subscripts attached to them. This function lets the `supsub` group know that
+ * its inner element should handle the superscripts and subscripts instead of
+ * handling them itself.
+ */
+var shouldHandleSupSub = function(group, options) {
+    if (!group) {
+        return false;
+    } else if (group.type === "op") {
+        // Operators handle supsubs differently when they have limits
+        // (e.g. `\displaystyle\sum_2^3`)
+        return group.value.limits &&
+            (options.style.size === Style.DISPLAY.size ||
+            group.value.alwaysHandleSupSub);
+    } else if (group.type === "accent") {
+        return isCharacterBox(group.value.base);
+    } else {
+        return null;
+    }
+};
+
+/**
+ * Sometimes we want to pull out the innermost element of a group. In most
+ * cases, this will just be the group itself, but when ordgroups and colors have
+ * a single element, we want to pull that out.
+ */
+var getBaseElem = function(group) {
+    if (!group) {
+        return false;
+    } else if (group.type === "ordgroup") {
+        if (group.value.length === 1) {
+            return getBaseElem(group.value[0]);
+        } else {
+            return group;
+        }
+    } else if (group.type === "color") {
+        if (group.value.value.length === 1) {
+            return getBaseElem(group.value.value[0]);
+        } else {
+            return group;
+        }
+    } else if (group.type === "font") {
+        return getBaseElem(group.value.body);
+    } else {
+        return group;
+    }
+};
+
+/**
+ * TeXbook algorithms often reference "character boxes", which are simply groups
+ * with a single character in them. To decide if something is a character box,
+ * we find its innermost group, and see if it is a single character.
+ */
+var isCharacterBox = function(group) {
+    var baseElem = getBaseElem(group);
+
+    // These are all they types of groups which hold single characters
+    return baseElem.type === "mathord" ||
+        baseElem.type === "textord" ||
+        baseElem.type === "bin" ||
+        baseElem.type === "rel" ||
+        baseElem.type === "inner" ||
+        baseElem.type === "open" ||
+        baseElem.type === "close" ||
+        baseElem.type === "punct";
+};
+
+var makeNullDelimiter = function(options, classes) {
+    return makeSpan(classes.concat([
+        "sizing", "reset-" + options.size, "size5",
+        options.style.reset(), Style.TEXT.cls(),
+        "nulldelimiter"]));
+};
+
+/**
+ * This is a map of group types to the function used to handle that type.
+ * Simpler types come at the beginning, while complicated types come afterwards.
+ */
+var groupTypes = {};
+
+groupTypes.mathord = function(group, options) {
+    return buildCommon.makeOrd(group, options, "mathord");
+};
+
+groupTypes.textord = function(group, options) {
+    return buildCommon.makeOrd(group, options, "textord");
+};
+
+groupTypes.bin = function(group, options) {
+    return buildCommon.mathsym(
+        group.value, group.mode, options, ["mbin"]);
+};
+
+groupTypes.rel = function(group, options) {
+    return buildCommon.mathsym(
+        group.value, group.mode, options, ["mrel"]);
+};
+
+groupTypes.open = function(group, options) {
+    return buildCommon.mathsym(
+        group.value, group.mode, options, ["mopen"]);
+};
+
+groupTypes.close = function(group, options) {
+    return buildCommon.mathsym(
+        group.value, group.mode, options, ["mclose"]);
+};
+
+groupTypes.inner = function(group, options) {
+    return buildCommon.mathsym(
+        group.value, group.mode, options, ["minner"]);
+};
+
+groupTypes.punct = function(group, options) {
+    return buildCommon.mathsym(
+        group.value, group.mode, options, ["mpunct"]);
+};
+
+groupTypes.ordgroup = function(group, options) {
+    return makeSpan(
+        ["mord", options.style.cls()],
+        buildExpression(group.value, options.reset(), true),
+        options
+    );
+};
+
+groupTypes.text = function(group, options) {
+    var newOptions = options.withFont(group.value.style);
+    var inner = buildExpression(group.value.body, newOptions, true);
+    for (var i = 0; i < inner.length - 1; i++) {
+        if (inner[i].tryCombine(inner[i + 1])) {
+            inner.splice(i + 1, 1);
+            i--;
+        }
+    }
+    return makeSpan(["mord", "text", newOptions.style.cls()],
+        inner, newOptions);
+};
+
+groupTypes.color = function(group, options) {
+    var elements = buildExpression(
+        group.value.value,
+        options.withColor(group.value.color),
+        false
+    );
+
+    // \color isn't supposed to affect the type of the elements it contains.
+    // To accomplish this, we wrap the results in a fragment, so the inner
+    // elements will be able to directly interact with their neighbors. For
+    // example, `\color{red}{2 +} 3` has the same spacing as `2 + 3`
+    return new buildCommon.makeFragment(elements);
+};
+
+groupTypes.supsub = function(group, options) {
+    // Superscript and subscripts are handled in the TeXbook on page
+    // 445-446, rules 18(a-f).
+
+    // Here is where we defer to the inner group if it should handle
+    // superscripts and subscripts itself.
+    if (shouldHandleSupSub(group.value.base, options)) {
+        return groupTypes[group.value.base.type](group, options);
+    }
+
+    var base = buildGroup(group.value.base, options.reset());
+    var supmid;
+    var submid;
+    var sup;
+    var sub;
+
+    var style = options.style;
+    var newOptions;
+
+    if (group.value.sup) {
+        newOptions = options.withStyle(style.sup());
+        sup = buildGroup(group.value.sup, newOptions);
+        supmid = makeSpan([style.reset(), style.sup().cls()],
+            [sup], newOptions);
+    }
+
+    if (group.value.sub) {
+        newOptions = options.withStyle(style.sub());
+        sub = buildGroup(group.value.sub, newOptions);
+        submid = makeSpan([style.reset(), style.sub().cls()],
+            [sub], newOptions);
+    }
+
+    // Rule 18a
+    var supShift;
+    var subShift;
+    if (isCharacterBox(group.value.base)) {
+        supShift = 0;
+        subShift = 0;
+    } else {
+        supShift = base.height - style.metrics.supDrop;
+        subShift = base.depth + style.metrics.subDrop;
+    }
+
+    // Rule 18c
+    var minSupShift;
+    if (style === Style.DISPLAY) {
+        minSupShift = style.metrics.sup1;
+    } else if (style.cramped) {
+        minSupShift = style.metrics.sup3;
+    } else {
+        minSupShift = style.metrics.sup2;
+    }
+
+    // scriptspace is a font-size-independent size, so scale it
+    // appropriately
+    var multiplier = Style.TEXT.sizeMultiplier *
+            style.sizeMultiplier;
+    var scriptspace =
+        (0.5 / fontMetrics.metrics.ptPerEm) / multiplier + "em";
+
+    var supsub;
+    if (!group.value.sup) {
+        // Rule 18b
+        subShift = Math.max(
+            subShift, style.metrics.sub1,
+            sub.height - 0.8 * style.metrics.xHeight);
+
+        supsub = buildCommon.makeVList([
+            {type: "elem", elem: submid}
+        ], "shift", subShift, options);
+
+        supsub.children[0].style.marginRight = scriptspace;
+
+        // Subscripts shouldn't be shifted by the base's italic correction.
+        // Account for that by shifting the subscript back the appropriate
+        // amount. Note we only do this when the base is a single symbol.
+        if (base instanceof domTree.symbolNode) {
+            supsub.children[0].style.marginLeft = -base.italic + "em";
+        }
+    } else if (!group.value.sub) {
+        // Rule 18c, d
+        supShift = Math.max(supShift, minSupShift,
+            sup.depth + 0.25 * style.metrics.xHeight);
+
+        supsub = buildCommon.makeVList([
+            {type: "elem", elem: supmid}
+        ], "shift", -supShift, options);
+
+        supsub.children[0].style.marginRight = scriptspace;
+    } else {
+        supShift = Math.max(
+            supShift, minSupShift, sup.depth + 0.25 * style.metrics.xHeight);
+        subShift = Math.max(subShift, style.metrics.sub2);
+
+        var ruleWidth = fontMetrics.metrics.defaultRuleThickness;
+
+        // Rule 18e
+        if ((supShift - sup.depth) - (sub.height - subShift) <
+                4 * ruleWidth) {
+            subShift = 4 * ruleWidth - (supShift - sup.depth) + sub.height;
+            var psi = 0.8 * style.metrics.xHeight - (supShift - sup.depth);
+            if (psi > 0) {
+                supShift += psi;
+                subShift -= psi;
+            }
+        }
+
+        supsub = buildCommon.makeVList([
+            {type: "elem", elem: submid, shift: subShift},
+            {type: "elem", elem: supmid, shift: -supShift}
+        ], "individualShift", null, options);
+
+        // See comment above about subscripts not being shifted
+        if (base instanceof domTree.symbolNode) {
+            supsub.children[0].style.marginLeft = -base.italic + "em";
+        }
+
+        supsub.children[0].style.marginRight = scriptspace;
+        supsub.children[1].style.marginRight = scriptspace;
+    }
+
+    // We ensure to wrap the supsub vlist in a span.msupsub to reset text-align
+    var mclass = getTypeOfDomTree(base) || "mord";
+    return makeSpan([mclass],
+        [base, makeSpan(["msupsub"], [supsub])],
+        options);
+};
+
+groupTypes.genfrac = function(group, options) {
+    // Fractions are handled in the TeXbook on pages 444-445, rules 15(a-e).
+    // Figure out what style this fraction should be in based on the
+    // function used
+    var style = options.style;
+    if (group.value.size === "display") {
+        style = Style.DISPLAY;
+    } else if (group.value.size === "text") {
+        style = Style.TEXT;
+    }
+
+    var nstyle = style.fracNum();
+    var dstyle = style.fracDen();
+    var newOptions;
+
+    newOptions = options.withStyle(nstyle);
+    var numer = buildGroup(group.value.numer, newOptions);
+    var numerreset = makeSpan([style.reset(), nstyle.cls()],
+        [numer], newOptions);
+
+    newOptions = options.withStyle(dstyle);
+    var denom = buildGroup(group.value.denom, newOptions);
+    var denomreset = makeSpan([style.reset(), dstyle.cls()],
+        [denom], newOptions);
+
+    var ruleWidth;
+    if (group.value.hasBarLine) {
+        ruleWidth = fontMetrics.metrics.defaultRuleThickness /
+            options.style.sizeMultiplier;
+    } else {
+        ruleWidth = 0;
+    }
+
+    // Rule 15b
+    var numShift;
+    var clearance;
+    var denomShift;
+    if (style.size === Style.DISPLAY.size) {
+        numShift = style.metrics.num1;
+        if (ruleWidth > 0) {
+            clearance = 3 * ruleWidth;
+        } else {
+            clearance = 7 * fontMetrics.metrics.defaultRuleThickness;
+        }
+        denomShift = style.metrics.denom1;
+    } else {
+        if (ruleWidth > 0) {
+            numShift = style.metrics.num2;
+            clearance = ruleWidth;
+        } else {
+            numShift = style.metrics.num3;
+            clearance = 3 * fontMetrics.metrics.defaultRuleThickness;
+        }
+        denomShift = style.metrics.denom2;
+    }
+
+    var frac;
+    if (ruleWidth === 0) {
+        // Rule 15c
+        var candidateClearance =
+            (numShift - numer.depth) - (denom.height - denomShift);
+        if (candidateClearance < clearance) {
+            numShift += 0.5 * (clearance - candidateClearance);
+            denomShift += 0.5 * (clearance - candidateClearance);
+        }
+
+        frac = buildCommon.makeVList([
+            {type: "elem", elem: denomreset, shift: denomShift},
+            {type: "elem", elem: numerreset, shift: -numShift}
+        ], "individualShift", null, options);
+    } else {
+        // Rule 15d
+        var axisHeight = style.metrics.axisHeight;
+
+        if ((numShift - numer.depth) - (axisHeight + 0.5 * ruleWidth) <
+                clearance) {
+            numShift +=
+                clearance - ((numShift - numer.depth) -
+                             (axisHeight + 0.5 * ruleWidth));
+        }
+
+        if ((axisHeight - 0.5 * ruleWidth) - (denom.height - denomShift) <
+                clearance) {
+            denomShift +=
+                clearance - ((axisHeight - 0.5 * ruleWidth) -
+                             (denom.height - denomShift));
+        }
+
+        var mid = makeSpan(
+            [options.style.reset(), Style.TEXT.cls(), "frac-line"]);
+        // Manually set the height of the line because its height is
+        // created in CSS
+        mid.height = ruleWidth;
+
+        var midShift = -(axisHeight - 0.5 * ruleWidth);
+
+        frac = buildCommon.makeVList([
+            {type: "elem", elem: denomreset, shift: denomShift},
+            {type: "elem", elem: mid,        shift: midShift},
+            {type: "elem", elem: numerreset, shift: -numShift}
+        ], "individualShift", null, options);
+    }
+
+    // Since we manually change the style sometimes (with \dfrac or \tfrac),
+    // account for the possible size change here.
+    frac.height *= style.sizeMultiplier / options.style.sizeMultiplier;
+    frac.depth *= style.sizeMultiplier / options.style.sizeMultiplier;
+
+    // Rule 15e
+    var delimSize;
+    if (style.size === Style.DISPLAY.size) {
+        delimSize = style.metrics.delim1;
+    } else {
+        delimSize = style.metrics.delim2;
+    }
+
+    var leftDelim;
+    var rightDelim;
+    if (group.value.leftDelim == null) {
+        leftDelim = makeNullDelimiter(options, ["mopen"]);
+    } else {
+        leftDelim = delimiter.customSizedDelim(
+            group.value.leftDelim, delimSize, true,
+            options.withStyle(style), group.mode, ["mopen"]);
+    }
+    if (group.value.rightDelim == null) {
+        rightDelim = makeNullDelimiter(options, ["mclose"]);
+    } else {
+        rightDelim = delimiter.customSizedDelim(
+            group.value.rightDelim, delimSize, true,
+            options.withStyle(style), group.mode, ["mclose"]);
+    }
+
+    return makeSpan(
+        ["mord", options.style.reset(), style.cls()],
+        [leftDelim, makeSpan(["mfrac"], [frac]), rightDelim],
+        options);
+};
+
+var calculateSize = function(sizeValue, style) {
+    var x = sizeValue.number;
+    if (sizeValue.unit === "ex") {
+        x *= style.metrics.emPerEx;
+    } else if (sizeValue.unit === "mu") {
+        x /= 18;
+    }
+    return x;
+};
+
+groupTypes.array = function(group, options) {
+    var r;
+    var c;
+    var nr = group.value.body.length;
+    var nc = 0;
+    var body = new Array(nr);
+
+    var style = options.style;
+
+    // Horizontal spacing
+    var pt = 1 / fontMetrics.metrics.ptPerEm;
+    var arraycolsep = 5 * pt; // \arraycolsep in article.cls
+
+    // Vertical spacing
+    var baselineskip = 12 * pt; // see size10.clo
+    // Default \arraystretch from lttab.dtx
+    // TODO(gagern): may get redefined once we have user-defined macros
+    var arraystretch = utils.deflt(group.value.arraystretch, 1);
+    var arrayskip = arraystretch * baselineskip;
+    var arstrutHeight = 0.7 * arrayskip; // \strutbox in ltfsstrc.dtx and
+    var arstrutDepth = 0.3 * arrayskip;  // \@arstrutbox in lttab.dtx
+
+    var totalHeight = 0;
+    for (r = 0; r < group.value.body.length; ++r) {
+        var inrow = group.value.body[r];
+        var height = arstrutHeight; // \@array adds an \@arstrut
+        var depth = arstrutDepth;   // to each tow (via the template)
+
+        if (nc < inrow.length) {
+            nc = inrow.length;
+        }
+
+        var outrow = new Array(inrow.length);
+        for (c = 0; c < inrow.length; ++c) {
+            var elt = buildGroup(inrow[c], options);
+            if (depth < elt.depth) {
+                depth = elt.depth;
+            }
+            if (height < elt.height) {
+                height = elt.height;
+            }
+            outrow[c] = elt;
+        }
+
+        var gap = 0;
+        if (group.value.rowGaps[r]) {
+            gap = calculateSize(group.value.rowGaps[r].value, style);
+            if (gap > 0) { // \@argarraycr
+                gap += arstrutDepth;
+                if (depth < gap) {
+                    depth = gap; // \@xargarraycr
+                }
+                gap = 0;
+            }
+        }
+
+        outrow.height = height;
+        outrow.depth = depth;
+        totalHeight += height;
+        outrow.pos = totalHeight;
+        totalHeight += depth + gap; // \@yargarraycr
+        body[r] = outrow;
+    }
+
+    var offset = totalHeight / 2 + style.metrics.axisHeight;
+    var colDescriptions = group.value.cols || [];
+    var cols = [];
+    var colSep;
+    var colDescrNum;
+    for (c = 0, colDescrNum = 0;
+         // Continue while either there are more columns or more column
+         // descriptions, so trailing separators don't get lost.
+         c < nc || colDescrNum < colDescriptions.length;
+         ++c, ++colDescrNum) {
+
+        var colDescr = colDescriptions[colDescrNum] || {};
+
+        var firstSeparator = true;
+        while (colDescr.type === "separator") {
+            // If there is more than one separator in a row, add a space
+            // between them.
+            if (!firstSeparator) {
+                colSep = makeSpan(["arraycolsep"], []);
+                colSep.style.width =
+                    fontMetrics.metrics.doubleRuleSep + "em";
+                cols.push(colSep);
+            }
+
+            if (colDescr.separator === "|") {
+                var separator = makeSpan(
+                    ["vertical-separator"],
+                    []);
+                separator.style.height = totalHeight + "em";
+                separator.style.verticalAlign =
+                    -(totalHeight - offset) + "em";
+
+                cols.push(separator);
+            } else {
+                throw new ParseError(
+                    "Invalid separator type: " + colDescr.separator);
+            }
+
+            colDescrNum++;
+            colDescr = colDescriptions[colDescrNum] || {};
+            firstSeparator = false;
+        }
+
+        if (c >= nc) {
+            continue;
+        }
+
+        var sepwidth;
+        if (c > 0 || group.value.hskipBeforeAndAfter) {
+            sepwidth = utils.deflt(colDescr.pregap, arraycolsep);
+            if (sepwidth !== 0) {
+                colSep = makeSpan(["arraycolsep"], []);
+                colSep.style.width = sepwidth + "em";
+                cols.push(colSep);
+            }
+        }
+
+        var col = [];
+        for (r = 0; r < nr; ++r) {
+            var row = body[r];
+            var elem = row[c];
+            if (!elem) {
+                continue;
+            }
+            var shift = row.pos - offset;
+            elem.depth = row.depth;
+            elem.height = row.height;
+            col.push({type: "elem", elem: elem, shift: shift});
+        }
+
+        col = buildCommon.makeVList(col, "individualShift", null, options);
+        col = makeSpan(
+            ["col-align-" + (colDescr.align || "c")],
+            [col]);
+        cols.push(col);
+
+        if (c < nc - 1 || group.value.hskipBeforeAndAfter) {
+            sepwidth = utils.deflt(colDescr.postgap, arraycolsep);
+            if (sepwidth !== 0) {
+                colSep = makeSpan(["arraycolsep"], []);
+                colSep.style.width = sepwidth + "em";
+                cols.push(colSep);
+            }
+        }
+    }
+    body = makeSpan(["mtable"], cols);
+    return makeSpan(["mord"], [body], options);
+};
+
+groupTypes.spacing = function(group, options) {
+    if (group.value === "\\ " || group.value === "\\space" ||
+        group.value === " " || group.value === "~") {
+        // Spaces are generated by adding an actual space. Each of these
+        // things has an entry in the symbols table, so these will be turned
+        // into appropriate outputs.
+        if (group.mode === "text") {
+            return buildCommon.makeOrd(group, options, "textord");
+        } else {
+            return makeSpan(["mspace"],
+                [buildCommon.mathsym(group.value, group.mode, options)],
+                options);
+        }
+    } else {
+        // Other kinds of spaces are of arbitrary width. We use CSS to
+        // generate these.
+        return makeSpan(
+            ["mspace",
+                buildCommon.spacingFunctions[group.value].className],
+            [], options);
+    }
+};
+
+groupTypes.llap = function(group, options) {
+    var inner = makeSpan(
+        ["inner"], [buildGroup(group.value.body, options.reset())]);
+    var fix = makeSpan(["fix"], []);
+    return makeSpan(
+        ["mord", "llap", options.style.cls()], [inner, fix], options);
+};
+
+groupTypes.rlap = function(group, options) {
+    var inner = makeSpan(
+        ["inner"], [buildGroup(group.value.body, options.reset())]);
+    var fix = makeSpan(["fix"], []);
+    return makeSpan(
+        ["mord", "rlap", options.style.cls()], [inner, fix], options);
+};
+
+groupTypes.op = function(group, options) {
+    // Operators are handled in the TeXbook pg. 443-444, rule 13(a).
+    var supGroup;
+    var subGroup;
+    var hasLimits = false;
+    if (group.type === "supsub") {
+        // If we have limits, supsub will pass us its group to handle. Pull
+        // out the superscript and subscript and set the group to the op in
+        // its base.
+        supGroup = group.value.sup;
+        subGroup = group.value.sub;
+        group = group.value.base;
+        hasLimits = true;
+    }
+
+    var style = options.style;
+
+    // Most operators have a large successor symbol, but these don't.
+    var noSuccessor = [
+        "\\smallint"
+    ];
+
+    var large = false;
+    if (style.size === Style.DISPLAY.size &&
+        group.value.symbol &&
+        !utils.contains(noSuccessor, group.value.body)) {
+
+        // Most symbol operators get larger in displaystyle (rule 13)
+        large = true;
+    }
+
+    var base;
+    var baseShift = 0;
+    var slant = 0;
+    if (group.value.symbol) {
+        // If this is a symbol, create the symbol.
+        var fontName = large ? "Size2-Regular" : "Size1-Regular";
+        base = buildCommon.makeSymbol(
+            group.value.body, fontName, "math", options,
+            ["mop", "op-symbol", large ? "large-op" : "small-op"]);
+
+        // Shift the symbol so its center lies on the axis (rule 13). It
+        // appears that our fonts have the centers of the symbols already
+        // almost on the axis, so these numbers are very small. Note we
+        // don't actually apply this here, but instead it is used either in
+        // the vlist creation or separately when there are no limits.
+        baseShift = (base.height - base.depth) / 2 -
+            style.metrics.axisHeight * style.sizeMultiplier;
+
+        // The slant of the symbol is just its italic correction.
+        slant = base.italic;
+    } else if (group.value.value) {
+        // If this is a list, compose that list.
+        var inner = buildExpression(group.value.value, options, true);
+
+        base = makeSpan(["mop"], inner, options);
+    } else {
+        // Otherwise, this is a text operator. Build the text from the
+        // operator's name.
+        // TODO(emily): Add a space in the middle of some of these
+        // operators, like \limsup
+        var output = [];
+        for (var i = 1; i < group.value.body.length; i++) {
+            output.push(buildCommon.mathsym(group.value.body[i], group.mode));
+        }
+        base = makeSpan(["mop"], output, options);
+    }
+
+    if (hasLimits) {
+        // IE 8 clips \int if it is in a display: inline-block. We wrap it
+        // in a new span so it is an inline, and works.
+        base = makeSpan([], [base]);
+
+        var supmid;
+        var supKern;
+        var submid;
+        var subKern;
+        var newOptions;
+        // We manually have to handle the superscripts and subscripts. This,
+        // aside from the kern calculations, is copied from supsub.
+        if (supGroup) {
+            newOptions = options.withStyle(style.sup());
+            var sup = buildGroup(supGroup, newOptions);
+            supmid = makeSpan([style.reset(), style.sup().cls()],
+                [sup], newOptions);
+
+            supKern = Math.max(
+                fontMetrics.metrics.bigOpSpacing1,
+                fontMetrics.metrics.bigOpSpacing3 - sup.depth);
+        }
+
+        if (subGroup) {
+            newOptions = options.withStyle(style.sub());
+            var sub = buildGroup(subGroup, newOptions);
+            submid = makeSpan([style.reset(), style.sub().cls()],
+                [sub], newOptions);
+
+            subKern = Math.max(
+                fontMetrics.metrics.bigOpSpacing2,
+                fontMetrics.metrics.bigOpSpacing4 - sub.height);
+        }
+
+        // Build the final group as a vlist of the possible subscript, base,
+        // and possible superscript.
+        var finalGroup;
+        var top;
+        var bottom;
+        if (!supGroup) {
+            top = base.height - baseShift;
+
+            finalGroup = buildCommon.makeVList([
+                {type: "kern", size: fontMetrics.metrics.bigOpSpacing5},
+                {type: "elem", elem: submid},
+                {type: "kern", size: subKern},
+                {type: "elem", elem: base}
+            ], "top", top, options);
+
+            // Here, we shift the limits by the slant of the symbol. Note
+            // that we are supposed to shift the limits by 1/2 of the slant,
+            // but since we are centering the limits adding a full slant of
+            // margin will shift by 1/2 that.
+            finalGroup.children[0].style.marginLeft = -slant + "em";
+        } else if (!subGroup) {
+            bottom = base.depth + baseShift;
+
+            finalGroup = buildCommon.makeVList([
+                {type: "elem", elem: base},
+                {type: "kern", size: supKern},
+                {type: "elem", elem: supmid},
+                {type: "kern", size: fontMetrics.metrics.bigOpSpacing5}
+            ], "bottom", bottom, options);
+
+            // See comment above about slants
+            finalGroup.children[1].style.marginLeft = slant + "em";
+        } else if (!supGroup && !subGroup) {
+            // This case probably shouldn't occur (this would mean the
+            // supsub was sending us a group with no superscript or
+            // subscript) but be safe.
+            return base;
+        } else {
+            bottom = fontMetrics.metrics.bigOpSpacing5 +
+                submid.height + submid.depth +
+                subKern +
+                base.depth + baseShift;
+
+            finalGroup = buildCommon.makeVList([
+                {type: "kern", size: fontMetrics.metrics.bigOpSpacing5},
+                {type: "elem", elem: submid},
+                {type: "kern", size: subKern},
+                {type: "elem", elem: base},
+                {type: "kern", size: supKern},
+                {type: "elem", elem: supmid},
+                {type: "kern", size: fontMetrics.metrics.bigOpSpacing5}
+            ], "bottom", bottom, options);
+
+            // See comment above about slants
+            finalGroup.children[0].style.marginLeft = -slant + "em";
+            finalGroup.children[2].style.marginLeft = slant + "em";
+        }
+
+        return makeSpan(["mop", "op-limits"], [finalGroup], options);
+    } else {
+        if (group.value.symbol) {
+            base.style.top = baseShift + "em";
+        }
+
+        return base;
+    }
+};
+
+groupTypes.mod = function(group, options) {
+    var inner = [];
+
+    if (group.value.modType === "bmod") {
+        // “\nonscript\mskip-\medmuskip\mkern5mu”
+        if (!options.style.isTight()) {
+            inner.push(makeSpan(
+                ["mspace", "negativemediumspace"], [], options));
+        }
+        inner.push(makeSpan(["mspace", "thickspace"], [], options));
+    } else if (options.style.size === Style.DISPLAY.size) {
+        inner.push(makeSpan(["mspace", "quad"], [], options));
+    } else if (group.value.modType === "mod") {
+        inner.push(makeSpan(["mspace", "twelvemuspace"], [], options));
+    } else {
+        inner.push(makeSpan(["mspace", "eightmuspace"], [], options));
+    }
+
+    if (group.value.modType === "pod" || group.value.modType === "pmod") {
+        inner.push(buildCommon.mathsym("(", group.mode));
+    }
+
+    if (group.value.modType !== "pod") {
+        var modInner = [
+            buildCommon.mathsym("m", group.mode),
+            buildCommon.mathsym("o", group.mode),
+            buildCommon.mathsym("d", group.mode)];
+        if (group.value.modType === "bmod") {
+            inner.push(makeSpan(["mbin"], modInner, options));
+            // “\mkern5mu\nonscript\mskip-\medmuskip”
+            inner.push(makeSpan(["mspace", "thickspace"], [], options));
+            if (!options.style.isTight()) {
+                inner.push(makeSpan(
+                    ["mspace", "negativemediumspace"], [], options));
+            }
+        } else {
+            Array.prototype.push.apply(inner, modInner);
+            inner.push(makeSpan(["mspace", "sixmuspace"], [], options));
+        }
+    }
+
+    if (group.value.value) {
+        Array.prototype.push.apply(inner,
+            buildExpression(group.value.value, options, false));
+    }
+
+    if (group.value.modType === "pod" || group.value.modType === "pmod") {
+        inner.push(buildCommon.mathsym(")", group.mode));
+    }
+
+    return buildCommon.makeFragment(inner);
+};
+
+groupTypes.katex = function(group, options) {
+    // The KaTeX logo. The offsets for the K and a were chosen to look
+    // good, but the offsets for the T, E, and X were taken from the
+    // definition of \TeX in TeX (see TeXbook pg. 356)
+    var k = makeSpan(
+        ["k"], [buildCommon.mathsym("K", group.mode)], options);
+    var a = makeSpan(
+        ["a"], [buildCommon.mathsym("A", group.mode)], options);
+
+    a.height = (a.height + 0.2) * 0.75;
+    a.depth = (a.height - 0.2) * 0.75;
+
+    var t = makeSpan(
+        ["t"], [buildCommon.mathsym("T", group.mode)], options);
+    var e = makeSpan(
+        ["e"], [buildCommon.mathsym("E", group.mode)], options);
+
+    e.height = (e.height - 0.2155);
+    e.depth = (e.depth + 0.2155);
+
+    var x = makeSpan(
+        ["x"], [buildCommon.mathsym("X", group.mode)], options);
+
+    return makeSpan(
+        ["mord", "katex-logo"], [k, a, t, e, x], options);
+};
+
+groupTypes.overline = function(group, options) {
+    // Overlines are handled in the TeXbook pg 443, Rule 9.
+    var style = options.style;
+
+    // Build the inner group in the cramped style.
+    var innerGroup = buildGroup(group.value.body,
+            options.withStyle(style.cramp()));
+
+    var ruleWidth = fontMetrics.metrics.defaultRuleThickness /
+        style.sizeMultiplier;
+
+    // Create the line above the body
+    var line = makeSpan(
+        [style.reset(), Style.TEXT.cls(), "overline-line"]);
+    line.height = ruleWidth;
+    line.maxFontSize = 1.0;
+
+    // Generate the vlist, with the appropriate kerns
+    var vlist = buildCommon.makeVList([
+        {type: "elem", elem: innerGroup},
+        {type: "kern", size: 3 * ruleWidth},
+        {type: "elem", elem: line},
+        {type: "kern", size: ruleWidth}
+    ], "firstBaseline", null, options);
+
+    return makeSpan(["mord", "overline"], [vlist], options);
+};
+
+groupTypes.underline = function(group, options) {
+    // Underlines are handled in the TeXbook pg 443, Rule 10.
+    var style = options.style;
+
+    // Build the inner group.
+    var innerGroup = buildGroup(group.value.body, options);
+
+    var ruleWidth = fontMetrics.metrics.defaultRuleThickness /
+        style.sizeMultiplier;
+
+    // Create the line above the body
+    var line = makeSpan([style.reset(), Style.TEXT.cls(), "underline-line"]);
+    line.height = ruleWidth;
+    line.maxFontSize = 1.0;
+
+    // Generate the vlist, with the appropriate kerns
+    var vlist = buildCommon.makeVList([
+        {type: "kern", size: ruleWidth},
+        {type: "elem", elem: line},
+        {type: "kern", size: 3 * ruleWidth},
+        {type: "elem", elem: innerGroup}
+    ], "top", innerGroup.height, options);
+
+    return makeSpan(["mord", "underline"], [vlist], options);
+};
+
+groupTypes.sqrt = function(group, options) {
+    // Square roots are handled in the TeXbook pg. 443, Rule 11.
+    var style = options.style;
+
+    // First, we do the same steps as in overline to build the inner group
+    // and line
+    var inner = buildGroup(group.value.body, options.withStyle(style.cramp()));
+
+    var ruleWidth = fontMetrics.metrics.defaultRuleThickness /
+        style.sizeMultiplier;
+
+    var line = makeSpan(
+        [style.reset(), Style.TEXT.cls(), "sqrt-line"], [],
+        options);
+    line.height = ruleWidth;
+    line.maxFontSize = 1.0;
+
+    var phi = ruleWidth;
+    if (style.id < Style.TEXT.id) {
+        phi = style.metrics.xHeight;
+    }
+
+    // Calculate the clearance between the body and line
+    var lineClearance = ruleWidth + phi / 4;
+
+    var innerHeight = (inner.height + inner.depth) * style.sizeMultiplier;
+    var minDelimiterHeight = innerHeight + lineClearance + ruleWidth;
+
+    // Create a \surd delimiter of the required minimum size
+    var delim = makeSpan(["sqrt-sign"], [
+        delimiter.customSizedDelim("\\surd", minDelimiterHeight,
+                                   false, options, group.mode)],
+                         options);
+
+    var delimDepth = (delim.height + delim.depth) - ruleWidth;
+
+    // Adjust the clearance based on the delimiter size
+    if (delimDepth > inner.height + inner.depth + lineClearance) {
+        lineClearance =
+            (lineClearance + delimDepth - inner.height - inner.depth) / 2;
+    }
+
+    // Shift the delimiter so that its top lines up with the top of the line
+    var delimShift = -(inner.height + lineClearance + ruleWidth) + delim.height;
+    delim.style.top = delimShift + "em";
+    delim.height -= delimShift;
+    delim.depth += delimShift;
+
+    // We add a special case here, because even when `inner` is empty, we
+    // still get a line. So, we use a simple heuristic to decide if we
+    // should omit the body entirely. (note this doesn't work for something
+    // like `\sqrt{\rlap{x}}`, but if someone is doing that they deserve for
+    // it not to work.
+    var body;
+    if (inner.height === 0 && inner.depth === 0) {
+        body = makeSpan();
+    } else {
+        body = buildCommon.makeVList([
+            {type: "elem", elem: inner},
+            {type: "kern", size: lineClearance},
+            {type: "elem", elem: line},
+            {type: "kern", size: ruleWidth}
+        ], "firstBaseline", null, options);
+    }
+
+    if (!group.value.index) {
+        return makeSpan(["mord", "sqrt"], [delim, body], options);
+    } else {
+        // Handle the optional root index
+
+        // The index is always in scriptscript style
+        var newOptions = options.withStyle(Style.SCRIPTSCRIPT);
+        var root = buildGroup(group.value.index, newOptions);
+        var rootWrap = makeSpan(
+            [style.reset(), Style.SCRIPTSCRIPT.cls()],
+            [root],
+            newOptions);
+
+        // Figure out the height and depth of the inner part
+        var innerRootHeight = Math.max(delim.height, body.height);
+        var innerRootDepth = Math.max(delim.depth, body.depth);
+
+        // The amount the index is shifted by. This is taken from the TeX
+        // source, in the definition of `\r@@t`.
+        var toShift = 0.6 * (innerRootHeight - innerRootDepth);
+
+        // Build a VList with the superscript shifted up correctly
+        var rootVList = buildCommon.makeVList(
+            [{type: "elem", elem: rootWrap}],
+            "shift", -toShift, options);
+        // Add a class surrounding it so we can add on the appropriate
+        // kerning
+        var rootVListWrap = makeSpan(["root"], [rootVList]);
+
+        return makeSpan(["mord", "sqrt"],
+            [rootVListWrap, delim, body], options);
+    }
+};
+
+groupTypes.sizing = function(group, options) {
+    // Handle sizing operators like \Huge. Real TeX doesn't actually allow
+    // these functions inside of math expressions, so we do some special
+    // handling.
+    var inner = buildExpression(group.value.value,
+            options.withSize(group.value.size), false);
+
+    // Compute the correct maxFontSize.
+    var style = options.style;
+    var fontSize = buildCommon.sizingMultiplier[group.value.size];
+    fontSize = fontSize * style.sizeMultiplier;
+
+    // Add size-resetting classes to the inner list and set maxFontSize
+    // manually. Handle nested size changes.
+    for (var i = 0; i < inner.length; i++) {
+        var pos = utils.indexOf(inner[i].classes, "sizing");
+        if (pos < 0) {
+            inner[i].classes.push("sizing", "reset-" + options.size,
+                                  group.value.size, style.cls());
+            inner[i].maxFontSize = fontSize;
+        } else if (inner[i].classes[pos + 1] === "reset-" + group.value.size) {
+            // This is a nested size change: e.g., inner[i] is the "b" in
+            // `\Huge a \small b`. Override the old size (the `reset-` class)
+            // but not the new size.
+            inner[i].classes[pos + 1] = "reset-" + options.size;
+        }
+    }
+
+    return buildCommon.makeFragment(inner);
+};
+
+groupTypes.styling = function(group, options) {
+    // Style changes are handled in the TeXbook on pg. 442, Rule 3.
+
+    // Figure out what style we're changing to.
+    var styleMap = {
+        "display": Style.DISPLAY,
+        "text": Style.TEXT,
+        "script": Style.SCRIPT,
+        "scriptscript": Style.SCRIPTSCRIPT
+    };
+
+    var newStyle = styleMap[group.value.style];
+    var newOptions = options.withStyle(newStyle);
+
+    // Build the inner expression in the new style.
+    var inner = buildExpression(
+        group.value.value, newOptions, false);
+
+    // Add style-resetting classes to the inner list. Handle nested changes.
+    for (var i = 0; i < inner.length; i++) {
+        var pos = utils.indexOf(inner[i].classes, newStyle.reset());
+        if (pos < 0) {
+            inner[i].classes.push(options.style.reset(), newStyle.cls());
+        } else {
+            // This is a nested style change, as `\textstyle a\scriptstyle b`.
+            // Only override the old style (the reset class).
+            inner[i].classes[pos] = options.style.reset();
+        }
+    }
+
+    return new buildCommon.makeFragment(inner);
+};
+
+groupTypes.font = function(group, options) {
+    var font = group.value.font;
+    return buildGroup(group.value.body, options.withFont(font));
+};
+
+groupTypes.delimsizing = function(group, options) {
+    var delim = group.value.value;
+
+    if (delim === ".") {
+        // Empty delimiters still count as elements, even though they don't
+        // show anything.
+        return makeSpan([group.value.mclass]);
+    }
+
+    // Use delimiter.sizedDelim to generate the delimiter.
+    return delimiter.sizedDelim(
+            delim, group.value.size, options, group.mode,
+            [group.value.mclass]);
+};
+
+groupTypes.leftright = function(group, options) {
+    // Build the inner expression
+    var inner = buildExpression(group.value.body, options.reset(), true);
+
+    var innerHeight = 0;
+    var innerDepth = 0;
+    var hadMiddle = false;
+
+    // Calculate its height and depth
+    for (var i = 0; i < inner.length; i++) {
+        if (inner[i].isMiddle) {
+            hadMiddle = true;
+        } else {
+            innerHeight = Math.max(inner[i].height, innerHeight);
+            innerDepth = Math.max(inner[i].depth, innerDepth);
+        }
+    }
+
+    var style = options.style;
+
+    // The size of delimiters is the same, regardless of what style we are
+    // in. Thus, to correctly calculate the size of delimiter we need around
+    // a group, we scale down the inner size based on the size.
+    innerHeight *= style.sizeMultiplier;
+    innerDepth *= style.sizeMultiplier;
+
+    var leftDelim;
+    if (group.value.left === ".") {
+        // Empty delimiters in \left and \right make null delimiter spaces.
+        leftDelim = makeNullDelimiter(options, ["mopen"]);
+    } else {
+        // Otherwise, use leftRightDelim to generate the correct sized
+        // delimiter.
+        leftDelim = delimiter.leftRightDelim(
+            group.value.left, innerHeight, innerDepth, options,
+            group.mode, ["mopen"]);
+    }
+    // Add it to the beginning of the expression
+    inner.unshift(leftDelim);
+
+    // Handle middle delimiters
+    if (hadMiddle) {
+        for (i = 1; i < inner.length; i++) {
+            if (inner[i].isMiddle) {
+                // Apply the options that were active when \middle was called
+                inner[i] = delimiter.leftRightDelim(
+                    inner[i].isMiddle.value, innerHeight, innerDepth,
+                    inner[i].isMiddle.options, group.mode, []);
+            }
+        }
+    }
+
+    var rightDelim;
+    // Same for the right delimiter
+    if (group.value.right === ".") {
+        rightDelim = makeNullDelimiter(options, ["mclose"]);
+    } else {
+        rightDelim = delimiter.leftRightDelim(
+            group.value.right, innerHeight, innerDepth, options,
+            group.mode, ["mclose"]);
+    }
+    // Add it to the end of the expression.
+    inner.push(rightDelim);
+
+    return makeSpan(
+        ["minner", style.cls()], inner, options);
+};
+
+groupTypes.middle = function(group, options) {
+    var middleDelim;
+    if (group.value.value === ".") {
+        middleDelim = makeNullDelimiter(options, []);
+    } else {
+        middleDelim = delimiter.sizedDelim(
+            group.value.value, 1, options,
+            group.mode, []);
+        middleDelim.isMiddle = {value: group.value.value, options: options};
+    }
+    return middleDelim;
+};
+
+groupTypes.rule = function(group, options) {
+    // Make an empty span for the rule
+    var rule = makeSpan(["mord", "rule"], [], options);
+    var style = options.style;
+
+    // Calculate the shift, width, and height of the rule, and account for units
+    var shift = 0;
+    if (group.value.shift) {
+        shift = calculateSize(group.value.shift, style);
+    }
+
+    var width = calculateSize(group.value.width, style);
+    var height = calculateSize(group.value.height, style);
+
+    // The sizes of rules are absolute, so make it larger if we are in a
+    // smaller style.
+    shift /= style.sizeMultiplier;
+    width /= style.sizeMultiplier;
+    height /= style.sizeMultiplier;
+
+    // Style the rule to the right size
+    rule.style.borderRightWidth = width + "em";
+    rule.style.borderTopWidth = height + "em";
+    rule.style.bottom = shift + "em";
+
+    // Record the height and width
+    rule.width = width;
+    rule.height = height + shift;
+    rule.depth = -shift;
+
+    return rule;
+};
+
+groupTypes.kern = function(group, options) {
+    // Make an empty span for the rule
+    var rule = makeSpan(["mord", "rule"], [], options);
+    var style = options.style;
+
+    var dimension = 0;
+    if (group.value.dimension) {
+        dimension = calculateSize(group.value.dimension, style);
+    }
+
+    dimension /= style.sizeMultiplier;
+
+    rule.style.marginLeft = dimension + "em";
+
+    return rule;
+};
+
+groupTypes.accent = function(group, options) {
+    // Accents are handled in the TeXbook pg. 443, rule 12.
+    var base = group.value.base;
+    var style = options.style;
+
+    var supsubGroup;
+    if (group.type === "supsub") {
+        // If our base is a character box, and we have superscripts and
+        // subscripts, the supsub will defer to us. In particular, we want
+        // to attach the superscripts and subscripts to the inner body (so
+        // that the position of the superscripts and subscripts won't be
+        // affected by the height of the accent). We accomplish this by
+        // sticking the base of the accent into the base of the supsub, and
+        // rendering that, while keeping track of where the accent is.
+
+        // The supsub group is the group that was passed in
+        var supsub = group;
+        // The real accent group is the base of the supsub group
+        group = supsub.value.base;
+        // The character box is the base of the accent group
+        base = group.value.base;
+        // Stick the character box into the base of the supsub group
+        supsub.value.base = base;
+
+        // Rerender the supsub group with its new base, and store that
+        // result.
+        supsubGroup = buildGroup(
+            supsub, options.reset());
+    }
+
+    // Build the base group
+    var body = buildGroup(
+        base, options.withStyle(style.cramp()));
+
+    // Calculate the skew of the accent. This is based on the line "If the
+    // nucleus is not a single character, let s = 0; otherwise set s to the
+    // kern amount for the nucleus followed by the \skewchar of its font."
+    // Note that our skew metrics are just the kern between each character
+    // and the skewchar.
+    var skew;
+    if (isCharacterBox(base)) {
+        // If the base is a character box, then we want the skew of the
+        // innermost character. To do that, we find the innermost character:
+        var baseChar = getBaseElem(base);
+        // Then, we render its group to get the symbol inside it
+        var baseGroup = buildGroup(
+            baseChar, options.withStyle(style.cramp()));
+        // Finally, we pull the skew off of the symbol.
+        skew = baseGroup.skew;
+        // Note that we now throw away baseGroup, because the layers we
+        // removed with getBaseElem might contain things like \color which
+        // we can't get rid of.
+        // TODO(emily): Find a better way to get the skew
+    } else {
+        skew = 0;
+    }
+
+    // calculate the amount of space between the body and the accent
+    var clearance = Math.min(
+        body.height,
+        style.metrics.xHeight);
+
+    // Build the accent
+    var accent = buildCommon.makeSymbol(
+        group.value.accent, "Main-Regular", "math", options);
+    // Remove the italic correction of the accent, because it only serves to
+    // shift the accent over to a place we don't want.
+    accent.italic = 0;
+
+    // The \vec character that the fonts use is a combining character, and
+    // thus shows up much too far to the left. To account for this, we add a
+    // specific class which shifts the accent over to where we want it.
+    // TODO(emily): Fix this in a better way, like by changing the font
+    var vecClass = group.value.accent === "\\vec" ? "accent-vec" : null;
+
+    var accentBody = makeSpan(["accent-body", vecClass], [
+        makeSpan([], [accent])]);
+
+    accentBody = buildCommon.makeVList([
+        {type: "elem", elem: body},
+        {type: "kern", size: -clearance},
+        {type: "elem", elem: accentBody}
+    ], "firstBaseline", null, options);
+
+    // Shift the accent over by the skew. Note we shift by twice the skew
+    // because we are centering the accent, so by adding 2*skew to the left,
+    // we shift it to the right by 1*skew.
+    accentBody.children[1].style.marginLeft = 2 * skew + "em";
+
+    var accentWrap = makeSpan(["mord", "accent"], [accentBody], options);
+
+    if (supsubGroup) {
+        // Here, we replace the "base" child of the supsub with our newly
+        // generated accent.
+        supsubGroup.children[0] = accentWrap;
+
+        // Since we don't rerun the height calculation after replacing the
+        // accent, we manually recalculate height.
+        supsubGroup.height = Math.max(accentWrap.height, supsubGroup.height);
+
+        // Accents should always be ords, even when their innards are not.
+        supsubGroup.classes[0] = "mord";
+
+        return supsubGroup;
+    } else {
+        return accentWrap;
+    }
+};
+
+groupTypes.phantom = function(group, options) {
+    var elements = buildExpression(
+        group.value.value,
+        options.withPhantom(),
+        false
+    );
+
+    // \phantom isn't supposed to affect the elements it contains.
+    // See "color" for more details.
+    return new buildCommon.makeFragment(elements);
+};
+
+groupTypes.mclass = function(group, options) {
+    var elements = buildExpression(group.value.value, options, true);
+
+    return makeSpan([group.value.mclass], elements, options);
+};
+
+/**
+ * buildGroup is the function that takes a group and calls the correct groupType
+ * function for it. It also handles the interaction of size and style changes
+ * between parents and children.
+ */
+var buildGroup = function(group, options) {
+    if (!group) {
+        return makeSpan();
+    }
+
+    if (groupTypes[group.type]) {
+        // Call the groupTypes function
+        var groupNode = groupTypes[group.type](group, options);
+        var multiplier;
+
+        // If the style changed between the parent and the current group,
+        // account for the size difference
+        if (options.style !== options.parentStyle) {
+            multiplier = options.style.sizeMultiplier /
+                    options.parentStyle.sizeMultiplier;
+
+            groupNode.height *= multiplier;
+            groupNode.depth *= multiplier;
+        }
+
+        // If the size changed between the parent and the current group, account
+        // for that size difference.
+        if (options.size !== options.parentSize) {
+            multiplier = buildCommon.sizingMultiplier[options.size] /
+                    buildCommon.sizingMultiplier[options.parentSize];
+
+            groupNode.height *= multiplier;
+            groupNode.depth *= multiplier;
+        }
+
+        return groupNode;
+    } else {
+        throw new ParseError(
+            "Got group of unknown type: '" + group.type + "'");
+    }
+};
+
+/**
+ * Take an entire parse tree, and build it into an appropriate set of HTML
+ * nodes.
+ */
+var buildHTML = function(tree, options) {
+    // buildExpression is destructive, so we need to make a clone
+    // of the incoming tree so that it isn't accidentally changed
+    tree = JSON.parse(JSON.stringify(tree));
+
+    // Build the expression contained in the tree
+    var expression = buildExpression(tree, options, true);
+    var body = makeSpan(["base", options.style.cls()], expression, options);
+
+    // Add struts, which ensure that the top of the HTML element falls at the
+    // height of the expression, and the bottom of the HTML element falls at the
+    // depth of the expression.
+    var topStrut = makeSpan(["strut"]);
+    var bottomStrut = makeSpan(["strut", "bottom"]);
+
+    topStrut.style.height = body.height + "em";
+    bottomStrut.style.height = (body.height + body.depth) + "em";
+    // We'd like to use `vertical-align: top` but in IE 9 this lowers the
+    // baseline of the box to the bottom of this strut (instead staying in the
+    // normal place) so we use an absolute value for vertical-align instead
+    bottomStrut.style.verticalAlign = -body.depth + "em";
+
+    // Wrap the struts and body together
+    var htmlNode = makeSpan(["katex-html"], [topStrut, bottomStrut, body]);
+
+    htmlNode.setAttribute("aria-hidden", "true");
+
+    return htmlNode;
+};
+
+module.exports = buildHTML;
+
+},{"./ParseError":6,"./Style":9,"./buildCommon":10,"./delimiter":14,"./domTree":15,"./fontMetrics":17,"./utils":25}],12:[function(require,module,exports){
+/**
+ * This file converts a parse tree into a cooresponding MathML tree. The main
+ * entry point is the `buildMathML` function, which takes a parse tree from the
+ * parser.
+ */
+
+var buildCommon = require("./buildCommon");
+var fontMetrics = require("./fontMetrics");
+var mathMLTree = require("./mathMLTree");
+var ParseError = require("./ParseError");
+var symbols = require("./symbols");
+var utils = require("./utils");
+
+var makeSpan = buildCommon.makeSpan;
+var fontMap = buildCommon.fontMap;
+
+/**
+ * Takes a symbol and converts it into a MathML text node after performing
+ * optional replacement from symbols.js.
+ */
+var makeText = function(text, mode) {
+    if (symbols[mode][text] && symbols[mode][text].replace) {
+        text = symbols[mode][text].replace;
+    }
+
+    return new mathMLTree.TextNode(text);
+};
+
+/**
+ * Returns the math variant as a string or null if none is required.
+ */
+var getVariant = function(group, options) {
+    var font = options.font;
+    if (!font) {
+        return null;
+    }
+
+    var mode = group.mode;
+    if (font === "mathit") {
+        return "italic";
+    }
+
+    var value = group.value;
+    if (utils.contains(["\\imath", "\\jmath"], value)) {
+        return null;
+    }
+
+    if (symbols[mode][value] && symbols[mode][value].replace) {
+        value = symbols[mode][value].replace;
+    }
+
+    var fontName = fontMap[font].fontName;
+    if (fontMetrics.getCharacterMetrics(value, fontName)) {
+        return fontMap[options.font].variant;
+    }
+
+    return null;
+};
+
+/**
+ * Functions for handling the different types of groups found in the parse
+ * tree. Each function should take a parse group and return a MathML node.
+ */
+var groupTypes = {};
+
+groupTypes.mathord = function(group, options) {
+    var node = new mathMLTree.MathNode(
+        "mi",
+        [makeText(group.value, group.mode)]);
+
+    var variant = getVariant(group, options);
+    if (variant) {
+        node.setAttribute("mathvariant", variant);
+    }
+    return node;
+};
+
+groupTypes.textord = function(group, options) {
+    var text = makeText(group.value, group.mode);
+
+    var variant = getVariant(group, options) || "normal";
+
+    var node;
+    if (/[0-9]/.test(group.value)) {
+        // TODO(kevinb) merge adjacent <mn> nodes
+        // do it as a post processing step
+        node = new mathMLTree.MathNode("mn", [text]);
+        if (options.font) {
+            node.setAttribute("mathvariant", variant);
+        }
+    } else {
+        node = new mathMLTree.MathNode("mi", [text]);
+        node.setAttribute("mathvariant", variant);
+    }
+
+    return node;
+};
+
+groupTypes.bin = function(group) {
+    var node = new mathMLTree.MathNode(
+        "mo", [makeText(group.value, group.mode)]);
+
+    return node;
+};
+
+groupTypes.rel = function(group) {
+    var node = new mathMLTree.MathNode(
+        "mo", [makeText(group.value, group.mode)]);
+
+    return node;
+};
+
+groupTypes.open = function(group) {
+    var node = new mathMLTree.MathNode(
+        "mo", [makeText(group.value, group.mode)]);
+
+    return node;
+};
+
+groupTypes.close = function(group) {
+    var node = new mathMLTree.MathNode(
+        "mo", [makeText(group.value, group.mode)]);
+
+    return node;
+};
+
+groupTypes.inner = function(group) {
+    var node = new mathMLTree.MathNode(
+        "mo", [makeText(group.value, group.mode)]);
+
+    return node;
+};
+
+groupTypes.punct = function(group) {
+    var node = new mathMLTree.MathNode(
+        "mo", [makeText(group.value, group.mode)]);
+
+    node.setAttribute("separator", "true");
+
+    return node;
+};
+
+groupTypes.ordgroup = function(group, options) {
+    var inner = buildExpression(group.value, options);
+
+    var node = new mathMLTree.MathNode("mrow", inner);
+
+    return node;
+};
+
+groupTypes.text = function(group, options) {
+    var inner = buildExpression(group.value.body, options);
+
+    var node = new mathMLTree.MathNode("mtext", inner);
+
+    return node;
+};
+
+groupTypes.color = function(group, options) {
+    var inner = buildExpression(group.value.value, options);
+
+    var node = new mathMLTree.MathNode("mstyle", inner);
+
+    node.setAttribute("mathcolor", group.value.color);
+
+    return node;
+};
+
+groupTypes.supsub = function(group, options) {
+    var children = [buildGroup(group.value.base, options)];
+
+    if (group.value.sub) {
+        children.push(buildGroup(group.value.sub, options));
+    }
+
+    if (group.value.sup) {
+        children.push(buildGroup(group.value.sup, options));
+    }
+
+    var nodeType;
+    if (!group.value.sub) {
+        nodeType = "msup";
+    } else if (!group.value.sup) {
+        nodeType = "msub";
+    } else {
+        nodeType = "msubsup";
+    }
+
+    var node = new mathMLTree.MathNode(nodeType, children);
+
+    return node;
+};
+
+groupTypes.genfrac = function(group, options) {
+    var node = new mathMLTree.MathNode(
+        "mfrac",
+        [buildGroup(group.value.numer, options),
+            buildGroup(group.value.denom, options)]);
+
+    if (!group.value.hasBarLine) {
+        node.setAttribute("linethickness", "0px");
+    }
+
+    if (group.value.leftDelim != null || group.value.rightDelim != null) {
+        var withDelims = [];
+
+        if (group.value.leftDelim != null) {
+            var leftOp = new mathMLTree.MathNode(
+                "mo", [new mathMLTree.TextNode(group.value.leftDelim)]);
+
+            leftOp.setAttribute("fence", "true");
+
+            withDelims.push(leftOp);
+        }
+
+        withDelims.push(node);
+
+        if (group.value.rightDelim != null) {
+            var rightOp = new mathMLTree.MathNode(
+                "mo", [new mathMLTree.TextNode(group.value.rightDelim)]);
+
+            rightOp.setAttribute("fence", "true");
+
+            withDelims.push(rightOp);
+        }
+
+        var outerNode = new mathMLTree.MathNode("mrow", withDelims);
+
+        return outerNode;
+    }
+
+    return node;
+};
+
+groupTypes.array = function(group, options) {
+    return new mathMLTree.MathNode(
+        "mtable", group.value.body.map(function(row) {
+            return new mathMLTree.MathNode(
+                "mtr", row.map(function(cell) {
+                    return new mathMLTree.MathNode(
+                        "mtd", [buildGroup(cell, options)]);
+                }));
+        }));
+};
+
+groupTypes.sqrt = function(group, options) {
+    var node;
+    if (group.value.index) {
+        node = new mathMLTree.MathNode(
+            "mroot", [
+                buildGroup(group.value.body, options),
+                buildGroup(group.value.index, options)
+            ]);
+    } else {
+        node = new mathMLTree.MathNode(
+            "msqrt", [buildGroup(group.value.body, options)]);
+    }
+
+    return node;
+};
+
+groupTypes.leftright = function(group, options) {
+    var inner = buildExpression(group.value.body, options);
+
+    if (group.value.left !== ".") {
+        var leftNode = new mathMLTree.MathNode(
+            "mo", [makeText(group.value.left, group.mode)]);
+
+        leftNode.setAttribute("fence", "true");
+
+        inner.unshift(leftNode);
+    }
+
+    if (group.value.right !== ".") {
+        var rightNode = new mathMLTree.MathNode(
+            "mo", [makeText(group.value.right, group.mode)]);
+
+        rightNode.setAttribute("fence", "true");
+
+        inner.push(rightNode);
+    }
+
+    var outerNode = new mathMLTree.MathNode("mrow", inner);
+
+    return outerNode;
+};
+
+groupTypes.middle = function(group, options) {
+    var middleNode = new mathMLTree.MathNode(
+        "mo", [makeText(group.value.middle, group.mode)]);
+    middleNode.setAttribute("fence", "true");
+    return middleNode;
+};
+
+groupTypes.accent = function(group, options) {
+    var accentNode = new mathMLTree.MathNode(
+        "mo", [makeText(group.value.accent, group.mode)]);
+
+    var node = new mathMLTree.MathNode(
+        "mover",
+        [buildGroup(group.value.base, options),
+            accentNode]);
+
+    node.setAttribute("accent", "true");
+
+    return node;
+};
+
+groupTypes.spacing = function(group) {
+    var node;
+
+    if (group.value === "\\ " || group.value === "\\space" ||
+        group.value === " " || group.value === "~") {
+        node = new mathMLTree.MathNode(
+            "mtext", [new mathMLTree.TextNode("\u00a0")]);
+    } else {
+        node = new mathMLTree.MathNode("mspace");
+
+        node.setAttribute(
+            "width", buildCommon.spacingFunctions[group.value].size);
+    }
+
+    return node;
+};
+
+groupTypes.op = function(group, options) {
+    var node;
+
+    // TODO(emily): handle big operators using the `largeop` attribute
+
+    if (group.value.symbol) {
+        // This is a symbol. Just add the symbol.
+        node = new mathMLTree.MathNode(
+            "mo", [makeText(group.value.body, group.mode)]);
+    } else if (group.value.value) {
+        // This is an operator with children. Add them.
+        node = new mathMLTree.MathNode(
+            "mo", buildExpression(group.value.value, options));
+    } else {
+        // This is a text operator. Add all of the characters from the
+        // operator's name.
+        // TODO(emily): Add a space in the middle of some of these
+        // operators, like \limsup.
+        node = new mathMLTree.MathNode(
+            "mi", [new mathMLTree.TextNode(group.value.body.slice(1))]);
+    }
+
+    return node;
+};
+
+groupTypes.mod = function(group, options) {
+    var inner = [];
+
+    if (group.value.modType === "pod" || group.value.modType === "pmod") {
+        inner.push(new mathMLTree.MathNode(
+            "mo", [makeText("(", group.mode)]));
+    }
+    if (group.value.modType !== "pod") {
+        inner.push(new mathMLTree.MathNode(
+            "mo", [makeText("mod", group.mode)]));
+    }
+    if (group.value.value) {
+        var space = new mathMLTree.MathNode("mspace");
+        space.setAttribute("width", "0.333333em");
+        inner.push(space);
+        inner = inner.concat(buildExpression(group.value.value, options));
+    }
+    if (group.value.modType === "pod" || group.value.modType === "pmod") {
+        inner.push(new mathMLTree.MathNode(
+            "mo", [makeText(")", group.mode)]));
+    }
+
+    return new mathMLTree.MathNode("mo", inner);
+};
+
+groupTypes.katex = function(group) {
+    var node = new mathMLTree.MathNode(
+        "mtext", [new mathMLTree.TextNode("KaTeX")]);
+
+    return node;
+};
+
+groupTypes.font = function(group, options) {
+    var font = group.value.font;
+    return buildGroup(group.value.body, options.withFont(font));
+};
+
+groupTypes.delimsizing = function(group) {
+    var children = [];
+
+    if (group.value.value !== ".") {
+        children.push(makeText(group.value.value, group.mode));
+    }
+
+    var node = new mathMLTree.MathNode("mo", children);
+
+    if (group.value.mclass === "mopen" ||
+        group.value.mclass === "mclose") {
+        // Only some of the delimsizing functions act as fences, and they
+        // return "mopen" or "mclose" mclass.
+        node.setAttribute("fence", "true");
+    } else {
+        // Explicitly disable fencing if it's not a fence, to override the
+        // defaults.
+        node.setAttribute("fence", "false");
+    }
+
+    return node;
+};
+
+groupTypes.styling = function(group, options) {
+    var inner = buildExpression(group.value.value, options);
+
+    var node = new mathMLTree.MathNode("mstyle", inner);
+
+    var styleAttributes = {
+        "display": ["0", "true"],
+        "text": ["0", "false"],
+        "script": ["1", "false"],
+        "scriptscript": ["2", "false"]
+    };
+
+    var attr = styleAttributes[group.value.style];
+
+    node.setAttribute("scriptlevel", attr[0]);
+    node.setAttribute("displaystyle", attr[1]);
+
+    return node;
+};
+
+groupTypes.sizing = function(group, options) {
+    var inner = buildExpression(group.value.value, options);
+
+    var node = new mathMLTree.MathNode("mstyle", inner);
+
+    // TODO(emily): This doesn't produce the correct size for nested size
+    // changes, because we don't keep state of what style we're currently
+    // in, so we can't reset the size to normal before changing it.  Now
+    // that we're passing an options parameter we should be able to fix
+    // this.
+    node.setAttribute(
+        "mathsize", buildCommon.sizingMultiplier[group.value.size] + "em");
+
+    return node;
+};
+
+groupTypes.overline = function(group, options) {
+    var operator = new mathMLTree.MathNode(
+        "mo", [new mathMLTree.TextNode("\u203e")]);
+    operator.setAttribute("stretchy", "true");
+
+    var node = new mathMLTree.MathNode(
+        "mover",
+        [buildGroup(group.value.body, options),
+            operator]);
+    node.setAttribute("accent", "true");
+
+    return node;
+};
+
+groupTypes.underline = function(group, options) {
+    var operator = new mathMLTree.MathNode(
+        "mo", [new mathMLTree.TextNode("\u203e")]);
+    operator.setAttribute("stretchy", "true");
+
+    var node = new mathMLTree.MathNode(
+        "munder",
+        [buildGroup(group.value.body, options),
+            operator]);
+    node.setAttribute("accentunder", "true");
+
+    return node;
+};
+
+groupTypes.rule = function(group) {
+    // TODO(emily): Figure out if there's an actual way to draw black boxes
+    // in MathML.
+    var node = new mathMLTree.MathNode("mrow");
+
+    return node;
+};
+
+groupTypes.kern = function(group) {
+    // TODO(kevin): Figure out if there's a way to add space in MathML
+    var node = new mathMLTree.MathNode("mrow");
+
+    return node;
+};
+
+groupTypes.llap = function(group, options) {
+    var node = new mathMLTree.MathNode(
+        "mpadded", [buildGroup(group.value.body, options)]);
+
+    node.setAttribute("lspace", "-1width");
+    node.setAttribute("width", "0px");
+
+    return node;
+};
+
+groupTypes.rlap = function(group, options) {
+    var node = new mathMLTree.MathNode(
+        "mpadded", [buildGroup(group.value.body, options)]);
+
+    node.setAttribute("width", "0px");
+
+    return node;
+};
+
+groupTypes.phantom = function(group, options) {
+    var inner = buildExpression(group.value.value, options);
+    return new mathMLTree.MathNode("mphantom", inner);
+};
+
+groupTypes.mclass = function(group, options) {
+    var inner = buildExpression(group.value.value, options);
+    return new mathMLTree.MathNode("mstyle", inner);
+};
+
+/**
+ * Takes a list of nodes, builds them, and returns a list of the generated
+ * MathML nodes. A little simpler than the HTML version because we don't do any
+ * previous-node handling.
+ */
+var buildExpression = function(expression, options) {
+    var groups = [];
+    for (var i = 0; i < expression.length; i++) {
+        var group = expression[i];
+        groups.push(buildGroup(group, options));
+    }
+    return groups;
+};
+
+/**
+ * Takes a group from the parser and calls the appropriate groupTypes function
+ * on it to produce a MathML node.
+ */
+var buildGroup = function(group, options) {
+    if (!group) {
+        return new mathMLTree.MathNode("mrow");
+    }
+
+    if (groupTypes[group.type]) {
+        // Call the groupTypes function
+        return groupTypes[group.type](group, options);
+    } else {
+        throw new ParseError(
+            "Got group of unknown type: '" + group.type + "'");
+    }
+};
+
+/**
+ * Takes a full parse tree and settings and builds a MathML representation of
+ * it. In particular, we put the elements from building the parse tree into a
+ * <semantics> tag so we can also include that TeX source as an annotation.
+ *
+ * Note that we actually return a domTree element with a `<math>` inside it so
+ * we can do appropriate styling.
+ */
+var buildMathML = function(tree, texExpression, options) {
+    var expression = buildExpression(tree, options);
+
+    // Wrap up the expression in an mrow so it is presented in the semantics
+    // tag correctly.
+    var wrapper = new mathMLTree.MathNode("mrow", expression);
+
+    // Build a TeX annotation of the source
+    var annotation = new mathMLTree.MathNode(
+        "annotation", [new mathMLTree.TextNode(texExpression)]);
+
+    annotation.setAttribute("encoding", "application/x-tex");
+
+    var semantics = new mathMLTree.MathNode(
+        "semantics", [wrapper, annotation]);
+
+    var math = new mathMLTree.MathNode("math", [semantics]);
+
+    // You can't style <math> nodes, so we wrap the node in a span.
+    return makeSpan(["katex-mathml"], [math]);
+};
+
+module.exports = buildMathML;
+
+},{"./ParseError":6,"./buildCommon":10,"./fontMetrics":17,"./mathMLTree":20,"./symbols":23,"./utils":25}],13:[function(require,module,exports){
+var buildHTML = require("./buildHTML");
+var buildMathML = require("./buildMathML");
+var buildCommon = require("./buildCommon");
+var Options = require("./Options");
+var Settings = require("./Settings");
+var Style = require("./Style");
+
+var makeSpan = buildCommon.makeSpan;
+
+var buildTree = function(tree, expression, settings) {
+    settings = settings || new Settings({});
+
+    var startStyle = Style.TEXT;
+    if (settings.displayMode) {
+        startStyle = Style.DISPLAY;
+    }
+
+    // Setup the default options
+    var options = new Options({
+        style: startStyle,
+        size: "size5"
+    });
+
+    // `buildHTML` sometimes messes with the parse tree (like turning bins ->
+    // ords), so we build the MathML version first.
+    var mathMLNode = buildMathML(tree, expression, options);
+    var htmlNode = buildHTML(tree, options);
+
+    var katexNode = makeSpan(["katex"], [
+        mathMLNode, htmlNode
+    ]);
+
+    if (settings.displayMode) {
+        return makeSpan(["katex-display"], [katexNode]);
+    } else {
+        return katexNode;
+    }
+};
+
+module.exports = buildTree;
+
+},{"./Options":5,"./Settings":8,"./Style":9,"./buildCommon":10,"./buildHTML":11,"./buildMathML":12}],14:[function(require,module,exports){
+/**
+ * This file deals with creating delimiters of various sizes. The TeXbook
+ * discusses these routines on page 441-442, in the "Another subroutine sets box
+ * x to a specified variable delimiter" paragraph.
+ *
+ * There are three main routines here. `makeSmallDelim` makes a delimiter in the
+ * normal font, but in either text, script, or scriptscript style.
+ * `makeLargeDelim` makes a delimiter in textstyle, but in one of the Size1,
+ * Size2, Size3, or Size4 fonts. `makeStackedDelim` makes a delimiter out of
+ * smaller pieces that are stacked on top of one another.
+ *
+ * The functions take a parameter `center`, which determines if the delimiter
+ * should be centered around the axis.
+ *
+ * Then, there are three exposed functions. `sizedDelim` makes a delimiter in
+ * one of the given sizes. This is used for things like `\bigl`.
+ * `customSizedDelim` makes a delimiter with a given total height+depth. It is
+ * called in places like `\sqrt`. `leftRightDelim` makes an appropriate
+ * delimiter which surrounds an expression of a given height an depth. It is
+ * used in `\left` and `\right`.
+ */
+
+var ParseError = require("./ParseError");
+var Style = require("./Style");
+
+var buildCommon = require("./buildCommon");
+var fontMetrics = require("./fontMetrics");
+var symbols = require("./symbols");
+var utils = require("./utils");
+
+var makeSpan = buildCommon.makeSpan;
+
+/**
+ * Get the metrics for a given symbol and font, after transformation (i.e.
+ * after following replacement from symbols.js)
+ */
+var getMetrics = function(symbol, font) {
+    if (symbols.math[symbol] && symbols.math[symbol].replace) {
+        return fontMetrics.getCharacterMetrics(
+            symbols.math[symbol].replace, font);
+    } else {
+        return fontMetrics.getCharacterMetrics(
+            symbol, font);
+    }
+};
+
+/**
+ * Builds a symbol in the given font size (note size is an integer)
+ */
+var mathrmSize = function(value, size, mode, options) {
+    return buildCommon.makeSymbol(value, "Size" + size + "-Regular",
+        mode, options);
+};
+
+/**
+ * Puts a delimiter span in a given style, and adds appropriate height, depth,
+ * and maxFontSizes.
+ */
+var styleWrap = function(delim, toStyle, options, classes) {
+    classes = classes || [];
+    var span = makeSpan(
+        classes.concat(["style-wrap", options.style.reset(), toStyle.cls()]),
+        [delim], options);
+
+    var multiplier = toStyle.sizeMultiplier / options.style.sizeMultiplier;
+
+    span.height *= multiplier;
+    span.depth *= multiplier;
+    span.maxFontSize = toStyle.sizeMultiplier;
+
+    return span;
+};
+
+/**
+ * Makes a small delimiter. This is a delimiter that comes in the Main-Regular
+ * font, but is restyled to either be in textstyle, scriptstyle, or
+ * scriptscriptstyle.
+ */
+var makeSmallDelim = function(delim, style, center, options, mode, classes) {
+    var text = buildCommon.makeSymbol(delim, "Main-Regular", mode, options);
+
+    var span = styleWrap(text, style, options, classes);
+
+    if (center) {
+        var shift =
+            (1 - options.style.sizeMultiplier / style.sizeMultiplier) *
+            options.style.metrics.axisHeight;
+
+        span.style.top = shift + "em";
+        span.height -= shift;
+        span.depth += shift;
+    }
+
+    return span;
+};
+
+/**
+ * Makes a large delimiter. This is a delimiter that comes in the Size1, Size2,
+ * Size3, or Size4 fonts. It is always rendered in textstyle.
+ */
+var makeLargeDelim = function(delim, size, center, options, mode, classes) {
+    var inner = mathrmSize(delim, size, mode, options);
+
+    var span = styleWrap(
+        makeSpan(["delimsizing", "size" + size], [inner], options),
+        Style.TEXT, options, classes);
+
+    if (center) {
+        var shift = (1 - options.style.sizeMultiplier) *
+            options.style.metrics.axisHeight;
+
+        span.style.top = shift + "em";
+        span.height -= shift;
+        span.depth += shift;
+    }
+
+    return span;
+};
+
+/**
+ * Make an inner span with the given offset and in the given font. This is used
+ * in `makeStackedDelim` to make the stacking pieces for the delimiter.
+ */
+var makeInner = function(symbol, font, mode) {
+    var sizeClass;
+    // Apply the correct CSS class to choose the right font.
+    if (font === "Size1-Regular") {
+        sizeClass = "delim-size1";
+    } else if (font === "Size4-Regular") {
+        sizeClass = "delim-size4";
+    }
+
+    var inner = makeSpan(
+        ["delimsizinginner", sizeClass],
+        [makeSpan([], [buildCommon.makeSymbol(symbol, font, mode)])]);
+
+    // Since this will be passed into `makeVList` in the end, wrap the element
+    // in the appropriate tag that VList uses.
+    return {type: "elem", elem: inner};
+};
+
+/**
+ * Make a stacked delimiter out of a given delimiter, with the total height at
+ * least `heightTotal`. This routine is mentioned on page 442 of the TeXbook.
+ */
+var makeStackedDelim = function(delim, heightTotal, center, options, mode,
+                                classes) {
+    // There are four parts, the top, an optional middle, a repeated part, and a
+    // bottom.
+    var top;
+    var middle;
+    var repeat;
+    var bottom;
+    top = repeat = bottom = delim;
+    middle = null;
+    // Also keep track of what font the delimiters are in
+    var font = "Size1-Regular";
+
+    // We set the parts and font based on the symbol. Note that we use
+    // '\u23d0' instead of '|' and '\u2016' instead of '\\|' for the
+    // repeats of the arrows
+    if (delim === "\\uparrow") {
+        repeat = bottom = "\u23d0";
+    } else if (delim === "\\Uparrow") {
+        repeat = bottom = "\u2016";
+    } else if (delim === "\\downarrow") {
+        top = repeat = "\u23d0";
+    } else if (delim === "\\Downarrow") {
+        top = repeat = "\u2016";
+    } else if (delim === "\\updownarrow") {
+        top = "\\uparrow";
+        repeat = "\u23d0";
+        bottom = "\\downarrow";
+    } else if (delim === "\\Updownarrow") {
+        top = "\\Uparrow";
+        repeat = "\u2016";
+        bottom = "\\Downarrow";
+    } else if (delim === "[" || delim === "\\lbrack") {
+        top = "\u23a1";
+        repeat = "\u23a2";
+        bottom = "\u23a3";
+        font = "Size4-Regular";
+    } else if (delim === "]" || delim === "\\rbrack") {
+        top = "\u23a4";
+        repeat = "\u23a5";
+        bottom = "\u23a6";
+        font = "Size4-Regular";
+    } else if (delim === "\\lfloor") {
+        repeat = top = "\u23a2";
+        bottom = "\u23a3";
+        font = "Size4-Regular";
+    } else if (delim === "\\lceil") {
+        top = "\u23a1";
+        repeat = bottom = "\u23a2";
+        font = "Size4-Regular";
+    } else if (delim === "\\rfloor") {
+        repeat = top = "\u23a5";
+        bottom = "\u23a6";
+        font = "Size4-Regular";
+    } else if (delim === "\\rceil") {
+        top = "\u23a4";
+        repeat = bottom = "\u23a5";
+        font = "Size4-Regular";
+    } else if (delim === "(") {
+        top = "\u239b";
+        repeat = "\u239c";
+        bottom = "\u239d";
+        font = "Size4-Regular";
+    } else if (delim === ")") {
+        top = "\u239e";
+        repeat = "\u239f";
+        bottom = "\u23a0";
+        font = "Size4-Regular";
+    } else if (delim === "\\{" || delim === "\\lbrace") {
+        top = "\u23a7";
+        middle = "\u23a8";
+        bottom = "\u23a9";
+        repeat = "\u23aa";
+        font = "Size4-Regular";
+    } else if (delim === "\\}" || delim === "\\rbrace") {
+        top = "\u23ab";
+        middle = "\u23ac";
+        bottom = "\u23ad";
+        repeat = "\u23aa";
+        font = "Size4-Regular";
+    } else if (delim === "\\lgroup") {
+        top = "\u23a7";
+        bottom = "\u23a9";
+        repeat = "\u23aa";
+        font = "Size4-Regular";
+    } else if (delim === "\\rgroup") {
+        top = "\u23ab";
+        bottom = "\u23ad";
+        repeat = "\u23aa";
+        font = "Size4-Regular";
+    } else if (delim === "\\lmoustache") {
+        top = "\u23a7";
+        bottom = "\u23ad";
+        repeat = "\u23aa";
+        font = "Size4-Regular";
+    } else if (delim === "\\rmoustache") {
+        top = "\u23ab";
+        bottom = "\u23a9";
+        repeat = "\u23aa";
+        font = "Size4-Regular";
+    } else if (delim === "\\surd") {
+        top = "\ue001";
+        bottom = "\u23b7";
+        repeat = "\ue000";
+        font = "Size4-Regular";
+    }
+
+    // Get the metrics of the four sections
+    var topMetrics = getMetrics(top, font);
+    var topHeightTotal = topMetrics.height + topMetrics.depth;
+    var repeatMetrics = getMetrics(repeat, font);
+    var repeatHeightTotal = repeatMetrics.height + repeatMetrics.depth;
+    var bottomMetrics = getMetrics(bottom, font);
+    var bottomHeightTotal = bottomMetrics.height + bottomMetrics.depth;
+    var middleHeightTotal = 0;
+    var middleFactor = 1;
+    if (middle !== null) {
+        var middleMetrics = getMetrics(middle, font);
+        middleHeightTotal = middleMetrics.height + middleMetrics.depth;
+        middleFactor = 2; // repeat symmetrically above and below middle
+    }
+
+    // Calcuate the minimal height that the delimiter can have.
+    // It is at least the size of the top, bottom, and optional middle combined.
+    var minHeight = topHeightTotal + bottomHeightTotal + middleHeightTotal;
+
+    // Compute the number of copies of the repeat symbol we will need
+    var repeatCount = Math.ceil(
+        (heightTotal - minHeight) / (middleFactor * repeatHeightTotal));
+
+    // Compute the total height of the delimiter including all the symbols
+    var realHeightTotal =
+        minHeight + repeatCount * middleFactor * repeatHeightTotal;
+
+    // The center of the delimiter is placed at the center of the axis. Note
+    // that in this context, "center" means that the delimiter should be
+    // centered around the axis in the current style, while normally it is
+    // centered around the axis in textstyle.
+    var axisHeight = options.style.metrics.axisHeight;
+    if (center) {
+        axisHeight *= options.style.sizeMultiplier;
+    }
+    // Calculate the depth
+    var depth = realHeightTotal / 2 - axisHeight;
+
+    // Now, we start building the pieces that will go into the vlist
+
+    // Keep a list of the inner pieces
+    var inners = [];
+
+    // Add the bottom symbol
+    inners.push(makeInner(bottom, font, mode));
+
+    var i;
+    if (middle === null) {
+        // Add that many symbols
+        for (i = 0; i < repeatCount; i++) {
+            inners.push(makeInner(repeat, font, mode));
+        }
+    } else {
+        // When there is a middle bit, we need the middle part and two repeated
+        // sections
+        for (i = 0; i < repeatCount; i++) {
+            inners.push(makeInner(repeat, font, mode));
+        }
+        inners.push(makeInner(middle, font, mode));
+        for (i = 0; i < repeatCount; i++) {
+            inners.push(makeInner(repeat, font, mode));
+        }
+    }
+
+    // Add the top symbol
+    inners.push(makeInner(top, font, mode));
+
+    // Finally, build the vlist
+    var inner = buildCommon.makeVList(inners, "bottom", depth, options);
+
+    return styleWrap(
+        makeSpan(["delimsizing", "mult"], [inner], options),
+        Style.TEXT, options, classes);
+};
+
+// There are three kinds of delimiters, delimiters that stack when they become
+// too large
+var stackLargeDelimiters = [
+    "(", ")", "[", "\\lbrack", "]", "\\rbrack",
+    "\\{", "\\lbrace", "\\}", "\\rbrace",
+    "\\lfloor", "\\rfloor", "\\lceil", "\\rceil",
+    "\\surd"
+];
+
+// delimiters that always stack
+var stackAlwaysDelimiters = [
+    "\\uparrow", "\\downarrow", "\\updownarrow",
+    "\\Uparrow", "\\Downarrow", "\\Updownarrow",
+    "|", "\\|", "\\vert", "\\Vert",
+    "\\lvert", "\\rvert", "\\lVert", "\\rVert",
+    "\\lgroup", "\\rgroup", "\\lmoustache", "\\rmoustache"
+];
+
+// and delimiters that never stack
+var stackNeverDelimiters = [
+    "<", ">", "\\langle", "\\rangle", "/", "\\backslash", "\\lt", "\\gt"
+];
+
+// Metrics of the different sizes. Found by looking at TeX's output of
+// $\bigl| // \Bigl| \biggl| \Biggl| \showlists$
+// Used to create stacked delimiters of appropriate sizes in makeSizedDelim.
+var sizeToMaxHeight = [0, 1.2, 1.8, 2.4, 3.0];
+
+/**
+ * Used to create a delimiter of a specific size, where `size` is 1, 2, 3, or 4.
+ */
+var makeSizedDelim = function(delim, size, options, mode, classes) {
+    // < and > turn into \langle and \rangle in delimiters
+    if (delim === "<" || delim === "\\lt") {
+        delim = "\\langle";
+    } else if (delim === ">" || delim === "\\gt") {
+        delim = "\\rangle";
+    }
+
+    // Sized delimiters are never centered.
+    if (utils.contains(stackLargeDelimiters, delim) ||
+        utils.contains(stackNeverDelimiters, delim)) {
+        return makeLargeDelim(delim, size, false, options, mode, classes);
+    } else if (utils.contains(stackAlwaysDelimiters, delim)) {
+        return makeStackedDelim(
+            delim, sizeToMaxHeight[size], false, options, mode, classes);
+    } else {
+        throw new ParseError("Illegal delimiter: '" + delim + "'");
+    }
+};
+
+/**
+ * There are three different sequences of delimiter sizes that the delimiters
+ * follow depending on the kind of delimiter. This is used when creating custom
+ * sized delimiters to decide whether to create a small, large, or stacked
+ * delimiter.
+ *
+ * In real TeX, these sequences aren't explicitly defined, but are instead
+ * defined inside the font metrics. Since there are only three sequences that
+ * are possible for the delimiters that TeX defines, it is easier to just encode
+ * them explicitly here.
+ */
+
+// Delimiters that never stack try small delimiters and large delimiters only
+var stackNeverDelimiterSequence = [
+    {type: "small", style: Style.SCRIPTSCRIPT},
+    {type: "small", style: Style.SCRIPT},
+    {type: "small", style: Style.TEXT},
+    {type: "large", size: 1},
+    {type: "large", size: 2},
+    {type: "large", size: 3},
+    {type: "large", size: 4}
+];
+
+// Delimiters that always stack try the small delimiters first, then stack
+var stackAlwaysDelimiterSequence = [
+    {type: "small", style: Style.SCRIPTSCRIPT},
+    {type: "small", style: Style.SCRIPT},
+    {type: "small", style: Style.TEXT},
+    {type: "stack"}
+];
+
+// Delimiters that stack when large try the small and then large delimiters, and
+// stack afterwards
+var stackLargeDelimiterSequence = [
+    {type: "small", style: Style.SCRIPTSCRIPT},
+    {type: "small", style: Style.SCRIPT},
+    {type: "small", style: Style.TEXT},
+    {type: "large", size: 1},
+    {type: "large", size: 2},
+    {type: "large", size: 3},
+    {type: "large", size: 4},
+    {type: "stack"}
+];
+
+/**
+ * Get the font used in a delimiter based on what kind of delimiter it is.
+ */
+var delimTypeToFont = function(type) {
+    if (type.type === "small") {
+        return "Main-Regular";
+    } else if (type.type === "large") {
+        return "Size" + type.size + "-Regular";
+    } else if (type.type === "stack") {
+        return "Size4-Regular";
+    }
+};
+
+/**
+ * Traverse a sequence of types of delimiters to decide what kind of delimiter
+ * should be used to create a delimiter of the given height+depth.
+ */
+var traverseSequence = function(delim, height, sequence, options) {
+    // Here, we choose the index we should start at in the sequences. In smaller
+    // sizes (which correspond to larger numbers in style.size) we start earlier
+    // in the sequence. Thus, scriptscript starts at index 3-3=0, script starts
+    // at index 3-2=1, text starts at 3-1=2, and display starts at min(2,3-0)=2
+    var start = Math.min(2, 3 - options.style.size);
+    for (var i = start; i < sequence.length; i++) {
+        if (sequence[i].type === "stack") {
+            // This is always the last delimiter, so we just break the loop now.
+            break;
+        }
+
+        var metrics = getMetrics(delim, delimTypeToFont(sequence[i]));
+        var heightDepth = metrics.height + metrics.depth;
+
+        // Small delimiters are scaled down versions of the same font, so we
+        // account for the style change size.
+
+        if (sequence[i].type === "small") {
+            heightDepth *= sequence[i].style.sizeMultiplier;
+        }
+
+        // Check if the delimiter at this size works for the given height.
+        if (heightDepth > height) {
+            return sequence[i];
+        }
+    }
+
+    // If we reached the end of the sequence, return the last sequence element.
+    return sequence[sequence.length - 1];
+};
+
+/**
+ * Make a delimiter of a given height+depth, with optional centering. Here, we
+ * traverse the sequences, and create a delimiter that the sequence tells us to.
+ */
+var makeCustomSizedDelim = function(delim, height, center, options, mode,
+                                    classes) {
+    if (delim === "<" || delim === "\\lt") {
+        delim = "\\langle";
+    } else if (delim === ">" || delim === "\\gt") {
+        delim = "\\rangle";
+    }
+
+    // Decide what sequence to use
+    var sequence;
+    if (utils.contains(stackNeverDelimiters, delim)) {
+        sequence = stackNeverDelimiterSequence;
+    } else if (utils.contains(stackLargeDelimiters, delim)) {
+        sequence = stackLargeDelimiterSequence;
+    } else {
+        sequence = stackAlwaysDelimiterSequence;
+    }
+
+    // Look through the sequence
+    var delimType = traverseSequence(delim, height, sequence, options);
+
+    // Depending on the sequence element we decided on, call the appropriate
+    // function.
+    if (delimType.type === "small") {
+        return makeSmallDelim(delim, delimType.style, center, options, mode,
+                              classes);
+    } else if (delimType.type === "large") {
+        return makeLargeDelim(delim, delimType.size, center, options, mode,
+                              classes);
+    } else if (delimType.type === "stack") {
+        return makeStackedDelim(delim, height, center, options, mode, classes);
+    }
+};
+
+/**
+ * Make a delimiter for use with `\left` and `\right`, given a height and depth
+ * of an expression that the delimiters surround.
+ */
+var makeLeftRightDelim = function(delim, height, depth, options, mode,
+                                  classes) {
+    // We always center \left/\right delimiters, so the axis is always shifted
+    var axisHeight =
+        options.style.metrics.axisHeight * options.style.sizeMultiplier;
+
+    // Taken from TeX source, tex.web, function make_left_right
+    var delimiterFactor = 901;
+    var delimiterExtend = 5.0 / fontMetrics.metrics.ptPerEm;
+
+    var maxDistFromAxis = Math.max(
+        height - axisHeight, depth + axisHeight);
+
+    var totalHeight = Math.max(
+        // In real TeX, calculations are done using integral values which are
+        // 65536 per pt, or 655360 per em. So, the division here truncates in
+        // TeX but doesn't here, producing different results. If we wanted to
+        // exactly match TeX's calculation, we could do
+        //   Math.floor(655360 * maxDistFromAxis / 500) *
+        //    delimiterFactor / 655360
+        // (To see the difference, compare
+        //    x^{x^{\left(\rule{0.1em}{0.68em}\right)}}
+        // in TeX and KaTeX)
+        maxDistFromAxis / 500 * delimiterFactor,
+        2 * maxDistFromAxis - delimiterExtend);
+
+    // Finally, we defer to `makeCustomSizedDelim` with our calculated total
+    // height
+    return makeCustomSizedDelim(delim, totalHeight, true, options, mode,
+                                classes);
+};
+
+module.exports = {
+    sizedDelim: makeSizedDelim,
+    customSizedDelim: makeCustomSizedDelim,
+    leftRightDelim: makeLeftRightDelim
+};
+
+},{"./ParseError":6,"./Style":9,"./buildCommon":10,"./fontMetrics":17,"./symbols":23,"./utils":25}],15:[function(require,module,exports){
+/**
+ * These objects store the data about the DOM nodes we create, as well as some
+ * extra data. They can then be transformed into real DOM nodes with the
+ * `toNode` function or HTML markup using `toMarkup`. They are useful for both
+ * storing extra properties on the nodes, as well as providing a way to easily
+ * work with the DOM.
+ *
+ * Similar functions for working with MathML nodes exist in mathMLTree.js.
+ */
+var unicodeRegexes = require("./unicodeRegexes");
+var utils = require("./utils");
+
+/**
+ * Create an HTML className based on a list of classes. In addition to joining
+ * with spaces, we also remove null or empty classes.
+ */
+var createClass = function(classes) {
+    classes = classes.slice();
+    for (var i = classes.length - 1; i >= 0; i--) {
+        if (!classes[i]) {
+            classes.splice(i, 1);
+        }
+    }
+
+    return classes.join(" ");
+};
+
+/**
+ * This node represents a span node, with a className, a list of children, and
+ * an inline style. It also contains information about its height, depth, and
+ * maxFontSize.
+ */
+function span(classes, children, options) {
+    this.classes = classes || [];
+    this.children = children || [];
+    this.height = 0;
+    this.depth = 0;
+    this.maxFontSize = 0;
+    this.style = {};
+    this.attributes = {};
+    if (options) {
+        if (options.style.isTight()) {
+            this.classes.push("mtight");
+        }
+        if (options.getColor()) {
+            this.style.color = options.getColor();
+        }
+    }
+}
+
+/**
+ * Sets an arbitrary attribute on the span. Warning: use this wisely. Not all
+ * browsers support attributes the same, and having too many custom attributes
+ * is probably bad.
+ */
+span.prototype.setAttribute = function(attribute, value) {
+    this.attributes[attribute] = value;
+};
+
+span.prototype.tryCombine = function(sibling) {
+    return false;
+};
+
+/**
+ * Convert the span into an HTML node
+ */
+span.prototype.toNode = function() {
+    var span = document.createElement("span");
+
+    // Apply the class
+    span.className = createClass(this.classes);
+
+    // Apply inline styles
+    for (var style in this.style) {
+        if (Object.prototype.hasOwnProperty.call(this.style, style)) {
+            span.style[style] = this.style[style];
+        }
+    }
+
+    // Apply attributes
+    for (var attr in this.attributes) {
+        if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
+            span.setAttribute(attr, this.attributes[attr]);
+        }
+    }
+
+    // Append the children, also as HTML nodes
+    for (var i = 0; i < this.children.length; i++) {
+        span.appendChild(this.children[i].toNode());
+    }
+
+    return span;
+};
+
+/**
+ * Convert the span into an HTML markup string
+ */
+span.prototype.toMarkup = function() {
+    var markup = "<span";
+
+    // Add the class
+    if (this.classes.length) {
+        markup += " class=\"";
+        markup += utils.escape(createClass(this.classes));
+        markup += "\"";
+    }
+
+    var styles = "";
+
+    // Add the styles, after hyphenation
+    for (var style in this.style) {
+        if (this.style.hasOwnProperty(style)) {
+            styles += utils.hyphenate(style) + ":" + this.style[style] + ";";
+        }
+    }
+
+    if (styles) {
+        markup += " style=\"" + utils.escape(styles) + "\"";
+    }
+
+    // Add the attributes
+    for (var attr in this.attributes) {
+        if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
+            markup += " " + attr + "=\"";
+            markup += utils.escape(this.attributes[attr]);
+            markup += "\"";
+        }
+    }
+
+    markup += ">";
+
+    // Add the markup of the children, also as markup
+    for (var i = 0; i < this.children.length; i++) {
+        markup += this.children[i].toMarkup();
+    }
+
+    markup += "</span>";
+
+    return markup;
+};
+
+/**
+ * This node represents a document fragment, which contains elements, but when
+ * placed into the DOM doesn't have any representation itself. Thus, it only
+ * contains children and doesn't have any HTML properties. It also keeps track
+ * of a height, depth, and maxFontSize.
+ */
+function documentFragment(children) {
+    this.children = children || [];
+    this.height = 0;
+    this.depth = 0;
+    this.maxFontSize = 0;
+}
+
+/**
+ * Convert the fragment into a node
+ */
+documentFragment.prototype.toNode = function() {
+    // Create a fragment
+    var frag = document.createDocumentFragment();
+
+    // Append the children
+    for (var i = 0; i < this.children.length; i++) {
+        frag.appendChild(this.children[i].toNode());
+    }
+
+    return frag;
+};
+
+/**
+ * Convert the fragment into HTML markup
+ */
+documentFragment.prototype.toMarkup = function() {
+    var markup = "";
+
+    // Simply concatenate the markup for the children together
+    for (var i = 0; i < this.children.length; i++) {
+        markup += this.children[i].toMarkup();
+    }
+
+    return markup;
+};
+
+var iCombinations = {
+    'î': '\u0131\u0302',
+    'ï': '\u0131\u0308',
+    'í': '\u0131\u0301',
+    // 'ī': '\u0131\u0304', // enable when we add Extended Latin
+    'ì': '\u0131\u0300'
+};
+
+/**
+ * A symbol node contains information about a single symbol. It either renders
+ * to a single text node, or a span with a single text node in it, depending on
+ * whether it has CSS classes, styles, or needs italic correction.
+ */
+function symbolNode(value, height, depth, italic, skew, classes, style) {
+    this.value = value || "";
+    this.height = height || 0;
+    this.depth = depth || 0;
+    this.italic = italic || 0;
+    this.skew = skew || 0;
+    this.classes = classes || [];
+    this.style = style || {};
+    this.maxFontSize = 0;
+
+    // Mark CJK characters with specific classes so that we can specify which
+    // fonts to use.  This allows us to render these characters with a serif
+    // font in situations where the browser would either default to a sans serif
+    // or render a placeholder character.
+    if (unicodeRegexes.cjkRegex.test(value)) {
+        // I couldn't find any fonts that contained Hangul as well as all of
+        // the other characters we wanted to test there for it gets its own
+        // CSS class.
+        if (unicodeRegexes.hangulRegex.test(value)) {
+            this.classes.push('hangul_fallback');
+        } else {
+            this.classes.push('cjk_fallback');
+        }
+    }
+
+    if (/[îïíì]/.test(this.value)) {    // add ī when we add Extended Latin
+        this.value = iCombinations[this.value];
+    }
+}
+
+symbolNode.prototype.tryCombine = function(sibling) {
+    if (!sibling
+        || !(sibling instanceof symbolNode)
+        || this.italic > 0
+        || createClass(this.classes) !== createClass(sibling.classes)
+        || this.skew !== sibling.skew
+        || this.maxFontSize !== sibling.maxFontSize) {
+        return false;
+    }
+    for (var style in this.style) {
+        if (this.style.hasOwnProperty(style)
+            && this.style[style] !== sibling.style[style]) {
+            return false;
+        }
+    }
+    for (style in sibling.style) {
+        if (sibling.style.hasOwnProperty(style)
+            && this.style[style] !== sibling.style[style]) {
+            return false;
+        }
+    }
+    this.value += sibling.value;
+    this.height = Math.max(this.height, sibling.height);
+    this.depth = Math.max(this.depth, sibling.depth);
+    this.italic = sibling.italic;
+    return true;
+};
+
+/**
+ * Creates a text node or span from a symbol node. Note that a span is only
+ * created if it is needed.
+ */
+symbolNode.prototype.toNode = function() {
+    var node = document.createTextNode(this.value);
+    var span = null;
+
+    if (this.italic > 0) {
+        span = document.createElement("span");
+        span.style.marginRight = this.italic + "em";
+    }
+
+    if (this.classes.length > 0) {
+        span = span || document.createElement("span");
+        span.className = createClass(this.classes);
+    }
+
+    for (var style in this.style) {
+        if (this.style.hasOwnProperty(style)) {
+            span = span || document.createElement("span");
+            span.style[style] = this.style[style];
+        }
+    }
+
+    if (span) {
+        span.appendChild(node);
+        return span;
+    } else {
+        return node;
+    }
+};
+
+/**
+ * Creates markup for a symbol node.
+ */
+symbolNode.prototype.toMarkup = function() {
+    // TODO(alpert): More duplication than I'd like from
+    // span.prototype.toMarkup and symbolNode.prototype.toNode...
+    var needsSpan = false;
+
+    var markup = "<span";
+
+    if (this.classes.length) {
+        needsSpan = true;
+        markup += " class=\"";
+        markup += utils.escape(createClass(this.classes));
+        markup += "\"";
+    }
+
+    var styles = "";
+
+    if (this.italic > 0) {
+        styles += "margin-right:" + this.italic + "em;";
+    }
+    for (var style in this.style) {
+        if (this.style.hasOwnProperty(style)) {
+            styles += utils.hyphenate(style) + ":" + this.style[style] + ";";
+        }
+    }
+
+    if (styles) {
+        needsSpan = true;
+        markup += " style=\"" + utils.escape(styles) + "\"";
+    }
+
+    var escaped = utils.escape(this.value);
+    if (needsSpan) {
+        markup += ">";
+        markup += escaped;
+        markup += "</span>";
+        return markup;
+    } else {
+        return escaped;
+    }
+};
+
+module.exports = {
+    span: span,
+    documentFragment: documentFragment,
+    symbolNode: symbolNode
+};
+
+},{"./unicodeRegexes":24,"./utils":25}],16:[function(require,module,exports){
+/* eslint no-constant-condition:0 */
+var parseData = require("./parseData");
+var ParseError = require("./ParseError");
+var Style = require("./Style");
+
+var ParseNode = parseData.ParseNode;
+
+/**
+ * Parse the body of the environment, with rows delimited by \\ and
+ * columns delimited by &, and create a nested list in row-major order
+ * with one group per cell.
+ */
+function parseArray(parser, result) {
+    var row = [];
+    var body = [row];
+    var rowGaps = [];
+    while (true) {
+        var cell = parser.parseExpression(false, null);
+        row.push(new ParseNode("ordgroup", cell, parser.mode));
+        var next = parser.nextToken.text;
+        if (next === "&") {
+            parser.consume();
+        } else if (next === "\\end") {
+            break;
+        } else if (next === "\\\\" || next === "\\cr") {
+            var cr = parser.parseFunction();
+            rowGaps.push(cr.value.size);
+            row = [];
+            body.push(row);
+        } else {
+            throw new ParseError("Expected & or \\\\ or \\end",
+                                 parser.nextToken);
+        }
+    }
+    result.body = body;
+    result.rowGaps = rowGaps;
+    return new ParseNode(result.type, result, parser.mode);
+}
+
+/*
+ * An environment definition is very similar to a function definition:
+ * it is declared with a name or a list of names, a set of properties
+ * and a handler containing the actual implementation.
+ *
+ * The properties include:
+ *  - numArgs: The number of arguments after the \begin{name} function.
+ *  - argTypes: (optional) Just like for a function
+ *  - allowedInText: (optional) Whether or not the environment is allowed inside
+ *                   text mode (default false) (not enforced yet)
+ *  - numOptionalArgs: (optional) Just like for a function
+ * A bare number instead of that object indicates the numArgs value.
+ *
+ * The handler function will receive two arguments
+ *  - context: information and references provided by the parser
+ *  - args: an array of arguments passed to \begin{name}
+ * The context contains the following properties:
+ *  - envName: the name of the environment, one of the listed names.
+ *  - parser: the parser object
+ *  - lexer: the lexer object
+ *  - positions: the positions associated with these arguments from args.
+ * The handler must return a ParseResult.
+ */
+
+function defineEnvironment(names, props, handler) {
+    if (typeof names === "string") {
+        names = [names];
+    }
+    if (typeof props === "number") {
+        props = { numArgs: props };
+    }
+    // Set default values of environments
+    var data = {
+        numArgs: props.numArgs || 0,
+        argTypes: props.argTypes,
+        greediness: 1,
+        allowedInText: !!props.allowedInText,
+        numOptionalArgs: props.numOptionalArgs || 0,
+        handler: handler
+    };
+    for (var i = 0; i < names.length; ++i) {
+        module.exports[names[i]] = data;
+    }
+}
+
+// Arrays are part of LaTeX, defined in lttab.dtx so its documentation
+// is part of the source2e.pdf file of LaTeX2e source documentation.
+defineEnvironment("array", {
+    numArgs: 1
+}, function(context, args) {
+    var colalign = args[0];
+    colalign = colalign.value.map ? colalign.value : [colalign];
+    var cols = colalign.map(function(node) {
+        var ca = node.value;
+        if ("lcr".indexOf(ca) !== -1) {
+            return {
+                type: "align",
+                align: ca
+            };
+        } else if (ca === "|") {
+            return {
+                type: "separator",
+                separator: "|"
+            };
+        }
+        throw new ParseError(
+            "Unknown column alignment: " + node.value,
+            node);
+    });
+    var res = {
+        type: "array",
+        cols: cols,
+        hskipBeforeAndAfter: true // \@preamble in lttab.dtx
+    };
+    res = parseArray(context.parser, res);
+    return res;
+});
+
+// The matrix environments of amsmath builds on the array environment
+// of LaTeX, which is discussed above.
+defineEnvironment([
+    "matrix",
+    "pmatrix",
+    "bmatrix",
+    "Bmatrix",
+    "vmatrix",
+    "Vmatrix"
+], {
+}, function(context) {
+    var delimiters = {
+        "matrix": null,
+        "pmatrix": ["(", ")"],
+        "bmatrix": ["[", "]"],
+        "Bmatrix": ["\\{", "\\}"],
+        "vmatrix": ["|", "|"],
+        "Vmatrix": ["\\Vert", "\\Vert"]
+    }[context.envName];
+    var res = {
+        type: "array",
+        hskipBeforeAndAfter: false // \hskip -\arraycolsep in amsmath
+    };
+    res = parseArray(context.parser, res);
+    if (delimiters) {
+        res = new ParseNode("leftright", {
+            body: [res],
+            left: delimiters[0],
+            right: delimiters[1]
+        }, context.mode);
+    }
+    return res;
+});
+
+// A cases environment (in amsmath.sty) is almost equivalent to
+// \def\arraystretch{1.2}%
+// \left\{\begin{array}{@{}l@{\quad}l@{}} … \end{array}\right.
+defineEnvironment("cases", {
+}, function(context) {
+    var res = {
+        type: "array",
+        arraystretch: 1.2,
+        cols: [{
+            type: "align",
+            align: "l",
+            pregap: 0,
+            // TODO(kevinb) get the current style.
+            // For now we use the metrics for TEXT style which is what we were
+            // doing before.  Before attempting to get the current style we
+            // should look at TeX's behavior especially for \over and matrices.
+            postgap: Style.TEXT.metrics.quad
+        }, {
+            type: "align",
+            align: "l",
+            pregap: 0,
+            postgap: 0
+        }]
+    };
+    res = parseArray(context.parser, res);
+    res = new ParseNode("leftright", {
+        body: [res],
+        left: "\\{",
+        right: "."
+    }, context.mode);
+    return res;
+});
+
+// An aligned environment is like the align* environment
+// except it operates within math mode.
+// Note that we assume \nomallineskiplimit to be zero,
+// so that \strut@ is the same as \strut.
+defineEnvironment("aligned", {
+}, function(context) {
+    var res = {
+        type: "array",
+        cols: []
+    };
+    res = parseArray(context.parser, res);
+    var emptyGroup = new ParseNode("ordgroup", [], context.mode);
+    var numCols = 0;
+    res.value.body.forEach(function(row) {
+        var i;
+        for (i = 1; i < row.length; i += 2) {
+            row[i].value.unshift(emptyGroup);
+        }
+        if (numCols < row.length) {
+            numCols = row.length;
+        }
+    });
+    for (var i = 0; i < numCols; ++i) {
+        var align = "r";
+        var pregap = 0;
+        if (i % 2 === 1) {
+            align = "l";
+        } else if (i > 0) {
+            pregap = 2; // one \qquad between columns
+        }
+        res.value.cols[i] = {
+            type: "align",
+            align: align,
+            pregap: pregap,
+            postgap: 0
+        };
+    }
+    return res;
+});
+
+},{"./ParseError":6,"./Style":9,"./parseData":21}],17:[function(require,module,exports){
+/* eslint no-unused-vars:0 */
+
+var Style = require("./Style");
+var cjkRegex = require("./unicodeRegexes").cjkRegex;
+
+/**
+ * This file contains metrics regarding fonts and individual symbols. The sigma
+ * and xi variables, as well as the metricMap map contain data extracted from
+ * TeX, TeX font metrics, and the TTF files. These data are then exposed via the
+ * `metrics` variable and the getCharacterMetrics function.
+ */
+
+// In TeX, there are actually three sets of dimensions, one for each of
+// textstyle, scriptstyle, and scriptscriptstyle.  These are provided in the
+// the arrays below, in that order.
+//
+// The font metrics are stored in fonts cmsy10, cmsy7, and cmsy5 respsectively.
+// This was determined by running the folllowing script:
+//
+//     latex -interaction=nonstopmode \
+//     '\documentclass{article}\usepackage{amsmath}\begin{document}' \
+//     '$a$ \expandafter\show\the\textfont2' \
+//     '\expandafter\show\the\scriptfont2' \
+//     '\expandafter\show\the\scriptscriptfont2' \
+//     '\stop'
+//
+// The metrics themselves were retreived using the following commands:
+//
+//     tftopl cmsy10
+//     tftopl cmsy7
+//     tftopl cmsy5
+//
+// The output of each of these commands is quite lengthy.  The only part we
+// care about is the FONTDIMEN section. Each value is measured in EMs.
+var sigmas = {
+    slant: [0.250, 0.250, 0.250],       // sigma1
+    space: [0.000, 0.000, 0.000],       // sigma2
+    stretch: [0.000, 0.000, 0.000],     // sigma3
+    shrink: [0.000, 0.000, 0.000],      // sigma4
+    xHeight: [0.431, 0.431, 0.431],     // sigma5
+    quad: [1.000, 1.171, 1.472],        // sigma6
+    extraSpace: [0.000, 0.000, 0.000],  // sigma7
+    num1: [0.677, 0.732, 0.925],        // sigma8
+    num2: [0.394, 0.384, 0.387],        // sigma9
+    num3: [0.444, 0.471, 0.504],        // sigma10
+    denom1: [0.686, 0.752, 1.025],      // sigma11
+    denom2: [0.345, 0.344, 0.532],      // sigma12
+    sup1: [0.413, 0.503, 0.504],        // sigma13
+    sup2: [0.363, 0.431, 0.404],        // sigma14
+    sup3: [0.289, 0.286, 0.294],        // sigma15
+    sub1: [0.150, 0.143, 0.200],        // sigma16
+    sub2: [0.247, 0.286, 0.400],        // sigma17
+    supDrop: [0.386, 0.353, 0.494],     // sigma18
+    subDrop: [0.050, 0.071, 0.100],     // sigma19
+    delim1: [2.390, 1.700, 1.980],      // sigma20
+    delim2: [1.010, 1.157, 1.420],      // sigma21
+    axisHeight: [0.250, 0.250, 0.250]  // sigma22
+};
+
+// These font metrics are extracted from TeX by using
+// \font\a=cmex10
+// \showthe\fontdimenX\a
+// where X is the corresponding variable number. These correspond to the font
+// parameters of the extension fonts (family 3). See the TeXbook, page 441.
+var xi1 = 0;
+var xi2 = 0;
+var xi3 = 0;
+var xi4 = 0;
+var xi5 = 0.431;
+var xi6 = 1;
+var xi7 = 0;
+var xi8 = 0.04;
+var xi9 = 0.111;
+var xi10 = 0.166;
+var xi11 = 0.2;
+var xi12 = 0.6;
+var xi13 = 0.1;
+
+// This value determines how large a pt is, for metrics which are defined in
+// terms of pts.
+// This value is also used in katex.less; if you change it make sure the values
+// match.
+var ptPerEm = 10.0;
+
+// The space between adjacent `|` columns in an array definition. From
+// `\showthe\doublerulesep` in LaTeX.
+var doubleRuleSep = 2.0 / ptPerEm;
+
+/**
+ * This is just a mapping from common names to real metrics
+ */
+var metrics = {
+    defaultRuleThickness: xi8,
+    bigOpSpacing1: xi9,
+    bigOpSpacing2: xi10,
+    bigOpSpacing3: xi11,
+    bigOpSpacing4: xi12,
+    bigOpSpacing5: xi13,
+    ptPerEm: ptPerEm,
+    doubleRuleSep: doubleRuleSep
+};
+
+// This map contains a mapping from font name and character code to character
+// metrics, including height, depth, italic correction, and skew (kern from the
+// character to the corresponding \skewchar)
+// This map is generated via `make metrics`. It should not be changed manually.
+var metricMap = require("./fontMetricsData");
+
+// These are very rough approximations.  We default to Times New Roman which
+// should have Latin-1 and Cyrillic characters, but may not depending on the
+// operating system.  The metrics do not account for extra height from the
+// accents.  In the case of Cyrillic characters which have both ascenders and
+// descenders we prefer approximations with ascenders, primarily to prevent
+// the fraction bar or root line from intersecting the glyph.
+// TODO(kevinb) allow union of multiple glyph metrics for better accuracy.
+var extraCharacterMap = {
+    // Latin-1
+    'À': 'A',
+    'Á': 'A',
+    'Â': 'A',
+    'Ã': 'A',
+    'Ä': 'A',
+    'Å': 'A',
+    'Æ': 'A',
+    'Ç': 'C',
+    'È': 'E',
+    'É': 'E',
+    'Ê': 'E',
+    'Ë': 'E',
+    'Ì': 'I',
+    'Í': 'I',
+    'Î': 'I',
+    'Ï': 'I',
+    'Ð': 'D',
+    'Ñ': 'N',
+    'Ò': 'O',
+    'Ó': 'O',
+    'Ô': 'O',
+    'Õ': 'O',
+    'Ö': 'O',
+    'Ø': 'O',
+    'Ù': 'U',
+    'Ú': 'U',
+    'Û': 'U',
+    'Ü': 'U',
+    'Ý': 'Y',
+    'Þ': 'o',
+    'ß': 'B',
+    'à': 'a',
+    'á': 'a',
+    'â': 'a',
+    'ã': 'a',
+    'ä': 'a',
+    'å': 'a',
+    'æ': 'a',
+    'ç': 'c',
+    'è': 'e',
+    'é': 'e',
+    'ê': 'e',
+    'ë': 'e',
+    'ì': 'i',
+    'í': 'i',
+    'î': 'i',
+    'ï': 'i',
+    'ð': 'd',
+    'ñ': 'n',
+    'ò': 'o',
+    'ó': 'o',
+    'ô': 'o',
+    'õ': 'o',
+    'ö': 'o',
+    'ø': 'o',
+    'ù': 'u',
+    'ú': 'u',
+    'û': 'u',
+    'ü': 'u',
+    'ý': 'y',
+    'þ': 'o',
+    'ÿ': 'y',
+
+    // Cyrillic
+    'А': 'A',
+    'Б': 'B',
+    'В': 'B',
+    'Г': 'F',
+    'Д': 'A',
+    'Е': 'E',
+    'Ж': 'K',
+    'З': '3',
+    'И': 'N',
+    'Й': 'N',
+    'К': 'K',
+    'Л': 'N',
+    'М': 'M',
+    'Н': 'H',
+    'О': 'O',
+    'П': 'N',
+    'Р': 'P',
+    'С': 'C',
+    'Т': 'T',
+    'У': 'y',
+    'Ф': 'O',
+    'Х': 'X',
+    'Ц': 'U',
+    'Ч': 'h',
+    'Ш': 'W',
+    'Щ': 'W',
+    'Ъ': 'B',
+    'Ы': 'X',
+    'Ь': 'B',
+    'Э': '3',
+    'Ю': 'X',
+    'Я': 'R',
+    'а': 'a',
+    'б': 'b',
+    'в': 'a',
+    'г': 'r',
+    'д': 'y',
+    'е': 'e',
+    'ж': 'm',
+    'з': 'e',
+    'и': 'n',
+    'й': 'n',
+    'к': 'n',
+    'л': 'n',
+    'м': 'm',
+    'н': 'n',
+    'о': 'o',
+    'п': 'n',
+    'р': 'p',
+    'с': 'c',
+    'т': 'o',
+    'у': 'y',
+    'ф': 'b',
+    'х': 'x',
+    'ц': 'n',
+    'ч': 'n',
+    'ш': 'w',
+    'щ': 'w',
+    'ъ': 'a',
+    'ы': 'm',
+    'ь': 'a',
+    'э': 'e',
+    'ю': 'm',
+    'я': 'r'
+};
+
+/**
+ * This function is a convenience function for looking up information in the
+ * metricMap table. It takes a character as a string, and a style.
+ *
+ * Note: the `width` property may be undefined if fontMetricsData.js wasn't
+ * built using `Make extended_metrics`.
+ */
+var getCharacterMetrics = function(character, style) {
+    var ch = character.charCodeAt(0);
+    if (character[0] in extraCharacterMap) {
+        ch = extraCharacterMap[character[0]].charCodeAt(0);
+    } else if (cjkRegex.test(character[0])) {
+        ch = 'M'.charCodeAt(0);
+    }
+    var metrics = metricMap[style][ch];
+    if (metrics) {
+        return {
+            depth: metrics[0],
+            height: metrics[1],
+            italic: metrics[2],
+            skew: metrics[3],
+            width: metrics[4]
+        };
+    }
+};
+
+module.exports = {
+    metrics: metrics,
+    sigmas: sigmas,
+    getCharacterMetrics: getCharacterMetrics
+};
+
+},{"./Style":9,"./fontMetricsData":18,"./unicodeRegexes":24}],18:[function(require,module,exports){
+module.exports = {
+    "AMS-Regular": {
+        "65": [0, 0.68889, 0, 0],
+        "66": [0, 0.68889, 0, 0],
+        "67": [0, 0.68889, 0, 0],
+        "68": [0, 0.68889, 0, 0],
+        "69": [0, 0.68889, 0, 0],
+        "70": [0, 0.68889, 0, 0],
+        "71": [0, 0.68889, 0, 0],
+        "72": [0, 0.68889, 0, 0],
+        "73": [0, 0.68889, 0, 0],
+        "74": [0.16667, 0.68889, 0, 0],
+        "75": [0, 0.68889, 0, 0],
+        "76": [0, 0.68889, 0, 0],
+        "77": [0, 0.68889, 0, 0],
+        "78": [0, 0.68889, 0, 0],
+        "79": [0.16667, 0.68889, 0, 0],
+        "80": [0, 0.68889, 0, 0],
+        "81": [0.16667, 0.68889, 0, 0],
+        "82": [0, 0.68889, 0, 0],
+        "83": [0, 0.68889, 0, 0],
+        "84": [0, 0.68889, 0, 0],
+        "85": [0, 0.68889, 0, 0],
+        "86": [0, 0.68889, 0, 0],
+        "87": [0, 0.68889, 0, 0],
+        "88": [0, 0.68889, 0, 0],
+        "89": [0, 0.68889, 0, 0],
+        "90": [0, 0.68889, 0, 0],
+        "107": [0, 0.68889, 0, 0],
+        "165": [0, 0.675, 0.025, 0],
+        "174": [0.15559, 0.69224, 0, 0],
+        "240": [0, 0.68889, 0, 0],
+        "295": [0, 0.68889, 0, 0],
+        "710": [0, 0.825, 0, 0],
+        "732": [0, 0.9, 0, 0],
+        "770": [0, 0.825, 0, 0],
+        "771": [0, 0.9, 0, 0],
+        "989": [0.08167, 0.58167, 0, 0],
+        "1008": [0, 0.43056, 0.04028, 0],
+        "8245": [0, 0.54986, 0, 0],
+        "8463": [0, 0.68889, 0, 0],
+        "8487": [0, 0.68889, 0, 0],
+        "8498": [0, 0.68889, 0, 0],
+        "8502": [0, 0.68889, 0, 0],
+        "8503": [0, 0.68889, 0, 0],
+        "8504": [0, 0.68889, 0, 0],
+        "8513": [0, 0.68889, 0, 0],
+        "8592": [-0.03598, 0.46402, 0, 0],
+        "8594": [-0.03598, 0.46402, 0, 0],
+        "8602": [-0.13313, 0.36687, 0, 0],
+        "8603": [-0.13313, 0.36687, 0, 0],
+        "8606": [0.01354, 0.52239, 0, 0],
+        "8608": [0.01354, 0.52239, 0, 0],
+        "8610": [0.01354, 0.52239, 0, 0],
+        "8611": [0.01354, 0.52239, 0, 0],
+        "8619": [0, 0.54986, 0, 0],
+        "8620": [0, 0.54986, 0, 0],
+        "8621": [-0.13313, 0.37788, 0, 0],
+        "8622": [-0.13313, 0.36687, 0, 0],
+        "8624": [0, 0.69224, 0, 0],
+        "8625": [0, 0.69224, 0, 0],
+        "8630": [0, 0.43056, 0, 0],
+        "8631": [0, 0.43056, 0, 0],
+        "8634": [0.08198, 0.58198, 0, 0],
+        "8635": [0.08198, 0.58198, 0, 0],
+        "8638": [0.19444, 0.69224, 0, 0],
+        "8639": [0.19444, 0.69224, 0, 0],
+        "8642": [0.19444, 0.69224, 0, 0],
+        "8643": [0.19444, 0.69224, 0, 0],
+        "8644": [0.1808, 0.675, 0, 0],
+        "8646": [0.1808, 0.675, 0, 0],
+        "8647": [0.1808, 0.675, 0, 0],
+        "8648": [0.19444, 0.69224, 0, 0],
+        "8649": [0.1808, 0.675, 0, 0],
+        "8650": [0.19444, 0.69224, 0, 0],
+        "8651": [0.01354, 0.52239, 0, 0],
+        "8652": [0.01354, 0.52239, 0, 0],
+        "8653": [-0.13313, 0.36687, 0, 0],
+        "8654": [-0.13313, 0.36687, 0, 0],
+        "8655": [-0.13313, 0.36687, 0, 0],
+        "8666": [0.13667, 0.63667, 0, 0],
+        "8667": [0.13667, 0.63667, 0, 0],
+        "8669": [-0.13313, 0.37788, 0, 0],
+        "8672": [-0.064, 0.437, 0, 0],
+        "8674": [-0.064, 0.437, 0, 0],
+        "8705": [0, 0.825, 0, 0],
+        "8708": [0, 0.68889, 0, 0],
+        "8709": [0.08167, 0.58167, 0, 0],
+        "8717": [0, 0.43056, 0, 0],
+        "8722": [-0.03598, 0.46402, 0, 0],
+        "8724": [0.08198, 0.69224, 0, 0],
+        "8726": [0.08167, 0.58167, 0, 0],
+        "8733": [0, 0.69224, 0, 0],
+        "8736": [0, 0.69224, 0, 0],
+        "8737": [0, 0.69224, 0, 0],
+        "8738": [0.03517, 0.52239, 0, 0],
+        "8739": [0.08167, 0.58167, 0, 0],
+        "8740": [0.25142, 0.74111, 0, 0],
+        "8741": [0.08167, 0.58167, 0, 0],
+        "8742": [0.25142, 0.74111, 0, 0],
+        "8756": [0, 0.69224, 0, 0],
+        "8757": [0, 0.69224, 0, 0],
+        "8764": [-0.13313, 0.36687, 0, 0],
+        "8765": [-0.13313, 0.37788, 0, 0],
+        "8769": [-0.13313, 0.36687, 0, 0],
+        "8770": [-0.03625, 0.46375, 0, 0],
+        "8774": [0.30274, 0.79383, 0, 0],
+        "8776": [-0.01688, 0.48312, 0, 0],
+        "8778": [0.08167, 0.58167, 0, 0],
+        "8782": [0.06062, 0.54986, 0, 0],
+        "8783": [0.06062, 0.54986, 0, 0],
+        "8785": [0.08198, 0.58198, 0, 0],
+        "8786": [0.08198, 0.58198, 0, 0],
+        "8787": [0.08198, 0.58198, 0, 0],
+        "8790": [0, 0.69224, 0, 0],
+        "8791": [0.22958, 0.72958, 0, 0],
+        "8796": [0.08198, 0.91667, 0, 0],
+        "8806": [0.25583, 0.75583, 0, 0],
+        "8807": [0.25583, 0.75583, 0, 0],
+        "8808": [0.25142, 0.75726, 0, 0],
+        "8809": [0.25142, 0.75726, 0, 0],
+        "8812": [0.25583, 0.75583, 0, 0],
+        "8814": [0.20576, 0.70576, 0, 0],
+        "8815": [0.20576, 0.70576, 0, 0],
+        "8816": [0.30274, 0.79383, 0, 0],
+        "8817": [0.30274, 0.79383, 0, 0],
+        "8818": [0.22958, 0.72958, 0, 0],
+        "8819": [0.22958, 0.72958, 0, 0],
+        "8822": [0.1808, 0.675, 0, 0],
+        "8823": [0.1808, 0.675, 0, 0],
+        "8828": [0.13667, 0.63667, 0, 0],
+        "8829": [0.13667, 0.63667, 0, 0],
+        "8830": [0.22958, 0.72958, 0, 0],
+        "8831": [0.22958, 0.72958, 0, 0],
+        "8832": [0.20576, 0.70576, 0, 0],
+        "8833": [0.20576, 0.70576, 0, 0],
+        "8840": [0.30274, 0.79383, 0, 0],
+        "8841": [0.30274, 0.79383, 0, 0],
+        "8842": [0.13597, 0.63597, 0, 0],
+        "8843": [0.13597, 0.63597, 0, 0],
+        "8847": [0.03517, 0.54986, 0, 0],
+        "8848": [0.03517, 0.54986, 0, 0],
+        "8858": [0.08198, 0.58198, 0, 0],
+        "8859": [0.08198, 0.58198, 0, 0],
+        "8861": [0.08198, 0.58198, 0, 0],
+        "8862": [0, 0.675, 0, 0],
+        "8863": [0, 0.675, 0, 0],
+        "8864": [0, 0.675, 0, 0],
+        "8865": [0, 0.675, 0, 0],
+        "8872": [0, 0.69224, 0, 0],
+        "8873": [0, 0.69224, 0, 0],
+        "8874": [0, 0.69224, 0, 0],
+        "8876": [0, 0.68889, 0, 0],
+        "8877": [0, 0.68889, 0, 0],
+        "8878": [0, 0.68889, 0, 0],
+        "8879": [0, 0.68889, 0, 0],
+        "8882": [0.03517, 0.54986, 0, 0],
+        "8883": [0.03517, 0.54986, 0, 0],
+        "8884": [0.13667, 0.63667, 0, 0],
+        "8885": [0.13667, 0.63667, 0, 0],
+        "8888": [0, 0.54986, 0, 0],
+        "8890": [0.19444, 0.43056, 0, 0],
+        "8891": [0.19444, 0.69224, 0, 0],
+        "8892": [0.19444, 0.69224, 0, 0],
+        "8901": [0, 0.54986, 0, 0],
+        "8903": [0.08167, 0.58167, 0, 0],
+        "8905": [0.08167, 0.58167, 0, 0],
+        "8906": [0.08167, 0.58167, 0, 0],
+        "8907": [0, 0.69224, 0, 0],
+        "8908": [0, 0.69224, 0, 0],
+        "8909": [-0.03598, 0.46402, 0, 0],
+        "8910": [0, 0.54986, 0, 0],
+        "8911": [0, 0.54986, 0, 0],
+        "8912": [0.03517, 0.54986, 0, 0],
+        "8913": [0.03517, 0.54986, 0, 0],
+        "8914": [0, 0.54986, 0, 0],
+        "8915": [0, 0.54986, 0, 0],
+        "8916": [0, 0.69224, 0, 0],
+        "8918": [0.0391, 0.5391, 0, 0],
+        "8919": [0.0391, 0.5391, 0, 0],
+        "8920": [0.03517, 0.54986, 0, 0],
+        "8921": [0.03517, 0.54986, 0, 0],
+        "8922": [0.38569, 0.88569, 0, 0],
+        "8923": [0.38569, 0.88569, 0, 0],
+        "8926": [0.13667, 0.63667, 0, 0],
+        "8927": [0.13667, 0.63667, 0, 0],
+        "8928": [0.30274, 0.79383, 0, 0],
+        "8929": [0.30274, 0.79383, 0, 0],
+        "8934": [0.23222, 0.74111, 0, 0],
+        "8935": [0.23222, 0.74111, 0, 0],
+        "8936": [0.23222, 0.74111, 0, 0],
+        "8937": [0.23222, 0.74111, 0, 0],
+        "8938": [0.20576, 0.70576, 0, 0],
+        "8939": [0.20576, 0.70576, 0, 0],
+        "8940": [0.30274, 0.79383, 0, 0],
+        "8941": [0.30274, 0.79383, 0, 0],
+        "8994": [0.19444, 0.69224, 0, 0],
+        "8995": [0.19444, 0.69224, 0, 0],
+        "9416": [0.15559, 0.69224, 0, 0],
+        "9484": [0, 0.69224, 0, 0],
+        "9488": [0, 0.69224, 0, 0],
+        "9492": [0, 0.37788, 0, 0],
+        "9496": [0, 0.37788, 0, 0],
+        "9585": [0.19444, 0.68889, 0, 0],
+        "9586": [0.19444, 0.74111, 0, 0],
+        "9632": [0, 0.675, 0, 0],
+        "9633": [0, 0.675, 0, 0],
+        "9650": [0, 0.54986, 0, 0],
+        "9651": [0, 0.54986, 0, 0],
+        "9654": [0.03517, 0.54986, 0, 0],
+        "9660": [0, 0.54986, 0, 0],
+        "9661": [0, 0.54986, 0, 0],
+        "9664": [0.03517, 0.54986, 0, 0],
+        "9674": [0.11111, 0.69224, 0, 0],
+        "9733": [0.19444, 0.69224, 0, 0],
+        "10003": [0, 0.69224, 0, 0],
+        "10016": [0, 0.69224, 0, 0],
+        "10731": [0.11111, 0.69224, 0, 0],
+        "10846": [0.19444, 0.75583, 0, 0],
+        "10877": [0.13667, 0.63667, 0, 0],
+        "10878": [0.13667, 0.63667, 0, 0],
+        "10885": [0.25583, 0.75583, 0, 0],
+        "10886": [0.25583, 0.75583, 0, 0],
+        "10887": [0.13597, 0.63597, 0, 0],
+        "10888": [0.13597, 0.63597, 0, 0],
+        "10889": [0.26167, 0.75726, 0, 0],
+        "10890": [0.26167, 0.75726, 0, 0],
+        "10891": [0.48256, 0.98256, 0, 0],
+        "10892": [0.48256, 0.98256, 0, 0],
+        "10901": [0.13667, 0.63667, 0, 0],
+        "10902": [0.13667, 0.63667, 0, 0],
+        "10933": [0.25142, 0.75726, 0, 0],
+        "10934": [0.25142, 0.75726, 0, 0],
+        "10935": [0.26167, 0.75726, 0, 0],
+        "10936": [0.26167, 0.75726, 0, 0],
+        "10937": [0.26167, 0.75726, 0, 0],
+        "10938": [0.26167, 0.75726, 0, 0],
+        "10949": [0.25583, 0.75583, 0, 0],
+        "10950": [0.25583, 0.75583, 0, 0],
+        "10955": [0.28481, 0.79383, 0, 0],
+        "10956": [0.28481, 0.79383, 0, 0],
+        "57350": [0.08167, 0.58167, 0, 0],
+        "57351": [0.08167, 0.58167, 0, 0],
+        "57352": [0.08167, 0.58167, 0, 0],
+        "57353": [0, 0.43056, 0.04028, 0],
+        "57356": [0.25142, 0.75726, 0, 0],
+        "57357": [0.25142, 0.75726, 0, 0],
+        "57358": [0.41951, 0.91951, 0, 0],
+        "57359": [0.30274, 0.79383, 0, 0],
+        "57360": [0.30274, 0.79383, 0, 0],
+        "57361": [0.41951, 0.91951, 0, 0],
+        "57366": [0.25142, 0.75726, 0, 0],
+        "57367": [0.25142, 0.75726, 0, 0],
+        "57368": [0.25142, 0.75726, 0, 0],
+        "57369": [0.25142, 0.75726, 0, 0],
+        "57370": [0.13597, 0.63597, 0, 0],
+        "57371": [0.13597, 0.63597, 0, 0]
+    },
+    "Caligraphic-Regular": {
+        "48": [0, 0.43056, 0, 0],
+        "49": [0, 0.43056, 0, 0],
+        "50": [0, 0.43056, 0, 0],
+        "51": [0.19444, 0.43056, 0, 0],
+        "52": [0.19444, 0.43056, 0, 0],
+        "53": [0.19444, 0.43056, 0, 0],
+        "54": [0, 0.64444, 0, 0],
+        "55": [0.19444, 0.43056, 0, 0],
+        "56": [0, 0.64444, 0, 0],
+        "57": [0.19444, 0.43056, 0, 0],
+        "65": [0, 0.68333, 0, 0.19445],
+        "66": [0, 0.68333, 0.03041, 0.13889],
+        "67": [0, 0.68333, 0.05834, 0.13889],
+        "68": [0, 0.68333, 0.02778, 0.08334],
+        "69": [0, 0.68333, 0.08944, 0.11111],
+        "70": [0, 0.68333, 0.09931, 0.11111],
+        "71": [0.09722, 0.68333, 0.0593, 0.11111],
+        "72": [0, 0.68333, 0.00965, 0.11111],
+        "73": [0, 0.68333, 0.07382, 0],
+        "74": [0.09722, 0.68333, 0.18472, 0.16667],
+        "75": [0, 0.68333, 0.01445, 0.05556],
+        "76": [0, 0.68333, 0, 0.13889],
+        "77": [0, 0.68333, 0, 0.13889],
+        "78": [0, 0.68333, 0.14736, 0.08334],
+        "79": [0, 0.68333, 0.02778, 0.11111],
+        "80": [0, 0.68333, 0.08222, 0.08334],
+        "81": [0.09722, 0.68333, 0, 0.11111],
+        "82": [0, 0.68333, 0, 0.08334],
+        "83": [0, 0.68333, 0.075, 0.13889],
+        "84": [0, 0.68333, 0.25417, 0],
+        "85": [0, 0.68333, 0.09931, 0.08334],
+        "86": [0, 0.68333, 0.08222, 0],
+        "87": [0, 0.68333, 0.08222, 0.08334],
+        "88": [0, 0.68333, 0.14643, 0.13889],
+        "89": [0.09722, 0.68333, 0.08222, 0.08334],
+        "90": [0, 0.68333, 0.07944, 0.13889]
+    },
+    "Fraktur-Regular": {
+        "33": [0, 0.69141, 0, 0],
+        "34": [0, 0.69141, 0, 0],
+        "38": [0, 0.69141, 0, 0],
+        "39": [0, 0.69141, 0, 0],
+        "40": [0.24982, 0.74947, 0, 0],
+        "41": [0.24982, 0.74947, 0, 0],
+        "42": [0, 0.62119, 0, 0],
+        "43": [0.08319, 0.58283, 0, 0],
+        "44": [0, 0.10803, 0, 0],
+        "45": [0.08319, 0.58283, 0, 0],
+        "46": [0, 0.10803, 0, 0],
+        "47": [0.24982, 0.74947, 0, 0],
+        "48": [0, 0.47534, 0, 0],
+        "49": [0, 0.47534, 0, 0],
+        "50": [0, 0.47534, 0, 0],
+        "51": [0.18906, 0.47534, 0, 0],
+        "52": [0.18906, 0.47534, 0, 0],
+        "53": [0.18906, 0.47534, 0, 0],
+        "54": [0, 0.69141, 0, 0],
+        "55": [0.18906, 0.47534, 0, 0],
+        "56": [0, 0.69141, 0, 0],
+        "57": [0.18906, 0.47534, 0, 0],
+        "58": [0, 0.47534, 0, 0],
+        "59": [0.12604, 0.47534, 0, 0],
+        "61": [-0.13099, 0.36866, 0, 0],
+        "63": [0, 0.69141, 0, 0],
+        "65": [0, 0.69141, 0, 0],
+        "66": [0, 0.69141, 0, 0],
+        "67": [0, 0.69141, 0, 0],
+        "68": [0, 0.69141, 0, 0],
+        "69": [0, 0.69141, 0, 0],
+        "70": [0.12604, 0.69141, 0, 0],
+        "71": [0, 0.69141, 0, 0],
+        "72": [0.06302, 0.69141, 0, 0],
+        "73": [0, 0.69141, 0, 0],
+        "74": [0.12604, 0.69141, 0, 0],
+        "75": [0, 0.69141, 0, 0],
+        "76": [0, 0.69141, 0, 0],
+        "77": [0, 0.69141, 0, 0],
+        "78": [0, 0.69141, 0, 0],
+        "79": [0, 0.69141, 0, 0],
+        "80": [0.18906, 0.69141, 0, 0],
+        "81": [0.03781, 0.69141, 0, 0],
+        "82": [0, 0.69141, 0, 0],
+        "83": [0, 0.69141, 0, 0],
+        "84": [0, 0.69141, 0, 0],
+        "85": [0, 0.69141, 0, 0],
+        "86": [0, 0.69141, 0, 0],
+        "87": [0, 0.69141, 0, 0],
+        "88": [0, 0.69141, 0, 0],
+        "89": [0.18906, 0.69141, 0, 0],
+        "90": [0.12604, 0.69141, 0, 0],
+        "91": [0.24982, 0.74947, 0, 0],
+        "93": [0.24982, 0.74947, 0, 0],
+        "94": [0, 0.69141, 0, 0],
+        "97": [0, 0.47534, 0, 0],
+        "98": [0, 0.69141, 0, 0],
+        "99": [0, 0.47534, 0, 0],
+        "100": [0, 0.62119, 0, 0],
+        "101": [0, 0.47534, 0, 0],
+        "102": [0.18906, 0.69141, 0, 0],
+        "103": [0.18906, 0.47534, 0, 0],
+        "104": [0.18906, 0.69141, 0, 0],
+        "105": [0, 0.69141, 0, 0],
+        "106": [0, 0.69141, 0, 0],
+        "107": [0, 0.69141, 0, 0],
+        "108": [0, 0.69141, 0, 0],
+        "109": [0, 0.47534, 0, 0],
+        "110": [0, 0.47534, 0, 0],
+        "111": [0, 0.47534, 0, 0],
+        "112": [0.18906, 0.52396, 0, 0],
+        "113": [0.18906, 0.47534, 0, 0],
+        "114": [0, 0.47534, 0, 0],
+        "115": [0, 0.47534, 0, 0],
+        "116": [0, 0.62119, 0, 0],
+        "117": [0, 0.47534, 0, 0],
+        "118": [0, 0.52396, 0, 0],
+        "119": [0, 0.52396, 0, 0],
+        "120": [0.18906, 0.47534, 0, 0],
+        "121": [0.18906, 0.47534, 0, 0],
+        "122": [0.18906, 0.47534, 0, 0],
+        "8216": [0, 0.69141, 0, 0],
+        "8217": [0, 0.69141, 0, 0],
+        "58112": [0, 0.62119, 0, 0],
+        "58113": [0, 0.62119, 0, 0],
+        "58114": [0.18906, 0.69141, 0, 0],
+        "58115": [0.18906, 0.69141, 0, 0],
+        "58116": [0.18906, 0.47534, 0, 0],
+        "58117": [0, 0.69141, 0, 0],
+        "58118": [0, 0.62119, 0, 0],
+        "58119": [0, 0.47534, 0, 0]
+    },
+    "Main-Bold": {
+        "33": [0, 0.69444, 0, 0],
+        "34": [0, 0.69444, 0, 0],
+        "35": [0.19444, 0.69444, 0, 0],
+        "36": [0.05556, 0.75, 0, 0],
+        "37": [0.05556, 0.75, 0, 0],
+        "38": [0, 0.69444, 0, 0],
+        "39": [0, 0.69444, 0, 0],
+        "40": [0.25, 0.75, 0, 0],
+        "41": [0.25, 0.75, 0, 0],
+        "42": [0, 0.75, 0, 0],
+        "43": [0.13333, 0.63333, 0, 0],
+        "44": [0.19444, 0.15556, 0, 0],
+        "45": [0, 0.44444, 0, 0],
+        "46": [0, 0.15556, 0, 0],
+        "47": [0.25, 0.75, 0, 0],
+        "48": [0, 0.64444, 0, 0],
+        "49": [0, 0.64444, 0, 0],
+        "50": [0, 0.64444, 0, 0],
+        "51": [0, 0.64444, 0, 0],
+        "52": [0, 0.64444, 0, 0],
+        "53": [0, 0.64444, 0, 0],
+        "54": [0, 0.64444, 0, 0],
+        "55": [0, 0.64444, 0, 0],
+        "56": [0, 0.64444, 0, 0],
+        "57": [0, 0.64444, 0, 0],
+        "58": [0, 0.44444, 0, 0],
+        "59": [0.19444, 0.44444, 0, 0],
+        "60": [0.08556, 0.58556, 0, 0],
+        "61": [-0.10889, 0.39111, 0, 0],
+        "62": [0.08556, 0.58556, 0, 0],
+        "63": [0, 0.69444, 0, 0],
+        "64": [0, 0.69444, 0, 0],
+        "65": [0, 0.68611, 0, 0],
+        "66": [0, 0.68611, 0, 0],
+        "67": [0, 0.68611, 0, 0],
+        "68": [0, 0.68611, 0, 0],
+        "69": [0, 0.68611, 0, 0],
+        "70": [0, 0.68611, 0, 0],
+        "71": [0, 0.68611, 0, 0],
+        "72": [0, 0.68611, 0, 0],
+        "73": [0, 0.68611, 0, 0],
+        "74": [0, 0.68611, 0, 0],
+        "75": [0, 0.68611, 0, 0],
+        "76": [0, 0.68611, 0, 0],
+        "77": [0, 0.68611, 0, 0],
+        "78": [0, 0.68611, 0, 0],
+        "79": [0, 0.68611, 0, 0],
+        "80": [0, 0.68611, 0, 0],
+        "81": [0.19444, 0.68611, 0, 0],
+        "82": [0, 0.68611, 0, 0],
+        "83": [0, 0.68611, 0, 0],
+        "84": [0, 0.68611, 0, 0],
+        "85": [0, 0.68611, 0, 0],
+        "86": [0, 0.68611, 0.01597, 0],
+        "87": [0, 0.68611, 0.01597, 0],
+        "88": [0, 0.68611, 0, 0],
+        "89": [0, 0.68611, 0.02875, 0],
+        "90": [0, 0.68611, 0, 0],
+        "91": [0.25, 0.75, 0, 0],
+        "92": [0.25, 0.75, 0, 0],
+        "93": [0.25, 0.75, 0, 0],
+        "94": [0, 0.69444, 0, 0],
+        "95": [0.31, 0.13444, 0.03194, 0],
+        "96": [0, 0.69444, 0, 0],
+        "97": [0, 0.44444, 0, 0],
+        "98": [0, 0.69444, 0, 0],
+        "99": [0, 0.44444, 0, 0],
+        "100": [0, 0.69444, 0, 0],
+        "101": [0, 0.44444, 0, 0],
+        "102": [0, 0.69444, 0.10903, 0],
+        "103": [0.19444, 0.44444, 0.01597, 0],
+        "104": [0, 0.69444, 0, 0],
+        "105": [0, 0.69444, 0, 0],
+        "106": [0.19444, 0.69444, 0, 0],
+        "107": [0, 0.69444, 0, 0],
+        "108": [0, 0.69444, 0, 0],
+        "109": [0, 0.44444, 0, 0],
+        "110": [0, 0.44444, 0, 0],
+        "111": [0, 0.44444, 0, 0],
+        "112": [0.19444, 0.44444, 0, 0],
+        "113": [0.19444, 0.44444, 0, 0],
+        "114": [0, 0.44444, 0, 0],
+        "115": [0, 0.44444, 0, 0],
+        "116": [0, 0.63492, 0, 0],
+        "117": [0, 0.44444, 0, 0],
+        "118": [0, 0.44444, 0.01597, 0],
+        "119": [0, 0.44444, 0.01597, 0],
+        "120": [0, 0.44444, 0, 0],
+        "121": [0.19444, 0.44444, 0.01597, 0],
+        "122": [0, 0.44444, 0, 0],
+        "123": [0.25, 0.75, 0, 0],
+        "124": [0.25, 0.75, 0, 0],
+        "125": [0.25, 0.75, 0, 0],
+        "126": [0.35, 0.34444, 0, 0],
+        "168": [0, 0.69444, 0, 0],
+        "172": [0, 0.44444, 0, 0],
+        "175": [0, 0.59611, 0, 0],
+        "176": [0, 0.69444, 0, 0],
+        "177": [0.13333, 0.63333, 0, 0],
+        "180": [0, 0.69444, 0, 0],
+        "215": [0.13333, 0.63333, 0, 0],
+        "247": [0.13333, 0.63333, 0, 0],
+        "305": [0, 0.44444, 0, 0],
+        "567": [0.19444, 0.44444, 0, 0],
+        "710": [0, 0.69444, 0, 0],
+        "711": [0, 0.63194, 0, 0],
+        "713": [0, 0.59611, 0, 0],
+        "714": [0, 0.69444, 0, 0],
+        "715": [0, 0.69444, 0, 0],
+        "728": [0, 0.69444, 0, 0],
+        "729": [0, 0.69444, 0, 0],
+        "730": [0, 0.69444, 0, 0],
+        "732": [0, 0.69444, 0, 0],
+        "768": [0, 0.69444, 0, 0],
+        "769": [0, 0.69444, 0, 0],
+        "770": [0, 0.69444, 0, 0],
+        "771": [0, 0.69444, 0, 0],
+        "772": [0, 0.59611, 0, 0],
+        "774": [0, 0.69444, 0, 0],
+        "775": [0, 0.69444, 0, 0],
+        "776": [0, 0.69444, 0, 0],
+        "778": [0, 0.69444, 0, 0],
+        "779": [0, 0.69444, 0, 0],
+        "780": [0, 0.63194, 0, 0],
+        "824": [0.19444, 0.69444, 0, 0],
+        "915": [0, 0.68611, 0, 0],
+        "916": [0, 0.68611, 0, 0],
+        "920": [0, 0.68611, 0, 0],
+        "923": [0, 0.68611, 0, 0],
+        "926": [0, 0.68611, 0, 0],
+        "928": [0, 0.68611, 0, 0],
+        "931": [0, 0.68611, 0, 0],
+        "933": [0, 0.68611, 0, 0],
+        "934": [0, 0.68611, 0, 0],
+        "936": [0, 0.68611, 0, 0],
+        "937": [0, 0.68611, 0, 0],
+        "8211": [0, 0.44444, 0.03194, 0],
+        "8212": [0, 0.44444, 0.03194, 0],
+        "8216": [0, 0.69444, 0, 0],
+        "8217": [0, 0.69444, 0, 0],
+        "8220": [0, 0.69444, 0, 0],
+        "8221": [0, 0.69444, 0, 0],
+        "8224": [0.19444, 0.69444, 0, 0],
+        "8225": [0.19444, 0.69444, 0, 0],
+        "8242": [0, 0.55556, 0, 0],
+        "8407": [0, 0.72444, 0.15486, 0],
+        "8463": [0, 0.69444, 0, 0],
+        "8465": [0, 0.69444, 0, 0],
+        "8467": [0, 0.69444, 0, 0],
+        "8472": [0.19444, 0.44444, 0, 0],
+        "8476": [0, 0.69444, 0, 0],
+        "8501": [0, 0.69444, 0, 0],
+        "8592": [-0.10889, 0.39111, 0, 0],
+        "8593": [0.19444, 0.69444, 0, 0],
+        "8594": [-0.10889, 0.39111, 0, 0],
+        "8595": [0.19444, 0.69444, 0, 0],
+        "8596": [-0.10889, 0.39111, 0, 0],
+        "8597": [0.25, 0.75, 0, 0],
+        "8598": [0.19444, 0.69444, 0, 0],
+        "8599": [0.19444, 0.69444, 0, 0],
+        "8600": [0.19444, 0.69444, 0, 0],
+        "8601": [0.19444, 0.69444, 0, 0],
+        "8636": [-0.10889, 0.39111, 0, 0],
+        "8637": [-0.10889, 0.39111, 0, 0],
+        "8640": [-0.10889, 0.39111, 0, 0],
+        "8641": [-0.10889, 0.39111, 0, 0],
+        "8656": [-0.10889, 0.39111, 0, 0],
+        "8657": [0.19444, 0.69444, 0, 0],
+        "8658": [-0.10889, 0.39111, 0, 0],
+        "8659": [0.19444, 0.69444, 0, 0],
+        "8660": [-0.10889, 0.39111, 0, 0],
+        "8661": [0.25, 0.75, 0, 0],
+        "8704": [0, 0.69444, 0, 0],
+        "8706": [0, 0.69444, 0.06389, 0],
+        "8707": [0, 0.69444, 0, 0],
+        "8709": [0.05556, 0.75, 0, 0],
+        "8711": [0, 0.68611, 0, 0],
+        "8712": [0.08556, 0.58556, 0, 0],
+        "8715": [0.08556, 0.58556, 0, 0],
+        "8722": [0.13333, 0.63333, 0, 0],
+        "8723": [0.13333, 0.63333, 0, 0],
+        "8725": [0.25, 0.75, 0, 0],
+        "8726": [0.25, 0.75, 0, 0],
+        "8727": [-0.02778, 0.47222, 0, 0],
+        "8728": [-0.02639, 0.47361, 0, 0],
+        "8729": [-0.02639, 0.47361, 0, 0],
+        "8730": [0.18, 0.82, 0, 0],
+        "8733": [0, 0.44444, 0, 0],
+        "8734": [0, 0.44444, 0, 0],
+        "8736": [0, 0.69224, 0, 0],
+        "8739": [0.25, 0.75, 0, 0],
+        "8741": [0.25, 0.75, 0, 0],
+        "8743": [0, 0.55556, 0, 0],
+        "8744": [0, 0.55556, 0, 0],
+        "8745": [0, 0.55556, 0, 0],
+        "8746": [0, 0.55556, 0, 0],
+        "8747": [0.19444, 0.69444, 0.12778, 0],
+        "8764": [-0.10889, 0.39111, 0, 0],
+        "8768": [0.19444, 0.69444, 0, 0],
+        "8771": [0.00222, 0.50222, 0, 0],
+        "8776": [0.02444, 0.52444, 0, 0],
+        "8781": [0.00222, 0.50222, 0, 0],
+        "8801": [0.00222, 0.50222, 0, 0],
+        "8804": [0.19667, 0.69667, 0, 0],
+        "8805": [0.19667, 0.69667, 0, 0],
+        "8810": [0.08556, 0.58556, 0, 0],
+        "8811": [0.08556, 0.58556, 0, 0],
+        "8826": [0.08556, 0.58556, 0, 0],
+        "8827": [0.08556, 0.58556, 0, 0],
+        "8834": [0.08556, 0.58556, 0, 0],
+        "8835": [0.08556, 0.58556, 0, 0],
+        "8838": [0.19667, 0.69667, 0, 0],
+        "8839": [0.19667, 0.69667, 0, 0],
+        "8846": [0, 0.55556, 0, 0],
+        "8849": [0.19667, 0.69667, 0, 0],
+        "8850": [0.19667, 0.69667, 0, 0],
+        "8851": [0, 0.55556, 0, 0],
+        "8852": [0, 0.55556, 0, 0],
+        "8853": [0.13333, 0.63333, 0, 0],
+        "8854": [0.13333, 0.63333, 0, 0],
+        "8855": [0.13333, 0.63333, 0, 0],
+        "8856": [0.13333, 0.63333, 0, 0],
+        "8857": [0.13333, 0.63333, 0, 0],
+        "8866": [0, 0.69444, 0, 0],
+        "8867": [0, 0.69444, 0, 0],
+        "8868": [0, 0.69444, 0, 0],
+        "8869": [0, 0.69444, 0, 0],
+        "8900": [-0.02639, 0.47361, 0, 0],
+        "8901": [-0.02639, 0.47361, 0, 0],
+        "8902": [-0.02778, 0.47222, 0, 0],
+        "8968": [0.25, 0.75, 0, 0],
+        "8969": [0.25, 0.75, 0, 0],
+        "8970": [0.25, 0.75, 0, 0],
+        "8971": [0.25, 0.75, 0, 0],
+        "8994": [-0.13889, 0.36111, 0, 0],
+        "8995": [-0.13889, 0.36111, 0, 0],
+        "9651": [0.19444, 0.69444, 0, 0],
+        "9657": [-0.02778, 0.47222, 0, 0],
+        "9661": [0.19444, 0.69444, 0, 0],
+        "9667": [-0.02778, 0.47222, 0, 0],
+        "9711": [0.19444, 0.69444, 0, 0],
+        "9824": [0.12963, 0.69444, 0, 0],
+        "9825": [0.12963, 0.69444, 0, 0],
+        "9826": [0.12963, 0.69444, 0, 0],
+        "9827": [0.12963, 0.69444, 0, 0],
+        "9837": [0, 0.75, 0, 0],
+        "9838": [0.19444, 0.69444, 0, 0],
+        "9839": [0.19444, 0.69444, 0, 0],
+        "10216": [0.25, 0.75, 0, 0],
+        "10217": [0.25, 0.75, 0, 0],
+        "10815": [0, 0.68611, 0, 0],
+        "10927": [0.19667, 0.69667, 0, 0],
+        "10928": [0.19667, 0.69667, 0, 0]
+    },
+    "Main-Italic": {
+        "33": [0, 0.69444, 0.12417, 0],
+        "34": [0, 0.69444, 0.06961, 0],
+        "35": [0.19444, 0.69444, 0.06616, 0],
+        "37": [0.05556, 0.75, 0.13639, 0],
+        "38": [0, 0.69444, 0.09694, 0],
+        "39": [0, 0.69444, 0.12417, 0],
+        "40": [0.25, 0.75, 0.16194, 0],
+        "41": [0.25, 0.75, 0.03694, 0],
+        "42": [0, 0.75, 0.14917, 0],
+        "43": [0.05667, 0.56167, 0.03694, 0],
+        "44": [0.19444, 0.10556, 0, 0],
+        "45": [0, 0.43056, 0.02826, 0],
+        "46": [0, 0.10556, 0, 0],
+        "47": [0.25, 0.75, 0.16194, 0],
+        "48": [0, 0.64444, 0.13556, 0],
+        "49": [0, 0.64444, 0.13556, 0],
+        "50": [0, 0.64444, 0.13556, 0],
+        "51": [0, 0.64444, 0.13556, 0],
+        "52": [0.19444, 0.64444, 0.13556, 0],
+        "53": [0, 0.64444, 0.13556, 0],
+        "54": [0, 0.64444, 0.13556, 0],
+        "55": [0.19444, 0.64444, 0.13556, 0],
+        "56": [0, 0.64444, 0.13556, 0],
+        "57": [0, 0.64444, 0.13556, 0],
+        "58": [0, 0.43056, 0.0582, 0],
+        "59": [0.19444, 0.43056, 0.0582, 0],
+        "61": [-0.13313, 0.36687, 0.06616, 0],
+        "63": [0, 0.69444, 0.1225, 0],
+        "64": [0, 0.69444, 0.09597, 0],
+        "65": [0, 0.68333, 0, 0],
+        "66": [0, 0.68333, 0.10257, 0],
+        "67": [0, 0.68333, 0.14528, 0],
+        "68": [0, 0.68333, 0.09403, 0],
+        "69": [0, 0.68333, 0.12028, 0],
+        "70": [0, 0.68333, 0.13305, 0],
+        "71": [0, 0.68333, 0.08722, 0],
+        "72": [0, 0.68333, 0.16389, 0],
+        "73": [0, 0.68333, 0.15806, 0],
+        "74": [0, 0.68333, 0.14028, 0],
+        "75": [0, 0.68333, 0.14528, 0],
+        "76": [0, 0.68333, 0, 0],
+        "77": [0, 0.68333, 0.16389, 0],
+        "78": [0, 0.68333, 0.16389, 0],
+        "79": [0, 0.68333, 0.09403, 0],
+        "80": [0, 0.68333, 0.10257, 0],
+        "81": [0.19444, 0.68333, 0.09403, 0],
+        "82": [0, 0.68333, 0.03868, 0],
+        "83": [0, 0.68333, 0.11972, 0],
+        "84": [0, 0.68333, 0.13305, 0],
+        "85": [0, 0.68333, 0.16389, 0],
+        "86": [0, 0.68333, 0.18361, 0],
+        "87": [0, 0.68333, 0.18361, 0],
+        "88": [0, 0.68333, 0.15806, 0],
+        "89": [0, 0.68333, 0.19383, 0],
+        "90": [0, 0.68333, 0.14528, 0],
+        "91": [0.25, 0.75, 0.1875, 0],
+        "93": [0.25, 0.75, 0.10528, 0],
+        "94": [0, 0.69444, 0.06646, 0],
+        "95": [0.31, 0.12056, 0.09208, 0],
+        "97": [0, 0.43056, 0.07671, 0],
+        "98": [0, 0.69444, 0.06312, 0],
+        "99": [0, 0.43056, 0.05653, 0],
+        "100": [0, 0.69444, 0.10333, 0],
+        "101": [0, 0.43056, 0.07514, 0],
+        "102": [0.19444, 0.69444, 0.21194, 0],
+        "103": [0.19444, 0.43056, 0.08847, 0],
+        "104": [0, 0.69444, 0.07671, 0],
+        "105": [0, 0.65536, 0.1019, 0],
+        "106": [0.19444, 0.65536, 0.14467, 0],
+        "107": [0, 0.69444, 0.10764, 0],
+        "108": [0, 0.69444, 0.10333, 0],
+        "109": [0, 0.43056, 0.07671, 0],
+        "110": [0, 0.43056, 0.07671, 0],
+        "111": [0, 0.43056, 0.06312, 0],
+        "112": [0.19444, 0.43056, 0.06312, 0],
+        "113": [0.19444, 0.43056, 0.08847, 0],
+        "114": [0, 0.43056, 0.10764, 0],
+        "115": [0, 0.43056, 0.08208, 0],
+        "116": [0, 0.61508, 0.09486, 0],
+        "117": [0, 0.43056, 0.07671, 0],
+        "118": [0, 0.43056, 0.10764, 0],
+        "119": [0, 0.43056, 0.10764, 0],
+        "120": [0, 0.43056, 0.12042, 0],
+        "121": [0.19444, 0.43056, 0.08847, 0],
+        "122": [0, 0.43056, 0.12292, 0],
+        "126": [0.35, 0.31786, 0.11585, 0],
+        "163": [0, 0.69444, 0, 0],
+        "305": [0, 0.43056, 0, 0.02778],
+        "567": [0.19444, 0.43056, 0, 0.08334],
+        "768": [0, 0.69444, 0, 0],
+        "769": [0, 0.69444, 0.09694, 0],
+        "770": [0, 0.69444, 0.06646, 0],
+        "771": [0, 0.66786, 0.11585, 0],
+        "772": [0, 0.56167, 0.10333, 0],
+        "774": [0, 0.69444, 0.10806, 0],
+        "775": [0, 0.66786, 0.11752, 0],
+        "776": [0, 0.66786, 0.10474, 0],
+        "778": [0, 0.69444, 0, 0],
+        "779": [0, 0.69444, 0.1225, 0],
+        "780": [0, 0.62847, 0.08295, 0],
+        "915": [0, 0.68333, 0.13305, 0],
+        "916": [0, 0.68333, 0, 0],
+        "920": [0, 0.68333, 0.09403, 0],
+        "923": [0, 0.68333, 0, 0],
+        "926": [0, 0.68333, 0.15294, 0],
+        "928": [0, 0.68333, 0.16389, 0],
+        "931": [0, 0.68333, 0.12028, 0],
+        "933": [0, 0.68333, 0.11111, 0],
+        "934": [0, 0.68333, 0.05986, 0],
+        "936": [0, 0.68333, 0.11111, 0],
+        "937": [0, 0.68333, 0.10257, 0],
+        "8211": [0, 0.43056, 0.09208, 0],
+        "8212": [0, 0.43056, 0.09208, 0],
+        "8216": [0, 0.69444, 0.12417, 0],
+        "8217": [0, 0.69444, 0.12417, 0],
+        "8220": [0, 0.69444, 0.1685, 0],
+        "8221": [0, 0.69444, 0.06961, 0],
+        "8463": [0, 0.68889, 0, 0]
+    },
+    "Main-Regular": {
+        "32": [0, 0, 0, 0],
+        "33": [0, 0.69444, 0, 0],
+        "34": [0, 0.69444, 0, 0],
+        "35": [0.19444, 0.69444, 0, 0],
+        "36": [0.05556, 0.75, 0, 0],
+        "37": [0.05556, 0.75, 0, 0],
+        "38": [0, 0.69444, 0, 0],
+        "39": [0, 0.69444, 0, 0],
+        "40": [0.25, 0.75, 0, 0],
+        "41": [0.25, 0.75, 0, 0],
+        "42": [0, 0.75, 0, 0],
+        "43": [0.08333, 0.58333, 0, 0],
+        "44": [0.19444, 0.10556, 0, 0],
+        "45": [0, 0.43056, 0, 0],
+        "46": [0, 0.10556, 0, 0],
+        "47": [0.25, 0.75, 0, 0],
+        "48": [0, 0.64444, 0, 0],
+        "49": [0, 0.64444, 0, 0],
+        "50": [0, 0.64444, 0, 0],
+        "51": [0, 0.64444, 0, 0],
+        "52": [0, 0.64444, 0, 0],
+        "53": [0, 0.64444, 0, 0],
+        "54": [0, 0.64444, 0, 0],
+        "55": [0, 0.64444, 0, 0],
+        "56": [0, 0.64444, 0, 0],
+        "57": [0, 0.64444, 0, 0],
+        "58": [0, 0.43056, 0, 0],
+        "59": [0.19444, 0.43056, 0, 0],
+        "60": [0.0391, 0.5391, 0, 0],
+        "61": [-0.13313, 0.36687, 0, 0],
+        "62": [0.0391, 0.5391, 0, 0],
+        "63": [0, 0.69444, 0, 0],
+        "64": [0, 0.69444, 0, 0],
+        "65": [0, 0.68333, 0, 0],
+        "66": [0, 0.68333, 0, 0],
+        "67": [0, 0.68333, 0, 0],
+        "68": [0, 0.68333, 0, 0],
+        "69": [0, 0.68333, 0, 0],
+        "70": [0, 0.68333, 0, 0],
+        "71": [0, 0.68333, 0, 0],
+        "72": [0, 0.68333, 0, 0],
+        "73": [0, 0.68333, 0, 0],
+        "74": [0, 0.68333, 0, 0],
+        "75": [0, 0.68333, 0, 0],
+        "76": [0, 0.68333, 0, 0],
+        "77": [0, 0.68333, 0, 0],
+        "78": [0, 0.68333, 0, 0],
+        "79": [0, 0.68333, 0, 0],
+        "80": [0, 0.68333, 0, 0],
+        "81": [0.19444, 0.68333, 0, 0],
+        "82": [0, 0.68333, 0, 0],
+        "83": [0, 0.68333, 0, 0],
+        "84": [0, 0.68333, 0, 0],
+        "85": [0, 0.68333, 0, 0],
+        "86": [0, 0.68333, 0.01389, 0],
+        "87": [0, 0.68333, 0.01389, 0],
+        "88": [0, 0.68333, 0, 0],
+        "89": [0, 0.68333, 0.025, 0],
+        "90": [0, 0.68333, 0, 0],
+        "91": [0.25, 0.75, 0, 0],
+        "92": [0.25, 0.75, 0, 0],
+        "93": [0.25, 0.75, 0, 0],
+        "94": [0, 0.69444, 0, 0],
+        "95": [0.31, 0.12056, 0.02778, 0],
+        "96": [0, 0.69444, 0, 0],
+        "97": [0, 0.43056, 0, 0],
+        "98": [0, 0.69444, 0, 0],
+        "99": [0, 0.43056, 0, 0],
+        "100": [0, 0.69444, 0, 0],
+        "101": [0, 0.43056, 0, 0],
+        "102": [0, 0.69444, 0.07778, 0],
+        "103": [0.19444, 0.43056, 0.01389, 0],
+        "104": [0, 0.69444, 0, 0],
+        "105": [0, 0.66786, 0, 0],
+        "106": [0.19444, 0.66786, 0, 0],
+        "107": [0, 0.69444, 0, 0],
+        "108": [0, 0.69444, 0, 0],
+        "109": [0, 0.43056, 0, 0],
+        "110": [0, 0.43056, 0, 0],
+        "111": [0, 0.43056, 0, 0],
+        "112": [0.19444, 0.43056, 0, 0],
+        "113": [0.19444, 0.43056, 0, 0],
+        "114": [0, 0.43056, 0, 0],
+        "115": [0, 0.43056, 0, 0],
+        "116": [0, 0.61508, 0, 0],
+        "117": [0, 0.43056, 0, 0],
+        "118": [0, 0.43056, 0.01389, 0],
+        "119": [0, 0.43056, 0.01389, 0],
+        "120": [0, 0.43056, 0, 0],
+        "121": [0.19444, 0.43056, 0.01389, 0],
+        "122": [0, 0.43056, 0, 0],
+        "123": [0.25, 0.75, 0, 0],
+        "124": [0.25, 0.75, 0, 0],
+        "125": [0.25, 0.75, 0, 0],
+        "126": [0.35, 0.31786, 0, 0],
+        "160": [0, 0, 0, 0],
+        "168": [0, 0.66786, 0, 0],
+        "172": [0, 0.43056, 0, 0],
+        "175": [0, 0.56778, 0, 0],
+        "176": [0, 0.69444, 0, 0],
+        "177": [0.08333, 0.58333, 0, 0],
+        "180": [0, 0.69444, 0, 0],
+        "215": [0.08333, 0.58333, 0, 0],
+        "247": [0.08333, 0.58333, 0, 0],
+        "305": [0, 0.43056, 0, 0],
+        "567": [0.19444, 0.43056, 0, 0],
+        "710": [0, 0.69444, 0, 0],
+        "711": [0, 0.62847, 0, 0],
+        "713": [0, 0.56778, 0, 0],
+        "714": [0, 0.69444, 0, 0],
+        "715": [0, 0.69444, 0, 0],
+        "728": [0, 0.69444, 0, 0],
+        "729": [0, 0.66786, 0, 0],
+        "730": [0, 0.69444, 0, 0],
+        "732": [0, 0.66786, 0, 0],
+        "768": [0, 0.69444, 0, 0],
+        "769": [0, 0.69444, 0, 0],
+        "770": [0, 0.69444, 0, 0],
+        "771": [0, 0.66786, 0, 0],
+        "772": [0, 0.56778, 0, 0],
+        "774": [0, 0.69444, 0, 0],
+        "775": [0, 0.66786, 0, 0],
+        "776": [0, 0.66786, 0, 0],
+        "778": [0, 0.69444, 0, 0],
+        "779": [0, 0.69444, 0, 0],
+        "780": [0, 0.62847, 0, 0],
+        "824": [0.19444, 0.69444, 0, 0],
+        "915": [0, 0.68333, 0, 0],
+        "916": [0, 0.68333, 0, 0],
+        "920": [0, 0.68333, 0, 0],
+        "923": [0, 0.68333, 0, 0],
+        "926": [0, 0.68333, 0, 0],
+        "928": [0, 0.68333, 0, 0],
+        "931": [0, 0.68333, 0, 0],
+        "933": [0, 0.68333, 0, 0],
+        "934": [0, 0.68333, 0, 0],
+        "936": [0, 0.68333, 0, 0],
+        "937": [0, 0.68333, 0, 0],
+        "8211": [0, 0.43056, 0.02778, 0],
+        "8212": [0, 0.43056, 0.02778, 0],
+        "8216": [0, 0.69444, 0, 0],
+        "8217": [0, 0.69444, 0, 0],
+        "8220": [0, 0.69444, 0, 0],
+        "8221": [0, 0.69444, 0, 0],
+        "8224": [0.19444, 0.69444, 0, 0],
+        "8225": [0.19444, 0.69444, 0, 0],
+        "8230": [0, 0.12, 0, 0],
+        "8242": [0, 0.55556, 0, 0],
+        "8407": [0, 0.71444, 0.15382, 0],
+        "8463": [0, 0.68889, 0, 0],
+        "8465": [0, 0.69444, 0, 0],
+        "8467": [0, 0.69444, 0, 0.11111],
+        "8472": [0.19444, 0.43056, 0, 0.11111],
+        "8476": [0, 0.69444, 0, 0],
+        "8501": [0, 0.69444, 0, 0],
+        "8592": [-0.13313, 0.36687, 0, 0],
+        "8593": [0.19444, 0.69444, 0, 0],
+        "8594": [-0.13313, 0.36687, 0, 0],
+        "8595": [0.19444, 0.69444, 0, 0],
+        "8596": [-0.13313, 0.36687, 0, 0],
+        "8597": [0.25, 0.75, 0, 0],
+        "8598": [0.19444, 0.69444, 0, 0],
+        "8599": [0.19444, 0.69444, 0, 0],
+        "8600": [0.19444, 0.69444, 0, 0],
+        "8601": [0.19444, 0.69444, 0, 0],
+        "8614": [0.011, 0.511, 0, 0],
+        "8617": [0.011, 0.511, 0, 0],
+        "8618": [0.011, 0.511, 0, 0],
+        "8636": [-0.13313, 0.36687, 0, 0],
+        "8637": [-0.13313, 0.36687, 0, 0],
+        "8640": [-0.13313, 0.36687, 0, 0],
+        "8641": [-0.13313, 0.36687, 0, 0],
+        "8652": [0.011, 0.671, 0, 0],
+        "8656": [-0.13313, 0.36687, 0, 0],
+        "8657": [0.19444, 0.69444, 0, 0],
+        "8658": [-0.13313, 0.36687, 0, 0],
+        "8659": [0.19444, 0.69444, 0, 0],
+        "8660": [-0.13313, 0.36687, 0, 0],
+        "8661": [0.25, 0.75, 0, 0],
+        "8704": [0, 0.69444, 0, 0],
+        "8706": [0, 0.69444, 0.05556, 0.08334],
+        "8707": [0, 0.69444, 0, 0],
+        "8709": [0.05556, 0.75, 0, 0],
+        "8711": [0, 0.68333, 0, 0],
+        "8712": [0.0391, 0.5391, 0, 0],
+        "8715": [0.0391, 0.5391, 0, 0],
+        "8722": [0.08333, 0.58333, 0, 0],
+        "8723": [0.08333, 0.58333, 0, 0],
+        "8725": [0.25, 0.75, 0, 0],
+        "8726": [0.25, 0.75, 0, 0],
+        "8727": [-0.03472, 0.46528, 0, 0],
+        "8728": [-0.05555, 0.44445, 0, 0],
+        "8729": [-0.05555, 0.44445, 0, 0],
+        "8730": [0.2, 0.8, 0, 0],
+        "8733": [0, 0.43056, 0, 0],
+        "8734": [0, 0.43056, 0, 0],
+        "8736": [0, 0.69224, 0, 0],
+        "8739": [0.25, 0.75, 0, 0],
+        "8741": [0.25, 0.75, 0, 0],
+        "8743": [0, 0.55556, 0, 0],
+        "8744": [0, 0.55556, 0, 0],
+        "8745": [0, 0.55556, 0, 0],
+        "8746": [0, 0.55556, 0, 0],
+        "8747": [0.19444, 0.69444, 0.11111, 0],
+        "8764": [-0.13313, 0.36687, 0, 0],
+        "8768": [0.19444, 0.69444, 0, 0],
+        "8771": [-0.03625, 0.46375, 0, 0],
+        "8773": [-0.022, 0.589, 0, 0],
+        "8776": [-0.01688, 0.48312, 0, 0],
+        "8781": [-0.03625, 0.46375, 0, 0],
+        "8784": [-0.133, 0.67, 0, 0],
+        "8800": [0.215, 0.716, 0, 0],
+        "8801": [-0.03625, 0.46375, 0, 0],
+        "8804": [0.13597, 0.63597, 0, 0],
+        "8805": [0.13597, 0.63597, 0, 0],
+        "8810": [0.0391, 0.5391, 0, 0],
+        "8811": [0.0391, 0.5391, 0, 0],
+        "8826": [0.0391, 0.5391, 0, 0],
+        "8827": [0.0391, 0.5391, 0, 0],
+        "8834": [0.0391, 0.5391, 0, 0],
+        "8835": [0.0391, 0.5391, 0, 0],
+        "8838": [0.13597, 0.63597, 0, 0],
+        "8839": [0.13597, 0.63597, 0, 0],
+        "8846": [0, 0.55556, 0, 0],
+        "8849": [0.13597, 0.63597, 0, 0],
+        "8850": [0.13597, 0.63597, 0, 0],
+        "8851": [0, 0.55556, 0, 0],
+        "8852": [0, 0.55556, 0, 0],
+        "8853": [0.08333, 0.58333, 0, 0],
+        "8854": [0.08333, 0.58333, 0, 0],
+        "8855": [0.08333, 0.58333, 0, 0],
+        "8856": [0.08333, 0.58333, 0, 0],
+        "8857": [0.08333, 0.58333, 0, 0],
+        "8866": [0, 0.69444, 0, 0],
+        "8867": [0, 0.69444, 0, 0],
+        "8868": [0, 0.69444, 0, 0],
+        "8869": [0, 0.69444, 0, 0],
+        "8872": [0.249, 0.75, 0, 0],
+        "8900": [-0.05555, 0.44445, 0, 0],
+        "8901": [-0.05555, 0.44445, 0, 0],
+        "8902": [-0.03472, 0.46528, 0, 0],
+        "8904": [0.005, 0.505, 0, 0],
+        "8942": [0.03, 0.9, 0, 0],
+        "8943": [-0.19, 0.31, 0, 0],
+        "8945": [-0.1, 0.82, 0, 0],
+        "8968": [0.25, 0.75, 0, 0],
+        "8969": [0.25, 0.75, 0, 0],
+        "8970": [0.25, 0.75, 0, 0],
+        "8971": [0.25, 0.75, 0, 0],
+        "8994": [-0.14236, 0.35764, 0, 0],
+        "8995": [-0.14236, 0.35764, 0, 0],
+        "9136": [0.244, 0.744, 0, 0],
+        "9137": [0.244, 0.744, 0, 0],
+        "9651": [0.19444, 0.69444, 0, 0],
+        "9657": [-0.03472, 0.46528, 0, 0],
+        "9661": [0.19444, 0.69444, 0, 0],
+        "9667": [-0.03472, 0.46528, 0, 0],
+        "9711": [0.19444, 0.69444, 0, 0],
+        "9824": [0.12963, 0.69444, 0, 0],
+        "9825": [0.12963, 0.69444, 0, 0],
+        "9826": [0.12963, 0.69444, 0, 0],
+        "9827": [0.12963, 0.69444, 0, 0],
+        "9837": [0, 0.75, 0, 0],
+        "9838": [0.19444, 0.69444, 0, 0],
+        "9839": [0.19444, 0.69444, 0, 0],
+        "10216": [0.25, 0.75, 0, 0],
+        "10217": [0.25, 0.75, 0, 0],
+        "10222": [0.244, 0.744, 0, 0],
+        "10223": [0.244, 0.744, 0, 0],
+        "10229": [0.011, 0.511, 0, 0],
+        "10230": [0.011, 0.511, 0, 0],
+        "10231": [0.011, 0.511, 0, 0],
+        "10232": [0.024, 0.525, 0, 0],
+        "10233": [0.024, 0.525, 0, 0],
+        "10234": [0.024, 0.525, 0, 0],
+        "10236": [0.011, 0.511, 0, 0],
+        "10815": [0, 0.68333, 0, 0],
+        "10927": [0.13597, 0.63597, 0, 0],
+        "10928": [0.13597, 0.63597, 0, 0]
+    },
+    "Math-BoldItalic": {
+        "47": [0.19444, 0.69444, 0, 0],
+        "65": [0, 0.68611, 0, 0],
+        "66": [0, 0.68611, 0.04835, 0],
+        "67": [0, 0.68611, 0.06979, 0],
+        "68": [0, 0.68611, 0.03194, 0],
+        "69": [0, 0.68611, 0.05451, 0],
+        "70": [0, 0.68611, 0.15972, 0],
+        "71": [0, 0.68611, 0, 0],
+        "72": [0, 0.68611, 0.08229, 0],
+        "73": [0, 0.68611, 0.07778, 0],
+        "74": [0, 0.68611, 0.10069, 0],
+        "75": [0, 0.68611, 0.06979, 0],
+        "76": [0, 0.68611, 0, 0],
+        "77": [0, 0.68611, 0.11424, 0],
+        "78": [0, 0.68611, 0.11424, 0],
+        "79": [0, 0.68611, 0.03194, 0],
+        "80": [0, 0.68611, 0.15972, 0],
+        "81": [0.19444, 0.68611, 0, 0],
+        "82": [0, 0.68611, 0.00421, 0],
+        "83": [0, 0.68611, 0.05382, 0],
+        "84": [0, 0.68611, 0.15972, 0],
+        "85": [0, 0.68611, 0.11424, 0],
+        "86": [0, 0.68611, 0.25555, 0],
+        "87": [0, 0.68611, 0.15972, 0],
+        "88": [0, 0.68611, 0.07778, 0],
+        "89": [0, 0.68611, 0.25555, 0],
+        "90": [0, 0.68611, 0.06979, 0],
+        "97": [0, 0.44444, 0, 0],
+        "98": [0, 0.69444, 0, 0],
+        "99": [0, 0.44444, 0, 0],
+        "100": [0, 0.69444, 0, 0],
+        "101": [0, 0.44444, 0, 0],
+        "102": [0.19444, 0.69444, 0.11042, 0],
+        "103": [0.19444, 0.44444, 0.03704, 0],
+        "104": [0, 0.69444, 0, 0],
+        "105": [0, 0.69326, 0, 0],
+        "106": [0.19444, 0.69326, 0.0622, 0],
+        "107": [0, 0.69444, 0.01852, 0],
+        "108": [0, 0.69444, 0.0088, 0],
+        "109": [0, 0.44444, 0, 0],
+        "110": [0, 0.44444, 0, 0],
+        "111": [0, 0.44444, 0, 0],
+        "112": [0.19444, 0.44444, 0, 0],
+        "113": [0.19444, 0.44444, 0.03704, 0],
+        "114": [0, 0.44444, 0.03194, 0],
+        "115": [0, 0.44444, 0, 0],
+        "116": [0, 0.63492, 0, 0],
+        "117": [0, 0.44444, 0, 0],
+        "118": [0, 0.44444, 0.03704, 0],
+        "119": [0, 0.44444, 0.02778, 0],
+        "120": [0, 0.44444, 0, 0],
+        "121": [0.19444, 0.44444, 0.03704, 0],
+        "122": [0, 0.44444, 0.04213, 0],
+        "915": [0, 0.68611, 0.15972, 0],
+        "916": [0, 0.68611, 0, 0],
+        "920": [0, 0.68611, 0.03194, 0],
+        "923": [0, 0.68611, 0, 0],
+        "926": [0, 0.68611, 0.07458, 0],
+        "928": [0, 0.68611, 0.08229, 0],
+        "931": [0, 0.68611, 0.05451, 0],
+        "933": [0, 0.68611, 0.15972, 0],
+        "934": [0, 0.68611, 0, 0],
+        "936": [0, 0.68611, 0.11653, 0],
+        "937": [0, 0.68611, 0.04835, 0],
+        "945": [0, 0.44444, 0, 0],
+        "946": [0.19444, 0.69444, 0.03403, 0],
+        "947": [0.19444, 0.44444, 0.06389, 0],
+        "948": [0, 0.69444, 0.03819, 0],
+        "949": [0, 0.44444, 0, 0],
+        "950": [0.19444, 0.69444, 0.06215, 0],
+        "951": [0.19444, 0.44444, 0.03704, 0],
+        "952": [0, 0.69444, 0.03194, 0],
+        "953": [0, 0.44444, 0, 0],
+        "954": [0, 0.44444, 0, 0],
+        "955": [0, 0.69444, 0, 0],
+        "956": [0.19444, 0.44444, 0, 0],
+        "957": [0, 0.44444, 0.06898, 0],
+        "958": [0.19444, 0.69444, 0.03021, 0],
+        "959": [0, 0.44444, 0, 0],
+        "960": [0, 0.44444, 0.03704, 0],
+        "961": [0.19444, 0.44444, 0, 0],
+        "962": [0.09722, 0.44444, 0.07917, 0],
+        "963": [0, 0.44444, 0.03704, 0],
+        "964": [0, 0.44444, 0.13472, 0],
+        "965": [0, 0.44444, 0.03704, 0],
+        "966": [0.19444, 0.44444, 0, 0],
+        "967": [0.19444, 0.44444, 0, 0],
+        "968": [0.19444, 0.69444, 0.03704, 0],
+        "969": [0, 0.44444, 0.03704, 0],
+        "977": [0, 0.69444, 0, 0],
+        "981": [0.19444, 0.69444, 0, 0],
+        "982": [0, 0.44444, 0.03194, 0],
+        "1009": [0.19444, 0.44444, 0, 0],
+        "1013": [0, 0.44444, 0, 0]
+    },
+    "Math-Italic": {
+        "47": [0.19444, 0.69444, 0, 0],
+        "65": [0, 0.68333, 0, 0.13889],
+        "66": [0, 0.68333, 0.05017, 0.08334],
+        "67": [0, 0.68333, 0.07153, 0.08334],
+        "68": [0, 0.68333, 0.02778, 0.05556],
+        "69": [0, 0.68333, 0.05764, 0.08334],
+        "70": [0, 0.68333, 0.13889, 0.08334],
+        "71": [0, 0.68333, 0, 0.08334],
+        "72": [0, 0.68333, 0.08125, 0.05556],
+        "73": [0, 0.68333, 0.07847, 0.11111],
+        "74": [0, 0.68333, 0.09618, 0.16667],
+        "75": [0, 0.68333, 0.07153, 0.05556],
+        "76": [0, 0.68333, 0, 0.02778],
+        "77": [0, 0.68333, 0.10903, 0.08334],
+        "78": [0, 0.68333, 0.10903, 0.08334],
+        "79": [0, 0.68333, 0.02778, 0.08334],
+        "80": [0, 0.68333, 0.13889, 0.08334],
+        "81": [0.19444, 0.68333, 0, 0.08334],
+        "82": [0, 0.68333, 0.00773, 0.08334],
+        "83": [0, 0.68333, 0.05764, 0.08334],
+        "84": [0, 0.68333, 0.13889, 0.08334],
+        "85": [0, 0.68333, 0.10903, 0.02778],
+        "86": [0, 0.68333, 0.22222, 0],
+        "87": [0, 0.68333, 0.13889, 0],
+        "88": [0, 0.68333, 0.07847, 0.08334],
+        "89": [0, 0.68333, 0.22222, 0],
+        "90": [0, 0.68333, 0.07153, 0.08334],
+        "97": [0, 0.43056, 0, 0],
+        "98": [0, 0.69444, 0, 0],
+        "99": [0, 0.43056, 0, 0.05556],
+        "100": [0, 0.69444, 0, 0.16667],
+        "101": [0, 0.43056, 0, 0.05556],
+        "102": [0.19444, 0.69444, 0.10764, 0.16667],
+        "103": [0.19444, 0.43056, 0.03588, 0.02778],
+        "104": [0, 0.69444, 0, 0],
+        "105": [0, 0.65952, 0, 0],
+        "106": [0.19444, 0.65952, 0.05724, 0],
+        "107": [0, 0.69444, 0.03148, 0],
+        "108": [0, 0.69444, 0.01968, 0.08334],
+        "109": [0, 0.43056, 0, 0],
+        "110": [0, 0.43056, 0, 0],
+        "111": [0, 0.43056, 0, 0.05556],
+        "112": [0.19444, 0.43056, 0, 0.08334],
+        "113": [0.19444, 0.43056, 0.03588, 0.08334],
+        "114": [0, 0.43056, 0.02778, 0.05556],
+        "115": [0, 0.43056, 0, 0.05556],
+        "116": [0, 0.61508, 0, 0.08334],
+        "117": [0, 0.43056, 0, 0.02778],
+        "118": [0, 0.43056, 0.03588, 0.02778],
+        "119": [0, 0.43056, 0.02691, 0.08334],
+        "120": [0, 0.43056, 0, 0.02778],
+        "121": [0.19444, 0.43056, 0.03588, 0.05556],
+        "122": [0, 0.43056, 0.04398, 0.05556],
+        "915": [0, 0.68333, 0.13889, 0.08334],
+        "916": [0, 0.68333, 0, 0.16667],
+        "920": [0, 0.68333, 0.02778, 0.08334],
+        "923": [0, 0.68333, 0, 0.16667],
+        "926": [0, 0.68333, 0.07569, 0.08334],
+        "928": [0, 0.68333, 0.08125, 0.05556],
+        "931": [0, 0.68333, 0.05764, 0.08334],
+        "933": [0, 0.68333, 0.13889, 0.05556],
+        "934": [0, 0.68333, 0, 0.08334],
+        "936": [0, 0.68333, 0.11, 0.05556],
+        "937": [0, 0.68333, 0.05017, 0.08334],
+        "945": [0, 0.43056, 0.0037, 0.02778],
+        "946": [0.19444, 0.69444, 0.05278, 0.08334],
+        "947": [0.19444, 0.43056, 0.05556, 0],
+        "948": [0, 0.69444, 0.03785, 0.05556],
+        "949": [0, 0.43056, 0, 0.08334],
+        "950": [0.19444, 0.69444, 0.07378, 0.08334],
+        "951": [0.19444, 0.43056, 0.03588, 0.05556],
+        "952": [0, 0.69444, 0.02778, 0.08334],
+        "953": [0, 0.43056, 0, 0.05556],
+        "954": [0, 0.43056, 0, 0],
+        "955": [0, 0.69444, 0, 0],
+        "956": [0.19444, 0.43056, 0, 0.02778],
+        "957": [0, 0.43056, 0.06366, 0.02778],
+        "958": [0.19444, 0.69444, 0.04601, 0.11111],
+        "959": [0, 0.43056, 0, 0.05556],
+        "960": [0, 0.43056, 0.03588, 0],
+        "961": [0.19444, 0.43056, 0, 0.08334],
+        "962": [0.09722, 0.43056, 0.07986, 0.08334],
+        "963": [0, 0.43056, 0.03588, 0],
+        "964": [0, 0.43056, 0.1132, 0.02778],
+        "965": [0, 0.43056, 0.03588, 0.02778],
+        "966": [0.19444, 0.43056, 0, 0.08334],
+        "967": [0.19444, 0.43056, 0, 0.05556],
+        "968": [0.19444, 0.69444, 0.03588, 0.11111],
+        "969": [0, 0.43056, 0.03588, 0],
+        "977": [0, 0.69444, 0, 0.08334],
+        "981": [0.19444, 0.69444, 0, 0.08334],
+        "982": [0, 0.43056, 0.02778, 0],
+        "1009": [0.19444, 0.43056, 0, 0.08334],
+        "1013": [0, 0.43056, 0, 0.05556]
+    },
+    "Math-Regular": {
+        "65": [0, 0.68333, 0, 0.13889],
+        "66": [0, 0.68333, 0.05017, 0.08334],
+        "67": [0, 0.68333, 0.07153, 0.08334],
+        "68": [0, 0.68333, 0.02778, 0.05556],
+        "69": [0, 0.68333, 0.05764, 0.08334],
+        "70": [0, 0.68333, 0.13889, 0.08334],
+        "71": [0, 0.68333, 0, 0.08334],
+        "72": [0, 0.68333, 0.08125, 0.05556],
+        "73": [0, 0.68333, 0.07847, 0.11111],
+        "74": [0, 0.68333, 0.09618, 0.16667],
+        "75": [0, 0.68333, 0.07153, 0.05556],
+        "76": [0, 0.68333, 0, 0.02778],
+        "77": [0, 0.68333, 0.10903, 0.08334],
+        "78": [0, 0.68333, 0.10903, 0.08334],
+        "79": [0, 0.68333, 0.02778, 0.08334],
+        "80": [0, 0.68333, 0.13889, 0.08334],
+        "81": [0.19444, 0.68333, 0, 0.08334],
+        "82": [0, 0.68333, 0.00773, 0.08334],
+        "83": [0, 0.68333, 0.05764, 0.08334],
+        "84": [0, 0.68333, 0.13889, 0.08334],
+        "85": [0, 0.68333, 0.10903, 0.02778],
+        "86": [0, 0.68333, 0.22222, 0],
+        "87": [0, 0.68333, 0.13889, 0],
+        "88": [0, 0.68333, 0.07847, 0.08334],
+        "89": [0, 0.68333, 0.22222, 0],
+        "90": [0, 0.68333, 0.07153, 0.08334],
+        "97": [0, 0.43056, 0, 0],
+        "98": [0, 0.69444, 0, 0],
+        "99": [0, 0.43056, 0, 0.05556],
+        "100": [0, 0.69444, 0, 0.16667],
+        "101": [0, 0.43056, 0, 0.05556],
+        "102": [0.19444, 0.69444, 0.10764, 0.16667],
+        "103": [0.19444, 0.43056, 0.03588, 0.02778],
+        "104": [0, 0.69444, 0, 0],
+        "105": [0, 0.65952, 0, 0],
+        "106": [0.19444, 0.65952, 0.05724, 0],
+        "107": [0, 0.69444, 0.03148, 0],
+        "108": [0, 0.69444, 0.01968, 0.08334],
+        "109": [0, 0.43056, 0, 0],
+        "110": [0, 0.43056, 0, 0],
+        "111": [0, 0.43056, 0, 0.05556],
+        "112": [0.19444, 0.43056, 0, 0.08334],
+        "113": [0.19444, 0.43056, 0.03588, 0.08334],
+        "114": [0, 0.43056, 0.02778, 0.05556],
+        "115": [0, 0.43056, 0, 0.05556],
+        "116": [0, 0.61508, 0, 0.08334],
+        "117": [0, 0.43056, 0, 0.02778],
+        "118": [0, 0.43056, 0.03588, 0.02778],
+        "119": [0, 0.43056, 0.02691, 0.08334],
+        "120": [0, 0.43056, 0, 0.02778],
+        "121": [0.19444, 0.43056, 0.03588, 0.05556],
+        "122": [0, 0.43056, 0.04398, 0.05556],
+        "915": [0, 0.68333, 0.13889, 0.08334],
+        "916": [0, 0.68333, 0, 0.16667],
+        "920": [0, 0.68333, 0.02778, 0.08334],
+        "923": [0, 0.68333, 0, 0.16667],
+        "926": [0, 0.68333, 0.07569, 0.08334],
+        "928": [0, 0.68333, 0.08125, 0.05556],
+        "931": [0, 0.68333, 0.05764, 0.08334],
+        "933": [0, 0.68333, 0.13889, 0.05556],
+        "934": [0, 0.68333, 0, 0.08334],
+        "936": [0, 0.68333, 0.11, 0.05556],
+        "937": [0, 0.68333, 0.05017, 0.08334],
+        "945": [0, 0.43056, 0.0037, 0.02778],
+        "946": [0.19444, 0.69444, 0.05278, 0.08334],
+        "947": [0.19444, 0.43056, 0.05556, 0],
+        "948": [0, 0.69444, 0.03785, 0.05556],
+        "949": [0, 0.43056, 0, 0.08334],
+        "950": [0.19444, 0.69444, 0.07378, 0.08334],
+        "951": [0.19444, 0.43056, 0.03588, 0.05556],
+        "952": [0, 0.69444, 0.02778, 0.08334],
+        "953": [0, 0.43056, 0, 0.05556],
+        "954": [0, 0.43056, 0, 0],
+        "955": [0, 0.69444, 0, 0],
+        "956": [0.19444, 0.43056, 0, 0.02778],
+        "957": [0, 0.43056, 0.06366, 0.02778],
+        "958": [0.19444, 0.69444, 0.04601, 0.11111],
+        "959": [0, 0.43056, 0, 0.05556],
+        "960": [0, 0.43056, 0.03588, 0],
+        "961": [0.19444, 0.43056, 0, 0.08334],
+        "962": [0.09722, 0.43056, 0.07986, 0.08334],
+        "963": [0, 0.43056, 0.03588, 0],
+        "964": [0, 0.43056, 0.1132, 0.02778],
+        "965": [0, 0.43056, 0.03588, 0.02778],
+        "966": [0.19444, 0.43056, 0, 0.08334],
+        "967": [0.19444, 0.43056, 0, 0.05556],
+        "968": [0.19444, 0.69444, 0.03588, 0.11111],
+        "969": [0, 0.43056, 0.03588, 0],
+        "977": [0, 0.69444, 0, 0.08334],
+        "981": [0.19444, 0.69444, 0, 0.08334],
+        "982": [0, 0.43056, 0.02778, 0],
+        "1009": [0.19444, 0.43056, 0, 0.08334],
+        "1013": [0, 0.43056, 0, 0.05556]
+    },
+    "SansSerif-Regular": {
+        "33": [0, 0.69444, 0, 0],
+        "34": [0, 0.69444, 0, 0],
+        "35": [0.19444, 0.69444, 0, 0],
+        "36": [0.05556, 0.75, 0, 0],
+        "37": [0.05556, 0.75, 0, 0],
+        "38": [0, 0.69444, 0, 0],
+        "39": [0, 0.69444, 0, 0],
+        "40": [0.25, 0.75, 0, 0],
+        "41": [0.25, 0.75, 0, 0],
+        "42": [0, 0.75, 0, 0],
+        "43": [0.08333, 0.58333, 0, 0],
+        "44": [0.125, 0.08333, 0, 0],
+        "45": [0, 0.44444, 0, 0],
+        "46": [0, 0.08333, 0, 0],
+        "47": [0.25, 0.75, 0, 0],
+        "48": [0, 0.65556, 0, 0],
+        "49": [0, 0.65556, 0, 0],
+        "50": [0, 0.65556, 0, 0],
+        "51": [0, 0.65556, 0, 0],
+        "52": [0, 0.65556, 0, 0],
+        "53": [0, 0.65556, 0, 0],
+        "54": [0, 0.65556, 0, 0],
+        "55": [0, 0.65556, 0, 0],
+        "56": [0, 0.65556, 0, 0],
+        "57": [0, 0.65556, 0, 0],
+        "58": [0, 0.44444, 0, 0],
+        "59": [0.125, 0.44444, 0, 0],
+        "61": [-0.13, 0.37, 0, 0],
+        "63": [0, 0.69444, 0, 0],
+        "64": [0, 0.69444, 0, 0],
+        "65": [0, 0.69444, 0, 0],
+        "66": [0, 0.69444, 0, 0],
+        "67": [0, 0.69444, 0, 0],
+        "68": [0, 0.69444, 0, 0],
+        "69": [0, 0.69444, 0, 0],
+        "70": [0, 0.69444, 0, 0],
+        "71": [0, 0.69444, 0, 0],
+        "72": [0, 0.69444, 0, 0],
+        "73": [0, 0.69444, 0, 0],
+        "74": [0, 0.69444, 0, 0],
+        "75": [0, 0.69444, 0, 0],
+        "76": [0, 0.69444, 0, 0],
+        "77": [0, 0.69444, 0, 0],
+        "78": [0, 0.69444, 0, 0],
+        "79": [0, 0.69444, 0, 0],
+        "80": [0, 0.69444, 0, 0],
+        "81": [0.125, 0.69444, 0, 0],
+        "82": [0, 0.69444, 0, 0],
+        "83": [0, 0.69444, 0, 0],
+        "84": [0, 0.69444, 0, 0],
+        "85": [0, 0.69444, 0, 0],
+        "86": [0, 0.69444, 0.01389, 0],
+        "87": [0, 0.69444, 0.01389, 0],
+        "88": [0, 0.69444, 0, 0],
+        "89": [0, 0.69444, 0.025, 0],
+        "90": [0, 0.69444, 0, 0],
+        "91": [0.25, 0.75, 0, 0],
+        "93": [0.25, 0.75, 0, 0],
+        "94": [0, 0.69444, 0, 0],
+        "95": [0.35, 0.09444, 0.02778, 0],
+        "97": [0, 0.44444, 0, 0],
+        "98": [0, 0.69444, 0, 0],
+        "99": [0, 0.44444, 0, 0],
+        "100": [0, 0.69444, 0, 0],
+        "101": [0, 0.44444, 0, 0],
+        "102": [0, 0.69444, 0.06944, 0],
+        "103": [0.19444, 0.44444, 0.01389, 0],
+        "104": [0, 0.69444, 0, 0],
+        "105": [0, 0.67937, 0, 0],
+        "106": [0.19444, 0.67937, 0, 0],
+        "107": [0, 0.69444, 0, 0],
+        "108": [0, 0.69444, 0, 0],
+        "109": [0, 0.44444, 0, 0],
+        "110": [0, 0.44444, 0, 0],
+        "111": [0, 0.44444, 0, 0],
+        "112": [0.19444, 0.44444, 0, 0],
+        "113": [0.19444, 0.44444, 0, 0],
+        "114": [0, 0.44444, 0.01389, 0],
+        "115": [0, 0.44444, 0, 0],
+        "116": [0, 0.57143, 0, 0],
+        "117": [0, 0.44444, 0, 0],
+        "118": [0, 0.44444, 0.01389, 0],
+        "119": [0, 0.44444, 0.01389, 0],
+        "120": [0, 0.44444, 0, 0],
+        "121": [0.19444, 0.44444, 0.01389, 0],
+        "122": [0, 0.44444, 0, 0],
+        "126": [0.35, 0.32659, 0, 0],
+        "305": [0, 0.44444, 0, 0],
+        "567": [0.19444, 0.44444, 0, 0],
+        "768": [0, 0.69444, 0, 0],
+        "769": [0, 0.69444, 0, 0],
+        "770": [0, 0.69444, 0, 0],
+        "771": [0, 0.67659, 0, 0],
+        "772": [0, 0.60889, 0, 0],
+        "774": [0, 0.69444, 0, 0],
+        "775": [0, 0.67937, 0, 0],
+        "776": [0, 0.67937, 0, 0],
+        "778": [0, 0.69444, 0, 0],
+        "779": [0, 0.69444, 0, 0],
+        "780": [0, 0.63194, 0, 0],
+        "915": [0, 0.69444, 0, 0],
+        "916": [0, 0.69444, 0, 0],
+        "920": [0, 0.69444, 0, 0],
+        "923": [0, 0.69444, 0, 0],
+        "926": [0, 0.69444, 0, 0],
+        "928": [0, 0.69444, 0, 0],
+        "931": [0, 0.69444, 0, 0],
+        "933": [0, 0.69444, 0, 0],
+        "934": [0, 0.69444, 0, 0],
+        "936": [0, 0.69444, 0, 0],
+        "937": [0, 0.69444, 0, 0],
+        "8211": [0, 0.44444, 0.02778, 0],
+        "8212": [0, 0.44444, 0.02778, 0],
+        "8216": [0, 0.69444, 0, 0],
+        "8217": [0, 0.69444, 0, 0],
+        "8220": [0, 0.69444, 0, 0],
+        "8221": [0, 0.69444, 0, 0]
+    },
+    "Script-Regular": {
+        "65": [0, 0.7, 0.22925, 0],
+        "66": [0, 0.7, 0.04087, 0],
+        "67": [0, 0.7, 0.1689, 0],
+        "68": [0, 0.7, 0.09371, 0],
+        "69": [0, 0.7, 0.18583, 0],
+        "70": [0, 0.7, 0.13634, 0],
+        "71": [0, 0.7, 0.17322, 0],
+        "72": [0, 0.7, 0.29694, 0],
+        "73": [0, 0.7, 0.19189, 0],
+        "74": [0.27778, 0.7, 0.19189, 0],
+        "75": [0, 0.7, 0.31259, 0],
+        "76": [0, 0.7, 0.19189, 0],
+        "77": [0, 0.7, 0.15981, 0],
+        "78": [0, 0.7, 0.3525, 0],
+        "79": [0, 0.7, 0.08078, 0],
+        "80": [0, 0.7, 0.08078, 0],
+        "81": [0, 0.7, 0.03305, 0],
+        "82": [0, 0.7, 0.06259, 0],
+        "83": [0, 0.7, 0.19189, 0],
+        "84": [0, 0.7, 0.29087, 0],
+        "85": [0, 0.7, 0.25815, 0],
+        "86": [0, 0.7, 0.27523, 0],
+        "87": [0, 0.7, 0.27523, 0],
+        "88": [0, 0.7, 0.26006, 0],
+        "89": [0, 0.7, 0.2939, 0],
+        "90": [0, 0.7, 0.24037, 0]
+    },
+    "Size1-Regular": {
+        "40": [0.35001, 0.85, 0, 0],
+        "41": [0.35001, 0.85, 0, 0],
+        "47": [0.35001, 0.85, 0, 0],
+        "91": [0.35001, 0.85, 0, 0],
+        "92": [0.35001, 0.85, 0, 0],
+        "93": [0.35001, 0.85, 0, 0],
+        "123": [0.35001, 0.85, 0, 0],
+        "125": [0.35001, 0.85, 0, 0],
+        "710": [0, 0.72222, 0, 0],
+        "732": [0, 0.72222, 0, 0],
+        "770": [0, 0.72222, 0, 0],
+        "771": [0, 0.72222, 0, 0],
+        "8214": [-0.00099, 0.601, 0, 0],
+        "8593": [1e-05, 0.6, 0, 0],
+        "8595": [1e-05, 0.6, 0, 0],
+        "8657": [1e-05, 0.6, 0, 0],
+        "8659": [1e-05, 0.6, 0, 0],
+        "8719": [0.25001, 0.75, 0, 0],
+        "8720": [0.25001, 0.75, 0, 0],
+        "8721": [0.25001, 0.75, 0, 0],
+        "8730": [0.35001, 0.85, 0, 0],
+        "8739": [-0.00599, 0.606, 0, 0],
+        "8741": [-0.00599, 0.606, 0, 0],
+        "8747": [0.30612, 0.805, 0.19445, 0],
+        "8748": [0.306, 0.805, 0.19445, 0],
+        "8749": [0.306, 0.805, 0.19445, 0],
+        "8750": [0.30612, 0.805, 0.19445, 0],
+        "8896": [0.25001, 0.75, 0, 0],
+        "8897": [0.25001, 0.75, 0, 0],
+        "8898": [0.25001, 0.75, 0, 0],
+        "8899": [0.25001, 0.75, 0, 0],
+        "8968": [0.35001, 0.85, 0, 0],
+        "8969": [0.35001, 0.85, 0, 0],
+        "8970": [0.35001, 0.85, 0, 0],
+        "8971": [0.35001, 0.85, 0, 0],
+        "9168": [-0.00099, 0.601, 0, 0],
+        "10216": [0.35001, 0.85, 0, 0],
+        "10217": [0.35001, 0.85, 0, 0],
+        "10752": [0.25001, 0.75, 0, 0],
+        "10753": [0.25001, 0.75, 0, 0],
+        "10754": [0.25001, 0.75, 0, 0],
+        "10756": [0.25001, 0.75, 0, 0],
+        "10758": [0.25001, 0.75, 0, 0]
+    },
+    "Size2-Regular": {
+        "40": [0.65002, 1.15, 0, 0],
+        "41": [0.65002, 1.15, 0, 0],
+        "47": [0.65002, 1.15, 0, 0],
+        "91": [0.65002, 1.15, 0, 0],
+        "92": [0.65002, 1.15, 0, 0],
+        "93": [0.65002, 1.15, 0, 0],
+        "123": [0.65002, 1.15, 0, 0],
+        "125": [0.65002, 1.15, 0, 0],
+        "710": [0, 0.75, 0, 0],
+        "732": [0, 0.75, 0, 0],
+        "770": [0, 0.75, 0, 0],
+        "771": [0, 0.75, 0, 0],
+        "8719": [0.55001, 1.05, 0, 0],
+        "8720": [0.55001, 1.05, 0, 0],
+        "8721": [0.55001, 1.05, 0, 0],
+        "8730": [0.65002, 1.15, 0, 0],
+        "8747": [0.86225, 1.36, 0.44445, 0],
+        "8748": [0.862, 1.36, 0.44445, 0],
+        "8749": [0.862, 1.36, 0.44445, 0],
+        "8750": [0.86225, 1.36, 0.44445, 0],
+        "8896": [0.55001, 1.05, 0, 0],
+        "8897": [0.55001, 1.05, 0, 0],
+        "8898": [0.55001, 1.05, 0, 0],
+        "8899": [0.55001, 1.05, 0, 0],
+        "8968": [0.65002, 1.15, 0, 0],
+        "8969": [0.65002, 1.15, 0, 0],
+        "8970": [0.65002, 1.15, 0, 0],
+        "8971": [0.65002, 1.15, 0, 0],
+        "10216": [0.65002, 1.15, 0, 0],
+        "10217": [0.65002, 1.15, 0, 0],
+        "10752": [0.55001, 1.05, 0, 0],
+        "10753": [0.55001, 1.05, 0, 0],
+        "10754": [0.55001, 1.05, 0, 0],
+        "10756": [0.55001, 1.05, 0, 0],
+        "10758": [0.55001, 1.05, 0, 0]
+    },
+    "Size3-Regular": {
+        "40": [0.95003, 1.45, 0, 0],
+        "41": [0.95003, 1.45, 0, 0],
+        "47": [0.95003, 1.45, 0, 0],
+        "91": [0.95003, 1.45, 0, 0],
+        "92": [0.95003, 1.45, 0, 0],
+        "93": [0.95003, 1.45, 0, 0],
+        "123": [0.95003, 1.45, 0, 0],
+        "125": [0.95003, 1.45, 0, 0],
+        "710": [0, 0.75, 0, 0],
+        "732": [0, 0.75, 0, 0],
+        "770": [0, 0.75, 0, 0],
+        "771": [0, 0.75, 0, 0],
+        "8730": [0.95003, 1.45, 0, 0],
+        "8968": [0.95003, 1.45, 0, 0],
+        "8969": [0.95003, 1.45, 0, 0],
+        "8970": [0.95003, 1.45, 0, 0],
+        "8971": [0.95003, 1.45, 0, 0],
+        "10216": [0.95003, 1.45, 0, 0],
+        "10217": [0.95003, 1.45, 0, 0]
+    },
+    "Size4-Regular": {
+        "40": [1.25003, 1.75, 0, 0],
+        "41": [1.25003, 1.75, 0, 0],
+        "47": [1.25003, 1.75, 0, 0],
+        "91": [1.25003, 1.75, 0, 0],
+        "92": [1.25003, 1.75, 0, 0],
+        "93": [1.25003, 1.75, 0, 0],
+        "123": [1.25003, 1.75, 0, 0],
+        "125": [1.25003, 1.75, 0, 0],
+        "710": [0, 0.825, 0, 0],
+        "732": [0, 0.825, 0, 0],
+        "770": [0, 0.825, 0, 0],
+        "771": [0, 0.825, 0, 0],
+        "8730": [1.25003, 1.75, 0, 0],
+        "8968": [1.25003, 1.75, 0, 0],
+        "8969": [1.25003, 1.75, 0, 0],
+        "8970": [1.25003, 1.75, 0, 0],
+        "8971": [1.25003, 1.75, 0, 0],
+        "9115": [0.64502, 1.155, 0, 0],
+        "9116": [1e-05, 0.6, 0, 0],
+        "9117": [0.64502, 1.155, 0, 0],
+        "9118": [0.64502, 1.155, 0, 0],
+        "9119": [1e-05, 0.6, 0, 0],
+        "9120": [0.64502, 1.155, 0, 0],
+        "9121": [0.64502, 1.155, 0, 0],
+        "9122": [-0.00099, 0.601, 0, 0],
+        "9123": [0.64502, 1.155, 0, 0],
+        "9124": [0.64502, 1.155, 0, 0],
+        "9125": [-0.00099, 0.601, 0, 0],
+        "9126": [0.64502, 1.155, 0, 0],
+        "9127": [1e-05, 0.9, 0, 0],
+        "9128": [0.65002, 1.15, 0, 0],
+        "9129": [0.90001, 0, 0, 0],
+        "9130": [0, 0.3, 0, 0],
+        "9131": [1e-05, 0.9, 0, 0],
+        "9132": [0.65002, 1.15, 0, 0],
+        "9133": [0.90001, 0, 0, 0],
+        "9143": [0.88502, 0.915, 0, 0],
+        "10216": [1.25003, 1.75, 0, 0],
+        "10217": [1.25003, 1.75, 0, 0],
+        "57344": [-0.00499, 0.605, 0, 0],
+        "57345": [-0.00499, 0.605, 0, 0],
+        "57680": [0, 0.12, 0, 0],
+        "57681": [0, 0.12, 0, 0],
+        "57682": [0, 0.12, 0, 0],
+        "57683": [0, 0.12, 0, 0]
+    },
+    "Typewriter-Regular": {
+        "33": [0, 0.61111, 0, 0],
+        "34": [0, 0.61111, 0, 0],
+        "35": [0, 0.61111, 0, 0],
+        "36": [0.08333, 0.69444, 0, 0],
+        "37": [0.08333, 0.69444, 0, 0],
+        "38": [0, 0.61111, 0, 0],
+        "39": [0, 0.61111, 0, 0],
+        "40": [0.08333, 0.69444, 0, 0],
+        "41": [0.08333, 0.69444, 0, 0],
+        "42": [0, 0.52083, 0, 0],
+        "43": [-0.08056, 0.53055, 0, 0],
+        "44": [0.13889, 0.125, 0, 0],
+        "45": [-0.08056, 0.53055, 0, 0],
+        "46": [0, 0.125, 0, 0],
+        "47": [0.08333, 0.69444, 0, 0],
+        "48": [0, 0.61111, 0, 0],
+        "49": [0, 0.61111, 0, 0],
+        "50": [0, 0.61111, 0, 0],
+        "51": [0, 0.61111, 0, 0],
+        "52": [0, 0.61111, 0, 0],
+        "53": [0, 0.61111, 0, 0],
+        "54": [0, 0.61111, 0, 0],
+        "55": [0, 0.61111, 0, 0],
+        "56": [0, 0.61111, 0, 0],
+        "57": [0, 0.61111, 0, 0],
+        "58": [0, 0.43056, 0, 0],
+        "59": [0.13889, 0.43056, 0, 0],
+        "60": [-0.05556, 0.55556, 0, 0],
+        "61": [-0.19549, 0.41562, 0, 0],
+        "62": [-0.05556, 0.55556, 0, 0],
+        "63": [0, 0.61111, 0, 0],
+        "64": [0, 0.61111, 0, 0],
+        "65": [0, 0.61111, 0, 0],
+        "66": [0, 0.61111, 0, 0],
+        "67": [0, 0.61111, 0, 0],
+        "68": [0, 0.61111, 0, 0],
+        "69": [0, 0.61111, 0, 0],
+        "70": [0, 0.61111, 0, 0],
+        "71": [0, 0.61111, 0, 0],
+        "72": [0, 0.61111, 0, 0],
+        "73": [0, 0.61111, 0, 0],
+        "74": [0, 0.61111, 0, 0],
+        "75": [0, 0.61111, 0, 0],
+        "76": [0, 0.61111, 0, 0],
+        "77": [0, 0.61111, 0, 0],
+        "78": [0, 0.61111, 0, 0],
+        "79": [0, 0.61111, 0, 0],
+        "80": [0, 0.61111, 0, 0],
+        "81": [0.13889, 0.61111, 0, 0],
+        "82": [0, 0.61111, 0, 0],
+        "83": [0, 0.61111, 0, 0],
+        "84": [0, 0.61111, 0, 0],
+        "85": [0, 0.61111, 0, 0],
+        "86": [0, 0.61111, 0, 0],
+        "87": [0, 0.61111, 0, 0],
+        "88": [0, 0.61111, 0, 0],
+        "89": [0, 0.61111, 0, 0],
+        "90": [0, 0.61111, 0, 0],
+        "91": [0.08333, 0.69444, 0, 0],
+        "92": [0.08333, 0.69444, 0, 0],
+        "93": [0.08333, 0.69444, 0, 0],
+        "94": [0, 0.61111, 0, 0],
+        "95": [0.09514, 0, 0, 0],
+        "96": [0, 0.61111, 0, 0],
+        "97": [0, 0.43056, 0, 0],
+        "98": [0, 0.61111, 0, 0],
+        "99": [0, 0.43056, 0, 0],
+        "100": [0, 0.61111, 0, 0],
+        "101": [0, 0.43056, 0, 0],
+        "102": [0, 0.61111, 0, 0],
+        "103": [0.22222, 0.43056, 0, 0],
+        "104": [0, 0.61111, 0, 0],
+        "105": [0, 0.61111, 0, 0],
+        "106": [0.22222, 0.61111, 0, 0],
+        "107": [0, 0.61111, 0, 0],
+        "108": [0, 0.61111, 0, 0],
+        "109": [0, 0.43056, 0, 0],
+        "110": [0, 0.43056, 0, 0],
+        "111": [0, 0.43056, 0, 0],
+        "112": [0.22222, 0.43056, 0, 0],
+        "113": [0.22222, 0.43056, 0, 0],
+        "114": [0, 0.43056, 0, 0],
+        "115": [0, 0.43056, 0, 0],
+        "116": [0, 0.55358, 0, 0],
+        "117": [0, 0.43056, 0, 0],
+        "118": [0, 0.43056, 0, 0],
+        "119": [0, 0.43056, 0, 0],
+        "120": [0, 0.43056, 0, 0],
+        "121": [0.22222, 0.43056, 0, 0],
+        "122": [0, 0.43056, 0, 0],
+        "123": [0.08333, 0.69444, 0, 0],
+        "124": [0.08333, 0.69444, 0, 0],
+        "125": [0.08333, 0.69444, 0, 0],
+        "126": [0, 0.61111, 0, 0],
+        "127": [0, 0.61111, 0, 0],
+        "305": [0, 0.43056, 0, 0],
+        "567": [0.22222, 0.43056, 0, 0],
+        "768": [0, 0.61111, 0, 0],
+        "769": [0, 0.61111, 0, 0],
+        "770": [0, 0.61111, 0, 0],
+        "771": [0, 0.61111, 0, 0],
+        "772": [0, 0.56555, 0, 0],
+        "774": [0, 0.61111, 0, 0],
+        "776": [0, 0.61111, 0, 0],
+        "778": [0, 0.61111, 0, 0],
+        "780": [0, 0.56597, 0, 0],
+        "915": [0, 0.61111, 0, 0],
+        "916": [0, 0.61111, 0, 0],
+        "920": [0, 0.61111, 0, 0],
+        "923": [0, 0.61111, 0, 0],
+        "926": [0, 0.61111, 0, 0],
+        "928": [0, 0.61111, 0, 0],
+        "931": [0, 0.61111, 0, 0],
+        "933": [0, 0.61111, 0, 0],
+        "934": [0, 0.61111, 0, 0],
+        "936": [0, 0.61111, 0, 0],
+        "937": [0, 0.61111, 0, 0],
+        "2018": [0, 0.61111, 0, 0],
+        "2019": [0, 0.61111, 0, 0],
+        "8242": [0, 0.61111, 0, 0]
+    }
+};
+
+},{}],19:[function(require,module,exports){
+var utils = require("./utils");
+var ParseError = require("./ParseError");
+var parseData = require("./parseData");
+var ParseNode = parseData.ParseNode;
+
+/* This file contains a list of functions that we parse, identified by
+ * the calls to defineFunction.
+ *
+ * The first argument to defineFunction is a single name or a list of names.
+ * All functions named in such a list will share a single implementation.
+ *
+ * Each declared function can have associated properties, which
+ * include the following:
+ *
+ *  - numArgs: The number of arguments the function takes.
+ *             If this is the only property, it can be passed as a number
+ *             instead of an element of a properties object.
+ *  - argTypes: (optional) An array corresponding to each argument of the
+ *              function, giving the type of argument that should be parsed. Its
+ *              length should be equal to `numArgs + numOptionalArgs`. Valid
+ *              types:
+ *               - "size": A size-like thing, such as "1em" or "5ex"
+ *               - "color": An html color, like "#abc" or "blue"
+ *               - "original": The same type as the environment that the
+ *                             function being parsed is in (e.g. used for the
+ *                             bodies of functions like \color where the first
+ *                             argument is special and the second argument is
+ *                             parsed normally)
+ *              Other possible types (probably shouldn't be used)
+ *               - "text": Text-like (e.g. \text)
+ *               - "math": Normal math
+ *              If undefined, this will be treated as an appropriate length
+ *              array of "original" strings
+ *  - greediness: (optional) The greediness of the function to use ungrouped
+ *                arguments.
+ *
+ *                E.g. if you have an expression
+ *                  \sqrt \frac 1 2
+ *                since \frac has greediness=2 vs \sqrt's greediness=1, \frac
+ *                will use the two arguments '1' and '2' as its two arguments,
+ *                then that whole function will be used as the argument to
+ *                \sqrt. On the other hand, the expressions
+ *                  \frac \frac 1 2 3
+ *                and
+ *                  \frac \sqrt 1 2
+ *                will fail because \frac and \frac have equal greediness
+ *                and \sqrt has a lower greediness than \frac respectively. To
+ *                make these parse, we would have to change them to:
+ *                  \frac {\frac 1 2} 3
+ *                and
+ *                  \frac {\sqrt 1} 2
+ *
+ *                The default value is `1`
+ *  - allowedInText: (optional) Whether or not the function is allowed inside
+ *                   text mode (default false)
+ *  - numOptionalArgs: (optional) The number of optional arguments the function
+ *                     should parse. If the optional arguments aren't found,
+ *                     `null` will be passed to the handler in their place.
+ *                     (default 0)
+ *  - infix: (optional) Must be true if the function is an infix operator.
+ *
+ * The last argument is that implementation, the handler for the function(s).
+ * It is called to handle these functions and their arguments.
+ * It receives two arguments:
+ *  - context contains information and references provided by the parser
+ *  - args is an array of arguments obtained from TeX input
+ * The context contains the following properties:
+ *  - funcName: the text (i.e. name) of the function, including \
+ *  - parser: the parser object
+ *  - lexer: the lexer object
+ *  - positions: the positions in the overall string of the function
+ *               and the arguments.
+ * The latter three should only be used to produce error messages.
+ *
+ * The function should return an object with the following keys:
+ *  - type: The type of element that this is. This is then used in
+ *          buildHTML/buildMathML to determine which function
+ *          should be called to build this node into a DOM node
+ * Any other data can be added to the object, which will be passed
+ * in to the function in buildHTML/buildMathML as `group.value`.
+ */
+
+function defineFunction(names, props, handler) {
+    if (typeof names === "string") {
+        names = [names];
+    }
+    if (typeof props === "number") {
+        props = { numArgs: props };
+    }
+    // Set default values of functions
+    var data = {
+        numArgs: props.numArgs,
+        argTypes: props.argTypes,
+        greediness: (props.greediness === undefined) ? 1 : props.greediness,
+        allowedInText: !!props.allowedInText,
+        numOptionalArgs: props.numOptionalArgs || 0,
+        infix: !!props.infix,
+        handler: handler
+    };
+    for (var i = 0; i < names.length; ++i) {
+        module.exports[names[i]] = data;
+    }
+}
+
+// Since the corresponding buildHTML/buildMathML function expects a
+// list of elements, we normalize for different kinds of arguments
+var ordargument = function(arg) {
+    if (arg.type === "ordgroup") {
+        return arg.value;
+    } else {
+        return [arg];
+    }
+};
+
+// A normal square root
+defineFunction("\\sqrt", {
+    numArgs: 1,
+    numOptionalArgs: 1
+}, function(context, args) {
+    var index = args[0];
+    var body = args[1];
+    return {
+        type: "sqrt",
+        body: body,
+        index: index
+    };
+});
+
+// Non-mathy text, possibly in a font
+var textFunctionStyles = {
+    "\\text": undefined, "\\textrm": "mathrm", "\\textsf": "mathsf",
+    "\\texttt": "mathtt", "\\textnormal": "mathrm", "\\textbf": "mathbf",
+    "\\textit": "textit"
+};
+
+defineFunction([
+    "\\text", "\\textrm", "\\textsf", "\\texttt", "\\textnormal",
+    "\\textbf", "\\textit"
+], {
+    numArgs: 1,
+    argTypes: ["text"],
+    greediness: 2,
+    allowedInText: true
+}, function(context, args) {
+    var body = args[0];
+    return {
+        type: "text",
+        body: ordargument(body),
+        style: textFunctionStyles[context.funcName]
+    };
+});
+
+// A two-argument custom color
+defineFunction("\\color", {
+    numArgs: 2,
+    allowedInText: true,
+    greediness: 3,
+    argTypes: ["color", "original"]
+}, function(context, args) {
+    var color = args[0];
+    var body = args[1];
+    return {
+        type: "color",
+        color: color.value,
+        value: ordargument(body)
+    };
+});
+
+// An overline
+defineFunction("\\overline", {
+    numArgs: 1
+}, function(context, args) {
+    var body = args[0];
+    return {
+        type: "overline",
+        body: body
+    };
+});
+
+// An underline
+defineFunction("\\underline", {
+    numArgs: 1
+}, function(context, args) {
+    var body = args[0];
+    return {
+        type: "underline",
+        body: body
+    };
+});
+
+// A box of the width and height
+defineFunction("\\rule", {
+    numArgs: 2,
+    numOptionalArgs: 1,
+    argTypes: ["size", "size", "size"]
+}, function(context, args) {
+    var shift = args[0];
+    var width = args[1];
+    var height = args[2];
+    return {
+        type: "rule",
+        shift: shift && shift.value,
+        width: width.value,
+        height: height.value
+    };
+});
+
+// TODO: In TeX, \mkern only accepts mu-units, and \kern does not accept
+// mu-units. In current KaTeX we relax this; both commands accept any unit.
+defineFunction(["\\kern", "\\mkern"], {
+    numArgs: 1,
+    argTypes: ["size"]
+}, function(context, args) {
+    return {
+        type: "kern",
+        dimension: args[0].value
+    };
+});
+
+// A KaTeX logo
+defineFunction("\\KaTeX", {
+    numArgs: 0
+}, function(context) {
+    return {
+        type: "katex"
+    };
+});
+
+defineFunction("\\phantom", {
+    numArgs: 1
+}, function(context, args) {
+    var body = args[0];
+    return {
+        type: "phantom",
+        value: ordargument(body)
+    };
+});
+
+// Math class commands except \mathop
+defineFunction([
+    "\\mathord", "\\mathbin", "\\mathrel", "\\mathopen",
+    "\\mathclose", "\\mathpunct", "\\mathinner"
+], {
+    numArgs: 1
+}, function(context, args) {
+    var body = args[0];
+    return {
+        type: "mclass",
+        mclass: "m" + context.funcName.substr(5),
+        value: ordargument(body)
+    };
+});
+
+// Build a relation by placing one symbol on top of another
+defineFunction("\\stackrel", {
+    numArgs: 2
+}, function(context, args) {
+    var top = args[0];
+    var bottom = args[1];
+
+    var bottomop = new ParseNode("op", {
+        type: "op",
+        limits: true,
+        alwaysHandleSupSub: true,
+        symbol: false,
+        value: ordargument(bottom)
+    }, bottom.mode);
+
+    var supsub = new ParseNode("supsub", {
+        base: bottomop,
+        sup: top,
+        sub: null
+    }, top.mode);
+
+    return {
+        type: "mclass",
+        mclass: "mrel",
+        value: [supsub]
+    };
+});
+
+// \mod-type functions
+defineFunction("\\bmod", {
+    numArgs: 0
+}, function(context, args) {
+    return {
+        type: "mod",
+        modType: "bmod",
+        value: null
+    };
+});
+
+defineFunction(["\\pod", "\\pmod", "\\mod"], {
+    numArgs: 1
+}, function(context, args) {
+    var body = args[0];
+    return {
+        type: "mod",
+        modType: context.funcName.substr(1),
+        value: ordargument(body)
+    };
+});
+
+// Extra data needed for the delimiter handler down below
+var delimiterSizes = {
+    "\\bigl" : {mclass: "mopen",    size: 1},
+    "\\Bigl" : {mclass: "mopen",    size: 2},
+    "\\biggl": {mclass: "mopen",    size: 3},
+    "\\Biggl": {mclass: "mopen",    size: 4},
+    "\\bigr" : {mclass: "mclose",   size: 1},
+    "\\Bigr" : {mclass: "mclose",   size: 2},
+    "\\biggr": {mclass: "mclose",   size: 3},
+    "\\Biggr": {mclass: "mclose",   size: 4},
+    "\\bigm" : {mclass: "mrel",     size: 1},
+    "\\Bigm" : {mclass: "mrel",     size: 2},
+    "\\biggm": {mclass: "mrel",     size: 3},
+    "\\Biggm": {mclass: "mrel",     size: 4},
+    "\\big"  : {mclass: "mord",     size: 1},
+    "\\Big"  : {mclass: "mord",     size: 2},
+    "\\bigg" : {mclass: "mord",     size: 3},
+    "\\Bigg" : {mclass: "mord",     size: 4}
+};
+
+var delimiters = [
+    "(", ")", "[", "\\lbrack", "]", "\\rbrack",
+    "\\{", "\\lbrace", "\\}", "\\rbrace",
+    "\\lfloor", "\\rfloor", "\\lceil", "\\rceil",
+    "<", ">", "\\langle", "\\rangle", "\\lt", "\\gt",
+    "\\lvert", "\\rvert", "\\lVert", "\\rVert",
+    "\\lgroup", "\\rgroup", "\\lmoustache", "\\rmoustache",
+    "/", "\\backslash",
+    "|", "\\vert", "\\|", "\\Vert",
+    "\\uparrow", "\\Uparrow",
+    "\\downarrow", "\\Downarrow",
+    "\\updownarrow", "\\Updownarrow",
+    "."
+];
+
+var fontAliases = {
+    "\\Bbb": "\\mathbb",
+    "\\bold": "\\mathbf",
+    "\\frak": "\\mathfrak"
+};
+
+// Single-argument color functions
+defineFunction([
+    "\\blue", "\\orange", "\\pink", "\\red",
+    "\\green", "\\gray", "\\purple",
+    "\\blueA", "\\blueB", "\\blueC", "\\blueD", "\\blueE",
+    "\\tealA", "\\tealB", "\\tealC", "\\tealD", "\\tealE",
+    "\\greenA", "\\greenB", "\\greenC", "\\greenD", "\\greenE",
+    "\\goldA", "\\goldB", "\\goldC", "\\goldD", "\\goldE",
+    "\\redA", "\\redB", "\\redC", "\\redD", "\\redE",
+    "\\maroonA", "\\maroonB", "\\maroonC", "\\maroonD", "\\maroonE",
+    "\\purpleA", "\\purpleB", "\\purpleC", "\\purpleD", "\\purpleE",
+    "\\mintA", "\\mintB", "\\mintC",
+    "\\grayA", "\\grayB", "\\grayC", "\\grayD", "\\grayE",
+    "\\grayF", "\\grayG", "\\grayH", "\\grayI",
+    "\\kaBlue", "\\kaGreen"
+], {
+    numArgs: 1,
+    allowedInText: true,
+    greediness: 3
+}, function(context, args) {
+    var body = args[0];
+    return {
+        type: "color",
+        color: "katex-" + context.funcName.slice(1),
+        value: ordargument(body)
+    };
+});
+
+// There are 2 flags for operators; whether they produce limits in
+// displaystyle, and whether they are symbols and should grow in
+// displaystyle. These four groups cover the four possible choices.
+
+// No limits, not symbols
+defineFunction([
+    "\\arcsin", "\\arccos", "\\arctan", "\\arg", "\\cos", "\\cosh",
+    "\\cot", "\\coth", "\\csc", "\\deg", "\\dim", "\\exp", "\\hom",
+    "\\ker", "\\lg", "\\ln", "\\log", "\\sec", "\\sin", "\\sinh",
+    "\\tan", "\\tanh"
+], {
+    numArgs: 0
+}, function(context) {
+    return {
+        type: "op",
+        limits: false,
+        symbol: false,
+        body: context.funcName
+    };
+});
+
+// Limits, not symbols
+defineFunction([
+    "\\det", "\\gcd", "\\inf", "\\lim", "\\liminf", "\\limsup", "\\max",
+    "\\min", "\\Pr", "\\sup"
+], {
+    numArgs: 0
+}, function(context) {
+    return {
+        type: "op",
+        limits: true,
+        symbol: false,
+        body: context.funcName
+    };
+});
+
+// No limits, symbols
+defineFunction([
+    "\\int", "\\iint", "\\iiint", "\\oint"
+], {
+    numArgs: 0
+}, function(context) {
+    return {
+        type: "op",
+        limits: false,
+        symbol: true,
+        body: context.funcName
+    };
+});
+
+// Limits, symbols
+defineFunction([
+    "\\coprod", "\\bigvee", "\\bigwedge", "\\biguplus", "\\bigcap",
+    "\\bigcup", "\\intop", "\\prod", "\\sum", "\\bigotimes",
+    "\\bigoplus", "\\bigodot", "\\bigsqcup", "\\smallint"
+], {
+    numArgs: 0
+}, function(context) {
+    return {
+        type: "op",
+        limits: true,
+        symbol: true,
+        body: context.funcName
+    };
+});
+
+// \mathop class command
+defineFunction("\\mathop", {
+    numArgs: 1
+}, function(context, args) {
+    var body = args[0];
+    return {
+        type: "op",
+        limits: false,
+        symbol: false,
+        value: ordargument(body)
+    };
+});
+
+// Fractions
+defineFunction([
+    "\\dfrac", "\\frac", "\\tfrac",
+    "\\dbinom", "\\binom", "\\tbinom",
+    "\\\\atopfrac" // can’t be entered directly
+], {
+    numArgs: 2,
+    greediness: 2
+}, function(context, args) {
+    var numer = args[0];
+    var denom = args[1];
+    var hasBarLine;
+    var leftDelim = null;
+    var rightDelim = null;
+    var size = "auto";
+
+    switch (context.funcName) {
+        case "\\dfrac":
+        case "\\frac":
+        case "\\tfrac":
+            hasBarLine = true;
+            break;
+        case "\\\\atopfrac":
+            hasBarLine = false;
+            break;
+        case "\\dbinom":
+        case "\\binom":
+        case "\\tbinom":
+            hasBarLine = false;
+            leftDelim = "(";
+            rightDelim = ")";
+            break;
+        default:
+            throw new Error("Unrecognized genfrac command");
+    }
+
+    switch (context.funcName) {
+        case "\\dfrac":
+        case "\\dbinom":
+            size = "display";
+            break;
+        case "\\tfrac":
+        case "\\tbinom":
+            size = "text";
+            break;
+    }
+
+    return {
+        type: "genfrac",
+        numer: numer,
+        denom: denom,
+        hasBarLine: hasBarLine,
+        leftDelim: leftDelim,
+        rightDelim: rightDelim,
+        size: size
+    };
+});
+
+// Left and right overlap functions
+defineFunction(["\\llap", "\\rlap"], {
+    numArgs: 1,
+    allowedInText: true
+}, function(context, args) {
+    var body = args[0];
+    return {
+        type: context.funcName.slice(1),
+        body: body
+    };
+});
+
+// Delimiter functions
+var checkDelimiter = function(delim, context) {
+    if (utils.contains(delimiters, delim.value)) {
+        return delim;
+    } else {
+        throw new ParseError(
+            "Invalid delimiter: '" + delim.value + "' after '" +
+            context.funcName + "'", delim);
+    }
+};
+
+defineFunction([
+    "\\bigl", "\\Bigl", "\\biggl", "\\Biggl",
+    "\\bigr", "\\Bigr", "\\biggr", "\\Biggr",
+    "\\bigm", "\\Bigm", "\\biggm", "\\Biggm",
+    "\\big",  "\\Big",  "\\bigg",  "\\Bigg"
+], {
+    numArgs: 1
+}, function(context, args) {
+    var delim = checkDelimiter(args[0], context);
+
+    return {
+        type: "delimsizing",
+        size: delimiterSizes[context.funcName].size,
+        mclass: delimiterSizes[context.funcName].mclass,
+        value: delim.value
+    };
+});
+
+defineFunction([
+    "\\left", "\\right"
+], {
+    numArgs: 1
+}, function(context, args) {
+    var delim = checkDelimiter(args[0], context);
+
+    // \left and \right are caught somewhere in Parser.js, which is
+    // why this data doesn't match what is in buildHTML.
+    return {
+        type: "leftright",
+        value: delim.value
+    };
+});
+
+defineFunction("\\middle", {
+    numArgs: 1
+}, function(context, args) {
+    var delim = checkDelimiter(args[0], context);
+    if (!context.parser.leftrightDepth) {
+        throw new ParseError("\\middle without preceding \\left", delim);
+    }
+
+    return {
+        type: "middle",
+        value: delim.value
+    };
+});
+
+// Sizing functions (handled in Parser.js explicitly, hence no handler)
+defineFunction([
+    "\\tiny", "\\scriptsize", "\\footnotesize", "\\small",
+    "\\normalsize", "\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge"
+], 0, null);
+
+// Style changing functions (handled in Parser.js explicitly, hence no
+// handler)
+defineFunction([
+    "\\displaystyle", "\\textstyle", "\\scriptstyle",
+    "\\scriptscriptstyle"
+], 0, null);
+
+defineFunction([
+    // styles
+    "\\mathrm", "\\mathit", "\\mathbf",
+
+    // families
+    "\\mathbb", "\\mathcal", "\\mathfrak", "\\mathscr", "\\mathsf",
+    "\\mathtt",
+
+    // aliases
+    "\\Bbb", "\\bold", "\\frak"
+], {
+    numArgs: 1,
+    greediness: 2
+}, function(context, args) {
+    var body = args[0];
+    var func = context.funcName;
+    if (func in fontAliases) {
+        func = fontAliases[func];
+    }
+    return {
+        type: "font",
+        font: func.slice(1),
+        body: body
+    };
+});
+
+// Accents
+defineFunction([
+    "\\acute", "\\grave", "\\ddot", "\\tilde", "\\bar", "\\breve",
+    "\\check", "\\hat", "\\vec", "\\dot"
+    // We don't support expanding accents yet
+    // "\\widetilde", "\\widehat"
+], {
+    numArgs: 1
+}, function(context, args) {
+    var base = args[0];
+    return {
+        type: "accent",
+        accent: context.funcName,
+        base: base
+    };
+});
+
+// Infix generalized fractions
+defineFunction(["\\over", "\\choose", "\\atop"], {
+    numArgs: 0,
+    infix: true
+}, function(context) {
+    var replaceWith;
+    switch (context.funcName) {
+        case "\\over":
+            replaceWith = "\\frac";
+            break;
+        case "\\choose":
+            replaceWith = "\\binom";
+            break;
+        case "\\atop":
+            replaceWith = "\\\\atopfrac";
+            break;
+        default:
+            throw new Error("Unrecognized infix genfrac command");
+    }
+    return {
+        type: "infix",
+        replaceWith: replaceWith,
+        token: context.token
+    };
+});
+
+// Row breaks for aligned data
+defineFunction(["\\\\", "\\cr"], {
+    numArgs: 0,
+    numOptionalArgs: 1,
+    argTypes: ["size"]
+}, function(context, args) {
+    var size = args[0];
+    return {
+        type: "cr",
+        size: size
+    };
+});
+
+// Environment delimiters
+defineFunction(["\\begin", "\\end"], {
+    numArgs: 1,
+    argTypes: ["text"]
+}, function(context, args) {
+    var nameGroup = args[0];
+    if (nameGroup.type !== "ordgroup") {
+        throw new ParseError("Invalid environment name", nameGroup);
+    }
+    var name = "";
+    for (var i = 0; i < nameGroup.value.length; ++i) {
+        name += nameGroup.value[i].value;
+    }
+    return {
+        type: "environment",
+        name: name,
+        nameGroup: nameGroup
+    };
+});
+
+},{"./ParseError":6,"./parseData":21,"./utils":25}],20:[function(require,module,exports){
+/**
+ * These objects store data about MathML nodes. This is the MathML equivalent
+ * of the types in domTree.js. Since MathML handles its own rendering, and
+ * since we're mainly using MathML to improve accessibility, we don't manage
+ * any of the styling state that the plain DOM nodes do.
+ *
+ * The `toNode` and `toMarkup` functions work simlarly to how they do in
+ * domTree.js, creating namespaced DOM nodes and HTML text markup respectively.
+ */
+
+var utils = require("./utils");
+
+/**
+ * This node represents a general purpose MathML node of any type. The
+ * constructor requires the type of node to create (for example, `"mo"` or
+ * `"mspace"`, corresponding to `<mo>` and `<mspace>` tags).
+ */
+function MathNode(type, children) {
+    this.type = type;
+    this.attributes = {};
+    this.children = children || [];
+}
+
+/**
+ * Sets an attribute on a MathML node. MathML depends on attributes to convey a
+ * semantic content, so this is used heavily.
+ */
+MathNode.prototype.setAttribute = function(name, value) {
+    this.attributes[name] = value;
+};
+
+/**
+ * Converts the math node into a MathML-namespaced DOM element.
+ */
+MathNode.prototype.toNode = function() {
+    var node = document.createElementNS(
+        "http://www.w3.org/1998/Math/MathML", this.type);
+
+    for (var attr in this.attributes) {
+        if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
+            node.setAttribute(attr, this.attributes[attr]);
+        }
+    }
+
+    for (var i = 0; i < this.children.length; i++) {
+        node.appendChild(this.children[i].toNode());
+    }
+
+    return node;
+};
+
+/**
+ * Converts the math node into an HTML markup string.
+ */
+MathNode.prototype.toMarkup = function() {
+    var markup = "<" + this.type;
+
+    // Add the attributes
+    for (var attr in this.attributes) {
+        if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
+            markup += " " + attr + "=\"";
+            markup += utils.escape(this.attributes[attr]);
+            markup += "\"";
+        }
+    }
+
+    markup += ">";
+
+    for (var i = 0; i < this.children.length; i++) {
+        markup += this.children[i].toMarkup();
+    }
+
+    markup += "</" + this.type + ">";
+
+    return markup;
+};
+
+/**
+ * This node represents a piece of text.
+ */
+function TextNode(text) {
+    this.text = text;
+}
+
+/**
+ * Converts the text node into a DOM text node.
+ */
+TextNode.prototype.toNode = function() {
+    return document.createTextNode(this.text);
+};
+
+/**
+ * Converts the text node into HTML markup (which is just the text itself).
+ */
+TextNode.prototype.toMarkup = function() {
+    return utils.escape(this.text);
+};
+
+module.exports = {
+    MathNode: MathNode,
+    TextNode: TextNode
+};
+
+},{"./utils":25}],21:[function(require,module,exports){
+/**
+ * The resulting parse tree nodes of the parse tree.
+ *
+ * It is possible to provide position information, so that a ParseNode can
+ * fulfil a role similar to a Token in error reporting.
+ * For details on the corresponding properties see Token constructor.
+ * Providing such information can lead to better error reporting.
+ *
+ * @param {string}  type       type of node, like e.g. "ordgroup"
+ * @param {?object} value      type-specific representation of the node
+ * @param {string}  mode       parse mode in action for this node,
+ *                             "math" or "text"
+ * @param {Token=} firstToken  first token of the input for this node,
+ *                             will omit position information if unset
+ * @param {Token=} lastToken   last token of the input for this node,
+ *                             will default to firstToken if unset
+ */
+function ParseNode(type, value, mode, firstToken, lastToken) {
+    this.type = type;
+    this.value = value;
+    this.mode = mode;
+    if (firstToken && (!lastToken || lastToken.lexer === firstToken.lexer)) {
+        this.lexer = firstToken.lexer;
+        this.start = firstToken.start;
+        this.end = (lastToken || firstToken).end;
+    }
+}
+
+module.exports = {
+    ParseNode: ParseNode
+};
+
+
+},{}],22:[function(require,module,exports){
+/**
+ * Provides a single function for parsing an expression using a Parser
+ * TODO(emily): Remove this
+ */
+
+var Parser = require("./Parser");
+
+/**
+ * Parses an expression using a Parser, then returns the parsed result.
+ */
+var parseTree = function(toParse, settings) {
+    if (!(typeof toParse === 'string' || toParse instanceof String)) {
+        throw new TypeError('KaTeX can only parse string typed expression');
+    }
+    var parser = new Parser(toParse, settings);
+
+    return parser.parse();
+};
+
+module.exports = parseTree;
+
+},{"./Parser":7}],23:[function(require,module,exports){
+/**
+ * This file holds a list of all no-argument functions and single-character
+ * symbols (like 'a' or ';').
+ *
+ * For each of the symbols, there are three properties they can have:
+ * - font (required): the font to be used for this symbol. Either "main" (the
+     normal font), or "ams" (the ams fonts).
+ * - group (required): the ParseNode group type the symbol should have (i.e.
+     "textord", "mathord", etc).
+     See https://github.com/Khan/KaTeX/wiki/Examining-TeX#group-types
+ * - replace: the character that this symbol or function should be
+ *   replaced with (i.e. "\phi" has a replace value of "\u03d5", the phi
+ *   character in the main font).
+ *
+ * The outermost map in the table indicates what mode the symbols should be
+ * accepted in (e.g. "math" or "text").
+ */
+
+module.exports = {
+    math: {},
+    text: {}
+};
+
+function defineSymbol(mode, font, group, replace, name) {
+    module.exports[mode][name] = {
+        font: font,
+        group: group,
+        replace: replace
+    };
+}
+
+// Some abbreviations for commonly used strings.
+// This helps minify the code, and also spotting typos using jshint.
+
+// modes:
+var math = "math";
+var text = "text";
+
+// fonts:
+var main = "main";
+var ams = "ams";
+
+// groups:
+var accent = "accent";
+var bin = "bin";
+var close = "close";
+var inner = "inner";
+var mathord = "mathord";
+var op = "op";
+var open = "open";
+var punct = "punct";
+var rel = "rel";
+var spacing = "spacing";
+var textord = "textord";
+
+// Now comes the symbol table
+
+// Relation Symbols
+defineSymbol(math, main, rel, "\u2261", "\\equiv");
+defineSymbol(math, main, rel, "\u227a", "\\prec");
+defineSymbol(math, main, rel, "\u227b", "\\succ");
+defineSymbol(math, main, rel, "\u223c", "\\sim");
+defineSymbol(math, main, rel, "\u22a5", "\\perp");
+defineSymbol(math, main, rel, "\u2aaf", "\\preceq");
+defineSymbol(math, main, rel, "\u2ab0", "\\succeq");
+defineSymbol(math, main, rel, "\u2243", "\\simeq");
+defineSymbol(math, main, rel, "\u2223", "\\mid");
+defineSymbol(math, main, rel, "\u226a", "\\ll");
+defineSymbol(math, main, rel, "\u226b", "\\gg");
+defineSymbol(math, main, rel, "\u224d", "\\asymp");
+defineSymbol(math, main, rel, "\u2225", "\\parallel");
+defineSymbol(math, main, rel, "\u22c8", "\\bowtie");
+defineSymbol(math, main, rel, "\u2323", "\\smile");
+defineSymbol(math, main, rel, "\u2291", "\\sqsubseteq");
+defineSymbol(math, main, rel, "\u2292", "\\sqsupseteq");
+defineSymbol(math, main, rel, "\u2250", "\\doteq");
+defineSymbol(math, main, rel, "\u2322", "\\frown");
+defineSymbol(math, main, rel, "\u220b", "\\ni");
+defineSymbol(math, main, rel, "\u221d", "\\propto");
+defineSymbol(math, main, rel, "\u22a2", "\\vdash");
+defineSymbol(math, main, rel, "\u22a3", "\\dashv");
+defineSymbol(math, main, rel, "\u220b", "\\owns");
+
+// Punctuation
+defineSymbol(math, main, punct, "\u002e", "\\ldotp");
+defineSymbol(math, main, punct, "\u22c5", "\\cdotp");
+
+// Misc Symbols
+defineSymbol(math, main, textord, "\u0023", "\\#");
+defineSymbol(text, main, textord, "\u0023", "\\#");
+defineSymbol(math, main, textord, "\u0026", "\\&");
+defineSymbol(text, main, textord, "\u0026", "\\&");
+defineSymbol(math, main, textord, "\u2135", "\\aleph");
+defineSymbol(math, main, textord, "\u2200", "\\forall");
+defineSymbol(math, main, textord, "\u210f", "\\hbar");
+defineSymbol(math, main, textord, "\u2203", "\\exists");
+defineSymbol(math, main, textord, "\u2207", "\\nabla");
+defineSymbol(math, main, textord, "\u266d", "\\flat");
+defineSymbol(math, main, textord, "\u2113", "\\ell");
+defineSymbol(math, main, textord, "\u266e", "\\natural");
+defineSymbol(math, main, textord, "\u2663", "\\clubsuit");
+defineSymbol(math, main, textord, "\u2118", "\\wp");
+defineSymbol(math, main, textord, "\u266f", "\\sharp");
+defineSymbol(math, main, textord, "\u2662", "\\diamondsuit");
+defineSymbol(math, main, textord, "\u211c", "\\Re");
+defineSymbol(math, main, textord, "\u2661", "\\heartsuit");
+defineSymbol(math, main, textord, "\u2111", "\\Im");
+defineSymbol(math, main, textord, "\u2660", "\\spadesuit");
+
+// Math and Text
+defineSymbol(math, main, textord, "\u2020", "\\dag");
+defineSymbol(math, main, textord, "\u2021", "\\ddag");
+
+// Large Delimiters
+defineSymbol(math, main, close, "\u23b1", "\\rmoustache");
+defineSymbol(math, main, open, "\u23b0", "\\lmoustache");
+defineSymbol(math, main, close, "\u27ef", "\\rgroup");
+defineSymbol(math, main, open, "\u27ee", "\\lgroup");
+
+// Binary Operators
+defineSymbol(math, main, bin, "\u2213", "\\mp");
+defineSymbol(math, main, bin, "\u2296", "\\ominus");
+defineSymbol(math, main, bin, "\u228e", "\\uplus");
+defineSymbol(math, main, bin, "\u2293", "\\sqcap");
+defineSymbol(math, main, bin, "\u2217", "\\ast");
+defineSymbol(math, main, bin, "\u2294", "\\sqcup");
+defineSymbol(math, main, bin, "\u25ef", "\\bigcirc");
+defineSymbol(math, main, bin, "\u2219", "\\bullet");
+defineSymbol(math, main, bin, "\u2021", "\\ddagger");
+defineSymbol(math, main, bin, "\u2240", "\\wr");
+defineSymbol(math, main, bin, "\u2a3f", "\\amalg");
+
+// Arrow Symbols
+defineSymbol(math, main, rel, "\u27f5", "\\longleftarrow");
+defineSymbol(math, main, rel, "\u21d0", "\\Leftarrow");
+defineSymbol(math, main, rel, "\u27f8", "\\Longleftarrow");
+defineSymbol(math, main, rel, "\u27f6", "\\longrightarrow");
+defineSymbol(math, main, rel, "\u21d2", "\\Rightarrow");
+defineSymbol(math, main, rel, "\u27f9", "\\Longrightarrow");
+defineSymbol(math, main, rel, "\u2194", "\\leftrightarrow");
+defineSymbol(math, main, rel, "\u27f7", "\\longleftrightarrow");
+defineSymbol(math, main, rel, "\u21d4", "\\Leftrightarrow");
+defineSymbol(math, main, rel, "\u27fa", "\\Longleftrightarrow");
+defineSymbol(math, main, rel, "\u21a6", "\\mapsto");
+defineSymbol(math, main, rel, "\u27fc", "\\longmapsto");
+defineSymbol(math, main, rel, "\u2197", "\\nearrow");
+defineSymbol(math, main, rel, "\u21a9", "\\hookleftarrow");
+defineSymbol(math, main, rel, "\u21aa", "\\hookrightarrow");
+defineSymbol(math, main, rel, "\u2198", "\\searrow");
+defineSymbol(math, main, rel, "\u21bc", "\\leftharpoonup");
+defineSymbol(math, main, rel, "\u21c0", "\\rightharpoonup");
+defineSymbol(math, main, rel, "\u2199", "\\swarrow");
+defineSymbol(math, main, rel, "\u21bd", "\\leftharpoondown");
+defineSymbol(math, main, rel, "\u21c1", "\\rightharpoondown");
+defineSymbol(math, main, rel, "\u2196", "\\nwarrow");
+defineSymbol(math, main, rel, "\u21cc", "\\rightleftharpoons");
+
+// AMS Negated Binary Relations
+defineSymbol(math, ams, rel, "\u226e", "\\nless");
+defineSymbol(math, ams, rel, "\ue010", "\\nleqslant");
+defineSymbol(math, ams, rel, "\ue011", "\\nleqq");
+defineSymbol(math, ams, rel, "\u2a87", "\\lneq");
+defineSymbol(math, ams, rel, "\u2268", "\\lneqq");
+defineSymbol(math, ams, rel, "\ue00c", "\\lvertneqq");
+defineSymbol(math, ams, rel, "\u22e6", "\\lnsim");
+defineSymbol(math, ams, rel, "\u2a89", "\\lnapprox");
+defineSymbol(math, ams, rel, "\u2280", "\\nprec");
+defineSymbol(math, ams, rel, "\u22e0", "\\npreceq");
+defineSymbol(math, ams, rel, "\u22e8", "\\precnsim");
+defineSymbol(math, ams, rel, "\u2ab9", "\\precnapprox");
+defineSymbol(math, ams, rel, "\u2241", "\\nsim");
+defineSymbol(math, ams, rel, "\ue006", "\\nshortmid");
+defineSymbol(math, ams, rel, "\u2224", "\\nmid");
+defineSymbol(math, ams, rel, "\u22ac", "\\nvdash");
+defineSymbol(math, ams, rel, "\u22ad", "\\nvDash");
+defineSymbol(math, ams, rel, "\u22ea", "\\ntriangleleft");
+defineSymbol(math, ams, rel, "\u22ec", "\\ntrianglelefteq");
+defineSymbol(math, ams, rel, "\u228a", "\\subsetneq");
+defineSymbol(math, ams, rel, "\ue01a", "\\varsubsetneq");
+defineSymbol(math, ams, rel, "\u2acb", "\\subsetneqq");
+defineSymbol(math, ams, rel, "\ue017", "\\varsubsetneqq");
+defineSymbol(math, ams, rel, "\u226f", "\\ngtr");
+defineSymbol(math, ams, rel, "\ue00f", "\\ngeqslant");
+defineSymbol(math, ams, rel, "\ue00e", "\\ngeqq");
+defineSymbol(math, ams, rel, "\u2a88", "\\gneq");
+defineSymbol(math, ams, rel, "\u2269", "\\gneqq");
+defineSymbol(math, ams, rel, "\ue00d", "\\gvertneqq");
+defineSymbol(math, ams, rel, "\u22e7", "\\gnsim");
+defineSymbol(math, ams, rel, "\u2a8a", "\\gnapprox");
+defineSymbol(math, ams, rel, "\u2281", "\\nsucc");
+defineSymbol(math, ams, rel, "\u22e1", "\\nsucceq");
+defineSymbol(math, ams, rel, "\u22e9", "\\succnsim");
+defineSymbol(math, ams, rel, "\u2aba", "\\succnapprox");
+defineSymbol(math, ams, rel, "\u2246", "\\ncong");
+defineSymbol(math, ams, rel, "\ue007", "\\nshortparallel");
+defineSymbol(math, ams, rel, "\u2226", "\\nparallel");
+defineSymbol(math, ams, rel, "\u22af", "\\nVDash");
+defineSymbol(math, ams, rel, "\u22eb", "\\ntriangleright");
+defineSymbol(math, ams, rel, "\u22ed", "\\ntrianglerighteq");
+defineSymbol(math, ams, rel, "\ue018", "\\nsupseteqq");
+defineSymbol(math, ams, rel, "\u228b", "\\supsetneq");
+defineSymbol(math, ams, rel, "\ue01b", "\\varsupsetneq");
+defineSymbol(math, ams, rel, "\u2acc", "\\supsetneqq");
+defineSymbol(math, ams, rel, "\ue019", "\\varsupsetneqq");
+defineSymbol(math, ams, rel, "\u22ae", "\\nVdash");
+defineSymbol(math, ams, rel, "\u2ab5", "\\precneqq");
+defineSymbol(math, ams, rel, "\u2ab6", "\\succneqq");
+defineSymbol(math, ams, rel, "\ue016", "\\nsubseteqq");
+defineSymbol(math, ams, bin, "\u22b4", "\\unlhd");
+defineSymbol(math, ams, bin, "\u22b5", "\\unrhd");
+
+// AMS Negated Arrows
+defineSymbol(math, ams, rel, "\u219a", "\\nleftarrow");
+defineSymbol(math, ams, rel, "\u219b", "\\nrightarrow");
+defineSymbol(math, ams, rel, "\u21cd", "\\nLeftarrow");
+defineSymbol(math, ams, rel, "\u21cf", "\\nRightarrow");
+defineSymbol(math, ams, rel, "\u21ae", "\\nleftrightarrow");
+defineSymbol(math, ams, rel, "\u21ce", "\\nLeftrightarrow");
+
+// AMS Misc
+defineSymbol(math, ams, rel, "\u25b3", "\\vartriangle");
+defineSymbol(math, ams, textord, "\u210f", "\\hslash");
+defineSymbol(math, ams, textord, "\u25bd", "\\triangledown");
+defineSymbol(math, ams, textord, "\u25ca", "\\lozenge");
+defineSymbol(math, ams, textord, "\u24c8", "\\circledS");
+defineSymbol(math, ams, textord, "\u00ae", "\\circledR");
+defineSymbol(math, ams, textord, "\u2221", "\\measuredangle");
+defineSymbol(math, ams, textord, "\u2204", "\\nexists");
+defineSymbol(math, ams, textord, "\u2127", "\\mho");
+defineSymbol(math, ams, textord, "\u2132", "\\Finv");
+defineSymbol(math, ams, textord, "\u2141", "\\Game");
+defineSymbol(math, ams, textord, "\u006b", "\\Bbbk");
+defineSymbol(math, ams, textord, "\u2035", "\\backprime");
+defineSymbol(math, ams, textord, "\u25b2", "\\blacktriangle");
+defineSymbol(math, ams, textord, "\u25bc", "\\blacktriangledown");
+defineSymbol(math, ams, textord, "\u25a0", "\\blacksquare");
+defineSymbol(math, ams, textord, "\u29eb", "\\blacklozenge");
+defineSymbol(math, ams, textord, "\u2605", "\\bigstar");
+defineSymbol(math, ams, textord, "\u2222", "\\sphericalangle");
+defineSymbol(math, ams, textord, "\u2201", "\\complement");
+defineSymbol(math, ams, textord, "\u00f0", "\\eth");
+defineSymbol(math, ams, textord, "\u2571", "\\diagup");
+defineSymbol(math, ams, textord, "\u2572", "\\diagdown");
+defineSymbol(math, ams, textord, "\u25a1", "\\square");
+defineSymbol(math, ams, textord, "\u25a1", "\\Box");
+defineSymbol(math, ams, textord, "\u25ca", "\\Diamond");
+defineSymbol(math, ams, textord, "\u00a5", "\\yen");
+defineSymbol(math, ams, textord, "\u2713", "\\checkmark");
+
+// AMS Hebrew
+defineSymbol(math, ams, textord, "\u2136", "\\beth");
+defineSymbol(math, ams, textord, "\u2138", "\\daleth");
+defineSymbol(math, ams, textord, "\u2137", "\\gimel");
+
+// AMS Greek
+defineSymbol(math, ams, textord, "\u03dd", "\\digamma");
+defineSymbol(math, ams, textord, "\u03f0", "\\varkappa");
+
+// AMS Delimiters
+defineSymbol(math, ams, open, "\u250c", "\\ulcorner");
+defineSymbol(math, ams, close, "\u2510", "\\urcorner");
+defineSymbol(math, ams, open, "\u2514", "\\llcorner");
+defineSymbol(math, ams, close, "\u2518", "\\lrcorner");
+
+// AMS Binary Relations
+defineSymbol(math, ams, rel, "\u2266", "\\leqq");
+defineSymbol(math, ams, rel, "\u2a7d", "\\leqslant");
+defineSymbol(math, ams, rel, "\u2a95", "\\eqslantless");
+defineSymbol(math, ams, rel, "\u2272", "\\lesssim");
+defineSymbol(math, ams, rel, "\u2a85", "\\lessapprox");
+defineSymbol(math, ams, rel, "\u224a", "\\approxeq");
+defineSymbol(math, ams, bin, "\u22d6", "\\lessdot");
+defineSymbol(math, ams, rel, "\u22d8", "\\lll");
+defineSymbol(math, ams, rel, "\u2276", "\\lessgtr");
+defineSymbol(math, ams, rel, "\u22da", "\\lesseqgtr");
+defineSymbol(math, ams, rel, "\u2a8b", "\\lesseqqgtr");
+defineSymbol(math, ams, rel, "\u2251", "\\doteqdot");
+defineSymbol(math, ams, rel, "\u2253", "\\risingdotseq");
+defineSymbol(math, ams, rel, "\u2252", "\\fallingdotseq");
+defineSymbol(math, ams, rel, "\u223d", "\\backsim");
+defineSymbol(math, ams, rel, "\u22cd", "\\backsimeq");
+defineSymbol(math, ams, rel, "\u2ac5", "\\subseteqq");
+defineSymbol(math, ams, rel, "\u22d0", "\\Subset");
+defineSymbol(math, ams, rel, "\u228f", "\\sqsubset");
+defineSymbol(math, ams, rel, "\u227c", "\\preccurlyeq");
+defineSymbol(math, ams, rel, "\u22de", "\\curlyeqprec");
+defineSymbol(math, ams, rel, "\u227e", "\\precsim");
+defineSymbol(math, ams, rel, "\u2ab7", "\\precapprox");
+defineSymbol(math, ams, rel, "\u22b2", "\\vartriangleleft");
+defineSymbol(math, ams, rel, "\u22b4", "\\trianglelefteq");
+defineSymbol(math, ams, rel, "\u22a8", "\\vDash");
+defineSymbol(math, ams, rel, "\u22aa", "\\Vvdash");
+defineSymbol(math, ams, rel, "\u2323", "\\smallsmile");
+defineSymbol(math, ams, rel, "\u2322", "\\smallfrown");
+defineSymbol(math, ams, rel, "\u224f", "\\bumpeq");
+defineSymbol(math, ams, rel, "\u224e", "\\Bumpeq");
+defineSymbol(math, ams, rel, "\u2267", "\\geqq");
+defineSymbol(math, ams, rel, "\u2a7e", "\\geqslant");
+defineSymbol(math, ams, rel, "\u2a96", "\\eqslantgtr");
+defineSymbol(math, ams, rel, "\u2273", "\\gtrsim");
+defineSymbol(math, ams, rel, "\u2a86", "\\gtrapprox");
+defineSymbol(math, ams, bin, "\u22d7", "\\gtrdot");
+defineSymbol(math, ams, rel, "\u22d9", "\\ggg");
+defineSymbol(math, ams, rel, "\u2277", "\\gtrless");
+defineSymbol(math, ams, rel, "\u22db", "\\gtreqless");
+defineSymbol(math, ams, rel, "\u2a8c", "\\gtreqqless");
+defineSymbol(math, ams, rel, "\u2256", "\\eqcirc");
+defineSymbol(math, ams, rel, "\u2257", "\\circeq");
+defineSymbol(math, ams, rel, "\u225c", "\\triangleq");
+defineSymbol(math, ams, rel, "\u223c", "\\thicksim");
+defineSymbol(math, ams, rel, "\u2248", "\\thickapprox");
+defineSymbol(math, ams, rel, "\u2ac6", "\\supseteqq");
+defineSymbol(math, ams, rel, "\u22d1", "\\Supset");
+defineSymbol(math, ams, rel, "\u2290", "\\sqsupset");
+defineSymbol(math, ams, rel, "\u227d", "\\succcurlyeq");
+defineSymbol(math, ams, rel, "\u22df", "\\curlyeqsucc");
+defineSymbol(math, ams, rel, "\u227f", "\\succsim");
+defineSymbol(math, ams, rel, "\u2ab8", "\\succapprox");
+defineSymbol(math, ams, rel, "\u22b3", "\\vartriangleright");
+defineSymbol(math, ams, rel, "\u22b5", "\\trianglerighteq");
+defineSymbol(math, ams, rel, "\u22a9", "\\Vdash");
+defineSymbol(math, ams, rel, "\u2223", "\\shortmid");
+defineSymbol(math, ams, rel, "\u2225", "\\shortparallel");
+defineSymbol(math, ams, rel, "\u226c", "\\between");
+defineSymbol(math, ams, rel, "\u22d4", "\\pitchfork");
+defineSymbol(math, ams, rel, "\u221d", "\\varpropto");
+defineSymbol(math, ams, rel, "\u25c0", "\\blacktriangleleft");
+defineSymbol(math, ams, rel, "\u2234", "\\therefore");
+defineSymbol(math, ams, rel, "\u220d", "\\backepsilon");
+defineSymbol(math, ams, rel, "\u25b6", "\\blacktriangleright");
+defineSymbol(math, ams, rel, "\u2235", "\\because");
+defineSymbol(math, ams, rel, "\u22d8", "\\llless");
+defineSymbol(math, ams, rel, "\u22d9", "\\gggtr");
+defineSymbol(math, ams, bin, "\u22b2", "\\lhd");
+defineSymbol(math, ams, bin, "\u22b3", "\\rhd");
+defineSymbol(math, ams, rel, "\u2242", "\\eqsim");
+defineSymbol(math, main, rel, "\u22c8", "\\Join");
+defineSymbol(math, ams, rel, "\u2251", "\\Doteq");
+
+// AMS Binary Operators
+defineSymbol(math, ams, bin, "\u2214", "\\dotplus");
+defineSymbol(math, ams, bin, "\u2216", "\\smallsetminus");
+defineSymbol(math, ams, bin, "\u22d2", "\\Cap");
+defineSymbol(math, ams, bin, "\u22d3", "\\Cup");
+defineSymbol(math, ams, bin, "\u2a5e", "\\doublebarwedge");
+defineSymbol(math, ams, bin, "\u229f", "\\boxminus");
+defineSymbol(math, ams, bin, "\u229e", "\\boxplus");
+defineSymbol(math, ams, bin, "\u22c7", "\\divideontimes");
+defineSymbol(math, ams, bin, "\u22c9", "\\ltimes");
+defineSymbol(math, ams, bin, "\u22ca", "\\rtimes");
+defineSymbol(math, ams, bin, "\u22cb", "\\leftthreetimes");
+defineSymbol(math, ams, bin, "\u22cc", "\\rightthreetimes");
+defineSymbol(math, ams, bin, "\u22cf", "\\curlywedge");
+defineSymbol(math, ams, bin, "\u22ce", "\\curlyvee");
+defineSymbol(math, ams, bin, "\u229d", "\\circleddash");
+defineSymbol(math, ams, bin, "\u229b", "\\circledast");
+defineSymbol(math, ams, bin, "\u22c5", "\\centerdot");
+defineSymbol(math, ams, bin, "\u22ba", "\\intercal");
+defineSymbol(math, ams, bin, "\u22d2", "\\doublecap");
+defineSymbol(math, ams, bin, "\u22d3", "\\doublecup");
+defineSymbol(math, ams, bin, "\u22a0", "\\boxtimes");
+
+// AMS Arrows
+defineSymbol(math, ams, rel, "\u21e2", "\\dashrightarrow");
+defineSymbol(math, ams, rel, "\u21e0", "\\dashleftarrow");
+defineSymbol(math, ams, rel, "\u21c7", "\\leftleftarrows");
+defineSymbol(math, ams, rel, "\u21c6", "\\leftrightarrows");
+defineSymbol(math, ams, rel, "\u21da", "\\Lleftarrow");
+defineSymbol(math, ams, rel, "\u219e", "\\twoheadleftarrow");
+defineSymbol(math, ams, rel, "\u21a2", "\\leftarrowtail");
+defineSymbol(math, ams, rel, "\u21ab", "\\looparrowleft");
+defineSymbol(math, ams, rel, "\u21cb", "\\leftrightharpoons");
+defineSymbol(math, ams, rel, "\u21b6", "\\curvearrowleft");
+defineSymbol(math, ams, rel, "\u21ba", "\\circlearrowleft");
+defineSymbol(math, ams, rel, "\u21b0", "\\Lsh");
+defineSymbol(math, ams, rel, "\u21c8", "\\upuparrows");
+defineSymbol(math, ams, rel, "\u21bf", "\\upharpoonleft");
+defineSymbol(math, ams, rel, "\u21c3", "\\downharpoonleft");
+defineSymbol(math, ams, rel, "\u22b8", "\\multimap");
+defineSymbol(math, ams, rel, "\u21ad", "\\leftrightsquigarrow");
+defineSymbol(math, ams, rel, "\u21c9", "\\rightrightarrows");
+defineSymbol(math, ams, rel, "\u21c4", "\\rightleftarrows");
+defineSymbol(math, ams, rel, "\u21a0", "\\twoheadrightarrow");
+defineSymbol(math, ams, rel, "\u21a3", "\\rightarrowtail");
+defineSymbol(math, ams, rel, "\u21ac", "\\looparrowright");
+defineSymbol(math, ams, rel, "\u21b7", "\\curvearrowright");
+defineSymbol(math, ams, rel, "\u21bb", "\\circlearrowright");
+defineSymbol(math, ams, rel, "\u21b1", "\\Rsh");
+defineSymbol(math, ams, rel, "\u21ca", "\\downdownarrows");
+defineSymbol(math, ams, rel, "\u21be", "\\upharpoonright");
+defineSymbol(math, ams, rel, "\u21c2", "\\downharpoonright");
+defineSymbol(math, ams, rel, "\u21dd", "\\rightsquigarrow");
+defineSymbol(math, ams, rel, "\u21dd", "\\leadsto");
+defineSymbol(math, ams, rel, "\u21db", "\\Rrightarrow");
+defineSymbol(math, ams, rel, "\u21be", "\\restriction");
+
+defineSymbol(math, main, textord, "\u2018", "`");
+defineSymbol(math, main, textord, "$", "\\$");
+defineSymbol(text, main, textord, "$", "\\$");
+defineSymbol(math, main, textord, "%", "\\%");
+defineSymbol(text, main, textord, "%", "\\%");
+defineSymbol(math, main, textord, "_", "\\_");
+defineSymbol(text, main, textord, "_", "\\_");
+defineSymbol(math, main, textord, "\u2220", "\\angle");
+defineSymbol(math, main, textord, "\u221e", "\\infty");
+defineSymbol(math, main, textord, "\u2032", "\\prime");
+defineSymbol(math, main, textord, "\u25b3", "\\triangle");
+defineSymbol(math, main, textord, "\u0393", "\\Gamma");
+defineSymbol(math, main, textord, "\u0394", "\\Delta");
+defineSymbol(math, main, textord, "\u0398", "\\Theta");
+defineSymbol(math, main, textord, "\u039b", "\\Lambda");
+defineSymbol(math, main, textord, "\u039e", "\\Xi");
+defineSymbol(math, main, textord, "\u03a0", "\\Pi");
+defineSymbol(math, main, textord, "\u03a3", "\\Sigma");
+defineSymbol(math, main, textord, "\u03a5", "\\Upsilon");
+defineSymbol(math, main, textord, "\u03a6", "\\Phi");
+defineSymbol(math, main, textord, "\u03a8", "\\Psi");
+defineSymbol(math, main, textord, "\u03a9", "\\Omega");
+defineSymbol(math, main, textord, "\u00ac", "\\neg");
+defineSymbol(math, main, textord, "\u00ac", "\\lnot");
+defineSymbol(math, main, textord, "\u22a4", "\\top");
+defineSymbol(math, main, textord, "\u22a5", "\\bot");
+defineSymbol(math, main, textord, "\u2205", "\\emptyset");
+defineSymbol(math, ams, textord, "\u2205", "\\varnothing");
+defineSymbol(math, main, mathord, "\u03b1", "\\alpha");
+defineSymbol(math, main, mathord, "\u03b2", "\\beta");
+defineSymbol(math, main, mathord, "\u03b3", "\\gamma");
+defineSymbol(math, main, mathord, "\u03b4", "\\delta");
+defineSymbol(math, main, mathord, "\u03f5", "\\epsilon");
+defineSymbol(math, main, mathord, "\u03b6", "\\zeta");
+defineSymbol(math, main, mathord, "\u03b7", "\\eta");
+defineSymbol(math, main, mathord, "\u03b8", "\\theta");
+defineSymbol(math, main, mathord, "\u03b9", "\\iota");
+defineSymbol(math, main, mathord, "\u03ba", "\\kappa");
+defineSymbol(math, main, mathord, "\u03bb", "\\lambda");
+defineSymbol(math, main, mathord, "\u03bc", "\\mu");
+defineSymbol(math, main, mathord, "\u03bd", "\\nu");
+defineSymbol(math, main, mathord, "\u03be", "\\xi");
+defineSymbol(math, main, mathord, "o", "\\omicron");
+defineSymbol(math, main, mathord, "\u03c0", "\\pi");
+defineSymbol(math, main, mathord, "\u03c1", "\\rho");
+defineSymbol(math, main, mathord, "\u03c3", "\\sigma");
+defineSymbol(math, main, mathord, "\u03c4", "\\tau");
+defineSymbol(math, main, mathord, "\u03c5", "\\upsilon");
+defineSymbol(math, main, mathord, "\u03d5", "\\phi");
+defineSymbol(math, main, mathord, "\u03c7", "\\chi");
+defineSymbol(math, main, mathord, "\u03c8", "\\psi");
+defineSymbol(math, main, mathord, "\u03c9", "\\omega");
+defineSymbol(math, main, mathord, "\u03b5", "\\varepsilon");
+defineSymbol(math, main, mathord, "\u03d1", "\\vartheta");
+defineSymbol(math, main, mathord, "\u03d6", "\\varpi");
+defineSymbol(math, main, mathord, "\u03f1", "\\varrho");
+defineSymbol(math, main, mathord, "\u03c2", "\\varsigma");
+defineSymbol(math, main, mathord, "\u03c6", "\\varphi");
+defineSymbol(math, main, bin, "\u2217", "*");
+defineSymbol(math, main, bin, "+", "+");
+defineSymbol(math, main, bin, "\u2212", "-");
+defineSymbol(math, main, bin, "\u22c5", "\\cdot");
+defineSymbol(math, main, bin, "\u2218", "\\circ");
+defineSymbol(math, main, bin, "\u00f7", "\\div");
+defineSymbol(math, main, bin, "\u00b1", "\\pm");
+defineSymbol(math, main, bin, "\u00d7", "\\times");
+defineSymbol(math, main, bin, "\u2229", "\\cap");
+defineSymbol(math, main, bin, "\u222a", "\\cup");
+defineSymbol(math, main, bin, "\u2216", "\\setminus");
+defineSymbol(math, main, bin, "\u2227", "\\land");
+defineSymbol(math, main, bin, "\u2228", "\\lor");
+defineSymbol(math, main, bin, "\u2227", "\\wedge");
+defineSymbol(math, main, bin, "\u2228", "\\vee");
+defineSymbol(math, main, textord, "\u221a", "\\surd");
+defineSymbol(math, main, open, "(", "(");
+defineSymbol(math, main, open, "[", "[");
+defineSymbol(math, main, open, "\u27e8", "\\langle");
+defineSymbol(math, main, open, "\u2223", "\\lvert");
+defineSymbol(math, main, open, "\u2225", "\\lVert");
+defineSymbol(math, main, close, ")", ")");
+defineSymbol(math, main, close, "]", "]");
+defineSymbol(math, main, close, "?", "?");
+defineSymbol(math, main, close, "!", "!");
+defineSymbol(math, main, close, "\u27e9", "\\rangle");
+defineSymbol(math, main, close, "\u2223", "\\rvert");
+defineSymbol(math, main, close, "\u2225", "\\rVert");
+defineSymbol(math, main, rel, "=", "=");
+defineSymbol(math, main, rel, "<", "<");
+defineSymbol(math, main, rel, ">", ">");
+defineSymbol(math, main, rel, ":", ":");
+defineSymbol(math, main, rel, "\u2248", "\\approx");
+defineSymbol(math, main, rel, "\u2245", "\\cong");
+defineSymbol(math, main, rel, "\u2265", "\\ge");
+defineSymbol(math, main, rel, "\u2265", "\\geq");
+defineSymbol(math, main, rel, "\u2190", "\\gets");
+defineSymbol(math, main, rel, ">", "\\gt");
+defineSymbol(math, main, rel, "\u2208", "\\in");
+defineSymbol(math, main, rel, "\u2209", "\\notin");
+defineSymbol(math, main, rel, "\u2282", "\\subset");
+defineSymbol(math, main, rel, "\u2283", "\\supset");
+defineSymbol(math, main, rel, "\u2286", "\\subseteq");
+defineSymbol(math, main, rel, "\u2287", "\\supseteq");
+defineSymbol(math, ams, rel, "\u2288", "\\nsubseteq");
+defineSymbol(math, ams, rel, "\u2289", "\\nsupseteq");
+defineSymbol(math, main, rel, "\u22a8", "\\models");
+defineSymbol(math, main, rel, "\u2190", "\\leftarrow");
+defineSymbol(math, main, rel, "\u2264", "\\le");
+defineSymbol(math, main, rel, "\u2264", "\\leq");
+defineSymbol(math, main, rel, "<", "\\lt");
+defineSymbol(math, main, rel, "\u2260", "\\ne");
+defineSymbol(math, main, rel, "\u2260", "\\neq");
+defineSymbol(math, main, rel, "\u2192", "\\rightarrow");
+defineSymbol(math, main, rel, "\u2192", "\\to");
+defineSymbol(math, ams, rel, "\u2271", "\\ngeq");
+defineSymbol(math, ams, rel, "\u2270", "\\nleq");
+defineSymbol(math, main, spacing, null, "\\!");
+defineSymbol(math, main, spacing, "\u00a0", "\\ ");
+defineSymbol(math, main, spacing, "\u00a0", "~");
+defineSymbol(math, main, spacing, null, "\\,");
+defineSymbol(math, main, spacing, null, "\\:");
+defineSymbol(math, main, spacing, null, "\\;");
+defineSymbol(math, main, spacing, null, "\\enspace");
+defineSymbol(math, main, spacing, null, "\\qquad");
+defineSymbol(math, main, spacing, null, "\\quad");
+defineSymbol(math, main, spacing, "\u00a0", "\\space");
+defineSymbol(math, main, punct, ",", ",");
+defineSymbol(math, main, punct, ";", ";");
+defineSymbol(math, main, punct, ":", "\\colon");
+defineSymbol(math, ams, bin, "\u22bc", "\\barwedge");
+defineSymbol(math, ams, bin, "\u22bb", "\\veebar");
+defineSymbol(math, main, bin, "\u2299", "\\odot");
+defineSymbol(math, main, bin, "\u2295", "\\oplus");
+defineSymbol(math, main, bin, "\u2297", "\\otimes");
+defineSymbol(math, main, textord, "\u2202", "\\partial");
+defineSymbol(math, main, bin, "\u2298", "\\oslash");
+defineSymbol(math, ams, bin, "\u229a", "\\circledcirc");
+defineSymbol(math, ams, bin, "\u22a1", "\\boxdot");
+defineSymbol(math, main, bin, "\u25b3", "\\bigtriangleup");
+defineSymbol(math, main, bin, "\u25bd", "\\bigtriangledown");
+defineSymbol(math, main, bin, "\u2020", "\\dagger");
+defineSymbol(math, main, bin, "\u22c4", "\\diamond");
+defineSymbol(math, main, bin, "\u22c6", "\\star");
+defineSymbol(math, main, bin, "\u25c3", "\\triangleleft");
+defineSymbol(math, main, bin, "\u25b9", "\\triangleright");
+defineSymbol(math, main, open, "{", "\\{");
+defineSymbol(text, main, textord, "{", "\\{");
+defineSymbol(math, main, close, "}", "\\}");
+defineSymbol(text, main, textord, "}", "\\}");
+defineSymbol(math, main, open, "{", "\\lbrace");
+defineSymbol(math, main, close, "}", "\\rbrace");
+defineSymbol(math, main, open, "[", "\\lbrack");
+defineSymbol(math, main, close, "]", "\\rbrack");
+defineSymbol(math, main, open, "\u230a", "\\lfloor");
+defineSymbol(math, main, close, "\u230b", "\\rfloor");
+defineSymbol(math, main, open, "\u2308", "\\lceil");
+defineSymbol(math, main, close, "\u2309", "\\rceil");
+defineSymbol(math, main, textord, "\\", "\\backslash");
+defineSymbol(math, main, textord, "\u2223", "|");
+defineSymbol(math, main, textord, "\u2223", "\\vert");
+defineSymbol(math, main, textord, "\u2225", "\\|");
+defineSymbol(math, main, textord, "\u2225", "\\Vert");
+defineSymbol(math, main, rel, "\u2191", "\\uparrow");
+defineSymbol(math, main, rel, "\u21d1", "\\Uparrow");
+defineSymbol(math, main, rel, "\u2193", "\\downarrow");
+defineSymbol(math, main, rel, "\u21d3", "\\Downarrow");
+defineSymbol(math, main, rel, "\u2195", "\\updownarrow");
+defineSymbol(math, main, rel, "\u21d5", "\\Updownarrow");
+defineSymbol(math, math, op, "\u2210", "\\coprod");
+defineSymbol(math, math, op, "\u22c1", "\\bigvee");
+defineSymbol(math, math, op, "\u22c0", "\\bigwedge");
+defineSymbol(math, math, op, "\u2a04", "\\biguplus");
+defineSymbol(math, math, op, "\u22c2", "\\bigcap");
+defineSymbol(math, math, op, "\u22c3", "\\bigcup");
+defineSymbol(math, math, op, "\u222b", "\\int");
+defineSymbol(math, math, op, "\u222b", "\\intop");
+defineSymbol(math, math, op, "\u222c", "\\iint");
+defineSymbol(math, math, op, "\u222d", "\\iiint");
+defineSymbol(math, math, op, "\u220f", "\\prod");
+defineSymbol(math, math, op, "\u2211", "\\sum");
+defineSymbol(math, math, op, "\u2a02", "\\bigotimes");
+defineSymbol(math, math, op, "\u2a01", "\\bigoplus");
+defineSymbol(math, math, op, "\u2a00", "\\bigodot");
+defineSymbol(math, math, op, "\u222e", "\\oint");
+defineSymbol(math, math, op, "\u2a06", "\\bigsqcup");
+defineSymbol(math, math, op, "\u222b", "\\smallint");
+defineSymbol(text, main, inner, "\u2026", "\\textellipsis");
+defineSymbol(math, main, inner, "\u2026", "\\mathellipsis");
+defineSymbol(text, main, inner, "\u2026", "\\ldots");
+defineSymbol(math, main, inner, "\u2026", "\\ldots");
+defineSymbol(math, main, inner, "\u22ef", "\\cdots");
+defineSymbol(math, main, inner, "\u22f1", "\\ddots");
+defineSymbol(math, main, textord, "\u22ee", "\\vdots");
+defineSymbol(math, main, accent, "\u00b4", "\\acute");
+defineSymbol(math, main, accent, "\u0060", "\\grave");
+defineSymbol(math, main, accent, "\u00a8", "\\ddot");
+defineSymbol(math, main, accent, "\u007e", "\\tilde");
+defineSymbol(math, main, accent, "\u00af", "\\bar");
+defineSymbol(math, main, accent, "\u02d8", "\\breve");
+defineSymbol(math, main, accent, "\u02c7", "\\check");
+defineSymbol(math, main, accent, "\u005e", "\\hat");
+defineSymbol(math, main, accent, "\u20d7", "\\vec");
+defineSymbol(math, main, accent, "\u02d9", "\\dot");
+defineSymbol(math, main, mathord, "\u0131", "\\imath");
+defineSymbol(math, main, mathord, "\u0237", "\\jmath");
+
+defineSymbol(text, main, textord, "\u2013", "--");
+defineSymbol(text, main, textord, "\u2014", "---");
+defineSymbol(text, main, textord, "\u2018", "`");
+defineSymbol(text, main, textord, "\u2019", "'");
+defineSymbol(text, main, textord, "\u201c", "``");
+defineSymbol(text, main, textord, "\u201d", "''");
+defineSymbol(math, main, textord, "\u00b0", "\\degree");
+defineSymbol(text, main, textord, "\u00b0", "\\degree");
+defineSymbol(math, main, mathord, "\u00a3", "\\pounds");
+defineSymbol(math, ams, textord, "\u2720", "\\maltese");
+defineSymbol(text, ams, textord, "\u2720", "\\maltese");
+
+defineSymbol(text, main, spacing, "\u00a0", "\\ ");
+defineSymbol(text, main, spacing, "\u00a0", " ");
+defineSymbol(text, main, spacing, "\u00a0", "~");
+
+// There are lots of symbols which are the same, so we add them in afterwards.
+var i;
+var ch;
+
+// All of these are textords in math mode
+var mathTextSymbols = "0123456789/@.\"";
+for (i = 0; i < mathTextSymbols.length; i++) {
+    ch = mathTextSymbols.charAt(i);
+    defineSymbol(math, main, textord, ch, ch);
+}
+
+// All of these are textords in text mode
+var textSymbols = "0123456789!@*()-=+[]\";:?/.,";
+for (i = 0; i < textSymbols.length; i++) {
+    ch = textSymbols.charAt(i);
+    defineSymbol(text, main, textord, ch, ch);
+}
+
+// All of these are textords in text mode, and mathords in math mode
+var letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+for (i = 0; i < letters.length; i++) {
+    ch = letters.charAt(i);
+    defineSymbol(math, main, mathord, ch, ch);
+    defineSymbol(text, main, textord, ch, ch);
+}
+
+// Latin-1 letters
+for (i = 0x00C0; i <= 0x00D6; i++) {
+    ch = String.fromCharCode(i);
+    defineSymbol(text, main, textord, ch, ch);
+}
+
+for (i = 0x00D8; i <= 0x00F6; i++) {
+    ch = String.fromCharCode(i);
+    defineSymbol(text, main, textord, ch, ch);
+}
+
+for (i = 0x00F8; i <= 0x00FF; i++) {
+    ch = String.fromCharCode(i);
+    defineSymbol(text, main, textord, ch, ch);
+}
+
+// Cyrillic
+for (i = 0x0410; i <= 0x044F; i++) {
+    ch = String.fromCharCode(i);
+    defineSymbol(text, main, textord, ch, ch);
+}
+
+// Unicode versions of existing characters
+defineSymbol(text, main, textord, "\u2013", "–");
+defineSymbol(text, main, textord, "\u2014", "—");
+defineSymbol(text, main, textord, "\u2018", "‘");
+defineSymbol(text, main, textord, "\u2019", "’");
+defineSymbol(text, main, textord, "\u201c", "“");
+defineSymbol(text, main, textord, "\u201d", "”");
+
+},{}],24:[function(require,module,exports){
+var hangulRegex = /[\uAC00-\uD7AF]/;
+
+// This regex combines
+// - Hiragana: [\u3040-\u309F]
+// - Katakana: [\u30A0-\u30FF]
+// - CJK ideograms: [\u4E00-\u9FAF]
+// - Hangul syllables: [\uAC00-\uD7AF]
+// Notably missing are halfwidth Katakana and Romanji glyphs.
+var cjkRegex =
+    /[\u3040-\u309F]|[\u30A0-\u30FF]|[\u4E00-\u9FAF]|[\uAC00-\uD7AF]/;
+
+module.exports = {
+    cjkRegex: cjkRegex,
+    hangulRegex: hangulRegex
+};
+
+},{}],25:[function(require,module,exports){
+/**
+ * This file contains a list of utility functions which are useful in other
+ * files.
+ */
+
+/**
+ * Provide an `indexOf` function which works in IE8, but defers to native if
+ * possible.
+ */
+var nativeIndexOf = Array.prototype.indexOf;
+var indexOf = function(list, elem) {
+    if (list == null) {
+        return -1;
+    }
+    if (nativeIndexOf && list.indexOf === nativeIndexOf) {
+        return list.indexOf(elem);
+    }
+    var i = 0;
+    var l = list.length;
+    for (; i < l; i++) {
+        if (list[i] === elem) {
+            return i;
+        }
+    }
+    return -1;
+};
+
+/**
+ * Return whether an element is contained in a list
+ */
+var contains = function(list, elem) {
+    return indexOf(list, elem) !== -1;
+};
+
+/**
+ * Provide a default value if a setting is undefined
+ */
+var deflt = function(setting, defaultIfUndefined) {
+    return setting === undefined ? defaultIfUndefined : setting;
+};
+
+// hyphenate and escape adapted from Facebook's React under Apache 2 license
+
+var uppercase = /([A-Z])/g;
+var hyphenate = function(str) {
+    return str.replace(uppercase, "-$1").toLowerCase();
+};
+
+var ESCAPE_LOOKUP = {
+    "&": "&amp;",
+    ">": "&gt;",
+    "<": "&lt;",
+    "\"": "&quot;",
+    "'": "&#x27;"
+};
+
+var ESCAPE_REGEX = /[&><"']/g;
+
+function escaper(match) {
+    return ESCAPE_LOOKUP[match];
+}
+
+/**
+ * Escapes text to prevent scripting attacks.
+ *
+ * @param {*} text Text value to escape.
+ * @return {string} An escaped string.
+ */
+function escape(text) {
+    return ("" + text).replace(ESCAPE_REGEX, escaper);
+}
+
+/**
+ * A function to set the text content of a DOM element in all supported
+ * browsers. Note that we don't define this if there is no document.
+ */
+var setTextContent;
+if (typeof document !== "undefined") {
+    var testNode = document.createElement("span");
+    if ("textContent" in testNode) {
+        setTextContent = function(node, text) {
+            node.textContent = text;
+        };
+    } else {
+        setTextContent = function(node, text) {
+            node.innerText = text;
+        };
+    }
+}
+
+/**
+ * A function to clear a node.
+ */
+function clearNode(node) {
+    setTextContent(node, "");
+}
+
+module.exports = {
+    contains: contains,
+    deflt: deflt,
+    escape: escape,
+    hyphenate: hyphenate,
+    indexOf: indexOf,
+    setTextContent: setTextContent,
+    clearNode: clearNode
+};
+
+},{}]},{},[1])(1)
+});
\ No newline at end of file
diff --git a/specs/2.2/katex/katex.min.css b/specs/2.2/katex/katex.min.css
new file mode 100644
index 0000000..d6fb837
--- /dev/null
+++ b/specs/2.2/katex/katex.min.css
@@ -0,0 +1 @@
+@font-face{font-family:KaTeX_AMS;src:url(fonts/KaTeX_AMS-Regular.eot);src:url(fonts/KaTeX_AMS-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_AMS-Regular.woff2) format('woff2'),url(fonts/KaTeX_AMS-Regular.woff) format('woff'),url(fonts/KaTeX_AMS-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Caligraphic;src:url(fonts/KaTeX_Caligraphic-Bold.eot);src:url(fonts/KaTeX_Caligraphic-Bold.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Caligraphic-Bold.woff2) format('woff2'),url(fonts/KaTeX_Caligraphic-Bold.woff) format('woff'),url(fonts/KaTeX_Caligraphic-Bold.ttf) format('truetype');font-weight:700;font-style:normal}@font-face{font-family:KaTeX_Caligraphic;src:url(fonts/KaTeX_Caligraphic-Regular.eot);src:url(fonts/KaTeX_Caligraphic-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Caligraphic-Regular.woff2) format('woff2'),url(fonts/KaTeX_Caligraphic-Regular.woff) format('woff'),url(fonts/KaTeX_Caligraphic-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Fraktur;src:url(fonts/KaTeX_Fraktur-Bold.eot);src:url(fonts/KaTeX_Fraktur-Bold.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Fraktur-Bold.woff2) format('woff2'),url(fonts/KaTeX_Fraktur-Bold.woff) format('woff'),url(fonts/KaTeX_Fraktur-Bold.ttf) format('truetype');font-weight:700;font-style:normal}@font-face{font-family:KaTeX_Fraktur;src:url(fonts/KaTeX_Fraktur-Regular.eot);src:url(fonts/KaTeX_Fraktur-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Fraktur-Regular.woff2) format('woff2'),url(fonts/KaTeX_Fraktur-Regular.woff) format('woff'),url(fonts/KaTeX_Fraktur-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Main;src:url(fonts/KaTeX_Main-Bold.eot);src:url(fonts/KaTeX_Main-Bold.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Main-Bold.woff2) format('woff2'),url(fonts/KaTeX_Main-Bold.woff) format('woff'),url(fonts/KaTeX_Main-Bold.ttf) format('truetype');font-weight:700;font-style:normal}@font-face{font-family:KaTeX_Main;src:url(fonts/KaTeX_Main-Italic.eot);src:url(fonts/KaTeX_Main-Italic.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Main-Italic.woff2) format('woff2'),url(fonts/KaTeX_Main-Italic.woff) format('woff'),url(fonts/KaTeX_Main-Italic.ttf) format('truetype');font-weight:400;font-style:italic}@font-face{font-family:KaTeX_Main;src:url(fonts/KaTeX_Main-Regular.eot);src:url(fonts/KaTeX_Main-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Main-Regular.woff2) format('woff2'),url(fonts/KaTeX_Main-Regular.woff) format('woff'),url(fonts/KaTeX_Main-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Math;src:url(fonts/KaTeX_Math-Italic.eot);src:url(fonts/KaTeX_Math-Italic.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Math-Italic.woff2) format('woff2'),url(fonts/KaTeX_Math-Italic.woff) format('woff'),url(fonts/KaTeX_Math-Italic.ttf) format('truetype');font-weight:400;font-style:italic}@font-face{font-family:KaTeX_SansSerif;src:url(fonts/KaTeX_SansSerif-Regular.eot);src:url(fonts/KaTeX_SansSerif-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_SansSerif-Regular.woff2) format('woff2'),url(fonts/KaTeX_SansSerif-Regular.woff) format('woff'),url(fonts/KaTeX_SansSerif-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Script;src:url(fonts/KaTeX_Script-Regular.eot);src:url(fonts/KaTeX_Script-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Script-Regular.woff2) format('woff2'),url(fonts/KaTeX_Script-Regular.woff) format('woff'),url(fonts/KaTeX_Script-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Size1;src:url(fonts/KaTeX_Size1-Regular.eot);src:url(fonts/KaTeX_Size1-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Size1-Regular.woff2) format('woff2'),url(fonts/KaTeX_Size1-Regular.woff) format('woff'),url(fonts/KaTeX_Size1-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Size2;src:url(fonts/KaTeX_Size2-Regular.eot);src:url(fonts/KaTeX_Size2-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Size2-Regular.woff2) format('woff2'),url(fonts/KaTeX_Size2-Regular.woff) format('woff'),url(fonts/KaTeX_Size2-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Size3;src:url(fonts/KaTeX_Size3-Regular.eot);src:url(fonts/KaTeX_Size3-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Size3-Regular.woff2) format('woff2'),url(fonts/KaTeX_Size3-Regular.woff) format('woff'),url(fonts/KaTeX_Size3-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Size4;src:url(fonts/KaTeX_Size4-Regular.eot);src:url(fonts/KaTeX_Size4-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Size4-Regular.woff2) format('woff2'),url(fonts/KaTeX_Size4-Regular.woff) format('woff'),url(fonts/KaTeX_Size4-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Typewriter;src:url(fonts/KaTeX_Typewriter-Regular.eot);src:url(fonts/KaTeX_Typewriter-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Typewriter-Regular.woff2) format('woff2'),url(fonts/KaTeX_Typewriter-Regular.woff) format('woff'),url(fonts/KaTeX_Typewriter-Regular.ttf) format('truetype');font-weight:400;font-style:normal}.katex-display{display:block;margin:1em 0;text-align:center}.katex-display>.katex{display:inline-block;text-align:initial}.katex{font:400 1.21em KaTeX_Main,Times New Roman,serif;line-height:1.2;white-space:nowrap;text-indent:0}.katex .katex-html{display:inline-block}.katex .katex-mathml{position:absolute;clip:rect(1px,1px,1px,1px);padding:0;border:0;height:1px;width:1px;overflow:hidden}.katex .base,.katex .strut{display:inline-block}.katex .mathrm{font-style:normal}.katex .textit{font-style:italic}.katex .mathit{font-family:KaTeX_Math;font-style:italic}.katex .mathbf{font-family:KaTeX_Main;font-weight:700}.katex .amsrm,.katex .mathbb{font-family:KaTeX_AMS}.katex .mathcal{font-family:KaTeX_Caligraphic}.katex .mathfrak{font-family:KaTeX_Fraktur}.katex .mathtt{font-family:KaTeX_Typewriter}.katex .mathscr{font-family:KaTeX_Script}.katex .mathsf{font-family:KaTeX_SansSerif}.katex .mainit{font-family:KaTeX_Main;font-style:italic}.katex .mord+.mop{margin-left:.16667em}.katex .mord+.mbin{margin-left:.22222em}.katex .mord+.mrel{margin-left:.27778em}.katex .mop+.mop,.katex .mop+.mord,.katex .mord+.minner{margin-left:.16667em}.katex .mop+.mrel{margin-left:.27778em}.katex .mop+.minner{margin-left:.16667em}.katex .mbin+.minner,.katex .mbin+.mop,.katex .mbin+.mopen,.katex .mbin+.mord{margin-left:.22222em}.katex .mrel+.minner,.katex .mrel+.mop,.katex .mrel+.mopen,.katex .mrel+.mord{margin-left:.27778em}.katex .mclose+.mop{margin-left:.16667em}.katex .mclose+.mbin{margin-left:.22222em}.katex .mclose+.mrel{margin-left:.27778em}.katex .mclose+.minner,.katex .minner+.mop,.katex .minner+.mord,.katex .mpunct+.mclose,.katex .mpunct+.minner,.katex .mpunct+.mop,.katex .mpunct+.mopen,.katex .mpunct+.mord,.katex .mpunct+.mpunct,.katex .mpunct+.mrel{margin-left:.16667em}.katex .minner+.mbin{margin-left:.22222em}.katex .minner+.mrel{margin-left:.27778em}.katex .minner+.minner,.katex .minner+.mopen,.katex .minner+.mpunct{margin-left:.16667em}.katex .mbin.mtight,.katex .mclose.mtight,.katex .minner.mtight,.katex .mop.mtight,.katex .mopen.mtight,.katex .mord.mtight,.katex .mpunct.mtight,.katex .mrel.mtight{margin-left:0}.katex .mclose+.mop.mtight,.katex .minner+.mop.mtight,.katex .mop+.mop.mtight,.katex .mop+.mord.mtight,.katex .mord+.mop.mtight{margin-left:.16667em}.katex .reset-textstyle.textstyle{font-size:1em}.katex .reset-textstyle.scriptstyle{font-size:.7em}.katex .reset-textstyle.scriptscriptstyle{font-size:.5em}.katex .reset-scriptstyle.textstyle{font-size:1.42857em}.katex .reset-scriptstyle.scriptstyle{font-size:1em}.katex .reset-scriptstyle.scriptscriptstyle{font-size:.71429em}.katex .reset-scriptscriptstyle.textstyle{font-size:2em}.katex .reset-scriptscriptstyle.scriptstyle{font-size:1.4em}.katex .reset-scriptscriptstyle.scriptscriptstyle{font-size:1em}.katex .style-wrap{position:relative}.katex .vlist{display:inline-block}.katex .vlist>span{display:block;height:0;position:relative}.katex .vlist>span>span{display:inline-block}.katex .vlist .baseline-fix{display:inline-table;table-layout:fixed}.katex .msupsub{text-align:left}.katex .mfrac>span>span{text-align:center}.katex .mfrac .frac-line{width:100%}.katex .mfrac .frac-line:before{border-bottom-style:solid;border-bottom-width:1px;content:"";display:block}.katex .mfrac .frac-line:after{border-bottom-style:solid;border-bottom-width:.04em;content:"";display:block;margin-top:-1px}.katex .mspace{display:inline-block}.katex .mspace.negativethinspace{margin-left:-.16667em}.katex .mspace.thinspace{width:.16667em}.katex .mspace.negativemediumspace{margin-left:-.22222em}.katex .mspace.mediumspace{width:.22222em}.katex .mspace.thickspace{width:.27778em}.katex .mspace.sixmuspace{width:.333333em}.katex .mspace.eightmuspace{width:.444444em}.katex .mspace.enspace{width:.5em}.katex .mspace.twelvemuspace{width:.666667em}.katex .mspace.quad{width:1em}.katex .mspace.qquad{width:2em}.katex .llap,.katex .rlap{width:0;position:relative}.katex .llap>.inner,.katex .rlap>.inner{position:absolute}.katex .llap>.fix,.katex .rlap>.fix{display:inline-block}.katex .llap>.inner{right:0}.katex .rlap>.inner{left:0}.katex .katex-logo .a{font-size:.75em;margin-left:-.32em;position:relative;top:-.2em}.katex .katex-logo .t{margin-left:-.23em}.katex .katex-logo .e{margin-left:-.1667em;position:relative;top:.2155em}.katex .katex-logo .x{margin-left:-.125em}.katex .rule{display:inline-block;border:0 solid;position:relative}.katex .overline .overline-line,.katex .underline .underline-line{width:100%}.katex .overline .overline-line:before,.katex .underline .underline-line:before{border-bottom-style:solid;border-bottom-width:1px;content:"";display:block}.katex .overline .overline-line:after,.katex .underline .underline-line:after{border-bottom-style:solid;border-bottom-width:.04em;content:"";display:block;margin-top:-1px}.katex .sqrt>.sqrt-sign{position:relative}.katex .sqrt .sqrt-line{width:100%}.katex .sqrt .sqrt-line:before{border-bottom-style:solid;border-bottom-width:1px;content:"";display:block}.katex .sqrt .sqrt-line:after{border-bottom-style:solid;border-bottom-width:.04em;content:"";display:block;margin-top:-1px}.katex .sqrt>.root{margin-left:.27777778em;margin-right:-.55555556em}.katex .fontsize-ensurer,.katex .sizing{display:inline-block}.katex .fontsize-ensurer.reset-size1.size1,.katex .sizing.reset-size1.size1{font-size:1em}.katex .fontsize-ensurer.reset-size1.size2,.katex .sizing.reset-size1.size2{font-size:1.4em}.katex .fontsize-ensurer.reset-size1.size3,.katex .sizing.reset-size1.size3{font-size:1.6em}.katex .fontsize-ensurer.reset-size1.size4,.katex .sizing.reset-size1.size4{font-size:1.8em}.katex .fontsize-ensurer.reset-size1.size5,.katex .sizing.reset-size1.size5{font-size:2em}.katex .fontsize-ensurer.reset-size1.size6,.katex .sizing.reset-size1.size6{font-size:2.4em}.katex .fontsize-ensurer.reset-size1.size7,.katex .sizing.reset-size1.size7{font-size:2.88em}.katex .fontsize-ensurer.reset-size1.size8,.katex .sizing.reset-size1.size8{font-size:3.46em}.katex .fontsize-ensurer.reset-size1.size9,.katex .sizing.reset-size1.size9{font-size:4.14em}.katex .fontsize-ensurer.reset-size1.size10,.katex .sizing.reset-size1.size10{font-size:4.98em}.katex .fontsize-ensurer.reset-size2.size1,.katex .sizing.reset-size2.size1{font-size:.71428571em}.katex .fontsize-ensurer.reset-size2.size2,.katex .sizing.reset-size2.size2{font-size:1em}.katex .fontsize-ensurer.reset-size2.size3,.katex .sizing.reset-size2.size3{font-size:1.14285714em}.katex .fontsize-ensurer.reset-size2.size4,.katex .sizing.reset-size2.size4{font-size:1.28571429em}.katex .fontsize-ensurer.reset-size2.size5,.katex .sizing.reset-size2.size5{font-size:1.42857143em}.katex .fontsize-ensurer.reset-size2.size6,.katex .sizing.reset-size2.size6{font-size:1.71428571em}.katex .fontsize-ensurer.reset-size2.size7,.katex .sizing.reset-size2.size7{font-size:2.05714286em}.katex .fontsize-ensurer.reset-size2.size8,.katex .sizing.reset-size2.size8{font-size:2.47142857em}.katex .fontsize-ensurer.reset-size2.size9,.katex .sizing.reset-size2.size9{font-size:2.95714286em}.katex .fontsize-ensurer.reset-size2.size10,.katex .sizing.reset-size2.size10{font-size:3.55714286em}.katex .fontsize-ensurer.reset-size3.size1,.katex .sizing.reset-size3.size1{font-size:.625em}.katex .fontsize-ensurer.reset-size3.size2,.katex .sizing.reset-size3.size2{font-size:.875em}.katex .fontsize-ensurer.reset-size3.size3,.katex .sizing.reset-size3.size3{font-size:1em}.katex .fontsize-ensurer.reset-size3.size4,.katex .sizing.reset-size3.size4{font-size:1.125em}.katex .fontsize-ensurer.reset-size3.size5,.katex .sizing.reset-size3.size5{font-size:1.25em}.katex .fontsize-ensurer.reset-size3.size6,.katex .sizing.reset-size3.size6{font-size:1.5em}.katex .fontsize-ensurer.reset-size3.size7,.katex .sizing.reset-size3.size7{font-size:1.8em}.katex .fontsize-ensurer.reset-size3.size8,.katex .sizing.reset-size3.size8{font-size:2.1625em}.katex .fontsize-ensurer.reset-size3.size9,.katex .sizing.reset-size3.size9{font-size:2.5875em}.katex .fontsize-ensurer.reset-size3.size10,.katex .sizing.reset-size3.size10{font-size:3.1125em}.katex .fontsize-ensurer.reset-size4.size1,.katex .sizing.reset-size4.size1{font-size:.55555556em}.katex .fontsize-ensurer.reset-size4.size2,.katex .sizing.reset-size4.size2{font-size:.77777778em}.katex .fontsize-ensurer.reset-size4.size3,.katex .sizing.reset-size4.size3{font-size:.88888889em}.katex .fontsize-ensurer.reset-size4.size4,.katex .sizing.reset-size4.size4{font-size:1em}.katex .fontsize-ensurer.reset-size4.size5,.katex .sizing.reset-size4.size5{font-size:1.11111111em}.katex .fontsize-ensurer.reset-size4.size6,.katex .sizing.reset-size4.size6{font-size:1.33333333em}.katex .fontsize-ensurer.reset-size4.size7,.katex .sizing.reset-size4.size7{font-size:1.6em}.katex .fontsize-ensurer.reset-size4.size8,.katex .sizing.reset-size4.size8{font-size:1.92222222em}.katex .fontsize-ensurer.reset-size4.size9,.katex .sizing.reset-size4.size9{font-size:2.3em}.katex .fontsize-ensurer.reset-size4.size10,.katex .sizing.reset-size4.size10{font-size:2.76666667em}.katex .fontsize-ensurer.reset-size5.size1,.katex .sizing.reset-size5.size1{font-size:.5em}.katex .fontsize-ensurer.reset-size5.size2,.katex .sizing.reset-size5.size2{font-size:.7em}.katex .fontsize-ensurer.reset-size5.size3,.katex .sizing.reset-size5.size3{font-size:.8em}.katex .fontsize-ensurer.reset-size5.size4,.katex .sizing.reset-size5.size4{font-size:.9em}.katex .fontsize-ensurer.reset-size5.size5,.katex .sizing.reset-size5.size5{font-size:1em}.katex .fontsize-ensurer.reset-size5.size6,.katex .sizing.reset-size5.size6{font-size:1.2em}.katex .fontsize-ensurer.reset-size5.size7,.katex .sizing.reset-size5.size7{font-size:1.44em}.katex .fontsize-ensurer.reset-size5.size8,.katex .sizing.reset-size5.size8{font-size:1.73em}.katex .fontsize-ensurer.reset-size5.size9,.katex .sizing.reset-size5.size9{font-size:2.07em}.katex .fontsize-ensurer.reset-size5.size10,.katex .sizing.reset-size5.size10{font-size:2.49em}.katex .fontsize-ensurer.reset-size6.size1,.katex .sizing.reset-size6.size1{font-size:.41666667em}.katex .fontsize-ensurer.reset-size6.size2,.katex .sizing.reset-size6.size2{font-size:.58333333em}.katex .fontsize-ensurer.reset-size6.size3,.katex .sizing.reset-size6.size3{font-size:.66666667em}.katex .fontsize-ensurer.reset-size6.size4,.katex .sizing.reset-size6.size4{font-size:.75em}.katex .fontsize-ensurer.reset-size6.size5,.katex .sizing.reset-size6.size5{font-size:.83333333em}.katex .fontsize-ensurer.reset-size6.size6,.katex .sizing.reset-size6.size6{font-size:1em}.katex .fontsize-ensurer.reset-size6.size7,.katex .sizing.reset-size6.size7{font-size:1.2em}.katex .fontsize-ensurer.reset-size6.size8,.katex .sizing.reset-size6.size8{font-size:1.44166667em}.katex .fontsize-ensurer.reset-size6.size9,.katex .sizing.reset-size6.size9{font-size:1.725em}.katex .fontsize-ensurer.reset-size6.size10,.katex .sizing.reset-size6.size10{font-size:2.075em}.katex .fontsize-ensurer.reset-size7.size1,.katex .sizing.reset-size7.size1{font-size:.34722222em}.katex .fontsize-ensurer.reset-size7.size2,.katex .sizing.reset-size7.size2{font-size:.48611111em}.katex .fontsize-ensurer.reset-size7.size3,.katex .sizing.reset-size7.size3{font-size:.55555556em}.katex .fontsize-ensurer.reset-size7.size4,.katex .sizing.reset-size7.size4{font-size:.625em}.katex .fontsize-ensurer.reset-size7.size5,.katex .sizing.reset-size7.size5{font-size:.69444444em}.katex .fontsize-ensurer.reset-size7.size6,.katex .sizing.reset-size7.size6{font-size:.83333333em}.katex .fontsize-ensurer.reset-size7.size7,.katex .sizing.reset-size7.size7{font-size:1em}.katex .fontsize-ensurer.reset-size7.size8,.katex .sizing.reset-size7.size8{font-size:1.20138889em}.katex .fontsize-ensurer.reset-size7.size9,.katex .sizing.reset-size7.size9{font-size:1.4375em}.katex .fontsize-ensurer.reset-size7.size10,.katex .sizing.reset-size7.size10{font-size:1.72916667em}.katex .fontsize-ensurer.reset-size8.size1,.katex .sizing.reset-size8.size1{font-size:.28901734em}.katex .fontsize-ensurer.reset-size8.size2,.katex .sizing.reset-size8.size2{font-size:.40462428em}.katex .fontsize-ensurer.reset-size8.size3,.katex .sizing.reset-size8.size3{font-size:.46242775em}.katex .fontsize-ensurer.reset-size8.size4,.katex .sizing.reset-size8.size4{font-size:.52023121em}.katex .fontsize-ensurer.reset-size8.size5,.katex .sizing.reset-size8.size5{font-size:.57803468em}.katex .fontsize-ensurer.reset-size8.size6,.katex .sizing.reset-size8.size6{font-size:.69364162em}.katex .fontsize-ensurer.reset-size8.size7,.katex .sizing.reset-size8.size7{font-size:.83236994em}.katex .fontsize-ensurer.reset-size8.size8,.katex .sizing.reset-size8.size8{font-size:1em}.katex .fontsize-ensurer.reset-size8.size9,.katex .sizing.reset-size8.size9{font-size:1.19653179em}.katex .fontsize-ensurer.reset-size8.size10,.katex .sizing.reset-size8.size10{font-size:1.43930636em}.katex .fontsize-ensurer.reset-size9.size1,.katex .sizing.reset-size9.size1{font-size:.24154589em}.katex .fontsize-ensurer.reset-size9.size2,.katex .sizing.reset-size9.size2{font-size:.33816425em}.katex .fontsize-ensurer.reset-size9.size3,.katex .sizing.reset-size9.size3{font-size:.38647343em}.katex .fontsize-ensurer.reset-size9.size4,.katex .sizing.reset-size9.size4{font-size:.43478261em}.katex .fontsize-ensurer.reset-size9.size5,.katex .sizing.reset-size9.size5{font-size:.48309179em}.katex .fontsize-ensurer.reset-size9.size6,.katex .sizing.reset-size9.size6{font-size:.57971014em}.katex .fontsize-ensurer.reset-size9.size7,.katex .sizing.reset-size9.size7{font-size:.69565217em}.katex .fontsize-ensurer.reset-size9.size8,.katex .sizing.reset-size9.size8{font-size:.83574879em}.katex .fontsize-ensurer.reset-size9.size9,.katex .sizing.reset-size9.size9{font-size:1em}.katex .fontsize-ensurer.reset-size9.size10,.katex .sizing.reset-size9.size10{font-size:1.20289855em}.katex .fontsize-ensurer.reset-size10.size1,.katex .sizing.reset-size10.size1{font-size:.20080321em}.katex .fontsize-ensurer.reset-size10.size2,.katex .sizing.reset-size10.size2{font-size:.2811245em}.katex .fontsize-ensurer.reset-size10.size3,.katex .sizing.reset-size10.size3{font-size:.32128514em}.katex .fontsize-ensurer.reset-size10.size4,.katex .sizing.reset-size10.size4{font-size:.36144578em}.katex .fontsize-ensurer.reset-size10.size5,.katex .sizing.reset-size10.size5{font-size:.40160643em}.katex .fontsize-ensurer.reset-size10.size6,.katex .sizing.reset-size10.size6{font-size:.48192771em}.katex .fontsize-ensurer.reset-size10.size7,.katex .sizing.reset-size10.size7{font-size:.57831325em}.katex .fontsize-ensurer.reset-size10.size8,.katex .sizing.reset-size10.size8{font-size:.69477912em}.katex .fontsize-ensurer.reset-size10.size9,.katex .sizing.reset-size10.size9{font-size:.8313253em}.katex .fontsize-ensurer.reset-size10.size10,.katex .sizing.reset-size10.size10{font-size:1em}.katex .delimsizing.size1{font-family:KaTeX_Size1}.katex .delimsizing.size2{font-family:KaTeX_Size2}.katex .delimsizing.size3{font-family:KaTeX_Size3}.katex .delimsizing.size4{font-family:KaTeX_Size4}.katex .delimsizing.mult .delim-size1>span{font-family:KaTeX_Size1}.katex .delimsizing.mult .delim-size4>span{font-family:KaTeX_Size4}.katex .nulldelimiter{display:inline-block;width:.12em}.katex .op-symbol{position:relative}.katex .op-symbol.small-op{font-family:KaTeX_Size1}.katex .op-symbol.large-op{font-family:KaTeX_Size2}.katex .accent>.vlist>span,.katex .op-limits>.vlist>span{text-align:center}.katex .accent .accent-body>span{width:0}.katex .accent .accent-body.accent-vec>span{position:relative;left:.326em}.katex .mtable .vertical-separator{display:inline-block;margin:0 -.025em;border-right:.05em solid #000}.katex .mtable .arraycolsep{display:inline-block}.katex .mtable .col-align-c>.vlist{text-align:center}.katex .mtable .col-align-l>.vlist{text-align:left}.katex .mtable .col-align-r>.vlist{text-align:right}
\ No newline at end of file
diff --git a/specs/2.2/katex/katex.min.js b/specs/2.2/katex/katex.min.js
new file mode 100644
index 0000000..66c0821
--- /dev/null
+++ b/specs/2.2/katex/katex.min.js
@@ -0,0 +1,4 @@
+(function(e){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=e()}else if(typeof define==="function"&&define.amd){define([],e)}else{var t;if(typeof window!=="undefined"){t=window}else if(typeof global!=="undefined"){t=global}else if(typeof self!=="undefined"){t=self}else{t=this}t.katex=e()}})(function(){var e,t,r;return function a(e,t,r){function i(s,l){if(!t[s]){if(!e[s]){var o=typeof require=="function"&&require;if(!l&&o)return o(s,!0);if(n)return n(s,!0);var u=new Error("Cannot find module '"+s+"'");throw u.code="MODULE_NOT_FOUND",u}var p=t[s]={exports:{}};e[s][0].call(p.exports,function(t){var r=e[s][1][t];return i(r?r:t)},p,p.exports,a,e,t,r)}return t[s].exports}var n=typeof require=="function"&&require;for(var s=0;s<r.length;s++)i(r[s]);return i}({1:[function(e,t,r){var a=e("./src/ParseError");var i=e("./src/Settings");var n=e("./src/buildTree");var s=e("./src/parseTree");var l=e("./src/utils");var o=function(e,t,r){l.clearNode(t);var a=new i(r);var o=s(e,a);var u=n(o,e,a).toNode();t.appendChild(u)};if(typeof document!=="undefined"){if(document.compatMode!=="CSS1Compat"){typeof console!=="undefined"&&console.warn("Warning: KaTeX doesn't work in quirks mode. Make sure your "+"website has a suitable doctype.");o=function(){throw new a("KaTeX doesn't work in quirks mode.")}}}var u=function(e,t){var r=new i(t);var a=s(e,r);return n(a,e,r).toMarkup()};var p=function(e,t){var r=new i(t);return s(e,r)};t.exports={render:o,renderToString:u,__parse:p,ParseError:a}},{"./src/ParseError":6,"./src/Settings":8,"./src/buildTree":13,"./src/parseTree":22,"./src/utils":25}],2:[function(e,t,r){"use strict";function a(e){if(!e.__matchAtRelocatable){var t=e.source+"|()";var r="g"+(e.ignoreCase?"i":"")+(e.multiline?"m":"")+(e.unicode?"u":"");e.__matchAtRelocatable=new RegExp(t,r)}return e.__matchAtRelocatable}function i(e,t,r){if(e.global||e.sticky){throw new Error("matchAt(...): Only non-global regexes are supported")}var i=a(e);i.lastIndex=r;var n=i.exec(t);if(n[n.length-1]==null){n.length=n.length-1;return n}else{return null}}t.exports=i},{}],3:[function(e,t,r){var a=e("match-at");var i=e("./ParseError");function n(e){this.input=e;this.pos=0}function s(e,t,r,a){this.text=e;this.start=t;this.end=r;this.lexer=a}s.prototype.range=function(e,t){if(e.lexer!==this.lexer){return new s(t)}return new s(t,this.start,e.end,this.lexer)};var l=new RegExp("([ \r\n	]+)|"+"([!-\\[\\]-\u2027\u202a-\ud7ff\uf900-\uffff]"+"|[\ud800-\udbff][\udc00-\udfff]"+"|\\\\(?:[a-zA-Z]+|[^\ud800-\udfff])"+")");n.prototype.lex=function(){var e=this.input;var t=this.pos;if(t===e.length){return new s("EOF",t,t,this)}var r=a(l,e,t);if(r===null){throw new i("Unexpected character: '"+e[t]+"'",new s(e[t],t,t+1,this))}var n=r[2]||" ";var o=this.pos;this.pos+=r[0].length;var u=this.pos;return new s(n,o,u,this)};t.exports=n},{"./ParseError":6,"match-at":2}],4:[function(e,t,r){var a=e("./Lexer");function i(e,t){this.lexer=new a(e);this.macros=t;this.stack=[];this.discardedWhiteSpace=[]}i.prototype.nextToken=function(){for(;;){if(this.stack.length===0){this.stack.push(this.lexer.lex())}var e=this.stack.pop();var t=e.text;if(!(t.charAt(0)==="\\"&&this.macros.hasOwnProperty(t))){return e}var r=this.macros[t];if(typeof r==="string"){var i=new a(r);r=[];var n=i.lex();while(n.text!=="EOF"){r.push(n);n=i.lex()}r.reverse();this.macros[t]=r}this.stack=this.stack.concat(r)}};i.prototype.get=function(e){this.discardedWhiteSpace=[];var t=this.nextToken();if(e){while(t.text===" "){this.discardedWhiteSpace.push(t);t=this.nextToken()}}return t};i.prototype.unget=function(e){this.stack.push(e);while(this.discardedWhiteSpace.length!==0){this.stack.push(this.discardedWhiteSpace.pop())}};t.exports=i},{"./Lexer":3}],5:[function(e,t,r){function a(e){this.style=e.style;this.color=e.color;this.size=e.size;this.phantom=e.phantom;this.font=e.font;if(e.parentStyle===undefined){this.parentStyle=e.style}else{this.parentStyle=e.parentStyle}if(e.parentSize===undefined){this.parentSize=e.size}else{this.parentSize=e.parentSize}}a.prototype.extend=function(e){var t={style:this.style,size:this.size,color:this.color,parentStyle:this.style,parentSize:this.size,phantom:this.phantom,font:this.font};for(var r in e){if(e.hasOwnProperty(r)){t[r]=e[r]}}return new a(t)};a.prototype.withStyle=function(e){return this.extend({style:e})};a.prototype.withSize=function(e){return this.extend({size:e})};a.prototype.withColor=function(e){return this.extend({color:e})};a.prototype.withPhantom=function(){return this.extend({phantom:true})};a.prototype.withFont=function(e){return this.extend({font:e||this.font})};a.prototype.reset=function(){return this.extend({})};var i={"katex-blue":"#6495ed","katex-orange":"#ffa500","katex-pink":"#ff00af","katex-red":"#df0030","katex-green":"#28ae7b","katex-gray":"gray","katex-purple":"#9d38bd","katex-blueA":"#ccfaff","katex-blueB":"#80f6ff","katex-blueC":"#63d9ea","katex-blueD":"#11accd","katex-blueE":"#0c7f99","katex-tealA":"#94fff5","katex-tealB":"#26edd5","katex-tealC":"#01d1c1","katex-tealD":"#01a995","katex-tealE":"#208170","katex-greenA":"#b6ffb0","katex-greenB":"#8af281","katex-greenC":"#74cf70","katex-greenD":"#1fab54","katex-greenE":"#0d923f","katex-goldA":"#ffd0a9","katex-goldB":"#ffbb71","katex-goldC":"#ff9c39","katex-goldD":"#e07d10","katex-goldE":"#a75a05","katex-redA":"#fca9a9","katex-redB":"#ff8482","katex-redC":"#f9685d","katex-redD":"#e84d39","katex-redE":"#bc2612","katex-maroonA":"#ffbde0","katex-maroonB":"#ff92c6","katex-maroonC":"#ed5fa6","katex-maroonD":"#ca337c","katex-maroonE":"#9e034e","katex-purpleA":"#ddd7ff","katex-purpleB":"#c6b9fc","katex-purpleC":"#aa87ff","katex-purpleD":"#7854ab","katex-purpleE":"#543b78","katex-mintA":"#f5f9e8","katex-mintB":"#edf2df","katex-mintC":"#e0e5cc","katex-grayA":"#f6f7f7","katex-grayB":"#f0f1f2","katex-grayC":"#e3e5e6","katex-grayD":"#d6d8da","katex-grayE":"#babec2","katex-grayF":"#888d93","katex-grayG":"#626569","katex-grayH":"#3b3e40","katex-grayI":"#21242c","katex-kaBlue":"#314453","katex-kaGreen":"#71B307"};a.prototype.getColor=function(){if(this.phantom){return"transparent"}else{return i[this.color]||this.color}};t.exports=a},{}],6:[function(e,t,r){function a(e,t){var r="KaTeX parse error: "+e;var i;var n;if(t&&t.lexer&&t.start<=t.end){var s=t.lexer.input;i=t.start;n=t.end;if(i===s.length){r+=" at end of input: "}else{r+=" at position "+(i+1)+": "}var l=s.slice(i,n).replace(/[^]/g,"$&\u0332");var o;if(i>15){o="\u2026"+s.slice(i-15,i)}else{o=s.slice(0,i)}var u;if(n+15<s.length){u=s.slice(n,n+15)+"\u2026"}else{u=s.slice(n)}r+=o+l+u}var p=new Error(r);p.name="ParseError";p.__proto__=a.prototype;p.position=i;return p}a.prototype.__proto__=Error.prototype;t.exports=a},{}],7:[function(e,t,r){var a=e("./functions");var i=e("./environments");var n=e("./MacroExpander");var s=e("./symbols");var l=e("./utils");var o=e("./unicodeRegexes").cjkRegex;var u=e("./parseData");var p=e("./ParseError");function h(e,t){this.gullet=new n(e,t.macros);this.settings=t;this.leftrightDepth=0}var c=u.ParseNode;function m(e,t,r){this.result=e;this.isFunction=t;this.token=r}h.prototype.expect=function(e,t){if(this.nextToken.text!==e){throw new p("Expected '"+e+"', got '"+this.nextToken.text+"'",this.nextToken)}if(t!==false){this.consume()}};h.prototype.consume=function(){this.nextToken=this.gullet.get(this.mode==="math")};h.prototype.switchMode=function(e){this.gullet.unget(this.nextToken);this.mode=e;this.consume()};h.prototype.parse=function(){this.mode="math";this.consume();var e=this.parseInput();return e};h.prototype.parseInput=function(){var e=this.parseExpression(false);this.expect("EOF",false);return e};var f=["}","\\end","\\right","&","\\\\","\\cr"];h.prototype.parseExpression=function(e,t){var r=[];while(true){var i=this.nextToken;if(f.indexOf(i.text)!==-1){break}if(t&&i.text===t){break}if(e&&a[i.text]&&a[i.text].infix){break}var n=this.parseAtom();if(!n){if(!this.settings.throwOnError&&i.text[0]==="\\"){var s=this.handleUnsupportedCmd();r.push(s);continue}break}r.push(n)}return this.handleInfixNodes(r)};h.prototype.handleInfixNodes=function(e){var t=-1;var r;for(var a=0;a<e.length;a++){var i=e[a];if(i.type==="infix"){if(t!==-1){throw new p("only one infix operator per group",i.value.token)}t=a;r=i.value.replaceWith}}if(t!==-1){var n;var s;var l=e.slice(0,t);var o=e.slice(t+1);if(l.length===1&&l[0].type==="ordgroup"){n=l[0]}else{n=new c("ordgroup",l,this.mode)}if(o.length===1&&o[0].type==="ordgroup"){s=o[0]}else{s=new c("ordgroup",o,this.mode)}var u=this.callFunction(r,[n,s],null);return[new c(u.type,u,this.mode)]}else{return e}};var v=1;h.prototype.handleSupSubscript=function(e){var t=this.nextToken;var r=t.text;this.consume();var i=this.parseGroup();if(!i){if(!this.settings.throwOnError&&this.nextToken.text[0]==="\\"){return this.handleUnsupportedCmd()}else{throw new p("Expected group after '"+r+"'",t)}}else if(i.isFunction){var n=a[i.result].greediness;if(n>v){return this.parseFunction(i)}else{throw new p("Got function '"+i.result+"' with no arguments "+"as "+e,t)}}else{return i.result}};h.prototype.handleUnsupportedCmd=function(){var e=this.nextToken.text;var t=[];for(var r=0;r<e.length;r++){t.push(new c("textord",e[r],"text"))}var a=new c("text",{body:t,type:"text"},this.mode);var i=new c("color",{color:this.settings.errorColor,value:[a],type:"color"},this.mode);this.consume();return i};h.prototype.parseAtom=function(){var e=this.parseImplicitGroup();if(this.mode==="text"){return e}var t;var r;while(true){var a=this.nextToken;if(a.text==="\\limits"||a.text==="\\nolimits"){if(!e||e.type!=="op"){throw new p("Limit controls must follow a math operator",a)}else{var i=a.text==="\\limits";e.value.limits=i;e.value.alwaysHandleSupSub=true}this.consume()}else if(a.text==="^"){if(t){throw new p("Double superscript",a)}t=this.handleSupSubscript("superscript")}else if(a.text==="_"){if(r){throw new p("Double subscript",a)}r=this.handleSupSubscript("subscript")}else if(a.text==="'"){var n=new c("textord","\\prime",this.mode);var s=[n];this.consume();while(this.nextToken.text==="'"){s.push(n);this.consume()}t=new c("ordgroup",s,this.mode)}else{break}}if(t||r){return new c("supsub",{base:e,sup:t,sub:r},this.mode)}else{return e}};var d=["\\tiny","\\scriptsize","\\footnotesize","\\small","\\normalsize","\\large","\\Large","\\LARGE","\\huge","\\Huge"];var g=["\\displaystyle","\\textstyle","\\scriptstyle","\\scriptscriptstyle"];h.prototype.parseImplicitGroup=function(){var e=this.parseSymbol();if(e==null){return this.parseFunction()}var t=e.result;var r;if(t==="\\left"){var a=this.parseFunction(e);++this.leftrightDepth;r=this.parseExpression(false);--this.leftrightDepth;this.expect("\\right",false);var n=this.parseFunction();return new c("leftright",{body:r,left:a.value.value,right:n.value.value},this.mode)}else if(t==="\\begin"){var s=this.parseFunction(e);var o=s.value.name;if(!i.hasOwnProperty(o)){throw new p("No such environment: "+o,s.value.nameGroup)}var u=i[o];var h=this.parseArguments("\\begin{"+o+"}",u);var m={mode:this.mode,envName:o,parser:this,positions:h.pop()};var f=u.handler(m,h);this.expect("\\end",false);var v=this.nextToken;var y=this.parseFunction();if(y.value.name!==o){throw new p("Mismatch: \\begin{"+o+"} matched "+"by \\end{"+y.value.name+"}",v)}f.position=y.position;return f}else if(l.contains(d,t)){r=this.parseExpression(false);return new c("sizing",{size:"size"+(l.indexOf(d,t)+1),value:r},this.mode)}else if(l.contains(g,t)){r=this.parseExpression(true);return new c("styling",{style:t.slice(1,t.length-5),value:r},this.mode)}else{return this.parseFunction(e)}};h.prototype.parseFunction=function(e){if(!e){e=this.parseGroup()}if(e){if(e.isFunction){var t=e.result;var r=a[t];if(this.mode==="text"&&!r.allowedInText){throw new p("Can't use function '"+t+"' in text mode",e.token)}var i=this.parseArguments(t,r);var n=e.token;var s=this.callFunction(t,i,i.pop(),n);return new c(s.type,s,this.mode)}else{return e.result}}else{return null}};h.prototype.callFunction=function(e,t,r,i){var n={funcName:e,parser:this,positions:r,token:i};return a[e].handler(n,t)};h.prototype.parseArguments=function(e,t){var r=t.numArgs+t.numOptionalArgs;if(r===0){return[[this.pos]]}var i=t.greediness;var n=[this.pos];var s=[];for(var l=0;l<r;l++){var o=this.nextToken;var u=t.argTypes&&t.argTypes[l];var h;if(l<t.numOptionalArgs){if(u){h=this.parseGroupOfType(u,true)}else{h=this.parseGroup(true)}if(!h){s.push(null);n.push(this.pos);continue}}else{if(u){h=this.parseGroupOfType(u)}else{h=this.parseGroup()}if(!h){if(!this.settings.throwOnError&&this.nextToken.text[0]==="\\"){h=new m(this.handleUnsupportedCmd(this.nextToken.text),false)}else{throw new p("Expected group after '"+e+"'",o)}}}var c;if(h.isFunction){var f=a[h.result].greediness;if(f>i){c=this.parseFunction(h)}else{throw new p("Got function '"+h.result+"' as "+"argument to '"+e+"'",o)}}else{c=h.result}s.push(c);n.push(this.pos)}s.push(n);return s};h.prototype.parseGroupOfType=function(e,t){var r=this.mode;if(e==="original"){e=r}if(e==="color"){return this.parseColorGroup(t)}if(e==="size"){return this.parseSizeGroup(t)}this.switchMode(e);if(e==="text"){while(this.nextToken.text===" "){this.consume()}}var a=this.parseGroup(t);this.switchMode(r);return a};h.prototype.parseStringGroup=function(e,t){if(t&&this.nextToken.text!=="["){return null}var r=this.mode;this.mode="text";this.expect(t?"[":"{");var a="";var i=this.nextToken;var n=i;while(this.nextToken.text!==(t?"]":"}")){if(this.nextToken.text==="EOF"){throw new p("Unexpected end of input in "+e,i.range(this.nextToken,a))}n=this.nextToken;a+=n.text;this.consume()}this.mode=r;this.expect(t?"]":"}");return i.range(n,a)};h.prototype.parseRegexGroup=function(e,t){var r=this.mode;this.mode="text";var a=this.nextToken;var i=a;var n="";while(this.nextToken.text!=="EOF"&&e.test(n+this.nextToken.text)){i=this.nextToken;n+=i.text;this.consume()}if(n===""){throw new p("Invalid "+t+": '"+a.text+"'",a)}this.mode=r;return a.range(i,n)};h.prototype.parseColorGroup=function(e){var t=this.parseStringGroup("color",e);if(!t){return null}var r=/^(#[a-z0-9]+|[a-z]+)$/i.exec(t.text);if(!r){throw new p("Invalid color: '"+t.text+"'",t)}return new m(new c("color",r[0],this.mode),false)};h.prototype.parseSizeGroup=function(e){var t;if(!e&&this.nextToken.text!=="{"){t=this.parseRegexGroup(/^[-+]? *(?:$|\d+|\d+\.\d*|\.\d*) *[a-z]{0,2}$/,"size")}else{t=this.parseStringGroup("size",e)}if(!t){return null}var r=/([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(t.text);if(!r){throw new p("Invalid size: '"+t.text+"'",t)}var a={number:+(r[1]+r[2]),unit:r[3]};if(a.unit!=="em"&&a.unit!=="ex"&&a.unit!=="mu"){throw new p("Invalid unit: '"+a.unit+"'",t)}return new m(new c("color",a,this.mode),false)};h.prototype.parseGroup=function(e){var t=this.nextToken;if(this.nextToken.text===(e?"[":"{")){this.consume();var r=this.parseExpression(false,e?"]":null);var a=this.nextToken;this.expect(e?"]":"}");if(this.mode==="text"){this.formLigatures(r)}return new m(new c("ordgroup",r,this.mode,t,a),false)}else{return e?null:this.parseSymbol()}};h.prototype.formLigatures=function(e){var t;var r=e.length-1;for(t=0;t<r;++t){var a=e[t];var i=a.value;if(i==="-"&&e[t+1].value==="-"){if(t+1<r&&e[t+2].value==="-"){e.splice(t,3,new c("textord","---","text",a,e[t+2]));r-=2}else{e.splice(t,2,new c("textord","--","text",a,e[t+1]));r-=1}}if((i==="'"||i==="`")&&e[t+1].value===i){e.splice(t,2,new c("textord",i+i,"text",a,e[t+1]));r-=1}}};h.prototype.parseSymbol=function(){var e=this.nextToken;if(a[e.text]){this.consume();return new m(e.text,true,e)}else if(s[this.mode][e.text]){this.consume();return new m(new c(s[this.mode][e.text].group,e.text,this.mode,e),false,e)}else if(this.mode==="text"&&o.test(e.text)){this.consume();return new m(new c("textord",e.text,this.mode,e),false,e)}else{return null}};h.prototype.ParseNode=c;t.exports=h},{"./MacroExpander":4,"./ParseError":6,"./environments":16,"./functions":19,"./parseData":21,"./symbols":23,"./unicodeRegexes":24,"./utils":25}],8:[function(e,t,r){function a(e,t){return e===undefined?t:e}function i(e){e=e||{};this.displayMode=a(e.displayMode,false);this.throwOnError=a(e.throwOnError,true);this.errorColor=a(e.errorColor,"#cc0000");this.macros=e.macros||{}}t.exports=i},{}],9:[function(e,t,r){var a=e("./fontMetrics.js").sigmas;var i=[{},{},{}];var n;for(var s in a){if(a.hasOwnProperty(s)){for(n=0;n<3;n++){i[n][s]=a[s][n]}}}for(n=0;n<3;n++){i[n].emPerEx=a.xHeight[n]/a.quad[n]}function l(e,t,r,a){this.id=e;this.size=t;this.cramped=a;this.sizeMultiplier=r;this.metrics=i[t>0?t-1:0]}l.prototype.sup=function(){return y[x[this.id]]};l.prototype.sub=function(){return y[b[this.id]]};l.prototype.fracNum=function(){return y[w[this.id]]};l.prototype.fracDen=function(){return y[k[this.id]]};l.prototype.cramp=function(){return y[z[this.id]]};l.prototype.cls=function(){return d[this.size]+(this.cramped?" cramped":" uncramped")};l.prototype.reset=function(){return g[this.size]};l.prototype.isTight=function(){return this.size>=2};var o=0;var u=1;var p=2;var h=3;var c=4;var m=5;var f=6;var v=7;var d=["displaystyle textstyle","textstyle","scriptstyle","scriptscriptstyle"];var g=["reset-textstyle","reset-textstyle","reset-scriptstyle","reset-scriptscriptstyle"];var y=[new l(o,0,1,false),new l(u,0,1,true),new l(p,1,1,false),new l(h,1,1,true),new l(c,2,.7,false),new l(m,2,.7,true),new l(f,3,.5,false),new l(v,3,.5,true)];var x=[c,m,c,m,f,v,f,v];var b=[m,m,m,m,v,v,v,v];var w=[p,h,c,m,f,v,f,v];var k=[h,h,m,m,v,v,v,v];var z=[u,u,h,h,m,m,v,v];t.exports={DISPLAY:y[o],TEXT:y[p],SCRIPT:y[c],SCRIPTSCRIPT:y[f]}},{"./fontMetrics.js":17}],10:[function(e,t,r){var a=e("./domTree");var i=e("./fontMetrics");var n=e("./symbols");var s=e("./utils");var l=["\\Gamma","\\Delta","\\Theta","\\Lambda","\\Xi","\\Pi","\\Sigma","\\Upsilon","\\Phi","\\Psi","\\Omega"];var o=["\u0131","\u0237","\xa3"];var u=function(e,t,r,s,l){if(n[r][e]&&n[r][e].replace){e=n[r][e].replace}var o=i.getCharacterMetrics(e,t);var u;if(o){var p=o.italic;if(r==="text"){p=0}u=new a.symbolNode(e,o.height,o.depth,p,o.skew,l)}else{typeof console!=="undefined"&&console.warn("No character metrics for '"+e+"' in style '"+t+"'");u=new a.symbolNode(e,0,0,0,0,l)}if(s){if(s.style.isTight()){u.classes.push("mtight")}if(s.getColor()){u.style.color=s.getColor()}}return u};var p=function(e,t,r,a){if(e==="\\"||n[t][e].font==="main"){return u(e,"Main-Regular",t,r,a)}else{return u(e,"AMS-Regular",t,r,a.concat(["amsrm"]))}};var h=function(e,t,r,a,i){if(i==="mathord"){return c(e,t,r,a)}else if(i==="textord"){return u(e,"Main-Regular",t,r,a.concat(["mathrm"]))}else{throw new Error("unexpected type: "+i+" in mathDefault")}};var c=function(e,t,r,a){if(/[0-9]/.test(e.charAt(0))||s.contains(o,e)||s.contains(l,e)){return u(e,"Main-Italic",t,r,a.concat(["mainit"]))}else{return u(e,"Math-Italic",t,r,a.concat(["mathit"]))}};var m=function(e,t,r){var a=e.mode;var l=e.value;if(n[a][l]&&n[a][l].replace){l=n[a][l].replace}var p=["mord"];var m=t.font;if(m){if(m==="mathit"||s.contains(o,l)){return c(l,a,t,p)}else{var f=k[m].fontName;if(i.getCharacterMetrics(l,f)){return u(l,f,a,t,p.concat([m]))}else{return h(l,a,t,p,r)}}}else{return h(l,a,t,p,r)}};var f=function(e){var t=0;var r=0;var a=0;if(e.children){for(var i=0;i<e.children.length;i++){if(e.children[i].height>t){t=e.children[i].height}if(e.children[i].depth>r){r=e.children[i].depth}if(e.children[i].maxFontSize>a){a=e.children[i].maxFontSize}}}e.height=t;e.depth=r;e.maxFontSize=a};var v=function(e,t,r){var i=new a.span(e,t,r);f(i);return i};var d=function(e,t){e.children=t.concat(e.children);f(e)};var g=function(e){var t=new a.documentFragment(e);f(t);return t};var y=function(e,t){var r=v([],[new a.symbolNode("\u200b")]);r.style.fontSize=t/e.style.sizeMultiplier+"em";var i=v(["fontsize-ensurer","reset-"+e.size,"size5"],[r]);return i};var x=function(e,t,r,i){var n;var s;var l;if(t==="individualShift"){var o=e;e=[o[0]];n=-o[0].shift-o[0].elem.depth;s=n;for(l=1;l<o.length;l++){var u=-o[l].shift-s-o[l].elem.depth;var p=u-(o[l-1].elem.height+o[l-1].elem.depth);s=s+u;e.push({type:"kern",size:p});e.push(o[l])}}else if(t==="top"){var h=r;for(l=0;l<e.length;l++){if(e[l].type==="kern"){h-=e[l].size}else{h-=e[l].elem.height+e[l].elem.depth}}n=h}else if(t==="bottom"){n=-r}else if(t==="shift"){n=-e[0].elem.depth-r}else if(t==="firstBaseline"){n=-e[0].elem.depth}else{n=0}var c=0;for(l=0;l<e.length;l++){if(e[l].type==="elem"){c=Math.max(c,e[l].elem.maxFontSize)}}var m=y(i,c);var f=[];s=n;for(l=0;l<e.length;l++){if(e[l].type==="kern"){s+=e[l].size}else{var d=e[l].elem;var g=-d.depth-s;s+=d.height+d.depth;var x=v([],[m,d]);x.height-=g;x.depth+=g;x.style.top=g+"em";f.push(x)}}var b=v(["baseline-fix"],[m,new a.symbolNode("\u200b")]);f.push(b);var w=v(["vlist"],f);w.height=Math.max(s,w.height);w.depth=Math.max(-n,w.depth);return w};var b={size1:.5,size2:.7,size3:.8,size4:.9,size5:1,size6:1.2,size7:1.44,size8:1.73,size9:2.07,size10:2.49};var w={"\\qquad":{size:"2em",className:"qquad"},"\\quad":{size:"1em",className:"quad"},"\\enspace":{size:"0.5em",className:"enspace"},"\\;":{size:"0.277778em",className:"thickspace"},"\\:":{size:"0.22222em",className:"mediumspace"},"\\,":{size:"0.16667em",className:"thinspace"},"\\!":{size:"-0.16667em",className:"negativethinspace"}};var k={mathbf:{variant:"bold",fontName:"Main-Bold"},mathrm:{variant:"normal",fontName:"Main-Regular"},textit:{variant:"italic",fontName:"Main-Italic"},mathbb:{variant:"double-struck",fontName:"AMS-Regular"},mathcal:{variant:"script",fontName:"Caligraphic-Regular"},mathfrak:{variant:"fraktur",fontName:"Fraktur-Regular"},mathscr:{variant:"script",fontName:"Script-Regular"},mathsf:{variant:"sans-serif",fontName:"SansSerif-Regular"},mathtt:{variant:"monospace",fontName:"Typewriter-Regular"}};t.exports={fontMap:k,makeSymbol:u,mathsym:p,makeSpan:v,makeFragment:g,makeVList:x,makeOrd:m,prependChildren:d,sizingMultiplier:b,spacingFunctions:w}},{"./domTree":15,"./fontMetrics":17,"./symbols":23,"./utils":25}],11:[function(e,t,r){var a=e("./ParseError");var i=e("./Style");var n=e("./buildCommon");var s=e("./delimiter");var l=e("./domTree");var o=e("./fontMetrics");var u=e("./utils");var p=n.makeSpan;var h=function(e){return e instanceof l.span&&e.classes[0]==="mspace"};var c=function(e){return e&&e.classes[0]==="mbin"};var m=function(e,t){if(e){return u.contains(["mbin","mopen","mrel","mop","mpunct"],e.classes[0])}else{return t}};var f=function(e,t){if(e){return u.contains(["mrel","mclose","mpunct"],e.classes[0])}else{return t}};var v=function(e,t,r){var a=[];for(var i=0;i<e.length;i++){var s=e[i];var o=z(s,t);if(o instanceof l.documentFragment){Array.prototype.push.apply(a,o.children)}else{a.push(o)}}var u=null;for(i=0;i<a.length;i++){if(h(a[i])){u=u||[];u.push(a[i]);a.splice(i,1);i--}else if(u){if(a[i]instanceof l.symbolNode){a[i]=p([].concat(a[i].classes),[a[i]])}n.prependChildren(a[i],u);u=null}}if(u){Array.prototype.push.apply(a,u)}for(i=0;i<a.length;i++){if(c(a[i])&&(m(a[i-1],r)||f(a[i+1],r))){a[i].classes[0]="mord"}}return a};var d=function(e){if(e instanceof l.documentFragment){if(e.children.length){return d(e.children[e.children.length-1])}}else{if(u.contains(["mord","mop","mbin","mrel","mopen","mclose","mpunct","minner"],e.classes[0])){return e.classes[0]}}return null};var g=function(e,t){if(!e){return false}else if(e.type==="op"){return e.value.limits&&(t.style.size===i.DISPLAY.size||e.value.alwaysHandleSupSub)}else if(e.type==="accent"){return x(e.value.base)}else{return null}};var y=function(e){if(!e){return false}else if(e.type==="ordgroup"){if(e.value.length===1){return y(e.value[0])}else{return e}}else if(e.type==="color"){if(e.value.value.length===1){return y(e.value.value[0])}else{return e}}else if(e.type==="font"){return y(e.value.body)}else{return e}};var x=function(e){var t=y(e);return t.type==="mathord"||t.type==="textord"||t.type==="bin"||t.type==="rel"||t.type==="inner"||t.type==="open"||t.type==="close"||t.type==="punct"};var b=function(e,t){return p(t.concat(["sizing","reset-"+e.size,"size5",e.style.reset(),i.TEXT.cls(),"nulldelimiter"]))};var w={};w.mathord=function(e,t){return n.makeOrd(e,t,"mathord")};w.textord=function(e,t){return n.makeOrd(e,t,"textord")};w.bin=function(e,t){return n.mathsym(e.value,e.mode,t,["mbin"])};w.rel=function(e,t){return n.mathsym(e.value,e.mode,t,["mrel"])};w.open=function(e,t){return n.mathsym(e.value,e.mode,t,["mopen"])};w.close=function(e,t){return n.mathsym(e.value,e.mode,t,["mclose"])};w.inner=function(e,t){return n.mathsym(e.value,e.mode,t,["minner"])};w.punct=function(e,t){return n.mathsym(e.value,e.mode,t,["mpunct"])};w.ordgroup=function(e,t){return p(["mord",t.style.cls()],v(e.value,t.reset(),true),t)};w.text=function(e,t){var r=t.withFont(e.value.style);var a=v(e.value.body,r,true);for(var i=0;i<a.length-1;i++){if(a[i].tryCombine(a[i+1])){a.splice(i+1,1);i--}}return p(["mord","text",r.style.cls()],a,r)};w.color=function(e,t){var r=v(e.value.value,t.withColor(e.value.color),false);return new n.makeFragment(r)};w.supsub=function(e,t){if(g(e.value.base,t)){return w[e.value.base.type](e,t)}var r=z(e.value.base,t.reset());var a;var s;var u;var h;var c=t.style;var m;if(e.value.sup){m=t.withStyle(c.sup());u=z(e.value.sup,m);a=p([c.reset(),c.sup().cls()],[u],m)}if(e.value.sub){m=t.withStyle(c.sub());h=z(e.value.sub,m);s=p([c.reset(),c.sub().cls()],[h],m)}var f;var v;if(x(e.value.base)){f=0;v=0}else{f=r.height-c.metrics.supDrop;v=r.depth+c.metrics.subDrop}var y;if(c===i.DISPLAY){y=c.metrics.sup1}else if(c.cramped){y=c.metrics.sup3}else{y=c.metrics.sup2}var b=i.TEXT.sizeMultiplier*c.sizeMultiplier;var k=.5/o.metrics.ptPerEm/b+"em";var S;if(!e.value.sup){v=Math.max(v,c.metrics.sub1,h.height-.8*c.metrics.xHeight);S=n.makeVList([{type:"elem",elem:s}],"shift",v,t);S.children[0].style.marginRight=k;if(r instanceof l.symbolNode){S.children[0].style.marginLeft=-r.italic+"em"}}else if(!e.value.sub){f=Math.max(f,y,u.depth+.25*c.metrics.xHeight);S=n.makeVList([{type:"elem",elem:a}],"shift",-f,t);S.children[0].style.marginRight=k}else{f=Math.max(f,y,u.depth+.25*c.metrics.xHeight);v=Math.max(v,c.metrics.sub2);var M=o.metrics.defaultRuleThickness;if(f-u.depth-(h.height-v)<4*M){v=4*M-(f-u.depth)+h.height;var T=.8*c.metrics.xHeight-(f-u.depth);if(T>0){f+=T;v-=T}}S=n.makeVList([{type:"elem",elem:s,shift:v},{type:"elem",elem:a,shift:-f}],"individualShift",null,t);if(r instanceof l.symbolNode){S.children[0].style.marginLeft=-r.italic+"em"}S.children[0].style.marginRight=k;S.children[1].style.marginRight=k}var A=d(r)||"mord";return p([A],[r,p(["msupsub"],[S])],t)};w.genfrac=function(e,t){var r=t.style;if(e.value.size==="display"){r=i.DISPLAY}else if(e.value.size==="text"){r=i.TEXT}var a=r.fracNum();var l=r.fracDen();var u;u=t.withStyle(a);var h=z(e.value.numer,u);var c=p([r.reset(),a.cls()],[h],u);u=t.withStyle(l);var m=z(e.value.denom,u);var f=p([r.reset(),l.cls()],[m],u);var v;if(e.value.hasBarLine){v=o.metrics.defaultRuleThickness/t.style.sizeMultiplier}else{v=0}var d;var g;var y;if(r.size===i.DISPLAY.size){d=r.metrics.num1;if(v>0){g=3*v}else{g=7*o.metrics.defaultRuleThickness}y=r.metrics.denom1}else{if(v>0){d=r.metrics.num2;g=v}else{d=r.metrics.num3;g=3*o.metrics.defaultRuleThickness}y=r.metrics.denom2}var x;if(v===0){var w=d-h.depth-(m.height-y);if(w<g){d+=.5*(g-w);y+=.5*(g-w)}x=n.makeVList([{type:"elem",elem:f,shift:y},{type:"elem",elem:c,shift:-d}],"individualShift",null,t)}else{var k=r.metrics.axisHeight;if(d-h.depth-(k+.5*v)<g){d+=g-(d-h.depth-(k+.5*v))}if(k-.5*v-(m.height-y)<g){y+=g-(k-.5*v-(m.height-y))}var S=p([t.style.reset(),i.TEXT.cls(),"frac-line"]);S.height=v;var M=-(k-.5*v);x=n.makeVList([{type:"elem",elem:f,shift:y},{type:"elem",elem:S,shift:M},{type:"elem",elem:c,shift:-d}],"individualShift",null,t)}x.height*=r.sizeMultiplier/t.style.sizeMultiplier;x.depth*=r.sizeMultiplier/t.style.sizeMultiplier;var T;if(r.size===i.DISPLAY.size){T=r.metrics.delim1}else{T=r.metrics.delim2}var A;var N;if(e.value.leftDelim==null){A=b(t,["mopen"])}else{A=s.customSizedDelim(e.value.leftDelim,T,true,t.withStyle(r),e.mode,["mopen"])}if(e.value.rightDelim==null){N=b(t,["mclose"])}else{N=s.customSizedDelim(e.value.rightDelim,T,true,t.withStyle(r),e.mode,["mclose"])}return p(["mord",t.style.reset(),r.cls()],[A,p(["mfrac"],[x]),N],t)};var k=function(e,t){var r=e.number;if(e.unit==="ex"){r*=t.metrics.emPerEx}else if(e.unit==="mu"){r/=18}return r};w.array=function(e,t){var r;var i;var s=e.value.body.length;var l=0;var h=new Array(s);var c=t.style;var m=1/o.metrics.ptPerEm;var f=5*m;var v=12*m;var d=u.deflt(e.value.arraystretch,1);var g=d*v;var y=.7*g;var x=.3*g;var b=0;for(r=0;r<e.value.body.length;++r){var w=e.value.body[r];var S=y;var M=x;if(l<w.length){l=w.length}var T=new Array(w.length);for(i=0;i<w.length;++i){var A=z(w[i],t);if(M<A.depth){M=A.depth}if(S<A.height){S=A.height}T[i]=A}var N=0;if(e.value.rowGaps[r]){N=k(e.value.rowGaps[r].value,c);if(N>0){N+=x;if(M<N){M=N}N=0}}T.height=S;T.depth=M;b+=S;T.pos=b;b+=M+N;h[r]=T}var q=b/2+c.metrics.axisHeight;var R=e.value.cols||[];var E=[];var C;var D;for(i=0,D=0;i<l||D<R.length;++i,++D){var O=R[D]||{};var P=true;while(O.type==="separator"){if(!P){C=p(["arraycolsep"],[]);C.style.width=o.metrics.doubleRuleSep+"em";E.push(C)}if(O.separator==="|"){var F=p(["vertical-separator"],[]);F.style.height=b+"em";F.style.verticalAlign=-(b-q)+"em";E.push(F)}else{throw new a("Invalid separator type: "+O.separator)}D++;O=R[D]||{};P=false}if(i>=l){continue}var I;if(i>0||e.value.hskipBeforeAndAfter){I=u.deflt(O.pregap,f);if(I!==0){C=p(["arraycolsep"],[]);C.style.width=I+"em";E.push(C)}}var L=[];for(r=0;r<s;++r){var B=h[r];var G=B[i];if(!G){continue}var V=B.pos-q;G.depth=B.depth;G.height=B.height;L.push({type:"elem",elem:G,shift:V})}L=n.makeVList(L,"individualShift",null,t);L=p(["col-align-"+(O.align||"c")],[L]);E.push(L);if(i<l-1||e.value.hskipBeforeAndAfter){I=u.deflt(O.postgap,f);if(I!==0){C=p(["arraycolsep"],[]);C.style.width=I+"em";E.push(C)}}}h=p(["mtable"],E);return p(["mord"],[h],t)};w.spacing=function(e,t){if(e.value==="\\ "||e.value==="\\space"||e.value===" "||e.value==="~"){if(e.mode==="text"){return n.makeOrd(e,t,"textord")}else{return p(["mspace"],[n.mathsym(e.value,e.mode,t)],t)}}else{return p(["mspace",n.spacingFunctions[e.value].className],[],t)}};w.llap=function(e,t){var r=p(["inner"],[z(e.value.body,t.reset())]);var a=p(["fix"],[]);return p(["mord","llap",t.style.cls()],[r,a],t)};w.rlap=function(e,t){var r=p(["inner"],[z(e.value.body,t.reset())]);var a=p(["fix"],[]);return p(["mord","rlap",t.style.cls()],[r,a],t)};w.op=function(e,t){var r;var a;var s=false;if(e.type==="supsub"){r=e.value.sup;a=e.value.sub;e=e.value.base;s=true}var l=t.style;var h=["\\smallint"];var c=false;if(l.size===i.DISPLAY.size&&e.value.symbol&&!u.contains(h,e.value.body)){c=true}var m;var f=0;var d=0;if(e.value.symbol){var g=c?"Size2-Regular":"Size1-Regular";m=n.makeSymbol(e.value.body,g,"math",t,["mop","op-symbol",c?"large-op":"small-op"]);f=(m.height-m.depth)/2-l.metrics.axisHeight*l.sizeMultiplier;d=m.italic}else if(e.value.value){var y=v(e.value.value,t,true);m=p(["mop"],y,t)}else{var x=[];for(var b=1;b<e.value.body.length;b++){x.push(n.mathsym(e.value.body[b],e.mode))}m=p(["mop"],x,t)}if(s){m=p([],[m]);var w;var k;var S;var M;var T;if(r){T=t.withStyle(l.sup());var A=z(r,T);w=p([l.reset(),l.sup().cls()],[A],T);k=Math.max(o.metrics.bigOpSpacing1,o.metrics.bigOpSpacing3-A.depth)}if(a){T=t.withStyle(l.sub());var N=z(a,T);S=p([l.reset(),l.sub().cls()],[N],T);M=Math.max(o.metrics.bigOpSpacing2,o.metrics.bigOpSpacing4-N.height)}var q;var R;var E;if(!r){R=m.height-f;q=n.makeVList([{type:"kern",size:o.metrics.bigOpSpacing5},{type:"elem",elem:S},{type:"kern",size:M},{type:"elem",elem:m}],"top",R,t);q.children[0].style.marginLeft=-d+"em"}else if(!a){E=m.depth+f;q=n.makeVList([{type:"elem",elem:m},{type:"kern",size:k},{type:"elem",elem:w},{type:"kern",size:o.metrics.bigOpSpacing5}],"bottom",E,t);q.children[1].style.marginLeft=d+"em"}else if(!r&&!a){return m}else{E=o.metrics.bigOpSpacing5+S.height+S.depth+M+m.depth+f;
+q=n.makeVList([{type:"kern",size:o.metrics.bigOpSpacing5},{type:"elem",elem:S},{type:"kern",size:M},{type:"elem",elem:m},{type:"kern",size:k},{type:"elem",elem:w},{type:"kern",size:o.metrics.bigOpSpacing5}],"bottom",E,t);q.children[0].style.marginLeft=-d+"em";q.children[2].style.marginLeft=d+"em"}return p(["mop","op-limits"],[q],t)}else{if(e.value.symbol){m.style.top=f+"em"}return m}};w.mod=function(e,t){var r=[];if(e.value.modType==="bmod"){if(!t.style.isTight()){r.push(p(["mspace","negativemediumspace"],[],t))}r.push(p(["mspace","thickspace"],[],t))}else if(t.style.size===i.DISPLAY.size){r.push(p(["mspace","quad"],[],t))}else if(e.value.modType==="mod"){r.push(p(["mspace","twelvemuspace"],[],t))}else{r.push(p(["mspace","eightmuspace"],[],t))}if(e.value.modType==="pod"||e.value.modType==="pmod"){r.push(n.mathsym("(",e.mode))}if(e.value.modType!=="pod"){var a=[n.mathsym("m",e.mode),n.mathsym("o",e.mode),n.mathsym("d",e.mode)];if(e.value.modType==="bmod"){r.push(p(["mbin"],a,t));r.push(p(["mspace","thickspace"],[],t));if(!t.style.isTight()){r.push(p(["mspace","negativemediumspace"],[],t))}}else{Array.prototype.push.apply(r,a);r.push(p(["mspace","sixmuspace"],[],t))}}if(e.value.value){Array.prototype.push.apply(r,v(e.value.value,t,false))}if(e.value.modType==="pod"||e.value.modType==="pmod"){r.push(n.mathsym(")",e.mode))}return n.makeFragment(r)};w.katex=function(e,t){var r=p(["k"],[n.mathsym("K",e.mode)],t);var a=p(["a"],[n.mathsym("A",e.mode)],t);a.height=(a.height+.2)*.75;a.depth=(a.height-.2)*.75;var i=p(["t"],[n.mathsym("T",e.mode)],t);var s=p(["e"],[n.mathsym("E",e.mode)],t);s.height=s.height-.2155;s.depth=s.depth+.2155;var l=p(["x"],[n.mathsym("X",e.mode)],t);return p(["mord","katex-logo"],[r,a,i,s,l],t)};w.overline=function(e,t){var r=t.style;var a=z(e.value.body,t.withStyle(r.cramp()));var s=o.metrics.defaultRuleThickness/r.sizeMultiplier;var l=p([r.reset(),i.TEXT.cls(),"overline-line"]);l.height=s;l.maxFontSize=1;var u=n.makeVList([{type:"elem",elem:a},{type:"kern",size:3*s},{type:"elem",elem:l},{type:"kern",size:s}],"firstBaseline",null,t);return p(["mord","overline"],[u],t)};w.underline=function(e,t){var r=t.style;var a=z(e.value.body,t);var s=o.metrics.defaultRuleThickness/r.sizeMultiplier;var l=p([r.reset(),i.TEXT.cls(),"underline-line"]);l.height=s;l.maxFontSize=1;var u=n.makeVList([{type:"kern",size:s},{type:"elem",elem:l},{type:"kern",size:3*s},{type:"elem",elem:a}],"top",a.height,t);return p(["mord","underline"],[u],t)};w.sqrt=function(e,t){var r=t.style;var a=z(e.value.body,t.withStyle(r.cramp()));var l=o.metrics.defaultRuleThickness/r.sizeMultiplier;var u=p([r.reset(),i.TEXT.cls(),"sqrt-line"],[],t);u.height=l;u.maxFontSize=1;var h=l;if(r.id<i.TEXT.id){h=r.metrics.xHeight}var c=l+h/4;var m=(a.height+a.depth)*r.sizeMultiplier;var f=m+c+l;var v=p(["sqrt-sign"],[s.customSizedDelim("\\surd",f,false,t,e.mode)],t);var d=v.height+v.depth-l;if(d>a.height+a.depth+c){c=(c+d-a.height-a.depth)/2}var g=-(a.height+c+l)+v.height;v.style.top=g+"em";v.height-=g;v.depth+=g;var y;if(a.height===0&&a.depth===0){y=p()}else{y=n.makeVList([{type:"elem",elem:a},{type:"kern",size:c},{type:"elem",elem:u},{type:"kern",size:l}],"firstBaseline",null,t)}if(!e.value.index){return p(["mord","sqrt"],[v,y],t)}else{var x=t.withStyle(i.SCRIPTSCRIPT);var b=z(e.value.index,x);var w=p([r.reset(),i.SCRIPTSCRIPT.cls()],[b],x);var k=Math.max(v.height,y.height);var S=Math.max(v.depth,y.depth);var M=.6*(k-S);var T=n.makeVList([{type:"elem",elem:w}],"shift",-M,t);var A=p(["root"],[T]);return p(["mord","sqrt"],[A,v,y],t)}};w.sizing=function(e,t){var r=v(e.value.value,t.withSize(e.value.size),false);var a=t.style;var i=n.sizingMultiplier[e.value.size];i=i*a.sizeMultiplier;for(var s=0;s<r.length;s++){var l=u.indexOf(r[s].classes,"sizing");if(l<0){r[s].classes.push("sizing","reset-"+t.size,e.value.size,a.cls());r[s].maxFontSize=i}else if(r[s].classes[l+1]==="reset-"+e.value.size){r[s].classes[l+1]="reset-"+t.size}}return n.makeFragment(r)};w.styling=function(e,t){var r={display:i.DISPLAY,text:i.TEXT,script:i.SCRIPT,scriptscript:i.SCRIPTSCRIPT};var a=r[e.value.style];var s=t.withStyle(a);var l=v(e.value.value,s,false);for(var o=0;o<l.length;o++){var p=u.indexOf(l[o].classes,a.reset());if(p<0){l[o].classes.push(t.style.reset(),a.cls())}else{l[o].classes[p]=t.style.reset()}}return new n.makeFragment(l)};w.font=function(e,t){var r=e.value.font;return z(e.value.body,t.withFont(r))};w.delimsizing=function(e,t){var r=e.value.value;if(r==="."){return p([e.value.mclass])}return s.sizedDelim(r,e.value.size,t,e.mode,[e.value.mclass])};w.leftright=function(e,t){var r=v(e.value.body,t.reset(),true);var a=0;var i=0;var n=false;for(var l=0;l<r.length;l++){if(r[l].isMiddle){n=true}else{a=Math.max(r[l].height,a);i=Math.max(r[l].depth,i)}}var o=t.style;a*=o.sizeMultiplier;i*=o.sizeMultiplier;var u;if(e.value.left==="."){u=b(t,["mopen"])}else{u=s.leftRightDelim(e.value.left,a,i,t,e.mode,["mopen"])}r.unshift(u);if(n){for(l=1;l<r.length;l++){if(r[l].isMiddle){r[l]=s.leftRightDelim(r[l].isMiddle.value,a,i,r[l].isMiddle.options,e.mode,[])}}}var h;if(e.value.right==="."){h=b(t,["mclose"])}else{h=s.leftRightDelim(e.value.right,a,i,t,e.mode,["mclose"])}r.push(h);return p(["minner",o.cls()],r,t)};w.middle=function(e,t){var r;if(e.value.value==="."){r=b(t,[])}else{r=s.sizedDelim(e.value.value,1,t,e.mode,[]);r.isMiddle={value:e.value.value,options:t}}return r};w.rule=function(e,t){var r=p(["mord","rule"],[],t);var a=t.style;var i=0;if(e.value.shift){i=k(e.value.shift,a)}var n=k(e.value.width,a);var s=k(e.value.height,a);i/=a.sizeMultiplier;n/=a.sizeMultiplier;s/=a.sizeMultiplier;r.style.borderRightWidth=n+"em";r.style.borderTopWidth=s+"em";r.style.bottom=i+"em";r.width=n;r.height=s+i;r.depth=-i;return r};w.kern=function(e,t){var r=p(["mord","rule"],[],t);var a=t.style;var i=0;if(e.value.dimension){i=k(e.value.dimension,a)}i/=a.sizeMultiplier;r.style.marginLeft=i+"em";return r};w.accent=function(e,t){var r=e.value.base;var a=t.style;var i;if(e.type==="supsub"){var s=e;e=s.value.base;r=e.value.base;s.value.base=r;i=z(s,t.reset())}var l=z(r,t.withStyle(a.cramp()));var o;if(x(r)){var u=y(r);var h=z(u,t.withStyle(a.cramp()));o=h.skew}else{o=0}var c=Math.min(l.height,a.metrics.xHeight);var m=n.makeSymbol(e.value.accent,"Main-Regular","math",t);m.italic=0;var f=e.value.accent==="\\vec"?"accent-vec":null;var v=p(["accent-body",f],[p([],[m])]);v=n.makeVList([{type:"elem",elem:l},{type:"kern",size:-c},{type:"elem",elem:v}],"firstBaseline",null,t);v.children[1].style.marginLeft=2*o+"em";var d=p(["mord","accent"],[v],t);if(i){i.children[0]=d;i.height=Math.max(d.height,i.height);i.classes[0]="mord";return i}else{return d}};w.phantom=function(e,t){var r=v(e.value.value,t.withPhantom(),false);return new n.makeFragment(r)};w.mclass=function(e,t){var r=v(e.value.value,t,true);return p([e.value.mclass],r,t)};var z=function(e,t){if(!e){return p()}if(w[e.type]){var r=w[e.type](e,t);var i;if(t.style!==t.parentStyle){i=t.style.sizeMultiplier/t.parentStyle.sizeMultiplier;r.height*=i;r.depth*=i}if(t.size!==t.parentSize){i=n.sizingMultiplier[t.size]/n.sizingMultiplier[t.parentSize];r.height*=i;r.depth*=i}return r}else{throw new a("Got group of unknown type: '"+e.type+"'")}};var S=function(e,t){e=JSON.parse(JSON.stringify(e));var r=v(e,t,true);var a=p(["base",t.style.cls()],r,t);var i=p(["strut"]);var n=p(["strut","bottom"]);i.style.height=a.height+"em";n.style.height=a.height+a.depth+"em";n.style.verticalAlign=-a.depth+"em";var s=p(["katex-html"],[i,n,a]);s.setAttribute("aria-hidden","true");return s};t.exports=S},{"./ParseError":6,"./Style":9,"./buildCommon":10,"./delimiter":14,"./domTree":15,"./fontMetrics":17,"./utils":25}],12:[function(e,t,r){var a=e("./buildCommon");var i=e("./fontMetrics");var n=e("./mathMLTree");var s=e("./ParseError");var l=e("./symbols");var o=e("./utils");var u=a.makeSpan;var p=a.fontMap;var h=function(e,t){if(l[t][e]&&l[t][e].replace){e=l[t][e].replace}return new n.TextNode(e)};var c=function(e,t){var r=t.font;if(!r){return null}var a=e.mode;if(r==="mathit"){return"italic"}var n=e.value;if(o.contains(["\\imath","\\jmath"],n)){return null}if(l[a][n]&&l[a][n].replace){n=l[a][n].replace}var s=p[r].fontName;if(i.getCharacterMetrics(n,s)){return p[t.font].variant}return null};var m={};m.mathord=function(e,t){var r=new n.MathNode("mi",[h(e.value,e.mode)]);var a=c(e,t);if(a){r.setAttribute("mathvariant",a)}return r};m.textord=function(e,t){var r=h(e.value,e.mode);var a=c(e,t)||"normal";var i;if(/[0-9]/.test(e.value)){i=new n.MathNode("mn",[r]);if(t.font){i.setAttribute("mathvariant",a)}}else{i=new n.MathNode("mi",[r]);i.setAttribute("mathvariant",a)}return i};m.bin=function(e){var t=new n.MathNode("mo",[h(e.value,e.mode)]);return t};m.rel=function(e){var t=new n.MathNode("mo",[h(e.value,e.mode)]);return t};m.open=function(e){var t=new n.MathNode("mo",[h(e.value,e.mode)]);return t};m.close=function(e){var t=new n.MathNode("mo",[h(e.value,e.mode)]);return t};m.inner=function(e){var t=new n.MathNode("mo",[h(e.value,e.mode)]);return t};m.punct=function(e){var t=new n.MathNode("mo",[h(e.value,e.mode)]);t.setAttribute("separator","true");return t};m.ordgroup=function(e,t){var r=f(e.value,t);var a=new n.MathNode("mrow",r);return a};m.text=function(e,t){var r=f(e.value.body,t);var a=new n.MathNode("mtext",r);return a};m.color=function(e,t){var r=f(e.value.value,t);var a=new n.MathNode("mstyle",r);a.setAttribute("mathcolor",e.value.color);return a};m.supsub=function(e,t){var r=[v(e.value.base,t)];if(e.value.sub){r.push(v(e.value.sub,t))}if(e.value.sup){r.push(v(e.value.sup,t))}var a;if(!e.value.sub){a="msup"}else if(!e.value.sup){a="msub"}else{a="msubsup"}var i=new n.MathNode(a,r);return i};m.genfrac=function(e,t){var r=new n.MathNode("mfrac",[v(e.value.numer,t),v(e.value.denom,t)]);if(!e.value.hasBarLine){r.setAttribute("linethickness","0px")}if(e.value.leftDelim!=null||e.value.rightDelim!=null){var a=[];if(e.value.leftDelim!=null){var i=new n.MathNode("mo",[new n.TextNode(e.value.leftDelim)]);i.setAttribute("fence","true");a.push(i)}a.push(r);if(e.value.rightDelim!=null){var s=new n.MathNode("mo",[new n.TextNode(e.value.rightDelim)]);s.setAttribute("fence","true");a.push(s)}var l=new n.MathNode("mrow",a);return l}return r};m.array=function(e,t){return new n.MathNode("mtable",e.value.body.map(function(e){return new n.MathNode("mtr",e.map(function(e){return new n.MathNode("mtd",[v(e,t)])}))}))};m.sqrt=function(e,t){var r;if(e.value.index){r=new n.MathNode("mroot",[v(e.value.body,t),v(e.value.index,t)])}else{r=new n.MathNode("msqrt",[v(e.value.body,t)])}return r};m.leftright=function(e,t){var r=f(e.value.body,t);if(e.value.left!=="."){var a=new n.MathNode("mo",[h(e.value.left,e.mode)]);a.setAttribute("fence","true");r.unshift(a)}if(e.value.right!=="."){var i=new n.MathNode("mo",[h(e.value.right,e.mode)]);i.setAttribute("fence","true");r.push(i)}var s=new n.MathNode("mrow",r);return s};m.middle=function(e,t){var r=new n.MathNode("mo",[h(e.value.middle,e.mode)]);r.setAttribute("fence","true");return r};m.accent=function(e,t){var r=new n.MathNode("mo",[h(e.value.accent,e.mode)]);var a=new n.MathNode("mover",[v(e.value.base,t),r]);a.setAttribute("accent","true");return a};m.spacing=function(e){var t;if(e.value==="\\ "||e.value==="\\space"||e.value===" "||e.value==="~"){t=new n.MathNode("mtext",[new n.TextNode("\xa0")])}else{t=new n.MathNode("mspace");t.setAttribute("width",a.spacingFunctions[e.value].size)}return t};m.op=function(e,t){var r;if(e.value.symbol){r=new n.MathNode("mo",[h(e.value.body,e.mode)])}else if(e.value.value){r=new n.MathNode("mo",f(e.value.value,t))}else{r=new n.MathNode("mi",[new n.TextNode(e.value.body.slice(1))])}return r};m.mod=function(e,t){var r=[];if(e.value.modType==="pod"||e.value.modType==="pmod"){r.push(new n.MathNode("mo",[h("(",e.mode)]))}if(e.value.modType!=="pod"){r.push(new n.MathNode("mo",[h("mod",e.mode)]))}if(e.value.value){var a=new n.MathNode("mspace");a.setAttribute("width","0.333333em");r.push(a);r=r.concat(f(e.value.value,t))}if(e.value.modType==="pod"||e.value.modType==="pmod"){r.push(new n.MathNode("mo",[h(")",e.mode)]))}return new n.MathNode("mo",r)};m.katex=function(e){var t=new n.MathNode("mtext",[new n.TextNode("KaTeX")]);return t};m.font=function(e,t){var r=e.value.font;return v(e.value.body,t.withFont(r))};m.delimsizing=function(e){var t=[];if(e.value.value!=="."){t.push(h(e.value.value,e.mode))}var r=new n.MathNode("mo",t);if(e.value.mclass==="mopen"||e.value.mclass==="mclose"){r.setAttribute("fence","true")}else{r.setAttribute("fence","false")}return r};m.styling=function(e,t){var r=f(e.value.value,t);var a=new n.MathNode("mstyle",r);var i={display:["0","true"],text:["0","false"],script:["1","false"],scriptscript:["2","false"]};var s=i[e.value.style];a.setAttribute("scriptlevel",s[0]);a.setAttribute("displaystyle",s[1]);return a};m.sizing=function(e,t){var r=f(e.value.value,t);var i=new n.MathNode("mstyle",r);i.setAttribute("mathsize",a.sizingMultiplier[e.value.size]+"em");return i};m.overline=function(e,t){var r=new n.MathNode("mo",[new n.TextNode("\u203e")]);r.setAttribute("stretchy","true");var a=new n.MathNode("mover",[v(e.value.body,t),r]);a.setAttribute("accent","true");return a};m.underline=function(e,t){var r=new n.MathNode("mo",[new n.TextNode("\u203e")]);r.setAttribute("stretchy","true");var a=new n.MathNode("munder",[v(e.value.body,t),r]);a.setAttribute("accentunder","true");return a};m.rule=function(e){var t=new n.MathNode("mrow");return t};m.kern=function(e){var t=new n.MathNode("mrow");return t};m.llap=function(e,t){var r=new n.MathNode("mpadded",[v(e.value.body,t)]);r.setAttribute("lspace","-1width");r.setAttribute("width","0px");return r};m.rlap=function(e,t){var r=new n.MathNode("mpadded",[v(e.value.body,t)]);r.setAttribute("width","0px");return r};m.phantom=function(e,t){var r=f(e.value.value,t);return new n.MathNode("mphantom",r)};m.mclass=function(e,t){var r=f(e.value.value,t);return new n.MathNode("mstyle",r)};var f=function(e,t){var r=[];for(var a=0;a<e.length;a++){var i=e[a];r.push(v(i,t))}return r};var v=function(e,t){if(!e){return new n.MathNode("mrow")}if(m[e.type]){return m[e.type](e,t)}else{throw new s("Got group of unknown type: '"+e.type+"'")}};var d=function(e,t,r){var a=f(e,r);var i=new n.MathNode("mrow",a);var s=new n.MathNode("annotation",[new n.TextNode(t)]);s.setAttribute("encoding","application/x-tex");var l=new n.MathNode("semantics",[i,s]);var o=new n.MathNode("math",[l]);return u(["katex-mathml"],[o])};t.exports=d},{"./ParseError":6,"./buildCommon":10,"./fontMetrics":17,"./mathMLTree":20,"./symbols":23,"./utils":25}],13:[function(e,t,r){var a=e("./buildHTML");var i=e("./buildMathML");var n=e("./buildCommon");var s=e("./Options");var l=e("./Settings");var o=e("./Style");var u=n.makeSpan;var p=function(e,t,r){r=r||new l({});var n=o.TEXT;if(r.displayMode){n=o.DISPLAY}var p=new s({style:n,size:"size5"});var h=i(e,t,p);var c=a(e,p);var m=u(["katex"],[h,c]);if(r.displayMode){return u(["katex-display"],[m])}else{return m}};t.exports=p},{"./Options":5,"./Settings":8,"./Style":9,"./buildCommon":10,"./buildHTML":11,"./buildMathML":12}],14:[function(e,t,r){var a=e("./ParseError");var i=e("./Style");var n=e("./buildCommon");var s=e("./fontMetrics");var l=e("./symbols");var o=e("./utils");var u=n.makeSpan;var p=function(e,t){if(l.math[e]&&l.math[e].replace){return s.getCharacterMetrics(l.math[e].replace,t)}else{return s.getCharacterMetrics(e,t)}};var h=function(e,t,r,a){return n.makeSymbol(e,"Size"+t+"-Regular",r,a)};var c=function(e,t,r,a){a=a||[];var i=u(a.concat(["style-wrap",r.style.reset(),t.cls()]),[e],r);var n=t.sizeMultiplier/r.style.sizeMultiplier;i.height*=n;i.depth*=n;i.maxFontSize=t.sizeMultiplier;return i};var m=function(e,t,r,a,i,s){var l=n.makeSymbol(e,"Main-Regular",i,a);var o=c(l,t,a,s);if(r){var u=(1-a.style.sizeMultiplier/t.sizeMultiplier)*a.style.metrics.axisHeight;o.style.top=u+"em";o.height-=u;o.depth+=u}return o};var f=function(e,t,r,a,n,s){var l=h(e,t,n,a);var o=c(u(["delimsizing","size"+t],[l],a),i.TEXT,a,s);if(r){var p=(1-a.style.sizeMultiplier)*a.style.metrics.axisHeight;o.style.top=p+"em";o.height-=p;o.depth+=p}return o};var v=function(e,t,r){var a;if(t==="Size1-Regular"){a="delim-size1"}else if(t==="Size4-Regular"){a="delim-size4"}var i=u(["delimsizinginner",a],[u([],[n.makeSymbol(e,t,r)])]);return{type:"elem",elem:i}};var d=function(e,t,r,a,s,l){var o;var h;var m;var f;o=m=f=e;h=null;var d="Size1-Regular";if(e==="\\uparrow"){m=f="\u23d0"}else if(e==="\\Uparrow"){m=f="\u2016"}else if(e==="\\downarrow"){o=m="\u23d0"}else if(e==="\\Downarrow"){o=m="\u2016"}else if(e==="\\updownarrow"){o="\\uparrow";m="\u23d0";f="\\downarrow"}else if(e==="\\Updownarrow"){o="\\Uparrow";m="\u2016";f="\\Downarrow"}else if(e==="["||e==="\\lbrack"){o="\u23a1";m="\u23a2";f="\u23a3";d="Size4-Regular"}else if(e==="]"||e==="\\rbrack"){o="\u23a4";m="\u23a5";f="\u23a6";d="Size4-Regular"}else if(e==="\\lfloor"){m=o="\u23a2";f="\u23a3";d="Size4-Regular"}else if(e==="\\lceil"){o="\u23a1";m=f="\u23a2";d="Size4-Regular"}else if(e==="\\rfloor"){m=o="\u23a5";f="\u23a6";d="Size4-Regular"}else if(e==="\\rceil"){o="\u23a4";m=f="\u23a5";d="Size4-Regular"}else if(e==="("){o="\u239b";m="\u239c";f="\u239d";d="Size4-Regular"}else if(e===")"){o="\u239e";m="\u239f";f="\u23a0";d="Size4-Regular"}else if(e==="\\{"||e==="\\lbrace"){o="\u23a7";h="\u23a8";f="\u23a9";m="\u23aa";d="Size4-Regular"}else if(e==="\\}"||e==="\\rbrace"){o="\u23ab";h="\u23ac";f="\u23ad";m="\u23aa";d="Size4-Regular"}else if(e==="\\lgroup"){o="\u23a7";f="\u23a9";m="\u23aa";d="Size4-Regular"}else if(e==="\\rgroup"){o="\u23ab";f="\u23ad";m="\u23aa";d="Size4-Regular"}else if(e==="\\lmoustache"){o="\u23a7";f="\u23ad";m="\u23aa";d="Size4-Regular"}else if(e==="\\rmoustache"){o="\u23ab";f="\u23a9";m="\u23aa";d="Size4-Regular"}else if(e==="\\surd"){o="\ue001";f="\u23b7";m="\ue000";d="Size4-Regular"}var g=p(o,d);var y=g.height+g.depth;var x=p(m,d);var b=x.height+x.depth;var w=p(f,d);var k=w.height+w.depth;var z=0;var S=1;if(h!==null){var M=p(h,d);z=M.height+M.depth;S=2}var T=y+k+z;var A=Math.ceil((t-T)/(S*b));var N=T+A*S*b;var q=a.style.metrics.axisHeight;if(r){q*=a.style.sizeMultiplier}var R=N/2-q;var E=[];E.push(v(f,d,s));var C;if(h===null){for(C=0;C<A;C++){E.push(v(m,d,s))}}else{for(C=0;C<A;C++){E.push(v(m,d,s))}E.push(v(h,d,s));for(C=0;C<A;C++){E.push(v(m,d,s))}}E.push(v(o,d,s));var D=n.makeVList(E,"bottom",R,a);return c(u(["delimsizing","mult"],[D],a),i.TEXT,a,l)};var g=["(",")","[","\\lbrack","]","\\rbrack","\\{","\\lbrace","\\}","\\rbrace","\\lfloor","\\rfloor","\\lceil","\\rceil","\\surd"];var y=["\\uparrow","\\downarrow","\\updownarrow","\\Uparrow","\\Downarrow","\\Updownarrow","|","\\|","\\vert","\\Vert","\\lvert","\\rvert","\\lVert","\\rVert","\\lgroup","\\rgroup","\\lmoustache","\\rmoustache"];var x=["<",">","\\langle","\\rangle","/","\\backslash","\\lt","\\gt"];var b=[0,1.2,1.8,2.4,3];var w=function(e,t,r,i,n){if(e==="<"||e==="\\lt"){e="\\langle"}else if(e===">"||e==="\\gt"){e="\\rangle"}if(o.contains(g,e)||o.contains(x,e)){return f(e,t,false,r,i,n)}else if(o.contains(y,e)){return d(e,b[t],false,r,i,n)}else{throw new a("Illegal delimiter: '"+e+"'")}};var k=[{type:"small",style:i.SCRIPTSCRIPT},{type:"small",style:i.SCRIPT},{type:"small",style:i.TEXT},{type:"large",size:1},{type:"large",size:2},{type:"large",size:3},{type:"large",size:4}];var z=[{type:"small",style:i.SCRIPTSCRIPT},{type:"small",style:i.SCRIPT},{type:"small",style:i.TEXT},{type:"stack"}];var S=[{type:"small",style:i.SCRIPTSCRIPT},{type:"small",style:i.SCRIPT},{type:"small",style:i.TEXT},{type:"large",size:1},{type:"large",size:2},{type:"large",size:3},{type:"large",size:4},{type:"stack"}];var M=function(e){if(e.type==="small"){return"Main-Regular"}else if(e.type==="large"){return"Size"+e.size+"-Regular"}else if(e.type==="stack"){return"Size4-Regular"}};var T=function(e,t,r,a){var i=Math.min(2,3-a.style.size);for(var n=i;n<r.length;n++){if(r[n].type==="stack"){break}var s=p(e,M(r[n]));var l=s.height+s.depth;if(r[n].type==="small"){l*=r[n].style.sizeMultiplier}if(l>t){return r[n]}}return r[r.length-1]};var A=function(e,t,r,a,i,n){if(e==="<"||e==="\\lt"){e="\\langle"}else if(e===">"||e==="\\gt"){e="\\rangle"}var s;if(o.contains(x,e)){s=k}else if(o.contains(g,e)){s=S}else{s=z}var l=T(e,t,s,a);if(l.type==="small"){return m(e,l.style,r,a,i,n)}else if(l.type==="large"){return f(e,l.size,r,a,i,n)}else if(l.type==="stack"){return d(e,t,r,a,i,n)}};var N=function(e,t,r,a,i,n){var l=a.style.metrics.axisHeight*a.style.sizeMultiplier;var o=901;var u=5/s.metrics.ptPerEm;var p=Math.max(t-l,r+l);var h=Math.max(p/500*o,2*p-u);return A(e,h,true,a,i,n)};t.exports={sizedDelim:w,customSizedDelim:A,leftRightDelim:N}},{"./ParseError":6,"./Style":9,"./buildCommon":10,"./fontMetrics":17,"./symbols":23,"./utils":25}],15:[function(e,t,r){var a=e("./unicodeRegexes");var i=e("./utils");var n=function(e){e=e.slice();for(var t=e.length-1;t>=0;t--){if(!e[t]){e.splice(t,1)}}return e.join(" ")};function s(e,t,r){this.classes=e||[];this.children=t||[];this.height=0;this.depth=0;this.maxFontSize=0;this.style={};this.attributes={};if(r){if(r.style.isTight()){this.classes.push("mtight")}if(r.getColor()){this.style.color=r.getColor()}}}s.prototype.setAttribute=function(e,t){this.attributes[e]=t};s.prototype.tryCombine=function(e){return false};s.prototype.toNode=function(){var e=document.createElement("span");e.className=n(this.classes);for(var t in this.style){if(Object.prototype.hasOwnProperty.call(this.style,t)){e.style[t]=this.style[t]}}for(var r in this.attributes){if(Object.prototype.hasOwnProperty.call(this.attributes,r)){e.setAttribute(r,this.attributes[r])}}for(var a=0;a<this.children.length;a++){e.appendChild(this.children[a].toNode())}return e};s.prototype.toMarkup=function(){var e="<span";if(this.classes.length){e+=' class="';e+=i.escape(n(this.classes));e+='"'}var t="";for(var r in this.style){if(this.style.hasOwnProperty(r)){t+=i.hyphenate(r)+":"+this.style[r]+";"}}if(t){e+=' style="'+i.escape(t)+'"'}for(var a in this.attributes){if(Object.prototype.hasOwnProperty.call(this.attributes,a)){e+=" "+a+'="';e+=i.escape(this.attributes[a]);e+='"'}}e+=">";for(var s=0;s<this.children.length;s++){e+=this.children[s].toMarkup()}e+="</span>";return e};function l(e){this.children=e||[];this.height=0;this.depth=0;this.maxFontSize=0}l.prototype.toNode=function(){var e=document.createDocumentFragment();for(var t=0;t<this.children.length;t++){e.appendChild(this.children[t].toNode())}return e};l.prototype.toMarkup=function(){var e="";for(var t=0;t<this.children.length;t++){e+=this.children[t].toMarkup()}return e};var o={"\xee":"\u0131\u0302","\xef":"\u0131\u0308","\xed":"\u0131\u0301","\xec":"\u0131\u0300"};function u(e,t,r,i,n,s,l){this.value=e||"";this.height=t||0;this.depth=r||0;this.italic=i||0;this.skew=n||0;this.classes=s||[];this.style=l||{};this.maxFontSize=0;if(a.cjkRegex.test(e)){if(a.hangulRegex.test(e)){this.classes.push("hangul_fallback")}else{this.classes.push("cjk_fallback")}}if(/[\xee\xef\xed\xec]/.test(this.value)){this.value=o[this.value]}}u.prototype.tryCombine=function(e){if(!e||!(e instanceof u)||this.italic>0||n(this.classes)!==n(e.classes)||this.skew!==e.skew||this.maxFontSize!==e.maxFontSize){return false}for(var t in this.style){if(this.style.hasOwnProperty(t)&&this.style[t]!==e.style[t]){return false}}for(t in e.style){if(e.style.hasOwnProperty(t)&&this.style[t]!==e.style[t]){return false}}this.value+=e.value;this.height=Math.max(this.height,e.height);this.depth=Math.max(this.depth,e.depth);this.italic=e.italic;return true};u.prototype.toNode=function(){var e=document.createTextNode(this.value);var t=null;if(this.italic>0){t=document.createElement("span");t.style.marginRight=this.italic+"em"}if(this.classes.length>0){t=t||document.createElement("span");t.className=n(this.classes)}for(var r in this.style){if(this.style.hasOwnProperty(r)){t=t||document.createElement("span");t.style[r]=this.style[r]}}if(t){t.appendChild(e);return t}else{return e}};u.prototype.toMarkup=function(){var e=false;var t="<span";if(this.classes.length){e=true;t+=' class="';t+=i.escape(n(this.classes));t+='"'}var r="";if(this.italic>0){r+="margin-right:"+this.italic+"em;"}for(var a in this.style){if(this.style.hasOwnProperty(a)){r+=i.hyphenate(a)+":"+this.style[a]+";"}}if(r){e=true;t+=' style="'+i.escape(r)+'"'}var s=i.escape(this.value);if(e){t+=">";t+=s;t+="</span>";return t}else{return s}};t.exports={span:s,documentFragment:l,symbolNode:u}},{"./unicodeRegexes":24,"./utils":25}],16:[function(e,t,r){var a=e("./parseData");var i=e("./ParseError");var n=e("./Style");var s=a.ParseNode;function l(e,t){var r=[];var a=[r];var n=[];while(true){var l=e.parseExpression(false,null);r.push(new s("ordgroup",l,e.mode));var o=e.nextToken.text;if(o==="&"){e.consume()}else if(o==="\\end"){break}else if(o==="\\\\"||o==="\\cr"){var u=e.parseFunction();n.push(u.value.size);r=[];a.push(r)}else{throw new i("Expected & or \\\\ or \\end",e.nextToken)}}t.body=a;t.rowGaps=n;return new s(t.type,t,e.mode)}function o(e,r,a){if(typeof e==="string"){e=[e]}if(typeof r==="number"){r={numArgs:r}}var i={numArgs:r.numArgs||0,argTypes:r.argTypes,greediness:1,allowedInText:!!r.allowedInText,numOptionalArgs:r.numOptionalArgs||0,handler:a};for(var n=0;n<e.length;++n){t.exports[e[n]]=i}}o("array",{numArgs:1},function(e,t){var r=t[0];r=r.value.map?r.value:[r];var a=r.map(function(e){var t=e.value;if("lcr".indexOf(t)!==-1){return{type:"align",align:t}}else if(t==="|"){return{type:"separator",separator:"|"}}throw new i("Unknown column alignment: "+e.value,e)});var n={type:"array",cols:a,hskipBeforeAndAfter:true};n=l(e.parser,n);return n});o(["matrix","pmatrix","bmatrix","Bmatrix","vmatrix","Vmatrix"],{},function(e){var t={matrix:null,pmatrix:["(",")"],bmatrix:["[","]"],Bmatrix:["\\{","\\}"],vmatrix:["|","|"],Vmatrix:["\\Vert","\\Vert"]}[e.envName];var r={type:"array",hskipBeforeAndAfter:false};r=l(e.parser,r);if(t){r=new s("leftright",{body:[r],left:t[0],right:t[1]},e.mode)}return r});o("cases",{},function(e){var t={type:"array",arraystretch:1.2,cols:[{type:"align",align:"l",pregap:0,postgap:n.TEXT.metrics.quad},{type:"align",align:"l",pregap:0,postgap:0}]};t=l(e.parser,t);t=new s("leftright",{body:[t],left:"\\{",right:"."},e.mode);return t});o("aligned",{},function(e){var t={type:"array",cols:[]};t=l(e.parser,t);var r=new s("ordgroup",[],e.mode);var a=0;t.value.body.forEach(function(e){var t;for(t=1;t<e.length;t+=2){e[t].value.unshift(r)}if(a<e.length){a=e.length}});for(var i=0;i<a;++i){var n="r";var o=0;if(i%2===1){n="l"}else if(i>0){o=2}t.value.cols[i]={type:"align",align:n,pregap:o,postgap:0}}return t})},{"./ParseError":6,"./Style":9,"./parseData":21}],17:[function(e,t,r){var a=e("./Style");var i=e("./unicodeRegexes").cjkRegex;var n={slant:[.25,.25,.25],space:[0,0,0],stretch:[0,0,0],shrink:[0,0,0],xHeight:[.431,.431,.431],quad:[1,1.171,1.472],extraSpace:[0,0,0],num1:[.677,.732,.925],num2:[.394,.384,.387],num3:[.444,.471,.504],denom1:[.686,.752,1.025],denom2:[.345,.344,.532],sup1:[.413,.503,.504],sup2:[.363,.431,.404],sup3:[.289,.286,.294],sub1:[.15,.143,.2],sub2:[.247,.286,.4],supDrop:[.386,.353,.494],subDrop:[.05,.071,.1],delim1:[2.39,1.7,1.98],delim2:[1.01,1.157,1.42],axisHeight:[.25,.25,.25]};var s=0;var l=0;var o=0;var u=0;var p=.431;var h=1;var c=0;var m=.04;var f=.111;var v=.166;var d=.2;var g=.6;var y=.1;var x=10;var b=2/x;var w={defaultRuleThickness:m,bigOpSpacing1:f,bigOpSpacing2:v,bigOpSpacing3:d,bigOpSpacing4:g,bigOpSpacing5:y,ptPerEm:x,doubleRuleSep:b};var k=e("./fontMetricsData");var z={"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xc6":"A","\xc7":"C","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xcc":"I","\xcd":"I","\xce":"I","\xcf":"I","\xd0":"D","\xd1":"N","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O","\xd8":"O","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xdd":"Y","\xde":"o","\xdf":"B","\xe0":"a","\xe1":"a","\xe2":"a","\xe3":"a","\xe4":"a","\xe5":"a","\xe6":"a","\xe7":"c","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xf0":"d","\xf1":"n","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xfd":"y","\xfe":"o","\xff":"y","\u0410":"A","\u0411":"B","\u0412":"B","\u0413":"F","\u0414":"A","\u0415":"E","\u0416":"K","\u0417":"3","\u0418":"N","\u0419":"N","\u041a":"K","\u041b":"N","\u041c":"M","\u041d":"H","\u041e":"O","\u041f":"N","\u0420":"P","\u0421":"C","\u0422":"T","\u0423":"y","\u0424":"O","\u0425":"X","\u0426":"U","\u0427":"h","\u0428":"W","\u0429":"W","\u042a":"B","\u042b":"X","\u042c":"B","\u042d":"3","\u042e":"X","\u042f":"R","\u0430":"a","\u0431":"b","\u0432":"a","\u0433":"r","\u0434":"y","\u0435":"e","\u0436":"m","\u0437":"e","\u0438":"n","\u0439":"n","\u043a":"n","\u043b":"n","\u043c":"m","\u043d":"n","\u043e":"o","\u043f":"n","\u0440":"p","\u0441":"c","\u0442":"o","\u0443":"y","\u0444":"b","\u0445":"x","\u0446":"n","\u0447":"n","\u0448":"w","\u0449":"w","\u044a":"a","\u044b":"m","\u044c":"a","\u044d":"e","\u044e":"m","\u044f":"r"};var S=function(e,t){var r=e.charCodeAt(0);if(e[0]in z){r=z[e[0]].charCodeAt(0)}else if(i.test(e[0])){r="M".charCodeAt(0)}var a=k[t][r];if(a){return{depth:a[0],height:a[1],italic:a[2],skew:a[3],width:a[4]}}};t.exports={metrics:w,sigmas:n,getCharacterMetrics:S}},{"./Style":9,"./fontMetricsData":18,"./unicodeRegexes":24}],18:[function(e,t,r){t.exports={"AMS-Regular":{65:[0,.68889,0,0],66:[0,.68889,0,0],67:[0,.68889,0,0],68:[0,.68889,0,0],69:[0,.68889,0,0],70:[0,.68889,0,0],71:[0,.68889,0,0],72:[0,.68889,0,0],73:[0,.68889,0,0],74:[.16667,.68889,0,0],75:[0,.68889,0,0],76:[0,.68889,0,0],77:[0,.68889,0,0],78:[0,.68889,0,0],79:[.16667,.68889,0,0],80:[0,.68889,0,0],81:[.16667,.68889,0,0],82:[0,.68889,0,0],83:[0,.68889,0,0],84:[0,.68889,0,0],85:[0,.68889,0,0],86:[0,.68889,0,0],87:[0,.68889,0,0],88:[0,.68889,0,0],89:[0,.68889,0,0],90:[0,.68889,0,0],107:[0,.68889,0,0],165:[0,.675,.025,0],174:[.15559,.69224,0,0],240:[0,.68889,0,0],295:[0,.68889,0,0],710:[0,.825,0,0],732:[0,.9,0,0],770:[0,.825,0,0],771:[0,.9,0,0],989:[.08167,.58167,0,0],1008:[0,.43056,.04028,0],8245:[0,.54986,0,0],8463:[0,.68889,0,0],8487:[0,.68889,0,0],8498:[0,.68889,0,0],8502:[0,.68889,0,0],8503:[0,.68889,0,0],8504:[0,.68889,0,0],8513:[0,.68889,0,0],8592:[-.03598,.46402,0,0],8594:[-.03598,.46402,0,0],8602:[-.13313,.36687,0,0],8603:[-.13313,.36687,0,0],8606:[.01354,.52239,0,0],8608:[.01354,.52239,0,0],8610:[.01354,.52239,0,0],8611:[.01354,.52239,0,0],8619:[0,.54986,0,0],8620:[0,.54986,0,0],8621:[-.13313,.37788,0,0],8622:[-.13313,.36687,0,0],8624:[0,.69224,0,0],8625:[0,.69224,0,0],8630:[0,.43056,0,0],8631:[0,.43056,0,0],8634:[.08198,.58198,0,0],8635:[.08198,.58198,0,0],8638:[.19444,.69224,0,0],8639:[.19444,.69224,0,0],8642:[.19444,.69224,0,0],8643:[.19444,.69224,0,0],8644:[.1808,.675,0,0],8646:[.1808,.675,0,0],8647:[.1808,.675,0,0],8648:[.19444,.69224,0,0],8649:[.1808,.675,0,0],8650:[.19444,.69224,0,0],8651:[.01354,.52239,0,0],8652:[.01354,.52239,0,0],8653:[-.13313,.36687,0,0],8654:[-.13313,.36687,0,0],8655:[-.13313,.36687,0,0],8666:[.13667,.63667,0,0],8667:[.13667,.63667,0,0],8669:[-.13313,.37788,0,0],8672:[-.064,.437,0,0],8674:[-.064,.437,0,0],8705:[0,.825,0,0],8708:[0,.68889,0,0],8709:[.08167,.58167,0,0],8717:[0,.43056,0,0],8722:[-.03598,.46402,0,0],8724:[.08198,.69224,0,0],8726:[.08167,.58167,0,0],8733:[0,.69224,0,0],8736:[0,.69224,0,0],8737:[0,.69224,0,0],8738:[.03517,.52239,0,0],8739:[.08167,.58167,0,0],8740:[.25142,.74111,0,0],8741:[.08167,.58167,0,0],8742:[.25142,.74111,0,0],8756:[0,.69224,0,0],8757:[0,.69224,0,0],8764:[-.13313,.36687,0,0],8765:[-.13313,.37788,0,0],8769:[-.13313,.36687,0,0],8770:[-.03625,.46375,0,0],8774:[.30274,.79383,0,0],8776:[-.01688,.48312,0,0],8778:[.08167,.58167,0,0],8782:[.06062,.54986,0,0],8783:[.06062,.54986,0,0],8785:[.08198,.58198,0,0],8786:[.08198,.58198,0,0],8787:[.08198,.58198,0,0],8790:[0,.69224,0,0],8791:[.22958,.72958,0,0],8796:[.08198,.91667,0,0],8806:[.25583,.75583,0,0],
+8807:[.25583,.75583,0,0],8808:[.25142,.75726,0,0],8809:[.25142,.75726,0,0],8812:[.25583,.75583,0,0],8814:[.20576,.70576,0,0],8815:[.20576,.70576,0,0],8816:[.30274,.79383,0,0],8817:[.30274,.79383,0,0],8818:[.22958,.72958,0,0],8819:[.22958,.72958,0,0],8822:[.1808,.675,0,0],8823:[.1808,.675,0,0],8828:[.13667,.63667,0,0],8829:[.13667,.63667,0,0],8830:[.22958,.72958,0,0],8831:[.22958,.72958,0,0],8832:[.20576,.70576,0,0],8833:[.20576,.70576,0,0],8840:[.30274,.79383,0,0],8841:[.30274,.79383,0,0],8842:[.13597,.63597,0,0],8843:[.13597,.63597,0,0],8847:[.03517,.54986,0,0],8848:[.03517,.54986,0,0],8858:[.08198,.58198,0,0],8859:[.08198,.58198,0,0],8861:[.08198,.58198,0,0],8862:[0,.675,0,0],8863:[0,.675,0,0],8864:[0,.675,0,0],8865:[0,.675,0,0],8872:[0,.69224,0,0],8873:[0,.69224,0,0],8874:[0,.69224,0,0],8876:[0,.68889,0,0],8877:[0,.68889,0,0],8878:[0,.68889,0,0],8879:[0,.68889,0,0],8882:[.03517,.54986,0,0],8883:[.03517,.54986,0,0],8884:[.13667,.63667,0,0],8885:[.13667,.63667,0,0],8888:[0,.54986,0,0],8890:[.19444,.43056,0,0],8891:[.19444,.69224,0,0],8892:[.19444,.69224,0,0],8901:[0,.54986,0,0],8903:[.08167,.58167,0,0],8905:[.08167,.58167,0,0],8906:[.08167,.58167,0,0],8907:[0,.69224,0,0],8908:[0,.69224,0,0],8909:[-.03598,.46402,0,0],8910:[0,.54986,0,0],8911:[0,.54986,0,0],8912:[.03517,.54986,0,0],8913:[.03517,.54986,0,0],8914:[0,.54986,0,0],8915:[0,.54986,0,0],8916:[0,.69224,0,0],8918:[.0391,.5391,0,0],8919:[.0391,.5391,0,0],8920:[.03517,.54986,0,0],8921:[.03517,.54986,0,0],8922:[.38569,.88569,0,0],8923:[.38569,.88569,0,0],8926:[.13667,.63667,0,0],8927:[.13667,.63667,0,0],8928:[.30274,.79383,0,0],8929:[.30274,.79383,0,0],8934:[.23222,.74111,0,0],8935:[.23222,.74111,0,0],8936:[.23222,.74111,0,0],8937:[.23222,.74111,0,0],8938:[.20576,.70576,0,0],8939:[.20576,.70576,0,0],8940:[.30274,.79383,0,0],8941:[.30274,.79383,0,0],8994:[.19444,.69224,0,0],8995:[.19444,.69224,0,0],9416:[.15559,.69224,0,0],9484:[0,.69224,0,0],9488:[0,.69224,0,0],9492:[0,.37788,0,0],9496:[0,.37788,0,0],9585:[.19444,.68889,0,0],9586:[.19444,.74111,0,0],9632:[0,.675,0,0],9633:[0,.675,0,0],9650:[0,.54986,0,0],9651:[0,.54986,0,0],9654:[.03517,.54986,0,0],9660:[0,.54986,0,0],9661:[0,.54986,0,0],9664:[.03517,.54986,0,0],9674:[.11111,.69224,0,0],9733:[.19444,.69224,0,0],10003:[0,.69224,0,0],10016:[0,.69224,0,0],10731:[.11111,.69224,0,0],10846:[.19444,.75583,0,0],10877:[.13667,.63667,0,0],10878:[.13667,.63667,0,0],10885:[.25583,.75583,0,0],10886:[.25583,.75583,0,0],10887:[.13597,.63597,0,0],10888:[.13597,.63597,0,0],10889:[.26167,.75726,0,0],10890:[.26167,.75726,0,0],10891:[.48256,.98256,0,0],10892:[.48256,.98256,0,0],10901:[.13667,.63667,0,0],10902:[.13667,.63667,0,0],10933:[.25142,.75726,0,0],10934:[.25142,.75726,0,0],10935:[.26167,.75726,0,0],10936:[.26167,.75726,0,0],10937:[.26167,.75726,0,0],10938:[.26167,.75726,0,0],10949:[.25583,.75583,0,0],10950:[.25583,.75583,0,0],10955:[.28481,.79383,0,0],10956:[.28481,.79383,0,0],57350:[.08167,.58167,0,0],57351:[.08167,.58167,0,0],57352:[.08167,.58167,0,0],57353:[0,.43056,.04028,0],57356:[.25142,.75726,0,0],57357:[.25142,.75726,0,0],57358:[.41951,.91951,0,0],57359:[.30274,.79383,0,0],57360:[.30274,.79383,0,0],57361:[.41951,.91951,0,0],57366:[.25142,.75726,0,0],57367:[.25142,.75726,0,0],57368:[.25142,.75726,0,0],57369:[.25142,.75726,0,0],57370:[.13597,.63597,0,0],57371:[.13597,.63597,0,0]},"Caligraphic-Regular":{48:[0,.43056,0,0],49:[0,.43056,0,0],50:[0,.43056,0,0],51:[.19444,.43056,0,0],52:[.19444,.43056,0,0],53:[.19444,.43056,0,0],54:[0,.64444,0,0],55:[.19444,.43056,0,0],56:[0,.64444,0,0],57:[.19444,.43056,0,0],65:[0,.68333,0,.19445],66:[0,.68333,.03041,.13889],67:[0,.68333,.05834,.13889],68:[0,.68333,.02778,.08334],69:[0,.68333,.08944,.11111],70:[0,.68333,.09931,.11111],71:[.09722,.68333,.0593,.11111],72:[0,.68333,.00965,.11111],73:[0,.68333,.07382,0],74:[.09722,.68333,.18472,.16667],75:[0,.68333,.01445,.05556],76:[0,.68333,0,.13889],77:[0,.68333,0,.13889],78:[0,.68333,.14736,.08334],79:[0,.68333,.02778,.11111],80:[0,.68333,.08222,.08334],81:[.09722,.68333,0,.11111],82:[0,.68333,0,.08334],83:[0,.68333,.075,.13889],84:[0,.68333,.25417,0],85:[0,.68333,.09931,.08334],86:[0,.68333,.08222,0],87:[0,.68333,.08222,.08334],88:[0,.68333,.14643,.13889],89:[.09722,.68333,.08222,.08334],90:[0,.68333,.07944,.13889]},"Fraktur-Regular":{33:[0,.69141,0,0],34:[0,.69141,0,0],38:[0,.69141,0,0],39:[0,.69141,0,0],40:[.24982,.74947,0,0],41:[.24982,.74947,0,0],42:[0,.62119,0,0],43:[.08319,.58283,0,0],44:[0,.10803,0,0],45:[.08319,.58283,0,0],46:[0,.10803,0,0],47:[.24982,.74947,0,0],48:[0,.47534,0,0],49:[0,.47534,0,0],50:[0,.47534,0,0],51:[.18906,.47534,0,0],52:[.18906,.47534,0,0],53:[.18906,.47534,0,0],54:[0,.69141,0,0],55:[.18906,.47534,0,0],56:[0,.69141,0,0],57:[.18906,.47534,0,0],58:[0,.47534,0,0],59:[.12604,.47534,0,0],61:[-.13099,.36866,0,0],63:[0,.69141,0,0],65:[0,.69141,0,0],66:[0,.69141,0,0],67:[0,.69141,0,0],68:[0,.69141,0,0],69:[0,.69141,0,0],70:[.12604,.69141,0,0],71:[0,.69141,0,0],72:[.06302,.69141,0,0],73:[0,.69141,0,0],74:[.12604,.69141,0,0],75:[0,.69141,0,0],76:[0,.69141,0,0],77:[0,.69141,0,0],78:[0,.69141,0,0],79:[0,.69141,0,0],80:[.18906,.69141,0,0],81:[.03781,.69141,0,0],82:[0,.69141,0,0],83:[0,.69141,0,0],84:[0,.69141,0,0],85:[0,.69141,0,0],86:[0,.69141,0,0],87:[0,.69141,0,0],88:[0,.69141,0,0],89:[.18906,.69141,0,0],90:[.12604,.69141,0,0],91:[.24982,.74947,0,0],93:[.24982,.74947,0,0],94:[0,.69141,0,0],97:[0,.47534,0,0],98:[0,.69141,0,0],99:[0,.47534,0,0],100:[0,.62119,0,0],101:[0,.47534,0,0],102:[.18906,.69141,0,0],103:[.18906,.47534,0,0],104:[.18906,.69141,0,0],105:[0,.69141,0,0],106:[0,.69141,0,0],107:[0,.69141,0,0],108:[0,.69141,0,0],109:[0,.47534,0,0],110:[0,.47534,0,0],111:[0,.47534,0,0],112:[.18906,.52396,0,0],113:[.18906,.47534,0,0],114:[0,.47534,0,0],115:[0,.47534,0,0],116:[0,.62119,0,0],117:[0,.47534,0,0],118:[0,.52396,0,0],119:[0,.52396,0,0],120:[.18906,.47534,0,0],121:[.18906,.47534,0,0],122:[.18906,.47534,0,0],8216:[0,.69141,0,0],8217:[0,.69141,0,0],58112:[0,.62119,0,0],58113:[0,.62119,0,0],58114:[.18906,.69141,0,0],58115:[.18906,.69141,0,0],58116:[.18906,.47534,0,0],58117:[0,.69141,0,0],58118:[0,.62119,0,0],58119:[0,.47534,0,0]},"Main-Bold":{33:[0,.69444,0,0],34:[0,.69444,0,0],35:[.19444,.69444,0,0],36:[.05556,.75,0,0],37:[.05556,.75,0,0],38:[0,.69444,0,0],39:[0,.69444,0,0],40:[.25,.75,0,0],41:[.25,.75,0,0],42:[0,.75,0,0],43:[.13333,.63333,0,0],44:[.19444,.15556,0,0],45:[0,.44444,0,0],46:[0,.15556,0,0],47:[.25,.75,0,0],48:[0,.64444,0,0],49:[0,.64444,0,0],50:[0,.64444,0,0],51:[0,.64444,0,0],52:[0,.64444,0,0],53:[0,.64444,0,0],54:[0,.64444,0,0],55:[0,.64444,0,0],56:[0,.64444,0,0],57:[0,.64444,0,0],58:[0,.44444,0,0],59:[.19444,.44444,0,0],60:[.08556,.58556,0,0],61:[-.10889,.39111,0,0],62:[.08556,.58556,0,0],63:[0,.69444,0,0],64:[0,.69444,0,0],65:[0,.68611,0,0],66:[0,.68611,0,0],67:[0,.68611,0,0],68:[0,.68611,0,0],69:[0,.68611,0,0],70:[0,.68611,0,0],71:[0,.68611,0,0],72:[0,.68611,0,0],73:[0,.68611,0,0],74:[0,.68611,0,0],75:[0,.68611,0,0],76:[0,.68611,0,0],77:[0,.68611,0,0],78:[0,.68611,0,0],79:[0,.68611,0,0],80:[0,.68611,0,0],81:[.19444,.68611,0,0],82:[0,.68611,0,0],83:[0,.68611,0,0],84:[0,.68611,0,0],85:[0,.68611,0,0],86:[0,.68611,.01597,0],87:[0,.68611,.01597,0],88:[0,.68611,0,0],89:[0,.68611,.02875,0],90:[0,.68611,0,0],91:[.25,.75,0,0],92:[.25,.75,0,0],93:[.25,.75,0,0],94:[0,.69444,0,0],95:[.31,.13444,.03194,0],96:[0,.69444,0,0],97:[0,.44444,0,0],98:[0,.69444,0,0],99:[0,.44444,0,0],100:[0,.69444,0,0],101:[0,.44444,0,0],102:[0,.69444,.10903,0],103:[.19444,.44444,.01597,0],104:[0,.69444,0,0],105:[0,.69444,0,0],106:[.19444,.69444,0,0],107:[0,.69444,0,0],108:[0,.69444,0,0],109:[0,.44444,0,0],110:[0,.44444,0,0],111:[0,.44444,0,0],112:[.19444,.44444,0,0],113:[.19444,.44444,0,0],114:[0,.44444,0,0],115:[0,.44444,0,0],116:[0,.63492,0,0],117:[0,.44444,0,0],118:[0,.44444,.01597,0],119:[0,.44444,.01597,0],120:[0,.44444,0,0],121:[.19444,.44444,.01597,0],122:[0,.44444,0,0],123:[.25,.75,0,0],124:[.25,.75,0,0],125:[.25,.75,0,0],126:[.35,.34444,0,0],168:[0,.69444,0,0],172:[0,.44444,0,0],175:[0,.59611,0,0],176:[0,.69444,0,0],177:[.13333,.63333,0,0],180:[0,.69444,0,0],215:[.13333,.63333,0,0],247:[.13333,.63333,0,0],305:[0,.44444,0,0],567:[.19444,.44444,0,0],710:[0,.69444,0,0],711:[0,.63194,0,0],713:[0,.59611,0,0],714:[0,.69444,0,0],715:[0,.69444,0,0],728:[0,.69444,0,0],729:[0,.69444,0,0],730:[0,.69444,0,0],732:[0,.69444,0,0],768:[0,.69444,0,0],769:[0,.69444,0,0],770:[0,.69444,0,0],771:[0,.69444,0,0],772:[0,.59611,0,0],774:[0,.69444,0,0],775:[0,.69444,0,0],776:[0,.69444,0,0],778:[0,.69444,0,0],779:[0,.69444,0,0],780:[0,.63194,0,0],824:[.19444,.69444,0,0],915:[0,.68611,0,0],916:[0,.68611,0,0],920:[0,.68611,0,0],923:[0,.68611,0,0],926:[0,.68611,0,0],928:[0,.68611,0,0],931:[0,.68611,0,0],933:[0,.68611,0,0],934:[0,.68611,0,0],936:[0,.68611,0,0],937:[0,.68611,0,0],8211:[0,.44444,.03194,0],8212:[0,.44444,.03194,0],8216:[0,.69444,0,0],8217:[0,.69444,0,0],8220:[0,.69444,0,0],8221:[0,.69444,0,0],8224:[.19444,.69444,0,0],8225:[.19444,.69444,0,0],8242:[0,.55556,0,0],8407:[0,.72444,.15486,0],8463:[0,.69444,0,0],8465:[0,.69444,0,0],8467:[0,.69444,0,0],8472:[.19444,.44444,0,0],8476:[0,.69444,0,0],8501:[0,.69444,0,0],8592:[-.10889,.39111,0,0],8593:[.19444,.69444,0,0],8594:[-.10889,.39111,0,0],8595:[.19444,.69444,0,0],8596:[-.10889,.39111,0,0],8597:[.25,.75,0,0],8598:[.19444,.69444,0,0],8599:[.19444,.69444,0,0],8600:[.19444,.69444,0,0],8601:[.19444,.69444,0,0],8636:[-.10889,.39111,0,0],8637:[-.10889,.39111,0,0],8640:[-.10889,.39111,0,0],8641:[-.10889,.39111,0,0],8656:[-.10889,.39111,0,0],8657:[.19444,.69444,0,0],8658:[-.10889,.39111,0,0],8659:[.19444,.69444,0,0],8660:[-.10889,.39111,0,0],8661:[.25,.75,0,0],8704:[0,.69444,0,0],8706:[0,.69444,.06389,0],8707:[0,.69444,0,0],8709:[.05556,.75,0,0],8711:[0,.68611,0,0],8712:[.08556,.58556,0,0],8715:[.08556,.58556,0,0],8722:[.13333,.63333,0,0],8723:[.13333,.63333,0,0],8725:[.25,.75,0,0],8726:[.25,.75,0,0],8727:[-.02778,.47222,0,0],8728:[-.02639,.47361,0,0],8729:[-.02639,.47361,0,0],8730:[.18,.82,0,0],8733:[0,.44444,0,0],8734:[0,.44444,0,0],8736:[0,.69224,0,0],8739:[.25,.75,0,0],8741:[.25,.75,0,0],8743:[0,.55556,0,0],8744:[0,.55556,0,0],8745:[0,.55556,0,0],8746:[0,.55556,0,0],8747:[.19444,.69444,.12778,0],8764:[-.10889,.39111,0,0],8768:[.19444,.69444,0,0],8771:[.00222,.50222,0,0],8776:[.02444,.52444,0,0],8781:[.00222,.50222,0,0],8801:[.00222,.50222,0,0],8804:[.19667,.69667,0,0],8805:[.19667,.69667,0,0],8810:[.08556,.58556,0,0],8811:[.08556,.58556,0,0],8826:[.08556,.58556,0,0],8827:[.08556,.58556,0,0],8834:[.08556,.58556,0,0],8835:[.08556,.58556,0,0],8838:[.19667,.69667,0,0],8839:[.19667,.69667,0,0],8846:[0,.55556,0,0],8849:[.19667,.69667,0,0],8850:[.19667,.69667,0,0],8851:[0,.55556,0,0],8852:[0,.55556,0,0],8853:[.13333,.63333,0,0],8854:[.13333,.63333,0,0],8855:[.13333,.63333,0,0],8856:[.13333,.63333,0,0],8857:[.13333,.63333,0,0],8866:[0,.69444,0,0],8867:[0,.69444,0,0],8868:[0,.69444,0,0],8869:[0,.69444,0,0],8900:[-.02639,.47361,0,0],8901:[-.02639,.47361,0,0],8902:[-.02778,.47222,0,0],8968:[.25,.75,0,0],8969:[.25,.75,0,0],8970:[.25,.75,0,0],8971:[.25,.75,0,0],8994:[-.13889,.36111,0,0],8995:[-.13889,.36111,0,0],9651:[.19444,.69444,0,0],9657:[-.02778,.47222,0,0],9661:[.19444,.69444,0,0],9667:[-.02778,.47222,0,0],9711:[.19444,.69444,0,0],9824:[.12963,.69444,0,0],9825:[.12963,.69444,0,0],9826:[.12963,.69444,0,0],9827:[.12963,.69444,0,0],9837:[0,.75,0,0],9838:[.19444,.69444,0,0],9839:[.19444,.69444,0,0],10216:[.25,.75,0,0],10217:[.25,.75,0,0],10815:[0,.68611,0,0],10927:[.19667,.69667,0,0],10928:[.19667,.69667,0,0]},"Main-Italic":{33:[0,.69444,.12417,0],34:[0,.69444,.06961,0],35:[.19444,.69444,.06616,0],37:[.05556,.75,.13639,0],38:[0,.69444,.09694,0],39:[0,.69444,.12417,0],40:[.25,.75,.16194,0],41:[.25,.75,.03694,0],42:[0,.75,.14917,0],43:[.05667,.56167,.03694,0],44:[.19444,.10556,0,0],45:[0,.43056,.02826,0],46:[0,.10556,0,0],47:[.25,.75,.16194,0],48:[0,.64444,.13556,0],49:[0,.64444,.13556,0],50:[0,.64444,.13556,0],51:[0,.64444,.13556,0],52:[.19444,.64444,.13556,0],53:[0,.64444,.13556,0],54:[0,.64444,.13556,0],55:[.19444,.64444,.13556,0],56:[0,.64444,.13556,0],57:[0,.64444,.13556,0],58:[0,.43056,.0582,0],59:[.19444,.43056,.0582,0],61:[-.13313,.36687,.06616,0],63:[0,.69444,.1225,0],64:[0,.69444,.09597,0],65:[0,.68333,0,0],66:[0,.68333,.10257,0],67:[0,.68333,.14528,0],68:[0,.68333,.09403,0],69:[0,.68333,.12028,0],70:[0,.68333,.13305,0],71:[0,.68333,.08722,0],72:[0,.68333,.16389,0],73:[0,.68333,.15806,0],74:[0,.68333,.14028,0],75:[0,.68333,.14528,0],76:[0,.68333,0,0],77:[0,.68333,.16389,0],78:[0,.68333,.16389,0],79:[0,.68333,.09403,0],80:[0,.68333,.10257,0],81:[.19444,.68333,.09403,0],82:[0,.68333,.03868,0],83:[0,.68333,.11972,0],84:[0,.68333,.13305,0],85:[0,.68333,.16389,0],86:[0,.68333,.18361,0],87:[0,.68333,.18361,0],88:[0,.68333,.15806,0],89:[0,.68333,.19383,0],90:[0,.68333,.14528,0],91:[.25,.75,.1875,0],93:[.25,.75,.10528,0],94:[0,.69444,.06646,0],95:[.31,.12056,.09208,0],97:[0,.43056,.07671,0],98:[0,.69444,.06312,0],99:[0,.43056,.05653,0],100:[0,.69444,.10333,0],101:[0,.43056,.07514,0],102:[.19444,.69444,.21194,0],103:[.19444,.43056,.08847,0],104:[0,.69444,.07671,0],105:[0,.65536,.1019,0],106:[.19444,.65536,.14467,0],107:[0,.69444,.10764,0],108:[0,.69444,.10333,0],109:[0,.43056,.07671,0],110:[0,.43056,.07671,0],111:[0,.43056,.06312,0],112:[.19444,.43056,.06312,0],113:[.19444,.43056,.08847,0],114:[0,.43056,.10764,0],115:[0,.43056,.08208,0],116:[0,.61508,.09486,0],117:[0,.43056,.07671,0],118:[0,.43056,.10764,0],119:[0,.43056,.10764,0],120:[0,.43056,.12042,0],121:[.19444,.43056,.08847,0],122:[0,.43056,.12292,0],126:[.35,.31786,.11585,0],163:[0,.69444,0,0],305:[0,.43056,0,.02778],567:[.19444,.43056,0,.08334],768:[0,.69444,0,0],769:[0,.69444,.09694,0],770:[0,.69444,.06646,0],771:[0,.66786,.11585,0],772:[0,.56167,.10333,0],774:[0,.69444,.10806,0],775:[0,.66786,.11752,0],776:[0,.66786,.10474,0],778:[0,.69444,0,0],779:[0,.69444,.1225,0],780:[0,.62847,.08295,0],915:[0,.68333,.13305,0],916:[0,.68333,0,0],920:[0,.68333,.09403,0],923:[0,.68333,0,0],926:[0,.68333,.15294,0],928:[0,.68333,.16389,0],931:[0,.68333,.12028,0],933:[0,.68333,.11111,0],934:[0,.68333,.05986,0],936:[0,.68333,.11111,0],937:[0,.68333,.10257,0],8211:[0,.43056,.09208,0],8212:[0,.43056,.09208,0],8216:[0,.69444,.12417,0],8217:[0,.69444,.12417,0],8220:[0,.69444,.1685,0],8221:[0,.69444,.06961,0],8463:[0,.68889,0,0]},"Main-Regular":{32:[0,0,0,0],33:[0,.69444,0,0],34:[0,.69444,0,0],35:[.19444,.69444,0,0],36:[.05556,.75,0,0],37:[.05556,.75,0,0],38:[0,.69444,0,0],39:[0,.69444,0,0],40:[.25,.75,0,0],41:[.25,.75,0,0],42:[0,.75,0,0],43:[.08333,.58333,0,0],44:[.19444,.10556,0,0],45:[0,.43056,0,0],46:[0,.10556,0,0],47:[.25,.75,0,0],48:[0,.64444,0,0],49:[0,.64444,0,0],50:[0,.64444,0,0],51:[0,.64444,0,0],52:[0,.64444,0,0],53:[0,.64444,0,0],54:[0,.64444,0,0],55:[0,.64444,0,0],56:[0,.64444,0,0],57:[0,.64444,0,0],58:[0,.43056,0,0],59:[.19444,.43056,0,0],60:[.0391,.5391,0,0],61:[-.13313,.36687,0,0],62:[.0391,.5391,0,0],63:[0,.69444,0,0],64:[0,.69444,0,0],65:[0,.68333,0,0],66:[0,.68333,0,0],67:[0,.68333,0,0],68:[0,.68333,0,0],69:[0,.68333,0,0],70:[0,.68333,0,0],71:[0,.68333,0,0],72:[0,.68333,0,0],73:[0,.68333,0,0],74:[0,.68333,0,0],75:[0,.68333,0,0],76:[0,.68333,0,0],77:[0,.68333,0,0],78:[0,.68333,0,0],79:[0,.68333,0,0],80:[0,.68333,0,0],81:[.19444,.68333,0,0],82:[0,.68333,0,0],83:[0,.68333,0,0],84:[0,.68333,0,0],85:[0,.68333,0,0],86:[0,.68333,.01389,0],87:[0,.68333,.01389,0],88:[0,.68333,0,0],89:[0,.68333,.025,0],90:[0,.68333,0,0],91:[.25,.75,0,0],92:[.25,.75,0,0],93:[.25,.75,0,0],94:[0,.69444,0,0],95:[.31,.12056,.02778,0],96:[0,.69444,0,0],97:[0,.43056,0,0],98:[0,.69444,0,0],99:[0,.43056,0,0],100:[0,.69444,0,0],101:[0,.43056,0,0],102:[0,.69444,.07778,0],103:[.19444,.43056,.01389,0],104:[0,.69444,0,0],105:[0,.66786,0,0],106:[.19444,.66786,0,0],107:[0,.69444,0,0],108:[0,.69444,0,0],109:[0,.43056,0,0],110:[0,.43056,0,0],111:[0,.43056,0,0],112:[.19444,.43056,0,0],113:[.19444,.43056,0,0],114:[0,.43056,0,0],115:[0,.43056,0,0],116:[0,.61508,0,0],117:[0,.43056,0,0],118:[0,.43056,.01389,0],119:[0,.43056,.01389,0],120:[0,.43056,0,0],121:[.19444,.43056,.01389,0],122:[0,.43056,0,0],123:[.25,.75,0,0],124:[.25,.75,0,0],125:[.25,.75,0,0],126:[.35,.31786,0,0],160:[0,0,0,0],168:[0,.66786,0,0],172:[0,.43056,0,0],175:[0,.56778,0,0],176:[0,.69444,0,0],177:[.08333,.58333,0,0],180:[0,.69444,0,0],215:[.08333,.58333,0,0],247:[.08333,.58333,0,0],305:[0,.43056,0,0],567:[.19444,.43056,0,0],710:[0,.69444,0,0],711:[0,.62847,0,0],713:[0,.56778,0,0],714:[0,.69444,0,0],715:[0,.69444,0,0],728:[0,.69444,0,0],729:[0,.66786,0,0],730:[0,.69444,0,0],732:[0,.66786,0,0],768:[0,.69444,0,0],769:[0,.69444,0,0],770:[0,.69444,0,0],771:[0,.66786,0,0],772:[0,.56778,0,0],774:[0,.69444,0,0],775:[0,.66786,0,0],776:[0,.66786,0,0],778:[0,.69444,0,0],779:[0,.69444,0,0],780:[0,.62847,0,0],824:[.19444,.69444,0,0],915:[0,.68333,0,0],916:[0,.68333,0,0],920:[0,.68333,0,0],923:[0,.68333,0,0],926:[0,.68333,0,0],928:[0,.68333,0,0],931:[0,.68333,0,0],933:[0,.68333,0,0],934:[0,.68333,0,0],936:[0,.68333,0,0],937:[0,.68333,0,0],8211:[0,.43056,.02778,0],8212:[0,.43056,.02778,0],8216:[0,.69444,0,0],8217:[0,.69444,0,0],8220:[0,.69444,0,0],8221:[0,.69444,0,0],8224:[.19444,.69444,0,0],8225:[.19444,.69444,0,0],8230:[0,.12,0,0],8242:[0,.55556,0,0],8407:[0,.71444,.15382,0],8463:[0,.68889,0,0],8465:[0,.69444,0,0],8467:[0,.69444,0,.11111],8472:[.19444,.43056,0,.11111],8476:[0,.69444,0,0],8501:[0,.69444,0,0],8592:[-.13313,.36687,0,0],8593:[.19444,.69444,0,0],8594:[-.13313,.36687,0,0],8595:[.19444,.69444,0,0],8596:[-.13313,.36687,0,0],8597:[.25,.75,0,0],8598:[.19444,.69444,0,0],8599:[.19444,.69444,0,0],8600:[.19444,.69444,0,0],8601:[.19444,.69444,0,0],8614:[.011,.511,0,0],8617:[.011,.511,0,0],8618:[.011,.511,0,0],8636:[-.13313,.36687,0,0],8637:[-.13313,.36687,0,0],8640:[-.13313,.36687,0,0],8641:[-.13313,.36687,0,0],8652:[.011,.671,0,0],8656:[-.13313,.36687,0,0],8657:[.19444,.69444,0,0],8658:[-.13313,.36687,0,0],8659:[.19444,.69444,0,0],8660:[-.13313,.36687,0,0],8661:[.25,.75,0,0],8704:[0,.69444,0,0],8706:[0,.69444,.05556,.08334],8707:[0,.69444,0,0],8709:[.05556,.75,0,0],8711:[0,.68333,0,0],8712:[.0391,.5391,0,0],8715:[.0391,.5391,0,0],8722:[.08333,.58333,0,0],8723:[.08333,.58333,0,0],8725:[.25,.75,0,0],8726:[.25,.75,0,0],8727:[-.03472,.46528,0,0],8728:[-.05555,.44445,0,0],8729:[-.05555,.44445,0,0],8730:[.2,.8,0,0],8733:[0,.43056,0,0],8734:[0,.43056,0,0],8736:[0,.69224,0,0],8739:[.25,.75,0,0],8741:[.25,.75,0,0],8743:[0,.55556,0,0],8744:[0,.55556,0,0],8745:[0,.55556,0,0],8746:[0,.55556,0,0],8747:[.19444,.69444,.11111,0],8764:[-.13313,.36687,0,0],8768:[.19444,.69444,0,0],8771:[-.03625,.46375,0,0],8773:[-.022,.589,0,0],8776:[-.01688,.48312,0,0],8781:[-.03625,.46375,0,0],8784:[-.133,.67,0,0],8800:[.215,.716,0,0],8801:[-.03625,.46375,0,0],8804:[.13597,.63597,0,0],8805:[.13597,.63597,0,0],8810:[.0391,.5391,0,0],8811:[.0391,.5391,0,0],8826:[.0391,.5391,0,0],8827:[.0391,.5391,0,0],8834:[.0391,.5391,0,0],8835:[.0391,.5391,0,0],8838:[.13597,.63597,0,0],8839:[.13597,.63597,0,0],8846:[0,.55556,0,0],8849:[.13597,.63597,0,0],8850:[.13597,.63597,0,0],8851:[0,.55556,0,0],8852:[0,.55556,0,0],8853:[.08333,.58333,0,0],8854:[.08333,.58333,0,0],8855:[.08333,.58333,0,0],8856:[.08333,.58333,0,0],8857:[.08333,.58333,0,0],8866:[0,.69444,0,0],8867:[0,.69444,0,0],8868:[0,.69444,0,0],8869:[0,.69444,0,0],8872:[.249,.75,0,0],8900:[-.05555,.44445,0,0],8901:[-.05555,.44445,0,0],8902:[-.03472,.46528,0,0],8904:[.005,.505,0,0],8942:[.03,.9,0,0],8943:[-.19,.31,0,0],8945:[-.1,.82,0,0],8968:[.25,.75,0,0],8969:[.25,.75,0,0],8970:[.25,.75,0,0],8971:[.25,.75,0,0],8994:[-.14236,.35764,0,0],8995:[-.14236,.35764,0,0],9136:[.244,.744,0,0],9137:[.244,.744,0,0],9651:[.19444,.69444,0,0],9657:[-.03472,.46528,0,0],9661:[.19444,.69444,0,0],9667:[-.03472,.46528,0,0],9711:[.19444,.69444,0,0],9824:[.12963,.69444,0,0],9825:[.12963,.69444,0,0],9826:[.12963,.69444,0,0],9827:[.12963,.69444,0,0],9837:[0,.75,0,0],9838:[.19444,.69444,0,0],9839:[.19444,.69444,0,0],10216:[.25,.75,0,0],10217:[.25,.75,0,0],10222:[.244,.744,0,0],10223:[.244,.744,0,0],10229:[.011,.511,0,0],10230:[.011,.511,0,0],10231:[.011,.511,0,0],10232:[.024,.525,0,0],10233:[.024,.525,0,0],10234:[.024,.525,0,0],10236:[.011,.511,0,0],10815:[0,.68333,0,0],10927:[.13597,.63597,0,0],10928:[.13597,.63597,0,0]},"Math-BoldItalic":{47:[.19444,.69444,0,0],65:[0,.68611,0,0],66:[0,.68611,.04835,0],67:[0,.68611,.06979,0],68:[0,.68611,.03194,0],69:[0,.68611,.05451,0],70:[0,.68611,.15972,0],71:[0,.68611,0,0],72:[0,.68611,.08229,0],73:[0,.68611,.07778,0],74:[0,.68611,.10069,0],75:[0,.68611,.06979,0],76:[0,.68611,0,0],77:[0,.68611,.11424,0],78:[0,.68611,.11424,0],79:[0,.68611,.03194,0],80:[0,.68611,.15972,0],81:[.19444,.68611,0,0],82:[0,.68611,.00421,0],83:[0,.68611,.05382,0],84:[0,.68611,.15972,0],85:[0,.68611,.11424,0],86:[0,.68611,.25555,0],87:[0,.68611,.15972,0],88:[0,.68611,.07778,0],89:[0,.68611,.25555,0],90:[0,.68611,.06979,0],97:[0,.44444,0,0],98:[0,.69444,0,0],99:[0,.44444,0,0],100:[0,.69444,0,0],101:[0,.44444,0,0],102:[.19444,.69444,.11042,0],103:[.19444,.44444,.03704,0],104:[0,.69444,0,0],105:[0,.69326,0,0],106:[.19444,.69326,.0622,0],107:[0,.69444,.01852,0],108:[0,.69444,.0088,0],109:[0,.44444,0,0],110:[0,.44444,0,0],111:[0,.44444,0,0],112:[.19444,.44444,0,0],113:[.19444,.44444,.03704,0],114:[0,.44444,.03194,0],115:[0,.44444,0,0],116:[0,.63492,0,0],117:[0,.44444,0,0],118:[0,.44444,.03704,0],119:[0,.44444,.02778,0],120:[0,.44444,0,0],121:[.19444,.44444,.03704,0],122:[0,.44444,.04213,0],915:[0,.68611,.15972,0],916:[0,.68611,0,0],920:[0,.68611,.03194,0],923:[0,.68611,0,0],926:[0,.68611,.07458,0],928:[0,.68611,.08229,0],931:[0,.68611,.05451,0],933:[0,.68611,.15972,0],934:[0,.68611,0,0],936:[0,.68611,.11653,0],937:[0,.68611,.04835,0],945:[0,.44444,0,0],946:[.19444,.69444,.03403,0],947:[.19444,.44444,.06389,0],948:[0,.69444,.03819,0],949:[0,.44444,0,0],950:[.19444,.69444,.06215,0],951:[.19444,.44444,.03704,0],952:[0,.69444,.03194,0],953:[0,.44444,0,0],954:[0,.44444,0,0],955:[0,.69444,0,0],956:[.19444,.44444,0,0],957:[0,.44444,.06898,0],958:[.19444,.69444,.03021,0],959:[0,.44444,0,0],960:[0,.44444,.03704,0],961:[.19444,.44444,0,0],962:[.09722,.44444,.07917,0],963:[0,.44444,.03704,0],964:[0,.44444,.13472,0],965:[0,.44444,.03704,0],966:[.19444,.44444,0,0],967:[.19444,.44444,0,0],968:[.19444,.69444,.03704,0],969:[0,.44444,.03704,0],977:[0,.69444,0,0],981:[.19444,.69444,0,0],982:[0,.44444,.03194,0],1009:[.19444,.44444,0,0],1013:[0,.44444,0,0]},"Math-Italic":{47:[.19444,.69444,0,0],65:[0,.68333,0,.13889],66:[0,.68333,.05017,.08334],67:[0,.68333,.07153,.08334],68:[0,.68333,.02778,.05556],69:[0,.68333,.05764,.08334],70:[0,.68333,.13889,.08334],71:[0,.68333,0,.08334],72:[0,.68333,.08125,.05556],73:[0,.68333,.07847,.11111],74:[0,.68333,.09618,.16667],75:[0,.68333,.07153,.05556],76:[0,.68333,0,.02778],77:[0,.68333,.10903,.08334],78:[0,.68333,.10903,.08334],79:[0,.68333,.02778,.08334],80:[0,.68333,.13889,.08334],81:[.19444,.68333,0,.08334],82:[0,.68333,.00773,.08334],83:[0,.68333,.05764,.08334],84:[0,.68333,.13889,.08334],85:[0,.68333,.10903,.02778],86:[0,.68333,.22222,0],87:[0,.68333,.13889,0],88:[0,.68333,.07847,.08334],89:[0,.68333,.22222,0],90:[0,.68333,.07153,.08334],97:[0,.43056,0,0],98:[0,.69444,0,0],99:[0,.43056,0,.05556],100:[0,.69444,0,.16667],101:[0,.43056,0,.05556],102:[.19444,.69444,.10764,.16667],103:[.19444,.43056,.03588,.02778],104:[0,.69444,0,0],105:[0,.65952,0,0],106:[.19444,.65952,.05724,0],107:[0,.69444,.03148,0],108:[0,.69444,.01968,.08334],109:[0,.43056,0,0],110:[0,.43056,0,0],111:[0,.43056,0,.05556],112:[.19444,.43056,0,.08334],113:[.19444,.43056,.03588,.08334],114:[0,.43056,.02778,.05556],115:[0,.43056,0,.05556],116:[0,.61508,0,.08334],117:[0,.43056,0,.02778],118:[0,.43056,.03588,.02778],119:[0,.43056,.02691,.08334],120:[0,.43056,0,.02778],121:[.19444,.43056,.03588,.05556],122:[0,.43056,.04398,.05556],915:[0,.68333,.13889,.08334],916:[0,.68333,0,.16667],920:[0,.68333,.02778,.08334],923:[0,.68333,0,.16667],926:[0,.68333,.07569,.08334],928:[0,.68333,.08125,.05556],931:[0,.68333,.05764,.08334],933:[0,.68333,.13889,.05556],934:[0,.68333,0,.08334],936:[0,.68333,.11,.05556],937:[0,.68333,.05017,.08334],945:[0,.43056,.0037,.02778],946:[.19444,.69444,.05278,.08334],947:[.19444,.43056,.05556,0],948:[0,.69444,.03785,.05556],949:[0,.43056,0,.08334],950:[.19444,.69444,.07378,.08334],951:[.19444,.43056,.03588,.05556],952:[0,.69444,.02778,.08334],953:[0,.43056,0,.05556],954:[0,.43056,0,0],955:[0,.69444,0,0],956:[.19444,.43056,0,.02778],957:[0,.43056,.06366,.02778],958:[.19444,.69444,.04601,.11111],959:[0,.43056,0,.05556],960:[0,.43056,.03588,0],961:[.19444,.43056,0,.08334],962:[.09722,.43056,.07986,.08334],963:[0,.43056,.03588,0],964:[0,.43056,.1132,.02778],965:[0,.43056,.03588,.02778],966:[.19444,.43056,0,.08334],967:[.19444,.43056,0,.05556],968:[.19444,.69444,.03588,.11111],969:[0,.43056,.03588,0],977:[0,.69444,0,.08334],981:[.19444,.69444,0,.08334],982:[0,.43056,.02778,0],1009:[.19444,.43056,0,.08334],1013:[0,.43056,0,.05556]},"Math-Regular":{65:[0,.68333,0,.13889],66:[0,.68333,.05017,.08334],67:[0,.68333,.07153,.08334],68:[0,.68333,.02778,.05556],69:[0,.68333,.05764,.08334],70:[0,.68333,.13889,.08334],71:[0,.68333,0,.08334],72:[0,.68333,.08125,.05556],73:[0,.68333,.07847,.11111],74:[0,.68333,.09618,.16667],75:[0,.68333,.07153,.05556],76:[0,.68333,0,.02778],77:[0,.68333,.10903,.08334],78:[0,.68333,.10903,.08334],79:[0,.68333,.02778,.08334],80:[0,.68333,.13889,.08334],81:[.19444,.68333,0,.08334],82:[0,.68333,.00773,.08334],83:[0,.68333,.05764,.08334],84:[0,.68333,.13889,.08334],85:[0,.68333,.10903,.02778],86:[0,.68333,.22222,0],87:[0,.68333,.13889,0],88:[0,.68333,.07847,.08334],89:[0,.68333,.22222,0],90:[0,.68333,.07153,.08334],97:[0,.43056,0,0],98:[0,.69444,0,0],99:[0,.43056,0,.05556],100:[0,.69444,0,.16667],101:[0,.43056,0,.05556],102:[.19444,.69444,.10764,.16667],103:[.19444,.43056,.03588,.02778],104:[0,.69444,0,0],105:[0,.65952,0,0],106:[.19444,.65952,.05724,0],107:[0,.69444,.03148,0],108:[0,.69444,.01968,.08334],109:[0,.43056,0,0],110:[0,.43056,0,0],111:[0,.43056,0,.05556],112:[.19444,.43056,0,.08334],113:[.19444,.43056,.03588,.08334],114:[0,.43056,.02778,.05556],115:[0,.43056,0,.05556],116:[0,.61508,0,.08334],117:[0,.43056,0,.02778],118:[0,.43056,.03588,.02778],119:[0,.43056,.02691,.08334],120:[0,.43056,0,.02778],121:[.19444,.43056,.03588,.05556],122:[0,.43056,.04398,.05556],915:[0,.68333,.13889,.08334],916:[0,.68333,0,.16667],920:[0,.68333,.02778,.08334],923:[0,.68333,0,.16667],926:[0,.68333,.07569,.08334],928:[0,.68333,.08125,.05556],931:[0,.68333,.05764,.08334],933:[0,.68333,.13889,.05556],934:[0,.68333,0,.08334],936:[0,.68333,.11,.05556],937:[0,.68333,.05017,.08334],945:[0,.43056,.0037,.02778],946:[.19444,.69444,.05278,.08334],947:[.19444,.43056,.05556,0],948:[0,.69444,.03785,.05556],949:[0,.43056,0,.08334],950:[.19444,.69444,.07378,.08334],951:[.19444,.43056,.03588,.05556],952:[0,.69444,.02778,.08334],953:[0,.43056,0,.05556],954:[0,.43056,0,0],955:[0,.69444,0,0],956:[.19444,.43056,0,.02778],957:[0,.43056,.06366,.02778],958:[.19444,.69444,.04601,.11111],959:[0,.43056,0,.05556],960:[0,.43056,.03588,0],961:[.19444,.43056,0,.08334],962:[.09722,.43056,.07986,.08334],963:[0,.43056,.03588,0],964:[0,.43056,.1132,.02778],965:[0,.43056,.03588,.02778],966:[.19444,.43056,0,.08334],967:[.19444,.43056,0,.05556],968:[.19444,.69444,.03588,.11111],969:[0,.43056,.03588,0],977:[0,.69444,0,.08334],981:[.19444,.69444,0,.08334],982:[0,.43056,.02778,0],1009:[.19444,.43056,0,.08334],1013:[0,.43056,0,.05556]},"SansSerif-Regular":{33:[0,.69444,0,0],34:[0,.69444,0,0],35:[.19444,.69444,0,0],36:[.05556,.75,0,0],37:[.05556,.75,0,0],38:[0,.69444,0,0],39:[0,.69444,0,0],40:[.25,.75,0,0],41:[.25,.75,0,0],42:[0,.75,0,0],43:[.08333,.58333,0,0],44:[.125,.08333,0,0],45:[0,.44444,0,0],46:[0,.08333,0,0],47:[.25,.75,0,0],48:[0,.65556,0,0],49:[0,.65556,0,0],50:[0,.65556,0,0],51:[0,.65556,0,0],52:[0,.65556,0,0],53:[0,.65556,0,0],54:[0,.65556,0,0],55:[0,.65556,0,0],56:[0,.65556,0,0],57:[0,.65556,0,0],58:[0,.44444,0,0],59:[.125,.44444,0,0],61:[-.13,.37,0,0],63:[0,.69444,0,0],64:[0,.69444,0,0],65:[0,.69444,0,0],66:[0,.69444,0,0],67:[0,.69444,0,0],68:[0,.69444,0,0],69:[0,.69444,0,0],70:[0,.69444,0,0],71:[0,.69444,0,0],72:[0,.69444,0,0],73:[0,.69444,0,0],74:[0,.69444,0,0],75:[0,.69444,0,0],76:[0,.69444,0,0],77:[0,.69444,0,0],78:[0,.69444,0,0],79:[0,.69444,0,0],80:[0,.69444,0,0],81:[.125,.69444,0,0],82:[0,.69444,0,0],83:[0,.69444,0,0],84:[0,.69444,0,0],85:[0,.69444,0,0],86:[0,.69444,.01389,0],87:[0,.69444,.01389,0],88:[0,.69444,0,0],89:[0,.69444,.025,0],90:[0,.69444,0,0],91:[.25,.75,0,0],93:[.25,.75,0,0],94:[0,.69444,0,0],95:[.35,.09444,.02778,0],97:[0,.44444,0,0],98:[0,.69444,0,0],99:[0,.44444,0,0],100:[0,.69444,0,0],101:[0,.44444,0,0],102:[0,.69444,.06944,0],103:[.19444,.44444,.01389,0],104:[0,.69444,0,0],105:[0,.67937,0,0],106:[.19444,.67937,0,0],107:[0,.69444,0,0],108:[0,.69444,0,0],109:[0,.44444,0,0],110:[0,.44444,0,0],111:[0,.44444,0,0],112:[.19444,.44444,0,0],113:[.19444,.44444,0,0],114:[0,.44444,.01389,0],115:[0,.44444,0,0],116:[0,.57143,0,0],117:[0,.44444,0,0],118:[0,.44444,.01389,0],119:[0,.44444,.01389,0],120:[0,.44444,0,0],121:[.19444,.44444,.01389,0],122:[0,.44444,0,0],126:[.35,.32659,0,0],305:[0,.44444,0,0],567:[.19444,.44444,0,0],768:[0,.69444,0,0],769:[0,.69444,0,0],770:[0,.69444,0,0],771:[0,.67659,0,0],772:[0,.60889,0,0],774:[0,.69444,0,0],775:[0,.67937,0,0],776:[0,.67937,0,0],778:[0,.69444,0,0],779:[0,.69444,0,0],780:[0,.63194,0,0],915:[0,.69444,0,0],916:[0,.69444,0,0],920:[0,.69444,0,0],923:[0,.69444,0,0],926:[0,.69444,0,0],928:[0,.69444,0,0],931:[0,.69444,0,0],933:[0,.69444,0,0],934:[0,.69444,0,0],936:[0,.69444,0,0],937:[0,.69444,0,0],8211:[0,.44444,.02778,0],8212:[0,.44444,.02778,0],8216:[0,.69444,0,0],8217:[0,.69444,0,0],8220:[0,.69444,0,0],8221:[0,.69444,0,0]},"Script-Regular":{65:[0,.7,.22925,0],66:[0,.7,.04087,0],67:[0,.7,.1689,0],68:[0,.7,.09371,0],69:[0,.7,.18583,0],70:[0,.7,.13634,0],71:[0,.7,.17322,0],72:[0,.7,.29694,0],73:[0,.7,.19189,0],74:[.27778,.7,.19189,0],75:[0,.7,.31259,0],76:[0,.7,.19189,0],77:[0,.7,.15981,0],78:[0,.7,.3525,0],79:[0,.7,.08078,0],80:[0,.7,.08078,0],81:[0,.7,.03305,0],82:[0,.7,.06259,0],83:[0,.7,.19189,0],84:[0,.7,.29087,0],85:[0,.7,.25815,0],86:[0,.7,.27523,0],87:[0,.7,.27523,0],88:[0,.7,.26006,0],89:[0,.7,.2939,0],90:[0,.7,.24037,0]},"Size1-Regular":{40:[.35001,.85,0,0],41:[.35001,.85,0,0],47:[.35001,.85,0,0],91:[.35001,.85,0,0],92:[.35001,.85,0,0],93:[.35001,.85,0,0],123:[.35001,.85,0,0],125:[.35001,.85,0,0],710:[0,.72222,0,0],732:[0,.72222,0,0],770:[0,.72222,0,0],771:[0,.72222,0,0],8214:[-99e-5,.601,0,0],8593:[1e-5,.6,0,0],8595:[1e-5,.6,0,0],8657:[1e-5,.6,0,0],8659:[1e-5,.6,0,0],8719:[.25001,.75,0,0],8720:[.25001,.75,0,0],8721:[.25001,.75,0,0],8730:[.35001,.85,0,0],8739:[-.00599,.606,0,0],8741:[-.00599,.606,0,0],8747:[.30612,.805,.19445,0],8748:[.306,.805,.19445,0],8749:[.306,.805,.19445,0],8750:[.30612,.805,.19445,0],8896:[.25001,.75,0,0],8897:[.25001,.75,0,0],8898:[.25001,.75,0,0],8899:[.25001,.75,0,0],8968:[.35001,.85,0,0],8969:[.35001,.85,0,0],8970:[.35001,.85,0,0],8971:[.35001,.85,0,0],9168:[-99e-5,.601,0,0],10216:[.35001,.85,0,0],10217:[.35001,.85,0,0],10752:[.25001,.75,0,0],10753:[.25001,.75,0,0],10754:[.25001,.75,0,0],10756:[.25001,.75,0,0],10758:[.25001,.75,0,0]},"Size2-Regular":{40:[.65002,1.15,0,0],41:[.65002,1.15,0,0],47:[.65002,1.15,0,0],91:[.65002,1.15,0,0],92:[.65002,1.15,0,0],93:[.65002,1.15,0,0],123:[.65002,1.15,0,0],125:[.65002,1.15,0,0],710:[0,.75,0,0],732:[0,.75,0,0],770:[0,.75,0,0],771:[0,.75,0,0],8719:[.55001,1.05,0,0],8720:[.55001,1.05,0,0],8721:[.55001,1.05,0,0],8730:[.65002,1.15,0,0],8747:[.86225,1.36,.44445,0],8748:[.862,1.36,.44445,0],8749:[.862,1.36,.44445,0],8750:[.86225,1.36,.44445,0],8896:[.55001,1.05,0,0],8897:[.55001,1.05,0,0],8898:[.55001,1.05,0,0],8899:[.55001,1.05,0,0],8968:[.65002,1.15,0,0],8969:[.65002,1.15,0,0],8970:[.65002,1.15,0,0],8971:[.65002,1.15,0,0],10216:[.65002,1.15,0,0],10217:[.65002,1.15,0,0],10752:[.55001,1.05,0,0],10753:[.55001,1.05,0,0],10754:[.55001,1.05,0,0],
+10756:[.55001,1.05,0,0],10758:[.55001,1.05,0,0]},"Size3-Regular":{40:[.95003,1.45,0,0],41:[.95003,1.45,0,0],47:[.95003,1.45,0,0],91:[.95003,1.45,0,0],92:[.95003,1.45,0,0],93:[.95003,1.45,0,0],123:[.95003,1.45,0,0],125:[.95003,1.45,0,0],710:[0,.75,0,0],732:[0,.75,0,0],770:[0,.75,0,0],771:[0,.75,0,0],8730:[.95003,1.45,0,0],8968:[.95003,1.45,0,0],8969:[.95003,1.45,0,0],8970:[.95003,1.45,0,0],8971:[.95003,1.45,0,0],10216:[.95003,1.45,0,0],10217:[.95003,1.45,0,0]},"Size4-Regular":{40:[1.25003,1.75,0,0],41:[1.25003,1.75,0,0],47:[1.25003,1.75,0,0],91:[1.25003,1.75,0,0],92:[1.25003,1.75,0,0],93:[1.25003,1.75,0,0],123:[1.25003,1.75,0,0],125:[1.25003,1.75,0,0],710:[0,.825,0,0],732:[0,.825,0,0],770:[0,.825,0,0],771:[0,.825,0,0],8730:[1.25003,1.75,0,0],8968:[1.25003,1.75,0,0],8969:[1.25003,1.75,0,0],8970:[1.25003,1.75,0,0],8971:[1.25003,1.75,0,0],9115:[.64502,1.155,0,0],9116:[1e-5,.6,0,0],9117:[.64502,1.155,0,0],9118:[.64502,1.155,0,0],9119:[1e-5,.6,0,0],9120:[.64502,1.155,0,0],9121:[.64502,1.155,0,0],9122:[-99e-5,.601,0,0],9123:[.64502,1.155,0,0],9124:[.64502,1.155,0,0],9125:[-99e-5,.601,0,0],9126:[.64502,1.155,0,0],9127:[1e-5,.9,0,0],9128:[.65002,1.15,0,0],9129:[.90001,0,0,0],9130:[0,.3,0,0],9131:[1e-5,.9,0,0],9132:[.65002,1.15,0,0],9133:[.90001,0,0,0],9143:[.88502,.915,0,0],10216:[1.25003,1.75,0,0],10217:[1.25003,1.75,0,0],57344:[-.00499,.605,0,0],57345:[-.00499,.605,0,0],57680:[0,.12,0,0],57681:[0,.12,0,0],57682:[0,.12,0,0],57683:[0,.12,0,0]},"Typewriter-Regular":{33:[0,.61111,0,0],34:[0,.61111,0,0],35:[0,.61111,0,0],36:[.08333,.69444,0,0],37:[.08333,.69444,0,0],38:[0,.61111,0,0],39:[0,.61111,0,0],40:[.08333,.69444,0,0],41:[.08333,.69444,0,0],42:[0,.52083,0,0],43:[-.08056,.53055,0,0],44:[.13889,.125,0,0],45:[-.08056,.53055,0,0],46:[0,.125,0,0],47:[.08333,.69444,0,0],48:[0,.61111,0,0],49:[0,.61111,0,0],50:[0,.61111,0,0],51:[0,.61111,0,0],52:[0,.61111,0,0],53:[0,.61111,0,0],54:[0,.61111,0,0],55:[0,.61111,0,0],56:[0,.61111,0,0],57:[0,.61111,0,0],58:[0,.43056,0,0],59:[.13889,.43056,0,0],60:[-.05556,.55556,0,0],61:[-.19549,.41562,0,0],62:[-.05556,.55556,0,0],63:[0,.61111,0,0],64:[0,.61111,0,0],65:[0,.61111,0,0],66:[0,.61111,0,0],67:[0,.61111,0,0],68:[0,.61111,0,0],69:[0,.61111,0,0],70:[0,.61111,0,0],71:[0,.61111,0,0],72:[0,.61111,0,0],73:[0,.61111,0,0],74:[0,.61111,0,0],75:[0,.61111,0,0],76:[0,.61111,0,0],77:[0,.61111,0,0],78:[0,.61111,0,0],79:[0,.61111,0,0],80:[0,.61111,0,0],81:[.13889,.61111,0,0],82:[0,.61111,0,0],83:[0,.61111,0,0],84:[0,.61111,0,0],85:[0,.61111,0,0],86:[0,.61111,0,0],87:[0,.61111,0,0],88:[0,.61111,0,0],89:[0,.61111,0,0],90:[0,.61111,0,0],91:[.08333,.69444,0,0],92:[.08333,.69444,0,0],93:[.08333,.69444,0,0],94:[0,.61111,0,0],95:[.09514,0,0,0],96:[0,.61111,0,0],97:[0,.43056,0,0],98:[0,.61111,0,0],99:[0,.43056,0,0],100:[0,.61111,0,0],101:[0,.43056,0,0],102:[0,.61111,0,0],103:[.22222,.43056,0,0],104:[0,.61111,0,0],105:[0,.61111,0,0],106:[.22222,.61111,0,0],107:[0,.61111,0,0],108:[0,.61111,0,0],109:[0,.43056,0,0],110:[0,.43056,0,0],111:[0,.43056,0,0],112:[.22222,.43056,0,0],113:[.22222,.43056,0,0],114:[0,.43056,0,0],115:[0,.43056,0,0],116:[0,.55358,0,0],117:[0,.43056,0,0],118:[0,.43056,0,0],119:[0,.43056,0,0],120:[0,.43056,0,0],121:[.22222,.43056,0,0],122:[0,.43056,0,0],123:[.08333,.69444,0,0],124:[.08333,.69444,0,0],125:[.08333,.69444,0,0],126:[0,.61111,0,0],127:[0,.61111,0,0],305:[0,.43056,0,0],567:[.22222,.43056,0,0],768:[0,.61111,0,0],769:[0,.61111,0,0],770:[0,.61111,0,0],771:[0,.61111,0,0],772:[0,.56555,0,0],774:[0,.61111,0,0],776:[0,.61111,0,0],778:[0,.61111,0,0],780:[0,.56597,0,0],915:[0,.61111,0,0],916:[0,.61111,0,0],920:[0,.61111,0,0],923:[0,.61111,0,0],926:[0,.61111,0,0],928:[0,.61111,0,0],931:[0,.61111,0,0],933:[0,.61111,0,0],934:[0,.61111,0,0],936:[0,.61111,0,0],937:[0,.61111,0,0],2018:[0,.61111,0,0],2019:[0,.61111,0,0],8242:[0,.61111,0,0]}}},{}],19:[function(e,t,r){var a=e("./utils");var i=e("./ParseError");var n=e("./parseData");var s=n.ParseNode;function l(e,r,a){if(typeof e==="string"){e=[e]}if(typeof r==="number"){r={numArgs:r}}var i={numArgs:r.numArgs,argTypes:r.argTypes,greediness:r.greediness===undefined?1:r.greediness,allowedInText:!!r.allowedInText,numOptionalArgs:r.numOptionalArgs||0,infix:!!r.infix,handler:a};for(var n=0;n<e.length;++n){t.exports[e[n]]=i}}var o=function(e){if(e.type==="ordgroup"){return e.value}else{return[e]}};l("\\sqrt",{numArgs:1,numOptionalArgs:1},function(e,t){var r=t[0];var a=t[1];return{type:"sqrt",body:a,index:r}});var u={"\\text":undefined,"\\textrm":"mathrm","\\textsf":"mathsf","\\texttt":"mathtt","\\textnormal":"mathrm","\\textbf":"mathbf","\\textit":"textit"};l(["\\text","\\textrm","\\textsf","\\texttt","\\textnormal","\\textbf","\\textit"],{numArgs:1,argTypes:["text"],greediness:2,allowedInText:true},function(e,t){var r=t[0];return{type:"text",body:o(r),style:u[e.funcName]}});l("\\color",{numArgs:2,allowedInText:true,greediness:3,argTypes:["color","original"]},function(e,t){var r=t[0];var a=t[1];return{type:"color",color:r.value,value:o(a)}});l("\\overline",{numArgs:1},function(e,t){var r=t[0];return{type:"overline",body:r}});l("\\underline",{numArgs:1},function(e,t){var r=t[0];return{type:"underline",body:r}});l("\\rule",{numArgs:2,numOptionalArgs:1,argTypes:["size","size","size"]},function(e,t){var r=t[0];var a=t[1];var i=t[2];return{type:"rule",shift:r&&r.value,width:a.value,height:i.value}});l(["\\kern","\\mkern"],{numArgs:1,argTypes:["size"]},function(e,t){return{type:"kern",dimension:t[0].value}});l("\\KaTeX",{numArgs:0},function(e){return{type:"katex"}});l("\\phantom",{numArgs:1},function(e,t){var r=t[0];return{type:"phantom",value:o(r)}});l(["\\mathord","\\mathbin","\\mathrel","\\mathopen","\\mathclose","\\mathpunct","\\mathinner"],{numArgs:1},function(e,t){var r=t[0];return{type:"mclass",mclass:"m"+e.funcName.substr(5),value:o(r)}});l("\\stackrel",{numArgs:2},function(e,t){var r=t[0];var a=t[1];var i=new s("op",{type:"op",limits:true,alwaysHandleSupSub:true,symbol:false,value:o(a)},a.mode);var n=new s("supsub",{base:i,sup:r,sub:null},r.mode);return{type:"mclass",mclass:"mrel",value:[n]}});l("\\bmod",{numArgs:0},function(e,t){return{type:"mod",modType:"bmod",value:null}});l(["\\pod","\\pmod","\\mod"],{numArgs:1},function(e,t){var r=t[0];return{type:"mod",modType:e.funcName.substr(1),value:o(r)}});var p={"\\bigl":{mclass:"mopen",size:1},"\\Bigl":{mclass:"mopen",size:2},"\\biggl":{mclass:"mopen",size:3},"\\Biggl":{mclass:"mopen",size:4},"\\bigr":{mclass:"mclose",size:1},"\\Bigr":{mclass:"mclose",size:2},"\\biggr":{mclass:"mclose",size:3},"\\Biggr":{mclass:"mclose",size:4},"\\bigm":{mclass:"mrel",size:1},"\\Bigm":{mclass:"mrel",size:2},"\\biggm":{mclass:"mrel",size:3},"\\Biggm":{mclass:"mrel",size:4},"\\big":{mclass:"mord",size:1},"\\Big":{mclass:"mord",size:2},"\\bigg":{mclass:"mord",size:3},"\\Bigg":{mclass:"mord",size:4}};var h=["(",")","[","\\lbrack","]","\\rbrack","\\{","\\lbrace","\\}","\\rbrace","\\lfloor","\\rfloor","\\lceil","\\rceil","<",">","\\langle","\\rangle","\\lt","\\gt","\\lvert","\\rvert","\\lVert","\\rVert","\\lgroup","\\rgroup","\\lmoustache","\\rmoustache","/","\\backslash","|","\\vert","\\|","\\Vert","\\uparrow","\\Uparrow","\\downarrow","\\Downarrow","\\updownarrow","\\Updownarrow","."];var c={"\\Bbb":"\\mathbb","\\bold":"\\mathbf","\\frak":"\\mathfrak"};l(["\\blue","\\orange","\\pink","\\red","\\green","\\gray","\\purple","\\blueA","\\blueB","\\blueC","\\blueD","\\blueE","\\tealA","\\tealB","\\tealC","\\tealD","\\tealE","\\greenA","\\greenB","\\greenC","\\greenD","\\greenE","\\goldA","\\goldB","\\goldC","\\goldD","\\goldE","\\redA","\\redB","\\redC","\\redD","\\redE","\\maroonA","\\maroonB","\\maroonC","\\maroonD","\\maroonE","\\purpleA","\\purpleB","\\purpleC","\\purpleD","\\purpleE","\\mintA","\\mintB","\\mintC","\\grayA","\\grayB","\\grayC","\\grayD","\\grayE","\\grayF","\\grayG","\\grayH","\\grayI","\\kaBlue","\\kaGreen"],{numArgs:1,allowedInText:true,greediness:3},function(e,t){var r=t[0];return{type:"color",color:"katex-"+e.funcName.slice(1),value:o(r)}});l(["\\arcsin","\\arccos","\\arctan","\\arg","\\cos","\\cosh","\\cot","\\coth","\\csc","\\deg","\\dim","\\exp","\\hom","\\ker","\\lg","\\ln","\\log","\\sec","\\sin","\\sinh","\\tan","\\tanh"],{numArgs:0},function(e){return{type:"op",limits:false,symbol:false,body:e.funcName}});l(["\\det","\\gcd","\\inf","\\lim","\\liminf","\\limsup","\\max","\\min","\\Pr","\\sup"],{numArgs:0},function(e){return{type:"op",limits:true,symbol:false,body:e.funcName}});l(["\\int","\\iint","\\iiint","\\oint"],{numArgs:0},function(e){return{type:"op",limits:false,symbol:true,body:e.funcName}});l(["\\coprod","\\bigvee","\\bigwedge","\\biguplus","\\bigcap","\\bigcup","\\intop","\\prod","\\sum","\\bigotimes","\\bigoplus","\\bigodot","\\bigsqcup","\\smallint"],{numArgs:0},function(e){return{type:"op",limits:true,symbol:true,body:e.funcName}});l("\\mathop",{numArgs:1},function(e,t){var r=t[0];return{type:"op",limits:false,symbol:false,value:o(r)}});l(["\\dfrac","\\frac","\\tfrac","\\dbinom","\\binom","\\tbinom","\\\\atopfrac"],{numArgs:2,greediness:2},function(e,t){var r=t[0];var a=t[1];var i;var n=null;var s=null;var l="auto";switch(e.funcName){case"\\dfrac":case"\\frac":case"\\tfrac":i=true;break;case"\\\\atopfrac":i=false;break;case"\\dbinom":case"\\binom":case"\\tbinom":i=false;n="(";s=")";break;default:throw new Error("Unrecognized genfrac command")}switch(e.funcName){case"\\dfrac":case"\\dbinom":l="display";break;case"\\tfrac":case"\\tbinom":l="text";break}return{type:"genfrac",numer:r,denom:a,hasBarLine:i,leftDelim:n,rightDelim:s,size:l}});l(["\\llap","\\rlap"],{numArgs:1,allowedInText:true},function(e,t){var r=t[0];return{type:e.funcName.slice(1),body:r}});var m=function(e,t){if(a.contains(h,e.value)){return e}else{throw new i("Invalid delimiter: '"+e.value+"' after '"+t.funcName+"'",e)}};l(["\\bigl","\\Bigl","\\biggl","\\Biggl","\\bigr","\\Bigr","\\biggr","\\Biggr","\\bigm","\\Bigm","\\biggm","\\Biggm","\\big","\\Big","\\bigg","\\Bigg"],{numArgs:1},function(e,t){var r=m(t[0],e);return{type:"delimsizing",size:p[e.funcName].size,mclass:p[e.funcName].mclass,value:r.value}});l(["\\left","\\right"],{numArgs:1},function(e,t){var r=m(t[0],e);return{type:"leftright",value:r.value}});l("\\middle",{numArgs:1},function(e,t){var r=m(t[0],e);if(!e.parser.leftrightDepth){throw new i("\\middle without preceding \\left",r)}return{type:"middle",value:r.value}});l(["\\tiny","\\scriptsize","\\footnotesize","\\small","\\normalsize","\\large","\\Large","\\LARGE","\\huge","\\Huge"],0,null);l(["\\displaystyle","\\textstyle","\\scriptstyle","\\scriptscriptstyle"],0,null);l(["\\mathrm","\\mathit","\\mathbf","\\mathbb","\\mathcal","\\mathfrak","\\mathscr","\\mathsf","\\mathtt","\\Bbb","\\bold","\\frak"],{numArgs:1,greediness:2},function(e,t){var r=t[0];var a=e.funcName;if(a in c){a=c[a]}return{type:"font",font:a.slice(1),body:r}});l(["\\acute","\\grave","\\ddot","\\tilde","\\bar","\\breve","\\check","\\hat","\\vec","\\dot"],{numArgs:1},function(e,t){var r=t[0];return{type:"accent",accent:e.funcName,base:r}});l(["\\over","\\choose","\\atop"],{numArgs:0,infix:true},function(e){var t;switch(e.funcName){case"\\over":t="\\frac";break;case"\\choose":t="\\binom";break;case"\\atop":t="\\\\atopfrac";break;default:throw new Error("Unrecognized infix genfrac command")}return{type:"infix",replaceWith:t,token:e.token}});l(["\\\\","\\cr"],{numArgs:0,numOptionalArgs:1,argTypes:["size"]},function(e,t){var r=t[0];return{type:"cr",size:r}});l(["\\begin","\\end"],{numArgs:1,argTypes:["text"]},function(e,t){var r=t[0];if(r.type!=="ordgroup"){throw new i("Invalid environment name",r)}var a="";for(var n=0;n<r.value.length;++n){a+=r.value[n].value}return{type:"environment",name:a,nameGroup:r}})},{"./ParseError":6,"./parseData":21,"./utils":25}],20:[function(e,t,r){var a=e("./utils");function i(e,t){this.type=e;this.attributes={};this.children=t||[]}i.prototype.setAttribute=function(e,t){this.attributes[e]=t};i.prototype.toNode=function(){var e=document.createElementNS("http://www.w3.org/1998/Math/MathML",this.type);for(var t in this.attributes){if(Object.prototype.hasOwnProperty.call(this.attributes,t)){e.setAttribute(t,this.attributes[t])}}for(var r=0;r<this.children.length;r++){e.appendChild(this.children[r].toNode())}return e};i.prototype.toMarkup=function(){var e="<"+this.type;for(var t in this.attributes){if(Object.prototype.hasOwnProperty.call(this.attributes,t)){e+=" "+t+'="';e+=a.escape(this.attributes[t]);e+='"'}}e+=">";for(var r=0;r<this.children.length;r++){e+=this.children[r].toMarkup()}e+="</"+this.type+">";return e};function n(e){this.text=e}n.prototype.toNode=function(){return document.createTextNode(this.text)};n.prototype.toMarkup=function(){return a.escape(this.text)};t.exports={MathNode:i,TextNode:n}},{"./utils":25}],21:[function(e,t,r){function a(e,t,r,a,i){this.type=e;this.value=t;this.mode=r;if(a&&(!i||i.lexer===a.lexer)){this.lexer=a.lexer;this.start=a.start;this.end=(i||a).end}}t.exports={ParseNode:a}},{}],22:[function(e,t,r){var a=e("./Parser");var i=function(e,t){if(!(typeof e==="string"||e instanceof String)){throw new TypeError("KaTeX can only parse string typed expression")}var r=new a(e,t);return r.parse()};t.exports=i},{"./Parser":7}],23:[function(e,t,r){t.exports={math:{},text:{}};function a(e,r,a,i,n){t.exports[e][n]={font:r,group:a,replace:i}}var i="math";var n="text";var s="main";var l="ams";var o="accent";var u="bin";var p="close";var h="inner";var c="mathord";var m="op";var f="open";var v="punct";var d="rel";var g="spacing";var y="textord";a(i,s,d,"\u2261","\\equiv");a(i,s,d,"\u227a","\\prec");a(i,s,d,"\u227b","\\succ");a(i,s,d,"\u223c","\\sim");a(i,s,d,"\u22a5","\\perp");a(i,s,d,"\u2aaf","\\preceq");a(i,s,d,"\u2ab0","\\succeq");a(i,s,d,"\u2243","\\simeq");a(i,s,d,"\u2223","\\mid");a(i,s,d,"\u226a","\\ll");a(i,s,d,"\u226b","\\gg");a(i,s,d,"\u224d","\\asymp");a(i,s,d,"\u2225","\\parallel");a(i,s,d,"\u22c8","\\bowtie");a(i,s,d,"\u2323","\\smile");a(i,s,d,"\u2291","\\sqsubseteq");a(i,s,d,"\u2292","\\sqsupseteq");a(i,s,d,"\u2250","\\doteq");a(i,s,d,"\u2322","\\frown");a(i,s,d,"\u220b","\\ni");a(i,s,d,"\u221d","\\propto");a(i,s,d,"\u22a2","\\vdash");a(i,s,d,"\u22a3","\\dashv");a(i,s,d,"\u220b","\\owns");a(i,s,v,".","\\ldotp");a(i,s,v,"\u22c5","\\cdotp");a(i,s,y,"#","\\#");a(n,s,y,"#","\\#");a(i,s,y,"&","\\&");a(n,s,y,"&","\\&");a(i,s,y,"\u2135","\\aleph");a(i,s,y,"\u2200","\\forall");a(i,s,y,"\u210f","\\hbar");a(i,s,y,"\u2203","\\exists");a(i,s,y,"\u2207","\\nabla");a(i,s,y,"\u266d","\\flat");a(i,s,y,"\u2113","\\ell");a(i,s,y,"\u266e","\\natural");a(i,s,y,"\u2663","\\clubsuit");a(i,s,y,"\u2118","\\wp");a(i,s,y,"\u266f","\\sharp");a(i,s,y,"\u2662","\\diamondsuit");a(i,s,y,"\u211c","\\Re");a(i,s,y,"\u2661","\\heartsuit");a(i,s,y,"\u2111","\\Im");a(i,s,y,"\u2660","\\spadesuit");a(i,s,y,"\u2020","\\dag");a(i,s,y,"\u2021","\\ddag");a(i,s,p,"\u23b1","\\rmoustache");a(i,s,f,"\u23b0","\\lmoustache");a(i,s,p,"\u27ef","\\rgroup");a(i,s,f,"\u27ee","\\lgroup");a(i,s,u,"\u2213","\\mp");a(i,s,u,"\u2296","\\ominus");a(i,s,u,"\u228e","\\uplus");a(i,s,u,"\u2293","\\sqcap");a(i,s,u,"\u2217","\\ast");a(i,s,u,"\u2294","\\sqcup");a(i,s,u,"\u25ef","\\bigcirc");a(i,s,u,"\u2219","\\bullet");a(i,s,u,"\u2021","\\ddagger");a(i,s,u,"\u2240","\\wr");a(i,s,u,"\u2a3f","\\amalg");a(i,s,d,"\u27f5","\\longleftarrow");a(i,s,d,"\u21d0","\\Leftarrow");a(i,s,d,"\u27f8","\\Longleftarrow");a(i,s,d,"\u27f6","\\longrightarrow");a(i,s,d,"\u21d2","\\Rightarrow");a(i,s,d,"\u27f9","\\Longrightarrow");a(i,s,d,"\u2194","\\leftrightarrow");a(i,s,d,"\u27f7","\\longleftrightarrow");a(i,s,d,"\u21d4","\\Leftrightarrow");a(i,s,d,"\u27fa","\\Longleftrightarrow");a(i,s,d,"\u21a6","\\mapsto");a(i,s,d,"\u27fc","\\longmapsto");a(i,s,d,"\u2197","\\nearrow");a(i,s,d,"\u21a9","\\hookleftarrow");a(i,s,d,"\u21aa","\\hookrightarrow");a(i,s,d,"\u2198","\\searrow");a(i,s,d,"\u21bc","\\leftharpoonup");a(i,s,d,"\u21c0","\\rightharpoonup");a(i,s,d,"\u2199","\\swarrow");a(i,s,d,"\u21bd","\\leftharpoondown");a(i,s,d,"\u21c1","\\rightharpoondown");a(i,s,d,"\u2196","\\nwarrow");a(i,s,d,"\u21cc","\\rightleftharpoons");a(i,l,d,"\u226e","\\nless");a(i,l,d,"\ue010","\\nleqslant");a(i,l,d,"\ue011","\\nleqq");a(i,l,d,"\u2a87","\\lneq");a(i,l,d,"\u2268","\\lneqq");a(i,l,d,"\ue00c","\\lvertneqq");a(i,l,d,"\u22e6","\\lnsim");a(i,l,d,"\u2a89","\\lnapprox");a(i,l,d,"\u2280","\\nprec");a(i,l,d,"\u22e0","\\npreceq");a(i,l,d,"\u22e8","\\precnsim");a(i,l,d,"\u2ab9","\\precnapprox");a(i,l,d,"\u2241","\\nsim");a(i,l,d,"\ue006","\\nshortmid");a(i,l,d,"\u2224","\\nmid");a(i,l,d,"\u22ac","\\nvdash");a(i,l,d,"\u22ad","\\nvDash");a(i,l,d,"\u22ea","\\ntriangleleft");a(i,l,d,"\u22ec","\\ntrianglelefteq");a(i,l,d,"\u228a","\\subsetneq");a(i,l,d,"\ue01a","\\varsubsetneq");a(i,l,d,"\u2acb","\\subsetneqq");a(i,l,d,"\ue017","\\varsubsetneqq");a(i,l,d,"\u226f","\\ngtr");a(i,l,d,"\ue00f","\\ngeqslant");a(i,l,d,"\ue00e","\\ngeqq");a(i,l,d,"\u2a88","\\gneq");a(i,l,d,"\u2269","\\gneqq");a(i,l,d,"\ue00d","\\gvertneqq");a(i,l,d,"\u22e7","\\gnsim");a(i,l,d,"\u2a8a","\\gnapprox");a(i,l,d,"\u2281","\\nsucc");a(i,l,d,"\u22e1","\\nsucceq");a(i,l,d,"\u22e9","\\succnsim");a(i,l,d,"\u2aba","\\succnapprox");a(i,l,d,"\u2246","\\ncong");a(i,l,d,"\ue007","\\nshortparallel");a(i,l,d,"\u2226","\\nparallel");a(i,l,d,"\u22af","\\nVDash");a(i,l,d,"\u22eb","\\ntriangleright");a(i,l,d,"\u22ed","\\ntrianglerighteq");a(i,l,d,"\ue018","\\nsupseteqq");a(i,l,d,"\u228b","\\supsetneq");a(i,l,d,"\ue01b","\\varsupsetneq");a(i,l,d,"\u2acc","\\supsetneqq");a(i,l,d,"\ue019","\\varsupsetneqq");a(i,l,d,"\u22ae","\\nVdash");a(i,l,d,"\u2ab5","\\precneqq");a(i,l,d,"\u2ab6","\\succneqq");a(i,l,d,"\ue016","\\nsubseteqq");a(i,l,u,"\u22b4","\\unlhd");a(i,l,u,"\u22b5","\\unrhd");a(i,l,d,"\u219a","\\nleftarrow");a(i,l,d,"\u219b","\\nrightarrow");a(i,l,d,"\u21cd","\\nLeftarrow");a(i,l,d,"\u21cf","\\nRightarrow");a(i,l,d,"\u21ae","\\nleftrightarrow");a(i,l,d,"\u21ce","\\nLeftrightarrow");a(i,l,d,"\u25b3","\\vartriangle");a(i,l,y,"\u210f","\\hslash");a(i,l,y,"\u25bd","\\triangledown");a(i,l,y,"\u25ca","\\lozenge");a(i,l,y,"\u24c8","\\circledS");a(i,l,y,"\xae","\\circledR");a(i,l,y,"\u2221","\\measuredangle");a(i,l,y,"\u2204","\\nexists");a(i,l,y,"\u2127","\\mho");a(i,l,y,"\u2132","\\Finv");a(i,l,y,"\u2141","\\Game");a(i,l,y,"k","\\Bbbk");a(i,l,y,"\u2035","\\backprime");a(i,l,y,"\u25b2","\\blacktriangle");a(i,l,y,"\u25bc","\\blacktriangledown");a(i,l,y,"\u25a0","\\blacksquare");a(i,l,y,"\u29eb","\\blacklozenge");a(i,l,y,"\u2605","\\bigstar");a(i,l,y,"\u2222","\\sphericalangle");a(i,l,y,"\u2201","\\complement");a(i,l,y,"\xf0","\\eth");a(i,l,y,"\u2571","\\diagup");a(i,l,y,"\u2572","\\diagdown");a(i,l,y,"\u25a1","\\square");a(i,l,y,"\u25a1","\\Box");a(i,l,y,"\u25ca","\\Diamond");a(i,l,y,"\xa5","\\yen");a(i,l,y,"\u2713","\\checkmark");a(i,l,y,"\u2136","\\beth");a(i,l,y,"\u2138","\\daleth");a(i,l,y,"\u2137","\\gimel");a(i,l,y,"\u03dd","\\digamma");a(i,l,y,"\u03f0","\\varkappa");a(i,l,f,"\u250c","\\ulcorner");a(i,l,p,"\u2510","\\urcorner");a(i,l,f,"\u2514","\\llcorner");a(i,l,p,"\u2518","\\lrcorner");a(i,l,d,"\u2266","\\leqq");a(i,l,d,"\u2a7d","\\leqslant");a(i,l,d,"\u2a95","\\eqslantless");a(i,l,d,"\u2272","\\lesssim");a(i,l,d,"\u2a85","\\lessapprox");a(i,l,d,"\u224a","\\approxeq");a(i,l,u,"\u22d6","\\lessdot");a(i,l,d,"\u22d8","\\lll");a(i,l,d,"\u2276","\\lessgtr");a(i,l,d,"\u22da","\\lesseqgtr");a(i,l,d,"\u2a8b","\\lesseqqgtr");a(i,l,d,"\u2251","\\doteqdot");a(i,l,d,"\u2253","\\risingdotseq");a(i,l,d,"\u2252","\\fallingdotseq");a(i,l,d,"\u223d","\\backsim");a(i,l,d,"\u22cd","\\backsimeq");a(i,l,d,"\u2ac5","\\subseteqq");a(i,l,d,"\u22d0","\\Subset");a(i,l,d,"\u228f","\\sqsubset");a(i,l,d,"\u227c","\\preccurlyeq");a(i,l,d,"\u22de","\\curlyeqprec");a(i,l,d,"\u227e","\\precsim");a(i,l,d,"\u2ab7","\\precapprox");a(i,l,d,"\u22b2","\\vartriangleleft");a(i,l,d,"\u22b4","\\trianglelefteq");a(i,l,d,"\u22a8","\\vDash");a(i,l,d,"\u22aa","\\Vvdash");a(i,l,d,"\u2323","\\smallsmile");a(i,l,d,"\u2322","\\smallfrown");a(i,l,d,"\u224f","\\bumpeq");a(i,l,d,"\u224e","\\Bumpeq");a(i,l,d,"\u2267","\\geqq");a(i,l,d,"\u2a7e","\\geqslant");a(i,l,d,"\u2a96","\\eqslantgtr");a(i,l,d,"\u2273","\\gtrsim");a(i,l,d,"\u2a86","\\gtrapprox");a(i,l,u,"\u22d7","\\gtrdot");a(i,l,d,"\u22d9","\\ggg");a(i,l,d,"\u2277","\\gtrless");a(i,l,d,"\u22db","\\gtreqless");a(i,l,d,"\u2a8c","\\gtreqqless");a(i,l,d,"\u2256","\\eqcirc");a(i,l,d,"\u2257","\\circeq");a(i,l,d,"\u225c","\\triangleq");a(i,l,d,"\u223c","\\thicksim");a(i,l,d,"\u2248","\\thickapprox");a(i,l,d,"\u2ac6","\\supseteqq");a(i,l,d,"\u22d1","\\Supset");a(i,l,d,"\u2290","\\sqsupset");a(i,l,d,"\u227d","\\succcurlyeq");a(i,l,d,"\u22df","\\curlyeqsucc");a(i,l,d,"\u227f","\\succsim");a(i,l,d,"\u2ab8","\\succapprox");a(i,l,d,"\u22b3","\\vartriangleright");a(i,l,d,"\u22b5","\\trianglerighteq");a(i,l,d,"\u22a9","\\Vdash");a(i,l,d,"\u2223","\\shortmid");a(i,l,d,"\u2225","\\shortparallel");a(i,l,d,"\u226c","\\between");a(i,l,d,"\u22d4","\\pitchfork");a(i,l,d,"\u221d","\\varpropto");a(i,l,d,"\u25c0","\\blacktriangleleft");a(i,l,d,"\u2234","\\therefore");a(i,l,d,"\u220d","\\backepsilon");a(i,l,d,"\u25b6","\\blacktriangleright");a(i,l,d,"\u2235","\\because");a(i,l,d,"\u22d8","\\llless");a(i,l,d,"\u22d9","\\gggtr");a(i,l,u,"\u22b2","\\lhd");a(i,l,u,"\u22b3","\\rhd");a(i,l,d,"\u2242","\\eqsim");a(i,s,d,"\u22c8","\\Join");a(i,l,d,"\u2251","\\Doteq");a(i,l,u,"\u2214","\\dotplus");a(i,l,u,"\u2216","\\smallsetminus");a(i,l,u,"\u22d2","\\Cap");a(i,l,u,"\u22d3","\\Cup");a(i,l,u,"\u2a5e","\\doublebarwedge");a(i,l,u,"\u229f","\\boxminus");a(i,l,u,"\u229e","\\boxplus");a(i,l,u,"\u22c7","\\divideontimes");a(i,l,u,"\u22c9","\\ltimes");a(i,l,u,"\u22ca","\\rtimes");a(i,l,u,"\u22cb","\\leftthreetimes");a(i,l,u,"\u22cc","\\rightthreetimes");a(i,l,u,"\u22cf","\\curlywedge");a(i,l,u,"\u22ce","\\curlyvee");a(i,l,u,"\u229d","\\circleddash");a(i,l,u,"\u229b","\\circledast");a(i,l,u,"\u22c5","\\centerdot");a(i,l,u,"\u22ba","\\intercal");a(i,l,u,"\u22d2","\\doublecap");a(i,l,u,"\u22d3","\\doublecup");a(i,l,u,"\u22a0","\\boxtimes");a(i,l,d,"\u21e2","\\dashrightarrow");a(i,l,d,"\u21e0","\\dashleftarrow");a(i,l,d,"\u21c7","\\leftleftarrows");a(i,l,d,"\u21c6","\\leftrightarrows");a(i,l,d,"\u21da","\\Lleftarrow");a(i,l,d,"\u219e","\\twoheadleftarrow");a(i,l,d,"\u21a2","\\leftarrowtail");a(i,l,d,"\u21ab","\\looparrowleft");a(i,l,d,"\u21cb","\\leftrightharpoons");a(i,l,d,"\u21b6","\\curvearrowleft");a(i,l,d,"\u21ba","\\circlearrowleft");a(i,l,d,"\u21b0","\\Lsh");a(i,l,d,"\u21c8","\\upuparrows");a(i,l,d,"\u21bf","\\upharpoonleft");a(i,l,d,"\u21c3","\\downharpoonleft");a(i,l,d,"\u22b8","\\multimap");a(i,l,d,"\u21ad","\\leftrightsquigarrow");a(i,l,d,"\u21c9","\\rightrightarrows");a(i,l,d,"\u21c4","\\rightleftarrows");a(i,l,d,"\u21a0","\\twoheadrightarrow");a(i,l,d,"\u21a3","\\rightarrowtail");a(i,l,d,"\u21ac","\\looparrowright");a(i,l,d,"\u21b7","\\curvearrowright");a(i,l,d,"\u21bb","\\circlearrowright");a(i,l,d,"\u21b1","\\Rsh");a(i,l,d,"\u21ca","\\downdownarrows");a(i,l,d,"\u21be","\\upharpoonright");a(i,l,d,"\u21c2","\\downharpoonright");a(i,l,d,"\u21dd","\\rightsquigarrow");a(i,l,d,"\u21dd","\\leadsto");a(i,l,d,"\u21db","\\Rrightarrow");a(i,l,d,"\u21be","\\restriction");a(i,s,y,"\u2018","`");a(i,s,y,"$","\\$");a(n,s,y,"$","\\$");a(i,s,y,"%","\\%");a(n,s,y,"%","\\%");a(i,s,y,"_","\\_");a(n,s,y,"_","\\_");a(i,s,y,"\u2220","\\angle");a(i,s,y,"\u221e","\\infty");a(i,s,y,"\u2032","\\prime");a(i,s,y,"\u25b3","\\triangle");a(i,s,y,"\u0393","\\Gamma");a(i,s,y,"\u0394","\\Delta");a(i,s,y,"\u0398","\\Theta");a(i,s,y,"\u039b","\\Lambda");a(i,s,y,"\u039e","\\Xi");a(i,s,y,"\u03a0","\\Pi");a(i,s,y,"\u03a3","\\Sigma");a(i,s,y,"\u03a5","\\Upsilon");a(i,s,y,"\u03a6","\\Phi");a(i,s,y,"\u03a8","\\Psi");a(i,s,y,"\u03a9","\\Omega");a(i,s,y,"\xac","\\neg");a(i,s,y,"\xac","\\lnot");a(i,s,y,"\u22a4","\\top");a(i,s,y,"\u22a5","\\bot");a(i,s,y,"\u2205","\\emptyset");a(i,l,y,"\u2205","\\varnothing");a(i,s,c,"\u03b1","\\alpha");a(i,s,c,"\u03b2","\\beta");a(i,s,c,"\u03b3","\\gamma");a(i,s,c,"\u03b4","\\delta");a(i,s,c,"\u03f5","\\epsilon");a(i,s,c,"\u03b6","\\zeta");a(i,s,c,"\u03b7","\\eta");a(i,s,c,"\u03b8","\\theta");a(i,s,c,"\u03b9","\\iota");a(i,s,c,"\u03ba","\\kappa");a(i,s,c,"\u03bb","\\lambda");a(i,s,c,"\u03bc","\\mu");a(i,s,c,"\u03bd","\\nu");a(i,s,c,"\u03be","\\xi");a(i,s,c,"o","\\omicron");a(i,s,c,"\u03c0","\\pi");a(i,s,c,"\u03c1","\\rho");a(i,s,c,"\u03c3","\\sigma");a(i,s,c,"\u03c4","\\tau");a(i,s,c,"\u03c5","\\upsilon");a(i,s,c,"\u03d5","\\phi");a(i,s,c,"\u03c7","\\chi");a(i,s,c,"\u03c8","\\psi");a(i,s,c,"\u03c9","\\omega");a(i,s,c,"\u03b5","\\varepsilon");a(i,s,c,"\u03d1","\\vartheta");a(i,s,c,"\u03d6","\\varpi");a(i,s,c,"\u03f1","\\varrho");a(i,s,c,"\u03c2","\\varsigma");a(i,s,c,"\u03c6","\\varphi");a(i,s,u,"\u2217","*");a(i,s,u,"+","+");a(i,s,u,"\u2212","-");a(i,s,u,"\u22c5","\\cdot");a(i,s,u,"\u2218","\\circ");a(i,s,u,"\xf7","\\div");a(i,s,u,"\xb1","\\pm");a(i,s,u,"\xd7","\\times");a(i,s,u,"\u2229","\\cap");a(i,s,u,"\u222a","\\cup");a(i,s,u,"\u2216","\\setminus");a(i,s,u,"\u2227","\\land");a(i,s,u,"\u2228","\\lor");a(i,s,u,"\u2227","\\wedge");a(i,s,u,"\u2228","\\vee");a(i,s,y,"\u221a","\\surd");a(i,s,f,"(","(");a(i,s,f,"[","[");a(i,s,f,"\u27e8","\\langle");a(i,s,f,"\u2223","\\lvert");a(i,s,f,"\u2225","\\lVert");a(i,s,p,")",")");a(i,s,p,"]","]");a(i,s,p,"?","?");a(i,s,p,"!","!");a(i,s,p,"\u27e9","\\rangle");a(i,s,p,"\u2223","\\rvert");a(i,s,p,"\u2225","\\rVert");a(i,s,d,"=","=");a(i,s,d,"<","<");a(i,s,d,">",">");a(i,s,d,":",":");a(i,s,d,"\u2248","\\approx");a(i,s,d,"\u2245","\\cong");a(i,s,d,"\u2265","\\ge");a(i,s,d,"\u2265","\\geq");a(i,s,d,"\u2190","\\gets");a(i,s,d,">","\\gt");a(i,s,d,"\u2208","\\in");a(i,s,d,"\u2209","\\notin");a(i,s,d,"\u2282","\\subset");a(i,s,d,"\u2283","\\supset");a(i,s,d,"\u2286","\\subseteq");a(i,s,d,"\u2287","\\supseteq");a(i,l,d,"\u2288","\\nsubseteq");a(i,l,d,"\u2289","\\nsupseteq");a(i,s,d,"\u22a8","\\models");a(i,s,d,"\u2190","\\leftarrow");a(i,s,d,"\u2264","\\le");a(i,s,d,"\u2264","\\leq");a(i,s,d,"<","\\lt");a(i,s,d,"\u2260","\\ne");a(i,s,d,"\u2260","\\neq");a(i,s,d,"\u2192","\\rightarrow");a(i,s,d,"\u2192","\\to");a(i,l,d,"\u2271","\\ngeq");a(i,l,d,"\u2270","\\nleq");a(i,s,g,null,"\\!");a(i,s,g,"\xa0","\\ ");a(i,s,g,"\xa0","~");a(i,s,g,null,"\\,");a(i,s,g,null,"\\:");a(i,s,g,null,"\\;");a(i,s,g,null,"\\enspace");a(i,s,g,null,"\\qquad");a(i,s,g,null,"\\quad");a(i,s,g,"\xa0","\\space");a(i,s,v,",",",");a(i,s,v,";",";");a(i,s,v,":","\\colon");a(i,l,u,"\u22bc","\\barwedge");a(i,l,u,"\u22bb","\\veebar");a(i,s,u,"\u2299","\\odot");a(i,s,u,"\u2295","\\oplus");a(i,s,u,"\u2297","\\otimes");a(i,s,y,"\u2202","\\partial");a(i,s,u,"\u2298","\\oslash");a(i,l,u,"\u229a","\\circledcirc");a(i,l,u,"\u22a1","\\boxdot");a(i,s,u,"\u25b3","\\bigtriangleup");a(i,s,u,"\u25bd","\\bigtriangledown");a(i,s,u,"\u2020","\\dagger");a(i,s,u,"\u22c4","\\diamond");a(i,s,u,"\u22c6","\\star");a(i,s,u,"\u25c3","\\triangleleft");a(i,s,u,"\u25b9","\\triangleright");a(i,s,f,"{","\\{");a(n,s,y,"{","\\{");a(i,s,p,"}","\\}");a(n,s,y,"}","\\}");a(i,s,f,"{","\\lbrace");a(i,s,p,"}","\\rbrace");a(i,s,f,"[","\\lbrack");a(i,s,p,"]","\\rbrack");a(i,s,f,"\u230a","\\lfloor");a(i,s,p,"\u230b","\\rfloor");a(i,s,f,"\u2308","\\lceil");a(i,s,p,"\u2309","\\rceil");a(i,s,y,"\\","\\backslash");a(i,s,y,"\u2223","|");a(i,s,y,"\u2223","\\vert");a(i,s,y,"\u2225","\\|");a(i,s,y,"\u2225","\\Vert");a(i,s,d,"\u2191","\\uparrow");a(i,s,d,"\u21d1","\\Uparrow");a(i,s,d,"\u2193","\\downarrow");a(i,s,d,"\u21d3","\\Downarrow");a(i,s,d,"\u2195","\\updownarrow");a(i,s,d,"\u21d5","\\Updownarrow");a(i,i,m,"\u2210","\\coprod");a(i,i,m,"\u22c1","\\bigvee");a(i,i,m,"\u22c0","\\bigwedge");a(i,i,m,"\u2a04","\\biguplus");a(i,i,m,"\u22c2","\\bigcap");a(i,i,m,"\u22c3","\\bigcup");a(i,i,m,"\u222b","\\int");a(i,i,m,"\u222b","\\intop");a(i,i,m,"\u222c","\\iint");a(i,i,m,"\u222d","\\iiint");a(i,i,m,"\u220f","\\prod");a(i,i,m,"\u2211","\\sum");a(i,i,m,"\u2a02","\\bigotimes");a(i,i,m,"\u2a01","\\bigoplus");a(i,i,m,"\u2a00","\\bigodot");a(i,i,m,"\u222e","\\oint");a(i,i,m,"\u2a06","\\bigsqcup");a(i,i,m,"\u222b","\\smallint");a(n,s,h,"\u2026","\\textellipsis");a(i,s,h,"\u2026","\\mathellipsis");a(n,s,h,"\u2026","\\ldots");a(i,s,h,"\u2026","\\ldots");a(i,s,h,"\u22ef","\\cdots");a(i,s,h,"\u22f1","\\ddots");a(i,s,y,"\u22ee","\\vdots");a(i,s,o,"\xb4","\\acute");a(i,s,o,"`","\\grave");a(i,s,o,"\xa8","\\ddot");a(i,s,o,"~","\\tilde");a(i,s,o,"\xaf","\\bar");a(i,s,o,"\u02d8","\\breve");a(i,s,o,"\u02c7","\\check");a(i,s,o,"^","\\hat");a(i,s,o,"\u20d7","\\vec");a(i,s,o,"\u02d9","\\dot");a(i,s,c,"\u0131","\\imath");a(i,s,c,"\u0237","\\jmath");a(n,s,y,"\u2013","--");a(n,s,y,"\u2014","---");a(n,s,y,"\u2018","`");a(n,s,y,"\u2019","'");a(n,s,y,"\u201c","``");a(n,s,y,"\u201d","''");a(i,s,y,"\xb0","\\degree");a(n,s,y,"\xb0","\\degree");a(i,s,c,"\xa3","\\pounds");a(i,l,y,"\u2720","\\maltese");a(n,l,y,"\u2720","\\maltese");a(n,s,g,"\xa0","\\ ");a(n,s,g,"\xa0"," ");a(n,s,g,"\xa0","~");var x;var b;var w='0123456789/@."';for(x=0;x<w.length;x++){b=w.charAt(x);a(i,s,y,b,b)}var k='0123456789!@*()-=+[]";:?/.,';for(x=0;x<k.length;x++){b=k.charAt(x);a(n,s,y,b,b)}var z="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";for(x=0;x<z.length;x++){b=z.charAt(x);a(i,s,c,b,b);a(n,s,y,b,b)}for(x=192;x<=214;x++){b=String.fromCharCode(x);a(n,s,y,b,b)}for(x=216;x<=246;x++){b=String.fromCharCode(x);a(n,s,y,b,b)}for(x=248;x<=255;x++){b=String.fromCharCode(x);a(n,s,y,b,b)}for(x=1040;x<=1103;x++){b=String.fromCharCode(x);a(n,s,y,b,b)}a(n,s,y,"\u2013","\u2013");a(n,s,y,"\u2014","\u2014");a(n,s,y,"\u2018","\u2018");a(n,s,y,"\u2019","\u2019");a(n,s,y,"\u201c","\u201c");a(n,s,y,"\u201d","\u201d")},{}],24:[function(e,t,r){var a=/[\uAC00-\uD7AF]/;var i=/[\u3040-\u309F]|[\u30A0-\u30FF]|[\u4E00-\u9FAF]|[\uAC00-\uD7AF]/;t.exports={cjkRegex:i,hangulRegex:a}},{}],25:[function(e,t,r){var a=Array.prototype.indexOf;var i=function(e,t){if(e==null){return-1}if(a&&e.indexOf===a){return e.indexOf(t)}var r=0;var i=e.length;for(;r<i;r++){if(e[r]===t){return r}}return-1};var n=function(e,t){return i(e,t)!==-1};var s=function(e,t){return e===undefined?t:e};var l=/([A-Z])/g;var o=function(e){return e.replace(l,"-$1").toLowerCase()};var u={"&":"&amp;",">":"&gt;","<":"&lt;",'"':"&quot;","'":"&#x27;"};var p=/[&><"']/g;function h(e){return u[e]}function c(e){return(""+e).replace(p,h)}var m;if(typeof document!=="undefined"){var f=document.createElement("span");if("textContent"in f){m=function(e,t){e.textContent=t}}else{m=function(e,t){e.innerText=t}}}function v(e){m(e,"")}t.exports={contains:n,deflt:s,escape:c,hyphenate:o,indexOf:i,setTextContent:m,clearNode:v}},{}]},{},[1])(1)});
diff --git a/specs/2.2/pdf/OpenCL_API.pdf b/specs/2.2/pdf/OpenCL_API.pdf
new file mode 100644
index 0000000..c3fab86
--- /dev/null
+++ b/specs/2.2/pdf/OpenCL_API.pdf
Binary files differ
diff --git a/specs/2.2/pdf/OpenCL_C.pdf b/specs/2.2/pdf/OpenCL_C.pdf
new file mode 100644
index 0000000..f9956f4
--- /dev/null
+++ b/specs/2.2/pdf/OpenCL_C.pdf
Binary files differ
diff --git a/specs/2.2/pdf/OpenCL_Cxx.pdf b/specs/2.2/pdf/OpenCL_Cxx.pdf
new file mode 100644
index 0000000..4f29345
--- /dev/null
+++ b/specs/2.2/pdf/OpenCL_Cxx.pdf
Binary files differ
diff --git a/specs/2.2/pdf/OpenCL_Env.pdf b/specs/2.2/pdf/OpenCL_Env.pdf
new file mode 100644
index 0000000..687bfb1
--- /dev/null
+++ b/specs/2.2/pdf/OpenCL_Env.pdf
Binary files differ
diff --git a/specs/2.2/pdf/OpenCL_Ext.pdf b/specs/2.2/pdf/OpenCL_Ext.pdf
new file mode 100644
index 0000000..e7acd68
--- /dev/null
+++ b/specs/2.2/pdf/OpenCL_Ext.pdf
Binary files differ
diff --git a/specs/2.2/pdf/OpenCL_ICD_Installation.pdf b/specs/2.2/pdf/OpenCL_ICD_Installation.pdf
new file mode 100644
index 0000000..bb85de4
--- /dev/null
+++ b/specs/2.2/pdf/OpenCL_ICD_Installation.pdf
Binary files differ