switched to (my) terminal colors, factored some stuff out into functions, added a litte update test

(proclaim '(optimize (speed 0) (safety 3) (debug 3)))

(ql:quickload '(alexandria iterate anaphora cl-cairo2 cl-cairo2-xlib cl-pango) :silent t)

(defpackage arboreta
  (:use cl iterate anaphora cl-cairo2))

(in-package arboreta)

(defparameter context nil)
(defparameter surface nil)
(defparameter layout nil)
(defparameter font nil)

(defparameter w 600)
(defparameter h 400)

(defparameter window-tree nil)

(defstruct window
	(x 0 :type fixnum)
	(y 0 :type fixnum)
	(width 0 :type fixnum)
	(height 0 :type fixnum)
	(subwindows nil))

(defun show-test-unicode ()
	(pango:pango_layout_set_text layout
     (format nil "~{~a~%~}"
       '("Hello, glorious pango text rendering!"
         "いあだ〜〜ずかしいです〜〜"
         "Τη γλώσσα μου έδωσαν ελληνική"
         "ᚠᛇᚻ᛫ᛒᛦᚦ᛫ᚠᚱᚩᚠᚢᚱ᛫ᚠᛁᚱᚪ᛫ᚷᛖᚻᚹᛦᛚᚳᚢᛗ"
         "ಬಾ ಇಲ್ಲಿ ಸಂಭವಿಸು ಇಂದೆನ್ನ ಹೃದಯದಲಿ "
         "मैं काँच खा सकता हूँ और मुझे उससे कोई चोट नहीं पहुंचती "))
     -1))

(defun pango-update ()
	(pango:pango_cairo_update_layout (slot-value *context* 'cairo::pointer) layout)
	(pango:pango_cairo_show_layout (slot-value *context* 'cairo::pointer) layout))

(defun flush-surface ()
	(surface-flush surface)
   (cairo::sync context))

(defun main ()
   (setf context (create-xlib-image-context w h :window-name "pango-test"))
   (setf surface (get-target context))

   (with-context (context)
      (set-source-rgb 37/255 46/255 50/255)
      (rectangle 0 0 w h)
      (fill-path)

      ;; had to do it without the helper macros, because they cause context errors for some reason
      ;; you might not have this font, change it to a good non-bitmap monospaced font you do have.

      ;; we're going to need to macro the shit out of this

      (new-path)
      (move-to 0 0)
      (set-source-rgb 81/255 81/255 81/255)

      (setf layout (pango:pango_cairo_create_layout (slot-value cairo:*context* 'cairo::pointer)))
      (setf font (pango:pango_font_description_from_string "Fantasque Sans Mono 10"))
      (pango:pango_layout_set_font_description layout font)

      (iter (with str = "Once upon a midnight dreary, while I pondered, weak and weary...")
				(for x from 0 to (length str))
				(set-source-rgb 37/255 46/255 50/255)
				(rectangle 0 0 w h)
            (fill-path)
				(new-path)
            (move-to 0 0)
            (set-source-rgb 148/255 163/255 165/255)
				(pango:pango_layout_set_text layout (subseq str 0 x) -1)
				(pango-update)
				(flush-surface)
				(sleep 0.1)))

      (princ "press enter here to exit")
      (finish-output)
      (when (read-line)
         (cairo:destroy context)
         (sb-ext:exit)))

;; (sb-ext:save-lisp-and-die "arboreta" :toplevel #'main :executable t)
(main)

(proclaim '(optimize (speed 0) (safety 3) (debug 3)))

(ql:quickload '(alexandria iterate anaphora cl-cairo2 cl-cairo2-xlib cl-pango) :silent t)

(defpackage arboreta
  (:use cl iterate anaphora cl-cairo2))

(in-package arboreta)

(defparameter context nil)
(defparameter surface nil)
(defparameter layout nil)
(defparameter font nil)

(defparameter w 600)
(defparameter h 400)

(defun main ()
   (setf context (create-xlib-image-context w h :window-name "pango-test"))
   (setf surface (get-target context))

   (with-context (context)
      (set-source-rgb 1 1 1)
      (rectangle 0 0 w h)
      (fill-path)

      ;; had to do it without the helper macros, because they cause context errors for some reason
      ;; you might not have this font, change it to a good non-bitmap monospaced font you do have.

      ;; we're going to need to macro the shit out of this

      (new-path)
      (move-to 0 0)
      (set-source-rgb 81/255 81/255 81/255)

      (setf layout (pango:pango_cairo_create_layout (slot-value cairo:*context* 'cairo::pointer)))
      (setf font (pango:pango_font_description_from_string "Fantasque Sans Mono 12"))
      (pango:pango_layout_set_font_description layout font)

      (pango:pango_layout_set_text layout
         (format nil "~{~a~%~}"
            '("Hello, glorious pango text rendering!"
              "いあだ〜〜ずかしいです〜〜"
              "Τη γλώσσα μου έδωσαν ελληνική"
              "ᚠᛇᚻ᛫ᛒᛦᚦ᛫ᚠᚱᚩᚠᚢᚱ᛫ᚠᛁᚱᚪ᛫ᚷᛖᚻᚹᛦᛚᚳᚢᛗ"
              "ಬಾ ಇಲ್ಲಿ ಸಂಭವಿಸು ಇಂದೆನ್ನ ಹೃದಯದಲಿ "
              "मैं काँच खा सकता हूँ और मुझे उससे कोई चोट नहीं पहुंचती "))
         -1)

      (pango:pango_cairo_update_layout (slot-value *context* 'cairo::pointer) layout)
      (pango:pango_cairo_show_layout (slot-value *context* 'cairo::pointer) layout)

      ;; make sure it updates. Use this sparingly
      (surface-flush surface)
      (cairo::sync context))

      (princ "press enter here to exit")
      (finish-output)
      (when (read-line)
         (cairo:destroy context)
         (sb-ext:exit)))

;; (sb-ext:save-lisp-and-die "arboreta" :toplevel #'main :executable t)
(main)


Make sure the startIdx is set before setting endIdx

/*
* Multiply a vector by a sparse matrix and get the resultant
* vector.
* The global # of work items will be equal to the number rows in the
* sparse matrix, which is assumed to be square (what would happen if it wasn't?)
*/
__kernel void sparseMatVec(int nVals, __global int *rows, __global int *cols,
	__global float *vals, __global float *vec, __global float *res)
{
	int id = get_global_id(0);
	//We use these to select the range of i to read our row's values from (row # == id)
	int startIdx = -1;
	int endIdx = -1;
	//Determine the indices containing the values for the row this kernel will be working on
	for (int i = id; i < nVals; ++i){
		if (rows[i] == id && startIdx == -1)
			startIdx = i;
		if (rows[i] == id + 1 && startIdx != -1 && endIdx == -1){
			endIdx = i - 1;
			break;
		}
		if (i == nVals - 1 && startIdx != -1 && endIdx == -1)
			endIdx = i;
	}
	float sum = 0.0f;
	for (int i = startIdx; i <= endIdx; ++i)
			sum += vals[i] * vec[cols[i]];

	res[id] = sum;
}

/*
* Multiply a vector by a sparse matrix and get the resultant
* vector.
* The global # of work items will be equal to the number rows in the
* sparse matrix, which is assumed to be square (what would happen if it wasn't?)
*/
__kernel void sparseMatVec(int nVals, __global int *rows, __global int *cols,
	__global float *vals, __global float *vec, __global float *res)
{
	int id = get_global_id(0);
	//We use these to select the range of i to read our row's values from (row # == id)
	int startIdx = -1;
	int endIdx = -1;
	//Determine the indices containing the values for the row this kernel will be working on
	for (int i = id; i < nVals; ++i){
		if (rows[i] == id && startIdx == -1)
			startIdx = i;
		if (rows[i] == id + 1 && endIdx == -1){
			endIdx = i - 1;
			break;
		}
		if (i == nVals - 1 && endIdx == -1)
			endIdx = i;
	}
	float sum = 0.0f;
	for (int i = startIdx; i <= endIdx; ++i)
			sum += vals[i] * vec[cols[i]];

	res[id] = sum;
}


support for backward 7x7

support for backward 7x7


Fix memory issue

Fix memory issue

/******************************************************************************
 * 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;
  position[a] = 0;
  position[b] = 0;
  barrier(FENCE_TYPE);
  // should be a parallel scan
  if (li == 0) {
    for (uint i = 1; i < WORK_GROUP_SIZE * 2; ++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 work_size) {
  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, work_size);
  // inclusive scan to create offsets, should be parallel
  offsets[li] = 0;
  barrier(FENCE_TYPE);
  if (li == 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;
  k = 0;
  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];
  volatile local int k;
  k = 0;
  //heads[li] = 0;
  //if ((li == 0) || (keys[li] != keys[li - 1]))
  //  heads[li] = 1;
  heads[li] = (li == 0) || (keys[li] != keys[li - 1]);
  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]; // 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;
}


dnn(ocl): fix fp16 kernel compilation

dnn(ocl): fix fp16 kernel compilation

/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2017, Intel Corporation, all rights reserved.
// Copyright (c) 2016-2017 Fabian David Tschopp, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// 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.
//
//M*/

#define CONCAT(A,B) A##_##B
#define TEMPLATE(name,type) CONCAT(name,type)
#define KERNEL_ARG_DTYPE float

#if defined(cl_khr_fp16)
#pragma OPENCL EXTENSION cl_khr_fp16 : enable
#endif

__kernel void ReLUForward(const int count, __global const T* in, __global T* out
#ifndef RELU_NO_SLOPE
, KERNEL_ARG_DTYPE negative_slope
#endif
) {
  int index = get_global_id(0);
  if(index < count)
#ifndef RELU_NO_SLOPE
  out[index] = in[index] > 0 ? in[index] : in[index] * negative_slope;
#else
  out[index] = in[index] > 0 ? in[index] : 0;
#endif
}

__kernel void ReLU6Forward(const int count, __global const T* in, __global T* out,
                           const KERNEL_ARG_DTYPE minValue, const KERNEL_ARG_DTYPE maxValue)
{
  int index = get_global_id(0);
  if(index < count)
  {
    T x = in[index];
    out[index] = clamp(x, convert_T(minValue), convert_T(maxValue));
  }
}

__kernel void PReLUForward(const int count, const int channels, const int plane_size,
                           __global const T* in, __global T* out,
                           __global const KERNEL_ARG_DTYPE* slope_data)
{
  int index = get_global_id(0);
  int c = (index / plane_size) % channels;
  if(index < count)
  out[index] = in[index] > 0 ? in[index] : in[index] * slope_data[c];
}

__kernel void TanHForward(const int count, __global T* in, __global T* out) {
  int index = get_global_id(0);
  if(index < count)
  out[index] = tanh(in[index]);
}

__kernel void SigmoidForward(const int count, __global const T* in, __global T* out) {
  int index = get_global_id(0);
  if(index < count)
  out[index] = 1.0f / (1.0f + exp(-in[index]));
}

__kernel void SwishForward(const int count, __global const T* in, __global T* out) {
  int index = get_global_id(0);
  if(index < count)
  out[index] = in[index] / (1.0f + exp(-in[index]));
}

__kernel void MishForward(const int count, __global const T* in, __global T* out) {
  int index = get_global_id(0);
  if(index < count)
  out[index] = in[index] * tanh(log(1.0f + exp(in[index])));
}

__kernel void BNLLForward(const int n, __global const T* in, __global T* out) {
  int index = get_global_id(0);
  if (index < n) {
    T x = in[index];
    out[index] = x > 0 ? x + log(1.0f + exp(-x)) : log(1.0f + exp(x));
  }
}

__kernel void AbsValForward(const int n, __global const T* in, __global T* out) {
  int index = get_global_id(0);
  if (index < n)
    out[index] = fabs(in[index]);
}

__kernel void PowForward(const int n, __global const T* in, __global T* out,
                         const KERNEL_ARG_DTYPE power,
                         const KERNEL_ARG_DTYPE scale,
                         const KERNEL_ARG_DTYPE shift)
{
  int index = get_global_id(0);
  if (index < n)
    out[index] = pow(shift + scale * in[index], power);
}

__kernel void ELUForward(const int n, __global const T* in, __global T* out,
                         const KERNEL_ARG_DTYPE alpha)
{
  int index = get_global_id(0);
  if (index < n)
  {
    T src = in[index];
    out[index] = (src >= 0.f) ? src : alpha * (exp(src) - 1);
  }
}

__kernel void ExpForward(const int n, __global const T* in, __global T* out,
                         const KERNEL_ARG_DTYPE normScale,
                         const KERNEL_ARG_DTYPE normShift)
{
  int index = get_global_id(0);
  if (index < n)
  {
    out[index] = exp(normShift + normScale * in[index]);
  }
}

__kernel void CeilForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = ceil(in[index]);
}

__kernel void FloorForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = floor(in[index]);
}

__kernel void LogForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = log(in[index]);
}

__kernel void RoundForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = rint(in[index]);
}

__kernel void SqrtForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = sqrt(in[index]);
}

__kernel void NotForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = floor(1.0f - in[index]);
}

__kernel void AcosForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = acos(in[index]);
}

__kernel void AcoshForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = acosh(in[index]);
}

__kernel void AsinForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = asin(in[index]);
}

__kernel void AsinhForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = asinh(in[index]);
}

__kernel void AtanForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = atan(in[index]);
}

__kernel void AtanhForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = atanh(in[index]);
}

__kernel void CosForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = cos(in[index]);
}

__kernel void CoshForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = cosh(in[index]);
}

__kernel void HardSwishForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = in[index] * max(0.f, min(1.f, in[index] / 6.f + 0.5f));
}

__kernel void SinForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = sin(in[index]);
}

__kernel void SinhForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = sinh(in[index]);
}

__kernel void SoftplusForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = log1p(exp(in[index]));
}

__kernel void SoftsignForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = in[index] / (1.f + fabs(in[index]));
}

