qr.h
上传用户:kellyonhid
上传日期:2013-10-12
资源大小:932k
文件大小:5k
源码类别:

3D图形编程

开发平台:

Visual C++

  1. // Template Numerical Toolkit (TNT) for Linear Algebra
  2. //
  3. // BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
  4. // Please see http://math.nist.gov/tnt for updates
  5. //
  6. // R. Pozo
  7. // Mathematical and Computational Sciences Division
  8. // National Institute of Standards and Technology
  9. #ifndef QR_H
  10. #define QR_H
  11. // Classical QR factorization example, based on Stewart[1973].
  12. //
  13. //
  14. // This algorithm computes the factorization of a matrix A
  15. // into a product of an orthognal matrix (Q) and an upper triangular 
  16. // matrix (R), such that QR = A.
  17. //
  18. // Parameters:
  19. //
  20. //  A   (in):       Matrix(1:N, 1:N)
  21. //
  22. //  Q   (output):   Matrix(1:N, 1:N), collection of Householder
  23. //                      column vectors Q1, Q2, ... QN
  24. //
  25. //  R   (output):   upper triangular Matrix(1:N, 1:N)
  26. //
  27. // Returns:  
  28. //
  29. //  0 if successful, 1 if A is detected to be singular
  30. //
  31. // needed for sqrt() below
  32. //
  33. #include <math.h>
  34. // for abs() and sign()
  35. //
  36. #include "tntmath.h"
  37. // Classical QR factorization, based on Stewart[1973].
  38. //
  39. //
  40. // This algorithm computes the factorization of a matrix A
  41. // into a product of an orthognal matrix (Q) and an upper triangular 
  42. // matrix (R), such that QR = A.
  43. //
  44. // Parameters:
  45. //
  46. //  A   (in/out):  On input, A is square, Matrix(1:N, 1:N), that represents
  47. //                  the matrix to be factored.
  48. //
  49. //                 On output, Q and R is encoded in the same Matrix(1:N,1:N)
  50. //                 in the following manner:
  51. //
  52. //                  R is contained in the upper triangular section of A,
  53. //                  except that R's main diagonal is in D.  The lower
  54. //                  triangular section of A represents Q, where each
  55. //                  column j is the vector  Qj = I - uj*uj'/pi_j.
  56. //
  57. //  C  (output):    vector of Pi[j]
  58. //  D  (output):    main diagonal of R, i.e. D(i) is R(i,i)
  59. //
  60. // Returns:  
  61. //
  62. //  0 if successful, 1 if A is detected to be singular
  63. //
  64. template <class Matrix, class Vector>
  65. int QR_factor(Matrix &A, Vector& C, Vector &D)
  66. {
  67.     assert(A.lbound() == 1);        // ensure these are all 
  68.     assert(C.lbound() == 1);        // 1-based arrays and vectors
  69.     assert(D.lbound() == 1);
  70.     Subscript M = A.num_rows();
  71.     Subscript N = A.num_cols(); 
  72.     assert(M == N);                 // make sure A is square
  73.     Subscript i,j,k;
  74.     Matrix::element_type eta, sigma, sum;
  75.     // adjust the shape of C and D, if needed...
  76.     if (N != C.size())  C.newsize(N);
  77.     if (N != D.size())  D.newsize(N);
  78.     for (k=1; k<N; k++)
  79.     {
  80.         // eta = max |M(i,k)|,  for k <= i <= n
  81.         //
  82.         eta = 0;
  83.         for (i=k; i<=N; i++)
  84.             eta = ( abs(A(i,k)) >  eta ? abs( A(i,k) ) : eta ); 
  85.         if (eta == 0)           // matrix is singular
  86.             return 1;
  87.         // form Qk and premiltiply M by it
  88.         //
  89.         for(i=k; i<=N; i++)
  90.             A(i,k)  = A(i,k) / eta;
  91.         sum = 0;
  92.         for (i=k; i<=N; i++)
  93.             sum = sum + A(i,k)*A(i,k);
  94.         sigma = sign(A(k,k)) *  sqrt(sum);
  95.         A(k,k) = A(k,k) + sigma;
  96.         C(k) = sigma * A(k,k);
  97.         D(k) = -eta * sigma;
  98.         for (j=k+1; j<=N; j++)
  99.         {
  100.             sum = 0;
  101.             for (i=k; i<=N; i++)
  102.                 sum = sum + A(i,k)*A(i,j);
  103.             sum = sum / C(k);
  104.             for (i=k; i<=N; i++)
  105.                 A(i,j) = A(i,j) - sum * A(i,k);
  106.         }
  107.         D(N) = A(N,N);
  108.     }
  109.     return 0;
  110. }
  111. // modified form of upper triangular solve, except that the main diagonal
  112. // of R (upper portion of A) is in D.
  113. //
  114. template <class Matrix, class Vector>
  115. int R_solve(const Matrix &A, const Vector &D, Vector &b)
  116. {
  117.     assert(A.lbound() == 1);        // ensure these are all 
  118.     assert(D.lbound() == 1);        // 1-based arrays and vectors
  119.     assert(b.lbound() == 1);
  120.     Subscript i,j;
  121.     Subscript N = A.num_rows();
  122.     assert(N == A.num_cols());
  123.     assert(N == D.dim());
  124.     assert(N == b.dim());
  125.     Matrix::element_type sum;
  126.     if (D(N) == 0)
  127.         return 1;
  128.     b(N) = b(N) / D(N);
  129.     for (i=N-1; i>=1; i--)
  130.     {
  131.         if (D(i) == 0)
  132.             return 1;
  133.         sum = 0;
  134.         for (j=i+1; j<=N; j++)
  135.             sum = sum + A(i,j)*b(j);
  136.         b(i) = ( b(i) - sum ) / D(i);
  137.     }
  138.     return 0;
  139. }
  140. template <class Matrix, class Vector>
  141. int QR_solve(const Matrix &A, const Vector &c, const Vector &d, 
  142.         Vector &b)
  143. {
  144.     assert(A.lbound() == 1);        // ensure these are all 
  145.     assert(c.lbound() == 1);        // 1-based arrays and vectors
  146.     assert(d.lbound() == 1);
  147.     Subscript N=A.num_rows();
  148.     assert(N == A.num_cols());
  149.     assert(N == c.dim());
  150.     assert(N == d.dim());
  151.     assert(N == b.dim());
  152.     Subscript i,j;
  153.     Matrix::element_type sum, tau;
  154.     for (j=1; j<N; j++)
  155.     {
  156.         // form Q'*b
  157.         sum = 0;
  158.         for (i=j; i<=N; i++)
  159.             sum = sum + A(i,j)*b(i);
  160.         if (c(j) == 0)
  161.             return 1;
  162.         tau = sum / c(j);
  163.        for (i=j; i<=N; i++)
  164.             b(i) = b(i) - tau * A(i,j);
  165.     }
  166.     return R_solve(A, d, b);        // solve Rx = Q'b
  167. }
  168. #endif
  169. // QR_H