Skip to content

Commit b082172

Browse files
committed
working on code generation
1 parent cd9a645 commit b082172

File tree

2 files changed

+221
-22
lines changed

2 files changed

+221
-22
lines changed

contour.js

+199-22
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
"use strict"
22

33
var pool = require("typedarray-pool")
4+
var beautify = require("js-beautify")
5+
var invert = require("invert-permutation")
46

57
module.exports = createSurfaceExtractor
68

@@ -11,6 +13,9 @@ function array(i) {
1113
function data(i) {
1214
return "d" + i
1315
}
16+
function cube(i,bitmask) {
17+
return "c" + i + "_" + bitmask
18+
}
1419
function shape(i) {
1520
return "s" + i
1621
}
@@ -35,14 +40,24 @@ function index(i) {
3540
function step(i,j) {
3641
return "u" + i + "_" + j
3742
}
43+
function pcube(bitmask) {
44+
return "b" + bitmask
45+
}
46+
function pdelta(bitmask) {
47+
return "e" + bitmask
48+
}
49+
function vert(i) {
50+
return "v" + i
51+
}
3852
var VERTEX_IDS = "V"
3953
var PHASES = "P"
4054
var VERTEX_COUNT = "N"
4155
var POOL_SIZE = "Q"
56+
var POINTER = "X"
4257

4358
//Generates the surface procedure
44-
function compileSurfaceProcedure(vertexFunc, faceFunc, phaseFunc, scalarArgs, order, typesignature) {
45-
var arrayArgs = typesignature.length
59+
function compileSurfaceProcedure(vertexFunc, faceFunc, phaseFunc, scalarArgs, order, typesig) {
60+
var arrayArgs = typesig.length
4661
var dimension = order.length
4762

4863
var funcName = "extractContour" + order.join("_")
@@ -60,39 +75,40 @@ function compileSurfaceProcedure(vertexFunc, faceFunc, phaseFunc, scalarArgs, or
6075

6176
//Shape
6277
for(var i=0; i<dimension; ++i) {
63-
vars.push(shape(i) + "=" + array(i) + ".shape[" + i + "]|0")
78+
vars.push(shape(i) + "=" + array(0) + ".shape[" + i + "]|0")
6479
}
6580
//Data, stride, offset pointers
6681
for(var i=0; i<arrayArgs; ++i) {
6782
vars.push(data(i) + "=" + array(i) + ".data",
6883
offset(i) + "=" + array(i) + ".offset")
6984
for(var j=0; j<dimension; ++j) {
70-
vars.push(stride(i,j) + "=" + array(i) + ".stride[" + j + "]")
85+
vars.push(stride(i,j) + "=" + array(i) + ".stride[" + j + "]|0")
7186
}
7287
}
73-
//Pointer and delta variables
88+
//Pointer, delta and cube variables
7489
for(var i=0; i<arrayArgs; ++i) {
75-
var ptrStr = [offset(i)]
76-
for(var j=0; j<dimension; ++i) {
77-
ptrStr.push(stride(i,j))
78-
}
79-
vars.push(pointer(i) + "=" + ptrStr.join("+"))
80-
for(var j=1; j<1<<dimension; ++i) {
81-
ptrStr.length = 0
90+
vars.push(pointer(i) + "=" + offset(i))
91+
vars.push(cube(i,0))
92+
for(var j=1; j<(1<<dimension); ++j) {
93+
var ptrStr = []
8294
for(var k=0; k<dimension; ++k) {
8395
if(j & (1<<k)) {
84-
ptrStr.push("-" + stride(i,j))
96+
ptrStr.push("-" + stride(i,k))
8597
}
8698
}
8799
vars.push(delta(i,j) + "=" + ptrStr.join(""))
100+
vars.push(cube(i,j))
88101
}
89102
}
103+
90104
//Create step variables
91105
for(var i=0; i<arrayArgs; ++i) {
92106
for(var j=0; j<dimension; ++j) {
93-
var stepVal = [ stride(i,j) ]
94-
//TODO: Compute step variables here
95-
vars.push(step(i,j) + "=(" + stepVal.join("+") + ")|0")
107+
var stepVal = [ stride(i,order[j]) ]
108+
for(var k=j-1; k>=0; --k) {
109+
stepVal.push(stride(i, order[k]) + "*" + shape(order[k]))
110+
}
111+
vars.push(step(i,order[j]) + "=(" + stepVal.join("-") + ")|0")
96112
}
97113
}
98114
//Create index variables
@@ -101,21 +117,176 @@ function compileSurfaceProcedure(vertexFunc, faceFunc, phaseFunc, scalarArgs, or
101117
}
102118
//Vertex count
103119
vars.push(VERTEX_COUNT + "=0")
104-
//Compute pool size
120+
//Compute pool size, initialize pool step
105121
var sizeVariable = ["2"]
106122
for(var i=dimension-2; i>=0; --i) {
107123
sizeVariable.push(shape(order[i]))
108124
}
109125
//Previous phases and vertex_ids
110126
vars.push(POOL_SIZE + "=(" + sizeVariable.join("*") + ")|0",
111127
PHASES + "=mallocUint32(" + POOL_SIZE + ")",
112-
VERTEX_IDS + "=mallocUint32(" + POOL_SIZE + ")")
128+
VERTEX_IDS + "=mallocUint32(" + POOL_SIZE + ")",
129+
POINTER + "=0")
130+
//Create cube variables for phases
131+
vars.push(pcube(0) + "=0")
132+
for(var j=1; j<(1<<dimension); ++j) {
133+
var cubeDelta = []
134+
var cubeStep = [ "1" ]
135+
for(var k=dimension-1; k>=0; --k) {
136+
if(j & (1<<order[k])) {
137+
cubeDelta.push(cubeStep.join("*"))
138+
}
139+
cubeStep.push(shape(order[k]))
140+
}
141+
vars.push(pdelta(j) + "=-(" + cubeDelta.join("+") + ")|0",
142+
pcube(j) + "=0")
143+
}
144+
for(var i=0; i<(1<<dimension)-1; ++i) {
145+
vars.push(vert(i) + "=0")
146+
}
147+
148+
function forLoopBegin(i, start) {
149+
code.push("for(", index(order[i]), "=", start, ";",
150+
index(order[i]), "<", shape(order[i]), ";",
151+
"++", index(order[i]), "){")
152+
}
153+
154+
function forLoopEnd(i) {
155+
for(var j=0; j<arrayArgs; ++j) {
156+
code.push(pointer(j), "+=", step(j,order[i]), ";")
157+
}
158+
code.push("}")
159+
}
160+
161+
function fillEmptySlice(k) {
162+
for(var i=k-1; i>=0; --i) {
163+
forLoopBegin(i, 0)
164+
}
165+
var phaseFuncArgs = []
166+
for(var i=0; i<arrayArgs; ++i) {
167+
if(typesig[i]) {
168+
phaseFuncArgs.push(data(i) + ".get(" + pointer(i) + ")")
169+
} else {
170+
phaseFuncArgs.push(data(i) + "[" + pointer(i) + "]")
171+
}
172+
}
173+
for(var i=0; j<scalarArgs; ++i) {
174+
phaseFuncArgs.push(scalar(i))
175+
}
176+
code.push(PHASES, "[", POINTER, "++]=phase(", phaseFuncArgs.join(), ");")
177+
for(var i=0; i<k; ++i) {
178+
forLoopEnd(i)
179+
}
180+
for(var j=0; j<arrayArgs; ++j) {
181+
code.push(pointer(j), "+=", step(j,order[k]), ";")
182+
}
183+
}
184+
185+
function processGridCell(mask) {
186+
//Read in local data
187+
for(var i=0; i<arrayArgs; ++i) {
188+
if(typesig[i]) {
189+
code.push(cube(i,0), "=", data(i), ".get(", pointer(i), ");")
190+
} else {
191+
code.push(cube(i,0), "=", data(i), "[", pointer(i), "];")
192+
}
193+
}
113194

114-
//Generate outermost loop
195+
//Read in phase
196+
var phaseFuncArgs = []
197+
for(var i=0; i<arrayArgs; ++i) {
198+
phaseFuncArgs.push(cube(i,0))
199+
}
200+
for(var i=0; j<scalarArgs; ++i) {
201+
phaseFuncArgs.push(scalar(i))
202+
}
203+
code.push(pcube(0), "=", PHASES, "[", POINTER, "]=phase(", phaseFuncArgs.join(), ");")
204+
205+
//Read in other cube data
206+
for(var j=1; j<(1<<dimension); ++j) {
207+
code.push(pcube(j), "=", PHASES, "[", POINTER, "+", pdelta(j), "];")
208+
}
115209

116-
//Generate inner loops
210+
//Check for boundary crossing
211+
var vertexPredicate = []
212+
for(var j=1; j<(1<<dimension); ++j) {
213+
vertexPredicate.push("(" + pcube(0) + "!==" + pcube(j) + ")")
214+
}
215+
code.push("if(", vertexPredicate.join("||"), "){")
216+
217+
//Read in boundary data
218+
var vertexArgs = []
219+
for(var i=0; i<dimension; ++i) {
220+
vertexArgs.push(index(i))
221+
}
222+
for(var i=0; i<arrayArgs; ++i) {
223+
vertexArgs.push(cube(i,0))
224+
for(var j=1; j<(1<<dimension); ++j) {
225+
if(typesig[i]) {
226+
code.push(cube(i,j), "=", data(i), ".get(", pointer(i), "+", delta(i,j), ");")
227+
} else {
228+
code.push(cube(i,j), "=", data(i), "[", pointer(i), "+", delta(i,j), "];")
229+
}
230+
vertexArgs.push(cube(i,j))
231+
}
232+
}
233+
for(var i=0; i<scalarArgs; ++i) {
234+
vertexArgs.push(scalar(i))
235+
}
236+
for(var i=0; i<(1<<dimension); ++i) {
237+
vertexArgs.push(pcube(i))
238+
}
117239

240+
//Generate vertex
241+
code.push("vertex(", vertexArgs.join(), ");",
242+
vert(0), "=", VERTEX_IDS, "[", POINTER, "]=", VERTEX_COUNT, "++;")
118243

244+
//TODO: Check face crossing
245+
if(mask < (1<<dimension)-1) {
246+
for(var j=1; j<(1<<dimension); ++j) {
247+
if((j & mask) === 0) {
248+
code.push(vert(j), "=", VERTEX_IDS, "[", POINTER, "+", pcube(j), "];")
249+
}
250+
}
251+
var corner = pcube((1<<dimension)-1)
252+
for(var j=0; j<dimension; ++j) {
253+
if(mask & (1<<j)) {
254+
//Check face
255+
var edge = pcube(((1<<dimension)-1)^(1<<j))
256+
var faceArgs = []
257+
258+
faceArgs.push(corner, edge)
259+
code.push("if(", corner, "!==", edge, "){",
260+
"face(", faceArgs.join(), ")}")
261+
}
262+
}
263+
264+
code.push("/*" + mask + "*/")
265+
}
266+
267+
//Increment pointer, close off if statement
268+
code.push("}",
269+
POINTER, "+=1;")
270+
}
271+
272+
function createLoop(i, mask) {
273+
if(i < 0) {
274+
processGridCell(mask)
275+
return
276+
}
277+
fillEmptySlice(i)
278+
code.push("if(", shape(order[i]), ">0){")
279+
createLoop(i-1, mask|(1<<i))
280+
for(var j=0; j<arrayArgs; ++j) {
281+
code.push(pointer(j), "+=", step(j,i), ";")
282+
}
283+
forLoopBegin(i, 2)
284+
createLoop(i-1, mask)
285+
forLoopEnd(i)
286+
code.push("}")
287+
}
288+
289+
createLoop(dimension-1, 0)
119290

120291
//Release scratch memory
121292
code.push("freeUint32(", VERTEX_IDS, ");freeUint32(", PHASES, ");")
@@ -128,6 +299,10 @@ function compileSurfaceProcedure(vertexFunc, faceFunc, phaseFunc, scalarArgs, or
128299
code.join(""),
129300
"}",
130301
"return ", funcName ].join("")
302+
303+
//Print code
304+
console.log(beautify(procedureCode))
305+
131306
var proc = new Function(
132307
"vertex",
133308
"face",
@@ -173,19 +348,21 @@ function createSurfaceExtractor(args) {
173348
}
174349
var getters = args.getters || []
175350
var typesig = new Array(arrays)
351+
console.log(getters)
176352
for(var i=0; i<arrays; ++i) {
353+
console.log("here1")
177354
if(getters.indexOf(i) >= 0) {
178355
typesig[i] = true
179356
} else {
180357
typesig[i] = false
181358
}
359+
console.log("here2")
182360
}
183361
return compileSurfaceProcedure(
184362
args.vertex,
185363
args.face,
186364
args.phase,
187-
dimension,
188365
scalars,
189366
order,
190-
typeSignature)
367+
typesig)
191368
}

test/test.js

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
"use strict"
2+
3+
var tape = require("tape")
4+
var createExtractor = require("../contour.js")
5+
6+
tape("test-vectorize", function(t) {
7+
8+
var testVectorizer = createExtractor({
9+
order: [1, 0],
10+
vertex: function(x, y, p00, p01, p10, p11, s00, s01, s10, s11) {
11+
console.log("got vertex:", x, y)
12+
},
13+
phase: function(s) {
14+
return s < 0
15+
},
16+
face: function(i, j, p0, p11) {
17+
console.log("face", i, j)
18+
}
19+
})
20+
21+
t.end()
22+
})

0 commit comments

Comments
 (0)