__kernel void TanForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = tan(in[index]);
}

__kernel void CeluForward(const int n, __global T* in, __global T* out,
                          const KERNEL_ARG_DTYPE alpha)
{
    int index = get_global_id(0);
    if(index < n)
        out[index] = max((T)0.f, in[index]) + (T)min(0.f, alpha * expm1(in[index] / alpha));
}

__kernel void HardSigmoidForward(const int n, __global T* in, __global T* out,
                                 const KERNEL_ARG_DTYPE alpha,
                                 const KERNEL_ARG_DTYPE beta)
{
    int index = get_global_id(0);
    if(index < n)
        out[index] = max((T)0.f, (T)min(1.f, alpha * in[index] + beta));
}

__kernel void SeluForward(const int n, __global T* in, __global T* out,
                          const KERNEL_ARG_DTYPE alpha,
                          const KERNEL_ARG_DTYPE gamma)
{
    int index = get_global_id(0);
    if(index < n)
        out[index] = gamma * (in[index] > 0.f ? in[index] : alpha * expm1(in[index]));
}

__kernel void ThresholdedReluForward(const int n, __global T* in, __global T* out,
                                     const KERNEL_ARG_DTYPE alpha)
{
    int index = get_global_id(0);
    if(index < n)
        out[index] = (in[index] > alpha ? in[index] : 0.f);
}

