fixed casts for CL1.2

fixed casts for CL1.2

/*
 * Copyright (c) 2016 AMD Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and/or associated documentation files (the
 * "Materials"), to deal in the Materials without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Materials, and to
 * permit persons to whom the Materials are 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 Materials.
 *
 * THE MATERIALS ARE 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
 * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
 */

#define _FLOAT					float
#define _FLOAT2					float2
#define _FLOAT4					float4
#define _FLOAT8					float8

#ifndef FLT_MAX
#define FLT_MAX         3.402823466e+38F        /* max value */
#endif

#define MLO_HW_WAVE_ID_SETTING 1
extern __attribute__((const)) uint __hsail_get_dynwave_id(void);

#define MLO_IN_LCL_WIDTH (MLO_IN_STRIDE + 2 * MLO_FILTER_PAD0)

inline int getWaveId()
{
	int wave_id = 0;
#if MLO_HW_WAVE_ID_SETTING
	wave_id = __hsail_get_dynwave_id();
	wave_id &= MLO_N_WAVES_MASK;
#else
	wave_id = (get_local_id(0) >> MLO_LG2_WAVE_SZ);
#endif
	return(wave_id);
}

inline int getWaveLocalId()
{
	int lcl_wave_id = get_local_id(0) - ((get_local_id(0) >> MLO_LG2_WAVE_SZ) << MLO_LG2_WAVE_SZ);;
	return(lcl_wave_id);
}

inline int getWaveLocalIds(int * lcl_wave_id1, int * lcl_wave_id0)
{
	int lcl_wave_id = getWaveLocalId();
	*lcl_wave_id1 = (lcl_wave_id >> MLO_LG2_WAVE_SZ0);
	*lcl_wave_id0 = lcl_wave_id - ((*lcl_wave_id1) << MLO_LG2_WAVE_SZ0);
	return(lcl_wave_id);
}

inline int getLocalIds(int * lcl_id1, int * lcl_id0)
{
    int lcl_wave_id = getWaveLocalId();
	int wave_id = getWaveId();
	int lcl_id = (wave_id << MLO_LG2_WAVE_SZ) + lcl_wave_id; //get_local_id(0);
	*lcl_id1 = (lcl_id >> MLO_LG2ALU_EXTENT_X);
	*lcl_id0 = lcl_id - ((*lcl_id1) << MLO_LG2ALU_EXTENT_X);
	return(lcl_id);
}

/*********************************************************************************************************

**********************************************************************************************************/

__attribute__((reqd_work_group_size(MLO_GRP_SZ0, MLO_GRP_SZ1, MLO_GRP_SZ2)))
__kernel void MLOpenCvD3x3_WSR0(
	const __global _FLOAT * in_ptr,
	const __global _FLOAT * restrict wei_ptr,
#if MLO_CONV_BIAS
	const __global _FLOAT * bias,
#endif
	__global _FLOAT *out_ptr,
	_FLOAT alpha // LRU fusion
	)
{
// all other allocation should be before this one since we may exceed lcl mem range
	__local _FLOAT in_lcl[MLO_IN_LCL_WIDTH * (MLO_OUT_EXTENT1 + 2 * MLO_FILTER_PAD1)];

	__private _FLOAT pvt_accum[MLO_N_LCL_OUT_MAPS * MLO_OUT_TILE1*MLO_OUT_TILE0];

	int grp_input_id = get_group_id(0); // tile id inside the input map
	int grp_gbl_offset = (grp_input_id == 0) ? 0 : (grp_input_id*MLO_OUT_EXTENT1 - 1)*MLO_IN_STRIDE;
	int gpr_lcl_off = (grp_input_id != 0) ? MLO_FILTER_PAD0 : MLO_IN_LCL_WIDTH*MLO_FILTER_PAD1 + MLO_FILTER_PAD0;

	int lcl_id1;
	int lcl_id0;
	int lcl_id = getLocalIds(&lcl_id1, &lcl_id0);
	grp_gbl_offset += lcl_id1*MLO_IN_STRIDE;
	gpr_lcl_off += lcl_id1*MLO_IN_LCL_WIDTH;

	int n_vert_reads = (MLO_OUT_EXTENT1 + 2 * MLO_FILTER_PAD1);
	n_vert_reads -= (grp_input_id == 0 || grp_input_id == get_num_groups(0) - 1) ? 1 : 0;

// output
	int o_block = get_group_id(1);

	int weave_id = getWaveId();
	//assumption is MLO_N_OUTPUTS is multiple of MLO_N_LCL_OUT_MAPS*MLO_N_WAVES
	int o_base = o_block*MLO_N_LCL_OUT_MAPS*MLO_N_WAVES + weave_id * MLO_N_LCL_OUT_MAPS;

	__private int weights_base_offsets[MLO_N_LCL_OUT_MAPS];

	for (uint i = 0; i < MLO_N_LCL_OUT_MAPS; ++i)
	{
		weights_base_offsets[i] = (o_base + i)*MLO_WEI_BATCH_STRIDE;
	}

// batch
	int b_block = get_group_id(2);
	// batch
	int b_base = b_block * MLO_N_LCL_BATCHS;

	grp_gbl_offset += b_base * MLO_IN_BATCH_STRIDE;

// padding
// ATT: padding == 1
	for (uint i = lcl_id; i < MLO_IN_LCL_WIDTH; i+=MLO_GRP_SZ)
	{
		in_lcl[i] = 0;
		in_lcl[i + MLO_IN_LCL_WIDTH * (MLO_OUT_EXTENT1 + MLO_FILTER_PAD1)] = 0;
	}
	for (uint i = lcl_id; i < (MLO_OUT_EXTENT1 + 2 * MLO_FILTER_PAD1); i += MLO_GRP_SZ)
	{
		in_lcl[i*MLO_IN_LCL_WIDTH] = 0;
		in_lcl[(i+1)*MLO_IN_LCL_WIDTH - 1] = 0;
	}

	// local read and relative output adresses and offsets
	int lcl_wave_id1;
	int lcl_wave_id0;
	getWaveLocalIds(&lcl_wave_id1, &lcl_wave_id0);
	int lcl_off1 = lcl_wave_id1 * MLO_OUT_TILE1;
	int lcl_off0 = lcl_wave_id0 * MLO_OUT_TILE0;
	int lcl_read_off = lcl_off1 * MLO_IN_LCL_WIDTH + lcl_off0;

	for (uint i = 0; i < MLO_N_LCL_OUT_MAPS * MLO_OUT_TILE1*MLO_OUT_TILE0; ++i)
	{
		pvt_accum[i] = 0;
	}

	barrier(CLK_LOCAL_MEM_FENCE);

#if 0

	if (get_group_id(0) == 0 && lcl_id0 == 1)
	{
		printf("k:s: %d %d %d %d %d\n",
			getWaveId(),
			lcl_id,
			lcl_id1,
			grp_gbl_offset,
			gpr_lcl_off
			);
	}
#endif

	// outer loop over all input maps
	for (uint c = 0, wei_offset = 0;
		c < MLO_N_INPUTS;
		++c,
		grp_gbl_offset += MLO_IN_CHANNEL_STRIDE, wei_offset += MLO_WEI_CHANNEL_STRIDE)
	{
// not to overwrite
		barrier(CLK_LOCAL_MEM_FENCE);

		int gbl_scan_off = grp_gbl_offset;
		int lcl_scan_off = gpr_lcl_off;
		for (uint j = lcl_id1; j < n_vert_reads; j += MLO_ALU_EXTENT_Y, gbl_scan_off += MLO_IN_STRIDE*MLO_ALU_EXTENT_Y, lcl_scan_off += MLO_IN_LCL_WIDTH*MLO_ALU_EXTENT_Y)
		{
//			*(MLO_READ_TYPE*)&in_lcl[lcl_scan_off + lcl_id0*MLO_READ_UNIT] = *(MLO_READ_TYPE*)&in_ptr[gbl_scan_off + lcl_id0*MLO_READ_UNIT];
			in_lcl[lcl_scan_off + lcl_id0*MLO_READ_UNIT] = in_ptr[gbl_scan_off + lcl_id0*MLO_READ_UNIT];
			in_lcl[lcl_scan_off + lcl_id0*MLO_READ_UNIT + 1] = in_ptr[gbl_scan_off + lcl_id0*MLO_READ_UNIT + 1];
			in_lcl[lcl_scan_off + lcl_id0*MLO_READ_UNIT + 2] = in_ptr[gbl_scan_off + lcl_id0*MLO_READ_UNIT + 2];
			in_lcl[lcl_scan_off + lcl_id0*MLO_READ_UNIT + 3] = in_ptr[gbl_scan_off + lcl_id0*MLO_READ_UNIT + 3];
#if 0

			if (get_group_id(0) == 0 && j < 3 && lcl_id0 == 0)
			{
				printf("k:i: %d %d %d  %f %f %f\n",
					n_vert_reads,
					lcl_scan_off + lcl_id0*MLO_READ_UNIT,
					gbl_scan_off + lcl_id0*MLO_READ_UNIT,
					in_lcl[lcl_scan_off - 1], in_lcl[lcl_scan_off + lcl_id0*MLO_READ_UNIT], in_lcl[lcl_scan_off + lcl_id0*MLO_READ_UNIT + 1]
					);
			}
#endif
		}
// finish reading
		barrier(CLK_LOCAL_MEM_FENCE);

// read weights
		__private _FLOAT pvt_wei_stage[MLO_N_LCL_OUT_MAPS * MLO_FILTER_SIZE0 * MLO_FILTER_SIZE0];
		for (uint j = 0; j < MLO_N_LCL_OUT_MAPS; ++j)
		{
			for (uint i = 0; i < MLO_WEI_CHANNEL_STRIDE; ++i)
			{
				int wei_gbl_off = weights_base_offsets[j] + wei_offset;
				pvt_wei_stage[j*MLO_WEI_CHANNEL_STRIDE + i] = wei_ptr[wei_gbl_off + i];
			}
		}

// read data
		__private _FLOAT pvt_in_stage[(MLO_OUT_TILE1 + 2 * MLO_FILTER_PAD1) * (MLO_OUT_TILE0 + 2 * MLO_FILTER_PAD0)];

		int lcl_read_scan_off = lcl_read_off;
		for (uint j = 0; j < (MLO_OUT_TILE1 + 2 * MLO_FILTER_PAD1); ++j, lcl_read_scan_off += MLO_IN_LCL_WIDTH)
		{
			for (uint i = 0; i < (MLO_OUT_TILE0 + 2 * MLO_FILTER_PAD0); ++i)
			{
				pvt_in_stage[j * (MLO_OUT_TILE0 + 2 * MLO_FILTER_PAD0) + i]
					= in_lcl[lcl_read_scan_off + i];

			}

		}

		// actual conv

		for (uint oc = 0; oc < MLO_N_LCL_OUT_MAPS; ++oc)
		{
			for (uint j = 0; j < MLO_OUT_TILE1; ++j)
			{
				for (uint i = 0; i < MLO_OUT_TILE0; ++i)
				{
					for (uint k = 0; k < MLO_FILTER_SIZE1; ++k)
					{
						for (uint l = 0; l < MLO_FILTER_SIZE0; ++l)
						{

							pvt_accum[(oc * MLO_OUT_TILE1 + j) * MLO_OUT_TILE0 + i]
								+= pvt_in_stage[(j + k) * (MLO_OUT_TILE0 + 2 * MLO_FILTER_PAD0) + i + l]
									* pvt_wei_stage[oc * MLO_WEI_CHANNEL_STRIDE + k * MLO_FILTER_SIZE0 + l];
#if 0

							if (get_group_id(0) == 0 && lcl_id == 0 && j == 0 && i == 0)
							{
								printf("k:c: %d %d %d  %f %f %f\n",
									oc,
									k,
									l,
									pvt_accum[(oc * MLO_OUT_TILE1 + j) * MLO_OUT_TILE0 + i],
									pvt_in_stage[(j + k) * (MLO_OUT_TILE0 + 2 * MLO_FILTER_PAD0) + i + l],
									pvt_wei_stage[oc * MLO_WEI_CHANNEL_STRIDE + k * MLO_FILTER_SIZE0 + l]
								);
							}
#endif

						} //for (int l = 0; l < MLO_FILTER_SIZE0; ++l)
					}

				} // for (int i = 0; i < MLO_OUT_TILE0; ++i)

			} // for (int j = 0; j < MLO_OUT_TILE1; ++j)

		}
	}

	// send it out
	// TODO: batch loop

	int grp_x = 0;
	int grp_y = grp_input_id*MLO_OUT_EXTENT1;
	int out_off = b_base*MLO_OUT_BATCH_STRIDE + o_base* MLO_OUT_CHANNEL_STRIDE + (grp_y + lcl_off1)*MLO_OUT_STRIDE + grp_x + lcl_off0;

//	int ib = 0;

//	out_off += ib*MLO_OUT_BATCH_STRIDE;

	int out_off1 = out_off;
	for (uint oc = 0; oc < MLO_N_LCL_OUT_MAPS
#if MLO_OUTPUTS_ALIGNED ==0
//		&& o + oc < MLO_N_OUTPUTS
#endif
		;
	++oc, out_off1 += MLO_OUT_CHANNEL_STRIDE)
	{
		int out_off2 = out_off1;
		for (uint j = 0; j < MLO_OUT_TILE1; ++j, out_off2 += MLO_OUT_STRIDE)
		{
			for (uint i = 0; i < MLO_OUT_TILE0 / MLO_READ_UNIT; ++i)
			{

				// WIDTH/HEIGHT
				*(__global MLO_READ_TYPE*)&out_ptr[out_off2 + i*MLO_READ_UNIT]
					= *(MLO_READ_TYPE*)&pvt_accum[/*ib*MLO_N_LCL_OUT_MAPS * MLO_OUT_TILE_SZ + */(oc * MLO_OUT_TILE1 + j) * MLO_OUT_TILE0 + i*MLO_READ_UNIT];
			}
		}
	}

}

/*********************************************************************************************************
reads weight sequentially, requiers rearanging kernel
**********************************************************************************************************/

__attribute__((reqd_work_group_size(MLO_GRP_SZ0, MLO_GRP_SZ1, MLO_GRP_SZ2)))
__kernel void MLOpenCvD3x3_WSR1(
	const __global _FLOAT * in_ptr,
	const __global _FLOAT * restrict wei_ptr,
#if MLO_CONV_BIAS
	const __global _FLOAT * bias,
#endif
	__global _FLOAT *out_ptr,
	_FLOAT alpha // LRU fusion
	)
{
// all other allocation should be before this one since we may exceed lcl mem range
	__local _FLOAT in_lcl[MLO_IN_LCL_WIDTH * (MLO_OUT_EXTENT1 + 2 * MLO_FILTER_PAD1)];

	__private _FLOAT pvt_accum[MLO_N_LCL_OUT_MAPS * MLO_OUT_TILE1*MLO_OUT_TILE0];

	int grp_input_id = get_group_id(0); // tile id inside the input map
	int grp_gbl_offset = (grp_input_id == 0) ? 0 : (grp_input_id*MLO_OUT_EXTENT1 - 1)*MLO_IN_STRIDE;
	int gpr_lcl_off = (grp_input_id != 0) ? MLO_FILTER_PAD0 : MLO_IN_LCL_WIDTH*MLO_FILTER_PAD1 + MLO_FILTER_PAD0;

	int lcl_id1;
	int lcl_id0;
	int lcl_id = getLocalIds(&lcl_id1, &lcl_id0);
	grp_gbl_offset += lcl_id1*MLO_IN_STRIDE;
	gpr_lcl_off += lcl_id1*MLO_IN_LCL_WIDTH;

	int n_vert_reads = (MLO_OUT_EXTENT1 + 2 * MLO_FILTER_PAD1);
	n_vert_reads -= (grp_input_id == 0 || grp_input_id == get_num_groups(0) - 1) ? 1 : 0;

// output
	int o_block = get_group_id(1);

	int weave_id = getWaveId();
	//assumption is MLO_N_OUTPUTS is multiple of MLO_N_LCL_OUT_MAPS*MLO_N_WAVES
	int o_base = o_block*MLO_N_LCL_OUT_MAPS*MLO_N_WAVES + weave_id * MLO_N_LCL_OUT_MAPS;

	__private int weights_base_offsets;

	weights_base_offsets = o_block*MLO_N_LCL_OUT_MAPS*MLO_N_WAVES*MLO_WEI_BATCH_STRIDE + weave_id*MLO_WEI_CHANNEL_STRIDE;

// batch
	int b_block = get_group_id(2);
	// batch
	int b_base = b_block * MLO_N_LCL_BATCHS;

	grp_gbl_offset += b_base * MLO_IN_BATCH_STRIDE;

// padding
// ATT: padding == 1
	for (int i = lcl_id; i < MLO_IN_LCL_WIDTH; i+=MLO_GRP_SZ)
	{
		in_lcl[i] = 0;
		in_lcl[i + MLO_IN_LCL_WIDTH * (MLO_OUT_EXTENT1 + MLO_FILTER_PAD1)] = 0;
	}
	for (int i = lcl_id; i < (MLO_OUT_EXTENT1 + 2 * MLO_FILTER_PAD1); i += MLO_GRP_SZ)
	{
		in_lcl[i*MLO_IN_LCL_WIDTH] = 0;
		in_lcl[(i+1)*MLO_IN_LCL_WIDTH - 1] = 0;
	}

	// local read and relative output adresses and offsets
	int lcl_wave_id1;
	int lcl_wave_id0;
	getWaveLocalIds(&lcl_wave_id1, &lcl_wave_id0);
	int lcl_off1 = lcl_wave_id1 * MLO_OUT_TILE1;
	int lcl_off0 = lcl_wave_id0 * MLO_OUT_TILE0;
	int lcl_read_off = lcl_off1 * MLO_IN_LCL_WIDTH + lcl_off0;

	for (int i = 0; i < MLO_N_LCL_OUT_MAPS * MLO_OUT_TILE1*MLO_OUT_TILE0; ++i)
	{
		pvt_accum[i] = 0;
	}

	barrier(CLK_LOCAL_MEM_FENCE);

#if 0

	if (get_group_id(0) == 0 && lcl_id0 == 1)
	{
		printf("k:s: %d %d %d %d %d\n",
			getWaveId(),
			lcl_id,
			lcl_id1,
			grp_gbl_offset,
			gpr_lcl_off
			);
	}
#endif

	// outer loop over all input maps
	for (int c = 0;
		c < MLO_N_INPUTS;
		++c,
		grp_gbl_offset += MLO_IN_CHANNEL_STRIDE, weights_base_offsets += MLO_N_LCL_OUT_MAPS*MLO_N_WAVES*MLO_WEI_CHANNEL_STRIDE)
	{
// not to overwrite
		barrier(CLK_LOCAL_MEM_FENCE);

		int gbl_scan_off = grp_gbl_offset;
		int lcl_scan_off = gpr_lcl_off;
		for (int j = lcl_id1; j < n_vert_reads; j += MLO_ALU_EXTENT_Y, gbl_scan_off += MLO_IN_STRIDE*MLO_ALU_EXTENT_Y, lcl_scan_off += MLO_IN_LCL_WIDTH*MLO_ALU_EXTENT_Y)
		{
//			*(MLO_READ_TYPE*)&in_lcl[lcl_scan_off + lcl_id0*MLO_READ_UNIT] = *(MLO_READ_TYPE*)&in_ptr[gbl_scan_off + lcl_id0*MLO_READ_UNIT];
			in_lcl[lcl_scan_off + lcl_id0*MLO_READ_UNIT] = in_ptr[gbl_scan_off + lcl_id0*MLO_READ_UNIT];
			in_lcl[lcl_scan_off + lcl_id0*MLO_READ_UNIT + 1] = in_ptr[gbl_scan_off + lcl_id0*MLO_READ_UNIT + 1];
			in_lcl[lcl_scan_off + lcl_id0*MLO_READ_UNIT + 2] = in_ptr[gbl_scan_off + lcl_id0*MLO_READ_UNIT + 2];
			in_lcl[lcl_scan_off + lcl_id0*MLO_READ_UNIT + 3] = in_ptr[gbl_scan_off + lcl_id0*MLO_READ_UNIT + 3];
#if 0

			if (get_group_id(0) == 0 && j < 3 && lcl_id0 == 0)
			{
				printf("k:i: %d %d %d  %f %f %f\n",
					n_vert_reads,
					lcl_scan_off + lcl_id0*MLO_READ_UNIT,
					gbl_scan_off + lcl_id0*MLO_READ_UNIT,
					in_lcl[lcl_scan_off - 1], in_lcl[lcl_scan_off + lcl_id0*MLO_READ_UNIT], in_lcl[lcl_scan_off + lcl_id0*MLO_READ_UNIT + 1]
					);
			}
#endif
		}
// finish reading
		barrier(CLK_LOCAL_MEM_FENCE);

// read weights
		__private _FLOAT pvt_wei_stage[MLO_N_LCL_OUT_MAPS * MLO_FILTER_SIZE0 * MLO_FILTER_SIZE0];
		int wei_gbl_off  = weights_base_offsets;
		for (int j = 0; j < MLO_N_LCL_OUT_MAPS; ++j, wei_gbl_off+= MLO_N_WAVES*MLO_WEI_CHANNEL_STRIDE)
		{
			for (int i = 0; i < MLO_WEI_CHANNEL_STRIDE; ++i)
			{
				pvt_wei_stage[j*MLO_WEI_CHANNEL_STRIDE + i] = wei_ptr[wei_gbl_off + i];
			}
		}

// read data
		__private _FLOAT pvt_in_stage[(MLO_OUT_TILE1 + 2 * MLO_FILTER_PAD1) * (MLO_OUT_TILE0 + 2 * MLO_FILTER_PAD0)];

		int lcl_read_scan_off = lcl_read_off;
		for (int j = 0; j < (MLO_OUT_TILE1 + 2 * MLO_FILTER_PAD1); ++j, lcl_read_scan_off += MLO_IN_LCL_WIDTH)
		{
			for (int i = 0; i < (MLO_OUT_TILE0 + 2 * MLO_FILTER_PAD0); ++i)
			{
				pvt_in_stage[j * (MLO_OUT_TILE0 + 2 * MLO_FILTER_PAD0) + i]
					= in_lcl[lcl_read_scan_off + i];

			}

		}

		// actual conv

		for (int oc = 0; oc < MLO_N_LCL_OUT_MAPS; ++oc)
		{
			for (int j = 0; j < MLO_OUT_TILE1; ++j)
			{
				for (int i = 0; i < MLO_OUT_TILE0; ++i)
				{
					for (int k = 0; k < MLO_FILTER_SIZE1; ++k)
					{
						for (int l = 0; l < MLO_FILTER_SIZE0; ++l)
						{

							pvt_accum[(oc * MLO_OUT_TILE1 + j) * MLO_OUT_TILE0 + i]
								+= pvt_in_stage[(j + k) * (MLO_OUT_TILE0 + 2 * MLO_FILTER_PAD0) + i + l]
									* pvt_wei_stage[oc * MLO_WEI_CHANNEL_STRIDE + k * MLO_FILTER_SIZE0 + l];
#if 0

							if (get_group_id(0) == 0 && lcl_id == 0 && j == 0 && i == 0)
							{
								printf("k:c: %d %d %d  %f %f %f\n",
									oc,
									k,
									l,
									pvt_accum[(oc * MLO_OUT_TILE1 + j) * MLO_OUT_TILE0 + i],
									pvt_in_stage[(j + k) * (MLO_OUT_TILE0 + 2 * MLO_FILTER_PAD0) + i + l],
									pvt_wei_stage[oc * MLO_WEI_CHANNEL_STRIDE + k * MLO_FILTER_SIZE0 + l]
								);
							}
#endif

						} //for (int l = 0; l < MLO_FILTER_SIZE0; ++l)
					}

				} // for (int i = 0; i < MLO_OUT_TILE0; ++i)

			} // for (int j = 0; j < MLO_OUT_TILE1; ++j)

		}
	}

	// send it out
	// TODO: batch loop

	int grp_x = 0;
	int grp_y = grp_input_id*MLO_OUT_EXTENT1;
	int out_off = b_base*MLO_OUT_BATCH_STRIDE + o_base* MLO_OUT_CHANNEL_STRIDE + (grp_y + lcl_off1)*MLO_OUT_STRIDE + grp_x + lcl_off0;

//	int ib = 0;

//	out_off += ib*MLO_OUT_BATCH_STRIDE;

	int out_off1 = out_off;
	for (int oc = 0; oc < MLO_N_LCL_OUT_MAPS
#if MLO_OUTPUTS_ALIGNED ==0
//		&& o + oc < MLO_N_OUTPUTS
#endif
		;
	++oc, out_off1 += MLO_OUT_CHANNEL_STRIDE)
	{
		int out_off2 = out_off1;
		for (int j = 0; j < MLO_OUT_TILE1; ++j, out_off2 += MLO_OUT_STRIDE)
		{
			for (int i = 0; i < MLO_OUT_TILE0 / MLO_READ_UNIT; ++i)
			{

				// WIDTH/HEIGHT
				*(__global MLO_READ_TYPE*)&out_ptr[out_off2 + i*MLO_READ_UNIT]
					= *(MLO_READ_TYPE*)&pvt_accum[/*ib*MLO_N_LCL_OUT_MAPS * MLO_OUT_TILE_SZ + */(oc * MLO_OUT_TILE1 + j) * MLO_OUT_TILE0 + i*MLO_READ_UNIT];
			}
		}
	}

}

/*
 * Copyright (c) 2016 AMD Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and/or associated documentation files (the
 * "Materials"), to deal in the Materials without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Materials, and to
 * permit persons to whom the Materials are 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 Materials.
 *
 * THE MATERIALS ARE 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
 * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
 */

#define _FLOAT					float
#define _FLOAT2					float2
#define _FLOAT4					float4
#define _FLOAT8					float8

#ifndef FLT_MAX
#define FLT_MAX         3.402823466e+38F        /* max value */
#endif

#define MLO_HW_WAVE_ID_SETTING 1
extern __attribute__((const)) uint __hsail_get_dynwave_id(void);

#define MLO_IN_LCL_WIDTH (MLO_IN_STRIDE + 2 * MLO_FILTER_PAD0)

inline int getWaveId()
{
	int wave_id = 0;
#if MLO_HW_WAVE_ID_SETTING
	wave_id = __hsail_get_dynwave_id();
	wave_id &= MLO_N_WAVES_MASK;
#else
	wave_id = (get_local_id(0) >> MLO_LG2_WAVE_SZ);
#endif
	return(wave_id);
}

inline int getWaveLocalId()
{
	int lcl_wave_id = get_local_id(0) - ((get_local_id(0) >> MLO_LG2_WAVE_SZ) << MLO_LG2_WAVE_SZ);;
	return(lcl_wave_id);
}

inline int getWaveLocalIds(int * lcl_wave_id1, int * lcl_wave_id0)
{
	int lcl_wave_id = getWaveLocalId();
	*lcl_wave_id1 = (lcl_wave_id >> MLO_LG2_WAVE_SZ0);
	*lcl_wave_id0 = lcl_wave_id - ((*lcl_wave_id1) << MLO_LG2_WAVE_SZ0);
	return(lcl_wave_id);
}

inline int getLocalIds(int * lcl_id1, int * lcl_id0)
{
    int lcl_wave_id = getWaveLocalId();
	int wave_id = getWaveId();
	int lcl_id = (wave_id << MLO_LG2_WAVE_SZ) + lcl_wave_id; //get_local_id(0);
	*lcl_id1 = (lcl_id >> MLO_LG2ALU_EXTENT_X);
	*lcl_id0 = lcl_id - ((*lcl_id1) << MLO_LG2ALU_EXTENT_X);
	return(lcl_id);
}

/*********************************************************************************************************

**********************************************************************************************************/

