used abs

used abs

/*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*/

/*
  Usage:
     after compiling this program user gets a single kernel called KF.
     the following flags should be passed:
     1) one of "-D BINARY_OP", "-D UNARY_OP", "-D MASK_BINARY_OP" or "-D MASK_UNARY_OP"
     2) the actual operation performed, one of "-D OP_...", see below the list of operations.
     2a) "-D dstDepth=<destination depth> [-D cn=<num channels]"
         for some operations, like min/max/and/or/xor it's enough
     2b) "-D srcDepth1=<source1 depth> -D srcDepth2=<source2 depth> -D dstDepth=<destination depth>
          -D workDepth=<work depth> [-D cn=<num channels>]" - for mixed-type operations
*/

#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

#if depth <= 5
#define CV_PI M_PI_F
#else
#define CV_PI M_PI
#endif

#ifndef cn
#define cn 1
#endif

#if cn == 1
#undef srcT1_C1
#undef srcT2_C1
#undef dstT_C1
#define srcT1_C1 srcT1
#define srcT2_C1 srcT2
#define dstT_C1 dstT
#endif

#if cn != 3
    #define storedst(val) *(__global dstT *)(dstptr + dst_index) = val
    #define storedst2(val) *(__global dstT *)(dstptr2 + dst_index2) = val
#else
    #define storedst(val) vstore3(val, 0, (__global dstT_C1 *)(dstptr + dst_index))
    #define storedst2(val) vstore3(val, 0, (__global dstT_C1 *)(dstptr2 + dst_index2))
#endif

#define noconvert

#ifndef workT

    #ifndef srcT1
    #define srcT1 dstT
    #endif

    #ifndef srcT1_C1
    #define srcT1_C1 dstT_C1
    #endif

    #ifndef srcT2
    #define srcT2 dstT
    #endif

    #ifndef srcT2_C1
    #define srcT2_C1 dstT_C1
    #endif

    #define workT dstT
    #if cn != 3
        #define srcelem1 *(__global srcT1 *)(srcptr1 + src1_index)
        #define srcelem2 *(__global srcT2 *)(srcptr2 + src2_index)
    #else
        #define srcelem1 vload3(0, (__global srcT1_C1 *)(srcptr1 + src1_index))
        #define srcelem2 vload3(0, (__global srcT2_C1 *)(srcptr2 + src2_index))
    #endif
    #ifndef convertToDT
    #define convertToDT noconvert
    #endif

#else

    #ifndef convertToWT2
    #define convertToWT2 convertToWT1
    #endif
    #if cn != 3
        #define srcelem1 convertToWT1(*(__global srcT1 *)(srcptr1 + src1_index))
        #define srcelem2 convertToWT2(*(__global srcT2 *)(srcptr2 + src2_index))
    #else
        #define srcelem1 convertToWT1(vload3(0, (__global srcT1_C1 *)(srcptr1 + src1_index)))
        #define srcelem2 convertToWT2(vload3(0, (__global srcT2_C1 *)(srcptr2 + src2_index)))
    #endif

#endif

#ifndef workST
#define workST workT
#endif

#define EXTRA_PARAMS
#define EXTRA_INDEX
#define EXTRA_INDEX_ADD

#if defined OP_ADD
#define PROCESS_ELEM storedst(convertToDT(srcelem1 + srcelem2))

#elif defined OP_SUB
#define PROCESS_ELEM storedst(convertToDT(srcelem1 - srcelem2))

#elif defined OP_RSUB
#define PROCESS_ELEM storedst(convertToDT(srcelem2 - srcelem1))

#elif defined OP_ABSDIFF
#if wdepth <= 4
#define PROCESS_ELEM \
    storedst(convertToDT(abs_diff(srcelem1, srcelem2)))
#else
#define PROCESS_ELEM \
    storedst(convertToDT(fabs(srcelem1 - srcelem2)))
#endif

#elif defined OP_AND
#define PROCESS_ELEM storedst(srcelem1 & srcelem2)

#elif defined OP_OR
#define PROCESS_ELEM storedst(srcelem1 | srcelem2)

#elif defined OP_XOR
#define PROCESS_ELEM storedst(srcelem1 ^ srcelem2)

#elif defined OP_NOT
#define PROCESS_ELEM storedst(~srcelem1)

#elif defined OP_MIN
#define PROCESS_ELEM storedst(min(srcelem1, srcelem2))

#elif defined OP_MAX
#define PROCESS_ELEM storedst(max(srcelem1, srcelem2))

#elif defined OP_MUL
#define PROCESS_ELEM storedst(convertToDT(srcelem1 * srcelem2))

#elif defined OP_MUL_SCALE
#undef EXTRA_PARAMS
#ifdef UNARY_OP
#define EXTRA_PARAMS , workST srcelem2_, scaleT scale
#undef srcelem2
#define srcelem2 srcelem2_
#else
#define EXTRA_PARAMS , scaleT scale
#endif
#define PROCESS_ELEM storedst(convertToDT(srcelem1 * scale * srcelem2))

#elif defined OP_DIV
#define PROCESS_ELEM \
        workT e2 = srcelem2, zero = (workT)(0); \
        storedst(convertToDT(e2 != zero ? srcelem1 / e2 : zero))

#elif defined OP_DIV_SCALE
#undef EXTRA_PARAMS
#ifdef UNARY_OP
#define EXTRA_PARAMS , workST srcelem2_, scaleT scale
#undef srcelem2
#define srcelem2 srcelem2_
#else
#define EXTRA_PARAMS , scaleT scale
#endif
#define PROCESS_ELEM \
        workT e2 = srcelem2, zero = (workT)(0); \
        storedst(convertToDT(e2 == zero ? zero : (srcelem1 * (workT)(scale) / e2)))

#elif defined OP_RDIV_SCALE
#undef EXTRA_PARAMS
#ifdef UNARY_OP
#define EXTRA_PARAMS , workST srcelem2_, scaleT scale
#undef srcelem2
#define srcelem2 srcelem2_
#else
#define EXTRA_PARAMS , scaleT scale
#endif
#define PROCESS_ELEM \
        workT e1 = srcelem1, zero = (workT)(0); \
        storedst(convertToDT(e1 == zero ? zero : (srcelem2 * (workT)(scale) / e1)))

#elif defined OP_RECIP_SCALE
#undef EXTRA_PARAMS
#define EXTRA_PARAMS , scaleT scale
#define PROCESS_ELEM \
        workT e1 = srcelem1, zero = (workT)(0); \
        storedst(convertToDT(e1 != zero ? scale / e1 : zero))

#elif defined OP_ADDW
#undef EXTRA_PARAMS
#define EXTRA_PARAMS , scaleT alpha, scaleT beta, scaleT gamma
#if wdepth <= 4
#define PROCESS_ELEM storedst(convertToDT(mad24(srcelem1, alpha, mad24(srcelem2, beta, gamma))))
#else
#define PROCESS_ELEM storedst(convertToDT(fma(srcelem1, alpha, mad(srcelem2, beta, gamma))))
#endif

#elif defined OP_MAG
#define PROCESS_ELEM storedst(hypot(srcelem1, srcelem2))

#elif defined OP_PHASE_RADIANS
#define PROCESS_ELEM \
    workT tmp = atan2(srcelem2, srcelem1); \
    if (tmp < 0) \
        tmp += 6.283185307179586232f; \
    storedst(tmp)

#elif defined OP_PHASE_DEGREES
    #define PROCESS_ELEM \
    workT tmp = degrees(atan2(srcelem2, srcelem1)); \
    if (tmp < 0) \
        tmp += 360; \
    storedst(tmp)

#elif defined OP_EXP
#if wdepth == 5
#define PROCESS_ELEM storedst(native_exp(srcelem1))
#else
#define PROCESS_ELEM storedst(exp(srcelem1))
#endif

#elif defined OP_POW
#define PROCESS_ELEM storedst(pow(srcelem1, srcelem2))

#elif defined OP_POWN
#undef workT
#define workT int
#define PROCESS_ELEM storedst(pown(srcelem1, srcelem2))

#elif defined OP_SQRT
#define PROCESS_ELEM storedst(native_sqrt(srcelem1))

#elif defined OP_LOG
#define PROCESS_ELEM \
    storedst(log(fabs(srcelem1)))

#elif defined OP_CMP
#define srcT2 srcT1
#ifndef convertToWT1
#define convertToWT1
#endif
#define PROCESS_ELEM \
    storedst(srcelem1 CMP_OPERATOR srcelem2 ? (dstT)(255) : (dstT)(0)))

#elif defined OP_CONVERT_SCALE_ABS
#undef EXTRA_PARAMS
#define EXTRA_PARAMS , workT1 alpha, workT1 beta
#if wdepth <= 4
#define PROCESS_ELEM \
    workT value = mad24(srcelem1, (workT)(alpha), (workT)(beta)); \
    storedst(convertToDT(abs(value)))
#else
#define PROCESS_ELEM \
    workT value = fma(srcelem1, (workT)(alpha), (workT)(beta)); \
    storedst(convertToDT(fabs(value)))
#endif

#elif defined OP_SCALE_ADD
#undef EXTRA_PARAMS
#define EXTRA_PARAMS , workT1 alpha
#if wdepth <= 4
#define PROCESS_ELEM storedst(convertToDT(mad24(srcelem1, (workT)(alpha), srcelem2)))
#else
#define PROCESS_ELEM storedst(convertToDT(fma(srcelem1, (workT)(alpha), srcelem2)))
#endif

#elif defined OP_CTP_AD || defined OP_CTP_AR
#if depth <= 5
#define CV_EPSILON FLT_EPSILON
#else
#define CV_EPSILON DBL_EPSILON
#endif
#ifdef OP_CTP_AD
#define TO_DEGREE cartToPolar = degrees(cartToPolar);
#elif defined OP_CTP_AR
#define TO_DEGREE
#endif
#define PROCESS_ELEM \
    dstT x = srcelem1, y = srcelem2; \
    dstT x2 = x * x, y2 = y * y; \
    dstT magnitude = sqrt(x2 + y2); \
    dstT tmp = y >= 0 ? 0 : CV_PI * 2; \
    tmp = x < 0 ? CV_PI : tmp; \
    dstT tmp1 = y >= 0 ? CV_PI * 0.5f : CV_PI * 1.5f; \
    dstT cartToPolar = y2 <= x2 ? x * y / mad((dstT)(0.28f), y2, x2 + CV_EPSILON) + tmp : (tmp1 - x * y / mad((dstT)(0.28f), x2, y2 + CV_EPSILON)); \
    TO_DEGREE \
    storedst(magnitude); \
    storedst2(cartToPolar)

#elif defined OP_PTC_AD || defined OP_PTC_AR
#ifdef OP_PTC_AD
#define FROM_DEGREE y = radians(y)
#else
#define FROM_DEGREE
#endif
#define PROCESS_ELEM \
    dstT x = srcelem1, y = srcelem2, cosval; \
    FROM_DEGREE; \
    storedst2(sincos(y, &srcelem2) * x); \
    storedst(cosval * x);

#elif defined OP_PATCH_NANS
#undef EXTRA_PARAMS
#define EXTRA_PARAMS , dstT val
#define PROCESS_ELEM \
    if (isnan(srcelem1)) \
        storedst(val)

#else
#error "unknown op type"
#endif

#if defined OP_CTP_AD || defined OP_CTP_AR || defined OP_PTC_AD || defined OP_PTC_AR
    #undef EXTRA_PARAMS
    #define EXTRA_PARAMS , __global uchar* dstptr2, int dststep2, int dstoffset2
    #undef EXTRA_INDEX
    #define EXTRA_INDEX int dst_index2 = mad24(y0, dststep2, mad24(x, (int)sizeof(dstT_C1) * cn, dstoffset2))
    #undef EXTRA_INDEX_ADD
    #define EXTRA_INDEX_ADD dst_index2 += dststep2
#endif

#if defined UNARY_OP || defined MASK_UNARY_OP

#if defined OP_AND || defined OP_OR || defined OP_XOR || defined OP_ADD || defined OP_SAT_ADD || \
    defined OP_SUB || defined OP_SAT_SUB || defined OP_RSUB || defined OP_SAT_RSUB || \
    defined OP_ABSDIFF || defined OP_CMP || defined OP_MIN || defined OP_MAX || defined OP_POW || \
    defined OP_MUL || defined OP_DIV || defined OP_POWN
    #undef EXTRA_PARAMS
    #define EXTRA_PARAMS , workST srcelem2_
    #undef srcelem2
    #define srcelem2 srcelem2_
