Create renderer.cl

Create renderer.cl

directly copied from https://raw.githubusercontent.com/thi-ng/raymarchcl/master/resources/renderer.cl

typedef struct {
  float3 pos;
  float3 dir;
} TRay;

typedef struct {
  float3 pos;
  float3 normal;
  float distance;
  int objectID;
  int iter;
} TIsec;

typedef struct {
  float4 albedo;
  float r0;
  float smoothness;
  float2 dummy;
} TMaterial;

typedef struct {
  float4 vertices[4];
  float4 normal;
  float4 color;
} TAreaLight;

typedef struct {
  float3 eyePos;
  float4 mcPos;
  float3 mcNormal;
  float2 pixelPos;
  float seed;
} TRenderState;

typedef struct {
  float3 eyePos;
  float3 targetPos;
  float3 up;
  float3 voxelBounds;
  float3 voxelBounds2;
  float3 voxelBoundsMin;
  float3 voxelBoundsMax;
  float3 invVoxelScale;
  float3 skyColor1;
  float3 skyColor2;
  int4 voxelRes;
  int2 resolution;
  float invAspect;
  float time;
  float fov;
  int maxIter;
  int maxVoxelIter;
  float maxDist;
  float startDist;
  float eps;
  int aoIter;
  float aoStepDist;
  float aoAmp;
  float voxelSize;
  float groundY;
  int shadowIter;
  int reflectIter;
  float shadowBias;
  float lightScatter;
  float minLightAtt;
  float gamma;
  float exposure;
  float dof;
  float frameBlend;
  float fogPow;
  float flareAmp;
  int mcTableLength;
  uchar isoVal;
  uchar numLights;
  float4 lightPos[4];
  float4 lightColor[4];
  TMaterial materials[4];
} TRenderOpts;

__constant float INV8BIT = 1.0f / 255.0f;
__constant int3 ONE = (int3)(1,0,-1);

float4 randFloat4(__global const float4* mcSamples, uint seed);
float2 distUnion(const float2 v1, const float2 v2);
float intersectsBox(const float3 bmin, const float3 bmax, const float3 p, const float3 dir);
int voxelLookup(__global const uchar* voxels, __private const TRenderOpts* opts, const float3 p);
float voxelLookupI(__global const uchar* voxels, __private const TRenderOpts* opts, const int3 q);
float3 voxelNormal(__global const uchar* voxels, __private const TRenderOpts* opts, const int3 q);
float3 voxelNormalSmooth(__global const uchar* voxels, __private const TRenderOpts* opts, const int3 q);
float voxelMaterial(__private const TRenderOpts* opts, const uchar v);
float2 distanceToScene(__global const uchar* voxels, __private const TRenderOpts* opts, TIsec* isec,
                       const float3 rpos, const float3 dir, int steps, bool smooth);
void raymarch(__global const uchar* voxels,
              __private const TRenderOpts* opts,
              const TRay* ray, TIsec* result, const float maxDist, int maxSteps, bool smooth);
float3 skyGradient(__private const TRenderOpts* opts, const float3 dir);
float3 lightPos(__global const float4* mcSamples,
                __private const TRenderOpts* opts,
                __private const TRenderState* state,
                const int i);
float3 reflect(const float3 v, const float3 n);
float3 applyAtmosphere(__global const float4* mcSamples,
                       __private const TRenderOpts* opts,
                       __private const TRenderState* state,
                       const TRay* ray, const TIsec* isec, float3 col);
float shadow(__global const uchar* voxels,
             __private const TRenderOpts* opts,
             const float3 p, const float3 ldir, const float ldist);
float schlick(const float r0, const float smooth, const float3 normal, const float3 view);
float diffuseIntensity(const float3 ldir, const float3 normal);
float blinnPhongIntensity(const float smooth, const TRay* ray,
                          const float3 lightDir, const float3 normal);
float ambientOcclusion(__global const uchar* voxels,
                       __global const float4* mcSamples,
                       __private const TRenderOpts* opts,
                       const float3 pos, const float3 normal);
float3 objectLighting(__global const uchar* voxels,
                      __global const float4* mcSamples,
                      __private const TRenderOpts* opts,
                      __private const TRenderState* state,
                      __private const TRay* ray,
                      __private TIsec* isec,
                      __private const TMaterial* mat,
                      const float3 normal, const float3 reflectCol);
float3 basicSceneColor(__global const uchar* voxels,
                       __global const float4* mcSamples,
                       const TRenderOpts* opts,
                       const TRenderState* state,
                       const TRay* ray, TIsec* isec);
float3 sceneColor(__global const uchar* voxels,
                  __global const float4* mcSamples,
                  const TRenderOpts* opts,
                  const TRenderState* state, const TRay* ray);
float3 gamma(const float3 col);
float3 tonemap(const float3 col, const float g);
TRay cameraRayLookat(const TRenderOpts* opts, const TRenderState* state);
TRenderState initRenderState(const TRenderOpts* opts,
                             __global const float4* mcSamples, const int id);

/* ---- implementation ---- */

float4 randFloat4(__global const float4* mcSamples, uint seed) {
  return mcSamples[seed & 0x3fff];
}

float2 distUnion(const float2 v1, const float2 v2) {
  return v1.x < v2.x ? v1 : v2;
}

/**
 * @returns distance to box or -1 if no isec
 */
float intersectsBox(const float3 bmin, const float3 bmax, const float3 p, const float3 dir) {
  const float3 omin = (bmin - p) / dir;
  const float3 omax = (bmax - p) / dir;
  float3 m = min(omax, omin);
  const float a = max(max(m.x, 0.0f), max(m.y, m.z));
  m = max(omax, omin);
  const float b = min(m.x, min(m.y, m.z));
  return b > a ? a : -1.0f;
}

int voxelLookup(__global const uchar* voxels, __private const TRenderOpts* opts, const float3 p) {
  const int4 res = opts->voxelRes;
  const int3 q = convert_int3_sat(p * convert_float3(res.xyz));
  if (q.z >= 0 && q.z < res.z && q.y >= 0 && q.y < res.y && q.x >= 0 && q.x < res.x) {
    return (int)voxels[q.z * res.w + q.y * res.x + q.x];
  }
  return -1;
}

float voxelLookupI(__global const uchar* voxels, __private const TRenderOpts* opts, const int3 q) {
  const int4 res = opts->voxelRes;
  if (q.z >= 0 && q.z < res.z && q.y >= 0 && q.y < res.y && q.x >= 0 && q.x < res.x) {
    return step((float)opts->isoVal, (float)voxels[q.z * res.w + q.y * res.x + q.x]);
  }
  return 0.0f;
}

float3 voxelNormal(__global const uchar* voxels, __private const TRenderOpts* opts, const int3 q) {
  float nx = voxelLookupI(voxels, opts, q + ONE.xyy)
    - voxelLookupI(voxels, opts, q - ONE.xyy);
  float ny = voxelLookupI(voxels, opts, q + ONE.yxy)
    - voxelLookupI(voxels, opts, q - ONE.yxy);
  float nz = voxelLookupI(voxels, opts, q + ONE.yyx)
    - voxelLookupI(voxels, opts, q - ONE.yyx);
  return -(float3)(nx, ny, nz);
}

float3 voxelNormalSmooth(__global const uchar* voxels, __private const TRenderOpts* opts, const int3 q) {
  float3 n = (float3)0.0f;
  for(char z = -1; z <= 1; z++) {
    for(char y = -1; y <= 1; y++) {
      for(char x = -1; x <= 1; x++) {
        int3 qq = (int3)(q.x + x, q.y + y, q.z + z);
        if (voxelLookupI(voxels, opts, qq) > 0.0f) {
          n += voxelNormal(voxels, opts, qq);
        }
      }
    }
  }
  return normalize(n);
}

float voxelMaterial(__private const TRenderOpts* opts, const uchar v) {
  return (v < 168 ? (v < 84 ? 1.0f : 2.0f) : 3.0f);
}

float2 distanceToScene(__global const uchar* voxels, __private const TRenderOpts* opts, TIsec* isec,
                       const float3 rpos, const float3 dir, int steps, bool smooth) {
  float2 res = distUnion((float2)(rpos.y + opts->groundY), (float2)(1e5f, -1.0f));
  isec->normal = (res.x < 1e5) ? (float3)(0.0f, 1.0f, 0.0f) : -dir;
  const float idist = intersectsBox(opts->voxelBoundsMin, opts->voxelBoundsMax, rpos, dir);
  if (idist >= 0.0f && idist < res.x) {
    const float3 delta = dir / (steps * 0.5f) * opts->invVoxelScale;
    float3 p = rpos + opts->voxelBounds;
    if (idist > 0.0f) p = mad(dir, (float3)idist, p);
    p *= opts->invVoxelScale;
    while(--steps >= 0) {
      const int v = voxelLookup(voxels, opts, p);
      if (v < 0) break;
      if (v > opts->isoVal) {
        const int4 vres = opts->voxelRes;
        const int3 q = convert_int3_sat(p * convert_float3(vres.xyz));
        if (smooth) {
          isec->normal = voxelNormalSmooth(voxels, opts, q);
        } else {
          isec->normal = normalize(voxelNormal(voxels, opts, q));
        }
        return distUnion((float2)(length(rpos - mad(p, opts->voxelBounds2, -opts->voxelBounds)) - opts->voxelSize,
                                  voxelMaterial(opts, v)), res);
      }
      p += delta;
    }
  }
  return res;
}

void raymarch(__global const uchar* voxels,
              __private const TRenderOpts* opts,
              const TRay* ray, TIsec* result, const float maxDist, int maxSteps, bool smooth) {
  result->distance = opts->startDist;
  while(--maxSteps >= 0) {
    result->pos = ray->pos + ray->dir * result->distance;
    const float2 sceneDist = distanceToScene(voxels, opts, result, result->pos, ray->dir, opts->maxVoxelIter, smooth);
    result->objectID = (int)sceneDist.y;
    if(fabs(sceneDist.x) <= opts->eps || result->distance >= maxDist) {
      break;
    }
    result->distance += sceneDist.x;
  }
  if(result->distance >= maxDist) {
    result->pos = ray->pos + ray->dir * result->distance;
    result->objectID = -1;
    result->distance = 1000.0f;
  }
}

float3 skyGradient(__private const TRenderOpts* opts, const float3 dir) {
  return mix(opts->skyColor1, opts->skyColor2, (float3)(dir.y * 0.5f + 0.5f));
}

float3 lightPos(__global const float4* mcSamples,
                __private const TRenderOpts* opts,
                __private const TRenderState* state,
                const int i) {
  uint seed = (uint)(state->pixelPos.x * 1957.0f + state->pixelPos.y * 2173.0f + opts->time * 4763.742f);
  return mad(randFloat4(mcSamples, seed).xyz, (float3)(opts->lightScatter), opts->lightPos[i].xyz);
}

float3 reflect(const float3 v, const float3 n){
  return v - 2.0f * dot(v, n) * n;
}

float3 applyAtmosphere(__global const float4* mcSamples,
                       __private const TRenderOpts* opts,
                       __private const TRenderState* state,
                       const TRay* ray,
                       const TIsec* isec,
                       float3 col) {
  const float3 fa = (float3)(1.0f - exp(isec->distance * isec->distance * -opts->fogPow));
  col = mad(skyGradient(opts, ray->dir) - col, fa, col);
  for(uchar i=0; i < opts->numLights; i++) {
    float3 lp = lightPos(mcSamples, opts, state, i);
    const float3 d = (float3)(clamp(dot(lp - ray->pos, ray->dir), 0.0f, isec->distance));
    lp = mad(ray->dir, d, ray->pos - lp);
    col = mad(opts->lightColor[i].xyz, (float3)(opts->flareAmp / dot(lp,lp)), col);
  }
  return col;
}

float shadow(__global const uchar* voxels,
             __private const TRenderOpts* opts,
             const float3 p, const float3 ldir, const float lightMaxDist) {
  TRay shadowRay;
  shadowRay.pos = p;
  shadowRay.dir = ldir;
  TIsec shadowIsec;
  raymarch(voxels, opts, &shadowRay, &shadowIsec, lightMaxDist, opts->shadowIter, false);
  return step(lightMaxDist, shadowIsec.distance);
}

// http://en.wikipedia.org/wiki/Schlick's_approximation
float schlick(const float r0, const float smooth, const float3 normal, const float3 view) {
  const float d = clamp(1.0f - dot(normal, -view), 0.0f, 1.0f);
  if (d > 0.0f) {
    const float d2 = d * d;
    return mad(1.0f - r0, smooth * d2 * d2 * d, r0);
  }
  return 0.0f;
}

float diffuseIntensity(const float3 ldir, const float3 normal) {
  return max(0.0f, dot(ldir, normal));
}

float blinnPhongIntensity(const float smooth, const TRay* ray,
                          const float3 lightDir, const float3 normal) {
  const float nh = dot(normalize(lightDir - ray->dir), normal);
  if (nh > 0.0f) {
    const float specPow = exp2(mad(6.0f, smooth, 4.0f));
    return pow(nh, specPow) * (specPow + 2.0f) * 0.125f;
  }
  return 0.0f;
}

