Trouble understanding statement order in Chisel - hdl

Here is a simple module containing a down counter:
import chisel3.util.{Valid, DeqIO}
class Input(WIDTH : Int) extends Bundle {
val x = UInt(WIDTH.W)
}
class Output(WIDTH : Int) extends Bundle {
val y = UInt(WIDTH.W)
}
class DownCount(WIDTH : Int) extends Module {
val io = IO(new Bundle {
val in = DeqIO(new Input(WIDTH))
val out = Output(Valid(new Output(WIDTH)))
})
val i = Reg(UInt(WIDTH.W))
val p = RegInit(false.B)
printf("i = %d, p = %b, out.valid = %b\n",
i, p, io.out.valid)
io.in.ready := !p
io.out.valid := false.B
io.out.bits.y := 10.U
when (p) {
i := i - 1.U
when (i === 0.U) {
printf("Before setting out.valid = %b\n", io.out.valid)
p := false.B
// Here the register is set to 1.
io.out.valid := true.B
}
}.otherwise {
when (io.in.valid) {
printf("Initializing\n")
i := WIDTH.U - 1.U
p := true.B
}
}
}
Here is the output after applying the clock.step() function on the module a few times:
i = 0, p = 0, out.valid = 0
Initializing
i = 7, p = 1, out.valid = 0
i = 6, p = 1, out.valid = 0
i = 5, p = 1, out.valid = 0
i = 4, p = 1, out.valid = 0
i = 3, p = 1, out.valid = 0
i = 2, p = 1, out.valid = 0
i = 1, p = 1, out.valid = 0
i = 0, p = 1, out.valid = 1
Before setting out.valid = 1 <-- why is it 1 here??
i = 255, p = 0, out.valid = 0
How on earth can io.out.valid be 1 (true) before it is assigned the true.B value? Is Chisel reordering printf statement in some weird way?

It seems to be normal behavior. With the := operator, the left-value will be written with right value at the end of clock cycle.
out.valid is still true.B just after false.B assignation.
// i = 0, p = 1, out.valid = 1
printf("i = %d, p = %b, out.valid = %b\n",i, p, io.out.valid)
io.in.ready := !p
io.out.valid := false.B
// Here, io.out.valid is still true.B if printf was true.B
// false.B will be written at the end of cycle,
// except if another connection write true.B
io.out.bits.y := 10.U
when (p) {
i := i - 1.U
when (i === 0.U) {
printf("Before setting out.valid = %b\n", io.out.valid)
p := false.B
// Here the register is set to 1.
io.out.valid := true.B // Will be set to true.B (but was already true.B)
}
}.otherwise {
when (io.in.valid) {
printf("Initializing\n")
i := WIDTH.U - 1.U
p := true.B
}
}
}

Related

Syntax Error Fix Required for the (Updated) Filtered Connors RSI in AFL AmiBroker

