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

📄 matrixfunctors.hpp

📁 gps源代码
💻 HPP
📖 第 1 页 / 共 2 页
字号:
#pragma ident "$Id: MatrixFunctors.hpp 142 2006-09-22 16:51:26Z architest $"/** * @file MatrixFunctors.hpp * Matrix function operators (SVD, LUD, etc) */ #ifndef GPSTK_MATRIX_FUNCTORS_HPP#define GPSTK_MATRIX_FUNCTORS_HPP//============================================================================////  This file is part of GPSTk, the GPS Toolkit.////  The GPSTk is free software; you can redistribute it and/or modify//  it under the terms of the GNU Lesser General Public License as published//  by the Free Software Foundation; either version 2.1 of the License, or//  any later version.////  The GPSTk is distributed in the hope that it will be useful,//  but WITHOUT ANY WARRANTY; without even the implied warranty of//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the//  GNU Lesser General Public License for more details.////  You should have received a copy of the GNU Lesser General Public//  License along with GPSTk; if not, write to the Free Software Foundation,//  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA//  //  Copyright 2004, The University of Texas at Austin////============================================================================#include <cmath>namespace gpstk{ /** @addtogroup VectorGroup */   //@{/** * Class SVD: A function object for the singular value decomposition of a matrix. * Given a matrix A [m,n], the SVD of A = U*S*transpose(V), where U is [m,m], * V is [n,n], and S is [m,n] (like A). Both U and V are unitary [meaning * transpose(U)*U = unity = transpose(V)*V] and the columns of U[resp,V] * are orthonormal vectors spanning the space A*transpose(A) [transpose(A)*A]. * Note that U*transpose(U)=1 and V*transpose(V)=1 are not true in general, * but may be. S[m,n] is 'diagonal' in the sense that only diagonal elements * are non-zero (even when m != n); the min(m,n) diagonal elements are called * the singular values of A, often referred to as S[i]. The singular values * may be sorted, as the SVD is invariant under a consistent re-ordering of * {singular values / columns of U / columns of V}. * The condition number of A is the ratio *    cn = fabs(largest S[i])/fabs(smallest S[i]). * Note that inverse(A) = V*inverse(S)*UT where inverse(S) is diagonal with * elements equal to the inverse of elements of S, and with dimension [n,m]. * The matrix A is non-singular matrix if and only if all of its singular * values are non-zero. If some of the singular values are zero, the * 'generalized inverse' of A may be formed by editing the singular values * in this way: if the ratio of S[i] to S[0] (where S[0] is the largest * singular value) is bigger than some tolerance (1.e-7 is good), then 1/S[i] * is set to zero in the inverse. In this way the 'generalized inverse' of * ANY matrix is guaranteed to exist. * The SVD algorithm never fails. * * Ref: Bulirsch and Stoer, "Introduction to Numerical Analysis," * NY, Springer-Verlag, 1980. * * @code * Matrix<double> m(and is assigned some value); * SVD<double> d; * d(m); * cout << d.U << endl << d.V << endl << d.S << endl; * @endcode */   template <class T>   class SVD   {   public:      SVD() : iterationMax(30) {}         /**          * Singular Value Decomposition          */      template <class BaseClass>      bool operator() (const ConstMatrixBase<T, BaseClass>& mat)         throw (MatrixException)         {            bool flip=false;            U = mat;            if(mat.rows() > mat.cols()) {               flip = true;               U = transpose(mat);            }            size_t n(U.cols()), m(U.rows());            size_t i, j, k, l, nm, jj, kk;            T anorm(0), scale(0), g(0), s, f, h, c, x, y, z;            V = Matrix<T>(n, n, T(0));            S = Vector<T>(n, T(1));            Vector<T> B(n, T(1));            for (i = 0; i < n; i++) {               l = i + 1;               B[i] = scale * g;               g = s = scale = T(0);               if (i < m) {                  for(k = i; k < m; k++) scale += ABS(U(k, i));                  if (scale) {                     for(k = i; k < m; k++) {                        U(k, i) /= scale;                        s += U(k, i) * U(k, i);                     }                     f = U(i, i);                     g = -SIGN(SQRT(s),f);                     h = f * g - s;                     U(i,i) = f - g;                     for(j = l; j < n; j++) {                        for(s = T(0), k = i; k < m; k++) s += U(k, i) * U(k, j);                        f = s / h;                        for(k = i; k < m; k++) U(k, j) += f * U(k, i);                     }                     for(k = i; k < m; k++) U(k, i) *= scale;                  } // if (scale)               }  // if (i < m)               S[i] = scale * g;               g = s = scale = T(0);               if ( (i < m) && (i != n-1) ) {                  for(k = l; k < n; k++) scale += ABS(U(i, k));                  if (scale) {                     for(k = l; k < n; k++) {                        U(i, k) /= scale;                        s += U(i, k) * U(i, k);                     }                     f = U(i, l);                     g = -SIGN(SQRT(s),f);                     h = f * g - s;                     U(i, l) = f - g;                     for(k = l; k < n; k++) B[k] = U(i, k) / h;                     for(j = l; j < m; j++) {                        for(s = T(0), k = l; k < n; k++) s += U(j, k) * U(i, k);                        for(k = l; k < n; k++) U(j, k) += s * B[k];                     }                     for(k = l; k < n; k++) U(i, k) *= scale;                  }               }               if(ABS(S[i])+ABS(B[i]) > anorm) anorm=ABS(S[i])+ABS(B[i]);            }            for(i = n - 1; ; i--) {               if (i < n - 1) {                  if (g) {                     for(j = l; j < n; j++) V(j, i) = (U(i, j) / U(i, l)) / g;                     for(j = l; j < n; j++) {                        for(s = T(0), k = l; k < n; k++) s += U(i, k) * V(k, j);                        for(k = l; k < n; k++) V(k, j) += s * V(k, i);                     }                  }                  for(j = l; j < n; j++) V(j, i) = V(i, j) = T(0);               }               V(i,i) =T(1);               g = B[i];               l = i;               if(i==0) break;            }            for(i = ( (m-1 < n-1) ? m-1 : n-1); ; i--) {               l = i+1;               g = S[i];               for(j=l; j<n; j++) U(i, j) = T(0);               if (g) {                  g = T(1) / g;                  for(j = l; j < n; j++) {                     for(s = T(0), k = l; k < m; k++) s += U(k,i) * U(k,j);                     f = (s / U(i,i)) * g;                     for(k=i; k<m; k++) U(k,j) += f * U(k,i);                  }                  for(j = i; j < m; j++) U(j,i) *= g;               }                else {                  for(j=i; j<m; j++) U(j,i) = T(0);               }               ++U(i,i);               if(i==0) break;            }            for(k = n - 1; ; k--) {               size_t its;               for(its = 1; its <= iterationMax; its++) {                  bool flag = true;                  for(l = k; ; l--) {                     nm = l - 1;                     if ((ABS(B[l])+anorm) == anorm) {                        flag = false;                        break;                     }                     if (l == 0) { // should never happen                        MatrixException e("SVD algorithm has nm==-1");                        GPSTK_THROW(e);                     }                     if ((ABS(S[nm])+anorm) == anorm) break;                     if(l == 0) break; // since l is unsigned...                  }                  if (flag) {                     c = T(0);                     s = T(1);                     for(i = l; i <= k; i++) {                        f = s * B[i];                        B[i] = c * B[i];                        if ((ABS(f) + anorm) == anorm) break;                        g = S[i];                        h = RSS(f,g);                        S[i] = h;                        h = T(1) / h;                        c = g * h;                        s = -f * h;                        for(j = 0; j < m; j++) {                           y = U(j, nm);                           z = U(j,i);                           U(j, nm) = y * c + z * s;                           U(j,i) = z * c - y * s;                        }                     }                  }                  z = S[k];                  if (l == k) {                     if (z < T(0)) {                        S[k] = -z;                        for(j = 0; j < n; j++) V(j,k) = -V(j,k);                     }                     break;                  }                              if (its == iterationMax) {                     MatrixException e("SVD algorithm did not converge");                     GPSTK_THROW(e);                  }                  x = S[l];                  if(k == 0) { // should never happen                     MatrixException e("SVD algorithm has k==0");                     GPSTK_THROW(e);                  }                  nm = k - 1;                  y = S[nm];                  g = B[nm];                  h = B[k];                  f = ( (y-z) * (y+z) + (g-h) * (g+h)) / (T(2) * h * y);                  g = RSS(f,T(1));                  f = ( (x-z) * (x+z) + h * ((y/(f + SIGN(g,f))) - h)) / x;                  c = s = 1.0;                  for(j = l; j <= nm; j++) {                     i = j + 1;                     g = B[i];                     y = S[i];                     h = s * g;                     g = c * g;                     z = RSS(f, h);                     B[j] = z;                     c = f / z;                     s = h / z;                     f = x * c + g * s;                     g = g * c - x * s;                     h = y * s;                     y *= c;                     for(jj = 0; jj < n; jj++) {                        x = V(jj, j);                        z = V(jj, i);                        V(jj, j) = x * c + z * s;                        V(jj, i) = z * c - x * s;                     }                     z = RSS(f, h);                     S[j] = z;                     if (z) {                        z = T(1) / z;                        c = f * z;                        s = h * z;                     }                     f = c * g + s * y;                     x = c * y - s * g;                     for(jj = 0; jj < m; jj++) {                        y = U(jj, j);                        z = U(jj, i);                        U(jj, j) = y * c + z * s;                        U(jj, i) = z * c - y * s;                     }                  }                  B[l] = T(0);                  B[k] = f;                  S[k] = x;               }               if(k==0) break;   // since k is unsigned...            }               // if U is not square - last n-m columns of U are zero - remove            if(U.cols() > U.rows()) {               for(i=1; i<S.size(); i++) {   // sort in descending order                  T sv=S[i],svj;                  kk = i-1;                  while(kk >= 0) {                     svj = S[kk];                     if(sv < svj) break;                     S[kk+1] = svj;                     // exchange columns kk and kk+1 in U and V                     U.swapCols(kk,kk+1);                     V.swapCols(kk,kk+1);                     kk = kk - 1;                  }                  S[kk+1] = sv;               }               Matrix<T> Temp(U);               U = Matrix<T>(Temp,0,0,Temp.rows(),Temp.rows());               S.resize(Temp.rows());            }            if(flip) {               Matrix<T> Temp(U);               U = V;               V = Temp;            }            return true;         }  // end SVD::operator() - the SVD algorithm            /** Backsubstitution using SVD.           * Solve A*x=b for vector x where A [mxn] has been SVD'ed and is given by           * U,W,V (*this); that is A[mxn] = U[mxm]*W[mxn]*VT[nxn]. b has dimension m,           * x dimension n. Singular values are NOT edited, except that if s.v. == 0,           * 1/0 is replaced by 0. Result is returned as b.         */      template <class BaseClass>      void backSub(RefVectorBase<T, BaseClass>& b) const          throw(MatrixException)      {         if(b.size() != U.rows())         {             MatrixException e("SVD::BackSub called with unequal dimensions");             GPSTK_THROW(e);         }            size_t i, n=V.cols(), m=U.rows();         Matrix<T> W(n,m,T(0));     // build the 'inverse singular values' matrix         for(i=0; i<S.size(); i++) W(i,i)=(S(i)==T(0)?T(0):T(1)/S(i));         Vector<T> Y;         Y = V*W*transpose(U)*b;         //b = Y;         // this fails because operator= is not defined for the base class         // (op= not inherited); use assignFrom instead         b.assignFrom(Y);      }  // end SVD::backSub         /// sort singular values      void sort(bool descending)         throw(MatrixException)      {         size_t i;         int j;         // j must be allowed to go negative         for(i=1; i<S.size(); i++) {            T sv=S(i),svj;            j = i - 1;            while(j >= 0) {               svj = S(j);               if(descending && sv < svj) break;               if(!descending && sv > svj) break;               S(j+1) = svj;               // exchange columns j and j+1 in U and V               U.swapCols(j,j+1);               V.swapCols(j,j+1);               j = j - 1;            }            S(j+1) = sv;         }      }  // end SVD::sort         /// compute determinant from SVD      inline T det(void)         throw(MatrixException)      {         T d(1);         for(size_t i=0; i<S.size(); i++) d *= S(i);         return d;      }  // end SVD::det

⌨️ 快捷键说明

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