Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
qr.h
1 /*
2 This file is distributed as part of the BIAS library (Basic ImageAlgorithmS)
3 but it has not been developed by the authors of BIAS.
4 
5 For copyright, author and license information see below.
6 */
7 
8 
9 /*
10 *
11 * Template Numerical Toolkit (TNT): Linear Algebra Module
12 *
13 * Mathematical and Computational Sciences Division
14 * National Institute of Technology,
15 * Gaithersburg, MD USA
16 *
17 *
18 * This software was developed at the National Institute of Standards and
19 * Technology (NIST) by employees of the Federal Government in the course
20 * of their official duties. Pursuant to title 17 Section 105 of the
21 * United States Code, this software is not subject to copyright protection
22 * and is in the public domain. The Template Numerical Toolkit (TNT) is
23 * an experimental system. NIST assumes no responsibility whatsoever for
24 * its use by other parties, and makes no guarantees, expressed or implied,
25 * about its quality, reliability, or any other characteristic.
26 *
27 * BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
28 * see http://math.nist.gov/tnt for latest updates.
29 *
30 */
31 
32 
33 #ifndef QR_H
34 #define QR_H
35 
36 // Classical QR factorization example, based on Stewart[1973].
37 //
38 //
39 // This algorithm computes the factorization of a matrix A
40 // into a product of an orthognal matrix (Q) and an upper triangular
41 // matrix (R), such that QR = A.
42 //
43 // Parameters:
44 //
45 // A (in): Matrix(1:N, 1:N)
46 //
47 // Q (output): Matrix(1:N, 1:N), collection of Householder
48 // column vectors Q1, Q2, ... QN
49 //
50 // R (output): upper triangular Matrix(1:N, 1:N)
51 //
52 // Returns:
53 //
54 // 0 if successful, 1 if A is detected to be singular
55 //
56 
57 
58 #include <cmath> //for sqrt() & fabs()
59 #include "tntmath.h" // for sign()
60 
61 // Classical QR factorization, based on Stewart[1973].
62 //
63 //
64 // This algorithm computes the factorization of a matrix A
65 // into a product of an orthognal matrix (Q) and an upper triangular
66 // matrix (R), such that QR = A.
67 //
68 // Parameters:
69 //
70 // A (in/out): On input, A is square, Matrix(1:N, 1:N), that represents
71 // the matrix to be factored.
72 //
73 // On output, Q and R is encoded in the same Matrix(1:N,1:N)
74 // in the following manner:
75 //
76 // R is contained in the upper triangular section of A,
77 // except that R's main diagonal is in D. The lower
78 // triangular section of A represents Q, where each
79 // column j is the vector Qj = I - uj*uj'/pi_j.
80 //
81 // C (output): vector of Pi[j]
82 // D (output): main diagonal of R, i.e. D(i) is R(i,i)
83 //
84 // Returns:
85 //
86 // 0 if successful, 1 if A is detected to be singular
87 //
88 
89 namespace TNT
90 {
91 
92  template <class MaTRiX, class Vector>
93  int QR_factor(MaTRiX &A, Vector& C, Vector &D)
94  {
95  BIASASSERT(A.lbound() == 1); // ensure these are all
96  BIASASSERT(C.lbound() == 1); // 1-based arrays and vectors
97  BIASASSERT(D.lbound() == 1);
98 
99  Subscript M = A.num_rows();
100  Subscript N = A.num_cols();
101 
102  BIASASSERT(M == N); // make sure A is square
103 
104  Subscript i,j,k;
105  typename MaTRiX::element_type eta, sigma, sum;
106 
107  // adjust the shape of C and D, if needed...
108 
109  if (N != C.size()) C.newsize(N);
110  if (N != D.size()) D.newsize(N);
111 
112  for (k=1; k<N; k++)
113  {
114  // eta = max |M(i,k)|, for k <= i <= n
115  //
116  eta = 0;
117  for (i=k; i<=N; i++)
118  {
119  double absA = fabs(A(i,k));
120  eta = ( absA > eta ? absA : eta );
121  }
122 
123  if (eta == 0) // matrix is singular
124  {
125  cerr << "QR: k=" << k << "\n";
126  return 1;
127  }
128 
129  // form Qk and premiltiply M by it
130  //
131  for(i=k; i<=N; i++)
132  A(i,k) = A(i,k) / eta;
133 
134  sum = 0;
135  for (i=k; i<=N; i++)
136  sum = sum + A(i,k)*A(i,k);
137  sigma = sign(A(k,k)) * sqrt(sum);
138 
139 
140  A(k,k) = A(k,k) + sigma;
141  C(k) = sigma * A(k,k);
142  D(k) = -eta * sigma;
143 
144  for (j=k+1; j<=N; j++)
145  {
146  sum = 0;
147  for (i=k; i<=N; i++)
148  sum = sum + A(i,k)*A(i,j);
149  sum = sum / C(k);
150 
151  for (i=k; i<=N; i++)
152  A(i,j) = A(i,j) - sum * A(i,k);
153  }
154 
155  D(N) = A(N,N);
156  }
157 
158  return 0;
159  }
160 
161  // modified form of upper triangular solve, except that the main diagonal
162  // of R (upper portion of A) is in D.
163  //
164  template <class MaTRiX, class Vector>
165  int R_solve(const MaTRiX &A, /*const*/ Vector &D, Vector &b)
166  {
167  BIASASSERT(A.lbound() == 1); // ensure these are all
168  BIASASSERT(D.lbound() == 1); // 1-based arrays and vectors
169  BIASASSERT(b.lbound() == 1);
170 
171  Subscript i,j;
172  Subscript N = A.num_rows();
173 
174  BIASASSERT(N == A.num_cols());
175  BIASASSERT(N == D.dim());
176  BIASASSERT(N == b.dim());
177 
178  typename MaTRiX::element_type sum;
179 
180  if (D(N) == 0)
181  return 1;
182 
183  b(N) = b(N) /
184  D(N);
185 
186  for (i=N-1; i>=1; i--)
187  {
188  if (D(i) == 0)
189  return 1;
190  sum = 0;
191  for (j=i+1; j<=N; j++)
192  sum = sum + A(i,j)*b(j);
193  b(i) = ( b(i) - sum ) /
194  D(i);
195  }
196 
197  return 0;
198  }
199 
200 
201  template <class MaTRiX, class Vector>
202  int QR_solve(const MaTRiX &A, const Vector &c, /*const*/ Vector &d,
203  Vector &b)
204  {
205  BIASASSERT(A.lbound() == 1); // ensure these are all
206  BIASASSERT(c.lbound() == 1); // 1-based arrays and vectors
207  BIASASSERT(d.lbound() == 1);
208 
209  Subscript N=A.num_rows();
210 
211  BIASASSERT(N == A.num_cols());
212  BIASASSERT(N == c.dim());
213  BIASASSERT(N == d.dim());
214  BIASASSERT(N == b.dim());
215 
216  Subscript i,j;
217  typename MaTRiX::element_type sum, tau;
218 
219  for (j=1; j<N; j++)
220  {
221  // form Q'*b
222  sum = 0;
223  for (i=j; i<=N; i++)
224  sum = sum + A(i,j)*b(i);
225  if (c(j) == 0)
226  return 1;
227  tau = sum / c(j);
228  for (i=j; i<=N; i++)
229  b(i) = b(i) - tau * A(i,j);
230  }
231  return R_solve(A, d, b); // solve Rx = Q'b
232  }
233 
234 } // namespace TNT
235 
236 #endif
237 // QR_H
int QR_factor(MaTRiX &A, Vector &C, Vector &D)
Definition: qr.h:93
TNT_SUBSCRIPT_TYPE Subscript
Definition: subscript.h:55
Subscript dim() const
Definition: vec.h:257
double sign(double a)
Definition: tntmath.h:92
Vector< T > & newsize(Subscript N)
Definition: vec.h:220
int R_solve(const MaTRiX &A, Vector &D, Vector &b)
Definition: qr.h:165
Subscript lbound() const
Definition: vec.h:70
int QR_solve(const MaTRiX &A, const Vector &c, Vector &d, Vector &b)
Definition: qr.h:202
Subscript size() const
Definition: vec.h:262