orth.h 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. //
  2. // orth.h
  3. //
  4. // Created by Olga Diamanti on 9/11/11.
  5. // Copyright (c) 2011 ETH Zurich. All rights reserved.
  6. //
  7. #ifndef IGL_ORTH_H
  8. #define IGL_ORTH_H
  9. #include <Eigen/Core>
  10. namespace igl
  11. {
  12. // ORTH Orthogonalization.
  13. // ORTH(A,Q) produces Q as an orthonormal basis for the range of A.
  14. // That is, Q'*Q = I, the columns of Q span the same space as
  15. // the columns of A, and the number of columns of Q is the
  16. // rank of A.
  17. //
  18. //
  19. // The algorithm uses singular value decomposition, SVD, instead of orthogonal
  20. // factorization, QR. This doubles the computation time, but
  21. // provides more reliable and consistent rank determination.
  22. // Closely follows MATLAB implementation in orth.m
  23. //
  24. inline void orth(const Eigen::MatrixXd &A, Eigen::MatrixXd &Q);
  25. }
  26. // Implementation
  27. inline void igl::orth(const Eigen::MatrixXd &A, Eigen::MatrixXd &Q)
  28. {
  29. //perform svd on A = U*S*V' (V is not computed and only the thin U is computed)
  30. Eigen::JacobiSVD<Eigen::MatrixXd> svd(A, Eigen::ComputeThinU );
  31. Eigen::MatrixXd U = svd.matrixU();
  32. const Eigen::VectorXd S = svd.singularValues();
  33. //get rank of A
  34. int m = A.rows();
  35. int n = A.cols();
  36. double tol = std::max(m,n) * S.maxCoeff() * 2.2204e-16;
  37. int r = 0;
  38. for (int i = 0; i < S.rows(); ++r,++i)
  39. {
  40. if (S[i] < tol)
  41. break;
  42. }
  43. //keep r first columns of U
  44. Q = U.block(0,0,U.rows(),r);
  45. }
  46. #endif