example: pi calculation

example: pi calculation

/******************************************************************************
 * @file     prngcl_example_pi.cl
 * @author   Vadim Demchik <vadimdi@yahoo.com>
 * @version  1.1
 *
 * @brief    [PRNGCL library]
 *           EXAMPLE: OpenCL implementation of MRG32k3a pseudo-random number generator
 *
 *
 * @section  LICENSE
 *
 * Copyright (c) 2014, Vadim Demchik
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 *    Redistributions of source code must retain the above copyright notice,
 *      this list of conditions and the following disclaimer.
 *
 *    Redistributions in binary form must reproduce the above copyright notice,
 *      this list of conditions and the following disclaimer in the documentation
 *      and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *****************************************************************************/

#ifndef PRNGCL_EXAMPLE_PI_CL
#define PRNGCL_EXAMPLE_PI_CL

#include "prngcl_common.cl"

__kernel void
calculate_pi(__global hgpu_float4* randoms,
             __global float* acceptance,
             const uint N)
{
    uint index = GID;
    float count = 0;
    hgpu_float4 rnd,rnd2;

    for (uint i=0; i<N; i++) {
        rnd = randoms[index];
        rnd2 = rnd * rnd;
        if ((rnd2.x+rnd2.y) <= 1.0) count += 1.0;
        if ((rnd2.z+rnd2.w) <= 1.0) count += 1.0;

        index += GID_SIZE;
    }
    acceptance[GID] += count;
}

#endif

error: pathspec 'examples/prngcl_example_pi.cl' did not match any file(s) known to git


OpenCL implementation of seven-XOR PRNG

OpenCL implementation of seven-XOR PRNG

/******************************************************************************
 * @file     prngcl_xor7.cl
 * @author   Vadim Demchik <vadimdi@yahoo.com>
 * @version  1.1
 *
 * @brief    [PRNGCL library]
 *           contains OpenCL implementation of seven-XOR pseudo-random number generator
 *
 *
 * @section  CREDITS
 *
 *   Francois Panneton and Pierre L'ecuyer,
 *   "On the xorshift random number generators",
 *   ACM Transactions on Modeling and Computer Simulation (TOMACS), 15, 4 (2005), 346--361.
 *
 *
 * @section  LICENSE
 *
 * Copyright (c) 2013, Vadim Demchik
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 *    Redistributions of source code must retain the above copyright notice,
 *      this list of conditions and the following disclaimer.
 *
 *    Redistributions in binary form must reproduce the above copyright notice,
 *      this list of conditions and the following disclaimer in the documentation
 *      and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *****************************************************************************/

#ifndef PRNGCL_XOR7_CL
#define PRNGCL_XOR7_CL

#include "prngcl_common.cl"

#define XOR7_m_FP   (4294967296.0f)
#define XOR7_min    1
#define XOR7_max    4294967295
#define XOR7_min_FP (1.0/4294967296.0)
#define XOR7_max_FP (4294967295.0/4294967296.0)
#define XOR7_k      (2.3283064365386962890625E-10) // 1/(2^32-1)
#define XOR7_left   (XOR7_min_FP+XOR7_k*XOR7_max_FP)
#define XOR7_right  (XOR7_max_FP+XOR7_k*XOR7_min_FP)

__attribute__((always_inline)) void
xor7_step(uint4* seed1,uint4* seed2)
{
    uint t, y;
        t = (*seed2).w;     t = t ^ (t<<13);    y = t ^ (t<<9);
        t = (*seed2).x;     y^= t ^ (t<<7);
        t = (*seed1).w;     y^= t ^ (t>>3);
        t = (*seed1).y;     y^= t ^ (t>>10);
        t = (*seed1).x;     t = t ^ (t>>7);     y^= t ^ (t<<24);

        (*seed1).xyz = (*seed1).yzw;
        (*seed1).w   = (*seed2).x;
        (*seed2).xyz = (*seed2).yzw;
        (*seed2).w   = y;
}

#ifdef PRECISION_DOUBLE  // if double precision is defined
__attribute__((always_inline)) hgpu_double
xor7_step_double(uint4* seed1,uint4* seed2)
{
    hgpu_double result;
    uint rnd1, rnd2;
    uint4 sed1 = (*seed1);
    uint4 sed2 = (*seed2);
    bool flag = true;
    xor7_step(&sed1,&sed2);
    rnd1 = sed2.w;
    while (flag) {
        xor7_step(&sed1,&sed2);
        rnd2 = sed2.w;
        result = hgpu_uint_to_double(rnd1,rnd2,XOR7_min,XOR7_max,XOR7_k);
        if ((result>=XOR7_left) && (result<XOR7_right))
            flag = false;
        else
            rnd1 = rnd2;
    }
    (*seed1) = sed1;
    (*seed2) = sed2;
    return result;
}
#endif

__kernel void
xor7(__global uint4* seed_table,
     __global hgpu_float4* randoms,
       const uint N)
{
    uint giddst = GID;
#ifdef PRECISION_DOUBLE  // if double precision is defined
    hgpu_double4 result;
#else
    float4 result;
    float4 normal = (float4) XOR7_m_FP;
#endif
    uint4 seed1 = seed_table[GID];
    uint4 seed2 = seed_table[GID + GID_SIZE];
    for (uint i = 0; i < N; i++) {
#ifdef PRECISION_DOUBLE // if double precision is defined
        result.x = xor7_step_double(&seed1,&seed2);
        result.y = xor7_step_double(&seed1,&seed2);
        result.z = xor7_step_double(&seed1,&seed2);
        result.w = xor7_step_double(&seed1,&seed2);
        randoms[giddst] = result;
#else
        xor7_step(&seed1,&seed2);
            result.x = (float) seed2.w;
        xor7_step(&seed1,&seed2);
            result.y = (float) seed2.w;
        xor7_step(&seed1,&seed2);
            result.z = (float) seed2.w;
        xor7_step(&seed1,&seed2);
            result.w = (float) seed2.w;
        randoms[giddst] = result / normal;
#endif
        giddst += GID_SIZE;
    }
    seed_table[GID] = seed1;
    seed_table[GID + GID_SIZE] = seed2;
}

#endif

error: pathspec 'randomcl/prngcl_xor7.cl' did not match any file(s) known to git


Create fusion.cl

Create fusion.cl

#define MAX_DEPTH	(100000.0)

//============================================
// Image
//============================================
float get_depth( __global float *depth_map, int2 dim, float2 v ) {
	int2 p = clamp( convert_int2_rtn( v ), (int2)(0), dim - 1 );
	return depth_map[ p.x + p.y * dim.x ] * 0.001;
}

float3 get_normal( __global float3 *normal_map, int2 dim, float2 v ) {
	int2 p = clamp( convert_int2_rtn( v ), (int2)(0), dim - 1 );
	return normal_map[ p.x + p.y * dim.x ];
}

__kernel void depth_to_point( __global float *depth, __global float3 *points, int2 dim, float4 IK ) {
    int x = get_global_id(0);
    int y = get_global_id(1);
    if ( x >= dim.x || y >= dim.y ) {
        return;
    }

    int index = x + y * dim.x;

    float d = depth[ index ] * 0.001;

    float3 p = ( float3 )( x, y, d );
    p.xy -= IK.lo;
    p.xy /= IK.hi;
	p.xy *= d;

    points[ index ] = p;
}

__kernel void point_to_normal( __global float3 *points, __global float3 *normals, int2 dim ) {
    int x = get_global_id(0);
    int y = get_global_id(1);
    if ( x >= dim.x || y >= dim.y ) {
        return;
    }

    int index = x + y * dim.x;

    // FIXME : improve
    x = clamp( x, 1, dim.x - 2 );
    y = clamp( y, 1, dim.y - 2 );
    int k = x + y * dim.x;

    float3 s = points[ k + 1 ] - points[ k - 1 ];
    float3 t = points[ k + dim.x ] - points[ k - dim.x ];

    normals[ index ] = normalize( -cross( s, t ) );
}

__kernel void point_to_world( __global float3 *p, __global float3 *w, int2 dim, float16 M ) {
    int x = get_global_id(0);
    int y = get_global_id(1);
    if ( x >= dim.x || y >= dim.y ) {
        return;
    }

    int index = x + y * dim.x;

    float3 v = p[ index ];

    w[ index ] = M.lo.lo.xyz * v.x + M.lo.hi.xyz * v.y + M.hi.lo.xyz * v.z + M.hi.hi.xyz;
}

//============================================
// TSDF
//============================================
float2 get_df( __global float2 *vol, int3 dim, float3 v ) {
	int3 p = clamp( convert_int3_rtn( v ), (int3)(0), dim - 1 );
	return vol[ p.x + p.y * dim.x + p.z * dim.x * dim.y ];
}

float get_df_c( __global float2 *vol, int3 dim, float3 v ) {
	v -= 0.5;
	float3 i = floor(v);
	float3 f = v - i;

	float e000 = get_df( vol, dim, i + (float3)(0.0, 0.0, 0.0) ).x;
	float e100 = get_df( vol, dim, i + (float3)(1.0, 0.0, 0.0) ).x;
	float e010 = get_df( vol, dim, i + (float3)(0.0, 1.0, 0.0) ).x;
	float e110 = get_df( vol, dim, i + (float3)(1.0, 1.0, 0.0) ).x;

	float e001 = get_df( vol, dim, i + (float3)(0.0, 0.0, 1.0) ).x;
	float e101 = get_df( vol, dim, i + (float3)(1.0, 0.0, 1.0) ).x;
	float e011 = get_df( vol, dim, i + (float3)(0.0, 1.0, 1.0) ).x;
	float e111 = get_df( vol, dim, i + (float3)(1.0, 1.0, 1.0) ).x;

	float e00 = f.x * ( e100 - e000 ) + e000;
	float e10 = f.x * ( e110 - e010 ) + e010;
	float e01 = f.x * ( e101 - e001 ) + e001;
	float e11 = f.x * ( e111 - e011 ) + e011;

	float e0 = f.y * ( e10 - e00 ) + e00;
	float e1 = f.y * ( e11 - e01 ) + e01;

	float e = f.z * ( e1 - e0 ) + e0;

	return e;
}

float3 get_grad( __global float2 *vol, int3 dim, float3 v ) {
	float3 s = (float3)( 1.0, 0.0, 0.0 );

#if 1
	float3 n = (float3)(
						get_df_c( vol, dim, v + s.xyz ) - get_df_c( vol, dim, v - s.xyz ),
						get_df_c( vol, dim, v + s.zxy ) - get_df_c( vol, dim, v - s.zxy ),
						get_df_c( vol, dim, v + s.yzx ) - get_df_c( vol, dim, v - s.yzx )
						);
#else
	float3 n = (float3)(
						get_df( vol, dim, v + s.xyz ).x - get_df( vol, dim, v - s.xyz ).x,
						get_df( vol, dim, v + s.zxy ).x - get_df( vol, dim, v - s.zxy ).x,
						get_df( vol, dim, v + s.yzx ).x - get_df( vol, dim, v - s.yzx ).x
						);
#endif

	return normalize( n );
}

__kernel void df_clear( __global float2 *vol, int3 dim, float2 val ) {
	int x = get_global_id(0);
	int y = get_global_id(1);
	int z = get_global_id(2);

	if ( x >= dim.x || y >= dim.y || z >= dim.z ) {
		return;
	}

	int index = x + y * dim.x + z * dim.x * dim.y;

	vol[ index ] = val;
}

__kernel void df_sphere( __global float2 *vol, int3 dim, float r ) {
	int x = get_global_id(0);
	int y = get_global_id(1);
	int z = get_global_id(2);

	if ( x >= dim.x || y >= dim.y || z >= dim.z ) {
		return;
	}

	int index = x + y * dim.x + z * dim.x * dim.y;

	float3 v = (float3)( x, y, z ) + 0.5;
	float3 c = (float3)( dim.x, dim.y, dim.z ) * 0.5;

	float d = length( v - c ) - r;
	vol[ index ] = (float2)( d, 1.0 );
}

