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