// (C) Copyright John Maddock 2015. // Use, modification and distribution are subject to the // Boost Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include #define BOOST_TEST_MAIN #include #include #include #include #include #include #include template void test_value(const T& val, const char* name) { using namespace boost::math; using std::fabs; T next = float_next(val); T prev = float_prior(val); if((boost::math::isinf)(next)) { BOOST_CHECK_EQUAL(relative_difference(val, next), tools::max_value()); return; } if((boost::math::isinf)(prev)) { BOOST_CHECK_EQUAL(relative_difference(val, prev), tools::max_value()); return; } BOOST_CHECK_EQUAL(relative_difference(val, next), relative_difference(next, val)); BOOST_CHECK_EQUAL(epsilon_difference(val, next), epsilon_difference(next, val)); BOOST_CHECK_LE(relative_difference(val, next), boost::math::tools::epsilon()); BOOST_CHECK_LE(epsilon_difference(val, next), T(1)); if((fabs(val) > tools::min_value()) || (fabs(next) > tools::min_value())) { BOOST_CHECK_GT(relative_difference(val, next), T(0)); BOOST_CHECK_GT(epsilon_difference(val, next), T(0)); } else { BOOST_CHECK_EQUAL(relative_difference(val, next), T(0)); BOOST_CHECK_EQUAL(epsilon_difference(val, next), T(0)); } BOOST_CHECK_EQUAL(relative_difference(val, prev), relative_difference(prev, val)); BOOST_CHECK_EQUAL(epsilon_difference(val, prev), epsilon_difference(prev, val)); if((fabs(val) > tools::min_value()) || (fabs(prev) > tools::min_value())) { BOOST_CHECK_GT(relative_difference(val, prev), T(0)); BOOST_CHECK_GT(epsilon_difference(val, prev), T(0)); } else { BOOST_CHECK_EQUAL(relative_difference(val, prev), T(0)); BOOST_CHECK_EQUAL(epsilon_difference(val, prev), T(0)); } } template void test_values(const T& val, const char* name) { static const T a = static_cast(1.3456724e22); static const T b = static_cast(1.3456724e-22); static const T z = 0; static const T one = 1; static const T two = 2; std::cout << "Testing type " << name << std::endl; T den = (std::numeric_limits::min)() / 4; if(den != 0) { std::cout << "Denormals are active\n"; } else { std::cout << "Denormals are flushed to zero.\n"; } test_value(a, name); test_value(-a, name); test_value(b, name); test_value(-b, name); test_value(boost::math::tools::epsilon(), name); test_value(-boost::math::tools::epsilon(), name); test_value(boost::math::tools::min_value(), name); test_value(-boost::math::tools::min_value(), name); if (std::numeric_limits::is_specialized && (std::numeric_limits::has_denorm == std::denorm_present) && ((std::numeric_limits::min)() / 2 != 0)) { test_value(z, name); test_value(-z, name); } test_value(one, name); test_value(-one, name); test_value(two, name); test_value(-two, name); static const int primes[] = { 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, }; for(unsigned i = 0; i < sizeof(primes) / sizeof(primes[0]); ++i) { for(unsigned j = 0; j < sizeof(primes) / sizeof(primes[0]); ++j) { test_value(T(primes[i]) / T(primes[j]), name); test_value(-T(primes[i]) / T(primes[j]), name); } } using namespace boost::math; BOOST_CHECK_EQUAL(relative_difference(tools::min_value(), -tools::min_value()), tools::max_value()); BOOST_CHECK_EQUAL(epsilon_difference(tools::min_value(), -tools::min_value()), tools::max_value()); if(std::numeric_limits::has_infinity) { BOOST_CHECK_EQUAL(relative_difference(std::numeric_limits::infinity(), std::numeric_limits::infinity()), T(0)); BOOST_CHECK_EQUAL(epsilon_difference(std::numeric_limits::infinity(), std::numeric_limits::infinity()), T(0)); BOOST_CHECK_EQUAL(relative_difference(std::numeric_limits::infinity(), tools::max_value()), tools::max_value()); BOOST_CHECK_EQUAL(epsilon_difference(std::numeric_limits::infinity(), tools::max_value()), tools::max_value()); BOOST_CHECK_EQUAL(relative_difference(std::numeric_limits::infinity(), tools::max_value() / 2), tools::max_value()); BOOST_CHECK_EQUAL(epsilon_difference(std::numeric_limits::infinity(), tools::max_value() / 2), tools::max_value()); BOOST_CHECK_EQUAL(relative_difference(tools::max_value(), std::numeric_limits::infinity()), tools::max_value()); BOOST_CHECK_EQUAL(epsilon_difference(tools::max_value(), std::numeric_limits::infinity()), tools::max_value()); BOOST_CHECK_EQUAL(relative_difference(tools::max_value() / 2, std::numeric_limits::infinity()), tools::max_value()); BOOST_CHECK_EQUAL(epsilon_difference(tools::max_value() / 2, std::numeric_limits::infinity()), tools::max_value()); } if(std::numeric_limits::has_quiet_NaN) { BOOST_CHECK_EQUAL(relative_difference(std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()), tools::max_value()); BOOST_CHECK_EQUAL(epsilon_difference(std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()), tools::max_value()); BOOST_CHECK_EQUAL(relative_difference(std::numeric_limits::quiet_NaN(), T(2)), tools::max_value()); BOOST_CHECK_EQUAL(epsilon_difference(std::numeric_limits::quiet_NaN(), T(2)), tools::max_value()); BOOST_CHECK_EQUAL(relative_difference(T(2), std::numeric_limits::quiet_NaN()), tools::max_value()); BOOST_CHECK_EQUAL(epsilon_difference(T(2), std::numeric_limits::quiet_NaN()), tools::max_value()); } } BOOST_AUTO_TEST_CASE( test_main ) { test_values(1.0f, "float"); test_values(1.0, "double"); #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS test_values(1.0L, "long double"); test_values(boost::math::concepts::real_concept(0), "real_concept"); #endif }