nonfinite_signaling_NaN.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  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
  6. /*!
  7. \file
  8. \brief Tests of nonfinite signaling NaN loopback.
  9. \detail nonfinite signaling NaN
  10. test outputs using nonfinite facets
  11. (output and input) and reads back in, and checks if loopback OK.
  12. Not expected to work on all platforms (if any). But shows that on MSVC,
  13. this legacy locale can ensure a consistent quiet NaN input from representations
  14. "1.#QNAN", "1.#SNAN" and "1.#IND"
  15. */
  16. #ifdef _MSC_VER
  17. # pragma warning(disable : 4702)
  18. #endif
  19. #include <boost/math/special_functions/nonfinite_num_facets.hpp>
  20. using boost::math::nonfinite_num_get;
  21. using boost::math::nonfinite_num_put;
  22. #include <iostream>
  23. using std::cout;
  24. using std::endl;
  25. #include <locale>
  26. using std::locale;
  27. #include <string>
  28. using std::string;
  29. #include <sstream>
  30. using std::stringstream;
  31. using std::istringstream;
  32. #include <limits>
  33. using std::numeric_limits;
  34. int main()
  35. {
  36. if((std::numeric_limits<double>::has_infinity == false) || (std::numeric_limits<double>::infinity() == 0))
  37. {
  38. std::cout << "Infinity not supported on this platform." << std::endl;
  39. return 0;
  40. }
  41. if((std::numeric_limits<double>::has_quiet_NaN == false) || (std::numeric_limits<double>::quiet_NaN() == 0))
  42. {
  43. std::cout << "NaN not supported on this platform." << std::endl;
  44. return 0;
  45. }
  46. locale default_locale; // Current global locale.
  47. // Try to use the default locale first.
  48. // On MSVC this doesn't work.
  49. { // Try Quiet NaN
  50. stringstream ss; // Both input and output.
  51. ss.imbue(default_locale); // Redundant, of course.
  52. string infs;
  53. if(numeric_limits<double>::has_quiet_NaN)
  54. { // Make sure quiet NaN is specialised for type double.
  55. double qnan = numeric_limits<double>::quiet_NaN();
  56. ss << qnan; // Output quiet_NaN.
  57. infs = ss.str(); //
  58. }
  59. else
  60. { // Need to provide a suitable string for quiet NaN.
  61. infs = "1.#QNAN";
  62. ss << infs;
  63. }
  64. double r;
  65. ss >> r; // Read back in.
  66. cout << "quiet_NaN output was " << infs << endl; // "1.#QNAN"
  67. cout << "quiet_NaN input was " << r << endl; // "1"
  68. }
  69. #if (!defined __BORLANDC__ && !defined __CODEGEARC__)
  70. // These compilers trap when trying to create a signaling_NaN!
  71. { // Try Signaling NaN
  72. stringstream ss; // Both input and output.
  73. ss.imbue(default_locale); // Redundant, of course.
  74. string infs;
  75. if(numeric_limits<double>::has_signaling_NaN)
  76. { // Make sure signaling NaN is specialised for type double.
  77. double qnan = numeric_limits<double>::signaling_NaN();
  78. ss << qnan; // Output signaling_NaN.
  79. infs = ss.str(); //
  80. }
  81. else
  82. { // Need to provide a suitable string for signaling NaN.
  83. infs = "1.#SNAN";
  84. ss << infs;
  85. }
  86. double r;
  87. ss >> r; // Read back in.
  88. cout << "signaling_NaN output was " << infs << endl; // "1.#QNAN" (or "1.#SNAN"?)
  89. cout << "signaling_NaN input was " << r << endl; // "1"
  90. }
  91. #endif // Not Borland or CodeGear.
  92. // Create legacy_locale and store the nonfinite_num_get facet (with legacy flag) in it.
  93. locale legacy_locale(default_locale, new nonfinite_num_get<char>(boost::math::legacy));
  94. // Note that the legacy flag has no effect on the nonfinite_num_put output facet.
  95. cout << "Use legacy locale." << endl;
  96. { // Try infinity.
  97. stringstream ss; // Both input and output.
  98. ss.imbue(legacy_locale);
  99. string infs;
  100. if(numeric_limits<double>::has_infinity)
  101. { // Make sure infinity is specialised for type double.
  102. double inf = numeric_limits<double>::infinity();
  103. ss << inf; // Output infinity.
  104. infs = ss.str(); //
  105. }
  106. else
  107. { // Need to provide a suitable string for infinity.
  108. infs = "1.#INF";
  109. ss << infs;
  110. }
  111. double r;
  112. ss >> r; // Read back in.
  113. cout << "infinity output was " << infs << endl; // "1.#INF"
  114. cout << "infinity input was " << r << endl; // "1.#INF"
  115. }
  116. { // Try input of "1.#SNAN".
  117. //double inf = numeric_limits<double>::signaling_NaN(); // Assigns "1.#QNAN" on MSVC.
  118. // So must use explicit string "1.#SNAN" instead.
  119. stringstream ss; // Both input and output.
  120. ss.imbue(legacy_locale);
  121. string s = "1.#SNAN";
  122. ss << s; // Write out.
  123. double r;
  124. ss >> r; // Read back in.
  125. cout << "SNAN output was " << s << endl; // "1.#SNAN"
  126. cout << "SNAN input was " << r << endl; // "1.#QNAN"
  127. }
  128. { // Try input of "1.#IND" .
  129. stringstream ss; // Both input and output.
  130. ss.imbue(legacy_locale);
  131. string s = "1.#IND";
  132. ss << s; // Write out.
  133. double r;
  134. ss >> r; // Read back in.
  135. cout << "IND output was " << s << endl; // "1.#IND"
  136. cout << "IND input was " << r << endl; // "1.#QNAN"
  137. }
  138. } // int main()
  139. /*
  140. Output:
  141. nonfinite_signaling_NaN.vcxproj -> J:\Cpp\fp_facet\fp_facet\Debug\nonfinite_signaling_NaN.exe
  142. quiet_NaN output was 1.#QNAN
  143. quiet_NaN input was 1
  144. signaling_NaN output was 1.#QNAN
  145. signaling_NaN input was 1
  146. Use legacy locale.
  147. infinity output was 1.#INF
  148. infinity input was 1.#INF
  149. SNAN output was 1.#SNAN
  150. SNAN input was 1.#QNAN
  151. IND output was 1.#IND
  152. IND input was 1.#QNAN
  153. */