/* ------------------------ * Constructor * ------------------------ */ ///<summary>QR Decomposition, computed by Householder reflections.</summary> ///<param name="A">Rectangular matrix</param> ///<returns>Structure to access R and the Householder vectors and compute Q.</returns> public QRDecomposition(Matrix3 A) { // Initialize. QR = A.ToFloatArray(); m = A.RowLength(); n = A.ColumnLength(); Rdiag = new float[n]; // Main loop. for (int k = 0; k < n; k++) { // Compute 2-norm of k-th column without under/overflow. float nrm = 0; for (int i = k; i < m; i++) { nrm = Convert.ToSingle(Maths.Hypot(nrm, QR[i, k])); } if (nrm != 0) { // Form k-th Householder vector. if (QR[k, k] < 0) { nrm = -nrm; } for (int i = k; i < m; i++) { QR[i, k] /= nrm; } QR[k, k] += 1.0f; // Apply transformation to remaining columns. for (int j = k + 1; j < n; j++) { float s = 0.0f; for (int i = k; i < m; i++) { s += QR[i, k] * QR[i, j]; } s = -s / QR[k, k]; for (int i = k; i < m; i++) { QR[i, j] += s * QR[i, k]; } } } Rdiag[k] = -nrm; } }
/// <summary> /// Symmetric tridiagonal QL algorithm. /// </summary> private void tql2() { // This is derived from the Algol procedures tql2, by // Bowdler, Martin, Reinsch, and Wilkinson, Handbook for // Auto. Comp., Vol.ii-Linear Algebra, and the corresponding // Fortran subroutine in EISPACK. for (int i = 1; i < n; i++) { e[i - 1] = e[i]; } e[n - 1] = 0.0f; float f = 0.0f; float tst1 = 0.0f; float eps = Convert.ToSingle(Math.Pow(2.0, -52)); for (int l = 0; l < n; l++) { // Find small subdiagonal element tst1 = Convert.ToSingle(Math.Max(tst1, Math.Abs(d[l]) + Math.Abs(e[l]))); int m = l; while (m < n) { if (Math.Abs(e[m]) <= eps * tst1) { break; } m++; } // If m == l, d[l] is an eigenvalue, // otherwise, iterate. if (m > l) { int iter = 0; do { iter = iter + 1; // (Could check iteration count here.) // Compute implicit shift float g = d[l]; float p = (d[l + 1] - g) / (2 * e[l]); float r = Convert.ToSingle(Maths.Hypot(p, 1)); if (p < 0) { r = -r; } d[l] = e[l] / (p + r); d[l + 1] = e[l] * (p + r); float dl1 = d[l + 1]; float h = g - d[l]; for (int i = l + 2; i < n; i++) { d[i] -= h; } f = f + h; // Implicit QL transformation. p = d[m]; float c = 1.0f; float c2 = c; float c3 = c; float el1 = e[l + 1]; float s = 0.0f; float s2 = 0.0f; for (int i = m - 1; i >= l; i--) { c3 = c2; c2 = c; s2 = s; g = c * e[i]; h = c * p; r = Convert.ToSingle(Maths.Hypot(p, e[i])); e[i + 1] = s * r; s = e[i] / r; c = p / r; p = c * d[i] - s * g; d[i + 1] = h + s * (c * g + s * d[i]); // Accumulate transformation. for (int k = 0; k < n; k++) { h = Varray[k, i + 1]; Varray[k, i + 1] = s * Varray[k, i] + c * h; Varray[k, i] = c * Varray[k, i] - s * h; } } p = -s * s2 * c3 * el1 * e[l] / dl1; e[l] = s * p; d[l] = c * p; // Check for convergence. } while (Math.Abs(e[l]) > eps * tst1); } d[l] = d[l] + f; e[l] = 0.0f; } // Sort eigenvalues and corresponding vectors. for (int i = 0; i < n - 1; i++) { int k = i; float p = d[i]; for (int j = i + 1; j < n; j++) { if (d[j] < p) { k = j; p = d[j]; } } if (k != i) { d[k] = d[i]; d[i] = p; for (int j = 0; j < n; j++) { p = Varray[j, i]; Varray[j, i] = Varray[j, k]; Varray[j, k] = p; } } } }