Skip to content

Instantly share code, notes, and snippets.

@syg
Created October 30, 2012 00:17
Show Gist options
  • Save syg/3977531 to your computer and use it in GitHub Desktop.
Save syg/3977531 to your computer and use it in GitHub Desktop.
//
// Higher dimensional wrapper with inferred shape for one-dimensional parallel
// arrays.
//
var ParallelMatrix = (function () {
function leafShape(pa) {
var row = pa[0];
if (!(row instanceof ParallelMatrix))
return [];
var infimum = row.shape;
for (var i = 1; i < pa.length; i++) {
row = pa[i];
if (!(row instanceof ParallelMatrix))
return [];
var l = 0;
while (l < infimum.length && row.shape[l] === infimum[l])
l++;
if (l === 0)
return [];
infimum.length = l;
}
return infimum;
}
function partialProducts(shape, d) {
var pp = [];
pp[d - 1] = 1;
for (var i = d - 1; i > 0; i--)
pp[i - 1] = shape[i] * pp[i];
return pp;
}
function ParallelMatrix(shape, f) {
var length = 1;
var iv = [];
for (var i = 0; i < shape.length; i++) {
iv.push(0);
length *= shape[i];
}
var buf = new ParallelArray(length, function (i) {
var v = f.apply(this, iv);
var d = iv.length - 1;
while (++iv[d] === shape[d])
iv[d--] = 0;
return v;
});
// Pretend these are private names.
this._shape = shape.concat(leafShape(buf));
this._buffer = buf;
this._offset = 0;
this._partials = partialProducts(shape, shape.length);
}
ParallelMatrix.prototype = {
get length() {
return this._shape[0];
},
get shape() {
return this._shape.slice();
},
map: function (f) {
return new ParallelMatrix([this.length], function (i) {
return f(this.get(i));
}.bind(this));
},
get: function () {
// Which dimension are we indexing?
var d = arguments.length;
if (d === 0)
return undefined;
var pp = this._partials;
var scalar = arguments[0] * pp[0];
for (var i = 1; i < arguments.length; i++)
scalar += arguments[i] * pp[i];
scalar += this._offset;
// Do we need to recur on the leaf?
if (d > pp.length) {
const Apslice = Array.prototype.slice;
var leaf = this._buffer[scalar];
return leaf.get.apply(leaf, Apslice.call(arguments, pp.length));
}
// Getting a leaf.
if (d === pp.length)
return this._buffer[scalar];
// Getting a row.
var pm = Object.create(ParallelMatrix.prototype);
pm._shape = this._shape.slice(arguments.length);
pm._buffer = this._buffer;
pm._offset = scalar;
pm._partials = partialProducts(pm._shape, pp.length - d);
return pm;
},
toString: function () {
var sb = [];
var buf = this._buffer;
for (var i = this._offset; i < this._partials[0] * this.length + this._offset; i++)
sb.push(buf[i]);
return "<(" + this.shape + "):" + sb.join(",") + ">";
}
};
return ParallelMatrix;
}.call(this));
var acc = 0;
var pm = new ParallelMatrix([2,2], function (i, j) { return acc++; });
var pm2 = pm.map(function (row) { return acc++; });
var pm3 = pm.map(function (row) {
return row.map(function (x) { return x + 1; });
});
print(pm);
print(pm2);
print(pm3);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment