// test Boost.Test on Nan and inf // Copyright Paul A. Bristow 2007. // 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 using std::cout; using std::endl; #include using std::numeric_limits; #pragma warning(disable: 4800) // int to book // We need TR1 Floating Point Utilities by Johan Råde in the review queue. // but here are some kludges for MSVC. template bool isfinite(T); template bool isinf(T); template bool isnan(T); template<> bool isfinite(double x) { #ifdef _MSC_VER // or BOOST_MSVC return (_finite(x)); #else # error isfinite not implemented here for this compiler? #endif } template<> bool isinf(double x) { #ifdef _MSC_VER // or BOOST_MSVC { if (_finite(x)) return false; if (_isnan(x)) return false; return true; // Must be infinite (+ or -). } #else # error isinf not implemented here for this compiler? #endif } template<> bool isnan(double x) { #ifdef _MSC_VER // or BOOST_MSVC return (_isnan(x)); #else # error isnan not implemented here for this compiler? #endif } #define BOOST_TEST_MODULE NaN_Inf_Tests #include #include // for BOOST_CHECK_CLOSE BOOST_AUTO_TEST_CASE(test_NaN) { //BOOST_CHECK(isfinite(0)); // fails to compile - isfinite is not specialized for int! BOOST_CHECK(isfinite(0.)); // pass BOOST_CHECK(isfinite(1.)); // pass BOOST_CHECK(isfinite(-1.)); // pass BOOST_CHECK(isfinite(numeric_limits::max())); // pass BOOST_CHECK(isfinite(numeric_limits::min())); // pass BOOST_CHECK(isnan(numeric_limits::quiet_NaN())); // pass BOOST_CHECK(! isfinite(numeric_limits::quiet_NaN())); // pass BOOST_CHECK(! isinf(numeric_limits::quiet_NaN())); // pass BOOST_CHECK(isinf(numeric_limits::infinity())); // pass BOOST_CHECK(isinf(-numeric_limits::infinity())); // pass BOOST_CHECK(! isfinite(numeric_limits::infinity())); // pass } // BOOST_AUTO_TEST_CASE(test_NaN) BOOST_AUTO_TEST_CASE(my_test_zero_NaN_inf) { // BOOST_CHECK (predicate) BOOST_CHECK(numeric_limits::quiet_NaN() != 0.); // pass BOOST_CHECK(numeric_limits::quiet_NaN() !=numeric_limits::max()); // pass BOOST_CHECK(numeric_limits::quiet_NaN() != numeric_limits::quiet_NaN()); // pass BOOST_CHECK(numeric_limits::quiet_NaN() != numeric_limits::infinity()); // pass BOOST_CHECK(numeric_limits::infinity() != numeric_limits::quiet_NaN()); // pass BOOST_CHECK(numeric_limits::infinity() == numeric_limits::infinity()); // pass BOOST_CHECK(0 == 0); // pass // BOOST_CHECK_EQUAL(parameter1, parameter2) - uses operator== inside BOOST_CHECK_EQUAL BOOST_CHECK_EQUAL(0, 0); // pass BOOST_CHECK_EQUAL(numeric_limits::infinity(), numeric_limits::infinity()); // pass //BOOST_CHECK_EQUAL(numeric_limits::quiet_NaN(), numeric_limits::quiet_NaN()); // fails //BOOST_CHECK_EQUAL(numeric_limits::quiet_NaN(), numeric_limits::quiet_NaN()); // fails BOOST_CHECK_EQUAL(numeric_limits::infinity(), numeric_limits::infinity()); // pass BOOST_CHECK_EQUAL(numeric_limits::min(), numeric_limits::min()); // pass BOOST_CHECK_EQUAL(numeric_limits::max(), numeric_limits::max()); // pass BOOST_CHECK_EQUAL(numeric_limits::denorm_min(), numeric_limits::denorm_min()); // pass BOOST_CHECK_CLOSE_FRACTION(0., 0., numeric_limits::epsilon()); // pass BOOST_CHECK_CLOSE_FRACTION(0., 0., numeric_limits::max()); // pass BOOST_CHECK_CLOSE_FRACTION(0., 0., 1.); // pass BOOST_CHECK_CLOSE_FRACTION(0., 0., 0.); // pass BOOST_CHECK_CLOSE_FRACTION(numeric_limits::min(), numeric_limits::min(), numeric_limits::epsilon()); // pass BOOST_CHECK_CLOSE_FRACTION(numeric_limits::denorm_min(), numeric_limits::denorm_min(), numeric_limits::epsilon()); // pass BOOST_CHECK_CLOSE_FRACTION(numeric_limits::max(), numeric_limits::max(), numeric_limits::epsilon()); // pass BOOST_CHECK_CLOSE_FRACTION(numeric_limits::max(), numeric_limits::max(), numeric_limits::infinity()); // pass // So all identical finites should be pass CHECK_CLOSE whatever the tolerance, (as long as finite) // BOOST_CHECK_CLOSE_FRACTION(numeric_limits::max(), numeric_limits::max(), numeric_limits::quiet_NaN()); // fails // but identical INfinites are expected to fail. // BOOST_CHECK_CLOSE_FRACTION(numeric_limits::infinity(), numeric_limits::infinity(), numeric_limits::epsilon()); // fails // BOOST_CHECK_CLOSE_FRACTION(numeric_limits::infinity(), numeric_limits::infinity(), 1.); // fails // BOOST_CHECK_CLOSE_FRACTION(numeric_limits::infinity(), numeric_limits::infinity(), numeric_limits::max()); // fails // BOOST_CHECK_CLOSE_FRACTION(numeric_limits::quiet_NaN(), numeric_limits::quiet_NaN(), 1.); // fails // BOOST_CHECK_CLOSE_FRACTION(numeric_limits::quiet_NaN(), numeric_limits::quiet_NaN(), numeric_limits::infinity()); // fails double x = 1.0000000000001; if (isfinite(x)) { BOOST_CHECK_CLOSE(x, 1., 0.001); } else { // If not finite then we expect the result to be NaN. BOOST_CHECK(isnan(x)); } double y = numeric_limits::quiet_NaN(); if (isfinite(y)) { BOOST_CHECK_CLOSE(y, 1., 0.000001); } else { // Check the case when some compute does result in the expected NaN. BOOST_CHECK(isnan(y)); } // Or we might expect the result to be infinity (not NaN). double z = numeric_limits::infinity(); if (isfinite(z)) { BOOST_CHECK_CLOSE(z, 1., 0.000001); } else {// If not finite then we expect the result to be infinity. BOOST_CHECK(isinf(z)); } double d = 1.23; double n = 0.; // force a divide by zero, double r = d / n; // expecting an infinity result. // cout << r << endl; // 1.#INF if (isfinite(r)) { BOOST_CHECK_CLOSE(r, 1., 0.000001); } else {// If not finite then we expect the result to be infinity. BOOST_CHECK(isinf(r)); } } // BOOST_AUTO_TEST_CASE(my_test_zero_NaN_inf)