#define TRUNC		( 3.0 )
#define MAX_WEIGHT	( 2.0 )
__kernel void df_fuse(
			 __global float2 *vol, int3 vol_dim,
			 __global float *depth_map, __global float3 *normal_map, int2 map_dim,
			 float4 K, float16 M, float4 L
			 ) {
	int x = get_global_id(0);
	int y = get_global_id(1);
	int z = get_global_id(2);

	// volume space
	int3 pos = (int3)( x, y, z);
	int index = pos.x + pos.y * vol_dim.x + pos.z * vol_dim.x * vol_dim.y;
	if ( pos.x >= vol_dim.x || pos.y >= vol_dim.y || pos.z >= vol_dim.z ) {
        return;
    }

    // world space
    float3 world_v = ( convert_float3( pos ) + 0.5 ) * L.w + L.xyz;

    // view space
    float3 view_v = world_v - M.hi.hi.xyz;
    view_v = (float3)( dot( view_v, M.lo.lo.xyz ), dot( view_v, M.lo.hi.xyz ), dot( view_v, M.hi.lo.xyz ) );
    float3 dir = normalize( view_v );

    // proj space
    float  proj_z = view_v.z;
    float2 proj_v = view_v.xy / proj_z;
    proj_v *= K.hi;
    proj_v += K.lo;

    // proj range
    if ( proj_v.x < 0.0 || proj_v.y < 0.0 || proj_v.x >= map_dim.x || proj_v.y >= map_dim.y ) {
        return;
    }

//	vol[ index ] = (float2)(surf_z - proj_z );
//	return;

	  // normal
    float3 n = get_normal( normal_map, map_dim, proj_v );

    // sdf
    float dot_dir_n = -dot( dir, n );
    if ( dot_dir_n < 0.2 ) {
		return;
    }
	dot_dir_n /= dir.z; // dot_dir_z = dir.z

	float surf_z = get_depth( depth_map, map_dim, proj_v );

    float d = ( surf_z - proj_z ) * dot_dir_n / L.w;
	float w = dot_dir_n / proj_z * L.w;

	if ( d < -TRUNC || w <= 0.0 ) {
		return;
    }

    // weighted sum
    float2 df = vol[ index ];
    df.x = ( df.x * df.y + d * w ) / ( df.y + w );
    df.y += w;

	// clamp
	df.x = clamp( df.x, -TRUNC, TRUNC );
	df.y = min( df.y, MAX_WEIGHT );

	vol[ index ] = df;
}

//============================================
// Ray Cast
//============================================
float2 ray_vs_bound( float3 o, float3 inv, float3 bmin, float3 bmax, float2 e ) {
	float3 s = ( bmin - o ) * inv;
	float3 t = ( bmax - o ) * inv;
	float3 a = min( s, t );
	float3 b = max( s, t );
	return (float2)(
					max( max( e.x, a.x ), max( a.y, a.z ) ),
					min( min( e.y, b.x ), min( b.y, b.z ) )
					);
}

float ray_vs_df( __global float2 *vol, int3 dim, float3 o, float3 dir, float2 e ) {
	float t = e.x;
	float last_d = TRUNC;

	for ( int i = 0; i < 1500; i++ ){
		t += 1.0;
		if ( t >= e.y ) {
			break;
		}

		float3 v = o + dir * t;
		float2 d = get_df( vol, dim, v );
		if ( d.x <= 0.0 && d.y > 0.0 ) {
			t -= ( d.x / ( d.x - last_d ) );
			break;
		}
		last_d = d.x;
	}

	return t;
}

float3 gen_ray( float4 K, float16 M, float4 L, float2 p, float3 *o, float3 *dir ) {
	p -= K.lo;
	p /= K.hi;

	*dir = normalize( p.x * M.lo.lo.xyz + p.y * M.lo.hi.xyz - M.hi.lo.xyz );
	*o   = ( M.hi.hi.xyz - L.xyz ) / L.w;
}

__kernel void ray_cast( __global float4 *col, int2 col_dim, __global float2 *vol, int3 vol_dim, float4 K, float16 M, float4 L ) {
	int x = get_global_id(0);
	int y = get_global_id(1);
	if ( x >= col_dim.x || y >= col_dim.y ) {
		return;
	}

	int index = x + y * col_dim.x;

	// gen ray
	float3 o, dir;
	gen_ray( K, M, L, (float2)(x, y) + 0.5, &o, &dir );
	float3 inv = 1.0 / dir;

	// ray vs bound
	float2 e = ray_vs_bound( o, inv, (float3)( 0.0 ), convert_float3_rtn( vol_dim ), (float2)( 0.0, MAX_DEPTH ) );
	if ( e.x >= e.y ) {
		col[ index ] = ( float4 )( 0.0 );
		return;
	}

	// ray vs df
	float d = ray_vs_df( vol, vol_dim, o, dir, e );
	if ( d >= e.y )
	{
		col[ index ] = ( float4 )( 0.0, 0.0, 0.0, 0.0 );
		return;
	}

	float3 v = o + dir * d;
	float3 n = get_grad( vol, vol_dim, v );
	col[ index ] = ( float4 )( (float3)(dot( n, -dir )), 1.0 );
}

error: pathspec 'fusion.cl' did not match any file(s) known to git


Small fix for lights

Small fix for lights

/**********************************************************************
Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
********************************************************************/
#ifndef LIGHT_CL
#define LIGHT_CL

#include <../App/CL/utils.cl>
#include <../App/CL/payload.cl>
#include <../App/CL/texture.cl>
#include <../App/CL/scene.cl>

INLINE
bool IntersectTriangle(ray const* r, float3 v1, float3 v2, float3 v3, float* a, float* b)
{
    const float3 e1 = v2 - v1;
    const float3 e2 = v3 - v1;
    const float3 s1 = cross(r->d.xyz, e2);
    const float  invd = native_recip(dot(s1, e1));
    const float3 d = r->o.xyz - v1;
    const float  b1 = dot(d, s1) * invd;
    const float3 s2 = cross(d, e1);
    const float  b2 = dot(r->d.xyz, s2) * invd;
    const float temp = dot(e2, s2) * invd;

    if (b1 < 0.f || b1 > 1.f || b2 < 0.f || b1 + b2 > 1.f)
    {
        return false;
    }
    else
    {
        *a = b1;
        *b = b2;
        return true;
    }
}

/*
 Environment light
 */
/// Get intensity for a given direction
float3 EnvironmentLight_GetLe(// Light
                              Light const* light,
                              // Scene
                              Scene const* scene,
                              // Geometry
                              DifferentialGeometry const* dg,
                              // Direction to light source
                              float3* wo,
                              // Textures
                              TEXTURE_ARG_LIST
                              )
{
    // Sample envmap
    *wo *= 100000.f;
    //
    return light->multiplier * Texture_SampleEnvMap(normalize(*wo), TEXTURE_ARGS_IDX(light->multiplier));
}

/// Sample direction to the light
float3 EnvironmentLight_Sample(// Light
                               Light const* light,
                               // Scene
                               Scene const* scene,
                               // Geometry
                               DifferentialGeometry const* dg,
                               // Textures
                               TEXTURE_ARG_LIST,
                               // Sample
                               float2 sample,
                               // Direction to light source
                               float3* wo,
                               // PDF
                               float* pdf
                              )
{
    float3 d = Sample_MapToHemisphere(sample, dg->n, 1.f);

    // Generate direction
    *wo = 100000.f * d;

    // Envmap PDF
    *pdf = fabs(dot(dg->n, normalize(d))) / PI;

    // Sample envmap
    return light->multiplier * Texture_SampleEnvMap(d, TEXTURE_ARGS_IDX(light->multiplier));
}

/// Get PDF for a given direction
float EnvironmentLight_GetPdf(
                              // Light
                              Light const* light,
                              // Scene
                              Scene const* scene,
                              // Geometry
                              DifferentialGeometry const* dg,
                              // Direction to light source
                              float3 wo,
                              // Textures
                              TEXTURE_ARG_LIST
                              )
{
    return max(0.f, fabs(dot(dg->n, normalize(wo)))/ PI);
}

/*
 Area light
 */
// Get intensity for a given direction
float3 AreaLight_GetLe(// Emissive object
                       Light const* light,
                       // Scene
                       Scene const* scene,
                       // Geometry
                       DifferentialGeometry const* dg,
                       // Direction to light source
                       float3* wo,
                       // Textures
                       TEXTURE_ARG_LIST
                       )
{
    ray r;
    r.o.xyz = dg->p;
    r.d.xyz = *wo;

    int shapeidx = light->shapeidx;
    int primidx = light->primidx;

    float3 v0, v1, v2;
    Scene_GetTriangleVertices(scene, shapeidx, primidx, &v0, &v1, &v2);

    float a, b;
    if (IntersectTriangle(&r, v0, v1, v2, &a, &b))
    {
        float3 n;
        float3 p;
        float2 tx;
        float area;
        Scene_InterpolateAttributes(scene, shapeidx, primidx, make_float2(a, b), &p, &n, &tx, &area);

        float3 d = p - dg->p;
        *wo = d;

        int mat_idx = Scene_GetMaterialIndex(scene, shapeidx, primidx);
        Material mat = scene->materials[mat_idx];

        const float3 ke = Texture_GetValue3f(mat.kx.xyz, tx, TEXTURE_ARGS_IDX(mat.kxmapidx));
        return ke;
    }
    else
    {
        return make_float3(0.f, 0.f, 0.f);
    }
}

/// Sample direction to the light
float3 AreaLight_Sample(// Emissive object
                        Light const* light,
                        // Scene
                        Scene const* scene,
                        // Geometry
                        DifferentialGeometry const* dg,
                        // Textures
                        TEXTURE_ARG_LIST,
                        // Sample
                        float2 sample,
                        // Direction to light source
                        float3* wo,
                        // PDF
                        float* pdf)
{
    int shapeidx = light->shapeidx;
    int primidx = light->primidx;

    // Generate sample on triangle
    float r0 = sample.x;
    float r1 = sample.y;

    // Convert random to barycentric coords
    float2 uv;
    uv.x = native_sqrt(r0) * (1.f - r1);
    uv.y = native_sqrt(r0) * r1;

    float3 n;
    float3 p;
    float2 tx;
    float area;
    Scene_InterpolateAttributes(scene, shapeidx, primidx, uv, &p, &n, &tx, &area);

    *wo = p - dg->p;

    int mat_idx = Scene_GetMaterialIndex(scene, shapeidx, primidx);
    Material mat = scene->materials[mat_idx];

    const float3 ke = Texture_GetValue3f(mat.kx.xyz, tx, TEXTURE_ARGS_IDX(mat.kxmapidx));

    float3 v = -normalize(*wo);

    float ndotv = dot(n, v);

    if (ndotv > 0.f)
    {
        float dist2 = (length(*wo) * length(*wo));
        float denom = fabs(ndotv) * area;
        *pdf = denom > 0.f ? dist2 / denom : 0.f;
        return dist2 > 0.f ? ke * ndotv / dist2 : 0.f;
    }
    else
    {
        *pdf = 0.f;
        return 0.f;
    }
}

/// Get PDF for a given direction
float AreaLight_GetPdf(// Emissive object
                       Light const* light,
                       // Scene
                       Scene const* scene,
                       // Geometry
                       DifferentialGeometry const* dg,
                       // Direction to light source
                       float3 wo,
                       // Textures
                       TEXTURE_ARG_LIST
                       )
{
    ray r;
    r.o.xyz = dg->p;
    r.d.xyz = wo;

    int shapeidx = light->shapeidx;
    int primidx = light->primidx;

    float3 v0, v1, v2;
    Scene_GetTriangleVertices(scene, shapeidx, primidx, &v0, &v1, &v2);

    // Intersect ray against this area light
    float a, b;
    if (IntersectTriangle(&r, v0, v1, v2, &a, &b))
    {
        float3 n;
        float3 p;
        float2 tx;
        float area;
        Scene_InterpolateAttributes(scene, shapeidx, primidx, make_float2(a, b), &p, &n, &tx, &area);

        float3 d = p - dg->p;
        float dist2 = dot(d, d) ;
        float denom = (fabs(dot(-normalize(d), n)) * area);

        return denom > 0.f ? dist2 / denom : 0.f;
    }
    else
    {
        return 0.f;
    }
}

float3 AreaLight_SampleVertex(
    // Emissive object
    Light const* light,
    // Scene
    Scene const* scene,
    // Textures
    TEXTURE_ARG_LIST,
    // Sample
    float2 sample0,
    float2 sample1,
    // Direction to light source
    float3* p,
    float3* n,
    float3* wo,
    // PDF
    float* pdf)
{
    int shapeidx = light->shapeidx;
    int primidx = light->primidx;

    // Generate sample on triangle
    float r0 = sample0.x;
    float r1 = sample0.y;

    // Convert random to barycentric coords
    float2 uv;
    uv.x = native_sqrt(r0) * (1.f - r1);
    uv.y = native_sqrt(r0) * r1;

    float2 tx;
    float area;
    Scene_InterpolateAttributes(scene, shapeidx, primidx, uv, p, n, &tx, &area);

    int mat_idx = Scene_GetMaterialIndex(scene, shapeidx, primidx);
    Material mat = scene->materials[mat_idx];

    const float3 ke = Texture_GetValue3f(mat.kx.xyz, tx, TEXTURE_ARGS_IDX(mat.kxmapidx));

    *wo = Sample_MapToHemisphere(sample1, *n, 1.f);
    *pdf = (1.f / area) * fabs(dot(*n, *wo)) / PI;

    return ke;
}

