2
0
mirror of https://github.com/boostorg/math.git synced 2026-01-19 04:22:09 +00:00

Add coverage for lround and iround

This commit is contained in:
Matt Borland
2023-04-03 14:06:29 +02:00
parent 8dfc73533d
commit 1de39c69ef
2 changed files with 95 additions and 22 deletions

View File

@@ -101,8 +101,15 @@ inline int iround(const T& v, const Policy& pol)
BOOST_MATH_STD_USING
using result_type = tools::promote_args_t<T>;
T r = boost::math::round(v, pol);
if(r > static_cast<result_type>((std::numeric_limits<int>::max)()) || r < static_cast<result_type>((std::numeric_limits<int>::min)()))
result_type r = boost::math::round(v, pol);
#ifdef BOOST_MATH_HAS_CONSTEXPR_LDEXP
constexpr result_type max_val = boost::math::ccmath::ldexp(static_cast<result_type>(1), std::numeric_limits<int>::digits);
#else
static const result_type max_val = std::ldexp(static_cast<result_type>(1), std::numeric_limits<int>::digits);
#endif
if(r >= max_val || r < -max_val)
{
return static_cast<int>(policies::raise_rounding_error("boost::math::iround<%1%>(%1%)", nullptr, v, 0, pol));
}
@@ -119,12 +126,20 @@ inline long lround(const T& v, const Policy& pol)
{
BOOST_MATH_STD_USING
using result_type = tools::promote_args_t<T>;
T r = boost::math::round(v, pol);
if(r > static_cast<result_type>((std::numeric_limits<long>::max)()) || r < static_cast<result_type>((std::numeric_limits<long>::min)()))
result_type r = boost::math::round(v, pol);
#ifdef BOOST_MATH_HAS_CONSTEXPR_LDEXP
constexpr result_type max_val = boost::math::ccmath::ldexp(static_cast<result_type>(1), std::numeric_limits<long>::digits);
#else
static const result_type max_val = std::ldexp(static_cast<result_type>(1), std::numeric_limits<long>::digits);
#endif
if(r >= max_val || r < -max_val)
{
return static_cast<long int>(policies::raise_rounding_error("boost::math::lround<%1%>(%1%)", nullptr, v, 0L, pol));
return static_cast<long>(policies::raise_rounding_error("boost::math::lround<%1%>(%1%)", nullptr, v, 0L, pol));
}
return static_cast<long int>(r);
return static_cast<long>(r);
}
template <class T>
inline long lround(const T& v)

View File

@@ -22,26 +22,84 @@ void test_llround_near_boundary()
Real value;
int i;
for (value = boundary, i = 0; i < 100; value = boost::math::float_next(value), ++i)
{
BOOST_CHECK_THROW(boost::math::llround(value), boost::math::rounding_error);
}
for (value = boost::math::float_prior(boundary), i = 0; i < 1000; value = boost::math::float_prior(value), ++i)
{
BOOST_CHECK_EQUAL(static_cast<Real>(boost::math::llround(value)), boost::math::round(value));
}
for (value = boost::math::float_prior(-boundary), i = 0; i < 100; value = boost::math::float_prior(value), ++i)
{
BOOST_CHECK_THROW(boost::math::llround(value), boost::math::rounding_error);
}
for (value = -boundary, i = 0; i < 1000; value = boost::math::float_next(value), ++i)
{
BOOST_CHECK_EQUAL(static_cast<Real>(boost::math::llround(value)), boost::math::round(value));
}
for (value = boundary, i = 0; i < 100; value = boost::math::float_next(value), ++i)
{
BOOST_CHECK_THROW(boost::math::llround(value), boost::math::rounding_error);
}
for (value = boost::math::float_prior(boundary), i = 0; i < 1000; value = boost::math::float_prior(value), ++i)
{
BOOST_CHECK_EQUAL(static_cast<Real>(boost::math::llround(value)), boost::math::round(value));
}
for (value = boost::math::float_prior(-boundary), i = 0; i < 100; value = boost::math::float_prior(value), ++i)
{
BOOST_CHECK_THROW(boost::math::llround(value), boost::math::rounding_error);
}
for (value = -boundary, i = 0; i < 1000; value = boost::math::float_next(value), ++i)
{
BOOST_CHECK_EQUAL(static_cast<Real>(boost::math::llround(value)), boost::math::round(value));
}
}
template <typename Real>
void test_lround_near_boundary()
{
using std::ldexp;
Real boundary = ldexp(static_cast<Real>(1), std::numeric_limits<long>::digits);
Real value;
int i;
for (value = boundary, i = 0; i < 100; value = boost::math::float_next(value), ++i)
{
BOOST_CHECK_THROW(boost::math::lround(value), boost::math::rounding_error);
}
for (value = boost::math::float_prior(boundary), i = 0; i < 1000; value = boost::math::float_prior(value), ++i)
{
BOOST_CHECK_EQUAL(static_cast<Real>(boost::math::lround(value)), boost::math::round(value));
}
for (value = boost::math::float_prior(-boundary), i = 0; i < 100; value = boost::math::float_prior(value), ++i)
{
BOOST_CHECK_THROW(boost::math::lround(value), boost::math::rounding_error);
}
for (value = -boundary, i = 0; i < 1000; value = boost::math::float_next(value), ++i)
{
BOOST_CHECK_EQUAL(static_cast<Real>(boost::math::lround(value)), boost::math::round(value));
}
}
template <typename Real>
void test_iround_near_boundary()
{
using std::ldexp;
Real boundary = ldexp(static_cast<Real>(1), std::numeric_limits<int>::digits);
Real value;
int i;
for (value = boundary, i = 0; i < 100; value = boost::math::float_next(value), ++i)
{
BOOST_CHECK_THROW(boost::math::iround(value), boost::math::rounding_error);
}
for (value = boost::math::float_prior(boundary), i = 0; i < 1000; value = boost::math::float_prior(value), ++i)
{
BOOST_CHECK_EQUAL(static_cast<Real>(boost::math::iround(value)), boost::math::round(value));
}
for (value = boost::math::float_prior(-boundary), i = 0; i < 100; value = boost::math::float_prior(value), ++i)
{
BOOST_CHECK_THROW(boost::math::iround(value), boost::math::rounding_error);
}
for (value = -boundary, i = 0; i < 1000; value = boost::math::float_next(value), ++i)
{
BOOST_CHECK_EQUAL(static_cast<Real>(boost::math::iround(value)), boost::math::round(value));
}
}
BOOST_AUTO_TEST_CASE( test_main )
{
test_llround_near_boundary<float>();
test_llround_near_boundary<double>();
test_lround_near_boundary<float>();
test_iround_near_boundary<float>();
}