Comparing version 0.0.0 to 0.1.0
@@ -0,21 +1,18 @@ | ||
//Import libraries | ||
var cwise = require("../index.js") | ||
, ndarray = require("ndarray") | ||
var moments = cwise("array") | ||
.begin(function() { | ||
this.moments = [0,0,0] | ||
this.stuff = 0 | ||
//Create operation | ||
var addeq = cwise({ | ||
args: ["array", "array"], | ||
body: function(a, b) { | ||
a += b | ||
} | ||
}) | ||
.body(function(a) { | ||
this .moments[0] += 1; | ||
this .moments[1] += a; | ||
this.moments[2] += a*a; | ||
}) | ||
.end(function() { | ||
return this.moments | ||
}) | ||
.compile({ printCode: true }) | ||
//Create two 2D arrays | ||
var X = ndarray.zeros([128,128]) | ||
var Y = ndarray.zeros([128,128]) | ||
var array = require("ndarray").zeros([128,128]) | ||
console.log(moments(array)) | ||
//Add them together | ||
addeq(X, Y) |
105
index.js
"use strict" | ||
var compile = require("./lib/compile.js") | ||
var Parser = require("./lib/parser.js") | ||
, createShim = require("./lib/shim.js") | ||
function Builder(args) { | ||
this._args = args | ||
this._pre = null | ||
this._body = null | ||
this._post = null | ||
this._options = {} | ||
} | ||
var REQUIRED_FIELDS = [ "args", "body" ] | ||
var OPTIONAL_FIELDS = [ "pre", "post", "unroll", "printCode" ] | ||
Builder.prototype.begin = function(func) { | ||
this._pre = func | ||
return this | ||
function CompiledProcedure() { | ||
this.numArgs = 0 | ||
this.numArrayArgs = 0 | ||
this.numScalarArgs = 0 | ||
this.hasIndex = false | ||
this.hasShape = false | ||
this.hasReturn = false | ||
this.pre = "" | ||
this.body = "" | ||
this.post = "" | ||
this.unroll = 1 | ||
this.printCode = false | ||
} | ||
Builder.prototype.body = function(func) { | ||
this._body = func | ||
return this | ||
function compile(user_args) { | ||
for(var id in user_args) { | ||
if(REQUIRED_FIELDS.indexOf(id) < 0 && | ||
OPTIONAL_FIELDS.indexOf(id) < 0) { | ||
throw new Error("Unknown argument '"+id+"' passed to expression compiler") | ||
} | ||
} | ||
for(var i=0; i<REQUIRED_FIELDS.length; ++i) { | ||
if(!user_args[REQUIRED_FIELDS[i]]) { | ||
throw new Error("Missing argument: " + REQUIRED_FIELDS[i]) | ||
} | ||
} | ||
//Parse arguments | ||
var proc = new CompiledProcedure() | ||
var proc_args = user_args.args.slice(0) | ||
var shim_args = [] | ||
for(var i=0; i<proc_args.length; ++i) { | ||
switch(proc_args[i]) { | ||
case "array": | ||
shim_args.push("array" + proc.numArrayArgs) | ||
proc_args[i] += (proc.numArrayArgs++) | ||
break | ||
case "scalar": | ||
shim_args.push("scalar" + proc.numScalarArgs) | ||
proc_args[i] += (proc.numScalarArgs++) | ||
break | ||
case "index": | ||
proc.hasIndex = true | ||
break | ||
case "shape": | ||
proc.hasShape = true | ||
break | ||
default: | ||
throw new Error("Unknown argument types") | ||
} | ||
} | ||
if(proc.numArrayArgs <= 0) { | ||
throw new Error("No array arguments specified") | ||
} | ||
//Parse blocks | ||
var parser = new Parser(proc_args) | ||
, pre = user_args.pre || null | ||
, body = user_args.body | ||
, post = user_args.post || null | ||
parser.preprocess(pre) | ||
parser.preprocess(body) | ||
parser.preprocess(post) | ||
proc.pre = parser.preBlock() + "\n" + parser.process(pre) | ||
proc.body = parser.process(body) | ||
proc.post = parser.process(post) + "\n" + parser.postBlock() | ||
proc.hasReturn = parser.hasReturn | ||
//Parse options | ||
proc.unroll = user_args.unroll || 1 | ||
proc.printCode = user_args.printCode || false | ||
//Assemble shim | ||
return createShim(shim_args, proc) | ||
} | ||
Builder.prototype.end = function(func) { | ||
this._post = func | ||
return this | ||
} | ||
Builder.prototype.compile = function(options) { | ||
this._options = options || {} | ||
return compile(this) | ||
} | ||
function makeBuilder() { | ||
return new Builder(Array.prototype.slice.call(arguments, 0)) | ||
} | ||
module.exports = makeBuilder | ||
module.exports = compile |
@@ -83,3 +83,3 @@ "use strict" | ||
if(node.parent.type === "MemberExpression") { | ||
if(node.parent.property === node || | ||
if((node.parent.property === node && !node.parent.computed) || | ||
node.parent.object.type === "ThisExpression") { | ||
@@ -86,0 +86,0 @@ return |
@@ -13,2 +13,13 @@ "use strict" | ||
Shim.prototype.checkShape = function(a, b) { | ||
if(a.length !== b.length) { | ||
throw new Error("Shape mismatch") | ||
} | ||
for(var i=a.length-1; i>=0; --i) { | ||
if(a[i] !== b[i]) { | ||
throw new Error("Shape mismatch") | ||
} | ||
} | ||
} | ||
Shim.prototype.getStack = function(size) { | ||
@@ -57,3 +68,6 @@ if(size < STACK.length) { | ||
var code = ["\"use strict\""], i | ||
//Check shapes | ||
for(i=1; i<procedure.numArrayArgs; ++i) { | ||
code.push("this.checkShape(array0.shape,array"+i+".shape)") | ||
} | ||
//Load/lazily generate procedure based on array ordering | ||
@@ -65,3 +79,2 @@ code.push("var proc = this.getProc([") | ||
code.push("])") | ||
//Call procedure | ||
@@ -74,3 +87,2 @@ if(procedure.hasReturn) { | ||
code.push("this.getStack(" + procedure.numArrayArgs + "*(array0.shape.length*32)), array0.shape.slice(0)") | ||
//Bind array arguments | ||
@@ -82,3 +94,2 @@ for(i=0; i<procedure.numArrayArgs; ++i) { | ||
} | ||
//Bind scalar arguments | ||
@@ -89,3 +100,2 @@ for(var i=0; i<procedure.numScalarArgs; ++i) { | ||
code.push(")") | ||
if(!procedure.hasReturn) { | ||
@@ -92,0 +102,0 @@ code.push("return array0") |
{ | ||
"name": "cwise", | ||
"version": "0.0.0", | ||
"version": "0.1.0", | ||
"description": "Component-wise map/reduce for ndarrays", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
121
README.md
@@ -19,7 +19,8 @@ cwise | ||
//Create operation | ||
var addeq = cwise("array", "array") | ||
.body(function(a, b) { | ||
a += b | ||
var addeq = cwise({ | ||
args: ["array", "array"], | ||
body: function(a, b) { | ||
a += b | ||
} | ||
}) | ||
.compile() | ||
@@ -44,2 +45,38 @@ //Create two 2D arrays | ||
`require("cwise")(user_args)` | ||
----------------------------- | ||
To use the library, you pass it an object with the following fields: | ||
* `args`: (Required) An array describing the type of the arguments passed to the body. These may be one of the following: | ||
+ `"array"`: An `ndarray`-type argument | ||
+ `"scalar"`: A globally broadcasted scalar argument | ||
+ `"index"`: (Hidden) An array representing the current index of the element being processed. Initially [0,0,...] in the pre block and set to some undefined value in the post block. | ||
+ `"shape"`: (Hidden) An array representing the shape of the arrays being processed | ||
* `pre`: A function to be executed before starting the loop | ||
* `body`: (Required) A function that gets applied to each element of the input arrays | ||
* `post`: Executed when loop completes | ||
The result is a procedure that you can call which executes these methods along the following lines: | ||
```javascript | ||
function(a0, a1, ...) { | ||
pre() | ||
for(var i=0; i<a0.shape[0]; ++i) { | ||
for(var j=0; j<a0.shape[1]; ++j) { | ||
... | ||
body(a0[i,j,...], a1[i,j,...], ... ) | ||
} | ||
} | ||
post() | ||
} | ||
``` | ||
### Notes | ||
* To pass variables between the pre/body/post, use `this.*` | ||
* The order in which variables get visited depends on the stride ordering if the input arrays. In general it is not safe to assume that elements get visited (co)lexicographically. | ||
* If no return statement is specified, the first ndarray argument is returned | ||
* All input arrays must have the same shape. If not, then the library will throw an error | ||
Examples | ||
@@ -51,7 +88,8 @@ ======== | ||
```javascript | ||
var muls = cwise("array", "scalar") | ||
.body(function(a, s) { | ||
var muls = cwise({ | ||
args: ["array", "scalar"], | ||
body: function(a, s) { | ||
a *= s | ||
}) | ||
.compile() | ||
} | ||
}) | ||
@@ -64,7 +102,8 @@ //Example usage: | ||
```javascript | ||
var mgrid = cwise("index", "array") | ||
.body(function(i, a) { | ||
var mgrid = cwise({ | ||
args: ["index", "array"], | ||
body: function(i, a) { | ||
a = i[0] | ||
}) | ||
.compile() | ||
} | ||
}) | ||
@@ -77,12 +116,13 @@ //Example usage: | ||
```javascript | ||
var any = cwise("array") | ||
.begin(function(a) { | ||
var any = cwise({ | ||
args: ["array"], | ||
body: function(a) { | ||
if(a) { | ||
return true | ||
} | ||
}) | ||
.end(function() { | ||
}, | ||
post: function() { | ||
return false | ||
}) | ||
.compile() | ||
} | ||
}) | ||
@@ -97,7 +137,8 @@ //Usage | ||
```javascript | ||
var lap_op = cwise("array", "array", "array", "array", "array", "array") | ||
.body(function(a, c, n, s, e, w) { | ||
var lap_op = cwise({ | ||
args: ["array", "array", "array", "array", "array", "array"], | ||
body: function(a, c, n, s, e, w) { | ||
a = 0.25 * (n + s + e + w) - c | ||
}) | ||
.compile() | ||
} | ||
}) | ||
@@ -119,13 +160,14 @@ function laplacian(dest, src) { | ||
```javascript | ||
var sum = cwise("array") | ||
.begin(function() { | ||
var sum = cwise({ | ||
args: ["array"], | ||
pre: function() { | ||
this.sum = 0 | ||
}) | ||
.body(function(a) { | ||
}, | ||
body: function(a) { | ||
this.sum += a | ||
}) | ||
.end(function() { | ||
}, | ||
post: function() { | ||
return this.sum | ||
}) | ||
.compile() | ||
} | ||
}) | ||
@@ -140,8 +182,9 @@ //Usage: | ||
```javascript | ||
var argmin = cwise("index", "a") | ||
.begin(function(index) { | ||
this.min_v = a | ||
var argmin = cwise({ | ||
args: ["index", "array"], | ||
pre: function(index) { | ||
this.min_v = Number.POSITIVE_INFINITY | ||
this.min_index = index.slice(0) | ||
}) | ||
.body(function(index, a) { | ||
}, | ||
body: function(index, a) { | ||
if(a < this.min_v) { | ||
@@ -153,7 +196,7 @@ this.min_v = a | ||
} | ||
}) | ||
.end(function() { | ||
}, | ||
post: function() { | ||
return this.min_index | ||
}) | ||
.compile() | ||
} | ||
}) | ||
@@ -160,0 +203,0 @@ //Usage: |
@@ -7,6 +7,9 @@ var cwise = require("../index.js") | ||
var binary = cwise(function(a,b,t,s,idx) { | ||
t.equals(a, 0, "idx:"+idx+", shape:"+s) | ||
a = b + 1001 | ||
}, { scalars: [2,3], index: 4 }) | ||
var binary = cwise({ | ||
args: ["array", "array", "scalar", "shape", "index"], | ||
body: function(a,b,t,s,idx) { | ||
t.equals(a, 0, "idx:"+idx+", shape:"+s) | ||
a = b + 1001 | ||
} | ||
}) | ||
@@ -13,0 +16,0 @@ function testBinary1D(P, Q) { |
@@ -7,4 +7,7 @@ var cwise = require("../index.js") | ||
var unary = cwise(function(a) { | ||
++a | ||
var unary = cwise({ | ||
args: ["array"], | ||
body: function(a) { | ||
++a | ||
} | ||
}) | ||
@@ -11,0 +14,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
26334
739
212