Remove #defines that define double precision in warpAffine and leave only single precision because AMD OpenCL compiler does not accept those defines

Former-commit-id: ed41f28f621e5c41e56a2be188fa45641a1e9542

// -*- c++ -*-
/*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
//    Zhang Ying, zhangying913@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 GpuMaterials 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*/

//warpAffine kernel
//support data types: CV_8UC1, CV_8UC4, CV_32FC1, CV_32FC4, and three interpolation methods: NN, Linear, Cubic.
//#if defined (DOUBLE_SUPPORT)
//# ifdef cl_khr_fp64
//#   pragma OPENCL EXTENSION cl_khr_fp64:enable
//# elif defined (cl_amd_fp64)
//#   pragma OPENCL EXTENSION cl_amd_fp64:enable
//# endif /* cl_khr_fp64 */
//typedef double F;
//typedef double4 F4;
//# define convert_F4 convert_double4
//#else /* NOT DOUBLE_SUPPORT */
typedef float F;
typedef float4 F4;
# define convert_F4 convert_float4
//#endif /* NOT DOUBLE_SUPPORT */

#define INTER_BITS 5
#define INTER_TAB_SIZE (1 << INTER_BITS)
#define INTER_SCALE 1.f/INTER_TAB_SIZE
#define AB_BITS max(10, (int)INTER_BITS)
#define AB_SCALE (1 << AB_BITS)
#define INTER_REMAP_COEF_BITS 15
#define INTER_REMAP_COEF_SCALE (1 << INTER_REMAP_COEF_BITS)

inline void interpolateCubic( float x, float* coeffs )
{
    const float A = -0.75f;

    coeffs[0] = ((A*(x + 1.f) - 5.0f*A)*(x + 1.f) + 8.0f*A)*(x + 1.f) - 4.0f*A;
    coeffs[1] = ((A + 2.f)*x - (A + 3.f))*x*x + 1.f;
    coeffs[2] = ((A + 2.f)*(1.f - x) - (A + 3.f))*(1.f - x)*(1.f - x) + 1.f;
    coeffs[3] = 1.f - coeffs[0] - coeffs[1] - coeffs[2];
}

/**********************************************8UC1*********************************************
***********************************************************************************************/
__kernel void warpAffineNN_C1_D0(__global uchar const * restrict src, __global uchar * dst, int src_cols, int src_rows,
                                 int dst_cols, int dst_rows, int srcStep, int dstStep,
                                 int src_offset, int dst_offset,  __constant F * M, int threadCols )
{
    int dx = get_global_id(0);
    int dy = get_global_id(1);

    if( dx < threadCols && dy < dst_rows)
    {
        dx = (dx<<2) - (dst_offset&3);

        int round_delta = (AB_SCALE>>1);

        int4 X, Y;
        int4 sx, sy;
        int4 DX = (int4)(dx, dx+1, dx+2, dx+3);
        DX = (DX << AB_BITS);
        F4 M0DX, M3DX;
        M0DX = M[0] * convert_F4(DX);
        M3DX = M[3] * convert_F4(DX);
        X = convert_int4(rint(M0DX));
        Y = convert_int4(rint(M3DX));
        int tmp1, tmp2;
        tmp1 = rint((M[1]*dy + M[2]) * AB_SCALE);
        tmp2 = rint((M[4]*dy + M[5]) * AB_SCALE);

        X += tmp1 + round_delta;
        Y += tmp2 + round_delta;

        sx = convert_int4(convert_short4(X >> AB_BITS));
        sy = convert_int4(convert_short4(Y >> AB_BITS));

        __global uchar4 * d = (__global uchar4 *)(dst+dst_offset+dy*dstStep+dx);
        uchar4 dval = *d;
        DX = (int4)(dx, dx+1, dx+2, dx+3);
        int4 dcon = DX >= 0 && DX < dst_cols && dy >= 0 && dy < dst_rows;
        int4 scon = sx >= 0 && sx < src_cols && sy >= 0 && sy < src_rows;
        int4 spos = src_offset + sy * srcStep + sx;
        uchar4 sval;
        sval.s0 = scon.s0 ? src[spos.s0] : 0;
        sval.s1 = scon.s1 ? src[spos.s1] : 0;
        sval.s2 = scon.s2 ? src[spos.s2] : 0;
        sval.s3 = scon.s3 ? src[spos.s3] : 0;
        dval = convert_uchar4(dcon) != (uchar4)(0,0,0,0) ? sval : dval;
        *d = dval;
    }
}

__kernel void warpAffineLinear_C1_D0(__global const uchar * restrict src, __global uchar * dst, int src_cols, int src_rows,
                                     int dst_cols, int dst_rows, int srcStep, int dstStep,
                                     int src_offset, int dst_offset,  __constant F * M, int threadCols )
{
    int dx = get_global_id(0);
    int dy = get_global_id(1);

    if( dx < threadCols && dy < dst_rows)
    {
        dx = (dx<<2) - (dst_offset&3);

        int round_delta = ((AB_SCALE >> INTER_BITS) >> 1);

        int4 X, Y;
        short4  ax, ay;
        int4 sx, sy;
        int4 DX = (int4)(dx, dx+1, dx+2, dx+3);
        DX = (DX << AB_BITS);
        F4 M0DX, M3DX;
        M0DX = M[0] * convert_F4(DX);
        M3DX = M[3] * convert_F4(DX);
        X = convert_int4(rint(M0DX));
        Y = convert_int4(rint(M3DX));

        int tmp1, tmp2;
        tmp1 = rint((M[1]*dy + M[2]) * AB_SCALE);
        tmp2 = rint((M[4]*dy + M[5]) * AB_SCALE);

        X += tmp1 + round_delta;
        Y += tmp2 + round_delta;

        X = X >> (AB_BITS - INTER_BITS);
        Y = Y >> (AB_BITS - INTER_BITS);

        sx = convert_int4(convert_short4(X >> INTER_BITS));
        sy = convert_int4(convert_short4(Y >> INTER_BITS));
        ax = convert_short4(X & (INTER_TAB_SIZE-1));
        ay = convert_short4(Y & (INTER_TAB_SIZE-1));

        uchar4 v0, v1, v2,v3;
        int4 scon0, scon1, scon2, scon3;
        int4 spos0, spos1, spos2, spos3;

        scon0 = (sx >= 0 && sx < src_cols && sy >= 0 && sy < src_rows);
        scon1 = (sx+1 >= 0 && sx+1 < src_cols && sy >= 0 && sy < src_rows);
        scon2 = (sx >= 0 && sx < src_cols && sy+1 >= 0 && sy+1 < src_rows);
        scon3 = (sx+1 >= 0 && sx+1 < src_cols && sy+1 >= 0 && sy+1 < src_rows);
        spos0 = src_offset + sy * srcStep + sx;
        spos1 = src_offset + sy * srcStep + sx + 1;
        spos2 = src_offset + (sy+1) * srcStep + sx;
        spos3 = src_offset + (sy+1) * srcStep + sx + 1;

        v0.s0 = scon0.s0 ? src[spos0.s0] : 0;
        v1.s0 = scon1.s0 ? src[spos1.s0] : 0;
        v2.s0 = scon2.s0 ? src[spos2.s0] : 0;
        v3.s0 = scon3.s0 ? src[spos3.s0] : 0;

        v0.s1 = scon0.s1 ? src[spos0.s1] : 0;
        v1.s1 = scon1.s1 ? src[spos1.s1] : 0;
        v2.s1 = scon2.s1 ? src[spos2.s1] : 0;
        v3.s1 = scon3.s1 ? src[spos3.s1] : 0;

        v0.s2 = scon0.s2 ? src[spos0.s2] : 0;
        v1.s2 = scon1.s2 ? src[spos1.s2] : 0;
        v2.s2 = scon2.s2 ? src[spos2.s2] : 0;
        v3.s2 = scon3.s2 ? src[spos3.s2] : 0;

        v0.s3 = scon0.s3 ? src[spos0.s3] : 0;
        v1.s3 = scon1.s3 ? src[spos1.s3] : 0;
        v2.s3 = scon2.s3 ? src[spos2.s3] : 0;
        v3.s3 = scon3.s3 ? src[spos3.s3] : 0;

        short4 itab0, itab1, itab2, itab3;
        float4 taby, tabx;
        taby = INTER_SCALE * convert_float4(ay);
        tabx = INTER_SCALE * convert_float4(ax);

        itab0 = convert_short4_sat(( (1.0f-taby)*(1.0f-tabx) * (float4)INTER_REMAP_COEF_SCALE ));
        itab1 = convert_short4_sat(( (1.0f-taby)*tabx * (float4)INTER_REMAP_COEF_SCALE ));
        itab2 = convert_short4_sat(( taby*(1.0f-tabx) * (float4)INTER_REMAP_COEF_SCALE ));
        itab3 = convert_short4_sat(( taby*tabx * (float4)INTER_REMAP_COEF_SCALE ));

        int4 val;
        uchar4 tval;
        val = convert_int4(v0) * convert_int4(itab0) + convert_int4(v1) * convert_int4(itab1)
              + convert_int4(v2) * convert_int4(itab2) + convert_int4(v3) * convert_int4(itab3);
        tval = convert_uchar4_sat ( (val + (1 << (INTER_REMAP_COEF_BITS-1))) >> INTER_REMAP_COEF_BITS ) ;

        __global uchar4 * d =(__global uchar4 *)(dst+dst_offset+dy*dstStep+dx);
        uchar4 dval = *d;
        DX = (int4)(dx, dx+1, dx+2, dx+3);
        int4 dcon = DX >= 0 && DX < dst_cols && dy >= 0 && dy < dst_rows;
        dval = convert_uchar4(dcon != 0) ? tval : dval;
        *d = dval;
    }
}

__kernel void warpAffineCubic_C1_D0(__global uchar * src, __global uchar * dst, int src_cols, int src_rows,
                                    int dst_cols, int dst_rows, int srcStep, int dstStep,
                                    int src_offset, int dst_offset,  __constant F * M, int threadCols )
{
    int dx = get_global_id(0);
    int dy = get_global_id(1);

    if( dx < threadCols && dy < dst_rows)
    {
        int round_delta = ((AB_SCALE>>INTER_BITS)>>1);

        int X0 = rint(M[0] * dx * AB_SCALE);
        int Y0 = rint(M[3] * dx * AB_SCALE);
        X0 += rint((M[1]*dy + M[2]) * AB_SCALE) + round_delta;
        Y0 += rint((M[4]*dy + M[5]) * AB_SCALE) + round_delta;
        int X = X0 >> (AB_BITS - INTER_BITS);
        int Y = Y0 >> (AB_BITS - INTER_BITS);

        short sx = (short)(X >> INTER_BITS) - 1;
        short sy = (short)(Y >> INTER_BITS) - 1;
        short ay = (short)(Y & (INTER_TAB_SIZE-1));
        short ax = (short)(X & (INTER_TAB_SIZE-1));

        uchar v[16];
        int i, j;

#pragma unroll 4
        for(i=0; i<4;  i++)
            for(j=0; j<4;  j++)
            {
                v[i*4+j] = (sx+j >= 0 && sx+j < src_cols && sy+i >= 0 && sy+i < src_rows) ? src[src_offset+(sy+i) * srcStep + (sx+j)] : 0;
            }

        short itab[16];
        float tab1y[4], tab1x[4];
        float axx, ayy;

        ayy = 1.f/INTER_TAB_SIZE * ay;
        axx = 1.f/INTER_TAB_SIZE * ax;
        interpolateCubic(ayy, tab1y);
        interpolateCubic(axx, tab1x);
        int isum = 0;

#pragma unroll 16
        for( i=0; i<16; i++ )
        {
            F v = tab1y[(i>>2)] * tab1x[(i&3)];
            isum += itab[i] = convert_short_sat( rint( v * INTER_REMAP_COEF_SCALE ) );
        }

        if( isum != INTER_REMAP_COEF_SCALE )
        {
            int k1, k2;
            int diff = isum - INTER_REMAP_COEF_SCALE;
            int Mk1=2, Mk2=2, mk1=2, mk2=2;
            for( k1 = 2; k1 < 4; k1++ )
                for( k2 = 2; k2 < 4; k2++ )
                {
                    if( itab[(k1<<2)+k2] < itab[(mk1<<2)+mk2] )
                        mk1 = k1, mk2 = k2;
                    else if( itab[(k1<<2)+k2] > itab[(Mk1<<2)+Mk2] )
                        Mk1 = k1, Mk2 = k2;
                }
            diff<0 ? (itab[(Mk1<<2)+Mk2]=(short)(itab[(Mk1<<2)+Mk2]-diff)) : (itab[(mk1<<2)+mk2]=(short)(itab[(mk1<<2)+mk2]-diff));
        }

        if( dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows)
        {
            int sum=0;
            for ( i =0; i<16; i++ )
            {
                sum += v[i] * itab[i] ;
            }
            dst[dst_offset+dy*dstStep+dx] = convert_uchar_sat( (sum + (1 << (INTER_REMAP_COEF_BITS-1))) >> INTER_REMAP_COEF_BITS ) ;
        }
    }
}

/**********************************************8UC4*********************************************
***********************************************************************************************/

__kernel void warpAffineNN_C4_D0(__global uchar4 const * restrict src, __global uchar4 * dst, int src_cols, int src_rows,
                                 int dst_cols, int dst_rows, int srcStep, int dstStep,
                                 int src_offset, int dst_offset,  __constant F * M, int threadCols )
{
    int dx = get_global_id(0);
    int dy = get_global_id(1);

    if( dx < threadCols && dy < dst_rows)
    {
        int round_delta = (AB_SCALE >> 1);

        int X0 = rint(M[0] * dx * AB_SCALE);
        int Y0 = rint(M[3] * dx * AB_SCALE);
        X0 += rint((M[1]*dy + M[2]) * AB_SCALE) + round_delta;
        Y0 += rint((M[4]*dy + M[5]) * AB_SCALE) + round_delta;

        int sx0 = (short)(X0 >> AB_BITS);
        int sy0 = (short)(Y0 >> AB_BITS);

        if(dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows)
            dst[(dst_offset>>2)+dy*(dstStep>>2)+dx]= (sx0>=0 && sx0<src_cols && sy0>=0 && sy0<src_rows) ? src[(src_offset>>2)+sy0*(srcStep>>2)+sx0] : (uchar4)0;
    }
}

__kernel void warpAffineLinear_C4_D0(__global uchar4 const * restrict src, __global uchar4 * dst, int src_cols, int src_rows,
                                     int dst_cols, int dst_rows, int srcStep, int dstStep,
                                     int src_offset, int dst_offset,  __constant F * M, int threadCols )
{
    int dx = get_global_id(0);
    int dy = get_global_id(1);

    if( dx < threadCols && dy < dst_rows)
    {
        int round_delta = AB_SCALE/INTER_TAB_SIZE/2;

        src_offset = (src_offset>>2);
        srcStep = (srcStep>>2);

        int tmp = (dx << AB_BITS);
        int X0 = rint(M[0] * tmp);
        int Y0 = rint(M[3] * tmp);
        X0 += rint((M[1]*dy + M[2]) * AB_SCALE) + round_delta;
        Y0 += rint((M[4]*dy + M[5]) * AB_SCALE) + round_delta;
        X0 = X0 >> (AB_BITS - INTER_BITS);
        Y0 = Y0 >> (AB_BITS - INTER_BITS);

        short sx0 = (short)(X0 >> INTER_BITS);
        short sy0 = (short)(Y0 >> INTER_BITS);
        short ax0 = (short)(X0 & (INTER_TAB_SIZE-1));
        short ay0 = (short)(Y0 & (INTER_TAB_SIZE-1));

        int4 v0, v1, v2, v3;

        v0 = (sx0 >= 0 && sx0 < src_cols && sy0 >= 0 && sy0 < src_rows) ? convert_int4(src[src_offset+sy0 * srcStep + sx0]) : 0;
        v1 = (sx0+1 >= 0 && sx0+1 < src_cols && sy0 >= 0 && sy0 < src_rows) ? convert_int4(src[src_offset+sy0 * srcStep + sx0+1]) : 0;
        v2 = (sx0 >= 0 && sx0 < src_cols && sy0+1 >= 0 && sy0+1 < src_rows) ? convert_int4(src[src_offset+(sy0+1) * srcStep + sx0]) : 0;
        v3 = (sx0+1 >= 0 && sx0+1 < src_cols && sy0+1 >= 0 && sy0+1 < src_rows) ? convert_int4(src[src_offset+(sy0+1) * srcStep + sx0+1]) : 0;

        int itab0, itab1, itab2, itab3;
        float taby, tabx;
        taby = 1.f/INTER_TAB_SIZE*ay0;
        tabx = 1.f/INTER_TAB_SIZE*ax0;

        itab0 = convert_short_sat(rint( (1.0f-taby)*(1.0f-tabx) * INTER_REMAP_COEF_SCALE ));
        itab1 = convert_short_sat(rint( (1.0f-taby)*tabx * INTER_REMAP_COEF_SCALE ));
        itab2 = convert_short_sat(rint( taby*(1.0f-tabx) * INTER_REMAP_COEF_SCALE ));
        itab3 = convert_short_sat(rint( taby*tabx * INTER_REMAP_COEF_SCALE ));

        int4 val;
        val = v0 * itab0 +  v1 * itab1 + v2 * itab2 + v3 * itab3;

        if(dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows)
            dst[(dst_offset>>2)+dy*(dstStep>>2)+dx] =  convert_uchar4_sat ( (val + (1 << (INTER_REMAP_COEF_BITS-1))) >> INTER_REMAP_COEF_BITS ) ;
    }
}

__kernel void warpAffineCubic_C4_D0(__global uchar4 const * restrict src, __global uchar4 * dst, int src_cols, int src_rows,
                                    int dst_cols, int dst_rows, int srcStep, int dstStep,
                                    int src_offset, int dst_offset,  __constant F * M, int threadCols )
{
    int dx = get_global_id(0);
    int dy = get_global_id(1);

    if( dx < threadCols && dy < dst_rows)
    {
        int round_delta = ((AB_SCALE>>INTER_BITS)>>1);

        src_offset = (src_offset>>2);
        srcStep = (srcStep>>2);
        dst_offset = (dst_offset>>2);
        dstStep = (dstStep>>2);

        int tmp = (dx << AB_BITS);
        int X0 = rint(M[0] * tmp);
        int Y0 = rint(M[3] * tmp);
        X0 += rint((M[1]*dy + M[2]) * AB_SCALE) + round_delta;
        Y0 += rint((M[4]*dy + M[5]) * AB_SCALE) + round_delta;
        X0 = X0 >> (AB_BITS - INTER_BITS);
        Y0 = Y0 >> (AB_BITS - INTER_BITS);

        int sx = (short)(X0 >> INTER_BITS) - 1;
        int sy = (short)(Y0 >> INTER_BITS) - 1;
        int ay = (short)(Y0 & (INTER_TAB_SIZE-1));
        int ax = (short)(X0 & (INTER_TAB_SIZE-1));

        uchar4 v[16];
        int i,j;
#pragma unroll 4
        for(i=0; i<4; i++)
            for(j=0; j<4; j++)
            {
                v[i*4+j] = (sx+j >= 0 && sx+j < src_cols && sy+i >= 0 && sy+i < src_rows) ? (src[src_offset+(sy+i) * srcStep + (sx+j)])  : (uchar4)0;
            }
        int itab[16];
        float tab1y[4], tab1x[4];
        float axx, ayy;

        ayy = INTER_SCALE * ay;
        axx = INTER_SCALE * ax;
        interpolateCubic(ayy, tab1y);
        interpolateCubic(axx, tab1x);
        int isum = 0;

#pragma unroll 16
        for( i=0; i<16; i++ )
        {
            float tmp;
            tmp = tab1y[(i>>2)] * tab1x[(i&3)] * INTER_REMAP_COEF_SCALE;
            itab[i] = rint(tmp);
            isum += itab[i];
        }

        if( isum != INTER_REMAP_COEF_SCALE )
        {
            int k1, k2;
            int diff = isum - INTER_REMAP_COEF_SCALE;
            int Mk1=2, Mk2=2, mk1=2, mk2=2;

            for( k1 = 2; k1 < 4; k1++ )
                for( k2 = 2; k2 < 4; k2++ )
                {

                    if( itab[(k1<<2)+k2] < itab[(mk1<<2)+mk2] )
                        mk1 = k1, mk2 = k2;
                    else if( itab[(k1<<2)+k2] > itab[(Mk1<<2)+Mk2] )
                        Mk1 = k1, Mk2 = k2;
                }

            diff<0 ? (itab[(Mk1<<2)+Mk2]=(short)(itab[(Mk1<<2)+Mk2]-diff)) : (itab[(mk1<<2)+mk2]=(short)(itab[(mk1<<2)+mk2]-diff));
        }

        if( dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows)
        {
            int4 sum=0;
            for ( i =0; i<16; i++ )
            {
                sum += convert_int4(v[i]) * itab[i];
            }
            dst[dst_offset+dy*dstStep+dx] = convert_uchar4_sat( (sum + (1 << (INTER_REMAP_COEF_BITS-1))) >> INTER_REMAP_COEF_BITS ) ;
        }
    }
}

/**********************************************32FC1********************************************
***********************************************************************************************/

__kernel void warpAffineNN_C1_D5(__global float * src, __global float * dst, int src_cols, int src_rows,
                                 int dst_cols, int dst_rows, int srcStep, int dstStep,
                                 int src_offset, int dst_offset,  __constant F * M, int threadCols )
{
    int dx = get_global_id(0);
    int dy = get_global_id(1);

    if( dx < threadCols && dy < dst_rows)
    {
        int round_delta = AB_SCALE/2;

        int X0 = rint(M[0] * dx * AB_SCALE);
        int Y0 = rint(M[3] * dx * AB_SCALE);
        X0 += rint((M[1]*dy + M[2]) * AB_SCALE) + round_delta;
        Y0 += rint((M[4]*dy + M[5]) * AB_SCALE) + round_delta;

        short sx0 = (short)(X0 >> AB_BITS);
        short sy0 = (short)(Y0 >> AB_BITS);

        if(dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows)
            dst[(dst_offset>>2)+dy*dstStep+dx]= (sx0>=0 && sx0<src_cols && sy0>=0 && sy0<src_rows) ? src[(src_offset>>2)+sy0*srcStep+sx0] : 0;
    }
}

__kernel void warpAffineLinear_C1_D5(
    __global float * src, __global float * dst, int src_cols, int src_rows,
    int dst_cols, int dst_rows, int srcStep, int dstStep,
    int src_offset, int dst_offset,  __constant F * M, int threadCols
    )
{
    int dx = get_global_id(0);
    int dy = get_global_id(1);

    if( dx < threadCols && dy < dst_rows)
    {
        int round_delta = AB_SCALE/INTER_TAB_SIZE/2;

        src_offset = (src_offset>>2);

        int X0 = rint(M[0] * dx * AB_SCALE);
        int Y0 = rint(M[3] * dx * AB_SCALE);
        X0 += rint((M[1]*dy + M[2]) * AB_SCALE) + round_delta;
        Y0 += rint((M[4]*dy + M[5]) * AB_SCALE) + round_delta;
        X0 = X0 >> (AB_BITS - INTER_BITS);
        Y0 = Y0 >> (AB_BITS - INTER_BITS);

        short sx0 = (short)(X0 >> INTER_BITS);
        short sy0 = (short)(Y0 >> INTER_BITS);
        short ax0 = (short)(X0 & (INTER_TAB_SIZE-1));
        short ay0 = (short)(Y0 & (INTER_TAB_SIZE-1));

        float v0, v1, v2, v3;

        v0 = (sx0 >= 0 && sx0 < src_cols && sy0 >= 0 && sy0 < src_rows) ? src[src_offset+sy0 * srcStep + sx0] : 0;
        v1 = (sx0+1 >= 0 && sx0+1 < src_cols && sy0 >= 0 && sy0 < src_rows) ? src[src_offset+sy0 * srcStep + sx0+1] : 0;
        v2 = (sx0 >= 0 && sx0 < src_cols && sy0+1 >= 0 && sy0+1 < src_rows) ? src[src_offset+(sy0+1) * srcStep + sx0] : 0;
        v3 = (sx0+1 >= 0 && sx0+1 < src_cols && sy0+1 >= 0 && sy0+1 < src_rows) ? src[src_offset+(sy0+1) * srcStep + sx0+1] : 0;

        float tab[4];
        float taby[2], tabx[2];
        taby[0] = 1.0 - 1.f/INTER_TAB_SIZE*ay0;
        taby[1] = 1.f/INTER_TAB_SIZE*ay0;
        tabx[0] = 1.0 - 1.f/INTER_TAB_SIZE*ax0;
        tabx[1] = 1.f/INTER_TAB_SIZE*ax0;

        tab[0] = taby[0] * tabx[0];
        tab[1] = taby[0] * tabx[1];
        tab[2] = taby[1] * tabx[0];
        tab[3] = taby[1] * tabx[1];

        float sum = 0;
        sum += v0 * tab[0] +  v1 * tab[1] +  v2 * tab[2] +  v3 * tab[3];
        if(dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows)
            dst[(dst_offset>>2)+dy*dstStep+dx] = sum;
    }
}

__kernel void warpAffineCubic_C1_D5(__global float * src, __global float * dst, int src_cols, int src_rows,
                                    int dst_cols, int dst_rows, int srcStep, int dstStep,
                                    int src_offset, int dst_offset,  __constant F * M, int threadCols )
{
    int dx = get_global_id(0);
    int dy = get_global_id(1);

    if( dx < threadCols && dy < dst_rows)
    {
        int round_delta = AB_SCALE/INTER_TAB_SIZE/2;

        src_offset = (src_offset>>2);
        dst_offset = (dst_offset>>2);

        int X0 = rint(M[0] * dx * AB_SCALE);
        int Y0 = rint(M[3] * dx * AB_SCALE);
        X0 += rint((M[1]*dy + M[2]) * AB_SCALE) + round_delta;
        Y0 += rint((M[4]*dy + M[5]) * AB_SCALE) + round_delta;
        X0 = X0 >> (AB_BITS - INTER_BITS);
        Y0 = Y0 >> (AB_BITS - INTER_BITS);

        short sx = (short)(X0 >> INTER_BITS) - 1;
        short sy = (short)(Y0 >> INTER_BITS) - 1;
        short ay = (short)(Y0 & (INTER_TAB_SIZE-1));
        short ax = (short)(X0 & (INTER_TAB_SIZE-1));

        float v[16];
        int i;

        for(i=0; i<16;  i++)
            v[i] = (sx+(i&3) >= 0 && sx+(i&3) < src_cols && sy+(i>>2) >= 0 && sy+(i>>2) < src_rows) ? src[src_offset+(sy+(i>>2)) * srcStep + (sx+(i&3))] : 0;

        float tab[16];
        float tab1y[4], tab1x[4];
        float axx, ayy;

        ayy = 1.f/INTER_TAB_SIZE * ay;
        axx = 1.f/INTER_TAB_SIZE * ax;
        interpolateCubic(ayy, tab1y);
        interpolateCubic(axx, tab1x);

#pragma unroll 4
        for( i=0; i<16; i++ )
        {
            tab[i] = tab1y[(i>>2)] * tab1x[(i&3)];
        }

        if( dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows)
        {
            float sum = 0;
#pragma unroll 4
            for ( i =0; i<16; i++ )
            {
                sum += v[i] * tab[i];
            }
            dst[dst_offset+dy*dstStep+dx] = sum;

        }
    }
}

/**********************************************32FC4********************************************
***********************************************************************************************/

__kernel void warpAffineNN_C4_D5(__global float4 * src, __global float4 * dst, int src_cols, int src_rows,
                                 int dst_cols, int dst_rows, int srcStep, int dstStep,
                                 int src_offset, int dst_offset,  __constant F * M, int threadCols )
{
    int dx = get_global_id(0);
    int dy = get_global_id(1);

    if( dx < threadCols && dy < dst_rows)
    {
        int round_delta = AB_SCALE/2;

        int X0 = rint(M[0] * dx * AB_SCALE);
        int Y0 = rint(M[3] * dx * AB_SCALE);
        X0 += rint((M[1]*dy + M[2]) * AB_SCALE) + round_delta;
        Y0 += rint((M[4]*dy + M[5]) * AB_SCALE) + round_delta;

        short sx0 = (short)(X0 >> AB_BITS);
        short sy0 = (short)(Y0 >> AB_BITS);

        if(dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows)
            dst[(dst_offset>>4)+dy*(dstStep>>2)+dx]= (sx0>=0 && sx0<src_cols && sy0>=0 && sy0<src_rows) ? src[(src_offset>>4)+sy0*(srcStep>>2)+sx0] : (float4)0;
    }
}