/*
Directional light
*/
// Get intensity for a given direction
float3 DirectionalLight_GetLe(// Emissive object
    Light const* light,
    // Scene
    Scene const* scene,
    // Geometry
    DifferentialGeometry const* dg,
    // Direction to light source
    float3* wo,
    // Textures
    TEXTURE_ARG_LIST
)
{
    return 0.f;
}

/// Sample direction to the light
float3 DirectionalLight_Sample(// Emissive object
    Light const* light,
    // Scene
    Scene const* scene,
    // Geometry
    DifferentialGeometry const* dg,
    // Textures
    TEXTURE_ARG_LIST,
    // Sample
    float2 sample,
    // Direction to light source
    float3* wo,
    // PDF
    float* pdf)
{
    *wo = 100000.f * -light->d;
    *pdf = 1.f;
    return light->intensity;
}

/// Get PDF for a given direction
float DirectionalLight_GetPdf(// Emissive object
    Light const* light,
    // Scene
    Scene const* scene,
    // Geometry
    DifferentialGeometry const* dg,
    // Direction to light source
    float3 wo,
    // Textures
    TEXTURE_ARG_LIST
)
{
    return 0.f;
}

/*
 Point light
 */
// Get intensity for a given direction
float3 PointLight_GetLe(// Emissive object
                              Light const* light,
                              // Scene
                              Scene const* scene,
                              // Geometry
                              DifferentialGeometry const* dg,
                              // Direction to light source
                              float3* wo,
                              // Textures
                              TEXTURE_ARG_LIST
                              )
{
    return 0.f;
}

/// Sample direction to the light
float3 PointLight_Sample(// Emissive object
                               Light const* light,
                               // Scene
                               Scene const* scene,
                               // Geometry
                               DifferentialGeometry const* dg,
                               // Textures
                               TEXTURE_ARG_LIST,
                               // Sample
                               float2 sample,
                               // Direction to light source
                               float3* wo,
                               // PDF
                               float* pdf)
{
    *wo = light->p - dg->p;
    *pdf = 1.f;
    return light->intensity / dot(*wo, *wo);
}

/// Get PDF for a given direction
float PointLight_GetPdf(// Emissive object
                              Light const* light,
                              // Scene
                              Scene const* scene,
                              // Geometry
                              DifferentialGeometry const* dg,
                              // Direction to light source
                              float3 wo,
                              // Textures
                              TEXTURE_ARG_LIST
                              )
{
    return 0.f;
}

/// Sample vertex on the light
float3 PointLight_SampleVertex(
    // Light object
    Light const* light,
    // Scene
    Scene const* scene,
    // Textures
    TEXTURE_ARG_LIST,
    // Sample
    float2 sample0,
    float2 sample1,
    // Direction to light source
    float3* p,
    float3* n,
    float3* wo,
    // PDF
    float* pdf)
{
    *p = light->p;
    *n = make_float3(0.f, 1.f, 0.f);
    *wo = Sample_MapToSphere(sample0);
    *pdf = 1.f / (4.f * PI);
    return light->intensity;
}

/*
 Spot light
 */
// Get intensity for a given direction
float3 SpotLight_GetLe(// Emissive object
                        Light const* light,
                        // Scene
                        Scene const* scene,
                        // Geometry
                        DifferentialGeometry const* dg,
                        // Direction to light source
                        float3* wo,
                        // Textures
                        TEXTURE_ARG_LIST
                        )
{
    return 0.f;
}

/// Sample direction to the light
float3 SpotLight_Sample(// Emissive object
                         Light const* light,
                         // Scene
                         Scene const* scene,
                         // Geometry
                         DifferentialGeometry const* dg,
                         // Textures
                         TEXTURE_ARG_LIST,
                         // Sample
                         float2 sample,
                         // Direction to light source
                         float3* wo,
                         // PDF
                         float* pdf)
{
    *wo = light->p - dg->p;
    float ddotwo = dot(-normalize(*wo), light->d);

    if (ddotwo > light->oa)
    {
        float3 intensity = light->intensity / dot(*wo, *wo);
        *pdf = 1.f;
        return ddotwo > light->ia ? intensity : intensity * (1.f - (light->ia - ddotwo) / (light->ia - light->oa));
    }
    else
    {
        *pdf = 0.f;
        return 0.f;
    }
}

/// Get PDF for a given direction
float SpotLight_GetPdf(// Emissive object
                        Light const* light,
                        // Scene
                        Scene const* scene,
                        // Geometry
                        DifferentialGeometry const* dg,
                        // Direction to light source
                        float3 wo,
                        // Textures
                        TEXTURE_ARG_LIST
                        )
{
    return 0.f;
}

/*
 Dispatch calls
 */

/// Get intensity for a given direction
float3 Light_GetLe(// Light index
                   int idx,
                   // Scene
                   Scene const* scene,
                   // Geometry
                   DifferentialGeometry const* dg,
                   // Direction to light source
                   float3* wo,
                   // Textures
                   TEXTURE_ARG_LIST
                   )
{
    Light light = scene->lights[idx];

    switch(light.type)
    {
        case kIbl:
            return EnvironmentLight_GetLe(&light, scene, dg, wo, TEXTURE_ARGS);
        case kArea:
            return AreaLight_GetLe(&light, scene, dg, wo, TEXTURE_ARGS);
        case kDirectional:
            return DirectionalLight_GetLe(&light, scene, dg, wo, TEXTURE_ARGS);
        case kPoint:
            return PointLight_GetLe(&light, scene, dg, wo, TEXTURE_ARGS);
        case kSpot:
            return SpotLight_GetLe(&light, scene, dg, wo, TEXTURE_ARGS);
    }

    return make_float3(0.f, 0.f, 0.f);
}

/// Sample direction to the light
float3 Light_Sample(// Light index
                    int idx,
                    // Scene
                    Scene const* scene,
                    // Geometry
                    DifferentialGeometry const* dg,
                    // Textures
                    TEXTURE_ARG_LIST,
                    // Sample
                    float2 sample,
                    // Direction to light source
                    float3* wo,
                    // PDF
                    float* pdf)
{
    Light light = scene->lights[idx];

    switch(light.type)
    {
        case kIbl:
            return EnvironmentLight_Sample(&light, scene, dg, TEXTURE_ARGS, sample, wo, pdf);
        case kArea:
            return AreaLight_Sample(&light, scene, dg, TEXTURE_ARGS, sample, wo, pdf);
        case kDirectional:
            return DirectionalLight_Sample(&light, scene, dg, TEXTURE_ARGS, sample, wo, pdf);
        case kPoint:
            return PointLight_Sample(&light, scene, dg, TEXTURE_ARGS, sample, wo, pdf);
        case kSpot:
            return SpotLight_Sample(&light, scene, dg, TEXTURE_ARGS, sample, wo, pdf);
    }

    *pdf = 0.f;
    return make_float3(0.f, 0.f, 0.f);
}

/// Get PDF for a given direction
float Light_GetPdf(// Light index
                   int idx,
                   // Scene
                   Scene const* scene,
                   // Geometry
                   DifferentialGeometry const* dg,
                   // Direction to light source
                   float3 wo,
                   // Textures
                   TEXTURE_ARG_LIST
                   )
{
    Light light = scene->lights[idx];

    switch(light.type)
    {
        case kIbl:
            return EnvironmentLight_GetPdf(&light, scene, dg, wo, TEXTURE_ARGS);
        case kArea:
            return AreaLight_GetPdf(&light, scene, dg, wo, TEXTURE_ARGS);
        case kDirectional:
            return DirectionalLight_GetPdf(&light, scene, dg, wo, TEXTURE_ARGS);
        case kPoint:
            return PointLight_GetPdf(&light, scene, dg, wo, TEXTURE_ARGS);
        case kSpot:
            return SpotLight_GetPdf(&light, scene, dg, wo, TEXTURE_ARGS);
    }

    return 0.f;
}

/// Sample vertex on the light
float3 Light_SampleVertex(
    // Light index
    int idx,
    // Scene
    Scene const* scene,
    // Textures
    TEXTURE_ARG_LIST,
    // Sample
    float2 sample0,
    float2 sample1,
    // Point on the light
    float3* p,
    // Normal at light vertex
    float3* n,
    // Direction
    float3* wo,
    // PDF
    float* pdf)
{
    Light light = scene->lights[idx];

    switch (light.type)
    {
        case kArea:
            return AreaLight_SampleVertex(&light, scene, TEXTURE_ARGS, sample0, sample1, p, n, wo, pdf);
        case kPoint:
            return PointLight_SampleVertex(&light, scene, TEXTURE_ARGS, sample0, sample1, p, n, wo, pdf);
    }

    *pdf = 0.f;
    return make_float3(0.f, 0.f, 0.f);
}

/// Check if the light is singular
bool Light_IsSingular(__global Light const* light)
{
    return light->type == kPoint ||
        light->type == kSpot ||
        light->type == kDirectional;
}

#endif // LIGHT_CLnv

/**********************************************************************
Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
********************************************************************/
#ifndef LIGHT_CL
#define LIGHT_CL

#include <../App/CL/utils.cl>
#include <../App/CL/payload.cl>
#include <../App/CL/texture.cl>
#include <../App/CL/scene.cl>

bool IntersectTriangle(ray const* r, float3 v1, float3 v2, float3 v3, float* a, float* b)
{
    const float3 e1 = v2 - v1;
    const float3 e2 = v3 - v1;
    const float3 s1 = cross(r->d.xyz, e2);
    const float  invd = native_recip(dot(s1, e1));
    const float3 d = r->o.xyz - v1;
    const float  b1 = dot(d, s1) * invd;
    const float3 s2 = cross(d, e1);
    const float  b2 = dot(r->d.xyz, s2) * invd;
    const float temp = dot(e2, s2) * invd;

    if (b1 < 0.f || b1 > 1.f || b2 < 0.f || b1 + b2 > 1.f)
    {
        return false;
    }
    else
    {
        *a = b1;
        *b = b2;
        return true;
    }
}

/*
 Environment light
 */
/// Get intensity for a given direction
float3 EnvironmentLight_GetLe(// Light
                              Light const* light,
                              // Scene
                              Scene const* scene,
                              // Geometry
                              DifferentialGeometry const* dg,
                              // Direction to light source
                              float3* wo,
                              // Textures
                              TEXTURE_ARG_LIST
                              )
{
    // Sample envmap
    *wo *= 100000.f;
    //
    return light->multiplier * Texture_SampleEnvMap(normalize(*wo), TEXTURE_ARGS_IDX(light->multiplier));
}

/// Sample direction to the light
float3 EnvironmentLight_Sample(// Light
                               Light const* light,
                               // Scene
                               Scene const* scene,
                               // Geometry
                               DifferentialGeometry const* dg,
                               // Textures
                               TEXTURE_ARG_LIST,
                               // Sample
                               float2 sample,
                               // Direction to light source
                               float3* wo,
                               // PDF
                               float* pdf
                              )
{
    float3 d = Sample_MapToHemisphere(sample, dg->n, 1.f);

    // Generate direction
    *wo = 100000.f * d;

    // Envmap PDF
    *pdf = fabs(dot(dg->n, normalize(d))) / PI;

    // Sample envmap
    return light->multiplier * Texture_SampleEnvMap(d, TEXTURE_ARGS_IDX(light->multiplier));
}

/// Get PDF for a given direction
float EnvironmentLight_GetPdf(
                              // Light
                              Light const* light,
                              // Scene
                              Scene const* scene,
                              // Geometry
                              DifferentialGeometry const* dg,
                              // Direction to light source
                              float3 wo,
                              // Textures
                              TEXTURE_ARG_LIST
                              )
{
    return max(0.f, fabs(dot(dg->n, normalize(wo)))/ PI);
}

/*
 Area light
 */
