Comment for clarification

Comment for clarification

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

#define FENCE_TYPE CLK_LOCAL_MEM_FENCE
#define WORK_GROUP_SIZE 1024

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

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

// main kernel
kernel void kernel_wah_index(global uint* config,
                             global uint* input,
                             global uint* index,
                             global uint* offsets,
                             global uint* rids,
                             global uint* chids,
                             global uint* lits) {
  // config structure:
  // config[0] : amount of values to process
  // config[1] : number of work groups
  // config[wg index + 2]     : input length for work group
  // config[wg index + 2 + 1] : index length for work group
  // One-dimensional array here, only dim 0
  // uint num_total = get_global_size(0);
  uint num_local = get_local_size(0);
  // uint gi = get_global_id(0); // global index
  uint li = get_local_id(0);  // local index
  uint wg = get_group_id(0);  // work group index
  uint cfg_pos   = (wg * 2) + 2;
  uint num_wg    = config[1]; // should be <= get_num_groups(0)
  uint work_size = config[cfg_pos];
  uint offset    = wg * num_local;
  // acquire pointers to the memory regions for this work group
  global uint* work_input   = input   + offset;
  global uint* work_index   = index   + (offset * 2);
  global uint* work_offsets = offsets + offset;
  global uint* work_rids    = rids    + offset;
  global uint* work_chids   = chids   + offset;
  global uint* work_lits    = lits    + offset;
  // Process local blocks, 1 work-item per value
  if (li < work_size && wg < num_wg) {
    sort_rids_by_value(work_input, work_rids, li, work_size);
    barrier(FENCE_TYPE);
    produce_chunck_id_literals(work_rids, work_chids, work_lits, li, work_size);
    barrier(FENCE_TYPE);
    size_t k = merged_lit_by_val_chids(work_input, work_chids, work_lits, li, work_size);
    barrier(FENCE_TYPE);
    produce_fills(work_input, work_chids, li, k);
    barrier(FENCE_TYPE);
    uint length = fuse_fill_literals(work_chids, work_lits, work_index, li, k);
    barrier(FENCE_TYPE);
    uint keycnt = compute_colum_length(work_input, work_chids, work_offsets, li, k);
    barrier(FENCE_TYPE);
    config[cfg_pos    ] = keycnt;
    config[cfg_pos + 1] = length;
  }
}

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

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

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

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

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

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

// Helper functions

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

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

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

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

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

#define FENCE_TYPE CLK_LOCAL_MEM_FENCE
#define WORK_GROUP_SIZE 1024

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

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

// main kernel
kernel void kernel_wah_index(global uint* config,
                             global uint* input,
                             global uint* index,
                             global uint* offsets,
                             global uint* rids,
                             global uint* chids,
                             global uint* lits) {
  // config structure:
  // config[0] : amount of values to process
  // config[1] : number of work groups
  // config[wg index + 2]     : input length for work group
  // config[wg index + 2 + 1] : index length for work group
  // One-dimensional array here, only dim 0
  // uint num_total = get_global_size(0);
  uint num_local = get_local_size(0);
  // uint gi = get_global_id(0); // global index
  uint li = get_local_id(0);  // local index
  uint wg = get_group_id(0);  // work group index
  uint cfg_pos   = (wg * 2) + 2;
  uint num_wg    = config[1];
  uint work_size = config[cfg_pos];
  uint offset    = wg * num_local;
  // acquire pointers to the memory regions for this work group
  global uint* work_input   = input   + offset;
  global uint* work_index   = index   + (offset * 2);
  global uint* work_offsets = offsets + offset;
  global uint* work_rids    = rids    + offset;
  global uint* work_chids   = chids   + offset;
  global uint* work_lits    = lits    + offset;
  // Process local blocks, 1 work-item per value
  if (li < work_size && wg < num_wg) {
    sort_rids_by_value(work_input, work_rids, li, work_size);
    barrier(FENCE_TYPE);
    produce_chunck_id_literals(work_rids, work_chids, work_lits, li, work_size);
    barrier(FENCE_TYPE);
    size_t k = merged_lit_by_val_chids(work_input, work_chids, work_lits, li, work_size);
    barrier(FENCE_TYPE);
    produce_fills(work_input, work_chids, li, k);
    barrier(FENCE_TYPE);
    uint length = fuse_fill_literals(work_chids, work_lits, work_index, li, k);
    barrier(FENCE_TYPE);
    uint keycnt = compute_colum_length(work_input, work_chids, work_offsets, li, k);
    barrier(FENCE_TYPE);
    config[cfg_pos    ] = keycnt;
    config[cfg_pos + 1] = length;
  }
}

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

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

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

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

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

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

// Helper functions

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

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

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

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


fix small issue

fix small issue

__kernel void reallySmallRSACrack(__global int* num, __global int* reasult, __global int* communicateBuffer)
{
	int targetNum = *num;
	int squareRoot = sqrt(convert_float(targetNum));
	int size = get_global_size(0);
	int id = get_global_id(0);
	int calcNum = squareRoot - id;

	//calcNum > 1 insures no process will find the solution calcNum=1 which is something we don't want.
	for(int i=id;i<squareRoot &&calcNum > 1;)
	{
		if(*communicateBuffer == 1)
			break;
		if(targetNum % calcNum == 0 && calcNum != 1)
		{
			*communicateBuffer = 1;
			reasult[0] = calcNum;
			reasult[1] = targetNum / calcNum;
		}
		calcNum -= size;
		i += size;
	}
}

__kernel void reallySmallRSACrack(__global int* num, __global int* reasult, __global int* communicateBuffer)
{
	int targetNum = *num;
	int squareRoot = sqrt(convert_float(targetNum));
	int size = get_global_size(0);
	int id = get_global_id(0);
	int calcNum = squareRoot - id;

	//calcNum > 1 insures no process will find the solution calcNum=1 which is something we don't want.
	for(int i=id;i<squareRoot;calcNum > 1)
	{
		if(*communicateBuffer == 1)
			break;
		if(targetNum % calcNum == 0 && calcNum != 1)
		{
			*communicateBuffer = 1;
			reasult[0] = calcNum;
			reasult[1] = targetNum / calcNum;
		}
		calcNum -= size;
		i += size;
	}
}


Change uchar2 to short

Change uchar2 to short

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

#if lcn == 1
    #if dcn == 4
        #define LUT_OP(num)\
            int idx = *(__global const int *)(srcptr + mad24(num, src_step, src_index));\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx & 0xff];\
            dst[1] = lut_l[(idx >> 8) & 0xff];\
            dst[2] = lut_l[(idx >> 16) & 0xff];\
            dst[3] = lut_l[(idx >> 24) & 0xff];
    #elif dcn == 3
        #define LUT_OP(num)\
            uchar3 idx = vload3(0, srcptr + mad24(num, src_step, src_index));\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx.x];\
            dst[1] = lut_l[idx.y];\
            dst[2] = lut_l[idx.z];
    #elif dcn == 2
        #define LUT_OP(num)\
            short idx = *(__global const short *)(srcptr + mad24(num, src_step, src_index));\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx & 0xff];\
            dst[1] = lut_l[(idx >> 8) & 0xff];
    #elif dcn == 1
        #define LUT_OP(num)\
            uchar idx = (srcptr + mad24(num, src_step, src_index))[0];\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx];
    #else
        #define LUT_OP(num)\
            __global const srcT * src = (__global const srcT *)(srcptr + mad24(num, src_step, src_index));\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            for (int cn = 0; cn < dcn; ++cn)\
                dst[cn] = lut_l[src[cn]];
    #endif
