mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-07-15 17:41:48 +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 *
|
* 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>
|
template<typename Scalar>
|
||||||
struct round_impl
|
struct round_impl
|
||||||
{
|
{
|
||||||
@ -495,12 +483,28 @@ inline NewType cast(const OldType& x)
|
|||||||
static inline Scalar run(const Scalar& x)
|
static inline Scalar run(const Scalar& x)
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT((!NumTraits<Scalar>::IsComplex), NUMERIC_TYPE_MUST_BE_REAL)
|
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(floor);
|
||||||
EIGEN_USING_STD(ceil);
|
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>
|
template<typename Scalar>
|
||||||
struct round_retval
|
struct round_retval
|
||||||
|
Loading…
x
Reference in New Issue
Block a user