⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jama_eig.h

📁 一个矩阵计算的库 包括几乎所有需要的矩阵运算 对3d计算和图形处理有很大帮助
💻 H
📖 第 1 页 / 共 2 页
字号:
         } else if (l == n-1) {            w = H[n][n-1] * H[n-1][n];            p = (H[n-1][n-1] - H[n][n]) / 2.0;            q = p * p + w;            z = sqrt(abs(q));            H[n][n] = H[n][n] + exshift;            H[n-1][n-1] = H[n-1][n-1] + exshift;            x = H[n][n];               // Real pair               if (q >= 0) {               if (p >= 0) {                  z = p + z;               } else {                  z = p - z;               }               d[n-1] = x + z;               d[n] = d[n-1];               if (z != 0.0) {                  d[n] = x - w / z;               }               e[n-1] = 0.0;               e[n] = 0.0;               x = H[n][n-1];               s = abs(x) + abs(z);               p = x / s;               q = z / s;               r = sqrt(p * p+q * q);               p = p / r;               q = q / r;                  // Row modification                  for (int j = n-1; j < nn; j++) {                  z = H[n-1][j];                  H[n-1][j] = q * z + p * H[n][j];                  H[n][j] = q * H[n][j] - p * z;               }                  // Column modification                  for (int i = 0; i <= n; i++) {                  z = H[i][n-1];                  H[i][n-1] = q * z + p * H[i][n];                  H[i][n] = q * H[i][n] - p * z;               }                  // Accumulate transformations                  for (int i = low; i <= high; i++) {                  z = V[i][n-1];                  V[i][n-1] = q * z + p * V[i][n];                  V[i][n] = q * V[i][n] - p * z;               }               // Complex pair               } else {               d[n-1] = x + p;               d[n] = x + p;               e[n-1] = z;               e[n] = -z;            }            n = n - 2;            iter = 0;            // No convergence yet            } else {               // Form shift               x = H[n][n];            y = 0.0;            w = 0.0;            if (l < n) {               y = H[n-1][n-1];               w = H[n][n-1] * H[n-1][n];            }               // Wilkinson's original ad hoc shift               if (iter == 10) {               exshift += x;               for (int i = low; i <= n; i++) {                  H[i][i] -= x;               }               s = abs(H[n][n-1]) + abs(H[n-1][n-2]);               x = y = 0.75 * s;               w = -0.4375 * s * s;            }            // MATLAB's new ad hoc shift            if (iter == 30) {                s = (y - x) / 2.0;                s = s * s + w;                if (s > 0) {                    s = sqrt(s);                    if (y < x) {                       s = -s;                    }                    s = x - w / ((y - x) / 2.0 + s);                    for (int i = low; i <= n; i++) {                       H[i][i] -= s;                    }                    exshift += s;                    x = y = w = 0.964;                }            }               iter = iter + 1;   // (Could check iteration count here.)               // Look for two consecutive small sub-diagonal elements               int m = n-2;            while (m >= l) {               z = H[m][m];               r = x - z;               s = y - z;               p = (r * s - w) / H[m+1][m] + H[m][m+1];               q = H[m+1][m+1] - z - r - s;               r = H[m+2][m+1];               s = abs(p) + abs(q) + abs(r);               p = p / s;               q = q / s;               r = r / s;               if (m == l) {                  break;               }               if (abs(H[m][m-1]) * (abs(q) + abs(r)) <                  eps * (abs(p) * (abs(H[m-1][m-1]) + abs(z) +                  abs(H[m+1][m+1])))) {                     break;               }               m--;            }               for (int i = m+2; i <= n; i++) {               H[i][i-2] = 0.0;               if (i > m+2) {                  H[i][i-3] = 0.0;               }            }               // Double QR step involving rows l:n and columns m:n               for (int k = m; k <= n-1; k++) {               int notlast = (k != n-1);               if (k != m) {                  p = H[k][k-1];                  q = H[k+1][k-1];                  r = (notlast ? H[k+2][k-1] : 0.0);                  x = abs(p) + abs(q) + abs(r);                  if (x != 0.0) {                     p = p / x;                     q = q / x;                     r = r / x;                  }               }               if (x == 0.0) {                  break;               }               s = sqrt(p * p + q * q + r * r);               if (p < 0) {                  s = -s;               }               if (s != 0) {                  if (k != m) {                     H[k][k-1] = -s * x;                  } else if (l != m) {                     H[k][k-1] = -H[k][k-1];                  }                  p = p + s;                  x = p / s;                  y = q / s;                  z = r / s;                  q = q / p;                  r = r / p;                     // Row modification                     for (int j = k; j < nn; j++) {                     p = H[k][j] + q * H[k+1][j];                     if (notlast) {                        p = p + r * H[k+2][j];                        H[k+2][j] = H[k+2][j] - p * z;                     }                     H[k][j] = H[k][j] - p * x;                     H[k+1][j] = H[k+1][j] - p * y;                  }                     // Column modification                     for (int i = 0; i <= min(n,k+3); i++) {                     p = x * H[i][k] + y * H[i][k+1];                     if (notlast) {                        p = p + z * H[i][k+2];                        H[i][k+2] = H[i][k+2] - p * r;                     }                     H[i][k] = H[i][k] - p;                     H[i][k+1] = H[i][k+1] - p * q;                  }                     // Accumulate transformations                     for (int i = low; i <= high; i++) {                     p = x * V[i][k] + y * V[i][k+1];                     if (notlast) {                        p = p + z * V[i][k+2];                        V[i][k+2] = V[i][k+2] - p * r;                     }                     V[i][k] = V[i][k] - p;                     V[i][k+1] = V[i][k+1] - p * q;                  }               }  // (s != 0)            }  // k loop         }  // check convergence      }  // while (n >= low)            // Backsubstitute to find vectors of upper triangular form      if (norm == 0.0) {         return;      }         for (n = nn-1; n >= 0; n--) {         p = d[n];         q = e[n];            // Real vector            if (q == 0) {            int l = n;            H[n][n] = 1.0;            for (int i = n-1; i >= 0; i--) {               w = H[i][i] - p;               r = 0.0;               for (int j = l; j <= n; j++) {                  r = r + H[i][j] * H[j][n];               }               if (e[i] < 0.0) {                  z = w;                  s = r;               } else {                  l = i;                  if (e[i] == 0.0) {                     if (w != 0.0) {                        H[i][n] = -r / w;                     } else {                        H[i][n] = -r / (eps * norm);                     }                     // Solve real equations                     } else {                     x = H[i][i+1];                     y = H[i+1][i];                     q = (d[i] - p) * (d[i] - p) + e[i] * e[i];                     t = (x * s - z * r) / q;                     H[i][n] = t;                     if (abs(x) > abs(z)) {                        H[i+1][n] = (-r - w * t) / x;                     } else {                        H[i+1][n] = (-s - y * t) / z;                     }                  }                     // Overflow control                     t = abs(H[i][n]);                  if ((eps * t) * t > 1) {                     for (int j = i; j <= n; j++) {                        H[j][n] = H[j][n] / t;                     }                  }               }            }            // Complex vector            } else if (q < 0) {            int l = n-1;            // Last vector component imaginary so matrix is triangular               if (abs(H[n][n-1]) > abs(H[n-1][n])) {               H[n-1][n-1] = q / H[n][n-1];               H[n-1][n] = -(H[n][n] - p) / H[n][n-1];            } else {               cdiv(0.0,-H[n-1][n],H[n-1][n-1]-p,q);               H[n-1][n-1] = cdivr;               H[n-1][n] = cdivi;            }            H[n][n-1] = 0.0;            H[n][n] = 1.0;            for (int i = n-2; i >= 0; i--) {               Real ra,sa,vr,vi;               ra = 0.0;               sa = 0.0;               for (int j = l; j <= n; j++) {                  ra = ra + H[i][j] * H[j][n-1];                  sa = sa + H[i][j] * H[j][n];               }               w = H[i][i] - p;                  if (e[i] < 0.0) {                  z = w;                  r = ra;                  s = sa;               } else {                  l = i;                  if (e[i] == 0) {                     cdiv(-ra,-sa,w,q);                     H[i][n-1] = cdivr;                     H[i][n] = cdivi;                  } else {                        // Solve complex equations                        x = H[i][i+1];                     y = H[i+1][i];                     vr = (d[i] - p) * (d[i] - p) + e[i] * e[i] - q * q;                     vi = (d[i] - p) * 2.0 * q;                     if ((vr == 0.0) && (vi == 0.0)) {                        vr = eps * norm * (abs(w) + abs(q) +                        abs(x) + abs(y) + abs(z));                     }                     cdiv(x*r-z*ra+q*sa,x*s-z*sa-q*ra,vr,vi);                     H[i][n-1] = cdivr;                     H[i][n] = cdivi;                     if (abs(x) > (abs(z) + abs(q))) {                        H[i+1][n-1] = (-ra - w * H[i][n-1] + q * H[i][n]) / x;                        H[i+1][n] = (-sa - w * H[i][n] - q * H[i][n-1]) / x;                     } else {                        cdiv(-r-y*H[i][n-1],-s-y*H[i][n],z,q);                        H[i+1][n-1] = cdivr;                        H[i+1][n] = cdivi;                     }                  }                     // Overflow control                  t = max(abs(H[i][n-1]),abs(H[i][n]));                  if ((eps * t) * t > 1) {                     for (int j = i; j <= n; j++) {                        H[j][n-1] = H[j][n-1] / t;                        H[j][n] = H[j][n] / t;                     }                  }               }            }         }      }         // Vectors of isolated roots         for (int i = 0; i < nn; i++) {         if (i < low || i > high) {            for (int j = i; j < nn; j++) {               V[i][j] = H[i][j];            }         }      }         // Back transformation to get eigenvectors of original matrix         for (int j = nn-1; j >= low; j--) {         for (int i = low; i <= high; i++) {            z = 0.0;            for (int k = low; k <= min(j,high); k++) {               z = z + V[i][k] * H[k][j];            }            V[i][j] = z;         }      }   }public:   /** Check for symmetry, then construct the eigenvalue decomposition   @param A    Square real (non-complex) matrix   */   Eigenvalue(const TNT::Array2D<Real> &A) {      n = A.dim2();      V = Array2D<Real>(n,n);      d = Array1D<Real>(n);      e = Array1D<Real>(n);      issymmetric = 1;      for (int j = 0; (j < n) && issymmetric; j++) {         for (int i = 0; (i < n) && issymmetric; i++) {            issymmetric = (A[i][j] == A[j][i]);         }      }      if (issymmetric) {         for (int i = 0; i < n; i++) {            for (int j = 0; j < n; j++) {               V[i][j] = A[i][j];            }         }            // Tridiagonalize.         tred2();            // Diagonalize.         tql2();      } else {         H = TNT::Array2D<Real>(n,n);         ort = TNT::Array1D<Real>(n);                  for (int j = 0; j < n; j++) {            for (int i = 0; i < n; i++) {               H[i][j] = A[i][j];            }         }            // Reduce to Hessenberg form.         orthes();            // Reduce Hessenberg to real Schur form.         hqr2();      }   }   /** Return the eigenvector matrix   @return     V   */   void getV (TNT::Array2D<Real> &V_) {      V_ = V;      return;   }   /** Return the real parts of the eigenvalues   @return     real(diag(D))   */   void getRealEigenvalues (TNT::Array1D<Real> &d_) {      d_ = d;      return ;   }   /** Return the imaginary parts of the eigenvalues   in parameter e_.   @pararm e_: new matrix with imaginary parts of the eigenvalues.   */   void getImagEigenvalues (TNT::Array1D<Real> &e_) {      e_ = e;      return;   }   /** 	Computes the block diagonal eigenvalue matrix.    If the original matrix A is not symmetric, then the eigenvalue 	matrix D is block diagonal with the real eigenvalues in 1-by-1 	blocks and any complex eigenvalues,    a + i*b, in 2-by-2 blocks, [a, b; -b, a].  That is, if the complex    eigenvalues look like<pre>          u + iv     .        .          .      .    .            .      u - iv     .          .      .    .            .        .      a + ib       .      .    .            .        .        .        a - ib   .    .            .        .        .          .      x    .            .        .        .          .      .    y</pre>        then D looks like<pre>            u        v        .          .      .    .           -v        u        .          .      .    .             .        .        a          b      .    .            .        .       -b          a      .    .            .        .        .          .      x    .            .        .        .          .      .    y</pre>    This keeps V a real matrix in both symmetric and non-symmetric    cases, and A*V = V*D.	@param D: upon return, the matrix is filled with the block diagonal 	eigenvalue matrix.	*/   void getD (TNT::Array2D<Real> &D) {      D = Array2D<Real>(n,n);      for (int i = 0; i < n; i++) {         for (int j = 0; j < n; j++) {            D[i][j] = 0.0;         }         D[i][i] = d[i];         if (e[i] > 0) {            D[i][i+1] = e[i];         } else if (e[i] < 0) {            D[i][i-1] = e[i];         }      }   }};} //namespace JAMA#endif// JAMA_EIG_H

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -