vectorious-plus
Version:
A high performance linear algebra library.
201 lines (174 loc) • 5.84 kB
JavaScript
(function () {
'use strict';
var Vector = require('./vector'),
Matrix = require('./matrix');
try {
var nblas = require('nblas-plus');
var SpVector = require('./sp_vector'),
SpMatrix = require('./sp_matrix');
} catch (error) {
console.warn("nblas not included!");
module.exports.Vector = Vector;
module.exports.Matrix = Matrix;
return;
}
// BLAS optimizations
Vector.prototype.add =
Matrix.prototype.add = function (b) {
if (b.type != this.type)
throw new Error('types are different');
var l1 = this instanceof Vector ? this.length : this.shape[0] * this.shape[1],
l2 = b instanceof Vector ? b.length : b.shape[0] * b.shape[1];
if (l1 !== l2)
throw new Error('sizes do not match!');
if (!l1 && !l2)
return this;
nblas.axpy(b.data, this.data);
return this;
};
Vector.prototype.subtract =
Matrix.prototype.subtract = function (b) {
if (b.type != this.type)
throw new Error('types are different');
var l1 = this instanceof Vector ? this.length : this.shape[0] * this.shape[1],
l2 = b instanceof Vector ? b.length : b.shape[0] * b.shape[1];
if (l1 !== l2)
throw new Error('sizes do not match!');
if (!l1 && !l2)
return this;
nblas.axpy(b.data, this.data, -1);
return this;
};
Vector.prototype.scale =
Matrix.prototype.scale = function (scalar) {
nblas.scal(this.data, scalar);
return this;
};
Vector.prototype.dot = function (vector) {
if (vector.type != this.type)
throw new Error('types are different');
if (this.length !== vector.length)
throw new Error('sizes do not match!');
return nblas.dot(this.data, vector.data);
};
Vector.prototype.magnitude = function () {
if (!this.length)
return 0;
return nblas.nrm2(this.data);
};
Vector.prototype.max = function() {
return this.data[nblas.iamax(this.data)];
};
Matrix.prototype.multiply = function(matrix, res) {
if (matrix.type != this.type)
throw new Error('types are different');
var r1 = this.shape[0],
c1 = this.shape[1],
r2 = matrix.shape[0],
c2 = matrix.shape[1];
if (res === undefined)
res = Matrix.fromTypedArray(new this.type(r1 * c2), [r1, c2]);
if (c1 !== r2)
throw new Error('sizes do not match');
nblas.gemm(this.data, matrix.data, res.data, r1, c2, c1);
return res;
};
// LAPACK optimizations
Matrix.solveSquare = function (a, b, x, keepA, ipiv) {
var isBVector = (b instanceof Vector);
if (keepA === undefined)
keepA = true;
if (a.type != b.type)
throw new Error('types are different');
var r1 = a.shape[0],
c1 = a.shape[1];
var r2 = isBVector ? b.length : b.shape[0],
c2 = isBVector ? 1 : b.shape[1];
if (c1 !== r2)
throw new Error('shapes are not aligned');
if (r1 != c1)
throw new Error('input matrix should be square');
if (x === undefined)
x = isBVector ? new Vector(b) : new Matrix(b);
else if (b != x) {
var xSize1 = x.data.constructor.BYTES_PER_ELEMENT;
nblas.BufCopy(x.data, 0, b.data, xSize1 * r2 * c2);
}
if (ipiv === undefined)
ipiv = new Int32Array(r1);
var af = keepA ? new Matrix(a) : a;
nblas.gesv(af.data, x.data, r1, c2, ipiv);
return x;
}
// luSquare() + luSolveSquare() is slower than solveSquare() by some reason.. (see benchmark)
Matrix.prototype.luSquare = function (af) {
var m = this.shape[0],
n = this.shape[1];
var ipiv = new Int32Array(Math.min(m, n));
if (af === undefined)
af = new Matrix(this);
nblas.getrf(af.data, ipiv, m, n);
return [af, ipiv];
}
Matrix.luSolveSquare = function (af, ipiv, a, b, x, r, c) {
var isBVector = (b instanceof Vector);
var r1 = a.shape[0],
c1 = a.shape[1];
var r2 = isBVector ? b.length : b.shape[0],
c2 = isBVector ? 1 : b.shape[1];
if (c1 !== r2)
throw new Error('shapes are not aligned');
if (r1 != c1)
throw new Error('input matrix should be square');
if (x === undefined)
x = isBVector ? new Vector(null, {type: b.type, length: b.length})
: new Matrix(null, {type: b.type, shape: b.shape});
nblas.gesvx(a.data, b.data, x.data, r1, c2, af.data, ipiv,
nblas.Lapack.Fact.F, undefined, undefined, r, c);
return x;
}
// Other optimizations
Matrix.prototype.transpose = function (res) {
var r = this.shape[0],
c = this.shape[1];
if (res === undefined)
res = Matrix.fromTypedArray(new this.type(c * r), [c, r]);
nblas.TrTo(this.data, res.data, r, c);
return res;
};
Matrix.prototype.transposed = function () {
var r = this.shape[0],
c = this.shape[1];
nblas.TrIp(this.data, r, c);
this.shape = [c, r];
return this;
};
Vector.prototype.zeros =
Matrix.prototype.zeros = function() {
var isVector = (this instanceof Vector);
var r = isVector ? 1 : this.shape[0],
c = isVector ? this.length : this.shape[1];
var size1 = this.data.constructor.BYTES_PER_ELEMENT;
nblas.BufSet(this.data, 0, +0, size1 * r * c);
return this;
};
Matrix.prototype.diagonal = function(val) {
var r = this.shape[0],
c = this.shape[1];
nblas.MatrixDiagonal(this.data, r, c, val);
return this;
};
Vector.prototype.ones =
Matrix.prototype.ones = function() {
var isVector = (this instanceof Vector);
var r = isVector ? 1 : this.shape[0],
c = isVector ? this.length : this.shape[1];
nblas.MatrixOnes(this.data, r, c, 1.);
return this;
};
module.exports.Vector = Vector;
module.exports.Matrix = Matrix;
module.exports.SpVector = SpVector;
module.exports.SpMatrix = SpMatrix;
module.exports.BLAS = nblas;
}());