__attribute__((reqd_work_group_size(MLO_GRP_SZ0, MLO_GRP_SZ1, MLO_GRP_SZ2)))
__kernel void MLOpenCvD3x3_WSR0(
	const __global _FLOAT * in_ptr,
	const __global _FLOAT * restrict wei_ptr,
#if MLO_CONV_BIAS
	const __global _FLOAT * bias,
#endif
	__global _FLOAT *out_ptr,
	_FLOAT alpha // LRU fusion
	)
{
// all other allocation should be before this one since we may exceed lcl mem range
	__local _FLOAT in_lcl[MLO_IN_LCL_WIDTH * (MLO_OUT_EXTENT1 + 2 * MLO_FILTER_PAD1)];

	__private _FLOAT pvt_accum[MLO_N_LCL_OUT_MAPS * MLO_OUT_TILE1*MLO_OUT_TILE0];

	int grp_input_id = get_group_id(0); // tile id inside the input map
	int grp_gbl_offset = (grp_input_id == 0) ? 0 : (grp_input_id*MLO_OUT_EXTENT1 - 1)*MLO_IN_STRIDE;
	int gpr_lcl_off = (grp_input_id != 0) ? MLO_FILTER_PAD0 : MLO_IN_LCL_WIDTH*MLO_FILTER_PAD1 + MLO_FILTER_PAD0;

	int lcl_id1;
	int lcl_id0;
	int lcl_id = getLocalIds(&lcl_id1, &lcl_id0);
	grp_gbl_offset += lcl_id1*MLO_IN_STRIDE;
	gpr_lcl_off += lcl_id1*MLO_IN_LCL_WIDTH;

	int n_vert_reads = (MLO_OUT_EXTENT1 + 2 * MLO_FILTER_PAD1);
	n_vert_reads -= (grp_input_id == 0 || grp_input_id == get_num_groups(0) - 1) ? 1 : 0;

// output
	int o_block = get_group_id(1);

	int weave_id = getWaveId();
	//assumption is MLO_N_OUTPUTS is multiple of MLO_N_LCL_OUT_MAPS*MLO_N_WAVES
	int o_base = o_block*MLO_N_LCL_OUT_MAPS*MLO_N_WAVES + weave_id * MLO_N_LCL_OUT_MAPS;

	__private int weights_base_offsets[MLO_N_LCL_OUT_MAPS];

	for (uint i = 0; i < MLO_N_LCL_OUT_MAPS; ++i)
	{
		weights_base_offsets[i] = (o_base + i)*MLO_WEI_BATCH_STRIDE;
	}

// batch
	int b_block = get_group_id(2);
	// batch
	int b_base = b_block * MLO_N_LCL_BATCHS;

	grp_gbl_offset += b_base * MLO_IN_BATCH_STRIDE;

// padding
// ATT: padding == 1
	for (uint i = lcl_id; i < MLO_IN_LCL_WIDTH; i+=MLO_GRP_SZ)
	{
		in_lcl[i] = 0;
		in_lcl[i + MLO_IN_LCL_WIDTH * (MLO_OUT_EXTENT1 + MLO_FILTER_PAD1)] = 0;
	}
	for (uint i = lcl_id; i < (MLO_OUT_EXTENT1 + 2 * MLO_FILTER_PAD1); i += MLO_GRP_SZ)
	{
		in_lcl[i*MLO_IN_LCL_WIDTH] = 0;
		in_lcl[(i+1)*MLO_IN_LCL_WIDTH - 1] = 0;
	}

	// local read and relative output adresses and offsets
	int lcl_wave_id1;
	int lcl_wave_id0;
	getWaveLocalIds(&lcl_wave_id1, &lcl_wave_id0);
	int lcl_off1 = lcl_wave_id1 * MLO_OUT_TILE1;
	int lcl_off0 = lcl_wave_id0 * MLO_OUT_TILE0;
	int lcl_read_off = lcl_off1 * MLO_IN_LCL_WIDTH + lcl_off0;

	for (uint i = 0; i < MLO_N_LCL_OUT_MAPS * MLO_OUT_TILE1*MLO_OUT_TILE0; ++i)
	{
		pvt_accum[i] = 0;
	}

	barrier(CLK_LOCAL_MEM_FENCE);

#if 0

	if (get_group_id(0) == 0 && lcl_id0 == 1)
	{
		printf("k:s: %d %d %d %d %d\n",
			getWaveId(),
			lcl_id,
			lcl_id1,
			grp_gbl_offset,
			gpr_lcl_off
			);
	}
#endif

	// outer loop over all input maps
	for (uint c = 0, wei_offset = 0;
		c < MLO_N_INPUTS;
		++c,
		grp_gbl_offset += MLO_IN_CHANNEL_STRIDE, wei_offset += MLO_WEI_CHANNEL_STRIDE)
	{
// not to overwrite
		barrier(CLK_LOCAL_MEM_FENCE);

		int gbl_scan_off = grp_gbl_offset;
		int lcl_scan_off = gpr_lcl_off;
		for (uint j = lcl_id1; j < n_vert_reads; j += MLO_ALU_EXTENT_Y, gbl_scan_off += MLO_IN_STRIDE*MLO_ALU_EXTENT_Y, lcl_scan_off += MLO_IN_LCL_WIDTH*MLO_ALU_EXTENT_Y)
		{
//			*(MLO_READ_TYPE*)&in_lcl[lcl_scan_off + lcl_id0*MLO_READ_UNIT] = *(MLO_READ_TYPE*)&in_ptr[gbl_scan_off + lcl_id0*MLO_READ_UNIT];
			in_lcl[lcl_scan_off + lcl_id0*MLO_READ_UNIT] = in_ptr[gbl_scan_off + lcl_id0*MLO_READ_UNIT];
			in_lcl[lcl_scan_off + lcl_id0*MLO_READ_UNIT + 1] = in_ptr[gbl_scan_off + lcl_id0*MLO_READ_UNIT + 1];
			in_lcl[lcl_scan_off + lcl_id0*MLO_READ_UNIT + 2] = in_ptr[gbl_scan_off + lcl_id0*MLO_READ_UNIT + 2];
			in_lcl[lcl_scan_off + lcl_id0*MLO_READ_UNIT + 3] = in_ptr[gbl_scan_off + lcl_id0*MLO_READ_UNIT + 3];
#if 0

			if (get_group_id(0) == 0 && j < 3 && lcl_id0 == 0)
			{
				printf("k:i: %d %d %d  %f %f %f\n",
					n_vert_reads,
					lcl_scan_off + lcl_id0*MLO_READ_UNIT,
					gbl_scan_off + lcl_id0*MLO_READ_UNIT,
					in_lcl[lcl_scan_off - 1], in_lcl[lcl_scan_off + lcl_id0*MLO_READ_UNIT], in_lcl[lcl_scan_off + lcl_id0*MLO_READ_UNIT + 1]
					);
			}
#endif
		}
// finish reading
		barrier(CLK_LOCAL_MEM_FENCE);

// read weights
		__private _FLOAT pvt_wei_stage[MLO_N_LCL_OUT_MAPS * MLO_FILTER_SIZE0 * MLO_FILTER_SIZE0];
		for (uint j = 0; j < MLO_N_LCL_OUT_MAPS; ++j)
		{
			for (uint i = 0; i < MLO_WEI_CHANNEL_STRIDE; ++i)
			{
				int wei_gbl_off = weights_base_offsets[j] + wei_offset;
				pvt_wei_stage[j*MLO_WEI_CHANNEL_STRIDE + i] = wei_ptr[wei_gbl_off + i];
			}
		}

// read data
		__private _FLOAT pvt_in_stage[(MLO_OUT_TILE1 + 2 * MLO_FILTER_PAD1) * (MLO_OUT_TILE0 + 2 * MLO_FILTER_PAD0)];

		int lcl_read_scan_off = lcl_read_off;
		for (uint j = 0; j < (MLO_OUT_TILE1 + 2 * MLO_FILTER_PAD1); ++j, lcl_read_scan_off += MLO_IN_LCL_WIDTH)
		{
			for (uint i = 0; i < (MLO_OUT_TILE0 + 2 * MLO_FILTER_PAD0); ++i)
			{
				pvt_in_stage[j * (MLO_OUT_TILE0 + 2 * MLO_FILTER_PAD0) + i]
					= in_lcl[lcl_read_scan_off + i];

			}

		}

		// actual conv

		for (uint oc = 0; oc < MLO_N_LCL_OUT_MAPS; ++oc)
		{
			for (uint j = 0; j < MLO_OUT_TILE1; ++j)
			{
				for (uint i = 0; i < MLO_OUT_TILE0; ++i)
				{
					for (uint k = 0; k < MLO_FILTER_SIZE1; ++k)
					{
						for (uint l = 0; l < MLO_FILTER_SIZE0; ++l)
						{

							pvt_accum[(oc * MLO_OUT_TILE1 + j) * MLO_OUT_TILE0 + i]
								+= pvt_in_stage[(j + k) * (MLO_OUT_TILE0 + 2 * MLO_FILTER_PAD0) + i + l]
									* pvt_wei_stage[oc * MLO_WEI_CHANNEL_STRIDE + k * MLO_FILTER_SIZE0 + l];
#if 0

							if (get_group_id(0) == 0 && lcl_id == 0 && j == 0 && i == 0)
							{
								printf("k:c: %d %d %d  %f %f %f\n",
									oc,
									k,
									l,
									pvt_accum[(oc * MLO_OUT_TILE1 + j) * MLO_OUT_TILE0 + i],
									pvt_in_stage[(j + k) * (MLO_OUT_TILE0 + 2 * MLO_FILTER_PAD0) + i + l],
									pvt_wei_stage[oc * MLO_WEI_CHANNEL_STRIDE + k * MLO_FILTER_SIZE0 + l]
								);
							}
#endif

						} //for (int l = 0; l < MLO_FILTER_SIZE0; ++l)
					}

				} // for (int i = 0; i < MLO_OUT_TILE0; ++i)

			} // for (int j = 0; j < MLO_OUT_TILE1; ++j)

		}
	}

	// send it out
	// TODO: batch loop

	int grp_x = 0;
	int grp_y = grp_input_id*MLO_OUT_EXTENT1;
	int out_off = b_base*MLO_OUT_BATCH_STRIDE + o_base* MLO_OUT_CHANNEL_STRIDE + (grp_y + lcl_off1)*MLO_OUT_STRIDE + grp_x + lcl_off0;

//	int ib = 0;

//	out_off += ib*MLO_OUT_BATCH_STRIDE;

	int out_off1 = out_off;
	for (uint oc = 0; oc < MLO_N_LCL_OUT_MAPS
#if MLO_OUTPUTS_ALIGNED ==0
//		&& o + oc < MLO_N_OUTPUTS
#endif
		;
	++oc, out_off1 += MLO_OUT_CHANNEL_STRIDE)
	{
		int out_off2 = out_off1;
		for (uint j = 0; j < MLO_OUT_TILE1; ++j, out_off2 += MLO_OUT_STRIDE)
		{
			for (uint i = 0; i < MLO_OUT_TILE0 / MLO_READ_UNIT; ++i)
			{

				// WIDTH/HEIGHT
				*(MLO_READ_TYPE*)&out_ptr[out_off2 + i*MLO_READ_UNIT]
					= *(MLO_READ_TYPE*)&pvt_accum[/*ib*MLO_N_LCL_OUT_MAPS * MLO_OUT_TILE_SZ + */(oc * MLO_OUT_TILE1 + j) * MLO_OUT_TILE0 + i*MLO_READ_UNIT];
			}
		}
	}

}

/*********************************************************************************************************
reads weight sequentially, requiers rearanging kernel
**********************************************************************************************************/

__attribute__((reqd_work_group_size(MLO_GRP_SZ0, MLO_GRP_SZ1, MLO_GRP_SZ2)))
__kernel void MLOpenCvD3x3_WSR1(
	const __global _FLOAT * in_ptr,
	const __global _FLOAT * restrict wei_ptr,
#if MLO_CONV_BIAS
	const __global _FLOAT * bias,
#endif
	__global _FLOAT *out_ptr,
	_FLOAT alpha // LRU fusion
	)
{
// all other allocation should be before this one since we may exceed lcl mem range
	__local _FLOAT in_lcl[MLO_IN_LCL_WIDTH * (MLO_OUT_EXTENT1 + 2 * MLO_FILTER_PAD1)];

	__private _FLOAT pvt_accum[MLO_N_LCL_OUT_MAPS * MLO_OUT_TILE1*MLO_OUT_TILE0];

	int grp_input_id = get_group_id(0); // tile id inside the input map
	int grp_gbl_offset = (grp_input_id == 0) ? 0 : (grp_input_id*MLO_OUT_EXTENT1 - 1)*MLO_IN_STRIDE;
	int gpr_lcl_off = (grp_input_id != 0) ? MLO_FILTER_PAD0 : MLO_IN_LCL_WIDTH*MLO_FILTER_PAD1 + MLO_FILTER_PAD0;

	int lcl_id1;
	int lcl_id0;
	int lcl_id = getLocalIds(&lcl_id1, &lcl_id0);
	grp_gbl_offset += lcl_id1*MLO_IN_STRIDE;
	gpr_lcl_off += lcl_id1*MLO_IN_LCL_WIDTH;

	int n_vert_reads = (MLO_OUT_EXTENT1 + 2 * MLO_FILTER_PAD1);
	n_vert_reads -= (grp_input_id == 0 || grp_input_id == get_num_groups(0) - 1) ? 1 : 0;

// output
	int o_block = get_group_id(1);

	int weave_id = getWaveId();
	//assumption is MLO_N_OUTPUTS is multiple of MLO_N_LCL_OUT_MAPS*MLO_N_WAVES
	int o_base = o_block*MLO_N_LCL_OUT_MAPS*MLO_N_WAVES + weave_id * MLO_N_LCL_OUT_MAPS;

	__private int weights_base_offsets;

	weights_base_offsets = o_block*MLO_N_LCL_OUT_MAPS*MLO_N_WAVES*MLO_WEI_BATCH_STRIDE + weave_id*MLO_WEI_CHANNEL_STRIDE;

// batch
	int b_block = get_group_id(2);
	// batch
	int b_base = b_block * MLO_N_LCL_BATCHS;

	grp_gbl_offset += b_base * MLO_IN_BATCH_STRIDE;

// padding
// ATT: padding == 1
	for (int i = lcl_id; i < MLO_IN_LCL_WIDTH; i+=MLO_GRP_SZ)
	{
		in_lcl[i] = 0;
		in_lcl[i + MLO_IN_LCL_WIDTH * (MLO_OUT_EXTENT1 + MLO_FILTER_PAD1)] = 0;
	}
	for (int i = lcl_id; i < (MLO_OUT_EXTENT1 + 2 * MLO_FILTER_PAD1); i += MLO_GRP_SZ)
	{
		in_lcl[i*MLO_IN_LCL_WIDTH] = 0;
		in_lcl[(i+1)*MLO_IN_LCL_WIDTH - 1] = 0;
	}

	// local read and relative output adresses and offsets
	int lcl_wave_id1;
	int lcl_wave_id0;
	getWaveLocalIds(&lcl_wave_id1, &lcl_wave_id0);
	int lcl_off1 = lcl_wave_id1 * MLO_OUT_TILE1;
	int lcl_off0 = lcl_wave_id0 * MLO_OUT_TILE0;
	int lcl_read_off = lcl_off1 * MLO_IN_LCL_WIDTH + lcl_off0;

	for (int i = 0; i < MLO_N_LCL_OUT_MAPS * MLO_OUT_TILE1*MLO_OUT_TILE0; ++i)
	{
		pvt_accum[i] = 0;
	}

	barrier(CLK_LOCAL_MEM_FENCE);

#if 0

	if (get_group_id(0) == 0 && lcl_id0 == 1)
	{
		printf("k:s: %d %d %d %d %d\n",
			getWaveId(),
			lcl_id,
			lcl_id1,
			grp_gbl_offset,
			gpr_lcl_off
			);
	}
#endif

	// outer loop over all input maps
	for (int c = 0;
		c < MLO_N_INPUTS;
		++c,
		grp_gbl_offset += MLO_IN_CHANNEL_STRIDE, weights_base_offsets += MLO_N_LCL_OUT_MAPS*MLO_N_WAVES*MLO_WEI_CHANNEL_STRIDE)
	{
// not to overwrite
		barrier(CLK_LOCAL_MEM_FENCE);

		int gbl_scan_off = grp_gbl_offset;
		int lcl_scan_off = gpr_lcl_off;
		for (int j = lcl_id1; j < n_vert_reads; j += MLO_ALU_EXTENT_Y, gbl_scan_off += MLO_IN_STRIDE*MLO_ALU_EXTENT_Y, lcl_scan_off += MLO_IN_LCL_WIDTH*MLO_ALU_EXTENT_Y)
		{
//			*(MLO_READ_TYPE*)&in_lcl[lcl_scan_off + lcl_id0*MLO_READ_UNIT] = *(MLO_READ_TYPE*)&in_ptr[gbl_scan_off + lcl_id0*MLO_READ_UNIT];
			in_lcl[lcl_scan_off + lcl_id0*MLO_READ_UNIT] = in_ptr[gbl_scan_off + lcl_id0*MLO_READ_UNIT];
			in_lcl[lcl_scan_off + lcl_id0*MLO_READ_UNIT + 1] = in_ptr[gbl_scan_off + lcl_id0*MLO_READ_UNIT + 1];
			in_lcl[lcl_scan_off + lcl_id0*MLO_READ_UNIT + 2] = in_ptr[gbl_scan_off + lcl_id0*MLO_READ_UNIT + 2];
			in_lcl[lcl_scan_off + lcl_id0*MLO_READ_UNIT + 3] = in_ptr[gbl_scan_off + lcl_id0*MLO_READ_UNIT + 3];
#if 0

			if (get_group_id(0) == 0 && j < 3 && lcl_id0 == 0)
			{
				printf("k:i: %d %d %d  %f %f %f\n",
					n_vert_reads,
					lcl_scan_off + lcl_id0*MLO_READ_UNIT,
					gbl_scan_off + lcl_id0*MLO_READ_UNIT,
					in_lcl[lcl_scan_off - 1], in_lcl[lcl_scan_off + lcl_id0*MLO_READ_UNIT], in_lcl[lcl_scan_off + lcl_id0*MLO_READ_UNIT + 1]
					);
			}
#endif
		}
// finish reading
		barrier(CLK_LOCAL_MEM_FENCE);

// read weights
		__private _FLOAT pvt_wei_stage[MLO_N_LCL_OUT_MAPS * MLO_FILTER_SIZE0 * MLO_FILTER_SIZE0];
		int wei_gbl_off  = weights_base_offsets;
		for (int j = 0; j < MLO_N_LCL_OUT_MAPS; ++j, wei_gbl_off+= MLO_N_WAVES*MLO_WEI_CHANNEL_STRIDE)
		{
			for (int i = 0; i < MLO_WEI_CHANNEL_STRIDE; ++i)
			{
				pvt_wei_stage[j*MLO_WEI_CHANNEL_STRIDE + i] = wei_ptr[wei_gbl_off + i];
			}
		}

// read data
		__private _FLOAT pvt_in_stage[(MLO_OUT_TILE1 + 2 * MLO_FILTER_PAD1) * (MLO_OUT_TILE0 + 2 * MLO_FILTER_PAD0)];

		int lcl_read_scan_off = lcl_read_off;
		for (int j = 0; j < (MLO_OUT_TILE1 + 2 * MLO_FILTER_PAD1); ++j, lcl_read_scan_off += MLO_IN_LCL_WIDTH)
		{
			for (int i = 0; i < (MLO_OUT_TILE0 + 2 * MLO_FILTER_PAD0); ++i)
			{
				pvt_in_stage[j * (MLO_OUT_TILE0 + 2 * MLO_FILTER_PAD0) + i]
					= in_lcl[lcl_read_scan_off + i];

			}

		}

		// actual conv

		for (int oc = 0; oc < MLO_N_LCL_OUT_MAPS; ++oc)
		{
			for (int j = 0; j < MLO_OUT_TILE1; ++j)
			{
				for (int i = 0; i < MLO_OUT_TILE0; ++i)
				{
					for (int k = 0; k < MLO_FILTER_SIZE1; ++k)
					{
						for (int l = 0; l < MLO_FILTER_SIZE0; ++l)
						{

							pvt_accum[(oc * MLO_OUT_TILE1 + j) * MLO_OUT_TILE0 + i]
								+= pvt_in_stage[(j + k) * (MLO_OUT_TILE0 + 2 * MLO_FILTER_PAD0) + i + l]
									* pvt_wei_stage[oc * MLO_WEI_CHANNEL_STRIDE + k * MLO_FILTER_SIZE0 + l];
#if 0

							if (get_group_id(0) == 0 && lcl_id == 0 && j == 0 && i == 0)
							{
								printf("k:c: %d %d %d  %f %f %f\n",
									oc,
									k,
									l,
									pvt_accum[(oc * MLO_OUT_TILE1 + j) * MLO_OUT_TILE0 + i],
									pvt_in_stage[(j + k) * (MLO_OUT_TILE0 + 2 * MLO_FILTER_PAD0) + i + l],
									pvt_wei_stage[oc * MLO_WEI_CHANNEL_STRIDE + k * MLO_FILTER_SIZE0 + l]
								);
							}
#endif

						} //for (int l = 0; l < MLO_FILTER_SIZE0; ++l)
					}

				} // for (int i = 0; i < MLO_OUT_TILE0; ++i)

			} // for (int j = 0; j < MLO_OUT_TILE1; ++j)

		}
	}

	// send it out
	// TODO: batch loop

	int grp_x = 0;
	int grp_y = grp_input_id*MLO_OUT_EXTENT1;
	int out_off = b_base*MLO_OUT_BATCH_STRIDE + o_base* MLO_OUT_CHANNEL_STRIDE + (grp_y + lcl_off1)*MLO_OUT_STRIDE + grp_x + lcl_off0;

//	int ib = 0;

//	out_off += ib*MLO_OUT_BATCH_STRIDE;

	int out_off1 = out_off;
	for (int oc = 0; oc < MLO_N_LCL_OUT_MAPS
#if MLO_OUTPUTS_ALIGNED ==0
//		&& o + oc < MLO_N_OUTPUTS
#endif
		;
	++oc, out_off1 += MLO_OUT_CHANNEL_STRIDE)
	{
		int out_off2 = out_off1;
		for (int j = 0; j < MLO_OUT_TILE1; ++j, out_off2 += MLO_OUT_STRIDE)
		{
			for (int i = 0; i < MLO_OUT_TILE0 / MLO_READ_UNIT; ++i)
			{

				// WIDTH/HEIGHT
				*(MLO_READ_TYPE*)&out_ptr[out_off2 + i*MLO_READ_UNIT]
					= *(MLO_READ_TYPE*)&pvt_accum[/*ib*MLO_N_LCL_OUT_MAPS * MLO_OUT_TILE_SZ + */(oc * MLO_OUT_TILE1 + j) * MLO_OUT_TILE0 + i*MLO_READ_UNIT];
			}
		}
	}

}