// Get intensity for a given direction
float3 AreaLight_GetLe(// Emissive object
                       Light const* light,
                       // Scene
                       Scene const* scene,
                       // Geometry
                       DifferentialGeometry const* dg,
                       // Direction to light source
                       float3* wo,
                       // Textures
                       TEXTURE_ARG_LIST
                       )
{
    ray r;
    r.o.xyz = dg->p;
    r.d.xyz = normalize(*wo);

    int shapeidx = light->shapeidx;
    int primidx = light->primidx;

    float v0, v1, v2;
    Scene_GetTriangleVertices(scene, shapeidx, primidx, &v0, &v1, &v2);

    float a, b;
    if (IntersectTriangle(&r, v0, v1, v2, &a, &b))
    {
        float3 n;
        float3 p;
        float2 tx;
        float area;
        Scene_InterpolateAttributes(scene, shapeidx, primidx, make_float2(a, b), &p, &n, &tx, &area);

        float3 d = p - dg->p;
        float  ld = length(d);
        *wo = p - dg->p;

        int mat_idx = Scene_GetMaterialIndex(scene, shapeidx, primidx);
        Material mat = scene->materials[mat_idx];

        const float3 ke = Texture_GetValue3f(mat.kx.xyz, tx, TEXTURE_ARGS_IDX(mat.kxmapidx));
        float ndotv = dot(n, -(normalize(d)));
        return  ke;
    }
    else
    {
        return 0.f;
    }
}

/// Sample direction to the light
float3 AreaLight_Sample(// Emissive object
                        Light const* light,
                        // Scene
                        Scene const* scene,
                        // Geometry
                        DifferentialGeometry const* dg,
                        // Textures
                        TEXTURE_ARG_LIST,
                        // Sample
                        float2 sample,
                        // Direction to light source
                        float3* wo,
                        // PDF
                        float* pdf)
{
    int shapeidx = light->shapeidx;
    int primidx = light->primidx;

    // Generate sample on triangle
    float r0 = sample.x;
    float r1 = sample.y;

    // Convert random to barycentric coords
    float2 uv;
    uv.x = native_sqrt(r0) * (1.f - r1);
    uv.y = native_sqrt(r0) * r1;

    float3 n;
    float3 p;
    float2 tx;
    float area;
    Scene_InterpolateAttributes(scene, shapeidx, primidx, uv, &p, &n, &tx, &area);

    *wo = p - dg->p;

    int mat_idx = Scene_GetMaterialIndex(scene, shapeidx, primidx);
    Material mat = scene->materials[mat_idx];

    const float3 ke = Texture_GetValue3f(mat.kx.xyz, tx, TEXTURE_ARGS_IDX(mat.kxmapidx));

    float3 v = -normalize(*wo);

    float ndotv = dot(n, v);

    if (ndotv > 0.f)
    {
        float dist2 = (length(*wo) * length(*wo));
        float denom = fabs(ndotv) * area;
        *pdf = denom > 0.f ? dist2 / denom : 0.f;
        return dist2 > 0.f ? ke * ndotv / dist2 : 0.f;
    }
    else
    {
        *pdf = 0.f;
        return 0.f;
    }
}

/// Get PDF for a given direction
float AreaLight_GetPdf(// Emissive object
                       Light const* light,
                       // Scene
                       Scene const* scene,
                       // Geometry
                       DifferentialGeometry const* dg,
                       // Direction to light source
                       float3 wo,
                       // Textures
                       TEXTURE_ARG_LIST
                       )
{
    ray r;
    r.o.xyz = dg->p;
    r.d.xyz = wo;

    int shapeidx = light->shapeidx;
    int primidx = light->primidx;

    float v0, v1, v2;
    Scene_GetTriangleVertices(scene, shapeidx, primidx, &v0, &v1, &v2);

    // Intersect ray against this area light
    float a, b;
    if (IntersectTriangle(&r, v0, v1, v2, &a, &b))
    {
        float3 n;
        float3 p;
        float2 tx;
        float area;
        Scene_InterpolateAttributes(scene, shapeidx, primidx, make_float2(a, b), &p, &n, &tx, &area);

        float3 d = p - dg->p;
        float dist2 = dot(d, d) ;
        float denom = (fabs(dot(-normalize(d), n)) * area);

        return denom > 0.f ? dist2 / denom : 0.f;
    }
    else
    {
        return 0.f;
    }
}

/*
Directional light
*/
// Get intensity for a given direction
float3 DirectionalLight_GetLe(// Emissive object
    Light const* light,
    // Scene
    Scene const* scene,
    // Geometry
    DifferentialGeometry const* dg,
    // Direction to light source
    float3* wo,
    // Textures
    TEXTURE_ARG_LIST
)
{
    return 0.f;
}

/// Sample direction to the light
float3 DirectionalLight_Sample(// Emissive object
    Light const* light,
    // Scene
    Scene const* scene,
    // Geometry
    DifferentialGeometry const* dg,
    // Textures
    TEXTURE_ARG_LIST,
    // Sample
    float2 sample,
    // Direction to light source
    float3* wo,
    // PDF
    float* pdf)
{
    *wo = 100000.f * -light->d;
    *pdf = 1.f;
    return light->intensity;
}

/// Get PDF for a given direction
float DirectionalLight_GetPdf(// Emissive object
    Light const* light,
    // Scene
    Scene const* scene,
    // Geometry
    DifferentialGeometry const* dg,
    // Direction to light source
    float3 wo,
    // Textures
    TEXTURE_ARG_LIST
)
{
    return 0.f;
}

/*
 Point light
 */
// Get intensity for a given direction
float3 PointLight_GetLe(// Emissive object
                              Light const* light,
                              // Scene
                              Scene const* scene,
                              // Geometry
                              DifferentialGeometry const* dg,
                              // Direction to light source
                              float3* wo,
                              // Textures
                              TEXTURE_ARG_LIST
                              )
{
    return 0.f;
}

/// Sample direction to the light
float3 PointLight_Sample(// Emissive object
                               Light const* light,
                               // Scene
                               Scene const* scene,
                               // Geometry
                               DifferentialGeometry const* dg,
                               // Textures
                               TEXTURE_ARG_LIST,
                               // Sample
                               float2 sample,
                               // Direction to light source
                               float3* wo,
                               // PDF
                               float* pdf)
{
    *wo = light->p - dg->p;
    *pdf = 1.f;
    return light->intensity / dot(*wo, *wo);
}

/// Get PDF for a given direction
float PointLight_GetPdf(// Emissive object
                              Light const* light,
                              // Scene
                              Scene const* scene,
                              // Geometry
                              DifferentialGeometry const* dg,
                              // Direction to light source
                              float3 wo,
                              // Textures
                              TEXTURE_ARG_LIST
                              )
{
    return 0.f;
}

/*
 Spot light
 */
// Get intensity for a given direction
float3 SpotLight_GetLe(// Emissive object
                        Light const* light,
                        // Scene
                        Scene const* scene,
                        // Geometry
                        DifferentialGeometry const* dg,
                        // Direction to light source
                        float3* wo,
                        // Textures
                        TEXTURE_ARG_LIST
                        )
{
    return 0.f;
}

/// Sample direction to the light
float3 SpotLight_Sample(// Emissive object
                         Light const* light,
                         // Scene
                         Scene const* scene,
                         // Geometry
                         DifferentialGeometry const* dg,
                         // Textures
                         TEXTURE_ARG_LIST,
                         // Sample
                         float2 sample,
                         // Direction to light source
                         float3* wo,
                         // PDF
                         float* pdf)
{
    *wo = light->p - dg->p;
    float ddotwo = dot(-normalize(*wo), light->d);

    if (ddotwo > light->oa)
    {
        float3 intensity = light->intensity / dot(*wo, *wo);
        *pdf = 1.f;
        return ddotwo > light->ia ? intensity : intensity * (1.f - (light->ia - ddotwo) / (light->ia - light->oa));
    }
    else
    {
        *pdf = 0.f;
        return 0.f;
    }
}

/// Get PDF for a given direction
float SpotLight_GetPdf(// Emissive object
                        Light const* light,
                        // Scene
                        Scene const* scene,
                        // Geometry
                        DifferentialGeometry const* dg,
                        // Direction to light source
                        float3 wo,
                        // Textures
                        TEXTURE_ARG_LIST
                        )
{
    return 0.f;
}

/*
 Dispatch calls
 */

/// Get intensity for a given direction
float3 Light_GetLe(// Light index
                   int idx,
                   // Scene
                   Scene const* scene,
                   // Geometry
                   DifferentialGeometry const* dg,
                   // Direction to light source
                   float3* wo,
                   // Textures
                   TEXTURE_ARG_LIST
                   )
{
    Light light = scene->lights[idx];

    switch(light.type)
    {
        case kIbl:
            return EnvironmentLight_GetLe(&light, scene, dg, wo, TEXTURE_ARGS);
        case kArea:
            return AreaLight_GetLe(&light, scene, dg, wo, TEXTURE_ARGS);
        case kDirectional:
            return DirectionalLight_GetLe(&light, scene, dg, wo, TEXTURE_ARGS);
        case kPoint:
            return PointLight_GetLe(&light, scene, dg, wo, TEXTURE_ARGS);
        case kSpot:
            return SpotLight_GetLe(&light, scene, dg, wo, TEXTURE_ARGS);
    }

    return make_float3(0.f, 0.f, 0.f);
}

/// Sample direction to the light
float3 Light_Sample(// Light index
                    int idx,
                    // Scene
                    Scene const* scene,
                    // Geometry
                    DifferentialGeometry const* dg,
                    // Textures
                    TEXTURE_ARG_LIST,
                    // Sample
                    float2 sample,
                    // Direction to light source
                    float3* wo,
                    // PDF
                    float* pdf)
{
    Light light = scene->lights[idx];

    switch(light.type)
    {
        case kIbl:
            return EnvironmentLight_Sample(&light, scene, dg, TEXTURE_ARGS, sample, wo, pdf);
        case kArea:
            return AreaLight_Sample(&light, scene, dg, TEXTURE_ARGS, sample, wo, pdf);
        case kDirectional:
            return DirectionalLight_Sample(&light, scene, dg, TEXTURE_ARGS, sample, wo, pdf);
        case kPoint:
            return PointLight_Sample(&light, scene, dg, TEXTURE_ARGS, sample, wo, pdf);
        case kSpot:
            return SpotLight_Sample(&light, scene, dg, TEXTURE_ARGS, sample, wo, pdf);
    }

    *pdf = 0.f;
    return make_float3(0.f, 0.f, 0.f);
}

/// Get PDF for a given direction
float Light_GetPdf(// Light index
                   int idx,
                   // Scene
                   Scene const* scene,
                   // Geometry
                   DifferentialGeometry const* dg,
                   // Direction to light source
                   float3 wo,
                   // Textures
                   TEXTURE_ARG_LIST
                   )
{
    Light light = scene->lights[idx];

    switch(light.type)
    {
        case kIbl:
            return EnvironmentLight_GetPdf(&light, scene, dg, wo, TEXTURE_ARGS);
        case kArea:
            return AreaLight_GetPdf(&light, scene, dg, wo, TEXTURE_ARGS);
        case kDirectional:
            return DirectionalLight_GetPdf(&light, scene, dg, wo, TEXTURE_ARGS);
        case kPoint:
            return PointLight_GetPdf(&light, scene, dg, wo, TEXTURE_ARGS);
        case kSpot:
            return SpotLight_GetPdf(&light, scene, dg, wo, TEXTURE_ARGS);
    }

    return 0.f;
}

/// Check if the light is singular
bool Light_IsSingular(__global Light const* light)
{
    return light->type == kPoint ||
        light->type == kSpot ||
        light->type == kDirectional;
}

#endif // LIGHT_CLnv


Adds initial kernel for harris response.

__kernel void harrisCornerResponse(
        __global float* xx,
        __global float* xy,
        __global float* yy,
        __global float* output,
        int width,
        int height,
        float sigmaD )
{
    float A = xx[i] * pow(sigmaD, 2);
    float B = yy[i] * pow(sigmaD, 2);
    float C = xy[i] * pow(sigmaD, 2);

    output[i] = A * B - C * C - alpha * pow(A + B, 2);
}

error: pathspec 'kernels/harris.cl' did not match any file(s) known to git


Update kernel.cl

Update kernel.cl

methode1 in kernel toegevoegd

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/MichielPauwels/LCS.git/'


HSAIL kernel lib: add implementation of exp()

This comes from libclc. Only float, the double version
requires a working ldexp().

/* OpenCL built-in library: exp()

   Copyright (c) 2015 Michal Babej / Tampere University of Technology

   Permission is hereby granted, free of charge, to any person obtaining a copy
   of this software and associated documentation files (the "Software"), to deal
   in the Software without restriction, including without limitation the rights
   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   copies of the Software, and to permit persons to whom the Software is
   furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included in
   all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   THE SOFTWARE.

   This implementation of exp() comes from libclc/generic/lib/math/exp.cl
   License:

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

*/