#endif

#if cn == 3
#undef srcelem2
#define srcelem2 (workT)(srcelem2_.x, srcelem2_.y, srcelem2_.z)
#endif

#endif

#if defined BINARY_OP

__kernel void KF(__global const uchar * srcptr1, int srcstep1, int srcoffset1,
                 __global const uchar * srcptr2, int srcstep2, int srcoffset2,
                 __global uchar * dstptr, int dststep, int dstoffset,
                 int rows, int cols EXTRA_PARAMS )
{
    int x = get_global_id(0);
    int y0 = get_global_id(1) * rowsPerWI;

    if (x < cols)
    {
        int src1_index = mad24(y0, srcstep1, mad24(x, (int)sizeof(srcT1_C1) * cn, srcoffset1));
#if !(defined(OP_RECIP_SCALE) || defined(OP_NOT))
        int src2_index = mad24(y0, srcstep2, mad24(x, (int)sizeof(srcT2_C1) * cn, srcoffset2));
#endif
        int dst_index  = mad24(y0, dststep, mad24(x, (int)sizeof(dstT_C1) * cn, dstoffset));
        EXTRA_INDEX;

        for (int y = y0, y1 = min(rows, y0 + rowsPerWI); y < y1; ++y, src1_index += srcstep1, dst_index += dststep)
        {
            PROCESS_ELEM;
#if !(defined(OP_RECIP_SCALE) || defined(OP_NOT))
            src2_index += srcstep2;
#endif
            EXTRA_INDEX_ADD;
        }
    }
}

#elif defined MASK_BINARY_OP

__kernel void KF(__global const uchar * srcptr1, int srcstep1, int srcoffset1,
                 __global const uchar * srcptr2, int srcstep2, int srcoffset2,
                 __global const uchar * mask, int maskstep, int maskoffset,
                 __global uchar * dstptr, int dststep, int dstoffset,
                 int rows, int cols EXTRA_PARAMS )
{
    int x = get_global_id(0);
    int y0 = get_global_id(1) * rowsPerWI;

    if (x < cols)
    {
        int mask_index = mad24(y0, maskstep, x + maskoffset);
        int src1_index = mad24(y0, srcstep1, mad24(x, (int)sizeof(srcT1_C1) * cn, srcoffset1));
        int src2_index = mad24(y0, srcstep2, mad24(x, (int)sizeof(srcT2_C1) * cn, srcoffset2));
        int dst_index  = mad24(y0, dststep, mad24(x, (int)sizeof(dstT_C1) * cn, dstoffset));

        for (int y = y0, y1 = min(rows, y0 + rowsPerWI); y < y1; ++y, src1_index += srcstep1, src2_index += srcstep2,
                                                                mask_index += maskstep, dst_index += dststep)
            if (mask[mask_index])
            {
                PROCESS_ELEM;
            }
    }
}

#elif defined UNARY_OP

__kernel void KF(__global const uchar * srcptr1, int srcstep1, int srcoffset1,
                 __global uchar * dstptr, int dststep, int dstoffset,
                 int rows, int cols EXTRA_PARAMS )
{
    int x = get_global_id(0);
    int y0 = get_global_id(1) * rowsPerWI;

    if (x < cols)
    {
        int src1_index = mad24(y0, srcstep1, mad24(x, (int)sizeof(srcT1_C1) * cn, srcoffset1));
        int dst_index  = mad24(y0, dststep, mad24(x, (int)sizeof(dstT_C1) * cn, dstoffset));

        for (int y = y0, y1 = min(rows, y0 + rowsPerWI); y < y1; ++y, src1_index += srcstep1, dst_index += dststep)
        {
            PROCESS_ELEM;
        }
    }
}

#elif defined MASK_UNARY_OP

__kernel void KF(__global const uchar * srcptr1, int srcstep1, int srcoffset1,
                 __global const uchar * mask, int maskstep, int maskoffset,
                 __global uchar * dstptr, int dststep, int dstoffset,
                 int rows, int cols EXTRA_PARAMS )
{
    int x = get_global_id(0);
    int y0 = get_global_id(1) * rowsPerWI;

    if (x < cols)
    {
        int mask_index = mad24(y0, maskstep, x + maskoffset);
        int src1_index = mad24(y0, srcstep1, mad24(x, (int)sizeof(srcT1_C1) * cn, srcoffset1));
        int dst_index  = mad24(y0, dststep, mad24(x, (int)sizeof(dstT_C1) * cn, dstoffset));

        for (int y = y0, y1 = min(rows, y0 + rowsPerWI); y < y1; ++y, src1_index += srcstep1, mask_index += maskstep, dst_index += dststep)
            if (mask[mask_index])
            {
                PROCESS_ELEM;
            }
    }
}

#else

#error "Unknown operation type"

#endif

/*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*/

/*
  Usage:
     after compiling this program user gets a single kernel called KF.
     the following flags should be passed:
     1) one of "-D BINARY_OP", "-D UNARY_OP", "-D MASK_BINARY_OP" or "-D MASK_UNARY_OP"
     2) the actual operation performed, one of "-D OP_...", see below the list of operations.
     2a) "-D dstDepth=<destination depth> [-D cn=<num channels]"
         for some operations, like min/max/and/or/xor it's enough
     2b) "-D srcDepth1=<source1 depth> -D srcDepth2=<source2 depth> -D dstDepth=<destination depth>
          -D workDepth=<work depth> [-D cn=<num channels>]" - for mixed-type operations
*/

#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

#if depth <= 5
#define CV_PI M_PI_F
#else
#define CV_PI M_PI
#endif

#ifndef cn
#define cn 1
#endif

#if cn == 1
#undef srcT1_C1
#undef srcT2_C1
#undef dstT_C1
#define srcT1_C1 srcT1
#define srcT2_C1 srcT2
#define dstT_C1 dstT
#endif

#if cn != 3
    #define storedst(val) *(__global dstT *)(dstptr + dst_index) = val
    #define storedst2(val) *(__global dstT *)(dstptr2 + dst_index2) = val
#else
    #define storedst(val) vstore3(val, 0, (__global dstT_C1 *)(dstptr + dst_index))
    #define storedst2(val) vstore3(val, 0, (__global dstT_C1 *)(dstptr2 + dst_index2))
#endif

#define noconvert

#ifndef workT

    #ifndef srcT1
    #define srcT1 dstT
    #endif

    #ifndef srcT1_C1
    #define srcT1_C1 dstT_C1
    #endif

    #ifndef srcT2
    #define srcT2 dstT
    #endif

    #ifndef srcT2_C1
    #define srcT2_C1 dstT_C1
    #endif

    #define workT dstT
    #if cn != 3
        #define srcelem1 *(__global srcT1 *)(srcptr1 + src1_index)
        #define srcelem2 *(__global srcT2 *)(srcptr2 + src2_index)
    #else
        #define srcelem1 vload3(0, (__global srcT1_C1 *)(srcptr1 + src1_index))
        #define srcelem2 vload3(0, (__global srcT2_C1 *)(srcptr2 + src2_index))
    #endif
    #ifndef convertToDT
    #define convertToDT noconvert
    #endif

#else

    #ifndef convertToWT2
    #define convertToWT2 convertToWT1
    #endif
    #if cn != 3
        #define srcelem1 convertToWT1(*(__global srcT1 *)(srcptr1 + src1_index))
        #define srcelem2 convertToWT2(*(__global srcT2 *)(srcptr2 + src2_index))
    #else
        #define srcelem1 convertToWT1(vload3(0, (__global srcT1_C1 *)(srcptr1 + src1_index)))
        #define srcelem2 convertToWT2(vload3(0, (__global srcT2_C1 *)(srcptr2 + src2_index)))
    #endif

#endif

#ifndef workST
#define workST workT
#endif

#define EXTRA_PARAMS
#define EXTRA_INDEX
#define EXTRA_INDEX_ADD

#if defined OP_ADD
#define PROCESS_ELEM storedst(convertToDT(srcelem1 + srcelem2))

#elif defined OP_SUB
#define PROCESS_ELEM storedst(convertToDT(srcelem1 - srcelem2))

#elif defined OP_RSUB
#define PROCESS_ELEM storedst(convertToDT(srcelem2 - srcelem1))

#elif defined OP_ABSDIFF
#define PROCESS_ELEM \
    workT v = srcelem1 - srcelem2; \
    storedst(convertToDT(v >= (workT)(0) ? v : -v))

#elif defined OP_AND
#define PROCESS_ELEM storedst(srcelem1 & srcelem2)

#elif defined OP_OR
#define PROCESS_ELEM storedst(srcelem1 | srcelem2)

#elif defined OP_XOR
#define PROCESS_ELEM storedst(srcelem1 ^ srcelem2)

#elif defined OP_NOT
#define PROCESS_ELEM storedst(~srcelem1)

#elif defined OP_MIN
#define PROCESS_ELEM storedst(min(srcelem1, srcelem2))

#elif defined OP_MAX
#define PROCESS_ELEM storedst(max(srcelem1, srcelem2))

#elif defined OP_MUL
#define PROCESS_ELEM storedst(convertToDT(srcelem1 * srcelem2))

#elif defined OP_MUL_SCALE
#undef EXTRA_PARAMS
#ifdef UNARY_OP
#define EXTRA_PARAMS , workST srcelem2_, scaleT scale
#undef srcelem2
#define srcelem2 srcelem2_
#else
#define EXTRA_PARAMS , scaleT scale
#endif
#define PROCESS_ELEM storedst(convertToDT(srcelem1 * scale * srcelem2))

#elif defined OP_DIV
#define PROCESS_ELEM \
        workT e2 = srcelem2, zero = (workT)(0); \
        storedst(convertToDT(e2 != zero ? srcelem1 / e2 : zero))

#elif defined OP_DIV_SCALE
#undef EXTRA_PARAMS
#ifdef UNARY_OP
#define EXTRA_PARAMS , workST srcelem2_, scaleT scale
#undef srcelem2
#define srcelem2 srcelem2_
#else
#define EXTRA_PARAMS , scaleT scale
#endif
#define PROCESS_ELEM \
        workT e2 = srcelem2, zero = (workT)(0); \
        storedst(convertToDT(e2 == zero ? zero : (srcelem1 * (workT)(scale) / e2)))

#elif defined OP_RDIV_SCALE
#undef EXTRA_PARAMS
#ifdef UNARY_OP
#define EXTRA_PARAMS , workST srcelem2_, scaleT scale
#undef srcelem2
#define srcelem2 srcelem2_
#else
#define EXTRA_PARAMS , scaleT scale
#endif
#define PROCESS_ELEM \
        workT e1 = srcelem1, zero = (workT)(0); \
        storedst(convertToDT(e1 == zero ? zero : (srcelem2 * (workT)(scale) / e1)))

#elif defined OP_RECIP_SCALE
#undef EXTRA_PARAMS
#define EXTRA_PARAMS , scaleT scale
#define PROCESS_ELEM \
        workT e1 = srcelem1, zero = (workT)(0); \
        storedst(convertToDT(e1 != zero ? scale / e1 : zero))

#elif defined OP_ADDW
#undef EXTRA_PARAMS
#define EXTRA_PARAMS , scaleT alpha, scaleT beta, scaleT gamma
#if wdepth <= 4
#define PROCESS_ELEM storedst(convertToDT(mad24(srcelem1, alpha, mad24(srcelem2, beta, gamma))))
#else
#define PROCESS_ELEM storedst(convertToDT(fma(srcelem1, alpha, mad(srcelem2, beta, gamma))))
#endif

#elif defined OP_MAG
#define PROCESS_ELEM storedst(hypot(srcelem1, srcelem2))

#elif defined OP_ABS_NOSAT
#define PROCESS_ELEM \
    dstT v = convertToDT(srcelem1); \
    storedst(v >= 0 ? v : -v)

#elif defined OP_PHASE_RADIANS
#define PROCESS_ELEM \
        workT tmp = atan2(srcelem2, srcelem1); \
        if (tmp < 0) \
            tmp += 6.283185307179586232f; \
        storedst(tmp)

#elif defined OP_PHASE_DEGREES
    #define PROCESS_ELEM \
    workT tmp = degrees(atan2(srcelem2, srcelem1)); \
    if (tmp < 0) \
        tmp += 360; \
    storedst(tmp)

