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)
8 #define _SCL_SECURE_NO_WARNINGS
13 #include <boost/limits.hpp>
14 #include <boost/math/special_functions/fpclassify.hpp>
17 #if !defined(TEST_MPF_50) && !defined(TEST_MPF) && !defined(TEST_BACKEND) && !defined(TEST_MPZ) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR) && !defined(TEST_MPFR_50) && !defined(TEST_MPQ) && !defined(TEST_MPFI_50) && !defined(TEST_FLOAT128) && !defined(TEST_CPP_BIN_FLOAT)
22 #define TEST_CPP_DEC_FLOAT
24 #define TEST_CPP_BIN_FLOAT
27 #pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!")
30 #pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!"
35 #if defined(TEST_MPF_50)
36 #include <boost/multiprecision/gmp.hpp>
39 #include <boost/multiprecision/mpfr.hpp>
42 #include <boost/multiprecision/mpfi.hpp>
45 #include <boost/multiprecision/concepts/mp_number_archetypes.hpp>
47 #ifdef TEST_CPP_DEC_FLOAT
48 #include <boost/multiprecision/cpp_dec_float.hpp>
51 #include <boost/multiprecision/float128.hpp>
53 #ifdef TEST_CPP_BIN_FLOAT
54 #include <boost/multiprecision/cpp_bin_float.hpp>
58 #pragma warning(disable : 4127) // conditional expression is constant
61 const char* method_name(const boost::math::detail::native_tag&)
66 const char* method_name(const boost::math::detail::generic_tag<true>&)
68 return "Generic (with numeric limits)";
71 const char* method_name(const boost::math::detail::generic_tag<false>&)
73 return "Generic (without numeric limits)";
76 const char* method_name(const boost::math::detail::ieee_tag&)
81 const char* method_name(const boost::math::detail::ieee_copy_all_bits_tag&)
83 return "IEEE std, copy all bits";
86 const char* method_name(const boost::math::detail::ieee_copy_leading_bits_tag&)
88 return "IEEE std, copy leading bits";
96 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_NORMAL);
97 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_NORMAL);
98 BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true);
99 BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true);
100 BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false);
101 BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false);
102 BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false);
103 BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false);
104 BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), true);
105 BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), true);
106 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (::boost::math::fpclassify)(t + 0));
107 if (std::numeric_limits<T>::is_specialized)
109 t = (std::numeric_limits<T>::max)();
110 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_NORMAL);
111 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_NORMAL);
112 BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true);
113 BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true);
114 BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false);
115 BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false);
116 BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false);
117 BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false);
118 BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), true);
119 BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), true);
120 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (::boost::math::fpclassify)(t + 0));
121 t = (std::numeric_limits<T>::min)();
122 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_NORMAL);
123 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_NORMAL);
124 BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true);
125 BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true);
126 BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false);
127 BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false);
128 BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false);
129 BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false);
130 BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), true);
131 BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), true);
132 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (::boost::math::fpclassify)(t + 0));
134 if (std::numeric_limits<T>::has_denorm)
136 t = (std::numeric_limits<T>::min)();
140 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_SUBNORMAL);
141 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_SUBNORMAL);
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 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (::boost::math::fpclassify)(t + 0));
152 t = std::numeric_limits<T>::denorm_min();
153 if ((t != 0) && (t < (std::numeric_limits<T>::min)()))
155 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_SUBNORMAL);
156 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_SUBNORMAL);
157 BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true);
158 BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true);
159 BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false);
160 BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false);
161 BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false);
162 BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false);
163 BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false);
164 BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false);
165 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (::boost::math::fpclassify)(t + 0));
170 std::cout << "Denormalised forms not tested" << std::endl;
173 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_ZERO);
174 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_ZERO);
175 BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true);
176 BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true);
177 BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false);
178 BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false);
179 BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false);
180 BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false);
181 BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false);
182 BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false);
183 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (::boost::math::fpclassify)(t + 0));
184 t /= -u; // create minus zero if it exists
185 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_ZERO);
186 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_ZERO);
187 BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), true);
188 BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), true);
189 BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false);
190 BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false);
191 BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false);
192 BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false);
193 BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false);
194 BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false);
195 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (::boost::math::fpclassify)(t + 0));
197 if (std::numeric_limits<T>::has_infinity)
199 // At least one std::numeric_limits<T>::infinity)() returns zero
200 // (Compaq true64 cxx), hence the check.
201 t = (std::numeric_limits<T>::infinity)();
202 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_INFINITE);
203 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_INFINITE);
204 BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), false);
205 BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), false);
206 BOOST_CHECK_EQUAL((::boost::math::isinf)(t), true);
207 BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), true);
208 BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false);
209 BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false);
210 BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false);
211 BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false);
212 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (::boost::math::fpclassify)(t + 0));
213 #if !defined(__BORLANDC__) && !(defined(__DECCXX) && !defined(_IEEE_FP))
214 // divide by zero on Borland triggers a C++ exception :-(
215 // divide by zero on Compaq CXX triggers a C style signal :-(
219 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_INFINITE);
220 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_INFINITE);
221 BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), false);
222 BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), false);
223 BOOST_CHECK_EQUAL((::boost::math::isinf)(t), true);
224 BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), true);
225 BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false);
226 BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false);
227 BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false);
228 BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false);
229 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (::boost::math::fpclassify)(t + 0));
232 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_INFINITE);
233 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_INFINITE);
234 BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), false);
235 BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), false);
236 BOOST_CHECK_EQUAL((::boost::math::isinf)(t), true);
237 BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), true);
238 BOOST_CHECK_EQUAL((::boost::math::isnan)(t), false);
239 BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), false);
240 BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false);
241 BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false);
242 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (::boost::math::fpclassify)(t + 0));
244 std::cout << "Infinities from divide by zero not tested" << std::endl;
249 std::cout << "Infinity not tested" << std::endl;
253 // Note that Borland throws an exception if we even try to obtain a Nan
254 // by calling std::numeric_limits<T>::quiet_NaN() !!!!!!!
255 if (std::numeric_limits<T>::has_quiet_NaN)
257 t = std::numeric_limits<T>::quiet_NaN();
258 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_NAN);
259 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_NAN);
260 BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), false);
261 BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), false);
262 BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false);
263 BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false);
264 BOOST_CHECK_EQUAL((::boost::math::isnan)(t), true);
265 BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), true);
266 BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false);
267 BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false);
271 std::cout << "Quiet NaN's not tested" << std::endl;
273 if (std::numeric_limits<T>::has_signaling_NaN)
275 t = std::numeric_limits<T>::signaling_NaN();
276 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(t), (int)FP_NAN);
277 BOOST_CHECK_EQUAL((::boost::math::fpclassify)(-t), (int)FP_NAN);
278 BOOST_CHECK_EQUAL((::boost::math::isfinite)(t), false);
279 BOOST_CHECK_EQUAL((::boost::math::isfinite)(-t), false);
280 BOOST_CHECK_EQUAL((::boost::math::isinf)(t), false);
281 BOOST_CHECK_EQUAL((::boost::math::isinf)(-t), false);
282 BOOST_CHECK_EQUAL((::boost::math::isnan)(t), true);
283 BOOST_CHECK_EQUAL((::boost::math::isnan)(-t), true);
284 BOOST_CHECK_EQUAL((::boost::math::isnormal)(t), false);
285 BOOST_CHECK_EQUAL((::boost::math::isnormal)(-t), false);
289 std::cout << "Signaling NaN's not tested" << std::endl;
293 // Try sign manipulation functions as well:
295 T one(1), minus_one(-1), zero(0);
296 BOOST_CHECK((::boost::math::sign)(one) > 0);
297 BOOST_CHECK((::boost::math::sign)(minus_one) < 0);
298 BOOST_CHECK((::boost::math::sign)(zero) == 0);
299 BOOST_CHECK((::boost::math::sign)(one + 2) > 0);
300 BOOST_CHECK((::boost::math::sign)(minus_one - 30) < 0);
301 BOOST_CHECK((::boost::math::sign)(-zero) == 0);
303 BOOST_CHECK((::boost::math::signbit)(one) == 0);
304 BOOST_CHECK((::boost::math::signbit)(minus_one) > 0);
305 BOOST_CHECK((::boost::math::signbit)(zero) == 0);
306 BOOST_CHECK((::boost::math::signbit)(one + 2) == 0);
307 BOOST_CHECK((::boost::math::signbit)(minus_one - 30) > 0);
308 //BOOST_CHECK((::boost::math::signbit)(-zero) == 0);
310 BOOST_CHECK((::boost::math::signbit)(boost::math::changesign(one)) > 0);
311 BOOST_CHECK_EQUAL(boost::math::changesign(one), minus_one);
312 BOOST_CHECK((::boost::math::signbit)(boost::math::changesign(minus_one)) == 0);
313 BOOST_CHECK_EQUAL(boost::math::changesign(minus_one), one);
314 //BOOST_CHECK((::boost::math::signbit)(zero) == 0);
315 BOOST_CHECK((::boost::math::signbit)(boost::math::changesign(one + 2)) > 0);
316 BOOST_CHECK_EQUAL(boost::math::changesign(one + 2), -3);
317 BOOST_CHECK((::boost::math::signbit)(boost::math::changesign(minus_one - 30)) == 0);
318 BOOST_CHECK_EQUAL(boost::math::changesign(minus_one - 30), 31);
319 //BOOST_CHECK((::boost::math::signbit)(-zero) == 0);
321 BOOST_CHECK((::boost::math::signbit)(boost::math::copysign(one, one)) == 0);
322 BOOST_CHECK_EQUAL(boost::math::copysign(one, one), one);
323 BOOST_CHECK((::boost::math::signbit)(boost::math::copysign(one, minus_one)) > 0);
324 BOOST_CHECK_EQUAL(boost::math::copysign(one, minus_one), minus_one);
325 BOOST_CHECK((::boost::math::signbit)(boost::math::copysign(minus_one, one)) == 0);
326 BOOST_CHECK_EQUAL(boost::math::copysign(minus_one, one), one);
327 BOOST_CHECK((::boost::math::signbit)(boost::math::copysign(minus_one, minus_one)) > 0);
328 BOOST_CHECK_EQUAL(boost::math::copysign(minus_one, minus_one), minus_one);
329 BOOST_CHECK((::boost::math::signbit)(boost::math::copysign(one + 1, one + 2)) == 0);
330 BOOST_CHECK_EQUAL(boost::math::copysign(one + 1, one + 2), 2);
331 BOOST_CHECK((::boost::math::signbit)(boost::math::copysign(one + 30, minus_one - 20)) > 0);
332 BOOST_CHECK_EQUAL(boost::math::copysign(one + 30, minus_one - 20), -31);
333 BOOST_CHECK((::boost::math::signbit)(boost::math::copysign(minus_one + 2, one + 2)) == 0);
334 BOOST_CHECK_EQUAL(boost::math::copysign(minus_one - 2, one + 2), 3);
335 BOOST_CHECK((::boost::math::signbit)(boost::math::copysign(minus_one - 20, minus_one - 30)) > 0);
336 BOOST_CHECK_EQUAL(boost::math::copysign(minus_one - 20, minus_one - 30), -21);
338 // Things involving signed zero, need to detect it first:
339 T neg_zero_test = -(std::numeric_limits<T>::min)();
340 neg_zero_test /= (std::numeric_limits<T>::max)();
341 if (std::numeric_limits<T>::has_infinity && (one / neg_zero_test < 0))
344 // Note that testing this with mpfi is in the "too difficult" drawer at present.
345 std::cout << neg_zero_test << std::endl;
346 BOOST_CHECK_EQUAL(neg_zero_test, 0);
347 BOOST_CHECK((::boost::math::sign)(neg_zero_test) == 0);
348 // We got -INF, so we have a signed zero:
349 BOOST_CHECK((::boost::math::signbit)(neg_zero_test) > 0);
350 BOOST_CHECK((::boost::math::signbit)(boost::math::changesign(zero)) > 0);
351 BOOST_CHECK_EQUAL(boost::math::changesign(zero), 0);
352 BOOST_CHECK((::boost::math::signbit)(boost::math::changesign(neg_zero_test)) == 0);
353 BOOST_CHECK_EQUAL(boost::math::changesign(neg_zero_test), 0);
354 BOOST_CHECK((::boost::math::signbit)(boost::math::copysign(zero, one)) == 0);
355 BOOST_CHECK_EQUAL(boost::math::copysign(zero, one), 0);
356 BOOST_CHECK((::boost::math::signbit)(boost::math::copysign(zero, minus_one)) > 0);
357 BOOST_CHECK_EQUAL(boost::math::copysign(zero, minus_one), 0);
358 BOOST_CHECK((::boost::math::signbit)(boost::math::copysign(neg_zero_test, one)) == 0);
359 BOOST_CHECK_EQUAL(boost::math::copysign(neg_zero_test, one), 0);
360 BOOST_CHECK((::boost::math::signbit)(boost::math::copysign(neg_zero_test, minus_one)) > 0);
361 BOOST_CHECK_EQUAL(boost::math::copysign(neg_zero_test, minus_one), 0);
368 BOOST_MATH_CONTROL_FP;
369 // start by printing some information:
371 std::cout << "Platform has isnan macro." << std::endl;
374 std::cout << "Platform has fpclassify macro." << std::endl;
376 #ifdef BOOST_HAS_FPCLASSIFY
377 std::cout << "Platform has FP_NORMAL macro." << std::endl;
379 std::cout << "FP_ZERO: " << (int)FP_ZERO << std::endl;
380 std::cout << "FP_NORMAL: " << (int)FP_NORMAL << std::endl;
381 std::cout << "FP_INFINITE: " << (int)FP_INFINITE << std::endl;
382 std::cout << "FP_NAN: " << (int)FP_NAN << std::endl;
383 std::cout << "FP_SUBNORMAL: " << (int)FP_SUBNORMAL << std::endl;
386 test<boost::multiprecision::mpf_float_50>();
387 test<boost::multiprecision::mpf_float_100>();
390 test<boost::multiprecision::mpfr_float_50>();
391 test<boost::multiprecision::mpfr_float_100>();
394 test<boost::multiprecision::mpfi_float_50>();
395 test<boost::multiprecision::mpfi_float_100>();
397 #ifdef TEST_CPP_DEC_FLOAT
398 test<boost::multiprecision::cpp_dec_float_50>();
399 test<boost::multiprecision::cpp_dec_float_100>();
402 test<boost::multiprecision::number<boost::multiprecision::concepts::number_backend_float_architype> >();
405 test<boost::multiprecision::float128>();
407 #ifdef TEST_CPP_BIN_FLOAT
408 test<boost::multiprecision::cpp_bin_float_50>();
409 test<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<35, boost::multiprecision::digit_base_10, std::allocator<char>, boost::long_long_type> > >();
411 return boost::report_errors();