#else
    #if dcn == 4
        #define LUT_OP(num)\
            __global const uchar4 *src_pixel = (__global const uchar4 *)(srcptr + mad24(num, src_step, src_index));\
            int4 idx = convert_int4(src_pixel[0]) * lcn + (int4)(0, 1, 2, 3);\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx.x];\
            dst[1] = lut_l[idx.y];\
            dst[2] = lut_l[idx.z];\
            dst[3] = lut_l[idx.w];
    #elif dcn == 3
        #define LUT_OP(num)\
            uchar3 src_pixel = vload3(0, srcptr + mad24(num, src_step, src_index));\
            int3 idx = convert_int3(src_pixel) * lcn + (int3)(0, 1, 2);\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx.x];\
            dst[1] = lut_l[idx.y];\
            dst[2] = lut_l[idx.z];
    #elif dcn == 2
        #define LUT_OP(num)\
            __global const uchar2 *src_pixel = (__global const uchar2 *)(srcptr + mad24(num, src_step, src_index));\
            int2 idx = convert_int2(src_pixel[0]) * lcn + (int2)(0, 1);\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx.x];\
            dst[1] = lut_l[idx.y];
    #elif dcn == 1 //error case (1 < lcn) ==> lcn == scn == dcn
        #define LUT_OP(num)\
            uchar idx = (srcptr + mad24(num, src_step, src_index))[0];\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx];
    #else
        #define LUT_OP(num)\
            __global const srcT *src = (__global const srcT *)(srcptr + mad24(num, src_step, src_index));\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            for (int cn = 0; cn < dcn; ++cn)\
                dst[cn] = lut_l[mad24(src[cn], lcn, cn)];
    #endif
#endif

#define LOCAL_LUT_INIT\
    {\
        __global const dstT * lut = (__global const dstT *)(lutptr + lut_offset);\
        int init = mad24((int)get_local_id(1), (int)get_local_size(0), (int)get_local_id(0));\
        int step = get_local_size(0) * get_local_size(1);\
        for (int i = init; i < 256 * lcn; i += step)\
        {\
            lut_l[i] = lut[i];\
        }\
        barrier(CLK_LOCAL_MEM_FENCE);\
    }

__kernel void LUT(__global const uchar * srcptr, int src_step, int src_offset,
                  __global const uchar * lutptr, int lut_step, int lut_offset,
                  __global uchar * dstptr, int dst_step, int dst_offset, int rows, int cols)
{
    __local dstT lut_l[256 * lcn];
    LOCAL_LUT_INIT;

    int x = get_global_id(0);
    int y = 4 * get_global_id(1);

    if (x < cols && y < rows)
    {
        int src_index = mad24(y, src_step, mad24(x, (int)sizeof(srcT) * dcn, src_offset));
        int dst_index = mad24(y, dst_step, mad24(x, (int)sizeof(dstT) * dcn, dst_offset));
        __global dstT * dst;
        LUT_OP(0);
        if (y < rows - 1)
        {
            LUT_OP(1);
            if (y < rows - 2)
            {
                LUT_OP(2);
                if (y < rows - 3)
                {
                    LUT_OP(3);
                }
            }
        }

    }
}

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

#if lcn == 1
    #if dcn == 4
        #define LUT_OP(num)\
            int idx = *(__global const int *)(srcptr + mad24(num, src_step, src_index));\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx & 0xff];\
            dst[1] = lut_l[(idx >> 8) & 0xff];\
            dst[2] = lut_l[(idx >> 16) & 0xff];\
            dst[3] = lut_l[(idx >> 24) & 0xff];
    #elif dcn == 3
        #define LUT_OP(num)\
            uchar3 idx = vload3(0, srcptr + mad24(num, src_step, src_index));\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx.x];\
            dst[1] = lut_l[idx.y];\
            dst[2] = lut_l[idx.z];
    #elif dcn == 2
        #define LUT_OP(num)\
            __global const uchar2 * idx = (__global const uchar2 *)(srcptr + mad24(num, src_step, src_index));\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx->x];\
            dst[1] = lut_l[idx->y];
    #elif dcn == 1
        #define LUT_OP(num)\
            uchar idx = (srcptr + mad24(num, src_step, src_index))[0];\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx];
    #else
        #define LUT_OP(num)\
            __global const srcT * src = (__global const srcT *)(srcptr + mad24(num, src_step, src_index));\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            for (int cn = 0; cn < dcn; ++cn)\
                dst[cn] = lut_l[src[cn]];
    #endif
#else
    #if dcn == 4
        #define LUT_OP(num)\
            __global const uchar4 *src_pixel = (__global const uchar4 *)(srcptr + mad24(num, src_step, src_index));\
            int4 idx = convert_int4(src_pixel[0]) * lcn + (int4)(0, 1, 2, 3);\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx.x];\
            dst[1] = lut_l[idx.y];\
            dst[2] = lut_l[idx.z];\
            dst[3] = lut_l[idx.w];
    #elif dcn == 3
        #define LUT_OP(num)\
            uchar3 src_pixel = vload3(0, srcptr + mad24(num, src_step, src_index));\
            int3 idx = convert_int3(src_pixel) * lcn + (int3)(0, 1, 2);\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx.x];\
            dst[1] = lut_l[idx.y];\
            dst[2] = lut_l[idx.z];
    #elif dcn == 2
        #define LUT_OP(num)\
            __global const uchar2 *src_pixel = (__global const uchar2 *)(srcptr + mad24(num, src_step, src_index));\
            int2 idx = convert_int2(src_pixel[0]) * lcn + (int2)(0, 1);\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx.x];\
            dst[1] = lut_l[idx.y];
    #elif dcn == 1 //error case (1 < lcn) ==> lcn == scn == dcn
        #define LUT_OP(num)\
            uchar idx = (srcptr + mad24(num, src_step, src_index))[0];\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx];
    #else
        #define LUT_OP(num)\
            __global const srcT *src = (__global const srcT *)(srcptr + mad24(num, src_step, src_index));\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            for (int cn = 0; cn < dcn; ++cn)\
                dst[cn] = lut_l[mad24(src[cn], lcn, cn)];
    #endif
#endif

#define LOCAL_LUT_INIT\
    {\
        __global const dstT * lut = (__global const dstT *)(lutptr + lut_offset);\
        int init = mad24((int)get_local_id(1), (int)get_local_size(0), (int)get_local_id(0));\
        int step = get_local_size(0) * get_local_size(1);\
        for (int i = init; i < 256 * lcn; i += step)\
        {\
            lut_l[i] = lut[i];\
        }\
        barrier(CLK_LOCAL_MEM_FENCE);\
    }

__kernel void LUT(__global const uchar * srcptr, int src_step, int src_offset,
                  __global const uchar * lutptr, int lut_step, int lut_offset,
                  __global uchar * dstptr, int dst_step, int dst_offset, int rows, int cols)
{
    __local dstT lut_l[256 * lcn];
    LOCAL_LUT_INIT;

    int x = get_global_id(0);
    int y = 4 * get_global_id(1);

    if (x < cols && y < rows)
    {
        int src_index = mad24(y, src_step, mad24(x, (int)sizeof(srcT) * dcn, src_offset));
        int dst_index = mad24(y, dst_step, mad24(x, (int)sizeof(dstT) * dcn, dst_offset));
        __global dstT * dst;
        LUT_OP(0);
        if (y < rows - 1)
        {
            LUT_OP(1);
            if (y < rows - 2)
            {
                LUT_OP(2);
                if (y < rows - 3)
                {
                    LUT_OP(3);
                }
            }
        }

    }
}


fixed 1x1 L

fixed 1x1 L

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

/*
Layout:

*/

