diff --git a/Eigen/src/Core/Fuzzy.h b/Eigen/src/Core/Fuzzy.h index 0a3620df9..3cd82d802 100644 --- a/Eigen/src/Core/Fuzzy.h +++ b/Eigen/src/Core/Fuzzy.h @@ -26,7 +26,67 @@ #ifndef EIGEN_FUZZY_H #define EIGEN_FUZZY_H -// TODO support small integer types properly i.e. do exact compare on coeffs --- taking a HS norm is guaranteed to cause integer overflow. +namespace internal +{ + +template::IsInteger> +struct isApprox_selector +{ + static bool run(const Derived& x, const OtherDerived& y, typename Derived::RealScalar prec) + { + const typename internal::nested::type nested(x); + const typename internal::nested::type otherNested(y); + return (nested - otherNested).cwiseAbs2().sum() <= prec * prec * std::min(nested.cwiseAbs2().sum(), otherNested.cwiseAbs2().sum()); + } +}; + +template +struct isApprox_selector +{ + static bool run(const Derived& x, const OtherDerived& y, typename Derived::RealScalar) + { + return x.matrix() == y.matrix(); + } +}; + +template::IsInteger> +struct isMuchSmallerThan_object_selector +{ + static bool run(const Derived& x, const OtherDerived& y, typename Derived::RealScalar prec) + { + return x.cwiseAbs2().sum() <= abs2(prec) * y.cwiseAbs2().sum(); + } +}; + +template +struct isMuchSmallerThan_object_selector +{ + static bool run(const Derived& x, const OtherDerived&, typename Derived::RealScalar) + { + return x.matrix() == Derived::Zero(x.rows(), x.cols()).matrix(); + } +}; + +template::IsInteger> +struct isMuchSmallerThan_scalar_selector +{ + static bool run(const Derived& x, const typename Derived::RealScalar& y, typename Derived::RealScalar prec) + { + return x.cwiseAbs2().sum() <= abs2(prec * y); + } +}; + +template +struct isMuchSmallerThan_scalar_selector +{ + static bool run(const Derived& x, const typename Derived::RealScalar&, typename Derived::RealScalar) + { + return x.matrix() == Derived::Zero(x.rows(), x.cols()).matrix(); + } +}; + +} // end namespace internal + /** \returns \c true if \c *this is approximately equal to \a other, within the precision * determined by \a prec. @@ -52,12 +112,7 @@ bool DenseBase::isApprox( RealScalar prec ) const { - const typename internal::nested::type nested(derived()); - const typename internal::nested::type otherNested(other.derived()); -// std::cerr << typeid(Derived).name() << " => " << typeid(typename internal::nested::type).name() << "\n"; -// std::cerr << typeid(OtherDerived).name() << " => " << typeid(typename internal::nested::type).name() << "\n"; -// return false; - return (nested - otherNested).cwiseAbs2().sum() <= prec * prec * std::min(nested.cwiseAbs2().sum(), otherNested.cwiseAbs2().sum()); + return internal::isApprox_selector::run(derived(), other.derived(), prec); } /** \returns \c true if the norm of \c *this is much smaller than \a other, @@ -79,7 +134,7 @@ bool DenseBase::isMuchSmallerThan( RealScalar prec ) const { - return derived().cwiseAbs2().sum() <= prec * prec * other * other; + return internal::isMuchSmallerThan_scalar_selector::run(derived(), other, prec); } /** \returns \c true if the norm of \c *this is much smaller than the norm of \a other, @@ -99,7 +154,7 @@ bool DenseBase::isMuchSmallerThan( RealScalar prec ) const { - return derived().cwiseAbs2().sum() <= prec * prec * other.derived().cwiseAbs2().sum(); + return internal::isMuchSmallerThan_object_selector::run(derived(), other.derived(), prec); } #endif // EIGEN_FUZZY_H