updated undulator.cl

updated undulator.cl

//__author__ = "Konstantin Klementiev, Roman Chernikov"
//__date__ = "03 Jul 2016"

#ifdef cl_khr_fp64
#if __OPENCL_VERSION__<120
#pragma OPENCL EXTENSION cl_khr_fp64: enable
#endif
#endif
// "float" will be automatically replaced by "double" if precision is float64
__constant float QUAR = 0.25;
__constant float HALF = 0.5;
__constant float TWO = 2.;
__constant float SIX = 6.;
__constant bool isHiPrecision = sizeof(TWO) == 8;
//__constant bool isHiPrecision = false;
__constant float2 zero2 = (float2)(0, 0);

__constant float PI2 = (float)6.283185307179586476925286766559;
//__constant float PI = (float)3.1415926535897932384626433832795;

__constant float E2W = 1.51926751475e15;
__constant float C = 2.99792458e11;
__constant float SIE0 = 1.602176565e-19;
__constant float SIM0 = 9.10938291e-31;

__kernel void undulator(const float alpha,
                        const float Kx,
                        const float Ky,
                        const float phase,
                        const int jend,
                        __global float* gamma,
                        __global float* wu,
                        __global float* w,
                        __global float* ww1,
                        __global float* ddphi,
                        __global float* ddpsi,
                        __global float* tg,
                        __global float* ag,
                        __global float2* Is_gl,
                        __global float2* Ip_gl)
{
    unsigned int ii = get_global_id(0);
    int j;

    float3 beta, betaP, n, nnb;
    float2 eucos;
    float ucos, sinucos, cosucos, sintg, costg, sintgph, costgph, krel;
    float2 Is = zero2;
    float2 Ip = zero2;
    float wwu2 = w[ii] / (wu[ii] * wu[ii]);
    float revg = 1. / gamma[ii];
    float revg2 = revg * revg;
    float wug = wu[ii] * revg;

    n.x = ddphi[ii];
    n.y = ddpsi[ii];
//    n.z = sqrt(1. - n.x*n.x - n.y*n.y);
    n.z = 1. - HALF*(n.x*n.x + n.y*n.y);

    for (j=0; j<jend; j++) {
        sintg = sincos(tg[j], &costg);
        sintgph = sincos(tg[j] + phase, &costgph);

        beta.x = Ky * revg * costg;
        beta.y = -Kx * revg * costgph;
//        beta.z = sqrt(1. - revg2 - beta.x*beta.x - beta.y*beta.y);
        beta.z = 1. - HALF*(revg2 + beta.x*beta.x + beta.y*beta.y);

        betaP.x = -Ky * wug * sintg;
        betaP.y = Kx * wug * sintgph;
        betaP.z = 0.;

        ucos = ww1[ii] * tg[j] + wwu2 * dot((n - QUAR*beta), betaP);

        betaP.z = -(betaP.x*beta.x + betaP.y*beta.y) / beta.z;
        sinucos = sincos(ucos, &cosucos);
        eucos.x = cosucos;
        eucos.y = sinucos;

        if (isHiPrecision) {
            krel = 1. - dot(n, beta);
            nnb = cross(n, cross((n - beta), betaP))/(krel*krel); }
        else
            nnb = (n - beta) * w[ii];
//        nnb = (n-beta)*dot(n, betaP)/(krel*krel) - betaP/krel;

        Is += (ag[j] * nnb.x) * eucos;
        Ip += (ag[j] * nnb.y) * eucos; }
    mem_fence(CLK_LOCAL_MEM_FENCE);
    Is_gl[ii] = Is;
    Ip_gl[ii] = Ip;
    }

__kernel void undulator_taper(const float alpha,
                              const float Kx,
                              const float Ky,
                              const float phase,
                              const int jend,
                              __global float* gamma,
                              __global float* wu,
                              __global float* w,
                              __global float* ww1,
                              __global float* ddphi,
                              __global float* ddpsi,
                              __global float* tg,
                              __global float* ag,
                              __global float2* Is_gl,
                              __global float2* Ip_gl)
{
    unsigned int ii = get_global_id(0);
    int j;

    float2 eucos;
    float3 n, nnb, beta, betaP;
    float ucos, sinucos, cosucos, sintg, sin2tg, sin2tgph, costg, sintgph, costgph, krel;
    float2 Is = zero2;
    float2 Ip = zero2;
    float Kx2 = Kx * Kx;
    float Ky2 = Ky * Ky;
    float alphaS = alpha * C / wu[ii] / E2W;
    float revg = 1. / gamma[ii];
    float revg2 = revg * revg;
    float wug = wu[ii] * revg;
    float wgwu = w[ii] * revg / wu[ii];
    n.x = ddphi[ii];
    n.y = ddpsi[ii];
    //n.z = sqrt(1. - n.x*n.x - n.y*n.y);
    n.z = 1 - HALF*(n.x*n.x + n.y*n.y);

    for (j=0; j<jend; j++) {
        sintg = sincos(tg[j], &costg);
        sintgph = sincos(tg[j] + phase, &costgph);
        sin2tg = TWO * sintg * costg; //sin(2*tg[j]);
        sin2tgph = TWO * sintgph * costgph; //sin(2*(tg[j] + phase));
        ucos = ww1[ii] * tg[j] + wgwu *
            (-Ky * n.x * (sintg + alphaS * (1. - costg - tg[j] * sintg)) +
             Kx * n.y * sintgph + 0.125 * revg *
                   (Ky2 * (sin2tg - TWO * alphaS *
                    (tg[j] * tg[j] + costg * costg + tg[j] * sin2tg)) +
                    Kx2 * sin2tgph));

        sinucos = sincos(ucos, &cosucos);
        eucos.x = cosucos;
        eucos.y = sinucos;

        beta.x = Ky * revg * costg * (1 - alphaS * tg[j]);
        beta.y = -Kx * revg * costgph;
        beta.z = 1 - HALF*(revg2 + beta.x*beta.x + beta.y*beta.y);

        betaP.x = -Ky * wug * (alphaS*costg + (1 - alphaS*tg[j])*sintg);
        betaP.y = Kx * wug * sintgph;
        betaP.z = wu[ii] * revg2 *
            (Kx2*sintgph*costgph + Ky2*(1 - alphaS*tg[j])*
             (alphaS * costg * costg + (1 - alphaS*tg[j])*sintg*costg));

        if (isHiPrecision) {
            krel = 1. - dot(n, beta);
            nnb = cross(n, cross((n - beta), betaP))/(krel*krel); }
        else
            nnb = (n - beta) * w[ii];

        Is += (ag[j] * nnb.x) * eucos;
        Ip += (ag[j] * nnb.y) * eucos; }

    mem_fence(CLK_LOCAL_MEM_FENCE);
    Is_gl[ii] = Is;
    Ip_gl[ii] = Ip;
}

__kernel void undulator_nf(const float R0,
                            const float L0,
                            const float Kx,
                            const float Ky,
                            const float phase,
                            const int jend,
                            __global float* gamma,
                            __global float* wu,
                            __global float* w,
                            __global float* ww1,
                            __global float* ddphi,
                            __global float* ddpsi,
                            __global float* tg,
                            __global float* ag,
                            __global float2* Is_gl,
                            __global float2* Ip_gl)
{
    unsigned int ii = get_global_id(0);
    int j;

    float2 eucos;
    float ucos, sinucos, cosucos, sintg, costg, sintgph, costgph, krel;
    float2 Is = zero2;
    float2 Ip = zero2;
    float3 r, r0, n, nnb, beta, betaP;
    float Kx2 = Kx * Kx;
    float Ky2 = Ky * Ky;
    float revg = 1. / gamma[ii];
    float revg2 = revg * revg;
    float wug = wu[ii] * revg;
    float wwu = w[ii] / wu[ii];
    float betam = 1 - (1 + HALF * Kx2 + HALF * Ky2) * HALF * revg2;
    float wR0 = R0 * PI2 / L0;

    r0.x = wR0 * tan(ddphi[ii]);
    r0.y = wR0 * tan(ddpsi[ii]);
    r0.z = wR0 * cos(sqrt(ddphi[ii]*ddphi[ii] + ddpsi[ii]*ddpsi[ii]));

    n.x = ddphi[ii];
    n.y = ddpsi[ii];
//    n.z = sqrt(1. - n.x*n.x - n.y*n.y);
    n.z = 1 - HALF*(n.x*n.x + n.y*n.y);

    for (j=0; j<jend; j++) {
        sintg = sincos(tg[j], &costg);
        sintgph = sincos(tg[j] + phase, &costgph);

        r.x = Ky * revg * sintg;
        r.y = -Kx * revg * sintgph;
        r.z = betam * tg[j] - QUAR * revg2 *
        (Ky2 * sintg * costg + Kx2 * sintgph * costgph);

        ucos = wwu * (tg[j] + length(r0 - r));

        sinucos = sincos(ucos, &cosucos);
        eucos.x = cosucos;
        eucos.y = sinucos;

        beta.x = Ky * revg * costg;
        beta.y = -Kx * revg * costgph;
//        beta.z = sqrt(1. - revg2 - beta.x*beta.x - beta.y*beta.y);
        beta.z = 1 - HALF*(revg2 + beta.x*beta.x + beta.y*beta.y);

        betaP.x = -Ky * wug * sintg;
        betaP.y = Kx * wug * sintgph;
        betaP.z = wu[ii] * revg2 * (Ky2*sintg*costg + Kx2*sintgph*costgph);
        //betaP.z = wu[ii]/beta.z*revg2*(Ky2*sintg*costg + Kx2*sintgph*costgph);

        if (isHiPrecision) {
            krel = 1. - dot(n, beta);
            nnb = cross(n, cross((n - beta), betaP))/(krel*krel);
//velocity field
//            nnb = nnb + (n - beta)*(1 - beta*beta)*C / (krel*krel*R0);
            }
        else
            nnb = (n - beta) * w[ii];

        Is += (ag[j] * nnb.x) * eucos;
        Ip += (ag[j] * nnb.y) * eucos; }

    mem_fence(CLK_LOCAL_MEM_FENCE);

    Is_gl[ii] = Is;
    Ip_gl[ii] = Ip;
}

