use a few left/right shifts instead of multiple/divide

#include "ocl_platform.cl"

// number of banks in local memory
// LDS_BANKS

//////////////////////////
// dimensions of window
// WIN_SIZE_X	assume this equals number of work items in work group
// WIN_SIZE_Y
///////////////////////////

/// Returns index ranging from 0 to num work items, such that first half
/// of the work items get even indices and others get odd indices. Each work item
/// gets a different index.
/// Example: (for WIN_SiZE_X == 8)   getLocalId(0):   0  1  2  3  4  5  6  7
///									 parityIdx:		  0  2  4  6  1  3  5  7
/// @return parity-separated index of work item
inline int parityIdx() {
	return (getLocalId(0) * 2) - (WIN_SIZE_X - 1) * (getLocalId(0) / (WIN_SIZE_X / 2));
}

// scratch buffer (in local memory of GPU) where block of input image is stored.

/// Odd and even columns are separated. (Generates less bank conflicts when using lifting scheme.)
/// All even columns are stored first, then all odd columns.
/// All operations expect WIN_SIZE_X threads.

/// BOUNDARY_X		number of extra pixels at the left and right side
///					boundary is expected to be smaller than half WIN_SIZE_X
///					Must be divisible by 2, because half of the boundary lies on the left of the image,
///                 half lies on the right

// two vertical neighbours: pointer diff:
#define VERTICAL_STRIDE 66			// BOUNDARY_X + (WIN_SIZE_X / 2)

// size of one of two buffers (odd or even)
#define BUFFER_SIZE     528          // VERTICAL_STRIDE * WIN_SIZE_Y

/// padding between even and odd buffers: used to reduce bank conflicts
#define PADDING			32           // LDS_BANKS - ((BUFFER_SIZE + LDS_BANKS / 2) % LDS_BANKS);

// offset of the odd columns buffer from the beginning of data buffer
#define ODD_OFFSET 560              // BUFFER_SIZE + PADDING

// size of buffer for both even and odd columns
#define TOTAL_BUFFER_SIZE  1088     // 2 * BUFFER_SIZE + PADDING;
///////////////////////////////////////////////////////////////////////

typedef struct _int4Pixel {
    int4 value;
} int4Pixel;

CONSTANT int4 twoVec = (int4)(2,2,2,2);

CONSTANT sampler_t sampler = CLK_NORMALIZED_COORDS_TRUE | CLK_ADDRESS_MIRRORED_REPEAT  | CLK_FILTER_NEAREST;

void readPixel(int4Pixel* const pix, LOCAL int*  restrict  src) {
	pix->value.x = *src ;
	src += TOTAL_BUFFER_SIZE;
	pix->value.y = *src;
	src += TOTAL_BUFFER_SIZE;
	pix->value.z = *src;
	src += TOTAL_BUFFER_SIZE;
	pix->value.w = *src;
}

void writePixel(int4 pix, LOCAL int*  restrict  dest) {
	*dest = pix.x;
	dest += TOTAL_BUFFER_SIZE;
	*dest = pix.y;
	dest += TOTAL_BUFFER_SIZE;
	*dest = pix.z;
	dest += TOTAL_BUFFER_SIZE;
	*dest = pix.w;
}

//fetch first pixel (and 2 top boundary pixels)
// -2  -1 0 1 2
void initVertical(__read_only image2d_t idata, float2 posIn, float yDelta, int4*  restrict const buff) {
	///////////////////////////////////////////////
	// read -2 point
	int4 minusTwo = read_imagei(idata, sampler, posIn);
	// read -1 point
	posIn.y += yDelta;
	buff[0] = read_imagei(idata, sampler, posIn);
	// read 0 point
	posIn.y += yDelta;
	buff[1] = read_imagei(idata, sampler, posIn);
	///////////////////////////////////////////////

	// transform -1 point (no need to write to local memory)
	buff[0] -= (minusTwo + buff[1]) >> 1;
}

// fetch next two pixels, store in circular buffer, and write last (even) and current (odd)
void fetchNextVertical(__read_only image2d_t idata, float2 posIn, float yDelta, int4*  restrict const buff, int buffStart, LOCAL int* restrict dest) {
    // read current (odd) point
	buff[buffStart] = read_imagei(idata, sampler, posIn);

	// read next (even) point
	posIn.y += yDelta;
	buff[(buffStart+1)&3] = read_imagei(idata, sampler, posIn);

	// transform current (odd) point
	buff[buffStart] -= (buff[(buffStart-1)&3] + buff[(buffStart+1)&3]) >> 1;

	// transform previous (even) point
	buff[(buffStart-1)&3] += (buff[(buffStart-2)&3] + buff[buffStart] + twoVec) >> 2;

	//write even
	writePixel(buff[(buffStart-1)&3], dest);

	//write odd
	dest += WIN_SIZE_X;
	writePixel(buff[buffStart], dest);
}

// assumptions: width and height are both even
// (we will probably have to relax these assumptions in the future)

//1. initialize column (and optionally boundary column)
//2. read column(s) into scratch
//3. vertically transform column(s)
//4. horizontally transform all rows corresponding to this column(s)
//5. write into destination
void KERNEL run(__read_only image2d_t idata, __write_only image2d_t odata,
                       const unsigned int  width, const unsigned int  height, const unsigned int steps) {
	LOCAL int scratch[TOTAL_BUFFER_SIZE << 2];
	float yDelta = 1.0/height;
	int firstY = getGlobalId(1) * (steps * WIN_SIZE_Y);
	int4 cache[4];

	const float2 posIn = {getGlobalId(0)/(float)width, (firstY - 2)*yDelta};
	initVertical(idata, posIn, yDelta, cache);
	int cachePosition = 0;

	// adjust input y so that loop starts at pixel 1
	posIn.y += yDelta;

	for (int i = 0; i < steps; ++i) {

	   LOCAL int* currentScratch = scratch + getLocalId(0);

	   //read pixels two at a time, and store in local buffer
	   for (int j = 0; j < WIN_SIZE_Y>>1; ++j) {

	   		// jump two pixels
	   		posIn.y += 2*yDelta;
			if (posIn.y >= 1)
			   break;
			cachePosition = (cachePosition +2) &3;
	        //fetch
			fetchNextVertical(idata,posIn , yDelta, cache, cachePosition, currentScratch);
			//advance scratch pointer
			currentScratch += WIN_SIZE_X << 1;

		}

	    localMemoryFence();

		// write even points to destination
		const int2 posOut = {getGlobalId(0), firstY>>1};
		currentScratch = scratch +  getLocalId(0);
		for (int j = 0; j < WIN_SIZE_Y; j+=2) {

	        if (posOut.x >= width || posOut.y >= height >> 1)
				break;

			int4Pixel pix;
			readPixel(&pix, currentScratch);
			write_imagei(odata, posOut,pix.value);

			currentScratch += WIN_SIZE_X << 1;
			posOut.y++;
		}
		//write odd points to destination
		posOut.y =  ((height + firstY)>>1) + 1;
		currentScratch = scratch +  getLocalId(0) + WIN_SIZE_X;
		for (int j = 0; j < WIN_SIZE_Y; j+=2) {

			 if (posOut.x >= width || posOut.y >= height)
				break;

			int4Pixel pix;
			readPixel(&pix, currentScratch);
			write_imagei(odata, posOut,pix.value);

			currentScratch += WIN_SIZE_X << 1;
			posOut.y++;
		}

		firstY += WIN_SIZE_Y;
		localMemoryFence();
	}

}

#include "ocl_platform.cl"

// number of banks in local memory
// LDS_BANKS

//////////////////////////
// dimensions of window
// WIN_SIZE_X	assume this equals number of work items in work group
// WIN_SIZE_Y
///////////////////////////

/// Returns index ranging from 0 to num work items, such that first half
/// of the work items get even indices and others get odd indices. Each work item
/// gets a different index.
/// Example: (for WIN_SiZE_X == 8)   getLocalId(0):   0  1  2  3  4  5  6  7
///									 parityIdx:		  0  2  4  6  1  3  5  7
/// @return parity-separated index of work item
inline int parityIdx() {
	return (getLocalId(0) * 2) - (WIN_SIZE_X - 1) * (getLocalId(0) / (WIN_SIZE_X / 2));
}

// scratch buffer (in local memory of GPU) where block of input image is stored.

/// Odd and even columns are separated. (Generates less bank conflicts when using lifting scheme.)
/// All even columns are stored first, then all odd columns.
/// All operations expect WIN_SIZE_X threads.

/// BOUNDARY_X		number of extra pixels at the left and right side
///					boundary is expected to be smaller than half WIN_SIZE_X
///					Must be divisible by 2, because half of the boundary lies on the left of the image,
///                 half lies on the right

// two vertical neighbours: pointer diff:
#define VERTICAL_STRIDE 66			// BOUNDARY_X + (WIN_SIZE_X / 2)

// size of one of two buffers (odd or even)
#define BUFFER_SIZE     528          // VERTICAL_STRIDE * WIN_SIZE_Y

/// padding between even and odd buffers: used to reduce bank conflicts
#define PADDING			32           // LDS_BANKS - ((BUFFER_SIZE + LDS_BANKS / 2) % LDS_BANKS);

