BUG: Fixed typo in ireduce_dim.cl

BUG: Fixed typo in ireduce_dim.cl

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

__kernel
void ireduce_dim_kernel(__global T *oData,
                        KParam oInfo,
                        __global uint *olData,
                        const __global T *iData,
                        KParam iInfo,
                        const __global uint *ilData,
                        uint groups_x, uint groups_y, uint group_dim)
{
    const uint lidx = get_local_id(0);
    const uint lidy = get_local_id(1);
    const uint lid  = lidy * THREADS_X + lidx;

    const uint zid = get_group_id(0) / groups_x;
    const uint wid = get_group_id(1) / groups_y;
    const uint groupId_x = get_group_id(0) - (groups_x) * zid;
    const uint groupId_y = get_group_id(1) - (groups_y) * wid;
    const uint xid = groupId_x * get_local_size(0) + lidx;
    const uint yid = groupId_y;

    uint ids[4] = {xid, yid, zid, wid};

    // There is only one element per group for out
    // There are get_local_size(1) elements per group for in
    // Hence increment ids[dim] just after offseting out and before offsetting in
    oData += ids[3] * oInfo.strides[3] + ids[2] * oInfo.strides[2] +
        ids[1] * oInfo.strides[1] + ids[0] + oInfo.offset;
    olData += ids[3] * oInfo.strides[3] + ids[2] * oInfo.strides[2] +
        ids[1] * oInfo.strides[1] + ids[0] + oInfo.offset;
    const uint id_dim_out = ids[dim];

    ids[dim] = ids[dim] * get_local_size(1) + lidy;

    iData  += ids[3] * iInfo.strides[3] + ids[2] * iInfo.strides[2] +
        ids[1] * iInfo.strides[1] + ids[0] + iInfo.offset;

    if (!IS_FIRST) {
        ilData  += ids[3] * iInfo.strides[3] + ids[2] * iInfo.strides[2] +
            ids[1] * iInfo.strides[1] + ids[0] + iInfo.offset;
    }

    const uint id_dim_in = ids[dim];
    const uint istride_dim = iInfo.strides[dim];

    bool is_valid =
        (ids[0] < iInfo.dims[0]) &&
        (ids[1] < iInfo.dims[1]) &&
        (ids[2] < iInfo.dims[2]) &&
        (ids[3] < iInfo.dims[3]);

    __local T s_val[THREADS_X * DIMY];
    __local uint s_idx[THREADS_X * DIMY];

    T out_val = init;
    uint out_idx = id_dim_in;

    if (is_valid && id_dim_in < iInfo.dims[dim]) {
        out_val = *iData;
        if (!IS_FIRST) out_idx = *ilData;
    }

    const uint id_dim_in_start = id_dim_in + group_dim * get_local_size(1);

    for (int id = id_dim_in_start; is_valid && (id < iInfo.dims[dim]);
         id += group_dim * get_local_size(1)) {

        iData = iData + group_dim * get_local_size(1) * istride_dim;

#if IS_FIRST
        binOp(&out_val, &out_idx, *iData, id);
#else
        ilData = ilData + group_dim * get_local_size(1) * istride_dim;
        binOp(&out_val, &out_idx, *iData, *ilData);
#endif
    }

    s_val[lid] = out_val;
    s_idx[lid] = out_idx;

    __local T *s_vptr = s_val + lid;
    __local uint *s_iptr = s_idx + lid;
    barrier(CLK_LOCAL_MEM_FENCE);

    if (DIMY == 8) {
        if (lidy < 4) {
            binOp(&out_val, &out_idx,
                  s_vptr[THREADS_X * 4], s_iptr[THREADS_X * 4]);
            *s_vptr = out_val;
            *s_iptr = out_idx;
        }
        barrier(CLK_LOCAL_MEM_FENCE);
    }

    if (DIMY >= 4) {
        if (lidy < 2) {
            binOp(&out_val, &out_idx,
                  s_vptr[THREADS_X * 2], s_iptr[THREADS_X * 2]);
            *s_vptr = out_val;
            *s_iptr = out_idx;
        }
        barrier(CLK_LOCAL_MEM_FENCE);
    }

    if (DIMY >= 2) {
        if (lidy < 1) {
            binOp(&out_val, &out_idx,
                  s_vptr[THREADS_X * 1], s_iptr[THREADS_X * 1]);
            *s_vptr = out_val;
            *s_iptr = out_idx;
        }
        barrier(CLK_LOCAL_MEM_FENCE);
    }

    if (lidy == 0 && is_valid &&
        (id_dim_out < oInfo.dims[dim])) {
        *oData = *s_vptr;
        *olData = *s_iptr;
    }

}

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

__kernel
void ireduce_dim_kernel(__global T *oData,
                        KParam oInfo,
                        __global uint *olData,
                        const __global T *iData,
                        KParam iInfo,
                        const __global uint *ilData,
                        uint groups_x, uint groups_y, uint group_dim)
{
    const uint lidx = get_local_id(0);
    const uint lidy = get_local_id(1);
    const uint lid  = lidy * THREADS_X + lidx;

    const uint zid = get_group_id(0) / groups_x;
    const uint wid = get_group_id(1) / groups_y;
    const uint groupId_x = get_group_id(0) - (groups_x) * zid;
    const uint groupId_y = get_group_id(1) - (groups_y) * wid;
    const uint xid = groupId_x * get_local_size(0) + lidx;
    const uint yid = groupId_y;

    uint ids[4] = {xid, yid, zid, wid};

    // There is only one element per group for out
    // There are get_local_size(1) elements per group for in
    // Hence increment ids[dim] just after offseting out and before offsetting in
    oData += ids[3] * oInfo.strides[3] + ids[2] * oInfo.strides[2] +
        ids[1] * oInfo.strides[1] + ids[0] + oInfo.offset;
    olData += ids[3] * oInfo.strides[3] + ids[2] * oInfo.strides[2] +
        ids[1] * oInfo.strides[1] + ids[0] + oInfo.offset;
    const uint id_dim_out = ids[dim];

    ids[dim] = ids[dim] * get_local_size(1) + lidy;

    iData  += ids[3] * iInfo.strides[3] + ids[2] * iInfo.strides[2] +
        ids[1] * iInfo.strides[1] + ids[0] + iInfo.offset;

    if (!IS_FIRST) {
        ilData  += ids[3] * iInfo.strides[3] + ids[2] * iInfo.strides[2] +
            ids[1] * iInfo.strides[1] + ids[0] + iInfo.offset;
    }

    const uint id_dim_in = ids[dim];
    const uint istride_dim = iInfo.strides[dim];

    bool is_valid =
        (ids[0] < iInfo.dims[0]) &&
        (ids[1] < iInfo.dims[1]) &&
        (ids[2] < iInfo.dims[2]) &&
        (ids[3] < iInfo.dims[3]);

    __local T s_val[THREADS_X * DIMY];
    __local uint s_idx[THREADS_X * DIMY];

    T out_val = init;
    uint out_idx = id_dim_in;

    if (is_valid && id_dim_in < iInfo.dims[dim]) {
        out_val = *iData;
        if (!IS_FIRST) out_idx = *ilData;
    }

    const uint id_dim_in_start = id_dim_in + group_dim + get_local_size(1);

    for (int id = id_dim_in_start; is_valid && (id < iInfo.dims[dim]);
         id += group_dim * get_local_size(1)) {

        iData = iData + group_dim * get_local_size(1) * istride_dim;

#if IS_FIRST
        binOp(&out_val, &out_idx, *iData, id);
#else
        ilData = ilData + group_dim * get_local_size(1) * istride_dim;
        binOp(&out_val, &out_idx, *iData, *ilData);
#endif
    }

    s_val[lid] = out_val;
    s_idx[lid] = out_idx;

    __local T *s_vptr = s_val + lid;
    __local uint *s_iptr = s_idx + lid;
    barrier(CLK_LOCAL_MEM_FENCE);

    if (DIMY == 8) {
        if (lidy < 4) {
            binOp(&out_val, &out_idx,
                  s_vptr[THREADS_X * 4], s_iptr[THREADS_X * 4]);
            *s_vptr = out_val;
            *s_iptr = out_idx;
        }
        barrier(CLK_LOCAL_MEM_FENCE);
    }

    if (DIMY >= 4) {
        if (lidy < 2) {
            binOp(&out_val, &out_idx,
                  s_vptr[THREADS_X * 2], s_iptr[THREADS_X * 2]);
            *s_vptr = out_val;
            *s_iptr = out_idx;
        }
        barrier(CLK_LOCAL_MEM_FENCE);
    }

    if (DIMY >= 2) {
        if (lidy < 1) {
            binOp(&out_val, &out_idx,
                  s_vptr[THREADS_X * 1], s_iptr[THREADS_X * 1]);
            *s_vptr = out_val;
            *s_iptr = out_idx;
        }
        barrier(CLK_LOCAL_MEM_FENCE);
    }

    if (lidy == 0 && is_valid &&
        (id_dim_out < oInfo.dims[dim])) {
        *oData = *s_vptr;
        *olData = *s_iptr;
    }

}


r2061: typo fix

r2061: typo fix

;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*-
;;;; *************************************************************************
;;;; FILE IDENTIFICATION
;;;;
;;;; Name:          package.cl
;;;; Purpose:       Package definition for base (low-level) SQL interface
;;;; Programmers:   Kevin M. Rosenberg based on
;;;;                Original code by Pierre R. Mai
;;;; Date Started:  Feb 2002
;;;;
;;;; $Id: package.cl,v 1.5 2002/05/20 17:46:34 kevin Exp $
;;;;
;;;; This file, part of CLSQL, is Copyright (c) 2002 by Kevin M. Rosenberg
;;;; and Copyright (c) 1999-2001 by Pierre R. Mai
;;;;
;;;; CLSQL users are granted the rights to distribute and use this software
;;;; as governed by the terms of the Lisp Lesser GNU Public License
;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL.
;;;; *************************************************************************

(declaim (optimize (debug 3) (speed 3) (safety 1) (compilation-speed 0)))
(in-package :cl-user)

;;;; This file makes the required package definitions for CLSQL's
;;;; core packages.

(eval-when (:compile-toplevel :load-toplevel :execute)
(defpackage :clsql-sys
  (:use :common-lisp)
  (:export
     ;; "Private" exports for use by interface packages
     #:check-connection-spec
     #:database-type-load-foreign
     #:database-type-library-loaded ;; KMR - Tests if foreign library okay
     #:database-initialize-database-type
     #:database-connect
     #:database-disconnect
     #:database-query
     #:database-execute-command
     #:database-query-result-set
     #:database-dump-result-set
     #:database-store-next-row

     ;; For UncommonSQL support
     #:database-list-tables
     #:database-list-attributes
     #:database-attribute-type
     #:database-create-sequence
     #:database-drop-sequence
     #:database-sequence-next
     #:sql-escape

     ;; Support for pooled connections
     #:database-type

     ;; Large objects (Marc B)
     #:database-create-large-object
     #:database-write-large-object
     #:database-read-large-object
     #:database-delete-large-object

     ;; Shared exports for re-export by CLSQL

     .
     #1=(#:clsql-condition
	 #:clsql-error
	 #:clsql-simple-error
	 #:clsql-warning
	 #:clsql-simple-warning
	 #:clsql-invalid-spec-error
	 #:clsql-invalid-spec-error-connection-spec
	 #:clsql-invalid-spec-error-database-type
	 #:clsql-invalid-spec-error-template
	 #:clsql-connect-error
	 #:clsql-connect-error-database-type
	 #:clsql-connect-error-connection-spec
	 #:clsql-connect-error-errno
	 #:clsql-connect-error-error
	 #:clsql-sql-error
	 #:clsql-sql-error-database
	 #:clsql-sql-error-expression
	 #:clsql-sql-error-errno
	 #:clsql-sql-error-error
	 #:clsql-database-warning
	 #:clsql-database-warning-database
	 #:clsql-database-warning-message
	 #:clsql-exists-condition
	 #:clsql-exists-condition-new-db
	 #:clsql-exists-condition-old-db
	 #:clsql-exists-warning
	 #:clsql-exists-error
	 #:clsql-closed-error
	 #:clsql-closed-error-database
	 #:*loaded-database-types*
	 #:reload-database-types
	 #:*default-database-type*
	 #:*initialized-database-types*
	 #:initialize-database-type
	 #:*connect-if-exists*
	 #:*default-database*
	 #:connected-databases
	 #:database
	 #:database-name
	 #:closed-database
	 #:find-database
	 #:database-name-from-spec
	 #:connect
	 #:disconnect
	 #:query
	 #:execute-command
	 #:map-query
	 #:do-query

	 ;; functional.cl
	 #:insert-records
	 #:delete-records
	 #:update-records
	 #:with-database

	 ;; utils.cl
	 #:number-to-sql-string
	 #:float-to-sql-string
	 #:sql-escape-quotes

	 ;; For UncommonSQL support
	 #:sql-ident
	 #:list-tables
	 #:list-attributes
	 #:attribute-type
	 #:create-sequence
	 #:drop-sequence
	 #:sequence-next

	 ;; Pooled connections
	 #:disconnect-pooled
	 #:find-or-create-connection-pool

	 ;; Transactions
	 #:with-transaction
	 #:commit-transaction
	 #:rollback-transaction
	 #:add-transaction-commit-hook
	 #:add-transaction-rollback-hook

	 ;; Large objects (Marc B)
	 #:create-large-object
	 #:write-large-object
	 #:read-large-object
	 #:delete-large-object
	 ))
    (:documentation "This is the INTERNAL SQL-Interface package of CLSQL."))