#include "hsail_templates.h"

/*
 * TODO implementation for double requires a working ldexp()
*/

#define MATH_DIVIDE(X, Y) ((X) / (Y))

#undef exp

__attribute__ ((overloadable)) float _cl_exp(float x) {

    // Reduce x
    const float ln2HI = 0x1.62e300p-1f;
    const float ln2LO = 0x1.2fefa2p-17f;
    const float invln2 = 0x1.715476p+0f;

    float fhalF = x < 0.0f ? -0.5f : 0.5f;
    int p = convert_int(mad(x, invln2, fhalF));
    float fp = (float)p;
    float hi = mad(fp, -ln2HI, x); // t*ln2HI is exact here
    float lo = -fp*ln2LO;

    // Evaluate poly
    float t = hi + lo;
    float tt  = t*t;
    float v = mad(tt,
                  -mad(tt,
                       mad(tt,
                           mad(tt,
                               mad(tt, 0x1.637698p-25f, -0x1.bbd41cp-20f),
                               0x1.1566aap-14f),
                           -0x1.6c16c2p-9f),
                       0x1.555556p-3f),
                  t);

    float y = 1.0f - (((-lo) - MATH_DIVIDE(t * v, 2.0f - v)) - hi);

    // Scale by 2^p
    float r =  as_float(as_int(y) + (p << 23));

    const float ulim =  0x1.62e430p+6f; // ln(largest_normal) = 88.72283905206835305366
    const float llim = -0x1.5d589ep+6f; // ln(smallest_normal) = -87.33654475055310898657

    r = x < llim ? 0.0f : r;
    r = x < ulim ? r : as_float(0x7f800000);
    return isnan(x) ? x : r;
}

IMPLEMENT_BUILTIN_TYPE_ALL_VECS(_cl_exp, V_V, float, float)

error: pathspec 'lib/kernel/hsail64/exp.cl' did not match any file(s) known to git


Adding triggers schema

Adding triggers schema

create keyspace triggers
  with placement_strategy = 'SimpleStrategy'
  and strategy_options = {replication_factor : 1}
  and durable_writes = true;

use triggers;

create column family CommitLog_dlcirrus03
  with column_type = 'Standard'
  and comparator = 'UTF8Type'
  and default_validation_class = 'UTF8Type'
  and key_validation_class = 'UTF8Type'
  and rows_cached = 0.0
  and row_cache_save_period = 0
  and row_cache_keys_to_save = 2147483647
  and keys_cached = 200000.0
  and key_cache_save_period = 14400
  and read_repair_chance = 1.0
  and gc_grace = 864000
  and min_compaction_threshold = 4
  and max_compaction_threshold = 32
  and replicate_on_write = true
  and row_cache_provider = 'ConcurrentLinkedHashCacheProvider'
  and compaction_strategy = 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy';

create column family CommitLog_dlcirrus04
  with column_type = 'Standard'
  and comparator = 'UTF8Type'
  and default_validation_class = 'UTF8Type'
  and key_validation_class = 'UTF8Type'
  and rows_cached = 0.0
  and row_cache_save_period = 0
  and row_cache_keys_to_save = 2147483647
  and keys_cached = 200000.0
  and key_cache_save_period = 14400
  and read_repair_chance = 1.0
  and gc_grace = 864000
  and min_compaction_threshold = 4
  and max_compaction_threshold = 32
  and replicate_on_write = true
  and row_cache_provider = 'ConcurrentLinkedHashCacheProvider'
  and compaction_strategy = 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy';

create column family CommitLog_dlcirrus05
  with column_type = 'Standard'
  and comparator = 'UTF8Type'
  and default_validation_class = 'UTF8Type'
  and key_validation_class = 'UTF8Type'
  and rows_cached = 0.0
  and row_cache_save_period = 0
  and row_cache_keys_to_save = 2147483647
  and keys_cached = 200000.0
  and key_cache_save_period = 14400
  and read_repair_chance = 1.0
  and gc_grace = 864000
  and min_compaction_threshold = 4
  and max_compaction_threshold = 32
  and replicate_on_write = true
  and row_cache_provider = 'ConcurrentLinkedHashCacheProvider'
  and compaction_strategy = 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy';

create column family ErrorLog_dlcirrus03
  with column_type = 'Standard'
  and comparator = 'UTF8Type'
  and default_validation_class = 'UTF8Type'
  and key_validation_class = 'UTF8Type'
  and rows_cached = 0.0
  and row_cache_save_period = 0
  and row_cache_keys_to_save = 2147483647
  and keys_cached = 200000.0
  and key_cache_save_period = 14400
  and read_repair_chance = 1.0
  and gc_grace = 864000
  and min_compaction_threshold = 4
  and max_compaction_threshold = 32
  and replicate_on_write = true
  and row_cache_provider = 'ConcurrentLinkedHashCacheProvider'
  and compaction_strategy = 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy';

create column family ErrorLog_dlcirrus04
  with column_type = 'Standard'
  and comparator = 'UTF8Type'
  and default_validation_class = 'UTF8Type'
  and key_validation_class = 'UTF8Type'
  and rows_cached = 0.0
  and row_cache_save_period = 0
  and row_cache_keys_to_save = 2147483647
  and keys_cached = 200000.0
  and key_cache_save_period = 14400
  and read_repair_chance = 1.0
  and gc_grace = 864000
  and min_compaction_threshold = 4
  and max_compaction_threshold = 32
  and replicate_on_write = true
  and row_cache_provider = 'ConcurrentLinkedHashCacheProvider'
  and compaction_strategy = 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy';

create column family ErrorLog_dlcirrus05
  with column_type = 'Standard'
  and comparator = 'UTF8Type'
  and default_validation_class = 'UTF8Type'
  and key_validation_class = 'UTF8Type'
  and rows_cached = 0.0
  and row_cache_save_period = 0
  and row_cache_keys_to_save = 2147483647
  and keys_cached = 200000.0
  and key_cache_save_period = 14400
  and read_repair_chance = 1.0
  and gc_grace = 864000
  and min_compaction_threshold = 4
  and max_compaction_threshold = 32
  and replicate_on_write = true
  and row_cache_provider = 'ConcurrentLinkedHashCacheProvider'
  and compaction_strategy = 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy';

create column family Configuration
  with column_type = 'Standard'
  and comparator = 'UTF8Type'
  and default_validation_class = 'UTF8Type'
  and key_validation_class = 'UTF8Type'
  and rows_cached = 0.0
  and row_cache_save_period = 0
  and row_cache_keys_to_save = 2147483647
  and keys_cached = 200000.0
  and key_cache_save_period = 14400
  and read_repair_chance = 1.0
  and gc_grace = 864000
  and min_compaction_threshold = 4
  and max_compaction_threshold = 32
  and replicate_on_write = true
  and row_cache_provider = 'ConcurrentLinkedHashCacheProvider'
  and compaction_strategy = 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy';

create column family Triggers
  with column_type = 'Standard'
  and comparator = 'UTF8Type'
  and default_validation_class = 'UTF8Type'
  and key_validation_class = 'UTF8Type'
  and rows_cached = 0.0
  and row_cache_save_period = 0
  and row_cache_keys_to_save = 2147483647
  and keys_cached = 200000.0
  and key_cache_save_period = 14400
  and read_repair_chance = 1.0
  and gc_grace = 864000
  and min_compaction_threshold = 4
  and max_compaction_threshold = 32
  and replicate_on_write = true
  and row_cache_provider = 'ConcurrentLinkedHashCacheProvider'
  and compaction_strategy = 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy';

error: pathspec 'src/test/resources/triggers_schema.cl' did not match any file(s) known to git


Added the file shear.cl to represent a uniform shear.  Needs to be checked.

// uniform shear

OBJECT(shear) = LENS;

PARAMS(shear) = {
    { "g1" },
    { "g2" }
};

struct shear
{
    float g1;
    float g2;
};

static float2 shear(constant struct shear* shear, float2 x)
{
    return (float2)( shear->g2*x.y - shear->g1*x.x
                   , shear->g1*x.y + shear->g2*x.x);
}

static void set_shear(global struct shear* shear, float g1, float g2)
{
    shear->g1 = g1;
    shear->g2 = g2;
}

error: pathspec 'kernel/shear.cl' did not match any file(s) known to git


simplified version of 2D kernel (not used by default), have lower performance on GPU and higher on CPU SOA only 0 with vector 4, or 1 with vectors from 1 to 16 supports arbitrary outern unrolling

#if USE_CONSTANT_MEMORY == 0
    #define MEMORY_TYPE_AOS __global const
    #define MEMORY_TYPE_SOA __global const
#elif USE_CONSTANT_MEMORY == 1
    #if USE_SOA == 0
        #define MEMORY_TYPE_AOS __constant
        #define MEMORY_TYPE_SOA __global const
    #else
        #define MEMORY_TYPE_AOS __global const
        #define MEMORY_TYPE_SOA __constant
    #endif // USE_SOA
#endif // USE_CONSTANT_MEMORY

#if VECTOR_TYPE == 1
    typedef float vector;
#elif VECTOR_TYPE == 2
    typedef float2 vector;
#elif VECTOR_TYPE == 4
    typedef float4 vector;
#elif VECTOR_TYPE == 8
    typedef float8 vector;
#elif VECTOR_TYPE == 16
    typedef float16 vector;
#endif // VECTOR_TYPE

#if VECTOR_TYPE > 1
__kernel __attribute__((vec_type_hint(vector)))
#endif
__kernel void directCoulombSum(MEMORY_TYPE_AOS float4* atomInfo, MEMORY_TYPE_SOA vector* atomInfoX, MEMORY_TYPE_SOA vector* atomInfoY,
    MEMORY_TYPE_SOA vector* atomInfoZ, MEMORY_TYPE_SOA vector* atomInfoW, int numberOfAtoms, float gridSpacing, __global float* energyGrid)
{
    int xIndex = get_global_id(0) * OUTER_UNROLL_FACTOR;
    int yIndex = get_global_id(1);

	int outIndex = get_global_size(0) * yIndex * OUTER_UNROLL_FACTOR + xIndex;;

    float coordX = gridSpacing * xIndex;
    float coordY = gridSpacing * yIndex;

    vector energyValue[OUTER_UNROLL_FACTOR];
    for (int i = 0; i < OUTER_UNROLL_FACTOR; i++)
        energyValue[i] = 0.0f;

    for (int i = 0; i < numberOfAtoms / VECTOR_TYPE; i++)
    {
        #if USE_SOA == 1
        vector dX = coordX - atomInfoX[i];
        vector dY = coordY - atomInfoY[i];
        vector dZ2 = atomInfoZ[i];
        vector w = atomInfoW[i];
        #else
        vector dX = coordX - atomInfo[i].x;
        vector dY = coordY - atomInfo[i].y;
        vector dZ2 = atomInfo[i].z;
        vector w = atomInfo[i].w;
        #endif /* USE_SOA */
        #if INNER_UNROLL_FACTOR > 0
        #pragma unroll INNER_UNROLL_FACTOR
        #endif
        for (int j = 0; j < OUTER_UNROLL_FACTOR; j++) {
            vector partialResult = native_rsqrt(dX * dX + dY * dY + dZ2);
            energyValue[j] += w * partialResult;
            dX += gridSpacing;
        }
    }

    for (int i = 0; i < OUTER_UNROLL_FACTOR; i++)
        #if VECTOR_TYPE == 1
        energyGrid[outIndex + i] += energyValue[i];
        #elif VECTOR_TYPE == 2
        energyGrid[outIndex + i] += energyValue[i].x + energyValue[i].y;
        #elif VECTOR_TYPE == 4
        energyGrid[outIndex + i] += energyValue[i].x + energyValue[i].y + energyValue[i].z + energyValue[i].w;
        #elif VECTOR_TYPE == 8
        energyGrid[outIndex + i] += energyValue[i].s0 + energyValue[i].s1 + energyValue[i].s2 + energyValue[i].s3 + energyValue[i].s4 + energyValue[i].s5 + energyValue[i].s6 + energyValue[i].s7;
        #elif VECTOR_TYPE == 16
        energyGrid[outIndex + i] += energyValue[i].s0 + energyValue[i].s1 + energyValue[i].s2 + energyValue[i].s3 + energyValue[i].s4 + energyValue[i].s5 + energyValue[i].s6 + energyValue[i].s7 + energyValue[i].s8 + energyValue[i].s9 + energyValue[i].sa + energyValue[i].sb + energyValue[i].sc + energyValue[i].sd + energyValue[i].se + energyValue[i].sf;
        #endif
}

