mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-10-25 18:10:21 -04:00 
			
		
		
		
	
		
			
	
	
		
			311 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			311 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
|  | //  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::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>::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 | ||
|  | 
 | ||
|  | */ |