From 48e179266b514aebfa0a2e8e9508ce5cd8604bda Mon Sep 17 00:00:00 2001 From: John Maddock Date: Wed, 12 Oct 2011 11:06:09 +0000 Subject: [PATCH] Fix error checking for trunc and round functions. Update tests to match. [SVN r74925] --- .../boost/math/special_functions/round.hpp | 6 +- .../boost/math/special_functions/trunc.hpp | 6 +- test/test_round.cpp | 68 ++++++++++++++++++- 3 files changed, 73 insertions(+), 7 deletions(-) diff --git a/include/boost/math/special_functions/round.hpp b/include/boost/math/special_functions/round.hpp index 4ea2eaa08..f11c6aeb1 100644 --- a/include/boost/math/special_functions/round.hpp +++ b/include/boost/math/special_functions/round.hpp @@ -43,7 +43,7 @@ inline int iround(const T& v, const Policy& pol) { BOOST_MATH_STD_USING T r = boost::math::round(v, pol); - if(fabs(r) > (std::numeric_limits::max)()) + if((r > (std::numeric_limits::max)()) || (r < (std::numeric_limits::min)())) return static_cast(policies::raise_rounding_error("boost::math::iround<%1%>(%1%)", 0, v, 0, pol)); return static_cast(r); } @@ -58,7 +58,7 @@ inline long lround(const T& v, const Policy& pol) { BOOST_MATH_STD_USING T r = boost::math::round(v, pol); - if(fabs(r) > (std::numeric_limits::max)()) + if((r > (std::numeric_limits::max)()) || (r < (std::numeric_limits::min)())) return static_cast(policies::raise_rounding_error("boost::math::lround<%1%>(%1%)", 0, v, 0L, pol)); return static_cast(r); } @@ -75,7 +75,7 @@ inline boost::long_long_type llround(const T& v, const Policy& pol) { BOOST_MATH_STD_USING T r = boost::math::round(v, pol); - if(fabs(r) > (std::numeric_limits::max)()) + if((r > (std::numeric_limits::max)()) || (r < (std::numeric_limits::min)())) return static_cast(policies::raise_rounding_error("boost::math::llround<%1%>(%1%)", 0, v, 0LL, pol)); return static_cast(r); } diff --git a/include/boost/math/special_functions/trunc.hpp b/include/boost/math/special_functions/trunc.hpp index f1702aea1..520ae89f5 100644 --- a/include/boost/math/special_functions/trunc.hpp +++ b/include/boost/math/special_functions/trunc.hpp @@ -43,7 +43,7 @@ inline int itrunc(const T& v, const Policy& pol) { BOOST_MATH_STD_USING T r = boost::math::trunc(v, pol); - if(fabs(r) > (std::numeric_limits::max)()) + if((r > (std::numeric_limits::max)()) || (r < (std::numeric_limits::min)())) return static_cast(policies::raise_rounding_error("boost::math::itrunc<%1%>(%1%)", 0, v, 0, pol)); return static_cast(r); } @@ -58,7 +58,7 @@ inline long ltrunc(const T& v, const Policy& pol) { BOOST_MATH_STD_USING T r = boost::math::trunc(v, pol); - if(fabs(r) > (std::numeric_limits::max)()) + if((r > (std::numeric_limits::max)()) || (r < (std::numeric_limits::min)())) return static_cast(policies::raise_rounding_error("boost::math::ltrunc<%1%>(%1%)", 0, v, 0L, pol)); return static_cast(r); } @@ -75,7 +75,7 @@ inline boost::long_long_type lltrunc(const T& v, const Policy& pol) { BOOST_MATH_STD_USING T r = boost::math::trunc(v, pol); - if(fabs(r) > (std::numeric_limits::max)()) + if((r > (std::numeric_limits::max)()) || (r < (std::numeric_limits::min)())) return static_cast(policies::raise_rounding_error("boost::math::lltrunc<%1%>(%1%)", 0, v, 0LL, pol)); return static_cast(r); } diff --git a/test/test_round.cpp b/test/test_round.cpp index 6f16b3d1e..31ca653a1 100644 --- a/test/test_round.cpp +++ b/test/test_round.cpp @@ -145,7 +145,17 @@ void test_round(T, const char* name ) r = boost::math::modf(arg, &i); check_modf_result(arg, r, i); } - + if(std::numeric_limits::digits >= std::numeric_limits::digits) + { + int si = boost::math::iround(static_cast((std::numeric_limits::max)())); + check_within_half(static_cast((std::numeric_limits::max)()), si); + si = boost::math::iround(static_cast((std::numeric_limits::min)())); + check_within_half(static_cast((std::numeric_limits::min)()), si); + si = boost::math::itrunc(static_cast((std::numeric_limits::max)())); + check_trunc_result(static_cast((std::numeric_limits::max)()), si); + si = boost::math::itrunc(static_cast((std::numeric_limits::min)())); + check_trunc_result(static_cast((std::numeric_limits::min)()), si); + } if(abs(r) < (std::numeric_limits::max)()) { long l = boost::math::lround(arg); @@ -155,6 +165,17 @@ void test_round(T, const char* name ) r = boost::math::modf(arg, &l); check_modf_result(arg, r, l); } + if(std::numeric_limits::digits >= std::numeric_limits::digits) + { + long k = boost::math::lround(static_cast((std::numeric_limits::max)())); + check_within_half(static_cast((std::numeric_limits::max)()), k); + k = boost::math::lround(static_cast((std::numeric_limits::min)())); + check_within_half(static_cast((std::numeric_limits::min)()), k); + k = boost::math::ltrunc(static_cast((std::numeric_limits::max)())); + check_trunc_result(static_cast((std::numeric_limits::max)()), k); + k = boost::math::ltrunc(static_cast((std::numeric_limits::min)())); + check_trunc_result(static_cast((std::numeric_limits::min)()), k); + } #ifdef BOOST_HAS_LONG_LONG if(abs(r) < (std::numeric_limits::max)()) @@ -166,6 +187,17 @@ void test_round(T, const char* name ) r = boost::math::modf(arg, &ll); check_modf_result(arg, r, ll); } + if(std::numeric_limits::digits >= std::numeric_limits::digits) + { + boost::long_long_type j = boost::math::llround(static_cast((std::numeric_limits::max)())); + check_within_half(static_cast((std::numeric_limits::max)()), j); + j = boost::math::llround(static_cast((std::numeric_limits::min)())); + check_within_half(static_cast((std::numeric_limits::min)()), j); + j = boost::math::lltrunc(static_cast((std::numeric_limits::max)())); + check_trunc_result(static_cast((std::numeric_limits::max)()), j); + j = boost::math::lltrunc(static_cast((std::numeric_limits::min)())); + check_trunc_result(static_cast((std::numeric_limits::min)()), j); + } #endif } // @@ -229,6 +261,40 @@ void test_round(T, const char* name ) BOOST_CHECK_THROW(boost::math::lltrunc(std::numeric_limits::quiet_NaN()), boost::math::rounding_error); #endif } + if(std::numeric_limits::digits >= std::numeric_limits::digits) + { + BOOST_CHECK_THROW(boost::math::itrunc(static_cast((std::numeric_limits::max)()) + 1), boost::math::rounding_error); + BOOST_CHECK_THROW(boost::math::itrunc(static_cast((std::numeric_limits::min)()) - 1), boost::math::rounding_error); + } + if(std::numeric_limits::digits >= std::numeric_limits::digits) + { + BOOST_CHECK_THROW(boost::math::ltrunc(static_cast((std::numeric_limits::max)()) + 1), boost::math::rounding_error); + BOOST_CHECK_THROW(boost::math::ltrunc(static_cast((std::numeric_limits::min)()) - 1), boost::math::rounding_error); + } +#ifndef BOOST_NO_LONG_LONG + if(std::numeric_limits::digits >= std::numeric_limits::digits) + { + BOOST_CHECK_THROW(boost::math::lltrunc(static_cast((std::numeric_limits::max)()) + 1), boost::math::rounding_error); + BOOST_CHECK_THROW(boost::math::lltrunc(static_cast((std::numeric_limits::min)()) - 1), boost::math::rounding_error); + } +#endif + if(std::numeric_limits::digits >= std::numeric_limits::digits) + { + BOOST_CHECK_THROW(boost::math::iround(static_cast((std::numeric_limits::max)()) + 1), boost::math::rounding_error); + BOOST_CHECK_THROW(boost::math::iround(static_cast((std::numeric_limits::min)()) - 1), boost::math::rounding_error); + } + if(std::numeric_limits::digits >= std::numeric_limits::digits) + { + BOOST_CHECK_THROW(boost::math::lround(static_cast((std::numeric_limits::max)()) + 1), boost::math::rounding_error); + BOOST_CHECK_THROW(boost::math::lround(static_cast((std::numeric_limits::min)()) - 1), boost::math::rounding_error); + } +#ifndef BOOST_NO_LONG_LONG + if(std::numeric_limits::digits >= std::numeric_limits::digits) + { + BOOST_CHECK_THROW(boost::math::llround(static_cast((std::numeric_limits::max)()) + 1), boost::math::rounding_error); + BOOST_CHECK_THROW(boost::math::llround(static_cast((std::numeric_limits::min)()) - 1), boost::math::rounding_error); + } +#endif } int test_main(int, char* [])