mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-02-11 18:00:51 +08:00
fix fuzzy compares for integer types, using a selector
This commit is contained in:
parent
c5c8efa575
commit
68a2e04a96
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user