diff options
author | Benoit Jacob <jacob.benoit.1@gmail.com> | 2011-02-07 10:53:17 -0500 |
---|---|---|
committer | Benoit Jacob <jacob.benoit.1@gmail.com> | 2011-02-07 10:53:17 -0500 |
commit | 68a2e04a96401db3339b47a18d1229e707aebdd9 (patch) | |
tree | 48bdbbc6bea88d525a77800a83af30b0807048c7 /Eigen/src/Core/Fuzzy.h | |
parent | c5c8efa575038fc2e428c17c60050f7abfbb7a1b (diff) |
fix fuzzy compares for integer types, using a selector
Diffstat (limited to 'Eigen/src/Core/Fuzzy.h')
-rw-r--r-- | Eigen/src/Core/Fuzzy.h | 73 |
1 files changed, 64 insertions, 9 deletions
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<typename Derived, typename OtherDerived, bool is_integer = NumTraits<typename Derived::Scalar>::IsInteger> +struct isApprox_selector +{ + static bool run(const Derived& x, const OtherDerived& y, typename Derived::RealScalar prec) + { + const typename internal::nested<Derived,2>::type nested(x); + const typename internal::nested<OtherDerived,2>::type otherNested(y); + return (nested - otherNested).cwiseAbs2().sum() <= prec * prec * std::min(nested.cwiseAbs2().sum(), otherNested.cwiseAbs2().sum()); + } +}; + +template<typename Derived, typename OtherDerived> +struct isApprox_selector<Derived, OtherDerived, true> +{ + static bool run(const Derived& x, const OtherDerived& y, typename Derived::RealScalar) + { + return x.matrix() == y.matrix(); + } +}; + +template<typename Derived, typename OtherDerived, bool is_integer = NumTraits<typename Derived::Scalar>::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<typename Derived, typename OtherDerived> +struct isMuchSmallerThan_object_selector<Derived, OtherDerived, true> +{ + static bool run(const Derived& x, const OtherDerived&, typename Derived::RealScalar) + { + return x.matrix() == Derived::Zero(x.rows(), x.cols()).matrix(); + } +}; + +template<typename Derived, bool is_integer = NumTraits<typename Derived::Scalar>::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<typename Derived> +struct isMuchSmallerThan_scalar_selector<Derived, true> +{ + 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<Derived>::isApprox( RealScalar prec ) const { - const typename internal::nested<Derived,2>::type nested(derived()); - const typename internal::nested<OtherDerived,2>::type otherNested(other.derived()); -// std::cerr << typeid(Derived).name() << " => " << typeid(typename internal::nested<Derived,2>::type).name() << "\n"; -// std::cerr << typeid(OtherDerived).name() << " => " << typeid(typename internal::nested<OtherDerived,2>::type).name() << "\n"; -// return false; - return (nested - otherNested).cwiseAbs2().sum() <= prec * prec * std::min(nested.cwiseAbs2().sum(), otherNested.cwiseAbs2().sum()); + return internal::isApprox_selector<Derived, OtherDerived>::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<Derived>::isMuchSmallerThan( RealScalar prec ) const { - return derived().cwiseAbs2().sum() <= prec * prec * other * other; + return internal::isMuchSmallerThan_scalar_selector<Derived>::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<Derived>::isMuchSmallerThan( RealScalar prec ) const { - return derived().cwiseAbs2().sum() <= prec * prec * other.derived().cwiseAbs2().sum(); + return internal::isMuchSmallerThan_object_selector<Derived, OtherDerived>::run(derived(), other.derived(), prec); } #endif // EIGEN_FUZZY_H |