__kernel void warpAffineLinear_C4_D5(__global float4 * src, __global float4 * dst, int src_cols, int src_rows,
                                     int dst_cols, int dst_rows, int srcStep, int dstStep,
                                     int src_offset, int dst_offset,  __constant F * M, int threadCols )
{
    int dx = get_global_id(0);
    int dy = get_global_id(1);

    if( dx < threadCols && dy < dst_rows)
    {
        int round_delta = AB_SCALE/INTER_TAB_SIZE/2;

        src_offset = (src_offset>>4);
        dst_offset = (dst_offset>>4);
        srcStep = (srcStep>>2);
        dstStep = (dstStep>>2);

        int X0 = rint(M[0] * dx * AB_SCALE);
        int Y0 = rint(M[3] * dx * AB_SCALE);
        X0 += rint((M[1]*dy + M[2]) * AB_SCALE) + round_delta;
        Y0 += rint((M[4]*dy + M[5]) * AB_SCALE) + round_delta;
        X0 = X0 >> (AB_BITS - INTER_BITS);
        Y0 = Y0 >> (AB_BITS - INTER_BITS);

        short sx0 = (short)(X0 >> INTER_BITS);
        short sy0 = (short)(Y0 >> INTER_BITS);
        short ax0 = (short)(X0 & (INTER_TAB_SIZE-1));
        short ay0 = (short)(Y0 & (INTER_TAB_SIZE-1));

        float4 v0, v1, v2, v3;

        v0 = (sx0 >= 0 && sx0 < src_cols && sy0 >= 0 && sy0 < src_rows) ? src[src_offset+sy0 * srcStep + sx0] : (float4)0;
        v1 = (sx0+1 >= 0 && sx0+1 < src_cols && sy0 >= 0 && sy0 < src_rows) ? src[src_offset+sy0 * srcStep + sx0+1] : (float4)0;
        v2 = (sx0 >= 0 && sx0 < src_cols && sy0+1 >= 0 && sy0+1 < src_rows) ? src[src_offset+(sy0+1) * srcStep + sx0] : (float4)0;
        v3 = (sx0+1 >= 0 && sx0+1 < src_cols && sy0+1 >= 0 && sy0+1 < src_rows) ? src[src_offset+(sy0+1) * srcStep + sx0+1] : (float4)0;

        float tab[4];
        float taby[2], tabx[2];
        taby[0] = 1.0 - 1.f/INTER_TAB_SIZE*ay0;
        taby[1] = 1.f/INTER_TAB_SIZE*ay0;
        tabx[0] = 1.0 - 1.f/INTER_TAB_SIZE*ax0;
        tabx[1] = 1.f/INTER_TAB_SIZE*ax0;

        tab[0] = taby[0] * tabx[0];
        tab[1] = taby[0] * tabx[1];
        tab[2] = taby[1] * tabx[0];
        tab[3] = taby[1] * tabx[1];

        float4 sum = 0;
        sum += v0 * tab[0] +  v1 * tab[1] +  v2 * tab[2] +  v3 * tab[3];
        if(dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows)
            dst[dst_offset+dy*dstStep+dx] = sum;
    }
}

__kernel void warpAffineCubic_C4_D5(__global float4 * src, __global float4 * dst, int src_cols, int src_rows,
                                    int dst_cols, int dst_rows, int srcStep, int dstStep,
                                    int src_offset, int dst_offset,  __constant F * M, int threadCols )
{
    int dx = get_global_id(0);
    int dy = get_global_id(1);

    if( dx < threadCols && dy < dst_rows)
    {
        int round_delta = AB_SCALE/INTER_TAB_SIZE/2;

        src_offset = (src_offset>>4);
        dst_offset = (dst_offset>>4);
        srcStep = (srcStep>>2);
        dstStep = (dstStep>>2);

        int X0 = rint(M[0] * dx * AB_SCALE);
        int Y0 = rint(M[3] * dx * AB_SCALE);
        X0 += rint((M[1]*dy + M[2]) * AB_SCALE) + round_delta;
        Y0 += rint((M[4]*dy + M[5]) * AB_SCALE) + round_delta;
        X0 = X0 >> (AB_BITS - INTER_BITS);
        Y0 = Y0 >> (AB_BITS - INTER_BITS);

        short sx = (short)(X0 >> INTER_BITS) - 1;
        short sy = (short)(Y0 >> INTER_BITS) - 1;
        short ay = (short)(Y0 & (INTER_TAB_SIZE-1));
        short ax = (short)(X0 & (INTER_TAB_SIZE-1));

        float4 v[16];
        int i;

        for(i=0; i<16;  i++)
            v[i] = (sx+(i&3) >= 0 && sx+(i&3) < src_cols && sy+(i>>2) >= 0 && sy+(i>>2) < src_rows) ? src[src_offset+(sy+(i>>2)) * srcStep + (sx+(i&3))] : (float4)0;

        float tab[16];
        float tab1y[4], tab1x[4];
        float axx, ayy;

        ayy = 1.f/INTER_TAB_SIZE * ay;
        axx = 1.f/INTER_TAB_SIZE * ax;
        interpolateCubic(ayy, tab1y);
        interpolateCubic(axx, tab1x);

#pragma unroll 4
        for( i=0; i<16; i++ )
        {
            tab[i] = tab1y[(i>>2)] * tab1x[(i&3)];
        }

        if( dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows)
        {
            float4 sum = 0;
#pragma unroll 4
            for ( i =0; i<16; i++ )
            {
                sum += v[i] * tab[i];
            }
            dst[dst_offset+dy*dstStep+dx] = sum;

        }
    }
}

// -*- c++ -*-
/*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
//    Zhang Ying, zhangying913@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 GpuMaterials 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*/

//warpAffine kernel
//support data types: CV_8UC1, CV_8UC4, CV_32FC1, CV_32FC4, and three interpolation methods: NN, Linear, Cubic.
#if defined (DOUBLE_SUPPORT)
# ifdef cl_khr_fp64
#   pragma OPENCL EXTENSION cl_khr_fp64:enable
# elif defined (cl_amd_fp64)
#   pragma OPENCL EXTENSION cl_amd_fp64:enable
# endif /* cl_khr_fp64 */
typedef double F;
typedef double4 F4;
# define convert_F4 convert_double4
#else /* NOT DOUBLE_SUPPORT */
typedef float F;
typedef float4 F4;
# define convert_F4 convert_float4
#endif /* NOT DOUBLE_SUPPORT */

#define INTER_BITS 5
#define INTER_TAB_SIZE (1 << INTER_BITS)
#define INTER_SCALE 1.f/INTER_TAB_SIZE
#define AB_BITS max(10, (int)INTER_BITS)
#define AB_SCALE (1 << AB_BITS)
#define INTER_REMAP_COEF_BITS 15
#define INTER_REMAP_COEF_SCALE (1 << INTER_REMAP_COEF_BITS)

inline void interpolateCubic( float x, float* coeffs )
{
    const float A = -0.75f;

    coeffs[0] = ((A*(x + 1.f) - 5.0f*A)*(x + 1.f) + 8.0f*A)*(x + 1.f) - 4.0f*A;
    coeffs[1] = ((A + 2.f)*x - (A + 3.f))*x*x + 1.f;
    coeffs[2] = ((A + 2.f)*(1.f - x) - (A + 3.f))*(1.f - x)*(1.f - x) + 1.f;
    coeffs[3] = 1.f - coeffs[0] - coeffs[1] - coeffs[2];
}

/**********************************************8UC1*********************************************
***********************************************************************************************/
__kernel void warpAffineNN_C1_D0(__global uchar const * restrict src, __global uchar * dst, int src_cols, int src_rows,
                                 int dst_cols, int dst_rows, int srcStep, int dstStep,
                                 int src_offset, int dst_offset,  __constant F * M, int threadCols )
{
    int dx = get_global_id(0);
    int dy = get_global_id(1);

    if( dx < threadCols && dy < dst_rows)
    {
        dx = (dx<<2) - (dst_offset&3);

        int round_delta = (AB_SCALE>>1);

        int4 X, Y;
        int4 sx, sy;
        int4 DX = (int4)(dx, dx+1, dx+2, dx+3);
        DX = (DX << AB_BITS);
        F4 M0DX, M3DX;
        M0DX = M[0] * convert_F4(DX);
        M3DX = M[3] * convert_F4(DX);
        X = convert_int4(rint(M0DX));
        Y = convert_int4(rint(M3DX));
        int tmp1, tmp2;
        tmp1 = rint((M[1]*dy + M[2]) * AB_SCALE);
        tmp2 = rint((M[4]*dy + M[5]) * AB_SCALE);

        X += tmp1 + round_delta;
        Y += tmp2 + round_delta;

        sx = convert_int4(convert_short4(X >> AB_BITS));
        sy = convert_int4(convert_short4(Y >> AB_BITS));

        __global uchar4 * d = (__global uchar4 *)(dst+dst_offset+dy*dstStep+dx);
        uchar4 dval = *d;
        DX = (int4)(dx, dx+1, dx+2, dx+3);
        int4 dcon = DX >= 0 && DX < dst_cols && dy >= 0 && dy < dst_rows;
        int4 scon = sx >= 0 && sx < src_cols && sy >= 0 && sy < src_rows;
        int4 spos = src_offset + sy * srcStep + sx;
        uchar4 sval;
        sval.s0 = scon.s0 ? src[spos.s0] : 0;
        sval.s1 = scon.s1 ? src[spos.s1] : 0;
        sval.s2 = scon.s2 ? src[spos.s2] : 0;
        sval.s3 = scon.s3 ? src[spos.s3] : 0;
        dval = convert_uchar4(dcon) != (uchar4)(0,0,0,0) ? sval : dval;
        *d = dval;
    }
}

__kernel void warpAffineLinear_C1_D0(__global const uchar * restrict src, __global uchar * dst, int src_cols, int src_rows,
                                     int dst_cols, int dst_rows, int srcStep, int dstStep,
                                     int src_offset, int dst_offset,  __constant F * M, int threadCols )
{
    int dx = get_global_id(0);
    int dy = get_global_id(1);

    if( dx < threadCols && dy < dst_rows)
    {
        dx = (dx<<2) - (dst_offset&3);

        int round_delta = ((AB_SCALE >> INTER_BITS) >> 1);

        int4 X, Y;
        short4  ax, ay;
        int4 sx, sy;
        int4 DX = (int4)(dx, dx+1, dx+2, dx+3);
        DX = (DX << AB_BITS);
        F4 M0DX, M3DX;
        M0DX = M[0] * convert_F4(DX);
        M3DX = M[3] * convert_F4(DX);
        X = convert_int4(rint(M0DX));
        Y = convert_int4(rint(M3DX));

        int tmp1, tmp2;
        tmp1 = rint((M[1]*dy + M[2]) * AB_SCALE);
        tmp2 = rint((M[4]*dy + M[5]) * AB_SCALE);

        X += tmp1 + round_delta;
        Y += tmp2 + round_delta;

        X = X >> (AB_BITS - INTER_BITS);
        Y = Y >> (AB_BITS - INTER_BITS);

        sx = convert_int4(convert_short4(X >> INTER_BITS));
        sy = convert_int4(convert_short4(Y >> INTER_BITS));
        ax = convert_short4(X & (INTER_TAB_SIZE-1));
        ay = convert_short4(Y & (INTER_TAB_SIZE-1));

        uchar4 v0, v1, v2,v3;
        int4 scon0, scon1, scon2, scon3;
        int4 spos0, spos1, spos2, spos3;

        scon0 = (sx >= 0 && sx < src_cols && sy >= 0 && sy < src_rows);
        scon1 = (sx+1 >= 0 && sx+1 < src_cols && sy >= 0 && sy < src_rows);
        scon2 = (sx >= 0 && sx < src_cols && sy+1 >= 0 && sy+1 < src_rows);
        scon3 = (sx+1 >= 0 && sx+1 < src_cols && sy+1 >= 0 && sy+1 < src_rows);
        spos0 = src_offset + sy * srcStep + sx;
        spos1 = src_offset + sy * srcStep + sx + 1;
        spos2 = src_offset + (sy+1) * srcStep + sx;
        spos3 = src_offset + (sy+1) * srcStep + sx + 1;

        v0.s0 = scon0.s0 ? src[spos0.s0] : 0;
        v1.s0 = scon1.s0 ? src[spos1.s0] : 0;
        v2.s0 = scon2.s0 ? src[spos2.s0] : 0;
        v3.s0 = scon3.s0 ? src[spos3.s0] : 0;

        v0.s1 = scon0.s1 ? src[spos0.s1] : 0;
        v1.s1 = scon1.s1 ? src[spos1.s1] : 0;
        v2.s1 = scon2.s1 ? src[spos2.s1] : 0;
        v3.s1 = scon3.s1 ? src[spos3.s1] : 0;

        v0.s2 = scon0.s2 ? src[spos0.s2] : 0;
        v1.s2 = scon1.s2 ? src[spos1.s2] : 0;
        v2.s2 = scon2.s2 ? src[spos2.s2] : 0;
        v3.s2 = scon3.s2 ? src[spos3.s2] : 0;

        v0.s3 = scon0.s3 ? src[spos0.s3] : 0;
        v1.s3 = scon1.s3 ? src[spos1.s3] : 0;
        v2.s3 = scon2.s3 ? src[spos2.s3] : 0;
        v3.s3 = scon3.s3 ? src[spos3.s3] : 0;

        short4 itab0, itab1, itab2, itab3;
        float4 taby, tabx;
        taby = INTER_SCALE * convert_float4(ay);
        tabx = INTER_SCALE * convert_float4(ax);

        itab0 = convert_short4_sat(( (1.0f-taby)*(1.0f-tabx) * (float4)INTER_REMAP_COEF_SCALE ));
        itab1 = convert_short4_sat(( (1.0f-taby)*tabx * (float4)INTER_REMAP_COEF_SCALE ));
        itab2 = convert_short4_sat(( taby*(1.0f-tabx) * (float4)INTER_REMAP_COEF_SCALE ));
        itab3 = convert_short4_sat(( taby*tabx * (float4)INTER_REMAP_COEF_SCALE ));

        int4 val;
        uchar4 tval;
        val = convert_int4(v0) * convert_int4(itab0) + convert_int4(v1) * convert_int4(itab1)
              + convert_int4(v2) * convert_int4(itab2) + convert_int4(v3) * convert_int4(itab3);
        tval = convert_uchar4_sat ( (val + (1 << (INTER_REMAP_COEF_BITS-1))) >> INTER_REMAP_COEF_BITS ) ;

        __global uchar4 * d =(__global uchar4 *)(dst+dst_offset+dy*dstStep+dx);
        uchar4 dval = *d;
        DX = (int4)(dx, dx+1, dx+2, dx+3);
        int4 dcon = DX >= 0 && DX < dst_cols && dy >= 0 && dy < dst_rows;
        dval = convert_uchar4(dcon != 0) ? tval : dval;
        *d = dval;
    }
}

__kernel void warpAffineCubic_C1_D0(__global uchar * src, __global uchar * dst, int src_cols, int src_rows,
                                    int dst_cols, int dst_rows, int srcStep, int dstStep,
                                    int src_offset, int dst_offset,  __constant F * M, int threadCols )
{
    int dx = get_global_id(0);
    int dy = get_global_id(1);

    if( dx < threadCols && dy < dst_rows)
    {
        int round_delta = ((AB_SCALE>>INTER_BITS)>>1);

        int X0 = rint(M[0] * dx * AB_SCALE);
        int Y0 = rint(M[3] * dx * AB_SCALE);
        X0 += rint((M[1]*dy + M[2]) * AB_SCALE) + round_delta;
        Y0 += rint((M[4]*dy + M[5]) * AB_SCALE) + round_delta;
        int X = X0 >> (AB_BITS - INTER_BITS);
        int Y = Y0 >> (AB_BITS - INTER_BITS);

        short sx = (short)(X >> INTER_BITS) - 1;
        short sy = (short)(Y >> INTER_BITS) - 1;
        short ay = (short)(Y & (INTER_TAB_SIZE-1));
        short ax = (short)(X & (INTER_TAB_SIZE-1));

        uchar v[16];
        int i, j;

#pragma unroll 4
        for(i=0; i<4;  i++)
            for(j=0; j<4;  j++)
            {
                v[i*4+j] = (sx+j >= 0 && sx+j < src_cols && sy+i >= 0 && sy+i < src_rows) ? src[src_offset+(sy+i) * srcStep + (sx+j)] : 0;
            }

        short itab[16];
        float tab1y[4], tab1x[4];
        float axx, ayy;

        ayy = 1.f/INTER_TAB_SIZE * ay;
        axx = 1.f/INTER_TAB_SIZE * ax;
        interpolateCubic(ayy, tab1y);
        interpolateCubic(axx, tab1x);
        int isum = 0;

#pragma unroll 16
        for( i=0; i<16; i++ )
        {
            F v = tab1y[(i>>2)] * tab1x[(i&3)];
            isum += itab[i] = convert_short_sat( rint( v * INTER_REMAP_COEF_SCALE ) );
        }

        if( isum != INTER_REMAP_COEF_SCALE )
        {
            int k1, k2;
            int diff = isum - INTER_REMAP_COEF_SCALE;
            int Mk1=2, Mk2=2, mk1=2, mk2=2;
            for( k1 = 2; k1 < 4; k1++ )
                for( k2 = 2; k2 < 4; k2++ )
                {
                    if( itab[(k1<<2)+k2] < itab[(mk1<<2)+mk2] )
                        mk1 = k1, mk2 = k2;
                    else if( itab[(k1<<2)+k2] > itab[(Mk1<<2)+Mk2] )
                        Mk1 = k1, Mk2 = k2;
                }
            diff<0 ? (itab[(Mk1<<2)+Mk2]=(short)(itab[(Mk1<<2)+Mk2]-diff)) : (itab[(mk1<<2)+mk2]=(short)(itab[(mk1<<2)+mk2]-diff));
        }

        if( dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows)
        {
            int sum=0;
            for ( i =0; i<16; i++ )
            {
                sum += v[i] * itab[i] ;
            }
            dst[dst_offset+dy*dstStep+dx] = convert_uchar_sat( (sum + (1 << (INTER_REMAP_COEF_BITS-1))) >> INTER_REMAP_COEF_BITS ) ;
        }
    }
}

/**********************************************8UC4*********************************************
***********************************************************************************************/

__kernel void warpAffineNN_C4_D0(__global uchar4 const * restrict src, __global uchar4 * dst, int src_cols, int src_rows,
                                 int dst_cols, int dst_rows, int srcStep, int dstStep,
                                 int src_offset, int dst_offset,  __constant F * M, int threadCols )
{
    int dx = get_global_id(0);
    int dy = get_global_id(1);

    if( dx < threadCols && dy < dst_rows)
    {
        int round_delta = (AB_SCALE >> 1);

        int X0 = rint(M[0] * dx * AB_SCALE);
        int Y0 = rint(M[3] * dx * AB_SCALE);
        X0 += rint((M[1]*dy + M[2]) * AB_SCALE) + round_delta;
        Y0 += rint((M[4]*dy + M[5]) * AB_SCALE) + round_delta;

        int sx0 = (short)(X0 >> AB_BITS);
        int sy0 = (short)(Y0 >> AB_BITS);

        if(dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows)
            dst[(dst_offset>>2)+dy*(dstStep>>2)+dx]= (sx0>=0 && sx0<src_cols && sy0>=0 && sy0<src_rows) ? src[(src_offset>>2)+sy0*(srcStep>>2)+sx0] : (uchar4)0;
    }
}

__kernel void warpAffineLinear_C4_D0(__global uchar4 const * restrict src, __global uchar4 * dst, int src_cols, int src_rows,
                                     int dst_cols, int dst_rows, int srcStep, int dstStep,
                                     int src_offset, int dst_offset,  __constant F * M, int threadCols )
{
    int dx = get_global_id(0);
    int dy = get_global_id(1);

    if( dx < threadCols && dy < dst_rows)
    {
        int round_delta = AB_SCALE/INTER_TAB_SIZE/2;

        src_offset = (src_offset>>2);
        srcStep = (srcStep>>2);

        int tmp = (dx << AB_BITS);
        int X0 = rint(M[0] * tmp);
        int Y0 = rint(M[3] * tmp);
        X0 += rint((M[1]*dy + M[2]) * AB_SCALE) + round_delta;
        Y0 += rint((M[4]*dy + M[5]) * AB_SCALE) + round_delta;
        X0 = X0 >> (AB_BITS - INTER_BITS);
        Y0 = Y0 >> (AB_BITS - INTER_BITS);

        short sx0 = (short)(X0 >> INTER_BITS);
        short sy0 = (short)(Y0 >> INTER_BITS);
        short ax0 = (short)(X0 & (INTER_TAB_SIZE-1));
        short ay0 = (short)(Y0 & (INTER_TAB_SIZE-1));

        int4 v0, v1, v2, v3;

        v0 = (sx0 >= 0 && sx0 < src_cols && sy0 >= 0 && sy0 < src_rows) ? convert_int4(src[src_offset+sy0 * srcStep + sx0]) : 0;
        v1 = (sx0+1 >= 0 && sx0+1 < src_cols && sy0 >= 0 && sy0 < src_rows) ? convert_int4(src[src_offset+sy0 * srcStep + sx0+1]) : 0;
        v2 = (sx0 >= 0 && sx0 < src_cols && sy0+1 >= 0 && sy0+1 < src_rows) ? convert_int4(src[src_offset+(sy0+1) * srcStep + sx0]) : 0;
        v3 = (sx0+1 >= 0 && sx0+1 < src_cols && sy0+1 >= 0 && sy0+1 < src_rows) ? convert_int4(src[src_offset+(sy0+1) * srcStep + sx0+1]) : 0;

        int itab0, itab1, itab2, itab3;
        float taby, tabx;
        taby = 1.f/INTER_TAB_SIZE*ay0;
        tabx = 1.f/INTER_TAB_SIZE*ax0;

        itab0 = convert_short_sat(rint( (1.0f-taby)*(1.0f-tabx) * INTER_REMAP_COEF_SCALE ));
        itab1 = convert_short_sat(rint( (1.0f-taby)*tabx * INTER_REMAP_COEF_SCALE ));
        itab2 = convert_short_sat(rint( taby*(1.0f-tabx) * INTER_REMAP_COEF_SCALE ));
        itab3 = convert_short_sat(rint( taby*tabx * INTER_REMAP_COEF_SCALE ));

        int4 val;
        val = v0 * itab0 +  v1 * itab1 + v2 * itab2 + v3 * itab3;

        if(dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows)
            dst[(dst_offset>>2)+dy*(dstStep>>2)+dx] =  convert_uchar4_sat ( (val + (1 << (INTER_REMAP_COEF_BITS-1))) >> INTER_REMAP_COEF_BITS ) ;
    }
}

__kernel void warpAffineCubic_C4_D0(__global uchar4 const * restrict src, __global uchar4 * dst, int src_cols, int src_rows,
                                    int dst_cols, int dst_rows, int srcStep, int dstStep,
                                    int src_offset, int dst_offset,  __constant F * M, int threadCols )
{
    int dx = get_global_id(0);
    int dy = get_global_id(1);

    if( dx < threadCols && dy < dst_rows)
    {
        int round_delta = ((AB_SCALE>>INTER_BITS)>>1);

        src_offset = (src_offset>>2);
        srcStep = (srcStep>>2);
        dst_offset = (dst_offset>>2);
        dstStep = (dstStep>>2);

        int tmp = (dx << AB_BITS);
        int X0 = rint(M[0] * tmp);
        int Y0 = rint(M[3] * tmp);
        X0 += rint((M[1]*dy + M[2]) * AB_SCALE) + round_delta;
        Y0 += rint((M[4]*dy + M[5]) * AB_SCALE) + round_delta;
        X0 = X0 >> (AB_BITS - INTER_BITS);
        Y0 = Y0 >> (AB_BITS - INTER_BITS);

        int sx = (short)(X0 >> INTER_BITS) - 1;
        int sy = (short)(Y0 >> INTER_BITS) - 1;
        int ay = (short)(Y0 & (INTER_TAB_SIZE-1));
        int ax = (short)(X0 & (INTER_TAB_SIZE-1));

        uchar4 v[16];
        int i,j;
#pragma unroll 4
        for(i=0; i<4; i++)
            for(j=0; j<4; j++)
            {
                v[i*4+j] = (sx+j >= 0 && sx+j < src_cols && sy+i >= 0 && sy+i < src_rows) ? (src[src_offset+(sy+i) * srcStep + (sx+j)])  : (uchar4)0;
            }
        int itab[16];
        float tab1y[4], tab1x[4];
        float axx, ayy;

        ayy = INTER_SCALE * ay;
        axx = INTER_SCALE * ax;
        interpolateCubic(ayy, tab1y);
        interpolateCubic(axx, tab1x);
        int isum = 0;

#pragma unroll 16
        for( i=0; i<16; i++ )
        {
            float tmp;
            tmp = tab1y[(i>>2)] * tab1x[(i&3)] * INTER_REMAP_COEF_SCALE;
            itab[i] = rint(tmp);
            isum += itab[i];
        }

        if( isum != INTER_REMAP_COEF_SCALE )
        {
            int k1, k2;
            int diff = isum - INTER_REMAP_COEF_SCALE;
            int Mk1=2, Mk2=2, mk1=2, mk2=2;

            for( k1 = 2; k1 < 4; k1++ )
                for( k2 = 2; k2 < 4; k2++ )
                {

                    if( itab[(k1<<2)+k2] < itab[(mk1<<2)+mk2] )
                        mk1 = k1, mk2 = k2;
                    else if( itab[(k1<<2)+k2] > itab[(Mk1<<2)+Mk2] )
                        Mk1 = k1, Mk2 = k2;
                }

            diff<0 ? (itab[(Mk1<<2)+Mk2]=(short)(itab[(Mk1<<2)+Mk2]-diff)) : (itab[(mk1<<2)+mk2]=(short)(itab[(mk1<<2)+mk2]-diff));
        }

        if( dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows)
        {
            int4 sum=0;
            for ( i =0; i<16; i++ )
            {
                sum += convert_int4(v[i]) * itab[i];
            }
            dst[dst_offset+dy*dstStep+dx] = convert_uchar4_sat( (sum + (1 << (INTER_REMAP_COEF_BITS-1))) >> INTER_REMAP_COEF_BITS ) ;
        }
    }
}

/**********************************************32FC1********************************************
***********************************************************************************************/

__kernel void warpAffineNN_C1_D5(__global float * src, __global float * dst, int src_cols, int src_rows,
                                 int dst_cols, int dst_rows, int srcStep, int dstStep,
                                 int src_offset, int dst_offset,  __constant F * M, int threadCols )
{
    int dx = get_global_id(0);
    int dy = get_global_id(1);

    if( dx < threadCols && dy < dst_rows)
    {
        int round_delta = AB_SCALE/2;

        int X0 = rint(M[0] * dx * AB_SCALE);
        int Y0 = rint(M[3] * dx * AB_SCALE);
        X0 += rint((M[1]*dy + M[2]) * AB_SCALE) + round_delta;
        Y0 += rint((M[4]*dy + M[5]) * AB_SCALE) + round_delta;

        short sx0 = (short)(X0 >> AB_BITS);
        short sy0 = (short)(Y0 >> AB_BITS);

        if(dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows)
            dst[(dst_offset>>2)+dy*dstStep+dx]= (sx0>=0 && sx0<src_cols && sy0>=0 && sy0<src_rows) ? src[(src_offset>>2)+sy0*srcStep+sx0] : 0;
    }
}

