Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

Tools/Math/LA_Qr_decomp.cpp

Go to the documentation of this file.
00001 //------------------------------------------------------------------------------
00002 #include <assert.h>
00003 #include <math.h>
00004 #include "LA_Qr_decomp.h"
00005 //------------------------------------------------------------------------------
00006 namespace LA
00007 {
00008 //------------------------------------------------------------------------------
00009 QR::QR(const Matrix& A)
00010 {
00011   QR_ = A;
00012   m = A.rows();
00013   n = A.columns();
00014   Rdiag.create(n);
00015   int i=0, j=0, k=0;
00016 
00017   // Main loop.
00018   for (k = 0; k < n; k++)
00019   {
00020     // Compute 2-norm of k-th column without under/overflow.
00021     double nrm = 0;
00022     for (i = k; i < m; i++)
00023     {
00024       nrm = _hypot(nrm,QR_[i][k]);
00025     }
00026 
00027     if (nrm != 0.0)
00028     {
00029       // Form k-th Householder vector.
00030       if (QR_[k][k] < 0)
00031       {
00032         nrm = -nrm;
00033       }
00034       for (i = k; i < m; i++)
00035       {
00036         QR_[i][k] /= nrm;
00037       }
00038       QR_[k][k] += 1.0;
00039 
00040       // Apply transformation to remaining columns.
00041       for (j = k+1; j < n; j++)
00042       {
00043         double s = 0.0; 
00044         for (i = k; i < m; i++)
00045         {
00046           s += QR_[i][k]*QR_[i][j];
00047         }
00048         s = -s/QR_[k][k];
00049         for (i = k; i < m; i++)
00050         {
00051           QR_[i][j] += s*QR_[i][k];
00052         }
00053       }
00054     }
00055     Rdiag[k] = -nrm;
00056   }
00057 }
00058 //------------------------------------------------------------------------------
00059 bool QR::isFullRank() const
00060 {
00061   for (int j = 0; j < n; j++) 
00062   {
00063     if (Rdiag[j] == 0)
00064       return false;
00065   }
00066   return true;
00067 }
00068 //------------------------------------------------------------------------------
00069 Matrix QR::getHouseholder() const
00070 {
00071   Matrix H(m,n);
00072 
00073   for (int i = 0; i < m; i++) 
00074   {
00075     for (int j = 0; j < n; j++) 
00076     {
00077       if (i >= j)
00078       {
00079         H[i][j] = QR_[i][j];
00080       }
00081       else
00082       {
00083         H[i][j] = 0.0;
00084       }
00085     }
00086   }
00087   return H;
00088 }
00089 //------------------------------------------------------------------------------
00090 Matrix QR::getR() const
00091 {
00092   Matrix R(n,n);
00093   for (int i = 0; i < n; i++)
00094   {
00095     for (int j = 0; j < n; j++)
00096     {
00097       if (i < j)
00098       {
00099         R[i][j] = QR_[i][j];
00100       }
00101       else if (i == j)
00102       {
00103         R[i][j] = Rdiag[i];
00104       }
00105       else
00106       {
00107         R[i][j] = 0.0;
00108       }
00109     }
00110   } 
00111   return R;
00112 }
00113 //------------------------------------------------------------------------------
00114 Matrix QR::getQ() const
00115 {
00116   int i=0, j=0, k=0;
00117 
00118   Matrix Q(m,n);
00119   for (k = n-1; k >= 0; k--)
00120   {
00121     for (i = 0; i < m; i++)
00122     {
00123       Q[i][k] = 0.0;
00124     }
00125     Q[k][k] = 1.0;
00126     for (j = k; j < n; j++)
00127     {
00128       if (QR_[k][k] != 0)
00129       {
00130         double s = 0.0;
00131         for (i = k; i < m; i++)
00132         {
00133           s += QR_[i][k]*Q[i][j];
00134         }
00135         s = -s / QR_[k][k];
00136         for (i = k; i < m; i++)
00137         {
00138           Q[i][j] += s*QR_[i][k];
00139         }
00140       }
00141     }
00142   }
00143   return Q;
00144 }
00145 //------------------------------------------------------------------------------
00146 Vector QR::solve(const Vector& b) const
00147 {
00148   assert(b.dim() == m); /* arrays must be conformant */
00149   
00150   if (!isFullRank())  /* matrix is rank deficient */
00151   {
00152     throw Exception(Exception::SingularMatrix);
00153   }
00154 
00155   Vector x = b;
00156   int i=0, j=0, k=0;
00157 
00158   // Compute Y = transpose(Q)*b
00159   for (k = 0; k < n; k++) 
00160   {
00161     double s = 0.0; 
00162     for (i = k; i < m; i++) 
00163     {
00164       s += QR_[i][k]*x[i];
00165     }
00166     s = -s/QR_[k][k];
00167     for (i = k; i < m; i++) 
00168     {
00169       x[i] += s*QR_[i][k];
00170     }
00171   }
00172   // Solve R*X = Y;
00173   for (k = n-1; k >= 0; k--) 
00174   {
00175     x[k] /= Rdiag[k];
00176     for (i = 0; i < k; i++)
00177     {
00178       x[i] -= x[k]*QR_[i][k];
00179     }
00180   }
00181 
00182 
00183   /* return n x nx portion of X */
00184   Vector x_(n);
00185   for (i=0; i<n; i++)
00186     x_[i] = x[i];
00187 
00188   return x_;
00189 }
00190 //------------------------------------------------------------------------------
00191 }
00192 //------------------------------------------------------------------------------

Generated on Mon Mar 20 22:00:06 2006 for GT2005 by doxygen 1.3.6