__kernel void undulator_full(const float alpha,
                             const float Kx,
                             const float Ky,
                             const float phase,
                             const int jend,
                             __global float* gamma,
                             __global float* wu,
                             __global float* w,
                             __global float* ww1,
                             __global float* ddphi,
                             __global float* ddpsi,
                             __global float* beta0x,
                             __global float* beta0y,
                             __global float* tg,
                             __global float* ag,
                             __global float2* Is_gl,
                             __global float2* Ip_gl)
{
    unsigned int ii = get_global_id(0);
    int j;

    float2 eucos;
    float2 beta0 = (float2)(beta0x[ii], beta0y[ii]);
    float ucos, sinucos, cosucos, sintg, costg, sintgph, costgph, krel;
    float2 Is = zero2;
    float2 Ip = zero2;
    float3 r, n, nnb, beta, betaP;
    float Kx2 = Kx * Kx;
    float Ky2 = Ky * Ky;
    float revg = 1. / gamma[ii];
    float revg2 = revg * revg;
    float wug = wu[ii] * revg;
    float wwu = w[ii] / wu[ii];
    float betam = 1 - (1 + HALF * Kx2 + HALF * Ky2) * HALF * revg2;

    n.x = ddphi[ii];
    n.y = ddpsi[ii];
    //float betax0 = 0; //1e-6;
    //float betay0 = 0;
    //float rx0 = 2e-2*PI2/L0/wu[ii];
    //float ry0 = 0;
    //n.z = sqrt(1. - n.x*n.x - n.y*n.y);
    n.z = 1 - HALF*(n.x*n.x + n.y*n.y);

    for (j=0; j<jend; j++) {
        sintg = sincos(tg[j], &costg);
        sintgph = sincos(tg[j] + phase, &costgph);

        beta.x = Ky*costg*revg + beta0.x;
        beta.y= -Kx*costgph*revg + beta0.y;
        beta.z = 1. - HALF*(revg2 + beta.x*beta.x + beta.y*beta.y);

        r.x = Ky*sintg*revg + beta0.x*tg[j];
        r.y = -Kx*sintgph*revg + beta0.y*tg[j];
        r.z = -QUAR*revg2*(Kx2*sintgph*costgph + Ky2*sintg*costg) + tg[j]*betam +
            Kx*beta0.y*sintgph*revg - Ky*beta0.x*sintg*revg -
            tg[j]*HALF*(beta0.x*beta0.x + beta0.y*beta0.y);

        //r.x = Ky / gamma[ii] * sintg;
        //r.y = -Kx / gamma[ii] * sintgph;
        //r.z = betam * tg[j] - 0.25 / gamma2 *
        //(Ky2 * sintg * costg + Kx2 * sintgph * costgph);

        ucos = wwu * (tg[j] - dot(n, r));

        sinucos = sincos(ucos, &cosucos);
        eucos.x = cosucos;
        eucos.y = sinucos;

        //beta.x = Ky / gamma[ii] * costg;
        //beta.y = -Kx / gamma[ii] * costgph;
        //beta.z = sqrt(1. - 1./gamma2 - beta.x*beta.x - beta.y*beta.y);
        //beta.z = 1 - 0.5*(1./gamma2 + beta.x*beta.x + beta.y*beta.y);

        betaP.x = -Ky * wug * sintg;
        betaP.y = Kx * wug * sintgph;
        betaP.z = wu[ii] * revg2 * (Ky2*sintg*costg + Kx2*sintgph*costgph);
        //betaP.z = wu[ii]/beta.z/gamma2*(Ky2*sintg*costg + Kx2*sintgph*costgph);

        if (isHiPrecision) {
            krel = 1. - dot(n, beta);
            nnb = cross(n, cross((n - beta), betaP))/(krel*krel); }
        else
            nnb = (n - beta) * w[ii];

        Is += (ag[j] * nnb.x) * eucos;
        Ip += (ag[j] * nnb.y) * eucos; }

    mem_fence(CLK_LOCAL_MEM_FENCE);

    Is_gl[ii] = Is;
    Ip_gl[ii] = Ip;
}

__kernel void undulator_nf_full(const float R0,
                            const float L0,
                            const float Kx,
                            const float Ky,
                            const float phase,
                            const int jend,
                            __global float* gamma,
                            __global float* wu,
                            __global float* w,
                            __global float* ww1,
                            __global float* ddphi,
                            __global float* ddpsi,
                            __global float* beta0x,
                            __global float* beta0y,
                            __global float* tg,
                            __global float* ag,
                            __global float2* Is_gl,
                            __global float2* Ip_gl)
{
    unsigned int ii = get_global_id(0);
    int j;

    float2 eucos;
    float ucos, sinucos, cosucos, sintg, costg, sintgph, costgph, krel;
    float2 beta0 = (float2)(beta0x[ii], beta0y[ii]);
    float2 Is = zero2;
    float2 Ip = zero2;
    float3 r, r0, n, nnb, beta, betaP;
    float Kx2 = Kx * Kx;
    float Ky2 = Ky * Ky;
    float revg = 1. / gamma[ii];
    float revg2 = revg * revg;
    float wug = wu[ii] * revg;
    float wwu = w[ii] / wu[ii];
    float betam = 1 - (1 + HALF * Kx2 + HALF * Ky2) * HALF * revg2;
    float wR0 = R0 * PI2 / L0;

    r0.x = wR0 * tan(ddphi[ii]);
    r0.y = wR0 * tan(ddpsi[ii]);
    r0.z = wR0 * cos(sqrt(ddphi[ii]*ddphi[ii] + ddpsi[ii]*ddpsi[ii]));

    n.x = ddphi[ii];
    n.y = ddpsi[ii];
    //n.z = sqrt(1. - n.x*n.x - n.y*n.y);
    n.z = 1 - HALF*(n.x*n.x + n.y*n.y);

    for (j=0; j<jend; j++) {
        sintg = sincos(tg[j], &costg);
        sintgph = sincos(tg[j] + phase, &costgph);

        //r.x = Ky / gamma[ii] * sintg;
        //r.y = -Kx / gamma[ii] * sintgph;
        //r.z = betam * tg[j] - 0.25 / gamma2 *
        //(Ky2 * sintg * costg + Kx2 * sintgph * costgph);
        beta.x = Ky*costg*revg + beta0.x;
        beta.y= -Kx*costgph*revg + beta0.y;
        beta.z = 1. - HALF*(revg2 + beta.x*beta.x + beta.y*beta.y);

        r.x = Ky*sintg*revg + beta0.x*tg[j];
        r.y = -Kx*sintgph*revg + beta0.y*tg[j];
        r.z = -QUAR*revg2*(Kx2*sintgph*costgph + Ky2*sintg*costg) + tg[j]*betam +
            Kx*beta0.y*sintgph*revg - Ky*beta0.x*sintg*revg -
            tg[j]*HALF*(beta0.x*beta0.x + beta0.y*beta0.y);

        ucos = wwu * (tg[j] + length(r0 - r));

        sinucos = sincos(ucos, &cosucos);
        eucos.x = cosucos;
        eucos.y = sinucos;

        //beta.x = Ky / gamma[ii] * costg;
        //beta.y = -Kx / gamma[ii] * costgph;
        //beta.z = sqrt(1. - 1./gamma2 - beta.x*beta.x - beta.y*beta.y);
        //beta.z = 1 - 0.5*(1./gamma2 + beta.x*beta.x + beta.y*beta.y);

        betaP.x = -Ky * wug * sintg;
        betaP.y = Kx * wug * sintgph;
        betaP.z = wu[ii] * revg2 * (Ky2*sintg*costg + Kx2*sintgph*costgph);
        //betaP.z = wu[ii]/beta.z/gamma2*(Ky2*sintg*costg + Kx2*sintgph*costgph);

        if (isHiPrecision) {
            krel = 1. - dot(n, beta);
            nnb = cross(n, cross((n - beta), betaP))/(krel*krel);
//velocity field
//            nnb = nnb + (n - beta)*(1 - beta*beta)*C / (krel*krel*R0);
            }
        else
            nnb = (n - beta) * w[ii];

        Is += (ag[j] * nnb.x) * eucos;
        Ip += (ag[j] * nnb.y) * eucos; }

    mem_fence(CLK_LOCAL_MEM_FENCE);

    Is_gl[ii] = Is;
    Ip_gl[ii] = Ip;
}

/*
__kernel void undulator_nf_byparts(const float alpha,
                        const float Kx,
                        const float Ky,
                        const float phase,
                        const int jend,
                        const float alim,
                        const float blim,
                        __global float* gamma,
                        __global float* wu,
                        __global float* w,
                        __global float* ww1,
                        __global float* ddphi,
                        __global float* ddpsi,
                        __global float* tg,
                        __global float* ag,
                        __global float2* Is_gl,
                        __global float2* Ip_gl)
{
    unsigned int ii = get_global_id(0);
    int j;

    float2 eg;
    float f, fP, varx;
    float g, gP, gPP, sing, cosg, sintgph, costgph;
    float sintg, costg;
    float sinph, cosph;
    float2 Is = zero2;
    float2 Ip = zero2;
    float gam = gamma[ii];
    float wwu = w[ii] / wu[ii];
    float Kx2 = Kx * Kx;
    float Ky2 = Ky * Ky;
    float Ky2Kx2;
    float gamma2 = gam * gam;
    float phi = ddphi[ii];
    float psi = ddpsi[ii];
    float3 r, rP, rPP, n;
    float betam = 1 - (0.5 + 0.25*Kx2 + 0.25*Ky2) / gamma2;

    //n.x = phi;
    //n.y = psi;
    //n.z = sqrt(1 - phi*phi - psi*psi);

    r0.x = wR0 * tan(ddphi[ii]);
    r0.y = wR0 * tan(ddpsi[ii]);
    r0.z = wR0 * cos(sqrt(ddphi[ii]*ddphi[ii] + ddpsi[ii]*ddpsi[ii]));

    sinph = sincos(phase, &cosph);
    for (j=0; j<jend; j++) {
        varx = tg[j];
        sintg = sincos(varx, &costg);
        sintgph = sintg*cosph + costg*sinph;
        costgph = costg*cosph - sintg*sinph;
        Ky2Kx2 = (Ky2 * sintg*costg + Kx2 * sintgph*costgph) / gamma2;

        r.x = Ky / gam * sintg;
        r.y = -Kx / gam * sintgph;
        r.z = betam * varx - 0.25 * Ky2Kx2;

        g = wwu * (varx + length(r0 - r));

        rP.x = Ky / gam * costg;
        rP.y = -Kx / gam * costgph;
        rP.z = betam - 0.25 / gamma2 *
            (Ky2 * (costg*costg - sintg*sintg) +
             Kx2 * (costgph*costgph - sintgph*sintgph));
        gP = wwu * (1 + dot(n, rP));

        rPP.x = -r.x;
        rPP.y = -r.y;
        rPP.z = Ky2Kx2;
        gPP = -wwu * dot(n, rPP);

        sing = sincos(g, &cosg);
        eg.x = -sing;
        eg.y = cosg;

        f = phi - Ky / gam * costg;
        fP = Ky / gam * sintg;
        Is += ag[j] * (fP - f*gPP/gP)/gP * eg;

        f = psi + Kx / gam * costgph;
        fP = -Kx / gam * sintgph;
        Ip += ag[j] * (fP - f*gPP/gP)/gP * eg;}

    mem_fence(CLK_LOCAL_MEM_FENCE);
    Is_gl[ii] = Is;
    Ip_gl[ii] = Ip;
    }
*/

float2 f_beta(float Bx, float By, float Bz,
               float emcg,
               float2 beta)
{
    return emcg*(float2)(beta.y*Bz - By,
                          Bx - beta.x*Bz);
}

float3 f_traj(float revgamma, float2 beta)
{
    return (float3)(beta.x,
                     beta.y,
                     sqrt(revgamma-beta.x*beta.x-beta.y*beta.y));
}

float2 next_beta_rk(float2 beta, int iZeroStep, int iHalfStep,
                     int iFullStep, float rkStep, float emcg,
                     __global float* Bx,
                     __global float* By,
                     __global float* Bz)
{
    float2 k1Beta, k2Beta, k3Beta, k4Beta;

    k1Beta = rkStep * f_beta(Bx[iZeroStep],
                             By[iZeroStep],
                             Bz[iZeroStep],
                             emcg, beta);
    k2Beta = rkStep * f_beta(Bx[iHalfStep],
                             By[iHalfStep],
                             Bz[iHalfStep],
                             emcg, beta + HALF*k1Beta);
    k3Beta = rkStep * f_beta(Bx[iHalfStep],
                             By[iHalfStep],
                             Bz[iHalfStep],
                             emcg, beta + HALF*k2Beta);
    k4Beta = rkStep * f_beta(Bx[iFullStep],
                             By[iFullStep],
                             Bz[iFullStep],
                             emcg, beta + k3Beta);
    return beta + (k1Beta + TWO*k2Beta + TWO*k3Beta + k4Beta) / SIX;
}

float8 next_traj_rk(float2 beta, float3 traj, int iZeroStep, int iHalfStep,
                     int iFullStep, float rkStep, float emcg,
                     float revgamma,
                     __global float* Bx,
                     __global float* By,
                     __global float* Bz)
{
    float2 k1Beta, k2Beta, k3Beta, k4Beta;
    float3 k1Traj, k2Traj, k3Traj, k4Traj;

    k1Beta = rkStep * f_beta(Bx[iZeroStep],
                             By[iZeroStep],
                             Bz[iZeroStep],
                             emcg, beta);
    k1Traj = rkStep * f_traj(revgamma, beta);

    k2Beta = rkStep * f_beta(Bx[iHalfStep],
                             By[iHalfStep],
                             Bz[iHalfStep],
                             emcg, beta + HALF*k1Beta);
    k2Traj = rkStep * f_traj(revgamma, beta + HALF*k1Beta);

    k3Beta = rkStep * f_beta(Bx[iHalfStep],
                             By[iHalfStep],
                             Bz[iHalfStep],
                             emcg, beta + HALF*k2Beta);
    k3Traj = rkStep * f_traj(revgamma, beta + HALF*k2Beta);

    k4Beta = rkStep * f_beta(Bx[iFullStep],
                             By[iFullStep],
                             Bz[iFullStep],
                             emcg, beta + k3Beta);
    k4Traj = rkStep * f_traj(revgamma, beta + k3Beta);

    return (float8)(beta + (k1Beta + TWO*k2Beta + TWO*k3Beta + k4Beta)/SIX,
                     traj + (k1Traj + TWO*k2Traj + TWO*k3Traj + k4Traj)/SIX,
                     0., 0., 0.);
}

__kernel void undulator_custom(const int jend,
                                const int nwt,
                                const float lUnd,
                                __global float* gamma,
                                __global float* w,
                                __global float* ddphi,
                                __global float* ddpsi,
                                __global float* tg,
                                __global float* ag,
                                __global float* Bx,
                                __global float* By,
                                __global float* Bz,
                                __global float2* Is_gl,
                                __global float2* Ip_gl)
{
    unsigned int ii = get_global_id(0);
    int j, k, jb;
    int iBase, iZeroStep, iHalfStep, iFullStep;

    float ucos, sinucos, cosucos, rkStep, wu_int, betam_int, krel;
    float revg = 1. / gamma[ii];
    float revg2 = revg * revg;
    float emcg = lUnd * SIE0 / SIM0 / C * revg / PI2;
    float revgamma = 1. - revg2;
    float8 betaTraj;
    float2 eucos;
    float2 Is = zero2;
    float2 Ip = zero2;
    float2 beta, beta0;
    float3 traj, n, traj0, betaC, betaP, nnb;

    n.x = ddphi[ii];
    n.y = ddpsi[ii];
    n.z = 1. - HALF*(n.x*n.x + n.y*n.y);

    beta = zero2;
    beta0 = zero2;
    betam_int = 0;

    for (j=1; j<jend; j++) {
        iBase = 2*(j-1)*nwt;
        rkStep = (tg[j] - tg[j-1]) / nwt;
        for (k=0; k<nwt; k++) {
            iZeroStep  = iBase + 2*k;
            iHalfStep = iBase + 2*k + 1;
            iFullStep = iBase + 2*(k + 1);
            beta = next_beta_rk(beta, iZeroStep, iHalfStep, iFullStep,
                                rkStep, emcg, Bx, By, Bz);
            beta0 += beta * rkStep; } }

    mem_fence(CLK_LOCAL_MEM_FENCE);
    beta0 /= -(tg[jend-1] - tg[0]);
    beta = beta0;
    traj = (float3)(0., 0., 0.);
    traj0 = (float3)(0., 0., 0.);

    for (j=1; j<jend; j++) {
        iBase = (j-1)*2*nwt;
        rkStep = (tg[j] - tg[j-1]) / nwt;
        for (k=0; k<nwt; k++) {
            iZeroStep  = iBase + 2*k;
            iHalfStep = iBase + 2*k + 1;
            iFullStep = iBase + 2*(k + 1);
            betaTraj = next_traj_rk(beta, traj,
                                    iZeroStep, iHalfStep, iFullStep,
                                    rkStep, emcg, revgamma, Bx, By, Bz);
            beta = betaTraj.s01;
            traj = betaTraj.s234;
            traj0 += traj * rkStep;
            betam_int += rkStep * sqrt(revgamma - beta.x*beta.x -
                                       beta.y*beta.y); } }

    mem_fence(CLK_LOCAL_MEM_FENCE);
    traj0 /= -(tg[jend-1] - tg[0]);
    beta = beta0;
    traj = traj0;
    betam_int /= (tg[jend-1] - tg[0]);
    wu_int = PI2 * C * betam_int / lUnd / E2W;

    for (j=1; j<jend; j++) {
        iBase = 2*(j-1)*nwt;
        rkStep = (tg[j] - tg[j-1]) / nwt;
        for (k=0; k<nwt; k++) {
            iZeroStep  = iBase + 2*k;
            iHalfStep = iBase + 2*k + 1;
            iFullStep = iBase + 2*(k + 1);
            betaTraj = next_traj_rk(beta, traj,
            iZeroStep, iHalfStep, iFullStep,
            rkStep, emcg, revgamma, Bx, By, Bz);
            beta = betaTraj.s01;
            traj = betaTraj.s234; }

        mem_fence(CLK_LOCAL_MEM_FENCE);
        ucos = w[ii] / wu_int * (tg[j]  - dot(n, traj));
        sinucos = sincos(ucos, &cosucos);
        eucos.x = cosucos;
        eucos.y = sinucos;

        jb = 2*j*nwt;

        betaC.x = beta.x;
        betaC.y = beta.y;
        betaC.z = 1 - HALF*(revg2 + betaC.x*betaC.x + betaC.y*betaC.y);

        betaP.x = wu_int * emcg * (betaC.y*Bz[jb] - By[jb]);
        betaP.y = wu_int * emcg * (-betaC.x*Bz[jb] + Bx[jb]);
        betaP.z = wu_int * emcg * (betaC.x*By[jb] - betaC.y*Bx[jb]);

        if (isHiPrecision) {
            krel = 1. - dot(n, betaC);
            nnb = cross(n, cross((n - betaC), betaP))/(krel*krel); }
        else
            nnb = (n - betaC) * w[ii];

        Is += (ag[j] * nnb.x) * eucos;
        Ip += (ag[j] * nnb.y) * eucos; }

        //Is += ag[j] * (ddphi[ii] - beta.x) * eucos;
        //Ip += ag[j] * (ddpsi[ii] - beta.y) * eucos; }

    mem_fence(CLK_LOCAL_MEM_FENCE);

    Is_gl[ii] = Is;
    Ip_gl[ii] = Ip;
}

