// This file is part of libigl, a simple c++ geometry processing library. // // Copyright (C) 2013 Alec Jacobson // // This Source Code Form is subject to the terms of the Mozilla Public License // v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "is_symmetric.h" #include "find.h" template IGL_INLINE bool igl::is_symmetric(const Eigen::SparseMatrix& A) { if(A.rows() != A.cols()) { return false; } // Not sure why this doesn't result in a .nonZeros() =0 below if(A.rows() == 1 && A.cols() == 1) { return true; } assert(A.size() != 0); Eigen::SparseMatrix AT = A.transpose(); Eigen::SparseMatrix AmAT = A-AT; //// Eigen screws up something with LLT if you try to do //SparseMatrix AmAT = A-A.transpose(); //// Eigen crashes at runtime if you try to do // return (A-A.transpose()).nonZeros() == 0; return AmAT.nonZeros() == 0; } template IGL_INLINE bool igl::is_symmetric( const Eigen::MatrixBase& A) { if(A.rows() != A.cols()) { return false; } assert(A.size() != 0); return (A-A.transpose()).eval().nonZeros() == 0; } template IGL_INLINE bool igl::is_symmetric( const Eigen::SparseMatrix& A, const epsilonT epsilon) { if(A.rows() != A.cols()) { return false; } // Not sure why this doesn't result in a .nonZeros() =0 below if(A.rows() == 1 && A.cols() == 1) { return true; } assert(A.size() != 0); Eigen::SparseMatrix AT = A.transpose(); Eigen::SparseMatrix AmAT = A-AT; Eigen::VectorXi AmATI,AmATJ; Eigen::Matrix AmATV; find(AmAT,AmATI,AmATJ,AmATV); if(AmATI.size() == 0) { return true; } return AmATV.maxCoeff() < epsilon && AmATV.minCoeff() > -epsilon; } #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh template bool igl::is_symmetric >(Eigen::MatrixBase > const&); // generated by autoexplicit.sh template bool igl::is_symmetric(Eigen::SparseMatrix const&); template bool igl::is_symmetric(Eigen::SparseMatrix const&, double); template bool igl::is_symmetric(Eigen::SparseMatrix const&, int); #endif