@bluemath/linalg
Version:
Bluemath Linear Algebra library
926 lines (871 loc) • 28.4 kB
text/typescript
/*
Copyright (C) 2017 Jayesh Salvi, Blue Math Software Inc.
This file is part of bluemath.
bluemath is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
bluemath is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with bluemath. If not, see <http://www.gnu.org/licenses/>.
*/
import {isequal,NDArray,Complex} from '@bluemath/common'
import * as linalg from '../src'
export default function testOps() {
QUnit.module('Ops', () => {
QUnit.module('matmul', () => {
QUnit.test("Square 3x3", assert => {
let A = new NDArray([[2,2,2],[2,2,2],[2,2,2]], {datatype:'i16'});
let B = new NDArray([[5,5,5],[5,5,5],[5,5,5]], {datatype:'i16'});
let M = linalg.matmul(A,B);
if(M instanceof NDArray) {
assert.deepEqual(M.shape, [3,3]);
for(let i=0; i<3; i++) {
for(let j=0; j<3; j++) {
assert.equal(M.get(i,j), 30);
}
}
} else {
assert.notOk(true);
}
});
QUnit.test("3x2 mul 2x3", assert => {
let A = new NDArray([[1,0],[2,1],[6,9]], {datatype:'i16'});
let B = new NDArray([[1,2,3],[1,2,9]], {datatype:'i16'});
let M = linalg.matmul(A,B);
if(M instanceof NDArray) {
assert.deepEqual(M.shape, [3,3]);
assert.equal(M.get(1,0), 3);
assert.equal(M.get(1,2), 15);
assert.equal(M.get(2,1), 30);
assert.equal(M.get(2,2), 99);
} else {
assert.notOk(true);
}
});
QUnit.test("3x2 mul 3x3, error", assert => {
let A = new NDArray([[1,0],[2,1],[6,9]], {datatype:'i16'});
let B = new NDArray([[1,2,3],[1,2,9],[4,5,3]], {datatype:'i16'});
assert.throws(() => {
linalg.matmul(A,B);
});
});
QUnit.test("mul by Vector (inner product)", assert => {
let A = new NDArray([[1,0,2]], {datatype:'i16'});
let B = new NDArray([[4,4,9]], {datatype:'i16'});
B.reshape([3,1]);
let M = linalg.matmul(A, B);
assert.deepEqual(M.shape, [1,1]);
assert.equal(M.get(0,0), 22);
});
QUnit.test("mul by Vector, error", assert => {
let A = new NDArray([[1,0,2],[3,5,6]], {datatype:'i16'});
let B = new NDArray([[4,4,9]], {datatype:'i16'});
assert.throws(() => linalg.matmul(A,B));
});
QUnit.test("mul by Vector (outer product)", assert => {
let A = new NDArray([[3,3]], {datatype:'i16'});
A.reshape([2,1]);
let B = new NDArray([[2,2]], {datatype:'i16'});
let M = linalg.matmul(A,B);
assert.deepEqual(M.shape, [2,2]);
assert.equal(M.get(0,0), 6);
assert.equal(M.get(0,1), 6);
assert.equal(M.get(1,0), 6);
assert.equal(M.get(1,1), 6);
});
});
QUnit.module('inner', () => {
QUnit.test('A(3), B(3)', assert => {
let A = new NDArray([3,4,5]);
let B = new NDArray([1,2,5]);
assert.equal(linalg.inner(A,B), 36);
});
QUnit.test('A(3), B(4)', assert => {
let A = new NDArray([3,4,5]);
let B = new NDArray([1,2,5,7]);
assert.equal(linalg.inner(A,B), 36);
});
QUnit.test('A(4), B(3)', assert => {
let A = new NDArray([3,4,5,6]);
let B = new NDArray([1,2,5]);
assert.throws(() => linalg.inner(A,B));
});
});
QUnit.module('outer', () => {
QUnit.test('A(3), B(3)', assert => {
let A = new NDArray([1,1,1]);
let B = new NDArray([1,1,1]);
assert.deepEqual(linalg.outer(A,B).toArray(),[
[1,1,1],[1,1,1],[1,1,1]
]);
});
QUnit.test('A(3x1), B(1x3)', assert => {
let A = new NDArray([[1],[1],[1]]);
let B = new NDArray([1,1,1]);
assert.deepEqual(linalg.outer(A,B).toArray(),[
[1,1,1],[1,1,1],[1,1,1]
]);
});
QUnit.test('A(1x3), B(3x1)', assert => {
let A = new NDArray([1,1,1]);
let B = new NDArray([[1],[1],[1]]);
assert.throws(() => linalg.outer(A,B));
});
});
QUnit.module('norm', () => {
QUnit.module('Vector', () => {
QUnit.test('0-norm', assert => {
let A = new NDArray([0,3,0,5]);
assert.equal(linalg.norm(A,0), 2);
});
QUnit.test('1-norm', assert => {
let A = new NDArray([2,3,4,5]);
assert.equal(linalg.norm(A,1), 14);
});
QUnit.test('2-norm', assert => {
let A = new NDArray([2,3,4,5]);
assert.ok(isequal(linalg.norm(A,2), 7.34847));
});
QUnit.test('3-norm', assert => {
let A = new NDArray([2,3,4,5]);
assert.ok(isequal(linalg.norm(A,3), 6.07318, 1e-4));
});
QUnit.test('Infinity-norm', assert => {
let A = new NDArray([2,3,4,5]);
assert.equal(linalg.norm(A,Infinity), 5);
A = new NDArray([2,3,-48,5]);
assert.equal(linalg.norm(A,Infinity), 48);
});
QUnit.test('-Infinity-norm', assert => {
let A = new NDArray([2,3,4,5]);
assert.equal(linalg.norm(A,-Infinity), 2);
A = new NDArray([2,3,-48,5]);
assert.equal(linalg.norm(A,-Infinity), 2);
});
});
QUnit.module('Matrix', () => {
QUnit.test('Frobenius norm', assert => {
let A = new NDArray([
[2,3,4],
[4,2,-9],
[0,3,1]
]);
assert.ok(isequal(linalg.norm(A, 'fro'),
11.832159566199232, 1e-6));
});
});
});
QUnit.module('lstsq', () => {
QUnit.test('Line fitting 1', assert => {
let Y = new NDArray([-1,0.2,0.9,2.1]);
let A = new NDArray([
[0,1], [1,1], [2,1], [3,1]
]);
let {x,residuals,rank,singulars} = linalg.lstsq(A,Y);
assert.ok(isequal(<number>x.get(0,0),1));
assert.ok(isequal(<number>x.get(1,0),-0.95));
assert.equal(rank, 2);
assert.ok(residuals.isEqual(new NDArray([0.05])));
assert.ok(singulars.isEqual(new NDArray([4.10003045, 1.09075677])));
});
QUnit.test('Line fitting 2', assert => {
let Y = new NDArray([3.9, 2.3, 2, -1.4, -1, -0.1]);
let A = new NDArray([
[-3, 1], [-0.9, 1], [-1.8, 1],
[3.2, 1], [1, 1], [3.3, 1]
]);
let {x,residuals,rank,singulars} = linalg.lstsq(A,Y);
assert.ok(isequal(<number>x.get(0, 0), -0.71853349));
assert.ok(isequal(<number>x.get(1, 0), 1.16556005));
assert.equal(rank, 2);
assert.ok(residuals.isEqual(new NDArray([4.1707015])));
assert.ok(singulars.isEqual(new NDArray([5.94059051, 2.42680538])));
});
});
QUnit.module('slogdet', () => {
QUnit.test('3x3', assert => {
let A = new NDArray([
[4,5,6],
[1,5,3],
[8,4,5]
]);
let [sign,logdet] = linalg.slogdet(A);
assert.equal(sign,-1);
assert.ok(isequal(logdet, Math.log(69)));
});
QUnit.test('2x2', assert => {
let A = new NDArray([
[4,5],
[1,5],
]);
let [sign,logdet] = linalg.slogdet(A);
assert.equal(sign,1);
assert.equal(logdet, Math.log(15));
});
});
QUnit.module('det', () => {
QUnit.test('3x3', assert => {
let A = new NDArray([
[4,5,6],
[1,5,3],
[8,4,5]
]);
let det = linalg.det(A);
assert.ok(isequal(det, -69, 1e-5));
});
QUnit.test('2x2', assert => {
let A = new NDArray([
[4,5],
[1,5],
]);
let det = linalg.det(A);
assert.equal(det, 15);
});
});
QUnit.module('inv', () => {
QUnit.test('2x2', assert => {
let A = new NDArray([
[4,5],
[1,3]
]);
let invA = linalg.inv(A);
assert.ok(invA.isEqual(new NDArray([
[ 0.42857143, -0.71428571],
[-0.14285714, 0.57142857]
])));
});
QUnit.test('3x3 test1', assert => {
let A = new NDArray([
[4,5,6],
[1,5,3],
[8,4,5]
]);
let invA = linalg.inv(A);
assert.ok(invA.isEqual(new NDArray([
[-0.1884058 , 0.01449275, 0.2173913 ],
[-0.27536232, 0.4057971 , 0.08695652],
[ 0.52173913, -0.34782609, -0.2173913 ]
])));
});
QUnit.test('3x3 test2', assert => {
let A = new NDArray([
[4,-5,6],
[1,0,3],
[-8,4,5]
]);
let invA = linalg.inv(A);
assert.ok(invA.isEqual(new NDArray([
[-0.09917355, 0.40495868, -0.12396694],
[-0.23966942, 0.56198347, -0.04958678],
[ 0.03305785, 0.19834711, 0.04132231]
])));
});
});
QUnit.module('rank', () => {
QUnit.test('Full rank 3x3', assert => {
let A = new NDArray([
[3,5,6],[3,2,1],[7,8,16]
]);
assert.equal(linalg.rank(A), 3);
});
QUnit.test('Rank 2 for 3x3', assert => {
let A = new NDArray([
[3,5,6],[3,2,6],[6,8,12]
]);
assert.equal(linalg.rank(A), 2);
});
QUnit.test('Rank 1 for 3x3', assert => {
let A = new NDArray([
[3,5,6],[3,5,6],[6,10,12]
]);
assert.equal(linalg.rank(A), 1);
});
});
QUnit.module('SVD', () => {
QUnit.test(
'svd 3x3 - full_matrices=true, complete_uv=true', assert => {
let A = new NDArray([
[-3,6,-1],
[11,-3,0],
[0,-1,3]
], {datatype:'f32'});
let [U,S,VT] = linalg.svd(A,true,true);
// Results generated from numpy
assert.ok(U.isEqual(new NDArray([
[-0.42847299, -0.81649658, 0.386968],
[0.90241006, -0.40824829, 0.1378021],
[0.04546408, 0.40824829, 0.91173809]
])));
assert.ok(S.isEqual(new NDArray([
12.4244289, 5.0, 2.5755711
])));
assert.ok(VT.isEqual(new NDArray([
[0.90241006, -0.42847299, 0.04546408],
[-0.40824829, -0.81649658, 0.40824829],
[0.1378021, 0.386968, 0.91173809]
])));
});
QUnit.test(
'svd 3x3 - full_matrices=false, complete_uv=false', assert => {
let A = new NDArray([
[-3,6,-1],
[11,-3,0],
[0,-1,3]
], {datatype:'f32'});
let [S] = linalg.svd(A,true,false);
assert.ok(S.isEqual(new NDArray([
12.4244289, 5.0, 2.5755711
])));
});
QUnit.test(
'svd 4x3 - full_matrices=false, complete_uv=false', assert => {
let A = new NDArray([
[-3,6,-1],
[11,-3,0],
[0,-1,3],
[4,4,4]
], {datatype:'f32'});
let [S] = linalg.svd(A,true,false);
assert.ok(S.isEqual(new NDArray([
12.66786356, 7.40286577, 4.32698638
])));
});
QUnit.skip(
'svd 4x3 - full_matrices=true, complete_uv=false', assert => {
let A = new NDArray([
[-3,6,-1],
[11,-3,0],
[0,-1,3],
[4,4,4]
], {datatype:'f32'});
let [U,S,VT] = linalg.svd(A,true,true);
assert.ok(U.isEqual(new NDArray([
[-0.38547869, -0.56023949, 0.51437432, -0.52245282],
[0.89197997, -0.02652779, 0.34920785, -0.28587041],
[0.05307408, -0.03691955, -0.71131891, -0.69988963],
[0.2301327, -0.82708218, -0.3278694, 0.39430402]
])));
assert.ok(S.isEqual(new NDArray([
12.66786356, 7.40286577, 4.32698638
])));
assert.ok(VT.isEqual(new NDArray([
[0.93849657, -0.32533941, 0.11566526],
[-0.25928012, -0.88523323, -0.38618124],
[0.22803071, 0.33244007, -0.91514239]
])));
});
QUnit.test(
'svd 4x3 - full_matrices=false, complete_uv=false', assert => {
let A = new NDArray([
[-3,6,-1],
[11,-3,0],
[0,-1,3],
[4,4,4]
], {datatype:'f32'});
let [U,S,VT] = linalg.svd(A,false,true);
assert.ok(U.isEqual(new NDArray([
[-0.38547869, -0.56023949, 0.51437432],
[0.89197997, -0.02652779, 0.34920785],
[0.05307408, -0.03691955, -0.71131891],
[0.2301327, -0.82708218, -0.3278694]
])));
assert.ok(S.isEqual(new NDArray([
12.66786356, 7.40286577, 4.32698638
])));
assert.ok(VT.isEqual(new NDArray([
[0.93849657, -0.32533941, 0.11566526],
[-0.25928012, -0.88523323, -0.38618124],
[0.22803071, 0.33244007, -0.91514239]
])));
});
});
/*
QUnit.module("Permutation", () => {
QUnit.test("Vector", assert => {
let V = new NDArray([34,65,23,90]);
let p = new NDArray([0,2,3,1]);
linalg.permuteVector(V,p);
assert.ok(V.isEqual(new NDArray([34,23,90,65])));
});
QUnit.test("Vector inverse", assert => {
// Same permutation vector, but used on original
let V = new NDArray([34,65,23,90]);
let p = new NDArray([0,2,3,1]);
linalg.ipermuteVector(V,p);
assert.ok(V.isEqual(new NDArray([34,90,65,23])));
// Same permutation vector, but used on result of first test
V = new NDArray([34,23,90,65]);
p = new NDArray([0,2,3,1]);
linalg.ipermuteVector(V,p);
assert.ok(V.isEqual(new NDArray([34,65,23,90])));
});
});
*/
/*
QUnit.module('LU Decomposition', () => {
QUnit.test('3x3', assert => {
let A = new NDArray([
[3,17,10],
[2,4,-2],
[6,18,-12]
]);
let P = linalg.lu(A);
assert.ok(P.isEqual(new NDArray([2,0,1])));
assert.ok(A.isEqual(new NDArray([
[6,18,-12],
[0.5,8,16],
[0.3333333,-0.25,6]
])));
});
});
*/
QUnit.module('Solve', () => {
QUnit.test('Upper tri', assert => {
let A = new NDArray([
[4,9],
[0,5]
]);
let x = new NDArray([32,10]);
linalg.solve(A,x);
assert.ok(x.isEqual(new NDArray([3.5,2])));
});
QUnit.test('Lower tri', assert => {
let A = new NDArray([
[3,0],
[11,5]
]);
let x = new NDArray([21,99]);
linalg.solve(A,x);
assert.ok(x.isEqual(new NDArray([7,4.4])));
});
QUnit.module('LU Solve', () => {
QUnit.test("Circuit matrix", assert => {
let A = new NDArray([
[11,-3,0],
[-3,6,-1],
[0,-1,3]
]);
let x = new NDArray([30,5,-25]);
linalg.solve(A,x);
assert.ok(x.isEqual(new NDArray([3,1,-8])));
});
QUnit.test("From numpy tests", assert => {
let A = new NDArray([
[3,1],
[1,2]
]);
let x = new NDArray([9,8]);
linalg.solve(A,x);
assert.ok(x.isEqual(new NDArray([2,3])));
});
QUnit.test("From GSL tests", assert => {
let A = new NDArray([
[0.18, 0.60, 0.57, 0.96],
[0.41, 0.24, 0.99, 0.58],
[0.14, 0.30, 0.97, 0.66],
[0.51, 0.13, 0.19, 0.85]
],{datatype:'f64'});
let x = new NDArray([1,2,3,4])
linalg.solve(A,x);
assert.ok(x.isEqual(new NDArray(
[-4.05205, -12.6056, 1.66091, 8.69377],{datatype:'f64'}),1e-4));
});
QUnit.test("Random tests 1 (match with numpy)", assert => {
let A = new NDArray([
[4, 7, 5, 12], [4, 3, 2, 1], [6, 2, 9, 3], [4, 1, 8, 8]])
let x = new NDArray([13, 15, 2, 90]);
linalg.solve(A,x);
assert.ok(x.isEqual(
new NDArray([40.50877193, -39.30526316, -25.02807018, 20.93684211]),1e-4));
});
QUnit.test("Random tests 2 (match with numpy)", assert => {
let A = new NDArray([
[4, 7, 5, 0.5], [4, 3, 2, 1], [6, 2, 99, 3], [4, 1, 8, 8]])
let x = new NDArray([13, 15, 2, 90]);
linalg.solve(A,x);
assert.ok(x.isEqual(new NDArray(
[0.19644227, 1.19044879, -0.36008822, 11.36306099])));
});
QUnit.test("Random tests 3 (match with numpy)", assert => {
let A = new NDArray([
[4, 0.0007, 5, 0.5], [4, 3, 2, 1], [6, 2, 9999, 3], [4, 1, 8, 8]])
let x = new NDArray([13, 15, 2, 90]);
linalg.solve(A,x);
assert.ok(x.isEqual(new NDArray(
[1.95364698e+00, -1.07265497e+00, -3.88138726e-03,
1.04111398e+01])));
});
QUnit.test("Random tests 4 (match with numpy)", assert => {
let A = new NDArray([
[4, 0.0007, 5, 0.5], [4, 3, 2, 1], [6, 2, 9999, 3], [4, 1, 8, 8]])
let x = new NDArray([13, 0.15, 2986, 90]);
linalg.solve(A,x);
assert.ok(x.isEqual(new NDArray(
[1.51620015, -5.80949758, 0.295605, 10.92248213]),1e-5));
});
QUnit.test("Solve multiple", assert => {
let A = new NDArray([
[4, 7, 5, 12], [4, 3, 2, 1], [6, 2, 9, 3], [4, 1, 8, 8]])
let x = new NDArray([
[13,45,3],
[15,66,3],
[2,0.02,8],
[90,1,0]
]);
linalg.solve(A,x);
assert.ok(x.isEqual(new NDArray([
[40.50877193, 31.61561404, -1.66667],
[-39.30526316, -8.06736842, 2.4],
[-25.02807018, -21.58596491, 1.933333],
[20.93684211, 6.91157895, -1.4]
]),1e-5));
});
});
});
QUnit.module('tri', () => {
QUnit.module('tril', () => {
QUnit.test('4x4', assert => {
let A = new NDArray([
[5,5,5,5],
[5,5,5,5],
[5,5,5,5],
[5,5,5,5]
]);
let trilA = linalg.tril(A);
assert.ok(trilA.isEqual(new NDArray([
[5,0,0,0],
[5,5,0,0],
[5,5,5,0],
[5,5,5,5]
])));
});
QUnit.test('4x4 diag -1', assert => {
let A = new NDArray([
[5,5,5,5],
[5,5,5,5],
[5,5,5,5],
[5,5,5,5]
]);
let trilA = linalg.tril(A,-1);
assert.ok(trilA.isEqual(new NDArray([
[0,0,0,0],
[5,0,0,0],
[5,5,0,0],
[5,5,5,0]
])));
});
QUnit.test('4x4 diag 1', assert => {
let A = new NDArray([
[5,5,5,5],
[5,5,5,5],
[5,5,5,5],
[5,5,5,5]
]);
let trilA = linalg.tril(A,1);
assert.ok(trilA.isEqual(new NDArray([
[5,5,0,0],
[5,5,5,0],
[5,5,5,5],
[5,5,5,5]
])));
});
QUnit.test('6x4', assert => {
let A = new NDArray([
[5,5,5,5],
[5,5,5,5],
[5,5,5,5],
[5,5,5,5],
[5,5,5,5],
[5,5,5,5]
]);
let trilA = linalg.tril(A);
assert.ok(trilA.isEqual(new NDArray([
[5,0,0,0],
[5,5,0,0],
[5,5,5,0],
[5,5,5,5],
[5,5,5,5],
[5,5,5,5]
])));
});
QUnit.test('4x6', assert => {
let A = new NDArray([
[5,5,5,5,5,5],
[5,5,5,5,5,5],
[5,5,5,5,5,5],
[5,5,5,5,5,5]
]);
let trilA = linalg.tril(A);
assert.ok(trilA.isEqual(new NDArray([
[5,0,0,0,0,0],
[5,5,0,0,0,0],
[5,5,5,0,0,0],
[5,5,5,5,0,0]
])));
});
});
QUnit.module('triu', () => {
QUnit.test('4x4', assert => {
let A = new NDArray([
[5,5,5,5],
[5,5,5,5],
[5,5,5,5],
[5,5,5,5]
]);
let triuA = linalg.triu(A);
assert.ok(triuA.isEqual(new NDArray([
[5,5,5,5],
[0,5,5,5],
[0,0,5,5],
[0,0,0,5]
])));
});
QUnit.test('4x4 diag -1', assert => {
let A = new NDArray([
[5,5,5,5],
[5,5,5,5],
[5,5,5,5],
[5,5,5,5]
]);
let triuA = linalg.triu(A,-1);
assert.ok(triuA.isEqual(new NDArray([
[5,5,5,5],
[5,5,5,5],
[0,5,5,5],
[0,0,5,5]
])));
});
QUnit.test('4x4 diag +1', assert => {
let A = new NDArray([
[5,5,5,5],
[5,5,5,5],
[5,5,5,5],
[5,5,5,5]
]);
let triuA = linalg.triu(A,1);
assert.ok(triuA.isEqual(new NDArray([
[0,5,5,5],
[0,0,5,5],
[0,0,0,5],
[0,0,0,0]
])));
});
QUnit.test('6x4', assert => {
let A = new NDArray([
[5,5,5,5],
[5,5,5,5],
[5,5,5,5],
[5,5,5,5],
[5,5,5,5],
[5,5,5,5]
]);
let triuA = linalg.triu(A);
assert.ok(triuA.isEqual(new NDArray([
[5,5,5,5],
[0,5,5,5],
[0,0,5,5],
[0,0,0,5],
[0,0,0,0],
[0,0,0,0]
])));
});
QUnit.test('4x6', assert => {
let A = new NDArray([
[5,5,5,5,5,5],
[5,5,5,5,5,5],
[5,5,5,5,5,5],
[5,5,5,5,5,5]
]);
let triuA = linalg.triu(A);
assert.ok(triuA.isEqual(new NDArray([
[5,5,5,5,5,5],
[0,5,5,5,5,5],
[0,0,5,5,5,5],
[0,0,0,5,5,5]
])));
});
});
});
QUnit.module('QR', () => {
QUnit.test('3x3', assert => {
let A = new NDArray([
[3, 6, 2],
[1, 7, 6],
[9, 3, 2]
]);
let [q,r] = linalg.qr(A);
assert.ok(q.isEqual(new NDArray([
[-0.31448545, -0.53452248, -0.78446454],
[-0.10482848, -0.80178373, 0.58834841],
[-0.94345635, 0.26726124, 0.19611614]
])));
assert.ok(r.isEqual(new NDArray([
[-9.53939201, -5.45108115, -3.14485451],
[0., -8.01783726, -5.34522484],
[0., 0., 2.35339362]
])));
});
QUnit.test('2x2', assert => {
let A = new NDArray([
[3,6],
[9,2]
]);
let [q,r] = linalg.qr(A);
assert.ok(q.isEqual(new NDArray([
[-0.31622777, -0.9486833],
[-0.9486833, 0.31622777]
])));
assert.ok(r.isEqual(new NDArray([
[-9.48683298, -3.79473319],
[0., -5.05964426]
])));
});
QUnit.skip('3x2', assert => {
let A = new NDArray([
[3,6],
[9,2],
[6,7]
]);
let [q,r] = linalg.qr(A);
assert.ok(q.isEqual(new NDArray([
[-0.26726124, 0.64927181],
[-0.80178373, -0.55971708],
[-0.53452248, 0.51493971]
])));
console.log(r.toString());
assert.ok(r.isEqual(new NDArray([
[-11.22497216, -6.94879229],
[0., 6.3807747]
])));
});
QUnit.skip('2x4', assert => {
let A = new NDArray([
[3,6,7,8],
[9,2,5,5]
]);
let [q,r] = linalg.qr(A);
assert.ok(q.isEqual(new NDArray([
[-0.31622777, -0.9486833],
[-0.9486833, 0.31622777]
])));
assert.ok(r.isEqual(new NDArray([
[-9.48683298, -3.79473319, -6.95701085, -7.27323862],
[0., -5.05964426, -5.05964426, -6.00832755]
])));
});
});
QUnit.module('Eigen', () => {
QUnit.test('eig 2x2', assert => {
let A = new NDArray([
[3,1],
[0,2]
]);
let [w,vl,vr] = linalg.eig(A);
!vl; // to fix the unused warning
assert.ok(w.isEqual(new NDArray([3,2])));
assert.ok(vr.isEqual(new NDArray([
[1, -0.70710678],
[0, 0.70710678]
])));
});
QUnit.test('eig 3x3', assert => {
let A = new NDArray([
[3,6,2],
[1,7,6],
[9,3,2]
]);
let [w,vl,vr] = linalg.eig(A);
!vl; // to fix the unused warning
let target_w = new NDArray({shape:[3]});
target_w.set(0, new Complex(-0.56082135, 3.66104822));
target_w.set(1, new Complex(-0.56082135, -3.66104822));
target_w.set(2, 13.12164269);
assert.ok(w.isEqual(target_w));
let target_vr = new NDArray({shape:[3,3]});
target_vr.set(0, 0, new Complex(-0.06160653, 0.39509838));
target_vr.set(0, 1, new Complex(-0.06160653, -0.39509838));
target_vr.set(0, 2, -0.49774794);
target_vr.set(1, 0, new Complex(-0.45396105, -0.27206987));
target_vr.set(1, 1, new Complex(-0.45396105, 0.27206987));
target_vr.set(1, 2, -0.64721249);
target_vr.set(2, 0, 0.74833098);
target_vr.set(2, 1, 0.74833098);
target_vr.set(2, 2, -0.57737594);
assert.ok(vr.isEqual(target_vr));
});
QUnit.test('eig 4x4', assert => {
let A = new NDArray([
[3,6,2,1],
[1,7,6,1],
[9,3,2,1],
[9,3,7,1]
]);
let [w,vl,vr] = linalg.eig(A);
!vl; // to fix the unused warning
let target_w = new NDArray({shape:[4]});
target_w.set(0, 14.4616694);
target_w.set(1, new Complex(-0.730834679,3.55021966));
target_w.set(2, new Complex(-0.730834679,-3.55021966));
target_w.set(3, 0);
assert.ok(w.isEqual(target_w));
let target_vr = new NDArray({shape:[4,4]});
// TODO:
// target_vr values at (0,0), (1,0), (2,0), (3,0) should
// have opposite signs to match the numpy output
target_vr.set(0,0, 0.397234093);
target_vr.set(0,1, new Complex(-0.295467105,0.08333459));
target_vr.set(0,2, new Complex(-0.295467105,-0.08333459));
target_vr.set(0,3, 0.0659380473);
target_vr.set(1,0, 0.503683695);
target_vr.set(1,1, new Complex(-0.0629882747,-0.36737993));
target_vr.set(1,2, new Complex(-0.0629882747,0.36737993));
target_vr.set(1,3, -0.131876095);
target_vr.set(2,0, 0.457555861);
target_vr.set(2,1, new Complex(0.225571507,0.42219946));
target_vr.set(2,2, new Complex(0.225571507,-0.42219946));
target_vr.set(2,3, 0);
target_vr.set(3,0, 0.615751934);
target_vr.set(3,1, 0.733269467);
target_vr.set(3,2, 0.733269467);
target_vr.set(3,3, 0.989070710);
assert.ok(vr.isEqual(target_vr));
});
});
QUnit.module('Cholesky', () => {
QUnit.test('3x3 1', assert => {
let A = new NDArray([
[4,12,-16],
[12,37,-43],
[-16,-43,98]
]);
let chA = linalg.cholesky(A);
assert.ok(chA.isEqual(new NDArray([
[2,0,0],
[6,1,0],
[-8,5,3]
])))
});
QUnit.test('3x3 2', assert => {
let A = new NDArray([[2, -1, 0], [-1, 2, -1], [0, -1, 2]])
let chA = linalg.cholesky(A);
assert.ok(chA.isEqual(new NDArray([
[1.41421356, 0., 0.],
[-0.70710678, 1.22474487, 0.],
[0., -0.81649658, 1.15470054]
])))
});
QUnit.test('not positive definite', assert => {
let A = new NDArray([
[4, 12, -16], [12, 0, -43], [-16, -43, 98]
]);
assert.throws(() => {
linalg.cholesky(A);
})
});
});
});
}