__kernel void MLOpenConv1x1(
       const __global _FLOAT * restrict in_ptr,
       const __global _FLOAT * restrict wei_ptr,
#if MLO_CONV_BIAS
       const __global _FLOAT * bias,
#endif
 	  __global _FLOAT *out_ptr,
	   _FLOAT dummy_val // nothing
	   )
{
// KERNEL
// private buffers
	__private _FLOAT4 in_stage[MLO_N_LCL_BATCHS][MLO_N_LCL_IN_MAPS];
	__private _FLOAT wei_stage[MLO_N_LCL_OUT_MAPS][MLO_N_LCL_IN_MAPS];
	__private _FLOAT4 out_tiles[MLO_N_LCL_BATCHS][MLO_N_LCL_OUT_MAPS];
	__local _FLOAT lcl_wei_stage[MLO_N_MAPS_PERGROUP*MLO_N_LCL_OUT_MAPS][MLO_N_LCL_IN_MAPS*MLO_N_MAPS_PERGROUP];
#if MLO_N_MAPS_PERGROUP > 1
	__local _FLOAT4 lcl_in_stage[MLO_GRP_SZ0];

#endif

	int lcl_id0 = get_local_id(0);
	int in_map_id = 0; // map
	int pix_id = get_global_id(0);  // inside map
	in_map_id = pix_id / MLO_MAP_SZ4; // mad id inside group
	int out_grp_block = get_group_id(1); // block of outputs for the entire group
	int out_block = out_grp_block;
	int batch_block = get_group_id(2); // block of batchs
// multipe maps per group
//#if MLO_N_MAPS_PERGROUP > 1
	pix_id = (pix_id - in_map_id * MLO_MAP_SZ4);  // pixel inside map
	out_block = out_grp_block * MLO_N_MAPS_PERGROUP + in_map_id;
//#endif

	int in_off = batch_block * MLO_N_LCL_BATCHS * MLO_IN_BATCH_STRIDE
		+ in_map_id * MLO_IN_CHANNEL_STRIDE
				+ pix_id * 4;

	int wei_off = out_grp_block * MLO_N_MAPS_PERGROUP * MLO_N_LCL_OUT_MAPS * MLO_WEI_BSTRIDE;
	for (int j = 0; j < MLO_N_LCL_BATCHS; ++j)
	{
		for (int i = 0; i < MLO_N_LCL_OUT_MAPS; ++i)
		{
			out_tiles[j][i] = 0;
		}
	}
// over all input maps; with step == MLO_N_LCL_IN_MAPS * MLO_N_MAPS_PERGROUP; MLO_IN_LOOP
	for (int c = 0; c < MLO_IN_LOOP; ++c,
		in_off += MLO_IN_CHANNEL_STRIDE*MLO_N_LCL_IN_MAPS * MLO_N_MAPS_PERGROUP,
		wei_off += MLO_N_LCL_IN_MAPS * MLO_N_MAPS_PERGROUP * MLO_WEI_CHANNEL_STRIDE
//#if MLO_DIR_FORWARD==0
//			* MLO_N_OUTPUTS
//#endif
		)
	{
		barrier(CLK_LOCAL_MEM_FENCE);

// read data
// over all local batchs
		int in_off1 = in_off;
		for (int ib = 0; ib < MLO_N_LCL_BATCHS
#if MLO_BATCH_ALIGNED == 0
			&& (batch_block*MLO_N_LCL_BATCHS + ib < MLO_BATCH_SZ)
#endif
			; ++ib, in_off1 += MLO_IN_BATCH_STRIDE)
		{
			int in_off2 = in_off1;
// lcl in maps (in data tiles) is has the stride = MLO_N_MAPS_PERGROUP
			for (int ilc = 0; ilc < MLO_N_LCL_IN_MAPS; ++ilc, in_off2 += MLO_IN_CHANNEL_STRIDE * MLO_N_MAPS_PERGROUP)
			{
				// read data
				in_stage[ib][ilc] = 0;
				if (c*MLO_N_LCL_IN_MAPS * MLO_N_MAPS_PERGROUP + in_map_id + ilc* MLO_N_MAPS_PERGROUP < MLO_N_INPUTS)
				{

					in_stage[ib][ilc] = *(_FLOAT4*)&in_ptr[in_off2];

#if !MLO_DIVBY4

					// if the last one
					if (pix_id == MLO_MAP_SZ4 - 1)
					{
						for (int j = 3; j >= MLO_C1x1_PIXLEFT; --j)
						{
							((_FLOAT*)&in_stage[ib][ilc])[j] = 0;
						}
					}

#endif
				}
				/*
				if(c*MLO_N_LCL_IN_MAPS * MLO_N_MAPS_PERGROUP + in_map_id + ilc* MLO_N_MAPS_PERGROUP >= MLO_N_INPUTS)
				{
					in_stage[ib][ilc] = 0;
				}
				*/

			}
		}

// read weights
// KCRS weights layout
		int wei_off1 = wei_off;

		for (int l = lcl_id0; l < MLO_N_MAPS_PERGROUP * MLO_N_LCL_OUT_MAPS * MLO_N_MAPS_PERGROUP * MLO_N_LCL_IN_MAPS; l += MLO_GRP_SZ0)
		{
			int o = (int)(((float)l + 0.000001f) / (MLO_N_LCL_IN_MAPS*MLO_N_MAPS_PERGROUP));
			int i = -mad24(o,(int)(MLO_N_LCL_IN_MAPS*MLO_N_MAPS_PERGROUP),-l);
			lcl_wei_stage[o][i] = wei_ptr[wei_off1 + mad24(o, (int)MLO_WEI_BSTRIDE, i)];
		}

		barrier(CLK_LOCAL_MEM_FENCE);

// convolve
		for (int olc = 0; olc < MLO_N_LCL_OUT_MAPS; ++olc)
		{
			// lcl in maps (in data tiles) is has the stride = MLO_N_MAPS_PERGROUP, weights are mapped accordingly

			for (int ilc = 0; ilc < MLO_N_LCL_IN_MAPS; ++ilc)
			{
				// read weights
				wei_stage[olc][ilc] = lcl_wei_stage[mad24(in_map_id, (int)MLO_N_LCL_OUT_MAPS, olc)][mad24(ilc, (int)MLO_N_MAPS_PERGROUP, in_map_id)];
				for (int ib = 0; ib < MLO_N_LCL_BATCHS;  ++ib)
				{
					out_tiles[ib][olc] += in_stage[ib][ilc] * (_FLOAT4)wei_stage[olc][ilc];
#if 0
					if (get_group_id(0) == 0 && get_group_id(1) == 0 && in_map_id == 0 && pix_id == 0 && olc == 0)
					{
						printf("k:c: 0 %d %d %d  %11.10f %11.10f %f %f\n",
							get_local_id(0),
							olc,
							ilc,
							out_tiles[ib][olc].s0,
							in_stage[ib][ilc].s0 * wei_stage[olc][ilc],
							in_stage[ib][ilc].s0,
							wei_stage[olc][ilc]
							);
					}
#endif

				}
			}
		}

#if MLO_N_MAPS_PERGROUP > 1
// exchange inputs with other MLO_N_MAPS_PERGROUP - 1 maps
		for (int im = 1; im < MLO_N_MAPS_PERGROUP; ++im)
		{

// mov to different output block
			// exchange data
//			if(pix_id < MLO_MAP_SZ4)
			{
				for(int ib = 0; ib < MLO_N_LCL_BATCHS; ++ib)
				{
					for(int ilc = 0; ilc < MLO_N_LCL_IN_MAPS; ++ilc)
					{
						barrier(CLK_LOCAL_MEM_FENCE);
						lcl_in_stage[lcl_id0] = in_stage[ib][ilc];
						int lcl_off = lcl_id0 + MLO_MAP_SZ4;
						lcl_off = (lcl_off >= MLO_N_MAPS_PERGROUP * MLO_MAP_SZ4) ? lcl_off - MLO_N_MAPS_PERGROUP * MLO_MAP_SZ4 : lcl_off;
						barrier(CLK_LOCAL_MEM_FENCE);
						in_stage[ib][ilc] = lcl_in_stage[lcl_off];
					}
				}
			}
			int imp = in_map_id + im;
			imp = (imp >= MLO_N_MAPS_PERGROUP) ? imp - MLO_N_MAPS_PERGROUP :  imp;

			// convolve
//			int wei_off1 = wei_off + in_map_id * MLO_WEI_BSTRIDE + imp * MLO_WEI_CHANNEL_STRIDE;
			for (int olc = 0; olc < MLO_N_LCL_OUT_MAPS; ++olc/*, wei_off1 += MLO_WEI_BSTRIDE*/)
			{
//				int wei_off2 = wei_off1;
				for (int ilc = 0; ilc < MLO_N_LCL_IN_MAPS; ++ilc/*, wei_off2 += MLO_WEI_CHANNEL_STRIDE * MLO_N_MAPS_PERGROUP*/)
				{
					// read weights
//					wei_stage[olc][ilc] = wei_ptr[wei_off2];
					wei_stage[olc][ilc] = lcl_wei_stage[mad24(in_map_id, (int)MLO_N_LCL_OUT_MAPS, olc)][mad24(ilc, (int)MLO_N_MAPS_PERGROUP, imp)];
					for (int ib = 0; ib < MLO_N_LCL_BATCHS;++ib)
					{
						out_tiles[ib][olc] += in_stage[ib][ilc] * (_FLOAT4)wei_stage[olc][ilc];
#if 0
						if (get_group_id(0) == 0 && get_group_id(1) == 0 && in_map_id == 0 && pix_id == 0 && olc == 0 )
						{
							printf("k:c: %d %d %d %d  %11.10f %11.10f %f %f\n",
								im,
								get_local_id(0),
								olc,
								ilc,
								out_tiles[ib][olc].s0,
								in_stage[ib][ilc].s0*wei_stage[olc][ilc],
								in_stage[ib][ilc].s0,
								wei_stage[olc][ilc]
								);
					}
#endif

					}
				}
			}

		}

#endif

	}

	if (in_map_id >= MLO_N_MAPS_PERGROUP || in_map_id*MLO_N_LCL_IN_MAPS >= MLO_N_INPUTS)
	{
		return;
	}

	out_block = out_grp_block * MLO_N_MAPS_PERGROUP + in_map_id;
	int out_off = batch_block * MLO_N_LCL_BATCHS * MLO_OUT_BATCH_STRIDE
		+ out_block * MLO_N_LCL_OUT_MAPS * MLO_OUT_CHANNEL_STRIDE
		+ pix_id * 4;

	int out_off1 = out_off;
	for (int ib = 0; ib < MLO_N_LCL_BATCHS
#if MLO_BATCH_ALIGNED == 0
		&& (batch_block*MLO_N_LCL_BATCHS + ib < MLO_BATCH_SZ)
#endif
		; ++ib, out_off1 += MLO_OUT_BATCH_STRIDE)
	{

		int out_off2 = out_off1;
		for (int olc = 0; olc < MLO_N_LCL_OUT_MAPS
#if MLO_OUTPUTS_ALIGNED == 0
			&& out_block* MLO_N_LCL_OUT_MAPS + olc < MLO_N_OUTPUTS
#endif
			; ++olc, out_off2 += MLO_OUT_CHANNEL_STRIDE)
		{

			_FLOAT  bias_val = 0;
#if MLO_CONV_BIAS
			bias_val = bias[out_block* MLO_N_LCL_OUT_MAPS + olc];
#endif
#if !MLO_DIVBY4

			// if the last one
			if (pix_id == MLO_MAP_SZ4 - 1)
			{
				for (int j = 0; j < MLO_C1x1_PIXLEFT; ++j)
				{
					out_ptr[out_off2 + j] = ((_FLOAT*)&out_tiles[ib][olc])[j] + bias_val;

				}

			}
			else
#endif
			{

				*((_FLOAT4*)&out_ptr[out_off2]) = (out_tiles[ib][olc] + (_FLOAT4)bias_val);
			}

#if 0
			if (out_block* MLO_N_LCL_OUT_MAPS + olc == 0 && pix_id == (444*720 +582) / 4)
			{
				printf("k:o: %d %d %d %d %d %d   %11.10f %f %11.10f\n",
					out_off2 + 2,
					get_group_id(0),
					get_group_id(1),
					in_map_id,
					pix_id,
					olc,
					out_ptr[out_off2 + 2],
					((_FLOAT*)&out_tiles[ib][olc])[2],
					bias_val
					);
			}
#endif

		}

	}

}

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

