// Copyright John Maddock 2006. // 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) #ifdef _MSC_VER #define _SCL_SECURE_NO_WARNINGS #endif #include #include #include #include #include "test.hpp" #if !defined(TEST_MPF_50) && !defined(TEST_MPF) && !defined(TEST_BACKEND) && !defined(TEST_MPZ) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR) && !defined(TEST_MPFR_50) && !defined(TEST_MPQ) && !defined(TEST_MPFI_50) && !defined(TEST_FLOAT128) && !defined(TEST_CPP_BIN_FLOAT) #define TEST_MPF_50 #define TEST_MPFR_50 #define TEST_MPFI_50 #define TEST_BACKEND #define TEST_CPP_DEC_FLOAT #define TEST_FLOAT128 #define TEST_CPP_BIN_FLOAT #ifdef _MSC_VER #pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") #endif #ifdef __GNUC__ #pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" #endif #endif #if defined(TEST_MPF_50) #include #endif #ifdef TEST_MPFR_50 #include #endif #ifdef TEST_MPFI_50 #include #endif #ifdef TEST_BACKEND #include #endif #ifdef TEST_CPP_DEC_FLOAT #include #endif #ifdef TEST_FLOAT128 #include #endif #ifdef TEST_CPP_BIN_FLOAT #include #endif #ifdef _MSC_VER #pragma warning(disable : 4127) // conditional expression is constant #endif const char* method_name(const boost::math::detail::native_tag&) { return "Native"; } const char* method_name(const boost::math::detail::generic_tag&) { return "Generic (with numeric limits)"; } const char* method_name(const boost::math::detail::generic_tag&) { return "Generic (without numeric limits)"; } const char* method_name(const boost::math::detail::ieee_tag&) { return "IEEE std"; } const char* method_name(const boost::math::detail::ieee_copy_all_bits_tag&) { return "IEEE std, copy all bits"; } const char* method_name(const boost::math::detail::ieee_copy_leading_bits_tag&) { return "IEEE std, copy leading bits"; } template void test() { T t = 2; T u = 2; BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_NORMAL); BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_NORMAL); BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true); BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true); BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false); BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false); BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false); BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false); BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), true); BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), true); BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (::boost::math::fpclassify)(t + 0)); if (std::numeric_limits::is_specialized) { t = (std::numeric_limits::max)(); BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_NORMAL); BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_NORMAL); BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true); BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true); BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false); BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false); BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false); BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false); BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), true); BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), true); BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (::boost::math::fpclassify)(t + 0)); t = (std::numeric_limits::min)(); BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_NORMAL); BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_NORMAL); BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true); BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true); BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false); BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false); BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false); BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false); BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), true); BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), true); BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (::boost::math::fpclassify)(t + 0)); } if (std::numeric_limits::has_denorm) { t = (std::numeric_limits::min)(); t /= 2; if (t != 0) { BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_SUBNORMAL); BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_SUBNORMAL); BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true); BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true); BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false); BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false); BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false); BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false); BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false); BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false); BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (::boost::math::fpclassify)(t + 0)); } t = std::numeric_limits::denorm_min(); if ((t != 0) && (t < (std::numeric_limits::min)())) { BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_SUBNORMAL); BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_SUBNORMAL); BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true); BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true); BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false); BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false); BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false); BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false); BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false); BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false); BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (::boost::math::fpclassify)(t + 0)); } } else { std::cout << "Denormalised forms not tested" << std::endl; } t = 0; BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_ZERO); BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_ZERO); BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true); BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true); BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false); BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false); BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false); BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false); BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false); BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false); BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (::boost::math::fpclassify)(t + 0)); t /= -u; // create minus zero if it exists BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_ZERO); BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_ZERO); BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true); BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true); BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false); BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false); BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false); BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false); BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false); BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false); BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (::boost::math::fpclassify)(t + 0)); // infinity: if (std::numeric_limits::has_infinity) { // At least one std::numeric_limits::infinity)() returns zero // (Compaq true64 cxx), hence the check. t = (std::numeric_limits::infinity)(); BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_INFINITE); BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_INFINITE); BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), false); BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), false); BOOST_CHECK_EQUAL((::boost::math::isinf)(t), true); BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), true); BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false); BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false); BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false); BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false); BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (::boost::math::fpclassify)(t + 0)); #if !defined(__BORLANDC__) && !(defined(__DECCXX) && !defined(_IEEE_FP)) // divide by zero on Borland triggers a C++ exception :-( // divide by zero on Compaq CXX triggers a C style signal :-( t = 2; u = 0; t /= u; BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_INFINITE); BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_INFINITE); BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), false); BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), false); BOOST_CHECK_EQUAL((::boost::math::isinf)(t), true); BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), true); BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false); BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false); BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false); BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false); BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (::boost::math::fpclassify)(t + 0)); t = -2; t /= u; BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_INFINITE); BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_INFINITE); BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), false); BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), false); BOOST_CHECK_EQUAL((::boost::math::isinf)(t), true); BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), true); BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false); BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false); BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false); BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false); BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (::boost::math::fpclassify)(t + 0)); #else std::cout << "Infinities from divide by zero not tested" << std::endl; #endif } else { std::cout << "Infinity not tested" << std::endl; } #ifndef __BORLANDC__ // NaN's: // Note that Borland throws an exception if we even try to obtain a Nan // by calling std::numeric_limits::quiet_NaN() !!!!!!! if (std::numeric_limits::has_quiet_NaN) { t = std::numeric_limits::quiet_NaN(); BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_NAN); BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_NAN); BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), false); BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), false); BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false); BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false); BOOST_CHECK_EQUAL((::boost::math::isnan)(t), true); BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), true); BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false); BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false); } else { std::cout << "Quiet NaN's not tested" << std::endl; } if (std::numeric_limits::has_signaling_NaN) { t = std::numeric_limits::signaling_NaN(); BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_NAN); BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_NAN); BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), false); BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), false); BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false); BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false); BOOST_CHECK_EQUAL((::boost::math::isnan)(t), true); BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), true); BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false); BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false); } else { std::cout << "Signaling NaN's not tested" << std::endl; } #endif // // Try sign manipulation functions as well: // T one(1), minus_one(-1), zero(0); BOOST_CHECK((::boost::math::sign)(one) > 0); BOOST_CHECK((::boost::math::sign)(minus_one) < 0); BOOST_CHECK((::boost::math::sign)(zero) == 0); BOOST_CHECK((::boost::math::sign)(one + 2) > 0); BOOST_CHECK((::boost::math::sign)(minus_one - 30) < 0); BOOST_CHECK((::boost::math::sign)(-zero) == 0); BOOST_CHECK((::boost::math::signbit)(one) == 0); BOOST_CHECK((::boost::math::signbit)(minus_one) > 0); BOOST_CHECK((::boost::math::signbit)(zero) == 0); BOOST_CHECK((::boost::math::signbit)(one + 2) == 0); BOOST_CHECK((::boost::math::signbit)(minus_one - 30) > 0); //BOOST_CHECK((::boost::math::signbit)(-zero) == 0); BOOST_CHECK((::boost::math::signbit)(boost::math::changesign(one)) > 0); BOOST_CHECK_EQUAL(boost::math::changesign(one), minus_one); BOOST_CHECK((::boost::math::signbit)(boost::math::changesign(minus_one)) == 0); BOOST_CHECK_EQUAL(boost::math::changesign(minus_one), one); //BOOST_CHECK((::boost::math::signbit)(zero) == 0); BOOST_CHECK((::boost::math::signbit)(boost::math::changesign(one + 2)) > 0); BOOST_CHECK_EQUAL(boost::math::changesign(one + 2), -3); BOOST_CHECK((::boost::math::signbit)(boost::math::changesign(minus_one - 30)) == 0); BOOST_CHECK_EQUAL(boost::math::changesign(minus_one - 30), 31); //BOOST_CHECK((::boost::math::signbit)(-zero) == 0); BOOST_CHECK((::boost::math::signbit)(boost::math::copysign(one, one)) == 0); BOOST_CHECK_EQUAL(boost::math::copysign(one, one), one); BOOST_CHECK((::boost::math::signbit)(boost::math::copysign(one, minus_one)) > 0); BOOST_CHECK_EQUAL(boost::math::copysign(one, minus_one), minus_one); BOOST_CHECK((::boost::math::signbit)(boost::math::copysign(minus_one, one)) == 0); BOOST_CHECK_EQUAL(boost::math::copysign(minus_one, one), one); BOOST_CHECK((::boost::math::signbit)(boost::math::copysign(minus_one, minus_one)) > 0); BOOST_CHECK_EQUAL(boost::math::copysign(minus_one, minus_one), minus_one); BOOST_CHECK((::boost::math::signbit)(boost::math::copysign(one + 1, one + 2)) == 0); BOOST_CHECK_EQUAL(boost::math::copysign(one + 1, one + 2), 2); BOOST_CHECK((::boost::math::signbit)(boost::math::copysign(one + 30, minus_one - 20)) > 0); BOOST_CHECK_EQUAL(boost::math::copysign(one + 30, minus_one - 20), -31); BOOST_CHECK((::boost::math::signbit)(boost::math::copysign(minus_one + 2, one + 2)) == 0); BOOST_CHECK_EQUAL(boost::math::copysign(minus_one - 2, one + 2), 3); BOOST_CHECK((::boost::math::signbit)(boost::math::copysign(minus_one - 20, minus_one - 30)) > 0); BOOST_CHECK_EQUAL(boost::math::copysign(minus_one - 20, minus_one - 30), -21); // Things involving signed zero, need to detect it first: T neg_zero_test = -(std::numeric_limits::min)(); neg_zero_test /= (std::numeric_limits::max)(); if (std::numeric_limits::has_infinity && (one / neg_zero_test < 0)) { #ifndef TEST_MPFI_50 // Note that testing this with mpfi is in the "too difficult" drawer at present. std::cout << neg_zero_test << std::endl; BOOST_CHECK_EQUAL(neg_zero_test, 0); BOOST_CHECK((::boost::math::sign)(neg_zero_test) == 0); // We got -INF, so we have a signed zero: BOOST_CHECK((::boost::math::signbit)(neg_zero_test) > 0); BOOST_CHECK((::boost::math::signbit)(boost::math::changesign(zero)) > 0); BOOST_CHECK_EQUAL(boost::math::changesign(zero), 0); BOOST_CHECK((::boost::math::signbit)(boost::math::changesign(neg_zero_test)) == 0); BOOST_CHECK_EQUAL(boost::math::changesign(neg_zero_test), 0); BOOST_CHECK((::boost::math::signbit)(boost::math::copysign(zero, one)) == 0); BOOST_CHECK_EQUAL(boost::math::copysign(zero, one), 0); BOOST_CHECK((::boost::math::signbit)(boost::math::copysign(zero, minus_one)) > 0); BOOST_CHECK_EQUAL(boost::math::copysign(zero, minus_one), 0); BOOST_CHECK((::boost::math::signbit)(boost::math::copysign(neg_zero_test, one)) == 0); BOOST_CHECK_EQUAL(boost::math::copysign(neg_zero_test, one), 0); BOOST_CHECK((::boost::math::signbit)(boost::math::copysign(neg_zero_test, minus_one)) > 0); BOOST_CHECK_EQUAL(boost::math::copysign(neg_zero_test, minus_one), 0); #endif } } int main() { BOOST_MATH_CONTROL_FP; // start by printing some information: #ifdef isnan std::cout << "Platform has isnan macro." << std::endl; #endif #ifdef fpclassify std::cout << "Platform has fpclassify macro." << std::endl; #endif #ifdef BOOST_HAS_FPCLASSIFY std::cout << "Platform has FP_NORMAL macro." << std::endl; #endif std::cout << "FP_ZERO: " << (int)FP_ZERO << std::endl; std::cout << "FP_NORMAL: " << (int)FP_NORMAL << std::endl; std::cout << "FP_INFINITE: " << (int)FP_INFINITE << std::endl; std::cout << "FP_NAN: " << (int)FP_NAN << std::endl; std::cout << "FP_SUBNORMAL: " << (int)FP_SUBNORMAL << std::endl; #ifdef TEST_MPF_50 test(); test(); #endif #ifdef TEST_MPFR_50 test(); test(); #endif #ifdef TEST_MPFI_50 test(); test(); #endif #ifdef TEST_CPP_DEC_FLOAT test(); test(); #endif #ifdef TEST_BACKEND test >(); #endif #ifdef TEST_FLOAT128 test(); #endif #ifdef TEST_CPP_BIN_FLOAT test(); test, boost::long_long_type> > >(); #endif return boost::report_errors(); }