Blender V2.61 - r43446
|
00001 00004 /* 00005 00006 * 00007 * Template Numerical Toolkit (TNT): Linear Algebra Module 00008 * 00009 * Mathematical and Computational Sciences Division 00010 * National Institute of Technology, 00011 * Gaithersburg, MD USA 00012 * 00013 * 00014 * This software was developed at the National Institute of Standards and 00015 * Technology (NIST) by employees of the Federal Government in the course 00016 * of their official duties. Pursuant to title 17 Section 105 of the 00017 * United States Code, this software is not subject to copyright protection 00018 * and is in the public domain. The Template Numerical Toolkit (TNT) is 00019 * an experimental system. NIST assumes no responsibility whatsoever for 00020 * its use by other parties, and makes no guarantees, expressed or implied, 00021 * about its quality, reliability, or any other characteristic. 00022 * 00023 * BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE 00024 * see http://math.nist.gov/tnt for latest updates. 00025 * 00026 */ 00027 00028 00029 #ifndef QR_H 00030 #define QR_H 00031 00032 // Classical QR factorization example, based on Stewart[1973]. 00033 // 00034 // 00035 // This algorithm computes the factorization of a matrix A 00036 // into a product of an orthognal matrix (Q) and an upper triangular 00037 // matrix (R), such that QR = A. 00038 // 00039 // Parameters: 00040 // 00041 // A (in): Matrix(1:N, 1:N) 00042 // 00043 // Q (output): Matrix(1:N, 1:N), collection of Householder 00044 // column vectors Q1, Q2, ... QN 00045 // 00046 // R (output): upper triangular Matrix(1:N, 1:N) 00047 // 00048 // Returns: 00049 // 00050 // 0 if successful, 1 if A is detected to be singular 00051 // 00052 00053 00054 #include <cmath> //for sqrt() & fabs() 00055 #include "tntmath.h" // for sign() 00056 00057 // Classical QR factorization, based on Stewart[1973]. 00058 // 00059 // 00060 // This algorithm computes the factorization of a matrix A 00061 // into a product of an orthognal matrix (Q) and an upper triangular 00062 // matrix (R), such that QR = A. 00063 // 00064 // Parameters: 00065 // 00066 // A (in/out): On input, A is square, Matrix(1:N, 1:N), that represents 00067 // the matrix to be factored. 00068 // 00069 // On output, Q and R is encoded in the same Matrix(1:N,1:N) 00070 // in the following manner: 00071 // 00072 // R is contained in the upper triangular section of A, 00073 // except that R's main diagonal is in D. The lower 00074 // triangular section of A represents Q, where each 00075 // column j is the vector Qj = I - uj*uj'/pi_j. 00076 // 00077 // C (output): vector of Pi[j] 00078 // D (output): main diagonal of R, i.e. D(i) is R(i,i) 00079 // 00080 // Returns: 00081 // 00082 // 0 if successful, 1 if A is detected to be singular 00083 // 00084 00085 namespace TNT 00086 { 00087 00088 template <class MaTRiX, class Vector> 00089 int QR_factor(MaTRiX &A, Vector& C, Vector &D) 00090 { 00091 assert(A.lbound() == 1); // ensure these are all 00092 assert(C.lbound() == 1); // 1-based arrays and vectors 00093 assert(D.lbound() == 1); 00094 00095 Subscript M = A.num_rows(); 00096 Subscript N = A.num_cols(); 00097 00098 assert(M == N); // make sure A is square 00099 00100 Subscript i,j,k; 00101 typename MaTRiX::element_type eta, sigma, sum; 00102 00103 // adjust the shape of C and D, if needed... 00104 00105 if (N != C.size()) C.newsize(N); 00106 if (N != D.size()) D.newsize(N); 00107 00108 for (k=1; k<N; k++) 00109 { 00110 // eta = max |M(i,k)|, for k <= i <= n 00111 // 00112 eta = 0; 00113 for (i=k; i<=N; i++) 00114 { 00115 double absA = fabs(A(i,k)); 00116 eta = ( absA > eta ? absA : eta ); 00117 } 00118 00119 if (eta == 0) // matrix is singular 00120 { 00121 cerr << "QR: k=" << k << "\n"; 00122 return 1; 00123 } 00124 00125 // form Qk and premiltiply M by it 00126 // 00127 for(i=k; i<=N; i++) 00128 A(i,k) = A(i,k) / eta; 00129 00130 sum = 0; 00131 for (i=k; i<=N; i++) 00132 sum = sum + A(i,k)*A(i,k); 00133 sigma = sign(A(k,k)) * sqrt(sum); 00134 00135 00136 A(k,k) = A(k,k) + sigma; 00137 C(k) = sigma * A(k,k); 00138 D(k) = -eta * sigma; 00139 00140 for (j=k+1; j<=N; j++) 00141 { 00142 sum = 0; 00143 for (i=k; i<=N; i++) 00144 sum = sum + A(i,k)*A(i,j); 00145 sum = sum / C(k); 00146 00147 for (i=k; i<=N; i++) 00148 A(i,j) = A(i,j) - sum * A(i,k); 00149 } 00150 00151 D(N) = A(N,N); 00152 } 00153 00154 return 0; 00155 } 00156 00157 // modified form of upper triangular solve, except that the main diagonal 00158 // of R (upper portion of A) is in D. 00159 // 00160 template <class MaTRiX, class Vector> 00161 int R_solve(const MaTRiX &A, /*const*/ Vector &D, Vector &b) 00162 { 00163 assert(A.lbound() == 1); // ensure these are all 00164 assert(D.lbound() == 1); // 1-based arrays and vectors 00165 assert(b.lbound() == 1); 00166 00167 Subscript i,j; 00168 Subscript N = A.num_rows(); 00169 00170 assert(N == A.num_cols()); 00171 assert(N == D.dim()); 00172 assert(N == b.dim()); 00173 00174 typename MaTRiX::element_type sum; 00175 00176 if (D(N) == 0) 00177 return 1; 00178 00179 b(N) = b(N) / 00180 D(N); 00181 00182 for (i=N-1; i>=1; i--) 00183 { 00184 if (D(i) == 0) 00185 return 1; 00186 sum = 0; 00187 for (j=i+1; j<=N; j++) 00188 sum = sum + A(i,j)*b(j); 00189 b(i) = ( b(i) - sum ) / 00190 D(i); 00191 } 00192 00193 return 0; 00194 } 00195 00196 00197 template <class MaTRiX, class Vector> 00198 int QR_solve(const MaTRiX &A, const Vector &c, /*const*/ Vector &d, 00199 Vector &b) 00200 { 00201 assert(A.lbound() == 1); // ensure these are all 00202 assert(c.lbound() == 1); // 1-based arrays and vectors 00203 assert(d.lbound() == 1); 00204 00205 Subscript N=A.num_rows(); 00206 00207 assert(N == A.num_cols()); 00208 assert(N == c.dim()); 00209 assert(N == d.dim()); 00210 assert(N == b.dim()); 00211 00212 Subscript i,j; 00213 typename MaTRiX::element_type sum, tau; 00214 00215 for (j=1; j<N; j++) 00216 { 00217 // form Q'*b 00218 sum = 0; 00219 for (i=j; i<=N; i++) 00220 sum = sum + A(i,j)*b(i); 00221 if (c(j) == 0) 00222 return 1; 00223 tau = sum / c(j); 00224 for (i=j; i<=N; i++) 00225 b(i) = b(i) - tau * A(i,j); 00226 } 00227 return R_solve(A, d, b); // solve Rx = Q'b 00228 } 00229 00230 } // namespace TNT 00231 00232 #endif // QR_H 00233