float ambientOcclusion(__global const uchar* voxels,
                       __global const float4* mcSamples,
                       __private const TRenderOpts* opts,
                       const float3 pos,
                       const float3 normal) {
  float ao = 1.0f;
  float3 d = (float3)0.0f;
  uint seed = (uint)(pos.x * 3183.75f + pos.y * 1831.42f + pos.z * 2945.87f + opts->time * 2671.918f);
  const float3 scatter = (float3)0.2f;
  const float3 ad = (float3)opts->aoStepDist;
  TIsec isec;
  for(int i = 0; i <= opts->aoIter && ao > 0.01; i++) {
    d += ad;
    seed += 37;
    const float3 n = normalize(mad(randFloat4(mcSamples, seed).xyz, scatter, normal));
    const float2 sceneDist = distanceToScene(voxels, opts, &isec, mad(n, d, pos), n, opts->maxVoxelIter / 2, false);
    ao *= 1.0f - max((d.x - sceneDist.x) * opts->aoAmp / d.x, 0.0f);
  }
  return ao;
}

float3 objectLighting(__global const uchar* voxels,
                      __global const float4* mcSamples,
                      __private const TRenderOpts* opts,
                      __private const TRenderState* state,
                      __private const TRay* ray,
                      __private TIsec* isec,
                      __private const TMaterial* mat,
                      const float3 normal,
                      const float3 reflectCol) {
  float ao = ambientOcclusion(voxels, mcSamples, opts, isec->pos, normal);
  float3 diffReflect = skyGradient(opts, normal) * ao;
  float3 specReflect = reflectCol * ao;
  float3 finalCol = (float3)0.0f;
  for(uchar i = 0; i < opts->numLights; i++) {
    // point light
    float3 deltaLight = lightPos(mcSamples, opts, state, i) - isec->pos;
    float lightDist = dot(deltaLight, deltaLight);
    float att = 1.0f / lightDist;
    if (att > opts->minLightAtt) {
      float3 lightDir = normalize(deltaLight);
      float shadowFactor = shadow(voxels, opts, isec->pos + lightDir * opts->shadowBias,
                                  lightDir, min(sqrt(lightDist) - opts->shadowBias, opts->maxDist));
      if (shadowFactor > 0.0f) {
        float3 incidentLight = opts->lightColor[i].xyz * shadowFactor * att;
        diffReflect += diffuseIntensity(lightDir, normal) * incidentLight;
        specReflect += blinnPhongIntensity(mat->smoothness, ray, lightDir, normal) * incidentLight;
      }
    }
    diffReflect *= mat->albedo.xyz;
    // specular
    finalCol += mix(diffReflect, specReflect, schlick(mat->r0, mat->smoothness, normal, ray->dir));
  }
  return finalCol / (float)(opts->numLights);
}

float3 basicSceneColor(__global const uchar* voxels,
                       __global const float4* mcSamples,
                       __private const TRenderOpts* opts,
                       __private const TRenderState* state,
                       __private const TRay* ray,
                       __private TIsec* isec) {
  raymarch(voxels, opts, ray, isec, opts->maxDist, opts->maxIter, false);
  float3 sceneCol;
  if(isec->objectID < 0) {
    sceneCol = skyGradient(opts, ray->dir);
  } else {
    const TMaterial* mat = &opts->materials[isec->objectID];
    //TMaterial m2 = *mat;
    //isec->normal = sceneNormal(voxels, opts, isec->pos, ray->dir);
    //if (isec->objectID > 0) {
    //m2.albedo = (float4)(isec->pos + 1.0f, 0.0f);
    //m2.albedo = (float4)(mad(isec->normal.zyx, 2.0, 2.0f), 0.0f);
    //}
    sceneCol = objectLighting(voxels, mcSamples, opts, state, ray, isec, mat, isec->normal,
                              skyGradient(opts, reflect(ray->dir, isec->normal)));
  }
  return applyAtmosphere(mcSamples, opts, state, ray, isec, sceneCol);
}

float3 sceneColor(__global const uchar* voxels,
                  __global const float4* mcSamples,
                  __private const TRenderOpts* opts,
                  __private const TRenderState* state,
                  __private const TRay* ray) {
  TIsec isec;
  raymarch(voxels, opts, ray, &isec, opts->maxDist, opts->maxIter, true);
  float3 sceneCol;
  if(isec.distance >= opts->maxDist) {
    sceneCol = skyGradient(opts, ray->dir);
  } else {
    const TMaterial* mat = &opts->materials[isec.objectID];
    //TMaterial m2 = *mat;
    float3 norm = mad(state->mcNormal, 1.0f / mad(mat->smoothness, 200.0f, 5.0f), isec.normal);
    float3 reflectCol = (float3)0.0f; //mat->r0;
    //if (isec.objectID > 0) {
    //m2.albedo = (float4)(isec.pos + 1.0f, 0.0);
    //m2.albedo = (float4)(mad(norm.zyx, 2.0f, 2.0f), 0.0f);
    //}
    if (mat->r0 > 0.0f && opts->reflectIter > 0) {
      TIsec rIsec;
      rIsec.pos = isec.pos;
      rIsec.normal = norm;
      TRay reflectRay;
      reflectRay.dir = ray->dir;
      for(int i = 0; i < opts->reflectIter; i++) {
        reflectRay.dir = reflect(reflectRay.dir, rIsec.normal);
        reflectRay.pos = rIsec.pos + reflectRay.dir * 0.0075f;
        reflectCol += basicSceneColor(voxels, mcSamples, opts, state, &reflectRay, &rIsec);
        if (rIsec.objectID < 0) break;
        if ((&opts->materials[rIsec.objectID])->r0 < 0.001) break;
      }
    } else {
      reflectCol = skyGradient(opts, reflect(ray->dir, norm));
    }
    sceneCol = objectLighting(voxels, mcSamples, opts, state, ray, &isec, mat, norm, reflectCol);
  }
  sceneCol = applyAtmosphere(mcSamples, opts, state, ray, &isec, sceneCol);
  return sceneCol;
}

float3 gamma(const float3 col) {
  return col * col;
}

float3 tonemap(const float3 col, const float g) {
  return gamma(col / (g + col));
}

TRay cameraRayLookat(__private const TRenderOpts* opts, __private const TRenderState* state) {
  float3 forward = normalize(opts->targetPos - state->eyePos);
  float3 right = normalize(cross(forward, opts->up));
  float2 viewCoord = state->pixelPos / (float2)(opts->resolution.x, opts->resolution.y) * opts->fov - opts->fov * 0.5f;
  viewCoord.y *= -opts->invAspect;
  TRay ray;
  ray.pos = state->eyePos;
  ray.dir = normalize(right * viewCoord.x + cross(right, forward) * viewCoord.y + forward);
  return ray;
}

TRenderState initRenderState(__private const TRenderOpts* opts,
                             __global const float4* mcSamples, const int id) {
  float2 p = (float2)(id % opts->resolution.x, id / opts->resolution.x);
  TRenderState state;
  state.mcPos = randFloat4(mcSamples, (uint)(id * 17) + (uint)(opts->time * 3141.3862f));
  state.mcNormal = normalize(randFloat4(mcSamples, (uint)(id * 37) + (uint)(opts->time * 1859.1467f)).xyz);
  state.pixelPos = p + state.mcPos.zw;
  state.eyePos = mad(state.mcNormal.zxy, (float3)opts->dof, opts->eyePos);
  return state;
}

__kernel void RenderImage(__global const uchar* voxels,
                          __global const float4* mcSamples,
                          __global const TRenderOpts* g_opts,
                          __global float4* pixels,
                          const int n) {
  const int id = get_global_id(0);
  if (id < n) {
    __private TRenderOpts opts;
    __private TRenderState state;
    __private TRay ray;
    opts = *g_opts;
    state = initRenderState(&opts, mcSamples, id);
    ray = cameraRayLookat(&opts, &state);
    const float3 sceneCol = sceneColor(voxels, mcSamples, &opts, &state, &ray) * opts.exposure;
    pixels[id] = (float4)(mix(pixels[id].xyz, sceneCol, opts.frameBlend), 1.0f);
  }
}

__kernel void TonemapImage(__global const float4* pixels,
                           __global TRenderOpts* opts,
                           __global uint* rgba,
                           const int n) {
  int id = get_global_id(0);
  if (id < n) {
    float3 col = tonemap(pixels[id].xyz, opts->gamma) * 255.0f;
    rgba[id] = 0xff000000 |
      ((int)(clamp(col.x, 0.0f, 255.0f)) << 16) |
      ((int)(clamp(col.y, 0.0f, 255.0f)) << 8) |
      (int)(clamp(col.z, 0.0f, 255.0f));
  }
}

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


More clos examples

More clos examples

(defclass Shape () ())
(defclass Rectangle (Shape) ())
(defclass Ellipse (Shape) ())
(defclass Triangle (Shape) ())

(defgeneric getstuff (shape)
  (:method-combination list))