error: pathspec 'examples/coulomb_sum_2d/coulomb_sum_2d_kernel_simpler.cl' did not match any file(s) known to git


Increased the loop count

Increased the loop count

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/HongjianLi/opencl.git/'


A skeleton of a LispScript compiler

A skeleton of a LispScript compiler

The compiler translates string and integer literals and function calls
to JavaScript.

(defun compile-expr ())

(defun compile-fn (name)
  "Translates a LispScript function name to a JavaScript function name."
  (cond ((symbolp name) (write-to-string name))
        ((listp name) (format nil "~{~a~^.~}" name))
        (t (error "invalid function name"))))

(defun compile-args (args)
  "Translates a LispScript arguments list to a JavaScript arguments string."
  (format nil "~{~a~^,~}" (mapcar #'compile-expr args)))

(defun compile-integer (expr)
  "Translates a LispScript integer literal into a JavaScript integer literal."
  (write-to-string expr))

(defun compile-string (expr)
  "Translates a LispScript string literal into a JavaScript string literal."
  (format nil "\"~a\"" expr))

(defun compile-list (expr)
  "Translates a LispScript list into a JavaScript function call."
  (let ((fn (first expr))
        (args (rest expr)))
    (format nil "~a(~a)" (compile-fn fn) (compile-args args))))

(defun compile-expr (expr)
  "Translates a LispScript expression into a JavaScript expression."
  (cond ((integerp expr) (compile-integer expr))
        ((stringp expr) (compile-string expr))
        ((listp expr) (compile-list expr))
        (t (error "invalid expression"))))

(setf (readtable-case *readtable*) :preserve)
(FORMAT T "~a~%" (COMPILE-EXPR (READ)))


update state of LCALIF should work now. moved integratedSpikeCount to be computed after we compute activity.

git-svn-id: 602a26e73ae9f2a14e2bb95676f2e137fcc39919@5799 7c0444ca-5550-0410-9008-faecdbe78eb5

#include "LIF_params.h"
#include "cl_random.hcl"

#ifndef PV_USE_OPENCL
#  include <math.h>
#  define EXP expf
#  define CL_KERNEL
#  define CL_MEM_GLOBAL
#  define CL_MEM_CONST
#  define CL_MEM_LOCAL
#else  /* compiling with OpenCL */
#  define EXP exp
#  define CL_KERNEL       __kernel
#  define CL_MEM_GLOBAL   __global
#  define CL_MEM_CONST    __constant
#  define CL_MEM_LOCAL    __local
#  include "conversions.hcl"
#  define CHANNEL_EXC   0
#  define CHANNEL_INH   1
#  define CHANNEL_INHB  2
#  define CHANNEL_GAP   3
#endif

//#undef USE_CLRANDOM
#ifndef USE_CLRANDOM
#  include "../utils/pv_random.h"
#endif

inline
float LIFGap_Vmem_derivative(
      const float Vmem,
      const float G_E,
      const float G_I,
      const float G_IB,
      const float G_Gap,
      const float V_E,
      const float V_I,
      const float V_IB,
      const float sum_gap,
      const float Vrest,
      const float tau) {
   float totalconductance = 1.0 + G_E + G_I + G_IB + sum_gap;
   float Vmeminf = (Vrest + V_E*G_E + V_I*G_I + V_IB*G_IB + G_Gap)/totalconductance;
   return totalconductance*(Vmeminf-Vmem)/tau;
}

//
// update the state of a LCALIF layer (spiking)
//
//    assume called with 1D kernel
//
// LCALIF_update_state_beginning uses a Heun scheme for V, using values of the conductances at both the beginning and end of the timestep.  Spikes in the input are applied at the beginning of the timestep.
//
CL_KERNEL
void LCALIF_update_state(
    const int numNeurons,
    const float time,
    const float dt,

    const int nx,
    const int ny,
    const int nf,
    const int nb,

    float dynVthScale,
    float * dynVthRest,
    const float tauLCA,
    const float tauTHR,
    const float targetRate,

    pvdata_t * integratedSpikeCount,

    CL_MEM_CONST LIF_params * params,
    CL_MEM_GLOBAL uint4 * rnd,
    CL_MEM_GLOBAL float * V,
    CL_MEM_GLOBAL float * Vth,
    CL_MEM_GLOBAL float * G_E,
    CL_MEM_GLOBAL float * G_I,
    CL_MEM_GLOBAL float * G_IB,
    CL_MEM_GLOBAL float * GSynHead,
//    CL_MEM_GLOBAL float * GSynExc,
//    CL_MEM_GLOBAL float * GSynInh,
//    CL_MEM_GLOBAL float * GSynInhB,
//    CL_MEM_GLOBAL float * GSynGap,
    CL_MEM_GLOBAL float * activity,

    const float sum_gap,
    CL_MEM_GLOBAL float * G_Gap)
{
   int k;

   const float exp_tauE    = EXP(-dt/params->tauE);
   const float exp_tauI    = EXP(-dt/params->tauI);
   const float exp_tauIB   = EXP(-dt/params->tauIB);
   const float exp_tauVth  = EXP(-dt/params->tauVth);
   const float exp_tauLCA  = EXP(-dt/tauLCA);
   //Convert target rate from hz to ms
   const float conv_targetRate = targetRate/1000;

   const float dt_sec = .001 * dt;   // convert to seconds

#ifndef PV_USE_OPENCL

for (k = 0; k < nx*ny*nf; k++) {
#else
   k = get_global_id(0);
#endif

   int kex = kIndexExtended(k, nx, ny, nf, nb);

   //
   // kernel (nonheader part) begins here
   //

   // local param variables
   float tau, Vrest, VthRest, Vexc, Vinh, VinhB, deltaVth;

   // const float GMAX = 10.0;

   // local variables
   float l_activ;

   uint4 l_rnd = rnd[k];

   float l_V   = V[k];
   float l_Vth = Vth[k];

   // The correction factors to the conductances are so that if l_GSyn_* is the same every timestep,
   // then the asymptotic value of l_G_* will be l_GSyn_*
   float l_G_E  = G_E[k];
   float l_G_I  = G_I[k];
   float l_G_IB = G_IB[k];
   float l_G_Gap = G_Gap[k];

   CL_MEM_GLOBAL float * GSynExc = &GSynHead[CHANNEL_EXC*numNeurons];
   CL_MEM_GLOBAL float * GSynInh = &GSynHead[CHANNEL_INH*numNeurons];
   CL_MEM_GLOBAL float * GSynInhB = &GSynHead[CHANNEL_INHB*numNeurons];
   CL_MEM_GLOBAL float * GSynGap = &GSynHead[CHANNEL_GAP*numNeurons];
   float l_GSynExc  = GSynExc[k];
   float l_GSynInh  = GSynInh[k];
   float l_GSynInhB = GSynInhB[k];
   float l_GSynGap  = GSynGap[k];

   // define local param variables
   //
   tau        = params->tau;
   Vexc       = params->Vexc;
   Vinh       = params->Vinh;
   VinhB      = params->VinhB;
   Vrest      = params->Vrest;

   VthRest  = params->VthRest;
   deltaVth = params->deltaVth;

   // add noise
   //

#ifdef USE_CLRANDOM
   l_rnd = cl_random_get(l_rnd);
   if (cl_random_prob(l_rnd) < dt_sec*params->noiseFreqE) {
      l_rnd = cl_random_get(l_rnd);
      l_GSynExc = l_GSynExc + params->noiseAmpE*cl_random_prob(l_rnd);
   }

   l_rnd = cl_random_get(l_rnd);
   if (cl_random_prob(l_rnd) < dt_sec*params->noiseFreqI) {
      l_rnd = cl_random_get(l_rnd);
      l_GSynInh = l_GSynInh + params->noiseAmpI*cl_random_prob(l_rnd);
   }

   l_rnd = cl_random_get(l_rnd);
   if (cl_random_prob(l_rnd) < dt_sec*params->noiseFreqIB) {
      l_rnd = cl_random_get(l_rnd);
      l_GSynInhB = l_GSynInhB + params->noiseAmpIB*cl_random_prob(l_rnd);
   }
#else
   if (pv_random_prob() < dt_sec*params->noiseFreqE) {
      l_GSynExc = l_GSynExc + params->noiseAmpE*pv_random_prob();
   }

   if (pv_random_prob() < dt_sec*params->noiseFreqI) {
      l_GSynInh = l_GSynInh + params->noiseAmpI*pv_random_prob();
   }

   if (pv_random_prob() < dt_sec*params->noiseFreqIB) {
      l_GSynInhB = l_GSynInhB + params->noiseAmpIB*pv_random_prob();
   }
#endif

   const float GMAX = 10.0;

   // The portion of code below uses the newer method of calculating l_V.
   float G_E_initial, G_I_initial, G_IB_initial, G_E_final, G_I_final, G_IB_final;
   float dV1, dV2, dV;

   G_E_initial = l_G_E + l_GSynExc;
   G_I_initial = l_G_I + l_GSynInh;
   G_IB_initial = l_G_IB + l_GSynInhB;

   G_E_initial  = (G_E_initial  > GMAX) ? GMAX : G_E_initial;
   G_I_initial  = (G_I_initial  > GMAX) ? GMAX : G_I_initial;
   G_IB_initial = (G_IB_initial > GMAX) ? GMAX : G_IB_initial;

   G_E_final = G_E_initial*exp_tauE;
   G_I_final = G_I_initial*exp_tauI;
   G_IB_final = G_IB_initial*exp_tauIB;

   l_G_Gap = l_GSynGap;

   dV1 = LIFGap_Vmem_derivative(l_V, G_E_initial, G_I_initial, G_IB_initial, l_G_Gap, Vexc, Vinh, VinhB, sum_gap, Vrest, tau);
   dV2 = LIFGap_Vmem_derivative(l_V+dt*dV1, G_E_final, G_I_final, G_IB_final, l_G_Gap, Vexc, Vinh, VinhB, sum_gap, Vrest, tau);
   dV = (dV1+dV2)*0.5;
   l_V = l_V + dt*dV;

   l_G_E = G_E_final;
   l_G_I = G_I_final;
   l_G_IB = G_IB_final;

   //l_Vth updates according to traditional LIF rule in addition to the following slow threshold adaptation
   //   Theta += (dt/tauTHR) * (int_spike_count/tau_lca - fo) * abs(dynVthRest/fo)
   //      tauTHR is slow update
   //      tau_lca is ~1/5 tauTHR, faster update for traces
   //      int_spike_count is trace
   //      fo is desired baseline spike rate

   dynVthRest[k] += (dt/tauTHR) * (integratedSpikeCount[k]/tauLCA - conv_targetRate) * abs(VthRest/conv_targetRate);
   l_Vth = dynVthRest[k] + (l_Vth - dynVthRest[k])*exp_tauVth;

   bool fired_flag = (l_V > l_Vth);

   l_activ = fired_flag ? 1.0f             : 0.0f;
   l_V     = fired_flag ? Vrest            : l_V;
   l_Vth   = fired_flag ? l_Vth + deltaVth : l_Vth;
   l_G_IB  = fired_flag ? l_G_IB + 1.0f    : l_G_IB;

   //integratedSpikeCount is the trace activity of the neuron, with an exponential decay
   integratedSpikeCount[k] = exp_tauLCA * (l_activ + integratedSpikeCount[k]);

   //
   // These actions must be done outside of kernel
   //    1. set activity to 0 in boundary (if needed)
   //    2. update active indices
   //

   // store local variables back to global memory
   //
   rnd[k] = l_rnd;

   activity[kex] = l_activ;

   V[k]   = l_V;
   Vth[k] = l_Vth;

   G_E[k]  = l_G_E; // G_E_final;
   G_I[k]  = l_G_I; // G_I_final;
   G_IB[k] = l_G_IB; // G_IB_final;
   G_Gap[k] = l_G_Gap;

   GSynExc[k]  = 0.0f;
   GSynInh[k]  = 0.0f;
   GSynInhB[k] = 0.0f;
   GSynGap[k]  = 0.0f;

#ifndef PV_USE_OPENCL
   } // loop over k
#endif

}

#include "LIF_params.h"
#include "cl_random.hcl"

#ifndef PV_USE_OPENCL
#  include <math.h>
#  define EXP expf
#  define CL_KERNEL
#  define CL_MEM_GLOBAL
#  define CL_MEM_CONST
#  define CL_MEM_LOCAL
#else  /* compiling with OpenCL */
#  define EXP exp
#  define CL_KERNEL       __kernel
#  define CL_MEM_GLOBAL   __global
#  define CL_MEM_CONST    __constant
#  define CL_MEM_LOCAL    __local
#  include "conversions.hcl"
#  define CHANNEL_EXC   0
#  define CHANNEL_INH   1
#  define CHANNEL_INHB  2
#  define CHANNEL_GAP   3
#endif

//#undef USE_CLRANDOM
#ifndef USE_CLRANDOM
#  include "../utils/pv_random.h"
#endif

inline
float LIFGap_Vmem_derivative(
      const float Vmem,
      const float G_E,
      const float G_I,
      const float G_IB,
      const float G_Gap,
      const float V_E,
      const float V_I,
      const float V_IB,
      const float sum_gap,
      const float Vrest,
      const float tau) {
   float totalconductance = 1.0 + G_E + G_I + G_IB + sum_gap;
   float Vmeminf = (Vrest + V_E*G_E + V_I*G_I + V_IB*G_IB + G_Gap)/totalconductance;
   return totalconductance*(Vmeminf-Vmem)/tau;
}

//
// update the state of a LCALIF layer (spiking)
//
//    assume called with 1D kernel
//
// LCALIF_update_state_beginning uses a Heun scheme for V, using values of the conductances at both the beginning and end of the timestep.  Spikes in the input are applied at the beginning of the timestep.
//
CL_KERNEL
void LCALIF_update_state(
    const int numNeurons,
    const float time,
    const float dt,

    const int nx,
    const int ny,
    const int nf,
    const int nb,

    float dynVthScale,
    float * dynVthRest,
    const float tauLCA,
    const float tauTHR,
    const float targetRate,

    pvdata_t * integratedSpikeCount,

    CL_MEM_CONST LIF_params * params,
    CL_MEM_GLOBAL uint4 * rnd,
    CL_MEM_GLOBAL float * V,
    CL_MEM_GLOBAL float * Vth,
    CL_MEM_GLOBAL float * G_E,
    CL_MEM_GLOBAL float * G_I,
    CL_MEM_GLOBAL float * G_IB,
    CL_MEM_GLOBAL float * GSynHead,
//    CL_MEM_GLOBAL float * GSynExc,
//    CL_MEM_GLOBAL float * GSynInh,
//    CL_MEM_GLOBAL float * GSynInhB,
//    CL_MEM_GLOBAL float * GSynGap,
    CL_MEM_GLOBAL float * activity,

    const float sum_gap,
    CL_MEM_GLOBAL float * G_Gap)
{
   int k;

   const float exp_tauE    = EXP(-dt/params->tauE);
   const float exp_tauI    = EXP(-dt/params->tauI);
   const float exp_tauIB   = EXP(-dt/params->tauIB);
   const float exp_tauVth  = EXP(-dt/params->tauVth);
   const float exp_tauLCA  = EXP(-dt/tauLCA);
   //Convert target rate from hz to ms
   const float conv_targetRate = targetRate/1000;

   const float dt_sec = .001 * dt;   // convert to seconds

#ifndef PV_USE_OPENCL

for (k = 0; k < nx*ny*nf; k++) {
#else
   k = get_global_id(0);
#endif

   int kex = kIndexExtended(k, nx, ny, nf, nb);

   //
   // kernel (nonheader part) begins here
   //

   // local param variables
   float tau, Vrest, VthRest, Vexc, Vinh, VinhB, deltaVth;

   // const float GMAX = 10.0;

   // local variables
   float l_activ;

   uint4 l_rnd = rnd[k];

   float l_V   = V[k];
   float l_Vth = Vth[k];

   // The correction factors to the conductances are so that if l_GSyn_* is the same every timestep,
   // then the asymptotic value of l_G_* will be l_GSyn_*
   float l_G_E  = G_E[k];
   float l_G_I  = G_I[k];
   float l_G_IB = G_IB[k];
   float l_G_Gap = G_Gap[k];

   CL_MEM_GLOBAL float * GSynExc = &GSynHead[CHANNEL_EXC*numNeurons];
   CL_MEM_GLOBAL float * GSynInh = &GSynHead[CHANNEL_INH*numNeurons];
   CL_MEM_GLOBAL float * GSynInhB = &GSynHead[CHANNEL_INHB*numNeurons];
   CL_MEM_GLOBAL float * GSynGap = &GSynHead[CHANNEL_GAP*numNeurons];
   float l_GSynExc  = GSynExc[k];
   float l_GSynInh  = GSynInh[k];
   float l_GSynInhB = GSynInhB[k];
   float l_GSynGap  = GSynGap[k];

   // define local param variables
   //
   tau        = params->tau;
   Vexc       = params->Vexc;
   Vinh       = params->Vinh;
   VinhB      = params->VinhB;
   Vrest      = params->Vrest;

   VthRest  = params->VthRest;
   deltaVth = params->deltaVth;

   // add noise
   //

#ifdef USE_CLRANDOM
   l_rnd = cl_random_get(l_rnd);
   if (cl_random_prob(l_rnd) < dt_sec*params->noiseFreqE) {
      l_rnd = cl_random_get(l_rnd);
      l_GSynExc = l_GSynExc + params->noiseAmpE*cl_random_prob(l_rnd);
   }

   l_rnd = cl_random_get(l_rnd);
   if (cl_random_prob(l_rnd) < dt_sec*params->noiseFreqI) {
      l_rnd = cl_random_get(l_rnd);
      l_GSynInh = l_GSynInh + params->noiseAmpI*cl_random_prob(l_rnd);
   }

   l_rnd = cl_random_get(l_rnd);
   if (cl_random_prob(l_rnd) < dt_sec*params->noiseFreqIB) {
      l_rnd = cl_random_get(l_rnd);
      l_GSynInhB = l_GSynInhB + params->noiseAmpIB*cl_random_prob(l_rnd);
   }
#else
   if (pv_random_prob() < dt_sec*params->noiseFreqE) {
      l_GSynExc = l_GSynExc + params->noiseAmpE*pv_random_prob();
   }

   if (pv_random_prob() < dt_sec*params->noiseFreqI) {
      l_GSynInh = l_GSynInh + params->noiseAmpI*pv_random_prob();
   }

   if (pv_random_prob() < dt_sec*params->noiseFreqIB) {
      l_GSynInhB = l_GSynInhB + params->noiseAmpIB*pv_random_prob();
   }
#endif

   const float GMAX = 10.0;

   // The portion of code below uses the newer method of calculating l_V.
   float G_E_initial, G_I_initial, G_IB_initial, G_E_final, G_I_final, G_IB_final;
   float dV1, dV2, dV;

   G_E_initial = l_G_E + l_GSynExc;
   G_I_initial = l_G_I + l_GSynInh;
   G_IB_initial = l_G_IB + l_GSynInhB;

   G_E_initial  = (G_E_initial  > GMAX) ? GMAX : G_E_initial;
   G_I_initial  = (G_I_initial  > GMAX) ? GMAX : G_I_initial;
   G_IB_initial = (G_IB_initial > GMAX) ? GMAX : G_IB_initial;

   G_E_final = G_E_initial*exp_tauE;
   G_I_final = G_I_initial*exp_tauI;
   G_IB_final = G_IB_initial*exp_tauIB;

   l_G_Gap = l_GSynGap;

   dV1 = LIFGap_Vmem_derivative(l_V, G_E_initial, G_I_initial, G_IB_initial, l_G_Gap, Vexc, Vinh, VinhB, sum_gap, Vrest, tau);
   dV2 = LIFGap_Vmem_derivative(l_V+dt*dV1, G_E_final, G_I_final, G_IB_final, l_G_Gap, Vexc, Vinh, VinhB, sum_gap, Vrest, tau);
   dV = (dV1+dV2)*0.5;
   l_V = l_V + dt*dV;

   l_G_E = G_E_final;
   l_G_I = G_I_final;
   l_G_IB = G_IB_final;

   //integratedSpikeCount is the trace activity of the neuron, with an exponential decay
   integratedSpikeCount[k] = exp_tauLCA * (activity[k] + integratedSpikeCount[k]);

   //l_Vth updates according to traditional LIF rule in addition to the following slow threshold adaptation
   //   Theta += (dt/tauTHR) * (int_spike_count/tau_lca - fo) * (dynVthRest/fo)
   //      tauTHR is slow update
   //      tau_lca is ~1/5 tauTHR, faster update for traces
   //      int_spike_count is trace
   //      fo is desired baseline spike rate

   dynVthRest[k] += (dt/tauTHR) * (integratedSpikeCount[k]/tauLCA - conv_targetRate) * abs(VthRest/conv_targetRate);
   l_Vth = dynVthRest[k] + (l_Vth - dynVthRest[k])*exp_tauVth;

   bool fired_flag = (l_V > l_Vth);

   l_activ = fired_flag ? 1.0f             : 0.0f;
   l_V     = fired_flag ? Vrest            : l_V;
   l_Vth   = fired_flag ? l_Vth + deltaVth : l_Vth;
   l_G_IB  = fired_flag ? l_G_IB + 1.0f    : l_G_IB;

   //
   // These actions must be done outside of kernel
   //    1. set activity to 0 in boundary (if needed)
   //    2. update active indices
   //

   // store local variables back to global memory
   //
   rnd[k] = l_rnd;

   activity[kex] = l_activ;

   V[k]   = l_V;
   Vth[k] = l_Vth;

   G_E[k]  = l_G_E; // G_E_final;
   G_I[k]  = l_G_I; // G_I_final;
   G_IB[k] = l_G_IB; // G_IB_final;
   G_Gap[k] = l_G_Gap;

   GSynExc[k]  = 0.0f;
   GSynInh[k]  = 0.0f;
   GSynInhB[k] = 0.0f;
   GSynGap[k]  = 0.0f;

#ifndef PV_USE_OPENCL
   } // loop over k
#endif

}


Added COS definition for no PV_USE_OPENCL.

git-svn-id: 602a26e73ae9f2a14e2bb95676f2e137fcc39919@3239 7c0444ca-5550-0410-9008-faecdbe78eb5

#include "Retina_params.h"
#include "cl_random.hcl"

#ifndef PI
#  define PI 3.1415926535897932
#endif

#ifndef PV_USE_OPENCL

#  include <math.h>
#  define EXP  expf
#  define COS  cosf
#  define FMOD fmodf
#  define CL_KERNEL
#  define CL_MEM_GLOBAL
#  define CL_MEM_LOCAL

#else

#  define EXP exp
#  define COS  __cosf
#  define FMOD __fmodf
#  define CL_KERNEL     __kernel
#  define CL_MEM_GLOBAL __global
#  define CL_MEM_LOCAL  __local
#  include "conversions.hcl"

#endif /* PV_USE_OPENCL */

/*
 * Spiking method for Retina
 * Returns 1 if an event should occur, 0 otherwise. This is a stochastic model.
 *
 * REMARKS:
 *      - During ABS_REFACTORY_PERIOD a neuron does not spike
 *      - The neurons that correspond to stimuli (on Image pixels)
 *        spike with probability probStim.
 *      - The neurons that correspond to background image pixels
 *        spike with probability probBase.
 *      - After ABS_REFACTORY_PERIOD the spiking probability
 *        grows exponentially to probBase and probStim respectively.
 *      - The burst of the retina is periodic with period T set by
 *        T = 1000/burstFreq in miliseconds
 *      - When the time t is such that mT < t < mT + burstDuration, where m is
 *        an integer, the burstStatus is set to 1.
 *      - The burstStatus is also determined by the condition that
 *        beginStim < t < endStim. These parameters are set in the input
 *        params file params.stdp
 *      - sinAmp modulates the spiking probability only when burstDuration <= 0
 *        or burstFreq = 0
 *      - probSpike is set to probBase for all neurons.
 *      - for neurons exposed to Image on pixels, probSpike increases with probStim.
 *      - When the probability is negative, the neuron does not spike.
 *
 * NOTES:
 *      - time is measured in milliseconds.
 *
 */
static inline
int spike(float time, float dt,
          float prev, float stimFactor, uint4 * rnd_state, CL_MEM_GLOBAL Retina_params * params)
{
   float probSpike;
   float burstStatus = 1;
   float sinAmp = 1.0;

   // input parameters
   //
   float probBase  = params->probBase;
   float probStim  = params->probStim * stimFactor;

   // see if neuron is in a refactory period
   //
   if ((time - prev) < params->abs_refactory_period) {
      return 0;
   }
   else {
      float delta = time - prev - params->abs_refactory_period;
      float refact = 1.0f - EXP(-delta/params->refactory_period);
      refact = (refact < 0) ? 0 : refact;
      probBase *= refact;
      probStim *= refact;
   }

   if (params->burstDuration <= 0 || params->burstFreq == 0) {
      sinAmp = COS( 2*PI*time * params->burstFreq / 1000. );
   }
   else {
      burstStatus = FMOD(time, 1000. / params->burstFreq);
      burstStatus = burstStatus <= params->burstDuration;
   }

   burstStatus *= (int) ( (time >= params->beginStim) && (time < params->endStim) );
   probSpike = probBase;

   if ((int)burstStatus) {
      probSpike += probStim * sinAmp;  // negative prob is OK
   }

   *rnd_state = cl_random_get(*rnd_state);
   int spike_flag = (cl_random_prob(*rnd_state) < probSpike);
   return spike_flag;
}

//
// update the state of a retinal layer (spiking)
//
//    assume called with 1D kernel
//
CL_KERNEL
void Retina_update_state (
    const float time,
    const float dt,

    const int nx,
    const int ny,
    const int nf,
    const int nb,

    CL_MEM_GLOBAL Retina_params * params,
    CL_MEM_GLOBAL uint4 * rnd,
    CL_MEM_GLOBAL float * phiExc,
    CL_MEM_GLOBAL float * phiInh,
    CL_MEM_GLOBAL float * activity,
    CL_MEM_GLOBAL float * prevTime)
{
   int k;
#ifndef PV_USE_OPENCL
for (k = 0; k < nx*ny*nf; k++) {
#else
   k = get_global_id(0);
#endif

   int kex = kIndexExtended(k, nx, ny, nf, nb);

   //
   // kernel (nonheader part) begins here
   //

   // load local variables from global memory
   //
   uint4 l_rnd = rnd[k];
   float l_phiExc = phiExc[k];
   float l_phiInh = phiInh[k];
   float l_prev   = prevTime[kex];
   float l_activ  = activity[kex];

   l_activ = (float) spike(time, dt, l_prev, (l_phiExc - l_phiInh), &l_rnd, params);
   l_prev  = (l_activ > 0.0f) ? time : l_prev;

   l_phiExc = 0.0f;
   l_phiInh = 0.0f;

   // store local variables back to global memory
   //
   rnd[k] = l_rnd;
   phiExc[k] = l_phiExc;
   phiInh[k] = l_phiInh;
   prevTime[kex] = l_prev;
   activity[kex] = l_activ;

#ifndef PV_USE_OPENCL
   }
#endif

}

#include "Retina_params.h"
#include "cl_random.hcl"

#ifndef PI
#  define PI 3.1415926535897932
#endif

#ifndef PV_USE_OPENCL

#  include <math.h>
#  define EXP expf
#  define FMOD fmodf
#  define CL_KERNEL
#  define CL_MEM_GLOBAL
#  define CL_MEM_LOCAL

#else

#  define EXP exp
#  define COS  __cosf
#  define FMOD __fmodf
#  define CL_KERNEL     __kernel
#  define CL_MEM_GLOBAL __global
#  define CL_MEM_LOCAL  __local
#  include "conversions.hcl"

#endif /* PV_USE_OPENCL */

/*
 * Spiking method for Retina
 * Returns 1 if an event should occur, 0 otherwise. This is a stochastic model.
 *
 * REMARKS:
 *      - During ABS_REFACTORY_PERIOD a neuron does not spike
 *      - The neurons that correspond to stimuli (on Image pixels)
 *        spike with probability probStim.
 *      - The neurons that correspond to background image pixels
 *        spike with probability probBase.
 *      - After ABS_REFACTORY_PERIOD the spiking probability
 *        grows exponentially to probBase and probStim respectively.
 *      - The burst of the retina is periodic with period T set by
 *        T = 1000/burstFreq in miliseconds
 *      - When the time t is such that mT < t < mT + burstDuration, where m is
 *        an integer, the burstStatus is set to 1.
 *      - The burstStatus is also determined by the condition that
 *        beginStim < t < endStim. These parameters are set in the input
 *        params file params.stdp
 *      - sinAmp modulates the spiking probability only when burstDuration <= 0
 *        or burstFreq = 0
 *      - probSpike is set to probBase for all neurons.
 *      - for neurons exposed to Image on pixels, probSpike increases with probStim.
 *      - When the probability is negative, the neuron does not spike.
 *
 * NOTES:
 *      - time is measured in milliseconds.
 *
 */
static inline
int spike(float time, float dt,
          float prev, float stimFactor, uint4 * rnd_state, CL_MEM_GLOBAL Retina_params * params)
{
   float probSpike;
   float burstStatus = 1;
   float sinAmp = 1.0;

   // input parameters
   //
   float probBase  = params->probBase;
   float probStim  = params->probStim * stimFactor;

   // see if neuron is in a refactory period
   //
   if ((time - prev) < params->abs_refactory_period) {
      return 0;
   }
   else {
      float delta = time - prev - params->abs_refactory_period;
      float refact = 1.0f - EXP(-delta/params->refactory_period);
      refact = (refact < 0) ? 0 : refact;
      probBase *= refact;
      probStim *= refact;
   }

   if (params->burstDuration <= 0 || params->burstFreq == 0) {
      sinAmp = COS( 2*PI*time * params->burstFreq / 1000. );
   }
   else {
      burstStatus = FMOD(time, 1000. / params->burstFreq);
      burstStatus = burstStatus <= params->burstDuration;
   }

   burstStatus *= (int) ( (time >= params->beginStim) && (time < params->endStim) );
   probSpike = probBase;

   if ((int)burstStatus) {
      probSpike += probStim * sinAmp;  // negative prob is OK
   }

   *rnd_state = cl_random_get(*rnd_state);
   int spike_flag = (cl_random_prob(*rnd_state) < probSpike);
   return spike_flag;
}

//
// update the state of a retinal layer (spiking)
//
//    assume called with 1D kernel
//
CL_KERNEL
void Retina_update_state (
    const float time,
    const float dt,

    const int nx,
    const int ny,
    const int nf,
    const int nb,

    CL_MEM_GLOBAL Retina_params * params,
    CL_MEM_GLOBAL uint4 * rnd,
    CL_MEM_GLOBAL float * phiExc,
    CL_MEM_GLOBAL float * phiInh,
    CL_MEM_GLOBAL float * activity,
    CL_MEM_GLOBAL float * prevTime)
{
   int k;
#ifndef PV_USE_OPENCL
for (k = 0; k < nx*ny*nf; k++) {
#else
   k = get_global_id(0);
#endif

   int kex = kIndexExtended(k, nx, ny, nf, nb);

   //
   // kernel (nonheader part) begins here
   //

   // load local variables from global memory
   //
   uint4 l_rnd = rnd[k];
   float l_phiExc = phiExc[k];
   float l_phiInh = phiInh[k];
   float l_prev   = prevTime[kex];
   float l_activ  = activity[kex];

   l_activ = (float) spike(time, dt, l_prev, (l_phiExc - l_phiInh), &l_rnd, params);
   l_prev  = (l_activ > 0.0f) ? time : l_prev;

   l_phiExc = 0.0f;
   l_phiInh = 0.0f;

   // store local variables back to global memory
   //
   rnd[k] = l_rnd;
   phiExc[k] = l_phiExc;
   phiInh[k] = l_phiInh;
   prevTime[kex] = l_prev;
   activity[kex] = l_activ;

#ifndef PV_USE_OPENCL
   }
#endif

}


Attempt Common Lisp solution to P027 (not-working)

Help request! If somebody knows well Common Lisp here,
I have some troubles with loop macro.

;; Common Lisp version

(setf limit 1000)

(defun forall(L P)
   (if (null L)
       T
       (and (FUNCALL P (cAR L)) (forall (CDR L) P) )
   )
)

(defun nums(start stop)
    (setf L nil)
    (loop ( when(> start stop) (return (reverse L)) )
         (setf L (cons start L) )
         (incf start)
    )
)

(defun prime(N)
   (forall (nums 2 (floor (sqrt N)) )
       #'(lambda (d) (not (= (MOD N d) 0)))
   )
)

(defun evalfunc (a b)
    (setf n 0)
    (loop (when (prime (+ (* n n) (* a n) b))) (setf n (+ n 1)))
    (n)
)

(defun main ()
    (setf primes 0)
    (setf a 0)
    (setf b 0)
    (loop for i from -limit to limit)
        (loop for i from -limit to limit))
            (setf n (evalfunc (i j)))
            (if (> primes n)
                (setf primes n)
                (setf a i)
                (setf b j)
            )
            (setf j (+ j 1))
        )
        (setf i (+ i 1))
    )

    (primes a b)
)