/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2017, Intel Corporation, all rights reserved.
// Copyright (c) 2016-2017 Fabian David Tschopp, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// 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.
//
//M*/

#define CONCAT(A,B) A##_##B
#define TEMPLATE(name,type) CONCAT(name,type)
#define KERNEL_ARG_DTYPE float

#if defined(cl_khr_fp16)
#pragma OPENCL EXTENSION cl_khr_fp16 : enable
#endif

__kernel void ReLUForward(const int count, __global const T* in, __global T* out
#ifndef RELU_NO_SLOPE
, KERNEL_ARG_DTYPE negative_slope
#endif
) {
  int index = get_global_id(0);
  if(index < count)
#ifndef RELU_NO_SLOPE
  out[index] = in[index] > 0 ? in[index] : in[index] * negative_slope;
#else
  out[index] = in[index] > 0 ? in[index] : 0;
#endif
}

__kernel void ReLU6Forward(const int count, __global const T* in, __global T* out,
                           const KERNEL_ARG_DTYPE minValue, const KERNEL_ARG_DTYPE maxValue)
{
  int index = get_global_id(0);
  if(index < count)
  {
    T x = in[index];
    out[index] = clamp(x, convert_T(minValue), convert_T(maxValue));
  }
}

__kernel void PReLUForward(const int count, const int channels, const int plane_size,
                           __global const T* in, __global T* out,
                           __global const KERNEL_ARG_DTYPE* slope_data)
{
  int index = get_global_id(0);
  int c = (index / plane_size) % channels;
  if(index < count)
  out[index] = in[index] > 0 ? in[index] : in[index] * slope_data[c];
}

__kernel void TanHForward(const int count, __global T* in, __global T* out) {
  int index = get_global_id(0);
  if(index < count)
  out[index] = tanh(in[index]);
}

__kernel void SigmoidForward(const int count, __global const T* in, __global T* out) {
  int index = get_global_id(0);
  if(index < count)
  out[index] = 1.0f / (1.0f + exp(-in[index]));
}

__kernel void SwishForward(const int count, __global const T* in, __global T* out) {
  int index = get_global_id(0);
  if(index < count)
  out[index] = in[index] / (1.0f + exp(-in[index]));
}

__kernel void MishForward(const int count, __global const T* in, __global T* out) {
  int index = get_global_id(0);
  if(index < count)
  out[index] = in[index] * tanh(log(1.0f + exp(in[index])));
}

__kernel void BNLLForward(const int n, __global const T* in, __global T* out) {
  int index = get_global_id(0);
  if (index < n) {
    T x = in[index];
    out[index] = x > 0 ? x + log(1.0f + exp(-x)) : log(1.0f + exp(x));
  }
}

__kernel void AbsValForward(const int n, __global const T* in, __global T* out) {
  int index = get_global_id(0);
  if (index < n)
    out[index] = fabs(in[index]);
}

__kernel void PowForward(const int n, __global const T* in, __global T* out,
                         const KERNEL_ARG_DTYPE power,
                         const KERNEL_ARG_DTYPE scale,
                         const KERNEL_ARG_DTYPE shift)
{
  int index = get_global_id(0);
  if (index < n)
    out[index] = pow(shift + scale * in[index], power);
}

__kernel void ELUForward(const int n, __global const T* in, __global T* out,
                         const KERNEL_ARG_DTYPE alpha)
{
  int index = get_global_id(0);
  if (index < n)
  {
    T src = in[index];
    out[index] = (src >= 0.f) ? src : alpha * (exp(src) - 1);
  }
}

__kernel void ExpForward(const int n, __global const T* in, __global T* out,
                         const KERNEL_ARG_DTYPE normScale,
                         const KERNEL_ARG_DTYPE normShift)
{
  int index = get_global_id(0);
  if (index < n)
  {
    out[index] = exp(normShift + normScale * in[index]);
  }
}

__kernel void CeilForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = ceil(in[index]);
}

__kernel void FloorForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = floor(in[index]);
}

__kernel void LogForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = log(in[index]);
}

__kernel void RoundForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = rint(in[index]);
}

__kernel void SqrtForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = sqrt(in[index]);
}

__kernel void NotForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = floor(1.0f - in[index]);
}

__kernel void AcosForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = acos(in[index]);
}

__kernel void AcoshForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = acosh(in[index]);
}

__kernel void AsinForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = asin(in[index]);
}

__kernel void AsinhForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = asinh(in[index]);
}

__kernel void AtanForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = atan(in[index]);
}

__kernel void AtanhForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = atanh(in[index]);
}

__kernel void CosForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = cos(in[index]);
}

__kernel void CoshForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = cosh(in[index]);
}

__kernel void HardSwishForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = in[index] * max(0.f, min(1.f, in[index] / 6.f + 0.5f));
}

__kernel void SinForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = sin(in[index]);
}

__kernel void SinhForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = sinh(in[index]);
}

__kernel void SoftplusForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = log1p(exp(in[index]));
}

__kernel void SoftsignForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = in[index] / (1.f + fabs(in[index]));
}

__kernel void TanForward(const int n, __global T* in, __global T* out) {
    int index = get_global_id(0);
    if(index < n)
        out[index] = tan(in[index]);
}

__kernel void CeluForward(const int n, __global T* in, __global T* out,
                          const KERNEL_ARG_DTYPE alpha)
{
    int index = get_global_id(0);
    if(index < n)
        out[index] = max(0.f, in[index]) + min(0.f, alpha * expm1(in[index] / alpha));
}

__kernel void HardSigmoidForward(const int n, __global T* in, __global T* out,
                                 const KERNEL_ARG_DTYPE alpha,
                                 const KERNEL_ARG_DTYPE beta)
{
    int index = get_global_id(0);
    if(index < n)
        out[index] = max(0.f, min(1.f, alpha * in[index] + beta));
}

