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)
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>
20 #pragma warning(disable: 4127 4146) // conditional expression is constant
23 const char* method_name(const boost::math::detail::native_tag
&)
28 const char* method_name(const boost::math::detail::generic_tag
<true>&)
30 return "Generic (with numeric limits)";
33 const char* method_name(const boost::math::detail::generic_tag
<false>&)
35 return "Generic (without numeric limits)";
38 const char* method_name(const boost::math::detail::ieee_tag
&)
43 const char* method_name(const boost::math::detail::ieee_copy_all_bits_tag
&)
45 return "IEEE std, copy all bits";
48 const char* method_name(const boost::math::detail::ieee_copy_leading_bits_tag
&)
50 return "IEEE std, copy leading bits";
54 void test_classify(T t
, const char* type
)
56 std::cout
<< "Testing type " << type
<< std::endl
;
58 typedef typename
boost::math::detail::fp_traits
<T
>::type traits
;
59 typedef typename
traits::method method
;
61 std::cout
<< "Evaluation method = " << method_name(method()) << std::endl
;
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
)
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
)();
91 BOOST_CHECK_EQUAL((::boost::math::fpclassify
)(t
), (int)FP_NORMAL
);
92 BOOST_CHECK_EQUAL((::boost::math::fpclassify
)(-t
), (int)FP_NORMAL
);
93 BOOST_CHECK_EQUAL((::boost::math::isfinite
)(t
), true);
94 BOOST_CHECK_EQUAL((::boost::math::isfinite
)(-t
), true);
95 BOOST_CHECK_EQUAL((::boost::math::isinf
)(t
), false);
96 BOOST_CHECK_EQUAL((::boost::math::isinf
)(-t
), false);
97 BOOST_CHECK_EQUAL((::boost::math::isnan
)(t
), false);
98 BOOST_CHECK_EQUAL((::boost::math::isnan
)(-t
), false);
99 BOOST_CHECK_EQUAL((::boost::math::isnormal
)(t
), true);
100 BOOST_CHECK_EQUAL((::boost::math::isnormal
)(-t
), true);
103 if(std::numeric_limits
<T
>::has_denorm
)
105 t
= (std::numeric_limits
<T
>::min
)();
109 BOOST_CHECK_EQUAL((::boost::math::fpclassify
)(t
), (int)FP_SUBNORMAL
);
110 BOOST_CHECK_EQUAL((::boost::math::fpclassify
)(-t
), (int)FP_SUBNORMAL
);
111 BOOST_CHECK_EQUAL((::boost::math::isfinite
)(t
), true);
112 BOOST_CHECK_EQUAL((::boost::math::isfinite
)(-t
), true);
113 BOOST_CHECK_EQUAL((::boost::math::isinf
)(t
), false);
114 BOOST_CHECK_EQUAL((::boost::math::isinf
)(-t
), false);
115 BOOST_CHECK_EQUAL((::boost::math::isnan
)(t
), false);
116 BOOST_CHECK_EQUAL((::boost::math::isnan
)(-t
), false);
117 BOOST_CHECK_EQUAL((::boost::math::isnormal
)(t
), false);
118 BOOST_CHECK_EQUAL((::boost::math::isnormal
)(-t
), false);
120 t
= std::numeric_limits
<T
>::denorm_min();
121 if((t
!= 0) && (t
< (std::numeric_limits
<T
>::min
)()))
123 BOOST_CHECK_EQUAL((::boost::math::fpclassify
)(t
), (int)FP_SUBNORMAL
);
124 BOOST_CHECK_EQUAL((::boost::math::fpclassify
)(-t
), (int)FP_SUBNORMAL
);
125 BOOST_CHECK_EQUAL((::boost::math::isfinite
)(t
), true);
126 BOOST_CHECK_EQUAL((::boost::math::isfinite
)(-t
), true);
127 BOOST_CHECK_EQUAL((::boost::math::isinf
)(t
), false);
128 BOOST_CHECK_EQUAL((::boost::math::isinf
)(-t
), false);
129 BOOST_CHECK_EQUAL((::boost::math::isnan
)(t
), false);
130 BOOST_CHECK_EQUAL((::boost::math::isnan
)(-t
), false);
131 BOOST_CHECK_EQUAL((::boost::math::isnormal
)(t
), false);
132 BOOST_CHECK_EQUAL((::boost::math::isnormal
)(-t
), false);
137 std::cout
<< "Denormalised forms not tested" << std::endl
;
140 BOOST_CHECK_EQUAL((::boost::math::fpclassify
)(t
), (int)FP_ZERO
);
141 BOOST_CHECK_EQUAL((::boost::math::fpclassify
)(-t
), (int)FP_ZERO
);
142 BOOST_CHECK_EQUAL((::boost::math::isfinite
)(t
), true);
143 BOOST_CHECK_EQUAL((::boost::math::isfinite
)(-t
), true);
144 BOOST_CHECK_EQUAL((::boost::math::isinf
)(t
), false);
145 BOOST_CHECK_EQUAL((::boost::math::isinf
)(-t
), false);
146 BOOST_CHECK_EQUAL((::boost::math::isnan
)(t
), false);
147 BOOST_CHECK_EQUAL((::boost::math::isnan
)(-t
), false);
148 BOOST_CHECK_EQUAL((::boost::math::isnormal
)(t
), false);
149 BOOST_CHECK_EQUAL((::boost::math::isnormal
)(-t
), false);
150 t
/= -u
; // create minus zero if it exists
151 BOOST_CHECK_EQUAL((::boost::math::fpclassify
)(t
), (int)FP_ZERO
);
152 BOOST_CHECK_EQUAL((::boost::math::fpclassify
)(-t
), (int)FP_ZERO
);
153 BOOST_CHECK_EQUAL((::boost::math::isfinite
)(t
), true);
154 BOOST_CHECK_EQUAL((::boost::math::isfinite
)(-t
), true);
155 BOOST_CHECK_EQUAL((::boost::math::isinf
)(t
), false);
156 BOOST_CHECK_EQUAL((::boost::math::isinf
)(-t
), false);
157 BOOST_CHECK_EQUAL((::boost::math::isnan
)(t
), false);
158 BOOST_CHECK_EQUAL((::boost::math::isnan
)(-t
), false);
159 BOOST_CHECK_EQUAL((::boost::math::isnormal
)(t
), false);
160 BOOST_CHECK_EQUAL((::boost::math::isnormal
)(-t
), false);
162 if(std::numeric_limits
<T
>::has_infinity
)
164 // At least one std::numeric_limits<T>::infinity)() returns zero
165 // (Compaq true64 cxx), hence the check.
166 t
= (std::numeric_limits
<T
>::infinity
)();
167 BOOST_CHECK_EQUAL((::boost::math::fpclassify
)(t
), (int)FP_INFINITE
);
168 BOOST_CHECK_EQUAL((::boost::math::fpclassify
)(-t
), (int)FP_INFINITE
);
169 BOOST_CHECK_EQUAL((::boost::math::isfinite
)(t
), false);
170 BOOST_CHECK_EQUAL((::boost::math::isfinite
)(-t
), false);
171 BOOST_CHECK_EQUAL((::boost::math::isinf
)(t
), true);
172 BOOST_CHECK_EQUAL((::boost::math::isinf
)(-t
), true);
173 BOOST_CHECK_EQUAL((::boost::math::isnan
)(t
), false);
174 BOOST_CHECK_EQUAL((::boost::math::isnan
)(-t
), false);
175 BOOST_CHECK_EQUAL((::boost::math::isnormal
)(t
), false);
176 BOOST_CHECK_EQUAL((::boost::math::isnormal
)(-t
), false);
177 #if !defined(__BORLANDC__) && !(defined(__DECCXX) && !defined(_IEEE_FP))
178 // divide by zero on Borland triggers a C++ exception :-(
179 // divide by zero on Compaq CXX triggers a C style signal :-(
183 BOOST_CHECK_EQUAL((::boost::math::fpclassify
)(t
), (int)FP_INFINITE
);
184 BOOST_CHECK_EQUAL((::boost::math::fpclassify
)(-t
), (int)FP_INFINITE
);
185 BOOST_CHECK_EQUAL((::boost::math::isfinite
)(t
), false);
186 BOOST_CHECK_EQUAL((::boost::math::isfinite
)(-t
), false);
187 BOOST_CHECK_EQUAL((::boost::math::isinf
)(t
), true);
188 BOOST_CHECK_EQUAL((::boost::math::isinf
)(-t
), true);
189 BOOST_CHECK_EQUAL((::boost::math::isnan
)(t
), false);
190 BOOST_CHECK_EQUAL((::boost::math::isnan
)(-t
), false);
191 BOOST_CHECK_EQUAL((::boost::math::isnormal
)(t
), false);
192 BOOST_CHECK_EQUAL((::boost::math::isnormal
)(-t
), false);
195 BOOST_CHECK_EQUAL((::boost::math::fpclassify
)(t
), (int)FP_INFINITE
);
196 BOOST_CHECK_EQUAL((::boost::math::fpclassify
)(-t
), (int)FP_INFINITE
);
197 BOOST_CHECK_EQUAL((::boost::math::isfinite
)(t
), false);
198 BOOST_CHECK_EQUAL((::boost::math::isfinite
)(-t
), false);
199 BOOST_CHECK_EQUAL((::boost::math::isinf
)(t
), true);
200 BOOST_CHECK_EQUAL((::boost::math::isinf
)(-t
), true);
201 BOOST_CHECK_EQUAL((::boost::math::isnan
)(t
), false);
202 BOOST_CHECK_EQUAL((::boost::math::isnan
)(-t
), false);
203 BOOST_CHECK_EQUAL((::boost::math::isnormal
)(t
), false);
204 BOOST_CHECK_EQUAL((::boost::math::isnormal
)(-t
), false);
206 std::cout
<< "Infinities from divide by zero not tested" << std::endl
;
211 std::cout
<< "Infinity not tested" << std::endl
;
215 // Note that Borland throws an exception if we even try to obtain a Nan
216 // by calling std::numeric_limits<T>::quiet_NaN() !!!!!!!
217 if(std::numeric_limits
<T
>::has_quiet_NaN
)
219 t
= std::numeric_limits
<T
>::quiet_NaN();
220 BOOST_CHECK_EQUAL((::boost::math::fpclassify
)(t
), (int)FP_NAN
);
221 BOOST_CHECK_EQUAL((::boost::math::fpclassify
)(-t
), (int)FP_NAN
);
222 BOOST_CHECK_EQUAL((::boost::math::isfinite
)(t
), false);
223 BOOST_CHECK_EQUAL((::boost::math::isfinite
)(-t
), false);
224 BOOST_CHECK_EQUAL((::boost::math::isinf
)(t
), false);
225 BOOST_CHECK_EQUAL((::boost::math::isinf
)(-t
), false);
226 BOOST_CHECK_EQUAL((::boost::math::isnan
)(t
), true);
227 BOOST_CHECK_EQUAL((::boost::math::isnan
)(-t
), true);
228 BOOST_CHECK_EQUAL((::boost::math::isnormal
)(t
), false);
229 BOOST_CHECK_EQUAL((::boost::math::isnormal
)(-t
), false);
233 std::cout
<< "Quiet NaN's not tested" << std::endl
;
235 if(std::numeric_limits
<T
>::has_signaling_NaN
)
237 t
= std::numeric_limits
<T
>::signaling_NaN();
238 BOOST_CHECK_EQUAL((::boost::math::fpclassify
)(t
), (int)FP_NAN
);
239 BOOST_CHECK_EQUAL((::boost::math::fpclassify
)(-t
), (int)FP_NAN
);
240 BOOST_CHECK_EQUAL((::boost::math::isfinite
)(t
), false);
241 BOOST_CHECK_EQUAL((::boost::math::isfinite
)(-t
), false);
242 BOOST_CHECK_EQUAL((::boost::math::isinf
)(t
), false);
243 BOOST_CHECK_EQUAL((::boost::math::isinf
)(-t
), false);
244 BOOST_CHECK_EQUAL((::boost::math::isnan
)(t
), true);
245 BOOST_CHECK_EQUAL((::boost::math::isnan
)(-t
), true);
246 BOOST_CHECK_EQUAL((::boost::math::isnormal
)(t
), false);
247 BOOST_CHECK_EQUAL((::boost::math::isnormal
)(-t
), false);
251 std::cout
<< "Signaling NaN's not tested" << std::endl
;
256 BOOST_AUTO_TEST_CASE( test_main
)
258 BOOST_MATH_CONTROL_FP
;
259 // start by printing some information:
261 std::cout
<< "Platform has isnan macro." << std::endl
;
264 std::cout
<< "Platform has fpclassify macro." << std::endl
;
266 #ifdef BOOST_HAS_FPCLASSIFY
267 std::cout
<< "Platform has FP_NORMAL macro." << std::endl
;
269 std::cout
<< "FP_ZERO: " << (int)FP_ZERO
<< std::endl
;
270 std::cout
<< "FP_NORMAL: " << (int)FP_NORMAL
<< std::endl
;
271 std::cout
<< "FP_INFINITE: " << (int)FP_INFINITE
<< std::endl
;
272 std::cout
<< "FP_NAN: " << (int)FP_NAN
<< std::endl
;
273 std::cout
<< "FP_SUBNORMAL: " << (int)FP_SUBNORMAL
<< std::endl
;
275 // then run the tests:
276 test_classify(float(0), "float");
277 test_classify(double(0), "double");
278 // long double support for fpclassify is considered "core" so we always test it
279 // even when long double support is turned off via BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
280 test_classify((long double)(0), "long double");
281 test_classify((boost::math::concepts::real_concept
)(0), "real_concept");
283 // We should test with integer types as well:
284 test_classify(int(0), "int");
285 test_classify(unsigned(0), "unsigned");
289 Autorun "i:\Boost-sandbox\math_toolkit\libs\math\test\MSVC80\debug\test_classify.exe"
290 Running 1 test case...
298 Testing type long double
299 Testing type real_concept
300 Denormalised forms not tested
302 Quiet NaN's not tested
303 Signaling NaN's not tested
304 Test suite "Test Program" passed with:
305 79 assertions out of 79 passed
306 1 test case out of 1 passed
307 Test case "test_main_caller( argc, argv )" passed with:
308 79 assertions out of 79 passed