polar_svd3x3.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #include "polar_svd3x3.h"
  9. #include "svd3x3.h"
  10. #ifdef __SSE__
  11. # include "svd3x3_sse.h"
  12. #endif
  13. #ifdef __AVX__
  14. # include "svd3x3_avx.h"
  15. #endif
  16. template<typename Mat>
  17. IGL_INLINE void igl::polar_svd3x3(const Mat& A, Mat& R)
  18. {
  19. // should be caught at compile time, but just to be 150% sure:
  20. assert(A.rows() == 3 && A.cols() == 3);
  21. Eigen::Matrix<typename Mat::Scalar, 3, 3> U, Vt;
  22. Eigen::Matrix<typename Mat::Scalar, 3, 1> S;
  23. svd3x3(A, U, S, Vt);
  24. R = U * Vt.transpose();
  25. }
  26. #ifdef __SSE__
  27. template<typename T>
  28. IGL_INLINE void igl::polar_svd3x3_sse(const Eigen::Matrix<T, 3*4, 3>& A, Eigen::Matrix<T, 3*4, 3> &R)
  29. {
  30. // should be caught at compile time, but just to be 150% sure:
  31. assert(A.rows() == 3*4 && A.cols() == 3);
  32. Eigen::Matrix<T, 3*4, 3> U, Vt;
  33. Eigen::Matrix<T, 3*4, 1> S;
  34. svd3x3_sse(A, U, S, Vt);
  35. for (int k=0; k<4; k++)
  36. {
  37. R.block(3*k, 0, 3, 3) = U.block(3*k, 0, 3, 3) * Vt.block(3*k, 0, 3, 3).transpose();
  38. }
  39. //// test:
  40. //for (int k=0; k<4; k++)
  41. //{
  42. // Eigen::Matrix3f Apart = A.block(3*k, 0, 3, 3);
  43. // Eigen::Matrix3f Rpart;
  44. // polar_svd3x3(Apart, Rpart);
  45. // Eigen::Matrix3f Rpart_SSE = R.block(3*k, 0, 3, 3);
  46. // Eigen::Matrix3f diff = Rpart - Rpart_SSE;
  47. // float diffNorm = diff.norm();
  48. // int hu = 1;
  49. //}
  50. //// eof test
  51. }
  52. #endif
  53. #ifdef __AVX__
  54. template<typename T>
  55. IGL_INLINE void igl::polar_svd3x3_avx(const Eigen::Matrix<T, 3*8, 3>& A, Eigen::Matrix<T, 3*8, 3> &R)
  56. {
  57. // should be caught at compile time, but just to be 150% sure:
  58. assert(A.rows() == 3*8 && A.cols() == 3);
  59. Eigen::Matrix<T, 3*8, 3> U, Vt;
  60. Eigen::Matrix<T, 3*8, 1> S;
  61. svd3x3_avx(A, U, S, Vt);
  62. for (int k=0; k<8; k++)
  63. {
  64. R.block(3*k, 0, 3, 3) = U.block(3*k, 0, 3, 3) * Vt.block(3*k, 0, 3, 3).transpose();
  65. }
  66. // test:
  67. for (int k=0; k<8; k++)
  68. {
  69. Eigen::Matrix3f Apart = A.block(3*k, 0, 3, 3);
  70. Eigen::Matrix3f Rpart;
  71. polar_svd3x3(Apart, Rpart);
  72. Eigen::Matrix3f Rpart_SSE = R.block(3*k, 0, 3, 3);
  73. Eigen::Matrix3f diff = Rpart - Rpart_SSE;
  74. float diffNorm = diff.norm();
  75. if (std::abs(diffNorm) > 0.001)
  76. {
  77. printf("Huh: diffNorm = %15f (k = %i)\n", diffNorm, k);
  78. }
  79. // Unused
  80. //int hu = 1;
  81. }
  82. // eof test
  83. }
  84. #endif
  85. #ifdef IGL_STATIC_LIBRARY
  86. // Explicit template specialization
  87. template void igl::polar_svd3x3<Eigen::Matrix<double, 3, 3, 0, 3, 3> >(Eigen::Matrix<double, 3, 3, 0, 3, 3> const&, Eigen::Matrix<double, 3, 3, 0, 3, 3>&);
  88. template void igl::polar_svd3x3<Eigen::Matrix<float,3,3,0,3,3> >(Eigen::Matrix<float,3,3,0,3,3> const &,Eigen::Matrix<float,3,3,0,3,3> &);
  89. #ifdef __SSE__
  90. template void igl::polar_svd3x3_sse<float>(Eigen::Matrix<float, 12, 3, 0, 12, 3> const&, Eigen::Matrix<float, 12, 3, 0, 12, 3>&);
  91. #endif
  92. #ifdef __AVX__
  93. template void igl::polar_svd3x3_avx<float>(Eigen::Matrix<float, 24, 3, 0, 24, 3> const&, Eigen::Matrix<float, 24, 3, 0, 24, 3>&);
  94. #endif
  95. #endif