1 //  Copyright John Maddock 2006.
2 //  Copyright Paul A. Bristow 2007
3 //  Use, modification and distribution are subject to the
4 //  Boost Software License, Version 1.0. (See accompanying file
5 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 
7 #include <pch.hpp>
8 
9 #include <cmath>
10 #include <math.h>
11 #include <boost/limits.hpp>
12 #include <boost/math/concepts/real_concept.hpp>
13 #include <boost/math/special_functions/fpclassify.hpp>
14 #define BOOST_TEST_MAIN
15 #include <boost/test/unit_test.hpp>
16 #include <iostream>
17 #include <iomanip>
18 
19 #ifdef _MSC_VER
20 #pragma warning(disable: 4127 4146) //  conditional expression is constant
21 #endif
22 
method_name(const boost::math::detail::native_tag &)23 const char* method_name(const boost::math::detail::native_tag&)
24 {
25    return "Native";
26 }
27 
method_name(const boost::math::detail::generic_tag<true> &)28 const char* method_name(const boost::math::detail::generic_tag<true>&)
29 {
30    return "Generic (with numeric limits)";
31 }
32 
method_name(const boost::math::detail::generic_tag<false> &)33 const char* method_name(const boost::math::detail::generic_tag<false>&)
34 {
35    return "Generic (without numeric limits)";
36 }
37 
method_name(const boost::math::detail::ieee_tag &)38 const char* method_name(const boost::math::detail::ieee_tag&)
39 {
40    return "IEEE std";
41 }
42 
method_name(const boost::math::detail::ieee_copy_all_bits_tag &)43 const char* method_name(const boost::math::detail::ieee_copy_all_bits_tag&)
44 {
45    return "IEEE std, copy all bits";
46 }
47 
method_name(const boost::math::detail::ieee_copy_leading_bits_tag &)48 const char* method_name(const boost::math::detail::ieee_copy_leading_bits_tag&)
49 {
50    return "IEEE std, copy leading bits";
51 }
52 
53 template <class T>
test_classify(T t,const char * type)54 void test_classify(T t, const char* type)
55 {
56    std::cout << "Testing type " << type << std::endl;
57 
58    typedef typename boost::math::detail::fp_traits<T>::type traits;
59    typedef typename traits::method method;
60 
61    std::cout << "Evaluation method = " << method_name(method()) << std::endl;
62 
63    t = 2;
64    T u = 2;
65    BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_NORMAL);
66    BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_NORMAL);
67    BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true);
68    BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true);
69    BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false);
70    BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false);
71    BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false);
72    BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false);
73    BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), true);
74    BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), true);
75    if(std::numeric_limits<T>::is_specialized)
76    {
77       t = (std::numeric_limits<T>::max)();
78       BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_NORMAL);
79       BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_NORMAL);
80       BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true);
81       BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true);
82       BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false);
83       BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false);
84       BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false);
85       BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false);
86       BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), true);
87       BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), true);
88       t = (std::numeric_limits<T>::min)();
89       if(t != 0)
90       {
91          BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_NORMAL);
92          BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true);
93          BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false);
94          BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false);
95          BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), true);
96          if(!std::numeric_limits<T>::is_integer)
97          {
98             BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_NORMAL);
99             BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true);
100             BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false);
101             BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), true);
102             BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false);
103          }
104       }
105    }
106    if(std::numeric_limits<T>::has_denorm)
107    {
108       t = (std::numeric_limits<T>::min)();
109       t /= 2;
110       if(t != 0)
111       {
112          BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_SUBNORMAL);
113          BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_SUBNORMAL);
114          BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true);
115          BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true);
116          BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false);
117          BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false);
118          BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false);
119          BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false);
120          BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false);
121          BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false);
122       }
123       t = std::numeric_limits<T>::denorm_min();
124       if((t != 0) && (t < (std::numeric_limits<T>::min)()))
125       {
126          BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_SUBNORMAL);
127          BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_SUBNORMAL);
128          BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true);
129          BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true);
130          BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false);
131          BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false);
132          BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false);
133          BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false);
134          BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false);
135          BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false);
136       }
137    }
138    else
139    {
140       std::cout << "Denormalised forms not tested" << std::endl;
141    }
142    t = 0;
143    BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_ZERO);
144    BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_ZERO);
145    BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true);
146    BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true);
147    BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false);
148    BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false);
149    BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false);
150    BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false);
151    BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false);
152    BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false);
153    t /= -u; // create minus zero if it exists
154    BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_ZERO);
155    BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_ZERO);
156    BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true);
157    BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true);
158    BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false);
159    BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false);
160    BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false);
161    BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false);
162    BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false);
163    BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false);
164    // infinity:
165    if(std::numeric_limits<T>::has_infinity)
166    {
167       // At least one std::numeric_limits<T>::infinity)() returns zero
168       // (Compaq true64 cxx), hence the check.
169       t = (std::numeric_limits<T>::infinity)();
170       BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_INFINITE);
171       BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_INFINITE);
172       BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), false);
173       BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), false);
174       BOOST_CHECK_EQUAL((::boost::math::isinf)(t), true);
175       BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), true);
176       BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false);
177       BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false);
178       BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false);
179       BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false);
180 #if !defined(__BORLANDC__) && !(defined(__DECCXX) && !defined(_IEEE_FP))
181       // divide by zero on Borland triggers a C++ exception :-(
182       // divide by zero on Compaq CXX triggers a C style signal :-(
183       t = 2;
184       u = 0;
185       t /= u;
186       BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_INFINITE);
187       BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_INFINITE);
188       BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), false);
189       BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), false);
190       BOOST_CHECK_EQUAL((::boost::math::isinf)(t), true);
191       BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), true);
192       BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false);
193       BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false);
194       BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false);
195       BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false);
196       t = -2;
197       t /= u;
198       BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_INFINITE);
199       BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_INFINITE);
200       BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), false);
201       BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), false);
202       BOOST_CHECK_EQUAL((::boost::math::isinf)(t), true);
203       BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), true);
204       BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false);
205       BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false);
206       BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false);
207       BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false);
208 #else
209       std::cout << "Infinities from divide by zero not tested" << std::endl;
210 #endif
211    }
212    else
213    {
214       std::cout << "Infinity not tested" << std::endl;
215    }
216 #ifndef __BORLANDC__
217    // NaN's:
218    // Note that Borland throws an exception if we even try to obtain a Nan
219    // by calling std::numeric_limits<T>::quiet_NaN() !!!!!!!
220    if(std::numeric_limits<T>::has_quiet_NaN)
221    {
222       t = std::numeric_limits<T>::quiet_NaN();
223       BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_NAN);
224       BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_NAN);
225       BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), false);
226       BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), false);
227       BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false);
228       BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false);
229       BOOST_CHECK_EQUAL((::boost::math::isnan)(t), true);
230       BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), true);
231       BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false);
232       BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false);
233    }
234    else
235    {
236       std::cout << "Quiet NaN's not tested" << std::endl;
237    }
238    if(std::numeric_limits<T>::has_signaling_NaN)
239    {
240       t = std::numeric_limits<T>::signaling_NaN();
241       BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_NAN);
242       BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_NAN);
243       BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), false);
244       BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), false);
245       BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false);
246       BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false);
247       BOOST_CHECK_EQUAL((::boost::math::isnan)(t), true);
248       BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), true);
249       BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false);
250       BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false);
251    }
252    else
253    {
254       std::cout << "Signaling NaN's not tested" << std::endl;
255    }
256 #endif
257 }
258 
BOOST_AUTO_TEST_CASE(test_main)259 BOOST_AUTO_TEST_CASE( test_main )
260 {
261    BOOST_MATH_CONTROL_FP;
262    // start by printing some information:
263 #ifdef isnan
264    std::cout << "Platform has isnan macro." << std::endl;
265 #endif
266 #ifdef fpclassify
267    std::cout << "Platform has fpclassify macro." << std::endl;
268 #endif
269 #ifdef BOOST_HAS_FPCLASSIFY
270    std::cout << "Platform has FP_NORMAL macro." << std::endl;
271 #endif
272    std::cout << "FP_ZERO: " << (int)FP_ZERO << std::endl;
273    std::cout << "FP_NORMAL: " << (int)FP_NORMAL << std::endl;
274    std::cout << "FP_INFINITE: " << (int)FP_INFINITE << std::endl;
275    std::cout << "FP_NAN: " << (int)FP_NAN << std::endl;
276    std::cout << "FP_SUBNORMAL: " << (int)FP_SUBNORMAL << std::endl;
277 
278    // then run the tests:
279    test_classify(float(0), "float");
280    test_classify(double(0), "double");
281    // long double support for fpclassify is considered "core" so we always test it
282    // even when long double support is turned off via BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
283    test_classify((long double)(0), "long double");
284    test_classify((boost::math::concepts::real_concept)(0), "real_concept");
285 
286    // We should test with integer types as well:
287    test_classify(int(0), "int");
288    test_classify(unsigned(0), "unsigned");
289 }
290 
291 /*
292 Autorun "i:\Boost-sandbox\math_toolkit\libs\math\test\MSVC80\debug\test_classify.exe"
293 Running 1 test case...
294 FP_ZERO: 0
295 FP_NORMAL: 1
296 FP_INFINITE: 2
297 FP_NAN: 3
298 FP_SUBNORMAL: 4
299 Testing type float
300 Testing type double
301 Testing type long double
302 Testing type real_concept
303 Denormalised forms not tested
304 Infinity not tested
305 Quiet NaN's not tested
306 Signaling NaN's not tested
307 Test suite "Test Program" passed with:
308   79 assertions out of 79 passed
309   1 test case out of 1 passed
310   Test case "test_main_caller( argc, argv )" passed with:
311     79 assertions out of 79 passed
312 
313 */
314