Here is the updated AFL for "Filtered Connors RSI" -
_SECTION_BEGIN("Filtered Connors RSI Final");
ma_length = Param("MA Length", 14, 3, 100);
c_length = Param("C Length", 3, 1, 100);
ud_length = Param("UD Length", 2, 1, 100);
roc_length = Param("ROC Length", 100, 1, 100);
function updown(input)
{
s = Close;
isEqual = s == Ref(s, -1);
isGrowing = s > Ref(s, -1);
ud = StaticVarGet("UD Self-Referencing", align=True);
ud = IIf(isEqual == 0, isGrowing, IIf(Nz(Ref(ud, -1)) <= 0, 1, Nz(Ref(ud, -1) + 1), IIf(Nz(Ref(ud, -1)) >= 0, -1, Nz(Ref(ud, -1) - 1)), Null);
return ud;
}
function RSIt(ARRAY, range)
{
return RSIa(Close, c_length);
}
function CRSI(Close, c_length, ud_length, roc_length)
{
updn = RSIa(updown(Close), c_length);
tRSI = RSIa(Close, c_length);
updownrsi = RSIt(updn, ud_length);
ptrk = PercentRank(ROC(Ref(Close, -1)), roc_length);
return (tRSI + updownrsi + ptrk)/3;
}
rsi_open = crsi( Open, c_length, ud_length, roc_length);
rsi_high = crsi( High, c_length, ud_length, roc_length);
rsi_low = crsi( Low, c_length, ud_length, roc_length);
rsi_close = crsi( Close, c_length, ud_length, roc_length);
function HaClose(O, H, L, C)
{
return (O + H + L + C) / 4;
}
source = HaClose(rsi_open, rsi_high, rsi_low, rsi_close);
fcrsi = TEMA(source, ma_length);
PlotGrid(70, colorGreen, pattern=10, width=1, label=True);
PlotGrid(60, colorPlum, pattern=9, width=1, label=True);
PlotGrid(50, colorBrown, pattern=9, width=1, label=True);
PlotGrid(40, colorPlum, pattern=9, width=1, label=True);
PlotGrid(30, colorRed, pattern=10, width=1, label=True);
Plot(fcrsi, "Filtered Connors RSI", colorBlue, styleLine|styleThick);
//Rescaling
Plot(100, "", colorWhite,styleLine|styleNoDraw|styleNoLabel);
Plot(0, "", colorWhite,styleLine|styleNoDraw|styleNoLabel);
_SECTION_END();
Here is the error -
Error 31. Syntax error, unexpected ';', expecting ')' or','
The line of pine script code based on the "Ternary Operator" I am trying to code with the "IIf" function in AFL is as follows -
ud := isEqual ? 0 : isGrowing ? (nz(ud[1]) <= 0 ? 1 : nz(ud[1])+1) :
(nz(ud[1]) >= 0 ? -1 : nz(ud[1])-1)
The pine script code snippet consists the whole function is as follows -
updown(float s) =>
isEqual = s == s[1]
isGrowing = s > s[1]
ud = 0.0
ud := isEqual ? 0 : isGrowing ? (nz(ud[1]) <= 0 ? 1 : nz(ud[1])+1) : (nz(ud[1]) >= 0 ? -1 : nz(ud[1])-1)
ud
Please help me to fix this. Regards.

THREE.JS + Delaunator.JS Keeping faces indexing

Probably this question is for Mapbox team and Delaunator.JS developers, but I hope that somebody could help me here.
I have a pseudo quadtree geometry (THREE.BufferGeometry) set by series of points having seven partitions with their individual draw call (geometry.addGroup() method) and material.
//pseudo quadtree
var points = [], indices = [], quad_uvs = [], groups = [], materials = [];
getSegmentSubpoints(0, new THREE.Vector3(-1024, 0, -1024), 1024, 1024, 4);
getSegmentSubpoints(1, new THREE.Vector3(0, 0, -1024), 1024, 1024, 4);
getSegmentSubpoints(2, new THREE.Vector3(-1024, 0, 0), 1024, 1024, 4);
getSegmentSubpoints(3, new THREE.Vector3(0, 0, 0), 512, 512, 8);
getSegmentSubpoints(4, new THREE.Vector3(512, 0, 0), 512, 512, 8);
getSegmentSubpoints(5, new THREE.Vector3(0, 0, 512), 512, 512, 8);
getSegmentSubpoints(6, new THREE.Vector3(512, 0, 512), 512, 512, 8);
var geometry = new THREE.BufferGeometry().setFromPoints(points);
geometry.setIndex(indices);
geometry.setAttribute( 'uv', new THREE.BufferAttribute(new Float32Array(quad_uvs), 2 ) );
geometry.computeVertexNormals();
var colors = [new THREE.Color(0xe6194b), new THREE.Color(0x3cb44b), new THREE.Color(0xffe119), new THREE.Color(0x4363d8), new THREE.Color(0xf58231), new THREE.Color(0x911eb4), new THREE.Color(0x46f0f0) ]
groups.forEach(function(g_, i_){ geometry.addGroup(g_.start, g_.end, g_.id); });
var plane = new THREE.Mesh(geometry, materials);
plane.rotation.set(Math.PI, 0, 0);
plane.position.set(-1152, 0, 0);
scene.add(plane);
function getSegmentSubpoints(id_, lt_, w_, h_, level_){
var subpoints = [];
var subindices = [];
var subquad = [];
var lastIndex = points.length;
var lastIndex2 = indices.length;
var step = {x: w_ / level_, z: h_ / level_ };
var stepT = {x: 1.0 / level_, z: 1.0 / level_ };
for(var z = 0; z <= level_; z++){
for(var x = 0; x <= level_; x++){
var dx = lt_.x + step.x * x;
var dz = lt_.z + step.z * z;
var dy = noise.simplex2(dx / 512.0, dz / 512.0) * 32.0;
subquad.push(...[stepT.x * x, stepT.z * z]);
subpoints.push(new THREE.Vector3(dx, dy, dz));
}
}
for(var i = 0; i < subpoints.length - level_ - 2; i++) {
if(i % (level_ + 1) != (level_)){
subindices.push(lastIndex + i, lastIndex + i + 1, lastIndex + i + level_ + 2, lastIndex + i + level_ + 2, lastIndex + i + level_ + 1, lastIndex + i);
}
}
points.push(...subpoints);
indices.push(...subindices);
quad_uvs.push(...subquad);
groups.push({id: id_, start: lastIndex2, end: subindices.length});
materials.push(new THREE.MeshBasicMaterial({ wireframe: true, map: new THREE.TextureLoader().load("textures/" + id_ + ".jpg")}));
}
Everything is fine, but for my project I have to process the current geometry through Delaunator.JS and it seems that the output has different triangles/faces indexing starting from the center.
There is dynamic colors for each segment to visualize indexing. Eventually, it has to be the same as previous one with seven materials and individual draw calls.
//delaunay
var geometry = new THREE.BufferGeometry().setFromPoints(points);
var indexDelaunay = Delaunator.from(points.map(v => { return [v.x, v.z]; }) );
var meshIndex = [];
for (let i = 0; i < indexDelaunay.triangles.length; i++){ meshIndex.push(indexDelaunay.triangles[i]); }
geometry.setIndex(meshIndex);
geometry.computeVertexNormals();
count = 0;
for(var i = 0; i < meshIndex.length; i += 6){
geometry.addGroup(i, 6, i / 6);
materials.push(new THREE.MeshBasicMaterial({ wireframe: true, color: new THREE.Color("hsl(" + (360 / 316 * count) + ",80%, 80%)")}))
count++;
}
var plane = new THREE.Mesh(geometry, materials);
plane.rotation.set(Math.PI, 0, 0)
plane.position.set(1152, 0, 0);
scene.add(plane);
So is there a way to re-index faces back so I could get the same result?
Yes, I could go through each Delaunator.triangles check its position/area for if it fits the certain partition, but it's not an elegant and fast solution. I bet it's possible to tweak Delaunator.JS code for right indexing on the fly.
The snippet is attached as well.
//https://hofk.de/main/discourse.threejs/2018/Triangulation/Triangulation.html
////by Mapbox https://github.com/mapbox/delaunator
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.Delaunator = factory());
}(this, (function () { 'use strict';
var EPSILON = Math.pow(2, -52);
var Delaunator = function Delaunator(coords) {
var this$1 = this;
var n = coords.length >> 1;
if (n > 0 && typeof coords[0] !== 'number') { throw new Error('Expected coords to contain numbers.'); }
this.coords = coords;
var maxTriangles = 2 * n - 5;
var triangles = this.triangles = new Uint32Array(maxTriangles * 3);
var halfedges = this.halfedges = new Int32Array(maxTriangles * 3);
this._hashSize = Math.ceil(Math.sqrt(n));
var hullPrev = this.hullPrev = new Uint32Array(n);
var hullNext = this.hullNext = new Uint32Array(n);
var hullTri = this.hullTri = new Uint32Array(n);
var hullHash = new Int32Array(this._hashSize).fill(-1);
var ids = new Uint32Array(n);
var minX = Infinity;
var minY = Infinity;
var maxX = -Infinity;
var maxY = -Infinity;
for (var i = 0; i < n; i++) {
var x = coords[2 * i];
var y = coords[2 * i + 1];
if (x < minX) { minX = x; }
if (y < minY) { minY = y; }
if (x > maxX) { maxX = x; }
if (y > maxY) { maxY = y; }
ids[i] = i;
}
var cx = (minX + maxX) / 2;
var cy = (minY + maxY) / 2;
var minDist = Infinity;
var i0, i1, i2;
for (var i$1 = 0; i$1 < n; i$1++) {
var d = dist(cx, cy, coords[2 * i$1], coords[2 * i$1 + 1]);
if (d < minDist) {
i0 = i$1;
minDist = d;
}
}
var i0x = coords[2 * i0];
var i0y = coords[2 * i0 + 1];
minDist = Infinity;
for (var i$2 = 0; i$2 < n; i$2++) {
if (i$2 === i0) { continue; }
var d$1 = dist(i0x, i0y, coords[2 * i$2], coords[2 * i$2 + 1]);
if (d$1 < minDist && d$1 > 0) {
i1 = i$2;
minDist = d$1;
}
}
var i1x = coords[2 * i1];
var i1y = coords[2 * i1 + 1];
var minRadius = Infinity;
for (var i$3 = 0; i$3 < n; i$3++) {
if (i$3 === i0 || i$3 === i1) { continue; }
var r = circumradius(i0x, i0y, i1x, i1y, coords[2 * i$3], coords[2 * i$3 + 1]);
if (r < minRadius) {
i2 = i$3;
minRadius = r;
}
}
var i2x = coords[2 * i2];
var i2y = coords[2 * i2 + 1];
if (minRadius === Infinity) {
throw new Error('No Delaunay triangulation exists for this input.');
}
if (orient(i0x, i0y, i1x, i1y, i2x, i2y)) {
var i$4 = i1;
var x$1 = i1x;
var y$1 = i1y;
i1 = i2;
i1x = i2x;
i1y = i2y;
i2 = i$4;
i2x = x$1;
i2y = y$1;
}
var center = circumcenter(i0x, i0y, i1x, i1y, i2x, i2y);
this._cx = center.x;
this._cy = center.y;
var dists = new Float64Array(n);
for (var i$5 = 0; i$5 < n; i$5++) {
dists[i$5] = dist(coords[2 * i$5], coords[2 * i$5 + 1], center.x, center.y);
}
quicksort(ids, dists, 0, n - 1);
this.hullStart = i0;
var hullSize = 3;
hullNext[i0] = hullPrev[i2] = i1;
hullNext[i1] = hullPrev[i0] = i2;
hullNext[i2] = hullPrev[i1] = i0;
hullTri[i0] = 0;
hullTri[i1] = 1;
hullTri[i2] = 2;
hullHash[this._hashKey(i0x, i0y)] = i0;
hullHash[this._hashKey(i1x, i1y)] = i1;
hullHash[this._hashKey(i2x, i2y)] = i2;
this.trianglesLen = 0;
this._addTriangle(i0, i1, i2, -1, -1, -1);
for (var k = 0, xp = (void 0), yp = (void 0); k < ids.length; k++) {
var i$6 = ids[k];
var x$2 = coords[2 * i$6];
var y$2 = coords[2 * i$6 + 1];
if (k > 0 && Math.abs(x$2 - xp) <= EPSILON && Math.abs(y$2 - yp) <= EPSILON) { continue; }
xp = x$2;
yp = y$2;
if (i$6 === i0 || i$6 === i1 || i$6 === i2) { continue; }
var start = 0;
for (var j = 0, key = this._hashKey(x$2, y$2); j < this._hashSize; j++) {
start = hullHash[(key + j) % this$1._hashSize];
if (start !== -1 && start !== hullNext[start]) { break; }
}
start = hullPrev[start];
var e = start, q = (void 0);
while (q = hullNext[e], !orient(x$2, y$2, coords[2 * e], coords[2 * e + 1], coords[2 * q], coords[2 * q + 1])) {
e = q;
if (e === start) {
e = -1;
break;
}
}
if (e === -1) { continue; }
var t = this$1._addTriangle(e, i$6, hullNext[e], -1, -1, hullTri[e]);
hullTri[i$6] = this$1._legalize(t + 2);
hullTri[e] = t;
hullSize++;
var n$1 = hullNext[e];
while (q = hullNext[n$1], orient(x$2, y$2, coords[2 * n$1], coords[2 * n$1 + 1], coords[2 * q], coords[2 * q + 1])) {
t = this$1._addTriangle(n$1, i$6, q, hullTri[i$6], -1, hullTri[n$1]);
hullTri[i$6] = this$1._legalize(t + 2);
hullNext[n$1] = n$1;
hullSize--;
n$1 = q;
}
if (e === start) {
while (q = hullPrev[e], orient(x$2, y$2, coords[2 * q], coords[2 * q + 1], coords[2 * e], coords[2 * e + 1])) {
t = this$1._addTriangle(q, i$6, e, -1, hullTri[e], hullTri[q]);
this$1._legalize(t + 2);
hullTri[q] = t;
hullNext[e] = e;
hullSize--;
e = q;
}
}
this$1.hullStart = hullPrev[i$6] = e;
hullNext[e] = hullPrev[n$1] = i$6;
hullNext[i$6] = n$1;
hullHash[this$1._hashKey(x$2, y$2)] = i$6;
hullHash[this$1._hashKey(coords[2 * e], coords[2 * e + 1])] = e;
}
this.hull = new Uint32Array(hullSize);
for (var i$7 = 0, e$1 = this.hullStart; i$7 < hullSize; i$7++) {
this$1.hull[i$7] = e$1;
e$1 = hullNext[e$1];
}
this.hullPrev = this.hullNext = this.hullTri = null;
this.triangles = triangles.subarray(0, this.trianglesLen);
this.halfedges = halfedges.subarray(0, this.trianglesLen);
};
Delaunator.from = function from (points, getX, getY) {
if ( getX === void 0 ) getX = defaultGetX;
if ( getY === void 0 ) getY = defaultGetY;
var n = points.length;
var coords = new Float64Array(n * 2);
for (var i = 0; i < n; i++) {
var p = points[i];
coords[2 * i] = getX(p);
coords[2 * i + 1] = getY(p);
}
return new Delaunator(coords);
};
Delaunator.prototype._hashKey = function _hashKey (x, y) {
return Math.floor(pseudoAngle(x - this._cx, y - this._cy) * this._hashSize) % this._hashSize;
};
Delaunator.prototype._legalize = function _legalize (a) {
var this$1 = this;
var ref = this;
var triangles = ref.triangles;
var coords = ref.coords;
var halfedges = ref.halfedges;
var b = halfedges[a];
var a0 = a - a % 3;
var b0 = b - b % 3;
var al = a0 + (a + 1) % 3;
var ar = a0 + (a + 2) % 3;
var bl = b0 + (b + 2) % 3;
if (b === -1) { return ar; }
var p0 = triangles[ar];
var pr = triangles[a];
var pl = triangles[al];
var p1 = triangles[bl];
var illegal = inCircle(
coords[2 * p0], coords[2 * p0 + 1],
coords[2 * pr], coords[2 * pr + 1],
coords[2 * pl], coords[2 * pl + 1],
coords[2 * p1], coords[2 * p1 + 1]);
if (illegal) {
triangles[a] = p1;
triangles[b] = p0;
var hbl = halfedges[bl];
if (hbl === -1) {
var e = this.hullStart;
do {
if (this$1.hullTri[e] === bl) {
this$1.hullTri[e] = a;
break;
}
e = this$1.hullNext[e];
} while (e !== this.hullStart);
}
this._link(a, hbl);
this._link(b, halfedges[ar]);
this._link(ar, bl);
var br = b0 + (b + 1) % 3;
this._legalize(a);
return this._legalize(br);
}
return ar;
};
Delaunator.prototype._link = function _link (a, b) {
this.halfedges[a] = b;
if (b !== -1) { this.halfedges[b] = a; }
};
Delaunator.prototype._addTriangle = function _addTriangle (i0, i1, i2, a, b, c) {
var t = this.trianglesLen;
this.triangles[t] = i0;
this.triangles[t + 1] = i1;
this.triangles[t + 2] = i2;
this._link(t, a);
this._link(t + 1, b);
this._link(t + 2, c);
this.trianglesLen += 3;
return t;
};
function pseudoAngle(dx, dy) {
var p = dx / (Math.abs(dx) + Math.abs(dy));
return (dy > 0 ? 3 - p : 1 + p) / 4;
}
function dist(ax, ay, bx, by) {
var dx = ax - bx;
var dy = ay - by;
return dx * dx + dy * dy;
}
function orient(px, py, qx, qy, rx, ry) {
return (qy - py) * (rx - qx) - (qx - px) * (ry - qy) < 0;
}
function inCircle(ax, ay, bx, by, cx, cy, px, py) {
var dx = ax - px;
var dy = ay - py;
var ex = bx - px;
var ey = by - py;
var fx = cx - px;
var fy = cy - py;
var ap = dx * dx + dy * dy;
var bp = ex * ex + ey * ey;
var cp = fx * fx + fy * fy;
return dx * (ey * cp - bp * fy) -
dy * (ex * cp - bp * fx) +
ap * (ex * fy - ey * fx) < 0;
}
function circumradius(ax, ay, bx, by, cx, cy) {
var dx = bx - ax;
var dy = by - ay;
var ex = cx - ax;
var ey = cy - ay;
var bl = dx * dx + dy * dy;
var cl = ex * ex + ey * ey;
var d = 0.5 / (dx * ey - dy * ex);
var x = (ey * bl - dy * cl) * d;
var y = (dx * cl - ex * bl) * d;
return x * x + y * y;
}
function circumcenter(ax, ay, bx, by, cx, cy) {
var dx = bx - ax;
var dy = by - ay;
var ex = cx - ax;
var ey = cy - ay;
var bl = dx * dx + dy * dy;
var cl = ex * ex + ey * ey;
var d = 0.5 / (dx * ey - dy * ex);
var x = ax + (ey * bl - dy * cl) * d;
var y = ay + (dx * cl - ex * bl) * d;
return {x: x, y: y};
}
function quicksort(ids, dists, left, right) {
if (right - left <= 20) {
for (var i = left + 1; i <= right; i++) {
var temp = ids[i];
var tempDist = dists[temp];
var j = i - 1;
while (j >= left && dists[ids[j]] > tempDist) { ids[j + 1] = ids[j--]; }
ids[j + 1] = temp;
}
} else {
var median = (left + right) >> 1;
var i$1 = left + 1;
var j$1 = right;
swap(ids, median, i$1);
if (dists[ids[left]] > dists[ids[right]]) { swap(ids, left, right); }
if (dists[ids[i$1]] > dists[ids[right]]) { swap(ids, i$1, right); }
if (dists[ids[left]] > dists[ids[i$1]]) { swap(ids, left, i$1); }
var temp$1 = ids[i$1];
var tempDist$1 = dists[temp$1];
while (true) {
do { i$1++; } while (dists[ids[i$1]] < tempDist$1);
do { j$1--; } while (dists[ids[j$1]] > tempDist$1);
if (j$1 < i$1) { break; }
swap(ids, i$1, j$1);
}
ids[left + 1] = ids[j$1];
ids[j$1] = temp$1;
if (right - i$1 + 1 >= j$1 - left) {
quicksort(ids, dists, i$1, right);
quicksort(ids, dists, left, j$1 - 1);
} else {
quicksort(ids, dists, left, j$1 - 1);
quicksort(ids, dists, i$1, right);
}
}
}
function swap(arr, i, j) {
var tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
function defaultGetX(p) {
return p[0];
}
function defaultGetY(p) {
return p[1];
}
return Delaunator;
})));
var renderer, scene, camera, controls, loader, terrain, glsl, uniforms, root, tree;
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x000000);
document.body.appendChild(renderer.domElement);
scene = new THREE.Scene();
loader = new THREE.TextureLoader();
loader.crossOrigin = "";
camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 1, 51200);
camera.position.set(-3072, 2048, -3072);
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.screenSpacePanning = false;
controls.minDistance = 8;
controls.maxDistance = 10240;
controls.maxPolarAngle = Math.PI / 2;
//simple pseudo quadtree
var points = [], indices = [], quad_uvs = [], groups = [], materials = [];
getSegmentSubpoints(0, new THREE.Vector3(-1024, 0, -1024), 1024, 1024, 4);
getSegmentSubpoints(1, new THREE.Vector3(0, 0, -1024), 1024, 1024, 4);
getSegmentSubpoints(2, new THREE.Vector3(-1024, 0, 0), 1024, 1024, 4);
getSegmentSubpoints(3, new THREE.Vector3(0, 0, 0), 512, 512, 8);
getSegmentSubpoints(4, new THREE.Vector3(512, 0, 0), 512, 512, 8);
getSegmentSubpoints(5, new THREE.Vector3(0, 0, 512), 512, 512, 8);
getSegmentSubpoints(6, new THREE.Vector3(512, 0, 512), 512, 512, 8);
var geometry = new THREE.BufferGeometry().setFromPoints(points);
geometry.setIndex(indices);
geometry.setAttribute( 'uv', new THREE.BufferAttribute(new Float32Array(quad_uvs), 2 ) );
geometry.computeVertexNormals();
var materials = [];
var colors = [new THREE.Color(0xe6194b), new THREE.Color(0x3cb44b), new THREE.Color(0xffe119), new THREE.Color(0x4363d8), new THREE.Color(0xf58231), new THREE.Color(0x911eb4), new THREE.Color(0x46f0f0) ]
groups.forEach(function(g_, i_){ geometry.addGroup(g_.start, g_.end, g_.id); materials.push(new THREE.MeshBasicMaterial({wireframe: true, color: colors[i_]})) });
var plane = new THREE.Mesh(geometry, materials);
plane.rotation.set(Math.PI, 0, 0);
plane.position.set(-1152, 0, 0);
scene.add(plane);
//delaunay
materials = [];
var geometry = new THREE.BufferGeometry().setFromPoints(points);
var indexDelaunay = Delaunator.from(points.map(v => { return [v.x, v.z]; }) );
var meshIndex = [];
for (let i = 0; i < indexDelaunay.triangles.length; i++){ meshIndex.push(indexDelaunay.triangles[i]); }
geometry.setIndex(meshIndex);
geometry.computeVertexNormals();
count = 0;
for(var i = 0; i < meshIndex.length; i += 6){
geometry.addGroup(i, 6, i / 6);
materials.push(new THREE.MeshBasicMaterial({ wireframe: true, color: new THREE.Color("hsl(" + (360 / 316 * count) + ",80%, 80%)")}))
count++;
}
var plane = new THREE.Mesh(geometry, materials); //new THREE.MeshBasicMaterial({color: 0xFF00FF, side: THREE.DoubleSide, wireframe: true}) );
plane.rotation.set(Math.PI, 0, 0)
plane.position.set(1152, 0, 0);
scene.add(plane);
animate();
function getSegmentSubpoints(id_, lt_, w_, h_, level_){
var subpoints = [];
var subindices = [];
var subquad = [];
var lastIndex = points.length;
var lastIndex2 = indices.length;
var step = {x: w_ / level_, z: h_ / level_ };
var stepT = {x: 1.0 / level_, z: 1.0 / level_ };
for(var z = 0; z <= level_; z++){
for(var x = 0; x <= level_; x++){
var dx = lt_.x + step.x * x;
var dz = lt_.z + step.z * z;
var dy = 0;
subquad.push(...[stepT.x * x, stepT.z * z]);
subpoints.push(new THREE.Vector3(dx, dy, dz));
}
}
for(var i = 0; i < subpoints.length - level_ - 2; i++) {
if(i % (level_ + 1) != (level_)){
subindices.push(lastIndex + i, lastIndex + i + 1, lastIndex + i + level_ + 2, lastIndex + i + level_ + 2, lastIndex + i + level_ + 1, lastIndex + i);
}
}
points.push(...subpoints);
indices.push(...subindices);
quad_uvs.push(...subquad);
groups.push({id: id_, start: lastIndex2, end: subindices.length});
materials.push(new THREE.MeshBasicMaterial({ wireframe: true, map: new THREE.TextureLoader().load("textures/" + id_ + ".jpg")}));
}
function animate(){
controls.update();
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
body { margin: 0; }
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>GLSL Intersection</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<script src="https://unpkg.com/three#0.116.0/build/three.min.js"></script>
<script src="https://unpkg.com/three#0.116.0/examples/js/controls/OrbitControls.js"></script>
</head>
<body>
</body>
</html>

Avoiding explicit record typing

Suppose I have the following functions for operating over an idealized stream:
fun Stream s = { pos = 0, row = 1, col = 0, str = s }
fun len { str, pos = _, row = _, col = _ } = String.size str
fun poke off { str, pos, row: int, col: int } =
let val n = pos + off in
if n >= 0 andalso n <= (String.size str) then SOME (String.sub(str, n)) else NONE
end
This works/compiles, but it's unfortunate to have to litter my function definitions with information I don't care about. row/col are ignored poke and len. However, while the wildcard can be used with len, it can't be with poke. Is there a way to restructure these functions so that less explicit typing needs to be put in, while still being able to pattern match/destructure?
If you give your type a name (such as stream), you can refer to it more briefly:
type stream = { pos : int, row : int, col : int, str : string }
fun Stream s = { pos = 0, row = 1, col = 0, str = s }
fun len ({ str, ... } : stream) = String.size str
fun poke off ({ str, pos, ... } : stream) =
let val n = pos + off in
if n >= 0 andalso n <= String.size str
then SOME (String.sub (str, n))
else NONE
end
Or, more-or-less equivalently:
datatype stream = STREAM of { pos : int, row : int, col : int, str : string }
fun Stream s = STREAM { pos = 0, row = 1, col = 0, str = s }
fun len (STREAM { str, ... }) = String.size str
fun poke off (STREAM { str, pos, ... }) =
let val n = pos + off in
if n >= 0 andalso n <= String.size str
then SOME (String.sub (str, n))
else NONE
end

Find missing number in sorted array

Whats wrong with this code ? Not able able to search missing number in a consecutive array using binary search.
a = [1,2,3,4,5,7,8]
lent = len(a)
beg =0
end = lent-1
while beg < end:
mid = (beg + end) / 2
if (a[mid]-a[beg])==(mid - beg):
beg = mid + 1
else:
end = mid -1
if(beg == end):
mid = (beg + end) / 2
print "missing"
print a[0]+ beg
Update #1: Yes, there was another one mistake. You're right. Here's updated version
Try this variant:
a = [1,2,3,4,5,7,8]
lent = len(a)
beg =0
end = lent-1
while beg < end:
mid = (beg + end) / 2
if (a[mid]-a[beg])==(mid - beg):
beg = mid
else:
end = mid
if abs(beg-end) <= 1:
print "missing: %s" % (a[0] + max(beg, mid),)
Result:
missing: 6
Also, try use functions, so you could easily test and debug your code on different lists:
def find_missing(a):
lent = len(a)
beg =0
end = lent-1
while beg < end:
mid = (beg + end) / 2
if (a[mid]-a[beg])==(mid - beg):
beg = mid
else:
end = mid
if abs(beg-end) <= 1:
return a[0] + max(beg, mid)
a = [1,2,3,4,5,7,8]
print find_missing(a)
a = [1,3,4,5,6]
print find_missing(a)
a = [1,2,3,4,5,7,8,9,10]
print find_missing(a)
Result:
6
2
6
//Implementation of the algorithm using java.
static int missingNumber(int [] nums) {
int i=0;
while(i < nums.length) {
int correct = nums[i];
if (nums[i] < nums.length && nums[i] != nums[correct]) {
swap(nums, i, correct);
} else {
i++;
}
}
for( int index=0; index<nums.length; index++){
if(index != nums[index]) {
return index;
}
}
return nums.length;
}
static void swap(int[] nums, int first, int second) {
int temp = nums[first];
nums[first] = nums[second];
nums[second] = temp;
}
int findMiss(int arr[], int low, int high)
{
if(low>high)
return -1;
if(arr[low]-1 != low)
return arr[low]-1;
int mid = (low + high) / 2;
if(arr[mid]-1 != mid)
return findMiss(arr,low,mid);
else
return findMiss(arr,mid+1,high);
}

google-bigquery UDF for jaro_winkle_distance

I am the following UDF code that calculate jaro_winkle_distance
It seems to work when test it with json test data but when I try to call it in the google-bigquery UI, it keeps consistently gives me a score of zero.
even with self join e.g.
input:
[
{a: "Liu",b:"Lau"},
{a: "John",b:"Jone"}]
Output:
[
{
"scr": 80
},
{
"scr": 87
}
]
SQL:
CREATE TEMP FUNCTION
jwd(a STRING,
b STRING)
RETURNS INT64
LANGUAGE js AS """
// Assumes 'doInterestingStuff' is defined in one of the library files.
//return doInterestingStuff(a, b);
return jaro_winkler_distance(a,b);
""" OPTIONS ( library="gs://kayama808/javascript/jaro_winkler_google_UDF.js" );
SELECT
x.name name1,
jwd(x.name,
x.name) scr
FROM
babynames.usa_1910_2013_copy x
WHERE
x.gender = 'F' and x.number >= 1000 and x.state = 'CA'
ORDER BY
scr DESC;
http://storage.googleapis.com/bigquery-udf-test-tool/testtool.html
https://storage.cloud.google.com/kayama808/javascript/jaro_winkler_google_UDF.js?_ga=1.184402278.1320598031.1475534357
Try below. It works as expected with result as
name1 name2 scr
Liu Liu 100
John Jone 87
Liu Lau 80
Hopefully, you will be able to put it back to your external lib file :o)
CREATE TEMP FUNCTION jwd(a STRING, b STRING)
RETURNS INT64
LANGUAGE js AS """
/* JS implementation of the strcmp95 C function written by
Bill Winkler, George McLaughlin, Matt Jaro and Maureen Lynch,
released in 1994 (http://web.archive.org/web/20100227020019/http://www.census.gov/geo/msb/stand/strcmp.c).
a and b should be strings. Always performs case-insensitive comparisons
and always adjusts for long strings. */
var jaro_winkler_adjustments = {
'A': 'E',
'A': 'I',
'A': 'O',
'A': 'U',
'B': 'V',
'E': 'I',
'E': 'O',
'E': 'U',
'I': 'O',
'I': 'U',
'O': 'U',
'I': 'Y',
'E': 'Y',
'C': 'G',
'E': 'F',
'W': 'U',
'W': 'V',
'X': 'K',
'S': 'Z',
'X': 'S',
'Q': 'C',
'U': 'V',
'M': 'N',
'L': 'I',
'Q': 'O',
'P': 'R',
'I': 'J',
'2': 'Z',
'5': 'S',
'8': 'B',
'1': 'I',
'1': 'L',
'0': 'O',
'0': 'Q',
'C': 'K',
'G': 'J',
'E': ' ',
'Y': ' ',
'S': ' '
};
if (!a || !b) { return 0.0; }
a = a.trim().toUpperCase();
b = b.trim().toUpperCase();
var a_len = a.length;
var b_len = b.length;
var a_flag = []; var b_flag = [];
var search_range = Math.floor(Math.max(a_len, b_len) / 2) - 1;
var minv = Math.min(a_len, b_len);
// Looking only within the search range, count and flag the matched pairs.
var Num_com = 0;
var yl1 = b_len - 1;
for (var i = 0; i < a_len; i++) {
var lowlim = (i >= search_range) ? i - search_range : 0;
var hilim = ((i + search_range) <= yl1) ? (i + search_range) : yl1;
for (var j = lowlim; j <= hilim; j++) {
if (b_flag[j] !== 1 && a[j] === b[i]) {
a_flag[j] = 1;
b_flag[i] = 1;
Num_com++;
break;
}
}
}
// Return if no characters in common
if (Num_com === 0) { return 0.0; }
// Count the number of transpositions
var k = 0; var N_trans = 0;
for (var i = 0; i < a_len; i++) {
if (a_flag[i] === 1) {
var j;
for (j = k; j < b_len; j++) {
if (b_flag[j] === 1) {
k = j + 1;
break;
}
}
if (a[i] !== b[j]) { N_trans++; }
}
}
N_trans = Math.floor(N_trans / 2);
// Adjust for similarities in nonmatched characters
var N_simi = 0; var adjwt = jaro_winkler_adjustments;
if (minv > Num_com) {
for (var i = 0; i < a_len; i++) {
if (!a_flag[i]) {
for (var j = 0; j < b_len; j++) {
if (!b_flag[j]) {
if (adjwt[a[i]] === b[j]) {
N_simi += 3;
b_flag[j] = 2;
break;
}
}
}
}
}
}
var Num_sim = (N_simi / 10.0) + Num_com;
// Main weight computation
var weight = Num_sim / a_len + Num_sim / b_len + (Num_com - N_trans) / Num_com;
weight = weight / 3;
// Continue to boost the weight if the strings are similar
if (weight > 0.7) {
// Adjust for having up to the first 4 characters in common
var j = (minv >= 4) ? 4 : minv;
var i;
for (i = 0; (i < j) && a[i] === b[i]; i++) { }
if (i) { weight += i * 0.1 * (1.0 - weight) };
// Adjust for long strings.
// After agreeing beginning chars, at least two more must agree
// and the agreeing characters must be more than half of the
// remaining characters.
if (minv > 4 && Num_com > i + 1 && 2 * Num_com >= minv + i) {
weight += (1 - weight) * ((Num_com - i - 1) / (a_len * b_len - i*2 + 2));
}
}
return Math.round(weight*100);
""";
SELECT
name1, name2,
jwd(name1, name2) scr
FROM -- babynames.usa_1910_2013_copy x
(
select "Liu" as name1, "Lau" as name2 union all
select "Liu" as name1, "Liu" as name2 union all
select "John" as name1, "Jone" as name2
) x
ORDER BY scr DESC
In addition: I've just double checked your jaro_winkler_google_UDF2.js file and clearly see that issue is in this file.
Fix this file using code in my answer
Or, just remove below lines in it
var a = r.a;
var b = r.b;
and uncomment
//jaro_winkler.distance = function(a, b) {
//return Math.round(weight*100)
and comment all with emit in it
jaro_winkler_distance=function(r, emit) {
emit(weight);
You should be ok then!