@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
118 lines (92 loc) • 3.16 kB
JavaScript
const EPSILON = 1e-10;
/**
* Perform QR factorization in-place
* Subfunction that analyzes eigenvalues by QR decomposition
* @see http://www-in.aut.ac.jp/~minemura/pub/Csimu/C/QRmethod.html
* @param {number[]} a Square matrix
* @param {number} n size of the matrix in single dimension
*/
export function matrix_qr_in_place(a, n) {
const q = new Float64Array(n * n);
const w = new Float64Array(n);
let mu, wa, sinx, cosx, sum1, sum2;
let m = n;
let i, j, k;
while (m > 1) {
const a10_index = n * (m - 1) + m - 2;
const a10 = a[a10_index];
// Convergence test
if (Math.abs(a10) < EPSILON) {
m = m - 1;
continue;
}
// Origin movement mu (compute Wilkinson's shift)
const a00 = a[n * (m - 2) + m - 2];
const a01 = a[n * (m - 2) + m - 1];
const a11 = a[n * (m - 1) + m - 1];
sum1 = a00 + a11;
sum2 = a00 * a11 - a01 * a10;
wa = sum1 * sum1 - 4.0 * sum2;
if (wa < 0.0) {
wa = 0.0;
} else {
wa = Math.sqrt(wa);
}
const lam1 = 0.5 * (sum1 + wa);
const lam2 = sum2 / lam1;
if (Math.abs(a11 - lam1) < Math.abs(a11 - lam2)) {
mu = a11 - lam1;
} else {
mu = a11 - lam2;
}
for (i = 0; i < m; i++) {
a[n * i + i] -= mu;
}
// QR decomposition, A becomes R
for (i = 0; i < m * m; i++) {
q[i] = 0.0;
}
for (i = 0; i < m; i++) {
q[m * i + i] = 1.0;
}
for (i = 0; i < m - 1; i++) {
sum1 = Math.sqrt(a[n * i + i] * a[n * i + i] + a[n * i + n + i] * a[n * i + n + i]);
if (Math.abs(sum1) < EPSILON) {
sinx = 0.0;
cosx = 0.0;
} else {
sinx = a[n * i + n + i] / sum1;
cosx = a[n * i + i] / sum1;
}
for (j = i + 1; j < m; j++) {
sum2 = a[n * i + j] * cosx + a[n * i + n + j] * sinx;
a[n * i + n + j] = -a[n * i + j] * sinx + a[n * i + n + j] * cosx;
a[n * i + j] = sum2;
}
a[n * i + n + i] = 0.0;
a[n * i + i] = sum1;
for (j = 0; j < m; j++) {
const m_j = m * j;
sum2 = q[m_j + i] * cosx + q[m_j + i + 1] * sinx;
q[m_j + i + 1] = -q[m_j + i] * sinx + q[m_j + i + 1] * cosx;
q[m_j + i] = sum2;
}
}
for (i = 0; i < m; i++) {
const n_i = n * i;
for (j = i; j < m; j++) {
w[j] = a[n_i + j];
}
for (j = 0; j < m; j++) {
sum1 = 0.0;
for (k = i; k < m; k++) {
sum1 += w[k] * q[m * k + j];
}
a[n_i + j] = sum1;
}
}
for (i = 0; i < m; i++) {
a[n * i + i] += mu;
}
}
}