/*
Layout:

*/

__kernel void MLOpenConv1x1(
       const __global _FLOAT * restrict in_ptr,
       const __global _FLOAT * restrict wei_ptr,
#if MLO_CONV_BIAS
       const __global _FLOAT * bias,
#endif
 	  __global _FLOAT *out_ptr,
	   _FLOAT dummy_val // nothing
	   )
{
// KERNEL
// private buffers
	__private _FLOAT4 in_stage[MLO_N_LCL_BATCHS][MLO_N_LCL_IN_MAPS];
	__private _FLOAT wei_stage[MLO_N_LCL_OUT_MAPS][MLO_N_LCL_IN_MAPS];
	__private _FLOAT4 out_tiles[MLO_N_LCL_BATCHS][MLO_N_LCL_OUT_MAPS];
	__local _FLOAT lcl_wei_stage[MLO_N_MAPS_PERGROUP*MLO_N_LCL_OUT_MAPS][MLO_N_LCL_IN_MAPS*MLO_N_MAPS_PERGROUP];
#if MLO_N_MAPS_PERGROUP > 1
	__local _FLOAT4 lcl_in_stage[MLO_GRP_SZ0];

#endif

	int lcl_id0 = get_local_id(0);
	int in_map_id = 0; // map
	int pix_id = get_global_id(0);  // inside map
	in_map_id = pix_id / MLO_MAP_SZ4; // mad id inside group
	int out_grp_block = get_group_id(1); // block of outputs for the entire group
	int out_block = out_grp_block;
	int batch_block = get_group_id(2); // block of batchs
// multipe maps per group
//#if MLO_N_MAPS_PERGROUP > 1
	pix_id = (pix_id - in_map_id * MLO_MAP_SZ4);  // pixel inside map
	out_block = out_grp_block * MLO_N_MAPS_PERGROUP + in_map_id;
//#endif

	int in_off = batch_block * MLO_N_LCL_BATCHS * MLO_IN_BATCH_STRIDE
		+ in_map_id * MLO_IN_CHANNEL_STRIDE
				+ pix_id * 4;

	int wei_off = out_grp_block * MLO_N_MAPS_PERGROUP * MLO_N_LCL_OUT_MAPS * MLO_WEI_BSTRIDE;
	for (int j = 0; j < MLO_N_LCL_BATCHS; ++j)
	{
		for (int i = 0; i < MLO_N_LCL_OUT_MAPS; ++i)
		{
			out_tiles[j][i] = 0;
		}
	}
// over all input maps; with step == MLO_N_LCL_IN_MAPS * MLO_N_MAPS_PERGROUP; MLO_IN_LOOP
	for (int c = 0; c < MLO_IN_LOOP; ++c,
		in_off += MLO_IN_CHANNEL_STRIDE*MLO_N_LCL_IN_MAPS * MLO_N_MAPS_PERGROUP,
		wei_off += MLO_N_LCL_IN_MAPS * MLO_N_MAPS_PERGROUP * MLO_WEI_CHANNEL_STRIDE
//#if MLO_DIR_FORWARD==0
//			* MLO_N_OUTPUTS
//#endif
		)
	{
		barrier(CLK_LOCAL_MEM_FENCE);

// read data
// over all local batchs
		int in_off1 = in_off;
		for (int ib = 0; ib < MLO_N_LCL_BATCHS
#if MLO_BATCH_ALIGNED == 0
			&& (batch_block*MLO_N_LCL_BATCHS + ib < MLO_BATCH_SZ)
#endif
			; ++ib, in_off1 += MLO_IN_BATCH_STRIDE)
		{
			int in_off2 = in_off1;
// lcl in maps (in data tiles) is has the stride = MLO_N_MAPS_PERGROUP
			for (int ilc = 0; ilc < MLO_N_LCL_IN_MAPS; ++ilc, in_off2 += MLO_IN_CHANNEL_STRIDE * MLO_N_MAPS_PERGROUP)
			{
				// read data
				in_stage[ib][ilc] = 0;
				if (c*MLO_N_LCL_IN_MAPS * MLO_N_MAPS_PERGROUP + in_map_id + ilc* MLO_N_MAPS_PERGROUP < MLO_N_INPUTS)
				{

					in_stage[ib][ilc] = *(_FLOAT4*)&in_ptr[in_off2];

#if !MLO_DIVBY4

					// if the last one
					if (pix_id == MLO_MAP_SZ4 - 1)
					{
						for (int j = 3; j >= MLO_C1x1_PIXLEFT; --j)
						{
							((_FLOAT*)&in_stage[ib][ilc])[j] = 0;
						}
					}

#endif
				}
				/*
				if(c*MLO_N_LCL_IN_MAPS * MLO_N_MAPS_PERGROUP + in_map_id + ilc* MLO_N_MAPS_PERGROUP >= MLO_N_INPUTS)
				{
					in_stage[ib][ilc] = 0;
				}
				*/

			}
		}

// read weights
// KCRS weights layout
		int wei_off1 = wei_off;

		for (int l = lcl_id0; l < MLO_N_MAPS_PERGROUP * MLO_N_LCL_OUT_MAPS * MLO_N_MAPS_PERGROUP * MLO_N_LCL_IN_MAPS; l += MLO_GRP_SZ0)
		{
			int o = (int)(((float)l + 0.000001f) / (MLO_N_LCL_IN_MAPS*MLO_N_MAPS_PERGROUP));
			int i = -mad24(o,(int)(MLO_N_LCL_IN_MAPS*MLO_N_MAPS_PERGROUP),-l);
			lcl_wei_stage[o][i] = wei_ptr[wei_off1 + mad24(o, (int)MLO_WEI_BSTRIDE,i)];
		}

		barrier(CLK_LOCAL_MEM_FENCE);

// convolve
		for (int olc = 0; olc < MLO_N_LCL_OUT_MAPS; ++olc)
		{
			// lcl in maps (in data tiles) is has the stride = MLO_N_MAPS_PERGROUP, weights are mapped accordingly

			for (int ilc = 0; ilc < MLO_N_LCL_IN_MAPS; ++ilc)
			{
				// read weights
				wei_stage[olc][ilc] = lcl_wei_stage[mad24(in_map_id, (int)MLO_N_LCL_OUT_MAPS, olc)][mad24(in_map_id, (int)MLO_N_LCL_IN_MAPS, ilc)];
				for (int ib = 0; ib < MLO_N_LCL_BATCHS;  ++ib)
				{
					out_tiles[ib][olc] += in_stage[ib][ilc] * (_FLOAT4)wei_stage[olc][ilc];
#if 0
					if (get_group_id(0) == 312 && get_group_id(1) == 0 && in_map_id == 0 && pix_id == 80065 && olc == 0)
					{
						printf("k:c: 0 %d %d %d %d  %11.10f %11.10f %f %f\n",
							wei_off2,
							get_local_id(0),
							olc,
							ilc,
							out_tiles[ib][olc].s2,
							in_stage[ib][ilc].s2 * wei_stage[olc][ilc],
							in_stage[ib][ilc].s2,
							wei_stage[olc][ilc]
							);
					}
#endif

				}
			}
		}

#if MLO_N_MAPS_PERGROUP > 1
// exchange inputs with other MLO_N_MAPS_PERGROUP - 1 maps
		for (int im = 1; im < MLO_N_MAPS_PERGROUP; ++im)
		{

// mov to different output block
			// exchange data
//			if(pix_id < MLO_MAP_SZ4)
			{
				for(int ib = 0; ib < MLO_N_LCL_BATCHS; ++ib)
				{
					for(int ilc = 0; ilc < MLO_N_LCL_IN_MAPS; ++ilc)
					{
						barrier(CLK_LOCAL_MEM_FENCE);
						lcl_in_stage[lcl_id0] = in_stage[ib][ilc];
						int lcl_off = lcl_id0 + MLO_MAP_SZ4;
						lcl_off = (lcl_off >= MLO_N_MAPS_PERGROUP * MLO_MAP_SZ4) ? lcl_off - MLO_N_MAPS_PERGROUP * MLO_MAP_SZ4 : lcl_off;
						barrier(CLK_LOCAL_MEM_FENCE);
						in_stage[ib][ilc] = lcl_in_stage[lcl_off];
					}
				}
			}
			int imp = in_map_id + im;
			imp = (imp >= MLO_N_MAPS_PERGROUP) ? imp - MLO_N_MAPS_PERGROUP :  imp;

			// convolve
//			int wei_off1 = wei_off + in_map_id * MLO_WEI_BSTRIDE + imp * MLO_WEI_CHANNEL_STRIDE;
			for (int olc = 0; olc < MLO_N_LCL_OUT_MAPS; ++olc/*, wei_off1 += MLO_WEI_BSTRIDE*/)
			{
				int wei_off2 = wei_off1;
				for (int ilc = 0; ilc < MLO_N_LCL_IN_MAPS; ++ilc/*, wei_off2 += MLO_WEI_CHANNEL_STRIDE * MLO_N_MAPS_PERGROUP*/)
				{
					// read weights
//					wei_stage[olc][ilc] = wei_ptr[wei_off2];
					wei_stage[olc][ilc] = lcl_wei_stage[mad24(in_map_id, (int)MLO_N_LCL_OUT_MAPS, olc)][mad24(imp, (int)MLO_N_LCL_IN_MAPS, ilc)];
					for (int ib = 0; ib < MLO_N_LCL_BATCHS;++ib)
					{
						out_tiles[ib][olc] += in_stage[ib][ilc] * (_FLOAT4)wei_stage[olc][ilc];
#if 0
						if (get_group_id(0) == 0 && get_group_id(1) == 0 && in_map_id == 4 && pix_id == 27 && olc == 1 )
						{
							printf("k:c: %d %d %d %d %d  %11.10f %11.10f %f %f\n",
								im,
								wei_off2,
								get_local_id(0),
								olc,
								ilc,
								out_tiles[ib][olc].s1,
								in_stage[ib][ilc].s1*wei_stage[olc][ilc],
								in_stage[ib][ilc].s1,
								wei_stage[olc][ilc]
								);
					}
#endif

					}
				}
			}

		}

#endif

	}

	if (in_map_id >= MLO_N_MAPS_PERGROUP || in_map_id*MLO_N_LCL_IN_MAPS >= MLO_N_INPUTS)
	{
		return;
	}

	out_block = out_grp_block * MLO_N_MAPS_PERGROUP + in_map_id;
	int out_off = batch_block * MLO_N_LCL_BATCHS * MLO_OUT_BATCH_STRIDE
		+ out_block * MLO_N_LCL_OUT_MAPS * MLO_OUT_CHANNEL_STRIDE
		+ pix_id * 4;

	int out_off1 = out_off;
	for (int ib = 0; ib < MLO_N_LCL_BATCHS
#if MLO_BATCH_ALIGNED == 0
		&& (batch_block*MLO_N_LCL_BATCHS + ib < MLO_BATCH_SZ)
#endif
		; ++ib, out_off1 += MLO_OUT_BATCH_STRIDE)
	{

		int out_off2 = out_off1;
		for (int olc = 0; olc < MLO_N_LCL_OUT_MAPS
#if MLO_OUTPUTS_ALIGNED == 0
			&& out_block* MLO_N_LCL_OUT_MAPS + olc < MLO_N_OUTPUTS
#endif
			; ++olc, out_off2 += MLO_OUT_CHANNEL_STRIDE)
		{

			_FLOAT  bias_val = 0;
#if MLO_CONV_BIAS
			bias_val = bias[out_block* MLO_N_LCL_OUT_MAPS + olc];
#endif
#if !MLO_DIVBY4

			// if the last one
			if (pix_id == MLO_MAP_SZ4 - 1)
			{
				for (int j = 0; j < MLO_C1x1_PIXLEFT; ++j)
				{
					out_ptr[out_off2 + j] = ((_FLOAT*)&out_tiles[ib][olc])[j] + bias_val;

				}

			}
			else
#endif
			{

				*((_FLOAT4*)&out_ptr[out_off2]) = (out_tiles[ib][olc] + (_FLOAT4)bias_val);
			}

#if 0
			if (out_block* MLO_N_LCL_OUT_MAPS + olc == 0 && pix_id == (444*720 +582) / 4)
			{
				printf("k:o: %d %d %d %d %d %d   %11.10f %f %11.10f\n",
					out_off2 + 2,
					get_group_id(0),
					get_group_id(1),
					in_map_id,
					pix_id,
					olc,
					out_ptr[out_off2 + 2],
					((_FLOAT*)&out_tiles[ib][olc])[2],
					bias_val
					);
			}
#endif

		}

	}

}