__kernel void SeluForward(const int n, __global T* in, __global T* out,
                          const KERNEL_ARG_DTYPE alpha,
                          const KERNEL_ARG_DTYPE gamma)
{
    int index = get_global_id(0);
    if(index < n)
        out[index] = gamma * (in[index] > 0.f ? in[index] : alpha * expm1(in[index]));
}

__kernel void ThresholdedReluForward(const int n, __global T* in, __global T* out,
                                     const KERNEL_ARG_DTYPE alpha)
{
    int index = get_global_id(0);
    if(index < n)
        out[index] = (in[index] > alpha ? in[index] : 0.f);
}


fixed big image size issue - integer divide

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

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

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

#define UNUSED __attribute__((__unused__))

#define DBG_OUT_OF_RNGE 0

// calculating the size of the area for weights prefetch

__attribute__((always_inline)) uint iDiv(uint v, uint d)
{
    uint r = (uint)((float)v * (1.0f / (float)d) + 0.00001f);
    return (r);
}

__attribute__((always_inline)) uint iMod(uint v, uint u, uint d)
{
    uint r = v - mul24(u, d);
    return (r);
}

__attribute__((reqd_work_group_size(MLO_GRP_SZ0, MLO_GRP_SZ1, MLO_GRP_SZ2))) __kernel void
MIOpenConv1x1(const __global _FLOAT* __restrict in_ptr,
              __constant _FLOAT* __restrict wei_ptr,
#if MLO_CONV_BIAS
              const __global _FLOAT* __restrict bias,
#endif
              __global _FLOAT* __restrict out_ptr,
              UNUSED _FLOAT dummy_val // nothing
              )
{

    _FLOAT weights[MLO_N_LCL_OUT_MAPS][MLO_N_LCL_IN_MAPS];

    uint gbl_id0  = get_global_id(0);
    uint batch_id = gbl_id0 / MLO_MAP_SZ4; // batch
    uint pos      = gbl_id0 % MLO_MAP_SZ4;

    uint out_grp_block = get_group_id(1); // block of outputs for the entire group
    uint out_id        = out_grp_block * MLO_N_LCL_OUT_MAPS;

    uint gbl_in_off = batch_id * MLO_IN_BATCH_STRIDE + pos * MLO_READ_UNIT;

    uint wei_off = out_id *
#if MLO_DIR_FORWARD == 1
                   MLO_WEI_BSTRIDE
#else
                   MLO_WEI_CHANNEL_STRIDE
#endif
        ;

    _FLOAT accum[MLO_N_LCL_OUT_MAPS][MLO_READ_UNIT];
    _FLOAT dat[MLO_N_LCL_IN_MAPS][MLO_READ_UNIT];

    for(uint o = 0; o < MLO_N_LCL_OUT_MAPS; ++o)
    {
        for(uint i = 0; i < MLO_READ_UNIT; ++i)
        {
            accum[o][i] = 0;
        }
    }

    for(uint ci = 0; ci < MLO_CLOOP0; ++ci,
             // move input offset
                                      gbl_in_off += MLO_N_LCL_IN_MAPS * MLO_IN_CHANNEL_STRIDE,

             // move weights offset
                                      wei_off += MLO_N_LCL_IN_MAPS *
#if MLO_DIR_FORWARD == 1
                                                 MLO_WEI_CHANNEL_STRIDE
#else
                                                 MLO_WEI_BSTRIDE
#endif
        )
    {
        // read weights

        for(uint o = 0, wei_off1 = wei_off; o < MLO_N_LCL_OUT_MAPS; ++o,
                 wei_off1 +=
#if MLO_DIR_FORWARD == 1
                                                                    MLO_WEI_BSTRIDE
#else
                                                                    MLO_WEI_CHANNEL_STRIDE
#endif
            )
        {
            for(uint c = 0, wei_off2 = wei_off1; c < MLO_N_LCL_IN_MAPS; ++c,
                     wei_off2 +=
#if MLO_DIR_FORWARD == 1
                                                                        MLO_WEI_CHANNEL_STRIDE
#else
                                                                        MLO_WEI_BSTRIDE
#endif
                )
            {
                weights[o][c] = wei_ptr[wei_off2];
#if DBG_OUT_OF_RNGE
				if ( wei_off2 >= MLO_N_INPUTS*MLO_N_OUTPUTS)
				{
					printf("K:oor: weights\n");
				}
#endif
            }
        }

        // convolve with all weights
        // read data
        for(uint j = 0, gbl_in_off1 = gbl_in_off; j < MLO_N_LCL_IN_MAPS;
            ++j, gbl_in_off1 += MLO_IN_CHANNEL_STRIDE)
        {
            for(uint i = 0; i < MLO_READ_UNIT; ++i)
            {
                dat[j][i] = in_ptr[gbl_in_off1 + i];
#if DBG_OUT_OF_RNGE
				if ( gbl_in_off1 + i >= MLO_IN_BATCH_STRIDE * MLO_BATCH_SZ)
				{
					printf("K:oor: inputs\n"
					);
				}
#endif
            }
        }

        // convolve
        for(uint o = 0; o < MLO_N_LCL_OUT_MAPS; ++o)
        {
            for(uint c = 0; c < MLO_N_LCL_IN_MAPS; ++c)
            {
                for(uint i = 0; i < MLO_READ_UNIT; ++i)
                {
                    accum[o][i] += dat[c][i] * weights[o][c];
                }
            }
        }
    }

    uint gbl_out_off =
        batch_id * MLO_OUT_BATCH_STRIDE + pos * MLO_READ_UNIT + out_id * MLO_OUT_CHANNEL_STRIDE;
    for(uint o = 0, gbl_out_off1 = gbl_out_off; o < MLO_N_LCL_OUT_MAPS;
        ++o, gbl_out_off1 += MLO_OUT_CHANNEL_STRIDE)
    {
        for(uint i = 0; i < MLO_READ_UNIT; ++i)
        {
            out_ptr[gbl_out_off1 + i] = accum[o][i];
        }
    }
}

/************************************************************************
stride and padding
*************************************************************************/
__attribute__((reqd_work_group_size(MLO_GRP_SZ0, MLO_GRP_SZ1, MLO_GRP_SZ2))) __kernel void
MIOpenConv1x1pquv(const __global _FLOAT* __restrict in_ptr,
                  __constant _FLOAT* __restrict wei_ptr,
#if MLO_CONV_BIAS
                  const __global _FLOAT* __restrict bias,
#endif
                  __global _FLOAT* __restrict out_ptr,
                  UNUSED _FLOAT dummy_val // nothing
                  )
{

    _FLOAT weights[MLO_N_LCL_OUT_MAPS][MLO_N_LCL_IN_MAPS];

    uint gbl_id0 = get_global_id(0);

    uint batch_id  = gbl_id0 / MLO_MAP_SZ4; // batch
    uint pos       = gbl_id0 % MLO_MAP_SZ4;
    uint pos_out_y = pos / MLO_OUT_WIDTH4;
    uint pos_out_x = pos % MLO_OUT_WIDTH4;

#if MLO_DIR_FORWARD == 1
    uint pos_in_y = pos_out_y * MLO_FILTER_STRIDE1;
    uint pos_in_x = pos_out_x * MLO_FILTER_STRIDE0;
#else
    uint pos_in_y = pos_out_y; /// MLO_FILTER_STRIDE1;   - divided already
    uint pos_in_x = pos_out_x; // MLO_FILTER_STRIDE0;  - divided already
#endif

    uint out_grp_block = get_group_id(1); // block of outputs for the entire group
    uint out_id        = out_grp_block * MLO_N_LCL_OUT_MAPS;

    uint gbl_in_off =
        batch_id * MLO_IN_BATCH_STRIDE + pos_in_y * MLO_IN_STRIDE + pos_in_x * MLO_READ_UNIT;
    //	bool vis = (pos_in_y < MLO_IN_HEIGHT);
    //	gbl_in_off = (vis) ? gbl_in_off : 0;

    uint wei_off = out_id *
#if MLO_DIR_FORWARD == 1
                   MLO_WEI_BSTRIDE
#else
                   MLO_WEI_CHANNEL_STRIDE
#endif
        ;

    _FLOAT accum[MLO_N_LCL_OUT_MAPS][MLO_READ_UNIT];
    _FLOAT dat[MLO_N_LCL_IN_MAPS][MLO_READ_UNIT];

    for(uint o = 0; o < MLO_N_LCL_OUT_MAPS; ++o)
    {
        for(uint i = 0; i < MLO_READ_UNIT; ++i)
        {
            accum[o][i] = 0;
        }
    }

    const __global _FLOAT* i_ptr = &in_ptr[gbl_in_off];
    __constant _FLOAT* w_ptr     = &wei_ptr[wei_off];
    for(uint ci = 0; ci < MLO_CLOOP0; ++ci)
    {

        // convolve with all weights
        // read data

        for(uint j = 0; j < MLO_N_LCL_IN_MAPS; ++j)
        {
            uint i = 0;
#if MLO_READ_UNIT > 1
            for(; i < MLO_READ_UNIT - 1; ++i)
            {
                uint off = i
#if MLO_DIR_FORWARD == 1
                           * MLO_FILTER_STRIDE0
#endif
                    ;
                dat[j][i] = i_ptr[off];
            }
#endif

            for(; i < MLO_READ_UNIT; ++i)
            {
                //				vis &= (pos_in_x + i*MLO_FILTER_STRIDE0 <
                // MLO_IN_WIDTH);
                uint off = i
#if MLO_DIR_FORWARD == 1
                           * MLO_FILTER_STRIDE0
#endif
                    ;
                //				off = (vis) ? off : 0;
                _FLOAT val = i_ptr[off];
                dat[j][i]  = val;
                //              dat[j][i] = (vis)? dat[j][i] : 0;
            }

            i_ptr += MLO_IN_CHANNEL_STRIDE;
        }
        // read weights
        __constant _FLOAT* w_ptr0 = w_ptr;

        for(uint o = 0; o < MLO_N_LCL_OUT_MAPS; ++o)
        {

            __constant _FLOAT* w_ptr1 = w_ptr0;

            for(uint c = 0; c < MLO_N_LCL_IN_MAPS; ++c)
            {
                weights[o][c] = *w_ptr1;
                w_ptr1 +=
#if MLO_DIR_FORWARD == 1
                    MLO_WEI_CHANNEL_STRIDE
#else
                    MLO_WEI_BSTRIDE
#endif
                    ;
            }

            w_ptr0 +=
#if MLO_DIR_FORWARD == 1
                MLO_WEI_BSTRIDE
#else
                MLO_WEI_CHANNEL_STRIDE
#endif
                ;
        }

        w_ptr += MLO_N_LCL_IN_MAPS *
#if MLO_DIR_FORWARD == 1
                 MLO_WEI_CHANNEL_STRIDE
#else
                 MLO_WEI_BSTRIDE
#endif
            ;
        // convolve
        for(uint o = 0; o < MLO_N_LCL_OUT_MAPS; ++o)
        {
            for(uint c = 0; c < MLO_N_LCL_IN_MAPS; ++c)
            {
                for(uint i = 0; i < MLO_READ_UNIT; ++i)
                {
                    accum[o][i] += dat[c][i] * weights[o][c];
#if 0
				if (get_global_id(0) == 4 && get_global_id(1) ==0 && o == 0 && i == 0)
				{
					printf((__constant char *)"K:c: %f %f %f %f\n",
					accum[o][i],
					dat[c][i] * weights[o][c],
					dat[c][i],
					weights[o][c]
					);
				}
#endif
                }
            }
        }
    }

    uint out_y = pos_out_y
#if MLO_DIR_FORWARD == 0
                 * MLO_FILTER_STRIDE1
#endif
        ;
    uint out_x = pos_out_x
#if MLO_DIR_FORWARD == 0
                 * MLO_FILTER_STRIDE0
#endif
        ;

    uint gbl_out_off = batch_id * MLO_OUT_BATCH_STRIDE + out_id * MLO_OUT_CHANNEL_STRIDE +
                       out_y * MLO_OUT_STRIDE + out_x * MLO_READ_UNIT;

    for(uint o = 0, gbl_out_off1 = gbl_out_off; o < MLO_N_LCL_OUT_MAPS;
        ++o, gbl_out_off1 += MLO_OUT_CHANNEL_STRIDE)
    {

        for(uint i = 0; i < MLO_READ_UNIT; ++i)
        {
            uint out_off = gbl_out_off1 +
                           i
#if MLO_DIR_FORWARD == 0
                               * MLO_FILTER_STRIDE0
#endif
                ;
            out_ptr[out_off] = accum[o][i];

#if MLO_DIR_FORWARD == 0
            for(uint s = 1; s < MLO_FILTER_STRIDE0; ++s)
            {
#if MLO_HORIZ_ALIGNED == 0
                if(out_x + s < MLO_OUT_WIDTH)
#endif
                {
                    out_ptr[out_off + s] = 0;
                }
            }
#endif
        }

#if MLO_DIR_FORWARD == 0
        for(uint j = 1; j < MLO_FILTER_STRIDE1; ++j)
        {
#if MLO_VERT_ALIGNED == 0
            if(out_y + j < MLO_OUT_HEIGHT)
#endif
            {
                uint out_off = gbl_out_off1 + j * MLO_OUT_STRIDE;
                for(uint s = 0; s < MLO_READ_UNIT * MLO_FILTER_STRIDE0; ++s)
                {
#if MLO_HORIZ_ALIGNED == 0
                    if(out_x + s < MLO_OUT_WIDTH)
#endif
                    {
                        out_ptr[out_off + s] = 0;
                    }
                }
            }
        }
#endif
    }
}

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

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

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

#define UNUSED __attribute__((__unused__))

#define DBG_OUT_OF_RNGE 0

// calculating the size of the area for weights prefetch

__attribute__((always_inline)) uint iDiv(uint v, uint d)
{
    uint r = (uint)((float)v * (1.0f / (float)d) + 0.00001f);
    return (r);
}

__attribute__((always_inline)) uint iMod(uint v, uint u, uint d)
{
    uint r = v - mul24(u, d);
    return (r);
}

