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

Coverage: Improve next.hpp.

This commit is contained in:
jzmaddock
2025-05-06 17:16:32 +01:00
parent aa1f9979d0
commit 1ec15ddad5
4 changed files with 45 additions and 31 deletions

View File

@@ -469,13 +469,9 @@ T float_distance_imp(const T& a, const T& b, const std::true_type&, const Policy
//
static const char* function = "float_distance<%1%>(%1%, %1%)";
if(!(boost::math::isfinite)(a))
return policies::raise_domain_error<T>(
function,
"Argument a must be finite, but got %1%", a, pol);
return policies::raise_domain_error<T>(function, "Argument a must be finite, but got %1%", a, pol);
if(!(boost::math::isfinite)(b))
return policies::raise_domain_error<T>(
function,
"Argument b must be finite, but got %1%", b, pol);
return policies::raise_domain_error<T>(function, "Argument b must be finite, but got %1%", b, pol);
//
// Special cases:
//
@@ -577,13 +573,9 @@ T float_distance_imp(const T& a, const T& b, const std::false_type&, const Polic
//
static const char* function = "float_distance<%1%>(%1%, %1%)";
if(!(boost::math::isfinite)(a))
return policies::raise_domain_error<T>(
function,
"Argument a must be finite, but got %1%", a, pol);
return policies::raise_domain_error<T>(function, "Argument a must be finite, but got %1%", a, pol);
if(!(boost::math::isfinite)(b))
return policies::raise_domain_error<T>(
function,
"Argument b must be finite, but got %1%", b, pol);
return policies::raise_domain_error<T>(function, "Argument b must be finite, but got %1%", b, pol);
//
// Special cases:
//
@@ -726,9 +718,7 @@ T float_advance_imp(T val, int distance, const std::true_type&, const Policy& po
int fpclass = (boost::math::fpclassify)(val);
if((fpclass == (int)FP_NAN) || (fpclass == (int)FP_INFINITE))
return policies::raise_domain_error<T>(
function,
"Argument val must be finite, but got %1%", val, pol);
return policies::raise_domain_error<T>(function, "Argument val must be finite, but got %1%", val, pol);
if(val < 0)
return -float_advance(-val, -distance, pol);
@@ -760,10 +750,8 @@ T float_advance_imp(T val, int distance, const std::true_type&, const Policy& po
int expon;
(void)frexp(val, &expon);
T limit = ldexp((distance < 0 ? T(0.5f) : T(1)), expon);
if(val <= tools::min_value<T>())
{
limit = sign(T(distance)) * tools::min_value<T>();
}
// We can not have denorms here, since we have taken care of them above:
BOOST_MATH_ASSERT(val > tools::min_value<T>());
T limit_distance = float_distance(val, limit);
while(fabs(limit_distance) < abs(distance))
{
@@ -782,7 +770,7 @@ T float_advance_imp(T val, int distance, const std::true_type&, const Policy& po
limit_distance = float_distance(val, limit);
if(distance && (limit_distance == 0))
{
return policies::raise_evaluation_error<T>(function, "Internal logic failed while trying to increment floating point value %1%: most likely your FPU is in non-IEEE conforming mode.", val, pol);
return policies::raise_evaluation_error<T>(function, "Internal logic failed while trying to increment floating point value %1%: most likely your FPU is in non-IEEE conforming mode.", val, pol); // LCOV_EXCL_LINE This *should* be unreachable.
}
}
if((0.5f == frexp(val, &expon)) && (distance < 0))
@@ -791,7 +779,7 @@ T float_advance_imp(T val, int distance, const std::true_type&, const Policy& po
if(val != 0)
diff = distance * ldexp(T(1), expon - tools::digits<T>());
if(diff == 0)
diff = distance * detail::get_smallest_value<T>();
diff = distance * detail::get_smallest_value<T>(); // LCOV_EXCL_LINE This *should* be unreachable given that denorms are handled above already.
return val += diff;
} // float_advance_imp
//
@@ -812,9 +800,7 @@ T float_advance_imp(T val, int distance, const std::false_type&, const Policy& p
int fpclass = (boost::math::fpclassify)(val);
if((fpclass == (int)FP_NAN) || (fpclass == (int)FP_INFINITE))
return policies::raise_domain_error<T>(
function,
"Argument val must be finite, but got %1%", val, pol);
return policies::raise_domain_error<T>(function, "Argument val must be finite, but got %1%", val, pol);
if(val < 0)
return -float_advance(-val, -distance, pol);
@@ -845,10 +831,7 @@ T float_advance_imp(T val, int distance, const std::false_type&, const Policy& p
std::intmax_t expon = 1 + ilogb(val);
T limit = scalbn(T(1), distance < 0 ? expon - 1 : expon);
if(val <= tools::min_value<T>())
{
limit = sign(T(distance)) * tools::min_value<T>();
}
BOOST_MATH_ASSERT(val > tools::min_value<T>()); // denorms already handled.
T limit_distance = float_distance(val, limit);
while(fabs(limit_distance) < abs(distance))
{
@@ -867,7 +850,7 @@ T float_advance_imp(T val, int distance, const std::false_type&, const Policy& p
limit_distance = float_distance(val, limit);
if(distance && (limit_distance == 0))
{
return policies::raise_evaluation_error<T>(function, "Internal logic failed while trying to increment floating point value %1%: most likely your FPU is in non-IEEE conforming mode.", val, pol);
return policies::raise_evaluation_error<T>(function, "Internal logic failed while trying to increment floating point value %1%: most likely your FPU is in non-IEEE conforming mode.", val, pol); // LCOV_EXCL_LINE should never get here!
}
}
/*expon = 1 + ilogb(val);
@@ -877,7 +860,7 @@ T float_advance_imp(T val, int distance, const std::false_type&, const Policy& p
if(val != 0)
diff = distance * scalbn(T(1), expon - std::numeric_limits<T>::digits);
if(diff == 0)
diff = distance * detail::get_smallest_value<T>();
diff = distance * detail::get_smallest_value<T>(); // LCOV_EXCL_LINE This *should* be unreachable given that denorms are handled above.
return val += diff;
} // float_advance_imp

View File

@@ -569,7 +569,7 @@ test-suite special_fun :
[ run test_ldouble_simple.cpp /boost/test//boost_unit_test_framework ]
# Needs to run in release mode, as it's rather slow:
[ run test_next.cpp pch /boost/test//boost_unit_test_framework : : : release ]
[ run test_next.cpp pch /boost/test//boost_unit_test_framework : : : [ check-target-builds ../config//is_ci_sanitizer_run "Sanitizer CI run" : debug : release ] ]
[ run test_next_decimal.cpp pch /boost/test//boost_unit_test_framework : : : release ]
[ run test_owens_t.cpp /boost/test//boost_unit_test_framework ]
[ run test_polygamma.cpp test_instances//test_instances pch_light /boost/test//boost_unit_test_framework ]

View File

@@ -61,6 +61,18 @@ void test_value(const T& val, const char* name)
BOOST_CHECK_EQUAL(float_distance(float_advance(float_next(float_next(val)), 4), float_next(float_next(val))), -4);
BOOST_CHECK_EQUAL(float_distance(float_advance(float_next(float_next(val)), -4), float_next(float_next(val))), 4);
}
#ifndef BOOST_MATH_NO_EXCEPTIONS
BOOST_MATH_IF_CONSTEXPR(std::numeric_limits<T>::has_quiet_NaN)
{
BOOST_CHECK_THROW(float_distance(val, std::numeric_limits<T>::quiet_NaN()), std::domain_error);
BOOST_CHECK_THROW(float_distance(std::numeric_limits<T>::quiet_NaN(), val), std::domain_error);
}
BOOST_MATH_IF_CONSTEXPR(std::numeric_limits<T>::has_infinity)
{
BOOST_CHECK_THROW(float_distance(val, std::numeric_limits<T>::infinity()), std::domain_error);
BOOST_CHECK_THROW(float_distance(-std::numeric_limits<T>::infinity(), val), std::domain_error);
}
#endif
if(val > 0)
{
T n = val + ulp(val);

View File

@@ -54,6 +54,22 @@ void test_value(const T& val, const char* name)
BOOST_CHECK_EQUAL(float_distance(float_prior(float_prior(val)), float_next(float_next(val))), 4);
BOOST_CHECK_EQUAL(float_distance(float_prior(float_next(val)), val), 0);
BOOST_CHECK_EQUAL(float_distance(float_next(float_prior(val)), val), 0);
BOOST_CHECK_EQUAL(float_advance(val, 1), float_next(val));
BOOST_CHECK_EQUAL(float_advance(val, -1), float_prior(val));
#ifndef BOOST_MATH_NO_EXCEPTIONS
BOOST_MATH_IF_CONSTEXPR(std::numeric_limits<T>::has_quiet_NaN)
{
BOOST_CHECK_THROW(float_distance(val, std::numeric_limits<T>::quiet_NaN()), std::domain_error);
BOOST_CHECK_THROW(float_distance(std::numeric_limits<T>::quiet_NaN(), val), std::domain_error);
}
BOOST_MATH_IF_CONSTEXPR(std::numeric_limits<T>::has_infinity)
{
BOOST_CHECK_THROW(float_distance(val, std::numeric_limits<T>::infinity()), std::domain_error);
BOOST_CHECK_THROW(float_distance(-std::numeric_limits<T>::infinity(), val), std::domain_error);
}
#endif
if (is_normalized_value(val))
{
BOOST_CHECK_EQUAL(float_prior(float_next(val)), val);
@@ -197,6 +213,9 @@ void test_values(const T& val, const char* name)
{
BOOST_MATH_CHECK_THROW(boost::math::float_prior(std::numeric_limits<T>::quiet_NaN()), std::domain_error);
BOOST_MATH_CHECK_THROW(boost::math::float_next(std::numeric_limits<T>::quiet_NaN()), std::domain_error);
BOOST_MATH_CHECK_THROW(boost::math::float_advance(std::numeric_limits<T>::quiet_NaN(), 3), std::domain_error);
BOOST_MATH_CHECK_THROW(boost::math::float_advance(std::numeric_limits<T>::infinity(), 3), std::domain_error);
BOOST_MATH_CHECK_THROW(boost::math::float_advance(-std::numeric_limits<T>::infinity(), 3), std::domain_error);
}
}