is_symmetric.cpp 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2013 Alec Jacobson <[email protected]>
  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 "is_symmetric.h"
  9. #include "find.h"
  10. template <typename T>
  11. IGL_INLINE bool igl::is_symmetric(const Eigen::SparseMatrix<T>& A)
  12. {
  13. if(A.rows() != A.cols())
  14. {
  15. return false;
  16. }
  17. // Not sure why this doesn't result in a .nonZeros() =0 below
  18. if(A.rows() == 1 && A.cols() == 1)
  19. {
  20. return true;
  21. }
  22. assert(A.size() != 0);
  23. Eigen::SparseMatrix<T> AT = A.transpose();
  24. Eigen::SparseMatrix<T> AmAT = A-AT;
  25. //// Eigen screws up something with LLT if you try to do
  26. //SparseMatrix<T> AmAT = A-A.transpose();
  27. //// Eigen crashes at runtime if you try to do
  28. // return (A-A.transpose()).nonZeros() == 0;
  29. return AmAT.nonZeros() == 0;
  30. }
  31. template <typename DerivedA>
  32. IGL_INLINE bool igl::is_symmetric(
  33. const Eigen::MatrixBase<DerivedA>& A)
  34. {
  35. if(A.rows() != A.cols())
  36. {
  37. return false;
  38. }
  39. assert(A.size() != 0);
  40. return (A-A.transpose()).eval().nonZeros() == 0;
  41. }
  42. template <typename AType, typename epsilonT>
  43. IGL_INLINE bool igl::is_symmetric(
  44. const Eigen::SparseMatrix<AType>& A,
  45. const epsilonT epsilon)
  46. {
  47. if(A.rows() != A.cols())
  48. {
  49. return false;
  50. }
  51. // Not sure why this doesn't result in a .nonZeros() =0 below
  52. if(A.rows() == 1 && A.cols() == 1)
  53. {
  54. return true;
  55. }
  56. assert(A.size() != 0);
  57. Eigen::SparseMatrix<AType> AT = A.transpose();
  58. Eigen::SparseMatrix<AType> AmAT = A-AT;
  59. Eigen::VectorXi AmATI,AmATJ;
  60. Eigen::Matrix<AType ,Eigen::Dynamic,1> AmATV;
  61. find(AmAT,AmATI,AmATJ,AmATV);
  62. if(AmATI.size() == 0)
  63. {
  64. return true;
  65. }
  66. return AmATV.maxCoeff() < epsilon && AmATV.minCoeff() > -epsilon;
  67. }
  68. #ifdef IGL_STATIC_LIBRARY
  69. // Explicit template instantiation
  70. // generated by autoexplicit.sh
  71. template bool igl::is_symmetric<Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&);
  72. // generated by autoexplicit.sh
  73. template bool igl::is_symmetric<double>(Eigen::SparseMatrix<double, 0, int> const&);
  74. template bool igl::is_symmetric<double, double>(Eigen::SparseMatrix<double, 0, int> const&, double);
  75. template bool igl::is_symmetric<double, int>(Eigen::SparseMatrix<double, 0, int> const&, int);
  76. #endif