float128_example.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. // Copyright John Maddock 2016
  2. // Copyright Christopher Kormanyos 2016.
  3. // Copyright Paul A. Bristow 2016.
  4. // Use, modification and distribution are subject to the
  5. // Boost Software License, Version 1.0. (See accompanying file
  6. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. // Contains Quickbook snippets as C++ comments - do not remove.
  8. // http://gcc.gnu.org/onlinedocs/libquadmath/ GCC Quad-Precision Math Library
  9. // https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format
  10. // https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Dialect-Options.html#C_002b_002b-Dialect-Options GNU 3.5 Options Controlling C++ Dialect
  11. // https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html#C-Dialect-Options 3.4 Options Controlling C Dialect
  12. //[float128_includes_1
  13. #include <boost/cstdfloat.hpp> // For float_64_t, float128_t. Must be first include!
  14. //#include <boost/config.hpp>
  15. #include <boost/multiprecision/float128.hpp>
  16. #include <boost/math/special_functions.hpp> // For gamma function.
  17. #include <boost/math/constants/constants.hpp> // For constants pi, e ...
  18. #include <typeinfo> //
  19. #include <cmath> // for pow function.
  20. // #include <quadmath.h>
  21. // C:\program files\gcc-6-win64\lib\gcc\x86_64-w64-mingw32\6.1.1\include\quadmath.h
  22. // i:\modular-boost\boost\multiprecision\float128.hpp|210| undefined reference to `quadmath_snprintf'.
  23. //] [/float128_includes_1]
  24. //[float128_dialect_1
  25. /*`To make float128 available it is vital to get the dialect and options on the command line correct.
  26. Quad type is forbidden by all the strict C++ standards, so using or adding -std=c++11 and later standards will prevent its use.
  27. so explicitly use -std=gnu++11, 1y, 14, 17, or 1z or ...
  28. For GCC 6.1.1, for example, the default is if no C++ language dialect options are given, is -std=gnu++14.
  29. See https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html#C-Dialect-Options
  30. https://gcc.gnu.org/onlinedocs/gcc/Standards.html#Standards 2 Language Standards Supported by GCC
  31. g++.exe -Wall -fexceptions -std=gnu++17 -g -fext-numeric-literals -fpermissive -lquadmath
  32. -II:\modular-boost\libs\math\include -Ii:\modular-boost -c J:\Cpp\float128\float128\float128_example.cpp -o obj\Debug\float128_example.o
  33. Requires GCC linker option -lquadmath
  34. If this is missing, then get errors like:
  35. \modular-boost\boost\multiprecision\float128.hpp|210|undefined reference to `quadmath_snprintf'|
  36. \modular-boost\boost\multiprecision\float128.hpp|351|undefined reference to `sqrtq'|
  37. Requires compile option
  38. -fext-numeric-literals
  39. If missing, then get errors like:
  40. \modular-boost\libs\math\include/boost/math/cstdfloat/cstdfloat_types.hpp:229:43: error: unable to find numeric literal operator 'operator""Q'
  41. A successful build log was:
  42. g++.exe -Wall -std=c++11 -fexceptions -std=gnu++17 -g -fext-numeric-literals -II:\modular-boost\libs\math\include -Ii:\modular-boost -c J:\Cpp\float128\float128\float128_example.cpp -o obj\Debug\float128_example.o
  43. g++.exe -o bin\Debug\float128.exe obj\Debug\float128_example.o -lquadmath
  44. */
  45. //] [/float128_dialect_1]
  46. void show_versions(std::string title)
  47. {
  48. std::cout << title << std::endl;
  49. std::cout << "Platform: " << BOOST_PLATFORM << '\n'
  50. << "Compiler: " << BOOST_COMPILER << '\n'
  51. << "STL : " << BOOST_STDLIB << '\n'
  52. << "Boost : " << BOOST_VERSION / 100000 << "."
  53. << BOOST_VERSION / 100 % 1000 << "."
  54. << BOOST_VERSION % 100
  55. << std::endl;
  56. #ifdef _MSC_VER
  57. std::cout << "_MSC_FULL_VER = " << _MSC_FULL_VER << std::endl; // VS 2015 190023026
  58. #if defined _M_IX86
  59. std::cout << "(x86)" << std::endl;
  60. #endif
  61. #if defined _M_X64
  62. std::cout << " (x64)" << std::endl;
  63. #endif
  64. #if defined _M_IA64
  65. std::cout << " (Itanium)" << std::endl;
  66. #endif
  67. // Something very wrong if more than one is defined (so show them in all just in case)!
  68. #endif // _MSC_VER
  69. #ifdef __GNUC__
  70. //PRINT_MACRO(__GNUC__);
  71. //PRINT_MACRO(__GNUC_MINOR__);
  72. //PRINT_MACRO(__GNUC_PATCH__);
  73. std::cout << "GCC " << __VERSION__ << std::endl;
  74. //PRINT_MACRO(LONG_MAX);
  75. #endif // __GNUC__
  76. return;
  77. } // void show_version(std::string title)
  78. int main()
  79. {
  80. try
  81. {
  82. //[float128_example_3
  83. // Always use try'n'catch blocks to ensure any error messages are displayed.
  84. //`Ensure that all possibly significant digits (17) including trailing zeros are shown.
  85. std::cout.precision(std::numeric_limits<boost::float64_t>::max_digits10);
  86. std::cout.setf(std::ios::showpoint); // Show all significant trailing zeros.
  87. //] [/ float128_example_3]
  88. #ifdef BOOST_FLOAT128_C
  89. std::cout << "Floating-point type boost::float128_t is available." << std::endl;
  90. std::cout << " std::numeric_limits<boost::float128_t>::digits10 == "
  91. << std::numeric_limits<boost::float128_t>::digits10 << std::endl;
  92. std::cout << " std::numeric_limits<boost::float128_t>::max_digits10 == "
  93. << std::numeric_limits<boost::float128_t>::max_digits10 << std::endl;
  94. #else
  95. std::cout << "Floating-point type boost::float128_t is NOT available." << std::endl;
  96. #endif
  97. show_versions("");
  98. using boost::multiprecision::float128; // Wraps, for example, __float128 or _Quad.
  99. // or
  100. //using namespace boost::multiprecision;
  101. std::cout.precision(std::numeric_limits<float128>::max_digits10); // Show all potentially meaningful digits.
  102. std::cout.setf(std::ios::showpoint); // Show all significant trailing zeros.
  103. // float128 pi0 = boost::math::constants::pi(); // Compile fails - need to specify a type for the constant!
  104. float128 pi1 = boost::math::constants::pi<float128>(); // Returns a constant of type float128.
  105. std::cout << sqrt(pi1) << std::endl; // 1.77245385090551602729816748334114514
  106. float128 pi2 = boost::math::constants::pi<__float128>(); // Constant of type __float128 gets converted to float128 on the assignment.
  107. std::cout << sqrt(pi2) << std::endl; // 1.77245385090551602729816748334114514
  108. // DIY decimal digit literal constant, with suffix Q.
  109. float128 pi3 = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348Q;
  110. std::cout << sqrt(pi3) << std::endl; // 1.77245385090551602729816748334114514
  111. // Compare to ready-rolled sqrt(pi) constant from Boost.Math:
  112. std::cout << boost::math::constants::root_pi<float128>() << std::endl; // 1.77245385090551602729816748334114514
  113. // DIY decimal digit literal constant, without suffix Q, suffering seventeen silent digits loss of precision!
  114. float128 pi4 = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348;
  115. std::cout << sqrt(pi4) << std::endl; // 1.77245385090551599275151910313924857
  116. // float128 variables constructed from a quad-type literal can be declared constexpr if required:
  117. #ifndef BOOST_NO_CXX11_CONSTEXPR
  118. constexpr float128 pi_constexpr = 3.1415926535897932384626433832795028841971693993751058Q;
  119. #endif
  120. std::cout << pi_constexpr << std::endl; // 3.14159265358979323846264338327950280
  121. // But sadly functions like sqrt are not yet available constexpr for float128.
  122. // constexpr float128 root_pi_constexpr = sqrt(pi_constexpr); // Fails - not constexpr (yet).
  123. // constexpr float128 root_pi_constexpr = std::sqrt(pi_constexpr); // Fails - no known conversion for argument 1 from 'const float128'.
  124. // constexpr float128 root_pi_constexpr = sqrt(pi_constexpr); // Call to non-constexpr
  125. // constexpr float128 root_pi_constexpr = boost::math::constants::root_pi(); // Missing type for constant.
  126. // Best current way to get a constexpr is to use a Boost.Math constant if one is available.
  127. constexpr float128 root_pi_constexpr = boost::math::constants::root_pi<float128>();
  128. std::cout << root_pi_constexpr << std::endl; // 1.77245385090551602729816748334114514
  129. // Note that casts within the sqrt call are NOT NEEDED (nor allowed),
  130. // since all the variables are the correct type to begin with.
  131. // std::cout << sqrt<float128>(pi3) << std::endl;
  132. // But note examples of catastrophic (but hard to see) loss of precision below.
  133. // Note also that the library functions, here sqrt, is NOT defined using std::sqrt,
  134. // so that the correct overload is found using Argument Dependent LookUp (ADL).
  135. float128 ee = boost::math::constants::e<float128>();
  136. std::cout << ee << std::endl; // 2.71828182845904523536028747135266231
  137. float128 e1 = exp(1.Q); // Note argument to exp is type float128.
  138. std::cout << e1 << std::endl; // 2.71828182845904523536028747135266231
  139. // Beware - it is all too easy to silently get a much lower precision by mistake.
  140. float128 e1d = exp(1.); // Caution - only double 17 decimal digits precision!
  141. std::cout << e1d << std::endl; // 2.71828182845904509079559829842764884
  142. float128 e1i = exp(1); // Caution int promoted to double so only 17 decimal digits precision!
  143. std::cout << e1i << std::endl; // 2.71828182845904509079559829842764884
  144. float f1 = 1.F;
  145. float128 e1f = exp(f1); // Caution float so only 6 decimal digits precision out of 36!
  146. std::cout << e1f << std::endl; // 2.71828174591064453125000000000000000
  147. // In all these cases you get what you asked for and not what you expected or wanted.
  148. // Casting is essential if you start with a lower precision type.
  149. float128 e1q = exp(static_cast<float128>(f1)); // Full 36 decimal digits precision!
  150. std::cout << e1q << std::endl; // 2.71828182845904523536028747135266231
  151. float128 e1qc = exp((float128)f1); // Full 36 decimal digits precision!
  152. std::cout << e1qc << std::endl; // 2.71828182845904523536028747135266231
  153. float128 e1qcc = exp(float128(f1)); // Full 36 decimal digits precision!
  154. std::cout << e1qcc << std::endl; // 2.71828182845904523536028747135266231
  155. //float128 e1q = exp<float128>(1.); // Compile fails.
  156. // std::cout << e1q << std::endl; //
  157. // http://en.cppreference.com/w/cpp/language/typeid
  158. // The name()is implementation-dependent mangled, and may not be able to be output.
  159. // The example showing output using one of the implementations where type_info::name prints full type names;
  160. // filter through c++filt -t if using gcc or similar.
  161. //[float128_type_info
  162. const std::type_info& tifu128 = typeid(__float128); // OK.
  163. //std::cout << tifu128.name() << std::endl; // On GCC, aborts (because not printable string).
  164. //std::cout << typeid(__float128).name() << std::endl; // Aborts -
  165. // string name cannot be output.
  166. const std::type_info& tif128 = typeid(float128); // OK.
  167. std::cout << tif128.name() << std::endl; // OK.
  168. std::cout << typeid(float128).name() << std::endl; // OK.
  169. const std::type_info& tpi = typeid(pi1); // OK using GCC 6.1.1.
  170. // (from GCC 5 according to http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43622)
  171. std::cout << tpi.name() << std::endl; // OK, Output implementation-dependent mangled name:
  172. // N5boost14multiprecision6numberINS0_8backends16float128_backendELNS0_26expression_template_optionE0EEE
  173. //] [/float128_type_info]
  174. }
  175. catch (std::exception ex)
  176. { // Display details about why any exceptions are thrown.
  177. std::cout << "Thrown exception " << ex.what() << std::endl;
  178. }
  179. } // int main()
  180. /*
  181. [float128_output
  182. -std=c++11 or -std=c++17 don't work
  183. Floating-point type boost::float128_t is NOT available.
  184. Platform: Win32
  185. Compiler: GNU C++ version 6.1.1 20160609
  186. STL : GNU libstdc++ version 20160609
  187. Boost : 1.62.0
  188. GCC 6.1.1 20160609
  189. Added -fext-numeric-literals to
  190. -std=gnu++11 -fext-numeric-literals -lquadmath
  191. Floating-point type boost::float128_t is available.
  192. std::numeric_limits<boost::float128_t>::digits10 == 33
  193. std::numeric_limits<boost::float128_t>::max_digits10 == 36
  194. Platform: Win32
  195. Compiler: GNU C++ version 6.1.1 20160609
  196. STL : GNU libstdc++ version 20160609
  197. Boost : 1.62.0
  198. GCC 6.1.1 20160609
  199. 1.77245385090551602729816748334114514
  200. 1.77245385090551602729816748334114514
  201. 1.77245385090551602729816748334114514
  202. 1.77245385090551602729816748334114514
  203. N5boost14multiprecision6numberINS0_8backends16float128_backendELNS0_26expression_template_optionE0EEE
  204. N5boost14multiprecision6numberINS0_8backends16float128_backendELNS0_26expression_template_optionE0EEE
  205. N5boost14multiprecision6numberINS0_8backends16float128_backendELNS0_26expression_template_optionE0EEE
  206. Process returned 0 (0x0) execution time : 0.033 s
  207. Press any key to continue.
  208. //] [/float128_output]
  209. */