#elif defined OP_EXP
#if wdepth == 5
#define PROCESS_ELEM storedst(native_exp(srcelem1))
#else
#define PROCESS_ELEM storedst(exp(srcelem1))
#endif

#elif defined OP_POW
#define PROCESS_ELEM storedst(pow(srcelem1, srcelem2))

#elif defined OP_POWN
#undef workT
#define workT int
#define PROCESS_ELEM storedst(pown(srcelem1, srcelem2))

#elif defined OP_SQRT
#define PROCESS_ELEM storedst(native_sqrt(srcelem1))

#elif defined OP_LOG
#define PROCESS_ELEM \
    dstT v = (dstT)(srcelem1); \
    storedst(v > (dstT)(0) ? log(v) : log(-v))

#elif defined OP_CMP
#define srcT2 srcT1
#ifndef convertToWT1
#define convertToWT1
#endif
#define PROCESS_ELEM \
    workT s1 = srcelem1, s2 = srcelem2; \
    storedst(s1 CMP_OPERATOR s2 ? (dstT)(255) : (dstT)(0))

#elif defined OP_CONVERT_SCALE_ABS
#undef EXTRA_PARAMS
#define EXTRA_PARAMS , workT1 alpha, workT1 beta
#if wdepth <= 4
#define PROCESS_ELEM \
    workT value = mad24(srcelem1, (workT)(alpha), (workT)(beta)); \
    storedst(convertToDT(value >= 0 ? value : -value))
#else
#define PROCESS_ELEM \
    workT value = fma(srcelem1, (workT)(alpha), (workT)(beta)); \
    storedst(convertToDT(value >= 0 ? value : -value))
#endif

#elif defined OP_SCALE_ADD
#undef EXTRA_PARAMS
#define EXTRA_PARAMS , workT1 alpha
#if wdepth <= 4
#define PROCESS_ELEM storedst(convertToDT(mad24(srcelem1, (workT)(alpha), srcelem2)))
#else
#define PROCESS_ELEM storedst(convertToDT(fma(srcelem1, (workT)(alpha), srcelem2)))
#endif

#elif defined OP_CTP_AD || defined OP_CTP_AR
#if depth <= 5
#define CV_EPSILON FLT_EPSILON
#else
#define CV_EPSILON DBL_EPSILON
#endif
#ifdef OP_CTP_AD
#define TO_DEGREE cartToPolar = degrees(cartToPolar);
#elif defined OP_CTP_AR
#define TO_DEGREE
#endif
#define PROCESS_ELEM \
    dstT x = srcelem1, y = srcelem2; \
    dstT x2 = x * x, y2 = y * y; \
    dstT magnitude = sqrt(x2 + y2); \
    dstT tmp = y >= 0 ? 0 : CV_PI * 2; \
    tmp = x < 0 ? CV_PI : tmp; \
    dstT tmp1 = y >= 0 ? CV_PI * 0.5f : CV_PI * 1.5f; \
    dstT cartToPolar = y2 <= x2 ? x * y / mad((dstT)(0.28f), y2, x2 + CV_EPSILON) + tmp : (tmp1 - x * y / mad((dstT)(0.28f), x2, y2 + CV_EPSILON)); \
    TO_DEGREE \
    storedst(magnitude); \
    storedst2(cartToPolar)

#elif defined OP_PTC_AD || defined OP_PTC_AR
#ifdef OP_PTC_AD
#define FROM_DEGREE y = radians(y)
#else
#define FROM_DEGREE
#endif
#define PROCESS_ELEM \
    dstT x = srcelem1, y = srcelem2, cosval; \
    FROM_DEGREE; \
    storedst2(sincos(y, &srcelem2) * x); \
    storedst(cosval * x);

#elif defined OP_PATCH_NANS
#undef EXTRA_PARAMS
#define EXTRA_PARAMS , dstT val
#define PROCESS_ELEM \
    if (isnan(srcelem1)) \
        storedst(val)

#else
#error "unknown op type"
#endif

#if defined OP_CTP_AD || defined OP_CTP_AR || defined OP_PTC_AD || defined OP_PTC_AR
    #undef EXTRA_PARAMS
    #define EXTRA_PARAMS , __global uchar* dstptr2, int dststep2, int dstoffset2
    #undef EXTRA_INDEX
    #define EXTRA_INDEX int dst_index2 = mad24(y0, dststep2, mad24(x, (int)sizeof(dstT_C1) * cn, dstoffset2))
    #undef EXTRA_INDEX_ADD
    #define EXTRA_INDEX_ADD dst_index2 += dststep2
#endif

#if defined UNARY_OP || defined MASK_UNARY_OP

#if defined OP_AND || defined OP_OR || defined OP_XOR || defined OP_ADD || defined OP_SAT_ADD || \
    defined OP_SUB || defined OP_SAT_SUB || defined OP_RSUB || defined OP_SAT_RSUB || \
    defined OP_ABSDIFF || defined OP_CMP || defined OP_MIN || defined OP_MAX || defined OP_POW || \
    defined OP_MUL || defined OP_DIV || defined OP_POWN
    #undef EXTRA_PARAMS
    #define EXTRA_PARAMS , workST srcelem2_
    #undef srcelem2
    #define srcelem2 srcelem2_
#endif

#if cn == 3
#undef srcelem2
#define srcelem2 (workT)(srcelem2_.x, srcelem2_.y, srcelem2_.z)
#endif

#endif

#if defined BINARY_OP

__kernel void KF(__global const uchar * srcptr1, int srcstep1, int srcoffset1,
                 __global const uchar * srcptr2, int srcstep2, int srcoffset2,
                 __global uchar * dstptr, int dststep, int dstoffset,
                 int rows, int cols EXTRA_PARAMS )
{
    int x = get_global_id(0);
    int y0 = get_global_id(1) * rowsPerWI;

    if (x < cols)
    {
        int src1_index = mad24(y0, srcstep1, mad24(x, (int)sizeof(srcT1_C1) * cn, srcoffset1));
#if !(defined(OP_RECIP_SCALE) || defined(OP_NOT))
        int src2_index = mad24(y0, srcstep2, mad24(x, (int)sizeof(srcT2_C1) * cn, srcoffset2));
#endif
        int dst_index  = mad24(y0, dststep, mad24(x, (int)sizeof(dstT_C1) * cn, dstoffset));
        EXTRA_INDEX;

        for (int y = y0, y1 = min(rows, y0 + rowsPerWI); y < y1; ++y, src1_index += srcstep1, dst_index += dststep)
        {
            PROCESS_ELEM;
#if !(defined(OP_RECIP_SCALE) || defined(OP_NOT))
            src2_index += srcstep2;
#endif
            EXTRA_INDEX_ADD;
        }
    }
}

#elif defined MASK_BINARY_OP

__kernel void KF(__global const uchar * srcptr1, int srcstep1, int srcoffset1,
                 __global const uchar * srcptr2, int srcstep2, int srcoffset2,
                 __global const uchar * mask, int maskstep, int maskoffset,
                 __global uchar * dstptr, int dststep, int dstoffset,
                 int rows, int cols EXTRA_PARAMS )
{
    int x = get_global_id(0);
    int y0 = get_global_id(1) * rowsPerWI;

    if (x < cols)
    {
        int mask_index = mad24(y0, maskstep, x + maskoffset);
        int src1_index = mad24(y0, srcstep1, mad24(x, (int)sizeof(srcT1_C1) * cn, srcoffset1));
        int src2_index = mad24(y0, srcstep2, mad24(x, (int)sizeof(srcT2_C1) * cn, srcoffset2));
        int dst_index  = mad24(y0, dststep, mad24(x, (int)sizeof(dstT_C1) * cn, dstoffset));

        for (int y = y0, y1 = min(rows, y0 + rowsPerWI); y < y1; ++y, src1_index += srcstep1, src2_index += srcstep2,
                                                                mask_index += maskstep, dst_index += dststep)
            if (mask[mask_index])
            {
                PROCESS_ELEM;
            }
    }
}

#elif defined UNARY_OP

__kernel void KF(__global const uchar * srcptr1, int srcstep1, int srcoffset1,
                 __global uchar * dstptr, int dststep, int dstoffset,
                 int rows, int cols EXTRA_PARAMS )
{
    int x = get_global_id(0);
    int y0 = get_global_id(1) * rowsPerWI;

    if (x < cols)
    {
        int src1_index = mad24(y0, srcstep1, mad24(x, (int)sizeof(srcT1_C1) * cn, srcoffset1));
        int dst_index  = mad24(y0, dststep, mad24(x, (int)sizeof(dstT_C1) * cn, dstoffset));

        for (int y = y0, y1 = min(rows, y0 + rowsPerWI); y < y1; ++y, src1_index += srcstep1, dst_index += dststep)
        {
            PROCESS_ELEM;
        }
    }
}

#elif defined MASK_UNARY_OP

__kernel void KF(__global const uchar * srcptr1, int srcstep1, int srcoffset1,
                 __global const uchar * mask, int maskstep, int maskoffset,
                 __global uchar * dstptr, int dststep, int dstoffset,
                 int rows, int cols EXTRA_PARAMS )
{
    int x = get_global_id(0);
    int y0 = get_global_id(1) * rowsPerWI;

    if (x < cols)
    {
        int mask_index = mad24(y0, maskstep, x + maskoffset);
        int src1_index = mad24(y0, srcstep1, mad24(x, (int)sizeof(srcT1_C1) * cn, srcoffset1));
        int dst_index  = mad24(y0, dststep, mad24(x, (int)sizeof(dstT_C1) * cn, dstoffset));

        for (int y = y0, y1 = min(rows, y0 + rowsPerWI); y < y1; ++y, src1_index += srcstep1, mask_index += maskstep, dst_index += dststep)
            if (mask[mask_index])
            {
                PROCESS_ELEM;
            }
    }
}

#else

#error "Unknown operation type"

#endif


cl demosaic: fix kernel typo and move 10 to 16 bits

 * fix typo
 * bit shfit was done in black level corretion, demosaic only need
   consider 16bits not 10 bits.

/*
 * function: kernel_demosaic
 * input:    image2d_t as read only
 * output:   image2d_t as write only
 */

"__kernel void kernel_demosaic (__read_only image2d_t input, __write_only image2d_t output)    "
"{                                                                                "
"    int x = 2 * get_global_id (0);                                                            "
"    int y = 2 * get_global_id (1);                                                            "
"    sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_NONE | CLK_FILTER_NEAREST;  "
//"    sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST;  "

"                                                                                "
"    int x0 = x - 1;                                                                           "
"    int y0 = y - 1;                                                                           "
"    float4 p[16];                                                                             "
"    for (int i = 0; i < 16; ++i) {                                                            "
"        p[i] = read_imagef (input, sampler, (int2)(x0 + i % 4, y0 + i / 4));                  "
"    }                                                                                "
"                                                                                "
"    float4 p00, p01, p10, p11;                                                                "
"    p00.x = (p[4].x + p[6].x) / 2.0;                                                          "
"    p00.y = (p[5].x * 4 + p[0].x + p[2].x + p[8].x + p[10].x) / 8.0;                          "
"    p00.z = (p[1].x + p[9].x) / 2.0;                                                          "
"    p01.x = p[6].x;                                                                           "
"    p01.y = (p[2].x + p[5].x + p[7].x+ p[10].x) / 4.0;                                        "
"    p01.z = (p[1].x + p[3].x + p[9].x+ p[11].x) / 4.0;                                        "
"    p10.x = (p[4].x + p[6].x + p[12].x+ p[14].x) / 4.0;                                       "
"    p10.y = (p[5].x + p[8].x + p[10].x+ p[13].x) / 4.0;                                       "
"    p10.z = p[9].x;                                                                           "
"    p11.x = (p[6].x + p[14].x) / 2.0;                                                         "
"    p11.y = (p[10].x * 4 + p[5].x + p[7].x + p[13].x + p[15].x) / 8.0;                        "
"    p11.z = (p[9].x + p[11].x) / 2.0;                                                         "
"                                                                                "
"    write_imagef (output, (int2)(x, y), p00);                                                 "
"    write_imagef (output, (int2)(x + 1, y), p01);                                             "
"    write_imagef (output, (int2)(x, y + 1), p10);                                             "
"    write_imagef (output, (int2)(x + 1, y + 1), p11);                                         "
"}                                                                                "

/*
 * function: kernel_demosaic
 * input:    image2d_t as read only
 * output:   image2d_t as write only
 */

