Skip to content

Commit 00c18e8

Browse files
maasenciohtargos
authored andcommitted
refactor: change decompositions to classes
BREAKING CHANGE: Now decompositions have to be created with "new".
1 parent 86ed94d commit 00c18e8

File tree

6 files changed

+626
-610
lines changed

6 files changed

+626
-610
lines changed

__tests__/decompositions/cholesky.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ describe('Cholesky decomposition', () => {
1919
expect(ltm.mmul(ltm.transpose())).toEqual(matrix);
2020
});
2121
it('should throw on bad input', () => {
22-
expect(() => CHO([[0, 1], [2, 0]])).toThrow('Matrix is not symmetric');
23-
expect(() => CHO([[1, 2], [2, 1]])).toThrow('Matrix is not positive definite');
22+
expect(() => new CHO([[0, 1], [2, 0]])).toThrow('Matrix is not symmetric');
23+
expect(() => new CHO([[1, 2], [2, 1]])).toThrow('Matrix is not positive definite');
2424
});
2525
});
2626

src/dc/cholesky.js

Lines changed: 45 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,53 @@
11
import Matrix from '../matrix';
22

3-
// https://github.com/lutzroeder/Mapack/blob/master/Source/CholeskyDecomposition.cs
4-
function CholeskyDecomposition(value) {
5-
if (!(this instanceof CholeskyDecomposition)) {
6-
return new CholeskyDecomposition(value);
7-
}
8-
value = Matrix.checkMatrix(value);
9-
if (!value.isSymmetric()) {
10-
throw new Error('Matrix is not symmetric');
11-
}
3+
/**
4+
* @class CholeskyDecomposition
5+
* @link https://github.com/lutzroeder/Mapack/blob/master/Source/CholeskyDecomposition.cs
6+
* @param {*} value
7+
*/
8+
export default class CholeskyDecomposition {
9+
constructor(value) {
10+
value = Matrix.checkMatrix(value);
11+
if (!value.isSymmetric()) {
12+
throw new Error('Matrix is not symmetric');
13+
}
14+
15+
var a = value;
16+
var dimension = a.rows;
17+
var l = new Matrix(dimension, dimension);
18+
var positiveDefinite = true;
19+
var i, j, k;
1220

13-
var a = value;
14-
var dimension = a.rows;
15-
var l = new Matrix(dimension, dimension);
16-
var positiveDefinite = true;
17-
var i, j, k;
18-
19-
for (j = 0; j < dimension; j++) {
20-
var Lrowj = l[j];
21-
var d = 0;
22-
for (k = 0; k < j; k++) {
23-
var Lrowk = l[k];
24-
var s = 0;
25-
for (i = 0; i < k; i++) {
26-
s += Lrowk[i] * Lrowj[i];
21+
for (j = 0; j < dimension; j++) {
22+
var Lrowj = l[j];
23+
var d = 0;
24+
for (k = 0; k < j; k++) {
25+
var Lrowk = l[k];
26+
var s = 0;
27+
for (i = 0; i < k; i++) {
28+
s += Lrowk[i] * Lrowj[i];
29+
}
30+
Lrowj[k] = s = (a[j][k] - s) / l[k][k];
31+
d = d + s * s;
2732
}
28-
Lrowj[k] = s = (a[j][k] - s) / l[k][k];
29-
d = d + s * s;
30-
}
3133

32-
d = a[j][j] - d;
34+
d = a[j][j] - d;
3335

34-
positiveDefinite &= (d > 0);
35-
l[j][j] = Math.sqrt(Math.max(d, 0));
36-
for (k = j + 1; k < dimension; k++) {
37-
l[j][k] = 0;
36+
positiveDefinite &= (d > 0);
37+
l[j][j] = Math.sqrt(Math.max(d, 0));
38+
for (k = j + 1; k < dimension; k++) {
39+
l[j][k] = 0;
40+
}
3841
}
39-
}
4042

41-
if (!positiveDefinite) {
42-
throw new Error('Matrix is not positive definite');
43-
}
43+
if (!positiveDefinite) {
44+
throw new Error('Matrix is not positive definite');
45+
}
4446

45-
this.L = l;
46-
}
47+
this.L = l;
48+
}
4749

48-
CholeskyDecomposition.prototype = {
49-
get lowerTriangularMatrix() {
50-
return this.L;
51-
},
52-
solve: function (value) {
50+
solve(value) {
5351
value = Matrix.checkMatrix(value);
5452

5553
var l = this.L;
@@ -83,6 +81,9 @@ CholeskyDecomposition.prototype = {
8381

8482
return B;
8583
}
86-
};
8784

88-
export default CholeskyDecomposition;
85+
get lowerTriangularMatrix() {
86+
return this.L;
87+
}
88+
}
89+

src/dc/evd.js

Lines changed: 57 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,78 @@
11
import Matrix from '../matrix';
22
import {hypotenuse, getFilled2DArray} from './util';
33

4-
const defaultOptions = {
5-
assumeSymmetric: false
6-
};
7-
8-
// https://github.com/lutzroeder/Mapack/blob/master/Source/EigenvalueDecomposition.cs
9-
function EigenvalueDecomposition(matrix, options) {
10-
options = Object.assign({}, defaultOptions, options);
11-
if (!(this instanceof EigenvalueDecomposition)) {
12-
return new EigenvalueDecomposition(matrix, options);
13-
}
14-
matrix = Matrix.checkMatrix(matrix);
15-
if (!matrix.isSquare()) {
16-
throw new Error('Matrix is not a square matrix');
17-
}
18-
19-
var n = matrix.columns;
20-
var V = getFilled2DArray(n, n, 0);
21-
var d = new Array(n);
22-
var e = new Array(n);
23-
var value = matrix;
24-
var i, j;
4+
/**
5+
* @class EigenvalueDecomposition
6+
* @link https://github.com/lutzroeder/Mapack/blob/master/Source/EigenvalueDecomposition.cs
7+
* @param {*} matrix
8+
* @param {object} [options]
9+
*/
10+
export default class EigenvalueDecomposition {
11+
constructor(matrix, options = {}) {
12+
const {
13+
assumeSymmetric = false
14+
} = options;
15+
16+
matrix = Matrix.checkMatrix(matrix);
17+
if (!matrix.isSquare()) {
18+
throw new Error('Matrix is not a square matrix');
19+
}
2520

26-
var isSymmetric = false;
27-
if (options.assumeSymmetric) {
28-
isSymmetric = true;
29-
} else {
30-
isSymmetric = matrix.isSymmetric();
31-
}
21+
var n = matrix.columns;
22+
var V = getFilled2DArray(n, n, 0);
23+
var d = new Array(n);
24+
var e = new Array(n);
25+
var value = matrix;
26+
var i, j;
3227

33-
if (isSymmetric) {
34-
for (i = 0; i < n; i++) {
35-
for (j = 0; j < n; j++) {
36-
V[i][j] = value.get(i, j);
37-
}
28+
var isSymmetric = false;
29+
if (assumeSymmetric) {
30+
isSymmetric = true;
31+
} else {
32+
isSymmetric = matrix.isSymmetric();
3833
}
39-
tred2(n, e, d, V);
40-
tql2(n, e, d, V);
41-
} else {
42-
var H = getFilled2DArray(n, n, 0);
43-
var ort = new Array(n);
44-
for (j = 0; j < n; j++) {
34+
35+
if (isSymmetric) {
4536
for (i = 0; i < n; i++) {
46-
H[i][j] = value.get(i, j);
37+
for (j = 0; j < n; j++) {
38+
V[i][j] = value.get(i, j);
39+
}
40+
}
41+
tred2(n, e, d, V);
42+
tql2(n, e, d, V);
43+
} else {
44+
var H = getFilled2DArray(n, n, 0);
45+
var ort = new Array(n);
46+
for (j = 0; j < n; j++) {
47+
for (i = 0; i < n; i++) {
48+
H[i][j] = value.get(i, j);
49+
}
4750
}
51+
orthes(n, H, ort, V);
52+
hqr2(n, e, d, V, H);
4853
}
49-
orthes(n, H, ort, V);
50-
hqr2(n, e, d, V, H);
51-
}
5254

53-
this.n = n;
54-
this.e = e;
55-
this.d = d;
56-
this.V = V;
57-
}
55+
this.n = n;
56+
this.e = e;
57+
this.d = d;
58+
this.V = V;
59+
}
5860

59-
EigenvalueDecomposition.prototype = {
6061
get realEigenvalues() {
6162
return this.d;
62-
},
63+
}
64+
6365
get imaginaryEigenvalues() {
6466
return this.e;
65-
},
67+
}
68+
6669
get eigenvectorMatrix() {
6770
if (!Matrix.isMatrix(this.V)) {
6871
this.V = new Matrix(this.V);
6972
}
7073
return this.V;
71-
},
74+
}
75+
7276
get diagonalMatrix() {
7377
var n = this.n;
7478
var e = this.e;
@@ -88,10 +92,10 @@ EigenvalueDecomposition.prototype = {
8892
}
8993
return X;
9094
}
91-
};
95+
}
9296

93-
function tred2(n, e, d, V) {
9497

98+
function tred2(n, e, d, V) {
9599
var f, g, h, i, j, k,
96100
hh, scale;
97101

@@ -772,5 +776,3 @@ function cdiv(xr, xi, yr, yi) {
772776
return [(r * xr + xi) / d, (r * xi - xr) / d];
773777
}
774778
}
775-
776-
export default EigenvalueDecomposition;

0 commit comments

Comments
 (0)