vectorious-plus
Version:
A high performance linear algebra library.
397 lines (320 loc) • 12.7 kB
JavaScript
(function() {
'use strict';
var assert = require('assert'),
Vector = require('../vector'),
Matrix = require('../matrix');
describe('Vector', function() {
describe('Vector.randomNormal()', function() {
it('should generate true normal distribution', function() {
//https://docs.scipy.org/doc/numpy/reference/generated/numpy.random.normal.html
var sigma = 0.1, mu = 0;
var a = Vector.randomNormal(1000, sigma, mu);
var sum = a.reduce(function (sum, value) {
return sum + value;
});
var mean = sum / a.length;
var squareDiffs = a.map(function(value){
var diff = value - mean;
var sqrDiff = diff * diff;
return sqrDiff;
});
var avgSquareDiff = squareDiffs.reduce(function (sum, value) {
return sum + value;
}) / squareDiffs.length;
var stdDev = Math.sqrt(avgSquareDiff);
var d1 = Math.abs(mu - mean);
var d2 = Math.abs(sigma - stdDev);
assert(d1 < 0.01, d1 + " < 0.01");
assert(d2 < 0.01, d2 + " < 0.01");
});
});
describe('Vector.add(a, b)', function() {
it('should work as the static equivalent of a.add(b)', function() {
var a = new Vector([1, 1, 1]);
var b = new Vector([1, 2, 3]);
assert.deepEqual(new Vector(a).add(b), Vector.add(a, b));
});
});
describe('Vector.subtract(a, b)', function() {
it('should work as the static equivalent of a.subtract(b)', function() {
var a = new Vector([2, 3, 4]);
var b = new Vector([1, 2, 3]);
assert.deepEqual(new Vector(a).subtract(b), Vector.subtract(a, b));
});
});
describe('Vector.dot(a, b)', function() {
it('should work as the static equivalent of a.dot(b)', function() {
var a = new Vector([2, 3, 4]);
var b = new Vector([1, 2, 3]);
assert.deepEqual(new Vector(a).dot(b), Vector.dot(a, b));
});
});
describe('Vector.scale(a, scalar)', function() {
it('should work as the static equivalent of a.scale(scalar)', function() {
var a = new Vector([2, 3, 4]);
assert.deepEqual(new Vector(a).scale(5), Vector.scale(a, 5));
});
});
describe('Vector.angle(a, b)', function() {
it('should work as the static equivalent of a.angle(b)', function() {
var a = new Vector([0, 1, 0]);
var b = new Vector([1, 0, 1]);
assert.deepEqual(new Vector(a).angle(b), Vector.angle(a, b));
});
});
describe('Vector.equals(a, b)', function() {
it('should work as the static equivalent of a.equals(b)', function() {
var a = new Vector([0, 1, 0]);
var b = new Vector([1, 0, 1]);
assert.deepEqual(new Vector(a).equals(b), Vector.equals(a, b));
});
});
describe('Vector.combine(a, b)', function() {
it('should work as the static equivalent of a.combine(b)', function() {
var a = new Vector([0, 1, 0]);
var b = new Vector([1, 0, 1]);
assert.deepEqual(new Vector(a).combine(b), Vector.combine(a, b));
});
});
describe('Vector.zeros()', function() {
it('should throw error if argument < 0', function() {
assert.throws(Vector.zeros.bind(new Vector(), -1), Error);
});
it('should return empty vector if argument === 0', function() {
assert.deepEqual(new Vector(), Vector.zeros(0));
});
it('should create Vector(0, 0, 0)', function() {
assert.deepEqual(new Vector([0, 0, 0]), Vector.zeros(3));
});
});
describe('Vector.ones()', function() {
it('should throw error if argument < 0', function() {
assert.throws(Vector.ones.bind(new Vector(), -1), Error);
});
it('should return empty vector if argument === 0', function() {
assert.deepEqual(new Vector(), Vector.ones(0));
});
it('should create Vector(1, 1, 1)', function() {
assert.deepEqual(new Vector([1, 1, 1]), Vector.ones(3));
});
});
describe('Vector.prototype', function() {
describe('.add()', function() {
it('should return empty vector if adding two empty vectors', function() {
var a = new Vector();
var b = new Vector();
assert.deepEqual(new Vector(), a.add(b));
});
it('should throw error if sizes do not match', function() {
var a = new Vector([1]);
var b = new Vector([1, 2]);
assert.throws(a.add.bind(a, b), Error);
});
it('should produce Vector(5, 7, 9) from Vector(1, 2, 3) and Vector(4, 5, 6)', function() {
var a = new Vector([1, 2, 3]);
var b = new Vector([4, 5, 6]);
var c = new Vector([5, 7, 9]);
assert.deepEqual(c, a.add(b));
});
});
describe('.subtract()', function() {
it('should return empty vector if subtracting two empty vectors', function() {
var a = new Vector();
var b = new Vector();
assert.deepEqual(new Vector(), a.subtract(b));
});
it('should throw error if sizes do not match', function() {
var a = new Vector([1]);
var b = new Vector([1, 2]);
assert.throws(a.subtract.bind(a, b), Error);
});
it('should produce Vector(-3, -3, -3) from Vector(1, 2, 3) and Vector(4, 5, 6)', function() {
var a = new Vector([1, 2, 3]);
var b = new Vector([4, 5, 6]);
var c = new Vector([-3, -3, -3]);
assert.deepEqual(c, a.subtract(b));
});
});
describe('.scale()', function() {
it('should scale Vector(1, 2, 3) by 2 to Vector(2, 4, 6)', function() {
var a = new Vector([1, 2, 3]);
var b = new Vector([2, 4, 6]);
assert.deepEqual(b, a.scale(2));
});
});
describe('.normalize()', function() {
it('should work as expected', function() {
var a = new Vector([1, 1]);
var b = new Vector([1 / Math.sqrt(2), 1 / Math.sqrt(2)]);
assert.deepEqual(b, a.normalize());
});
});
describe('.project()', function() {
it('should throw error if sizes do not match', function() {
var a = new Vector([1]);
var b = new Vector([1, 2]);
assert.throws(a.project.bind(a, b), Error);
});
it('should work as expected', function() {
var a = new Vector([2, 1]);
var b = new Vector([-3, 4]);
var c = new Vector([6 / 25, -8 / 25]);
assert.deepEqual(c, a.project(b));
});
});
describe('.range()', function() {
it('should throw error if wrong number or arguments supplied', function() {
assert.throws(Vector.range.bind(new Vector(), 1), Error);
assert.throws(Vector.range.bind(new Vector(), 1, 2, 3, 4), Error);
});
it('should throw error if step > start - end', function() {
assert.throws(Vector.range.bind(new Vector(), 0, 0), Error);
assert.throws(Vector.range.bind(new Vector(), 1, 3, 2), Error);
});
it('should work as expected', function() {
var a = Vector.range(0, 5);
var b = Vector.range(5, 2, 10);
var c = Vector.range(5, 0);
var d = Vector.range(5, 2, 0);
assert.deepEqual(new Vector([0, 1, 2, 3, 4]), a);
assert.deepEqual(new Vector([5, 7, 9]), b);
assert.deepEqual(new Vector([5, 4, 3, 2, 1]), c);
assert.deepEqual(new Vector([5, 3, 1]), d);
});
});
describe('.dot()', function() {
it('should throw error if sizes do not match', function() {
var a = new Vector([1]);
var b = new Vector([1, 2]);
assert.throws(a.dot.bind(a, b), Error);
});
it('should work as expected', function() {
var a = new Vector([1, 2, 3]);
var b = new Vector([4, 5, 6]);
assert.equal(32, a.dot(b));
});
});
describe('.magnitude()', function() {
it('should return 0 if empty vector', function() {
assert.equal(0, new Vector().magnitude());
});
it('should work as expected', function() {
assert.equal(4, new Vector([1, 1, 1, 2, 3]).magnitude());
});
});
describe('.angle()', function() {
it('should work as expected', function() {
var a = new Vector([1, 0]);
var b = new Vector([0, 1]);
assert.equal(Math.PI / 2, a.angle(b));
});
});
describe('.equals()', function() {
it('should work as expected', function() {
assert.equal(true, new Vector([1, 3, 2]).equals(new Vector([1, 3, 2])));
assert.equal(true, new Vector().equals(new Vector()));
assert.equal(false, new Vector([1, 2, 3]).equals(new Vector([1, 3, 2])));
});
});
describe('.get()', function() {
it('should throw error if index out of bounds', function() {
var a = new Vector([1, 2, 3]);
assert.throws(a.get.bind(a, -1), Error);
assert.throws(a.get.bind(a, 3), Error);
});
it('should work as expected', function() {
var a = new Vector([1, 3, 2, 4]);
assert.equal(1, a.get(0));
assert.equal(3, a.get(1));
assert.equal(2, a.get(2));
assert.equal(4, a.get(3));
});
});
describe('.min()', function() {
it('should find the minimum number in vectors', function() {
var a = new Vector([1, 2, 3]);
var b = new Vector([3, -1, 1]);
var c = new Vector([2, 5, 1]);
assert.equal(1, a.min());
assert.equal(-1, b.min());
assert.equal(1, c.min());
});
});
describe('.max()', function() {
it('should find the maximum number in vectors', function() {
var a = new Vector([1, 2, 3]);
var b = new Vector([3, -1, 1]);
var c = new Vector([2, 5, 1]);
assert.equal(3, a.max());
assert.equal(3, b.max());
assert.equal(5, c.max());
});
});
describe('.set()', function() {
it('should throw error if index out of bounds', function() {
var a = new Vector([1, 2]);
assert.throws(a.set.bind(a, -1, 0), Error);
assert.throws(a.set.bind(a, 2, 0), Error);
});
it('should work as expected', function() {
var a = new Vector([1, 2]);
a.set(0, 0);
a.set(1, 1);
assert.equal(0, a.get(0));
assert.equal(1, a.get(1));
});
});
describe('.combine()', function() {
it('should return current vector if combined with empty vector', function() {
assert.deepEqual(new Vector([1, 2, 3]), new Vector([1, 2, 3]).combine(new Vector()));
});
it('should work as expected', function() {
assert.deepEqual(new Vector([1, 2, 3, 0, 1]), new Vector([1, 2, 3]).combine(new Vector([0, 1])));
});
});
describe('.push()', function() {
it('should start with Vector(1, 2), push(3) to get Vector(1, 2, 3)', function() {
assert.deepEqual(new Vector([1, 2, 3]), new Vector([1, 2]).push(3));
});
});
describe('.map()', function() {
it('should work as expected', function() {
var a = new Vector([1, 2, 3]);
var b = a.map(function(value) { return value * value; });
assert.deepEqual(new Vector([1, 4, 9]), b);
});
});
describe('.each()', function() {
it('should work as expected', function() {
var a = new Vector([1, 2, 3]);
var b = new Vector();
a.each(function(value, index) {
b.push(value * index);
});
assert.deepEqual(new Vector([0, 2, 6]), b);
});
});
describe('.reduce()', function() {
it('should work as expected', function() {
function sum(a, b) {
return a + b;
}
var a = new Vector([1, 2, 3]);
var b = new Vector([1, 2, 3, 4, 5, 6]);
assert.deepEqual(6, a.reduce(sum));
assert.deepEqual(21, b.reduce(sum));
});
});
describe('.toString()', function() {
it('should work as expected', function() {
assert.equal('[1, 2, 3]', new Vector([1, 2, 3]).toString());
});
});
describe('.toArray()', function() {
it('should work as expected', function() {
assert.deepEqual([1, 2, 3], new Vector([1, 2, 3]).toArray());
});
});
});
});
})();