__kernel void warpAffineLinear_C1_D5(
    __global float * src, __global float * dst, int src_cols, int src_rows,
    int dst_cols, int dst_rows, int srcStep, int dstStep,
    int src_offset, int dst_offset,  __constant F * M, int threadCols
    )
{
    int dx = get_global_id(0);
    int dy = get_global_id(1);

    if( dx < threadCols && dy < dst_rows)
    {
        int round_delta = AB_SCALE/INTER_TAB_SIZE/2;

        src_offset = (src_offset>>2);

        int X0 = rint(M[0] * dx * AB_SCALE);
        int Y0 = rint(M[3] * dx * AB_SCALE);
        X0 += rint((M[1]*dy + M[2]) * AB_SCALE) + round_delta;
        Y0 += rint((M[4]*dy + M[5]) * AB_SCALE) + round_delta;
        X0 = X0 >> (AB_BITS - INTER_BITS);
        Y0 = Y0 >> (AB_BITS - INTER_BITS);

        short sx0 = (short)(X0 >> INTER_BITS);
        short sy0 = (short)(Y0 >> INTER_BITS);
        short ax0 = (short)(X0 & (INTER_TAB_SIZE-1));
        short ay0 = (short)(Y0 & (INTER_TAB_SIZE-1));

        float v0, v1, v2, v3;

        v0 = (sx0 >= 0 && sx0 < src_cols && sy0 >= 0 && sy0 < src_rows) ? src[src_offset+sy0 * srcStep + sx0] : 0;
        v1 = (sx0+1 >= 0 && sx0+1 < src_cols && sy0 >= 0 && sy0 < src_rows) ? src[src_offset+sy0 * srcStep + sx0+1] : 0;
        v2 = (sx0 >= 0 && sx0 < src_cols && sy0+1 >= 0 && sy0+1 < src_rows) ? src[src_offset+(sy0+1) * srcStep + sx0] : 0;
        v3 = (sx0+1 >= 0 && sx0+1 < src_cols && sy0+1 >= 0 && sy0+1 < src_rows) ? src[src_offset+(sy0+1) * srcStep + sx0+1] : 0;

        float tab[4];
        float taby[2], tabx[2];
        taby[0] = 1.0 - 1.f/INTER_TAB_SIZE*ay0;
        taby[1] = 1.f/INTER_TAB_SIZE*ay0;
        tabx[0] = 1.0 - 1.f/INTER_TAB_SIZE*ax0;
        tabx[1] = 1.f/INTER_TAB_SIZE*ax0;

        tab[0] = taby[0] * tabx[0];
        tab[1] = taby[0] * tabx[1];
        tab[2] = taby[1] * tabx[0];
        tab[3] = taby[1] * tabx[1];

        float sum = 0;
        sum += v0 * tab[0] +  v1 * tab[1] +  v2 * tab[2] +  v3 * tab[3];
        if(dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows)
            dst[(dst_offset>>2)+dy*dstStep+dx] = sum;
    }
}

__kernel void warpAffineCubic_C1_D5(__global float * src, __global float * dst, int src_cols, int src_rows,
                                    int dst_cols, int dst_rows, int srcStep, int dstStep,
                                    int src_offset, int dst_offset,  __constant F * M, int threadCols )
{
    int dx = get_global_id(0);
    int dy = get_global_id(1);

    if( dx < threadCols && dy < dst_rows)
    {
        int round_delta = AB_SCALE/INTER_TAB_SIZE/2;

        src_offset = (src_offset>>2);
        dst_offset = (dst_offset>>2);

        int X0 = rint(M[0] * dx * AB_SCALE);
        int Y0 = rint(M[3] * dx * AB_SCALE);
        X0 += rint((M[1]*dy + M[2]) * AB_SCALE) + round_delta;
        Y0 += rint((M[4]*dy + M[5]) * AB_SCALE) + round_delta;
        X0 = X0 >> (AB_BITS - INTER_BITS);
        Y0 = Y0 >> (AB_BITS - INTER_BITS);

        short sx = (short)(X0 >> INTER_BITS) - 1;
        short sy = (short)(Y0 >> INTER_BITS) - 1;
        short ay = (short)(Y0 & (INTER_TAB_SIZE-1));
        short ax = (short)(X0 & (INTER_TAB_SIZE-1));

        float v[16];
        int i;

        for(i=0; i<16;  i++)
            v[i] = (sx+(i&3) >= 0 && sx+(i&3) < src_cols && sy+(i>>2) >= 0 && sy+(i>>2) < src_rows) ? src[src_offset+(sy+(i>>2)) * srcStep + (sx+(i&3))] : 0;

        float tab[16];
        float tab1y[4], tab1x[4];
        float axx, ayy;

        ayy = 1.f/INTER_TAB_SIZE * ay;
        axx = 1.f/INTER_TAB_SIZE * ax;
        interpolateCubic(ayy, tab1y);
        interpolateCubic(axx, tab1x);

#pragma unroll 4
        for( i=0; i<16; i++ )
        {
            tab[i] = tab1y[(i>>2)] * tab1x[(i&3)];
        }

        if( dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows)
        {
            float sum = 0;
#pragma unroll 4
            for ( i =0; i<16; i++ )
            {
                sum += v[i] * tab[i];
            }
            dst[dst_offset+dy*dstStep+dx] = sum;

        }
    }
}

/**********************************************32FC4********************************************
***********************************************************************************************/

__kernel void warpAffineNN_C4_D5(__global float4 * src, __global float4 * dst, int src_cols, int src_rows,
                                 int dst_cols, int dst_rows, int srcStep, int dstStep,
                                 int src_offset, int dst_offset,  __constant F * M, int threadCols )
{
    int dx = get_global_id(0);
    int dy = get_global_id(1);

    if( dx < threadCols && dy < dst_rows)
    {
        int round_delta = AB_SCALE/2;

        int X0 = rint(M[0] * dx * AB_SCALE);
        int Y0 = rint(M[3] * dx * AB_SCALE);
        X0 += rint((M[1]*dy + M[2]) * AB_SCALE) + round_delta;
        Y0 += rint((M[4]*dy + M[5]) * AB_SCALE) + round_delta;

        short sx0 = (short)(X0 >> AB_BITS);
        short sy0 = (short)(Y0 >> AB_BITS);

        if(dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows)
            dst[(dst_offset>>4)+dy*(dstStep>>2)+dx]= (sx0>=0 && sx0<src_cols && sy0>=0 && sy0<src_rows) ? src[(src_offset>>4)+sy0*(srcStep>>2)+sx0] : (float4)0;
    }
}

__kernel void warpAffineLinear_C4_D5(__global float4 * src, __global float4 * dst, int src_cols, int src_rows,
                                     int dst_cols, int dst_rows, int srcStep, int dstStep,
                                     int src_offset, int dst_offset,  __constant F * M, int threadCols )
{
    int dx = get_global_id(0);
    int dy = get_global_id(1);

    if( dx < threadCols && dy < dst_rows)
    {
        int round_delta = AB_SCALE/INTER_TAB_SIZE/2;

        src_offset = (src_offset>>4);
        dst_offset = (dst_offset>>4);
        srcStep = (srcStep>>2);
        dstStep = (dstStep>>2);

        int X0 = rint(M[0] * dx * AB_SCALE);
        int Y0 = rint(M[3] * dx * AB_SCALE);
        X0 += rint((M[1]*dy + M[2]) * AB_SCALE) + round_delta;
        Y0 += rint((M[4]*dy + M[5]) * AB_SCALE) + round_delta;
        X0 = X0 >> (AB_BITS - INTER_BITS);
        Y0 = Y0 >> (AB_BITS - INTER_BITS);

        short sx0 = (short)(X0 >> INTER_BITS);
        short sy0 = (short)(Y0 >> INTER_BITS);
        short ax0 = (short)(X0 & (INTER_TAB_SIZE-1));
        short ay0 = (short)(Y0 & (INTER_TAB_SIZE-1));

        float4 v0, v1, v2, v3;

        v0 = (sx0 >= 0 && sx0 < src_cols && sy0 >= 0 && sy0 < src_rows) ? src[src_offset+sy0 * srcStep + sx0] : (float4)0;
        v1 = (sx0+1 >= 0 && sx0+1 < src_cols && sy0 >= 0 && sy0 < src_rows) ? src[src_offset+sy0 * srcStep + sx0+1] : (float4)0;
        v2 = (sx0 >= 0 && sx0 < src_cols && sy0+1 >= 0 && sy0+1 < src_rows) ? src[src_offset+(sy0+1) * srcStep + sx0] : (float4)0;
        v3 = (sx0+1 >= 0 && sx0+1 < src_cols && sy0+1 >= 0 && sy0+1 < src_rows) ? src[src_offset+(sy0+1) * srcStep + sx0+1] : (float4)0;

        float tab[4];
        float taby[2], tabx[2];
        taby[0] = 1.0 - 1.f/INTER_TAB_SIZE*ay0;
        taby[1] = 1.f/INTER_TAB_SIZE*ay0;
        tabx[0] = 1.0 - 1.f/INTER_TAB_SIZE*ax0;
        tabx[1] = 1.f/INTER_TAB_SIZE*ax0;

        tab[0] = taby[0] * tabx[0];
        tab[1] = taby[0] * tabx[1];
        tab[2] = taby[1] * tabx[0];
        tab[3] = taby[1] * tabx[1];

        float4 sum = 0;
        sum += v0 * tab[0] +  v1 * tab[1] +  v2 * tab[2] +  v3 * tab[3];
        if(dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows)
            dst[dst_offset+dy*dstStep+dx] = sum;
    }
}

__kernel void warpAffineCubic_C4_D5(__global float4 * src, __global float4 * dst, int src_cols, int src_rows,
                                    int dst_cols, int dst_rows, int srcStep, int dstStep,
                                    int src_offset, int dst_offset,  __constant F * M, int threadCols )
{
    int dx = get_global_id(0);
    int dy = get_global_id(1);

    if( dx < threadCols && dy < dst_rows)
    {
        int round_delta = AB_SCALE/INTER_TAB_SIZE/2;

        src_offset = (src_offset>>4);
        dst_offset = (dst_offset>>4);
        srcStep = (srcStep>>2);
        dstStep = (dstStep>>2);

        int X0 = rint(M[0] * dx * AB_SCALE);
        int Y0 = rint(M[3] * dx * AB_SCALE);
        X0 += rint((M[1]*dy + M[2]) * AB_SCALE) + round_delta;
        Y0 += rint((M[4]*dy + M[5]) * AB_SCALE) + round_delta;
        X0 = X0 >> (AB_BITS - INTER_BITS);
        Y0 = Y0 >> (AB_BITS - INTER_BITS);

        short sx = (short)(X0 >> INTER_BITS) - 1;
        short sy = (short)(Y0 >> INTER_BITS) - 1;
        short ay = (short)(Y0 & (INTER_TAB_SIZE-1));
        short ax = (short)(X0 & (INTER_TAB_SIZE-1));

        float4 v[16];
        int i;

        for(i=0; i<16;  i++)
            v[i] = (sx+(i&3) >= 0 && sx+(i&3) < src_cols && sy+(i>>2) >= 0 && sy+(i>>2) < src_rows) ? src[src_offset+(sy+(i>>2)) * srcStep + (sx+(i&3))] : (float4)0;

        float tab[16];
        float tab1y[4], tab1x[4];
        float axx, ayy;

        ayy = 1.f/INTER_TAB_SIZE * ay;
        axx = 1.f/INTER_TAB_SIZE * ax;
        interpolateCubic(ayy, tab1y);
        interpolateCubic(axx, tab1x);

#pragma unroll 4
        for( i=0; i<16; i++ )
        {
            tab[i] = tab1y[(i>>2)] * tab1x[(i&3)];
        }

        if( dx >= 0 && dx < dst_cols && dy >= 0 && dy < dst_rows)
        {
            float4 sum = 0;
#pragma unroll 4
            for ( i =0; i<16; i++ )
            {
                sum += v[i] * tab[i];
            }
            dst[dst_offset+dy*dstStep+dx] = sum;

        }
    }
}


vector recognise

vector recognise

__kernel void vector_add(__global int *A, __global int *B, __global int *C) {

    // Get the index of the current element
    int i = get_global_id(0);

    // Do the operation
    C[i] = A[i] + B[i];
}

__kernel void taskParrallelSub(__global float *A, __global float *B, __global float *C) {
    int base = 1;

    C[base+0] = A[base+0] - B[base+0];
    C[base+4] = A[base+4] - b[base+4];
}

__kernel void dataParallel(__global float *A, __global float *B, __global float *C) {
        int base = 4*get_global_id(0);
        C[base+0] = A[base+0] + B[base+0];
        C[base+1] = A[base+1] - B[base+1];
        C[base+2] = A[base+2] * B[base+2];
        C[base+3] = A[base+3] / B[base+3];
}

__kernel void runRecogniser(__global float *imageVal) {

}

__kernel void vector_add(__global int *A, __global int *B, __global int *C) {

    // Get the index of the current element
    int i = get_global_id(0);

    // Do the operation
    C[i] = A[i] + B[i];
}

__kernel void taskParrallelSub(__global float *A, __global float *B, __global float *C) {
    int base = 1;

    C[base+0] = A[base+0] - B[base+0];
    C[base+4] = A[base+4] - b[base+4];
}

__kernel void
dataParallel(__global float* A, __global float* B, __global float* C) {
        int base = 4*get_global_id(0);
        C[base+0] = A[base+0] + B[base+0];
        C[base+1] = A[base+1] - B[base+1];
        C[base+2] = A[base+2] * B[base+2];
        C[base+3] = A[base+3] / B[base+3];
}


removed inter_light useless funk

removed inter_light useless funk

#include "kernel_header.h"
#include "kernel_color.h"
#include "kernel_data.h"
#include "kernel_vector.h"
#include "kernel_debug.h"

float3						rotat_zyx(float3 vect, float pitch, float yaw, float roll)
{
	float3					res;
	float					rad_pitch = pitch * DEG2RAD;
	float					rad_yaw = yaw * DEG2RAD;
	float					rad_roll = roll * DEG2RAD;

	res.x = vect.x * cos(rad_roll) * cos(rad_yaw) + vect.y * (cos(rad_pitch) * -sin(rad_roll) + cos(rad_roll) * sin(rad_yaw) * sin(rad_pitch)) + vect.z * (-sin(rad_roll) * -sin(rad_pitch) + cos(rad_roll) * sin(rad_yaw) * cos(rad_pitch));
	res.y = vect.x * sin(rad_roll) * cos(rad_yaw) + vect.y * (cos(rad_roll) * cos(rad_pitch) + sin(rad_roll) * sin(rad_yaw) * sin(rad_pitch)) + vect.z * (cos(rad_roll) * -sin(rad_pitch) + sin(rad_roll) * sin(rad_yaw) * cos(rad_pitch));
	res.z = vect.x * -sin(rad_yaw) + vect.y * cos(rad_yaw) * sin(rad_pitch) + vect.z * cos(rad_yaw) * cos(rad_pitch);
	return (res);
}

float3						rotat_xyz(float3 vect, float pitch, float yaw, float roll)
{
	float3					res;
	float					rad_pitch = pitch * DEG2RAD;
	float					rad_yaw = yaw * DEG2RAD;
	float					rad_roll = roll * DEG2RAD;

	res.x = vect.x * cos(rad_yaw) * cos(rad_roll) + vect.y * cos(rad_yaw) * -sin(rad_roll) + vect.z * sin(rad_yaw);
	res.y = vect.x * (-sin(rad_pitch) * -sin(rad_yaw) * cos(rad_roll) + cos(rad_pitch) * sin(rad_roll)) + vect.y * (-sin(rad_pitch) * -sin(rad_yaw) * -sin(rad_roll) + cos(rad_pitch) * cos(rad_roll)) + vect.z * cos(rad_yaw) * -sin(rad_pitch);
	res.z = vect.x * (cos(rad_pitch) * -sin(rad_yaw) * cos(rad_roll) + sin(rad_pitch) * sin(rad_roll)) + vect.y * (cos(rad_pitch) * -sin(rad_yaw) * -sin(rad_roll) + sin(rad_pitch) * cos(rad_roll)) + vect.z * cos(rad_yaw) * cos(rad_pitch);
	return (res);
}