__kernel void get_trajectory(const int jend,
                             const int nwt,
                             const float emcg,
                             const float gamma,
                             __global float* tg,
                             __global float* Bx,
                             __global float* By,
                             __global float* Bz,
                             __global float* betax,
                             __global float* betay,
                             __global float* betazav,
                             __global float* trajx,
                             __global float* trajy,
                             __global float* trajz)
{
    int j, k;
    int iBase, iZeroStep, iHalfStep, iFullStep;

    float rkStep;
    float revgamma = 1. - 1./gamma/gamma;
    float betam_int = 0;
    float2 beta, beta0;
    float3 traj, traj0;
    float8 betaTraj;

    beta = zero2;
    beta0 = zero2;

    for (j=1; j<jend; j++) {
        iBase = (j-1)*2*nwt;
        rkStep = (tg[j] - tg[j-1]) / nwt;
        for (k=0; k<nwt; k++) {
            iZeroStep  = iBase + 2*k;
            iHalfStep = iBase + 2*k + 1;
            iFullStep = iBase + 2*(k + 1);
            beta = next_beta_rk(beta, iZeroStep, iHalfStep, iFullStep,
                                rkStep, emcg, Bx, By, Bz);
            beta0 += beta * rkStep; } }
    mem_fence(CLK_LOCAL_MEM_FENCE);
    beta0 /= -(tg[jend-1] - tg[0]);
    beta = beta0;
    traj = (float3)(0., 0., 0.);
    traj0 = (float3)(0., 0., 0.);

    for (j=1; j<jend; j++) {
        iBase = 2*(j-1)*nwt;
        rkStep = (tg[j] - tg[j-1]) / nwt;
        for (k=0; k<nwt; k++) {
            iZeroStep  = iBase + 2*k;
            iHalfStep = iBase + 2*k + 1;
            iFullStep = iBase + 2*(k + 1);
            betaTraj = next_traj_rk(beta, traj,
                                    iZeroStep, iHalfStep, iFullStep,
                                    rkStep, emcg, revgamma, Bx, By, Bz);
            beta = betaTraj.s01;
            traj = betaTraj.s234;
            traj0 += traj * rkStep;
            betam_int += rkStep*sqrt(revgamma - beta.x*beta.x -
                                     beta.y*beta.y); } }
    mem_fence(CLK_LOCAL_MEM_FENCE);
    traj0 /= -(tg[jend-1] - tg[0]);
    beta = beta0;
    traj = traj0;
    betam_int /= tg[jend-1] - tg[0];

    for (j=1; j<jend; j++) {
        iBase = 2*(j-1)*nwt;
        rkStep = (tg[j] - tg[j-1]) / nwt;
        for (k=0; k<nwt; k++) {
            iZeroStep  = iBase + 2*k;
            iHalfStep = iBase + 2*k + 1;
            iFullStep = iBase + 2*(k + 1);
            betaTraj = next_traj_rk(beta, traj,
                                    iZeroStep, iHalfStep, iFullStep,
                                    rkStep, emcg, revgamma, Bx, By, Bz);
            beta = betaTraj.s01;
            traj = betaTraj.s234; }

        betax[j] = beta.x;
        betay[j] = beta.y;
        betazav[j] = betam_int;
        trajx[j] = traj.x;
        trajy[j] = traj.y;
        trajz[j] = traj.z; }

    barrier(CLK_LOCAL_MEM_FENCE);
}

__kernel void undulator_custom_filament(const int jend,
                                        const int nwt,
                                        const float emcg,
                                        const float gamma2,
                                        const float wu,
                                        const float L0,
                                        const float R0,
                                        __global float* w,
                                        __global float* ddphi,
                                        __global float* ddpsi,
                                        __global float* tg,
                                        __global float* ag,
                                        __global float* Bx,
                                        __global float* By,
                                        __global float* Bz,
                                        __global float* betax,
                                        __global float* betay,
                                        __global float* trajx,
                                        __global float* trajy,
                                        __global float* trajz,
                                        __global float2* Is_gl,
                                        __global float2* Ip_gl)
{
    unsigned int ii = get_global_id(0);
    int j, jb;

    float ucos, sinucos, cosucos, wR0, krel;
    float revg2 = 1./gamma2;

    float2 eucos;
    float2 Is = (float2)(0., 0.);
    float2 Ip = (float2)(0., 0.);

    float3 traj, n, r0, betaC, betaP, nnb;

    n.x = ddphi[ii];
    n.y = ddpsi[ii];
    n.z = 1. - HALF*(n.x*n.x + n.y*n.y);

    if (R0>0) {
        wR0 = R0 * PI2 / L0;
        r0.x = wR0 * tan(ddphi[ii]);
        r0.y = wR0 * tan(ddpsi[ii]);
        r0.z = wR0 * cos(sqrt(ddphi[ii]*ddphi[ii] + ddpsi[ii]*ddpsi[ii])); }

    for (j=1; j<jend; j++) {
        traj.x = trajx[j];
        traj.y = trajy[j];
        traj.z = trajz[j];
        if (R0 > 0) {
            ucos = w[ii] / wu * (tg[j] + length(r0 - traj)); }
        else {
            ucos = w[ii] / wu * (tg[j] - dot(n, traj)); }
        sinucos = sincos(ucos, &cosucos);
        eucos.x = cosucos;
        eucos.y = sinucos;

        jb = 2*j*nwt;

        betaC.x = betax[j];
        betaC.y = betay[j];
        betaC.z = 1 - HALF*(revg2 + betaC.x*betaC.x + betaC.y*betaC.y);

        betaP.x = wu * emcg * (betaC.y*Bz[jb] - By[jb]);
        betaP.y = wu * emcg * (-betaC.x*Bz[jb] + Bx[jb]);
        betaP.z = wu * emcg * (betaC.x*By[jb] - betaC.y*Bx[jb]);

        if (isHiPrecision) {
            krel = 1. - dot(n, betaC);
            nnb = cross(n, cross((n - betaC), betaP))/(krel*krel); }
        else
            nnb = (n - betaC) * w[ii];

        Is += (ag[j] * nnb.x) * eucos;
        Ip += (ag[j] * nnb.y) * eucos; }

        //Is += ag[j] * (n.x - betax[j]) * eucos;
        //Ip += ag[j] * (n.y - betay[j]) * eucos; }

    mem_fence(CLK_LOCAL_MEM_FENCE);
    Is_gl[ii] = Is;
    Ip_gl[ii] = Ip;
}


Added signbit(float3) back in

Added signbit(float3) back in

/* OpenCL built-in library: signbit()

   Copyright (c) 2011 Universidad Rey Juan Carlos

   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 NONORDEREDRINGEMENT. IN NO EVENT SHALL THE
   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   THE SOFTWARE.
*/

#define IMPLEMENT_SIGNBIT_BUILTIN_FLOAT  __builtin_signbitf(a)
#define IMPLEMENT_SIGNBIT_BUILTIN_DOUBLE __builtin_signbit(a)
#define IMPLEMENT_SIGNBIT_DIRECT                \
  ({                                            \
    int bits = CHAR_BIT * sizeof(stype);        \
    *(jtype*)&a >> (jtype)(bits-1);             \
  })

#define IMPLEMENT_DIRECT(NAME, VTYPE, STYPE, JTYPE, EXPR)       \
  JTYPE _CL_OVERLOADABLE NAME(VTYPE a)                          \
  {                                                             \
    typedef VTYPE vtype;                                        \
    typedef STYPE stype;                                        \
    typedef JTYPE jtype;                                        \
    return EXPR;                                                \
  }

IMPLEMENT_DIRECT(signbit, float  , float, int  , IMPLEMENT_SIGNBIT_BUILTIN_FLOAT)
IMPLEMENT_DIRECT(signbit, float2 , float, int2 , IMPLEMENT_SIGNBIT_DIRECT)
#if (__clang_major__ > 3) || ((__clang_major__ == 3) && (__clang_minor__ < 3))
// Clang 3.2 and earlier crashes when generating this. Probably due to the
// conversion *(jtype*)&a.
IMPLEMENT_DIRECT(signbit, float3 , float, int3 , IMPLEMENT_SIGNBIT_DIRECT)
#endif
IMPLEMENT_DIRECT(signbit, float4 , float, int4 , IMPLEMENT_SIGNBIT_DIRECT)
IMPLEMENT_DIRECT(signbit, float8 , float, int8 , IMPLEMENT_SIGNBIT_DIRECT)
IMPLEMENT_DIRECT(signbit, float16, float, int16, IMPLEMENT_SIGNBIT_DIRECT)

#ifdef cl_khr_fp64
IMPLEMENT_DIRECT(signbit, double  , double, int   , IMPLEMENT_SIGNBIT_BUILTIN_DOUBLE)
IMPLEMENT_DIRECT(signbit, double2 , double, long2 , IMPLEMENT_SIGNBIT_DIRECT)
IMPLEMENT_DIRECT(signbit, double3 , double, long3 , IMPLEMENT_SIGNBIT_DIRECT)
IMPLEMENT_DIRECT(signbit, double4 , double, long4 , IMPLEMENT_SIGNBIT_DIRECT)
IMPLEMENT_DIRECT(signbit, double8 , double, long8 , IMPLEMENT_SIGNBIT_DIRECT)
IMPLEMENT_DIRECT(signbit, double16, double, long16, IMPLEMENT_SIGNBIT_DIRECT)
#endif

/* OpenCL built-in library: signbit()

   Copyright (c) 2011 Universidad Rey Juan Carlos

   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 NONORDEREDRINGEMENT. IN NO EVENT SHALL THE
   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   THE SOFTWARE.
*/

#define IMPLEMENT_SIGNBIT_BUILTIN_FLOAT  __builtin_signbitf(a)
#define IMPLEMENT_SIGNBIT_BUILTIN_DOUBLE __builtin_signbit(a)
#define IMPLEMENT_SIGNBIT_DIRECT                \
  ({                                            \
    int bits = CHAR_BIT * sizeof(stype);        \
    *(jtype*)&a >> (jtype)(bits-1);             \
  })

#define IMPLEMENT_DIRECT(NAME, VTYPE, STYPE, JTYPE, EXPR)       \
  JTYPE _CL_OVERLOADABLE NAME(VTYPE a)                          \
  {                                                             \
    typedef VTYPE vtype;                                        \
    typedef STYPE stype;                                        \
    typedef JTYPE jtype;                                        \
    return EXPR;                                                \
  }

IMPLEMENT_DIRECT(signbit, float  , float, int  , IMPLEMENT_SIGNBIT_BUILTIN_FLOAT)
IMPLEMENT_DIRECT(signbit, float2 , float, int2 , IMPLEMENT_SIGNBIT_DIRECT)
#if (__clang_major__ > 3) || ((__clang_major__ == 3) && (__clang_minor__ > 3))
// Clang 3.2 and earlier crashes when generating this. Probably due to the
// conversion *(jtype*)&a.
IMPLEMENT_DIRECT(signbit, float3 , float, int3 , IMPLEMENT_SIGNBIT_DIRECT)
#endif
IMPLEMENT_DIRECT(signbit, float4 , float, int4 , IMPLEMENT_SIGNBIT_DIRECT)
IMPLEMENT_DIRECT(signbit, float8 , float, int8 , IMPLEMENT_SIGNBIT_DIRECT)
IMPLEMENT_DIRECT(signbit, float16, float, int16, IMPLEMENT_SIGNBIT_DIRECT)

#ifdef cl_khr_fp64
IMPLEMENT_DIRECT(signbit, double  , double, int   , IMPLEMENT_SIGNBIT_BUILTIN_DOUBLE)
IMPLEMENT_DIRECT(signbit, double2 , double, long2 , IMPLEMENT_SIGNBIT_DIRECT)
IMPLEMENT_DIRECT(signbit, double3 , double, long3 , IMPLEMENT_SIGNBIT_DIRECT)
IMPLEMENT_DIRECT(signbit, double4 , double, long4 , IMPLEMENT_SIGNBIT_DIRECT)
IMPLEMENT_DIRECT(signbit, double8 , double, long8 , IMPLEMENT_SIGNBIT_DIRECT)
IMPLEMENT_DIRECT(signbit, double16, double, long16, IMPLEMENT_SIGNBIT_DIRECT)
#endif


added #ifdef cl_khr_3d_image_writes to min max calculation to avoid error on nvidia devices when compiling

#ifdef TYPE_FLOAT
#define TYPE float4
#define BUFFER_TYPE float
#define READ_IMAGE read_imagef
#define WRITE_IMAGE write_imagef
#define MAX_VALUE FLT_MAX
#define MIN_VALUE FLT_MIN
#elif TYPE_UINT8
#define TYPE uint4
#define BUFFER_TYPE uchar
#define READ_IMAGE read_imageui
#define WRITE_IMAGE write_imageui
#define MAX_VALUE UCHAR_MAX
#define MIN_VALUE 0
#elif TYPE_INT8
#define TYPE int4
#define BUFFER_TYPE char
#define READ_IMAGE read_imagei
#define WRITE_IMAGE write_imagei
#define MAX_VALUE CHAR_MAX
#define MIN_VALUE CHAR_MIN
#elif TYPE_UINT16
#define TYPE uint4
#define BUFFER_TYPE ushort
#define READ_IMAGE read_imageui
#define WRITE_IMAGE write_imageui
#define MAX_VALUE USHRT_MAX
#define MIN_VALUE 0
#else
#define TYPE int4
#define BUFFER_TYPE short
#define READ_IMAGE read_imagei
#define WRITE_IMAGE write_imagei
#define MAX_VALUE SHRT_MAX
#define MIN_VALUE SHRT_MIN
#endif

__constant int2 offset2D[4] = {
                   {0,0},
                   {0,1},
                   {1,0},
                   {1,1}
};

