/src/Geometry_Eigen/Eigen/src/Core/Fuzzy.h
C Header | 161 lines | 83 code | 14 blank | 64 comment | 3 complexity | 26f7a314741ac28ac604a3a5c28040c3 MD5 | raw file
Possible License(s): AGPL-3.0, LGPL-2.1, LGPL-3.0, GPL-2.0
1// This file is part of Eigen, a lightweight C++ template library 2// for linear algebra. 3// 4// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com> 5// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr> 6// 7// Eigen is free software; you can redistribute it and/or 8// modify it under the terms of the GNU Lesser General Public 9// License as published by the Free Software Foundation; either 10// version 3 of the License, or (at your option) any later version. 11// 12// Alternatively, you can redistribute it and/or 13// modify it under the terms of the GNU General Public License as 14// published by the Free Software Foundation; either version 2 of 15// the License, or (at your option) any later version. 16// 17// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY 18// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 19// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the 20// GNU General Public License for more details. 21// 22// You should have received a copy of the GNU Lesser General Public 23// License and a copy of the GNU General Public License along with 24// Eigen. If not, see <http://www.gnu.org/licenses/>. 25 26#ifndef EIGEN_FUZZY_H 27#define EIGEN_FUZZY_H 28 29namespace internal 30{ 31 32template<typename Derived, typename OtherDerived, bool is_integer = NumTraits<typename Derived::Scalar>::IsInteger> 33struct isApprox_selector 34{ 35 static bool run(const Derived& x, const OtherDerived& y, typename Derived::RealScalar prec) 36 { 37 using std::min; 38 const typename internal::nested<Derived,2>::type nested(x); 39 const typename internal::nested<OtherDerived,2>::type otherNested(y); 40 return (nested - otherNested).cwiseAbs2().sum() <= prec * prec * (min)(nested.cwiseAbs2().sum(), otherNested.cwiseAbs2().sum()); 41 } 42}; 43 44template<typename Derived, typename OtherDerived> 45struct isApprox_selector<Derived, OtherDerived, true> 46{ 47 static bool run(const Derived& x, const OtherDerived& y, typename Derived::RealScalar) 48 { 49 return x.matrix() == y.matrix(); 50 } 51}; 52 53template<typename Derived, typename OtherDerived, bool is_integer = NumTraits<typename Derived::Scalar>::IsInteger> 54struct isMuchSmallerThan_object_selector 55{ 56 static bool run(const Derived& x, const OtherDerived& y, typename Derived::RealScalar prec) 57 { 58 return x.cwiseAbs2().sum() <= abs2(prec) * y.cwiseAbs2().sum(); 59 } 60}; 61 62template<typename Derived, typename OtherDerived> 63struct isMuchSmallerThan_object_selector<Derived, OtherDerived, true> 64{ 65 static bool run(const Derived& x, const OtherDerived&, typename Derived::RealScalar) 66 { 67 return x.matrix() == Derived::Zero(x.rows(), x.cols()).matrix(); 68 } 69}; 70 71template<typename Derived, bool is_integer = NumTraits<typename Derived::Scalar>::IsInteger> 72struct isMuchSmallerThan_scalar_selector 73{ 74 static bool run(const Derived& x, const typename Derived::RealScalar& y, typename Derived::RealScalar prec) 75 { 76 return x.cwiseAbs2().sum() <= abs2(prec * y); 77 } 78}; 79 80template<typename Derived> 81struct isMuchSmallerThan_scalar_selector<Derived, true> 82{ 83 static bool run(const Derived& x, const typename Derived::RealScalar&, typename Derived::RealScalar) 84 { 85 return x.matrix() == Derived::Zero(x.rows(), x.cols()).matrix(); 86 } 87}; 88 89} // end namespace internal 90 91 92/** \returns \c true if \c *this is approximately equal to \a other, within the precision 93 * determined by \a prec. 94 * 95 * \note The fuzzy compares are done multiplicatively. Two vectors \f$ v \f$ and \f$ w \f$ 96 * are considered to be approximately equal within precision \f$ p \f$ if 97 * \f[ \Vert v - w \Vert \leqslant p\,\(min)(\Vert v\Vert, \Vert w\Vert). \f] 98 * For matrices, the comparison is done using the Hilbert-Schmidt norm (aka Frobenius norm 99 * L2 norm). 100 * 101 * \note Because of the multiplicativeness of this comparison, one can't use this function 102 * to check whether \c *this is approximately equal to the zero matrix or vector. 103 * Indeed, \c isApprox(zero) returns false unless \c *this itself is exactly the zero matrix 104 * or vector. If you want to test whether \c *this is zero, use internal::isMuchSmallerThan(const 105 * RealScalar&, RealScalar) instead. 106 * 107 * \sa internal::isMuchSmallerThan(const RealScalar&, RealScalar) const 108 */ 109template<typename Derived> 110template<typename OtherDerived> 111bool DenseBase<Derived>::isApprox( 112 const DenseBase<OtherDerived>& other, 113 RealScalar prec 114) const 115{ 116 return internal::isApprox_selector<Derived, OtherDerived>::run(derived(), other.derived(), prec); 117} 118 119/** \returns \c true if the norm of \c *this is much smaller than \a other, 120 * within the precision determined by \a prec. 121 * 122 * \note The fuzzy compares are done multiplicatively. A vector \f$ v \f$ is 123 * considered to be much smaller than \f$ x \f$ within precision \f$ p \f$ if 124 * \f[ \Vert v \Vert \leqslant p\,\vert x\vert. \f] 125 * 126 * For matrices, the comparison is done using the Hilbert-Schmidt norm. For this reason, 127 * the value of the reference scalar \a other should come from the Hilbert-Schmidt norm 128 * of a reference matrix of same dimensions. 129 * 130 * \sa isApprox(), isMuchSmallerThan(const DenseBase<OtherDerived>&, RealScalar) const 131 */ 132template<typename Derived> 133bool DenseBase<Derived>::isMuchSmallerThan( 134 const typename NumTraits<Scalar>::Real& other, 135 RealScalar prec 136) const 137{ 138 return internal::isMuchSmallerThan_scalar_selector<Derived>::run(derived(), other, prec); 139} 140 141/** \returns \c true if the norm of \c *this is much smaller than the norm of \a other, 142 * within the precision determined by \a prec. 143 * 144 * \note The fuzzy compares are done multiplicatively. A vector \f$ v \f$ is 145 * considered to be much smaller than a vector \f$ w \f$ within precision \f$ p \f$ if 146 * \f[ \Vert v \Vert \leqslant p\,\Vert w\Vert. \f] 147 * For matrices, the comparison is done using the Hilbert-Schmidt norm. 148 * 149 * \sa isApprox(), isMuchSmallerThan(const RealScalar&, RealScalar) const 150 */ 151template<typename Derived> 152template<typename OtherDerived> 153bool DenseBase<Derived>::isMuchSmallerThan( 154 const DenseBase<OtherDerived>& other, 155 RealScalar prec 156) const 157{ 158 return internal::isMuchSmallerThan_object_selector<Derived, OtherDerived>::run(derived(), other.derived(), prec); 159} 160 161#endif // EIGEN_FUZZY_H