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