float3					rotate_obj(float3 v, float pitch, float yaw, float roll)
{
	float3				res;

	res = rotat_zyx(v, pitch, yaw, roll);

	return (normalize(res));
}

float3					get_sphere_abc(float radius, float3 ray, float3 origin)
{
	float3		abc;

	abc.x = dot(ray, ray);
	abc.y = 2 * dot(ray, origin);
	abc.z = dot(origin, origin) - (radius * radius);
	return (abc);
}

float					inter_sphere(t_sphere sphere, float3 ray, float3 origin)
{
	float3				abc;
	float				d;
	float				res1;
	float				res2;

	origin -= sphere.pos;
	abc = get_sphere_abc(sphere.radius, ray, origin);
	d = (abc.y * abc.y) - (4 * (abc.x * abc.z));
	if (d < 0)
		return (0);
	if (d == 0)
		return ((-abc[1]) / (2 * abc[0]));
	res1 = (((-abc[1]) + sqrt(d)) / (2 * abc[0]));
	res2 = (((-abc[1]) - sqrt(d)) / (2 * abc[0]));
	if ((res1 < res2 && res1 > 0) || (res1 > res2 && res2 < 0))
		return (res1);
	return (res2);
}

float3					get_cylinder_abc(float radius, float3 dir, float3 ray, float3 origin)
{
	float3		abc;

	// SEMBLE OK
	abc.x = dot(ray, ray) - (dot(ray, dir) * dot(ray, dir));
	abc.y = 2 * (dot(ray, origin) - (dot(ray, dir) * dot(origin, dir)));
	abc.z = dot(origin, origin) - (dot(origin, dir) * dot(origin, dir)) - (radius * radius);
	return (abc);
}

float					inter_cylinder(float height, float3 dir, float radius, float3 pos, float3 ray, float3 origin)
{
	float3				abc;
	//float3				dir = rotate_obj(cyl.dir, cyl.pitch, cyl.yaw, 0);
	float				d;
	float				res1 = 0;
	float				res2 = 0;
	float				m;

	origin -= pos;
	abc = get_cylinder_abc(radius, dir, ray, origin);
	d = (abc.y * abc.y) - (4 * (abc.x * abc.z));
	if (d < 0)
		return (0);
	if (d == 0)
		res1 = (-abc[1]) / (2 * abc[0]);
	else
	{
		res1 = (((-abc[1]) + sqrt(d)) / (2 * abc[0]));
		res2 = (((-abc[1]) - sqrt(d)) / (2 * abc[0]));
	}
	if (res1 < 0 && res2 < 0)
		return (0);
	if ((res1 < res2 && res1 > 0) || (res1 > res2 && res2 < 0))
	{
		if (height == 0 || (dot(ray, dir) * res1 +
			dot(origin, dir) < height && dot(ray, dir) * res1 +
			dot(origin, dir) > 0))
			return (res1);
	}
	if (height ==  0 || (dot(ray, dir) * res2 +
			dot(origin, dir) < height && dot(ray, dir) * res2 +
			dot(origin, dir) > 0))
		return (res2);
	else
		return (0);
}

float3					get_cone_abc(t_cone cone, float3 ray, float3 origin)
{
	float3		abc = 0;
	float		k = cone.angle * DEG2RAD;
	k = tan(k);
	k = 1 + k * k;

	abc.x = dot(ray, ray) - (k * (dot(ray, cone.dir) * dot(ray, cone.dir)));
	abc.y = 2 * (dot(ray, origin) - (k * \
			(dot(ray, cone.dir) * dot(origin, cone.dir))));
	abc.z = (dot(origin, origin) - \
			(k * (dot(origin, cone.dir) * dot(origin, cone.dir))));
	return (abc);
}

float					inter_cone(t_cone cone, float3 ray, float3 origin)
{
	float3				abc;
	float				d;
	float				res1;
	float				res2;
	float				res;

	origin -= cone.pos;
	abc = get_cone_abc(cone, ray, origin);
	d = (abc.y * abc.y) - (4 * (abc.x * abc.z));
	if (d < 0)
		return (0);
	if (d == 0)
		res = (-abc[1]) / (2 * abc[0]);
	res1 = (((-abc[1]) + sqrt(d)) / (2 * abc[0]));
	res2 = (((-abc[1]) - sqrt(d)) / (2 * abc[0]));
	if ((res1 < res2 && res1 > 0) || (res1 > res2 && res2 < 0))
		res = res1;
	else
		res = res2;
	return (res);
}

float					inter_plan(t_plane plane, float3 ray, float3 origin)
{
	float				t;

	if ((t = dot(normalize(ray), normalize(plane.normale))) == 0)
		return (0);
	t = (dot(plane.pos - origin, normalize(plane.normale))) / t;
		if (t < 0.001)
		return (0);
	return (t);
}

