mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-04-19 16:19:37 +08:00
Fix numext::round pre c++11 for large inputs.
This is to resolve an issue for large inputs when +0.5 can actually lead to +1 if the input doesn't have enough precision to resolve the addition - leading to an off-by-one error. See discussion on 9a663973.
This commit is contained in:
parent
c9d4367fa4
commit
14b7ebea11
@ -476,18 +476,6 @@ inline NewType cast(const OldType& x)
|
||||
* Implementation of round *
|
||||
****************************************************************************/
|
||||
|
||||
#if EIGEN_HAS_CXX11_MATH
|
||||
template<typename Scalar>
|
||||
struct round_impl {
|
||||
EIGEN_DEVICE_FUNC
|
||||
static inline Scalar run(const Scalar& x)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT((!NumTraits<Scalar>::IsComplex), NUMERIC_TYPE_MUST_BE_REAL)
|
||||
EIGEN_USING_STD(round);
|
||||
return Scalar(round(x));
|
||||
}
|
||||
};
|
||||
#else
|
||||
template<typename Scalar>
|
||||
struct round_impl
|
||||
{
|
||||
@ -495,12 +483,28 @@ inline NewType cast(const OldType& x)
|
||||
static inline Scalar run(const Scalar& x)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT((!NumTraits<Scalar>::IsComplex), NUMERIC_TYPE_MUST_BE_REAL)
|
||||
#if EIGEN_HAS_CXX11_MATH
|
||||
EIGEN_USING_STD(round);
|
||||
return Scalar(round(x));
|
||||
#elif EIGEN_HAS_C99_MATH
|
||||
if (is_same<Scalar, float>::value) {
|
||||
return Scalar(::roundf(x));
|
||||
} else {
|
||||
return Scalar(round(x));
|
||||
}
|
||||
#else
|
||||
EIGEN_USING_STD(floor);
|
||||
EIGEN_USING_STD(ceil);
|
||||
return (x > Scalar(0)) ? floor(x + Scalar(0.5)) : ceil(x - Scalar(0.5));
|
||||
// If not enough precision to resolve a decimal at all, return the input.
|
||||
// Otherwise, adding 0.5 can trigger an increment by 1.
|
||||
const Scalar limit = Scalar(1ull << (NumTraits<Scalar>::digits() - 1));
|
||||
if (x >= limit || x <= -limit) {
|
||||
return x;
|
||||
}
|
||||
return (x > Scalar(0)) ? Scalar(floor(x + Scalar(0.5))) : Scalar(ceil(x - Scalar(0.5)));
|
||||
#endif
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
template<typename Scalar>
|
||||
struct round_retval
|
||||
|
Loading…
x
Reference in New Issue
Block a user