"__kernel void kernel_demosaic (__read_only image2d_t input, __write_only image2d_t output)    "
"{                                                                                "
"    int x = 2 * get_global_id (0);                                                            "
"    int y = 2 * get_global_id (1);                                                            "
"    sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_NONE | CLK_FILTER_NEAREST;  "
//"    sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST;  "

"                                                                                "
"    int x0 = x - 1;                                                                           "
"    int y0 = y - 1;                                                                           "
"    float4 p[16];                                                                             "
"    for (int i = 0; i < 16; ++i) {                                                            "
"        p[i] = read_imagef (input, sampler, (int2)(x0 + i % 4, y0 + i / 4));                  "
"        p[i].x *= 64.0;                                                                       "
"    }                                                                                "
"                                                                                "
"    float4 p00, p01, p10, p11;                                                                "
"    p00.x = (p[4].x + p[6].x) / 2.0;                                                          "
"    p00.y = (p[5].x * 4 + p[0].x + p[2].x + p[8].x + p[10].x) / 8.0;                          "
"    p00.z = (p[1].x + p[9].x) / 2.0;                                                          "
"    p01.x = p[6].x;                                                                           "
"    p01.y = (p[2].x + p[5].x + p[7].x+ p[10].x) / 4.0;                                        "
"    p01.z = (p[1].x + p[3].x + p[9].x+ p[11].x) / 4.0;                                        "
"    p10.x = (p[4].x + p[6].x + p[12].x+ p[14].x) / 4.0;                                       "
"    p10.y = (p[5].x + p[8].x + p[10].x+ p[13].x) / 4.0;                                       "
"    p10.z = p[9].x;                                                                           "
"    p11.x = (p[6].x + p[14].x) / 2.0;                                                         "
"    p11.y = (p[10].x * 4 + p[5].x + p[7].x + p[13].x + p[15].x) / 8.0;                        "
"    p11.z = (p[9].x + p[11].x) / 2.0;                                                         "
"                                                                                "
"    write_imagef (output, (int2)(x, y), p00);                                                 "
"    write_imagef (output, (int2)(x + 1, y), p01);                                             "
"    write_imagef (output, (int2)(x, y + 1), p10);                                             "
"    write_imagef (output, (int2)(x + 1, y + 1), p10);                                         "
"}                                                                                "


Fix whitespaces.

Fix whitespaces.

/*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-2013, Multicoreware, Inc., all rights reserved.
// Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// @Authors
//    Peng Xiao, pengxiao@multicorewareinc.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 oclMaterials 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 Intel Corporation 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*/

//data (which is float) is aligend in 32 bytes
#define WIDTH_MULTIPLE (32 >> 2)

/////////////////////////////////////////////////////////
//*******************************************************
// basicretinafilter
//////////////// _spatiotemporalLPfilter ////////////////
//_horizontalCausalFilter_addInput
kernel void horizontalCausalFilter_addInput(
    global const float * input,
    global float * output,
    const int cols,
    const int rows,
    const int elements_per_row,
    const int in_offset,
    const int out_offset,
    const float _tau,
    const float _a
)
{
    int gid = get_global_id(0);
    if(gid >= rows)
    {
        return;
    }

    global const float * iptr =
        input  + mad24(gid, elements_per_row, in_offset / 4);
    global float * optr =
        output + mad24(gid, elements_per_row, out_offset / 4);

    float res;
    float4 in_v4, out_v4, res_v4 = (float4)(0);
    //vectorize to increase throughput
    for(int i = 0; i < cols / 4; ++i, iptr += 4, optr += 4)
    {
        in_v4  = vload4(0, iptr);
        out_v4 = vload4(0, optr);

        res_v4.x = in_v4.x + _tau * out_v4.x + _a * res_v4.w;
        res_v4.y = in_v4.y + _tau * out_v4.y + _a * res_v4.x;
        res_v4.z = in_v4.z + _tau * out_v4.z + _a * res_v4.y;
        res_v4.w = in_v4.w + _tau * out_v4.w + _a * res_v4.z;

        vstore4(res_v4, 0, optr);
    }
    res = res_v4.w;
    // there may be left some
    for(int i = 0; i < cols % 4;  ++i, ++iptr, ++optr)
    {
        res = *iptr + _tau * *optr + _a * res;
        *optr = res;
    }
}

//_horizontalAnticausalFilter
kernel void horizontalAnticausalFilter(
    global float * output,
    const int cols,
    const int rows,
    const int elements_per_row,
    const int out_offset,
    const float _a
)
{
    int gid = get_global_id(0);
    if(gid >= rows)
    {
        return;
    }

    global float * optr = output +
                          mad24(gid + 1, elements_per_row, - 1 + out_offset / 4);

    float4 result_v4 = (float4)(0), out_v4;
    float result = 0;
    // we assume elements_per_row is multple of WIDTH_MULTIPLE
    for(int i = 0; i < WIDTH_MULTIPLE; ++ i, -- optr)
    {
        if(i >= elements_per_row - cols)
        {
            result = *optr + _a * result;
        }
        *optr = result;
    }
    result_v4.x = result;
    optr -= 3;
    for(int i = WIDTH_MULTIPLE / 4; i < elements_per_row / 4; ++i, optr -= 4)
    {
        // shift left, `offset` is type `size_t` so it cannot be negative
        out_v4 = vload4(0, optr);

        result_v4.w = out_v4.w + _a * result_v4.x;
        result_v4.z = out_v4.z + _a * result_v4.w;
        result_v4.y = out_v4.y + _a * result_v4.z;
        result_v4.x = out_v4.x + _a * result_v4.y;

        vstore4(result_v4, 0, optr);
    }
}

//_verticalCausalFilter
kernel void verticalCausalFilter(
    global float * output,
    const int cols,
    const int rows,
    const int elements_per_row,
    const int out_offset,
    const float _a
)
{
    int gid = get_global_id(0);
    if(gid >= cols)
    {
        return;
    }

    global float * optr = output + gid + out_offset / 4;
    float result = 0;
    for(int i = 0; i < rows; ++i, optr += elements_per_row)
    {
        result = *optr + _a * result;
        *optr = result;
    }
}

//_verticalCausalFilter
kernel void verticalAnticausalFilter_multGain(
    global float * output,
    const int cols,
    const int rows,
    const int elements_per_row,
    const int out_offset,
    const float _a,
    const float _gain
)
{
    int gid = get_global_id(0);
    if(gid >= cols)
    {
        return;
    }

    global float * optr = output + (rows - 1) * elements_per_row + gid + out_offset / 4;
    float result = 0;
    for(int i = 0; i < rows; ++i, optr -= elements_per_row)
    {
        result = *optr + _a * result;
        *optr = _gain * result;
    }
}
//
// end of _spatiotemporalLPfilter
/////////////////////////////////////////////////////////////////////

//////////////// horizontalAnticausalFilter_Irregular ////////////////
kernel void horizontalAnticausalFilter_Irregular(
    global float * output,
    global float * buffer,
    const int cols,
    const int rows,
    const int elements_per_row,
    const int out_offset,
    const int buffer_offset
)
{
    int gid = get_global_id(0);
    if(gid >= rows)
    {
        return;
    }

    global float * optr =
        output + mad24(rows - gid, elements_per_row, -1 + out_offset / 4);
    global float * bptr =
        buffer + mad24(rows - gid, elements_per_row, -1 + buffer_offset / 4);

    float4 buf_v4, out_v4, res_v4 = (float4)(0);
    float result = 0;
    // we assume elements_per_row is multple of WIDTH_MULTIPLE
    for(int i = 0; i < WIDTH_MULTIPLE; ++ i, -- optr, -- bptr)
    {
        if(i >= elements_per_row - cols)
        {
            result = *optr + *bptr * result;
        }
        *optr = result;
    }
    res_v4.x = result;
    optr -= 3;
    bptr -= 3;
    for(int i = WIDTH_MULTIPLE / 4; i < elements_per_row / 4; ++i, optr -= 4, bptr -= 4)
    {
        buf_v4 = vload4(0, bptr);
        out_v4 = vload4(0, optr);

        res_v4.w = out_v4.w + buf_v4.w * res_v4.x;
        res_v4.z = out_v4.z + buf_v4.z * res_v4.w;
        res_v4.y = out_v4.y + buf_v4.y * res_v4.z;
        res_v4.x = out_v4.x + buf_v4.x * res_v4.y;

        vstore4(res_v4, 0, optr);
    }
}

//////////////// verticalCausalFilter_Irregular ////////////////
kernel void verticalCausalFilter_Irregular(
    global float * output,
    global float * buffer,
    const int cols,
    const int rows,
    const int elements_per_row,
    const int out_offset,
    const int buffer_offset
)
{
    int gid = get_global_id(0);
    if(gid >= cols)
    {
        return;
    }

    global float * optr = output + gid + out_offset / 4;
    global float * bptr = buffer + gid + buffer_offset / 4;
    float result = 0;
    for(int i = 0; i < rows; ++i, optr += elements_per_row, bptr += elements_per_row)
    {
        result = *optr + *bptr * result;
        *optr = result;
    }
}

//////////////// _adaptiveHorizontalCausalFilter_addInput ////////////////
kernel void adaptiveHorizontalCausalFilter_addInput(
    global const float * input,
    global const float * gradient,
    global float * output,
    const int cols,
    const int rows,
    const int elements_per_row,
    const int in_offset,
    const int grad_offset,
    const int out_offset
)
{
    int gid = get_global_id(0);
    if(gid >= rows)
    {
        return;
    }

    global const float * iptr =
        input + mad24(gid, elements_per_row, in_offset / 4);
    global const float * gptr =
        gradient + mad24(gid, elements_per_row, grad_offset / 4);
    global float * optr =
        output + mad24(gid, elements_per_row, out_offset / 4);

    float4 in_v4, grad_v4, out_v4, res_v4 = (float4)(0);
    for(int i = 0; i < cols / 4; ++i, iptr += 4, gptr += 4, optr += 4)
    {
        in_v4   = vload4(0, iptr);
        grad_v4 = vload4(0, gptr);

        res_v4.x = in_v4.x + grad_v4.x * res_v4.w;
        res_v4.y = in_v4.y + grad_v4.y * res_v4.x;
        res_v4.z = in_v4.z + grad_v4.z * res_v4.y;
        res_v4.w = in_v4.w + grad_v4.w * res_v4.z;

        vstore4(res_v4, 0, optr);
    }
    for(int i = 0; i < cols % 4; ++i, ++iptr, ++gptr, ++optr)
    {
        res_v4.w = *iptr + *gptr * res_v4.w;
        *optr = res_v4.w;
    }
}

//////////////// _adaptiveVerticalAnticausalFilter_multGain ////////////////
kernel void adaptiveVerticalAnticausalFilter_multGain(
    global const float * gradient,
    global float * output,
    const int cols,
    const int rows,
    const int elements_per_row,
    const int grad_offset,
    const int out_offset,
    const float gain
)
{
    int gid = get_global_id(0);
    if(gid >= cols)
    {
        return;
    }

    int start_idx = mad24(rows - 1, elements_per_row, gid);

    global const float * gptr = gradient + start_idx + grad_offset / 4;
    global float * optr = output + start_idx + out_offset / 4;

    float result = 0;
    for(int i = 0; i < rows; ++i, gptr -= elements_per_row, optr -= elements_per_row)
    {
        result = *optr + *gptr * result;
        *optr = gain * result;
    }
}

