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
00018 for (k = 0; k < n; k++)
00019 {
00020
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
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
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);
00149
00150 if (!isFullRank())
00151 {
00152 throw Exception(Exception::SingularMatrix);
00153 }
00154
00155 Vector x = b;
00156 int i=0, j=0, k=0;
00157
00158
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
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
00184 Vector x_(n);
00185 for (i=0; i<n; i++)
00186 x_[i] = x[i];
00187
00188 return x_;
00189 }
00190
00191 }
00192