You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
86 lines
4.1 KiB
86 lines
4.1 KiB
"use strict"
|
|
|
|
// The function below is called when constructing a cwise function object, and does the following:
|
|
// A function object is constructed which accepts as argument a compilation function and returns another function.
|
|
// It is this other function that is eventually returned by createThunk, and this function is the one that actually
|
|
// checks whether a certain pattern of arguments has already been used before and compiles new loops as needed.
|
|
// The compilation passed to the first function object is used for compiling new functions.
|
|
// Once this function object is created, it is called with compile as argument, where the first argument of compile
|
|
// is bound to "proc" (essentially containing a preprocessed version of the user arguments to cwise).
|
|
// So createThunk roughly works like this:
|
|
// function createThunk(proc) {
|
|
// var thunk = function(compileBound) {
|
|
// var CACHED = {}
|
|
// return function(arrays and scalars) {
|
|
// if (dtype and order of arrays in CACHED) {
|
|
// var func = CACHED[dtype and order of arrays]
|
|
// } else {
|
|
// var func = CACHED[dtype and order of arrays] = compileBound(dtype and order of arrays)
|
|
// }
|
|
// return func(arrays and scalars)
|
|
// }
|
|
// }
|
|
// return thunk(compile.bind1(proc))
|
|
// }
|
|
|
|
var compile = require("./compile.js")
|
|
|
|
function createThunk(proc) {
|
|
var code = ["'use strict'", "var CACHED={}"]
|
|
var vars = []
|
|
var thunkName = proc.funcName + "_cwise_thunk"
|
|
|
|
//Build thunk
|
|
code.push(["return function ", thunkName, "(", proc.shimArgs.join(","), "){"].join(""))
|
|
var typesig = []
|
|
var string_typesig = []
|
|
var proc_args = [["array",proc.arrayArgs[0],".shape.slice(", // Slice shape so that we only retain the shape over which we iterate (which gets passed to the cwise operator as SS).
|
|
Math.max(0,proc.arrayBlockIndices[0]),proc.arrayBlockIndices[0]<0?(","+proc.arrayBlockIndices[0]+")"):")"].join("")]
|
|
var shapeLengthConditions = [], shapeConditions = []
|
|
// Process array arguments
|
|
for(var i=0; i<proc.arrayArgs.length; ++i) {
|
|
var j = proc.arrayArgs[i]
|
|
vars.push(["t", j, "=array", j, ".dtype,",
|
|
"r", j, "=array", j, ".order"].join(""))
|
|
typesig.push("t" + j)
|
|
typesig.push("r" + j)
|
|
string_typesig.push("t"+j)
|
|
string_typesig.push("r"+j+".join()")
|
|
proc_args.push("array" + j + ".data")
|
|
proc_args.push("array" + j + ".stride")
|
|
proc_args.push("array" + j + ".offset|0")
|
|
if (i>0) { // Gather conditions to check for shape equality (ignoring block indices)
|
|
shapeLengthConditions.push("array" + proc.arrayArgs[0] + ".shape.length===array" + j + ".shape.length+" + (Math.abs(proc.arrayBlockIndices[0])-Math.abs(proc.arrayBlockIndices[i])))
|
|
shapeConditions.push("array" + proc.arrayArgs[0] + ".shape[shapeIndex+" + Math.max(0,proc.arrayBlockIndices[0]) + "]===array" + j + ".shape[shapeIndex+" + Math.max(0,proc.arrayBlockIndices[i]) + "]")
|
|
}
|
|
}
|
|
// Check for shape equality
|
|
if (proc.arrayArgs.length > 1) {
|
|
code.push("if (!(" + shapeLengthConditions.join(" && ") + ")) throw new Error('cwise: Arrays do not all have the same dimensionality!')")
|
|
code.push("for(var shapeIndex=array" + proc.arrayArgs[0] + ".shape.length-" + Math.abs(proc.arrayBlockIndices[0]) + "; shapeIndex-->0;) {")
|
|
code.push("if (!(" + shapeConditions.join(" && ") + ")) throw new Error('cwise: Arrays do not all have the same shape!')")
|
|
code.push("}")
|
|
}
|
|
// Process scalar arguments
|
|
for(var i=0; i<proc.scalarArgs.length; ++i) {
|
|
proc_args.push("scalar" + proc.scalarArgs[i])
|
|
}
|
|
// Check for cached function (and if not present, generate it)
|
|
vars.push(["type=[", string_typesig.join(","), "].join()"].join(""))
|
|
vars.push("proc=CACHED[type]")
|
|
code.push("var " + vars.join(","))
|
|
|
|
code.push(["if(!proc){",
|
|
"CACHED[type]=proc=compile([", typesig.join(","), "])}",
|
|
"return proc(", proc_args.join(","), ")}"].join(""))
|
|
|
|
if(proc.debug) {
|
|
console.log("-----Generated thunk:\n" + code.join("\n") + "\n----------")
|
|
}
|
|
|
|
//Compile thunk
|
|
var thunk = new Function("compile", code.join("\n"))
|
|
return thunk(compile.bind(undefined, proc))
|
|
}
|
|
|
|
module.exports = createThunk
|
|
|