__attribute__((reqd_work_group_size(MLO_GRP_SZ0, MLO_GRP_SZ1, MLO_GRP_SZ2))) __kernel void
MIOpenConv1x1(const __global _FLOAT* __restrict in_ptr,
              __constant _FLOAT* __restrict wei_ptr,
#if MLO_CONV_BIAS
              const __global _FLOAT* __restrict bias,
#endif
              __global _FLOAT* __restrict out_ptr,
              UNUSED _FLOAT dummy_val // nothing
              )
{

    _FLOAT weights[MLO_N_LCL_OUT_MAPS][MLO_N_LCL_IN_MAPS];

    uint gbl_id0  = get_global_id(0);
    uint batch_id = iDiv(gbl_id0, MLO_MAP_SZ4); // batch
    uint pos      = iMod(gbl_id0, batch_id, MLO_MAP_SZ4);

    uint out_grp_block = get_group_id(1); // block of outputs for the entire group
    uint out_id        = out_grp_block * MLO_N_LCL_OUT_MAPS;

    uint gbl_in_off = batch_id * MLO_IN_BATCH_STRIDE + pos * MLO_READ_UNIT;

    uint wei_off = out_id *
#if MLO_DIR_FORWARD == 1
                   MLO_WEI_BSTRIDE
#else
                   MLO_WEI_CHANNEL_STRIDE
#endif
        ;

    _FLOAT accum[MLO_N_LCL_OUT_MAPS][MLO_READ_UNIT];
    _FLOAT dat[MLO_N_LCL_IN_MAPS][MLO_READ_UNIT];

    for(uint o = 0; o < MLO_N_LCL_OUT_MAPS; ++o)
    {
        for(uint i = 0; i < MLO_READ_UNIT; ++i)
        {
            accum[o][i] = 0;
        }
    }

    for(uint ci = 0; ci < MLO_CLOOP0; ++ci,
             // move input offset
                                      gbl_in_off += MLO_N_LCL_IN_MAPS * MLO_IN_CHANNEL_STRIDE,

             // move weights offset
                                      wei_off += MLO_N_LCL_IN_MAPS *
#if MLO_DIR_FORWARD == 1
                                                 MLO_WEI_CHANNEL_STRIDE
#else
                                                 MLO_WEI_BSTRIDE
#endif
        )
    {
        // read weights

        for(uint o = 0, wei_off1 = wei_off; o < MLO_N_LCL_OUT_MAPS; ++o,
                 wei_off1 +=
#if MLO_DIR_FORWARD == 1
                                                                    MLO_WEI_BSTRIDE
#else
                                                                    MLO_WEI_CHANNEL_STRIDE
#endif
            )
        {
            for(uint c = 0, wei_off2 = wei_off1; c < MLO_N_LCL_IN_MAPS; ++c,
                     wei_off2 +=
#if MLO_DIR_FORWARD == 1
                                                                        MLO_WEI_CHANNEL_STRIDE
#else
                                                                        MLO_WEI_BSTRIDE
#endif
                )
            {
                weights[o][c] = wei_ptr[wei_off2];
            }
        }

        // convolve with all weights
        // read data
        for(uint j = 0, gbl_in_off1 = gbl_in_off; j < MLO_N_LCL_IN_MAPS;
            ++j, gbl_in_off1 += MLO_IN_CHANNEL_STRIDE)
        {
            for(uint i = 0; i < MLO_READ_UNIT; ++i)
            {
                dat[j][i] = in_ptr[gbl_in_off1 + i];
            }
        }

        // convolve
        for(uint o = 0; o < MLO_N_LCL_OUT_MAPS; ++o)
        {
            for(uint c = 0; c < MLO_N_LCL_IN_MAPS; ++c)
            {
                for(uint i = 0; i < MLO_READ_UNIT; ++i)
                {
                    accum[o][i] += dat[c][i] * weights[o][c];
                }
            }
        }
    }

    uint gbl_out_off =
        batch_id * MLO_OUT_BATCH_STRIDE + pos * MLO_READ_UNIT + out_id * MLO_OUT_CHANNEL_STRIDE;
    for(uint o = 0, gbl_out_off1 = gbl_out_off; o < MLO_N_LCL_OUT_MAPS;
        ++o, gbl_out_off1 += MLO_OUT_CHANNEL_STRIDE)
    {
        for(uint i = 0; i < MLO_READ_UNIT; ++i)
        {
            out_ptr[gbl_out_off1 + i] = accum[o][i];
        }
    }
}

