vectorious-plus
Version:
A high performance linear algebra library.
216 lines (190 loc) • 6.36 kB
JavaScript
(function () {
'use strict';
var Vector = require('./vector'),
Matrix = require('./matrix');
try {
var nblas = require('nblas-plus');
} catch (error) {
return;
}
var nodeCleanup = require('node-cleanup');
nodeCleanup(function() {
SpMatrix.handles.forEach(function(h, i) {
nblas.usds(h);
});
SpMatrix.handles = [];
});
/**
* @method constructor
* @desc Creates a `SpMatrix` from the supplied arguments.
**/
function SpMatrix () {
this.type = SpMatrix.defaultType;
this.shape = [];
this.handle = 0;
this.nz = 0;
}
/**
* Holds all active handles
* Should be released on process exit
*/
SpMatrix.handles = [];
/**
* Default type for data
**/
SpMatrix.defaultType = Float64Array;
/**
*
**/
SpMatrix.prototype.beginConstruction = function (options) {
if (this.handle)
throw new Error("Handle is already created");
if (!options.shape)
throw new Error("No shape specified");
this.shape = options.shape;
if (options.type)
this.type = options.type;
this.handle = nblas.uscr_begin(this.type == Float64Array, options.shape[0], options.shape[1]);
SpMatrix.handles.push(this.handle);
};
/**
*
**/
SpMatrix.prototype.addEntry = function (val, i, j) {
nblas.uscr_insert_entry(this.handle, val, i, j);
};
/**
*
**/
SpMatrix.prototype.addEntries = function (vals, indx, jndx) {
if (vals instanceof Array)
vals = new this.type(vals);
if (indx instanceof Array)
indx = new Int32Array(indx);
if (jndx instanceof Array)
jndx = new Int32Array(jndx);
var nz = vals.length;
if (!(vals.length == indx.length && indx.length == jndx.length))
throw new Error("Sizes of input arrays diesn't match");
if (!(vals instanceof this.type))
throw new Error("Incorrect type of vals array, should match one specified at construction");
nblas.uscr_insert_entries(this.handle, nz, vals, indx, jndx);
};
/**
*
**/
SpMatrix.prototype.addCol = function (j, vals, indx) {
if (vals instanceof Array)
vals = new this.type(vals);
if (indx instanceof Array)
indx = new Int32Array(indx);
var nz = vals.length;
if (!(vals.length == indx.length))
throw new Error("Sizes of input arrays diesn't match");
if (!(vals instanceof this.type))
throw new Error("Incorrect type of vals array, should match one specified at construction");
nblas.uscr_insert_col(this.handle, j, nz, vals, indx);
};
/**
*
**/
SpMatrix.prototype.addRow = function (i, vals, jndx) {
if (vals instanceof Array)
vals = new this.type(vals);
if (jndx instanceof Array)
jndx = new Int32Array(jndx);
var nz = vals.length;
if (!(vals.length == jndx.length))
throw new Error("Sizes of input arrays diesn't match");
if (!(vals instanceof this.type))
throw new Error("Incorrect type of vals array, should match one specified at construction");
nblas.uscr_insert_row(this.handle, i, nz, vals, jndx);
};
/**
*
**/
SpMatrix.prototype.endConstruction = function () {
nblas.uscr_end(this.handle);
};
/**
* Multiplies sparse matrix `a` and dense matrix/vector `b` of aligned dimensions.
* this - sparse matrix, size m x n
* @param {Matrix/Vector} dense matrix n x k or vector with length n
* @param {Matrix/Vector} res optional, dense matrix with size m x k or
* vector with length m to hold result of product of `a` and `b`
* If not present, will be created
* @returns {Matrix/Vector} dense matrix with size m x k or vector with length m
* containing the matrix product of `a` and `b`
**/
SpMatrix.prototype.multiply = function (b, res) {
if (b instanceof Matrix)
return this.multiplyMatrix(b, res);
else if (b instanceof Vector)
return this.multiplyVector(b, res);
else
throw new Error("Unsupported type of b");
}
/**
* Multiplies sparse matrix `a` and dense matrix `b` of aligned dimensions.
* this - sparse matrix, size m x n
* @param {Matrix} dense matrix, size n x k
* @param {Matrix} res optional, dense matrix with size m x k
* to hold result of product of `a` and `b`
* If not present, will be created
* @returns {Matrix} resultant dense matrix with size m x k
* containing the matrix product of `a` and `b`
**/
SpMatrix.prototype.multiplyMatrix = function (matrix, res) {
if (matrix.type != this.type)
throw new Error('types are different');
var r1 = this.shape[0], // rows in this matrix
c1 = this.shape[1], // columns in this matrix
r2 = matrix.shape[0], // rows in multiplicand
c2 = matrix.shape[1]; // columns in multiplicand
if (c1 !== r2)
throw new Error('sizes are not aligned');
if (res === undefined)
res = Matrix.fromTypedArray(new this.type(r1 * c2), [r1, c2]);
nblas.usmm(this.handle, matrix.data, res.data, c2);
return res;
};
/**
* Multiplies sparse matrix `a` and dense vector `b` of aligned dimensions.
* this - sparse matrix, size m x n
* @param {Vector} dense vector, length n
* @param {Vector} res optional, dense vector with length m
* to hold result of product of `a` and `b`
* If not present, will be created
* @returns {Vector} resultant dense vector with length m
* containing the matrix product of `a` and `b`
**/
SpMatrix.prototype.multiplyVector = function (vector, res) {
if (vector.type != this.type)
throw new Error('types are different');
var r = this.shape[0], // rows in this matrix
c = this.shape[1], // columns in this matrix
l = vector.length; // length of vector
if (c !== l)
throw new Error('sizes are not aligned');
if (res === undefined)
res = Vector.fromTypedArray(new this.type(r), r);
nblas.usmv(this.handle, vector.data, res.data);
return res;
};
/**
*
**/
SpMatrix.prototype.destroy = function () {
nblas.usds(this.handle);
var ind = SpMatrix.handles.indexOf(this.handle);
if (ind != -1)
SpMatrix.handles.splice(ind, 1);
this.handle = 0;
this.nz = 0;
this.shape = [];
};
module.exports = SpMatrix;
try {
window.SpMatrix = SpMatrix;
} catch (e) {}
}());