//////////////// _localLuminanceAdaptation ////////////////
// FIXME:
//  This kernel seems to have precision problem on GPU
kernel void localLuminanceAdaptation(
    global const float * luma,
    global const float * input,
    global float * output,
    const int cols,
    const int rows,
    const int elements_per_row,
    const float _localLuminanceAddon,
    const float _localLuminanceFactor,
    const float _maxInputValue
)
{
    int gidx = get_global_id(0), gidy = get_global_id(1);
    if(gidx >= cols || gidy >= rows)
    {
        return;
    }
    int offset = mad24(gidy, elements_per_row, gidx);

    float X0 = luma[offset] * _localLuminanceFactor + _localLuminanceAddon;
    float input_val = input[offset];
    // output of the following line may be different between GPU and CPU
    output[offset] = (_maxInputValue + X0) * input_val / (input_val + X0 + 0.00000000001f);
}
// end of basicretinafilter
//*******************************************************
/////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////
//******************************************************
// magno
// TODO: this kernel has too many buffer accesses, better to make it
//   vector read/write for fetch efficiency
kernel void amacrineCellsComputing(
    global const float * opl_on,
    global const float * opl_off,
    global float * prev_in_on,
    global float * prev_in_off,
    global float * out_on,
    global float * out_off,
    const int cols,
    const int rows,
    const int elements_per_row,
    const float coeff
)
{
    int gidx = get_global_id(0), gidy = get_global_id(1);
    if(gidx >= cols || gidy >= rows)
    {
        return;
    }

    int offset = mad24(gidy, elements_per_row, gidx);
    opl_on      += offset;
    opl_off     += offset;
    prev_in_on  += offset;
    prev_in_off += offset;
    out_on      += offset;
    out_off     += offset;

    float magnoXonPixelResult = coeff * (*out_on + *opl_on - *prev_in_on);
    *out_on = fmax(magnoXonPixelResult, 0);
    float magnoXoffPixelResult = coeff * (*out_off + *opl_off - *prev_in_off);
    *out_off = fmax(magnoXoffPixelResult, 0);

    *prev_in_on = *opl_on;
    *prev_in_off = *opl_off;
}

/////////////////////////////////////////////////////////
//******************************************************
// parvo
// TODO: this kernel has too many buffer accesses, needs optimization
kernel void OPL_OnOffWaysComputing(
    global float4 * photo_out,
    global float4 * horiz_out,
    global float4 * bipol_on,
    global float4 * bipol_off,
    global float4 * parvo_on,
    global float4 * parvo_off,
    const int cols,
    const int rows,
    const int elements_per_row
)
{
    int gidx = get_global_id(0), gidy = get_global_id(1);
    if(gidx * 4 >= cols || gidy >= rows)
    {
        return;
    }
    // we assume elements_per_row must be multiples of 4
    int offset = mad24(gidy, elements_per_row >> 2, gidx);
    photo_out += offset;
    horiz_out += offset;
    bipol_on  += offset;
    bipol_off += offset;
    parvo_on  += offset;
    parvo_off += offset;

    float4 diff = *photo_out - *horiz_out;
    float4 isPositive;// = convert_float4(diff > (float4)(0.0f, 0.0f, 0.0f, 0.0f));
    isPositive.x = diff.x > 0.0f;
    isPositive.y = diff.y > 0.0f;
    isPositive.z = diff.z > 0.0f;
    isPositive.w = diff.w > 0.0f;
    float4 res_on  = isPositive * diff;
    float4 res_off = (isPositive - (float4)(1.0f)) * diff;

    *bipol_on = res_on;
    *parvo_on = res_on;

    *bipol_off = res_off;
    *parvo_off = res_off;
}

/////////////////////////////////////////////////////////
//******************************************************
// retinacolor
inline int bayerSampleOffset(int step, int rows, int x, int y)
{
    return mad24(y, step, x) +
           ((y % 2) + (x % 2)) * rows * step;
}

/////// colorMultiplexing //////
kernel void runColorMultiplexingBayer(
    global const float * input,
    global float * output,
    const int cols,
    const int rows,
    const int elements_per_row
)
{
    int gidx = get_global_id(0), gidy = get_global_id(1);
    if(gidx >= cols || gidy >= rows)
    {
        return;
    }

    int offset = mad24(gidy, elements_per_row, gidx);
    output[offset] = input[bayerSampleOffset(elements_per_row, rows, gidx, gidy)];
}

kernel void runColorDemultiplexingBayer(
    global const float * input,
    global float * output,
    const int cols,
    const int rows,
    const int elements_per_row
)
{
    int gidx = get_global_id(0), gidy = get_global_id(1);
    if(gidx >= cols || gidy >= rows)
    {
        return;
    }

    int offset = mad24(gidy, elements_per_row, gidx);
    output[bayerSampleOffset(elements_per_row, rows, gidx, gidy)] = input[offset];
}

kernel void demultiplexAssign(
    global const float * input,
    global float * output,
    const int cols,
    const int rows,
    const int elements_per_row
)
{
    int gidx = get_global_id(0), gidy = get_global_id(1);
    if(gidx >= cols || gidy >= rows)
    {
        return;
    }

    int offset = bayerSampleOffset(elements_per_row, rows, gidx, gidy);
    output[offset] = input[offset];
}

//// normalizeGrayOutputCentredSigmoide
kernel void normalizeGrayOutputCentredSigmoide(
    global const float * input,
    global float * output,
    const int cols,
    const int rows,
    const int elements_per_row,
    const float meanval,
    const float X0
)

{
    int gidx = get_global_id(0), gidy = get_global_id(1);
    if(gidx >= cols || gidy >= rows)
    {
        return;
    }
    int offset = mad24(gidy, elements_per_row, gidx);

    float input_val = input[offset];
    output[offset] = meanval +
                     (meanval + X0) * (input_val - meanval) / (fabs(input_val - meanval) + X0);
}

//// normalize by photoreceptors density
kernel void normalizePhotoDensity(
    global const float * chroma,
    global const float * colorDensity,
    global const float * multiplex,
    global float * luma,
    global float * demultiplex,
    const int cols,
    const int rows,
    const int elements_per_row,
    const float pG
)
{
    const int gidx = get_global_id(0), gidy = get_global_id(1);
    if(gidx >= cols || gidy >= rows)
    {
        return;
    }
    const int offset = mad24(gidy, elements_per_row, gidx);
    int index = offset;

    float Cr = chroma[index] * colorDensity[index];
    index += elements_per_row * rows;
    float Cg = chroma[index] * colorDensity[index];
    index += elements_per_row * rows;
    float Cb = chroma[index] * colorDensity[index];

    const float luma_res = (Cr + Cg + Cb) * pG;
    luma[offset] = luma_res;
    demultiplex[bayerSampleOffset(elements_per_row, rows, gidx, gidy)] =
        multiplex[offset] - luma_res;
}

//////// computeGradient ///////
// TODO:
// this function maybe accelerated by image2d_t or lds
kernel void computeGradient(
    global const float * luma,
    global float * gradient,
    const int cols,
    const int rows,
    const int elements_per_row
)
{
    int gidx = get_global_id(0) + 2, gidy = get_global_id(1) + 2;
    if(gidx >= cols - 2 || gidy >= rows - 2)
    {
        return;
    }
    int offset = mad24(gidy, elements_per_row, gidx);
    luma += offset;

    // horizontal and vertical local gradients
    const float v_grad = fabs(luma[elements_per_row] - luma[- elements_per_row]);
    const float h_grad = fabs(luma[1] - luma[-1]);

    // neighborhood horizontal and vertical gradients
    const float cur_val  = luma[0];
    const float v_grad_p = fabs(cur_val - luma[- 2 * elements_per_row]);
    const float h_grad_p = fabs(cur_val - luma[- 2]);
    const float v_grad_n = fabs(cur_val - luma[2 * elements_per_row]);
    const float h_grad_n = fabs(cur_val - luma[2]);

    const float horiz_grad = 0.5f * h_grad + 0.25f * (h_grad_p + h_grad_n);
    const float verti_grad = 0.5f * v_grad + 0.25f * (v_grad_p + v_grad_n);
    const bool is_vertical_greater = horiz_grad < verti_grad;

    gradient[offset + elements_per_row * rows] = is_vertical_greater ? 0.06f : 0.57f;
    gradient[offset                          ] = is_vertical_greater ? 0.57f : 0.06f;
}

/////// substractResidual ///////
kernel void substractResidual(
    global float * input,
    const int cols,
    const int rows,
    const int elements_per_row,
    const float pR,
    const float pG,
    const float pB
)
{
    const int gidx = get_global_id(0), gidy = get_global_id(1);
    if(gidx >= cols || gidy >= rows)
    {
        return;
    }
    int indices [3] =
    {
        mad24(gidy, elements_per_row, gidx),
        mad24(gidy + rows, elements_per_row, gidx),
        mad24(gidy + 2 * rows, elements_per_row, gidx)
    };
    float vals[3] = {input[indices[0]], input[indices[1]], input[indices[2]]};
    float residu = pR * vals[0] + pG * vals[1] + pB * vals[2];

    input[indices[0]] = vals[0] - residu;
    input[indices[1]] = vals[1] - residu;
    input[indices[2]] = vals[2] - residu;
}

///// clipRGBOutput_0_maxInputValue /////
kernel void clipRGBOutput_0_maxInputValue(
    global float * input,
    const int cols,
    const int rows,
    const int elements_per_row,
    const float maxVal
)
{
    const int gidx = get_global_id(0), gidy = get_global_id(1);
    if(gidx >= cols || gidy >= rows)
    {
        return;
    }
    const int offset = mad24(gidy, elements_per_row, gidx);
    float val = input[offset];
    val = clamp(val, 0.0f, maxVal);
    input[offset] = val;
}

//// normalizeGrayOutputNearZeroCentreredSigmoide ////
kernel void normalizeGrayOutputNearZeroCentreredSigmoide(
    global float * input,
    global float * output,
    const int cols,
    const int rows,
    const int elements_per_row,
    const float maxVal,
    const float X0cube
)
{
    const int gidx = get_global_id(0), gidy = get_global_id(1);
    if(gidx >= cols || gidy >= rows)
    {
        return;
    }
    const int offset = mad24(gidy, elements_per_row, gidx);
    float currentCubeLuminance = input[offset];
    currentCubeLuminance = currentCubeLuminance * currentCubeLuminance * currentCubeLuminance;
    output[offset] = currentCubeLuminance * X0cube / (X0cube + currentCubeLuminance);
}

//// centerReductImageLuminance ////
kernel void centerReductImageLuminance(
    global float * input,
    const int cols,
    const int rows,
    const int elements_per_row,
    const float mean,
    const float std_dev
)
{
    const int gidx = get_global_id(0), gidy = get_global_id(1);
    if(gidx >= cols || gidy >= rows)
    {
        return;
    }
    const int offset = mad24(gidy, elements_per_row, gidx);

    float val = input[offset];
    input[offset] = (val - mean) / std_dev;
}

//// inverseValue ////
kernel void inverseValue(
    global float * input,
    const int cols,
    const int rows,
    const int elements_per_row
)
{
    const int gidx = get_global_id(0), gidy = get_global_id(1);
    if(gidx >= cols || gidy >= rows)
    {
        return;
    }
    const int offset = mad24(gidy, elements_per_row, gidx);
    input[offset] = 1.f / input[offset];
}

#define CV_PI 3.1415926535897932384626433832795

//// _processRetinaParvoMagnoMapping ////
kernel void processRetinaParvoMagnoMapping(
    global float * parvo,
    global float * magno,
    global float * output,
    const int cols,
    const int rows,
    const int halfCols,
    const int halfRows,
    const int elements_per_row,
    const float minDistance
)
{
    const int gidx = get_global_id(0), gidy = get_global_id(1);
    if(gidx >= cols || gidy >= rows)
    {
        return;
    }
    const int offset = mad24(gidy, elements_per_row, gidx);

    float distanceToCenter =
        sqrt(((float)(gidy - halfRows) * (gidy - halfRows) + (gidx - halfCols) * (gidx - halfCols)));

    float a = distanceToCenter < minDistance ?
              (0.5f + 0.5f * (float)cos(CV_PI * distanceToCenter / minDistance)) : 0;
    float b = 1.f - a;

    output[offset] = parvo[offset] * a + magno[offset] * b;
}


Fixed the bwd bias kernel

Fixed the bwd bias kernel

/*******************************************************************************
 *
 * MIT License
 *
 * Copyright (c) 2017 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 *******************************************************************************/
#define PPCAT_NX(A, B) A##B
#define PPCAT(A, B) PPCAT_NX(A, B)
#define TWO 2
#define FOUR 4
#define EIGHT 8

#if MIOPEN_USE_FP16 == 1
#pragma OPENCL EXTENSION cl_khr_fp16 : enable
#define _FLOAT half
#endif
#if MIOPEN_USE_FP32 == 1
#define _FLOAT float
#endif

#define _FLOAT2 PPCAT(_FLOAT, TWO)
#define _FLOAT4 PPCAT(_FLOAT, FOUR)
#define _FLOAT8 PPCAT(_FLOAT, EIGHT)

static inline int iDiv(int v, int d)
{
    int r = (int)((float)v / d + 0.00001f);
    return (r);
}

static inline int iMod(int v, int u, int d)
{
    int r = v - mul24((int)u, (int)d);
    return (r);
}

static inline void ReduceKernel(__local _FLOAT* lcl_mem, int sum_stride, int unit_id, int unit_len)
{
    _FLOAT sum     = (_FLOAT)(0);
    int lcl_offset = unit_id * unit_len;
    for(int i = 0; i < unit_len; i += sum_stride)
    {
        sum += lcl_mem[lcl_offset + i];
    }
    lcl_mem[lcl_offset] = sum;
}

__attribute__((reqd_work_group_size(MLO_CONVBWD_GROUP_SZ0, MLO_CONVBWD_GROUP_SZ1, 1))) __kernel void
MIOpenConvBwdB(const __global _FLOAT* top_df, __global _FLOAT* bias_df)
{
    int lid        = (int)get_local_id(0);
    int output_map = get_group_id(1);

    __local _FLOAT lcl_sum[MLO_CONVBWDB_LCL_MEMSZ];
    _FLOAT sum = (_FLOAT)(0);

    for(int j = lid; j < MLO_WK_SIZE * MLO_OUT_BATCH_SZ; j += MLO_CONVBWD_GROUP_SZ0)
    {
        int map_id            = iDiv(j, MLO_WK_SIZE);
        int read_id           = iMod(j, map_id, MLO_WK_SIZE);
        int glb_top_df_offset = output_map * MLO_OUT_CHANNEL_STRIDE +
                                (map_id * MLO_OUT_BATCH_STRIDE) + (read_id * MLO_CONVBWDB_UNITSIZE);
#if MLO_N_PIX_OFF
        if(read_id == MLO_WK_SIZE - 1)
        {
            for(int k = 0; k < MLO_N_PIX_OFF; k++)
                sum += top_df[glb_top_df_offset + k];
        }
        else
        {
            for(int k = 0; k < MLO_CONVBWDB_UNITSIZE; k++)
                sum += top_df[glb_top_df_offset + k];
        }
#else
        for(int k = 0; k < MLO_CONVBWDB_UNITSIZE; k++)
            sum += top_df[glb_top_df_offset + k];
#endif
    }
    lcl_sum[lid] = sum;

    barrier(CLK_LOCAL_MEM_FENCE);

    // Reduction over a work-grp: 256 -> 64 -> 16 -> 1
    if(lid < (MLO_CONVBWD_GROUP_SZ0 >> 2))
    {
        ReduceKernel(lcl_sum, 1, lid, 4);
    }
    barrier(CLK_LOCAL_MEM_FENCE);

    if(lid < (MLO_CONVBWD_GROUP_SZ0 >> 4))
    {
        ReduceKernel(lcl_sum, 4, lid, 16);
    }
    barrier(CLK_LOCAL_MEM_FENCE);

    if(lid == 0)
    {
        ReduceKernel(lcl_sum, 16, lid, 256);
    }
    barrier(CLK_LOCAL_MEM_FENCE);

    bias_df[output_map] = lcl_sum[0];
}

/*******************************************************************************
 *
 * MIT License
 *
 * Copyright (c) 2017 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 *******************************************************************************/
#define PPCAT_NX(A, B) A##B
#define PPCAT(A, B) PPCAT_NX(A, B)
#define TWO 2
#define FOUR 4
#define EIGHT 8

#if MIOPEN_USE_FP16 == 1
#pragma OPENCL EXTENSION cl_khr_fp16 : enable
#define _FLOAT half
#endif
#if MIOPEN_USE_FP32 == 1
#define _FLOAT float
#endif

#define _FLOAT2 PPCAT(_FLOAT, TWO)
#define _FLOAT4 PPCAT(_FLOAT, FOUR)
#define _FLOAT8 PPCAT(_FLOAT, EIGHT)

static inline int iDiv(int v, int d)
{
    int r = (int)((float)v / d + 0.00001f);
    return (r);
}

static inline int iMod(int v, int u, int d)
{
    int r = v - mul24((int)u, (int)d);
    return (r);
}

static inline void ReduceKernel(__local _FLOAT* lcl_mem, int sum_stride, int unit_id, int unit_len)
{
    _FLOAT sum     = (_FLOAT)(0);
    int lcl_offset = unit_id * unit_len;
    for(int i = 0; i < unit_len; i += sum_stride)
    {
        sum += lcl_mem[lcl_offset + i];
    }
    lcl_mem[lcl_offset] = sum;
}

__attribute__((reqd_work_group_size(MLO_CONVBWD_GROUP_SZ0, MLO_CONVBWD_GROUP_SZ1, 1))) __kernel void
MIOpenConvBwdB(const __global _FLOAT* top_df, __global _FLOAT* bias_df)
{
    int lid        = (int)get_local_id(0);
    int output_map = get_group_id(1);

    __local _FLOAT lcl_sum[MLO_CONVBWDB_LCL_MEMSZ];
    _FLOAT sum = (_FLOAT)(0);

    for(int j = lid; j < MLO_WK_SIZE * MLO_OUT_BATCH_SZ; j += MLO_CONVBWD_GROUP_SZ0)
    {
        int map_id            = iDiv(j, MLO_WK_SIZE);
        int read_id           = iMod(j, map_id, MLO_WK_SIZE);
        int glb_top_df_offset = output_map * MLO_OUT_CHANNEL_STRIDE +
                                (map_id * MLO_OUT_BATCH_STRIDE) + (read_id * MLO_CONVBWDB_UNITSIZE);
#if MLO_N_PIX_OFF
        if(read_id == MLO_WK_SIZE - 1)
        {
            for(int k = 0; k < MLO_N_PIX_OFF; k++)
                sum += top_df[glb_top_df_offset + k];
        }
#else
        for(int k = 0; k < MLO_CONVBWDB_UNITSIZE; k++)
            sum += top_df[glb_top_df_offset + k];
#endif
    }
    lcl_sum[lid] = sum;

    barrier(CLK_LOCAL_MEM_FENCE);

    // Reduction over a work-grp: 256 -> 64 -> 16 -> 1
    if(lid < (MLO_CONVBWD_GROUP_SZ0 >> 2))
    {
        ReduceKernel(lcl_sum, 1, lid, 4);
    }
    barrier(CLK_LOCAL_MEM_FENCE);

    if(lid < (MLO_CONVBWD_GROUP_SZ0 >> 4))
    {
        ReduceKernel(lcl_sum, 4, lid, 16);
    }
    barrier(CLK_LOCAL_MEM_FENCE);

    if(lid == 0)
    {
        ReduceKernel(lcl_sum, 16, lid, 256);
    }
    barrier(CLK_LOCAL_MEM_FENCE);

    bias_df[output_map] = lcl_sum[0];
}


fix stereobm crash on some cpu ocl

fix stereobm crash on some cpu ocl

/*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.
// Third party copyrights are property of their respective owners.
//
// @Authors
//    Jia Haipeng, jiahaipeng95@gmail.com
//    Sen Liu, swjtuls1987@126.com
//    Peng Xiao, pengxiao@outlook.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 oclMaterials 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 Intel Corporation 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*/

#define ROWSperTHREAD 21     // the number of rows a thread will process
#define BLOCK_W       128    // the thread block width (464)
#define N_DISPARITIES 8

#define STEREO_MIND 0                    // The minimum d range to check
#define STEREO_DISP_STEP N_DISPARITIES   // the d step, must be <= 1 to avoid aliasing

#ifndef radius
#define radius 64
#endif

unsigned int CalcSSD(__local unsigned int *col_ssd)
{
    unsigned int cache = col_ssd[0];

#pragma unroll
    for(int i = 1; i <= (radius << 1); i++)
        cache += col_ssd[i];

    return cache;
}

uint2 MinSSD(__local unsigned int *col_ssd)
{
    unsigned int ssd[N_DISPARITIES];
    const int win_size = (radius << 1);

    //See above:  #define COL_SSD_SIZE (BLOCK_W + WIN_SIZE)
    ssd[0] = CalcSSD(col_ssd + 0 * (BLOCK_W + win_size));
    ssd[1] = CalcSSD(col_ssd + 1 * (BLOCK_W + win_size));
    ssd[2] = CalcSSD(col_ssd + 2 * (BLOCK_W + win_size));
    ssd[3] = CalcSSD(col_ssd + 3 * (BLOCK_W + win_size));
    ssd[4] = CalcSSD(col_ssd + 4 * (BLOCK_W + win_size));
    ssd[5] = CalcSSD(col_ssd + 5 * (BLOCK_W + win_size));
    ssd[6] = CalcSSD(col_ssd + 6 * (BLOCK_W + win_size));
    ssd[7] = CalcSSD(col_ssd + 7 * (BLOCK_W + win_size));

    unsigned int mssd = min(min(min(ssd[0], ssd[1]), min(ssd[4], ssd[5])), min(min(ssd[2], ssd[3]), min(ssd[6], ssd[7])));

    int bestIdx = 0;

    for (int i = 0; i < N_DISPARITIES; i++)
    {
        if (mssd == ssd[i])
            bestIdx = i;
    }

    return (uint2)(mssd, bestIdx);
}

void StepDown(int idx1, int idx2, __global unsigned char* imageL,
              __global unsigned char* imageR, int d,   __local unsigned int *col_ssd)
{
    uint8 imgR1 = convert_uint8(vload8(0, imageR + (idx1 - d - 7)));
    uint8 imgR2 = convert_uint8(vload8(0, imageR + (idx2 - d - 7)));
    uint8 diff1 = (uint8)(imageL[idx1]) - imgR1;
    uint8 diff2 = (uint8)(imageL[idx2]) - imgR2;
    uint8 res = diff2 * diff2 - diff1 * diff1;
    const int win_size = (radius << 1);
    col_ssd[0 * (BLOCK_W + win_size)] += res.s7;
    col_ssd[1 * (BLOCK_W + win_size)] += res.s6;
    col_ssd[2 * (BLOCK_W + win_size)] += res.s5;
    col_ssd[3 * (BLOCK_W + win_size)] += res.s4;
    col_ssd[4 * (BLOCK_W + win_size)] += res.s3;
    col_ssd[5 * (BLOCK_W + win_size)] += res.s2;
    col_ssd[6 * (BLOCK_W + win_size)] += res.s1;
    col_ssd[7 * (BLOCK_W + win_size)] += res.s0;
}

void InitColSSD(int x_tex, int y_tex, int im_pitch, __global unsigned char* imageL,
                __global unsigned char* imageR, int d,
                 __local unsigned int *col_ssd)
{
    uint8 leftPixel1;
    uint8 diffa = 0;
    int idx = y_tex * im_pitch + x_tex;
    const int win_size = (radius << 1);
    for(int i = 0; i < (win_size + 1); i++)
    {
        leftPixel1 = (uint8)(imageL[idx]);
        uint8 imgR = convert_uint8(vload8(0, imageR + (idx - d - 7)));
        uint8 res = leftPixel1 - imgR;
        diffa += res * res;

        idx += im_pitch;
    }
    //See above:  #define COL_SSD_SIZE (BLOCK_W + WIN_SIZE)
    col_ssd[0 * (BLOCK_W + win_size)] = diffa.s7;
    col_ssd[1 * (BLOCK_W + win_size)] = diffa.s6;
    col_ssd[2 * (BLOCK_W + win_size)] = diffa.s5;
    col_ssd[3 * (BLOCK_W + win_size)] = diffa.s4;
    col_ssd[4 * (BLOCK_W + win_size)] = diffa.s3;
    col_ssd[5 * (BLOCK_W + win_size)] = diffa.s2;
    col_ssd[6 * (BLOCK_W + win_size)] = diffa.s1;
    col_ssd[7 * (BLOCK_W + win_size)] = diffa.s0;
}

