diff --git a/applyBlasOptimizations.js b/applyBlasOptimizations.js new file mode 100644 index 00000000..71d7ceb5 --- /dev/null +++ b/applyBlasOptimizations.js @@ -0,0 +1,68 @@ +module.exports = function(Vector, Matrix, nblas) { + 'use strict'; + + // BLAS optimizations + Vector.prototype.add = + Matrix.prototype.add = function (data) { + var l1 = this instanceof Vector ? this.length : this.shape[0] * this.shape[1], + l2 = data instanceof Vector ? data.length : data.shape[0] * data.shape[1]; + if (l1 !== l2) + throw new Error('sizes do not match!'); + if (!l1 && !l2) + return this; + + nblas.axpy(data.data, this.data); + return this; + }; + + Vector.prototype.subtract = + Matrix.prototype.subtract = function (data) { + var l1 = this instanceof Vector ? this.length : this.shape[0] * this.shape[1], + l2 = data instanceof Vector ? data.length : data.shape[0] * data.shape[1]; + if (l1 !== l2) + throw new Error('sizes do not match!'); + if (!l1 && !l2) + return this; + + nblas.axpy(data.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 (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.idamax(this.length, this.data, 1)]; + }; + + Matrix.prototype.multiply = function(matrix) { + var r1 = this.shape[0], + c1 = this.shape[1], + r2 = matrix.shape[0], + c2 = matrix.shape[1], + data = new this.type(r1 * c2); + + if (c1 !== r2) + throw new Error('sizes do not match'); + + nblas.gemm(this.data, matrix.data, data, r1, c2, c1); + return Matrix.fromTypedArray(data, [r1, c2]); + }; +}; diff --git a/package.json b/package.json index 0bd1df8b..c51bd350 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "A high performance linear algebra library.", "main": "vectorious.js", "scripts": { - "test": "./node_modules/mocha/bin/mocha", + "test": "mocha", "benchmark": "node ./benchmarks/vector.js && node ./benchmarks/matrix.js", "coverage": "istanbul cover _mocha -- -R spec" }, @@ -19,6 +19,9 @@ "algebra" ], "author": "Mateo Gianolio", + "contributors": [ + "Bart van Andel " + ], "license": "MIT", "bugs": { "url": "https://github.com/mateogianolio/vectorious/issues" @@ -28,7 +31,7 @@ "benchmark": "^2.1.0", "mocha": "^2.4.5" }, - "dependencies": { + "peerDependencies": { "nblas": "^1.2.0" } } diff --git a/vectorious.js b/vectorious.js index 1bdc817e..b9d2c543 100644 --- a/vectorious.js +++ b/vectorious.js @@ -1,82 +1,15 @@ (function () { 'use strict'; - var Vector = require('./vector'), - Matrix = require('./matrix'); + var Vector = module.exports.Vector = require('./vector'), + Matrix = module.exports.Matrix = require('./matrix'); + try { - var nblas = require('nblas'); + var nblas = module.exports.BLAS = require('nblas'), + applyBlasOptimizations = require('./applyBlasOptimizations'); + + applyBlasOptimizations(Vector, Matrix, nblas); } catch (error) { - module.exports.Vector = Vector; - module.exports.Matrix = Matrix; - return; - } - - // BLAS optimizations - Vector.prototype.add = - Matrix.prototype.add = function (data) { - var l1 = this instanceof Vector ? this.length : this.shape[0] * this.shape[1], - l2 = data instanceof Vector ? data.length : data.shape[0] * data.shape[1]; - if (l1 !== l2) - throw new Error('sizes do not match!'); - if (!l1 && !l2) - return this; - - nblas.axpy(data.data, this.data); - return this; - }; - - Vector.prototype.subtract = - Matrix.prototype.subtract = function (data) { - var l1 = this instanceof Vector ? this.length : this.shape[0] * this.shape[1], - l2 = data instanceof Vector ? data.length : data.shape[0] * data.shape[1]; - if (l1 !== l2) - throw new Error('sizes do not match!'); - if (!l1 && !l2) - return this; - - nblas.axpy(data.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 (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.idamax(this.length, this.data, 1)]; - }; - - Matrix.prototype.multiply = function(matrix) { - var r1 = this.shape[0], - c1 = this.shape[1], - r2 = matrix.shape[0], - c2 = matrix.shape[1], - data = new this.type(r1 * c2); - - if (c1 !== r2) - throw new Error('sizes do not match'); - - nblas.gemm(this.data, matrix.data, data, r1, c2, c1); - return Matrix.fromTypedArray(data, [r1, c2]); - }; - - module.exports.Vector = Vector; - module.exports.Matrix = Matrix; - module.exports.BLAS = nblas; + } }()); diff --git a/withblas.js b/withblas.js new file mode 100644 index 00000000..aab2f612 --- /dev/null +++ b/withblas.js @@ -0,0 +1,11 @@ +(function () { + 'use strict'; + + var Vector = module.exports.Vector = require('./vector'), + Matrix = module.exports.Matrix = require('./matrix'), + nblas = module.exports.BLAS = require('nblas'), + + applyBlasOptimizations = require('./applyBlasOptimizations'); + + applyBlasOptimizations(Vector, Matrix, nblas); +}()); diff --git a/withoutblas.js b/withoutblas.js new file mode 100644 index 00000000..cfa7483c --- /dev/null +++ b/withoutblas.js @@ -0,0 +1,6 @@ +(function () { + 'use strict'; + + var Vector = module.exports.Vector = require('./vector'), + Matrix = module.exports.Matrix = require('./matrix'); +}());