UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

118 lines (92 loc) 3.16 kB
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; } } }