__kernel void stereoKernel(__global unsigned char *left, __global unsigned char *right,
                           __global unsigned int *cminSSDImage, int cminSSD_step,
                           __global unsigned char *disp, int disp_step,int cwidth, int cheight,
                           int img_step, int maxdisp,
                           __local unsigned int *col_ssd_cache)
{
    __local unsigned int *col_ssd = col_ssd_cache + get_local_id(0);
    __local unsigned int *col_ssd_extra = get_local_id(0) < (radius << 1) ? col_ssd + BLOCK_W : 0;

    int X = get_group_id(0) * BLOCK_W + get_local_id(0) + maxdisp + radius;

#define Y (get_group_id(1) * ROWSperTHREAD + radius)

    __global unsigned int* minSSDImage = cminSSDImage + X + Y * cminSSD_step;
    __global unsigned char* disparImage = disp + X + Y * disp_step;

    int end_row = ROWSperTHREAD < (cheight - Y) ? ROWSperTHREAD:(cheight - Y);
    int y_tex;
    int x_tex = X - radius;

    //if (x_tex >= cwidth)
    //    return;

    for(int d = STEREO_MIND; d < maxdisp; d += STEREO_DISP_STEP)
    {
        y_tex = Y - radius;

        InitColSSD(x_tex, y_tex, img_step, left, right, d, col_ssd);
        if (col_ssd_extra > 0)
            if (x_tex + BLOCK_W < cwidth)
                InitColSSD(x_tex + BLOCK_W, y_tex, img_step, left, right, d, col_ssd_extra);

        barrier(CLK_LOCAL_MEM_FENCE); //before MinSSD function

        uint2 minSSD = MinSSD(col_ssd);
        if (X < cwidth - radius && Y < cheight - radius)
        {
            if (minSSD.x < minSSDImage[0])
            {
                disparImage[0] = (unsigned char)(d + minSSD.y);
                minSSDImage[0] = minSSD.x;
            }
        }

        for(int row = 1; row < end_row; row++)
        {
            int idx1 = y_tex * img_step + x_tex;
            int idx2 = min(y_tex + ((radius << 1) + 1), cheight - 1) * img_step + x_tex;

            barrier(CLK_LOCAL_MEM_FENCE);

            StepDown(idx1, idx2, left, right, d, col_ssd);
            if (col_ssd_extra > 0)
                if (x_tex + BLOCK_W < cwidth)
                    StepDown(idx1, idx2, left + BLOCK_W, right + BLOCK_W, d, col_ssd_extra);

            barrier(CLK_LOCAL_MEM_FENCE);

            uint2 minSSD = MinSSD(col_ssd);
            if (X < cwidth - radius && row < cheight - radius - Y)
            {
                int idx = row * cminSSD_step;
                if (minSSD.x < minSSDImage[idx])
                {
                    disparImage[disp_step * row] = (unsigned char)(d + minSSD.y);
                    minSSDImage[idx] = minSSD.x;
                }
            }

            y_tex++;
        } // for row loop
    } // for d loop
}
//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////// Sobel Prefiler (signal channel)//////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////

__kernel void prefilter_xsobel(__global unsigned char *input, __global unsigned char *output,
                               int rows, int cols, int prefilterCap)
{
    int x = get_global_id(0);
    int y = get_global_id(1);

    if(x < cols && y < rows)
    {
        int cov = input[(y-1) * cols + (x-1)] * (-1) + input[(y-1) * cols + (x+1)] * (1) +
                  input[(y)   * cols + (x-1)] * (-2) + input[(y)   * cols + (x+1)] * (2) +
                  input[(y+1) * cols + (x-1)] * (-1) + input[(y+1) * cols + (x+1)] * (1);

        cov = min(min(max(-prefilterCap, cov), prefilterCap) + prefilterCap, 255);
        output[y * cols + x] = cov & 0xFF;
    }
}

//////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////// Textureness filtering ////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////

float sobel(__global unsigned char *input, int x, int y, int rows, int cols)
{
    float conv = 0;
    int y1 = y==0? 0 : y-1;
    int x1 = x==0? 0 : x-1;
    if(x < cols && y < rows && x > 0 && y > 0)
    {
        conv = (float)input[(y1)  * cols + (x1)] * (-1) + (float)input[(y1)  * cols + (x+1)] * (1) +
               (float)input[(y)   * cols + (x1)] * (-2) + (float)input[(y)   * cols + (x+1)] * (2) +
               (float)input[(y+1) * cols + (x1)] * (-1) + (float)input[(y+1) * cols + (x+1)] * (1);

    }
    return fabs(conv);
}

float CalcSums(__local float *cols, __local float *cols_cache, int winsz)
{
    float cache = 0;
    float cache2 = 0;
    int winsz2 = winsz/2;

    int x = get_local_id(0);
    int group_size_x = get_local_size(0);

    for(int i = 1; i <= winsz2; i++)
        cache += cols[i];

    cols_cache[0] = cache;

    barrier(CLK_LOCAL_MEM_FENCE);

    if (x < group_size_x - winsz2)
        cache2 = cols_cache[winsz2];
    else
        for(int i = winsz2 + 1; i < winsz; i++)
            cache2 += cols[i];

    return cols[0] + cache + cache2;
}

#define RpT (2 * ROWSperTHREAD)  // got experimentally
__kernel void textureness_kernel(__global unsigned char *disp, int disp_rows, int disp_cols,
                                 int disp_step, __global unsigned char *input, int input_rows,
                                 int input_cols,int winsz, float threshold,
                                 __local float *cols_cache)
{
    int winsz2 = winsz/2;
    int n_dirty_pixels = (winsz2) * 2;

    int local_id_x = get_local_id(0);
    int group_size_x = get_local_size(0);
    int group_id_y = get_group_id(1);

    __local float *cols = cols_cache + group_size_x + local_id_x;
    __local float *cols_extra = local_id_x < n_dirty_pixels ? cols + group_size_x : 0;

    int x = get_global_id(0);
    int beg_row = group_id_y * RpT;
    int end_row = min(beg_row + RpT, disp_rows);

//   if (x < disp_cols)
//   {
    int y = beg_row;

    float sum = 0;
    float sum_extra = 0;

    for(int i = y - winsz2; i <= y + winsz2; ++i)
    {
        sum += sobel(input, x - winsz2, i, input_rows, input_cols);
        if (cols_extra)
            sum_extra += sobel(input, x + group_size_x - winsz2, i, input_rows, input_cols);
    }
    *cols = sum;
    if (cols_extra)
        *cols_extra = sum_extra;

    barrier(CLK_LOCAL_MEM_FENCE);

    float sum_win = CalcSums(cols, cols_cache + local_id_x, winsz) * 255;
    if (sum_win < threshold)
        disp[y * disp_step + x] = 0;

    barrier(CLK_LOCAL_MEM_FENCE);

    for(int y = beg_row + 1; y < end_row; ++y)
    {
        sum = sum - sobel(input, x - winsz2, y - winsz2 - 1, input_rows, input_cols) +
              sobel(input, x - winsz2, y + winsz2, input_rows, input_cols);
        *cols = sum;

        if (cols_extra)
        {
            sum_extra = sum_extra - sobel(input, x + group_size_x - winsz2, y - winsz2 - 1,input_rows, input_cols)
                        + sobel(input, x + group_size_x - winsz2, y + winsz2, input_rows, input_cols);
            *cols_extra = sum_extra;
        }

        barrier(CLK_LOCAL_MEM_FENCE);
        float sum_win = CalcSums(cols, cols_cache + local_id_x, winsz) * 255;
        if (sum_win < threshold)
            disp[y * disp_step + x] = 0;

        barrier(CLK_LOCAL_MEM_FENCE);
    }
    //  }
}

/*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.
// Third party copyrights are property of their respective owners.
//
// @Authors
//    Jia Haipeng, jiahaipeng95@gmail.com
//    Sen Liu, swjtuls1987@126.com
//    Peng Xiao, pengxiao@outlook.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 oclMaterials 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 Intel Corporation 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*/

#define ROWSperTHREAD 21     // the number of rows a thread will process
#define BLOCK_W       128    // the thread block width (464)
#define N_DISPARITIES 8

#define STEREO_MIND 0                    // The minimum d range to check
#define STEREO_DISP_STEP N_DISPARITIES   // the d step, must be <= 1 to avoid aliasing

#ifndef radius
#define radius 64
#endif

unsigned int CalcSSD(__local unsigned int *col_ssd)
{
    unsigned int cache = col_ssd[0];

#pragma unroll
    for(int i = 1; i <= (radius << 1); i++)
        cache += col_ssd[i];

    return cache;
}

uint2 MinSSD(__local unsigned int *col_ssd)
{
    unsigned int ssd[N_DISPARITIES];
    const int win_size = (radius << 1);

    //See above:  #define COL_SSD_SIZE (BLOCK_W + WIN_SIZE)
    ssd[0] = CalcSSD(col_ssd + 0 * (BLOCK_W + win_size));
    ssd[1] = CalcSSD(col_ssd + 1 * (BLOCK_W + win_size));
    ssd[2] = CalcSSD(col_ssd + 2 * (BLOCK_W + win_size));
    ssd[3] = CalcSSD(col_ssd + 3 * (BLOCK_W + win_size));
    ssd[4] = CalcSSD(col_ssd + 4 * (BLOCK_W + win_size));
    ssd[5] = CalcSSD(col_ssd + 5 * (BLOCK_W + win_size));
    ssd[6] = CalcSSD(col_ssd + 6 * (BLOCK_W + win_size));
    ssd[7] = CalcSSD(col_ssd + 7 * (BLOCK_W + win_size));

    unsigned int mssd = min(min(min(ssd[0], ssd[1]), min(ssd[4], ssd[5])), min(min(ssd[2], ssd[3]), min(ssd[6], ssd[7])));

    int bestIdx = 0;

    for (int i = 0; i < N_DISPARITIES; i++)
    {
        if (mssd == ssd[i])
            bestIdx = i;
    }

    return (uint2)(mssd, bestIdx);
}

void StepDown(int idx1, int idx2, __global unsigned char* imageL,
              __global unsigned char* imageR, int d,   __local unsigned int *col_ssd)
{
    uint8 imgR1 = convert_uint8(vload8(0, imageR + (idx1 - d - 7)));
    uint8 imgR2 = convert_uint8(vload8(0, imageR + (idx2 - d - 7)));
    uint8 diff1 = (uint8)(imageL[idx1]) - imgR1;
    uint8 diff2 = (uint8)(imageL[idx2]) - imgR2;
    uint8 res = diff2 * diff2 - diff1 * diff1;
    const int win_size = (radius << 1);
    col_ssd[0 * (BLOCK_W + win_size)] += res.s7;
    col_ssd[1 * (BLOCK_W + win_size)] += res.s6;
    col_ssd[2 * (BLOCK_W + win_size)] += res.s5;
    col_ssd[3 * (BLOCK_W + win_size)] += res.s4;
    col_ssd[4 * (BLOCK_W + win_size)] += res.s3;
    col_ssd[5 * (BLOCK_W + win_size)] += res.s2;
    col_ssd[6 * (BLOCK_W + win_size)] += res.s1;
    col_ssd[7 * (BLOCK_W + win_size)] += res.s0;
}

void InitColSSD(int x_tex, int y_tex, int im_pitch, __global unsigned char* imageL,
                __global unsigned char* imageR, int d,
                 __local unsigned int *col_ssd)
{
    uint8 leftPixel1;
    uint8 diffa = 0;
    int idx = y_tex * im_pitch + x_tex;
    const int win_size = (radius << 1);
    for(int i = 0; i < (win_size + 1); i++)
    {
        leftPixel1 = (uint8)(imageL[idx]);
        uint8 imgR = convert_uint8(vload8(0, imageR + (idx - d - 7)));
        uint8 res = leftPixel1 - imgR;
        diffa += res * res;

        idx += im_pitch;
    }
    //See above:  #define COL_SSD_SIZE (BLOCK_W + WIN_SIZE)
    col_ssd[0 * (BLOCK_W + win_size)] = diffa.s7;
    col_ssd[1 * (BLOCK_W + win_size)] = diffa.s6;
    col_ssd[2 * (BLOCK_W + win_size)] = diffa.s5;
    col_ssd[3 * (BLOCK_W + win_size)] = diffa.s4;
    col_ssd[4 * (BLOCK_W + win_size)] = diffa.s3;
    col_ssd[5 * (BLOCK_W + win_size)] = diffa.s2;
    col_ssd[6 * (BLOCK_W + win_size)] = diffa.s1;
    col_ssd[7 * (BLOCK_W + win_size)] = diffa.s0;
}

