Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/boost/multiprecision/cpp_bin_float.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2172,7 +2172,7 @@ class numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bi
{
return number_type(0);
}
static constexpr number_type denorm_min() { return number_type(0); }
static constexpr number_type denorm_min() { return get_min(); }
static constexpr bool is_iec559 = false;
static constexpr bool is_bounded = true;
static constexpr bool is_modulo = false;
Expand Down
2 changes: 1 addition & 1 deletion include/boost/multiprecision/cpp_dec_float.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3591,7 +3591,7 @@ class numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_de
static constexpr boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> infinity() { return boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::inf(); }
static constexpr boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> quiet_NaN() { return boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::nan(); }
static constexpr boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> signaling_NaN() { return boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::zero(); }
static constexpr boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> denorm_min() { return boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::zero(); }
static constexpr boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> denorm_min() { return (boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::min)(); }
};

template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
Expand Down
4 changes: 2 additions & 2 deletions include/boost/multiprecision/gmp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3595,7 +3595,7 @@ class numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_fl
static constexpr number_type infinity() { return number_type(); }
static constexpr number_type quiet_NaN() { return number_type(); }
static constexpr number_type signaling_NaN() { return number_type(); }
static constexpr number_type denorm_min() { return number_type(); }
static constexpr number_type denorm_min() { return (min)(); }
static constexpr bool is_iec559 = false;
static constexpr bool is_bounded = true;
static constexpr bool is_modulo = false;
Expand Down Expand Up @@ -3871,7 +3871,7 @@ class numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_ra
static number_type infinity() { return number_type(); }
static number_type quiet_NaN() { return number_type(); }
static number_type signaling_NaN() { return number_type(); }
static number_type denorm_min() { return number_type(); }
static number_type denorm_min() { return (min)(); }
static constexpr bool is_iec559 = false;
static constexpr bool is_bounded = false;
static constexpr bool is_modulo = false;
Expand Down
2 changes: 1 addition & 1 deletion include/boost/multiprecision/mpfi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2388,7 +2388,7 @@ class numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfi_f
{
return number_type(0);
}
static constexpr number_type denorm_min() { return number_type(0); }
static constexpr number_type denorm_min() { return (min)(); }
static constexpr bool is_iec559 = false;
static constexpr bool is_bounded = true;
static constexpr bool is_modulo = false;
Expand Down
4 changes: 2 additions & 2 deletions include/boost/multiprecision/mpfr.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3434,7 +3434,7 @@ class numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_f
{
return number_type(0);
}
static constexpr number_type denorm_min() { return number_type(0); }
static constexpr number_type denorm_min() { return (min)(); }
static constexpr bool is_iec559 = false;
static constexpr bool is_bounded = true;
static constexpr bool is_modulo = false;
Expand Down Expand Up @@ -3550,7 +3550,7 @@ class numeric_limits<boost::multiprecision::number<boost::multiprecision::mpfr_f
return value;
}
static number_type signaling_NaN() { return number_type(0); }
static number_type denorm_min() { return number_type(0); }
static number_type denorm_min() { return (min)(); }
static constexpr bool is_iec559 = false;
static constexpr bool is_bounded = true;
static constexpr bool is_modulo = false;
Expand Down
88 changes: 46 additions & 42 deletions test/test_cpp_bin_float.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,25 +50,29 @@ typedef number<cpp_bin_float<std::numeric_limits<good_type>::digits, digit_base_
void test_special_cases()
{
#if !defined(BOOST_CI_ASAN_BUILD) && !defined(BOOST_CI_USAN_BUID)
test_type max_val = (std::numeric_limits<test_type>::max)();
test_type min_val = (std::numeric_limits<test_type>::min)();
test_type eps = std::numeric_limits<test_type>::epsilon();
test_type inf_val = (std::numeric_limits<test_type>::infinity)();
test_type nan_val = (std::numeric_limits<test_type>::quiet_NaN)();
test_type half = 0.5;
test_type one_point_5 = 1.5;
test_type max_val = (std::numeric_limits<test_type>::max)();
test_type denorm_min_val = std::numeric_limits<test_type>::denorm_min();
test_type min_val = (std::numeric_limits<test_type>::min)();
test_type eps = std::numeric_limits<test_type>::epsilon();
test_type inf_val = (std::numeric_limits<test_type>::infinity)();
test_type nan_val = (std::numeric_limits<test_type>::quiet_NaN)();
test_type half = 0.5;
test_type one_point_5 = 1.5;

BOOST_CHECK((boost::math::isnormal)(max_val));
BOOST_CHECK((boost::math::isnormal)(-max_val));
BOOST_CHECK((boost::math::isnormal)(min_val));
BOOST_CHECK((boost::math::isnormal)(-min_val));
BOOST_CHECK((boost::math::isnormal)(denorm_min_val));
BOOST_CHECK((boost::math::isnormal)(-denorm_min_val));
BOOST_CHECK((boost::math::isinf)(inf_val));
BOOST_CHECK((boost::math::isinf)(-inf_val));
BOOST_CHECK((boost::math::isnan)(nan_val));
BOOST_CHECK((boost::math::isnan)(-nan_val));

if (std::numeric_limits<test_type>::has_denorm)
min_val = std::numeric_limits<test_type>::denorm_min();
if (!std::numeric_limits<test_type>::has_denorm) {
BOOST_CHECK_EQUAL(denorm_min_val, min_val);
} else {
BOOST_CHECK_LE(denorm_min_val, min_val);
}

// Adding epsilon will increment 1.0:
BOOST_CHECK(test_type(1) + eps != test_type(1));
Expand All @@ -89,24 +93,24 @@ void test_special_cases()
BOOST_CHECK_EQUAL(max_val * -2, -inf_val);
BOOST_CHECK_EQUAL(max_val / half, inf_val);
BOOST_CHECK_EQUAL(max_val / -half, -inf_val);
BOOST_CHECK_EQUAL(max_val / min_val, inf_val);
BOOST_CHECK_EQUAL(max_val / -min_val, -inf_val);
BOOST_CHECK_EQUAL(max_val / denorm_min_val, inf_val);
BOOST_CHECK_EQUAL(max_val / -denorm_min_val, -inf_val);
// Underflow:
BOOST_CHECK_EQUAL(min_val * 2 - one_point_5 * min_val, 0);
BOOST_CHECK_EQUAL(-min_val * 2 + one_point_5 * min_val, 0);
BOOST_CHECK_EQUAL(min_val / 2, 0);
BOOST_CHECK_EQUAL(min_val / max_val, 0);
BOOST_CHECK_EQUAL(min_val * half, 0);
BOOST_CHECK_EQUAL(min_val - min_val, 0);
BOOST_CHECK_EQUAL(denorm_min_val * 2 - one_point_5 * denorm_min_val, 0);
BOOST_CHECK_EQUAL(-denorm_min_val * 2 + one_point_5 * denorm_min_val, 0);
BOOST_CHECK_EQUAL(denorm_min_val / 2, 0);
BOOST_CHECK_EQUAL(denorm_min_val / max_val, 0);
BOOST_CHECK_EQUAL(denorm_min_val * half, 0);
BOOST_CHECK_EQUAL(denorm_min_val - denorm_min_val, 0);
BOOST_CHECK_EQUAL(max_val - max_val, 0);
BOOST_CHECK_EQUAL(-min_val + min_val, 0);
BOOST_CHECK_EQUAL(-denorm_min_val + denorm_min_val, 0);
BOOST_CHECK_EQUAL(-max_val + max_val, 0);
// Things which should not over/underflow:
BOOST_CHECK_EQUAL((min_val * 2) / 2, min_val);
BOOST_CHECK_EQUAL((denorm_min_val * 2) / 2, denorm_min_val);
BOOST_CHECK_EQUAL((max_val / 2) * 2, max_val);
BOOST_CHECK_GE((min_val * 2.0000001) / 1.9999999999999999, min_val);
BOOST_CHECK_GE((denorm_min_val * 2.0000001) / 1.9999999999999999, denorm_min_val);
BOOST_CHECK_LE((max_val / 2.0000001) * 1.9999999999999999, max_val);
BOOST_CHECK_EQUAL(min_val * 2 - min_val, min_val);
BOOST_CHECK_EQUAL(denorm_min_val * 2 - denorm_min_val, denorm_min_val);
BOOST_CHECK_EQUAL(max_val / 2 + max_val / 2, max_val);
// Things involving zero:
BOOST_CHECK_EQUAL(max_val + 0, max_val);
Expand Down Expand Up @@ -210,26 +214,26 @@ void test_special_cases()
// Corner cases:
BOOST_CHECK_EQUAL((max_val * half) / half, max_val);
BOOST_CHECK_EQUAL((max_val / 2) * 2, max_val);
BOOST_CHECK_EQUAL((min_val / half) * half, min_val);
BOOST_CHECK_EQUAL((min_val * 2) / 2, min_val);
BOOST_CHECK_EQUAL(max_val + min_val, max_val);
BOOST_CHECK_EQUAL(min_val + max_val, max_val);
BOOST_CHECK_EQUAL(max_val - min_val, max_val);
BOOST_CHECK_EQUAL(min_val - max_val, -max_val);
BOOST_CHECK_EQUAL((denorm_min_val / half) * half, denorm_min_val);
BOOST_CHECK_EQUAL((denorm_min_val * 2) / 2, denorm_min_val);
BOOST_CHECK_EQUAL(max_val + denorm_min_val, max_val);
BOOST_CHECK_EQUAL(denorm_min_val + max_val, max_val);
BOOST_CHECK_EQUAL(max_val - denorm_min_val, max_val);
BOOST_CHECK_EQUAL(denorm_min_val - max_val, -max_val);
// Signed zeros:
BOOST_CHECK(boost::math::signbit(min_val * -min_val));
BOOST_CHECK(boost::math::signbit(min_val * min_val) == 0);
BOOST_CHECK(boost::math::signbit(-min_val * -min_val) == 0);
BOOST_CHECK(boost::math::signbit(-min_val * min_val));
BOOST_CHECK(boost::math::signbit(min_val / max_val) == 0);
BOOST_CHECK(boost::math::signbit(min_val / -max_val));
BOOST_CHECK(boost::math::signbit(-min_val / -max_val) == 0);
BOOST_CHECK(boost::math::signbit(-min_val / max_val));
BOOST_CHECK(boost::math::signbit(min_val / 2) == 0);
BOOST_CHECK(boost::math::signbit(min_val / -2));
BOOST_CHECK(boost::math::signbit(-min_val / -2) == 0);
BOOST_CHECK(boost::math::signbit(-min_val / 2));
test_type neg_zero = min_val * -min_val;
BOOST_CHECK(boost::math::signbit(denorm_min_val * -denorm_min_val));
BOOST_CHECK(boost::math::signbit(denorm_min_val * denorm_min_val) == 0);
BOOST_CHECK(boost::math::signbit(-denorm_min_val * -denorm_min_val) == 0);
BOOST_CHECK(boost::math::signbit(-denorm_min_val * denorm_min_val));
BOOST_CHECK(boost::math::signbit(denorm_min_val / max_val) == 0);
BOOST_CHECK(boost::math::signbit(denorm_min_val / -max_val));
BOOST_CHECK(boost::math::signbit(-denorm_min_val / -max_val) == 0);
BOOST_CHECK(boost::math::signbit(-denorm_min_val / max_val));
BOOST_CHECK(boost::math::signbit(denorm_min_val / 2) == 0);
BOOST_CHECK(boost::math::signbit(denorm_min_val / -2));
BOOST_CHECK(boost::math::signbit(-denorm_min_val / -2) == 0);
BOOST_CHECK(boost::math::signbit(-denorm_min_val / 2));
test_type neg_zero = denorm_min_val * -denorm_min_val;
test_type zero = 0;
// Arithmetic involving signed zero:
BOOST_CHECK_EQUAL(-neg_zero, 0);
Expand Down
31 changes: 20 additions & 11 deletions test/test_numeric_limits.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,33 +83,33 @@ void test_specific(const std::integral_constant<int, boost::multiprecision::numb
BOOST_CHECK((boost::math::isnormal)(sqrt(minv)));
BOOST_CHECK((boost::math::isnormal)(sqrt(maxv)));

if (std::numeric_limits<Number>::is_specialized)
BOOST_IF_CONSTEXPR(std::numeric_limits<Number>::is_specialized)
{
if (std::numeric_limits<Number>::has_quiet_NaN)
BOOST_IF_CONSTEXPR(std::numeric_limits<Number>::has_quiet_NaN)
{
BOOST_TEST((boost::math::isnan)(std::numeric_limits<Number>::quiet_NaN()));
BOOST_TEST(FP_NAN == (boost::math::fpclassify)(std::numeric_limits<Number>::quiet_NaN()));
BOOST_TEST(!(boost::math::isfinite)(std::numeric_limits<Number>::quiet_NaN()));
BOOST_TEST(!(boost::math::isnormal)(std::numeric_limits<Number>::quiet_NaN()));
BOOST_TEST(!(boost::math::isinf)(std::numeric_limits<Number>::quiet_NaN()));
}
if (std::numeric_limits<Number>::has_signaling_NaN)
BOOST_IF_CONSTEXPR(std::numeric_limits<Number>::has_signaling_NaN)
{
BOOST_TEST((boost::math::isnan)(std::numeric_limits<Number>::signaling_NaN()));
BOOST_TEST(FP_NAN == (boost::math::fpclassify)(std::numeric_limits<Number>::signaling_NaN()));
BOOST_TEST(!(boost::math::isfinite)(std::numeric_limits<Number>::signaling_NaN()));
BOOST_TEST(!(boost::math::isnormal)(std::numeric_limits<Number>::signaling_NaN()));
BOOST_TEST(!(boost::math::isinf)(std::numeric_limits<Number>::signaling_NaN()));
}
if (std::numeric_limits<Number>::has_infinity)
BOOST_IF_CONSTEXPR(std::numeric_limits<Number>::has_infinity)
{
BOOST_TEST((boost::math::isinf)(std::numeric_limits<Number>::infinity()));
BOOST_TEST(FP_INFINITE == (boost::math::fpclassify)(std::numeric_limits<Number>::infinity()));
BOOST_TEST(!(boost::math::isfinite)(std::numeric_limits<Number>::infinity()));
BOOST_TEST(!(boost::math::isnormal)(std::numeric_limits<Number>::infinity()));
BOOST_TEST(!(boost::math::isnan)(std::numeric_limits<Number>::infinity()));
}
if (std::numeric_limits<Number>::has_denorm == std::denorm_present)
BOOST_IF_CONSTEXPR(std::numeric_limits<Number>::has_denorm == std::denorm_present)
{
BOOST_TEST(FP_SUBNORMAL == (boost::math::fpclassify)(std::numeric_limits<Number>::denorm_min()));
BOOST_TEST(FP_SUBNORMAL == (boost::math::fpclassify)((std::numeric_limits<Number>::min)() / 2));
Expand All @@ -121,6 +121,15 @@ void test_specific(const std::integral_constant<int, boost::multiprecision::numb
BOOST_TEST(0 != (std::numeric_limits<Number>::min)() / 2);
BOOST_TEST(0 != std::numeric_limits<Number>::denorm_min());
}
BOOST_IF_CONSTEXPR(std::numeric_limits<Number>::has_denorm == std::denorm_absent)
{
BOOST_TEST(std::numeric_limits<Number>::denorm_min() > 0);
BOOST_TEST(!(std::numeric_limits<Number>::denorm_min() > (std::numeric_limits<Number>::min)()));
BOOST_TEST(!(std::numeric_limits<Number>::denorm_min() < (std::numeric_limits<Number>::min)()));
BOOST_TEST(FP_NORMAL == (boost::math::fpclassify)(std::numeric_limits<Number>::denorm_min()));
BOOST_TEST(FP_NORMAL == (boost::math::fpclassify)(-std::numeric_limits<Number>::denorm_min()));
BOOST_TEST(FP_ZERO != (boost::math::fpclassify)(std::numeric_limits<Number>::denorm_min()));
}
}
Number n = 0;
BOOST_TEST((boost::math::fpclassify)(n) == FP_ZERO);
Expand All @@ -135,11 +144,11 @@ void test_specific(const std::integral_constant<int, boost::multiprecision::numb
BOOST_TEST(!(boost::math::isinf)(n));
BOOST_TEST(!(boost::math::isnan)(n));

if (std::numeric_limits<Number>::round_style == std::round_to_nearest)
BOOST_IF_CONSTEXPR(std::numeric_limits<Number>::round_style == std::round_to_nearest)
{
BOOST_CHECK_EQUAL(std::numeric_limits<Number>::round_error(), 0.5);
}
else if (std::numeric_limits<Number>::round_style != std::round_indeterminate)
else BOOST_IF_CONSTEXPR(std::numeric_limits<Number>::round_style != std::round_indeterminate)
{
// Round error is 1.0:
BOOST_CHECK_EQUAL(std::numeric_limits<Number>::round_error(), 1);
Expand All @@ -154,9 +163,9 @@ void test_specific(const std::integral_constant<int, boost::multiprecision::numb
template <class Number>
void test_specific(const std::integral_constant<int, boost::multiprecision::number_kind_integer>&)
{
if (std::numeric_limits<Number>::is_modulo)
BOOST_IF_CONSTEXPR(std::numeric_limits<Number>::is_modulo)
{
if (!std::numeric_limits<Number>::is_signed)
BOOST_IF_CONSTEXPR(!std::numeric_limits<Number>::is_signed)
{
BOOST_TEST(1 + (std::numeric_limits<Number>::max)() == 0);
BOOST_TEST(--Number(0) == (std::numeric_limits<Number>::max)());
Expand Down Expand Up @@ -186,13 +195,13 @@ void test()
std::cout << "numeric_limits values for type " << typeid(Number).name() << std::endl;

PRINT(is_specialized);
if (std::numeric_limits<Number>::is_integer)
BOOST_IF_CONSTEXPR(std::numeric_limits<Number>::is_integer)
{
std::cout << std::hex << std::showbase;
}
std::cout << "max()"
<< " = " << (std::numeric_limits<Number>::max)() << std::endl;
if (std::numeric_limits<Number>::is_integer)
BOOST_IF_CONSTEXPR(std::numeric_limits<Number>::is_integer)
{
std::cout << std::dec;
}
Expand Down