00001 #ifndef JAMA_QR_H
00002 #define JAMA_QR_H
00003
00004 #include "tnt_array1d.h"
00005 #include "tnt_array2d.h"
00006 #include "tnt_math_utils.h"
00007
00008 namespace JAMA
00009 {
00010
00034 template <class Real>
00035 class QR {
00036
00037
00042 TNT::Array2D<Real> QR_;
00043
00048 int m, n;
00049
00053 TNT::Array1D<Real> Rdiag;
00054
00055
00056 public:
00057
00063 QR(const TNT::Array2D<Real> &A)
00064 {
00065 QR_ = A.copy();
00066 m = A.dim1();
00067 n = A.dim2();
00068 Rdiag = TNT::Array1D<Real>(n);
00069 int i=0, j=0, k=0;
00070
00071
00072 for (k = 0; k < n; k++) {
00073
00074 Real nrm = 0;
00075 for (i = k; i < m; i++) {
00076 nrm = TNT::hypot(nrm,QR_[i][k]);
00077 }
00078
00079 if (nrm != 0.0) {
00080
00081 if (QR_[k][k] < 0) {
00082 nrm = -nrm;
00083 }
00084 for (i = k; i < m; i++) {
00085 QR_[i][k] /= nrm;
00086 }
00087 QR_[k][k] += 1.0;
00088
00089
00090 for (j = k+1; j < n; j++) {
00091 Real s = 0.0;
00092 for (i = k; i < m; i++) {
00093 s += QR_[i][k]*QR_[i][j];
00094 }
00095 s = -s/QR_[k][k];
00096 for (i = k; i < m; i++) {
00097 QR_[i][j] += s*QR_[i][k];
00098 }
00099 }
00100 }
00101 Rdiag[k] = -nrm;
00102 }
00103 }
00104
00105
00111 int isFullRank() const
00112 {
00113 for (int j = 0; j < n; j++)
00114 {
00115 if (Rdiag[j] == 0)
00116 return 0;
00117 }
00118 return 1;
00119 }
00120
00121
00122
00123
00130 TNT::Array2D<Real> getHouseholder (void) const
00131 {
00132 TNT::Array2D<Real> H(m,n);
00133
00134
00135
00136
00137 for (int i = 0; i < m; i++)
00138 {
00139 for (int j = 0; j < n; j++)
00140 {
00141 if (i >= j) {
00142 H[i][j] = QR_[i][j];
00143 } else {
00144 H[i][j] = 0.0;
00145 }
00146 }
00147 }
00148 return H;
00149 }
00150
00151
00152
00157 TNT::Array2D<Real> getR() const
00158 {
00159 TNT::Array2D<Real> R(n,n);
00160 for (int i = 0; i < n; i++) {
00161 for (int j = 0; j < n; j++) {
00162 if (i < j) {
00163 R[i][j] = QR_[i][j];
00164 } else if (i == j) {
00165 R[i][j] = Rdiag[i];
00166 } else {
00167 R[i][j] = 0.0;
00168 }
00169 }
00170 }
00171 return R;
00172 }
00173
00174
00175
00176
00177
00183 TNT::Array2D<Real> getQ() const
00184 {
00185 int i=0, j=0, k=0;
00186
00187 TNT::Array2D<Real> Q(m,n);
00188 for (k = n-1; k >= 0; k--) {
00189 for (i = 0; i < m; i++) {
00190 Q[i][k] = 0.0;
00191 }
00192 Q[k][k] = 1.0;
00193 for (j = k; j < n; j++) {
00194 if (QR_[k][k] != 0) {
00195 Real s = 0.0;
00196 for (i = k; i < m; i++) {
00197 s += QR_[i][k]*Q[i][j];
00198 }
00199 s = -s/QR_[k][k];
00200 for (i = k; i < m; i++) {
00201 Q[i][j] += s*QR_[i][k];
00202 }
00203 }
00204 }
00205 }
00206 return Q;
00207 }
00208
00209
00217 TNT::Array1D<Real> solve(const TNT::Array1D<Real> &b) const
00218 {
00219 if (b.dim1() != m)
00220 return TNT::Array1D<Real>();
00221
00222 if ( !isFullRank() )
00223 {
00224 return TNT::Array1D<Real>();
00225 }
00226
00227 TNT::Array1D<Real> x = b.copy();
00228
00229
00230 for (int k = 0; k < n; k++)
00231 {
00232 Real s = 0.0;
00233 for (int i = k; i < m; i++)
00234 {
00235 s += QR_[i][k]*x[i];
00236 }
00237 s = -s/QR_[k][k];
00238 for (int i = k; i < m; i++)
00239 {
00240 x[i] += s*QR_[i][k];
00241 }
00242 }
00243
00244 for (int k = n-1; k >= 0; k--)
00245 {
00246 x[k] /= Rdiag[k];
00247 for (int i = 0; i < k; i++) {
00248 x[i] -= x[k]*QR_[i][k];
00249 }
00250 }
00251
00252
00253
00254 TNT::Array1D<Real> x_(n);
00255 for (int i=0; i<n; i++)
00256 x_[i] = x[i];
00257
00258 return x_;
00259 }
00260
00268 TNT::Array2D<Real> solve(const TNT::Array2D<Real> &B) const
00269 {
00270 if (B.dim1() != m)
00271 return TNT::Array2D<Real>(0,0);
00272
00273 if ( !isFullRank() )
00274 {
00275 return TNT::Array2D<Real>(0,0);
00276 }
00277
00278 int nx = B.dim2();
00279 TNT::Array2D<Real> X = B.copy();
00280 int i=0, j=0, k=0;
00281
00282
00283 for (k = 0; k < n; k++) {
00284 for (j = 0; j < nx; j++) {
00285 Real s = 0.0;
00286 for (i = k; i < m; i++) {
00287 s += QR_[i][k]*X[i][j];
00288 }
00289 s = -s/QR_[k][k];
00290 for (i = k; i < m; i++) {
00291 X[i][j] += s*QR_[i][k];
00292 }
00293 }
00294 }
00295
00296 for (k = n-1; k >= 0; k--) {
00297 for (j = 0; j < nx; j++) {
00298 X[k][j] /= Rdiag[k];
00299 }
00300 for (i = 0; i < k; i++) {
00301 for (j = 0; j < nx; j++) {
00302 X[i][j] -= X[k][j]*QR_[i][k];
00303 }
00304 }
00305 }
00306
00307
00308
00309 TNT::Array2D<Real> X_(n,nx);
00310 for (i=0; i<n; i++)
00311 for (j=0; j<nx; j++)
00312 X_[i][j] = X[i][j];
00313
00314 return X_;
00315 }
00316
00317
00318 };
00319
00320
00321 }
00322
00323
00324 #endif
00325
00326