// offset of the odd columns buffer from the beginning of data buffer
#define ODD_OFFSET 560              // BUFFER_SIZE + PADDING

// size of buffer for both even and odd columns
#define TOTAL_BUFFER_SIZE  1088     // 2 * BUFFER_SIZE + PADDING;
///////////////////////////////////////////////////////////////////////

typedef struct _int4Pixel {
    int4 value;
} int4Pixel;

CONSTANT int4 twoVec = (int4)(2,2,2,2);

CONSTANT sampler_t sampler = CLK_NORMALIZED_COORDS_TRUE | CLK_ADDRESS_MIRRORED_REPEAT  | CLK_FILTER_NEAREST;

void readPixel(int4Pixel* const pix, LOCAL int*  restrict  src) {
	pix->value.x = *src ;
	src += TOTAL_BUFFER_SIZE;
	pix->value.y = *src;
	src += TOTAL_BUFFER_SIZE;
	pix->value.z = *src;
	src += TOTAL_BUFFER_SIZE;
	pix->value.w = *src;
}

void writePixel(int4 pix, LOCAL int*  restrict  dest) {
	*dest = pix.x;
	dest += TOTAL_BUFFER_SIZE;
	*dest = pix.y;
	dest += TOTAL_BUFFER_SIZE;
	*dest = pix.z;
	dest += TOTAL_BUFFER_SIZE;
	*dest = pix.w;
}

//fetch first pixel (and 2 top boundary pixels)
// -2  -1 0 1 2
void initVertical(__read_only image2d_t idata, float2 posIn, float yDelta, int4*  restrict const buff) {
	///////////////////////////////////////////////
	// read -2 point
	int4 minusTwo = read_imagei(idata, sampler, posIn);
	// read -1 point
	posIn.y += yDelta;
	buff[0] = read_imagei(idata, sampler, posIn);
	// read 0 point
	posIn.y += yDelta;
	buff[1] = read_imagei(idata, sampler, posIn);
	///////////////////////////////////////////////

	// transform -1 point (no need to write to local memory)
	buff[0] -= (minusTwo + buff[1]) >> 1;
}

// fetch next two pixels, store in circular buffer, and write last (even) and current (odd)
void fetchNextVertical(__read_only image2d_t idata, float2 posIn, float yDelta, int4*  restrict const buff, int buffStart, LOCAL int* restrict dest) {
    // read current (odd) point
	buff[buffStart] = read_imagei(idata, sampler, posIn);

	// read next (even) point
	posIn.y += yDelta;
	buff[(buffStart+1)&3] = read_imagei(idata, sampler, posIn);

	// transform current (odd) point
	buff[buffStart] -= (buff[(buffStart-1)&3] + buff[(buffStart+1)&3]) >> 1;

	// transform previous (even) point
	buff[(buffStart-1)&3] += (buff[(buffStart-2)&3] + buff[buffStart] + twoVec) >> 2;

	//write even
	writePixel(buff[(buffStart-1)&3], dest);

	//write odd
	dest += WIN_SIZE_X;
	writePixel(buff[buffStart], dest);
}

//1. initialize column (and optionally boundary column)
//2. read column(s) into scratch
//3. vertically transform column(s)
//4. horizontally transform all rows corresponding to this column(s)
//5. write into destination
void KERNEL run(__read_only image2d_t idata, __write_only image2d_t odata,
                       const unsigned int  width, const unsigned int  height, const unsigned int steps) {
	LOCAL int scratch[TOTAL_BUFFER_SIZE*4];
	float yDelta = 1.0/height;
	int firstY = getGlobalId(1) * (steps * WIN_SIZE_Y);
	int4 cache[4];

	const float2 posIn = {getGlobalId(0)/(float)width, (firstY - 2)*yDelta};
	initVertical(idata, posIn, yDelta, cache);
	int cachePosition = 0;

	// adjust input y so that loop starts at pixel 1
	posIn.y += yDelta;

	for (int i = 0; i < steps; ++i) {

	   LOCAL int* currentScratch = scratch + getLocalId(0);

	   //read pixels two at a time, and store in local buffer
	   for (int j = 0; j < WIN_SIZE_Y/2; ++j) {

	   		// jump two pixels
	   		posIn.y += 2*yDelta;
			if (posIn.y >= 1)
			   break;
			cachePosition = (cachePosition +2) &3;
	        //fetch
			fetchNextVertical(idata,posIn , yDelta, cache, cachePosition, currentScratch);
			//advance scratch pointer
			currentScratch += 2*WIN_SIZE_X;

		}

	    localMemoryFence();

		// write even points to destination
		const int2 posOut = {getGlobalId(0), firstY>>1};
		currentScratch = scratch +  getLocalId(0);
		for (int j = 0; j < WIN_SIZE_Y; j+=2) {

	        if (posOut.x >= width || posOut.y >= height/2)
				break;

			int4Pixel pix;
			readPixel(&pix, currentScratch);
			write_imagei(odata, posOut,pix.value);

			currentScratch += 2*WIN_SIZE_X;
			posOut.y++;
		}
		//write odd points to destination
		posOut.y =  ((height + firstY)>>1) + 1;
		currentScratch = scratch +  getLocalId(0) + WIN_SIZE_X;
		for (int j = 0; j < WIN_SIZE_Y; j+=2) {

			 if (posOut.x >= width || posOut.y >= height)
				break;

			int4Pixel pix;
			readPixel(&pix, currentScratch);
			write_imagei(odata, posOut,pix.value);

			currentScratch += 2*WIN_SIZE_X;
			posOut.y++;
		}

		firstY += WIN_SIZE_Y;
		localMemoryFence();
	}

}


/******************************************************************************
 * @file     prngcl_common.cl
 * @author   Vadim Demchik <vadimdi@yahoo.com>
 * @version  1.1.1
 *
 * @brief    [PRNGCL library]
 *           common module for all PRNG implementations
 *           contains precision selection, etc.
 *
 *
 * @section  LICENSE
 *
 * Copyright (c) 2013, 2014 Vadim Demchik
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 *    Redistributions of source code must retain the above copyright notice,
 *      this list of conditions and the following disclaimer.
 *
 *    Redistributions in binary form must reproduce the above copyright notice,
 *      this list of conditions and the following disclaimer in the documentation
 *      and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
 *
 *****************************************************************************/

#ifndef PRNGCL_COMMON_CL
#define PRNGCL_COMMON_CL

#define GID_SIZE    (get_global_size(0) * get_global_size(1) * get_global_size(2))
#define GID         (get_global_id(0) + get_global_id(1) * get_global_size(0) + get_global_id(2) * get_global_size(0) * get_global_size(1))

#define hgpu_single  float
#define hgpu_single2 float2
#define hgpu_single3 float3
#define hgpu_single4 float4

#if defined(cl_khr_fp64)

#define hgpu_double     double
#define hgpu_double2    double2
#define hgpu_double3    double3
#define hgpu_double4    double4

//#define PRNG_SKIP_CHECK     // if defined = skip uniformity checking in double precision

#if defined(cl_amd_fp64)    // AMD extension available?
	#pragma OPENCL EXTENSION cl_amd_fp64 : enable
#elif defined(cl_khr_fp64)  // Khronos extension available?
	#pragma OPENCL EXTENSION cl_khr_fp64 : enable
#endif

#ifndef PRNG_PRECISION
#define PRNG_PRECISION   0       // single precision by default
#endif

#if ((PRNG_PRECISION==0)||(PRNG_PRECISION==1))
#define PRECISION_SINGLE            // define single precision
#elif (PRNG_PRECISION==2)
#define PRECISION_DOUBLE            // define double precision
#endif

#ifdef PRECISION_DOUBLE
#define hgpu_float   hgpu_double
#define hgpu_float2  hgpu_double2
#define hgpu_float3  hgpu_double3
#define hgpu_float4  hgpu_double4
#else
#define hgpu_float   float
#define hgpu_float2  float2
#define hgpu_float3  float3
#define hgpu_float4  float4
#endif

inline hgpu_double4 hgpu_uint4_2_double4(uint4 x){
    hgpu_double4 result;
    result.x = (double) x.x;
    result.y = (double) x.y;
    result.z = (double) x.z;
    result.w = (double) x.w;

    return result;
}

inline hgpu_double hgpu_uint_to_double(uint rnd1, uint rnd2, uint rnd_min, uint rnd_max, double k){
    hgpu_double result = (rnd1 + k * rnd2 - (rnd_min + k * rnd_max)) / ((rnd_max - rnd_min) * (1.0 - k));
    return result;
}

inline hgpu_double4 hgpu_uint4_to_double4(uint4 rnd1, uint4 rnd2, uint rnd_min, uint rnd_max, double k){
    hgpu_double4 result;
    hgpu_double4 drnd1 = hgpu_uint4_2_double4(rnd1);
    hgpu_double4 drnd2 = hgpu_uint4_2_double4(rnd2);
    double a1 = (rnd_min + k * rnd_max);
    double a2 = ((rnd_max - rnd_min) * (1.0 - k));
        result.x = (drnd1.x + k * drnd2.x - a1) / a2;
        result.y = (drnd1.y + k * drnd2.y - a1) / a2;
        result.z = (drnd1.z + k * drnd2.z - a1) / a2;
        result.w = (drnd1.w + k * drnd2.w - a1) / a2;
        return result;
}

