@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
92 lines (69 loc) • 2.16 kB
JavaScript
const EPSILON = 1e-10;
/**
* NxN matrix Householder reduction
* Return subfunction to upper Hessenberg matrix by Householder transformation
* @see http://www-in.aut.ac.jp/~minemura/pub/Csimu/C/QRmethod.html
* @param {number[]} a
* @param {number} n
*/
export function matrix_householder_in_place(a, n) {
const u = new Float64Array(n);
const d = new Float64Array(n);
const ds = new Float64Array(n);
let i, j, k;
let sum;
for (k = 0; k <= n - 3; k++) {
for (i = 0; i <= k; i++) {
u[i] = 0;
}
for (i = k + 1; i < n; i++) {
u[i] = a[n * i + k];
}
// Build transformation matrix H
sum = 0.0;
for (i = k + 1; i < n; i++) {
sum = sum + u[i] * u[i];
}
const u_k_1 = u[k + 1];
const u_k_1_abs = Math.abs(u_k_1);
if (u_k_1_abs < EPSILON) {
continue;
}
const sigma = Math.sqrt(sum) * u_k_1 / u_k_1_abs;
u[k + 1] += sigma;
const v_norm = Math.sqrt(2.0 * sigma * u[k + 1]);
for (i = k + 1; i < n; i++) {
u[i] /= v_norm;
}
// Similarity transformation
for (i = 0; i < n; i++) {
d[i] = 0.0;
ds[i] = 0.0;
for (j = k + 1; j <= n - 1; j++) {
const u_j = u[j];
d[i] += a[n * i + j] * u_j;
ds[i] += a[n * j + i] * u_j;
}
}
let ud = 0.0;
let uds = 0.0;
for (i = k + 1; i < n; i++) {
const u_i = u[i];
ud += u_i * d[i];
uds += u_i * ds[i];
}
for (i = 0; i < n; i++) {
const u_i = u[i];
d[i] = 2.0 * (d[i] - ud * u_i);
ds[i] = 2.0 * (ds[i] - uds * u_i);
}
for (i = 0; i < n; i++) {
const u_i = u[i];
const d_i = d[i];
const n_i = n * i;
for (j = 0; j < n; j++) {
a[n_i + j] -= u_i * ds[j] + d_i * u[j];
}
}
}
}