This repository has been archived by the owner on Sep 10, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathcholesky.hhs
102 lines (82 loc) · 2.73 KB
/
cholesky.hhs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/**
*
* Function for decomposing a matrix via cholesky method, returning the L in the L*L^T part.
* @author Xinran Wang, Jason Reynolds
* @param inputMatrix the matrix to be decomposed into L
* @returns the cholesky decomposition's L part
*/
function cholesky(inputMatrix) {
*import math: transpose
*import math: is_symmetric
// argument number
if (arguments.length === 0) {
throw new Error('Exception occurred in cholesky - no argument given');
}
else if (arguments.length > 1) {
throw new Error('Exception occurred in cholesky - wrong argument number');
}
// type check
if (!(Array.isArray(inputMatrix)) && !(inputMatrix instanceof Mat) && !(inputMatrix instanceof Tensor)) {
throw new Error('Exception occurred in cholesky - inputMatrix is not a Mat, Tensor or JS Array');
}
//Cholesky: if the input is Mat, check rows/cols and symmetricity
if (inputMatrix instanceof Mat) {
L: Mat;
if (!(inputMatrix.rows === inputMatrix.cols) || inputMatrix.rows === 0 || inputMatrix.cols === 0) {
throw new Error('Wrong dimension for' + inputMatrix);
}
if (!(inputMatrix === transpose(inputMatrix))) {
throw new Error('Matrix is not symmetric:' + inputMatrix)
}
if (!is_symmetric(inputMatrix)) {
throw new Error('Not symmetric')
}
//dimension n
const n = inputMatrix.rows;
//matrix L
const L = new Mat().zeros(n, n);
//iteration
for (let i = 0; i < n; i++) {
for (let k = 0; k < i + 1; k++) {
let sum = 0;
for (let j = 0; j < k; j++) {
sum += L.val[i][j] * L.val[k][j];
}
if (i === k) {
L.val[i][k] = Math.sqrt(inputMatrix.val[i][i] - sum);
} else {
L.val[i][k] = (1.0 / L.val[k][k]) * (inputMatrix.val[i][k] - sum);
}
}
}
return L;
}
//in the case the array is raw
//consider the tensor
if (inputMatrix instanceof Tensor) {
inputMatrix = inputMatrix.val;
}
if (!(inputMatrix.length === inputMatrix[0].length) || inputMatrix.length === 0 || inputMatrix[0].length === 0) {
throw new Error('Wrong dimensions for ' + inputMatrix);
}
if (!(is_symmetric(inputMatrix))) {
throw new Error('Not symmetric');
}
const n_2 = inputMatrix.length;
const L_2 = zeros(n_2).val;
//const L_2 = Array(n_2).fill(0).map(() => Array(n_2).fill(0));
for (let x = 0; x < n_2; x++) {
for (let y = 0; y < x + 1; y++) {
let sum2 = 0;
for (let z = 0; z < y; z++) {
sum2 += L_2[x][z] * L_2[y][z];
}
if (x === y) {
L_2[x][y] = Math.sqrt(inputMatrix[x][x] - sum2);
} else {
L_2[x][y] = (1.0 / L_2[y][y]) * (inputMatrix[x][y] - sum2);
}
}
}
return (mat(L_2));
}