test_basic_nonfinite.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. // Distributed under the Boost Software License, Version 1.0.
  2. // (See accompanying file LICENSE_1_0.txt
  3. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  4. // Copyright (c) 2006 Johan Rade
  5. // Copyright (c) 2011 Paul A. Bristow comments
  6. // Copyright (c) 2011 John Maddock
  7. /*!
  8. \file
  9. \brief Basic tests of the nonfinite num facets.
  10. \detail If has_infinity and has_nan, then
  11. basic_test outputs using nonfinite_num_put facet
  12. and reads back in using nonfinite_num_ facet,
  13. and checks loopback OK.
  14. Also checks that output of infinity, -infinity and NaN are as expected,
  15. using C99 specification "nan -nan nan -nan" and "inf -inf".
  16. Also includes a few combinations of display manipulators
  17. (left, right, internal, showpos)
  18. and checks that can input C99 infinity and NaN too.
  19. */
  20. #ifdef _MSC_VER
  21. # pragma warning(disable : 4702) // Unreachable code.
  22. #endif
  23. #include <iomanip>
  24. #include <locale>
  25. #include <sstream>
  26. #define BOOST_TEST_MAIN
  27. #include <boost/test/unit_test.hpp>
  28. #include "almost_equal.ipp"
  29. #include "s_.ipp"
  30. #include <boost/math/special_functions/nonfinite_num_facets.hpp>
  31. namespace
  32. { // The anonymous namespace resolves ambiguities on
  33. // platforms with fpclassify etc functions at global scope.
  34. using namespace boost::math;
  35. using boost::math::signbit;
  36. using boost::math::changesign;
  37. using boost::math::isnan;
  38. //------------------------------------------------------------------------------
  39. void basic_test_finite();
  40. void basic_test_inf();
  41. void basic_test_nan();
  42. void basic_test_format();
  43. BOOST_AUTO_TEST_CASE(basic_test)
  44. {
  45. basic_test_finite();
  46. basic_test_inf();
  47. basic_test_nan();
  48. basic_test_format();
  49. }
  50. //------------------------------------------------------------------------------
  51. template<class CharType, class ValType> void basic_test_finite_impl();
  52. void basic_test_finite()
  53. {
  54. basic_test_finite_impl<char, float>();
  55. basic_test_finite_impl<char, double>();
  56. basic_test_finite_impl<char, long double>();
  57. basic_test_finite_impl<wchar_t, float>();
  58. basic_test_finite_impl<wchar_t, double>();
  59. basic_test_finite_impl<wchar_t, long double>();
  60. }
  61. template<class CharType, class ValType> void basic_test_finite_impl()
  62. {
  63. if((std::numeric_limits<ValType>::has_infinity == 0) || (std::numeric_limits<ValType>::infinity() == 0))
  64. return;
  65. std::locale old_locale;
  66. std::locale tmp_locale(old_locale, new nonfinite_num_put<CharType>);
  67. std::locale new_locale(tmp_locale, new nonfinite_num_get<CharType>);
  68. std::basic_stringstream<CharType> ss;
  69. ss.imbue(new_locale);
  70. ValType a1 = (ValType)1.2;
  71. ValType a2 = (ValType)-3.5;
  72. ValType a3 = (std::numeric_limits<ValType>::max)();
  73. ValType a4 = -(std::numeric_limits<ValType>::max)();
  74. ss << a1 << ' ' << a2 << ' ' << a3 << ' ' << a4;
  75. ValType b1, b2, b3, b4;
  76. ss >> b1 >> b2 >> b3 >> b4;
  77. BOOST_CHECK(almost_equal(b1, a1));
  78. BOOST_CHECK(almost_equal(b2, a2));
  79. BOOST_CHECK(almost_equal(b3, a3));
  80. BOOST_CHECK(almost_equal(b4, a4));
  81. BOOST_CHECK(b3 != std::numeric_limits<ValType>::infinity());
  82. BOOST_CHECK(b4 != -std::numeric_limits<ValType>::infinity());
  83. BOOST_CHECK(ss.rdstate() == std::ios_base::eofbit);
  84. ss.clear();
  85. ss.str(S_(""));
  86. ss << "++5";
  87. ValType b5;
  88. ss >> b5;
  89. BOOST_CHECK(ss.rdstate() == std::ios_base::failbit);
  90. }
  91. //------------------------------------------------------------------------------
  92. template<class CharType, class ValType> void basic_test_inf_impl();
  93. void basic_test_inf()
  94. {
  95. basic_test_inf_impl<char, float>();
  96. basic_test_inf_impl<char, double>();
  97. basic_test_inf_impl<char, long double>();
  98. basic_test_inf_impl<wchar_t, float>();
  99. basic_test_inf_impl<wchar_t, double>();
  100. basic_test_inf_impl<wchar_t, long double>();
  101. }
  102. template<class CharType, class ValType> void basic_test_inf_impl()
  103. {
  104. if((std::numeric_limits<ValType>::has_infinity == 0) || (std::numeric_limits<ValType>::infinity() == 0))
  105. return;
  106. std::locale old_locale;
  107. std::locale tmp_locale(old_locale, new nonfinite_num_put<CharType>);
  108. std::locale new_locale(tmp_locale, new nonfinite_num_get<CharType>);
  109. std::basic_stringstream<CharType> ss;
  110. ss.imbue(new_locale);
  111. ValType a1 = std::numeric_limits<ValType>::infinity();
  112. ValType a2 = -std::numeric_limits<ValType>::infinity();
  113. BOOST_CHECK((boost::math::isinf)(a1));
  114. BOOST_CHECK((boost::math::isinf)(a2));
  115. ss << a1 << ' ' << a2;
  116. std::basic_string<CharType> s = S_("inf -inf");
  117. BOOST_CHECK(ss.str() == s);
  118. ss << " infinity"; // Alternative C99 representation of infinity.
  119. ValType b1, b2, b3;
  120. ss >> b1;
  121. ss >> b2;
  122. ss >> b3;
  123. BOOST_CHECK(b1 == a1);
  124. BOOST_CHECK(b2 == a2);
  125. BOOST_CHECK(b3 == std::numeric_limits<ValType>::infinity());
  126. BOOST_CHECK(ss.rdstate() == std::ios_base::eofbit);
  127. }
  128. //------------------------------------------------------------------------------
  129. template<class CharType, class ValType> void basic_test_nan_impl();
  130. void basic_test_nan()
  131. {
  132. basic_test_nan_impl<char, float>();
  133. basic_test_nan_impl<char, double>();
  134. basic_test_nan_impl<char, long double>();
  135. basic_test_nan_impl<wchar_t, float>();
  136. basic_test_nan_impl<wchar_t, double>();
  137. basic_test_nan_impl<wchar_t, long double>();
  138. }
  139. template<class CharType, class ValType> void basic_test_nan_impl()
  140. {
  141. if((std::numeric_limits<ValType>::has_quiet_NaN == 0) || (std::numeric_limits<ValType>::quiet_NaN() == 0))
  142. return;
  143. std::locale old_locale;
  144. std::locale tmp_locale(old_locale, new nonfinite_num_put<CharType>);
  145. std::locale new_locale(tmp_locale, new nonfinite_num_get<CharType>);
  146. std::basic_stringstream<CharType> ss;
  147. ss.imbue(new_locale);
  148. ValType a1 = std::numeric_limits<ValType>::quiet_NaN();
  149. ValType a2 = (boost::math::changesign)(std::numeric_limits<ValType>::quiet_NaN());
  150. ValType a3 = std::numeric_limits<ValType>::signaling_NaN();
  151. ValType a4 = (boost::math::changesign)(std::numeric_limits<ValType>::signaling_NaN());
  152. ss << a1 << ' ' << a2 << ' ' << a3 << ' ' << a4;
  153. BOOST_CHECK((boost::math::isnan)(a1) && (boost::math::isnan)(a2) && (boost::math::isnan)(a3) && (boost::math::isnan)(a4));
  154. std::basic_string<CharType> s = S_("nan -nan nan -nan");
  155. BOOST_CHECK(ss.str() == s);
  156. // Alternative C99 representation of NaN.
  157. ss << " nan(foo)";
  158. ValType b1, b2, b3, b4, b5;
  159. ss >> b1 >> b2 >> b3 >> b4 >> b5;
  160. BOOST_CHECK((isnan)(b1));
  161. BOOST_CHECK((isnan)(b2));
  162. BOOST_CHECK((isnan)(b3));
  163. BOOST_CHECK((isnan)(b4));
  164. BOOST_CHECK((isnan)(b5));
  165. BOOST_CHECK(!(signbit)(b1));
  166. BOOST_CHECK((signbit)(b2));
  167. BOOST_CHECK(!(signbit)(b3));
  168. BOOST_CHECK((signbit)(b4));
  169. BOOST_CHECK(!(signbit)(b5));
  170. BOOST_CHECK(ss.rdstate() == std::ios_base::eofbit);
  171. }
  172. //------------------------------------------------------------------------------
  173. template<class CharType, class ValType> void basic_test_format_impl();
  174. void basic_test_format()
  175. {
  176. basic_test_format_impl<char, float>();
  177. basic_test_format_impl<char, double>();
  178. basic_test_format_impl<char, long double>();
  179. basic_test_format_impl<wchar_t, float>();
  180. basic_test_format_impl<wchar_t, double>();
  181. basic_test_format_impl<wchar_t, long double>();
  182. }
  183. template<class CharType, class ValType> void basic_test_format_impl()
  184. {
  185. if((std::numeric_limits<ValType>::has_infinity == 0) || (std::numeric_limits<ValType>::infinity() == 0))
  186. return;
  187. std::locale old_locale;
  188. std::locale tmp_locale(old_locale, new nonfinite_num_put<CharType>);
  189. std::locale new_locale(tmp_locale, new nonfinite_num_get<CharType>);
  190. std::basic_stringstream<CharType> ss;
  191. ss.imbue(new_locale);
  192. ValType a = std::numeric_limits<ValType>::infinity();
  193. BOOST_CHECK((boost::math::isinf)(a));
  194. ss << std::setw(6) << a; // Expect right justified in field of six, so 3 leading spaces.
  195. ss << '|';
  196. ss << std::setw(2) << a; // Too narrow for "inf", but should still be "inf".
  197. ss << '|';
  198. ss << std::left << std::setw(5) << a; // 5 - 3 leaves two trailing spaces.
  199. ss << '|';
  200. ss << std::showpos << std::internal << std::setw(7) << a; // 3 internal spaces between + and "inf".
  201. ss << '|';
  202. ss << std::uppercase << std::right << std::setw(6) << a; // still showpos, so "space, space, +INF".
  203. std::basic_string<CharType> s = S_(" inf|inf|inf |+ inf| +INF");
  204. BOOST_CHECK(ss.str() == s);
  205. }
  206. //------------------------------------------------------------------------------
  207. } // anonymous namespace