JavaCL: Fixed rgba2hsla routine

JavaCL: Fixed rgba2hsla routine

#ifndef _LIBCL_RGBA_2_HSLA_CL_
#define _LIBCL_RGBA_2_HSLA_CL_

inline float4 rgba2hsla(float4 rgba) {
	float
		r = rgba.x,
		g = rgba.y,
		b = rgba.z,
		a = rgba.w;

	float mn = min(r, min(g, b));
	float mx = max(r, max(g, b));

	float l = (mn + mx) / 2.f;
	float s, h;
	if (mn == mx) {
		s = h = 0;
	} else {
		float diff = mx - mn;
		float sum = mx + mn;
		if (l < 0.5f)
			s = diff / sum;
		else
			s = diff / (2.0f - sum);
		if (r == mx)
			h = (g - b) / diff;
		else if (g == mx)
			h = 2.0f + (b - r) / diff;
		else //if (b == mx)
			h = 4.0f + (r - g) / diff;
	}
	h = clamp(h / 6.0f, 0.0f, 1.0f);
	return (float4)(h, s, l, a);
}

#endif // _LIBCL_HSLA_2_RGBA_CL_

#ifndef _LIBCL_RGBA_2_HSLA_CL_
#define _LIBCL_RGBA_2_HSLA_CL_