/************************************************************************
stride and padding
*************************************************************************/
__attribute__((reqd_work_group_size(MLO_GRP_SZ0, MLO_GRP_SZ1, MLO_GRP_SZ2))) __kernel void
MIOpenConv1x1pquv(const __global _FLOAT* __restrict in_ptr,
                  __constant _FLOAT* __restrict wei_ptr,
#if MLO_CONV_BIAS
                  const __global _FLOAT* __restrict bias,
#endif
                  __global _FLOAT* __restrict out_ptr,
                  UNUSED _FLOAT dummy_val // nothing
                  )
{

    _FLOAT weights[MLO_N_LCL_OUT_MAPS][MLO_N_LCL_IN_MAPS];

    uint gbl_id0 = get_global_id(0);

    uint batch_id  = iDiv(gbl_id0, MLO_MAP_SZ4); // batch
    uint pos       = iMod(gbl_id0, batch_id, MLO_MAP_SZ4);
    uint pos_out_y = iDiv(pos, MLO_OUT_WIDTH4);
    uint pos_out_x = iMod(pos, pos_out_y, MLO_OUT_WIDTH4);

#if MLO_DIR_FORWARD == 1
    uint pos_in_y = pos_out_y * MLO_FILTER_STRIDE1;
    uint pos_in_x = pos_out_x * MLO_FILTER_STRIDE0;
#else
    uint pos_in_y = pos_out_y; /// MLO_FILTER_STRIDE1;   - divided already
    uint pos_in_x = pos_out_x; // MLO_FILTER_STRIDE0;  - divided already
#endif

    uint out_grp_block = get_group_id(1); // block of outputs for the entire group
    uint out_id        = out_grp_block * MLO_N_LCL_OUT_MAPS;

    uint gbl_in_off =
        batch_id * MLO_IN_BATCH_STRIDE + pos_in_y * MLO_IN_STRIDE + pos_in_x * MLO_READ_UNIT;
    //	bool vis = (pos_in_y < MLO_IN_HEIGHT);
    //	gbl_in_off = (vis) ? gbl_in_off : 0;

    uint wei_off = out_id *
#if MLO_DIR_FORWARD == 1
                   MLO_WEI_BSTRIDE
#else
                   MLO_WEI_CHANNEL_STRIDE
#endif
        ;

    _FLOAT accum[MLO_N_LCL_OUT_MAPS][MLO_READ_UNIT];
    _FLOAT dat[MLO_N_LCL_IN_MAPS][MLO_READ_UNIT];

    for(uint o = 0; o < MLO_N_LCL_OUT_MAPS; ++o)
    {
        for(uint i = 0; i < MLO_READ_UNIT; ++i)
        {
            accum[o][i] = 0;
        }
    }

    const __global _FLOAT* i_ptr = &in_ptr[gbl_in_off];
    __constant _FLOAT* w_ptr     = &wei_ptr[wei_off];
    for(uint ci = 0; ci < MLO_CLOOP0; ++ci)
    {

        // convolve with all weights
        // read data

        for(uint j = 0; j < MLO_N_LCL_IN_MAPS; ++j)
        {
            uint i = 0;
#if MLO_READ_UNIT > 1
            for(; i < MLO_READ_UNIT - 1; ++i)
            {
                uint off = i
#if MLO_DIR_FORWARD == 1
                           * MLO_FILTER_STRIDE0
#endif
                    ;
                dat[j][i] = i_ptr[off];
            }
#endif

            for(; i < MLO_READ_UNIT; ++i)
            {
                //				vis &= (pos_in_x + i*MLO_FILTER_STRIDE0 <
                // MLO_IN_WIDTH);
                uint off = i
#if MLO_DIR_FORWARD == 1
                           * MLO_FILTER_STRIDE0
#endif
                    ;
                //				off = (vis) ? off : 0;
                _FLOAT val = i_ptr[off];
                dat[j][i]  = val;
                //              dat[j][i] = (vis)? dat[j][i] : 0;
            }

            i_ptr += MLO_IN_CHANNEL_STRIDE;
        }
        // read weights
        __constant _FLOAT* w_ptr0 = w_ptr;

        for(uint o = 0; o < MLO_N_LCL_OUT_MAPS; ++o)
        {

            __constant _FLOAT* w_ptr1 = w_ptr0;

            for(uint c = 0; c < MLO_N_LCL_IN_MAPS; ++c)
            {
                weights[o][c] = *w_ptr1;
                w_ptr1 +=
#if MLO_DIR_FORWARD == 1
                    MLO_WEI_CHANNEL_STRIDE
#else
                    MLO_WEI_BSTRIDE
#endif
                    ;
            }

            w_ptr0 +=
#if MLO_DIR_FORWARD == 1
                MLO_WEI_BSTRIDE
#else
                MLO_WEI_CHANNEL_STRIDE
#endif
                ;
        }

        w_ptr += MLO_N_LCL_IN_MAPS *
#if MLO_DIR_FORWARD == 1
                 MLO_WEI_CHANNEL_STRIDE
#else
                 MLO_WEI_BSTRIDE
#endif
            ;
        // convolve
        for(uint o = 0; o < MLO_N_LCL_OUT_MAPS; ++o)
        {
            for(uint c = 0; c < MLO_N_LCL_IN_MAPS; ++c)
            {
                for(uint i = 0; i < MLO_READ_UNIT; ++i)
                {
                    accum[o][i] += dat[c][i] * weights[o][c];
#if 0
				if (get_global_id(0) == 4 && get_global_id(1) ==0 && o == 0 && i == 0)
				{
					printf((__constant char *)"K:c: %f %f %f %f\n",
					accum[o][i],
					dat[c][i] * weights[o][c],
					dat[c][i],
					weights[o][c]
					);
				}
#endif
                }
            }
        }
    }

    uint out_y = pos_out_y
#if MLO_DIR_FORWARD == 0
                 * MLO_FILTER_STRIDE1
#endif
        ;
    uint out_x = pos_out_x
#if MLO_DIR_FORWARD == 0
                 * MLO_FILTER_STRIDE0
#endif
        ;

    uint gbl_out_off = batch_id * MLO_OUT_BATCH_STRIDE + out_id * MLO_OUT_CHANNEL_STRIDE +
                       out_y * MLO_OUT_STRIDE + out_x * MLO_READ_UNIT;

    for(uint o = 0, gbl_out_off1 = gbl_out_off; o < MLO_N_LCL_OUT_MAPS;
        ++o, gbl_out_off1 += MLO_OUT_CHANNEL_STRIDE)
    {

        for(uint i = 0; i < MLO_READ_UNIT; ++i)
        {
            uint out_off = gbl_out_off1 +
                           i
#if MLO_DIR_FORWARD == 0
                               * MLO_FILTER_STRIDE0
#endif
                ;
            out_ptr[out_off] = accum[o][i];

#if MLO_DIR_FORWARD == 0
            for(uint s = 1; s < MLO_FILTER_STRIDE0; ++s)
            {
#if MLO_HORIZ_ALIGNED == 0
                if(out_x + s < MLO_OUT_WIDTH)
#endif
                {
                    out_ptr[out_off + s] = 0;
                }
            }
#endif
        }

#if MLO_DIR_FORWARD == 0
        for(uint j = 1; j < MLO_FILTER_STRIDE1; ++j)
        {
#if MLO_VERT_ALIGNED == 0
            if(out_y + j < MLO_OUT_HEIGHT)
#endif
            {
                uint out_off = gbl_out_off1 + j * MLO_OUT_STRIDE;
                for(uint s = 0; s < MLO_READ_UNIT * MLO_FILTER_STRIDE0; ++s)
                {
#if MLO_HORIZ_ALIGNED == 0
                    if(out_x + s < MLO_OUT_WIDTH)
#endif
                    {
                        out_ptr[out_off + s] = 0;
                    }
                }
            }
        }
#endif
    }
}


tests/sixtracklib/opencl: fix/change memory region decorators in the particle tracking kernel

#ifndef TESTS_SIXTRACKLIB_OPENCL_TEST_PARTICLES_KERNEL_OPENCL_CL__
#define TESTS_SIXTRACKLIB_OPENCL_TEST_PARTICLES_KERNEL_OPENCL_CL__

#if !defined( SIXTRL_NO_INCLUDES )
    #include "sixtracklib/_impl/definitions.h"
    #include "sixtracklib/common/impl/buffer_defines.h"
    #include "sixtracklib/common/impl/managed_buffer_minimal.h"
    #include "sixtracklib/common/impl/managed_buffer_remap.h"
    #include "sixtracklib/common/particles.h"
#endif /* !defined( SIXTRL_NO_INCLUDES ) */

#pragma OPENCL_EXTENSION cl_khr_int32_extended_atomics

