mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-10-30 12:30:23 -04:00 
			
		
		
		
	
		
			
	
	
		
			552 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			552 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|  | [/cstdfloat.qbk  Specified-width floating-point typedefs] | ||
|  | 
 | ||
|  | [def __IEEE754  [@http://en.wikipedia.org/wiki/IEEE_floating_point IEEE_floating_point]] | ||
|  | [def __N3626  [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3626.pdf N3626]] | ||
|  | [def __N1703 [@http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1703.pdf N1703]] | ||
|  | 
 | ||
|  | [import ../../example/cstdfloat_example.cpp] | ||
|  | [import ../../example/normal_tables.cpp] | ||
|  | [/Removed as unhelpful for C++ users, but might have use as a check that quadmath is available and linked OK.] | ||
|  | [/import ../../example/quadmath_snprintf.c] | ||
|  | 
 | ||
|  | [section:specified_typedefs Overview] | ||
|  | 
 | ||
|  | The header `<boost/cstdfloat.hpp>` provides [*optional] | ||
|  | standardized floating-point `typedef`s having [*specified widths]. | ||
|  | These are useful for writing portable code because they | ||
|  | should behave identically on all platforms. | ||
|  | These `typedef`s are the floating-point analog of specified-width integers in `<cstdint>` and `stdint.h`. | ||
|  | 
 | ||
|  | The `typedef`s are based on __N3626 | ||
|  | proposed for a new C++14 standard header `<cstdfloat>` and | ||
|  | __N1703 proposed for a new C language standard header `<stdfloat.h>`. | ||
|  | 
 | ||
|  | All `typedef`s are in `namespace boost` (would be in namespace `std` if eventually standardized). | ||
|  | 
 | ||
|  | The `typedef`s include `float16_t, float32_t, float64_t, float80_t, float128_t`, | ||
|  | their corresponding least and fast types, | ||
|  | and the corresponding maximum-width type. | ||
|  | The `typedef`s are based on underlying built-in types | ||
|  | such as `float`, `double`, or `long double`, or the proposed __short_float, | ||
|  | or based on other compiler-specific non-standardized types such as `__float128`. | ||
|  | The underlying types of these `typedef`s must conform with | ||
|  | the corresponding specifications of binary16, binary32, binary64, | ||
|  | and binary128 in __IEEE754 floating-point format, and | ||
|  | `std::numeric_limits<>::is_iec559 == true`. | ||
|  | 
 | ||
|  | The 128-bit floating-point type (of great interest in scientific and | ||
|  | numeric programming) is not required in the Boost header, | ||
|  | and may not be supplied for all platforms/compilers, because compiler | ||
|  | support for a 128-bit floating-point type is not mandated by either | ||
|  | the C standard or the C++ standard. | ||
|  | 
 | ||
|  | If 128-bit floating-point is supported, then including `boost/cstdfloat.hpp` | ||
|  | provides a [*native] 128-bit type, and | ||
|  | includes other headers in folder `boost/math/cstdfloat` that provide C++ | ||
|  | quad support for __C_math in `<cmath>`, `<limits>`, `<iostream>`, `<complex>`, | ||
|  | and the available floating-point types. | ||
|  | 
 | ||
|  | One can also, more robustly, include `boost/multiprecision/float128.hpp` | ||
|  | and this provides a thin wrapper selecting the appropriate 128-bit native type | ||
|  | from `cstdfloat` if available, or else a 128-bit multiprecision type. | ||
|  | 
 | ||
|  | See [link math_toolkit.examples.je_lambda Jahnke-Emden-Lambda function example] | ||
|  | for an example using both a `<cmath>` function and a Boost.Math function | ||
|  | to evaluate a moderately interesting function, the | ||
|  | [@http://mathworld.wolfram.com/LambdaFunction.html Jahnke-Emden-Lambda function] | ||
|  | and [link math_toolkit.examples.normal_table normal distribution] | ||
|  | as an example of a statistical distribution from Boost.Math. | ||
|  | 
 | ||
|  | [endsect] [/section:specified_typedefs Overview] | ||
|  | 
 | ||
|  | [section:rationale Rationale] | ||
|  | 
 | ||
|  | The implementation of `<boost/cstdfloat.hpp>` is designed to utilize `<float.h>`, | ||
|  | defined in the 1989 C standard. The preprocessor is used to query certain | ||
|  | preprocessor definitions in `<float.h>` such as FLT_MAX, DBL_MAX, etc. | ||
|  | Based on the results of these queries, an attempt is made to automatically | ||
|  | detect the presence of built-in floating-point types having specified widths. | ||
|  | An unequivocal test requiring conformance with __IEEE754 (IEC599) based on | ||
|  | [@ http://en.cppreference.com/w/cpp/types/numeric_limits/is_iec559 `std::numeric_limits<>::is_iec559`] | ||
|  | is performed with `BOOST_STATIC_ASSERT`. | ||
|  | 
 | ||
|  | In addition, this Boost implementation `<boost/cstdfloat.hpp>` | ||
|  | supports an 80-bit floating-point `typedef` if it can be detected, | ||
|  | and a 128-bit floating-point `typedef` if it can be detected, | ||
|  | provided that the underlying types conform with | ||
|  | [@http://en.wikipedia.org/wiki/Extended_precision IEEE-754 precision extension] | ||
|  | (provided `std::numeric_limits<>::is_iec559 == true` for this type). | ||
|  | 
 | ||
|  | The header `<boost/cstdfloat.hpp>` makes the standardized floating-point | ||
|  | `typedef`s safely available in `namespace boost` without placing any names | ||
|  | in `namespace std`. The intention is to complement rather than compete | ||
|  | with a potential future C/C++ Standard Library that may contain these `typedef`s. | ||
|  | Should some future C/C++ standard include `<stdfloat.h>` and `<cstdfloat>`, | ||
|  | then `<boost/cstdfloat.hpp>` will continue to function, but will become redundant | ||
|  | and may be safely deprecated. | ||
|  | 
 | ||
|  | Because `<boost/cstdfloat.hpp>` is a Boost header, its name conforms to the | ||
|  | boost header naming conventions, not the C++ Standard Library header | ||
|  | naming conventions. | ||
|  | 
 | ||
|  | [note | ||
|  | `<boost/cstdfloat.hpp>` [*cannot synthesize or create | ||
|  | a `typedef` if the underlying type is not provided by the compiler]. | ||
|  | For example, if a compiler does not have an underlying floating-point | ||
|  | type with 128 bits (highly sought-after in scientific and numeric programming), | ||
|  | then `float128_t` and its corresponding least and fast types are [*not] | ||
|  | provided by `<boost/cstdfloat.hpp`>.] | ||
|  | 
 | ||
|  | [warning If `<boost/cstdfloat.hpp>` uses a compiler-specific non-standardized type | ||
|  | ([*not] derived from `float, double,` or `long double`) for one or more | ||
|  | of its floating-point `typedef`s, then there is no guarantee that | ||
|  | specializations of `numeric_limits<>` will be available for these types. | ||
|  | Typically, specializations of `numeric_limits<>` will only be available for these | ||
|  | types if the compiler itself supports corresponding specializations | ||
|  | for the underlying type(s), exceptions are GCC's `__float128` type and | ||
|  | Intel's `_Quad` type which are explicitly supported via our own code.] | ||
|  | 
 | ||
|  | [warning | ||
|  | As an implementation artifact, certain C macro names from `<float.h>` | ||
|  | may possibly be visible to users of `<boost/cstdfloat.hpp>`. | ||
|  | Don't rely on using these macros; they are not part of any Boost-specified interface. | ||
|  | Use `std::numeric_limits<>` for floating-point ranges, etc. instead.] | ||
|  | 
 | ||
|  | [tip For best results, `<boost/cstdfloat.hpp>` should be `#include`d before | ||
|  | other headers that define generic code making use of standard library functions | ||
|  | defined in <cmath>. | ||
|  | 
 | ||
|  | This is because `<boost/cstdfloat.hpp>` may define overloads of | ||
|  | standard library functions where a non-standard type (i.e. other than | ||
|  | `float`, `double`, or `long double`) is used for one of the specified | ||
|  | width types.  If generic code (for example in another Boost.Math header) | ||
|  | calls a standard library function, then the correct overload will only be | ||
|  | found if these overloads are defined prior to the point of use. | ||
|  | See [link math_toolkit.float128.overloading overloading template functions with float128_t] | ||
|  | and the implementation of `cstdfloat.hpp` for more details. | ||
|  | 
 | ||
|  | For this reason, making `#include <boost/cstdfloat.hpp>` the [*first | ||
|  | include] is usually best. | ||
|  | ] | ||
|  | [endsect] [/section:rationale Rationale] | ||
|  | 
 | ||
|  | [section:exact_typdefs Exact-Width Floating-Point `typedef`s] | ||
|  | 
 | ||
|  | The `typedef float#_t`, with # replaced by the width, designates a | ||
|  | floating-point type of exactly # bits. For example `float32_t` denotes | ||
|  | a single-precision floating-point type with approximately | ||
|  | 7 decimal digits of precision (equivalent to binary32 in __IEEE754). | ||
|  | 
 | ||
|  | Floating-point types in C and C++ are specified to be allowed to have | ||
|  | (optionally) implementation-specific widths and formats. | ||
|  | However, if a platform supports underlying | ||
|  | floating-point types (conformant with __IEEE754) with widths of | ||
|  | 16, 32, 64, 80, 128 bits, or any combination thereof, | ||
|  | then `<boost/cstdfloat.hpp>` does provide the corresponding `typedef`s | ||
|  | `float16_t, float32_t, float64_t, float80_t, float128_t,` | ||
|  | their corresponding least and fast types, | ||
|  | and the corresponding maximum-width type. | ||
|  | 
 | ||
|  | [h4 How to tell which widths are supported] | ||
|  | 
 | ||
|  | The definition (or not) of a | ||
|  | [link math_toolkit.macros floating-point constant macro] | ||
|  | is a way to test if a [*specific width floating-point] is available on a platform. | ||
|  | 
 | ||
|  | 	#if defined(BOOST_FLOAT16_C) | ||
|  | 	// Can use boost::float16_t, perhaps a proposed __short_float. | ||
|  | 	// P0192R1, Adding Fundamental Type for Short Float, | ||
|  | 	// Boris Fomitchev, Sergei Nikolaev, Olivier Giroux, Lawrence Crowl, 2016 Feb14 | ||
|  | 	// http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2016.pdf | ||
|  | 	#endif | ||
|  | 
 | ||
|  | 	#if defined(BOOST_FLOAT32_C) | ||
|  | 	// Can use boost::float32_t, usually type `float`. | ||
|  | 	#endif | ||
|  | 
 | ||
|  | 	#if defined(BOOST_FLOAT64_C) | ||
|  | 	// Can use boost::float64_t, usually type `double`, and sometimes also type `long double`. | ||
|  | 	#endif | ||
|  | 
 | ||
|  | 	#if defined(BOOST_FLOAT80_C) | ||
|  | 	// Can use boost::float80_t, sometimes type `long double`. | ||
|  | 	#endif | ||
|  | 
 | ||
|  | 	#if defined(BOOST_FLOAT128_C) | ||
|  | 	// Can use boost::float128_t. Sometimes type `__float128` or `_Quad`. | ||
|  | 	#endif | ||
|  | 
 | ||
|  | This can be used to write code which will compile and run (albeit differently) on several platforms. | ||
|  | Without these tests, if a width, say `float128_t` is not supported, then compilation would fail. | ||
|  | (It is, of course, rare for `float64_t` or `float32_t` not to be supported). | ||
|  | 
 | ||
|  | The number of bits in just the significand can be determined using: | ||
|  | 
 | ||
|  |    std::numeric_limits<boost::floatmax_t>::digits | ||
|  | 
 | ||
|  | and from this one can safely infer the total number of bits because the type must be IEEE754 format, | ||
|  | `std::numeric_limits<boost::floatmax_t>::is_iec559 == true`, | ||
|  | so, for example, if `std::numeric_limits<boost::floatmax_t>::digits == 113`, | ||
|  | then `floatmax_t` must be` float128_t`. | ||
|  | 
 | ||
|  | The [*total] number of bits using `floatmax_t` can be found thus: | ||
|  | 
 | ||
|  | [floatmax_1] | ||
|  | 
 | ||
|  | and the number of 'guaranteed' decimal digits using | ||
|  | 
 | ||
|  |    std::numeric_limits<boost::floatmax_t>::digits10 | ||
|  | 
 | ||
|  | and the maximum number of  possibly significant decimal digits using | ||
|  | 
 | ||
|  |     std::numeric_limits<boost::floatmax_t>::max_digits10 | ||
|  | 
 | ||
|  | [tip  `max_digits10` is not always supported, | ||
|  | but can be calculated at compile-time using the Kahan formula, | ||
|  | `2 + binary_digits * 0.3010` which can be calculated [*at compile time] using | ||
|  | `2 + binary_digits * 3010/10000`. | ||
|  | ] | ||
|  | 
 | ||
|  | [note One could test that | ||
|  | 
 | ||
|  |   std::is_same<boost::floatmax_t, boost::float128_t>::value == true | ||
|  | 
 | ||
|  | but this would fail to compile on a platform where  `boost::float128_t` is not defined. | ||
|  | So it is better to use the MACROs `BOOST_FLOATnnn_C`. ] | ||
|  | 
 | ||
|  | [endsect] [/section:exact_typdefs Exact-Width Floating-Point `typedef`s] | ||
|  | 
 | ||
|  | [section:minimum_typdefs Minimum-width floating-point `typedef`s] | ||
|  | 
 | ||
|  | The `typedef float_least#_t`, with # replaced by the width, designates a | ||
|  | floating-point type with a [*width of at least # bits], such that no | ||
|  | floating-point type with lesser size has at least the specified width. | ||
|  | Thus, `float_least32_t` denotes the smallest floating-point type with | ||
|  | a width of at least 32 bits. | ||
|  | 
 | ||
|  | Minimum-width floating-point types are provided for all existing | ||
|  | exact-width floating-point types on a given platform. | ||
|  | 
 | ||
|  | For example, if a platform supports `float32_t` and `float64_t`, | ||
|  | then `float_least32_t` and `float_least64_t` will also be supported, etc. | ||
|  | 
 | ||
|  | [endsect] [/section:minimum_typdefs Minimum-width floating-point `typedef`s] | ||
|  | 
 | ||
|  | [section:fastest_typdefs Fastest floating-point `typedef`s] | ||
|  | 
 | ||
|  | The `typedef float_fast#_t`, with # replaced by the width, designates | ||
|  | the [*fastest] floating-point type with a [*width of at least # bits]. | ||
|  | 
 | ||
|  | There is no absolute guarantee that these types are the fastest for all purposes. | ||
|  | In any case, however, they satisfy the precision and width requirements. | ||
|  | 
 | ||
|  | Fastest minimum-width floating-point types are provided for all existing | ||
|  | exact-width floating-point types on a given platform. | ||
|  | 
 | ||
|  | For example, if a platform supports `float32_t` and `float64_t`, | ||
|  | then `float_fast32_t` and `float_fast64_t` will also be supported, etc. | ||
|  | 
 | ||
|  | [endsect] [/section:fastest_typdefs Fastest floating-point `typedef`s] | ||
|  | 
 | ||
|  | [section:greatest_typdefs Greatest-width floating-point typedef] | ||
|  | 
 | ||
|  | The `typedef floatmax_t` designates a floating-point type capable of representing | ||
|  | any value of any floating-point type in a given platform most precisely. | ||
|  | 
 | ||
|  | The greatest-width `typedef` is provided for all platforms, but, of course, the size may vary. | ||
|  | 
 | ||
|  | To provide floating-point [*constants] most precisely representable for a `floatmax_t` type, | ||
|  | use the macro `BOOST_FLOATMAX_C`. | ||
|  | 
 | ||
|  | For example, replace a constant `123.4567890123456789012345678901234567890` with | ||
|  | 
 | ||
|  |   BOOST_FLOATMAX_C(123.4567890123456789012345678901234567890) | ||
|  | 
 | ||
|  | If, for example, `floatmax_t` is `float64_t` then the result will be equivalent to a `long double` suffixed with L, | ||
|  | but if `floatmax_t` is `float128_t` then the result will be equivalent to a `quad type` suffixed with Q | ||
|  | (assuming, of course, that `float128_t` (`__float128` or `Quad`) is supported). | ||
|  | 
 | ||
|  | If we display with `max_digits10`, the maximum possibly significant decimal digits: | ||
|  | 
 | ||
|  | [floatmax_widths_1] | ||
|  | 
 | ||
|  | then on a 128-bit platform (GCC 4.8.1 or higher with quadmath): | ||
|  | 
 | ||
|  | [floatmax_widths_2] | ||
|  | 
 | ||
|  | [endsect] [/section:greatest_typdefs Greatest-width floating-point typedef] | ||
|  | 
 | ||
|  | [section:macros Floating-Point Constant Macros] | ||
|  | 
 | ||
|  | All macros of the type `BOOST_FLOAT16_C, BOOST_FLOAT32_C, BOOST_FLOAT64_C, | ||
|  | BOOST_FLOAT80_C, BOOST_FLOAT128_C, ` and `BOOST_FLOATMAX_C` | ||
|  | are always defined after inclusion of `<boost/cstdfloat.hpp>`. | ||
|  | 
 | ||
|  | [cstdfloat_constant_2] | ||
|  | 
 | ||
|  | [tip Boost.Math provides many constants 'built-in', so always use Boost.Math constants if available, for example:] | ||
|  | 
 | ||
|  | [cstdfloat_constant_1] | ||
|  | 
 | ||
|  | from [@../../example/cstdfloat_example.cpp  cstdfloat_example.cpp]. | ||
|  | 
 | ||
|  | See the complete list of __constants. | ||
|  | 
 | ||
|  | [endsect] [/section:macros Floating-Point Constant Macros] | ||
|  | 
 | ||
|  | [section:examples Examples] | ||
|  | 
 | ||
|  | [h3:je_lambda Jahnke-Emden-Lambda function] | ||
|  | 
 | ||
|  | The following code uses `<boost/cstdfloat.hpp>` in combination with | ||
|  | `<boost/math/special_functions.hpp>` to compute a simplified | ||
|  | version of the | ||
|  | [@http://mathworld.wolfram.com/LambdaFunction.html Jahnke-Emden-Lambda function]. | ||
|  | Here, we specify a floating-point type with [*exactly 64 bits] (i.e., `float64_t`). | ||
|  | If we were to use, for instance, built-in `double`, | ||
|  | then there would be no guarantee that the code would | ||
|  | behave identically on all platforms. With `float64_t` from | ||
|  | `<boost/cstdfloat.hpp>`, however, it is very likely to be identical. | ||
|  | 
 | ||
|  | Using `float64_t`, we know that | ||
|  | this code is as portable as possible and uses a floating-point type | ||
|  | with approximately 15 decimal digits of precision, | ||
|  | regardless of the compiler or version or operating system. | ||
|  | 
 | ||
|  | [cstdfloat_example_1] | ||
|  | [cstdfloat_example_2] | ||
|  | [cstdfloat_example_3] | ||
|  | 
 | ||
|  | For details, see [@../../example/cstdfloat_example.cpp  cstdfloat_example.cpp] | ||
|  | - a extensive example program. | ||
|  | 
 | ||
|  | [h3:normal_table Normal distribution table] | ||
|  | 
 | ||
|  | This example shows printing tables of a normal distribution's PDF and CDF, | ||
|  | using `boost::math` implementation of normal distribution. | ||
|  | 
 | ||
|  | A function templated on floating-point type prints a table for a range of standard variate z values. | ||
|  | 
 | ||
|  | The example shows use of the specified-width typedefs to either use a specific width, | ||
|  | or to use the maximum available on the platform, perhaps a high as 128-bit. | ||
|  | 
 | ||
|  | The number of digits displayed is controlled by the precision of the type, | ||
|  | so there are no spurious insignificant decimal digits: | ||
|  | 
 | ||
|  |    float_32_t    0    0.39894228 | ||
|  |    float_128_t  0    0.398942280401432702863218082711682655 | ||
|  | 
 | ||
|  | Some sample output for two different platforms is appended to the code at | ||
|  | [@../../example/normal_tables.cpp  normal_tables.cpp]. | ||
|  | 
 | ||
|  | [normal_table_1] | ||
|  | 
 | ||
|  | [endsect]  [/section:examples examples] | ||
|  | 
 | ||
|  | [section:float128_hints  Hints on using float128 (and __float128)] | ||
|  | 
 | ||
|  | [h5:different_float128 __float128 versus float128] | ||
|  | * __float128 is the (optionally) compiler supplied hardware type, | ||
|  | it's an C-ish extension to C++ and there is only | ||
|  | minimal support for it in normal C++ | ||
|  | (no IO streams or `numeric_limits` support, | ||
|  | function names in libquadmath all have different names to the | ||
|  | `std::` ones etc.) | ||
|  | So you can program type `__float128` directly, but it's harder work. | ||
|  | 
 | ||
|  | * Type `float128` uses __float128 and makes it C++ and generic code friendly, | ||
|  | with all the usual standard `iostream`, `numeric_limits`, `complex` in namspace `std::` available, | ||
|  | so strongly recommended for C++ use. | ||
|  | 
 | ||
|  | [h5 Hints and tips] | ||
|  | 
 | ||
|  | * Make sure you declare variables with the correct type, here `float128`. | ||
|  | * Make sure that if you pass a variable to a function then it is casted to `float128`. | ||
|  | * Make sure you declare literals with the correct suffix - otherwise | ||
|  | they'll be treated as type `double` with catastrophic loss of precision. | ||
|  | So make sure they have a Q suffix for 128-bit floating-point literals. | ||
|  | * All the std library functions, cmath functions, plus all the constants, and special | ||
|  | functions from Boost.Math should then just work. | ||
|  | * Make sure std lib functions are called [*unqualified] so that the correct | ||
|  | overload is found via __ADL. So write | ||
|  |   sqrt(variable) | ||
|  | and not | ||
|  |   std::sqrt(variable). | ||
|  | * In general, try not to reinvent stuff - using constants from | ||
|  | Boost.Math is probably less error prone than declaring your own, | ||
|  | likewise the special functions etc. | ||
|  | 
 | ||
|  | Some examples of what can go horribly and silently wrong are at | ||
|  | [@../../example/float128_example.cpp  float128_example.cpp]. | ||
|  | 
 | ||
|  | [endsect]  [/section:float128_hints  Hints on using float128] | ||
|  | 
 | ||
|  | [section:float128 Implementation of Float128 type] | ||
|  | 
 | ||
|  | Since few compilers implement a true 128-bit floating-point, and language features like the suffix Q | ||
|  | (which may need an option `-fext-numeric-literals` to enable), | ||
|  | and C++ Standard library functions are as-yet missing or incomplete in C++11, | ||
|  | this Boost.Math implementation wraps `__float128` provided by the GCC compiler | ||
|  | [@https://gcc.gnu.org/onlinedocs/gcc/Floating-Types.html GCC floating-point types] | ||
|  | or the `_Quad` type provided by the Intel compiler. | ||
|  | 
 | ||
|  | This is provided to in order to demonstrate, and users to evaluate, the feasibility and benefits of higher-precision floating-point, | ||
|  | especially to allow use of the full <cmath> and Boost.Math library of functions and distributions at high precision. | ||
|  | 
 | ||
|  | (It is also possible to use Boost.Math with Boost.Multiprecision decimal and binary, but since these are entirely software solutions, | ||
|  | allowing much higher precision or arbitrary precision, they are likely to be slower). | ||
|  | 
 | ||
|  | We also provide (we believe full) support for `<limits>, <cmath>`, I/O stream operations in `<iostream>`, and `<complex>`. | ||
|  | 
 | ||
|  | As a prototype for a future C++ standard, we place all these in `namespace std`. | ||
|  | This contravenes the existing C++ standard of course, so selecting any compiler that promises to check conformance will fail. | ||
|  | 
 | ||
|  | [tip For GCC, compile with `-std=gnu++11` or `-std=gnu++03` and do not use `-std=stdc++11` or any 'strict' options, as | ||
|  | these turn off full support for `__float128`.  These requirements also apply to the Intel compiler on Linux, for | ||
|  | Intel on Windows you need to compile with `-Qoption,cpp,--extended_float_type -DBOOST_MATH_USE_FLOAT128` in order to | ||
|  | activate 128-bit floating point support.] | ||
|  | 
 | ||
|  | The `__float128` type is provided by the [@http://gcc.gnu.org/onlinedocs/libquadmath/ libquadmath library] on GCC or | ||
|  | by Intel's FORTRAN library with Intel C++. THey also provide a full set of `<cmath>` functions in `namespace std`. | ||
|  | 
 | ||
|  | [h4 Using C __float128 quadmath type] | ||
|  | 
 | ||
|  | [quadmath_snprintf_1] | ||
|  | 
 | ||
|  | The source code is at [@../../example/quadmath_snprintf.c quadmath_snprintf.c]. | ||
|  | 
 | ||
|  | [h4 Using C++ `float128` quadmath type] | ||
|  | 
 | ||
|  | For C++ programs, you will want to use the C++ type `float128` | ||
|  | 
 | ||
|  | See example at [@../../example/cstdfloat_example.cpp cstdfloat_example.cpp]. | ||
|  | 
 | ||
|  | A typical invocation of the compiler is | ||
|  | 
 | ||
|  |   g++ -O3 -std=gnu++11 test.cpp -I/c/modular-boost -lquadmath -o test.exe | ||
|  | 
 | ||
|  | [tip If you are trying to use the develop branch of Boost.Math,  then make `-I/c/modular-boost/libs/math/include` the [*first] include directory.] | ||
|  | 
 | ||
|  |   g++ -O3 -std=gnu++11 test.cpp -I/c/modular-boost/libs/math/include -I/c/modular-boost -lquadmath -o test.exe | ||
|  | 
 | ||
|  | [note So far, the only missing detail that we had noted was in trying to use `<typeinfo>`, | ||
|  | for example for `std::cout << typeid<__float_128>.name();`. | ||
|  | `` | ||
|  | Link fails: undefined reference to typeinfo for __float128. | ||
|  | `` | ||
|  | See [@http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43622  GCC Bug 43622 - no C++ typeinfo for __float128]. | ||
|  | But this is reported (Marc Glisse 2015-04-04 ) fixed in GCC 5 (and above). | ||
|  | 
 | ||
|  | For example, with GCC6.1.1 this works as expected to  a [*mangled] string name, and output (if possible - not always). | ||
|  | `` | ||
|  | const std::type_info& tifu128 = typeid(__float128); // OK. | ||
|  | //std::cout << tifu128.name() << std::endl; // On GCC, aborts (because not printable string). | ||
|  | //std::cout << typeid(__float128).name() << std::endl; // Aborts - string name cannot be output. | ||
|  | 
 | ||
|  | const std::type_info& tif128 = typeid(float128); // OK. | ||
|  | std::cout << tif128.name() << std::endl; // OK. | ||
|  | std::cout << typeid(float128).name() << std::endl; // OK. | ||
|  | 
 | ||
|  | const std::type_info& tpi = typeid(pi1); // OK GCC 6.1.1 (from GCC 5 according to http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43622) | ||
|  | std::cout << tpi.name() << std::endl; // Output mangled name: | ||
|  | 
 | ||
|  | // N5boost14multiprecision6numberINS0_8backends16float128_backendELNS0_26expression_template_optionE0EEE | ||
|  | 
 | ||
|  | `` | ||
|  | ] [/note] | ||
|  | 
 | ||
|  | [section:overloading Overloading template functions with float128_t] | ||
|  | 
 | ||
|  | An artifact of providing C++ standard library support for | ||
|  | quadmath may mandate the inclusion of `<boost/cstdfloat.hpp>` | ||
|  | [*before] the inclusion of other headers. | ||
|  | 
 | ||
|  | Consider a function that calls `fabs(x)` and has previously injected `std::fabs()` | ||
|  | into local scope via a `using` directive: | ||
|  | 
 | ||
|  |    template <class T> | ||
|  |    bool unsigned_compare(T a, T b) | ||
|  |    { | ||
|  |       using std::fabs; | ||
|  |       return fabs(a) == fabs(b); | ||
|  |    } | ||
|  | 
 | ||
|  | In this function, the correct overload of `fabs` may be found via | ||
|  | [@http://en.wikipedia.org/wiki/Argument-dependent_name_lookup argument-dependent-lookup (ADL)] | ||
|  | or by calling one of the `std::fabs` overloads.  There is a key difference between them | ||
|  | however: an overload in the same namespace as T and found via ADL need ['[*not be defined at the | ||
|  | time the function is declared]].  However, all the types declared in `<boost/cstdfloat.hpp>` are | ||
|  | fundamental types, so for these types we are relying on finding an overload declared in namespace `std`. | ||
|  | In that case however, ['[*all such overloads must be declared prior to the definition of function | ||
|  | `unsigned_compare` otherwise they are not considered]]. | ||
|  | 
 | ||
|  | In the event that `<boost/cstdfloat.hpp>` has been included [*after] the | ||
|  | definition of the above function, the correct overload of `fabs`, while present, is simply | ||
|  | not considered as part of the overload set. | ||
|  | So the compiler tries to downcast the `float128_t` argument first to | ||
|  | `long double`, then to `double`, then to `float`; | ||
|  | the compilation fails because the result is ambiguous. | ||
|  | However the compiler error message will appear cruelly inscrutable, | ||
|  | at an apparently irelevant line number and making no mention of `float128`: | ||
|  | the word ['ambiguous] is the clue to what is wrong. | ||
|  | 
 | ||
|  | Provided you `#include <boost/cstdfloat.hpp>` [*before] the inclusion | ||
|  | of the any header containing generic floating point code (such as other | ||
|  | Boost.Math headers, then the compiler | ||
|  | will know about and use the `std::fabs(std::float128_t)` | ||
|  | that we provide in `#include <boost/cstdfloat.hpp>`. | ||
|  | 
 | ||
|  | [endsect] | ||
|  | 
 | ||
|  | [section:exp_function Exponential function] | ||
|  | 
 | ||
|  | There was a bug when using any quadmath `expq` function  on GCC : | ||
|  | [@http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60349  GCC bug #60349] | ||
|  | caused by | ||
|  | [@http://sourceforge.net/p/mingw-w64/bugs/368/ mingw-64 bug #368]. | ||
|  | 
 | ||
|  | To work round this defect, an alternative implementation of 128-bit exp | ||
|  | was temporarily provided by `boost/cstdfloat.hpp`. | ||
|  | 
 | ||
|  | The mingw bug was fixed at 2014-03-12 and GCC 6.1.1 now works as expected. | ||
|  | 
 | ||
|  | [tip It is essential to link to the quadmath library]. | ||
|  | 
 | ||
|  | [endsect] [/section:exp_function exp function] | ||
|  | 
 | ||
|  | [section:typeinfo `typeinfo`] | ||
|  | 
 | ||
|  | For GCC 4.8.1 it was not yet possible to use `typeinfo` for `float_128` on GCC: | ||
|  | see [@http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43622   GCC 43622]. | ||
|  | 
 | ||
|  | So this code (to display the mangled name) | ||
|  | failed to link `undefined reference to typeinfo for __float128` | ||
|  | 
 | ||
|  |   std::cout << typeid(boost::float128_t).name() << std::endl; | ||
|  | 
 | ||
|  | This prevent using the existing tests for Boost.Math distributions, | ||
|  | (unless a few lines are commented out) | ||
|  | and if a MACRO BOOST_MATH_INSTRUMENT controlling them is defined | ||
|  | then some diagnostic displays in Boost.Math will not work. | ||
|  | 
 | ||
|  | However this was only used for display purposes | ||
|  | and could be commented out until this was fixed in GCC 5. | ||
|  | 
 | ||
|  | [tip Not all managed names can be [*displayed] using `std::cout`.] | ||
|  | 
 | ||
|  | [endsect] [/section:typeinfo `typeinfo`] | ||
|  | 
 | ||
|  | 
 | ||
|  | [endsect] [/section:float128 Float128 type] | ||
|  | 
 | ||
|  | [/ cstdfloat.qbk | ||
|  |   Copyright 2014 Christopher Kormanyos, John Maddock and Paul A. Bristow. | ||
|  |   Distributed under the Boost Software License, Version 1.0. | ||
|  |   (See accompanying file LICENSE_1_0.txt or copy at | ||
|  |   http://www.boost.org/LICENSE_1_0.txt). | ||
|  | ] | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 |