Skip to content

Commit

Permalink
refactor: change decompositions to classes
Browse files Browse the repository at this point in the history
BREAKING CHANGE:
Now decompositions have to be created with "new".
  • Loading branch information
maasencioh authored and targos committed Jul 19, 2017
1 parent 86ed94d commit 00c18e8
Show file tree
Hide file tree
Showing 6 changed files with 626 additions and 610 deletions.
4 changes: 2 additions & 2 deletions __tests__/decompositions/cholesky.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ describe('Cholesky decomposition', () => {
expect(ltm.mmul(ltm.transpose())).toEqual(matrix);
});
it('should throw on bad input', () => {
expect(() => CHO([[0, 1], [2, 0]])).toThrow('Matrix is not symmetric');
expect(() => CHO([[1, 2], [2, 1]])).toThrow('Matrix is not positive definite');
expect(() => new CHO([[0, 1], [2, 0]])).toThrow('Matrix is not symmetric');
expect(() => new CHO([[1, 2], [2, 1]])).toThrow('Matrix is not positive definite');
});
});

Expand Down
89 changes: 45 additions & 44 deletions src/dc/cholesky.js
Original file line number Diff line number Diff line change
@@ -1,55 +1,53 @@
import Matrix from '../matrix';

// https://github.com/lutzroeder/Mapack/blob/master/Source/CholeskyDecomposition.cs
function CholeskyDecomposition(value) {
if (!(this instanceof CholeskyDecomposition)) {
return new CholeskyDecomposition(value);
}
value = Matrix.checkMatrix(value);
if (!value.isSymmetric()) {
throw new Error('Matrix is not symmetric');
}
/**
* @class CholeskyDecomposition
* @link https://github.com/lutzroeder/Mapack/blob/master/Source/CholeskyDecomposition.cs
* @param {*} value
*/
export default class CholeskyDecomposition {
constructor(value) {
value = Matrix.checkMatrix(value);
if (!value.isSymmetric()) {
throw new Error('Matrix is not symmetric');
}

var a = value;
var dimension = a.rows;
var l = new Matrix(dimension, dimension);
var positiveDefinite = true;
var i, j, k;

var a = value;
var dimension = a.rows;
var l = new Matrix(dimension, dimension);
var positiveDefinite = true;
var i, j, k;

for (j = 0; j < dimension; j++) {
var Lrowj = l[j];
var d = 0;
for (k = 0; k < j; k++) {
var Lrowk = l[k];
var s = 0;
for (i = 0; i < k; i++) {
s += Lrowk[i] * Lrowj[i];
for (j = 0; j < dimension; j++) {
var Lrowj = l[j];
var d = 0;
for (k = 0; k < j; k++) {
var Lrowk = l[k];
var s = 0;
for (i = 0; i < k; i++) {
s += Lrowk[i] * Lrowj[i];
}
Lrowj[k] = s = (a[j][k] - s) / l[k][k];
d = d + s * s;
}
Lrowj[k] = s = (a[j][k] - s) / l[k][k];
d = d + s * s;
}

d = a[j][j] - d;
d = a[j][j] - d;

positiveDefinite &= (d > 0);
l[j][j] = Math.sqrt(Math.max(d, 0));
for (k = j + 1; k < dimension; k++) {
l[j][k] = 0;
positiveDefinite &= (d > 0);
l[j][j] = Math.sqrt(Math.max(d, 0));
for (k = j + 1; k < dimension; k++) {
l[j][k] = 0;
}
}
}

if (!positiveDefinite) {
throw new Error('Matrix is not positive definite');
}
if (!positiveDefinite) {
throw new Error('Matrix is not positive definite');
}

this.L = l;
}
this.L = l;
}

CholeskyDecomposition.prototype = {
get lowerTriangularMatrix() {
return this.L;
},
solve: function (value) {
solve(value) {
value = Matrix.checkMatrix(value);

var l = this.L;
Expand Down Expand Up @@ -83,6 +81,9 @@ CholeskyDecomposition.prototype = {

return B;
}
};

export default CholeskyDecomposition;
get lowerTriangularMatrix() {
return this.L;
}
}

112 changes: 57 additions & 55 deletions src/dc/evd.js
Original file line number Diff line number Diff line change
@@ -1,74 +1,78 @@
import Matrix from '../matrix';
import {hypotenuse, getFilled2DArray} from './util';

const defaultOptions = {
assumeSymmetric: false
};

// https://github.com/lutzroeder/Mapack/blob/master/Source/EigenvalueDecomposition.cs
function EigenvalueDecomposition(matrix, options) {
options = Object.assign({}, defaultOptions, options);
if (!(this instanceof EigenvalueDecomposition)) {
return new EigenvalueDecomposition(matrix, options);
}
matrix = Matrix.checkMatrix(matrix);
if (!matrix.isSquare()) {
throw new Error('Matrix is not a square matrix');
}

var n = matrix.columns;
var V = getFilled2DArray(n, n, 0);
var d = new Array(n);
var e = new Array(n);
var value = matrix;
var i, j;
/**
* @class EigenvalueDecomposition
* @link https://github.com/lutzroeder/Mapack/blob/master/Source/EigenvalueDecomposition.cs
* @param {*} matrix
* @param {object} [options]
*/
export default class EigenvalueDecomposition {
constructor(matrix, options = {}) {
const {
assumeSymmetric = false
} = options;

matrix = Matrix.checkMatrix(matrix);
if (!matrix.isSquare()) {
throw new Error('Matrix is not a square matrix');
}

var isSymmetric = false;
if (options.assumeSymmetric) {
isSymmetric = true;
} else {
isSymmetric = matrix.isSymmetric();
}
var n = matrix.columns;
var V = getFilled2DArray(n, n, 0);
var d = new Array(n);
var e = new Array(n);
var value = matrix;
var i, j;

if (isSymmetric) {
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
V[i][j] = value.get(i, j);
}
var isSymmetric = false;
if (assumeSymmetric) {
isSymmetric = true;
} else {
isSymmetric = matrix.isSymmetric();
}
tred2(n, e, d, V);
tql2(n, e, d, V);
} else {
var H = getFilled2DArray(n, n, 0);
var ort = new Array(n);
for (j = 0; j < n; j++) {

if (isSymmetric) {
for (i = 0; i < n; i++) {
H[i][j] = value.get(i, j);
for (j = 0; j < n; j++) {
V[i][j] = value.get(i, j);
}
}
tred2(n, e, d, V);
tql2(n, e, d, V);
} else {
var H = getFilled2DArray(n, n, 0);
var ort = new Array(n);
for (j = 0; j < n; j++) {
for (i = 0; i < n; i++) {
H[i][j] = value.get(i, j);
}
}
orthes(n, H, ort, V);
hqr2(n, e, d, V, H);
}
orthes(n, H, ort, V);
hqr2(n, e, d, V, H);
}

this.n = n;
this.e = e;
this.d = d;
this.V = V;
}
this.n = n;
this.e = e;
this.d = d;
this.V = V;
}

EigenvalueDecomposition.prototype = {
get realEigenvalues() {
return this.d;
},
}

get imaginaryEigenvalues() {
return this.e;
},
}

get eigenvectorMatrix() {
if (!Matrix.isMatrix(this.V)) {
this.V = new Matrix(this.V);
}
return this.V;
},
}

get diagonalMatrix() {
var n = this.n;
var e = this.e;
Expand All @@ -88,10 +92,10 @@ EigenvalueDecomposition.prototype = {
}
return X;
}
};
}

function tred2(n, e, d, V) {

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

Expand Down Expand Up @@ -772,5 +776,3 @@ function cdiv(xr, xi, yr, yi) {
return [(r * xr + xi) / d, (r * xi - xr) / d];
}
}

export default EigenvalueDecomposition;
Loading

0 comments on commit 00c18e8

Please sign in to comment.