123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313 |
- // 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)
- #include <pch.hpp>
- #include <cmath>
- #include <math.h>
- #include <boost/limits.hpp>
- #include <boost/math/concepts/real_concept.hpp>
- #include <boost/math/special_functions/fpclassify.hpp>
- #define BOOST_TEST_MAIN
- #include <boost/test/unit_test.hpp>
- #include <iostream>
- #include <iomanip>
- #ifdef _MSC_VER
- #pragma warning(disable: 4127 4146) // 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<true>&)
- {
- return "Generic (with numeric limits)";
- }
- const char* method_name(const boost::math::detail::generic_tag<false>&)
- {
- 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 <class T>
- void test_classify(T t, const char* type)
- {
- std::cout << "Testing type " << type << std::endl;
- typedef typename boost::math::detail::fp_traits<T>::type traits;
- typedef typename traits::method method;
- std::cout << "Evaluation method = " << method_name(method()) << std::endl;
- 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);
- if(std::numeric_limits<T>::is_specialized)
- {
- t = (std::numeric_limits<T>::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);
- t = (std::numeric_limits<T>::min)();
- if(t != 0)
- {
- BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_NORMAL);
- BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true);
- BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false);
- BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false);
- BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), true);
- if(!std::numeric_limits<T>::is_integer)
- {
- BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_NORMAL);
- BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true);
- BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false);
- BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), true);
- BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false);
- }
- }
- }
- if(std::numeric_limits<T>::has_denorm)
- {
- t = (std::numeric_limits<T>::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);
- }
- t = std::numeric_limits<T>::denorm_min();
- if((t != 0) && (t < (std::numeric_limits<T>::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);
- }
- }
- 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);
- 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);
- // infinity:
- if(std::numeric_limits<T>::has_infinity)
- {
- // At least one std::numeric_limits<T>::infinity)() returns zero
- // (Compaq true64 cxx), hence the check.
- t = (std::numeric_limits<T>::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);
- #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);
- 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);
- #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<T>::quiet_NaN() !!!!!!!
- if(std::numeric_limits<T>::has_quiet_NaN)
- {
- t = std::numeric_limits<T>::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<T>::has_signaling_NaN)
- {
- t = std::numeric_limits<T>::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
- }
- BOOST_AUTO_TEST_CASE( test_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;
- // then run the tests:
- test_classify(float(0), "float");
- test_classify(double(0), "double");
- // long double support for fpclassify is considered "core" so we always test it
- // even when long double support is turned off via BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
- test_classify((long double)(0), "long double");
- test_classify((boost::math::concepts::real_concept)(0), "real_concept");
- // We should test with integer types as well:
- test_classify(int(0), "int");
- test_classify(unsigned(0), "unsigned");
- }
- /*
- Autorun "i:\Boost-sandbox\math_toolkit\libs\math\test\MSVC80\debug\test_classify.exe"
- Running 1 test case...
- FP_ZERO: 0
- FP_NORMAL: 1
- FP_INFINITE: 2
- FP_NAN: 3
- FP_SUBNORMAL: 4
- Testing type float
- Testing type double
- Testing type long double
- Testing type real_concept
- Denormalised forms not tested
- Infinity not tested
- Quiet NaN's not tested
- Signaling NaN's not tested
- Test suite "Test Program" passed with:
- 79 assertions out of 79 passed
- 1 test case out of 1 passed
- Test case "test_main_caller( argc, argv )" passed with:
- 79 assertions out of 79 passed
- */
|