t_hit			ray_hit(float3 origin, float3 ray, t_scene scene)
{
	unsigned int			i = 0;
	int						max = get_max_obj(PARAM);
	t_hit					hit = hit_init();
	float					dist = 0;

	while (i < max)
	{
		if (i < PARAM->n_cones)
			if (((dist = inter_cone(CONES[i], ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 1;
				hit.id = i;
			}
		if (i < PARAM->n_cylinders)
			if (((dist = inter_cylinder(CYLIND[i].height, rotate_obj(CYLIND[i].dir, CYLIND[i].pitch, CYLIND[i].yaw, 0), CYLIND[i].radius, CYLIND[i].pos, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 2;
				hit.id = i;
			}
		if (i < PARAM->n_planes)
			if (((dist = inter_plan(PLANE[i], ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 4;
				hit.id = i;
			}
		if (i < PARAM->n_spheres)
			if (((dist = inter_sphere(SPHERE[i], ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 5;
				hit.id = i;
			}
		i++;
	}
	return (hit);
}

float3			rotate_matrix(float angle, float3 v)
{
	float3		res;

	res.x = v.x;
	res.y = (cos(angle) * v.y) - (sin(angle) * v.z);
	res.z = (sin(angle) * v.y) + (cos(angle) * v.z);
	return (res);
}

float16			trans_matrix(float3 dir, float angle)
{
	float16		res = 0;
	float3		rot = 0;

	rot = rotate_obj(dir, 0, angle, 0);
	res[0] = rot.x;
	res[1] = rot.y;
	res[2] = rot.z;
	rot = rotate_obj(dir, -angle, 0, 0);
	res[4] = rot.x;
	res[5] = rot.y;
	res[6] = rot.z;
	res[8] = dir.x;
	res[9] = dir.y;
	res[10] = dir.z;
	return (res);
}

float3			apply_matrix(float16 mat, float3 v)
{
	float3		res = 0;

	res.x = mat[0] * v.x + mat[4] * v.y + mat[8] * v.z;
	res.y = mat[1] * v.x + mat[5] * v.y + mat[9] * v.z;
	res.z = mat[2] * v.x + mat[6] * v.y + mat[10] * v.z;
	return (res);
}

float3			get_hit_normale(t_scene scene, t_hit hit)
{
	float3		res;

	if (hit.type == 1)
	{
		float k = CONES[hit.id].angle * DEG2RAD;
		k = tan(k);
		k = 1 + k * k;
		res = dot(-scene.ray, normalize(CONES[hit.id].dir)) * \
			hit.dist - dot(ACTIVECAM.pos + PARAM->mvt - CONES[hit.id].pos, normalize(CONES[hit.id].dir));
		res = ((hit.pos - normalize(CONES[hit.id].pos)) - (k * normalize(CONES[hit.id].dir) * res)) * -1;
	}
	else if (hit.type == 2)
	{
		/*float3	base = CYLIND[hit.id].pos;
		res = hit.pos;

		res = rotate_matrix(45 * DEG2RAD, res);
		base.z = res.z;
		base = rotate_matrix(-45 * DEG2RAD, base);
		res = rotate_matrix(-45 * DEG2RAD, res);
		res -= base;*/
//		res = dot(-scene.ray, normalize(CYLIND[hit.id].dir) * hit.dist + \
//			dot(ACTIVECAM.pos + PARAM->mvt - CYLIND[hit.id].pos, normalize(CYLIND[hit.id].dir)));
//		res = hit.pos - CYLIND[hit.id].pos - normalize(CYLIND[hit.id].dir) * res;

	/*	res = normalize(hit.pos - CYLIND[hit.id].pos);
	// fonctionne pour cylindre aligné en Z
		if (dot(normalize(CYLIND[hit.id].dir), res) < 0)
		{
			res += normalize(CYLIND[hit.id].dir);
			res.z += 1;
		}
		else
		{
			res -= normalize(CYLIND[hit.id].dir);
			res.z += 1;
		}*/
		int		i = hit.id;
		float3	dir = rotate_obj(CYLIND[i].dir, CYLIND[i].pitch, CYLIND[i].yaw, 0);
		float16 ok = trans_matrix(dir, 90);
		//printf("the first\n0 : %f, 1 : %f, 2 : %f\n4 : %f, 5 : %f, 6 : %f\n8 : %f, 9 : %f, 10 : %f\n\n", ok[0], ok[1], ok[2], ok[4], ok[5], ok[6], ok[8], ok[9], ok[10]);
		res = apply_matrix(ok, hit.pos) - CYLIND[i].pos;
		res.z = 0;
		//ok = trans_matrix(dir, -90);
		//printf("the second\n0 : %f, 1 : %f, 2 : %f\n4 : %f, 5 : %f, 6 : %f\n8 : %f, 9 : %f, 10 : %f\n\n", ok[0], ok[1], ok[2], ok[4], ok[5], ok[6], ok[8], ok[9], ok[10]);
		res = apply_matrix(-ok, res);
		/*res = trans_matrix(dir, hit.pos);
		res = res - CYLIND[i].pos;
		res.z = 0;*/
		//res = trans_matrix(dir, res;
		/*
		nbase.dist = inter_cylinder(CYLIND[i].height, CYLIND[i].dir, CYLIND[i].radius, CYLIND[i].pos,  rotate_obj(scene.ray, -CYLIND[i].pitch, CYLIND[i].yaw, 0), (ACTIVECAM.pos + PARAM->mvt));
		nbase.pos = (ACTIVECAM.pos + PARAM->mvt) + normalize((rotate_obj(scene.ray, -CYLIND[i].pitch, -CYLIND[i].yaw, 0)) * nbase.dist);
		res = nbase.pos - CYLIND[i].pos;
		res.z = 0;
		res = rotate_obj(normalize(res), CYLIND[i].pitch, CYLIND[i].yaw, 0);*/
	}
	else if (hit.type == 4)
	{
		if (dot(PLANE[hit.id].normale, -scene.ray) < 0)
			res = -PLANE[hit.id].normale;
		else
			res = PLANE[hit.id].normale;
	}
	else if (hit.type == 5)
		res = hit.pos - SPHERE[hit.id].pos;
	return (normalize(res));
}

unsigned int			phong(t_hit hit, t_scene scene)
{
	int					i = -1;
	unsigned int		res_color = get_ambient(scene, get_obj_hue(scene, hit));
	float				tmp;
	float3				reflect = 0;

	t_light_ray			light_ray;
	t_hit				light_hit = hit_init();

	while (++i < PARAM->n_lights)
	{
		tmp = 0;
		light_ray.dir = LIGHT[i].pos - hit.pos;
		light_ray.dist = length(light_ray.dir);
		light_ray.dir = normalize(light_ray.dir);
		light_hit = ray_hit(hit.pos, light_ray.dir, scene);
		light_hit.id = i;
		light_hit.type = 3;
		if (light_hit.dist < light_ray.dist && light_hit.dist > 0)
		;
		else
		{
			tmp = dot(hit.normale, light_ray.dir);
		//	if ((scene.pix.x == 175 || scene.pix.x == 525 || scene.pix.x == 845) && scene.pix.y == 370)
		//		printf("light.id = %d | light.color = %08x\n", light_hit.id, LIGHT[light_hit.id].color);
		//		printf("l_hit.id = %d l_hit.type = %d l_hit.dist = %f\n", light_hit.id, light_hit.type, light_hit.dist);
			if (tmp > 0)
				res_color = color_diffuse(scene, hit, light_hit, res_color, tmp);
			reflect = normalize(mult_fvect(2.0 * dot(hit.normale, light_ray.dir), hit.normale) - light_ray.dir);
			tmp = dot(reflect, -scene.ray);
			if (tmp > 0)
				res_color = color_specular(scene, hit, light_hit, res_color, tmp);
		}
	}
	return (res_color);
}

unsigned int			phong2(t_hit hit, t_scene scene)
{
	int					i = -1;
	unsigned int		res_color = get_ambient(scene, get_obj_hue(scene, hit));
	float				tmp = 0;
	float3				reflect = 0;

	t_light_ray			light_ray;
	t_hit				light_hit;

	while (++i < PARAM->n_lights)
	{
		light_ray.dir = LIGHT[i].pos - hit.pos;
		light_ray.dist = length(light_ray.dir);
		light_ray.dir = normalize(light_ray.dir);
		light_hit = ray_hit(hit.pos, light_ray.dir, scene);
		if (light_hit.dist < light_ray.dist && light_hit.dist > 0)
		;
		else
		{
			tmp = dot(hit.normale, light_ray.dir);
			if (tmp > 0)
				res_color = color_diffuse(scene, hit, light_hit, res_color, tmp);
			reflect = normalize(mult_fvect(2.0 * dot(hit.normale, light_ray.dir), hit.normale) - light_ray.dir);
			tmp = dot(reflect, -scene.ray);
			if (tmp > 0)
				res_color = color_specular(scene, hit, light_hit, res_color, tmp);
		}
	}
	return (res_color);
}

unsigned int		bounce(t_scene scene, t_hit old_hit, int depth)
{
	unsigned int	color = 0;
	float3			reflex = 0;
	t_hit			new_hit;
	while (depth > 0)
	{
		reflex = normalize(scene.ray - mult_fvect((2 * dot(old_hit.normale, scene.ray)), old_hit.normale));
		new_hit.dist = MAX_DIST;
		new_hit = ray_hit(old_hit.pos, reflex, scene);
		if (new_hit.dist > 0 && new_hit.dist < MAX_DIST)
		{
			new_hit.pos = mult_fvect(new_hit.dist, reflex) + old_hit.pos;
			new_hit.normale = get_hit_normale(scene, new_hit);
			new_hit.pos = new_hit.pos + ((new_hit.dist / 100) * new_hit.normale);
			color += 0.1 * phong2(new_hit, scene);
		}
		depth--;
	}
	return (color);
}

unsigned int	get_pixel_color(t_scene scene)
{
	t_hit			hit;
	int				depth = PARAM->depth;
	unsigned int	color  = 0;
	unsigned int	bounce_color = 0;

	hit.dist = MAX_DIST;
	hit = ray_hit((ACTIVECAM.pos + PARAM->mvt), scene.ray, scene);
	if (hit.dist > 0 && hit.dist < MAX_DIST) // ajout d'une distance max pour virer acnee mais pas fiable a 100%
	{
		hit.pos = mult_fvect(hit.dist, scene.ray) + (ACTIVECAM.pos + PARAM->mvt);
		hit.normale = get_hit_normale(scene, hit);
		hit.pos = hit.pos + ((hit.dist / 100) * hit.normale);
		color = phong(hit, scene);
		if (depth > 0)
			bounce_color = bounce(scene, hit, depth);
		return (color + bounce_color);
//		return (blend_add(color, 0.8*bounce_color));
	}
	return (get_ambient(scene, BACKCOLOR));
}

float3						get_ray_cam(t_cam cam, t_scene scene, int x, int y)
{
	float3					cam_ray = 0;
	float					ratio = (float)PARAM->win_w / (float)PARAM->win_h;

	cam_ray.x = ((2 * ((x + 0.5) / PARAM->win_w)) - 1) * ratio * (tan((cam.fov / 2) * DEG2RAD));
	cam_ray.y = ((1 - (2 * ((y + 0.5) / PARAM->win_h))) * tan((cam.fov / 2) * DEG2RAD));
	cam_ray.z = 1;
/*  rotation XYZ
	cam_ray.x = xx * cos(yaw) * cos(roll) + yy * cos(yaw) * -sin(roll) + sin(yaw);
	cam_ray.y = xx * (-sin(pitch) * -sin(yaw) * cos(roll) + cos(pitch) * sin(roll)) + yy * (-sin(pitch) * -sin(yaw) * -sin(roll) + cos(pitch) * cos(roll)) + cos(yaw) * -sin(pitch);
	cam_ray.z = xx * (cos(pitch) * -sin(yaw) * cos(roll) + sin(pitch) * sin(roll)) + yy * (cos(pitch) * -sin(yaw) * -sin(roll) + sin(pitch) * cos(roll)) + cos(yaw) * cos(pitch);

// rotation ZYX
	cam_ray.x = xx * cos(roll) * cos(yaw) + yy * (cos(pitch) * -sin(roll) + cos(roll) * sin(yaw) * sin(pitch)) + (-sin(roll) * -sin(pitch) + cos(roll) * sin(yaw) * cos(pitch));
	cam_ray.y = xx * sin(roll) * cos(yaw) + yy * (cos(roll) * cos(pitch) + sin(roll) * sin(yaw) * sin(pitch)) + (cos(roll) * -sin(pitch) + sin(roll) * sin(yaw) * cos(pitch));
	cam_ray.z = xx * -sin(yaw) + yy * cos(yaw) * sin(pitch) + cos(yaw) * cos(pitch);
calcul simplifié
	cam_ray.x = xx * cos(yaw) + yy * (sin(yaw) * sin(pitch)) + (sin(yaw) * cos(pitch));
	cam_ray.y = yy * cos(pitch) + -sin(pitch);
	cam_ray.z = xx * -sin(yaw) + yy * cos(yaw) * sin(pitch) + cos(yaw) * cos(pitch);
*/
	cam_ray = rotat_zyx(cam_ray, cam.pitch, cam.yaw, 0);
	return(normalize(cam_ray));
}

__kernel void	ray_trace(__global		char		*output,
						  				t_param		param,
						  __constant	t_cam		*cameras,
						  __constant	t_cone		*cones,
						  __constant	t_cylinder	*cylinders,
						  __constant	t_light		*lights,
						  __constant	t_plane		*planes,
						  __constant	t_sphere	*spheres,
						  __global		t_hit		*target_obj)
{
	t_scene		scene = grab_data(cameras, cones, cylinders, lights, planes, spheres, param);
	scene.pix.x = get_global_id(0);
	scene.pix.y = get_global_id(1);
	int			id = scene.pix.x + (PARAM->win_w * scene.pix.y); // NE PAS VIRER ID CAR BESOIN DANS MACRO OUTPUTE
	scene.ray = get_ray_cam(ACTIVECAM, scene, scene.pix.x ,scene.pix.y);
	if (scene.pix.x == PARAM->mou_x && scene.pix.y == PARAM->mou_y)
		*target_obj = ray_hit((ACTIVECAM.pos + PARAM->mvt), scene.ray, scene);
	OUTPUTE = get_pixel_color(scene);
}

#include "kernel_header.h"
#include "kernel_color.h"
#include "kernel_data.h"
#include "kernel_vector.h"
#include "kernel_debug.h"

float3						rotat_zyx(float3 vect, float pitch, float yaw, float roll)
{
	float3					res;
	float					rad_pitch = pitch * DEG2RAD;
	float					rad_yaw = yaw * DEG2RAD;
	float					rad_roll = roll * DEG2RAD;

	res.x = vect.x * cos(rad_roll) * cos(rad_yaw) + vect.y * (cos(rad_pitch) * -sin(rad_roll) + cos(rad_roll) * sin(rad_yaw) * sin(rad_pitch)) + vect.z * (-sin(rad_roll) * -sin(rad_pitch) + cos(rad_roll) * sin(rad_yaw) * cos(rad_pitch));
	res.y = vect.x * sin(rad_roll) * cos(rad_yaw) + vect.y * (cos(rad_roll) * cos(rad_pitch) + sin(rad_roll) * sin(rad_yaw) * sin(rad_pitch)) + vect.z * (cos(rad_roll) * -sin(rad_pitch) + sin(rad_roll) * sin(rad_yaw) * cos(rad_pitch));
	res.z = vect.x * -sin(rad_yaw) + vect.y * cos(rad_yaw) * sin(rad_pitch) + vect.z * cos(rad_yaw) * cos(rad_pitch);
	return (res);
}

float3						rotat_xyz(float3 vect, float pitch, float yaw, float roll)
{
	float3					res;
	float					rad_pitch = pitch * DEG2RAD;
	float					rad_yaw = yaw * DEG2RAD;
	float					rad_roll = roll * DEG2RAD;

	res.x = vect.x * cos(rad_yaw) * cos(rad_roll) + vect.y * cos(rad_yaw) * -sin(rad_roll) + vect.z * sin(rad_yaw);
	res.y = vect.x * (-sin(rad_pitch) * -sin(rad_yaw) * cos(rad_roll) + cos(rad_pitch) * sin(rad_roll)) + vect.y * (-sin(rad_pitch) * -sin(rad_yaw) * -sin(rad_roll) + cos(rad_pitch) * cos(rad_roll)) + vect.z * cos(rad_yaw) * -sin(rad_pitch);
	res.z = vect.x * (cos(rad_pitch) * -sin(rad_yaw) * cos(rad_roll) + sin(rad_pitch) * sin(rad_roll)) + vect.y * (cos(rad_pitch) * -sin(rad_yaw) * -sin(rad_roll) + sin(rad_pitch) * cos(rad_roll)) + vect.z * cos(rad_yaw) * cos(rad_pitch);
	return (res);
}

float3					rotate_obj(float3 v, float pitch, float yaw, float roll)
{
	float3				res;

	res = rotat_zyx(v, pitch, yaw, roll);

	return (normalize(res));
}

float3					get_sphere_abc(float radius, float3 ray, float3 origin)
{
	float3		abc;

	abc.x = dot(ray, ray);
	abc.y = 2 * dot(ray, origin);
	abc.z = dot(origin, origin) - (radius * radius);
	return (abc);
}

float					inter_sphere(t_sphere sphere, float3 ray, float3 origin)
{
	float3				abc;
	float				d;
	float				res1;
	float				res2;

	origin -= sphere.pos;
	abc = get_sphere_abc(sphere.radius, ray, origin);
	d = (abc.y * abc.y) - (4 * (abc.x * abc.z));
	if (d < 0)
		return (0);
	if (d == 0)
		return ((-abc[1]) / (2 * abc[0]));
	res1 = (((-abc[1]) + sqrt(d)) / (2 * abc[0]));
	res2 = (((-abc[1]) - sqrt(d)) / (2 * abc[0]));
	if ((res1 < res2 && res1 > 0) || (res1 > res2 && res2 < 0))
		return (res1);
	return (res2);
}

float					inter_light(t_light light, float3 ray, float3 origin)
{
	float3				abc;
	float				d;
	float				res1;
	float				res2;

	origin -= light.pos;
	abc = get_sphere_abc(0.21, ray, origin);
	d = (abc.y * abc.y) - (4 * (abc.x * abc.z));
	if (d < 0)
		return (0);
	if (d == 0)
		return ((-abc[1]) / (2 * abc[0]));
	res1 = (((-abc[1]) + sqrt(d)) / (2 * abc[0]));
	res2 = (((-abc[1]) - sqrt(d)) / (2 * abc[0]));
	if ((res1 < res2 && res1 > 0) || (res1 > res2 && res2 < 0))
		return (res1);
	return (res2);
}

float3					get_cylinder_abc(float radius, float3 dir, float3 ray, float3 origin)
{
	float3		abc;

	// SEMBLE OK
	abc.x = dot(ray, ray) - (dot(ray, dir) * dot(ray, dir));
	abc.y = 2 * (dot(ray, origin) - (dot(ray, dir) * dot(origin, dir)));
	abc.z = dot(origin, origin) - (dot(origin, dir) * dot(origin, dir)) - (radius * radius);
	return (abc);
}

float					inter_cylinder(float height, float3 dir, float radius, float3 pos, float3 ray, float3 origin)
{
	float3				abc;
	//float3				dir = rotate_obj(cyl.dir, cyl.pitch, cyl.yaw, 0);
	float				d;
	float				res1 = 0;
	float				res2 = 0;
	float				m;

	origin -= pos;
	abc = get_cylinder_abc(radius, dir, ray, origin);
	d = (abc.y * abc.y) - (4 * (abc.x * abc.z));
	if (d < 0)
		return (0);
	if (d == 0)
		res1 = (-abc[1]) / (2 * abc[0]);
	else
	{
		res1 = (((-abc[1]) + sqrt(d)) / (2 * abc[0]));
		res2 = (((-abc[1]) - sqrt(d)) / (2 * abc[0]));
	}
	if (res1 < 0 && res2 < 0)
		return (0);
	if ((res1 < res2 && res1 > 0) || (res1 > res2 && res2 < 0))
	{
		if (height == 0 || (dot(ray, dir) * res1 +
			dot(origin, dir) < height && dot(ray, dir) * res1 +
			dot(origin, dir) > 0))
			return (res1);
	}
	if (height ==  0 || (dot(ray, dir) * res2 +
			dot(origin, dir) < height && dot(ray, dir) * res2 +
			dot(origin, dir) > 0))
		return (res2);
	else
		return (0);
}

float3					get_cone_abc(t_cone cone, float3 ray, float3 origin)
{
	float3		abc = 0;
	float		k = cone.angle * DEG2RAD;
	k = tan(k);
	k = 1 + k * k;

	abc.x = dot(ray, ray) - (k * (dot(ray, cone.dir) * dot(ray, cone.dir)));
	abc.y = 2 * (dot(ray, origin) - (k * \
			(dot(ray, cone.dir) * dot(origin, cone.dir))));
	abc.z = (dot(origin, origin) - \
			(k * (dot(origin, cone.dir) * dot(origin, cone.dir))));
	return (abc);
}

float					inter_cone(t_cone cone, float3 ray, float3 origin)
{
	float3				abc;
	float				d;
	float				res1;
	float				res2;
	float				res;

	origin -= cone.pos;
	abc = get_cone_abc(cone, ray, origin);
	d = (abc.y * abc.y) - (4 * (abc.x * abc.z));
	if (d < 0)
		return (0);
	if (d == 0)
		res = (-abc[1]) / (2 * abc[0]);
	res1 = (((-abc[1]) + sqrt(d)) / (2 * abc[0]));
	res2 = (((-abc[1]) - sqrt(d)) / (2 * abc[0]));
	if ((res1 < res2 && res1 > 0) || (res1 > res2 && res2 < 0))
		res = res1;
	else
		res = res2;
	return (res);
}

float					inter_plan(t_plane plane, float3 ray, float3 origin)
{
	float				t;

	if ((t = dot(normalize(ray), normalize(plane.normale))) == 0)
		return (0);
	t = (dot(plane.pos - origin, normalize(plane.normale))) / t;
		if (t < 0.001)
		return (0);
	return (t);
}

t_hit			ray_hit(float3 origin, float3 ray, t_scene scene)
{
	unsigned int			i = 0;
	int						max = get_max_obj(PARAM);
	t_hit					hit = hit_init();
	float					dist = 0;

	while (i < max)
	{
		if (i < PARAM->n_cones)
			if (((dist = inter_cone(CONES[i], ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 1;
				hit.id = i;
			}
		if (i < PARAM->n_cylinders)
			if (((dist = inter_cylinder(CYLIND[i].height, rotate_obj(CYLIND[i].dir, CYLIND[i].pitch, CYLIND[i].yaw, 0), CYLIND[i].radius, CYLIND[i].pos, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 2;
				hit.id = i;
			}
		if (i < PARAM->n_planes)
			if (((dist = inter_plan(PLANE[i], ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 4;
				hit.id = i;
			}
		if (i < PARAM->n_spheres)
			if (((dist = inter_sphere(SPHERE[i], ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 5;
				hit.id = i;
			}
		i++;
	}
	return (hit);
}

float3			rotate_matrix(float angle, float3 v)
{
	float3		res;

	res.x = v.x;
	res.y = (cos(angle) * v.y) - (sin(angle) * v.z);
	res.z = (sin(angle) * v.y) + (cos(angle) * v.z);
	return (res);
}

float16			trans_matrix(float3 dir, float angle)
{
	float16		res = 0;
	float3		rot = 0;

	rot = rotate_obj(dir, 0, angle, 0);
	res[0] = rot.x;
	res[1] = rot.y;
	res[2] = rot.z;
	rot = rotate_obj(dir, -angle, 0, 0);
	res[4] = rot.x;
	res[5] = rot.y;
	res[6] = rot.z;
	res[8] = dir.x;
	res[9] = dir.y;
	res[10] = dir.z;
	return (res);
}

float3			apply_matrix(float16 mat, float3 v)
{
	float3		res = 0;

	res.x = mat[0] * v.x + mat[4] * v.y + mat[8] * v.z;
	res.y = mat[1] * v.x + mat[5] * v.y + mat[9] * v.z;
	res.z = mat[2] * v.x + mat[6] * v.y + mat[10] * v.z;
	return (res);
}

float3			get_hit_normale(t_scene scene, t_hit hit)
{
	float3		res;

	if (hit.type == 1)
	{
		float k = CONES[hit.id].angle * DEG2RAD;
		k = tan(k);
		k = 1 + k * k;
		res = dot(-scene.ray, normalize(CONES[hit.id].dir)) * \
			hit.dist - dot(ACTIVECAM.pos + PARAM->mvt - CONES[hit.id].pos, normalize(CONES[hit.id].dir));
		res = ((hit.pos - normalize(CONES[hit.id].pos)) - (k * normalize(CONES[hit.id].dir) * res)) * -1;
	}
	else if (hit.type == 2)
	{
		/*float3	base = CYLIND[hit.id].pos;
		res = hit.pos;

		res = rotate_matrix(45 * DEG2RAD, res);
		base.z = res.z;
		base = rotate_matrix(-45 * DEG2RAD, base);
		res = rotate_matrix(-45 * DEG2RAD, res);
		res -= base;*/
//		res = dot(-scene.ray, normalize(CYLIND[hit.id].dir) * hit.dist + \
//			dot(ACTIVECAM.pos + PARAM->mvt - CYLIND[hit.id].pos, normalize(CYLIND[hit.id].dir)));
//		res = hit.pos - CYLIND[hit.id].pos - normalize(CYLIND[hit.id].dir) * res;

	/*	res = normalize(hit.pos - CYLIND[hit.id].pos);
	// fonctionne pour cylindre aligné en Z
		if (dot(normalize(CYLIND[hit.id].dir), res) < 0)
		{
			res += normalize(CYLIND[hit.id].dir);
			res.z += 1;
		}
		else
		{
			res -= normalize(CYLIND[hit.id].dir);
			res.z += 1;
		}*/
		int		i = hit.id;
		float3	dir = rotate_obj(CYLIND[i].dir, CYLIND[i].pitch, CYLIND[i].yaw, 0);
		float16 ok = trans_matrix(dir, 90);
		//printf("the first\n0 : %f, 1 : %f, 2 : %f\n4 : %f, 5 : %f, 6 : %f\n8 : %f, 9 : %f, 10 : %f\n\n", ok[0], ok[1], ok[2], ok[4], ok[5], ok[6], ok[8], ok[9], ok[10]);
		res = apply_matrix(ok, hit.pos) - CYLIND[i].pos;
		res.z = 0;
		//ok = trans_matrix(dir, -90);
		//printf("the second\n0 : %f, 1 : %f, 2 : %f\n4 : %f, 5 : %f, 6 : %f\n8 : %f, 9 : %f, 10 : %f\n\n", ok[0], ok[1], ok[2], ok[4], ok[5], ok[6], ok[8], ok[9], ok[10]);
		res = apply_matrix(-ok, res);
		/*res = trans_matrix(dir, hit.pos);
		res = res - CYLIND[i].pos;
		res.z = 0;*/
		//res = trans_matrix(dir, res;
		/*
		nbase.dist = inter_cylinder(CYLIND[i].height, CYLIND[i].dir, CYLIND[i].radius, CYLIND[i].pos,  rotate_obj(scene.ray, -CYLIND[i].pitch, CYLIND[i].yaw, 0), (ACTIVECAM.pos + PARAM->mvt));
		nbase.pos = (ACTIVECAM.pos + PARAM->mvt) + normalize((rotate_obj(scene.ray, -CYLIND[i].pitch, -CYLIND[i].yaw, 0)) * nbase.dist);
		res = nbase.pos - CYLIND[i].pos;
		res.z = 0;
		res = rotate_obj(normalize(res), CYLIND[i].pitch, CYLIND[i].yaw, 0);*/
	}
	else if (hit.type == 4)
	{
		if (dot(PLANE[hit.id].normale, -scene.ray) < 0)
			res = -PLANE[hit.id].normale;
		else
			res = PLANE[hit.id].normale;
	}
	else if (hit.type == 5)
		res = hit.pos - SPHERE[hit.id].pos;
	return (normalize(res));
}

unsigned int			phong(t_hit hit, t_scene scene)
{
	int					i = -1;
	unsigned int		res_color = get_ambient(scene, get_obj_hue(scene, hit));
	float				tmp;
	float3				reflect = 0;

	t_light_ray			light_ray;
	t_hit				light_hit = hit_init();

	while (++i < PARAM->n_lights)
	{
		tmp = 0;
		light_ray.dir = LIGHT[i].pos - hit.pos;
		light_ray.dist = length(light_ray.dir);
		light_ray.dir = normalize(light_ray.dir);
		light_hit = ray_hit(hit.pos, light_ray.dir, scene);
		light_hit.id = i;
		light_hit.type = 3;
		if (light_hit.dist < light_ray.dist && light_hit.dist > 0)
		;
		else
		{
			tmp = dot(hit.normale, light_ray.dir);
		//	if ((scene.pix.x == 175 || scene.pix.x == 525 || scene.pix.x == 845) && scene.pix.y == 370)
		//		printf("light.id = %d | light.color = %08x\n", light_hit.id, LIGHT[light_hit.id].color);
		//		printf("l_hit.id = %d l_hit.type = %d l_hit.dist = %f\n", light_hit.id, light_hit.type, light_hit.dist);
			if (tmp > 0)
				res_color = color_diffuse(scene, hit, light_hit, res_color, tmp);
			reflect = normalize(mult_fvect(2.0 * dot(hit.normale, light_ray.dir), hit.normale) - light_ray.dir);
			tmp = dot(reflect, -scene.ray);
			if (tmp > 0)
				res_color = color_specular(scene, hit, light_hit, res_color, tmp);
		}
	}
	return (res_color);
}

unsigned int			phong2(t_hit hit, t_scene scene)
{
	int					i = -1;
	unsigned int		res_color = get_ambient(scene, get_obj_hue(scene, hit));
	float				tmp = 0;
	float3				reflect = 0;

	t_light_ray			light_ray;
	t_hit				light_hit;

	while (++i < PARAM->n_lights)
	{
		light_ray.dir = LIGHT[i].pos - hit.pos;
		light_ray.dist = length(light_ray.dir);
		light_ray.dir = normalize(light_ray.dir);
		light_hit = ray_hit(hit.pos, light_ray.dir, scene);
		if (light_hit.dist < light_ray.dist && light_hit.dist > 0)
		;
		else
		{
			tmp = dot(hit.normale, light_ray.dir);
			if (tmp > 0)
				res_color = color_diffuse(scene, hit, light_hit, res_color, tmp);
			reflect = normalize(mult_fvect(2.0 * dot(hit.normale, light_ray.dir), hit.normale) - light_ray.dir);
			tmp = dot(reflect, -scene.ray);
			if (tmp > 0)
				res_color = color_specular(scene, hit, light_hit, res_color, tmp);
		}
	}
	return (res_color);
}

unsigned int		bounce(t_scene scene, t_hit old_hit, int depth)
{
	unsigned int	color = 0;
	float3			reflex = 0;
	t_hit			new_hit;
	while (depth > 0)
	{
		reflex = normalize(scene.ray - mult_fvect((2 * dot(old_hit.normale, scene.ray)), old_hit.normale));
		new_hit.dist = MAX_DIST;
		new_hit = ray_hit(old_hit.pos, reflex, scene);
		if (new_hit.dist > 0 && new_hit.dist < MAX_DIST)
		{
			new_hit.pos = mult_fvect(new_hit.dist, reflex) + old_hit.pos;
			new_hit.normale = get_hit_normale(scene, new_hit);
			new_hit.pos = new_hit.pos + ((new_hit.dist / 100) * new_hit.normale);
			color += 0.1 * phong2(new_hit, scene);
		}
		depth--;
	}
	return (color);
}

unsigned int	get_pixel_color(t_scene scene)
{
	t_hit			hit;
	int				depth = PARAM->depth;
	unsigned int	color  = 0;
	unsigned int	bounce_color = 0;

	hit.dist = MAX_DIST;
	hit = ray_hit((ACTIVECAM.pos + PARAM->mvt), scene.ray, scene);
	if (hit.dist > 0 && hit.dist < MAX_DIST) // ajout d'une distance max pour virer acnee mais pas fiable a 100%
	{
		hit.pos = mult_fvect(hit.dist, scene.ray) + (ACTIVECAM.pos + PARAM->mvt);
		hit.normale = get_hit_normale(scene, hit);
		hit.pos = hit.pos + ((hit.dist / 100) * hit.normale);
		color = phong(hit, scene);
		if (depth > 0)
			bounce_color = bounce(scene, hit, depth);
		return (color + bounce_color);
//		return (blend_add(color, 0.8*bounce_color));
	}
	return (get_ambient(scene, BACKCOLOR));
}

float3						get_ray_cam(t_cam cam, t_scene scene, int x, int y)
{
	float3					cam_ray = 0;
	float					ratio = (float)PARAM->win_w / (float)PARAM->win_h;

	cam_ray.x = ((2 * ((x + 0.5) / PARAM->win_w)) - 1) * ratio * (tan((cam.fov / 2) * DEG2RAD));
	cam_ray.y = ((1 - (2 * ((y + 0.5) / PARAM->win_h))) * tan((cam.fov / 2) * DEG2RAD));
	cam_ray.z = 1;
/*  rotation XYZ
	cam_ray.x = xx * cos(yaw) * cos(roll) + yy * cos(yaw) * -sin(roll) + sin(yaw);
	cam_ray.y = xx * (-sin(pitch) * -sin(yaw) * cos(roll) + cos(pitch) * sin(roll)) + yy * (-sin(pitch) * -sin(yaw) * -sin(roll) + cos(pitch) * cos(roll)) + cos(yaw) * -sin(pitch);
	cam_ray.z = xx * (cos(pitch) * -sin(yaw) * cos(roll) + sin(pitch) * sin(roll)) + yy * (cos(pitch) * -sin(yaw) * -sin(roll) + sin(pitch) * cos(roll)) + cos(yaw) * cos(pitch);

// rotation ZYX
	cam_ray.x = xx * cos(roll) * cos(yaw) + yy * (cos(pitch) * -sin(roll) + cos(roll) * sin(yaw) * sin(pitch)) + (-sin(roll) * -sin(pitch) + cos(roll) * sin(yaw) * cos(pitch));
	cam_ray.y = xx * sin(roll) * cos(yaw) + yy * (cos(roll) * cos(pitch) + sin(roll) * sin(yaw) * sin(pitch)) + (cos(roll) * -sin(pitch) + sin(roll) * sin(yaw) * cos(pitch));
	cam_ray.z = xx * -sin(yaw) + yy * cos(yaw) * sin(pitch) + cos(yaw) * cos(pitch);
calcul simplifié
	cam_ray.x = xx * cos(yaw) + yy * (sin(yaw) * sin(pitch)) + (sin(yaw) * cos(pitch));
	cam_ray.y = yy * cos(pitch) + -sin(pitch);
	cam_ray.z = xx * -sin(yaw) + yy * cos(yaw) * sin(pitch) + cos(yaw) * cos(pitch);
*/
	cam_ray = rotat_zyx(cam_ray, cam.pitch, cam.yaw, 0);
	return(normalize(cam_ray));
}

__kernel void	ray_trace(__global		char		*output,
						  				t_param		param,
						  __constant	t_cam		*cameras,
						  __constant	t_cone		*cones,
						  __constant	t_cylinder	*cylinders,
						  __constant	t_light		*lights,
						  __constant	t_plane		*planes,
						  __constant	t_sphere	*spheres,
						  __global		t_hit		*target_obj)
{
	t_scene		scene = grab_data(cameras, cones, cylinders, lights, planes, spheres, param);
	scene.pix.x = get_global_id(0);
	scene.pix.y = get_global_id(1);
	int			id = scene.pix.x + (PARAM->win_w * scene.pix.y); // NE PAS VIRER ID CAR BESOIN DANS MACRO OUTPUTE
	scene.ray = get_ray_cam(ACTIVECAM, scene, scene.pix.x ,scene.pix.y);
	if (scene.pix.x == PARAM->mou_x && scene.pix.y == PARAM->mou_y)
		*target_obj = ray_hit((ACTIVECAM.pos + PARAM->mvt), scene.ray, scene);
	OUTPUTE = get_pixel_color(scene);
}


Make CMJ default sampler

Make CMJ default sampler

/**********************************************************************
Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved.

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.
********************************************************************/
#ifndef COMMON_CL
#define COMMON_CL

#define CRAZY_LOW_THROUGHPUT 0.0f
#define CRAZY_HIGH_RADIANCE 3.f
#define CRAZY_HIGH_DISTANCE 1000000.f
#define CRAZY_LOW_DISTANCE 0.001f
#define REASONABLE_RADIANCE(x) (clamp((x), 0.f, CRAZY_HIGH_RADIANCE))
#define NON_BLACK(x) (length(x) > 0.f)

#define MULTISCATTER

#define RANDOM 1
#define SOBOL 2
#define CMJ 3

#define SAMPLER CMJ

#define CMJ_DIM 16

#endif // COMMON_CL

/**********************************************************************
Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved.

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.
********************************************************************/
#ifndef COMMON_CL
#define COMMON_CL

#define CRAZY_LOW_THROUGHPUT 0.0f
#define CRAZY_HIGH_RADIANCE 3.f
#define CRAZY_HIGH_DISTANCE 1000000.f
#define CRAZY_LOW_DISTANCE 0.001f
#define REASONABLE_RADIANCE(x) (clamp((x), 0.f, CRAZY_HIGH_RADIANCE))
#define NON_BLACK(x) (length(x) > 0.f)

#define MULTISCATTER

#define RANDOM 1
#define SOBOL 2
#define CMJ 3

#define SAMPLER SOBOL

#define CMJ_DIM 4

#endif // COMMON_CL