inline hgpu_double hgpu_float_to_double(float rnd1, float rnd2, double rnd_min, double rnd_max, double k){
    double a1 = (rnd_max - rnd_min);
    double a2 = trunc((a1-2.0*k) / k) + a1;
        return (trunc((rnd1-rnd_min-k) / k) + rnd2 - rnd_min) / a2 * (1.0-k*k);
}

inline hgpu_double2 hgpu_float4_to_double2(float4 rnd, double rnd_min, double rnd_max, double k){
    hgpu_double2 result;
    double a1 = (rnd_max - rnd_min);
    double a2 = trunc((a1-2.0*k) / k) + a1;
        result.x = (trunc((rnd.x-rnd_min-k) / k) + rnd.y - rnd_min) / a2 * (1.0-k*k);
        result.y = (trunc((rnd.z-rnd_min-k) / k) + rnd.w - rnd_min) / a2 * (1.0-k*k);
        return result;
}

inline hgpu_double4 hgpu_float4_to_double4(float4 rnd1, float4 rnd2, double rnd_min, double rnd_max, double k){
    hgpu_double4 result;
    double a1 = (rnd_max - rnd_min);
    double a2 = trunc((a1-2.0*k) / k) + a1;
        result.x = (trunc((rnd1.x-rnd_min-k) / k) + rnd2.x - rnd_min) / a2 * (1.0-k*k);
        result.y = (trunc((rnd1.y-rnd_min-k) / k) + rnd2.y - rnd_min) / a2 * (1.0-k*k);
        result.z = (trunc((rnd1.z-rnd_min-k) / k) + rnd2.z - rnd_min) / a2 * (1.0-k*k);
        result.w = (trunc((rnd1.w-rnd_min-k) / k) + rnd2.w - rnd_min) / a2 * (1.0-k*k);
        return result;
}

#else

#define hgpu_float   float
#define hgpu_float2  float2
#define hgpu_float3  float3
#define hgpu_float4  float4

#endif

inline float4 hgpu_uint4_to_float4(uint4 x){
    float4 result;
    result.x = (float) x.x;
    result.y = (float) x.y;
    result.z = (float) x.z;
    result.w = (float) x.w;

    return result;
}

typedef union _Uint_and_Float   // Uint <---> Float converter
{
    uint uint_value;
    float float_value;
} Uint_and_Float;

#endif

/******************************************************************************
 * @file     prngcl_common.cl
 * @author   Vadim Demchik <vadimdi@yahoo.com>
 * @version  1.1
 *
 * @brief    [PRNGCL library]
 *           common module for all PRNG implementations
 *           contains precision selection, etc.
 *
 *
 * @section  LICENSE
 *
 * Copyright (c) 2013, Vadim Demchik
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 *    Redistributions of source code must retain the above copyright notice,
 *      this list of conditions and the following disclaimer.
 *
 *    Redistributions in binary form must reproduce the above copyright notice,
 *      this list of conditions and the following disclaimer in the documentation
 *      and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
 *
 *****************************************************************************/

#ifndef PRNGCL_COMMON_CL
#define PRNGCL_COMMON_CL

#define GID_SIZE    (get_global_size(0) * get_global_size(1) * get_global_size(2))
#define GID         (get_global_id(0) + get_global_id(1) * get_global_size(0) + get_global_id(2) * get_global_size(0) * get_global_size(1))

#if defined(cl_khr_fp64)

#define hgpu_double     double
#define hgpu_double2    double2
#define hgpu_double3    double3
#define hgpu_double4    double4

#if defined(cl_amd_fp64)    // AMD extension available?
	#pragma OPENCL EXTENSION cl_amd_fp64 : enable
#elif defined(cl_khr_fp64)  // Khronos extension available?
	#pragma OPENCL EXTENSION cl_khr_fp64 : enable
#endif

#ifndef PRNG_PRECISION
#define PRNG_PRECISION   0       // single precision by default
#endif

#if ((PRNG_PRECISION==0)||(PRNG_PRECISION==1))
#define PRECISION_SINGLE            // define single precision
#elif (PRNG_PRECISION==2)
#define PRECISION_DOUBLE            // define double precision
#endif

#ifdef PRECISION_DOUBLE
#define hgpu_float   hgpu_double
#define hgpu_float2  hgpu_double2
#define hgpu_float3  hgpu_double3
#define hgpu_float4  hgpu_double4
#else
#define hgpu_float   float
#define hgpu_float2  float2
#define hgpu_float3  float3
#define hgpu_float4  float4
#endif

#define hgpu_single  float
#define hgpu_single2 float2
#define hgpu_single3 float3
#define hgpu_single4 float4

inline hgpu_double4 hgpu_uint4_2_double4(uint4 x){
    hgpu_double4 result;
    result.x = (double) x.x;
    result.y = (double) x.y;
    result.z = (double) x.z;
    result.w = (double) x.w;

    return result;
}

inline hgpu_double hgpu_uint_to_double(uint rnd1, uint rnd2, uint rnd_min, uint rnd_max, double k){
    hgpu_double result = (rnd1 + k * rnd2 - (rnd_min + k * rnd_max)) / ((rnd_max - rnd_min) * (1.0 - k));
    return result;
}

inline hgpu_double4 hgpu_uint4_to_double4(uint4 rnd1, uint4 rnd2, uint rnd_min, uint rnd_max, double k){
    hgpu_double4 result;
    hgpu_double4 drnd1 = hgpu_uint4_2_double4(rnd1);
    hgpu_double4 drnd2 = hgpu_uint4_2_double4(rnd2);
    double a1 = (rnd_min + k * rnd_max);
    double a2 = ((rnd_max - rnd_min) * (1.0 - k));
        result.x = (drnd1.x + k * drnd2.x - a1) / a2;
        result.y = (drnd1.y + k * drnd2.y - a1) / a2;
        result.z = (drnd1.z + k * drnd2.z - a1) / a2;
        result.w = (drnd1.w + k * drnd2.w - a1) / a2;
        return result;
}

inline hgpu_double hgpu_float_to_double(float rnd1, float rnd2, double rnd_min, double rnd_max, double k){
    hgpu_double result;
        double a1 = (rnd_max - rnd_min);
        double a2 = k * a1;
        double a3 = a1 * (1.0 - k);
        double a4 = -(rnd_min / a1 + rnd_max) * k - rnd_min;
        result = (trunc((rnd1 - rnd_min) / a2) + rnd2 / a1) * k / a3 + a4 / a3;
        return result;
}

inline hgpu_double2 hgpu_float4_to_double2(float4 rnd, double rnd_min, double rnd_max, double k){
    hgpu_double2 result;
        double a1 = (rnd_max - rnd_min);
        double a2 = k * a1;
        double a3 = a1 * (1.0 - k);
        double a4 = -(rnd_min / a1 + rnd_max) * k - rnd_min;
        result.x = (trunc((rnd.x - rnd_min) / a2) + rnd.y / a1) * k / a3 + a4 / a3;
        result.y = (trunc((rnd.z - rnd_min) / a2) + rnd.w / a1) * k / a3 + a4 / a3;
        return result;
}

inline hgpu_double4 hgpu_float4_to_double4(float4 rnd1, float4 rnd2, double rnd_min, double rnd_max, double k){
    hgpu_double4 result;
        double a1 = (rnd_max - rnd_min);
        double a2 = k * a1;
        double a3 = a1 * (1.0 - k);
        double a4 = -(rnd_min / a1 + rnd_max) * k - rnd_min;
        result.x = (trunc((rnd1.x - rnd_min) / a2) + rnd2.x / a1) * k / a3 + a4 / a3;
        result.y = (trunc((rnd1.y - rnd_min) / a2) + rnd2.y / a1) * k / a3 + a4 / a3;
        result.z = (trunc((rnd1.z - rnd_min) / a2) + rnd2.z / a1) * k / a3 + a4 / a3;
        result.w = (trunc((rnd1.w - rnd_min) / a2) + rnd2.w / a1) * k / a3 + a4 / a3;
        return result;
}

#endif

inline float4 hgpu_uint4_to_float4(uint4 x){
    float4 result;
    result.x = (float) x.x;
    result.y = (float) x.y;
    result.z = (float) x.z;
    result.w = (float) x.w;

    return result;
}

typedef union _Uint_and_Float   // Uint <---> Float converter
{
    uint uint_value;
    float float_value;
} Uint_and_Float;

#endif


Phong fix ?

Phong fix ?

