aboutsummaryrefslogtreecommitdiffhomepage
path: root/Eigen/src/Core/Fuzzy.h
diff options
context:
space:
mode:
authorGravatar Benoit Jacob <jacob.benoit.1@gmail.com>2011-02-07 10:53:17 -0500
committerGravatar Benoit Jacob <jacob.benoit.1@gmail.com>2011-02-07 10:53:17 -0500
commit68a2e04a96401db3339b47a18d1229e707aebdd9 (patch)
tree48bdbbc6bea88d525a77800a83af30b0807048c7 /Eigen/src/Core/Fuzzy.h
parentc5c8efa575038fc2e428c17c60050f7abfbb7a1b (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.h73
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