(defpackage #:clsql
    (:import-from #:clsql-sys . #1#)
    (:export . #1#)
    (:documentation "This is the SQL-Interface package of CLSQL."))
);eval-when

(defpackage #:clsql-user
    (:use #:common-lisp #:clsql)
    (:documentation "This is the user package for experimenting with CLSQL."))

;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*-
;;;; *************************************************************************
;;;; FILE IDENTIFICATION
;;;;
;;;; Name:          package.cl
;;;; Purpose:       Package definition for high-level SQL interface
;;;; Programmers:   Kevin M. Rosenberg based on
;;;;                Original code by Pierre R. Mai
;;;; Date Started:  Feb 2002
;;;;
;;;; $Id: package.cl,v 1.4 2002/05/19 16:05:22 kevin Exp $
;;;;
;;;; This file, part of CLSQL, is Copyright (c) 2002 by Kevin M. Rosenberg
;;;; and Copyright (c) 1999-2001 by Pierre R. Mai
;;;;
;;;; CLSQL users are granted the rights to distribute and use this software
;;;; as governed by the terms of the Lisp Lesser GNU Public License
;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL.
;;;; *************************************************************************

(declaim (optimize (debug 3) (speed 3) (safety 1) (compilation-speed 0)))
(in-package :cl-user)

;;;; This file makes the required package definitions for CLSQL's
;;;; core packages.

(eval-when (:compile-toplevel :load-toplevel :execute)
(defpackage :clsql-sys
  (:use :common-lisp)
  (:export
     ;; "Private" exports for use by interface packages
     #:check-connection-spec
     #:database-type-load-foreign
     #:database-type-library-loaded ;; KMR - Tests if foreign library okay
     #:database-initialize-database-type
     #:database-connect
     #:database-disconnect
     #:database-query
     #:database-execute-command
     #:database-query-result-set
     #:database-dump-result-set
     #:database-store-next-row

     ;; For UncommonSQL support
     #:database-list-tables
     #:database-list-attributes
     #:database-attribute-type
     #:database-create-sequence
     #:database-drop-sequence
     #:database-sequence-next
     #:sql-escape

     ;; Support for pooled connections
     #:database-type

     ;; Large objects (Marc B)
     #:database-create-large-object
     #:database-write-large-object
     #:database-read-large-object
     #:database-delete-large-object

     ;; Shared exports for re-export by CLSQL

     .
     #1=(#:clsql-condition
	 #:clsql-error
	 #:clsql-simple-error
	 #:clsql-warning
	 #:clsql-simple-warning
	 #:clsql-invalid-spec-error
	 #:clsql-invalid-spec-error-connection-spec
	 #:clsql-invalid-spec-error-database-type
	 #:clsql-invalid-spec-error-template
	 #:clsql-connect-error
	 #:clsql-connect-error-database-type
	 #:clsql-connect-error-connection-spec
	 #:clsql-connect-error-errno
	 #:clsql-connect-error-error
	 #:clsql-sql-error
	 #:clsql-sql-error-database
	 #:clsql-sql-error-expression
	 #:clsql-sql-error-errno
	 #:clsql-sql-error-error
	 #:clsql-database-warning
	 #:clsql-database-warning-database
	 #:clsql-database-warning-message
	 #:clsql-exists-condition
	 #:clsql-exists-condition-new-db
	 #:clsql-exists-condition-old-db
	 #:clsql-exists-warning
	 #:clsql-exists-error
	 #:clsql-closed-error
	 #:clsql-closed-error-database
	 #:*loaded-database-types*
	 #:reload-database-types
	 #:*default-database-type*
	 #:*initialized-database-types*
	 #:initialize-database-type
	 #:*connect-if-exists*
	 #:*default-database*
	 #:connected-databases
	 #:database
	 #:database-name
	 #:closed-database
	 #:find-database
	 #:database-name-from-spec
	 #:connect
	 #:disconnect
	 #:query
	 #:execute-command
	 #:map-query
	 #:do-query

	 ;; functional.cl
	 #:insert-records
	 #:delete-records
	 #:update-records
	 #:with-database

	 ;; utils.cl
	 #:number-to-sql-string
	 #:float-to-sql-string
	 #:sql-escape-quotes

	 ;; For UncommonSQL support
	 #:sql-ident
	 #:list-tables
	 #:list-attributes
	 #:attribute-type
	 #:create-sequence
	 #:drop-sequence
	 #:sequence-next

	 ;; Pooled connections
	 #:disconnect-pooled
	 #:find-or-create-connection-pool

	 ;; Transactions
	 #:with-transaction
	 #:commit-transaction
	 #:rollback-transaction
	 #:add-transaction-commit-hook
	 #:add-transaction-rollback-hook

	 ;; Large objects (Marc B)
	 #:create-large-object
	 #:write-large-object
	 #:read-large-object
	 #:delete-large-object
	 ))
    (:documentation "This is the INTERNAL SQL-Interface package of CLSQL."))

(defpackage #:clsql
    (:import-from #:clsql-sys . #1#)
    (:export . #1#)
    (:documentation "This is the SQL-Interface package of CLSQL."))
);eval-when

(defpackage #:clsql-user
    (:use #:common-lisp #:clsql)
    (:documentation "This is the user package for experimenting with CLSQL."))


Fix one hard coded value I missed in r339185.

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

// RUN: %clang_cc1 -cl-std=CL2.0 -O0 -emit-llvm -o - -triple amdgcn < %s | FileCheck %s --check-prefixes=COMMON,AMDGPU
// RUN: %clang_cc1 -cl-std=CL2.0 -O0 -emit-llvm -o - -triple "spir-unknown-unknown" < %s | FileCheck %s --check-prefixes=COMMON,SPIR32
// RUN: %clang_cc1 -cl-std=CL2.0 -O0 -emit-llvm -o - -triple "spir64-unknown-unknown" < %s | FileCheck %s --check-prefixes=COMMON,SPIR64
// RUN: %clang_cc1 -cl-std=CL2.0 -O0 -debug-info-kind=limited -emit-llvm -o - -triple amdgcn < %s | FileCheck %s --check-prefixes=CHECK-DEBUG

// Check that the enqueue_kernel array temporary is in the entry block to avoid
// a dynamic alloca

typedef struct {int a;} ndrange_t;

kernel void test(int i) {
// COMMON-LABEL: define {{.*}} void @test
// COMMON-LABEL: entry:
// AMDGPU: %block_sizes = alloca [1 x i64]
// SPIR32: %block_sizes = alloca [1 x i32]
// SPIR64: %block_sizes = alloca [1 x i64]
// COMMON-LABEL: if.then:
// COMMON-NOT: alloca
// CHECK-DEBUG: getelementptr {{.*}} %block_sizes, {{.*}} !dbg ![[TEMPLOCATION:[0-9]+]]
// COMMON-LABEL: if.end
  queue_t default_queue;
  unsigned flags = 0;
  ndrange_t ndrange;
  if (i)
    enqueue_kernel(default_queue, flags, ndrange, ^(local void *a) { }, 32);
}

// Check that the temporary is scoped to the `if`

// CHECK-DEBUG: ![[TESTFILE:[0-9]+]] = !DIFile(filename: "<stdin>"
// CHECK-DEBUG: ![[TESTSCOPE:[0-9]+]] = distinct !DISubprogram(name: "test", {{.*}} file: ![[TESTFILE]]
// CHECK-DEBUG: ![[IFSCOPE:[0-9]+]] = distinct !DILexicalBlock(scope: ![[TESTSCOPE]], file: ![[TESTFILE]], line: 24)
// CHECK-DEBUG: ![[TEMPLOCATION]] = !DILocation(line: 25, scope: ![[IFSCOPE]])

// RUN: %clang_cc1 -cl-std=CL2.0 -O0 -emit-llvm -o - -triple amdgcn < %s | FileCheck %s --check-prefixes=COMMON,AMDGPU
// RUN: %clang_cc1 -cl-std=CL2.0 -O0 -emit-llvm -o - -triple "spir-unknown-unknown" < %s | FileCheck %s --check-prefixes=COMMON,SPIR32
// RUN: %clang_cc1 -cl-std=CL2.0 -O0 -emit-llvm -o - -triple "spir64-unknown-unknown" < %s | FileCheck %s --check-prefixes=COMMON,SPIR64
// RUN: %clang_cc1 -cl-std=CL2.0 -O0 -debug-info-kind=limited -emit-llvm -o - -triple amdgcn < %s | FileCheck %s --check-prefixes=CHECK-DEBUG

// Check that the enqueue_kernel array temporary is in the entry block to avoid
// a dynamic alloca

typedef struct {int a;} ndrange_t;

kernel void test(int i) {
// COMMON-LABEL: define {{.*}} void @test
// COMMON-LABEL: entry:
// AMDGPU: %block_sizes = alloca [1 x i64]
// SPIR32: %block_sizes = alloca [1 x i32]
// SPIR64: %block_sizes = alloca [1 x i64]
// COMMON-LABEL: if.then:
// COMMON-NOT: alloca
// CHECK-DEBUG: getelementptr {{.*}} %block_sizes, {{.*}} !dbg ![[TEMPLOCATION:[0-9]+]]
// COMMON-LABEL: if.end
  queue_t default_queue;
  unsigned flags = 0;
  ndrange_t ndrange;
  if (i)
    enqueue_kernel(default_queue, flags, ndrange, ^(local void *a) { }, 32);
}

// Check that the temporary is scoped to the `if`

// CHECK-DEBUG: ![[TESTFILE:[0-9]+]] = !DIFile(filename: "<stdin>"
// CHECK-DEBUG: ![[TESTSCOPE:[0-9]+]] = distinct !DISubprogram(name: "test", {{.*}} file: ![[TESTFILE]]
// CHECK-DEBUG: ![[IFSCOPE:[0-9]+]] = distinct !DILexicalBlock(scope: ![[TESTSCOPE]], file: !1, line: 24)
// CHECK-DEBUG: ![[TEMPLOCATION]] = !DILocation(line: 25, scope: ![[IFSCOPE]])


r2048: Debian build

r2048: Debian build

;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*-
;;;; *************************************************************************
;;;; FILE IDENTIFICATION
;;;;
;;;; Name:          postgresql-usql.sql
;;;; Purpose:       PostgreSQL interface for USQL routines
;;;; Programmers:   Kevin M. Rosenberg and onShore Development Inc
;;;; Date Started:  Mar 2002
;;;;
;;;; $Id: postgresql-usql.cl,v 1.3 2002/05/15 17:03:43 kevin Exp $
;;;;
;;;; This file, part of CLSQL, is Copyright (c) 2002 by Kevin M. Rosenberg
;;;; and by onShore Development Inc.
;;;;
;;;; CLSQL users are granted the rights to distribute and use this software
;;;; as governed by the terms of the Lisp Lesser GNU Public License
;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL.
;;;; *************************************************************************

(declaim (optimize (debug 3) (speed 3) (safety 1) (compilation-speed 0)))
(in-package :clsql-postgresql)

(defmethod database-list-tables ((database postgresql-database)
                                 &key (system-tables nil))
  (let ((res (mapcar #'car (database-query
			    "SELECT tablename FROM pg_tables"
			    database nil))))
    (if (not system-tables)
        (remove-if #'(lambda (table)
                       (equal (subseq table 0 3)
                              "pg_")) res)
      res)))

(defmethod database-list-attributes ((table string)
				     (database postgresql-database))
  (let* ((result
	  (mapcar #'car
		  (database-query
		   (format nil
			   "SELECT attname FROM pg_class,pg_attribute WHERE pg_class.oid=attrelid AND relname='~A'" relname)
		   database nil))))
    (if result
	(reverse
         (remove-if #'(lambda (it) (member it '("cmin"
                                                "cmax"
                                                "xmax"
                                                "xmin"
						"oid"
                                                "ctid"
						;; kmr -- added tableoid
						"tableoid") :test #'equal))
		    result)))))

(defmethod database-attribute-type (attribute (table string)
				    (database postgresql-database))
  (let ((result
	  (mapcar #'car
		  (database-query
		   (format nil
			   "SELECT pg_type.typname FROM pg_type,pg_class,pg_attribute WHERE pg_class.oid=pg_attribute.attrelid AND pg_class.relname='~A' AND pg_attribute.attname='~A' AND pg_attribute.atttypid=pg_type.oid"
			   table attribute)
		   database nil))))
    (if result
	(intern (string-upcase (car result)) :keyword) nil)))

(defmethod database-create-sequence (sequence-name
				     (database postgresql-database))
  (database-execute-command
   (concatenate 'string "CREATE SEQUENCE " (sql-escape sequence-name)) database))

(defmethod database-drop-sequence (sequence-name
				   (database postgresql-database))
  (database-execute-command
   (concatenate 'string "DROP SEQUENCE " (sql-escape sequence-name)) database))

(defmethod database-sequence-next (sequence-name
				   (database postgresql-database))
  (parse-integer
   (caar
    (database-query
     (concatenate 'string "SELECT NEXTVAL ('" (sql-escape sequence-name) "')")
     database nil))))

;; Functions depending upon high-level USQL classes/functions

#|
(defmethod database-output-sql ((expr clsql-sys::sql-typecast-exp)
				(database postgresql-database))
  (with-slots (clsql-sys::modifier clsql-sys::components)
    expr
    (if clsql-sys::modifier
        (progn
          (clsql-sys::output-sql clsql-sys::components database)
          (write-char #\: clsql-sys::*sql-stream*)
          (write-char #\: clsql-sys::*sql-stream*)
          (write-string (symbol-name clsql-sys::modifier)
			clsql-sys::*sql-stream*)))))

(defmethod database-output-sql-as-type ((type (eql 'integer)) val
					(database postgresql-database))
  ;; typecast it so it uses the indexes
  (when val
    (make-instance 'clsql-sys::sql-typecast-exp
                   :modifier 'int8
                   :components val)))
|#

;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*-
;;;; *************************************************************************
;;;; FILE IDENTIFICATION
;;;;
;;;; Name:          postgresql-usql.sql
;;;; Purpose:       PostgreSQL interface for USQL routines
;;;; Programmers:   Kevin M. Rosenberg and onShore Development Inc
;;;; Date Started:  Mar 2002
;;;;
;;;; $Id: postgresql-usql.cl,v 1.2 2002/04/07 15:11:04 kevin Exp $
;;;;
;;;; This file, part of CLSQL, is Copyright (c) 2002 by Kevin M. Rosenberg
;;;; and by onShore Development Inc.
;;;;
;;;; CLSQL users are granted the rights to distribute and use this software
;;;; as governed by the terms of the Lisp Lesser GNU Public License
;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL.
;;;; *************************************************************************

(declaim (optimize (debug 3) (speed 3) (safety 1) (compilation-speed 0)))
(in-package :clsql-postgresql)

(defmethod database-list-tables ((database postgresql-database)
                                 &key (system-tables nil))
  (let ((res (mapcar #'car (database-query
			    "SELECT tablename FROM pg_tables"
			    database nil))))
    (if (not system-tables)
        (remove-if #'(lambda (table)
                       (equal (subseq table 0 3)
                              "pg_")) res)
      res)))

(defmethod database-list-attributes ((table string)
				     (database postgresql-database))
  (let* ((result
	  (mapcar #'car
		  (database-query
		   (format nil
			   "SELECT attname FROM pg_class,pg_attribute WHERE pg_class.oid=attrelid AND relname='~A'" relname)
		   database nil))))
    (if result
	(reverse
         (remove-if #'(lambda (it) (member it '("cmin"
                                                "cmax"
                                                "xmax"
                                                "xmin"
						"oid"
                                                "ctid"
						;; kmr -- added tableoid
						"tableoid") :test #'equal))
		    result)))))

(defmethod database-attribute-type (attribute (table string)
				    (database postgresql-database))
  (let ((result
	  (mapcar #'car
		  (database-query
		   (format nil
			   "SELECT pg_type.typname FROM pg_type,pg_class,pg_attribute WHERE pg_class.oid=pg_attribute.attrelid AND pg_class.relname='~A' AND pg_attribute.attname='~A' AND pg_attribute.atttypid=pg_type.oid"
			   table attribute)
		   database nil))))
    (if result
	(intern (string-upcase (car result)) :keyword) nil)))

(defmethod database-create-sequence (sequence-name
				     (database postgresql-database))
  (database-execute-command
   (concatenate 'string "CREATE SEQUENCE " (sql-escape sequence-name)) database))

(defmethod database-drop-sequence (sequence-name
				   (database postgresql-database))
  (database-execute-command
   (concatenate 'string "DROP SEQUENCE " (sql-escape sequence-name)) database))

(defmethod database-sequence-next (sequence-name
				   (database postgresql-database))
  (parse-integer
   (caar
    (database-query
     (concatenate 'string "SELECT NEXTVAL ('" (sql-escape sequence-name) "')")
     database nil))))

(defmethod database-output-sql ((expr clsql-sys::sql-typecast-exp)
				(database postgresql-database))
  (with-slots (clsql-sys::modifier clsql-sys::components)
    expr
    (if clsql-sys::modifier
        (progn
          (clsql-sys::output-sql clsql-sys::components database)
          (write-char #\: clsql-sys::*sql-stream*)
          (write-char #\: clsql-sys::*sql-stream*)
          (write-string (symbol-name clsql-sys::modifier)
			clsql-sys::*sql-stream*)))))

(defmethod database-output-sql-as-type ((type (eql 'integer)) val
					(database postgresql-database))
  ;; typecast it so it uses the indexes
  (when val
    (make-instance 'clsql-sys::sql-typecast-exp
                   :modifier 'int8
                   :components val)))


fix the mismatch running on cpu devices

fix the mismatch running on cpu devices

/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// @Authors
//    Nathan, liujun@multicorewareinc.com
//    Peng Xiao, pengxiao@outlook.com
//    Baichuan Su, baichuan@multicorewareinc.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 oclMaterials 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*/

#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics:enable
#define MAX_FLOAT 3.40282e+038f

#ifndef T
#define T float
#endif

#ifndef BLOCK_SIZE
#define BLOCK_SIZE 16
#endif
#ifndef MAX_DESC_LEN
#define MAX_DESC_LEN 64
#endif

#ifndef DIST_TYPE
#define DIST_TYPE 0
#endif

//http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
int bit1Count(int v)
{
    v = v - ((v >> 1) & 0x55555555);                    // reuse input as temporary
    v = (v & 0x33333333) + ((v >> 2) & 0x33333333);     // temp
    return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; // count
}

// dirty fix for non-template support
#if   (DIST_TYPE == 0) // L1Dist
#   ifdef T_FLOAT
#       define DIST(x, y) fabs((x) - (y))
        typedef float value_type;
        typedef float result_type;
#   else
#       define DIST(x, y) abs((x) - (y))
        typedef int value_type;
        typedef int result_type;
#   endif
#define DIST_RES(x) (x)
#elif (DIST_TYPE == 1) // L2Dist
#define DIST(x, y) (((x) - (y)) * ((x) - (y)))
typedef float value_type;
typedef float result_type;
#define DIST_RES(x) sqrt(x)
#elif (DIST_TYPE == 2) // Hamming
#define DIST(x, y) bit1Count( (x) ^ (y) )
typedef int value_type;
typedef int result_type;
#define DIST_RES(x) (x)
#endif

result_type reduce_block(
    __local value_type *s_query,
    __local value_type *s_train,
    int lidx,
    int lidy
    )
{
    result_type result = 0;
    #pragma unroll
    for (int j = 0 ; j < BLOCK_SIZE ; j++)
    {
        result += DIST(
            s_query[lidy * BLOCK_SIZE + j],
            s_train[j * BLOCK_SIZE + lidx]);
    }
    return DIST_RES(result);
}

result_type reduce_block_match(
    __local value_type *s_query,
    __local value_type *s_train,
    int lidx,
    int lidy
    )
{
    result_type result = 0;
    #pragma unroll
    for (int j = 0 ; j < BLOCK_SIZE ; j++)
    {
        result += DIST(
            s_query[lidy * BLOCK_SIZE + j],
            s_train[j * BLOCK_SIZE + lidx]);
    }
    return (result);
}

result_type reduce_multi_block(
    __local value_type *s_query,
    __local value_type *s_train,
    int block_index,
    int lidx,
    int lidy
    )
{
    result_type result = 0;
    #pragma unroll
    for (int j = 0 ; j < BLOCK_SIZE ; j++)
    {
        result += DIST(
            s_query[lidy * MAX_DESC_LEN + block_index * BLOCK_SIZE + j],
            s_train[j * BLOCK_SIZE + lidx]);
    }
    return result;
}

/* 2dim launch, global size: dim0 is (query rows + BLOCK_SIZE - 1) / BLOCK_SIZE * BLOCK_SIZE, dim1 is BLOCK_SIZE
local size: dim0 is BLOCK_SIZE, dim1 is BLOCK_SIZE.
*/
__kernel void BruteForceMatch_UnrollMatch(
    __global T *query,
    __global T *train,
    //__global float *mask,
    __global int *bestTrainIdx,
    __global float *bestDistance,
    __local float *sharebuffer,
    int query_rows,
    int query_cols,
    int train_rows,
    int train_cols,
    int step
)
{
    const int lidx = get_local_id(0);
    const int lidy = get_local_id(1);
    const int groupidx = get_group_id(0);

    __local value_type *s_query = (__local value_type *)sharebuffer;
    __local value_type *s_train = (__local value_type *)sharebuffer + BLOCK_SIZE * MAX_DESC_LEN;

    int queryIdx = groupidx * BLOCK_SIZE + lidy;
    // load the query into local memory.
    #pragma unroll
    for (int i = 0 ;  i <  MAX_DESC_LEN / BLOCK_SIZE; i ++)
    {
        int loadx = lidx + i * BLOCK_SIZE;
        s_query[lidy * MAX_DESC_LEN + loadx] = loadx < query_cols ? query[min(queryIdx, query_rows - 1)  * (step / sizeof(float)) + loadx] : 0;
    }

    float myBestDistance = MAX_FLOAT;
    int myBestTrainIdx = -1;

    // loopUnrolledCached to find the best trainIdx and best distance.
    volatile int imgIdx = 0;
    for (int t = 0, endt = (train_rows + BLOCK_SIZE - 1) / BLOCK_SIZE; t < endt; t++)
    {
        result_type result = 0;
        #pragma unroll
        for (int i = 0 ; i < MAX_DESC_LEN / BLOCK_SIZE ; i++)
        {
            //load a BLOCK_SIZE * BLOCK_SIZE block into local train.
            const int loadx = lidx + i * BLOCK_SIZE;
            s_train[lidx * BLOCK_SIZE + lidy] = loadx < train_cols ? train[min(t * BLOCK_SIZE + lidy, train_rows - 1) * (step / sizeof(float)) + loadx] : 0;

            //synchronize to make sure each elem for reduceIteration in share memory is written already.
            barrier(CLK_LOCAL_MEM_FENCE);

            result += reduce_multi_block(s_query, s_train, i, lidx, lidy);

            barrier(CLK_LOCAL_MEM_FENCE);
        }

        result = DIST_RES(result);

        int trainIdx = t * BLOCK_SIZE + lidx;

        if (queryIdx < query_rows && trainIdx < train_rows && result < myBestDistance/* && mask(queryIdx, trainIdx)*/)
        {
            //bestImgIdx = imgIdx;
            myBestDistance = result;
            myBestTrainIdx = trainIdx;
        }
    }

    barrier(CLK_LOCAL_MEM_FENCE);
    __local float *s_distance = (__local float*)(sharebuffer);
    __local int* s_trainIdx = (__local int *)(sharebuffer + BLOCK_SIZE * BLOCK_SIZE);

    //find BestMatch
    s_distance += lidy * BLOCK_SIZE;
    s_trainIdx += lidy * BLOCK_SIZE;
    s_distance[lidx] = myBestDistance;
    s_trainIdx[lidx] = myBestTrainIdx;

    barrier(CLK_LOCAL_MEM_FENCE);

    //reduce -- now all reduce implement in each threads.
    #pragma unroll
    for (int k = 0 ; k < BLOCK_SIZE; k++)
    {
        if (myBestDistance > s_distance[k])
        {
            myBestDistance = s_distance[k];
            myBestTrainIdx = s_trainIdx[k];
        }
    }

    if (queryIdx < query_rows && lidx == 0)
    {
        bestTrainIdx[queryIdx] = myBestTrainIdx;
        bestDistance[queryIdx] = myBestDistance;
    }
}

__kernel void BruteForceMatch_Match(
    __global T *query,
    __global T *train,
    //__global float *mask,
    __global int *bestTrainIdx,
    __global float *bestDistance,
    __local float *sharebuffer,
    int query_rows,
    int query_cols,
    int train_rows,
    int train_cols,
    int step
)
{
    const int lidx = get_local_id(0);
    const int lidy = get_local_id(1);
    const int groupidx = get_group_id(0);

    const int queryIdx = groupidx * BLOCK_SIZE + lidy;

    float myBestDistance = MAX_FLOAT;
    int myBestTrainIdx = -1;

    __local value_type *s_query = (__local value_type *)sharebuffer;
    __local value_type *s_train = (__local value_type *)sharebuffer + BLOCK_SIZE * BLOCK_SIZE;

    // loop
    for (int t = 0 ;  t < (train_rows + BLOCK_SIZE - 1) / BLOCK_SIZE ; t++)
    {
        result_type result = 0;
        for (int i = 0 ; i < (query_cols + BLOCK_SIZE - 1) / BLOCK_SIZE ; i++)
        {
            const int loadx = lidx + i * BLOCK_SIZE;
            //load query and train into local memory
            s_query[lidy * BLOCK_SIZE + lidx] = 0;
            s_train[lidx * BLOCK_SIZE + lidy] = 0;

            if (loadx < query_cols)
            {
                s_query[lidy * BLOCK_SIZE + lidx] = query[min(queryIdx, query_rows - 1) * (step / sizeof(float)) + loadx];
                s_train[lidx * BLOCK_SIZE + lidy] = train[min(t * BLOCK_SIZE + lidy, train_rows - 1) * (step / sizeof(float)) + loadx];
            }

            barrier(CLK_LOCAL_MEM_FENCE);

            result += reduce_block_match(s_query, s_train, lidx, lidy);

            barrier(CLK_LOCAL_MEM_FENCE);
        }

        result = DIST_RES(result);

        const int trainIdx = t * BLOCK_SIZE + lidx;

        if (queryIdx < query_rows && trainIdx < train_rows && result < myBestDistance /*&& mask(queryIdx, trainIdx)*/)
        {
            //myBestImgidx = imgIdx;
            myBestDistance = result;
            myBestTrainIdx = trainIdx;
        }
    }

    barrier(CLK_LOCAL_MEM_FENCE);

    __local float *s_distance = (__local float *)sharebuffer;
    __local int *s_trainIdx = (__local int *)(sharebuffer + BLOCK_SIZE * BLOCK_SIZE);

    //findBestMatch
    s_distance += lidy * BLOCK_SIZE;
    s_trainIdx += lidy * BLOCK_SIZE;
    s_distance[lidx] = myBestDistance;
    s_trainIdx[lidx] = myBestTrainIdx;

    barrier(CLK_LOCAL_MEM_FENCE);

    //reduce -- now all reduce implement in each threads.
    for (int k = 0 ; k < BLOCK_SIZE; k++)
    {
        if (myBestDistance > s_distance[k])
        {
            myBestDistance = s_distance[k];
            myBestTrainIdx = s_trainIdx[k];
        }
    }

    if (queryIdx < query_rows && lidx == 0)
    {
        bestTrainIdx[queryIdx] = myBestTrainIdx;
        bestDistance[queryIdx] = myBestDistance;
    }
}

//radius_unrollmatch
__kernel void BruteForceMatch_RadiusUnrollMatch(
    __global T *query,
    __global T *train,
    float maxDistance,
    //__global float *mask,
    __global int *bestTrainIdx,
    __global float *bestDistance,
    __global int *nMatches,
    __local float *sharebuffer,
    int query_rows,
    int query_cols,
    int train_rows,
    int train_cols,
    int bestTrainIdx_cols,
    int step,
    int ostep
)
{
    const int lidx = get_local_id(0);
    const int lidy = get_local_id(1);
    const int groupidx = get_group_id(0);
    const int groupidy = get_group_id(1);

    const int queryIdx = groupidy * BLOCK_SIZE + lidy;
    const int trainIdx = groupidx * BLOCK_SIZE + lidx;

    __local value_type *s_query = (__local value_type *)sharebuffer;
    __local value_type *s_train = (__local value_type *)sharebuffer + BLOCK_SIZE * BLOCK_SIZE;

    result_type result = 0;
    for (int i = 0 ; i < MAX_DESC_LEN / BLOCK_SIZE ; ++i)
    {
        //load a BLOCK_SIZE * BLOCK_SIZE block into local train.
        const int loadx = lidx + i * BLOCK_SIZE;

        s_query[lidy * BLOCK_SIZE + lidx] = loadx < query_cols ? query[min(queryIdx, query_rows - 1)  * (step / sizeof(float)) + loadx] : 0;
        s_train[lidx * BLOCK_SIZE + lidy] = loadx < query_cols ? train[min(groupidx * BLOCK_SIZE + lidy, train_rows - 1)  * (step / sizeof(float)) + loadx] : 0;

        //synchronize to make sure each elem for reduceIteration in share memory is written already.
        barrier(CLK_LOCAL_MEM_FENCE);

        result += reduce_block(s_query, s_train, lidx, lidy);

        barrier(CLK_LOCAL_MEM_FENCE);
    }

    if (queryIdx < query_rows && trainIdx < train_rows &&
        convert_float(result) < maxDistance/* && mask(queryIdx, trainIdx)*/)
    {
        unsigned int ind = atom_inc(nMatches + queryIdx/*, (unsigned int) -1*/);

        if(ind < bestTrainIdx_cols)
        {
            //bestImgIdx = imgIdx;
            bestTrainIdx[queryIdx * (ostep / sizeof(int)) + ind] = trainIdx;
            bestDistance[queryIdx * (ostep / sizeof(float)) + ind] = result;
        }
    }
}

//radius_match
__kernel void BruteForceMatch_RadiusMatch(
    __global T *query,
    __global T *train,
    float maxDistance,
    //__global float *mask,
    __global int *bestTrainIdx,
    __global float *bestDistance,
    __global int *nMatches,
    __local float *sharebuffer,
    int query_rows,
    int query_cols,
    int train_rows,
    int train_cols,
    int bestTrainIdx_cols,
    int step,
    int ostep
)
{
    const int lidx = get_local_id(0);
    const int lidy = get_local_id(1);
    const int groupidx = get_group_id(0);
    const int groupidy = get_group_id(1);

    const int queryIdx = groupidy * BLOCK_SIZE + lidy;
    const int trainIdx = groupidx * BLOCK_SIZE + lidx;

    __local value_type *s_query = (__local value_type *)sharebuffer;
    __local value_type *s_train = (__local value_type *)sharebuffer + BLOCK_SIZE * BLOCK_SIZE;

    result_type result = 0;
    for (int i = 0 ; i < (query_cols + BLOCK_SIZE - 1) / BLOCK_SIZE ; ++i)
    {
        //load a BLOCK_SIZE * BLOCK_SIZE block into local train.
        const int loadx = lidx + i * BLOCK_SIZE;

        s_query[lidy * BLOCK_SIZE + lidx] = loadx < query_cols ? query[min(queryIdx, query_rows - 1)  * (step / sizeof(float)) + loadx] : 0;
        s_train[lidx * BLOCK_SIZE + lidy] = loadx < query_cols ? train[min(groupidx * BLOCK_SIZE + lidy, train_rows - 1)  * (step / sizeof(float)) + loadx] : 0;

        //synchronize to make sure each elem for reduceIteration in share memory is written already.
        barrier(CLK_LOCAL_MEM_FENCE);

        result += reduce_block(s_query, s_train, lidx, lidy);

        barrier(CLK_LOCAL_MEM_FENCE);
    }

    if (queryIdx < query_rows && trainIdx < train_rows &&
        convert_float(result) < maxDistance/* && mask(queryIdx, trainIdx)*/)
    {
        unsigned int ind = atom_inc(nMatches + queryIdx);

        if(ind < bestTrainIdx_cols)
        {
            //bestImgIdx = imgIdx;
            bestTrainIdx[queryIdx * (ostep / sizeof(int)) + ind] = trainIdx;
            bestDistance[queryIdx * (ostep / sizeof(float)) + ind] = result;
        }
    }
}

__kernel void BruteForceMatch_knnUnrollMatch(
    __global T *query,
    __global T *train,
    //__global float *mask,
    __global int2 *bestTrainIdx,
    __global float2 *bestDistance,
    __local float *sharebuffer,
    int query_rows,
    int query_cols,
    int train_rows,
    int train_cols,
    int step
)
{
    const int lidx = get_local_id(0);
    const int lidy = get_local_id(1);
    const int groupidx = get_group_id(0);

    const int queryIdx = groupidx * BLOCK_SIZE + lidy;
    __local value_type *s_query = (__local value_type *)sharebuffer;
    __local value_type *s_train = (__local value_type *)sharebuffer + BLOCK_SIZE * MAX_DESC_LEN;

    // load the query into local memory.
    for (int i = 0 ;  i <  MAX_DESC_LEN / BLOCK_SIZE; i ++)
    {
        int loadx = lidx + i * BLOCK_SIZE;
        s_query[lidy * MAX_DESC_LEN + loadx] = loadx < query_cols ? query[min(queryIdx, query_rows - 1)  * (step / sizeof(float)) + loadx] : 0;
    }

    float myBestDistance1 = MAX_FLOAT;
    float myBestDistance2 = MAX_FLOAT;
    int myBestTrainIdx1 = -1;
    int myBestTrainIdx2 = -1;

    //loopUnrolledCached
    volatile int imgIdx = 0;
    for (int t = 0 ; t < (train_rows + BLOCK_SIZE - 1) / BLOCK_SIZE ; t++)
    {
        result_type result = 0;
        for (int i = 0 ; i < MAX_DESC_LEN / BLOCK_SIZE ; i++)
        {
            //load a BLOCK_SIZE * BLOCK_SIZE block into local train.
            const int loadx = lidx + i * BLOCK_SIZE;
            s_train[lidx * BLOCK_SIZE + lidy] = loadx < train_cols ? train[min(t * BLOCK_SIZE + lidy, train_rows - 1) * (step / sizeof(float)) + loadx] : 0;

            //synchronize to make sure each elem for reduceIteration in share memory is written already.
            barrier(CLK_LOCAL_MEM_FENCE);

            result += reduce_multi_block(s_query, s_train, i, lidx, lidy);

            barrier(CLK_LOCAL_MEM_FENCE);
        }

        result = DIST_RES(result);

        const int trainIdx = t * BLOCK_SIZE + lidx;

        if (queryIdx < query_rows && trainIdx < train_rows)
        {
            if (result < myBestDistance1)
            {
                myBestDistance2 = myBestDistance1;
                myBestTrainIdx2 = myBestTrainIdx1;
                myBestDistance1 = result;
                myBestTrainIdx1 = trainIdx;
            }
            else if (result < myBestDistance2)
            {
                myBestDistance2 = result;
                myBestTrainIdx2 = trainIdx;
            }
        }
    }

    barrier(CLK_LOCAL_MEM_FENCE);

    __local float *s_distance = (local float *)sharebuffer;
    __local int *s_trainIdx = (local int *)(sharebuffer + BLOCK_SIZE * BLOCK_SIZE);

    // find BestMatch
    s_distance += lidy * BLOCK_SIZE;
    s_trainIdx += lidy * BLOCK_SIZE;

    s_distance[lidx] = myBestDistance1;
    s_trainIdx[lidx] = myBestTrainIdx1;

    float bestDistance1 = MAX_FLOAT;
    float bestDistance2 = MAX_FLOAT;
    int bestTrainIdx1 = -1;
    int bestTrainIdx2 = -1;
    barrier(CLK_LOCAL_MEM_FENCE);

    if (lidx == 0)
    {
        for (int i = 0 ; i < BLOCK_SIZE ; i++)
        {
            float val = s_distance[i];
            if (val < bestDistance1)
            {
                bestDistance2 = bestDistance1;
                bestTrainIdx2 = bestTrainIdx1;

                bestDistance1 = val;
                bestTrainIdx1 = s_trainIdx[i];
            }
            else if (val < bestDistance2)
            {
                bestDistance2 = val;
                bestTrainIdx2 = s_trainIdx[i];
            }
        }
    }

    barrier(CLK_LOCAL_MEM_FENCE);

    s_distance[lidx] = myBestDistance2;
    s_trainIdx[lidx] = myBestTrainIdx2;

    barrier(CLK_LOCAL_MEM_FENCE);

    if (lidx == 0)
    {
        for (int i = 0 ; i < BLOCK_SIZE ; i++)
        {
            float val = s_distance[i];

            if (val < bestDistance2)
            {
                bestDistance2 = val;
                bestTrainIdx2 = s_trainIdx[i];
            }
        }
    }

    myBestDistance1 = bestDistance1;
    myBestDistance2 = bestDistance2;

    myBestTrainIdx1 = bestTrainIdx1;
    myBestTrainIdx2 = bestTrainIdx2;

    if (queryIdx < query_rows && lidx == 0)
    {
        bestTrainIdx[queryIdx] = (int2)(myBestTrainIdx1, myBestTrainIdx2);
        bestDistance[queryIdx] = (float2)(myBestDistance1, myBestDistance2);
    }
}

__kernel void BruteForceMatch_knnMatch(
    __global T *query,
    __global T *train,
    //__global float *mask,
    __global int2 *bestTrainIdx,
    __global float2 *bestDistance,
    __local float *sharebuffer,
    int query_rows,
    int query_cols,
    int train_rows,
    int train_cols,
    int step
)
{
    const int lidx = get_local_id(0);
    const int lidy = get_local_id(1);
    const int groupidx = get_group_id(0);

    const int queryIdx = groupidx * BLOCK_SIZE + lidy;
    __local value_type *s_query = (__local value_type *)sharebuffer;
    __local value_type *s_train = (__local value_type *)sharebuffer + BLOCK_SIZE * BLOCK_SIZE;

    float myBestDistance1 = MAX_FLOAT;
    float myBestDistance2 = MAX_FLOAT;
    int myBestTrainIdx1 = -1;
    int myBestTrainIdx2 = -1;

    //loop
    for (int  t = 0 ; t < (train_rows + BLOCK_SIZE - 1) / BLOCK_SIZE ; t++)
    {
        result_type result = 0.0f;
        for (int i = 0 ; i < (query_cols + BLOCK_SIZE -1) / BLOCK_SIZE ; i++)
        {
            const int loadx = lidx + i * BLOCK_SIZE;
            //load query and train into local memory
            s_query[lidy * BLOCK_SIZE + lidx] = 0;
            s_train[lidx * BLOCK_SIZE + lidy] = 0;

            if (loadx < query_cols)
            {
                s_query[lidy * BLOCK_SIZE + lidx] = query[min(queryIdx, query_rows - 1) * (step / sizeof(float)) + loadx];
                s_train[lidx * BLOCK_SIZE + lidy] = train[min(t * BLOCK_SIZE + lidy, train_rows - 1) * (step / sizeof(float)) + loadx];
            }

            barrier(CLK_LOCAL_MEM_FENCE);

            result += reduce_block_match(s_query, s_train, lidx, lidy);

            barrier(CLK_LOCAL_MEM_FENCE);
        }

        result = DIST_RES(result);

        const int trainIdx = t * BLOCK_SIZE + lidx;

        if (queryIdx < query_rows && trainIdx < train_rows /*&& mask(queryIdx, trainIdx)*/)
        {
            if (result < myBestDistance1)
            {
                myBestDistance2 = myBestDistance1;
                myBestTrainIdx2 = myBestTrainIdx1;
                myBestDistance1 = result;
                myBestTrainIdx1 = trainIdx;
            }
            else if (result < myBestDistance2)
            {
                myBestDistance2 = result;
                myBestTrainIdx2 = trainIdx;
            }
        }
    }

    barrier(CLK_LOCAL_MEM_FENCE);

    __local float *s_distance = (__local float *)sharebuffer;
    __local int *s_trainIdx = (__local int *)(sharebuffer + BLOCK_SIZE * BLOCK_SIZE);

    //findBestMatch
    s_distance += lidy * BLOCK_SIZE;
    s_trainIdx += lidy * BLOCK_SIZE;

    s_distance[lidx] = myBestDistance1;
    s_trainIdx[lidx] = myBestTrainIdx1;

    float bestDistance1 = MAX_FLOAT;
    float bestDistance2 = MAX_FLOAT;
    int bestTrainIdx1 = -1;
    int bestTrainIdx2 = -1;
    barrier(CLK_LOCAL_MEM_FENCE);

    if (lidx == 0)
    {
        for (int i = 0 ; i < BLOCK_SIZE ; i++)
        {
            float val = s_distance[i];
            if (val < bestDistance1)
            {
                bestDistance2 = bestDistance1;
                bestTrainIdx2 = bestTrainIdx1;

                bestDistance1 = val;
                bestTrainIdx1 = s_trainIdx[i];
            }
            else if (val < bestDistance2)
            {
                bestDistance2 = val;
                bestTrainIdx2 = s_trainIdx[i];
            }
        }
    }

    barrier(CLK_LOCAL_MEM_FENCE);

    s_distance[lidx] = myBestDistance2;
    s_trainIdx[lidx] = myBestTrainIdx2;

    barrier(CLK_LOCAL_MEM_FENCE);

    if (lidx == 0)
    {
        for (int i = 0 ; i < BLOCK_SIZE ; i++)
        {
            float val = s_distance[i];

            if (val < bestDistance2)
            {
                bestDistance2 = val;
                bestTrainIdx2 = s_trainIdx[i];
            }
        }
    }

    myBestDistance1 = bestDistance1;
    myBestDistance2 = bestDistance2;

    myBestTrainIdx1 = bestTrainIdx1;
    myBestTrainIdx2 = bestTrainIdx2;

    if (queryIdx < query_rows && lidx == 0)
    {
        bestTrainIdx[queryIdx] = (int2)(myBestTrainIdx1, myBestTrainIdx2);
        bestDistance[queryIdx] = (float2)(myBestDistance1, myBestDistance2);
    }
}

kernel void BruteForceMatch_calcDistanceUnrolled(
    __global T *query,
    __global T *train,
    //__global float *mask,
    __global float *allDist,
    __local float *sharebuffer,
    int query_rows,
    int query_cols,
    int train_rows,
    int train_cols,
    int step)
{
    /* Todo */
}

kernel void BruteForceMatch_calcDistance(
    __global T *query,
    __global T *train,
    //__global float *mask,
    __global float *allDist,
    __local float *sharebuffer,
    int query_rows,
    int query_cols,
    int train_rows,
    int train_cols,
    int step)
{
    /* Todo */
}

kernel void BruteForceMatch_findBestMatch(
    __global float *allDist,
    __global int *bestTrainIdx,
    __global float *bestDistance,
    int k
)
{
    /* Todo */
}

/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// @Authors
//    Nathan, liujun@multicorewareinc.com
//    Peng Xiao, pengxiao@outlook.com
//    Baichuan Su, baichuan@multicorewareinc.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 oclMaterials 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*/

#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics:enable
#define MAX_FLOAT 3.40282e+038f

#ifndef T
#define T float
#endif

#ifndef BLOCK_SIZE
#define BLOCK_SIZE 16
#endif
#ifndef MAX_DESC_LEN
#define MAX_DESC_LEN 64
#endif

#ifndef DIST_TYPE
#define DIST_TYPE 0
#endif

//http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
int bit1Count(int v)
{
    v = v - ((v >> 1) & 0x55555555);                    // reuse input as temporary
    v = (v & 0x33333333) + ((v >> 2) & 0x33333333);     // temp
    return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; // count
}

// dirty fix for non-template support
#if   (DIST_TYPE == 0) // L1Dist
#   ifdef T_FLOAT
#       define DIST(x, y) fabs((x) - (y))
        typedef float value_type;
        typedef float result_type;
#   else
#       define DIST(x, y) abs((x) - (y))
        typedef int value_type;
        typedef int result_type;
#   endif
#define DIST_RES(x) (x)
#elif (DIST_TYPE == 1) // L2Dist
#define DIST(x, y) (((x) - (y)) * ((x) - (y)))
typedef float value_type;
typedef float result_type;
#define DIST_RES(x) sqrt(x)
#elif (DIST_TYPE == 2) // Hamming
#define DIST(x, y) bit1Count( (x) ^ (y) )
typedef int value_type;
typedef int result_type;
#define DIST_RES(x) (x)
#endif

result_type reduce_block(
    __local value_type *s_query,
    __local value_type *s_train,
    int lidx,
    int lidy
    )
{
    result_type result = 0;
    #pragma unroll
    for (int j = 0 ; j < BLOCK_SIZE ; j++)
    {
        result += DIST(
            s_query[lidy * BLOCK_SIZE + j],
            s_train[j * BLOCK_SIZE + lidx]);
    }
    return DIST_RES(result);
}

result_type reduce_multi_block(
    __local value_type *s_query,
    __local value_type *s_train,
    int block_index,
    int lidx,
    int lidy
    )
{
    result_type result = 0;
    #pragma unroll
    for (int j = 0 ; j < BLOCK_SIZE ; j++)
    {
        result += DIST(
            s_query[lidy * MAX_DESC_LEN + block_index * BLOCK_SIZE + j],
            s_train[j * BLOCK_SIZE + lidx]);
    }
    return result;
}

/* 2dim launch, global size: dim0 is (query rows + BLOCK_SIZE - 1) / BLOCK_SIZE * BLOCK_SIZE, dim1 is BLOCK_SIZE
local size: dim0 is BLOCK_SIZE, dim1 is BLOCK_SIZE.
*/
__kernel void BruteForceMatch_UnrollMatch(
    __global T *query,
    __global T *train,
    //__global float *mask,
    __global int *bestTrainIdx,
    __global float *bestDistance,
    __local float *sharebuffer,
    int query_rows,
    int query_cols,
    int train_rows,
    int train_cols,
    int step
)
{
    const int lidx = get_local_id(0);
    const int lidy = get_local_id(1);
    const int groupidx = get_group_id(0);

    __local value_type *s_query = (__local value_type *)sharebuffer;
    __local value_type *s_train = (__local value_type *)sharebuffer + BLOCK_SIZE * MAX_DESC_LEN;

    int queryIdx = groupidx * BLOCK_SIZE + lidy;
    // load the query into local memory.
    #pragma unroll
    for (int i = 0 ;  i <  MAX_DESC_LEN / BLOCK_SIZE; i ++)
    {
        int loadx = lidx + i * BLOCK_SIZE;
        s_query[lidy * MAX_DESC_LEN + loadx] = loadx < query_cols ? query[min(queryIdx, query_rows - 1)  * (step / sizeof(float)) + loadx] : 0;
    }

    float myBestDistance = MAX_FLOAT;
    int myBestTrainIdx = -1;

    // loopUnrolledCached to find the best trainIdx and best distance.
    volatile int imgIdx = 0;
    for (int t = 0, endt = (train_rows + BLOCK_SIZE - 1) / BLOCK_SIZE; t < endt; t++)
    {
        result_type result = 0;
        #pragma unroll
        for (int i = 0 ; i < MAX_DESC_LEN / BLOCK_SIZE ; i++)
        {
            //load a BLOCK_SIZE * BLOCK_SIZE block into local train.
            const int loadx = lidx + i * BLOCK_SIZE;
            s_train[lidx * BLOCK_SIZE + lidy] = loadx < train_cols ? train[min(t * BLOCK_SIZE + lidy, train_rows - 1) * (step / sizeof(float)) + loadx] : 0;

            //synchronize to make sure each elem for reduceIteration in share memory is written already.
            barrier(CLK_LOCAL_MEM_FENCE);

            result += reduce_multi_block(s_query, s_train, i, lidx, lidy);

            barrier(CLK_LOCAL_MEM_FENCE);
        }

        result = DIST_RES(result);

        int trainIdx = t * BLOCK_SIZE + lidx;

        if (queryIdx < query_rows && trainIdx < train_rows && result < myBestDistance/* && mask(queryIdx, trainIdx)*/)
        {
            //bestImgIdx = imgIdx;
            myBestDistance = result;
            myBestTrainIdx = trainIdx;
        }
    }

    barrier(CLK_LOCAL_MEM_FENCE);
    __local float *s_distance = (__local float*)(sharebuffer);
    __local int* s_trainIdx = (__local int *)(sharebuffer + BLOCK_SIZE * BLOCK_SIZE);

    //find BestMatch
    s_distance += lidy * BLOCK_SIZE;
    s_trainIdx += lidy * BLOCK_SIZE;
    s_distance[lidx] = myBestDistance;
    s_trainIdx[lidx] = myBestTrainIdx;

    barrier(CLK_LOCAL_MEM_FENCE);

    //reduce -- now all reduce implement in each threads.
    #pragma unroll
    for (int k = 0 ; k < BLOCK_SIZE; k++)
    {
        if (myBestDistance > s_distance[k])
        {
            myBestDistance = s_distance[k];
            myBestTrainIdx = s_trainIdx[k];
        }
    }

    if (queryIdx < query_rows && lidx == 0)
    {
        bestTrainIdx[queryIdx] = myBestTrainIdx;
        bestDistance[queryIdx] = myBestDistance;
    }
}

__kernel void BruteForceMatch_Match(
    __global T *query,
    __global T *train,
    //__global float *mask,
    __global int *bestTrainIdx,
    __global float *bestDistance,
    __local float *sharebuffer,
    int query_rows,
    int query_cols,
    int train_rows,
    int train_cols,
    int step
)
{
    const int lidx = get_local_id(0);
    const int lidy = get_local_id(1);
    const int groupidx = get_group_id(0);

    const int queryIdx = groupidx * BLOCK_SIZE + lidy;

    float myBestDistance = MAX_FLOAT;
    int myBestTrainIdx = -1;

    __local value_type *s_query = (__local value_type *)sharebuffer;
    __local value_type *s_train = (__local value_type *)sharebuffer + BLOCK_SIZE * BLOCK_SIZE;

    // loop
    for (int t = 0 ;  t < (train_rows + BLOCK_SIZE - 1) / BLOCK_SIZE ; t++)
    {
        result_type result = 0;
        for (int i = 0 ; i < (query_cols + BLOCK_SIZE - 1) / BLOCK_SIZE ; i++)
        {
            const int loadx = lidx + i * BLOCK_SIZE;
            //load query and train into local memory
            s_query[lidy * BLOCK_SIZE + lidx] = 0;
            s_train[lidx * BLOCK_SIZE + lidy] = 0;

            if (loadx < query_cols)
            {
                s_query[lidy * BLOCK_SIZE + lidx] = query[min(queryIdx, query_rows - 1) * (step / sizeof(float)) + loadx];
                s_train[lidx * BLOCK_SIZE + lidy] = train[min(t * BLOCK_SIZE + lidy, train_rows - 1) * (step / sizeof(float)) + loadx];
            }

            barrier(CLK_LOCAL_MEM_FENCE);

            result += reduce_block(s_query, s_train, lidx, lidy);

            barrier(CLK_LOCAL_MEM_FENCE);
        }

        const int trainIdx = t * BLOCK_SIZE + lidx;

        if (queryIdx < query_rows && trainIdx < train_rows && result < myBestDistance /*&& mask(queryIdx, trainIdx)*/)
        {
            //myBestImgidx = imgIdx;
            myBestDistance = result;
            myBestTrainIdx = trainIdx;
        }
    }

    barrier(CLK_LOCAL_MEM_FENCE);

    __local float *s_distance = (__local float *)sharebuffer;
    __local int *s_trainIdx = (__local int *)(sharebuffer + BLOCK_SIZE * BLOCK_SIZE);

    //findBestMatch
    s_distance += lidy * BLOCK_SIZE;
    s_trainIdx += lidy * BLOCK_SIZE;
    s_distance[lidx] = myBestDistance;
    s_trainIdx[lidx] = myBestTrainIdx;

    barrier(CLK_LOCAL_MEM_FENCE);

    //reduce -- now all reduce implement in each threads.
    for (int k = 0 ; k < BLOCK_SIZE; k++)
    {
        if (myBestDistance > s_distance[k])
        {
            myBestDistance = s_distance[k];
            myBestTrainIdx = s_trainIdx[k];
        }
    }

    if (queryIdx < query_rows && lidx == 0)
    {
        bestTrainIdx[queryIdx] = myBestTrainIdx;
        bestDistance[queryIdx] = myBestDistance;
    }
}

//radius_unrollmatch
__kernel void BruteForceMatch_RadiusUnrollMatch(
    __global T *query,
    __global T *train,
    float maxDistance,
    //__global float *mask,
    __global int *bestTrainIdx,
    __global float *bestDistance,
    __global int *nMatches,
    __local float *sharebuffer,
    int query_rows,
    int query_cols,
    int train_rows,
    int train_cols,
    int bestTrainIdx_cols,
    int step,
    int ostep
)
{
    const int lidx = get_local_id(0);
    const int lidy = get_local_id(1);
    const int groupidx = get_group_id(0);
    const int groupidy = get_group_id(1);

    const int queryIdx = groupidy * BLOCK_SIZE + lidy;
    const int trainIdx = groupidx * BLOCK_SIZE + lidx;

    __local value_type *s_query = (__local value_type *)sharebuffer;
    __local value_type *s_train = (__local value_type *)sharebuffer + BLOCK_SIZE * BLOCK_SIZE;

    result_type result = 0;
    for (int i = 0 ; i < MAX_DESC_LEN / BLOCK_SIZE ; ++i)
    {
        //load a BLOCK_SIZE * BLOCK_SIZE block into local train.
        const int loadx = lidx + i * BLOCK_SIZE;

        s_query[lidy * BLOCK_SIZE + lidx] = loadx < query_cols ? query[min(queryIdx, query_rows - 1)  * (step / sizeof(float)) + loadx] : 0;
        s_train[lidx * BLOCK_SIZE + lidy] = loadx < query_cols ? train[min(groupidx * BLOCK_SIZE + lidy, train_rows - 1)  * (step / sizeof(float)) + loadx] : 0;

        //synchronize to make sure each elem for reduceIteration in share memory is written already.
        barrier(CLK_LOCAL_MEM_FENCE);

        result += reduce_block(s_query, s_train, lidx, lidy);

        barrier(CLK_LOCAL_MEM_FENCE);
    }

    if (queryIdx < query_rows && trainIdx < train_rows &&
        convert_float(result) < maxDistance/* && mask(queryIdx, trainIdx)*/)
    {
        unsigned int ind = atom_inc(nMatches + queryIdx/*, (unsigned int) -1*/);

        if(ind < bestTrainIdx_cols)
        {
            //bestImgIdx = imgIdx;
            bestTrainIdx[queryIdx * (ostep / sizeof(int)) + ind] = trainIdx;
            bestDistance[queryIdx * (ostep / sizeof(float)) + ind] = result;
        }
    }
}

//radius_match
__kernel void BruteForceMatch_RadiusMatch(
    __global T *query,
    __global T *train,
    float maxDistance,
    //__global float *mask,
    __global int *bestTrainIdx,
    __global float *bestDistance,
    __global int *nMatches,
    __local float *sharebuffer,
    int query_rows,
    int query_cols,
    int train_rows,
    int train_cols,
    int bestTrainIdx_cols,
    int step,
    int ostep
)
{
    const int lidx = get_local_id(0);
    const int lidy = get_local_id(1);
    const int groupidx = get_group_id(0);
    const int groupidy = get_group_id(1);

    const int queryIdx = groupidy * BLOCK_SIZE + lidy;
    const int trainIdx = groupidx * BLOCK_SIZE + lidx;

    __local value_type *s_query = (__local value_type *)sharebuffer;
    __local value_type *s_train = (__local value_type *)sharebuffer + BLOCK_SIZE * BLOCK_SIZE;

    result_type result = 0;
    for (int i = 0 ; i < (query_cols + BLOCK_SIZE - 1) / BLOCK_SIZE ; ++i)
    {
        //load a BLOCK_SIZE * BLOCK_SIZE block into local train.
        const int loadx = lidx + i * BLOCK_SIZE;

        s_query[lidy * BLOCK_SIZE + lidx] = loadx < query_cols ? query[min(queryIdx, query_rows - 1)  * (step / sizeof(float)) + loadx] : 0;
        s_train[lidx * BLOCK_SIZE + lidy] = loadx < query_cols ? train[min(groupidx * BLOCK_SIZE + lidy, train_rows - 1)  * (step / sizeof(float)) + loadx] : 0;

        //synchronize to make sure each elem for reduceIteration in share memory is written already.
        barrier(CLK_LOCAL_MEM_FENCE);

        result += reduce_block(s_query, s_train, lidx, lidy);

        barrier(CLK_LOCAL_MEM_FENCE);
    }

    if (queryIdx < query_rows && trainIdx < train_rows &&
        convert_float(result) < maxDistance/* && mask(queryIdx, trainIdx)*/)
    {
        unsigned int ind = atom_inc(nMatches + queryIdx);

        if(ind < bestTrainIdx_cols)
        {
            //bestImgIdx = imgIdx;
            bestTrainIdx[queryIdx * (ostep / sizeof(int)) + ind] = trainIdx;
            bestDistance[queryIdx * (ostep / sizeof(float)) + ind] = result;
        }
    }
}

__kernel void BruteForceMatch_knnUnrollMatch(
    __global T *query,
    __global T *train,
    //__global float *mask,
    __global int2 *bestTrainIdx,
    __global float2 *bestDistance,
    __local float *sharebuffer,
    int query_rows,
    int query_cols,
    int train_rows,
    int train_cols,
    int step
)
{
    const int lidx = get_local_id(0);
    const int lidy = get_local_id(1);
    const int groupidx = get_group_id(0);

    const int queryIdx = groupidx * BLOCK_SIZE + lidy;
    __local value_type *s_query = (__local value_type *)sharebuffer;
    __local value_type *s_train = (__local value_type *)sharebuffer + BLOCK_SIZE * MAX_DESC_LEN;

    // load the query into local memory.
    for (int i = 0 ;  i <  MAX_DESC_LEN / BLOCK_SIZE; i ++)
    {
        int loadx = lidx + i * BLOCK_SIZE;
        s_query[lidy * MAX_DESC_LEN + loadx] = loadx < query_cols ? query[min(queryIdx, query_rows - 1)  * (step / sizeof(float)) + loadx] : 0;
    }

    float myBestDistance1 = MAX_FLOAT;
    float myBestDistance2 = MAX_FLOAT;
    int myBestTrainIdx1 = -1;
    int myBestTrainIdx2 = -1;

    //loopUnrolledCached
    volatile int imgIdx = 0;
    for (int t = 0 ; t < (train_rows + BLOCK_SIZE - 1) / BLOCK_SIZE ; t++)
    {
        result_type result = 0;
        for (int i = 0 ; i < MAX_DESC_LEN / BLOCK_SIZE ; i++)
        {
            //load a BLOCK_SIZE * BLOCK_SIZE block into local train.
            const int loadx = lidx + i * BLOCK_SIZE;
            s_train[lidx * BLOCK_SIZE + lidy] = loadx < train_cols ? train[min(t * BLOCK_SIZE + lidy, train_rows - 1) * (step / sizeof(float)) + loadx] : 0;

            //synchronize to make sure each elem for reduceIteration in share memory is written already.
            barrier(CLK_LOCAL_MEM_FENCE);

            result += reduce_multi_block(s_query, s_train, i, lidx, lidy);

            barrier(CLK_LOCAL_MEM_FENCE);
        }

        result = DIST_RES(result);

        const int trainIdx = t * BLOCK_SIZE + lidx;

        if (queryIdx < query_rows && trainIdx < train_rows)
        {
            if (result < myBestDistance1)
            {
                myBestDistance2 = myBestDistance1;
                myBestTrainIdx2 = myBestTrainIdx1;
                myBestDistance1 = result;
                myBestTrainIdx1 = trainIdx;
            }
            else if (result < myBestDistance2)
            {
                myBestDistance2 = result;
                myBestTrainIdx2 = trainIdx;
            }
        }
    }

    barrier(CLK_LOCAL_MEM_FENCE);

    __local float *s_distance = (local float *)sharebuffer;
    __local int *s_trainIdx = (local int *)(sharebuffer + BLOCK_SIZE * BLOCK_SIZE);

    // find BestMatch
    s_distance += lidy * BLOCK_SIZE;
    s_trainIdx += lidy * BLOCK_SIZE;

    s_distance[lidx] = myBestDistance1;
    s_trainIdx[lidx] = myBestTrainIdx1;

    float bestDistance1 = MAX_FLOAT;
    float bestDistance2 = MAX_FLOAT;
    int bestTrainIdx1 = -1;
    int bestTrainIdx2 = -1;
    barrier(CLK_LOCAL_MEM_FENCE);

    if (lidx == 0)
    {
        for (int i = 0 ; i < BLOCK_SIZE ; i++)
        {
            float val = s_distance[i];
            if (val < bestDistance1)
            {
                bestDistance2 = bestDistance1;
                bestTrainIdx2 = bestTrainIdx1;

                bestDistance1 = val;
                bestTrainIdx1 = s_trainIdx[i];
            }
            else if (val < bestDistance2)
            {
                bestDistance2 = val;
                bestTrainIdx2 = s_trainIdx[i];
            }
        }
    }

    barrier(CLK_LOCAL_MEM_FENCE);

    s_distance[lidx] = myBestDistance2;
    s_trainIdx[lidx] = myBestTrainIdx2;

    barrier(CLK_LOCAL_MEM_FENCE);

    if (lidx == 0)
    {
        for (int i = 0 ; i < BLOCK_SIZE ; i++)
        {
            float val = s_distance[i];

            if (val < bestDistance2)
            {
                bestDistance2 = val;
                bestTrainIdx2 = s_trainIdx[i];
            }
        }
    }

    myBestDistance1 = bestDistance1;
    myBestDistance2 = bestDistance2;

    myBestTrainIdx1 = bestTrainIdx1;
    myBestTrainIdx2 = bestTrainIdx2;

    if (queryIdx < query_rows && lidx == 0)
    {
        bestTrainIdx[queryIdx] = (int2)(myBestTrainIdx1, myBestTrainIdx2);
        bestDistance[queryIdx] = (float2)(myBestDistance1, myBestDistance2);
    }
}

__kernel void BruteForceMatch_knnMatch(
    __global T *query,
    __global T *train,
    //__global float *mask,
    __global int2 *bestTrainIdx,
    __global float2 *bestDistance,
    __local float *sharebuffer,
    int query_rows,
    int query_cols,
    int train_rows,
    int train_cols,
    int step
)
{
    const int lidx = get_local_id(0);
    const int lidy = get_local_id(1);
    const int groupidx = get_group_id(0);

    const int queryIdx = groupidx * BLOCK_SIZE + lidy;
    __local value_type *s_query = (__local value_type *)sharebuffer;
    __local value_type *s_train = (__local value_type *)sharebuffer + BLOCK_SIZE * BLOCK_SIZE;

    float myBestDistance1 = MAX_FLOAT;
    float myBestDistance2 = MAX_FLOAT;
    int myBestTrainIdx1 = -1;
    int myBestTrainIdx2 = -1;

    //loop
    for (int  t = 0 ; t < (train_rows + BLOCK_SIZE - 1) / BLOCK_SIZE ; t++)
    {
        result_type result = 0.0f;
        for (int i = 0 ; i < (query_cols + BLOCK_SIZE -1) / BLOCK_SIZE ; i++)
        {
            const int loadx = lidx + i * BLOCK_SIZE;
            //load query and train into local memory
            s_query[lidy * BLOCK_SIZE + lidx] = 0;
            s_train[lidx * BLOCK_SIZE + lidy] = 0;

            if (loadx < query_cols)
            {
                s_query[lidy * BLOCK_SIZE + lidx] = query[min(queryIdx, query_rows - 1) * (step / sizeof(float)) + loadx];
                s_train[lidx * BLOCK_SIZE + lidy] = train[min(t * BLOCK_SIZE + lidy, train_rows - 1) * (step / sizeof(float)) + loadx];
            }

            barrier(CLK_LOCAL_MEM_FENCE);

            result += reduce_block(s_query, s_train, lidx, lidy);

            barrier(CLK_LOCAL_MEM_FENCE);
        }

        const int trainIdx = t * BLOCK_SIZE + lidx;

        if (queryIdx < query_rows && trainIdx < train_rows /*&& mask(queryIdx, trainIdx)*/)
        {
            if (result < myBestDistance1)
            {
                myBestDistance2 = myBestDistance1;
                myBestTrainIdx2 = myBestTrainIdx1;
                myBestDistance1 = result;
                myBestTrainIdx1 = trainIdx;
            }
            else if (result < myBestDistance2)
            {
                myBestDistance2 = result;
                myBestTrainIdx2 = trainIdx;
            }
        }
    }

    barrier(CLK_LOCAL_MEM_FENCE);

    __local float *s_distance = (__local float *)sharebuffer;
    __local int *s_trainIdx = (__local int *)(sharebuffer + BLOCK_SIZE * BLOCK_SIZE);

    //findBestMatch
    s_distance += lidy * BLOCK_SIZE;
    s_trainIdx += lidy * BLOCK_SIZE;

    s_distance[lidx] = myBestDistance1;
    s_trainIdx[lidx] = myBestTrainIdx1;

    float bestDistance1 = MAX_FLOAT;
    float bestDistance2 = MAX_FLOAT;
    int bestTrainIdx1 = -1;
    int bestTrainIdx2 = -1;
    barrier(CLK_LOCAL_MEM_FENCE);

    if (lidx == 0)
    {
        for (int i = 0 ; i < BLOCK_SIZE ; i++)
        {
            float val = s_distance[i];
            if (val < bestDistance1)
            {
                bestDistance2 = bestDistance1;
                bestTrainIdx2 = bestTrainIdx1;

                bestDistance1 = val;
                bestTrainIdx1 = s_trainIdx[i];
            }
            else if (val < bestDistance2)
            {
                bestDistance2 = val;
                bestTrainIdx2 = s_trainIdx[i];
            }
        }
    }

    barrier(CLK_LOCAL_MEM_FENCE);

    s_distance[lidx] = myBestDistance2;
    s_trainIdx[lidx] = myBestTrainIdx2;

    barrier(CLK_LOCAL_MEM_FENCE);

    if (lidx == 0)
    {
        for (int i = 0 ; i < BLOCK_SIZE ; i++)
        {
            float val = s_distance[i];

            if (val < bestDistance2)
            {
                bestDistance2 = val;
                bestTrainIdx2 = s_trainIdx[i];
            }
        }
    }

    myBestDistance1 = bestDistance1;
    myBestDistance2 = bestDistance2;

    myBestTrainIdx1 = bestTrainIdx1;
    myBestTrainIdx2 = bestTrainIdx2;

    if (queryIdx < query_rows && lidx == 0)
    {
        bestTrainIdx[queryIdx] = (int2)(myBestTrainIdx1, myBestTrainIdx2);
        bestDistance[queryIdx] = (float2)(myBestDistance1, myBestDistance2);
    }
}

kernel void BruteForceMatch_calcDistanceUnrolled(
    __global T *query,
    __global T *train,
    //__global float *mask,
    __global float *allDist,
    __local float *sharebuffer,
    int query_rows,
    int query_cols,
    int train_rows,
    int train_cols,
    int step)
{
    /* Todo */
}

kernel void BruteForceMatch_calcDistance(
    __global T *query,
    __global T *train,
    //__global float *mask,
    __global float *allDist,
    __local float *sharebuffer,
    int query_rows,
    int query_cols,
    int train_rows,
    int train_cols,
    int step)
{
    /* Todo */
}

kernel void BruteForceMatch_findBestMatch(
    __global float *allDist,
    __global int *bestTrainIdx,
    __global float *bestDistance,
    int k
)
{
    /* Todo */
}


Test fixed.

Test fixed.


COMP: GPUPDEDeformableRegistrationFilter.cl fails to "compile".

The failure happens on Mac OS 10.8 with Intel OpenCL.
It is due to a non OpenCL conformant signature for the GPUPDEDeformableRegistrationFilter.cl
function, cf. http://software.intel.com/en-us/forums/topic/280040

/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

//
// Compute index for Global memory
//

// For 1 or 2 dimensional images, we have ysize = 1 and/or zsize = 1
#define MAXDIM 3

// Global memory order (indir/outdir)
//
//  0 (fast x) : x/y/z
//  1 (fast y) : y/z/x
//  2 (fast z) : z/x/y
int GetImageOffset(int order,
                    __constant int * size,
                    int index[MAXDIM])
{
  int idx;

  if(order == 0)
  {
    idx = (index[2]*size[1] + index[1])*size[0] + index[0];
  }
  else if(order == 1)
  {
    idx = (index[0]*size[2] + index[2])*size[1] + index[1];
  }
  else
  {
    idx = (index[1]*size[0] + index[0])*size[2] + index[2];
  }

  return idx;
}

//
// 3D block dimension is blockx*1*1 or 1*blocky*1 or 1*1*blockz
//
// For an image that is stored with the indir-th dimension as the consecutive dimension,
// smooth along the indir-th dimension, and store the result with the outdir-th dimension
// as the consecutive dimension.
__kernel void SmoothingFilterReorder(__global OUTPIXELTYPE *imgIn, __global OUTPIXELTYPE *imgOut,
                                    __constant int *imgSize, int dim,
                                    __constant OUTPIXELTYPE *filter, int filterSize,
                                    int indir, int outdir,
                                    __local volatile OUTPIXELTYPE *sharedFilter,
                                    __local volatile OUTPIXELTYPE *sharedData
                                    )
{
  int blockSize = get_local_size(indir);
  int threadId  = get_local_id(indir);
  int index[MAXDIM];
  int tempIndex[MAXDIM];

  int component;
  int radius = filterSize / 2;
  OUTPIXELTYPE sum;
  int i;
  int lowerBound = 0;
  int upperBound = max(0, imgSize[indir] - 1);

  for (i = threadId; i < filterSize; i += blockSize)
    {
    sharedFilter[i] = filter[i];
    }

  for (i = 0; i<MAXDIM; i++)
    {
    index[i] = get_global_id(i);
    tempIndex[i] = get_global_id(i);
    }

  for (component = 0; component < dim; component ++ )
    {
    index[indir] -= radius;

    // Load (blockSize+filterSize-1) elements along indir dimension
    for (i = threadId; i < blockSize+filterSize-1; i += blockSize)
      {
        if (index[indir] < 0 )
        {
          tempIndex[indir] = lowerBound;
        }
        else if (index[indir] > upperBound)
        {
          tempIndex[indir] = upperBound;
        }
        else
        {
          tempIndex[indir] = index[indir];
        }
        sharedData[i] = imgIn[GetImageOffset(indir, imgSize, tempIndex) * dim + component];
        index[indir] += blockSize;
      }
    // wait for loading data to shared memory
    barrier(CLK_LOCAL_MEM_FENCE);
    index[indir] = get_global_id(indir);

    // Important: we can't simply skip the above loading process if
    // get_global_id() is beyond the image region. This is due to that
    // thread with threadId loads elements at
    // (threadId - radius + blockSize * k)
    // where k is an interger.
    //
    // Otherwise, some boundary voxel may be not loaded. For example,
    // let us assume,
    // radius = 2, blockSize = 16, imgSize[0] = 8, indir = 0, dim = 2,
    // imgIn[0][7] is expected to be loaded by threadId = 7+2 = 9.
    // If we skip thread with threadId = 9 by simply checking
    // threadId >= imgSize[0], we will not load element imgIn[0][7].
    //
    // Therefore, we put the boundary check below before computing and
    // storing the dot sum.

    /* NOTE: More than three-level nested conditional statements (e.g.,
       if A && B && C..) invalidates command queue during kernel
       execution on Apple OpenCL 1.0 (such Macbook Pro with NVIDIA 9600M
       GT). Therefore, we flattened conditional statements. */

    bool isValid = true;
    if(get_global_id(0) >= imgSize[0]) isValid = false;
    if(get_global_id(1) >= imgSize[1]) isValid = false;
    if(get_global_id(2) >= imgSize[2]) isValid = false;

    if ( isValid )
      {
      // Compute the dot product
      sum = 0;
      for (i=0; i<filterSize; i++)
        {
          sum += sharedData[threadId+i] * sharedFilter[i];
        }
      imgOut[GetImageOffset(outdir, imgSize, index) * dim + component] = sum;
      }
    } // for component
}

// Smoothe the deformation field without reordering dimensions in the storage
// outdir is no longer used here, but it is kept as an argument for compatibility
__kernel void SmoothingFilter(__global OUTPIXELTYPE *imgIn, __global OUTPIXELTYPE *imgOut,
                              __constant int *imgSize, int dim,
                              __constant OUTPIXELTYPE *filter, int filterSize,
                              int indir, int outdir,
                              __local volatile OUTPIXELTYPE *sharedFilter,
                              __local volatile OUTPIXELTYPE *sharedData
)
{
  int blockSize = get_local_size(indir);
  int threadId  = get_local_id(indir);
  int index[MAXDIM];
  int tempIndex[MAXDIM];

  int component;
  int radius = filterSize / 2;
  OUTPIXELTYPE sum;
  int i, offset;
  int lowerBound = 0;
  int upperBound = max(0, imgSize[indir] - 1);

  for (i = threadId; i < filterSize; i += blockSize)
    {
    sharedFilter[i] = filter[i];
    }

  for (i = 0; i<MAXDIM; i++)
    {
    index[i] = get_global_id(i);
    tempIndex[i] = get_global_id(i);
    }

  for (component = 0; component < dim; component ++ )
    {
    index[indir] -= radius;

    // Load (blockSize+filterSize-1) elements along indir dimension
    for (i = threadId; i < blockSize+filterSize-1; i += blockSize)
      {
        if (index[indir] < 0 )
        {
          tempIndex[indir] = lowerBound;
        }
        else if (index[indir] > upperBound)
        {
          tempIndex[indir] = upperBound;
        }
        else
        {
          tempIndex[indir] = index[indir];
        }
        offset = (tempIndex[2]*imgSize[1] + tempIndex[1])*imgSize[0] + tempIndex[0];
        sharedData[i] = imgIn[offset * dim + component];

        index[indir] += blockSize;
      }
    // wait for loading data to shared memory
    barrier(CLK_LOCAL_MEM_FENCE);
    index[indir] = get_global_id(indir);

    // Important: we can't simply skip the above loading process if
    // get_global_id() is beyond the image region. This is due to that
    // thread with threadId loads elements at
    // (threadId - radius + blockSize * k)
    // where k is an interger.
    //
    // Otherwise, some boundary voxel may be not loaded. For example,
    // let us assume,
    // radius = 2, blockSize = 16, imgSize[0] = 8, indir = 0, dim = 2,
    // imgIn[0][7] is expected to be loaded by threadId = 7+2 = 9.
    // If we skip thread with threadId = 9 by simply checking
    // threadId >= imgSize[0], we will not load element imgIn[0][7].
    //
    // Therefore, we put the boundary check below before computing and
    // storing the dot sum.

    /* NOTE: More than three-level nested conditional statements (e.g.,
       if A && B && C..) invalidates command queue during kernel
       execution on Apple OpenCL 1.0 (such Macbook Pro with NVIDIA 9600M
       GT). Therefore, we flattened conditional statements. */

    bool isValid = true;
    if(get_global_id(0) >= imgSize[0]) isValid = false;
    if(get_global_id(1) >= imgSize[1]) isValid = false;
    if(get_global_id(2) >= imgSize[2]) isValid = false;

    if ( isValid )
      {
      // Compute the dot product
      sum = 0;
      for (i=0; i<filterSize; i++)
        {
        sum += sharedData[threadId+i] * sharedFilter[i];
        }
      offset = (index[2]*imgSize[1] + index[1])*imgSize[0] + index[0];
      imgOut[offset * dim + component] = sum;
      }
    } // for component
}

/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

//
// Compute index for Global memory
//

// For 1 or 2 dimensional images, we have ysize = 1 and/or zsize = 1
#define MAXDIM 3

// Global memory order (indir/outdir)
//
//  0 (fast x) : x/y/z
//  1 (fast y) : y/z/x
//  2 (fast z) : z/x/y
int GetImageOffset(int order,
                    __constant int size[MAXDIM],
                    int index[MAXDIM])
{
  int idx;

  if(order == 0)
  {
    idx = (index[2]*size[1] + index[1])*size[0] + index[0];
  }
  else if(order == 1)
  {
    idx = (index[0]*size[2] + index[2])*size[1] + index[1];
  }
  else
  {
    idx = (index[1]*size[0] + index[0])*size[2] + index[2];
  }

  return idx;
}

//
// 3D block dimension is blockx*1*1 or 1*blocky*1 or 1*1*blockz
//
// For an image that is stored with the indir-th dimension as the consecutive dimension,
// smooth along the indir-th dimension, and store the result with the outdir-th dimension
// as the consecutive dimension.
__kernel void SmoothingFilterReorder(__global OUTPIXELTYPE *imgIn, __global OUTPIXELTYPE *imgOut,
                                    __constant int *imgSize, int dim,
                                    __constant OUTPIXELTYPE *filter, int filterSize,
                                    int indir, int outdir,
                                    __local volatile OUTPIXELTYPE *sharedFilter,
                                    __local volatile OUTPIXELTYPE *sharedData
                                    )
{
  int blockSize = get_local_size(indir);
  int threadId  = get_local_id(indir);
  int index[MAXDIM];
  int tempIndex[MAXDIM];

  int component;
  int radius = filterSize / 2;
  OUTPIXELTYPE sum;
  int i;
  int lowerBound = 0;
  int upperBound = max(0, imgSize[indir] - 1);

  for (i = threadId; i < filterSize; i += blockSize)
    {
    sharedFilter[i] = filter[i];
    }

  for (i = 0; i<MAXDIM; i++)
    {
    index[i] = get_global_id(i);
    tempIndex[i] = get_global_id(i);
    }

  for (component = 0; component < dim; component ++ )
    {
    index[indir] -= radius;

    // Load (blockSize+filterSize-1) elements along indir dimension
    for (i = threadId; i < blockSize+filterSize-1; i += blockSize)
      {
        if (index[indir] < 0 )
        {
          tempIndex[indir] = lowerBound;
        }
        else if (index[indir] > upperBound)
        {
          tempIndex[indir] = upperBound;
        }
        else
        {
          tempIndex[indir] = index[indir];
        }
        sharedData[i] = imgIn[GetImageOffset(indir, imgSize, tempIndex) * dim + component];
        index[indir] += blockSize;
      }
    // wait for loading data to shared memory
    barrier(CLK_LOCAL_MEM_FENCE);
    index[indir] = get_global_id(indir);

    // Important: we can't simply skip the above loading process if
    // get_global_id() is beyond the image region. This is due to that
    // thread with threadId loads elements at
    // (threadId - radius + blockSize * k)
    // where k is an interger.
    //
    // Otherwise, some boundary voxel may be not loaded. For example,
    // let us assume,
    // radius = 2, blockSize = 16, imgSize[0] = 8, indir = 0, dim = 2,
    // imgIn[0][7] is expected to be loaded by threadId = 7+2 = 9.
    // If we skip thread with threadId = 9 by simply checking
    // threadId >= imgSize[0], we will not load element imgIn[0][7].
    //
    // Therefore, we put the boundary check below before computing and
    // storing the dot sum.

    /* NOTE: More than three-level nested conditional statements (e.g.,
       if A && B && C..) invalidates command queue during kernel
       execution on Apple OpenCL 1.0 (such Macbook Pro with NVIDIA 9600M
       GT). Therefore, we flattened conditional statements. */

    bool isValid = true;
    if(get_global_id(0) >= imgSize[0]) isValid = false;
    if(get_global_id(1) >= imgSize[1]) isValid = false;
    if(get_global_id(2) >= imgSize[2]) isValid = false;

    if ( isValid )
      {
      // Compute the dot product
      sum = 0;
      for (i=0; i<filterSize; i++)
        {
          sum += sharedData[threadId+i] * sharedFilter[i];
        }
      imgOut[GetImageOffset(outdir, imgSize, index) * dim + component] = sum;
      }
    } // for component
}

// Smoothe the deformation field without reordering dimensions in the storage
// outdir is no longer used here, but it is kept as an argument for compatibility
__kernel void SmoothingFilter(__global OUTPIXELTYPE *imgIn, __global OUTPIXELTYPE *imgOut,
                              __constant int *imgSize, int dim,
                              __constant OUTPIXELTYPE *filter, int filterSize,
                              int indir, int outdir,
                              __local volatile OUTPIXELTYPE *sharedFilter,
                              __local volatile OUTPIXELTYPE *sharedData
)
{
  int blockSize = get_local_size(indir);
  int threadId  = get_local_id(indir);
  int index[MAXDIM];
  int tempIndex[MAXDIM];

  int component;
  int radius = filterSize / 2;
  OUTPIXELTYPE sum;
  int i, offset;
  int lowerBound = 0;
  int upperBound = max(0, imgSize[indir] - 1);

  for (i = threadId; i < filterSize; i += blockSize)
    {
    sharedFilter[i] = filter[i];
    }

  for (i = 0; i<MAXDIM; i++)
    {
    index[i] = get_global_id(i);
    tempIndex[i] = get_global_id(i);
    }

  for (component = 0; component < dim; component ++ )
    {
    index[indir] -= radius;

    // Load (blockSize+filterSize-1) elements along indir dimension
    for (i = threadId; i < blockSize+filterSize-1; i += blockSize)
      {
        if (index[indir] < 0 )
        {
          tempIndex[indir] = lowerBound;
        }
        else if (index[indir] > upperBound)
        {
          tempIndex[indir] = upperBound;
        }
        else
        {
          tempIndex[indir] = index[indir];
        }
        offset = (tempIndex[2]*imgSize[1] + tempIndex[1])*imgSize[0] + tempIndex[0];
        sharedData[i] = imgIn[offset * dim + component];

        index[indir] += blockSize;
      }
    // wait for loading data to shared memory
    barrier(CLK_LOCAL_MEM_FENCE);
    index[indir] = get_global_id(indir);

    // Important: we can't simply skip the above loading process if
    // get_global_id() is beyond the image region. This is due to that
    // thread with threadId loads elements at
    // (threadId - radius + blockSize * k)
    // where k is an interger.
    //
    // Otherwise, some boundary voxel may be not loaded. For example,
    // let us assume,
    // radius = 2, blockSize = 16, imgSize[0] = 8, indir = 0, dim = 2,
    // imgIn[0][7] is expected to be loaded by threadId = 7+2 = 9.
    // If we skip thread with threadId = 9 by simply checking
    // threadId >= imgSize[0], we will not load element imgIn[0][7].
    //
    // Therefore, we put the boundary check below before computing and
    // storing the dot sum.

    /* NOTE: More than three-level nested conditional statements (e.g.,
       if A && B && C..) invalidates command queue during kernel
       execution on Apple OpenCL 1.0 (such Macbook Pro with NVIDIA 9600M
       GT). Therefore, we flattened conditional statements. */

    bool isValid = true;
    if(get_global_id(0) >= imgSize[0]) isValid = false;
    if(get_global_id(1) >= imgSize[1]) isValid = false;
    if(get_global_id(2) >= imgSize[2]) isValid = false;

    if ( isValid )
      {
      // Compute the dot product
      sum = 0;
      for (i=0; i<filterSize; i++)
        {
        sum += sharedData[threadId+i] * sharedFilter[i];
        }
      offset = (index[2]*imgSize[1] + index[1])*imgSize[0] + index[0];
      imgOut[offset * dim + component] = sum;
      }
    } // for component
}


rgb to planar:  check for out of bounds coordinates

/*  Copyright 2014 Aaron Boxer

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */

#include "ocl_platform.cl"

CONSTANT sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE  | CLK_FILTER_NEAREST;

void KERNEL run(read_only image2d_t idata, const unsigned int  width, const unsigned int height,
						write_only image2d_t R,
						 write_only image2d_t G,
						 write_only image2d_t B,
						 write_only image2d_t A ) {

        int x = getLocalId(0) + getGroupId(0) * WIN_SIZE_X;
		int y = getLocalId(1) + getGroupId(1) * WIN_SIZE_Y;
		if (x >=width || y >= height)
			return;
		int2 pos = (int2)(x,y);
		int4 pix = read_imagei(idata, sampler, pos);
		write_imagei(R,pos, (int4)(pix.x,0,0,0));
		write_imagei(G,pos, (int4)(pix.y,0,0,0));
		write_imagei(B,pos, (int4)(pix.z,0,0,0));
		write_imagei(A,pos, (int4)(pix.w,0,0,0));

}

/*  Copyright 2014 Aaron Boxer

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */

#include "ocl_platform.cl"

CONSTANT sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE  | CLK_FILTER_NEAREST;

void KERNEL run(read_only image2d_t idata, const unsigned int  width, const unsigned int height,
						write_only image2d_t R,
						 write_only image2d_t G,
						 write_only image2d_t B,
						 write_only image2d_t A ) {

        int x = getLocalId(0) + getGroupId(0) * WIN_SIZE_X;
		int y = getLocalId(1) + getGroupId(1) * WIN_SIZE_Y;
		int2 pos = (int2)(x,y);
		int4 pix = read_imagei(idata, sampler, pos);
		write_imagei(R,pos, (int4)(pix.x,0,0,0));
		write_imagei(G,pos, (int4)(pix.y,0,0,0));
		write_imagei(B,pos, (int4)(pix.z,0,0,0));
		write_imagei(A,pos, (int4)(pix.w,0,0,0));

}


Delete FastNoise.cl

Delete FastNoise.cl