inline float4 rgba2hsla(float4 rgba) {
	float
		r = rgba.x,
		g = rgba.y,
		b = rgba.z,
		a = rgba.w;

	float mn = min(r, min(g, b));
	float mx = max(r, max(g, b));

	float l = (mn + mx) / 2.f;
	float s, h;
	if (mn == mx) {
		s = h = 0;
	} else {
		float diff = mx - mn;
		float sum = mx + mn;
		if (l < 0.5f)
			s = diff / sum;
		else
			s = diff / (2.0f - sum);
		if (r == mx)
			h = (g - b) / diff;
		else if (g == mx)
			h = 2.0f + (b - r) / diff;
		else //if (b == mx)
			h = 4.0f + (r - g) / diff;
	}
	h = clamp(h / 6.0f, 0, 1);
	return (float4)(h, s, l, a);
}

#endif // _LIBCL_HSLA_2_RGBA_CL_


fix llvm3.7 compiler_function_qualifiers utest fail.

Must explicit use void if function don't have parameter.

Signed-off-by: Yang Rong <78759e37dc7114caed18f74e7515c5cb519dbf6d@intel.com>
Reviewed-by: Ruiling Song <286a174c1339c6eff91abc41c3a1012c95030c95@intel.com>
Reviewed-by: Igor Gnatenko <c869b0bfe2cf1da26c2efd33f6d6d74ddcbbdd2b@gmail.com>

/* test OpenCL 1.1 Function Qualifiers (section 6.7) */
kernel void compiler_function_qualifiers(void)
__attribute__((vec_type_hint(float)))
__attribute__((work_group_size_hint(4,1,1)))
__attribute__((reqd_work_group_size(4,1,1)));

kernel void compiler_function_qualifiers(void)
{
}

/* test OpenCL 1.1 Function Qualifiers (section 6.7) */
kernel void compiler_function_qualifiers()
__attribute__((vec_type_hint(float)))
__attribute__((work_group_size_hint(4,1,1)))
__attribute__((reqd_work_group_size(4,1,1)));

kernel void compiler_function_qualifiers()
{
}


Corrected syntax in constants declaration

//__author__ = "Konstantin Klementiev, Roman Chernikov"
//__date__ = "10 Apr 2015"

#ifdef cl_khr_fp64
#if __OPENCL_VERSION__<120
#pragma OPENCL EXTENSION cl_khr_fp64: enable
#endif
#endif

//#include "materials.cl"
//__constant float Pi = 3.141592653589793;
__constant const double twoPi = (double)6.283185307179586476;
__constant const double invTwoPi = (double)(1./6.283185307179586476);
__constant const float invFourPi = (float)0.07957747154594767;
__constant float2 cmp0 = (float2)(0, 0);
__constant float2 cmpi1 = (float2)(0, 1);
__constant double2 cmp0_d = (double2)(0, 0);
__constant double2 cmpi1_d = (double2)(0, 1);
__constant const double2 cfactor = (double2)(0, -0.07957747154594767);

float2 prod_c(float2 a, float2 b)
{
    return (float2)(a.x*b.x - a.y*b.y, a.y*b.x + a.x*b.y);
}
double2 prod_c_d(double2 a, double2 b)
{
    return (double2)(a.x*b.x - a.y*b.y, a.y*b.x + a.x*b.y);
}
double to2pi(double val)
{
	return val - trunc(val*invTwoPi) * twoPi;
}
//double dot3(double3 a, double3 b)
//{
//    return (double)(a.x*b.x + a.y*b.y + a.z*b.z);
//}

//float2 conj_c(float2 a)
//  {
//    return (float2)(a.x, -a.y);
//  }
//float abs_c(float2 a)
//  {
//    return sqrt(a.x*a.x + a.y*a.y);
//  }
//float abs_c2(float2 a)
//  {
//    return (a.x*a.x + a.y*a.y);
//  }

//float arg_c(float2 a)
//  {
//    if(a.x > 0)
//      {
//        return atan(a.y / a.x);
//      }
//    else if(a.x < 0 && a.y >= 0)
//      {
//        return atan(a.y / a.x) + Pi;
//      }
//    else if(a.x < 0 && a.y < 0)
//      {
//        return atan(a.y / a.x) - Pi;
//      }
//    else if(a.x == 0 && a.y > 0)
//      {
//        return Pi/2;
//      }
//    else if(a.x == 0 && a.y < 0)
//      {
//        return -Pi/2;
//      }
//    else
//      {
//        return 0;
//      }
//  }

__kernel void integrate_kirchhoff(
                    //const unsigned int imageLength,
                    const unsigned int fullnrays,
                    __global float* x_glo,
                    __global float* y_glo,
                    __global float* z_glo,
                    __global float* cosGamma,
                    __global float2* Es,
                    __global float2* Ep,
                    __global float* k,
                    __global float3* beamOEglo,
                    __global float3* oe_surface_normal,
//                    __global float* beam_OE_loc_path,
                    __global float2* KirchS_gl,
                    __global float2* KirchP_gl,
                    __global float2* KirchA_gl,
                    __global float2* KirchB_gl,
                    __global float2* KirchC_gl)
{
    unsigned int i;
//    unsigned int imageLength = get_global_size(0);
    float3 beam_coord_glo, beam_angle_glo;
    float2 gi, giEs, giEp, cfactor;
    float2 KirchS_loc, KirchP_loc;
    float2 KirchA_loc, KirchB_loc, KirchC_loc;
    float pathAfter, cosAlpha, cr, sinphase, cosphase;
    unsigned int ii_screen = get_global_id(0);
    float phase;
    float invPathAfter, kip;

    KirchS_loc = cmp0;
    KirchP_loc = cmp0;
    KirchA_loc = cmp0;
    KirchB_loc = cmp0;
    KirchC_loc = cmp0;

    beam_coord_glo.x = x_glo[ii_screen];
    beam_coord_glo.y = y_glo[ii_screen];
    beam_coord_glo.z = z_glo[ii_screen];
    for (i=0; i<fullnrays; i++)
      {
        beam_angle_glo = beam_coord_glo - beamOEglo[i];
        pathAfter = length(beam_angle_glo);
        invPathAfter = 1. / pathAfter;
//        invPathAfter = rsqrt(dot(beam_angle_glo, beam_angle_glo));
        cosAlpha = dot(beam_angle_glo, oe_surface_normal[i]) * invPathAfter;
        phase = k[i] * pathAfter;
//        phase = k[i] / invPathAfter;
        kip = k[i] * invPathAfter;
        cr = kip * (cosAlpha + cosGamma[i]);
        sinphase = sincos(phase, &cosphase);
        gi = (float2)(cr * cosphase, cr * sinphase);
        giEs = prod_c(gi, Es[i]);
        giEp = prod_c(gi, Ep[i]);
        KirchS_loc += giEs;
        KirchP_loc += giEp;
        gi = k[i] * kip * (giEs+giEp);
        KirchA_loc += prod_c(gi, beam_angle_glo.x);
        KirchB_loc += prod_c(gi, beam_angle_glo.y);
        KirchC_loc += prod_c(gi, beam_angle_glo.z);
      }
  mem_fence(CLK_LOCAL_MEM_FENCE);

  cfactor = -cmpi1 * invFourPi;
  KirchS_gl[ii_screen] = prod_c(cfactor, KirchS_loc);
  KirchP_gl[ii_screen] = prod_c(cfactor, KirchP_loc);
  KirchA_gl[ii_screen] = KirchA_loc * invFourPi;
  KirchB_gl[ii_screen] = KirchB_loc * invFourPi;
  KirchC_gl[ii_screen] = KirchC_loc * invFourPi;

  mem_fence(CLK_LOCAL_MEM_FENCE);
}

