Typo fix in reference manual's introduction.

2015-10-12  Didier Verna  <didier@didierverna.net>

	* doc/generate.cl (+introduction+): Add a missing ~ to denote a
	directive.

;;; generate.cl --- Declt reference manual generation script

;; Copyright (C) 2010-2013, 2015 Didier Verna

;; Author: Didier Verna <didier@didierverna.net>

;; This file is part of FoCus.

;; Permission to use, copy, modify, and distribute this software for any
;; purpose with or without fee is hereby granted, provided that the above
;; copyright notice and this permission notice appear in all copies.

;; THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
;; WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
;; MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
;; ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
;; WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
;; ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
;; OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

;;; Commentary:

;;; Code:

(require "asdf")

(defconstant +introduction+
  "@macro focus
@t{FoCus}
@end macro

@macro Fmt
@code{Format}
@end macro

@macro fmt
@code{format}
@end macro

@macro cl
Common-Lisp
@end macro

@macro etc
@i{etc.}
@end macro

@Fmt{} is a powerful utility in the @cl{} standard. Format strings are
written in what can be considered as a printing DSL (Domain Specific
Language). However powerful that language is though, it suffers from two
important limitations.

@enumerate
@item
It is not modifiable: only a predefined set of standard directive
characters can be used and it is not possible to alter their semantics.
@item
It is hardly extensible. The only embryonic extension mechanism
available, the @code{~/} directive, is extremely cumbersome to use. The
called function must either reside in the @code{cl-user} package, or you
must always use its fully qualified name in the format string, even if
the corresponding code lies in the appropriate package. For instance,
consider that there is a function called @code{my-format-function} in
the package named @code{:my.long.package.name}. Every time you want to
use this function, you need to write something like
@verbatim
(format t \"~/my.long.package.name:my-format-function/\" ...)
@end verbatim
which essentially makes the @code{/} directive unusable.
@end enumerate

@focus{} is a library designed to circumvent those limitations. It
allows you to customize the @fmt{} DSL by adding new directive
characters or modifying the standard ones. The semantics of these
directive characters is specified in a so-called @dfn{format table}, a
concept very close to that of readtables. @focus{} ultimately translates
into regular @fmt{} calls.

This is the @focus{} reference manual, and as such, it is not meant to be
read. It may help you find sleep in case of insomnia though.
@ifinfo
See @xref{Top, , The FoCus User Manual, focus-user},
@end ifinfo
@ifhtml
See @xref{Top, , The FoCus User Manual, user},
@end ifhtml
@ifnotinfo
@ifnothtml
@xref{Top, , , user, The FoCus User Manual},
@end ifnothtml
@end ifnotinfo
for a more human-readable guide to using @focus{}."
  "The reference manual's introductory text.")

(asdf:load-system :net.didierverna.declt)
(net.didierverna.declt:nickname-package)

;; ASDF doesn't understand my version numnbering scheme. That will change
;; soon, but in the meantime, I have to provide my version number explicitly
;; here (and so I need to load the system in order to get the VERSION
;; function).
(asdf:load-system :net.didierverna.focus)

(if (and (second sb-ext:*posix-argv*)
	 (string= (second sb-ext:*posix-argv*) "--web"))
    (declt:declt :net.didierverna.focus
		 :library-name "FoCus"
		 :texi-file "webreference.texi"
		 :info-file "focus-webreference" ; but we don't care
		 :introduction +introduction+
		 :version (net.didierverna.focus:version :long)
		 :license :bsd
		 :copyright-date "2015")
    (declt:declt :net.didierverna.focus
		 :library-name "FoCus"
		 :texi-file "reference.texi"
		 :info-file "focus-reference"
		 :introduction +introduction+
		 :version (net.didierverna.focus:version :long)
		 :license :bsd
		 :copyright-date "2015"
		 :hyperlinks t))

(uiop:quit)

;;; generate.cl ends here

;;; generate.cl --- Declt reference manual generation script

;; Copyright (C) 2010-2013, 2015 Didier Verna

;; Author: Didier Verna <didier@didierverna.net>

;; This file is part of FoCus.

;; Permission to use, copy, modify, and distribute this software for any
;; purpose with or without fee is hereby granted, provided that the above
;; copyright notice and this permission notice appear in all copies.

;; THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
;; WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
;; MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
;; ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
;; WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
;; ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
;; OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

;;; Commentary:

;;; Code:

(require "asdf")

(defconstant +introduction+
  "@macro focus
@t{FoCus}
@end macro

@macro Fmt
@code{Format}
@end macro

@macro fmt
@code{format}
@end macro

@macro cl
Common-Lisp
@end macro

@macro etc
@i{etc.}
@end macro

@Fmt{} is a powerful utility in the @cl{} standard. Format strings are
written in what can be considered as a printing DSL (Domain Specific
Language). However powerful that language is though, it suffers from two
important limitations.

@enumerate
@item
It is not modifiable: only a predefined set of standard directive
characters can be used and it is not possible to alter their semantics.
@item
It is hardly extensible. The only embryonic extension mechanism
available, the @code{/} directive, is extremely cumbersome to use. The
called function must either reside in the @code{cl-user} package, or you
must always use its fully qualified name in the format string, even if
the corresponding code lies in the appropriate package. For instance,
consider that there is a function called @code{my-format-function} in
the package named @code{:my.long.package.name}. Every time you want to
use this function, you need to write something like
@verbatim
(format t \"~/my.long.package.name:my-format-function/\" ...)
@end verbatim
which essentially makes the @code{/} directive unusable.
@end enumerate

@focus{} is a library designed to circumvent those limitations. It
allows you to customize the @fmt{} DSL by adding new directive
characters or modifying the standard ones. The semantics of these
directive characters is specified in a so-called @dfn{format table}, a
concept very close to that of readtables. @focus{} ultimately translates
into regular @fmt{} calls.

This is the @focus{} reference manual, and as such, it is not meant to be
read. It may help you find sleep in case of insomnia though.
@ifinfo
See @xref{Top, , The FoCus User Manual, focus-user},
@end ifinfo
@ifhtml
See @xref{Top, , The FoCus User Manual, user},
@end ifhtml
@ifnotinfo
@ifnothtml
@xref{Top, , , user, The FoCus User Manual},
@end ifnothtml
@end ifnotinfo
for a more human-readable guide to using @focus{}."
  "The reference manual's introductory text.")

(asdf:load-system :net.didierverna.declt)
(net.didierverna.declt:nickname-package)

;; ASDF doesn't understand my version numnbering scheme. That will change
;; soon, but in the meantime, I have to provide my version number explicitly
;; here (and so I need to load the system in order to get the VERSION
;; function).
(asdf:load-system :net.didierverna.focus)

(if (and (second sb-ext:*posix-argv*)
	 (string= (second sb-ext:*posix-argv*) "--web"))
    (declt:declt :net.didierverna.focus
		 :library-name "FoCus"
		 :texi-file "webreference.texi"
		 :info-file "focus-webreference" ; but we don't care
		 :introduction +introduction+
		 :version (net.didierverna.focus:version :long)
		 :license :bsd
		 :copyright-date "2015")
    (declt:declt :net.didierverna.focus
		 :library-name "FoCus"
		 :texi-file "reference.texi"
		 :info-file "focus-reference"
		 :introduction +introduction+
		 :version (net.didierverna.focus:version :long)
		 :license :bsd
		 :copyright-date "2015"
		 :hyperlinks t))

(uiop:quit)

;;; generate.cl ends here


check before copy

check before copy

#ifndef VSMC_HELPER_PARALLEL_CL_COMMON_CL
#define VSMC_HELPER_PARALLEL_CL_COMMON_CL

#if defined(cl_khr_fp64)
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
#elif defined(cl_amd_fp64)
#pragma OPENCL EXTENSION cl_amd_fp64 : enable
#else
#define R123_USE_U01_DOUBLE 0
#endif

#include <Random123/philox.h>
#include <Random123/threefry.h>
#include <Random123/u01.h>

__kernel
void copy (__global state_struct *state, __global uint *source)
{
    size_type to = get_global_id(0);

    if (to >= Size)
        return;

    size_t from = source[to];
    if (to != form)
        state[to] = state[from];
}

#endif // VSMC_HELPER_PARALLEL_CL_COMMON_CL

#ifndef VSMC_HELPER_PARALLEL_CL_COMMON_CL
#define VSMC_HELPER_PARALLEL_CL_COMMON_CL

#if defined(cl_khr_fp64)
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
#elif defined(cl_amd_fp64)
#pragma OPENCL EXTENSION cl_amd_fp64 : enable
#else
#define R123_USE_U01_DOUBLE 0
#endif

#include <Random123/philox.h>
#include <Random123/threefry.h>
#include <Random123/u01.h>

__kernel
void copy (__global state_struct *state, __global uint *source)
{
    size_type to = get_global_id(0);

    if (to >= Size)
        return;

    size_t from = source[to];
    state[to] = state[from];
}

#endif // VSMC_HELPER_PARALLEL_CL_COMMON_CL


Raytracing test using distance fields and a hardcoded scene; no lights

The tracer kernel has been expanded will helper macros that generate
distance field estimators for planes, spheres, boxes and torii. The test
uses a hardcoded cornel box-like scene and just emits the material color
for surface hits


opencl/cvtclr_dx: fix not compile-time constants issue.

fix the "initializing global variables with values that are not
compile-time constants" issue in Intel SDK for OpenCL. The root cause
is when initializing global variables with value, the variable need is
compile-time constants.

Thanks Zheng, Yang <yang.zheng@intel.com>,
Chodor, Jaroslaw <jaroslaw.chodor@intel.com> give a help.

Signed-off-by: Liu,Kaixuan <e532cc908bb4938287f46b28a2bf43cc1a9f4c63@intel.com>
Signed-off-by: Jun Zhao <a9404aefee6448c29674fb00fe4b4109ebaab451@intel.com>

/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// @Authors
//    Jia Haipeng, jiahaipeng95@gmail.com
//
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of the copyright holders may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors as is and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the copyright holders or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

#ifdef DOUBLE_SUPPORT
#ifdef cl_amd_fp64
#pragma OPENCL EXTENSION cl_amd_fp64:enable
#elif defined cl_khr_fp64
#pragma OPENCL EXTENSION cl_khr_fp64:enable
#endif
#endif

#ifdef INTEL_DEVICE
#pragma OPENCL FP_CONTRACT ON
#pragma OPENCL FP_FAST_FMAF ON
#pragma OPENCL FP_FAST_FMA ON
#endif

static
__constant
float c_YUV2RGBCoeffs_420[5] =
{
     1.163999557f,
     2.017999649f,
    -0.390999794f,
    -0.812999725f,
     1.5959997177f
};

static const __constant float CV_8U_MAX         = 255.0f;
static const __constant float CV_8U_HALF        = 128.0f;
static const __constant float BT601_BLACK_RANGE = 16.0f;
static const __constant float CV_8U_SCALE       = 1.0f / 255.0f;
static const __constant float d1                = BT601_BLACK_RANGE / CV_8U_MAX;
static const __constant float d2                = CV_8U_HALF / CV_8U_MAX;

#define NCHANNELS 3

__kernel
void YUV2BGR_NV12_8u(
    read_only image2d_t imgY,
    read_only image2d_t imgUV,
    __global unsigned char* pBGR,
   int bgrStep,
   int cols,
   int rows)
{
    int x = get_global_id(0);
    int y = get_global_id(1);

    if (x < cols)
    {
        if (y < rows)
        {
            __global uchar* pDstRow1 = pBGR + mad24(y, bgrStep, mad24(x, NCHANNELS, 0));
            __global uchar* pDstRow2 = pDstRow1 + bgrStep;

            float4 Y1 = read_imagef(imgY, (int2)(x+0, y+0));
            float4 Y2 = read_imagef(imgY, (int2)(x+1, y+0));
            float4 Y3 = read_imagef(imgY, (int2)(x+0, y+1));
            float4 Y4 = read_imagef(imgY, (int2)(x+1, y+1));

            float4 UV = read_imagef(imgUV, (int2)(x/2, y/2)) - d2;

            __constant float* coeffs = c_YUV2RGBCoeffs_420;

            Y1 = max(0.f, Y1 - d1) * coeffs[0];
            Y2 = max(0.f, Y2 - d1) * coeffs[0];
            Y3 = max(0.f, Y3 - d1) * coeffs[0];
            Y4 = max(0.f, Y4 - d1) * coeffs[0];

            float ruv = fma(coeffs[4], UV.y, 0.0f);
            float guv = fma(coeffs[3], UV.y, fma(coeffs[2], UV.x, 0.0f));
            float buv = fma(coeffs[1], UV.x, 0.0f);

            float R1 = (Y1.x + ruv) * CV_8U_MAX;
            float G1 = (Y1.x + guv) * CV_8U_MAX;
            float B1 = (Y1.x + buv) * CV_8U_MAX;

            float R2 = (Y2.x + ruv) * CV_8U_MAX;
            float G2 = (Y2.x + guv) * CV_8U_MAX;
            float B2 = (Y2.x + buv) * CV_8U_MAX;

            float R3 = (Y3.x + ruv) * CV_8U_MAX;
            float G3 = (Y3.x + guv) * CV_8U_MAX;
            float B3 = (Y3.x + buv) * CV_8U_MAX;

            float R4 = (Y4.x + ruv) * CV_8U_MAX;
            float G4 = (Y4.x + guv) * CV_8U_MAX;
            float B4 = (Y4.x + buv) * CV_8U_MAX;

            pDstRow1[0*NCHANNELS + 0] = convert_uchar_sat(B1);
            pDstRow1[0*NCHANNELS + 1] = convert_uchar_sat(G1);
            pDstRow1[0*NCHANNELS + 2] = convert_uchar_sat(R1);

            pDstRow1[1*NCHANNELS + 0] = convert_uchar_sat(B2);
            pDstRow1[1*NCHANNELS + 1] = convert_uchar_sat(G2);
            pDstRow1[1*NCHANNELS + 2] = convert_uchar_sat(R2);

            pDstRow2[0*NCHANNELS + 0] = convert_uchar_sat(B3);
            pDstRow2[0*NCHANNELS + 1] = convert_uchar_sat(G3);
            pDstRow2[0*NCHANNELS + 2] = convert_uchar_sat(R3);

            pDstRow2[1*NCHANNELS + 0] = convert_uchar_sat(B4);
            pDstRow2[1*NCHANNELS + 1] = convert_uchar_sat(G4);
            pDstRow2[1*NCHANNELS + 2] = convert_uchar_sat(R4);
        }
    }
}

static
__constant float c_RGB2YUVCoeffs_420[8] =
{
     0.256999969f,  0.50399971f,   0.09799957f,   -0.1479988098f,
    -0.2909994125f, 0.438999176f, -0.3679990768f, -0.0709991455f
};

__kernel
void BGR2YUV_NV12_8u(
    __global unsigned char* pBGR,
    int bgrStep,
    int cols,
    int rows,
    write_only image2d_t imgY,
    write_only image2d_t imgUV)
{
    int x = get_global_id(0);
    int y = get_global_id(1);

    if (x < cols)
    {
        if (y < rows)
        {
            __global const uchar* pSrcRow1 = pBGR + mad24(y, bgrStep, mad24(x, NCHANNELS, 0));
            __global const uchar* pSrcRow2 = pSrcRow1 + bgrStep;

            float4 src_pix1 = convert_float4(vload4(0, pSrcRow1 + 0*NCHANNELS)) * CV_8U_SCALE;
            float4 src_pix2 = convert_float4(vload4(0, pSrcRow1 + 1*NCHANNELS)) * CV_8U_SCALE;
            float4 src_pix3 = convert_float4(vload4(0, pSrcRow2 + 0*NCHANNELS)) * CV_8U_SCALE;
            float4 src_pix4 = convert_float4(vload4(0, pSrcRow2 + 1*NCHANNELS)) * CV_8U_SCALE;

            __constant float* coeffs = c_RGB2YUVCoeffs_420;

            float Y1 = fma(coeffs[0], src_pix1.z, fma(coeffs[1], src_pix1.y, fma(coeffs[2], src_pix1.x, d1)));
            float Y2 = fma(coeffs[0], src_pix2.z, fma(coeffs[1], src_pix2.y, fma(coeffs[2], src_pix2.x, d1)));
            float Y3 = fma(coeffs[0], src_pix3.z, fma(coeffs[1], src_pix3.y, fma(coeffs[2], src_pix3.x, d1)));
            float Y4 = fma(coeffs[0], src_pix4.z, fma(coeffs[1], src_pix4.y, fma(coeffs[2], src_pix4.x, d1)));

            float4 UV;
            UV.x = fma(coeffs[3], src_pix1.z, fma(coeffs[4], src_pix1.y, fma(coeffs[5], src_pix1.x, d2)));
            UV.y = fma(coeffs[5], src_pix1.z, fma(coeffs[6], src_pix1.y, fma(coeffs[7], src_pix1.x, d2)));

            write_imagef(imgY, (int2)(x+0, y+0), Y1);
            write_imagef(imgY, (int2)(x+1, y+0), Y2);
            write_imagef(imgY, (int2)(x+0, y+1), Y3);
            write_imagef(imgY, (int2)(x+1, y+1), Y4);

            write_imagef(imgUV, (int2)((x/2), (y/2)), UV);
        }
    }
}

/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// @Authors
//    Jia Haipeng, jiahaipeng95@gmail.com
//
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of the copyright holders may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors as is and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the copyright holders or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

#ifdef DOUBLE_SUPPORT
#ifdef cl_amd_fp64
#pragma OPENCL EXTENSION cl_amd_fp64:enable
#elif defined cl_khr_fp64
#pragma OPENCL EXTENSION cl_khr_fp64:enable
#endif
#endif

#ifdef INTEL_DEVICE
#pragma OPENCL FP_CONTRACT ON
#pragma OPENCL FP_FAST_FMAF ON
#pragma OPENCL FP_FAST_FMA ON
#endif

static
__constant
float c_YUV2RGBCoeffs_420[5] =
{
     1.163999557f,
     2.017999649f,
    -0.390999794f,
    -0.812999725f,
     1.5959997177f
};

static __constant float CV_8U_MAX         = 255.0f;
static __constant float CV_8U_HALF        = 128.0f;
static __constant float BT601_BLACK_RANGE = 16.0f;
static __constant float CV_8U_SCALE       = 1.0f / 255.0f;
static __constant float d1                = BT601_BLACK_RANGE / CV_8U_MAX;
static __constant float d2                = CV_8U_HALF / CV_8U_MAX;

#define NCHANNELS 3

__kernel
void YUV2BGR_NV12_8u(
    read_only image2d_t imgY,
    read_only image2d_t imgUV,
    __global unsigned char* pBGR,
   int bgrStep,
   int cols,
   int rows)
{
    int x = get_global_id(0);
    int y = get_global_id(1);

    if (x < cols)
    {
        if (y < rows)
        {
            __global uchar* pDstRow1 = pBGR + mad24(y, bgrStep, mad24(x, NCHANNELS, 0));
            __global uchar* pDstRow2 = pDstRow1 + bgrStep;

            float4 Y1 = read_imagef(imgY, (int2)(x+0, y+0));
            float4 Y2 = read_imagef(imgY, (int2)(x+1, y+0));
            float4 Y3 = read_imagef(imgY, (int2)(x+0, y+1));
            float4 Y4 = read_imagef(imgY, (int2)(x+1, y+1));

            float4 UV = read_imagef(imgUV, (int2)(x/2, y/2)) - d2;

            __constant float* coeffs = c_YUV2RGBCoeffs_420;

            Y1 = max(0.f, Y1 - d1) * coeffs[0];
            Y2 = max(0.f, Y2 - d1) * coeffs[0];
            Y3 = max(0.f, Y3 - d1) * coeffs[0];
            Y4 = max(0.f, Y4 - d1) * coeffs[0];

            float ruv = fma(coeffs[4], UV.y, 0.0f);
            float guv = fma(coeffs[3], UV.y, fma(coeffs[2], UV.x, 0.0f));
            float buv = fma(coeffs[1], UV.x, 0.0f);

            float R1 = (Y1.x + ruv) * CV_8U_MAX;
            float G1 = (Y1.x + guv) * CV_8U_MAX;
            float B1 = (Y1.x + buv) * CV_8U_MAX;

            float R2 = (Y2.x + ruv) * CV_8U_MAX;
            float G2 = (Y2.x + guv) * CV_8U_MAX;
            float B2 = (Y2.x + buv) * CV_8U_MAX;

            float R3 = (Y3.x + ruv) * CV_8U_MAX;
            float G3 = (Y3.x + guv) * CV_8U_MAX;
            float B3 = (Y3.x + buv) * CV_8U_MAX;

            float R4 = (Y4.x + ruv) * CV_8U_MAX;
            float G4 = (Y4.x + guv) * CV_8U_MAX;
            float B4 = (Y4.x + buv) * CV_8U_MAX;

            pDstRow1[0*NCHANNELS + 0] = convert_uchar_sat(B1);
            pDstRow1[0*NCHANNELS + 1] = convert_uchar_sat(G1);
            pDstRow1[0*NCHANNELS + 2] = convert_uchar_sat(R1);

            pDstRow1[1*NCHANNELS + 0] = convert_uchar_sat(B2);
            pDstRow1[1*NCHANNELS + 1] = convert_uchar_sat(G2);
            pDstRow1[1*NCHANNELS + 2] = convert_uchar_sat(R2);

            pDstRow2[0*NCHANNELS + 0] = convert_uchar_sat(B3);
            pDstRow2[0*NCHANNELS + 1] = convert_uchar_sat(G3);
            pDstRow2[0*NCHANNELS + 2] = convert_uchar_sat(R3);

            pDstRow2[1*NCHANNELS + 0] = convert_uchar_sat(B4);
            pDstRow2[1*NCHANNELS + 1] = convert_uchar_sat(G4);
            pDstRow2[1*NCHANNELS + 2] = convert_uchar_sat(R4);
        }
    }
}

static
__constant float c_RGB2YUVCoeffs_420[8] =
{
     0.256999969f,  0.50399971f,   0.09799957f,   -0.1479988098f,
    -0.2909994125f, 0.438999176f, -0.3679990768f, -0.0709991455f
};

__kernel
void BGR2YUV_NV12_8u(
    __global unsigned char* pBGR,
    int bgrStep,
    int cols,
    int rows,
    write_only image2d_t imgY,
    write_only image2d_t imgUV)
{
    int x = get_global_id(0);
    int y = get_global_id(1);

    if (x < cols)
    {
        if (y < rows)
        {
            __global const uchar* pSrcRow1 = pBGR + mad24(y, bgrStep, mad24(x, NCHANNELS, 0));
            __global const uchar* pSrcRow2 = pSrcRow1 + bgrStep;

            float4 src_pix1 = convert_float4(vload4(0, pSrcRow1 + 0*NCHANNELS)) * CV_8U_SCALE;
            float4 src_pix2 = convert_float4(vload4(0, pSrcRow1 + 1*NCHANNELS)) * CV_8U_SCALE;
            float4 src_pix3 = convert_float4(vload4(0, pSrcRow2 + 0*NCHANNELS)) * CV_8U_SCALE;
            float4 src_pix4 = convert_float4(vload4(0, pSrcRow2 + 1*NCHANNELS)) * CV_8U_SCALE;

            __constant float* coeffs = c_RGB2YUVCoeffs_420;

            float Y1 = fma(coeffs[0], src_pix1.z, fma(coeffs[1], src_pix1.y, fma(coeffs[2], src_pix1.x, d1)));
            float Y2 = fma(coeffs[0], src_pix2.z, fma(coeffs[1], src_pix2.y, fma(coeffs[2], src_pix2.x, d1)));
            float Y3 = fma(coeffs[0], src_pix3.z, fma(coeffs[1], src_pix3.y, fma(coeffs[2], src_pix3.x, d1)));
            float Y4 = fma(coeffs[0], src_pix4.z, fma(coeffs[1], src_pix4.y, fma(coeffs[2], src_pix4.x, d1)));

            float4 UV;
            UV.x = fma(coeffs[3], src_pix1.z, fma(coeffs[4], src_pix1.y, fma(coeffs[5], src_pix1.x, d2)));
            UV.y = fma(coeffs[5], src_pix1.z, fma(coeffs[6], src_pix1.y, fma(coeffs[7], src_pix1.x, d2)));

            write_imagef(imgY, (int2)(x+0, y+0), Y1);
            write_imagef(imgY, (int2)(x+1, y+0), Y2);
            write_imagef(imgY, (int2)(x+0, y+1), Y3);
            write_imagef(imgY, (int2)(x+1, y+1), Y4);

            write_imagef(imgUV, (int2)((x/2), (y/2)), UV);
        }
    }
}


Add memory fences to prevent race conditions

/******************************************************************************
 * function: wah_bitmap                                                       *
 * input:    32-bit integer                                                   *
 * output:   wah compressed bitmap index, offsets for its values              *
 ******************************************************************************/

#define FENCE_TYPE CLK_LOCAL_MEM_FENCE
#define WORK_GROUP_SIZE 1024

// Processing steps
void sort_rids_by_value(global uint* input, global  uint* rids,
                        size_t idx, size_t total);
void produce_chunck_id_literals(global uint* rids, global uint* chids,
                                global uint* lits, size_t idx, size_t total);
size_t merged_lit_by_val_chids(global uint* input, global uint* chids,
                               global uint* lits, size_t idx, size_t total);
void produce_fills(global uint* input, global uint* chids,
                   size_t idx, size_t total);
size_t fuse_fill_literals(global uint* chids, global uint* lits,
                          global uint* index, size_t idx, size_t total);
size_t compute_colum_length(global uint* input, global uint* chids,
                            global uint* offsets, size_t idx, size_t total);

// helper functions
void parallel_selection_sort(global uint* key, global uint* data,
                             size_t idx, size_t total);
size_t reduce_by_key_OR(global uint* keys_high, global uint* keys_low,
                        global uint* data, size_t idx, size_t total);
size_t reduce_by_key_SUM(global uint* keys, local uint* data,
                         size_t idx, size_t total);

// main kernel
kernel void kernel_wah_index(global uint* config,
                             global uint* input,
                             global uint* index,
                             global uint* offsets,
                             global uint* rids,
                             global uint* chids,
                             global uint* lits) {
  // just 1 dimension here: 0
  size_t total = get_global_size(0);
  size_t idx = get_global_id(0);
  if (total > WORK_GROUP_SIZE) {
    offsets[idx] = total;
    index[idx] = WORK_GROUP_SIZE;
    return;
  }
  // CONSIDERATIONS:
  // * some scaling state of the are functions required
  //  - sorting
  //  - scan
  //  - stream compaction
  //  - reduce by key
  // * when do we need barriers?
  //  - at the end of functions, before return?
  //  - can be just assign return values to global stuff
  //  - ...

  // read config data
  // uint input_size       = config[0];
  // uint index_size       = config[1]; should be 2* input size
  // uint processed_ values = config[2];

  // Currently 1 work item per value
  total = config[0];

  //__gloabl uint[index_size] rids;
  sort_rids_by_value(input, rids, idx, total);
  barrier(FENCE_TYPE);
  //index[idx] = rids[idx];
  //offsets[idx] = 0;
  //config[4] = total;
  produce_chunck_id_literals(rids, chids, lits, idx, total);
  barrier(FENCE_TYPE);
  //input[idx] = rids[idx];
  //index[idx] = chids[idx];
  //offsets[idx] = lits[idx];
  //config[4] = total;
  size_t k = merged_lit_by_val_chids(input, chids, lits, idx, total);
  barrier(FENCE_TYPE);
  //index[idx] = chids[idx];
  //offsets[idx] = lits[idx];
  //config[3] = (uint) k;
  //config[4] = (uint) k;
  //config[5] = (uint) k;
  produce_fills(input, chids, idx, k);
  barrier(FENCE_TYPE);
  //config[1] = k;
  //index[idx] = chids[idx];
  //offsets[idx] = lits[idx];
  uint idxlen = fuse_fill_literals(chids, lits, index, idx, k);
  barrier(FENCE_TYPE);
  config[1] = idxlen;
  uint keycnt = compute_colum_length(input, chids, offsets, idx, k);
  barrier(FENCE_TYPE);
  config[0] = keycnt;
}

void sort_rids_by_value(global uint* input,global uint* rids,
                        size_t idx, size_t total) {
  rids[idx] = idx;
  barrier(FENCE_TYPE); // is this needed here?
  // sort by input value
  parallel_selection_sort(input, rids, idx, total);
}

void produce_chunck_id_literals(global uint* rids, global uint* chids,
                                global uint* lits, size_t idx, size_t total) {
  (void) total;
  lits[idx] = 1u << (rids[idx] % 31u);
  lits[idx] |= 1u << 31;
  chids[idx] = (uint) rids[idx] / 31;
}

size_t merged_lit_by_val_chids(global uint* input, global uint* chids,
                               global uint* lits, size_t idx, size_t total) {
  // avoid merge of chids and input into keys,
  // simply pass them both
  size_t k = reduce_by_key_OR(chids, input, lits, idx, total);
  return k;
}

void produce_fills(global uint* input, global uint* chids,
                   size_t idx, size_t total) {
  uint tmp = chids[idx];
  if (idx != 0 && input[idx] == input[idx - 1]) {
    tmp = chids[idx] - chids[idx - 1] - 1;
  }
  // This branch leads to loss of fills at the beginning of
  // a bitmap index.
  /* else {
    if (chids[idx] != 0) {
      chids[idx] = chids[idx] - 1;
    }
  }*/
  barrier(FENCE_TYPE);
  chids[idx] = tmp;
}

size_t fuse_fill_literals(global uint* chids, global uint* lits,
                          global uint* index, size_t idx, size_t total) {
  local uint markers [WORK_GROUP_SIZE * 2];
  local uint position[WORK_GROUP_SIZE * 2];
  volatile local int len;
  len = 0;
  uint a =  2 * idx;
  uint b = (2 * idx) + 1;
  index[a] = chids[idx];
  index[b] = lits[idx];
  barrier(FENCE_TYPE);
  // stream compaction
  markers[a] = index[a] != 0; // ? 1 : 0;
  markers[b] = index[b] != 0; // ? 1 : 0;
  barrier(FENCE_TYPE);
  // should be a parallel scan
  if (idx == 0) {
    position[0] = 0;
    for (uint i = 1; i < (2 * total); ++i) {
      position[i] = position[i - 1] + markers[i - 1];
    }
  }
  // end parallel scan
  uint tmp_a = index[a];
  uint tmp_b = index[b];
  barrier(FENCE_TYPE);
  if (idx < total) {
    if (markers[a] == 1) {
      index[position[a]] = tmp_a;
      atomic_add(&len, 1);
      //atomic_max(&len, position[a] + 1);
    }
    if (markers[b] == 1) {
      index[position[b]] = tmp_b;
      atomic_add(&len, 1);
      //atomic_max(&len, position[b] + 1);
    }
  }
  // end stream compaction
  barrier(FENCE_TYPE); // <-- should there be a barrier here?
  return len;
}

size_t compute_colum_length(global uint* input, global uint* chids,
                            global uint* offsets, size_t idx, size_t k) {
  local uint tmp[WORK_GROUP_SIZE];
  tmp[idx] = (1 + (chids[idx] != 0)); // ? 0 : 1));
  barrier(FENCE_TYPE);
  uint keycnt = reduce_by_key_SUM(input, tmp, idx, k);
  // inclusive scan to create offsets, should be parallel
  barrier(FENCE_TYPE);
  if (idx == 0) {
    offsets[0] = 0;
    for (uint i = 1; i < keycnt; ++i) {
      offsets[i] = offsets[i - 1] + tmp[i - 1];
    }
  }
  barrier(FENCE_TYPE);
  return keycnt;
}

// Helper functions

// we have 64 bit keys consisting of (high << 32 | low), but want to
// avoid the extra copy, so ...
size_t reduce_by_key_OR(global uint* keys_high, global uint* keys_low,
                        global uint* data, size_t idx, size_t total) {
  local uint heads[WORK_GROUP_SIZE];
  volatile local int k;
  heads[idx] = (idx == 0) ||
               (keys_high[idx] != keys_high[idx - 1]) ||
               (keys_low [idx] != keys_low [idx - 1]);
  barrier(FENCE_TYPE);
  if (heads[idx] != 0) {
    uint val = data[idx];
    uint curr = idx + 1;
    while (heads[curr] == 0 && curr < total) {
      val |= data[curr]; // OR operation
      curr += 1;
    }
    atomic_add(&k, 1);
    data[idx] = val;
  }
  barrier(FENCE_TYPE);
  if (idx == 0) {
    uint pos = 0;
    for (uint i = 0; i < total; ++i) {
      if (heads[i] != 0) {
        keys_high[pos] = keys_high[i];
        keys_low[pos] = keys_low[i];
        data[pos] = data[i];
        pos += 1;
      }
    }
  }
  return (uint) k;
}

size_t reduce_by_key_SUM(global uint* keys, local uint* data,
                         size_t idx, size_t total) {
  local uint heads[WORK_GROUP_SIZE];
  heads[idx] = idx == 0 || (keys[idx] != keys[idx - 1]);
  volatile local int k;
  barrier(FENCE_TYPE);
  if (heads[idx] != 0 && idx < total) {
    uint val = data[idx];
    uint curr = idx + 1;
    while (heads[curr] == 0 && curr < total) {
      val += data[curr]; // SUM operation
      curr += 1;
    }
    atomic_add(&k, 1);
    data[idx] = val;
  }
  barrier(FENCE_TYPE);
  if (idx == 0) {
    uint pos = 0;
    for (uint i = 0; i < total; ++i) {
      if (heads[i] != 0) {
        keys[pos] = keys[i];
        data[pos] = data[i];
        pos += 1;
      }
    }
  }
  return (uint) k;
}

/**
 * Sort found on: http://www.bealto.com/gpu-sorting_intro.html
 * License:set syntax=:
 *  This code is released under the following license (BSD-style).
 *  --
 *
 *  Copyright (c) 2011, Eric Bainville
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *      * Redistributions of source code must retain the above copyright
 *        notice, this list of conditions and the following disclaimer.
 *      * Redistributions in binary form must reproduce the above copyright
 *        notice, this list of conditions and the following disclaimer in the
 *        documentation and/or other materials provided with the distribution.
 *      * Neither the name of Eric Bainville nor the
 *        names of its contributors may be used to endorse or promote products
 *        derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY ERIC BAINVILLE ''AS IS'' AND ANY
 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *  DISCLAIMED. IN NO EVENT SHALL ERIC BAINVILLE BE LIABLE FOR ANY
 *  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 **/

void parallel_selection_sort(global uint* key, global uint* data,
                             size_t idx, size_t total) {
  uint key_value = key[idx];
  uint data_value = data[idx];
  // Compute position of in[i] in output
  int pos = 0;
  for (size_t j = 0; j < total; ++j) {
    uint curr = key[j]; // broadcasted
    bool smaller = (curr < key_value) || (curr == key_value && j < idx);
    pos += (smaller) ? 1 : 0;
  }
  barrier(CLK_LOCAL_MEM_FENCE);
  key[pos] = key_value;
  data[pos] = data_value;
}

/******************************************************************************
 * function: wah_bitmap                                                       *
 * input:    32-bit integer                                                   *
 * output:   wah compressed bitmap index, offsets for its values              *
 ******************************************************************************/

#define FENCE_TYPE CLK_LOCAL_MEM_FENCE
#define WORK_GROUP_SIZE 1024

// Processing steps
void sort_rids_by_value(global uint* input, global  uint* rids,
                        size_t idx, size_t total);
void produce_chunck_id_literals(global uint* rids, global uint* chids,
                                global uint* lits, size_t idx, size_t total);
size_t merged_lit_by_val_chids(global uint* input, global uint* chids,
                               global uint* lits, size_t idx, size_t total);
void produce_fills(global uint* input, global uint* chids,
                   size_t idx, size_t total);
size_t fuse_fill_literals(global uint* chids, global uint* lits,
                          global uint* index, size_t idx, size_t total);
size_t compute_colum_length(global uint* input, global uint* chids,
                            global uint* offsets, size_t idx, size_t total);

// helper functions
void parallel_selection_sort(global uint* key, global uint* data,
                             size_t idx, size_t total);
size_t reduce_by_key_OR(global uint* keys_high, global uint* keys_low,
                        global uint* data, size_t idx, size_t total);
size_t reduce_by_key_SUM(global uint* keys, local uint* data,
                         size_t idx, size_t total);

// main kernel
kernel void kernel_wah_index(global uint* config,
                             global uint* input,
                             global uint* index,
                             global uint* offsets,
                             global uint* rids,
                             global uint* chids,
                             global uint* lits) {
  // just 1 dimension here: 0
  size_t total = get_global_size(0);
  size_t idx = get_global_id(0);
  if (total > WORK_GROUP_SIZE) {
    offsets[idx] = total;
    index[idx] = WORK_GROUP_SIZE;
    return;
  }
  // CONSIDERATIONS:
  // * some scaling state of the are functions required
  //  - sorting
  //  - scan
  //  - stream compaction
  //  - reduce by key
  // * when do we need barriers?
  //  - at the end of functions, before return?
  //  - can be just assign return values to global stuff
  //  - ...

  // read config data
  // uint input_size       = config[0];
  // uint index_size       = config[1]; should be 2* input size
  // uint processed_ values = config[2];

  // Currently 1 work item per value
  total = config[0];

  //__gloabl uint[index_size] rids;
  sort_rids_by_value(input, rids, idx, total);
  barrier(FENCE_TYPE);
  //index[idx] = rids[idx];
  //offsets[idx] = 0;
  //config[4] = total;
  produce_chunck_id_literals(rids, chids, lits, idx, total);
  barrier(FENCE_TYPE);
  //input[idx] = rids[idx];
  //index[idx] = chids[idx];
  //offsets[idx] = lits[idx];
  //config[4] = total;
  size_t k = merged_lit_by_val_chids(input, chids, lits, idx, total);
  barrier(FENCE_TYPE);
  //index[idx] = chids[idx];
  //offsets[idx] = lits[idx];
  //config[3] = (uint) k;
  //config[4] = (uint) k;
  //config[5] = (uint) k;
  produce_fills(input, chids, idx, k);
  barrier(FENCE_TYPE);
  //config[1] = k;
  //index[idx] = chids[idx];
  //offsets[idx] = lits[idx];
  uint idxlen = fuse_fill_literals(chids, lits, index, idx, k);
  barrier(FENCE_TYPE);
  config[1] = idxlen;
  uint keycnt = compute_colum_length(input, chids, offsets, idx, k);
  barrier(FENCE_TYPE);
  config[0] = keycnt;
}

void sort_rids_by_value(global uint* input,global uint* rids,
                        size_t idx, size_t total) {
  rids[idx] = idx;
  barrier(FENCE_TYPE); // is this needed here?
  // sort by input value
  parallel_selection_sort(input, rids, idx, total);
}

void produce_chunck_id_literals(global uint* rids, global uint* chids,
                                global uint* lits, size_t idx, size_t total) {
  (void) total;
  lits[idx] = 1u << (rids[idx] % 31u);
  lits[idx] |= 1u << 31;
  chids[idx] = (uint) rids[idx] / 31;
}

size_t merged_lit_by_val_chids(global uint* input, global uint* chids,
                               global uint* lits, size_t idx, size_t total) {
  // avoid merge of chids and input into keys,
  // simply pass them both
  size_t k = reduce_by_key_OR(chids, input, lits, idx, total);
  return k;
}

void produce_fills(global uint* input, global uint* chids,
                   size_t idx, size_t total) {
  uint tmp = chids[idx];
  if (idx != 0 && input[idx] == input[idx - 1]) {
    tmp = chids[idx] - chids[idx - 1] - 1;
  }
  // This branch leads to loss of fills at the beginning of
  // a bitmap index.
  /* else {
    if (chids[idx] != 0) {
      chids[idx] = chids[idx] - 1;
    }
  }*/
  barrier(FENCE_TYPE);
  chids[idx] = tmp;
}

size_t fuse_fill_literals(global uint* chids, global uint* lits,
                          global uint* index, size_t idx, size_t total) {
  local uint markers [WORK_GROUP_SIZE * 2];
  local uint position[WORK_GROUP_SIZE * 2];
  volatile local int len;
  uint a =  2 * idx;
  uint b = (2 * idx) + 1;
  len = 0;
  index[a] = chids[idx];
  index[b] = lits[idx];
  barrier(FENCE_TYPE);
  // stream compaction
  markers[a] = index[a] != 0; // ? 1 : 0;
  markers[b] = index[b] != 0; // ? 1 : 0;
  barrier(FENCE_TYPE);
  // should be a parallel scan
  if (idx == 0) {
    position[0] = 0;
    for (uint i = 1; i < (2 * total); ++i) {
      position[i] = position[i - 1] + markers[i - 1];
    }
  }
  // end parallel scan
  uint tmp_a = index[a];
  uint tmp_b = index[b];
  barrier(FENCE_TYPE);
  if (idx < total) {
    if (markers[a] == 1) {
      index[position[a]] = tmp_a;
      atomic_add(&len, 1);
    }
    if (markers[b] == 1) {
      index[position[b]] = tmp_b;
      atomic_add(&len, 1);
    }
  }
  barrier(FENCE_TYPE); // <-- should there be a barrier here?
  return len;
}

size_t compute_colum_length(global uint* input, global uint* chids,
                            global uint* offsets, size_t idx, size_t k) {
  local uint tmp[WORK_GROUP_SIZE];
  tmp[idx] = (1 + (chids[idx] == 0 ? 0 : 1));
  uint keycnt = reduce_by_key_SUM(input, tmp, idx, k);
  // inclusive scan to create offsets, should be parallel
  barrier(FENCE_TYPE);
  if (idx == 0) {
    offsets[0] = 0;
    for (uint i = 1; i < keycnt; ++i) {
      offsets[i] = offsets[i - 1] + tmp[i - 1];
    }
  }
  return keycnt;
}

// Helper functions

// we have 64 bit keys consisting of (high << 32 | low), but want to
// avoid the extra copy, so ...
size_t reduce_by_key_OR(global uint* keys_high, global uint* keys_low,
                        global uint* data, size_t idx, size_t total) {
  local uint heads[WORK_GROUP_SIZE];
  volatile local int k;
  heads[idx] = (idx == 0) ||
               (keys_high[idx] != keys_high[idx - 1]) ||
               (keys_low [idx] != keys_low [idx - 1]);
  barrier(FENCE_TYPE);
  if (heads[idx] != 0) {
    uint val = data[idx];
    uint curr = idx + 1;
    while (heads[curr] == 0 && curr < total) {
      val |= data[curr]; // OR operation
      curr += 1;
    }
    atomic_add(&k, 1);
    data[idx] = val;
  }
  barrier(FENCE_TYPE);
  if (idx == 0) {
    uint pos = 0;
    for (uint i = 0; i < total; ++i) {
      if (heads[i] != 0) {
        keys_high[pos] = keys_high[i];
        keys_low[pos] = keys_low[i];
        data[pos] = data[i];
        pos += 1;
      }
    }
  }
  return (uint) k;
}

size_t reduce_by_key_SUM(global uint* keys, local uint* data,
                         size_t idx, size_t total) {
  local uint heads[WORK_GROUP_SIZE];
  heads[idx] = idx == 0 || (keys[idx] != keys[idx - 1]);
  volatile local int k;
  if (heads[idx] != 0 && idx < total) {
    uint val = data[idx];
    uint curr = idx + 1;
    while (heads[curr] == 0 && curr < total) {
      val += data[curr]; // SUM operation
      curr += 1;
    }
    atomic_add(&k, 1);
    data[idx] = val;
  }
  barrier(FENCE_TYPE);
  if (idx == 0) {
    uint pos = 0;
    for (uint i = 0; i < total; ++i) {
      if (heads[i] != 0) {
        keys[pos] = keys[i];
        data[pos] = data[i];
        pos += 1;
      }
    }
  }
  return (uint) k;
}

/**
 * Sort found on: http://www.bealto.com/gpu-sorting_intro.html
 * License:set syntax=:
 *  This code is released under the following license (BSD-style).
 *  --
 *
 *  Copyright (c) 2011, Eric Bainville
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *      * Redistributions of source code must retain the above copyright
 *        notice, this list of conditions and the following disclaimer.
 *      * Redistributions in binary form must reproduce the above copyright
 *        notice, this list of conditions and the following disclaimer in the
 *        documentation and/or other materials provided with the distribution.
 *      * Neither the name of Eric Bainville nor the
 *        names of its contributors may be used to endorse or promote products
 *        derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY ERIC BAINVILLE ''AS IS'' AND ANY
 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *  DISCLAIMED. IN NO EVENT SHALL ERIC BAINVILLE BE LIABLE FOR ANY
 *  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 **/

void parallel_selection_sort(global uint* key, global uint* data,
                             size_t idx, size_t total) {
  uint key_value = key[idx];
  uint data_value = data[idx];
  // Compute position of in[i] in output
  int pos = 0;
  for (size_t j = 0; j < total; ++j) {
    uint curr = key[j]; // broadcasted
    bool smaller = (curr < key_value) || (curr == key_value && j < idx);
    pos += (smaller) ? 1 : 0;
  }
  barrier(CLK_LOCAL_MEM_FENCE);
  key[pos] = key_value;
  data[pos] = data_value;
}


libocl: refine implementation of abs_diff()

Make it generate less instructions.

Signed-off-by: Ruiling Song <286a174c1339c6eff91abc41c3a1012c95030c95@intel.com>
Reviewed-by: Zhigang Gong <e04a7b9b70b1e4c6318cf117dcd1a9056e14b97a@linux.intel.com>

/*
 * Copyright © 2012 - 2014 Intel Corporation
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 *
 */
#include "ocl_integer.h"

PURE CONST uint __gen_ocl_fbh(uint);
PURE CONST uint __gen_ocl_fbl(uint);

PURE CONST OVERLOADABLE uint __gen_ocl_cbit(uint);
PURE CONST OVERLOADABLE uint __gen_ocl_cbit(int);
PURE CONST OVERLOADABLE uint __gen_ocl_cbit(ushort);
PURE CONST OVERLOADABLE uint __gen_ocl_cbit(short);
PURE CONST OVERLOADABLE uint __gen_ocl_cbit(uchar);
PURE CONST OVERLOADABLE uint __gen_ocl_cbit(char);

#define SDEF(TYPE, TYPE_NAME, SIZE)        \
OVERLOADABLE TYPE clz(TYPE x){ return clz_##TYPE_NAME##SIZE(x);}
SDEF(char, s, 8);
SDEF(uchar, u, 8);
SDEF(short, s, 16);
SDEF(ushort, u, 16);
SDEF(int, s, 32);
SDEF(uint, u, 32);
SDEF(long, s, 64);
SDEF(ulong, u, 64);
#undef SDEF

#define SDEF(TYPE)        \
OVERLOADABLE TYPE popcount(TYPE x){ return __gen_ocl_cbit(x);}
SDEF(char);
SDEF(uchar);
SDEF(short);
SDEF(ushort);
SDEF(int);
SDEF(uint);
#undef SDEF

OVERLOADABLE long popcount(long x) {
  union { int i[2]; long x; } u;
  u.x = x;
  uint v = popcount(u.i[1]);
  v += popcount(u.i[0]);
  return v;
}

OVERLOADABLE ulong popcount(ulong x) {
  union { uint i[2]; ulong x; } u;
  u.x = x;
  uint v = popcount(u.i[1]);
  v += popcount(u.i[0]);
  return v;
}

// sat
#define SDEF(TYPE)        \
OVERLOADABLE TYPE ocl_sadd_sat(TYPE x, TYPE y);   \
OVERLOADABLE TYPE ocl_ssub_sat(TYPE x, TYPE y);   \
OVERLOADABLE TYPE add_sat(TYPE x, TYPE y) { return ocl_sadd_sat(x, y); } \
OVERLOADABLE TYPE sub_sat(TYPE x, TYPE y) { return ocl_ssub_sat(x, y); }
SDEF(char);
SDEF(short);
#undef SDEF
OVERLOADABLE int ocl_sadd_sat(int x, int y);
OVERLOADABLE int add_sat(int x, int y) { return ocl_sadd_sat(x, y); }
OVERLOADABLE int ocl_ssub_sat(int x, int y);
OVERLOADABLE int sub_sat(int x, int y) {
  return (y == 0x80000000u) ? (ocl_sadd_sat(ocl_sadd_sat(0x7fffffff, x), 1)) : ocl_ssub_sat(x, y);
}
OVERLOADABLE long ocl_sadd_sat(long x, long y);
OVERLOADABLE long add_sat(long x, long y) {
  union {long l; uint i[2];} ux, uy;
  ux.l = x;
  uy.l = y;
  if((ux.i[1] ^ uy.i[1]) & 0x80000000u)
    return x + y;
  return ocl_sadd_sat(x, y);
}
OVERLOADABLE long ocl_ssub_sat(long x, long y);
OVERLOADABLE long sub_sat(long x, long y) {
  union {long l; uint i[2];} ux, uy;
  ux.l = x;
  uy.l = y;
  if((ux.i[1] ^ uy.i[1]) & 0x80000000u)
    return ocl_ssub_sat(x, y);
  return x - y;
}
#define UDEF(TYPE)    \
OVERLOADABLE TYPE ocl_uadd_sat(TYPE x, TYPE y);                          \
OVERLOADABLE TYPE ocl_usub_sat(TYPE x, TYPE y);                          \
OVERLOADABLE TYPE add_sat(TYPE x, TYPE y) { return ocl_uadd_sat(x, y); } \
OVERLOADABLE TYPE sub_sat(TYPE x, TYPE y) { return ocl_usub_sat(x, y); }
UDEF(uchar);
UDEF(ushort);
UDEF(uint);
UDEF(ulong);
#undef UDEF

OVERLOADABLE int __gen_ocl_mul_hi(int x, int y);
OVERLOADABLE uint __gen_ocl_mul_hi(uint x, uint y);
OVERLOADABLE long __gen_ocl_mul_hi(long x, long y);
OVERLOADABLE ulong __gen_ocl_mul_hi(ulong x, ulong y);
OVERLOADABLE char mul_hi(char x, char y) { return (x * y) >> 8; }
OVERLOADABLE uchar mul_hi(uchar x, uchar y) { return (x * y) >> 8; }
OVERLOADABLE short mul_hi(short x, short y) { return (x * y) >> 16; }
OVERLOADABLE ushort mul_hi(ushort x, ushort y) { return (x * y) >> 16; }
OVERLOADABLE int mul_hi(int x, int y) { return __gen_ocl_mul_hi(x, y); }
OVERLOADABLE uint mul_hi(uint x, uint y) { return __gen_ocl_mul_hi(x, y); }
OVERLOADABLE long mul_hi(long x, long y) {
  return __gen_ocl_mul_hi(x, y);
}
OVERLOADABLE ulong mul_hi(ulong x, ulong y) {
  return __gen_ocl_mul_hi(x, y);
}

#define DEF(type) OVERLOADABLE type mad_hi(type a, type b, type c) { return mul_hi(a, b) + c; }
DEF(char)
DEF(uchar)
DEF(short)
DEF(ushort)
DEF(int)
DEF(uint)
DEF(long)
DEF(ulong)
#undef DEF

OVERLOADABLE int mul24(int a, int b) { return ((a << 8) >> 8) * ((b << 8) >> 8); }
OVERLOADABLE uint mul24(uint a, uint b) { return (a & 0xFFFFFF) * (b & 0xFFFFFF); }

OVERLOADABLE int mad24(int a, int b, int c) { return mul24(a, b) + c; }
OVERLOADABLE uint mad24(uint a, uint b, uint c) { return mul24(a, b) + c; }

OVERLOADABLE char mad_sat(char a, char b, char c) {
  int x = (int)a * (int)b + (int)c;
  if (x > 127)
    x = 127;
  if (x < -128)
    x = -128;
  return x;
}

OVERLOADABLE uchar mad_sat(uchar a, uchar b, uchar c) {
  uint x = (uint)a * (uint)b + (uint)c;
  if (x > 255)
    x = 255;
  return x;
}

OVERLOADABLE short mad_sat(short a, short b, short c) {
  int x = (int)a * (int)b + (int)c;
  if (x > 32767)
    x = 32767;
  if (x < -32768)
    x = -32768;
  return x;
}

OVERLOADABLE ushort mad_sat(ushort a, ushort b, ushort c) {
  uint x = (uint)a * (uint)b + (uint)c;
  if (x > 65535)
    x = 65535;
  return x;
}

OVERLOADABLE int mad_sat(int a, int b, int c) {
  long x = (long)a * (long)b + (long)c;
  if (x > 0x7FFFFFFF)
    x = 0x7FFFFFFF;
  else if (x < -0x7FFFFFFF-1)
    x = -0x7FFFFFFF-1;
  return (int)x;
}

OVERLOADABLE uint mad_sat(uint a, uint b, uint c) {
  ulong x = (ulong)a * (ulong)b + (ulong)c;
  if (x > 0xFFFFFFFFu)
    x = 0xFFFFFFFFu;
  return (uint)x;
}

OVERLOADABLE long __gen_ocl_mad_sat(long a, long b, long c);
OVERLOADABLE ulong __gen_ocl_mad_sat(ulong a, ulong b, ulong c);

OVERLOADABLE long mad_sat(long a, long b, long c) {
  return __gen_ocl_mad_sat(a, b, c);
}

OVERLOADABLE ulong mad_sat(ulong a, ulong b, ulong c) {
  return __gen_ocl_mad_sat(a, b, c);
}

OVERLOADABLE uchar __rotate_left(uchar x, uchar y) { return (x << y) | (x >> (8 - y)); }
OVERLOADABLE char __rotate_left(char x, char y) { return __rotate_left((uchar)x, (uchar)y); }
OVERLOADABLE ushort __rotate_left(ushort x, ushort y) { return (x << y) | (x >> (16 - y)); }
OVERLOADABLE short __rotate_left(short x, short y) { return __rotate_left((ushort)x, (ushort)y); }
OVERLOADABLE uint __rotate_left(uint x, uint y) { return (x << y) | (x >> (32 - y)); }
OVERLOADABLE int __rotate_left(int x, int y) { return __rotate_left((uint)x, (uint)y); }
OVERLOADABLE ulong __rotate_left(ulong x, ulong y) { return (x << y) | (x >> (64 - y)); }
OVERLOADABLE long __rotate_left(long x, long y) { return __rotate_left((ulong)x, (ulong)y); }
#define DEF(type, m) OVERLOADABLE type rotate(type x, type y) { return __rotate_left(x, (type)(y & m)); }
DEF(char, 7)
DEF(uchar, 7)
DEF(short, 15)
DEF(ushort, 15)
DEF(int, 31)
DEF(uint, 31)
DEF(long, 63)
DEF(ulong, 63)
#undef DEF

OVERLOADABLE short __gen_ocl_upsample(short hi, short lo);
OVERLOADABLE int __gen_ocl_upsample(int hi, int lo);
OVERLOADABLE long __gen_ocl_upsample(long hi, long lo);
OVERLOADABLE short upsample(char hi, uchar lo) { return __gen_ocl_upsample((short)hi, (short)lo); }
OVERLOADABLE ushort upsample(uchar hi, uchar lo) { return __gen_ocl_upsample((short)hi, (short)lo); }
OVERLOADABLE int upsample(short hi, ushort lo) { return __gen_ocl_upsample((int)hi, (int)lo); }
OVERLOADABLE uint upsample(ushort hi, ushort lo) { return __gen_ocl_upsample((int)hi, (int)lo); }
OVERLOADABLE long upsample(int hi, uint lo) {
  return __gen_ocl_upsample((long)hi, (long)lo);
}
OVERLOADABLE ulong upsample(uint hi, uint lo) {
  return __gen_ocl_upsample((long)hi, (long)lo);
}

OVERLOADABLE uint __gen_ocl_hadd(uint x, uint y);
OVERLOADABLE uint __gen_ocl_rhadd(uint x, uint y);
#define DEC DEF(char); DEF(uchar); DEF(short); DEF(ushort)
#define DEF(type) OVERLOADABLE type hadd(type x, type y) { return (x + y) >> 1; }
DEC
#undef DEF
#define DEF(type) OVERLOADABLE type rhadd(type x, type y) { return (x + y + 1) >> 1; }
DEC
#undef DEF
#undef DEC
OVERLOADABLE int hadd(int x, int y) {
  return (x < 0 && y > 0) || (x > 0 && y < 0) ?
         ((x + y) >> 1) :
         __gen_ocl_hadd((uint)x, (uint)y);
}
OVERLOADABLE uint hadd(uint x, uint y) { return __gen_ocl_hadd(x, y); }
OVERLOADABLE int rhadd(int x, int y) {
  return (x < 0 && y > 0) || (x > 0 && y < 0) ?
         ((x + y + 1) >> 1) :
         __gen_ocl_rhadd((uint)x, (uint)y);
 }
OVERLOADABLE uint rhadd(uint x, uint y) { return __gen_ocl_rhadd(x, y); }
OVERLOADABLE ulong __gen_ocl_hadd(ulong x, ulong y);
OVERLOADABLE ulong __gen_ocl_rhadd(ulong x, ulong y);
OVERLOADABLE long hadd(long x, long y) {
  return (x < 0 && y > 0) || (x > 0 && y < 0) ?
         ((x + y) >> 1) :
         __gen_ocl_hadd((ulong)x, (ulong)y);
}
OVERLOADABLE ulong hadd(ulong x, ulong y) {
  return __gen_ocl_hadd(x, y);
}
OVERLOADABLE long rhadd(long x, long y) {
  return (x < 0 && y > 0) || (x > 0 && y < 0) ?
         ((x + y + 1) >> 1) :
         __gen_ocl_rhadd((ulong)x, (ulong)y);
}
OVERLOADABLE ulong rhadd(ulong x, ulong y) {
  return __gen_ocl_rhadd(x, y);
}

PURE CONST OVERLOADABLE char __gen_ocl_abs(char x);
PURE CONST OVERLOADABLE short __gen_ocl_abs(short x);
PURE CONST OVERLOADABLE int __gen_ocl_abs(int x);
#define DEC(TYPE) OVERLOADABLE u##TYPE abs(TYPE x) { return (u##TYPE) __gen_ocl_abs(x); }
DEC(int)
DEC(short)
DEC(char)
#undef DEC
OVERLOADABLE ulong abs(long x) { return x < 0 ? -x : x; }
/* For unsigned types, do nothing. */
#define DEC(TYPE) OVERLOADABLE TYPE abs(TYPE x) { return x; }
DEC(uint)
DEC(ushort)
DEC(uchar)
DEC(ulong)
#undef DEC

/* Char and short type abs diff */
/* promote char and short to int and will be no module overflow */
#define DEC(TYPE, UTYPE) OVERLOADABLE UTYPE abs_diff(TYPE x, TYPE y) \
      { return y > x ? (y -x) : (x - y); }
DEC(char, uchar)
DEC(uchar, uchar)
DEC(short, ushort)
DEC(ushort, ushort)
DEC(int, uint)
DEC(uint, uint)
DEC(long, ulong)
DEC(ulong, ulong)
#undef DEC

#define DECL_MIN_MAX_CLAMP(TYPE) \
OVERLOADABLE TYPE max(TYPE a, TYPE b) { \
  return a > b ? a : b; \
} \
OVERLOADABLE TYPE min(TYPE a, TYPE b) { \
  return a < b ? a : b; \
} \
OVERLOADABLE TYPE clamp(TYPE v, TYPE l, TYPE u) { \
  return max(min(v, u), l); \
}
DECL_MIN_MAX_CLAMP(int)
DECL_MIN_MAX_CLAMP(short)
DECL_MIN_MAX_CLAMP(char)
DECL_MIN_MAX_CLAMP(uint)
DECL_MIN_MAX_CLAMP(unsigned short)
DECL_MIN_MAX_CLAMP(unsigned char)
DECL_MIN_MAX_CLAMP(long)
DECL_MIN_MAX_CLAMP(ulong)
#undef DECL_MIN_MAX_CLAMP

/*
 * Copyright © 2012 - 2014 Intel Corporation
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 *
 */
#include "ocl_integer.h"

PURE CONST uint __gen_ocl_fbh(uint);
PURE CONST uint __gen_ocl_fbl(uint);

PURE CONST OVERLOADABLE uint __gen_ocl_cbit(uint);
PURE CONST OVERLOADABLE uint __gen_ocl_cbit(int);
PURE CONST OVERLOADABLE uint __gen_ocl_cbit(ushort);
PURE CONST OVERLOADABLE uint __gen_ocl_cbit(short);
PURE CONST OVERLOADABLE uint __gen_ocl_cbit(uchar);
PURE CONST OVERLOADABLE uint __gen_ocl_cbit(char);

#define SDEF(TYPE, TYPE_NAME, SIZE)        \
OVERLOADABLE TYPE clz(TYPE x){ return clz_##TYPE_NAME##SIZE(x);}
SDEF(char, s, 8);
SDEF(uchar, u, 8);
SDEF(short, s, 16);
SDEF(ushort, u, 16);
SDEF(int, s, 32);
SDEF(uint, u, 32);
SDEF(long, s, 64);
SDEF(ulong, u, 64);
#undef SDEF

#define SDEF(TYPE)        \
OVERLOADABLE TYPE popcount(TYPE x){ return __gen_ocl_cbit(x);}
SDEF(char);
SDEF(uchar);
SDEF(short);
SDEF(ushort);
SDEF(int);
SDEF(uint);
#undef SDEF

OVERLOADABLE long popcount(long x) {
  union { int i[2]; long x; } u;
  u.x = x;
  uint v = popcount(u.i[1]);
  v += popcount(u.i[0]);
  return v;
}

OVERLOADABLE ulong popcount(ulong x) {
  union { uint i[2]; ulong x; } u;
  u.x = x;
  uint v = popcount(u.i[1]);
  v += popcount(u.i[0]);
  return v;
}

// sat
#define SDEF(TYPE)        \
OVERLOADABLE TYPE ocl_sadd_sat(TYPE x, TYPE y);   \
OVERLOADABLE TYPE ocl_ssub_sat(TYPE x, TYPE y);   \
OVERLOADABLE TYPE add_sat(TYPE x, TYPE y) { return ocl_sadd_sat(x, y); } \
OVERLOADABLE TYPE sub_sat(TYPE x, TYPE y) { return ocl_ssub_sat(x, y); }
SDEF(char);
SDEF(short);
#undef SDEF
OVERLOADABLE int ocl_sadd_sat(int x, int y);
OVERLOADABLE int add_sat(int x, int y) { return ocl_sadd_sat(x, y); }
OVERLOADABLE int ocl_ssub_sat(int x, int y);
OVERLOADABLE int sub_sat(int x, int y) {
  return (y == 0x80000000u) ? (ocl_sadd_sat(ocl_sadd_sat(0x7fffffff, x), 1)) : ocl_ssub_sat(x, y);
}
OVERLOADABLE long ocl_sadd_sat(long x, long y);
OVERLOADABLE long add_sat(long x, long y) {
  union {long l; uint i[2];} ux, uy;
  ux.l = x;
  uy.l = y;
  if((ux.i[1] ^ uy.i[1]) & 0x80000000u)
    return x + y;
  return ocl_sadd_sat(x, y);
}
OVERLOADABLE long ocl_ssub_sat(long x, long y);
OVERLOADABLE long sub_sat(long x, long y) {
  union {long l; uint i[2];} ux, uy;
  ux.l = x;
  uy.l = y;
  if((ux.i[1] ^ uy.i[1]) & 0x80000000u)
    return ocl_ssub_sat(x, y);
  return x - y;
}
#define UDEF(TYPE)    \
OVERLOADABLE TYPE ocl_uadd_sat(TYPE x, TYPE y);                          \
OVERLOADABLE TYPE ocl_usub_sat(TYPE x, TYPE y);                          \
OVERLOADABLE TYPE add_sat(TYPE x, TYPE y) { return ocl_uadd_sat(x, y); } \
OVERLOADABLE TYPE sub_sat(TYPE x, TYPE y) { return ocl_usub_sat(x, y); }
UDEF(uchar);
UDEF(ushort);
UDEF(uint);
UDEF(ulong);
#undef UDEF

OVERLOADABLE int __gen_ocl_mul_hi(int x, int y);
OVERLOADABLE uint __gen_ocl_mul_hi(uint x, uint y);
OVERLOADABLE long __gen_ocl_mul_hi(long x, long y);
OVERLOADABLE ulong __gen_ocl_mul_hi(ulong x, ulong y);
OVERLOADABLE char mul_hi(char x, char y) { return (x * y) >> 8; }
OVERLOADABLE uchar mul_hi(uchar x, uchar y) { return (x * y) >> 8; }
OVERLOADABLE short mul_hi(short x, short y) { return (x * y) >> 16; }
OVERLOADABLE ushort mul_hi(ushort x, ushort y) { return (x * y) >> 16; }
OVERLOADABLE int mul_hi(int x, int y) { return __gen_ocl_mul_hi(x, y); }
OVERLOADABLE uint mul_hi(uint x, uint y) { return __gen_ocl_mul_hi(x, y); }
OVERLOADABLE long mul_hi(long x, long y) {
  return __gen_ocl_mul_hi(x, y);
}
OVERLOADABLE ulong mul_hi(ulong x, ulong y) {
  return __gen_ocl_mul_hi(x, y);
}

#define DEF(type) OVERLOADABLE type mad_hi(type a, type b, type c) { return mul_hi(a, b) + c; }
DEF(char)
DEF(uchar)
DEF(short)
DEF(ushort)
DEF(int)
DEF(uint)
DEF(long)
DEF(ulong)
#undef DEF

OVERLOADABLE int mul24(int a, int b) { return ((a << 8) >> 8) * ((b << 8) >> 8); }
OVERLOADABLE uint mul24(uint a, uint b) { return (a & 0xFFFFFF) * (b & 0xFFFFFF); }

OVERLOADABLE int mad24(int a, int b, int c) { return mul24(a, b) + c; }
OVERLOADABLE uint mad24(uint a, uint b, uint c) { return mul24(a, b) + c; }

OVERLOADABLE char mad_sat(char a, char b, char c) {
  int x = (int)a * (int)b + (int)c;
  if (x > 127)
    x = 127;
  if (x < -128)
    x = -128;
  return x;
}

OVERLOADABLE uchar mad_sat(uchar a, uchar b, uchar c) {
  uint x = (uint)a * (uint)b + (uint)c;
  if (x > 255)
    x = 255;
  return x;
}

OVERLOADABLE short mad_sat(short a, short b, short c) {
  int x = (int)a * (int)b + (int)c;
  if (x > 32767)
    x = 32767;
  if (x < -32768)
    x = -32768;
  return x;
}

OVERLOADABLE ushort mad_sat(ushort a, ushort b, ushort c) {
  uint x = (uint)a * (uint)b + (uint)c;
  if (x > 65535)
    x = 65535;
  return x;
}

OVERLOADABLE int mad_sat(int a, int b, int c) {
  long x = (long)a * (long)b + (long)c;
  if (x > 0x7FFFFFFF)
    x = 0x7FFFFFFF;
  else if (x < -0x7FFFFFFF-1)
    x = -0x7FFFFFFF-1;
  return (int)x;
}

OVERLOADABLE uint mad_sat(uint a, uint b, uint c) {
  ulong x = (ulong)a * (ulong)b + (ulong)c;
  if (x > 0xFFFFFFFFu)
    x = 0xFFFFFFFFu;
  return (uint)x;
}

OVERLOADABLE long __gen_ocl_mad_sat(long a, long b, long c);
OVERLOADABLE ulong __gen_ocl_mad_sat(ulong a, ulong b, ulong c);

OVERLOADABLE long mad_sat(long a, long b, long c) {
  return __gen_ocl_mad_sat(a, b, c);
}

OVERLOADABLE ulong mad_sat(ulong a, ulong b, ulong c) {
  return __gen_ocl_mad_sat(a, b, c);
}

OVERLOADABLE uchar __rotate_left(uchar x, uchar y) { return (x << y) | (x >> (8 - y)); }
OVERLOADABLE char __rotate_left(char x, char y) { return __rotate_left((uchar)x, (uchar)y); }
OVERLOADABLE ushort __rotate_left(ushort x, ushort y) { return (x << y) | (x >> (16 - y)); }
OVERLOADABLE short __rotate_left(short x, short y) { return __rotate_left((ushort)x, (ushort)y); }
OVERLOADABLE uint __rotate_left(uint x, uint y) { return (x << y) | (x >> (32 - y)); }
OVERLOADABLE int __rotate_left(int x, int y) { return __rotate_left((uint)x, (uint)y); }
OVERLOADABLE ulong __rotate_left(ulong x, ulong y) { return (x << y) | (x >> (64 - y)); }
OVERLOADABLE long __rotate_left(long x, long y) { return __rotate_left((ulong)x, (ulong)y); }
#define DEF(type, m) OVERLOADABLE type rotate(type x, type y) { return __rotate_left(x, (type)(y & m)); }
DEF(char, 7)
DEF(uchar, 7)
DEF(short, 15)
DEF(ushort, 15)
DEF(int, 31)
DEF(uint, 31)
DEF(long, 63)
DEF(ulong, 63)
#undef DEF

OVERLOADABLE short __gen_ocl_upsample(short hi, short lo);
OVERLOADABLE int __gen_ocl_upsample(int hi, int lo);
OVERLOADABLE long __gen_ocl_upsample(long hi, long lo);
OVERLOADABLE short upsample(char hi, uchar lo) { return __gen_ocl_upsample((short)hi, (short)lo); }
OVERLOADABLE ushort upsample(uchar hi, uchar lo) { return __gen_ocl_upsample((short)hi, (short)lo); }
OVERLOADABLE int upsample(short hi, ushort lo) { return __gen_ocl_upsample((int)hi, (int)lo); }
OVERLOADABLE uint upsample(ushort hi, ushort lo) { return __gen_ocl_upsample((int)hi, (int)lo); }
OVERLOADABLE long upsample(int hi, uint lo) {
  return __gen_ocl_upsample((long)hi, (long)lo);
}
OVERLOADABLE ulong upsample(uint hi, uint lo) {
  return __gen_ocl_upsample((long)hi, (long)lo);
}

OVERLOADABLE uint __gen_ocl_hadd(uint x, uint y);
OVERLOADABLE uint __gen_ocl_rhadd(uint x, uint y);
#define DEC DEF(char); DEF(uchar); DEF(short); DEF(ushort)
#define DEF(type) OVERLOADABLE type hadd(type x, type y) { return (x + y) >> 1; }
DEC
#undef DEF
#define DEF(type) OVERLOADABLE type rhadd(type x, type y) { return (x + y + 1) >> 1; }
DEC
#undef DEF
#undef DEC
OVERLOADABLE int hadd(int x, int y) {
  return (x < 0 && y > 0) || (x > 0 && y < 0) ?
         ((x + y) >> 1) :
         __gen_ocl_hadd((uint)x, (uint)y);
}
OVERLOADABLE uint hadd(uint x, uint y) { return __gen_ocl_hadd(x, y); }
OVERLOADABLE int rhadd(int x, int y) {
  return (x < 0 && y > 0) || (x > 0 && y < 0) ?
         ((x + y + 1) >> 1) :
         __gen_ocl_rhadd((uint)x, (uint)y);
 }
OVERLOADABLE uint rhadd(uint x, uint y) { return __gen_ocl_rhadd(x, y); }
OVERLOADABLE ulong __gen_ocl_hadd(ulong x, ulong y);
OVERLOADABLE ulong __gen_ocl_rhadd(ulong x, ulong y);
OVERLOADABLE long hadd(long x, long y) {
  return (x < 0 && y > 0) || (x > 0 && y < 0) ?
         ((x + y) >> 1) :
         __gen_ocl_hadd((ulong)x, (ulong)y);
}
OVERLOADABLE ulong hadd(ulong x, ulong y) {
  return __gen_ocl_hadd(x, y);
}
OVERLOADABLE long rhadd(long x, long y) {
  return (x < 0 && y > 0) || (x > 0 && y < 0) ?
         ((x + y + 1) >> 1) :
         __gen_ocl_rhadd((ulong)x, (ulong)y);
}
OVERLOADABLE ulong rhadd(ulong x, ulong y) {
  return __gen_ocl_rhadd(x, y);
}

PURE CONST OVERLOADABLE char __gen_ocl_abs(char x);
PURE CONST OVERLOADABLE short __gen_ocl_abs(short x);
PURE CONST OVERLOADABLE int __gen_ocl_abs(int x);
#define DEC(TYPE) OVERLOADABLE u##TYPE abs(TYPE x) { return (u##TYPE) __gen_ocl_abs(x); }
DEC(int)
DEC(short)
DEC(char)
#undef DEC
OVERLOADABLE ulong abs(long x) { return x < 0 ? -x : x; }
/* For unsigned types, do nothing. */
#define DEC(TYPE) OVERLOADABLE TYPE abs(TYPE x) { return x; }
DEC(uint)
DEC(ushort)
DEC(uchar)
DEC(ulong)
#undef DEC

/* Char and short type abs diff */
/* promote char and short to int and will be no module overflow */
#define DEC(TYPE, UTYPE) OVERLOADABLE UTYPE abs_diff(TYPE x, TYPE y) \
                         { return (UTYPE) (abs((int)x - (int)y)); }
DEC(char, uchar)
DEC(uchar, uchar)
DEC(short, ushort)
DEC(ushort, ushort)
#undef DEC

OVERLOADABLE uint abs_diff (uint x, uint y) {
    /* same signed will never overflow. */
    return y > x ? (y -x) : (x - y);
}

OVERLOADABLE uint abs_diff (int x, int y) {
    /* same signed will never module overflow. */
    if ((x >= 0 && y >= 0) || (x <= 0 && y <= 0))
        return abs(x - y);

    return (abs(x) + abs(y));
}

OVERLOADABLE ulong abs_diff (long x, long y) {
  if ((x >= 0 && y >= 0) || (x <= 0 && y <= 0))
    return abs(x - y);
  return abs(x) + abs(y);
}
OVERLOADABLE ulong abs_diff (ulong x, ulong y) {
  return y > x ? (y - x) : (x - y);
}

#define DECL_MIN_MAX_CLAMP(TYPE) \
OVERLOADABLE TYPE max(TYPE a, TYPE b) { \
  return a > b ? a : b; \
} \
OVERLOADABLE TYPE min(TYPE a, TYPE b) { \
  return a < b ? a : b; \
} \
OVERLOADABLE TYPE clamp(TYPE v, TYPE l, TYPE u) { \
  return max(min(v, u), l); \
}
DECL_MIN_MAX_CLAMP(int)
DECL_MIN_MAX_CLAMP(short)
DECL_MIN_MAX_CLAMP(char)
DECL_MIN_MAX_CLAMP(uint)
DECL_MIN_MAX_CLAMP(unsigned short)
DECL_MIN_MAX_CLAMP(unsigned char)
DECL_MIN_MAX_CLAMP(long)
DECL_MIN_MAX_CLAMP(ulong)
#undef DECL_MIN_MAX_CLAMP


Ported geometry check to OpenCL

Ported geometry check to OpenCL

bool isInsideBulbs(double cReal, double cImag);
bool isInLargerBulb(double cReal, double cImag);
bool isInsideCircle(double centerReal, double centerImag, double radius, double cReal, double cImag);

kernel void iterate_points_double(
    constant const double* cReals,
    constant const double* cImags,
    global int* finalIterations,
    const int maxIterations)
{
    size_t globalId = get_global_id(0);

    double cReal = cReals[globalId];
    double cImag = cImags[globalId];

    if (isInsideBulbs(cReal, cImag))
    {
        finalIterations[globalId] = maxIterations;
        return;
    }

    double zReal = 0;
    double zImag = 0;

    double zReal2 = 0;
    double zImag2 = 0;

    int iterations = 0;

    for (int i = 0; i < maxIterations; i++)
    {
        zImag = 2 * zReal * zImag + cImag;
        zReal = zReal2 - zImag2 + cReal;

        zReal2 = zReal * zReal;
        zImag2 = zImag * zImag;

        // Only increment if the point is still inside the circle
        iterations += (zReal2 + zImag2) <= 4.0;
    }

    finalIterations[globalId] = iterations;
}

bool isInsideBulbs(double cReal, double cImag)
{
    return
        isInLargerBulb(cReal, cImag) ||
        isInsideCircle(-1, 0, 0.25, cReal, cImag) ||
        isInsideCircle(-0.125, 0.744, 0.092, cReal, cImag) ||
        isInsideCircle(-1.308, 0, 0.058, cReal, cImag);
}

bool isInLargerBulb(double cReal, double cImag)
{
    double realMinusFourth = cReal - 0.25;
    double imagSquared = cImag * cImag;
    double q = realMinusFourth * realMinusFourth + imagSquared;

    return (q * (q + realMinusFourth)) < (0.25 * imagSquared);
}

bool isInsideCircle(double centerReal, double centerImag, double radius, double cReal, double cImag)
{
    double translatedReal = cReal - centerReal;
    double translatedImag = cImag - centerImag;

    return (translatedReal*translatedReal + translatedImag*translatedImag) <= (radius * radius);
}

kernel void iterate_points_float(
    constant const float* cReals,
    constant const float* cImags,
    global int* finalIterations,
    const int maxIterations)
{
    size_t globalId = get_global_id(0);

    float cReal = cReals[globalId];
    float cImag = cImags[globalId];

    float zReal = 0;
    float zImag = 0;

    float zReal2 = 0;
    float zImag2 = 0;

    int iterations = 0;

    for (int i = 0; i < maxIterations; i++)
    {
        zImag = 2 * zReal * zImag + cImag;
        zReal = zReal2 - zImag2 + cReal;

        zReal2 = zReal * zReal;
        zImag2 = zImag * zImag;

        // Only increment if the point is still inside the circle
        iterations += (zReal2 + zImag2) <= 4.0;
    }

    finalIterations[globalId] = iterations;
}

kernel void iterate_points(
    constant const double* cReals,
    constant const double* cImags,
    global int* finalIterations,
    const int maxIterations)
{
    // Initialize z
    double zReal = 0;
    double zImag = 0;

    // Initialize z2
    double zReal2 = 0;
    double zImag2 = 0;

    size_t globalId = get_global_id(0);

    double cReal = cReals[globalId];
    double cImag = cImags[globalId];

    int iterations = 0;

    for (int i = 0; i < maxIterations; i++)
    {
        zImag = 2 * zReal * zImag + cImag;
        zReal = zReal2 - zImag2 + cReal;

        zReal2 = zReal * zReal;
        zImag2 = zImag * zImag;

        // Only increment if the point is still inside the circle
        iterations += (zReal2 + zImag2) <= 4.0;
    }

    finalIterations[globalId] = iterations;
}