__kernel void NS(Particles_copy_buffer_opencl)(
    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT in_buffer_begin,
    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT out_buffer_begin,
    SIXTRL_DATAPTR_DEC int* SIXTRL_RESTRICT ptr_success_flag )
{
    typedef NS(buffer_size_t) buf_size_t;
    typedef SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)*       obj_iter_t;
    typedef SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* obj_const_iter_t;

    typedef SIXTRL_PARTICLE_ARGPTR_DEC NS(Particles) const* ptr_const_particles_t;
    typedef SIXTRL_PARTICLE_ARGPTR_DEC NS(Particles)*       ptr_particles_t;

    int success_flag = ( int )0u;
    buf_size_t const slot_size = ( buf_size_t )8u;

    if( ( !NS(ManagedBuffer_needs_remapping(  in_buffer_begin,  slot_size ) ) ) &&
        ( !NS(ManagedBuffer_needs_remapping( out_buffer_begin,  slot_size ) ) ) &&
        (  NS(ManagedBuffer_get_num_objects)( out_buffer_begin, slot_size ) ==
           NS(ManagedBuffer_get_num_objects)(  in_buffer_begin, slot_size ) ) )
    {
        obj_const_iter_t in_obj_it  = NS(ManagedBuffer_get_const_objects_index_begin)(
            in_buffer_begin, slot_size );

        obj_const_iter_t in_obj_end = NS(ManagedBuffer_get_const_objects_index_end)(
            in_buffer_begin, slot_size );

        obj_iter_t out_obj_it = NS(ManagedBuffer_get_objects_index_begin)(
            out_buffer_begin, slot_size );

        buf_size_t obj_begin_index = ( buf_size_t )0u;

        size_t const global_id = get_global_id( 0 );

        for( ; in_obj_it != in_obj_end ; ++in_obj_it, ++out_obj_it )
        {
            ptr_const_particles_t in_particles = ( ptr_const_particles_t )(
                uintptr_t )NS(Object_get_begin_addr)( in_obj_it );

            ptr_particles_t out_particles = ( ptr_particles_t )(
                uintptr_t )NS(Object_get_begin_addr)( out_obj_it );

            buf_size_t const nn =
                NS(Particles_get_num_of_particles)( in_particles );

            buf_size_t const obj_end_index = obj_begin_index + nn;

            if( nn == NS(Particles_get_num_of_particles)( out_particles ) )
            {
                if( ( global_id >= obj_begin_index ) &&
                    ( global_id <  obj_end_index ) )
                {
                    buf_size_t const particle_id = global_id - obj_begin_index;

                    if( particle_id < nn )
                    {
                        NS(Particles_copy_single)( out_particles, particle_id,
                            in_particles, particle_id );
                    }
                    else
                    {
                        success_flag |= -1;
                    }

                    break;
                }
            }
            else
            {
                success_flag |= -2;
            }
        }
    }
    else
    {
        if( NS(ManagedBuffer_needs_remapping(  in_buffer_begin, slot_size ) ) )
        {
            success_flag |= -4;
        }

        if( NS(ManagedBuffer_needs_remapping( out_buffer_begin, slot_size ) ) )
        {
            success_flag |= -8;
        }

        if(  NS(ManagedBuffer_get_num_objects)( out_buffer_begin, slot_size ) !=
             NS(ManagedBuffer_get_num_objects)(  in_buffer_begin, slot_size ) )
        {
            success_flag |= -16;
        }
    }

    if( ( success_flag != 0 ) && ( ptr_success_flag != SIXTRL_NULLPTR ) )
    {
        atomic_or( ptr_success_flag, success_flag );
    }

    return;
}

#endif /* TESTS_SIXTRACKLIB_OPENCL_TEST_PARTICLES_KERNEL_OPENCL_CL__ */

/* end: tests/sixtracklib/opencl/test_particles_kernel.cl */

#ifndef TESTS_SIXTRACKLIB_OPENCL_TEST_PARTICLES_KERNEL_OPENCL_CL__
#define TESTS_SIXTRACKLIB_OPENCL_TEST_PARTICLES_KERNEL_OPENCL_CL__

#if !defined( SIXTRL_NO_INCLUDES )
    #include "sixtracklib/_impl/definitions.h"
    #include "sixtracklib/common/impl/buffer_defines.h"
    #include "sixtracklib/common/impl/managed_buffer_minimal.h"
    #include "sixtracklib/common/impl/managed_buffer_remap.h"
    #include "sixtracklib/common/particles.h"
#endif /* !defined( SIXTRL_NO_INCLUDES ) */

#pragma OPENCL_EXTENSION cl_khr_int32_extended_atomics

__kernel void NS(Particles_copy_buffer_opencl)(
    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT in_buffer_begin,
    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT out_buffer_begin,
    SIXTRL_DATAPTR_DEC int* SIXTRL_RESTRICT ptr_success_flag )
{
    typedef NS(buffer_size_t) buf_size_t;
    typedef __global NS(Object)*       obj_iter_t;
    typedef __global NS(Object) const* obj_const_iter_t;

    typedef __global NS(Particles) const* ptr_const_particles_t;
    typedef __global NS(Particles)*       ptr_particles_t;

    int success_flag = ( int )0u;
    buf_size_t const slot_size = ( buf_size_t )8u;

    if( ( !NS(ManagedBuffer_needs_remapping(  in_buffer_begin,  slot_size ) ) ) &&
        ( !NS(ManagedBuffer_needs_remapping( out_buffer_begin,  slot_size ) ) ) &&
        (  NS(ManagedBuffer_get_num_objects)( out_buffer_begin, slot_size ) ==
           NS(ManagedBuffer_get_num_objects)(  in_buffer_begin, slot_size ) ) )
    {
        obj_const_iter_t in_obj_it  = NS(ManagedBuffer_get_const_objects_index_begin)(
            in_buffer_begin, slot_size );

        obj_const_iter_t in_obj_end = NS(ManagedBuffer_get_const_objects_index_end)(
            in_buffer_begin, slot_size );

        obj_iter_t out_obj_it = NS(ManagedBuffer_get_objects_index_begin)(
            out_buffer_begin, slot_size );

        buf_size_t obj_begin_index = ( buf_size_t )0u;

        size_t const global_id = get_global_id( 0 );

        for( ; in_obj_it != in_obj_end ; ++in_obj_it, ++out_obj_it )
        {
            ptr_const_particles_t in_particles = ( ptr_const_particles_t )(
                uintptr_t )NS(Object_get_begin_addr)( in_obj_it );

            ptr_particles_t out_particles = ( ptr_particles_t )(
                uintptr_t )NS(Object_get_begin_addr)( out_obj_it );

            buf_size_t const nn =
                NS(Particles_get_num_of_particles)( in_particles );

            buf_size_t const obj_end_index = obj_begin_index + nn;

            if( nn == NS(Particles_get_num_of_particles)( out_particles ) )
            {
                if( ( global_id >= obj_begin_index ) &&
                    ( global_id <  obj_end_index ) )
                {
                    buf_size_t const particle_id = global_id - obj_begin_index;

                    if( particle_id < nn )
                    {
                        NS(Particles_copy_single)( out_particles, particle_id,
                            in_particles, particle_id );
                    }
                    else
                    {
                        success_flag |= -1;
                    }

                    break;
                }
            }
            else
            {
                success_flag |= -2;
            }
        }
    }
    else
    {
        if( NS(ManagedBuffer_needs_remapping(  in_buffer_begin, slot_size ) ) )
        {
            success_flag |= -4;
        }

        if( NS(ManagedBuffer_needs_remapping( out_buffer_begin, slot_size ) ) )
        {
            success_flag |= -8;
        }

        if(  NS(ManagedBuffer_get_num_objects)( out_buffer_begin, slot_size ) !=
             NS(ManagedBuffer_get_num_objects)(  in_buffer_begin, slot_size ) )
        {
            success_flag |= -16;
        }
    }

    if( ( success_flag != 0 ) && ( ptr_success_flag != SIXTRL_NULLPTR ) )
    {
        atomic_or( ptr_success_flag, success_flag );
    }

    return;
}

#endif /* TESTS_SIXTRACKLIB_OPENCL_TEST_PARTICLES_KERNEL_OPENCL_CL__ */

/* end: tests/sixtracklib/opencl/test_particles_kernel.cl */


cl warning fix

cl warning fix