//__kernel void integrate_kirchhoff_d(
//                    //const unsigned int imageLength,
//                    const unsigned int fullnrays,
//                    __global double* x_glo,
//                    __global double* y_glo,
//                    __global double* z_glo,
//                    __global double* cosGamma,
//                    __global double2* Es,
//                    __global double2* Ep,
//                    __global double* k,
//                    __global double3* beamOEglo,
//                    __global double3* oe_surface_normal,
////                    __global double* beam_OE_loc_path,
//                    __global double2* KirchS_gl,
//                    __global double2* KirchP_gl,
//                    __global double2* KirchA_gl,
//                    __global double2* KirchB_gl,
//                    __global double2* KirchC_gl)
//{
//    unsigned int i;
////    unsigned int imageLength = get_global_size(0);
//    double3 beam_coord_glo, beam_angle_glo;
//    double2 gi, giEs, giEp;
//    double2 KirchS_loc, KirchP_loc;
//    double2 KirchA_loc, KirchB_loc, KirchC_loc;
////    double pathAfter, cosAlpha, cr;
//    double cosAlpha, cr;
//    float sinphase, cosphase;
//    double phase;
//    double invPathAfter, kp;
//    unsigned int ii_screen = get_global_id(0);
//
//    KirchS_loc = cmp0_d;
//    KirchP_loc = cmp0_d;
//    KirchA_loc = cmp0_d;
//    KirchB_loc = cmp0_d;
//    KirchC_loc = cmp0_d;
//
//    beam_coord_glo.x = x_glo[ii_screen];
//    beam_coord_glo.y = y_glo[ii_screen];
//    beam_coord_glo.z = z_glo[ii_screen];
//    for (i=0; i<fullnrays; i++)
//    {
//        beam_angle_glo = beam_coord_glo - beamOEglo[i];
////        pathAfter = length(beam_angle_glo);
////        invPathAfter = 1. / pathAfter;
//        invPathAfter = rsqrt(dot(beam_angle_glo, beam_angle_glo));
////        phase = to2pi(k[i] * pathAfter);
//        phase = to2pi(k[i] / invPathAfter);
//        kp = k[i] * invPathAfter;
//        cosAlpha = dot(beam_angle_glo, oe_surface_normal[i]) * invPathAfter;
//        cr = kp * (cosAlpha + cosGamma[i]);
//        sinphase = sincos((float)phase, &cosphase);
//        gi = (double2)((double)cosphase, (double)sinphase);
//        giEs = prod_c_d(gi, Es[i]);
//        giEp = prod_c_d(gi, Ep[i]);
//        KirchS_loc += giEs * cr;
//        KirchP_loc += giEp * cr;
//        gi = k[i] * kp * (giEs + giEp);
//        KirchA_loc += gi * beam_angle_glo.x;
//        KirchB_loc += gi * beam_angle_glo.y;
//        KirchC_loc += gi * beam_angle_glo.z;
//    }
//    mem_fence(CLK_LOCAL_MEM_FENCE);
//
//    KirchS_gl[ii_screen] = prod_c_d(KirchS_loc, cfactor);
//    KirchP_gl[ii_screen] = prod_c_d(KirchP_loc, cfactor);
//    KirchA_gl[ii_screen] = KirchA_loc * invFourPi;
//    KirchB_gl[ii_screen] = KirchB_loc * invFourPi;
//    KirchC_gl[ii_screen] = KirchC_loc * invFourPi;
//
//    mem_fence(CLK_LOCAL_MEM_FENCE);
//}

//__kernel void integrate_fraunhofer(
//                    const unsigned int imageLength,
//                    const unsigned int fullnrays,
//                    const float chbar,
//                    __global float* cosGamma,
//                    __global float* a_glo,
//                    __global float* b_glo,
//                    __global float* c_glo,
//                    __global float2* Es,
//                    __global float2* Ep,
//                    __global float* E_loc,
//                    __global float3* beamOEglo,
//                    __global float3* oe_surface_normal,
//                    __global float* beam_OE_loc_path,
//                    __global float2* KirchS_gl,
//                    __global float2* KirchP_gl)
//
//{
//    unsigned int i;
//
////    float3 beam_coord_glo;
//    float3 beam_angle_glo;
//    float2 gi, KirchS_loc, KirchP_loc;
//    float pathAfter, cosAlpha, cr;
//    unsigned int ii_screen = get_global_id(0);
////    float wavelength;
//    float k, phase;
//
//    KirchS_loc = (float2)(0, 0);
//    KirchP_loc = KirchS_loc;
//
//    beam_angle_glo.x = a_glo[ii_screen];
//    beam_angle_glo.y = b_glo[ii_screen];
//    beam_angle_glo.z = c_glo[ii_screen];
//    //if (ii_screen==128 || ii_screen==129) printf("Pix %i, beam_coord_glo %0.32v3f\n",ii_screen, beam_coord_glo);
//    for (i=0; i<fullnrays; i++)
//      {
//        //printf("point %i\n",i);
//        pathAfter = -dot(beam_angle_glo, beamOEglo[i]);
//        cosAlpha = dot(beam_angle_glo, oe_surface_normal[i]);
//        k = E_loc[i] / chbar * 1.e7;
////        wavelength = twoPi / k;
//        phase = k * (pathAfter + beam_OE_loc_path[i]);
//        cr = (cosAlpha + cosGamma[i]) / pathAfter;
//        gi = (float2)(cr * cos(phase), cr * sin(phase));
//        KirchS_loc += prod_c(gi, Es[i]);
//        KirchP_loc += prod_c(gi, Ep[i]);
//      }
//  mem_fence(CLK_LOCAL_MEM_FENCE);
//
//  KirchS_gl[ii_screen] = -prod_c(cmpi1*k*invFourPi, KirchS_loc);
//  KirchP_gl[ii_screen] = -prod_c(cmpi1*k*invFourPi, KirchP_loc);
//  mem_fence(CLK_LOCAL_MEM_FENCE);
//}

//__author__ = "Konstantin Klementiev, Roman Chernikov"
//__date__ = "10 Apr 2015"

#ifdef cl_khr_fp64
#if __OPENCL_VERSION__<120
#pragma OPENCL EXTENSION cl_khr_fp64: enable
#endif
#endif

//#include "materials.cl"
//__constant float Pi = 3.141592653589793;
__constant const double twoPi = (double)6.283185307179586476;
__constant const double invTwoPi = (double)(1./twoPi);
__constant const float invFourPi = (float)0.07957747154594767;
__constant float2 cmp0 = (float2)(0, 0);
__constant float2 cmpi1 = (float2)(0, 1);
__constant double2 cmp0_d = (double2)(0, 0);
__constant double2 cmpi1_d = (double2)(0, 1);
__constant const double2 cfactor = (double2)(0, -invFourPi);

float2 prod_c(float2 a, float2 b)
{
    return (float2)(a.x*b.x - a.y*b.y, a.y*b.x + a.x*b.y);
}
double2 prod_c_d(double2 a, double2 b)
{
    return (double2)(a.x*b.x - a.y*b.y, a.y*b.x + a.x*b.y);
}
double to2pi(double val)
{
	return val - trunc(val*invTwoPi) * twoPi;
}
//double dot3(double3 a, double3 b)
//{
//    return (double)(a.x*b.x + a.y*b.y + a.z*b.z);
//}

//float2 conj_c(float2 a)
//  {
//    return (float2)(a.x, -a.y);
//  }
//float abs_c(float2 a)
//  {
//    return sqrt(a.x*a.x + a.y*a.y);
//  }
//float abs_c2(float2 a)
//  {
//    return (a.x*a.x + a.y*a.y);
//  }

//float arg_c(float2 a)
//  {
//    if(a.x > 0)
//      {
//        return atan(a.y / a.x);
//      }
//    else if(a.x < 0 && a.y >= 0)
//      {
//        return atan(a.y / a.x) + Pi;
//      }
//    else if(a.x < 0 && a.y < 0)
//      {
//        return atan(a.y / a.x) - Pi;
//      }
//    else if(a.x == 0 && a.y > 0)
//      {
//        return Pi/2;
//      }
//    else if(a.x == 0 && a.y < 0)
//      {
//        return -Pi/2;
//      }
//    else
//      {
//        return 0;
//      }
//  }