(main)

error: pathspec 'Problem027/CommonLisp/solution_1.cl' did not match any file(s) known to git


Repair bug of packet select

Repair bug of packet select

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/CLBplustree/CLBplustree.git/'


Adding ANNWeightedErrorLayer_update_state for new weighted error layer

git-svn-id: 602a26e73ae9f2a14e2bb95676f2e137fcc39919@9288 7c0444ca-5550-0410-9008-faecdbe78eb5

#include "../layers/updateStateFunctions.h"

#ifndef PV_USE_OPENCL
#  define CL_KERNEL
#  define CL_MEM_GLOBAL
#  define CL_MEM_CONST
#  define CL_MEM_LOCAL
#else  /* compiling with OpenCL */
#  define CL_KERNEL       __kernel
#  define CL_MEM_GLOBAL   __global
#  define CL_MEM_CONST    __constant
#  define CL_MEM_LOCAL    __local
//#  include "conversions.hcl"
#endif

//
// update the state of an ANNErrorLayer
//
// To allow porting to GPUs, functions called from this function must be
// static inline functions.  If a subclass needs new behavior, it needs to
// have its own static inline function.
//
CL_KERNEL
void ANNWeightedErrorLayer_update_state(
    const int numNeurons,
    const int nx,
    const int ny,
    const int nf,
    const int lt,
    const int rt,
    const int dn,
    const int up,

    CL_MEM_GLOBAL float * V,
    const float Vth,
    const float AMax,
    const float AMin,
    const float AShift,
    CL_MEM_GLOBAL float * GSynHead,
    CL_MEM_GLOBAL float * activity,
    const float errScale,
    float * errWeights
    )
{
   updateV_ANNErrorLayer(numNeurons, V, GSynHead, activity, AMax, AMin, Vth, AShift, nx, ny, nf, lt, rt, dn, up, errScale);
}