#include "kernel_header.hcl"
#include "kernel_matrix.hcl"
#include "kernel_cam.hcl"
#include "kernel_color.hcl"
#include "kernel_cone.hcl"
#include "kernel_cylinder.hcl"
#include "kernel_data.hcl"
#include "kernel_debug.hcl"
#include "kernel_plane.hcl"
#include "kernel_sphere.hcl"

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

	while (i < max)
	{
		if (i < scene->n_cones)
			if (((dist = inter_cone(scene, i, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 1;
				hit.id = i;
			}
		if (i < scene->n_cylinders)
			if (((dist = inter_cylinder(scene, i, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 2;
				hit.id = i;
			}
		if (i < scene->n_planes)
			if (((dist = inter_plan(scene, i, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 4;
				hit.id = i;
			}
		if (i < scene->n_spheres)
			if (((dist = inter_sphere(scene, i, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 5;
				hit.id = i;
			}
		i++;
	}
	return (hit);
}

static t_hit			ray_hit2(const __local t_scene *scene, const float3 origin, const float3 ray)
{
	unsigned int			i = 0;
	int						max = get_max_obj(scene);
	t_hit					hit = hit_init();
	float					dist = 0;

	while (i < max)
	{
		if (i < scene->n_cones)
			if (((dist = inter_cone(scene, i, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 1;
				hit.id = i;
			}
		if (i < scene->n_cylinders)
			if (((dist = inter_cylinder(scene, i, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 2;
				hit.id = i;
			}
		if (i < scene->n_planes)
			if (((dist = inter_plan(scene, i, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 4;
				hit.id = i;
			}
		if (i < scene->n_spheres)
			if (((dist = inter_sphere(scene, i, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 5;
				hit.id = i;
			}
		i++;
	}
	return (hit);
}

float3			get_hit_normale(const __local t_scene *scene, float3 ray, t_hit hit)
{
	float3		res;

	if (hit.type == 1)
		res = get_cone_normale(scene, hit);
	else if (hit.type == 2)
		res = get_cylinder_normal(scene, hit);
	else if (hit.type == 4)
	{
		if (dot(PLANE[hit.id].normale, -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 (fast_normalize(res));
}

unsigned int			color_diffuse2(const __local t_scene *scene, const t_hit hit, \
										const t_hit light_hit, const unsigned int color, const float coef)
{
	float3		__private	diffuse = get_obj_diffuse(scene, hit);
	float		__private	brightness = (float __private)LIGHT[light_hit.id].brightness;

	if (hit.type == 1)
		diffuse = (float3 __private)CONES[hit.id].diff;
	else if (hit.type == 2)
		diffuse = (float3 __private)CYLIND[hit.id].diff;
	else if (hit.type == 4)
		diffuse = (float3 __private)PLANE[hit.id].diff;
	else if (hit.type == 5)
		diffuse = (float3 __private)SPHERE[hit.id].diff;
	else
		diffuse = 0.f;

	int __private hue;

	if (hit.type == 1)
		hue = (int __private)CONES[hit.id].color;
	if (hit.type == 2)
		hue = (int __private)CYLIND[hit.id].color;
	if (hit.type == 3)
		hue = (int __private)LIGHT[hit.id].color;
	if (hit.type == 4)
		hue = (int __private)PLANE[hit.id].color;
	if (hit.type == 5)
		hue = (int __private)SPHERE[hit.id].color;
	int __private hue_light;

	if (hit.type == 1)
		hue_light = (int __private)CONES[light_hit.id].color;
	if (hit.type == 2)
		hue_light = (int __private)CYLIND[light_hit.id].color;
	if (hit.type == 3)
		hue_light = (int __private)LIGHT[light_hit.id].color;
	if (hit.type == 4)
		hue_light = (int __private)PLANE[light_hit.id].color;
	if (hit.type == 5)
		hue_light = (int __private)SPHERE[light_hit.id].color;
	unsigned int	col_r = (color & 0xFF0000) >> 16;
	unsigned int	col_g = (color & 0x00FF00) >> 8;
	unsigned int	col_b = (color & 0x0000FF);
	unsigned int	obj_r = (hue & 0xFF0000) >> 16;
	unsigned int	obj_g = (hue & 0x00FF00) >> 8;
	unsigned int	obj_b = (hue & 0x00000FF);
	unsigned int	l_r = (hue_light & 0xFF0000) >> 16;
	unsigned int	l_g = (hue_light & 0x00FF00) >> 8;
	unsigned int	l_b = (hue_light & 0x0000FF);

	col_r += ((l_r * brightness) + obj_r) * coef * diffuse.x;
	col_g += ((l_g * brightness) + obj_g) * coef * diffuse.y;
	col_b += ((l_b * brightness) + obj_b) * coef * diffuse.z;
	(col_r > 255 ? col_r = 255 : 0);
	(col_g > 255 ? col_g = 255 : 0);
	(col_b > 255 ? col_b = 255 : 0);
	return ((col_r << 16) + (col_g << 8) + col_b);
}

unsigned int			color_specular2(const __local t_scene *scene, const t_hit hit, \
										const t_hit light_hit, const unsigned int color, const float coef)
{
	float3 __private	speculos = 0.f;
	if (hit.type == 1)
		speculos = (float3 __private)CONES[hit.id].spec;
	else if (hit.type == 2)
		speculos = (float3 __private)CYLIND[hit.id].spec;
	else if (hit.type == 4)
		speculos = (float3 __private)PLANE[hit.id].spec;
	else if (hit.type == 5)
		speculos = (float3 __private)SPHERE[hit.id].spec;
	else
		speculos = 0.f;
	float			old_coef = coef;
	unsigned int	col_r = (color & 0x00FF0000) >> 16;
	unsigned int	col_g = (color & 0x0000FF00) >> 8;
	unsigned int	col_b = (color & 0x000000FF);

	float pow_of_spec;
	pow_of_spec = native_powr(old_coef, (int)(LIGHT[light_hit.id].shrink));
 	int light_color = LIGHT[light_hit.id].color;
	//printf("%.2f\n", pow_of_spec);
	//float a = pow_of_spec * 2;
	col_r += (((light_color & 0xFF0000) >> 16) * pow_of_spec) * speculos.x;
	//printf("%.2f\n", speculos.x);
	col_g += ((light_color & 0x00FF00) >> 8) * pow_of_spec * speculos.y;
	col_b += (light_color & 0x0000FF) * pow_of_spec * speculos.z;
	(col_r > 255 ? col_r = 255 : 0);
	(col_g > 255 ? col_g = 255 : 0);
	(col_b > 255 ? col_b = 255 : 0);
	return ((col_r << 16) + (col_g << 8) + col_b);
}

unsigned int			phong(const __local t_scene *scene, const t_hit hit, const float3 ray)
{
	int					i = -1;
//	unsigned int		res_color = get_ambient(scene, get_obj_hue(scene, hit));
float				tmp2;
	float				tmp;
	float3				reflect = 0;
	unsigned int __private obj_color;
	if (hit.type == 1)
		obj_color = (unsigned int __private)CONES[hit.id].color;
	if (hit.type == 2)
		obj_color = (unsigned int __private)CYLIND[hit.id].color;
	if (hit.type == 3)
		obj_color = (unsigned int __private)LIGHT[hit.id].color;
	if (hit.type == 4)
		obj_color = (unsigned int __private)PLANE[hit.id].color;
	if (hit.type == 5)
		obj_color = (unsigned int __private)SPHERE[hit.id].color;
	unsigned int r, g, b;

	r = (obj_color & 0xFF0000) >> 16;
	g = (obj_color & 0x00FF00) >> 8;
	b = (obj_color & 0x0000FF);
	r = (0.01 + r * scene->ambient.x > 255 ? 255 : 0.01 + r * scene->ambient.x);
	g = (0.01 + g * scene->ambient.y > 255 ? 255 : 0.01 + g * scene->ambient.y);
	b = (0.01 + b * scene->ambient.z > 255 ? 255 : 0.01 + b * scene->ambient.z);
	unsigned int res_color = ((r << 16) + (g << 8) + b);

//	unsigned int res_color = 0x0FF0FF;
	t_light_ray			light_ray;
	t_hit				light_hit;// = hit_init();
	light_hit.dist = 0.0;
	light_hit.type = 0;
	light_hit.id = 0;
	light_hit.pos = 0.0;
	light_hit.normale = 0.0;

	while (++i < scene->n_lights)
	{
		tmp = 0;
		tmp2 = 0;
		light_ray.dir = LIGHT[i].pos - hit.pos;
		light_ray.dist = fast_length(light_ray.dir);
		light_ray.dir = fast_normalize(light_ray.dir);
		light_hit = ray_hit(scene, hit.pos, light_ray.dir);
		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 (tmp > 0.005)
			{
				float3		__private	diffuse = get_obj_diffuse(scene, hit);
				float		__private	brightness = (float __private)LIGHT[light_hit.id].brightness;

				if (hit.type == 1)
					diffuse = (float3 __private)CONES[hit.id].diff;
				else if (hit.type == 2)
					diffuse = (float3 __private)CYLIND[hit.id].diff;
				else if (hit.type == 4)
					diffuse = (float3 __private)PLANE[hit.id].diff;
				else if (hit.type == 5)
					diffuse = (float3 __private)SPHERE[hit.id].diff;
				else
					diffuse = 0.f;

				int __private hue;

				if (hit.type == 1)
					hue = (int __private)CONES[hit.id].color;
				if (hit.type == 2)
					hue = (int __private)CYLIND[hit.id].color;
				if (hit.type == 3)
					hue = (int __private)LIGHT[hit.id].color;
				if (hit.type == 4)
					hue = (int __private)PLANE[hit.id].color;
				if (hit.type == 5)
					hue = (int __private)SPHERE[hit.id].color;
				int __private hue_light;

				if (hit.type == 1)
					hue_light = (int __private)CONES[light_hit.id].color;
				if (hit.type == 2)
					hue_light = (int __private)CYLIND[light_hit.id].color;
				if (hit.type == 3)
					hue_light = (int __private)LIGHT[light_hit.id].color;
				if (hit.type == 4)
					hue_light = (int __private)PLANE[light_hit.id].color;
				if (hit.type == 5)
					hue_light = (int __private)SPHERE[light_hit.id].color;
				unsigned int	col_r = (res_color & 0xFF0000) >> 16;
				unsigned int	col_g = (res_color & 0x00FF00) >> 8;
				unsigned int	col_b = (res_color & 0x0000FF);
				unsigned int	obj_r = (hue & 0xFF0000) >> 16;
				unsigned int	obj_g = (hue & 0x00FF00) >> 8;
				unsigned int	obj_b = (hue & 0x00000FF);
				unsigned int	l_r = (hue_light & 0xFF0000) >> 16;
				unsigned int	l_g = (hue_light & 0x00FF00) >> 8;
				unsigned int	l_b = (hue_light & 0x0000FF);

				col_r += ((l_r * brightness) + obj_r) * tmp * diffuse.x;
				col_g += ((l_g * brightness) + obj_g) * tmp * diffuse.y;
				col_b += ((l_b * brightness) + obj_b) * tmp * diffuse.z;
				(col_r > 255 ? col_r = 255 : 0);
				(col_g > 255 ? col_g = 255 : 0);
				(col_b > 255 ? col_b = 255 : 0);
				res_color = ((col_r << 16) + (col_g << 8) + col_b);
			}
			reflect = fast_normalize(((float)(2.0 * dot(hit.normale, light_ray.dir)) * hit.normale) - light_ray.dir);
			tmp2 = dot(reflect, -ray);
			if (tmp2 > 0.005)
			{
				//res_color = color_specular2(scene, hit, light_hit, res_color, tmp2);
			}
		}
	}
	return (res_color);
}

unsigned int			phong2(const __local t_scene *scene, const t_hit hit, const float3 ray)
{
	int					i;
	i = 0;
	unsigned int		res_color;
	res_color = get_ambient(scene, get_obj_hue(scene, hit));
	float				tmp;
	tmp = 0;
	float3				reflect;
	reflect = 0;
	float3 __private	diffuse;
	diffuse = 0;
	float __private	brightness;
	brightness = 0;
	int __private hue;
	hue = 0;
	int __private hue_light;
	hue_light = 0;
	unsigned int __private col_r, col_g, col_b, obj_r, obj_g, obj_b, l_r, l_b, l_g;
	col_r = 0;
	col_g = 0;
	col_b = 0;
	obj_r = 0;
	obj_g = 0;
	obj_b = 0;
	l_r = 0;
	l_g = 0;
	l_b = 0;
	t_light_ray			light_ray;
	t_hit				light_hit;
	float __private pow_of_spec;
	pow_of_spec = 0;
	int __private light_color;
	light_color = 0;
	float3 __private speculos;
	speculos = 0;

	light_ray.dir = LIGHT[0].pos - hit.pos;
	light_ray.dist = fast_length(light_ray.dir);
	light_ray.dir = fast_normalize(light_ray.dir);
	light_hit = ray_hit(scene, hit.pos, light_ray.dir);
	light_hit.id = i;
	light_hit.type = 3;

		tmp = 0;
		light_ray.dir = LIGHT[i].pos - hit.pos;
		light_ray.dist = fast_length(light_ray.dir);
		light_ray.dir = fast_normalize(light_ray.dir);
		light_hit = ray_hit(scene, hit.pos, light_ray.dir);
		light_hit.id = i;
		light_hit.type = 3;
		if (light_hit.dist < light_ray.dist && light_hit.dist > 0)
			res_color = 0;
		else
		{
			tmp = dot(hit.normale, light_ray.dir);
			if (tmp > 0.f)
			{
				brightness = (float __private)LIGHT[light_hit.id].brightness;

				if (hit.type == 1)
					diffuse = (float3 __private)CONES[hit.id].diff;
				else if (hit.type == 2)
					diffuse = (float3 __private)CYLIND[hit.id].diff;
				else if (hit.type == 4)
					diffuse = (float3 __private)PLANE[hit.id].diff;
				else if (hit.type == 5)
					diffuse = (float3 __private)SPHERE[hit.id].diff;
				else
					diffuse = 0.f;

				if (hit.type == 1)
					hue = (int __private)CONES[hit.id].color;
				if (hit.type == 2)
					hue = (int __private)CYLIND[hit.id].color;
				if (hit.type == 3)
					hue = (int __private)LIGHT[hit.id].color;
				if (hit.type == 4)
					hue = (int __private)PLANE[hit.id].color;
				if (hit.type == 5)
					hue = (int __private)SPHERE[hit.id].color;

				if (hit.type == 1)
					hue_light = (int __private)CONES[light_hit.id].color;
				if (hit.type == 2)
					hue_light = (int __private)CYLIND[light_hit.id].color;
				if (hit.type == 3)
					hue_light = (int __private)LIGHT[light_hit.id].color;
				if (hit.type == 4)
					hue_light = (int __private)PLANE[light_hit.id].color;
				if (hit.type == 5)
					hue_light = (int __private)SPHERE[light_hit.id].color;
				col_r = (res_color & 0xFF0000) >> 16;
				col_g = (res_color & 0x00FF00) >> 8;
				col_b = (res_color & 0x0000FF);
				obj_r = (hue & 0xFF0000) >> 16;
				obj_g = (hue & 0x00FF00) >> 8;
				obj_b = (hue & 0x00000FF);
				l_r = (hue_light & 0xFF0000) >> 16;
				l_g = (hue_light & 0x00FF00) >> 8;
				l_b = (hue_light & 0x0000FF);

				col_r += ((l_r * brightness) + obj_r) * tmp * diffuse.x;
				col_g += ((l_g * brightness) + obj_g) * tmp * diffuse.y;
				col_b += ((l_b * brightness) + obj_b) * tmp * diffuse.z;
				(col_r > 255 ? col_r = 255 : 0);
				(col_g > 255 ? col_g = 255 : 0);
				(col_b > 255 ? col_b = 255 : 0);
				res_color = ((col_r << 16) + (col_g << 8) + col_b);
			}
		//		res_color = color_diffuse(scene, hit, light_hit, res_color, tmp);
			reflect = fast_normalize(((float)(2.0 * dot(hit.normale, light_ray.dir)) * hit.normale) - light_ray.dir);
			tmp = dot(reflect, -ray);
			if (tmp > 0.f)
			{
				speculos = 0.f;
				if (hit.type == 1)
					speculos = (float3 __private)CONES[hit.id].spec;
				else if (hit.type == 2)
					speculos = (float3 __private)CYLIND[hit.id].spec;
				else if (hit.type == 4)
					speculos = (float3 __private)PLANE[hit.id].spec;
				else if (hit.type == 5)
					speculos = (float3 __private)SPHERE[hit.id].spec;
				else
					speculos = 0.f;
				col_r = (res_color & 0x00FF0000) >> 16;
				col_g = (res_color & 0x0000FF00) >> 8;
				col_b = (res_color & 0x000000FF);

				pow_of_spec = native_powr(tmp, (int)(LIGHT[light_hit.id].shrink));
				light_color = LIGHT[light_hit.id].color;
				//printf("%.2f\n", pow_of_spec);
				//float a = pow_of_spec * 2;
				col_r += (((light_color & 0xFF0000) >> 16) * pow_of_spec) * speculos.x;
				//printf("%.2f\n", speculos.x);
				col_g += ((light_color & 0x00FF00) >> 8) * pow_of_spec * speculos.y;
				col_b += (light_color & 0x0000FF) * pow_of_spec * speculos.z;
				(col_r > 255 ? col_r = 255 : 0);
				(col_g > 255 ? col_g = 255 : 0);
				(col_b > 255 ? col_b = 255 : 0);
				res_color = ((col_r << 16) + (col_g << 8) + col_b);
			}
		}
	return (res_color);
}

unsigned int			phong3(const __local t_scene *scene, const t_hit hit, const float3 ray)
{
	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 < scene->n_lights)
	{
		tmp = 0;
		light_ray.dir = LIGHT[i].pos - hit.pos;
		light_ray.dist = fast_length(light_ray.dir);
		light_ray.dir = fast_normalize(light_ray.dir);
		light_hit = ray_hit(scene, hit.pos, light_ray.dir);
		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 (tmp > 0)
				res_color = color_diffuse(scene, hit, light_hit, res_color, tmp);
			reflect = fast_normalize(((float)(2.0 * dot(hit.normale, light_ray.dir)) * hit.normale) - light_ray.dir);
			tmp = dot(reflect, -ray);
			if (tmp > 0)
				res_color = color_specular(scene, hit, light_hit, res_color, tmp);
		}
	}
	return (res_color);
}

unsigned int			phong4(const __local t_scene *scene, const t_hit hit, const float3 ray)
{
	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 < scene->n_lights)
	{
		tmp = 0;
		light_ray.dir = LIGHT[i].pos - hit.pos;
		light_ray.dist = fast_length(light_ray.dir);
		light_ray.dir = fast_normalize(light_ray.dir);
		light_hit = ray_hit(scene, hit.pos, light_ray.dir);
		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 (tmp > 0)
				res_color = color_diffuse(scene, hit, light_hit, res_color, tmp);
			reflect = fast_normalize(((float)(2.0 * dot(hit.normale, light_ray.dir)) * hit.normale) - light_ray.dir);
			tmp = dot(reflect, -ray);
			if (tmp > 0)
				res_color = color_specular(scene, hit, light_hit, res_color, tmp);
		}
	}
	return (res_color);
}

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

static unsigned int	get_pixel_color(const __local t_scene *scene, float3 ray)
{
	t_hit			hit;
	int				depth = scene->depth;
	unsigned int	color  = 0;
	unsigned int	bounce_color = 0;

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

__kernel void	ray_trace(	__global	char		*output,
							__global	t_hit		*target_obj,
							__global	t_scene		*scene_data,
							__global	t_cam		*cameras_data,
							__global	t_cone		*cones_data,
							__global	t_cylinder	*cylinders_data,
							__global	t_light		*lights_data,
							__global	t_plane		*planes_data,
							__global	t_sphere	*spheres_data,
							__local		t_scene		*scene,
							__local		t_cam		*cameras,
							__local		t_cone		*cones,
							__local		t_cylinder	*cylinders,
							__local		t_light		*lights,
							__local		t_plane		*planes,
							__local		t_sphere	*spheres)
{
 	event_t	ev;
	ev = async_work_group_copy((__local char *)scene, (__global char *)scene_data, sizeof(t_scene), 0);
	wait_group_events(1, &ev);
	ev = async_work_group_copy((__local char *)cameras, (__global char *)cameras_data, sizeof(t_cam) * scene->n_cams, 0);
	wait_group_events(1, &ev);
	ev = async_work_group_copy((__local char *)cones, (__global char *)cones_data, sizeof(t_cone) * scene->n_cones, 0);
	wait_group_events(1, &ev);
	ev = async_work_group_copy((__local char *)cylinders, (__global char *)cylinders_data, sizeof(t_cylinder) * scene->n_cylinders, 0);
	wait_group_events(1, &ev);
	ev = async_work_group_copy((__local char *)lights, (__global char *)lights_data, sizeof(t_light) * scene->n_lights, 0);
	wait_group_events(1, &ev);
	ev = async_work_group_copy((__local char *)planes, (__global char *)planes_data, sizeof(t_plane) * scene->n_planes, 0);
	wait_group_events(1, &ev);
	ev = async_work_group_copy((__local char *)spheres, (__global char *)spheres_data, sizeof(t_sphere) * scene->n_spheres, 0);
	wait_group_events(1, &ev);

	scene->cameras = cameras;
	scene->cones = cones;
	scene->cylinders = cylinders;
	scene->lights = lights;
	scene->planes = planes;
	scene->spheres = spheres;

	uint2	pix;
	pix.x = get_global_id(0);
	pix.y = get_global_id(1);
	int			id = pix.x + (scene->win_w * pix.y); // NE PAS VIRER ID CAR BESOIN DANS MACRO OUTPUTE

	float3	prim_ray = get_ray_cam(scene, pix);
	if (pix.x == scene->mou_x && pix.y == scene->mou_y)
		*target_obj = ray_hit(scene, ACTIVECAM.pos, prim_ray);
	OUTPUTE = get_pixel_color(scene, prim_ray);
}

#include "kernel_header.hcl"
#include "kernel_matrix.hcl"
#include "kernel_cam.hcl"
#include "kernel_color.hcl"
#include "kernel_cone.hcl"
#include "kernel_cylinder.hcl"
#include "kernel_data.hcl"
#include "kernel_debug.hcl"
#include "kernel_plane.hcl"
#include "kernel_sphere.hcl"

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

	while (i < max)
	{
		if (i < scene->n_cones)
			if (((dist = inter_cone(scene, i, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 1;
				hit.id = i;
			}
		if (i < scene->n_cylinders)
			if (((dist = inter_cylinder(scene, i, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 2;
				hit.id = i;
			}
		if (i < scene->n_planes)
			if (((dist = inter_plan(scene, i, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 4;
				hit.id = i;
			}
		if (i < scene->n_spheres)
			if (((dist = inter_sphere(scene, i, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 5;
				hit.id = i;
			}
		i++;
	}
	return (hit);
}

float3			get_hit_normale(const __local t_scene *scene, float3 ray, t_hit hit)
{
	float3		res;

	if (hit.type == 1)
		res = get_cone_normale(scene, hit);
	else if (hit.type == 2)
		res = get_cylinder_normal(scene, hit);
	else if (hit.type == 4)
	{
		if (dot(PLANE[hit.id].normale, -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 (fast_normalize(res));
}

static unsigned int			phong(const __local t_scene *scene, const t_hit hit, const float3 ray)
{
	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 < scene->n_lights)
	{
		tmp = 0;
		light_ray.dir = LIGHT[i].pos - hit.pos;
		light_ray.dist = fast_length(light_ray.dir);
		light_ray.dir = fast_normalize(light_ray.dir);
		light_hit = ray_hit(scene, hit.pos, light_ray.dir);
		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 (tmp > 0)
				res_color = color_diffuse(scene, hit, light_hit, res_color, tmp);
			reflect = fast_normalize(((float)(2.0 * dot(hit.normale, light_ray.dir)) * hit.normale) - light_ray.dir);
			tmp = dot(reflect, -ray);
			if (tmp > 0)
				res_color = color_specular(scene, hit, light_hit, res_color, tmp);
		}
	}
	return (res_color);
}

static unsigned int			phong2(const __local t_scene *scene, const t_hit hit, const float3 ray)
{
	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 < scene->n_lights)
	{
		tmp = 0;
		light_ray.dir = LIGHT[i].pos - hit.pos;
		light_ray.dist = fast_length(light_ray.dir);
		light_ray.dir = fast_normalize(light_ray.dir);
		light_hit = ray_hit(scene, hit.pos, light_ray.dir);
		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 (tmp > 0)
				res_color = color_diffuse(scene, hit, light_hit, res_color, tmp);
			reflect = fast_normalize(((float)(2.0 * dot(hit.normale, light_ray.dir)) * hit.normale) - light_ray.dir);
			tmp = dot(reflect, -ray);
			if (tmp > 0)
				res_color = color_specular(scene, hit, light_hit, res_color, tmp);
		}
	}
	return (res_color);
}

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

static unsigned int	get_pixel_color(const __local t_scene *scene, float3 ray)
{
	t_hit			hit;
	int				depth = scene->depth;
	unsigned int	color  = 0;
	unsigned int	bounce_color = 0;

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

__kernel void	ray_trace(	__global	char		*output,
							__global	t_hit		*target_obj,
							__global	t_scene		*scene_data,
							__global	t_cam		*cameras_data,
							__global	t_cone		*cones_data,
							__global	t_cylinder	*cylinders_data,
							__global	t_light		*lights_data,
							__global	t_plane		*planes_data,
							__global	t_sphere	*spheres_data,
							__local		t_scene		*scene,
							__local		t_cam		*cameras,
							__local		t_cone		*cones,
							__local		t_cylinder	*cylinders,
							__local		t_light		*lights,
							__local		t_plane		*planes,
							__local		t_sphere	*spheres)
{
 	event_t	ev;
	ev = async_work_group_copy((__local char *)scene, (__global char *)scene_data, sizeof(t_scene), 0);
	wait_group_events(1, &ev);
	ev = async_work_group_copy((__local char *)cameras, (__global char *)cameras_data, sizeof(t_cam) * scene->n_cams, 0);
	wait_group_events(1, &ev);
	ev = async_work_group_copy((__local char *)cones, (__global char *)cones_data, sizeof(t_cone) * scene->n_cones, 0);
	wait_group_events(1, &ev);
	ev = async_work_group_copy((__local char *)cylinders, (__global char *)cylinders_data, sizeof(t_cylinder) * scene->n_cylinders, 0);
	wait_group_events(1, &ev);
	ev = async_work_group_copy((__local char *)lights, (__global char *)lights_data, sizeof(t_light) * scene->n_lights, 0);
	wait_group_events(1, &ev);
	ev = async_work_group_copy((__local char *)planes, (__global char *)planes_data, sizeof(t_plane) * scene->n_planes, 0);
	wait_group_events(1, &ev);
	ev = async_work_group_copy((__local char *)spheres, (__global char *)spheres_data, sizeof(t_sphere) * scene->n_spheres, 0);
	wait_group_events(1, &ev);

	scene->cameras = cameras;
	scene->cones = cones;
	scene->cylinders = cylinders;
	scene->lights = lights;
	scene->planes = planes;
	scene->spheres = spheres;

	uint2	pix;
	pix.x = get_global_id(0);
	pix.y = get_global_id(1);
	int			id = pix.x + (scene->win_w * pix.y); // NE PAS VIRER ID CAR BESOIN DANS MACRO OUTPUTE

	float3	prim_ray = get_ray_cam(scene, pix);
	if (pix.x == scene->mou_x && pix.y == scene->mou_y)
		*target_obj = ray_hit(scene, ACTIVECAM.pos, prim_ray);
	OUTPUTE = get_pixel_color(scene, prim_ray);
}


Filter the filters

Filter the filters

(use-package :regexp)

(load "cl-fad/load.lisp" :verbose nil)

(defstruct rdata start-marker end-marker replacement-callback include-markers)

(setq project-file-extension "vcxproj")
(setq solution-file-extension "sln")
(setq filters-file-extension "filters")

(defun regexp-replace (string pat repl)
  (reduce #'(lambda (x y) (string-concat x repl y))
          (regexp:regexp-split pat string))
)

(defun file-string (path)
  (with-open-file (infile path :if-does-not-exist nil)
    (cond ((not (null infile))
            (format nil "~{~A~^~%~}"
              (loop
                for line = (read-line infile nil)
                while line
                collect line
              )
            )
          )
          (t nil) ; file not found
    )
  )
)

(defun write-file (file-name content)
  (with-open-file (outfile file-name
      :direction :output
      :if-exists :supersede
      :if-does-not-exist :create)
  (format outfile "~A" content)))

(defmacro get-next-substr-index (str &key start-marker end-marker start-index end-index include-markers (next-index 0))
  `(progn
    (let ((start-m (match ,start-marker ,str :start ,next-index))
         )
      (cond ((null start-m) nil)
            (t
              (setq ,start-index  (if include-markers
                                     (match-start start-m)
                                     (match-end start-m)
                                  )
              )
              (let ((end-m (match ,end-marker ,str :start (match-end start-m))))
                (cond ((null end-m) nil)
                      (t
                        (setq ,end-index  (if include-markers
                                             (match-end end-m)
                                             (match-start end-m)
                                          )
                        )
                        (match-end end-m)
                      )
                )
              )
            )
      )
    )
  )
)
(defun concat-string-list (s)
  (format nil "~{~A~}" s))

(defun parse-replace (str template)
    (concat-string-list
      (let ((sm (rdata-start-marker template))
            (em (rdata-end-marker template))
            (callback (rdata-replacement-callback template))
            (include-markers (rdata-include-markers template))
            )
           ;(write-line (format nil "Replacing: ~A to ~A" sm em))
           (loop  with index = 0
                  do (setq next-index (get-next-substr-index str :start-marker sm
                               :end-marker em
                               :start-index si
                               :end-index ei
                               :next-index index
                               :include-markers include-markers))
                  if (null next-index)
                    collect (progn ;(write-line (format nil "~A -> ~A" index (length str)))
                              (subseq str index)
                             )
                  while next-index
                  collect (subseq str index si)
                  collect (funcall callback (subseq str si ei))
                  collect (subseq str ei next-index)
                  do (progn ;(write-line (format nil "~A -> [~A ~A] -> ~A" index si ei next-index))
                        (setq index next-index)
                      )
           )
      )
    )
)

(defun apply-replacement-templates (str templates)
  (cond ((null templates) str)
        (t (apply-replacement-templates
            (parse-replace str (car templates))
            (cdr templates)
           )
        )
  )
)

(defun apply-parse-file (file-name-in file-name-out templates)
  (write-file file-name-out
    (apply-replacement-templates (file-string file-name-in) templates)
  )
)

(defun replace-all (string part replacement &key (test #'char=))
  "Returns a new string in which all the occurences of the part
is replaced with replacement."
  (with-output-to-string (out)
    (loop with part-length = (length part)
       for old-pos = 0 then (+ pos part-length)
       for pos = (search part string
                         :start2 old-pos
                         :test test)
       do (write-string string out
                        :start old-pos
                        :end (or pos (length string)))
       when pos do (write-string replacement out)
       while pos)))

(defmacro create-rdata-list (listname addname)
  `(progn
    (setq ,listname nil)
    (defun ,addname (&rest args)
      (let ((rd (apply #'make-rdata args)))
        (setq ,listname (cons rd ,listname))
      )
    )
  )
)

(create-rdata-list proj-data-list add-projdata)
(create-rdata-list sln-data-list add-slndata)
(create-rdata-list filter-data-list add-filterdata)

(setq tp1 (make-rdata :start-marker "<data[^>]*>"
                     :end-marker "</data>"
                     :replacement-callback (lambda (str) "_123_")
                     :include-markers T))

(defun back-to-forward-slashes (str)
  (replace-all str "\\" "/")
)

(setq lambda-path-to-sln-dir (lambda (str) (regexp-replace (back-to-forward-slashes str)
                                                           (back-to-forward-slashes build-dir)
                                                           "$(SolutionDir)")))
(setq lambda-remove (lambda (str) ""))

(add-projdata :start-marker "<AdditionalIncludeDirectories>"
              :end-marker "</AdditionalIncludeDirectories>"
              :replacement-callback (lambda (str) (replace-all str "\\$$(SolutionDir)" "$(SolutionDir)")))
(add-projdata :start-marker "<OutDir[^>]*>"
              :end-marker "</OutDir>"
              :replacement-callback lambda-path-to-sln-dir)
(add-projdata :start-marker "<ImportLibrary[^>]*>"
              :end-marker "</ImportLibrary>"
              :replacement-callback lambda-path-to-sln-dir)
(add-projdata :start-marker "<ProgramDataBaseFile[^>]*>"
              :end-marker "</ProgramDataBaseFile>"
              :replacement-callback lambda-path-to-sln-dir)
(add-projdata :start-marker "[^<>]*<ItemGroup[^>]*>[^<]*<CustomBuild[^>]*CMakeLists[.]txt[^>]*>"
              :end-marker "</ItemGroup>"
              :replacement-callback lambda-remove
              :include-markers T)
(add-projdata :start-marker "[^<>]*<ItemGroup[^>]*>[^<]*<ProjectReference[^>]*ZERO_CHECK[.]vcxproj[^>]*>"
              :end-marker "</ItemGroup>"
              :replacement-callback lambda-remove
              :include-markers T)
(add-projdata :start-marker "CMAKE_INTDIR="
              :end-marker ";"
              :replacement-callback lambda-remove
              :include-markers T)

(add-filterdata :start-marker "[^<>]*<ItemGroup[^>]*>[^<]*<CustomBuild[^>]*CMakeLists[.]txt[^>]*>"
              :end-marker "</ItemGroup>"
              :replacement-callback lambda-remove
              :include-markers T)

(add-slndata  :start-marker "Project([^,]*ALL_BUILD"
              :end-marker "EndProject"
              :replacement-callback lambda-remove
              :include-markers T)
(add-slndata  :start-marker "Project([^,]*ZERO_CHECK"
              :end-marker "EndProject"
              :replacement-callback lambda-remove
              :include-markers T)

(defun mapc-directory-tree (fn directory)
  (dolist (entry (cl-fad:list-directory directory))
    (when (cl-fad:directory-pathname-p entry)
      (mapc-directory-tree fn entry))
    (funcall fn entry)))

(defun get-temp-filename (fn)
  (format nil "~A.tmp" fn))

(defun process-file (filename-in file-extension)
  (let ((filename-out (get-temp-filename filename-in))
        (data-list (cond ((equal file-extension solution-file-extension) sln-data-list)
                         ((equal file-extension filters-file-extension) filter-data-list)
                         (t proj-data-list)))
       )
    (apply-parse-file filename-in filename-out data-list)
    (delete-file filename-in)
    (rename-file filename-out filename-in)
  )
)

(defun process (dir)
  (setq build-dir dir)
  (let ((target-directory (if (null dir)
                              (ext:cd)
                              dir)))
    (write-line (format nil "Base directory: ~A~%" target-directory))
    (mapc-directory-tree (lambda (x)
                           (let ((file-extension (pathname-type x)))
                             (when (or (equal file-extension project-file-extension)
                                       (equal file-extension filters-file-extension)
                                       (equal file-extension solution-file-extension))
                               (write-line (format nil "~A"
                                                   (enough-namestring x target-directory)
                                                   ))
                               (process-file (namestring x) file-extension))
                           )
                         )
                         target-directory)))

(defun _ () (load "parse-replace.cl" :verbose nil))

(when (>= (length *args*) 1)
  (let ((path (car *args*)))
    (process path)
  )
)

(use-package :regexp)

(load "cl-fad/load.lisp" :verbose nil)

(defstruct rdata start-marker end-marker replacement-callback include-markers)

(setq project-file-extension "vcxproj")
(setq solution-file-extension "sln")

(defun regexp-replace (string pat repl)
  (reduce #'(lambda (x y) (string-concat x repl y))
          (regexp:regexp-split pat string))
)

(defun file-string (path)
  (with-open-file (infile path :if-does-not-exist nil)
    (cond ((not (null infile))
            (format nil "~{~A~^~%~}"
              (loop
                for line = (read-line infile nil)
                while line
                collect line
              )
            )
          )
          (t nil) ; file not found
    )
  )
)

(defun write-file (file-name content)
  (with-open-file (outfile file-name
      :direction :output
      :if-exists :supersede
      :if-does-not-exist :create)
  (format outfile "~A" content)))

(defmacro get-next-substr-index (str &key start-marker end-marker start-index end-index include-markers (next-index 0))
  `(progn
    (let ((start-m (match ,start-marker ,str :start ,next-index))
         )
      (cond ((null start-m) nil)
            (t
              (setq ,start-index  (if include-markers
                                     (match-start start-m)
                                     (match-end start-m)
                                  )
              )
              (let ((end-m (match ,end-marker ,str :start (match-end start-m))))
                (cond ((null end-m) nil)
                      (t
                        (setq ,end-index  (if include-markers
                                             (match-end end-m)
                                             (match-start end-m)
                                          )
                        )
                        (match-end end-m)
                      )
                )
              )
            )
      )
    )
  )
)
(defun concat-string-list (s)
  (format nil "~{~A~}" s))

(defun parse-replace (str template)
    (concat-string-list
      (let ((sm (rdata-start-marker template))
            (em (rdata-end-marker template))
            (callback (rdata-replacement-callback template))
            (include-markers (rdata-include-markers template))
            )
           ;(write-line (format nil "Replacing: ~A to ~A" sm em))
           (loop  with index = 0
                  do (setq next-index (get-next-substr-index str :start-marker sm
                               :end-marker em
                               :start-index si
                               :end-index ei
                               :next-index index
                               :include-markers include-markers))
                  if (null next-index)
                    collect (progn ;(write-line (format nil "~A -> ~A" index (length str)))
                              (subseq str index)
                             )
                  while next-index
                  collect (subseq str index si)
                  collect (funcall callback (subseq str si ei))
                  collect (subseq str ei next-index)
                  do (progn ;(write-line (format nil "~A -> [~A ~A] -> ~A" index si ei next-index))
                        (setq index next-index)
                      )
           )
      )
    )
)

(defun apply-replacement-templates (str templates)
  (cond ((null templates) str)
        (t (apply-replacement-templates
            (parse-replace str (car templates))
            (cdr templates)
           )
        )
  )
)

(defun apply-parse-file (file-name-in file-name-out templates)
  (write-file file-name-out
    (apply-replacement-templates (file-string file-name-in) templates)
  )
)

(defun replace-all (string part replacement &key (test #'char=))
  "Returns a new string in which all the occurences of the part
is replaced with replacement."
  (with-output-to-string (out)
    (loop with part-length = (length part)
       for old-pos = 0 then (+ pos part-length)
       for pos = (search part string
                         :start2 old-pos
                         :test test)
       do (write-string string out
                        :start old-pos
                        :end (or pos (length string)))
       when pos do (write-string replacement out)
       while pos)))

(setq proj-data-list nil)
(defun add-projdata (&rest args)
  (let ((rd (apply #'make-rdata args)))
    (setq proj-data-list (cons rd proj-data-list))
  )
)

(setq sln-data-list nil)
(defun add-slndata (&rest args)
  (let ((rd (apply #'make-rdata args)))
    (setq sln-data-list (cons rd sln-data-list))
  )
)

(setq tp1 (make-rdata :start-marker "<data[^>]*>"
                     :end-marker "</data>"
                     :replacement-callback (lambda (str) "_123_")
                     :include-markers T))

(defun back-to-forward-slashes (str)
  (replace-all str "\\" "/")
)

(setq lambda-path-to-sln-dir (lambda (str) (regexp-replace (back-to-forward-slashes str)
                                                           (back-to-forward-slashes build-dir)
                                                           "$(SolutionDir)")))
(setq lambda-remove (lambda (str) ""))

(add-projdata :start-marker "<AdditionalIncludeDirectories>"
              :end-marker "</AdditionalIncludeDirectories>"
              :replacement-callback (lambda (str) (replace-all str "\\$$(SolutionDir)" "$(SolutionDir)")))
(add-projdata :start-marker "<OutDir[^>]*>"
              :end-marker "</OutDir>"
              :replacement-callback lambda-path-to-sln-dir)
(add-projdata :start-marker "<ImportLibrary[^>]*>"
              :end-marker "</ImportLibrary>"
              :replacement-callback lambda-path-to-sln-dir)
(add-projdata :start-marker "<ProgramDataBaseFile[^>]*>"
              :end-marker "</ProgramDataBaseFile>"
              :replacement-callback lambda-path-to-sln-dir)
(add-projdata :start-marker "[^<>]*<ItemGroup[^>]*>[^<]*<CustomBuild[^>]*CMakeLists[.]txt[^>]*>"
              :end-marker "</CustomBuild>[^<]*</ItemGroup>"
              :replacement-callback lambda-remove
              :include-markers T)
(add-projdata :start-marker "[^<>]*<ItemGroup[^>]*>[^<]*<ProjectReference[^>]*ZERO_CHECK[.]vcxproj[^>]*>"
              :end-marker "</ProjectReference>[^<]*</ItemGroup>"
              :replacement-callback lambda-remove
              :include-markers T)
(add-projdata :start-marker "CMAKE_INTDIR="
              :end-marker ";"
              :replacement-callback lambda-remove
              :include-markers T)

(add-slndata  :start-marker "Project([^,]*ALL_BUILD"
              :end-marker "EndProject"
              :replacement-callback lambda-remove
              :include-markers T)
(add-slndata  :start-marker "Project([^,]*ZERO_CHECK"
              :end-marker "EndProject"
              :replacement-callback lambda-remove
              :include-markers T)

(defun mapc-directory-tree (fn directory)
  (dolist (entry (cl-fad:list-directory directory))
    (when (cl-fad:directory-pathname-p entry)
      (mapc-directory-tree fn entry))
    (funcall fn entry)))

(defun get-temp-filename (fn)
  (format nil "~A.tmp" fn))

(defun process-file (filename-in file-extension)
  (let ((filename-out (get-temp-filename filename-in))
        (data-list (cond ((equal file-extension solution-file-extension) sln-data-list)
                         (t proj-data-list)))
       )
    (apply-parse-file filename-in filename-out data-list)
    (delete-file filename-in)
    (rename-file filename-out filename-in)
  )
)

(defun process (dir)
  (setq build-dir dir)
  (let ((target-directory (if (null dir)
                              (ext:cd)
                              dir)))
    (write-line (format nil "Base directory: ~A~%" target-directory))
    (mapc-directory-tree (lambda (x)
                           (let ((file-extension (pathname-type x)))
                             (when (or (equal file-extension project-file-extension)
                                       (equal file-extension solution-file-extension))
                               (write-line (format nil "~A"
                                                   (enough-namestring x target-directory)
                                                   ))
                               (process-file (namestring x) file-extension))
                           )
                         )
                         target-directory)))

(defun _ () (load "parse-replace.cl" :verbose nil))

(when (>= (length *args*) 1)
  (let ((path (car *args*)))
    (process path)
  )
)


BUGFIX: Fixing data access patterns in OpenCL backend for identity

/*******************************************************
 * Copyright (c) 2014, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

__kernel
void identity_kernel(__global T *oData, KParam oInfo, dim_type groups_x, dim_type groups_y)
{

    unsigned idz = get_group_id(0) / groups_x;
    unsigned idw = get_group_id(1) / groups_y;

    unsigned groupId_x = get_group_id(0) - idz * groups_x;
    unsigned groupId_y = get_group_id(1) - idw * groups_y;

    unsigned idx = get_local_id(0) + groupId_x * get_local_size(0);
    unsigned idy = get_local_id(1) + groupId_y * get_local_size(1);

    if(idx >= oInfo.dims[0] ||
       idy >= oInfo.dims[1] ||
       idz >= oInfo.dims[2] ||
       idw >= oInfo.dims[3])
        return;

    __global T *ptr = oData + idw * oInfo.strides[2] + idz * oInfo.strides[3];
    T val = (idx == idy) ? ONE : ZERO;
    ptr[idx + idy * oInfo.strides[1]] = val;
}

/*******************************************************
 * Copyright (c) 2014, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

__kernel
void identity_kernel(__global T *oData, KParam oInfo, dim_type groups_x, dim_type groups_y)
{
    unsigned idz = get_group_id(0) / groups_x;
    unsigned idw = get_group_id(1) / groups_y;

    unsigned groupId_x = get_group_id(0) - idz * groups_x;
    unsigned groupId_y = get_group_id(1) - idw * groups_y;

    unsigned idx = get_local_id(0) + groupId_x * get_num_groups(0);
    unsigned idy = get_local_id(1) + groupId_y * get_num_groups(1);

    if(idx >= oInfo.dims[0] ||
       idy >= oInfo.dims[1] ||
       idz >= oInfo.dims[2] ||
       idw >= oInfo.dims[3])
        return;

    __global T *ptr = oData + idw * oInfo.strides[2] + idz * oInfo.strides[3];
    T val = (idx == idy) ? ONE : ZERO;
    ptr[idx + idy * oInfo.strides[1]] = val;
}