test_classify.cpp 13 KB

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