• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //  (C) Copyright John Maddock 2015.
2 //  Use, modification and distribution are subject to the
3 //  Boost Software License, Version 1.0. (See accompanying file
4 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #include <boost/math/concepts/real_concept.hpp>
7 #define BOOST_TEST_MAIN
8 #include <boost/test/unit_test.hpp>
9 #include <boost/test/tools/floating_point_comparison.hpp>
10 #include <boost/math/special_functions/next.hpp>
11 #include <boost/math/special_functions/ulp.hpp>
12 #include <boost/math/special_functions/relative_difference.hpp>
13 #include <iostream>
14 #include <iomanip>
15 
16 template <class T>
test_value(const T & val,const char * name)17 void test_value(const T& val, const char* name)
18 {
19    using namespace boost::math;
20    using std::fabs;
21    T next = float_next(val);
22    T prev = float_prior(val);
23 
24    if((boost::math::isinf)(next))
25    {
26       BOOST_CHECK_EQUAL(relative_difference(val, next), tools::max_value<T>());
27       return;
28    }
29    if((boost::math::isinf)(prev))
30    {
31       BOOST_CHECK_EQUAL(relative_difference(val, prev), tools::max_value<T>());
32       return;
33    }
34 
35    BOOST_CHECK_EQUAL(relative_difference(val, next), relative_difference(next, val));
36    BOOST_CHECK_EQUAL(epsilon_difference(val, next), epsilon_difference(next, val));
37    BOOST_CHECK_LE(relative_difference(val, next), boost::math::tools::epsilon<T>());
38    BOOST_CHECK_LE(epsilon_difference(val, next), T(1));
39    if((fabs(val) > tools::min_value<T>()) || (fabs(next) > tools::min_value<T>()))
40    {
41       BOOST_CHECK_GT(relative_difference(val, next), T(0));
42       BOOST_CHECK_GT(epsilon_difference(val, next), T(0));
43    }
44    else
45    {
46       BOOST_CHECK_EQUAL(relative_difference(val, next), T(0));
47       BOOST_CHECK_EQUAL(epsilon_difference(val, next), T(0));
48    }
49 
50    BOOST_CHECK_EQUAL(relative_difference(val, prev), relative_difference(prev, val));
51    BOOST_CHECK_EQUAL(epsilon_difference(val, prev), epsilon_difference(prev, val));
52    if((fabs(val) > tools::min_value<T>()) || (fabs(prev) > tools::min_value<T>()))
53    {
54       BOOST_CHECK_GT(relative_difference(val, prev), T(0));
55       BOOST_CHECK_GT(epsilon_difference(val, prev), T(0));
56    }
57    else
58    {
59       BOOST_CHECK_EQUAL(relative_difference(val, prev), T(0));
60       BOOST_CHECK_EQUAL(epsilon_difference(val, prev), T(0));
61    }
62 }
63 
64 template <class T>
test_values(const T & val,const char * name)65 void test_values(const T& val, const char* name)
66 {
67    static const T a = static_cast<T>(1.3456724e22);
68    static const T b = static_cast<T>(1.3456724e-22);
69    static const T z = 0;
70    static const T one = 1;
71    static const T two = 2;
72 
73    std::cout << "Testing type " << name << std::endl;
74 
75    T den = (std::numeric_limits<T>::min)() / 4;
76    if(den != 0)
77    {
78       std::cout << "Denormals are active\n";
79    }
80    else
81    {
82       std::cout << "Denormals are flushed to zero.\n";
83    }
84 
85    test_value(a, name);
86    test_value(-a, name);
87    test_value(b, name);
88    test_value(-b, name);
89    test_value(boost::math::tools::epsilon<T>(), name);
90    test_value(-boost::math::tools::epsilon<T>(), name);
91    test_value(boost::math::tools::min_value<T>(), name);
92    test_value(-boost::math::tools::min_value<T>(), name);
93    if (std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::has_denorm == std::denorm_present) && ((std::numeric_limits<T>::min)() / 2 != 0))
94    {
95       test_value(z, name);
96       test_value(-z, name);
97    }
98    test_value(one, name);
99    test_value(-one, name);
100    test_value(two, name);
101    test_value(-two, name);
102 
103    static const int primes[] = {
104       11,     13,     17,     19,     23,     29,
105       31,     37,     41,     43,     47,     53,     59,     61,     67,     71,
106       73,     79,     83,     89,     97,    101,    103,    107,    109,    113,
107       127,    131,    137,    139,    149,    151,    157,    163,    167,    173,
108       179,    181,    191,    193,    197,    199,    211,    223,    227,    229,
109       233,    239,    241,    251,    257,    263,    269,    271,    277,    281,
110       283,    293,    307,    311,    313,    317,    331,    337,    347,    349,
111       353,    359,    367,    373,    379,    383,    389,    397,    401,    409,
112       419,    421,    431,    433,    439,    443,    449,    457,    461,    463,
113    };
114 
115    for(unsigned i = 0; i < sizeof(primes) / sizeof(primes[0]); ++i)
116    {
117       for(unsigned j = 0; j < sizeof(primes) / sizeof(primes[0]); ++j)
118       {
119          test_value(T(primes[i]) / T(primes[j]), name);
120          test_value(-T(primes[i]) / T(primes[j]), name);
121       }
122    }
123    using namespace boost::math;
124    BOOST_CHECK_EQUAL(relative_difference(tools::min_value<T>(), -tools::min_value<T>()), tools::max_value<T>());
125    BOOST_CHECK_EQUAL(epsilon_difference(tools::min_value<T>(), -tools::min_value<T>()), tools::max_value<T>());
126    if(std::numeric_limits<T>::has_infinity)
127    {
128       BOOST_CHECK_EQUAL(relative_difference(std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity()), T(0));
129       BOOST_CHECK_EQUAL(epsilon_difference(std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity()), T(0));
130       BOOST_CHECK_EQUAL(relative_difference(std::numeric_limits<T>::infinity(), tools::max_value<T>()), tools::max_value<T>());
131       BOOST_CHECK_EQUAL(epsilon_difference(std::numeric_limits<T>::infinity(), tools::max_value<T>()), tools::max_value<T>());
132       BOOST_CHECK_EQUAL(relative_difference(std::numeric_limits<T>::infinity(), tools::max_value<T>() / 2), tools::max_value<T>());
133       BOOST_CHECK_EQUAL(epsilon_difference(std::numeric_limits<T>::infinity(), tools::max_value<T>() / 2), tools::max_value<T>());
134       BOOST_CHECK_EQUAL(relative_difference(tools::max_value<T>(), std::numeric_limits<T>::infinity()), tools::max_value<T>());
135       BOOST_CHECK_EQUAL(epsilon_difference(tools::max_value<T>(), std::numeric_limits<T>::infinity()), tools::max_value<T>());
136       BOOST_CHECK_EQUAL(relative_difference(tools::max_value<T>() / 2, std::numeric_limits<T>::infinity()), tools::max_value<T>());
137       BOOST_CHECK_EQUAL(epsilon_difference(tools::max_value<T>() / 2, std::numeric_limits<T>::infinity()), tools::max_value<T>());
138    }
139    if(std::numeric_limits<T>::has_quiet_NaN)
140    {
141       BOOST_CHECK_EQUAL(relative_difference(std::numeric_limits<T>::quiet_NaN(), std::numeric_limits<T>::quiet_NaN()), tools::max_value<T>());
142       BOOST_CHECK_EQUAL(epsilon_difference(std::numeric_limits<T>::quiet_NaN(), std::numeric_limits<T>::quiet_NaN()), tools::max_value<T>());
143       BOOST_CHECK_EQUAL(relative_difference(std::numeric_limits<T>::quiet_NaN(), T(2)), tools::max_value<T>());
144       BOOST_CHECK_EQUAL(epsilon_difference(std::numeric_limits<T>::quiet_NaN(), T(2)), tools::max_value<T>());
145       BOOST_CHECK_EQUAL(relative_difference(T(2), std::numeric_limits<T>::quiet_NaN()), tools::max_value<T>());
146       BOOST_CHECK_EQUAL(epsilon_difference(T(2), std::numeric_limits<T>::quiet_NaN()), tools::max_value<T>());
147    }
148 
149 }
150 
BOOST_AUTO_TEST_CASE(test_main)151 BOOST_AUTO_TEST_CASE( test_main )
152 {
153    test_values(1.0f, "float");
154    test_values(1.0, "double");
155 #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
156    test_values(1.0L, "long double");
157    test_values(boost::math::concepts::real_concept(0), "real_concept");
158 #endif
159 }
160 
161 
162