__kernel void stereoKernel(__global unsigned char *left, __global unsigned char *right,
                           __global unsigned int *cminSSDImage, int cminSSD_step,
                           __global unsigned char *disp, int disp_step,int cwidth, int cheight,
                           int img_step, int maxdisp,
                           __local unsigned int *col_ssd_cache)
{
    __local unsigned int *col_ssd = col_ssd_cache + get_local_id(0);
    __local unsigned int *col_ssd_extra = get_local_id(0) < (radius << 1) ? col_ssd + BLOCK_W : 0;

    int X = get_group_id(0) * BLOCK_W + get_local_id(0) + maxdisp + radius;

#define Y (get_group_id(1) * ROWSperTHREAD + radius)

    __global unsigned int* minSSDImage = cminSSDImage + X + Y * cminSSD_step;
    __global unsigned char* disparImage = disp + X + Y * disp_step;

    int end_row = ROWSperTHREAD < (cheight - Y) ? ROWSperTHREAD:(cheight - Y);
    int y_tex;
    int x_tex = X - radius;

    if (x_tex >= cwidth)
        return;

    for(int d = STEREO_MIND; d < maxdisp; d += STEREO_DISP_STEP)
    {
        y_tex = Y - radius;

        InitColSSD(x_tex, y_tex, img_step, left, right, d, col_ssd);
        if (col_ssd_extra > 0)
            if (x_tex + BLOCK_W < cwidth)
                InitColSSD(x_tex + BLOCK_W, y_tex, img_step, left, right, d, col_ssd_extra);

        barrier(CLK_LOCAL_MEM_FENCE); //before MinSSD function

        uint2 minSSD = MinSSD(col_ssd);
        if (X < cwidth - radius && Y < cheight - radius)
        {
            if (minSSD.x < minSSDImage[0])
            {
                disparImage[0] = (unsigned char)(d + minSSD.y);
                minSSDImage[0] = minSSD.x;
            }
        }

        for(int row = 1; row < end_row; row++)
        {
            int idx1 = y_tex * img_step + x_tex;
            int idx2 = min(y_tex + ((radius << 1) + 1), cheight - 1) * img_step + x_tex;

            barrier(CLK_LOCAL_MEM_FENCE);

            StepDown(idx1, idx2, left, right, d, col_ssd);
            if (col_ssd_extra > 0)
                if (x_tex + BLOCK_W < cwidth)
                    StepDown(idx1, idx2, left + BLOCK_W, right + BLOCK_W, d, col_ssd_extra);

            barrier(CLK_LOCAL_MEM_FENCE);

            uint2 minSSD = MinSSD(col_ssd);
            if (X < cwidth - radius && row < cheight - radius - Y)
            {
                int idx = row * cminSSD_step;
                if (minSSD.x < minSSDImage[idx])
                {
                    disparImage[disp_step * row] = (unsigned char)(d + minSSD.y);
                    minSSDImage[idx] = minSSD.x;
                }
            }

            y_tex++;
        } // for row loop
    } // for d loop
}
//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////// Sobel Prefiler (signal channel)//////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////

__kernel void prefilter_xsobel(__global unsigned char *input, __global unsigned char *output,
                               int rows, int cols, int prefilterCap)
{
    int x = get_global_id(0);
    int y = get_global_id(1);

    if(x < cols && y < rows)
    {
        int cov = input[(y-1) * cols + (x-1)] * (-1) + input[(y-1) * cols + (x+1)] * (1) +
                  input[(y)   * cols + (x-1)] * (-2) + input[(y)   * cols + (x+1)] * (2) +
                  input[(y+1) * cols + (x-1)] * (-1) + input[(y+1) * cols + (x+1)] * (1);

        cov = min(min(max(-prefilterCap, cov), prefilterCap) + prefilterCap, 255);
        output[y * cols + x] = cov & 0xFF;
    }
}

//////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////// Textureness filtering ////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////

float sobel(__global unsigned char *input, int x, int y, int rows, int cols)
{
    float conv = 0;
    int y1 = y==0? 0 : y-1;
    int x1 = x==0? 0 : x-1;
    if(x < cols && y < rows && x > 0 && y > 0)
    {
        conv = (float)input[(y1)  * cols + (x1)] * (-1) + (float)input[(y1)  * cols + (x+1)] * (1) +
               (float)input[(y)   * cols + (x1)] * (-2) + (float)input[(y)   * cols + (x+1)] * (2) +
               (float)input[(y+1) * cols + (x1)] * (-1) + (float)input[(y+1) * cols + (x+1)] * (1);

    }
    return fabs(conv);
}

float CalcSums(__local float *cols, __local float *cols_cache, int winsz)
{
    float cache = 0;
    float cache2 = 0;
    int winsz2 = winsz/2;

    int x = get_local_id(0);
    int group_size_x = get_local_size(0);

    for(int i = 1; i <= winsz2; i++)
        cache += cols[i];

    cols_cache[0] = cache;

    barrier(CLK_LOCAL_MEM_FENCE);

    if (x < group_size_x - winsz2)
        cache2 = cols_cache[winsz2];
    else
        for(int i = winsz2 + 1; i < winsz; i++)
            cache2 += cols[i];

    return cols[0] + cache + cache2;
}

#define RpT (2 * ROWSperTHREAD)  // got experimentally
__kernel void textureness_kernel(__global unsigned char *disp, int disp_rows, int disp_cols,
                                 int disp_step, __global unsigned char *input, int input_rows,
                                 int input_cols,int winsz, float threshold,
                                 __local float *cols_cache)
{
    int winsz2 = winsz/2;
    int n_dirty_pixels = (winsz2) * 2;

    int local_id_x = get_local_id(0);
    int group_size_x = get_local_size(0);
    int group_id_y = get_group_id(1);

    __local float *cols = cols_cache + group_size_x + local_id_x;
    __local float *cols_extra = local_id_x < n_dirty_pixels ? cols + group_size_x : 0;

    int x = get_global_id(0);
    int beg_row = group_id_y * RpT;
    int end_row = min(beg_row + RpT, disp_rows);

//   if (x < disp_cols)
//   {
    int y = beg_row;

    float sum = 0;
    float sum_extra = 0;

    for(int i = y - winsz2; i <= y + winsz2; ++i)
    {
        sum += sobel(input, x - winsz2, i, input_rows, input_cols);
        if (cols_extra)
            sum_extra += sobel(input, x + group_size_x - winsz2, i, input_rows, input_cols);
    }
    *cols = sum;
    if (cols_extra)
        *cols_extra = sum_extra;

    barrier(CLK_LOCAL_MEM_FENCE);

    float sum_win = CalcSums(cols, cols_cache + local_id_x, winsz) * 255;
    if (sum_win < threshold)
        disp[y * disp_step + x] = 0;

    barrier(CLK_LOCAL_MEM_FENCE);

    for(int y = beg_row + 1; y < end_row; ++y)
    {
        sum = sum - sobel(input, x - winsz2, y - winsz2 - 1, input_rows, input_cols) +
              sobel(input, x - winsz2, y + winsz2, input_rows, input_cols);
        *cols = sum;

        if (cols_extra)
        {
            sum_extra = sum_extra - sobel(input, x + group_size_x - winsz2, y - winsz2 - 1,input_rows, input_cols)
                        + sobel(input, x + group_size_x - winsz2, y + winsz2, input_rows, input_cols);
            *cols_extra = sum_extra;
        }

        barrier(CLK_LOCAL_MEM_FENCE);
        float sum_win = CalcSums(cols, cols_cache + local_id_x, winsz) * 255;
        if (sum_win < threshold)
            disp[y * disp_step + x] = 0;

        barrier(CLK_LOCAL_MEM_FENCE);
    }
    //  }
}


Streamline code, and sort of bug fix

Streamline code, and sort of bug fix

;; Add two polynomials together
(defun poly+ (poly1 poly2)
  (add-terms (append poly1 poly2)))

;; Subtract one polynomial from another
(defun poly- (poly1 poly2)
  (add-terms (append poly1 (flip-multipliers poly2))))

;; Returns the variable component of a singular polynomial
(defun variable-symbol (single-poly)
  (car (car single-poly)))

;; Returns the exponent component of a singular polynomial
(defun exponent (single-poly)
  (car (cdr (car single-poly))))

;; Returns the multiplier component of a singular polynomial
(defun multiplier (single-poly)
  (car (cdr single-poly)))

;; Returns a polynomial with all the multipliers multiplied by -1
(defun flip-multipliers (poly)
  (map 'list #'(lambda (x)
                 (list (list (variable-symbol x) (exponent x))
                       (* (multiplier x) -1))) poly))

;; Returns an added term if the addition is succesful, nil otherwise
(defun term-addition (term1 term2)
  (if (and (equal (variable-symbol term1) (variable-symbol term2))
           (equal (exponent term1) (exponent term2)))
    (list (list (variable-symbol term1) (exponent term1))
          (+ (multiplier term1) (multiplier term2)))
    nil))

;; Returns the failed term if the addition fails, nil otherwise
(defun term-failure (term1 term2)
  (if (and (equal (variable-symbol term1) (variable-symbol term2))
           (equal (exponent term1) (exponent term2)))
    nil
    term2))

;; Returns true if a polynomial contains only unique terms
(defun poly-unique-terms? (poly)
  (cond ((equal poly nil) T)
  (T (if (some #'(lambda (x) (equal (car x) (car (car poly)))) (cdr poly))
    nil
    (poly-unique-terms? (cdr poly))))))

;; This function replaces a full list of nils with the replace-term, otherwise
;; returns the list
(defun useful-replace-nil (addition-seq replace-term)
  (if (equal (remove nil addition-seq) nil)
    (list replace-term)
    addition-seq))

;; Removes all zeroes from the polynomial
(defun clear-zero (poly)
  (remove nil (map 'list #'(lambda (x)
                 (if (equal (multiplier x) 0) nil x)) poly)))

;; Recursively adds all the terms in the list
(defun add-terms (poly)
  (cond
    ((poly-unique-terms? poly) (clear-zero poly))
    (T (add-terms (remove nil (append (map 'list #'(lambda (x)
                                     (term-failure (car poly) x))
                           (cdr poly))
        (useful-replace-nil (map 'list #'(lambda (y)
                       (term-addition (car poly) y))
             (cdr poly)) (car poly))))))))

; (poly+ '(((x 2) 3)) '(((y 2) 4)))
; (poly+ '(((x 2) 3) ((y 2) 3)) '(((y 2) 4)))

;; Add two polynomials together
(defun poly+ (poly1 poly2)
  (add-terms (append poly1 poly2) nil nil))

;; Subtract one polynomial from another
(defun poly- (poly1 poly2)
  (add-terms (append poly1 (flip-multipliers poly2)) nil nil))

;; Returns the variable component of a singular polynomial
(defun variable-symbol (single-poly)
  (car (car single-poly)))

;; Returns the exponent component of a singular polynomial
(defun exponent (single-poly)
  (car (cdr (car single-poly))))

;; Returns the multiplier component of a singular polynomial
(defun multiplier (single-poly)
  (car (cdr single-poly)))

;; Returns a polynomial with all the multipliers multiplied by -1
(defun flip-multipliers (poly)
  (map 'list #'(lambda (x)
                 (list (list (variable-symbol x) (exponent x))
                       (* (multiplier x) -1))) poly))

;; Returns an added term if the addition is succesful, nil otherwise
(defun term-addition (term1 term2)
  (if (and (equal (variable-symbol term1) (variable-symbol term2))
           (equal (exponent term1) (exponent term2)))
    (list (list (variable-symbol term1) (exponent term1))
          (+ (multiplier term1) (multiplier term2)))
    nil))

;; Returns the failed term if the addition fails, nil otherwise
(defun term-failure (term1 term2)
  (if (and (equal (variable-symbol term1) (variable-symbol term2))
           (equal (exponent term1) (exponent term2)))
    nil
    term2))

;; This function replaces a full list of nils with the replace-term, otherwise
;; returns the list
(defun useful-replace-nil (addition-seq replace-term)
  (if (equal (remove nil addition-seq) nil)
    (list replace-term)
    addition-seq))

;; Removes all zeroes from the polynomial
(defun clear-zero (poly)
  (remove nil (map 'list #'(lambda (x)
                 (if (equal (multiplier x) 0) nil x)) poly)))

;; Recursively adds all the terms in the list
(defun add-terms (poly orig_var curr_var)
  (cond
    ((and (equal orig_var curr_var) (not (equal orig_var nil))) (clear-zero poly))
    (T (add-terms (remove nil (append (map 'list #'(lambda (x)
                                     (term-failure (car poly) x))
                           (cdr poly))
        (useful-replace-nil (map 'list #'(lambda (y)
                       (term-addition (car poly) y))
             (cdr poly)) (car poly))))
                  (if (equal orig_var nil) (car (car poly)) orig_var)
                  (car (car (cdr poly)))))))

; (poly+ '(((x 2) 3)) '(((y 2) 4)))
; (poly+ '(((x 2) 3) ((y 2) 3)) '(((y 2) 4)))