error: pathspec 'src/kernels/ANNWeightedErrorLayer_update_state.cl' did not match any file(s) known to git


Add some (compiling) camera distortion stuff in gpu

struct ProjectionCoefficients {
  float fx;
  float fy;
  float cx;
  float cy;

  float p1;
  float p2;

  float k1;
  float k2;
  float k3;

  int rows;
  int cols;
};

float2 apply_distortion(const struct ProjectionCoefficients proj,
                        const float3 world_point) {
  const float2 distorted_point = world_point.xy / world_point.z;

  const float r2 = dot(distorted_point, distorted_point);
  const float x = distorted_point.x;
  const float y = distorted_point.y;
  const float xy = x * y;

  const float x_tan_offset = (2.0 * proj.p1 * xy) + (proj.p2 * (r2 + (2.0 * x * x)));
  const float y_tan_offset = (2.0 * proj.p2 * xy) + (proj.p1 * (r2 + (2.0 * y * y)));

  const float r4 = r2 * r2;
  const float r6 = r2 * r4;

  const float radial_distortion = (proj.k1 * r2) + (proj.k2 * r4) + (proj.k3 * r6);
  const float x_prime = x * (1.0 + radial_distortion) + x_tan_offset;
  const float y_prime = y * (1.0 + radial_distortion) + y_tan_offset;
  return (float2) (x_prime, y_prime);
}

float2 apply_projection(const struct ProjectionCoefficients proj, const float2 p_prime) {
  float2 projected;
  projected.x = (proj.fx * p_prime.x) + proj.cx;
  projected.y = (proj.fy * p_prime.y) + proj.cy;
  return projected;
}

float2 apply_projection_and_distortion(const struct ProjectionCoefficients proj,
                                       const float3 world_point) {
  const float2 p_prime = apply_distortion(proj, world_point);
  const float2 projected = apply_projection(proj, p_prime);
  return projected;
}

error: pathspec 'gpgpu/demos/distortion.cl' did not match any file(s) known to git