__kernel void integrate_kirchhoff(
                    //const unsigned int imageLength,
                    const unsigned int fullnrays,
                    __global float* x_glo,
                    __global float* y_glo,
                    __global float* z_glo,
                    __global float* cosGamma,
                    __global float2* Es,
                    __global float2* Ep,
                    __global float* k,
                    __global float3* beamOEglo,
                    __global float3* oe_surface_normal,
//                    __global float* beam_OE_loc_path,
                    __global float2* KirchS_gl,
                    __global float2* KirchP_gl,
                    __global float2* KirchA_gl,
                    __global float2* KirchB_gl,
                    __global float2* KirchC_gl)
{
    unsigned int i;
//    unsigned int imageLength = get_global_size(0);
    float3 beam_coord_glo, beam_angle_glo;
    float2 gi, giEs, giEp, cfactor;
    float2 KirchS_loc, KirchP_loc;
    float2 KirchA_loc, KirchB_loc, KirchC_loc;
    float pathAfter, cosAlpha, cr, sinphase, cosphase;
    unsigned int ii_screen = get_global_id(0);
    float phase;
    float invPathAfter, kip;

    KirchS_loc = cmp0;
    KirchP_loc = cmp0;
    KirchA_loc = cmp0;
    KirchB_loc = cmp0;
    KirchC_loc = cmp0;

    beam_coord_glo.x = x_glo[ii_screen];
    beam_coord_glo.y = y_glo[ii_screen];
    beam_coord_glo.z = z_glo[ii_screen];
    for (i=0; i<fullnrays; i++)
      {
        beam_angle_glo = beam_coord_glo - beamOEglo[i];
        pathAfter = length(beam_angle_glo);
        invPathAfter = 1. / pathAfter;
//        invPathAfter = rsqrt(dot(beam_angle_glo, beam_angle_glo));
        cosAlpha = dot(beam_angle_glo, oe_surface_normal[i]) * invPathAfter;
        phase = k[i] * pathAfter;
//        phase = k[i] / invPathAfter;
        kip = k[i] * invPathAfter;
        cr = kip * (cosAlpha + cosGamma[i]);
        sinphase = sincos(phase, &cosphase);
        gi = (float2)(cr * cosphase, cr * sinphase);
        giEs = prod_c(gi, Es[i]);
        giEp = prod_c(gi, Ep[i]);
        KirchS_loc += giEs;
        KirchP_loc += giEp;
        gi = k[i] * kip * (giEs+giEp);
        KirchA_loc += prod_c(gi, beam_angle_glo.x);
        KirchB_loc += prod_c(gi, beam_angle_glo.y);
        KirchC_loc += prod_c(gi, beam_angle_glo.z);
      }
  mem_fence(CLK_LOCAL_MEM_FENCE);

  cfactor = -cmpi1 * invFourPi;
  KirchS_gl[ii_screen] = prod_c(cfactor, KirchS_loc);
  KirchP_gl[ii_screen] = prod_c(cfactor, KirchP_loc);
  KirchA_gl[ii_screen] = KirchA_loc * invFourPi;
  KirchB_gl[ii_screen] = KirchB_loc * invFourPi;
  KirchC_gl[ii_screen] = KirchC_loc * invFourPi;

  mem_fence(CLK_LOCAL_MEM_FENCE);
}

//__kernel void integrate_kirchhoff_d(
//                    //const unsigned int imageLength,
//                    const unsigned int fullnrays,
//                    __global double* x_glo,
//                    __global double* y_glo,
//                    __global double* z_glo,
//                    __global double* cosGamma,
//                    __global double2* Es,
//                    __global double2* Ep,
//                    __global double* k,
//                    __global double3* beamOEglo,
//                    __global double3* oe_surface_normal,
////                    __global double* beam_OE_loc_path,
//                    __global double2* KirchS_gl,
//                    __global double2* KirchP_gl,
//                    __global double2* KirchA_gl,
//                    __global double2* KirchB_gl,
//                    __global double2* KirchC_gl)
//{
//    unsigned int i;
////    unsigned int imageLength = get_global_size(0);
//    double3 beam_coord_glo, beam_angle_glo;
//    double2 gi, giEs, giEp;
//    double2 KirchS_loc, KirchP_loc;
//    double2 KirchA_loc, KirchB_loc, KirchC_loc;
////    double pathAfter, cosAlpha, cr;
//    double cosAlpha, cr;
//    float sinphase, cosphase;
//    double phase;
//    double invPathAfter, kp;
//    unsigned int ii_screen = get_global_id(0);
//
//    KirchS_loc = cmp0_d;
//    KirchP_loc = cmp0_d;
//    KirchA_loc = cmp0_d;
//    KirchB_loc = cmp0_d;
//    KirchC_loc = cmp0_d;
//
//    beam_coord_glo.x = x_glo[ii_screen];
//    beam_coord_glo.y = y_glo[ii_screen];
//    beam_coord_glo.z = z_glo[ii_screen];
//    for (i=0; i<fullnrays; i++)
//    {
//        beam_angle_glo = beam_coord_glo - beamOEglo[i];
////        pathAfter = length(beam_angle_glo);
////        invPathAfter = 1. / pathAfter;
//        invPathAfter = rsqrt(dot(beam_angle_glo, beam_angle_glo));
////        phase = to2pi(k[i] * pathAfter);
//        phase = to2pi(k[i] / invPathAfter);
//        kp = k[i] * invPathAfter;
//        cosAlpha = dot(beam_angle_glo, oe_surface_normal[i]) * invPathAfter;
//        cr = kp * (cosAlpha + cosGamma[i]);
//        sinphase = sincos((float)phase, &cosphase);
//        gi = (double2)((double)cosphase, (double)sinphase);
//        giEs = prod_c_d(gi, Es[i]);
//        giEp = prod_c_d(gi, Ep[i]);
//        KirchS_loc += giEs * cr;
//        KirchP_loc += giEp * cr;
//        gi = k[i] * kp * (giEs + giEp);
//        KirchA_loc += gi * beam_angle_glo.x;
//        KirchB_loc += gi * beam_angle_glo.y;
//        KirchC_loc += gi * beam_angle_glo.z;
//    }
//    mem_fence(CLK_LOCAL_MEM_FENCE);
//
//    KirchS_gl[ii_screen] = prod_c_d(KirchS_loc, cfactor);
//    KirchP_gl[ii_screen] = prod_c_d(KirchP_loc, cfactor);
//    KirchA_gl[ii_screen] = KirchA_loc * invFourPi;
//    KirchB_gl[ii_screen] = KirchB_loc * invFourPi;
//    KirchC_gl[ii_screen] = KirchC_loc * invFourPi;
//
//    mem_fence(CLK_LOCAL_MEM_FENCE);
//}

//__kernel void integrate_fraunhofer(
//                    const unsigned int imageLength,
//                    const unsigned int fullnrays,
//                    const float chbar,
//                    __global float* cosGamma,
//                    __global float* a_glo,
//                    __global float* b_glo,
//                    __global float* c_glo,
//                    __global float2* Es,
//                    __global float2* Ep,
//                    __global float* E_loc,
//                    __global float3* beamOEglo,
//                    __global float3* oe_surface_normal,
//                    __global float* beam_OE_loc_path,
//                    __global float2* KirchS_gl,
//                    __global float2* KirchP_gl)
//
//{
//    unsigned int i;
//
////    float3 beam_coord_glo;
//    float3 beam_angle_glo;
//    float2 gi, KirchS_loc, KirchP_loc;
//    float pathAfter, cosAlpha, cr;
//    unsigned int ii_screen = get_global_id(0);
////    float wavelength;
//    float k, phase;
//
//    KirchS_loc = (float2)(0, 0);
//    KirchP_loc = KirchS_loc;
//
//    beam_angle_glo.x = a_glo[ii_screen];
//    beam_angle_glo.y = b_glo[ii_screen];
//    beam_angle_glo.z = c_glo[ii_screen];
//    //if (ii_screen==128 || ii_screen==129) printf("Pix %i, beam_coord_glo %0.32v3f\n",ii_screen, beam_coord_glo);
//    for (i=0; i<fullnrays; i++)
//      {
//        //printf("point %i\n",i);
//        pathAfter = -dot(beam_angle_glo, beamOEglo[i]);
//        cosAlpha = dot(beam_angle_glo, oe_surface_normal[i]);
//        k = E_loc[i] / chbar * 1.e7;
////        wavelength = twoPi / k;
//        phase = k * (pathAfter + beam_OE_loc_path[i]);
//        cr = (cosAlpha + cosGamma[i]) / pathAfter;
//        gi = (float2)(cr * cos(phase), cr * sin(phase));
//        KirchS_loc += prod_c(gi, Es[i]);
//        KirchP_loc += prod_c(gi, Ep[i]);
//      }
//  mem_fence(CLK_LOCAL_MEM_FENCE);
//
//  KirchS_gl[ii_screen] = -prod_c(cmpi1*k*invFourPi, KirchS_loc);
//  KirchP_gl[ii_screen] = -prod_c(cmpi1*k*invFourPi, KirchP_loc);
//  mem_fence(CLK_LOCAL_MEM_FENCE);
//}