(defmethod getstuff list ((s Shape))
  '(shape stuff))

(defmethod getstuff list ((r Rectangle))
  '(rectangle stuff))

(print (getstuff (make-instance 'Rectangle)))

error: pathspec '2016/multiple-dispatch/common-lisp/list-combination.cl' did not match any file(s) known to git


Add preliminary opencl kernel

Add preliminary opencl kernel

#define EPSILON 0.00001

typedef struct PRNG {
    ulong m_seed[16];
    ulong m_p;
} PRNG;

typedef struct Camera {
    float3 m_pos;
    float3 m_dir;
    float3 m_world_up;
    float3 m_right;
    float3 m_up;
    float m_canvas_width;
    float m_canvas_height;
    float3 m_canvas_center_pos;
    float3 m_canvas_dir_x;
    float3 m_canvas_dir_y;
    float m_near_plane_dist;
    float m_far_plane_dist;
    int m_screen_width;
    int m_screen_height;
    float m_vertical_fov;
    float m_horizontal_fov;
} Camera;

typedef struct Material {
    float3 m_reflectance;
    float3 m_emittance;
} Material;

typedef struct Triangle {
    float3 m_v1;
    float3 m_v2;
    float3 m_v3;
    Material m_material;
    float3 m_normal;
    float3 m_centroid;
    float m_area;
} Triangle;

typedef struct FlatStructure {
    Triangle m_triangles[100];
    unsigned m_num_triangles;
} FlatStructure;

typedef struct Ray {
    float3 m_origin;
    float3 m_dir;
    float3 m_invdir;
} Ray;

typedef struct IntersectionInfo {
    bool m_has_intersected;
    float3 m_pos;
    float3 m_normal;
    Ray m_incoming_ray;
    Material m_material;
} IntersectionInfo;

typedef struct AABB {
    float3 m_min;
    float3 m_max;
} AABB;

// From http://xorshift.di.unimi.it/xorshift1024star.c
ulong xorshift1024star(__local PRNG *prng) {
    ulong s0 = prng->m_seed[prng->m_p];
    ulong s1 = prng->m_seed[prng->m_p = (prng->m_p + 1) & 15];
    s1 ^= s1 << 31; // a
    s1 ^= s1 >> 11; // b
    s0 ^= s0 >> 30; // c
    return (prng->m_seed[prng->m_p] = s0 ^ s1) * 1181783497276652981L;
}

float rand_range(__local PRNG *prng, const float min, const float max) {
    return min + ((float)xorshift1024star(prng)) / (float)(ULONG_MAX / (max - min));
}

bool AABB_is_null(const AABB *aabb) {
    bool min_null = length(aabb->m_min) == 0;
    bool max_null = length(aabb->m_max) == 0;
    return min_null && max_null;
}

float3 AABB_min(const AABB *aabb) {
    return aabb->m_min;
}

float3 AABB_max(const AABB *aabb) {
    return aabb->m_max;
}

float3 AABB_diagonal(const AABB *aabb) {
    return aabb->m_max - aabb->m_min;
}

float3 AABB_center(const AABB *aabb) {
    return aabb->m_min + (AABB_diagonal(aabb) * 0.5f);
}

// std_array<glm_vec3, 8> AABB_vertices(AABB &aabb) {
//     std_array<glm_vec3, 8> result;
//     result[0] = {aabb.m_min.x, aabb.m_min.y, aabb.m_min.z}; // lower left front
//     result[1] = {aabb.m_max.x, aabb.m_min.y, aabb.m_min.z}; // lower right front
//     result[2] = {aabb.m_min.x, aabb.m_max.y, aabb.m_min.z}; // upper left front
//     result[3] = {aabb.m_max.x, aabb.m_max.y, aabb.m_min.z}; // upper right front
//     result[4] = {aabb.m_min.x, aabb.m_min.y, aabb.m_max.z}; // lower left back
//     result[5] = {aabb.m_max.x, aabb.m_min.y, aabb.m_max.z}; // lower right back
//     result[6] = {aabb.m_min.x, aabb.m_max.y, aabb.m_max.z}; // upper left back
//     result[7] = {aabb.m_max.x, aabb.m_max.y, aabb.m_max.z}; // upper right back
//     return result;
// }

void AABB_extend(AABB *aabb, float3 point) {
    aabb->m_min = min(point, aabb->m_min);
    aabb->m_max = max(point, aabb->m_max);
}

bool AABB_overlaps(const AABB *first, const AABB *second) {
    return first->m_max.x > second->m_min.x && first->m_min.x < second->m_max.x &&
           first->m_max.y > second->m_min.y && first->m_min.y < second->m_max.y &&
           first->m_max.z > second->m_min.z && first->m_min.z < second->m_max.z;
}

void AABB_reset(AABB *aabb) {
    aabb->m_min = 0;
    aabb->m_max = 0;
}

float2 Camera_screenspace_to_camspace(__constant const Camera *camera, unsigned x, unsigned y) {
    float rel_x = -(x - camera->m_screen_width / 2.f) / camera->m_screen_width;
    float rel_y = -(y - camera->m_screen_height / 2.f) / camera->m_screen_height;
    return (float2)(rel_x, rel_y);
}

int2 Camera_camspace_to_screenspace(__constant const Camera *camera, int2 coords) {
    int screen_x = round(0.5f * (camera->m_screen_width - 2.f * camera->m_screen_width * coords.x));
    int screen_y =
        round(0.5f * (camera->m_screen_height - 2.f * camera->m_screen_height * coords.y));
    return (int2)(screen_x, screen_y);
}

float3 Camera_camspace_to_worldspace(__constant const Camera *camera, float2 rel_pos) {
    float3 worldspace = camera->m_canvas_center_pos + (rel_pos.x * camera->m_canvas_dir_x) +
                        (rel_pos.y * camera->m_canvas_dir_y);
    return worldspace;
}

// float2 Camera_worldspace_to_camspace(const Camera *camera, float3 world_pos_on_canvas) {
//     float3 canvas_center_to_point = world_pos_on_canvas - Camera_canvas_center_pos(camera);
//
//     // Manually calculate angle between the positive y-axis on the canvas and the world point
//     float3 ay = canvas_center_to_point;
//     float3 by = Camera_up(camera);
//     float3 cy = cross(ay, by);
//     float angle1y = atan(dot(ay, by), length(cy));
//
//     // Manually calculate angle between the positive x-axis on the canvas and the world point
//     float3 ax = canvas_center_to_point;
//     float3 bx = Camera_right(camera);
//     float3 cx = cross(ax, bx);
//     float angle1x = atan(length(cx), dot(ax, bx));
//
//     float angle2x = glm_pi<float>() - (glm_half_pi<float>() + angle1x);
//     float len = length(canvas_center_to_point);
//     float x = sin(angle2x) * len;
//     float y = sin(angle1y) * len;
//     float rel_x = -(2 * x) / Camera_canvas_width(camera);
//     float rel_y = -(2 * y) / Camera_canvas_height(camera);
//     return (float2)(rel_x, -rel_y);
// }

// glm_vec3 Camera_worldpoint_to_worldspace(const Camera *camera, glm_vec3 world_point) {
//     auto ray_to_cam = pos(camera) - world_point;
//     float dist = 0;
//     bool collided = glm_intersectRayPlane(world_point, glm_normalize(ray_to_cam),
//                                           canvas_center_pos(camera), dir(camera), dist);
//     if (collided) {
//         return world_point + glm_normalize(ray_to_cam) * dist;
//     } else {
//         return glm_vec3(0);
//     }
// }

// From
// http://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-box-intersection
bool intersect_ray_aabb(const Ray *ray, const AABB *aabb) {
    float tmin, tmax, tymin, tymax, tzmin, tzmax;

    float3 bounds[2];
    bounds[0] = AABB_min(aabb);
    bounds[1] = AABB_max(aabb);

    char3 sign;
    sign.x = (ray->m_invdir.x < 0);
    sign.y = (ray->m_invdir.y < 0);
    sign.z = (ray->m_invdir.z < 0);

    tmin = (bounds[sign.x].x - ray->m_origin.x) * ray->m_invdir.x;
    tmax = (bounds[1 - sign.x].x - ray->m_origin.x) * ray->m_invdir.x;
    tymin = (bounds[sign.y].y - ray->m_origin.y) * ray->m_invdir.y;
    tymax = (bounds[1 - sign.y].y - ray->m_origin.y) * ray->m_invdir.y;

    if ((tmin > tymax) || (tymin > tmax))
        return false;
    if (tymin > tmin)
        tmin = tymin;
    if (tymax < tmax)
        tmax = tymax;

    tzmin = (bounds[sign.z].z - ray->m_origin.z) * ray->m_invdir.z;
    tzmax = (bounds[1 - sign.z].z - ray->m_origin.z) * ray->m_invdir.z;

    if ((tmin > tzmax) || (tzmin > tmax))
        return false;
    if (tzmin > tmin)
        tmin = tzmin;
    if (tzmax < tmax)
        tmax = tzmax;

    return true;
}

// Möller-Trumbore intersection algorithm
// (see https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm)
bool intersect_ray_triangle(const Ray *ray, __constant const Triangle *triangle, float *dist) {
    // Calculate edges of triangle from v0.
    float3 e0 = triangle->m_v2 - triangle->m_v1;
    float3 e1 = triangle->m_v3 - triangle->m_v1;

    // Calculate determinant to check whether the ray is in the newly calculated plane made up from
    // e0 and e1.
    float3 pvec = cross(ray->m_dir, e1);
    float det = dot(e0, pvec);

    // Check whether determinant is close to 0. If that is the case, the ray is in the same plane as
    // the triangle itself which means that they can't collide. This effectively disables backface
    // culling for which we would instead only check whether det < epsilon.
    if (det > -EPSILON && det < EPSILON)
        return false;

    float inv_det = 1.f / det;

    // Calculate distance from v1 to ray origin
    float3 tvec = ray->m_origin - triangle->m_v1;

    // Calculate u parameter and test bound
    float u = dot(tvec, pvec) * inv_det;

    // Check whether the intersection lies outside of the triangle
    if (u < 0.f || u > 1.f)
        return false;

    // Prepare to test v parameter
    float3 qvec = cross(tvec, e0);

    // Calculate v parameter and test bound
    float v = dot(ray->m_dir, qvec) * inv_det;

    // Check whether the intersection lies outside of the triangle
    if (v < 0.f || u + v > 1.f)
        return false;

    float t = dot(e1, qvec) * inv_det;

    if (t > EPSILON) {
        *dist = t - EPSILON;
        return true;
    }

    // If we end up here, there was no hit
    return false;
}

IntersectionInfo Scene_intersect(__constant FlatStructure *accel_struct, Ray *ray) {
    IntersectionInfo intersect_info;

    // Keep track of closest triangle
    float closest_dist = FLT_MAX;
    Triangle closest_triangle;
    // for (const auto &shape : FlatStructure::shapes(flatstruct)) {
    //     if (intersect_ray_aabb(ray, Shape::aabb(shape))) {
    //         for (auto &tri : Shape::triangles(shape)) {
    for (unsigned i = 0; i < accel_struct->m_num_triangles; i++) {
        float dist_to_intersect;
        __constant Triangle *tri = &(accel_struct->m_triangles[i]);
        bool intersected = intersect_ray_triangle(ray, tri, &dist_to_intersect);
        if (intersected) {
            // Find closest triangle
            if (dist_to_intersect < closest_dist) {
                closest_dist = dist_to_intersect;
                closest_triangle = *tri;

                intersect_info.m_has_intersected = true;
                intersect_info.m_pos = ray->m_origin + ray->m_dir * closest_dist;
                intersect_info.m_incoming_ray = *ray;
                intersect_info.m_normal = closest_triangle.m_normal;
                intersect_info.m_material = closest_triangle.m_material;
            }
        }
    }
    //     }
    // }

    return intersect_info;
}

__kernel void renderer_trace_pixel_color(__write_only __global float4 *output, const unsigned max_depth,
                                         __local PRNG *prng, __constant Camera *camera,
                                         __constant FlatStructure *flatstruct) {
    int x = get_global_id(0);
    int y = get_global_id(1);
    int index = y * get_global_size(x) + x;

    // float2 rel_pos = Camera_screenspace_to_camspace(camera, x, y);
    // float3 world_pos = Camera_camspace_to_worldspace(camera, rel_pos);
    // float3 ray_dir = normalize(world_pos - camera->m_pos);
    //
    // float3 ret_color = (float3)(0);
    // Ray next_ray = {world_pos, ray_dir};
    // float3 brdf = (float3)(1);
    // for (unsigned depth = 0; depth < max_depth; depth++) {
    //     IntersectionInfo intersect_info = Scene_intersect(flatstruct, &next_ray);
    //     if (intersect_info.m_has_intersected) {
    //         // Get the local radiance only on first bounce
    //         float3 local_radiance;
    //         // if (depth == 0) {
    //         // auto ray = ray_pos - impact_pos;
    //         // float dist2 = glm_dot(ray, ray);
    //         // auto cos_area = glm_dot(-ray_dir, tri->m_normal) * tri->m_area;
    //         // auto solid_angle = cos_area / glm_max(dist2, 1e-6f);
    //         //
    //         // if (cos_area > 0.0)
    //         //     local_radiance = tri->m_emittance * solid_angle;
    //         //     local_radiance = intersect_info.m_material.m_emittance;
    //         // }
    //
    //         local_radiance = intersect_info.m_material.m_emittance;
    //
    //         // Emitter sample
    //         // TODO
    //         // glm_vec3 illumination;
    //
    //         float3 normal =
    //             intersect_info.m_normal *
    //             -sign(dot(intersect_info.m_normal, intersect_info.m_incoming_ray.m_dir));
    //
    //         // Find new random direction for diffuse reflection
    //         float u = 2.f * rand_range(prng, 0.f, 1.f);
    //         float v = 2.f * M_PI_F * rand_range(prng, 0.f, 1.f);
    //         float xx = sqrt(1 - u * u) * cos(v);
    //         float yy = sqrt(1 - u * u) * sin(v);
    //         float zz = u;
    //         float3 new_ray_dir = {xx, yy, zz};
    //         new_ray_dir = normalize(new_ray_dir);
    //         if (dot(new_ray_dir, normal) < 0) {
    //             new_ray_dir = -new_ray_dir;
    //         }
    //
    //         float cos_theta = dot(new_ray_dir, normal);
    //
    //         ret_color += brdf * local_radiance;
    //         brdf *= 2.f * intersect_info.m_material.m_reflectance * cos_theta;
    //
    //         // Make a new ray
    //         Ray new_ray = {intersect_info.m_pos, new_ray_dir};
    //         next_ray = new_ray;
    //
    //     } else {
    //         break;
    //     }
    // }
    //
    // output[index] = (float4)(ret_color.x, ret_color.y, ret_color.z, 1.f);
    output[index] = (float4)(.5f, .2f, .9f, 1.f);
}

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


Practice with functions(optional, rest and keyword parameters)

;; @file test.cl
;;
;; @breif Places to test things
;;

; Optionals function parameters &optional
(defun test-opt-func-params (a b &optional (c 3 c-supplied-p))
 "Optional function parameters with default value and flag indicating whether
 or not the optional argument is supplied"
 (list a b c c-supplied-p))

; Rest function parameter &rest
(defun test-rest-func-params (a &optional (b 2) &rest numbers)
 "Rest parameter catches all remaining arguments not consumed by required and
 optional parameters"
 (list a b :rest numbers))

; Keyword function parameters &key
(defun test-key-func-params (width height
                             &key ((:square s) (* width height) s-supplied-p))
 "Unlike optional parameters, keyword parameters is not positional"
 (list width height :keyword (list s s-supplied-p)))

; Function as argument, aka, high-order function
(defun plot (fn min max step)
 "Plot ASCII-art graph of the results of the function with arguments from min
 to max, with step as the increment step"
 (loop for i from min to max by step do
  (loop repeat (funcall fn i) do (format t "*"))
  (format t "~%")))
; Usage
(funcall #'plot #'exp 0 4 1/2)
(defvar plot-data (list #'exp 0 4 1/2))
(apply #'plot plot-data)

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


Add a simple test for semant

Add a simple test for semant

class Test {
  checkInt() : Int { 1 };
  checkTrue() : Bool { true };
  checkFalse() : Bool { false };
  checkString() : String { "Test" };

  checkAssignInt(a : Int) : Int { a <- 123 };
  checkAssignBool(b: Bool) : Bool { b <- true };
  checkAssignString(c : String) : String { c <- "Test" };
};

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


Initial commit, sets 1 and 2

Initial commit, sets 1 and 2

;this file is a re-write of my solutions to www.cryptopals.com, trying out cl21 and apps hungarian notation

(eval-when (:execute)
  (ql-dist:install-dist "http://dists.cl21.org/cl21.txt"))

(eval-when (:compile-toplevel :execute)
  (ql:quickload :cl21)
  (ql:quickload :cl-test-more)
  (ql:quickload "ironclad")
  (ql:quickload "hunchentoot")
  (ql:quickload :drakma)
  (ql:quickload :iterate))

(in-package :cl21-user)
(defpackage cryptopals
  (:use :cl21
	:cl-test-more
	:iterate)
  (:shadowing-import-from :iterate :until)
  (:shadowing-import-from :iterate :while))
(in-package :cryptopals)

#|prefixes:
bv  -  byte vector
in  -  int
s   -  string
hs  -  hex string (eg, "12ef" for #x12ef)
hc  -  hex char
b64 -  base64 encoded data, represented as a string
cb  -  count of bytes
by  -  byte
?   -  boolean predicate

|#

;some utility functions
(defun bv-make (cb-length &optional by-initial-element)
  (if by-initial-element
      (make-array cb-length :element-type '(unsigned-byte 8) :initial-element by-initial-element)
      (make-array cb-length :element-type '(unsigned-byte 8) :initial-element 0)))

(defun bv-rand (cb-length)
  (ironclad:make-random-salt cb-length))

(defun bv-pad (bv padded-len)
  (concatenate 'vector (bv-make (- padded-len (length bv))) bv))

(defun bv-from-in (in)
   (loop for i = in then (/ (- i (mod i 256)) 256)
       while (>= i 1)
       with res = #()
       do (push (mod i 256) res)
       finally (return (nreverse res))))

(defun bv-from-s (s)
  (map-to 'vector #'char-code s))

(defun bv-from-hs (hs)
  (let ((nibbles (map-to 'vector #'in-from-hc hs)))
    (let ((pairs (nreverse (subdivide (nreverse nibbles) 2)))) ;to handle odd lengths correctly
      (map-to 'vector (lm (pair) (+ (* 16 (second pair)) (first pair)))
	      pairs))))

(defun in-combine-bytes (high low bit-len)
  (+ (* high (expt 2 bit-len)) low))

(defun in-from-bv (bv)
  (reduce (lm (x y) (in-combine-bytes x y 8)) bv))

(defun in-from-s (s)
  (in-from-bv (bv-from-s s)))

(defun in-from-hc (hc)
  (let ((index "0123456789abcdef")
	(hc-dc (char-downcase hc)))
    (position hc-dc index)))

(defun in-from-hs (hs)
  (in-from-bv (bv-from-hs hs)))

(defun s-from-in (in)
  (s-from-bv (bv-from-in in)))

(defun s-from-bv (bv)
  (map-to 'string #'code-char bv))

(defun s-from-hs (hs)
  (s-from-bv (bv-from-hs hs)))

(defun s-from-seq (seq)
  (with-output-to-string (s)
    (doeach (x seq)
      (princ x s))))

(defun s-make (len &optional (c-initial-element #\a))
  (map-to 'string #'code-char (bv-make len (char-code c-initial-element))))

(defun hs-from-by (by)
  (let ((index "0123456789abcdef")
	(high (floor (/ by 16)))
	(low (mod by 16)))
    (format nil "~{~A~}" (list (getf index high) (getf index low)))))

(defun hs-from-bv (bv)
  (reduce (lm (x y) (concatenate 'string x y))
	  (map-to 'list #'hs-from-by bv)))

(defun hs-from-in (in)
  (hs-from-bv (bv-from-in in)))

(defun hs-from-s (s)
  (hs-from-bv (bv-from-s s)))

;conversion function tests
(ok (equalp (bv-pad #(1 2) 3) #(0 1 2))
    "bv-pad")
(ok (equalp (bv-from-in 258) #(1 2))
    "bv-from-in 1")
(ok (equalp (bv-from-in 123) #(123))
    "bv-from-in 2")
(ok (equalp (bv-from-s "ab") #((char-code #\a) (char-code #\b)))
    "bv-from-s")
(is (in-from-bv #(1 2)) 258)
(is (in-from-hc #\a) 10)
(is (in-from-hs "BC614e") 12345678)
(is (s-from-seq '(#\a #\b #\c #\d #\e #\f)) "abcdef")
(is (s-from-seq #(#\a #\b #\c #\d #\e #\f)) "abcdef")
(is (hs-from-by 255) "ff")
(is (hs-from-bv #(255 0)) "ff00")
(is (s-from-in (+ (* 97 256) 98)) "ab")

;set 1

;1. Convert hex to base64 encoding.  Base64 will be represented as a string in all future cases in this file

(defun mod-remainder (num div)
  (if (= (mod num div) 0)
      0
      (- div (mod num div))))

(defun b64c-from-6bits (n)
  (let ((base64-index "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"))
        (getf base64-index n)))

(defun b64-from-3bytes (bv)
  (let ((len-pad (mod-remainder (length bv) 3)))
    (let ((in-padded (in-from-bv (concatenate 'vector bv (bv-make len-pad))))
	  (s-padding (s-from-bv (bv-make len-pad 61))))
	(loop for offset in '(0 6 12 18)
	   for cur-bits = (ldb (byte 6 offset) in-padded)
	   collecting (b64c-from-6bits cur-bits) into l-res
	   finally (return (concatenate 'string
					(subseq (s-from-seq (nreverse l-res))
						0
						(- 4 len-pad))
					s-padding))))))

(defun b64-from-bv (bv)
  (s-from-seq (map #'b64-from-3bytes (subdivide bv 3))))

(defun b64-from-hs (hs)
  (b64-from-bv (bv-from-hs hs)))

(defun b64-from-s (s)
  (b64-from-bv (bv-from-s s)))

(defun b64-from-in (in)
  (b64-from-bv (bv-from-in in)))

(is (b64-from-s "l pleasure.") "bCBwbGVhc3VyZS4=")

(defun 6bits-from-b64c (b64c)
  (position b64c "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"))

(defun 3bv-from-b64 (b64)
  (let ((len-pad 0))
    (cond ((equalp (getf b64 2) #\=) (setf len-pad 2))
	  ((equalp (getf b64 3) #\=) (setf len-pad 1)))
    (let ((b64-padding (s-make len-pad #\A))
	  (b64-without-pad (subseq b64 0 (- 4 len-pad))))
      (let ((in-total (reduce (lm (high low) (in-combine-bytes high low 6))
			      (map-to 'vector #'6bits-from-b64c (concatenate 'string b64-without-pad b64-padding)))))
	(subseq (bv-pad (bv-from-in in-total) 3) 0 (- 3 len-pad))))))

(defun bv-from-b64 (b64)
  (reduce #'append (map-to 'vector #'3bv-from-b64 (subdivide b64 4))))

(defun in-from-b64 (b64)
  (in-from-bv (bv-from-b64 b64)))

(defun s-from-b64 (b64)
  (s-from-bv (bv-from-b64 b64)))

(defun hs-from-b64 (b64)
  (hs-from-bv (bv-from-b64 b64)))

(defun bv-from-b64-file (file-name)
  (bv-from-b64 (remove #\Newline (remove #\Return (read-file-into-string file-name)))))

(is (b64-from-hs "49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d")
    "SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t")

;2. Fixed XOR

;(int-to-hex-string (hex-string-xor "1c0111001f010100061a024b53535009181c" "686974207468652062756c6c277320657965"))

;output: "746865206b696420646f6e277420706c6179"

(defun bv-xor (bv1 bv2)
  (map-to 'vector #'logxor bv1 bv2))

(defun hs-xor (hs1 hs2)
  (hs-from-bv (bv-xor (bv-from-hs hs1) (bv-from-hs hs2))))

(defun s-xor (s1 s2)
  (s-from-bv (bv-xor (bv-from-s s1) (bv-from-s s2))))

(defun int-xor (&rest ints)
  (apply #'logxor ints))

(is (hs-xor "1c0111001f010100061a024b53535009181c" "686974207468652062756c6c277320657965")
    "746865206b696420646f6e277420706c6179")

;3. Single-character XOR Cipher:

;frequency table derived from http://www.data-compression.com/english.html
(defvar *frequency-table* #H(#\a .0651738 #\b .0124248 #\c .0217339 #\d .0349835 #\e .1041442 #\f .0197881 #\g .0158610 #\h .049288 #\i .0558094 #\j .0009033 #\k .0050529 #\l .0331490 #\m .0202124 #\n .0564513 #\o .0596302 #\p .0137645 #\q .0008606 #\r .0497563 #\s .0515760 #\t .0729357 #\u .0225134 #\v .0082903 #\w .0171272 #\x .0013692 #\y .0145984 #\z .0007836 #\  .1918182 #\newline .01 #\Return .01 #\' .01 #\. .01 #\" .01 #\, .01 #\0 .001 #\1 .001 #\2 .001 #\3 .001 #\4 .001 #\5 .001 #\6 .001 #\7 .001 #\8 .001 #\9 .001))

#|
;frequency table derived from Vanilla Ice lyrics
(defvar *frequency-table* #H(#\! 1/3101 #\1 1/3101 #\0 1/3101 #\. 2/3101 #\5 1/3101 #\z 3/3101 #\q 2/3101 #\j 13/3101 #\- 2/3101 #\x 4/3101 #\u 62/3101 #\? 3/3101 #\f 29/3101 #\m 66/3101 #\w 6/443 #\d 11/443 #\n 137/3101 #\h 109/3101 #\g 51/3101 #\r 78/3101 #\a 204/3101 #\b 76/3101 #\c 107/3101 #\k 47/3101 #\s 110/3101 #\' 33/3101 #\t 173/3101 #\e 257/3101 #\l 151/3101 #\Newline 110/3101 #\p 47/3101 #\i 207/3101 #\v 36/3101 #\  526/3101 #\, 72/3101 #\o 179/3101 #\y 82/3101))
|#

(defun ft-from-string (s)
  (let ((ft #H()))
    (doeach (chr s)
      (inc-hash ft (char-downcase chr)))
    (ft-normalize-hash ft)))

(defun ft-from-file (file)
  (let ((s (read-file-into-string file)))
    (ft-from-string s)))

(defun ft-from-bv (bv)
  (ft-from-string (s-from-bv bv)))

(defun inc-hash (table key)
  (let ((?-exists (nth-value 1 (getf table key))))
    (if ?-exists
        (incf (getf table key))
      (setf (getf table key) 1))))

(defun ft-normalize-hash (ft)
  (let ((sum (reduce #'+ (map-to 'list #'cdr ft))))
    (doeach ((key val) ft)
      (setf (getf ft key) (/ val sum)))
    ft))

(defun fl-frequency-compare (ft-test ft-ref)
  (let ((res 0))
    (doeach ((key val) ft-test res)
      (if (getf ft-ref key)
	  (incf res (expt (abs (- val (getf ft-ref key))) 5))
	  (incf res 100)))))

(defun bv-xor-with-byte (bv by)
  (map (lm (x) (logxor x by)) bv))

(defun xor-crack (bv-ciphertext ft-ref)
  (let ((res (list "default result" 0 1000)))
    (doeach (x (iota 256) res)
      (let ((cand (fl-frequency-compare (ft-from-bv (bv-xor-with-byte bv-ciphertext x))
					ft-ref)))
	(if (< cand (nth res 2))
	    (setf res (list (s-from-bv (bv-xor-with-byte bv-ciphertext x)) x cand)))))))

(is (nth (xor-crack (bv-from-hs "1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736") *frequency-table*) 0)
    "Cooking MC's like a pound of bacon")

;4. Detect single-character XOR

(defun slist-from-file (file-name)
  (let ((s-file (read-file-into-string file-name)))
    (split #\newline s-file)))

(defun xor-find-crack (slist-cipher ft-ref)
  (let ((res (list "default result" 0 1000)) ;must match the layout of the output from xor-crack above
	(slist-plain (map (lm (x) (xor-crack (bv-from-hs x) ft-ref)) slist-cipher)))
    (doeach (x slist-plain res)
      (if (< (nth x 2) (nth res 2))
		 (setf res x)))))

(defun file-xor-find-crack (file-name ft-ref)
  (nth (xor-find-crack (slist-from-file file-name) ft-ref) 0))

(ok (equalp (file-xor-find-crack "/home/adminuser/4.txt" *frequency-table*)
	    "Now that the party is jumping\n")
    "file-xor-find-crack")

;5. Repeating-key XOR Cipher

(defun repeated-key-xor (bv-plain bv-key)
  (let ((bv-split (subdivide bv-plain (length bv-key))))
    (apply #'append (map-to 'list (lm (x) (bv-xor x bv-key)) bv-split))))

(is (hs-from-bv (repeated-key-xor (bv-from-s "Burning 'em, if you ain't quick and nimble I go crazy when I hear a cymbal")
				  (bv-from-s "ICE")))
    "0b3637272a2b2e63622c2e69692a23693a2a3c6324202d623d63343c2a26226324272765272a282b2f20690a652e2c652a3124333a653e2b2027630c692b20283165286326302e27282f")

;6. Break repeating-key XOR:

;(file-xor-crack "c:\\temp\\xor.txt" dict)

;outputs "Terminator X: Bring the noise" as the key, and some terrible vanila ice song as the plain text.

(defun in-bit-distance (in1 in2)
  (expt (logcount (logxor in1 in2)) 1))

(defun fl-bit-distance (bv1 bv2)
  (/ (reduce #'+ (map-to 'vector #'in-bit-distance bv1 bv2))
     (length bv1)))

(is (fl-bit-distance (bv-from-s "this is a test") (bv-from-s "wokka wokka!!!")) 37/14)

(is (fl-bit-distance #(2 4 8) #(3 5 9)) 1)
(is (fl-bit-distance #(2 4) #(3 5)) 1)

(defun map-pairs (fn seq)
  ;todo:  make this a generic function or something, so that the output type matches the
  ;       input type, instead of always outputing a list
  (loop repeat (- (length seq) 1)
     for elem = (first seq) then (first rest)
     for rest = (subseq seq 1) then (subseq rest 1)
     appending (map-to 'list (lm (x) (funcall fn x elem)) rest)))

(is (map-pairs #'+ '(1 2 3 4)) '(3 4 5 5 6 7))
(is (map-pairs #'+ #(1 2 3 4)) '(3 4 5 5 6 7))

(defun fact (in)
  (reduce #'* (iota in :start 1)))

(is (fact 1) 1)
(is (fact 5) 120)

(defun n-choose-r (n r)
  (/ (fact n) (* (fact r) (fact (- n r)))))

(is (n-choose-r 6 2) 15)

(defun lst-xor-block-size (bv-cipher max-size)
  (let ((lens (iota max-size :start 1)))
    (let ((cands (map (lm (x) (xor-block-size-helper bv-cipher x))
		      lens)))
      (take 15 (sort cands (lm (pair1 pair2) (< (cdr pair1) (cdr pair2))))))))

(defun xor-block-size-helper (bv-cipher len)
  (let ((blocks (subdivide bv-cipher len)))
    (cons len
	  (/ (reduce #'+ (map-pairs #'fl-bit-distance blocks))
	     (n-choose-r (length blocks) 2)))))

(defun lst-block-transpose (bv block-len)
  (let ((res '())
	(blocks (subdivide bv block-len)))
    (doeach (i (iota block-len) res)
      (push (map-to 'vector (lm (x) (if (< i (length x)) (elt x i) 0)) blocks) res))
    (nreverse res)))

(ok (equalp (lst-block-transpose #(1 2 3 4 5 6 7 8) 2)
	    (list (vector 1 3 5 7) (vector 2 4 6 8)))
    "lst-block-transpose")

(defun bv-find-repeat-key (bv-cipher)
 (let* ((block-lens (map #'car (lst-xor-block-size bv-cipher 50)))
	(transposes (map (lm (x) (lst-block-transpose bv-cipher x)) block-lens)))
    (let* ((lst-keys (map (lm (transpose) (map-to 'vector (lm (bv) (elt (xor-crack bv *frequency-table*) 1))
						 transpose))
			  transposes))
	   (lst-bvs (map (lm (key) (repeated-key-xor bv-cipher key))
			 lst-keys)))
      (car (sort lst-bvs (lm (bv1 bv2) (< (fl-frequency-compare (ft-from-bv bv1) *frequency-table*)
					  (fl-frequency-compare (ft-from-bv bv2) *frequency-table*))))))))

(defun s-file-find-repeat-key (filename)
  (s-from-bv (bv-find-repeat-key (bv-from-b64-file filename))))

(eval-when (:execute)
  (print (s-file-find-repeat-key "c:\\temp\\xor.txt")))

(eval-when (:execute)
  (print (s-file-find-repeat-key "/home/adminuser/6.txt")))

;7. AES in ECB mode:

(defun bv-AES-encrypt (bv-msg bv-key)
  (let ((bv-res (bv-make (length bv-msg)))
	(cipher (ironclad:make-cipher :AES :mode :ECB :key (coerce bv-key '(vector (unsigned-byte 8))))))
    (ironclad:encrypt cipher (coerce bv-msg '(vector (unsigned-byte 8))) bv-res)
    bv-res))

(defun bv-AES-decrypt (bv-msg bv-key)
  (let ((bv-res (bv-make (length bv-msg)))
	(cipher (ironclad:make-cipher :AES :mode :ECB :key (coerce bv-key '(vector (unsigned-byte 8))))))
    (ironclad:decrypt cipher (coerce bv-msg '(vector (unsigned-byte 8))) bv-res)
    bv-res))

(defun s-AES-encrypt (s-msg s-key)
  (let ((bv-msg (bv-from-s s-msg))
	(bv-key (bv-from-s s-key)))
    (s-from-bv (bv-aes-encrypt bv-msg bv-key))))

(defun s-AES-decrypt (s-msg s-key)
  (let ((bv-msg (bv-from-s s-msg))
	(bv-key (bv-from-s s-key)))
    (s-from-bv (bv-aes-decrypt bv-msg bv-key))))

(defun bv-file-aes-encrypt (file-name bv-key)
  (let ((bv-msg (bv-from-s (read-file-into-string file-name))))
    (bv-aes-encrypt bv-msg bv-key)))

(defun bv-file-aes-decrypt (file-name bv-key)
  (let ((bv-msg (bv-from-s (read-file-into-string file-name))))
    (bv-aes-decrypt bv-msg bv-key)))

(defun s-file-aes-encrypt (file-name s-key)
  (let ((bv-key (bv-from-s s-key)))
    (s-from-bv (bv-file-aes-encrypt file-name bv-key))))

(defun s-file-aes-decrypt (file-name s-key)
  (let ((bv-key (bv-from-s s-key)))
    (s-from-bv (bv-file-aes-decrypt file-name bv-key))))

(eval-when (:execute)
  (print (s-from-bv (bv-aes-decrypt (bv-from-b64-file "/home/adminuser/7.txt") (bv-from-s "YELLOW SUBMARINE")))))

;8. Detect AES in ECB mode

;this is easy.  The only distinguishing fact about ECB is that identical blocks give identical encryption, so look for identical blocks

(defun bv-find-duplicate-blocks (lst-bvs cb-len)
  (let ((lst-blocks (map (lm (bv) (subdivide bv cb-len)) lst-bvs))
	(res #()))
    (doeach (blocks lst-blocks res)
      (if (not (= (reduce #'+ (map-pairs #'fl-bit-distance blocks)) 0))
	  (setf res (apply #'concatenate 'vector blocks))))))

(defun bv-file-find-duplicate-blocks (file-name cb-len)
  (let* ((lst-hs (split #\newline (read-file-into-string file-name)))
	 (lst-bvs (map #'bv-from-hs lst-hs)))
    (bv-find-duplicate-blocks lst-bvs cb-len)))

(eval-when (:execute)
  (print (bv-file-find-duplicate-blocks "/home/adminuser/8.txt" 16)))

;problems from set 2

;9. Implement PKCS#7 padding

(defun bv-pkcs7-pad (bv cb-block-len)
  ;gives a full block of padding for even multiples of the block length
  (let ((cb-padding-len (- cb-block-len (mod (length bv) cb-block-len))))
    (concatenate 'vector bv (make-array cb-padding-len :initial-element cb-padding-len))))

(ok (equalp (bv-pkcs7-pad (bv-from-s "YELLOW SUBMARINE") 20)
	    #(89 69 76 76 79 87 32 83 85 66 77 65 82 73 78 69 4 4 4 4))
    "bv-pkcs7-pad 1")

(ok (equalp (bv-pkcs7-pad (bv-from-s "YELLOW SUBMARINE") 16)
	       #(89 69 76 76 79 87 32 83 85 66 77 65 82 73 78 69 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16))
    "bv-pkcs7-pad 2")

;this is nominally challenge 15, but using it makes #13 easier to implement, so I'm writing it now
(defun bv-pkcs7-unpad (bv cb-block-len)
  ;returns nil for invalid padding
  (iterate (for i from 1)
	   (until (equalp (subseq bv (- (length bv) i)) (bv-make i i)))
	   (until (> i cb-block-len))
	   (finally (if (<= i cb-block-len)
			(return (subseq bv 0 (- (length bv) i)))
			(return 'nil)))))

(ok (equalp (bv-pkcs7-unpad (bv-pkcs7-pad (bv-from-s "YELLOW SUBMARINE") 20) 20)
	    (bv-from-s "YELLOW SUBMARINE"))
    "bv-pkcs7-unpad 1")

(ok (equalp (bv-pkcs7-unpad #(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16) 16)
	    'nil)
    "bv-pkcs7-unpad 2")

(defun bv-aes-pkcs7-encrypt (bv-msg bv-key)
  (bv-aes-encrypt (bv-pkcs7-pad bv-msg 16) bv-key))

(defun bv-aes-pkcs7-decrypt (bv-msg bv-key)
  (bv-aes-decrypt (bv-pkcs7-unpad bv-msg 16) bv-key))

;10. Implement CBC Mode

(defun bv-aes-cbc-encrypt (bv-msg bv-iv bv-key)
  (let* ((bv-padded (bv-pkcs7-pad bv-msg 16))
	 (blocks (subdivide bv-padded 16))
	 (res (iterate (for next in blocks)
		       (for prev previous ctext initially bv-iv)
		       (for ctext = (bv-aes-encrypt (bv-xor prev next) bv-key))
		       (collecting ctext))))
    (apply #'concatenate 'vector res)))

(defun bv-aes-cbc-decrypt (bv-msg bv-iv bv-key)
  (let* ((blocks (subdivide bv-msg 16))
	 (res (iterate (for next in blocks)
		       (for prev previous next initially bv-iv)
		       (collecting (bv-xor (bv-aes-decrypt next bv-key) prev)))))
    (bv-pkcs7-unpad (apply #'concatenate 'vector res) 16)))

(defun bv-file-aes-cbc-encrypt (file-name bv-iv bv-key)
  (let ((bv-msg (bv-from-b64-file file-name)))
    (bv-aes-cbc-encrypt bv-msg bv-iv bv-key)))

(defun s-file-aes-cbc-encrypt (file-name s-iv s-key)
  (let ((bv-iv (bv-from-s s-iv))
	(bv-key (bv-from-s s-key)))
    (s-from-bv (bv-file-aes-cbc-encrypt file-name bv-iv bv-key))))

(defun bv-file-aes-cbc-decrypt (file-name bv-iv bv-key)
  (let ((bv-msg (bv-from-b64-file file-name)))
    (bv-aes-cbc-decrypt bv-msg bv-iv bv-key)))

(defun s-file-aes-cbc-decrypt (file-name s-iv s-key)
  (let ((bv-iv (bv-from-s s-iv))
	(bv-key (bv-from-s s-key)))
    (s-from-bv (bv-file-aes-cbc-decrypt file-name bv-iv bv-key))))

(ok (equalp (let ((bv-msg (bv-make 48 65))
		  (bv-key (bv-rand 16))
		  (bv-iv (bv-rand 16)))
	      (bv-aes-cbc-decrypt (bv-aes-cbc-encrypt bv-msg bv-iv bv-key) bv-iv bv-key))
	    (bv-make 48 65))
    "bv-aes-cbc-encrypt/decrypt")

;11. An ECB/CBC detection oracle

;This is also easy:  just send a long repeated string as input, check for repeats in the output

(defun ch11-oracle (bv-msg)
  (let ((bv-pre-pad (bv-rand (+ 5 (random 6))))
	(bv-post-pad (bv-rand (+ 5 (random 6)))))
    (let ((bv-iv (bv-rand 16))
	  (bv-key (bv-rand 16))
	  (bv-padded (concatenate 'vector bv-pre-pad bv-msg bv-post-pad)))
      (if (= (random 2) 0)
	  (progn (print "cbc")
		 (bv-aes-cbc-encrypt bv-padded bv-iv bv-key))
	  (progn (print "ecb")
		 (bv-aes-encrypt bv-padded bv-key))))))

(defun ?-duplicate-blocks (blocks)
  (some (lm (x) (= x 0)) (map-pairs #'fl-bit-distance blocks)))

(defun ch11-crack ()
  (let* ((bv-msg (bv-make 48 65))
	 (bv-res (coerce (ch11-oracle bv-msg) '(and common-lisp:vector (not simple-array))))
	 (blocks (subdivide bv-res 16)))
    (if (?-duplicate-blocks blocks)
	"ecb"
	"cbc")))

(print (ch11-crack))

;12. Byte-at-a-time ECB decryption (Simple)

(defun ch12-oracle (bv-msg)
  (let ((bv-post-pad (bv-rand (+ 5 (random 6))))
	(bv-secret (bv-from-b64 "Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWctdG9wIGRvd24gc28gbXkgaGFpciBjYW4gYmxvdwpUaGUgZ2lybGllcyBvbiBzdGFuZGJ5IHdhdmluZyBqdXN0IHRvIHNheSBoaQpEaWQgeW91IHN0b3A/IE5vLCBJIGp1c3QgZHJvdmUgYnkK"))
	(bv-key (bv-rand 16)))
    (bv-aes-encrypt (bv-pkcs7-pad (concatenate 'vector bv-msg bv-secret bv-post-pad) 16) bv-key)))

(defun ch12-crack ()
  (let ((bv-res #()))
    (iterate (for i upfrom 1)
	     (for cb-offset = (- 16 (mod i 16)))
	     (for bv-offset = (bv-make cb-offset))
	     (for bv-prefix initially (bv-make 15) then (concatenate 'vector (subseq bv-prefix 1) (vector by-res)))
	     (for by-res = (iterate (for i from 0 to 255)
				    (for bv-msg = (concatenate 'vector bv-prefix (vector i) bv-offset))
				    (for bv-oracle-output = (ch12-oracle bv-msg))
				    (until (?-duplicate-blocks (subdivide bv-oracle-output 16)))
				    (finally (return i))))
	     (until (= by-res 256))
	     (after-each (push by-res bv-res))
	     (finally (return (s-from-bv bv-res))))))

(eval-when (:execute)
  (print (ch12-crack)))

;13.  ECB cut-and-paste

(defun ch13-parse (s-cookie)
  (let* ((s-pairs (split #\& s-cookie))
	 ;map doesn't work here, seems to give a list with slightly incorrect structure
	 (s-keys-vals (iterate (for s in s-pairs)
			       (appending (split #\= s)))))
    (apply #'hash-table #'equal s-keys-vals)))

(defun ch13-make-profile (s-email)
  (let ((s-stripped (remove #\= (remove #\& s-email))))
    #"email=${s-stripped}&uid=10&role=user"))

(is (ch13-make-profile "foo@bar.com") "email=foo@bar.com&uid=10&role=user")

(defun ch13-test (bv-ctext bv-key)
  (let* ((s-cookie (s-from-bv (bv-pkcs7-unpad (bv-aes-decrypt bv-ctext bv-key) 16)))
	 (profile-table (ch13-parse s-cookie)))
    (if (equal (getf profile-table "role") "admin")
	"victory"
	"failure")))

(is (ch13-test (bv-aes-encrypt (bv-pkcs7-pad (bv-from-s "email=foo@bar.com&uid=10&role=admin") 16)
			       (bv-make 16)) (bv-make 16))
    "victory")

(defun ch13-enc-profile (s-email bv-key)
  (bv-aes-pkcs7-encrypt (bv-from-s (ch13-make-profile s-email)) bv-key))

(defun ch13-crack ()
  (let ((bv-key (bv-rand 16)))
    (let ((bv-padding (last (subdivide (ch13-enc-profile "fo@ba.com" bv-key) 16))) ;encryption of 16 16's
	  (bv-email (subseq (ch13-enc-profile "bcobu@foo.com" bv-key) 0 32))
	  (bv-admin (elt (subdivide (ch13-enc-profile "foo@bar.coadmin" bv-key) 16) 1)))
      (ch13-test (concatenate 'vector bv-email bv-admin bv-padding) bv-key))))

(is (ch13-crack)
    "victory")

;14. Byte-at-a-time ECB decryption (Harder)

;this is identical to #12, except that there's an initial step where we find the length of the 'random' prefix
(defvar *ch14-prefix-len* (+ 5 (random 6)))

(defun ch14-oracle (bv-msg)
  (let ((bv-pre-pad (bv-rand *ch14-prefix-len*))
	(bv-post-pad (bv-rand (+ 5 (random 6))))
	(bv-secret (bv-from-b64 "Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWctdG9wIGRvd24gc28gbXkgaGFpciBjYW4gYmxvdwpUaGUgZ2lybGllcyBvbiBzdGFuZGJ5IHdhdmluZyBqdXN0IHRvIHNheSBoaQpEaWQgeW91IHN0b3A/IE5vLCBJIGp1c3QgZHJvdmUgYnkK"))
	(bv-key (bv-rand 16)))
    (bv-aes-encrypt (bv-pkcs7-pad (concatenate 'vector bv-pre-pad bv-msg bv-secret bv-post-pad) 16) bv-key)))

(defun ch14-prefix-len ()
  (iterate (for i from 0 to 16)
	   (for bv-oracle-output = (ch14-oracle (concatenate 'vector (bv-rand i) (bv-make 32))))
	   (until (?-duplicate-blocks (subdivide bv-oracle-output 16)))
	   (finally (return i))))

(defun ch14-crack ()
  (let ((bv-res #())
	(cb-prefix-len (ch14-prefix-len)))
    (iterate (for i upfrom 1)
	     (for cb-offset = (- 16 (mod i 16)))
	     (for bv-offset = (bv-make cb-offset))
	     (for bv-prefix initially (bv-make (+ cb-prefix-len 15)) then (concatenate 'vector (subseq bv-prefix 1) (vector by-res)))
	     (for by-res = (iterate (for i from 0 to 255)
				    (for bv-msg = (concatenate 'vector bv-prefix (vector i) bv-offset))
				    (for bv-oracle-output = (ch14-oracle bv-msg))
				    (until (?-duplicate-blocks (subdivide bv-oracle-output 16)))
				    (finally (return i))))
	     (until (= by-res 256))
	     (after-each (push by-res bv-res))
	     (finally (return (s-from-bv bv-res))))))

(eval-when (:execute)
  (print (ch14-crack)))

;15. PKCS#7 padding validation

;implementing above under #9, because it's used in #13

;16. CBC bitflipping attacks

(defun ch16-encrypt (s-userdata bv-iv bv-key)
  (let ((s-stripped (remove #\= (remove #\; s-userdata)))
	(s-pre "comment1=cooking%20MCs;userdata=")
	(s-post ";comment2=%20like%20a%20pound%20of%20bacon"))
    (let ((bv-msg (bv-from-s (concatenate 'string s-pre s-stripped s-post))))
      (bv-aes-cbc-encrypt bv-msg bv-iv bv-key))))

(defun ch16-check (bv-ctext bv-iv bv-key)
  (let ((s-ptext (s-from-bv (bv-aes-cbc-decrypt bv-ctext bv-iv bv-key))))
    (search";admin=true;" s-ptext)))

(defun ch16-crack ()
  (let* ((bv-userdata (bv-make 16 65))
	 (bv-iv (bv-rand 16))
	 (bv-key (bv-rand 16))
	 (bv-ctext (ch16-encrypt (s-from-bv bv-userdata) bv-iv bv-key))
	 (bv-target (bv-from-s "a;admin=true;aaa"))
	 (bv-edit (bv-xor (bv-xor bv-userdata bv-target) (subseq bv-ctext 16 32))))
    (ch16-check bv-ctext bv-iv bv-key)
    (ch16-check (concatenate 'vector (subseq bv-ctext 0 16) bv-edit (subseq bv-ctext 32))
		bv-iv
		bv-key)))

(ok (ch16-crack) "Challenge 16")

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


Addded some more testing for openc and changes makes files/config

__kernel void cgm_kernel(__global image2d_t *aImg, __global image2d_t *bImg,
						int numElements, int dim,
						int gap, int offset,
						int keyLength, __global uint *matches)
{
	const sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE
								| CLK_ADDRESS_CLAMP_TO_EDGE
								| CLK_FILTER_NEAREST;
	const size_t x = get_global_id (0);
	const size_t y = get_global_id (1);

	int a_x = x%dim;
	int a_y = x/dim;
	int b_x = y%dim;
	int b_y = y/dim;

	const int2 aCoord = (int2)(a_x, a_y);
	const int2 bCoord = (int2)(b_x, b_y);

	int4 a4 = read_imagei(aImg, sampler, aCoord);
	int4 b4 = read_imagei(bImg, sampler, bCoord);

	if(b4.x == a4.x + keyLength + gap)
		matches[x] = a4.x - offset;
	if(b4.y == a4.y + keyLength + gap)
		matches[x] = a4.y - offset;
	if(b4.z == a4.z + keyLength + gap)
		matches[x] = a4.z - offset;
	if(b4.w == a4.w + keyLength + gap)
		matches[x] = a4.w - offset;
	if(b4.x == a4.y + keyLength + gap)
		matches[x] = a4.y - offset;
	if(b4.x == a4.z + keyLength + gap)
		matches[x] = a4.z - offset;
	if(b4.x == a4.w + keyLength + gap)
		matches[x] = a4.w - offset;
	if(b4.y == a4.x + keyLength + gap)
		matches[x] = a4.x - offset;
	if(b4.y == a4.z + keyLength + gap)
		matches[x] = a4.z - offset;
	if(b4.y == a4.w + keyLength + gap)
		matches[x] = a4.w - offset;
	if(b4.z == a4.x + keyLength + gap)
		matches[x] = a4.x - offset;
	if(b4.z == a4.y + keyLength + gap)
		matches[x] = a4.y - offset;
	if(b4.z == a4.w + keyLength + gap)
		matches[x] = a4.w - offset;
	if(b4.w == a4.x + keyLength + gap)
		matches[x] = a4.x - offset;
	if(b4.w == a4.y + keyLength + gap)
		matches[x] = a4.y - offset;
	if(b4.w == a4.z + keyLength + gap)
		matches[x] = a4.z - offset;
}

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


OpenCL implementation of constant "PRNG"

/******************************************************************************
 * @file     prngcl_constant.cl
 * @author   Vadim Demchik <vadimdi@yahoo.com>
 * @version  1.1
 *
 * @brief    [PRNGCL library]
 *           contains OpenCL implementation of constant "pseudo-random number generator",
 *           which produces series of constant values for debugging purposes
 *
 *
 * @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_CONSTANT_CL
#define PRNGCL_CONSTANT_CL

#include "prngcl_common.cl"

/**
 * generates the series of constant values predefined by CONSTANT_FP parameter
 * @param randoms output buffer for generated PRNs
 * @param N number of PRNs to be produced
 */
__kernel void
constant_series(__global hgpu_float4* randoms,
                const uint N)
{
    uint giddst = GID;
        for (uint i = 0; i < N; i++) {
        randoms[giddst] = (hgpu_float4) CONSTANT_FP;
        giddst += GID_SIZE;
    }
}

#endif

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


Fixed screen coordinate calculation. Flat spheres can now be rendered

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/emr4378/GPU-Ray-Tracer.git/'


nothing too

nothing too

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


Tenative cl for nnz count without atomic_lock

__kernel void m_mul_m_count(
          __global const unsigned int * row_indices_a,
          __global const unsigned int * column_indices_a,
          __global const unsigned int * row_indices_b,
          __global const unsigned int * column_indices_b,
          __global unsigned int * resultBig,
          const uint work_per_item)
{
	// Offset di moltiplicazione per riga ( tutta la computazione dei moduli sull'host)
	unsigned int row_start = get_local_id(0) * work_per_item;
	unsigned int row_stop  = min( (uint) ((get_local_id(0) + 1) * work_per_item), (uint) ROWSIZE);

  	// Shortcut al risultato
	__global unsigned char * result = resultBig + get_group_id(0) * row_start;

	// Variabili riutilizzabili
	unsigned int row_a;
	unsigned int row_b;
	unsigned int nnz_row;

	unsigned int col_ptr_a;
	unsigned int col_ptr_end_a;
	unsigned int col_ptr_b;
	unsigned int col_ptr_end_b;
  	unsigned int col_val_a;
  	unsigned int col_val_b;

	// Inizia computazione
	for (row_a = (row_start * get_group_id(0)); row_a < (row_stop * get_group_id(0)); ++row_a) {
  		nnz_row = 0;
		col_ptr_end_a = row_indices_a[row_a + 1];

		// copia in loacal cache tutta la riga cosi' da evitare di rileggere dalla mem.globale

   		// questo for deve essere scalato, ogni wi parte da una riga diversa e gira
   		// evita serializzazione d'accesso alla memoria
   		// qualcosa tipo row_b = get_global_id; row_b < ROWS_B + get_global_id
   		// (rowb + x) % ROWS_B, se ROWS_B è potenza di 2 è pure meglio
		for(unsigned int row_b = 0; row_b < ROWS_B; ++row_b) {
			col_ptr_end_b = row_indices_b[row_b + 1];

			// While variables
			col_ptr_a = row_indices_a[row_a];
			col_ptr_b = row_indices_b[row_b];

			while ((col_ptr_a < col_ptr_end_a) && (col_ptr_b < col_ptr_end_b)) {

				col_val_a = column_indices_a[col_ptr_a];
				col_val_b = column_indices_b[col_ptr_b];

				if (col_val_a == col_val_b) {
					nnz_row = nnz_row + 1;
				} else if ( col_val_a < col_val_b) {
					col_ptr_a++;
				} else {
					col_ptr_b++;
				}
			}
		}

		result[ row ] = nnz_row;
	}

	// Alla fine mi ritrovo l'array da dare in pasto alla prefix sum
}

error: pathspec 'src/main/resources/it/cvdlab/lar/pipeline/kernelwrap/experimental/csr_run_1.cl' did not match any file(s) known to git


added missing reference kernel

added missing reference kernel

kernel void calculate(__global double* var2_global, int var2_rows, int var2_view, __global double* var3_global, int var3_rows, int var3_view, const int rows, const int cols){
const int gid_i = get_global_id(0);
const int gid_j = get_global_id(1);
const int lid_i = get_local_id(0);
const int lsize_i = get_local_size(0);
const int gsize_i = get_global_size(0);
const int gsize_j = get_global_size(1);
const int wg_id_i = get_group_id(0);
const int wg_id_j = get_group_id(1);
const int n_groups_i = get_num_groups(0);
__local double var1_local[LOCAL_SIZE_];
double var1 = 0;
for(int j = gid_j; j < cols; j+=gsize_j){
for(int i = gid_i; i < rows; i+=gsize_i){
double var2 = 0; if (!((!contains_nonzero(var2_view, LOWER) && j < i) || (!contains_nonzero(var2_view, UPPER) && j > i))) {var2 = var2_global[i + var2_rows * j];}
var1 = var1 + var2;
}
}
var1_local[lid_i] = var1;
barrier(CLK_LOCAL_MEM_FENCE);
for (int step = lsize_i / REDUCTION_STEP_SIZE; step > 0; step /= REDUCTION_STEP_SIZE) {
  if (lid_i < step) {
    for (int i = 1; i < REDUCTION_STEP_SIZE; i++) {
      var1_local[lid_i] = var1_local[lid_i] + var1_local[lid_i + step * i];
    }
  }
  barrier(CLK_LOCAL_MEM_FENCE);
}
if (lid_i == 0) {
var3_global[wg_id_j * n_groups_i + wg_id_i] = var1_local[0];
}
}

error: pathspec 'test/unit/math/opencl/kernel_generator/reference_kernels/sum_2d.cl' did not match any file(s) known to git


untested OpenCL C rgbToLab

untested OpenCL C rgbToLab

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/drones-for-ag/treecount.git/'


Delete collatzGlide.cl

Delete collatzGlide.cl

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/SosirisTseng/collatz-opencl.git/'


Initial version.  Originally mem.cl.

Initial version.  Originally mem.cl.

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

//#include <OpenCL/opencl.h>

#include <stdio.h>

//
// simple compute kernel
//

//
//// 4. change if () guard so that it uses kx and ky

__kernel void bandwidth (
    __global float * V,
    __global float * G_E,
    __global float * phiExc,
    __global float * G_I,
    __global float * phiInh,
    __global float * G_IB,
    __global float * phiInhB,
    const uint nx,
    const uint ny,
    const uint nPad)
{
   float tauInf, VmemInf;
   float expExcite, expInhib, expInhibB;
   float dt, tau;
   float Vrest, Vexc, Vinh, VinhB;

   //ADD DT, HARD CODE IN VARIABLES, FIX stuff, implement and check by hand, and check boundaries

   const uint kx = get_global_id(0);
   const uint ky = get_global_id(1);
   const uint k  = kx + nx*ky;

   float one = 1.1f;

   VmemInf = 20.0f;
   //tauInf = 3.141f;

   //Hard Coded Variables
   tau = 20.0;
   Vrest = -70.0;
   Vexc = 0.0;
   Vinh = -75.0;
   VinhB = -90.0;

   dt = 1.0f;
   tau = 1.0f;
   Vrest = 2.0f;
   Vexc = 2.0f;
   Vinh = 2.0f;
   VinhB = 2.0f;

   expExcite = 1.0f;
   expInhib = 2.0f;
   expInhibB = 2.0f;

   if (kx < 4096 && ky < 4096) {         //(k < nx*ny) {
      //printf ("%f %f %f\n", kx, ky, k);
      G_E[k]  = 1 + G_E[k] ;phiExc[k] + G_E[k]  * expExcite;
      G_I[k]  = phiInh[k]; //phiInh[k] + G_I[k]  * expInhib;
      G_IB[k] = phiInhB[k] + G_IB[k] * expInhibB;
      tauInf  = (dt / tau) * (1 + G_E[k] + G_I[k] + G_IB[k]);
      VmemInf = ( Vrest + G_E[k] * Vexc + G_I[k] * Vinh + G_IB[k] * VinhB )
                / (1.0 + G_E[k] + G_I[k] + G_IB[k]);
      V[k] = VmemInf + (V[k] - VmemInf) * exp(-tauInf);

      //printf("G_I[%d]=%f\n", k, G_I[k]);
      //printf("kx=%f\n", kx);
      //printf("nx=%f\n", nx);

//      V[k] = 8.0f;
   }
}

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


correctly barrier async_work_group_copy

correctly barrier async_work_group_copy

//============================================================================
// vSMC/example/gmm/gmm_smc_cl.cl
//----------------------------------------------------------------------------
//                         vSMC: Scalable Monte Carlo
//----------------------------------------------------------------------------
// Copyright (c) 2013,2014, Yan Zhou
// 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.
//============================================================================

#include <vsmc/rng/normal01.h>

typedef struct {
    fp_type mu[CompNum];
    fp_type lambda[CompNum];
    fp_type weight[CompNum];
    fp_type log_prior;
    fp_type log_likelihood;
    fp_type log_target;
} gmm_param;

VSMC_STATIC_INLINE fp_type log_prior (gmm_param *pparam,
        fp_type mu0, fp_type sd0, fp_type shape0, fp_type scale0)
{
    fp_type lp = 0;
    for (uint d = 0; d != CompNum; ++d) {
        fp_type resid = pparam->mu[d] - mu0;
        lp += -0.5F * (resid * resid) / (sd0 * sd0);
        lp += (shape0 - 1) * log(pparam->lambda[d]) -
            pparam->lambda[d] / scale0;
    }

    return pparam->log_prior = lp;
}

VSMC_STATIC_INLINE fp_type log_likelihood (gmm_param *pparam,
        __local const fp_type *obs)
{
    fp_type log_lambda[CompNum];
    for (uint d = 0; d != CompNum; ++d)
        log_lambda[d] = log(pparam->lambda[d]);

    const fp_type hlf = 0.5;
    const fp_type drift = 1e-13;

    fp_type ll = 0;
    for (uint i = 0; i != DataNum; ++i) {
        fp_type lli = 0;
        for (uint d = 0; d != CompNum; ++d) {
            fp_type resid = obs[i] - pparam->mu[d];
            lli += pparam->weight[d] * exp(hlf * log_lambda[d]
                    - hlf * pparam->lambda[d] * resid * resid);
        }
        ll += log(lli + drift);
    }

    return pparam->log_likelihood = ll;
}

VSMC_STATIC_INLINE fp_type log_target (gmm_param *pparam,
        __local const fp_type *obs, fp_type alpha,
        fp_type mu0, fp_type sd0, fp_type shape0, fp_type scale0)
{
    fp_type lt = log_prior(pparam, mu0, sd0, shape0, scale0) +
        alpha * log_likelihood(pparam, obs);

    return pparam->log_target = lt;
}

__kernel
void query_size (__global uint *sizes)
{
    if (!get_global_id(0)) {
        gmm_param gmm_param_array[2];
        sizes[0] = sizeof(gmm_param);
        sizes[1] = 2;
        sizes[2] = sizeof(gmm_param_array);
    }
}

__kernel
void gmm_init (__global gmm_param *state, __global ulong *accept,
        __global const fp_type *lambda_host,
        __global const fp_type *weight_host,
        __global const fp_type *dat, __local fp_type *obs,
        fp_type mu0, fp_type sd0, fp_type shape0, fp_type scale0,
        __global struct r123array4x32 *counter)
{
    size_type id = get_global_id(0);
    if (id >= Size)
        return;

    gmm_param param  = state[id];

    cburng4x32_rng_t rng;
    cburng4x32_init(&rng, Seed + id);
    NORMAL01_4x32 rnorm;
    NORMAL01_4x32_INIT(&rnorm, &rng);

    for (uint d = 0; d != CompNum; ++d) {
        param.mu[d] =  mu0 + NORMAL01_4x32_RAND(&rnorm, &rng) * sd0;
        param.lambda[d] = lambda_host[d * Size + id];
        param.weight[d] = weight_host[d * Size + id];
    }

    barrier(CLK_LOCAL_MEM_FENCE);
    async_work_group_copy(obs, dat, DataNum, 0);
    barrier(CLK_LOCAL_MEM_FENCE);
    log_target(&param, obs, 0, mu0, sd0, shape0, scale0);
    state[id] = param;
    accept[id] = 0;
    counter[id] = rng.ctr;
}

__kernel
void gmm_move_smc (ulong iter,
        __global gmm_param *state, __global ulong *accept,
        __global fp_type *inc_weight, fp_type alpha_inc)
{
    size_type id = get_global_id(0);
    if (id >= Size)
        return;

    inc_weight[id] = alpha_inc * state[id].log_likelihood;
    accept[id] = 0;
}

__kernel
void gmm_move_mu (ulong iter,
        __global gmm_param *state, __global ulong *accept,
        __global const fp_type *dat, __local fp_type *obs,
        fp_type alpha, fp_type sd,
        fp_type mu0, fp_type sd0, fp_type shape0, fp_type scale0,
        __global struct r123array4x32 *counter)
{
    size_type id = get_global_id(0);
    if (id >= Size)
        return;

    gmm_param param = state[id];
    fp_type mu_old[CompNum];
    for (uint d = 0; d != CompNum; ++d)
        mu_old[d] = param.mu[d];
    const fp_type log_prior_old = param.log_prior;
    const fp_type log_likelihood_old = param.log_likelihood;
    const fp_type log_target_old =
        param.log_prior + alpha * param.log_likelihood;

    cburng4x32_rng_t rng;
    cburng4x32_init(&rng, Seed + id);
    rng.ctr = counter[id];
    NORMAL01_4x32 rnorm;
    NORMAL01_4x32_INIT(&rnorm, &rng);

    for (uint d = 0; d != CompNum; ++d)
        param.mu[d] += NORMAL01_4x32_RAND(&rnorm, &rng) * sd;

    barrier(CLK_LOCAL_MEM_FENCE);
    async_work_group_copy(obs, dat, DataNum, 0);
    barrier(CLK_LOCAL_MEM_FENCE);
    log_target(&param, obs, alpha, mu0, sd0, shape0, scale0);
    fp_type p = param.log_target - log_target_old;
    fp_type u = log(U01_OPEN_CLOSED_32(cburng4x32_rand(&rng)));
    ulong acc = 1;
    if (p < u) {
        for (uint d = 0; d != CompNum; ++d)
            param.mu[d] = mu_old[d];
        param.log_prior      = log_prior_old;
        param.log_likelihood = log_likelihood_old;
        param.log_target     = log_target_old;
        acc = 0;
    }

    state[id] = param;
    accept[id] = acc;
    counter[id] = rng.ctr;
}

__kernel
void gmm_move_lambda (ulong iter,
        __global gmm_param *state, __global ulong *accept,
        __global const fp_type *dat, __local fp_type *obs,
        fp_type alpha, fp_type sd,
        fp_type mu0, fp_type sd0, fp_type shape0, fp_type scale0,
        __global struct r123array4x32 *counter)
{
    size_type id = get_global_id(0);
    if (id >= Size)
        return;

    gmm_param param = state[id];
    fp_type lambda_old[CompNum];
    for (uint d = 0; d != CompNum; ++d)
        lambda_old[d] = param.lambda[d];
    const fp_type log_prior_old = param.log_prior;
    const fp_type log_likelihood_old = param.log_likelihood;
    const fp_type log_target_old =
        param.log_prior + alpha * param.log_likelihood;

    cburng4x32_rng_t rng;
    cburng4x32_init(&rng, Seed + id);
    rng.ctr = counter[id];
    NORMAL01_4x32 rnorm;
    NORMAL01_4x32_INIT(&rnorm, &rng);

    for (uint d = 0; d != CompNum; ++d)
        param.lambda[d] *= exp(NORMAL01_4x32_RAND(&rnorm, &rng) * sd);

    barrier(CLK_LOCAL_MEM_FENCE);
    async_work_group_copy(obs, dat, DataNum, 0);
    barrier(CLK_LOCAL_MEM_FENCE);
    log_target(&param, obs, alpha, mu0, sd0, shape0, scale0);
    fp_type p = param.log_target - log_target_old;
    for (uint d = 0; d != CompNum; ++d)
        p += log(param.lambda[d]) - log(lambda_old[d]);
    fp_type u = log(U01_OPEN_CLOSED_32(cburng4x32_rand(&rng)));
    ulong acc = 1;
    if (p < u) {
        for (uint d = 0; d != CompNum; ++d)
            param.lambda[d] = lambda_old[d];
        param.log_prior      = log_prior_old;
        param.log_likelihood = log_likelihood_old;
        param.log_target     = log_target_old;
        acc = 0;
    }

    state[id] = param;
    accept[id] = acc;
    counter[id] = rng.ctr;
}

__kernel
void gmm_move_weight (ulong iter,
        __global gmm_param *state, __global ulong *accept,
        __global const fp_type *dat, __local fp_type *obs,
        fp_type alpha, fp_type sd,
        fp_type mu0, fp_type sd0, fp_type shape0, fp_type scale0,
        __global struct r123array4x32 *counter)
{
    size_type id = get_global_id(0);
    if (id >= Size)
        return;

    gmm_param param = state[id];
    fp_type weight_old[CompNum];
    for (uint d = 0; d != CompNum; ++d)
        weight_old[d] = param.weight[d];
    const fp_type log_prior_old = param.log_prior;
    const fp_type log_likelihood_old = param.log_likelihood;
    const fp_type log_target_old =
        param.log_prior + alpha * param.log_likelihood;

    cburng4x32_rng_t rng;
    cburng4x32_init(&rng, Seed + id);
    rng.ctr = counter[id];
    NORMAL01_4x32 rnorm;
    NORMAL01_4x32_INIT(&rnorm, &rng);

    fp_type sum_weight = 1;
    for (uint d = 0; d != CompNum - 1; ++d) {
        param.weight[d] = log(param.weight[d] / param.weight[CompNum - 1]);
        param.weight[d] += NORMAL01_4x32_RAND(&rnorm, &rng) * sd;
        param.weight[d] = exp(param.weight[d]);
        sum_weight += param.weight[d];
    }
    param.weight[CompNum - 1] = 1;
    for (unsigned d = 0; d != CompNum; ++d)
        param.weight[d] /= sum_weight;

    fp_type sum_lw, sum_llw;

    sum_lw = 1;
    sum_llw = 0;
    for (unsigned d = 0; d != CompNum - 1; ++d) {
        fp_type w = param.weight[d] / param.weight[CompNum - 1];
        sum_lw += w;
        sum_llw += log(w);
    }
    sum_llw -= CompNum * log(sum_lw);
    fp_type lp = sum_llw;

    sum_lw = 1;
    sum_llw = 0;
    for (unsigned d = 0; d != CompNum - 1; ++d) {
        fp_type w = weight_old[d] / weight_old[CompNum - 1];
        sum_lw += w;
        sum_llw += log(w);
    }
    sum_llw -= CompNum * log(sum_lw);
    fp_type lp_old = sum_llw;

    barrier(CLK_LOCAL_MEM_FENCE);
    async_work_group_copy(obs, dat, DataNum, 0);
    barrier(CLK_LOCAL_MEM_FENCE);
    log_target(&param, obs, alpha, mu0, sd0, shape0, scale0);
    fp_type p = param.log_target - log_target_old + lp - lp_old;
    fp_type u = log(U01_OPEN_CLOSED_32(cburng4x32_rand(&rng)));
    ulong acc = 1;
    if (p < u) {
        for (uint d = 0; d != CompNum; ++d)
            param.weight[d] = weight_old[d];
        param.log_prior      = log_prior_old;
        param.log_likelihood = log_likelihood_old;
        param.log_target     = log_target_old;
        acc = 0;
    }

    state[id] = param;
    accept[id] = acc;
    counter[id] = rng.ctr;
}

__kernel
void gmm_path_state (ulong iter, __global gmm_param *state,
        __global fp_type *res)
{
    size_type id = get_global_id(0);
    if (id >= Size)
        return;

    res[id] = state[id].log_likelihood;
}

//============================================================================
// vSMC/example/gmm/gmm_smc_cl.cl
//----------------------------------------------------------------------------
//                         vSMC: Scalable Monte Carlo
//----------------------------------------------------------------------------
// Copyright (c) 2013,2014, Yan Zhou
// 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.
//============================================================================

#include <vsmc/rng/normal01.h>

typedef struct {
    fp_type mu[CompNum];
    fp_type lambda[CompNum];
    fp_type weight[CompNum];
    fp_type log_prior;
    fp_type log_likelihood;
    fp_type log_target;
} gmm_param;

VSMC_STATIC_INLINE fp_type log_prior (gmm_param *pparam,
        fp_type mu0, fp_type sd0, fp_type shape0, fp_type scale0)
{
    fp_type lp = 0;
    for (uint d = 0; d != CompNum; ++d) {
        fp_type resid = pparam->mu[d] - mu0;
        lp += -0.5F * (resid * resid) / (sd0 * sd0);
        lp += (shape0 - 1) * log(pparam->lambda[d]) -
            pparam->lambda[d] / scale0;
    }

    return pparam->log_prior = lp;
}

VSMC_STATIC_INLINE fp_type log_likelihood (gmm_param *pparam,
        __local const fp_type *obs)
{
    fp_type log_lambda[CompNum];
    for (uint d = 0; d != CompNum; ++d)
        log_lambda[d] = log(pparam->lambda[d]);

    const fp_type hlf = 0.5;
    const fp_type drift = 1e-13;

    fp_type ll = 0;
    for (uint i = 0; i != DataNum; ++i) {
        fp_type lli = 0;
        for (uint d = 0; d != CompNum; ++d) {
            fp_type resid = obs[i] - pparam->mu[d];
            lli += pparam->weight[d] * exp(hlf * log_lambda[d]
                    - hlf * pparam->lambda[d] * resid * resid);
        }
        ll += log(lli + drift);
    }

    return pparam->log_likelihood = ll;
}

VSMC_STATIC_INLINE fp_type log_target (gmm_param *pparam,
        __local const fp_type *obs, fp_type alpha,
        fp_type mu0, fp_type sd0, fp_type shape0, fp_type scale0)
{
    fp_type lt = log_prior(pparam, mu0, sd0, shape0, scale0) +
        alpha * log_likelihood(pparam, obs);

    return pparam->log_target = lt;
}

__kernel
void query_size (__global uint *sizes)
{
    if (!get_global_id(0)) {
        gmm_param gmm_param_array[2];
        sizes[0] = sizeof(gmm_param);
        sizes[1] = 2;
        sizes[2] = sizeof(gmm_param_array);
    }
}

__kernel
void gmm_init (__global gmm_param *state, __global ulong *accept,
        __global const fp_type *lambda_host,
        __global const fp_type *weight_host,
        __global const fp_type *dat, __local fp_type *obs,
        fp_type mu0, fp_type sd0, fp_type shape0, fp_type scale0,
        __global struct r123array4x32 *counter)
{
    size_type id = get_global_id(0);
    if (id >= Size)
        return;

    gmm_param param  = state[id];

    cburng4x32_rng_t rng;
    cburng4x32_init(&rng, Seed + id);
    NORMAL01_4x32 rnorm;
    NORMAL01_4x32_INIT(&rnorm, &rng);

    for (uint d = 0; d != CompNum; ++d) {
        param.mu[d] =  mu0 + NORMAL01_4x32_RAND(&rnorm, &rng) * sd0;
        param.lambda[d] = lambda_host[d * Size + id];
        param.weight[d] = weight_host[d * Size + id];
    }

    async_work_group_copy(obs, dat, DataNum, 0);
    mem_fence(CLK_LOCAL_MEM_FENCE);
    log_target(&param, obs, 0, mu0, sd0, shape0, scale0);
    state[id] = param;
    accept[id] = 0;
    counter[id] = rng.ctr;
}

__kernel
void gmm_move_smc (ulong iter,
        __global gmm_param *state, __global ulong *accept,
        __global fp_type *inc_weight, fp_type alpha_inc)
{
    size_type id = get_global_id(0);
    if (id >= Size)
        return;

    inc_weight[id] = alpha_inc * state[id].log_likelihood;
    accept[id] = 0;
}

__kernel
void gmm_move_mu (ulong iter,
        __global gmm_param *state, __global ulong *accept,
        __global const fp_type *dat, __local fp_type *obs,
        fp_type alpha, fp_type sd,
        fp_type mu0, fp_type sd0, fp_type shape0, fp_type scale0,
        __global struct r123array4x32 *counter)
{
    size_type id = get_global_id(0);
    if (id >= Size)
        return;

    gmm_param param = state[id];
    fp_type mu_old[CompNum];
    for (uint d = 0; d != CompNum; ++d)
        mu_old[d] = param.mu[d];
    const fp_type log_prior_old = param.log_prior;
    const fp_type log_likelihood_old = param.log_likelihood;
    const fp_type log_target_old =
        param.log_prior + alpha * param.log_likelihood;

    cburng4x32_rng_t rng;
    cburng4x32_init(&rng, Seed + id);
    rng.ctr = counter[id];
    NORMAL01_4x32 rnorm;
    NORMAL01_4x32_INIT(&rnorm, &rng);

    for (uint d = 0; d != CompNum; ++d)
        param.mu[d] += NORMAL01_4x32_RAND(&rnorm, &rng) * sd;

    async_work_group_copy(obs, dat, DataNum, 0);
    mem_fence(CLK_LOCAL_MEM_FENCE);
    log_target(&param, obs, alpha, mu0, sd0, shape0, scale0);
    fp_type p = param.log_target - log_target_old;
    fp_type u = log(U01_OPEN_CLOSED_32(cburng4x32_rand(&rng)));
    ulong acc = 1;
    if (p < u) {
        for (uint d = 0; d != CompNum; ++d)
            param.mu[d] = mu_old[d];
        param.log_prior      = log_prior_old;
        param.log_likelihood = log_likelihood_old;
        param.log_target     = log_target_old;
        acc = 0;
    }

    state[id] = param;
    accept[id] = acc;
    counter[id] = rng.ctr;
}

__kernel
void gmm_move_lambda (ulong iter,
        __global gmm_param *state, __global ulong *accept,
        __global const fp_type *dat, __local fp_type *obs,
        fp_type alpha, fp_type sd,
        fp_type mu0, fp_type sd0, fp_type shape0, fp_type scale0,
        __global struct r123array4x32 *counter)
{
    size_type id = get_global_id(0);
    if (id >= Size)
        return;

    gmm_param param = state[id];
    fp_type lambda_old[CompNum];
    for (uint d = 0; d != CompNum; ++d)
        lambda_old[d] = param.lambda[d];
    const fp_type log_prior_old = param.log_prior;
    const fp_type log_likelihood_old = param.log_likelihood;
    const fp_type log_target_old =
        param.log_prior + alpha * param.log_likelihood;

    cburng4x32_rng_t rng;
    cburng4x32_init(&rng, Seed + id);
    rng.ctr = counter[id];
    NORMAL01_4x32 rnorm;
    NORMAL01_4x32_INIT(&rnorm, &rng);

    for (uint d = 0; d != CompNum; ++d)
        param.lambda[d] *= exp(NORMAL01_4x32_RAND(&rnorm, &rng) * sd);

    async_work_group_copy(obs, dat, DataNum, 0);
    mem_fence(CLK_LOCAL_MEM_FENCE);
    log_target(&param, obs, alpha, mu0, sd0, shape0, scale0);
    fp_type p = param.log_target - log_target_old;
    for (uint d = 0; d != CompNum; ++d)
        p += log(param.lambda[d]) - log(lambda_old[d]);
    fp_type u = log(U01_OPEN_CLOSED_32(cburng4x32_rand(&rng)));
    ulong acc = 1;
    if (p < u) {
        for (uint d = 0; d != CompNum; ++d)
            param.lambda[d] = lambda_old[d];
        param.log_prior      = log_prior_old;
        param.log_likelihood = log_likelihood_old;
        param.log_target     = log_target_old;
        acc = 0;
    }

    state[id] = param;
    accept[id] = acc;
    counter[id] = rng.ctr;
}

__kernel
void gmm_move_weight (ulong iter,
        __global gmm_param *state, __global ulong *accept,
        __global const fp_type *dat, __local fp_type *obs,
        fp_type alpha, fp_type sd,
        fp_type mu0, fp_type sd0, fp_type shape0, fp_type scale0,
        __global struct r123array4x32 *counter)
{
    size_type id = get_global_id(0);
    if (id >= Size)
        return;

    gmm_param param = state[id];
    fp_type weight_old[CompNum];
    for (uint d = 0; d != CompNum; ++d)
        weight_old[d] = param.weight[d];
    const fp_type log_prior_old = param.log_prior;
    const fp_type log_likelihood_old = param.log_likelihood;
    const fp_type log_target_old =
        param.log_prior + alpha * param.log_likelihood;

    cburng4x32_rng_t rng;
    cburng4x32_init(&rng, Seed + id);
    rng.ctr = counter[id];
    NORMAL01_4x32 rnorm;
    NORMAL01_4x32_INIT(&rnorm, &rng);

    fp_type sum_weight = 1;
    for (uint d = 0; d != CompNum - 1; ++d) {
        param.weight[d] = log(param.weight[d] / param.weight[CompNum - 1]);
        param.weight[d] += NORMAL01_4x32_RAND(&rnorm, &rng) * sd;
        param.weight[d] = exp(param.weight[d]);
        sum_weight += param.weight[d];
    }
    param.weight[CompNum - 1] = 1;
    for (unsigned d = 0; d != CompNum; ++d)
        param.weight[d] /= sum_weight;

    fp_type sum_lw, sum_llw;

    sum_lw = 1;
    sum_llw = 0;
    for (unsigned d = 0; d != CompNum - 1; ++d) {
        fp_type w = param.weight[d] / param.weight[CompNum - 1];
        sum_lw += w;
        sum_llw += log(w);
    }
    sum_llw -= CompNum * log(sum_lw);
    fp_type lp = sum_llw;

    sum_lw = 1;
    sum_llw = 0;
    for (unsigned d = 0; d != CompNum - 1; ++d) {
        fp_type w = weight_old[d] / weight_old[CompNum - 1];
        sum_lw += w;
        sum_llw += log(w);
    }
    sum_llw -= CompNum * log(sum_lw);
    fp_type lp_old = sum_llw;

    async_work_group_copy(obs, dat, DataNum, 0);
    mem_fence(CLK_LOCAL_MEM_FENCE);
    log_target(&param, obs, alpha, mu0, sd0, shape0, scale0);
    fp_type p = param.log_target - log_target_old + lp - lp_old;
    fp_type u = log(U01_OPEN_CLOSED_32(cburng4x32_rand(&rng)));
    ulong acc = 1;
    if (p < u) {
        for (uint d = 0; d != CompNum; ++d)
            param.weight[d] = weight_old[d];
        param.log_prior      = log_prior_old;
        param.log_likelihood = log_likelihood_old;
        param.log_target     = log_target_old;
        acc = 0;
    }

    state[id] = param;
    accept[id] = acc;
    counter[id] = rng.ctr;
}

__kernel
void gmm_path_state (ulong iter, __global gmm_param *state,
        __global fp_type *res)
{
    size_type id = get_global_id(0);
    if (id >= Size)
        return;

    res[id] = state[id].log_likelihood;
}


Example of a convolution running on a CPU.

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

#undef DEBUG_PRINT

#ifdef DEBUG_PRINT
#  include <stdio.h>
#endif

//
// Simple compute kernel that computes a convolution over an input array
//
__kernel void convolve_cpu (
    __global float * idata,
    __global float * odata,
    const unsigned int nxGlobal,
    const unsigned int nyGlobal,
    const unsigned int nPad,
    __local float * ldata_ex)
{
   const unsigned int kx = get_global_id(0);
   const unsigned int ky = get_global_id(1);
   const unsigned int k  = kx + ky*nxGlobal;

   const unsigned int kex = (kx + nPad) + (ky + nPad)*(nxGlobal + 2*nPad);

   // perform convolution
   //
   if (k < nxGlobal*nyGlobal) {
      float sum = 0.0f;
      const int sy = nxGlobal + 2*nPad;

      for (int i = 0; i < 3; i++) {
         int offset = (i-1)*sy;
         sum += 1.1f*idata[kex+offset-1] + 2.1f*idata[kex+offset] + 3.1f*idata[kex+offset+1];
      }
      odata[k] = sum;
   }

#ifdef DEBUG_PRINT
   if (ky == 4) {
      printf("idata[%d]==%f odata[%d]==%f k==%d kx==%d ky==%d\n",
             k, idata[k], k, odata[k], k, get_global_id(0), get_global_id(1));
   }

   if (k == 0) {
      printf("    local_idx==%d local_idy==%d\n", get_local_id(0), get_local_id(1));
      printf("    global_idx==%d global_idy==%d\n", get_global_id(0), get_global_id(1));
	  float4 o4 = f4[0] + f4[0];
	 // printf("odata[%d]==%f %f %f %f\n", k, o4.x, o4.y, o4.z, o4.w);
	  printf("ldata[%d]==%f idata==%f\n", k, ldata_ex[0], idata[k]);
   }
#endif

}

error: pathspec 'src/arch/opencl/convolve_cpu.cl' did not match any file(s) known to git