__constant int4 offset3D[8] = {
                   {0,0,0,0},
                   {1,0,0,0},
                   {0,1,0,0},
                   {0,0,1,0},
                   {1,0,1,0},
                   {1,1,1,0},
                   {0,1,1,0},
                   {1,1,0,0}
};

__constant sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_NONE | CLK_FILTER_NEAREST;

__kernel void createFirstMinMaxImage2DLevel(
        __read_only image2d_t image,
        __write_only image2d_t firstLevel
        ) {
    const int2 pos = {get_global_id(0), get_global_id(1)};
    const int2 readPos = pos*2;
    const int2 size = {get_image_width(image), get_image_height(image)};

    TYPE result = {MAX_VALUE, MIN_VALUE,0,0};
    // Check if in bounds
    for(int i = 0; i < 4; i++) {
        TYPE temp;
        temp = READ_IMAGE(image, sampler, select((int2)(0,0), readPos+offset2D[i], readPos+offset2D[i] < size));
        result.x = min(result.x, temp.x);
        result.y = max(result.y, temp.x);
    }

    WRITE_IMAGE(firstLevel, pos, result);
}

__kernel void createMinMaxImage2DLevel(
        __read_only image2d_t readLevel,
        __write_only image2d_t writeLevel
        ) {
    const int2 pos = {get_global_id(0), get_global_id(1)};
    const int2 readPos = pos*2;

    TYPE result = {MAX_VALUE, MIN_VALUE,0,0};
    TYPE temp;
    temp = READ_IMAGE(readLevel, sampler, readPos + offset2D[0]);
    result.x = min(result.x, temp.x);
    result.y = max(result.y, temp.y);
    temp = READ_IMAGE(readLevel, sampler, readPos + offset2D[1]);
    result.x = min(result.x, temp.x);
    result.y = max(result.y, temp.y);
    temp = READ_IMAGE(readLevel, sampler, readPos + offset2D[2]);
    result.x = min(result.x, temp.x);
    result.y = max(result.y, temp.y);
    temp = READ_IMAGE(readLevel, sampler, readPos + offset2D[3]);
    result.x = min(result.x, temp.x);
    result.y = max(result.y, temp.y);

    WRITE_IMAGE(writeLevel, pos, result);
}

#ifdef cl_khr_3d_image_writes
__kernel void createFirstMinMaxImage3DLevel(
        __read_only image3d_t image,
        __write_only image3d_t firstLevel
        ) {
    const int4 pos = {get_global_id(0), get_global_id(1), get_global_id(2), 0};
    const int4 readPos = pos*2;
    const int4 size = {get_image_width(image), get_image_height(image), get_image_depth(image), 1};

    TYPE result = {MAX_VALUE, MIN_VALUE,0,0};
    for(int i = 0; i < 8; i++) {
        TYPE temp;
        temp = READ_IMAGE(image, sampler,  select((int4)(0,0,0,0), readPos+offset3D[i], readPos+offset3D[i] < size));
        result.x = min(result.x, temp.x);
        result.y = max(result.y, temp.x);
    }

    WRITE_IMAGE(firstLevel, pos, result);
}

__kernel void createMinMaxImage3DLevel(
        __read_only image3d_t readLevel,
        __write_only image3d_t writeLevel
        ) {
    const int4 pos = {get_global_id(0), get_global_id(1), get_global_id(2), 0};
    const int4 readPos = pos*2;

    TYPE result = {MAX_VALUE, MIN_VALUE,0,0};
    for(int i = 0; i < 8; i++) {
        TYPE temp;
        temp = READ_IMAGE(readLevel, sampler, readPos + offset3D[i]);
        result.x = min(result.x, temp.x);
        result.y = max(result.y, temp.y);
    }

    WRITE_IMAGE(writeLevel, pos, result);
}
#endif

__kernel void reduce(
        __global BUFFER_TYPE* buffer,
        __local BUFFER_TYPE* minScratch,
        __local BUFFER_TYPE* maxScratch,
        __private int length,
        __private int X,
        __global BUFFER_TYPE* result) {

    int global_index = get_global_id(0)*X;
    BUFFER_TYPE minAccumulator = MAX_VALUE;
    BUFFER_TYPE maxAccumulator = MIN_VALUE;
    // Loop sequentially over chunks of input vector
    for(int i = 0; i < X && global_index < length; i++) {
        float element = buffer[global_index];
        minAccumulator = (minAccumulator < element) ? minAccumulator : element;
        maxAccumulator = (maxAccumulator > element) ? maxAccumulator : element;
        global_index += 1;
    }

    // Perform parallel reduction
    int local_index = get_local_id(0);
    minScratch[local_index] = minAccumulator;
    maxScratch[local_index] = maxAccumulator;
    barrier(CLK_LOCAL_MEM_FENCE);
    for(int offset = get_local_size(0) / 2; offset > 0; offset = offset / 2) {
        if(local_index < offset) {
          BUFFER_TYPE other = minScratch[local_index + offset];
          BUFFER_TYPE mine = minScratch[local_index];
          minScratch[local_index] = (mine < other) ? mine : other;
          other = maxScratch[local_index + offset];
          mine = maxScratch[local_index];
          maxScratch[local_index] = (mine > other) ? mine : other;
        }
        barrier(CLK_LOCAL_MEM_FENCE);
    }
    if(local_index == 0) {
        result[get_group_id(0)*2] = minScratch[0];
        result[get_group_id(0)*2+1] = maxScratch[0];
    }
}

#ifdef TYPE_FLOAT
#define TYPE float4
#define BUFFER_TYPE float
#define READ_IMAGE read_imagef
#define WRITE_IMAGE write_imagef
#define MAX_VALUE FLT_MAX
#define MIN_VALUE FLT_MIN
#elif TYPE_UINT8
#define TYPE uint4
#define BUFFER_TYPE uchar
#define READ_IMAGE read_imageui
#define WRITE_IMAGE write_imageui
#define MAX_VALUE UCHAR_MAX
#define MIN_VALUE 0
#elif TYPE_INT8
#define TYPE int4
#define BUFFER_TYPE char
#define READ_IMAGE read_imagei
#define WRITE_IMAGE write_imagei
#define MAX_VALUE CHAR_MAX
#define MIN_VALUE CHAR_MIN
#elif TYPE_UINT16
#define TYPE uint4
#define BUFFER_TYPE ushort
#define READ_IMAGE read_imageui
#define WRITE_IMAGE write_imageui
#define MAX_VALUE USHRT_MAX
#define MIN_VALUE 0
#else
#define TYPE int4
#define BUFFER_TYPE short
#define READ_IMAGE read_imagei
#define WRITE_IMAGE write_imagei
#define MAX_VALUE SHRT_MAX
#define MIN_VALUE SHRT_MIN
#endif

__constant int2 offset2D[4] = {
                   {0,0},
                   {0,1},
                   {1,0},
                   {1,1}
};

__constant int4 offset3D[8] = {
                   {0,0,0,0},
                   {1,0,0,0},
                   {0,1,0,0},
                   {0,0,1,0},
                   {1,0,1,0},
                   {1,1,1,0},
                   {0,1,1,0},
                   {1,1,0,0}
};

__constant sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_NONE | CLK_FILTER_NEAREST;

__kernel void createFirstMinMaxImage2DLevel(
        __read_only image2d_t image,
        __write_only image2d_t firstLevel
        ) {
    const int2 pos = {get_global_id(0), get_global_id(1)};
    const int2 readPos = pos*2;
    const int2 size = {get_image_width(image), get_image_height(image)};

    TYPE result = {MAX_VALUE, MIN_VALUE,0,0};
    // Check if in bounds
    for(int i = 0; i < 4; i++) {
        TYPE temp;
        temp = READ_IMAGE(image, sampler, select((int2)(0,0), readPos+offset2D[i], readPos+offset2D[i] < size));
        result.x = min(result.x, temp.x);
        result.y = max(result.y, temp.x);
    }

    WRITE_IMAGE(firstLevel, pos, result);
}

__kernel void createMinMaxImage2DLevel(
        __read_only image2d_t readLevel,
        __write_only image2d_t writeLevel
        ) {
    const int2 pos = {get_global_id(0), get_global_id(1)};
    const int2 readPos = pos*2;

    TYPE result = {MAX_VALUE, MIN_VALUE,0,0};
    TYPE temp;
    temp = READ_IMAGE(readLevel, sampler, readPos + offset2D[0]);
    result.x = min(result.x, temp.x);
    result.y = max(result.y, temp.y);
    temp = READ_IMAGE(readLevel, sampler, readPos + offset2D[1]);
    result.x = min(result.x, temp.x);
    result.y = max(result.y, temp.y);
    temp = READ_IMAGE(readLevel, sampler, readPos + offset2D[2]);
    result.x = min(result.x, temp.x);
    result.y = max(result.y, temp.y);
    temp = READ_IMAGE(readLevel, sampler, readPos + offset2D[3]);
    result.x = min(result.x, temp.x);
    result.y = max(result.y, temp.y);

    WRITE_IMAGE(writeLevel, pos, result);
}

__kernel void createFirstMinMaxImage3DLevel(
        __read_only image3d_t image,
        __write_only image3d_t firstLevel
        ) {
    const int4 pos = {get_global_id(0), get_global_id(1), get_global_id(2), 0};
    const int4 readPos = pos*2;
    const int4 size = {get_image_width(image), get_image_height(image), get_image_depth(image), 1};

    TYPE result = {MAX_VALUE, MIN_VALUE,0,0};
    for(int i = 0; i < 8; i++) {
        TYPE temp;
        temp = READ_IMAGE(image, sampler,  select((int4)(0,0,0,0), readPos+offset3D[i], readPos+offset3D[i] < size));
        result.x = min(result.x, temp.x);
        result.y = max(result.y, temp.x);
    }

    WRITE_IMAGE(firstLevel, pos, result);
}

__kernel void createMinMaxImage3DLevel(
        __read_only image3d_t readLevel,
        __write_only image3d_t writeLevel
        ) {
    const int4 pos = {get_global_id(0), get_global_id(1), get_global_id(2), 0};
    const int4 readPos = pos*2;

    TYPE result = {MAX_VALUE, MIN_VALUE,0,0};
    for(int i = 0; i < 8; i++) {
        TYPE temp;
        temp = READ_IMAGE(readLevel, sampler, readPos + offset3D[i]);
        result.x = min(result.x, temp.x);
        result.y = max(result.y, temp.y);
    }

    WRITE_IMAGE(writeLevel, pos, result);
}

__kernel void reduce(
        __global BUFFER_TYPE* buffer,
        __local BUFFER_TYPE* minScratch,
        __local BUFFER_TYPE* maxScratch,
        __private int length,
        __private int X,
        __global BUFFER_TYPE* result) {

    int global_index = get_global_id(0)*X;
    BUFFER_TYPE minAccumulator = MAX_VALUE;
    BUFFER_TYPE maxAccumulator = MIN_VALUE;
    // Loop sequentially over chunks of input vector
    for(int i = 0; i < X && global_index < length; i++) {
        float element = buffer[global_index];
        minAccumulator = (minAccumulator < element) ? minAccumulator : element;
        maxAccumulator = (maxAccumulator > element) ? maxAccumulator : element;
        global_index += 1;
    }

    // Perform parallel reduction
    int local_index = get_local_id(0);
    minScratch[local_index] = minAccumulator;
    maxScratch[local_index] = maxAccumulator;
    barrier(CLK_LOCAL_MEM_FENCE);
    for(int offset = get_local_size(0) / 2; offset > 0; offset = offset / 2) {
        if(local_index < offset) {
          BUFFER_TYPE other = minScratch[local_index + offset];
          BUFFER_TYPE mine = minScratch[local_index];
          minScratch[local_index] = (mine < other) ? mine : other;
          other = maxScratch[local_index + offset];
          mine = maxScratch[local_index];
          maxScratch[local_index] = (mine > other) ? mine : other;
        }
        barrier(CLK_LOCAL_MEM_FENCE);
    }
    if(local_index == 0) {
        result[get_group_id(0)*2] = minScratch[0];
        result[get_group_id(0)*2+1] = maxScratch[0];
    }
}


modifying the coalesced traspose to be fine-grained.

/*-------------transpose2d.cl-------------------------------------------------//
*
* Purpose: to reimplement the 2d transpose notated here:
*              http://developer.download.nvidia.com/compute/DevZone/C/html_x64/6_Advanced/transpose/doc/MatrixTranspose.pdf
*
*-----------------------------------------------------------------------------*/

#pragma OPENCL EXTENSION cl_khr_fp64 : enable
__kernel void transpose2d(__global int *in, __global int *out,
                          __local int *tile,
                          const unsigned int width, const unsigned int height,
                          const unsigned int tile_size,
                          const unsigned int block_rows){
/*
    // STRAIGHT FORWARD EXAMPLE
    int xid = get_global_id(0);
    int yid = get_global_id(1);

    int index_in = xid + width*yid;
    int index_out = yid + height*xid;

    out[index_out] = in[index_in];
*/

/*
    // TILE EXAMPLE
    // Global Thread ID
    int xid = get_group_id(0)*tile_size + get_local_id(0);
    int yid = get_group_id(1)*tile_size + get_local_id(1);

    int index_in = xid + width*yid;
    int index_out = yid + height*xid;
    for (int i = 0; i < tile;  i+=block_rows){
        out[index_out + i] = in[index_in + i*width];
    }
*/
/*
    // COALESCED, FINE-GRAIN TRANSPOSE
    int xthread = get_local_id(0);
    int ythread = get_local_id(1);
    int xid = get_group_id(0)*tile_size + xthread;
    int yid = get_group_id(1)*tile_size + ythread;

    int index = xid + yid * width;

    int tile_index = 0;
    for (int i = 0; i < tile_size; i += block_rows){
        tile_index = (ythread+i)*width + xthread;
        tile[tile_index] = in[index + i*width];
    }

    barrier(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE);

    for (int i = 0; i < tile_size; i += block_rows){
        tile_index = ythread + i + xthread*height;
        out[index + i*height] = tile[tile_index];
    }
*/
/*
    int blockIdx_x, blockIdx_y;

    if (width == height){
        blockIdx_y = get_group_id(0);
        blockIdx_x = (get_group_id(0)+get_group_id(1))%get_global_size(0);
    }
    else{
        int bid = get_group_id(0) + get_global_size(0)*get_group_id(1);
        blockIdx_y = bid%get_global_size(1);
        blockIdx_x = ((bid/get_global_size(1))+get_group_id(1))
                     %get_global_size(0);
    }
    int xthread = get_local_id(0);
    int ythread = get_local_id(1);
    int xid = blockIdx_x*tile_size + xthread;
    int yid = blockIdx_y*tile_size + ythread;
    int index_in = xid + width*yid;

    xid = blockIdx_y*tile_size + xthread;
    yid = blockIdx_x*tile_size + ythread;
    int index_out = xid + height*yid;

    int tile_index = 0;
    for (int i = 0; i < tile_size; i += block_rows){
        tile_index = (ythread+i)*width + xthread;
        tile[tile_index] = in[index_in + i*width];
    }

    barrier(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE);

    for (int i = 0; i < tile_size; i += block_rows){
        tile_index = ythread + i + xthread*width;
        out[index_out + i*height] = tile[tile_index];
    }
*/
}

/*-------------transpose2d.cl-------------------------------------------------//
*
* Purpose: to reimplement the 2d transpose notated here:
*              http://developer.download.nvidia.com/compute/DevZone/C/html_x64/6_Advanced/transpose/doc/MatrixTranspose.pdf
*
*-----------------------------------------------------------------------------*/

#pragma OPENCL EXTENSION cl_khr_fp64 : enable
__kernel void transpose2d(__global int *in, __global int *out,
                          __local int *tile,
                          const unsigned int width, const unsigned int height,
                          const unsigned int tile_size,
                          const unsigned int block_rows){
    // STRAIGHT FORWARD EXAMPLE
    int xid = get_global_id(0);
    int yid = get_global_id(1);

    int index_in = xid + width*yid;
    int index_out = yid + height*xid;

    out[index_out] = in[index_in];

/*
    // TILE EXAMPLE
    // Global Thread ID
    int xid = get_group_id(0)*tile_size + get_local_id(0);
    int yid = get_group_id(1)*tile_size + get_local_id(1);

    int index_in = xid + width*yid;
    int index_out = yid + height*xid;
    for (int i = 0; i < tile;  i+=block_rows){
        out[index_out + i] = in[index_in + i*width];
    }
*/
/*
    // COALESCED TRANSPOSE
    int xthread = get_local_id(0);
    int ythread = get_local_id(1);
    int xid = get_group_id(0)*tile_size + xthread;
    int yid = get_group_id(1)*tile_size + ythread;

    int index_in = xid + yid * width;

    xid = get_group_id(1) * tile_size + xthread;
    yid = get_group_id(0) * tile_size + ythread;

    int index_out = xid + yid * height;

    int tile_index = 0;
    for (int i = 0; i < tile_size; i += block_rows){
        tile_index = (ythread+i)*width + xthread;
        tile[tile_index] = in[index_in + width];
    }

    barrier(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE);

    for (int i = 0; i < tile_size; i += block_rows){
        tile_index = ythread + i + xthread*height;
        out[index_out + i*height] = tile[tile_index];
    }
*/
/*
    int blockIdx_x, blockIdx_y;

    if (width == height){
        blockIdx_y = get_group_id(0);
        blockIdx_x = (get_group_id(0)+get_group_id(1))%get_global_size(0);
    }
    else{
        int bid = get_group_id(0) + get_global_size(0)*get_group_id(1);
        blockIdx_y = bid%get_global_size(1);
        blockIdx_x = ((bid/get_global_size(1))+get_group_id(1))
                     %get_global_size(0);
    }
    int xthread = get_local_id(0);
    int ythread = get_local_id(1);
    int xid = blockIdx_x*tile_size + xthread;
    int yid = blockIdx_y*tile_size + ythread;
    int index_in = xid + width*yid;

    xid = blockIdx_y*tile_size + xthread;
    yid = blockIdx_x*tile_size + ythread;
    int index_out = xid + height*yid;

    int tile_index = 0;
    for (int i = 0; i < tile_size; i += block_rows){
        tile_index = (ythread+i)*width + xthread;
        tile[tile_index] = in[index_in + i*width];
    }

    barrier(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE);

    for (int i = 0; i < tile_size; i += block_rows){
        tile_index = ythread + i + xthread*width;
        out[index_out + i*height] = tile[tile_index];
    }
*/
}


Fix a lit test issue exposed by r290056

Fix a lit test issue exposed by r290056

The test requests a target which supports cl_khr_gl_msaa_sharing since in test/PCH/ocl_types.h
it tries to enable cl_khr_gl_msaa_sharing. Therefore this test fails on targets not supporting
cl_khr_gl_msaa_sharing, e.g. ppc64, etc.

The fix is to add triple spir-unknown-unknown which supports cl_khr_gl_msaa_sharing.

git-svn-id: ffe668792ed300d6c2daa1f6eba2e0aa28d7ec6c@290059 91177308-0d34-0410-b5e6-96231b3b80d8

// Test this without pch.
// RUN: %clang_cc1 -triple spir-unknown-unknown -include %S/ocl_types.h -fsyntax-only %s -cl-std=CL2.0 -D__OPENCL_VERSION__=200

// Test with pch.
// RUN: %clang_cc1 -triple spir-unknown-unknown -x cl -emit-pch -o %t %S/ocl_types.h -cl-std=CL2.0 -D__OPENCL_VERSION__=200
// RUN: %clang_cc1 -triple spir-unknown-unknown -include-pch %t -fsyntax-only %s -ast-print -cl-std=CL2.0 -D__OPENCL_VERSION__=200

void foo1(img1d_t img);

void foo2(img1darr_t img);

void foo3(img1dbuff_t img);

void foo4(img2d_t img);

void foo5(img2darr_t img);

void foo6(img3d_t img);

void foo7(smp_t smp) {
  smp_t loc_smp;
}

void foo8(evt_t evt) {
  evt_t loc_evt;
}

#if __OPENCL_VERSION__ >= 200

void foo9(pipe int P) {
  int_pipe_function(P);
}

void foo10(pipe Person P) {
  person_pipe_function(P);
}

#endif

// Test this without pch.
// RUN: %clang_cc1 -include %S/ocl_types.h -fsyntax-only %s -cl-std=CL2.0 -D__OPENCL_VERSION__=200

// Test with pch.
// RUN: %clang_cc1 -x cl -emit-pch -o %t %S/ocl_types.h -cl-std=CL2.0 -D__OPENCL_VERSION__=200
// RUN: %clang_cc1 -include-pch %t -fsyntax-only %s -ast-print -cl-std=CL2.0 -D__OPENCL_VERSION__=200

void foo1(img1d_t img);

void foo2(img1darr_t img);

void foo3(img1dbuff_t img);

void foo4(img2d_t img);

void foo5(img2darr_t img);

void foo6(img3d_t img);

void foo7(smp_t smp) {
  smp_t loc_smp;
}

void foo8(evt_t evt) {
  evt_t loc_evt;
}

#if __OPENCL_VERSION__ >= 200

void foo9(pipe int P) {
  int_pipe_function(P);
}

void foo10(pipe Person P) {
  person_pipe_function(P);
}

#endif


inlined rng

inlined rng

#define __CLKERNEL

#ifdef __CLKERNEL
#else
#include <stdio.h>
#define uint unsigned int
#endif

#define OFFSET_BASIS 2166136261
#define FNV_PRIME 16777619
#define FLOAT_T float
#define HASH_T uint
#define N 5

typedef float4 Point;
typedef int4 IntPoint;

// FNV hash: http://isthe.com/chongo/tech/comp/fnv/#FNV-source
HASH_T hash(HASH_T i, HASH_T j, HASH_T k) {
  return (HASH_T)((((((OFFSET_BASIS ^ (HASH_T)i) * FNV_PRIME) ^ (HASH_T)j) * FNV_PRIME) ^ (HASH_T)k) * FNV_PRIME);
}

//~ FLOAT_T our_distance(Point p1, Point p2) {
    //~ Point d = fabs(p1-p2);
    //~ if(d.x > d.y && d.x > d.z)
	//~ return d.x;
    //~ if(d.y > d.z)
	//~ return d.y;
    //~ return d.z;
//~ }

// Return the square of the distance between points p1 and p2
FLOAT_T our_distance(Point p1, Point p2) {
  return (p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y) + (p1.z-p2.z)*(p1.z-p2.z);
}

void insert(FLOAT_T *arr, FLOAT_T value) {
  // Ugly hack to prevent duplicate values
  for(int i=0; i < N; ++i)
    if(arr[i] == value)
  	return;

  float temp;
  for(int i=N-1; i>=0; i--) {
    if(value > arr[i]) break;
    temp = arr[i];
    arr[i] = value;
    if(i+1<N) arr[i+1] = temp;
  }
}

// LCG Random Number Generator
#define rng(last) ((1103515245 * last + 12345) % 0x100000000)

// Generated with "AccountingForm[N[Table[CDF[PoissonDistribution[4], i], {i, 1, 9}], 20]*2^32]" //"N[Table[CDF[PoissonDistribution[4], i], {i, 1, 9}], 20]"
uint prob_lookup(uint value)
{
    if(value < 393325350) return 1;
    if(value < 1022645910) return 2;
    if(value < 1861739990) return 3;
    if(value < 2700834071) return 4;
    if(value < 3372109335) return 5;
    if(value < 3819626178) return 6;
    if(value < 4075350088) return 7;
    if(value < 4203212043) return 8;
    return 9;
}

void findDistancesForCube(FLOAT_T *distanceArray, Point p, IntPoint c) {
  uint rngLast = rng( hash(c.x, c.y, c.z) );
  uint rng1,rng2,rng3;
  Point randomDiff,featurePoint;
  uint numFPoints = prob_lookup( rngLast );

  for(uint i = 0; i < numFPoints; ++i) {
	rng1 = rng(rngLast);
	rng2 = rng(rng1);
	rng3 = rng(rng2);
	rngLast = rng3;

	randomDiff.x = (float)rng1 / 0x100000000;
	randomDiff.y = (float)rng2 / 0x100000000;
	randomDiff.z = (float)rng3 / 0x100000000;
	featurePoint = randomDiff + convert_float4(c);

	insert(distanceArray, our_distance(p,featurePoint));
  }
}

void forAll(FLOAT_T *distanceArray, Point p) {
    for(int i=-1; i < 2; ++i) {
	for(int j=-1; j < 2; ++j) {
	    for(int k=-1; k < 2; ++k) {
		IntPoint cube;
		cube.x = p.x + i;
		cube.y = p.y + j;
		cube.z = p.z + k;
		findDistancesForCube(distanceArray, p, cube);
	    }
	}
    }
}

__kernel void WorleyNoise(__global FLOAT_T *arrX, __global FLOAT_T *arrY, __global FLOAT_T *arrZ, __global FLOAT_T *output) {//, int width, int height, int depth) {
    uint idX = get_global_id(0);
    uint idY = get_global_id(1);
    uint idZ = get_global_id(2);
    uint width = get_global_size(0);
    uint height = get_global_size(1);
    uint depth = get_global_size(2);

  // Shall we do work?
  if(idX < width && idY < height && idZ < depth) {
	// Initalize array
	FLOAT_T darr[N];
	for(int i=0; i<N; ++i)
	  darr[i] = 888;

	Point p;
	p.x = arrX[idX];
	p.y = arrY[idY];
	p.z = arrZ[idZ];
	forAll(darr,p);
	//findDistancesForCube(darr, p, convert_int4(p));

	output[depth*height*idX + depth*idY + idZ] = darr[1] - darr[0];
  }
}

#define __CLKERNEL

#ifdef __CLKERNEL
#else
#include <stdio.h>
#define uint unsigned int
#endif

#define OFFSET_BASIS 2166136261
#define FNV_PRIME 16777619
#define FLOAT_T float
#define HASH_T uint
#define N 5

typedef float4 Point;
typedef int4 IntPoint;

// FNV hash: http://isthe.com/chongo/tech/comp/fnv/#FNV-source
HASH_T hash(HASH_T i, HASH_T j, HASH_T k) {
  return (HASH_T)((((((OFFSET_BASIS ^ (HASH_T)i) * FNV_PRIME) ^ (HASH_T)j) * FNV_PRIME) ^ (HASH_T)k) * FNV_PRIME);
}

//~ FLOAT_T our_distance(Point p1, Point p2) {
    //~ Point d = fabs(p1-p2);
    //~ if(d.x > d.y && d.x > d.z)
	//~ return d.x;
    //~ if(d.y > d.z)
	//~ return d.y;
    //~ return d.z;
//~ }

// Return the square of the distance between points p1 and p2
FLOAT_T our_distance(Point p1, Point p2) {
  return (p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y) + (p1.z-p2.z)*(p1.z-p2.z);
}

void insert(FLOAT_T *arr, FLOAT_T value) {
  // Ugly hack to prevent duplicate values
  for(int i=0; i < N; ++i)
    if(arr[i] == value)
  	return;

  float temp;
  for(int i=N-1; i>=0; i--) {
    if(value > arr[i]) break;
    temp = arr[i];
    arr[i] = value;
    if(i+1<N) arr[i+1] = temp;
  }
}

// LCG Random Number Generator
uint rng(uint last) {
  return ((1103515245 * last + 12345) % 0x100000000);
}

// Generated with "AccountingForm[N[Table[CDF[PoissonDistribution[4], i], {i, 1, 9}], 20]*2^32]" //"N[Table[CDF[PoissonDistribution[4], i], {i, 1, 9}], 20]"
uint prob_lookup(uint value)
{
    if(value < 393325350) return 1;
    if(value < 1022645910) return 2;
    if(value < 1861739990) return 3;
    if(value < 2700834071) return 4;
    if(value < 3372109335) return 5;
    if(value < 3819626178) return 6;
    if(value < 4075350088) return 7;
    if(value < 4203212043) return 8;
    return 9;
}

void findDistancesForCube(FLOAT_T *distanceArray, Point p, IntPoint c) {
  uint rngLast = rng( hash(c.x, c.y, c.z) );
  uint rng1,rng2,rng3;
  Point randomDiff,featurePoint;
  uint numFPoints = prob_lookup( rngLast );

  for(uint i = 0; i < numFPoints; ++i) {
	rng1 = rng(rngLast);
	rng2 = rng(rng1);
	rng3 = rng(rng2);
	rngLast = rng3;

	randomDiff.x = (float)rng1 / 0x100000000;
	randomDiff.y = (float)rng2 / 0x100000000;
	randomDiff.z = (float)rng3 / 0x100000000;
	featurePoint = randomDiff + convert_float4(c);

	insert(distanceArray, our_distance(p,featurePoint));
  }
}

void forAll(FLOAT_T *distanceArray, Point p) {
    for(int i=-1; i < 2; ++i) {
	for(int j=-1; j < 2; ++j) {
	    for(int k=-1; k < 2; ++k) {
		IntPoint cube;
		cube.x = p.x + i;
		cube.y = p.y + j;
		cube.z = p.z + k;
		findDistancesForCube(distanceArray, p, cube);
	    }
	}
    }
}

__kernel void WorleyNoise(__global FLOAT_T *arrX, __global FLOAT_T *arrY, __global FLOAT_T *arrZ, __global FLOAT_T *output) {//, int width, int height, int depth) {
    uint idX = get_global_id(0);
    uint idY = get_global_id(1);
    uint idZ = get_global_id(2);
    uint width = get_global_size(0);
    uint height = get_global_size(1);
    uint depth = get_global_size(2);

  // Shall we do work?
  if(idX < width && idY < height && idZ < depth) {
	// Initalize array
	FLOAT_T darr[N];
	for(int i=0; i<N; ++i)
	  darr[i] = 888;

	Point p;
	p.x = arrX[idX];
	p.y = arrY[idY];
	p.z = arrZ[idZ];
	forAll(darr,p);
	//findDistancesForCube(darr, p, convert_int4(p));

	output[depth*height*idX + depth*idY + idZ] = darr[1] - darr[0];
  }
}


r600: Fix get_global_id implementation

r600: Fix get_global_id implementation

git-svn-id: e7f1ab7c2a259259587475a3e7520e757882f167@184976 91177308-0d34-0410-b5e6-96231b3b80d8

#include <clc/clc.h>

_CLC_DEF size_t get_global_id(uint dim) {
  switch (dim) {
  case 0:  return __builtin_r600_read_tgid_x()*__builtin_r600_read_local_size_x()+__builtin_r600_read_tidig_x();
  case 1:  return __builtin_r600_read_tgid_y()*__builtin_r600_read_local_size_y()+__builtin_r600_read_tidig_y();
  case 2:  return __builtin_r600_read_tgid_z()*__builtin_r600_read_local_size_z()+__builtin_r600_read_tidig_z();
  default: return 0;
  }
}

#include <clc/clc.h>

_CLC_DEF size_t get_global_id(uint dim) {
  switch (dim) {
  case 0:  return __builtin_r600_read_tgid_x()*__builtin_r600_read_ngroups_x()+__builtin_r600_read_tidig_x();
  case 1:  return __builtin_r600_read_tgid_y()*__builtin_r600_read_ngroups_y()+__builtin_r600_read_tidig_y();
  case 2:  return __builtin_r600_read_tgid_z()*__builtin_r600_read_ngroups_z()+__builtin_r600_read_tidig_z();
  default: return 0;
  }
}