Brian Silverman | 32ed54e | 2018-08-04 23:37:28 -0700 | [diff] [blame^] | 1 | [/cstdfloat.qbk Specified-width floating-point typedefs] |
| 2 | |
| 3 | [def __IEEE754 [@http://en.wikipedia.org/wiki/IEEE_floating_point IEEE_floating_point]] |
| 4 | [def __N3626 [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3626.pdf N3626]] |
| 5 | [def __N1703 [@http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1703.pdf N1703]] |
| 6 | |
| 7 | [import ../../example/cstdfloat_example.cpp] |
| 8 | [import ../../example/normal_tables.cpp] |
| 9 | [/Removed as unhelpful for C++ users, but might have use as a check that quadmath is available and linked OK.] |
| 10 | [/import ../../example/quadmath_snprintf.c] |
| 11 | |
| 12 | [section:specified_typedefs Overview] |
| 13 | |
| 14 | The header `<boost/cstdfloat.hpp>` provides [*optional] |
| 15 | standardized floating-point `typedef`s having [*specified widths]. |
| 16 | These are useful for writing portable code because they |
| 17 | should behave identically on all platforms. |
| 18 | These `typedef`s are the floating-point analog of specified-width integers in `<cstdint>` and `stdint.h`. |
| 19 | |
| 20 | The `typedef`s are based on __N3626 |
| 21 | proposed for a new C++14 standard header `<cstdfloat>` and |
| 22 | __N1703 proposed for a new C language standard header `<stdfloat.h>`. |
| 23 | |
| 24 | All `typedef`s are in `namespace boost` (would be in namespace `std` if eventually standardized). |
| 25 | |
| 26 | The `typedef`s include `float16_t, float32_t, float64_t, float80_t, float128_t`, |
| 27 | their corresponding least and fast types, |
| 28 | and the corresponding maximum-width type. |
| 29 | The `typedef`s are based on underlying built-in types |
| 30 | such as `float`, `double`, or `long double`, or the proposed __short_float, |
| 31 | or based on other compiler-specific non-standardized types such as `__float128`. |
| 32 | The underlying types of these `typedef`s must conform with |
| 33 | the corresponding specifications of binary16, binary32, binary64, |
| 34 | and binary128 in __IEEE754 floating-point format, and |
| 35 | `std::numeric_limits<>::is_iec559 == true`. |
| 36 | |
| 37 | The 128-bit floating-point type (of great interest in scientific and |
| 38 | numeric programming) is not required in the Boost header, |
| 39 | and may not be supplied for all platforms/compilers, because compiler |
| 40 | support for a 128-bit floating-point type is not mandated by either |
| 41 | the C standard or the C++ standard. |
| 42 | |
| 43 | If 128-bit floating-point is supported, then including `boost/cstdfloat.hpp` |
| 44 | provides a [*native] 128-bit type, and |
| 45 | includes other headers in folder `boost/math/cstdfloat` that provide C++ |
| 46 | quad support for __C_math in `<cmath>`, `<limits>`, `<iostream>`, `<complex>`, |
| 47 | and the available floating-point types. |
| 48 | |
| 49 | One can also, more robustly, include `boost/multiprecision/float128.hpp` |
| 50 | and this provides a thin wrapper selecting the appropriate 128-bit native type |
| 51 | from `cstdfloat` if available, or else a 128-bit multiprecision type. |
| 52 | |
| 53 | See [link math_toolkit.examples.je_lambda Jahnke-Emden-Lambda function example] |
| 54 | for an example using both a `<cmath>` function and a Boost.Math function |
| 55 | to evaluate a moderately interesting function, the |
| 56 | [@http://mathworld.wolfram.com/LambdaFunction.html Jahnke-Emden-Lambda function] |
| 57 | and [link math_toolkit.examples.normal_table normal distribution] |
| 58 | as an example of a statistical distribution from Boost.Math. |
| 59 | |
| 60 | [endsect] [/section:specified_typedefs Overview] |
| 61 | |
| 62 | [section:rationale Rationale] |
| 63 | |
| 64 | The implementation of `<boost/cstdfloat.hpp>` is designed to utilize `<float.h>`, |
| 65 | defined in the 1989 C standard. The preprocessor is used to query certain |
| 66 | preprocessor definitions in `<float.h>` such as FLT_MAX, DBL_MAX, etc. |
| 67 | Based on the results of these queries, an attempt is made to automatically |
| 68 | detect the presence of built-in floating-point types having specified widths. |
| 69 | An unequivocal test requiring conformance with __IEEE754 (IEC599) based on |
| 70 | [@ http://en.cppreference.com/w/cpp/types/numeric_limits/is_iec559 `std::numeric_limits<>::is_iec559`] |
| 71 | is performed with `BOOST_STATIC_ASSERT`. |
| 72 | |
| 73 | In addition, this Boost implementation `<boost/cstdfloat.hpp>` |
| 74 | supports an 80-bit floating-point `typedef` if it can be detected, |
| 75 | and a 128-bit floating-point `typedef` if it can be detected, |
| 76 | provided that the underlying types conform with |
| 77 | [@http://en.wikipedia.org/wiki/Extended_precision IEEE-754 precision extension] |
| 78 | (provided `std::numeric_limits<>::is_iec559 == true` for this type). |
| 79 | |
| 80 | The header `<boost/cstdfloat.hpp>` makes the standardized floating-point |
| 81 | `typedef`s safely available in `namespace boost` without placing any names |
| 82 | in `namespace std`. The intention is to complement rather than compete |
| 83 | with a potential future C/C++ Standard Library that may contain these `typedef`s. |
| 84 | Should some future C/C++ standard include `<stdfloat.h>` and `<cstdfloat>`, |
| 85 | then `<boost/cstdfloat.hpp>` will continue to function, but will become redundant |
| 86 | and may be safely deprecated. |
| 87 | |
| 88 | Because `<boost/cstdfloat.hpp>` is a Boost header, its name conforms to the |
| 89 | boost header naming conventions, not the C++ Standard Library header |
| 90 | naming conventions. |
| 91 | |
| 92 | [note |
| 93 | `<boost/cstdfloat.hpp>` [*cannot synthesize or create |
| 94 | a `typedef` if the underlying type is not provided by the compiler]. |
| 95 | For example, if a compiler does not have an underlying floating-point |
| 96 | type with 128 bits (highly sought-after in scientific and numeric programming), |
| 97 | then `float128_t` and its corresponding least and fast types are [*not] |
| 98 | provided by `<boost/cstdfloat.hpp`>.] |
| 99 | |
| 100 | [warning If `<boost/cstdfloat.hpp>` uses a compiler-specific non-standardized type |
| 101 | ([*not] derived from `float, double,` or `long double`) for one or more |
| 102 | of its floating-point `typedef`s, then there is no guarantee that |
| 103 | specializations of `numeric_limits<>` will be available for these types. |
| 104 | Typically, specializations of `numeric_limits<>` will only be available for these |
| 105 | types if the compiler itself supports corresponding specializations |
| 106 | for the underlying type(s), exceptions are GCC's `__float128` type and |
| 107 | Intel's `_Quad` type which are explicitly supported via our own code.] |
| 108 | |
| 109 | [warning |
| 110 | As an implementation artifact, certain C macro names from `<float.h>` |
| 111 | may possibly be visible to users of `<boost/cstdfloat.hpp>`. |
| 112 | Don't rely on using these macros; they are not part of any Boost-specified interface. |
| 113 | Use `std::numeric_limits<>` for floating-point ranges, etc. instead.] |
| 114 | |
| 115 | [tip For best results, `<boost/cstdfloat.hpp>` should be `#include`d before |
| 116 | other headers that define generic code making use of standard library functions |
| 117 | defined in <cmath>. |
| 118 | |
| 119 | This is because `<boost/cstdfloat.hpp>` may define overloads of |
| 120 | standard library functions where a non-standard type (i.e. other than |
| 121 | `float`, `double`, or `long double`) is used for one of the specified |
| 122 | width types. If generic code (for example in another Boost.Math header) |
| 123 | calls a standard library function, then the correct overload will only be |
| 124 | found if these overloads are defined prior to the point of use. |
| 125 | See [link math_toolkit.float128.overloading overloading template functions with float128_t] |
| 126 | and the implementation of `cstdfloat.hpp` for more details. |
| 127 | |
| 128 | For this reason, making `#include <boost/cstdfloat.hpp>` the [*first |
| 129 | include] is usually best. |
| 130 | ] |
| 131 | [endsect] [/section:rationale Rationale] |
| 132 | |
| 133 | [section:exact_typdefs Exact-Width Floating-Point `typedef`s] |
| 134 | |
| 135 | The `typedef float#_t`, with # replaced by the width, designates a |
| 136 | floating-point type of exactly # bits. For example `float32_t` denotes |
| 137 | a single-precision floating-point type with approximately |
| 138 | 7 decimal digits of precision (equivalent to binary32 in __IEEE754). |
| 139 | |
| 140 | Floating-point types in C and C++ are specified to be allowed to have |
| 141 | (optionally) implementation-specific widths and formats. |
| 142 | However, if a platform supports underlying |
| 143 | floating-point types (conformant with __IEEE754) with widths of |
| 144 | 16, 32, 64, 80, 128 bits, or any combination thereof, |
| 145 | then `<boost/cstdfloat.hpp>` does provide the corresponding `typedef`s |
| 146 | `float16_t, float32_t, float64_t, float80_t, float128_t,` |
| 147 | their corresponding least and fast types, |
| 148 | and the corresponding maximum-width type. |
| 149 | |
| 150 | [h4 How to tell which widths are supported] |
| 151 | |
| 152 | The definition (or not) of a |
| 153 | [link math_toolkit.macros floating-point constant macro] |
| 154 | is a way to test if a [*specific width floating-point] is available on a platform. |
| 155 | |
| 156 | #if defined(BOOST_FLOAT16_C) |
| 157 | // Can use boost::float16_t, perhaps a proposed __short_float. |
| 158 | // P0192R1, Adding Fundamental Type for Short Float, |
| 159 | // Boris Fomitchev, Sergei Nikolaev, Olivier Giroux, Lawrence Crowl, 2016 Feb14 |
| 160 | // http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2016.pdf |
| 161 | #endif |
| 162 | |
| 163 | #if defined(BOOST_FLOAT32_C) |
| 164 | // Can use boost::float32_t, usually type `float`. |
| 165 | #endif |
| 166 | |
| 167 | #if defined(BOOST_FLOAT64_C) |
| 168 | // Can use boost::float64_t, usually type `double`, and sometimes also type `long double`. |
| 169 | #endif |
| 170 | |
| 171 | #if defined(BOOST_FLOAT80_C) |
| 172 | // Can use boost::float80_t, sometimes type `long double`. |
| 173 | #endif |
| 174 | |
| 175 | #if defined(BOOST_FLOAT128_C) |
| 176 | // Can use boost::float128_t. Sometimes type `__float128` or `_Quad`. |
| 177 | #endif |
| 178 | |
| 179 | This can be used to write code which will compile and run (albeit differently) on several platforms. |
| 180 | Without these tests, if a width, say `float128_t` is not supported, then compilation would fail. |
| 181 | (It is, of course, rare for `float64_t` or `float32_t` not to be supported). |
| 182 | |
| 183 | The number of bits in just the significand can be determined using: |
| 184 | |
| 185 | std::numeric_limits<boost::floatmax_t>::digits |
| 186 | |
| 187 | and from this one can safely infer the total number of bits because the type must be IEEE754 format, |
| 188 | `std::numeric_limits<boost::floatmax_t>::is_iec559 == true`, |
| 189 | so, for example, if `std::numeric_limits<boost::floatmax_t>::digits == 113`, |
| 190 | then `floatmax_t` must be` float128_t`. |
| 191 | |
| 192 | The [*total] number of bits using `floatmax_t` can be found thus: |
| 193 | |
| 194 | [floatmax_1] |
| 195 | |
| 196 | and the number of 'guaranteed' decimal digits using |
| 197 | |
| 198 | std::numeric_limits<boost::floatmax_t>::digits10 |
| 199 | |
| 200 | and the maximum number of possibly significant decimal digits using |
| 201 | |
| 202 | std::numeric_limits<boost::floatmax_t>::max_digits10 |
| 203 | |
| 204 | [tip `max_digits10` is not always supported, |
| 205 | but can be calculated at compile-time using the Kahan formula, |
| 206 | `2 + binary_digits * 0.3010` which can be calculated [*at compile time] using |
| 207 | `2 + binary_digits * 3010/10000`. |
| 208 | ] |
| 209 | |
| 210 | [note One could test that |
| 211 | |
| 212 | std::is_same<boost::floatmax_t, boost::float128_t>::value == true |
| 213 | |
| 214 | but this would fail to compile on a platform where `boost::float128_t` is not defined. |
| 215 | So it is better to use the MACROs `BOOST_FLOATnnn_C`. ] |
| 216 | |
| 217 | [endsect] [/section:exact_typdefs Exact-Width Floating-Point `typedef`s] |
| 218 | |
| 219 | [section:minimum_typdefs Minimum-width floating-point `typedef`s] |
| 220 | |
| 221 | The `typedef float_least#_t`, with # replaced by the width, designates a |
| 222 | floating-point type with a [*width of at least # bits], such that no |
| 223 | floating-point type with lesser size has at least the specified width. |
| 224 | Thus, `float_least32_t` denotes the smallest floating-point type with |
| 225 | a width of at least 32 bits. |
| 226 | |
| 227 | Minimum-width floating-point types are provided for all existing |
| 228 | exact-width floating-point types on a given platform. |
| 229 | |
| 230 | For example, if a platform supports `float32_t` and `float64_t`, |
| 231 | then `float_least32_t` and `float_least64_t` will also be supported, etc. |
| 232 | |
| 233 | [endsect] [/section:minimum_typdefs Minimum-width floating-point `typedef`s] |
| 234 | |
| 235 | [section:fastest_typdefs Fastest floating-point `typedef`s] |
| 236 | |
| 237 | The `typedef float_fast#_t`, with # replaced by the width, designates |
| 238 | the [*fastest] floating-point type with a [*width of at least # bits]. |
| 239 | |
| 240 | There is no absolute guarantee that these types are the fastest for all purposes. |
| 241 | In any case, however, they satisfy the precision and width requirements. |
| 242 | |
| 243 | Fastest minimum-width floating-point types are provided for all existing |
| 244 | exact-width floating-point types on a given platform. |
| 245 | |
| 246 | For example, if a platform supports `float32_t` and `float64_t`, |
| 247 | then `float_fast32_t` and `float_fast64_t` will also be supported, etc. |
| 248 | |
| 249 | [endsect] [/section:fastest_typdefs Fastest floating-point `typedef`s] |
| 250 | |
| 251 | [section:greatest_typdefs Greatest-width floating-point typedef] |
| 252 | |
| 253 | The `typedef floatmax_t` designates a floating-point type capable of representing |
| 254 | any value of any floating-point type in a given platform most precisely. |
| 255 | |
| 256 | The greatest-width `typedef` is provided for all platforms, but, of course, the size may vary. |
| 257 | |
| 258 | To provide floating-point [*constants] most precisely representable for a `floatmax_t` type, |
| 259 | use the macro `BOOST_FLOATMAX_C`. |
| 260 | |
| 261 | For example, replace a constant `123.4567890123456789012345678901234567890` with |
| 262 | |
| 263 | BOOST_FLOATMAX_C(123.4567890123456789012345678901234567890) |
| 264 | |
| 265 | If, for example, `floatmax_t` is `float64_t` then the result will be equivalent to a `long double` suffixed with L, |
| 266 | but if `floatmax_t` is `float128_t` then the result will be equivalent to a `quad type` suffixed with Q |
| 267 | (assuming, of course, that `float128_t` (`__float128` or `Quad`) is supported). |
| 268 | |
| 269 | If we display with `max_digits10`, the maximum possibly significant decimal digits: |
| 270 | |
| 271 | [floatmax_widths_1] |
| 272 | |
| 273 | then on a 128-bit platform (GCC 4.8.1 or higher with quadmath): |
| 274 | |
| 275 | [floatmax_widths_2] |
| 276 | |
| 277 | [endsect] [/section:greatest_typdefs Greatest-width floating-point typedef] |
| 278 | |
| 279 | [section:macros Floating-Point Constant Macros] |
| 280 | |
| 281 | All macros of the type `BOOST_FLOAT16_C, BOOST_FLOAT32_C, BOOST_FLOAT64_C, |
| 282 | BOOST_FLOAT80_C, BOOST_FLOAT128_C, ` and `BOOST_FLOATMAX_C` |
| 283 | are always defined after inclusion of `<boost/cstdfloat.hpp>`. |
| 284 | |
| 285 | [cstdfloat_constant_2] |
| 286 | |
| 287 | [tip Boost.Math provides many constants 'built-in', so always use Boost.Math constants if available, for example:] |
| 288 | |
| 289 | [cstdfloat_constant_1] |
| 290 | |
| 291 | from [@../../example/cstdfloat_example.cpp cstdfloat_example.cpp]. |
| 292 | |
| 293 | See the complete list of __constants. |
| 294 | |
| 295 | [endsect] [/section:macros Floating-Point Constant Macros] |
| 296 | |
| 297 | [section:examples Examples] |
| 298 | |
| 299 | [h3:je_lambda Jahnke-Emden-Lambda function] |
| 300 | |
| 301 | The following code uses `<boost/cstdfloat.hpp>` in combination with |
| 302 | `<boost/math/special_functions.hpp>` to compute a simplified |
| 303 | version of the |
| 304 | [@http://mathworld.wolfram.com/LambdaFunction.html Jahnke-Emden-Lambda function]. |
| 305 | Here, we specify a floating-point type with [*exactly 64 bits] (i.e., `float64_t`). |
| 306 | If we were to use, for instance, built-in `double`, |
| 307 | then there would be no guarantee that the code would |
| 308 | behave identically on all platforms. With `float64_t` from |
| 309 | `<boost/cstdfloat.hpp>`, however, it is very likely to be identical. |
| 310 | |
| 311 | Using `float64_t`, we know that |
| 312 | this code is as portable as possible and uses a floating-point type |
| 313 | with approximately 15 decimal digits of precision, |
| 314 | regardless of the compiler or version or operating system. |
| 315 | |
| 316 | [cstdfloat_example_1] |
| 317 | [cstdfloat_example_2] |
| 318 | [cstdfloat_example_3] |
| 319 | |
| 320 | For details, see [@../../example/cstdfloat_example.cpp cstdfloat_example.cpp] |
| 321 | - a extensive example program. |
| 322 | |
| 323 | [h3:normal_table Normal distribution table] |
| 324 | |
| 325 | This example shows printing tables of a normal distribution's PDF and CDF, |
| 326 | using `boost::math` implementation of normal distribution. |
| 327 | |
| 328 | A function templated on floating-point type prints a table for a range of standard variate z values. |
| 329 | |
| 330 | The example shows use of the specified-width typedefs to either use a specific width, |
| 331 | or to use the maximum available on the platform, perhaps a high as 128-bit. |
| 332 | |
| 333 | The number of digits displayed is controlled by the precision of the type, |
| 334 | so there are no spurious insignificant decimal digits: |
| 335 | |
| 336 | float_32_t 0 0.39894228 |
| 337 | float_128_t 0 0.398942280401432702863218082711682655 |
| 338 | |
| 339 | Some sample output for two different platforms is appended to the code at |
| 340 | [@../../example/normal_tables.cpp normal_tables.cpp]. |
| 341 | |
| 342 | [normal_table_1] |
| 343 | |
| 344 | [endsect] [/section:examples examples] |
| 345 | |
| 346 | [section:float128_hints Hints on using float128 (and __float128)] |
| 347 | |
| 348 | [h5:different_float128 __float128 versus float128] |
| 349 | * __float128 is the (optionally) compiler supplied hardware type, |
| 350 | it's an C-ish extension to C++ and there is only |
| 351 | minimal support for it in normal C++ |
| 352 | (no IO streams or `numeric_limits` support, |
| 353 | function names in libquadmath all have different names to the |
| 354 | `std::` ones etc.) |
| 355 | So you can program type `__float128` directly, but it's harder work. |
| 356 | |
| 357 | * Type `float128` uses __float128 and makes it C++ and generic code friendly, |
| 358 | with all the usual standard `iostream`, `numeric_limits`, `complex` in namspace `std::` available, |
| 359 | so strongly recommended for C++ use. |
| 360 | |
| 361 | [h5 Hints and tips] |
| 362 | |
| 363 | * Make sure you declare variables with the correct type, here `float128`. |
| 364 | * Make sure that if you pass a variable to a function then it is casted to `float128`. |
| 365 | * Make sure you declare literals with the correct suffix - otherwise |
| 366 | they'll be treated as type `double` with catastrophic loss of precision. |
| 367 | So make sure they have a Q suffix for 128-bit floating-point literals. |
| 368 | * All the std library functions, cmath functions, plus all the constants, and special |
| 369 | functions from Boost.Math should then just work. |
| 370 | * Make sure std lib functions are called [*unqualified] so that the correct |
| 371 | overload is found via __ADL. So write |
| 372 | sqrt(variable) |
| 373 | and not |
| 374 | std::sqrt(variable). |
| 375 | * In general, try not to reinvent stuff - using constants from |
| 376 | Boost.Math is probably less error prone than declaring your own, |
| 377 | likewise the special functions etc. |
| 378 | |
| 379 | Some examples of what can go horribly and silently wrong are at |
| 380 | [@../../example/float128_example.cpp float128_example.cpp]. |
| 381 | |
| 382 | [endsect] [/section:float128_hints Hints on using float128] |
| 383 | |
| 384 | [section:float128 Implementation of Float128 type] |
| 385 | |
| 386 | Since few compilers implement a true 128-bit floating-point, and language features like the suffix Q |
| 387 | (which may need an option `-fext-numeric-literals` to enable), |
| 388 | and C++ Standard library functions are as-yet missing or incomplete in C++11, |
| 389 | this Boost.Math implementation wraps `__float128` provided by the GCC compiler |
| 390 | [@https://gcc.gnu.org/onlinedocs/gcc/Floating-Types.html GCC floating-point types] |
| 391 | or the `_Quad` type provided by the Intel compiler. |
| 392 | |
| 393 | This is provided to in order to demonstrate, and users to evaluate, the feasibility and benefits of higher-precision floating-point, |
| 394 | especially to allow use of the full <cmath> and Boost.Math library of functions and distributions at high precision. |
| 395 | |
| 396 | (It is also possible to use Boost.Math with Boost.Multiprecision decimal and binary, but since these are entirely software solutions, |
| 397 | allowing much higher precision or arbitrary precision, they are likely to be slower). |
| 398 | |
| 399 | We also provide (we believe full) support for `<limits>, <cmath>`, I/O stream operations in `<iostream>`, and `<complex>`. |
| 400 | |
| 401 | As a prototype for a future C++ standard, we place all these in `namespace std`. |
| 402 | This contravenes the existing C++ standard of course, so selecting any compiler that promises to check conformance will fail. |
| 403 | |
| 404 | [tip For GCC, compile with `-std=gnu++11` or `-std=gnu++03` and do not use `-std=stdc++11` or any 'strict' options, as |
| 405 | these turn off full support for `__float128`. These requirements also apply to the Intel compiler on Linux, for |
| 406 | Intel on Windows you need to compile with `-Qoption,cpp,--extended_float_type -DBOOST_MATH_USE_FLOAT128` in order to |
| 407 | activate 128-bit floating point support.] |
| 408 | |
| 409 | The `__float128` type is provided by the [@http://gcc.gnu.org/onlinedocs/libquadmath/ libquadmath library] on GCC or |
| 410 | by Intel's FORTRAN library with Intel C++. THey also provide a full set of `<cmath>` functions in `namespace std`. |
| 411 | |
| 412 | [h4 Using C __float128 quadmath type] |
| 413 | |
| 414 | [quadmath_snprintf_1] |
| 415 | |
| 416 | The source code is at [@../../example/quadmath_snprintf.c quadmath_snprintf.c]. |
| 417 | |
| 418 | [h4 Using C++ `float128` quadmath type] |
| 419 | |
| 420 | For C++ programs, you will want to use the C++ type `float128` |
| 421 | |
| 422 | See example at [@../../example/cstdfloat_example.cpp cstdfloat_example.cpp]. |
| 423 | |
| 424 | A typical invocation of the compiler is |
| 425 | |
| 426 | g++ -O3 -std=gnu++11 test.cpp -I/c/modular-boost -lquadmath -o test.exe |
| 427 | |
| 428 | [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.] |
| 429 | |
| 430 | g++ -O3 -std=gnu++11 test.cpp -I/c/modular-boost/libs/math/include -I/c/modular-boost -lquadmath -o test.exe |
| 431 | |
| 432 | [note So far, the only missing detail that we had noted was in trying to use `<typeinfo>`, |
| 433 | for example for `std::cout << typeid<__float_128>.name();`. |
| 434 | `` |
| 435 | Link fails: undefined reference to typeinfo for __float128. |
| 436 | `` |
| 437 | See [@http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43622 GCC Bug 43622 - no C++ typeinfo for __float128]. |
| 438 | But this is reported (Marc Glisse 2015-04-04 ) fixed in GCC 5 (and above). |
| 439 | |
| 440 | For example, with GCC6.1.1 this works as expected to a [*mangled] string name, and output (if possible - not always). |
| 441 | `` |
| 442 | const std::type_info& tifu128 = typeid(__float128); // OK. |
| 443 | //std::cout << tifu128.name() << std::endl; // On GCC, aborts (because not printable string). |
| 444 | //std::cout << typeid(__float128).name() << std::endl; // Aborts - string name cannot be output. |
| 445 | |
| 446 | const std::type_info& tif128 = typeid(float128); // OK. |
| 447 | std::cout << tif128.name() << std::endl; // OK. |
| 448 | std::cout << typeid(float128).name() << std::endl; // OK. |
| 449 | |
| 450 | 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) |
| 451 | std::cout << tpi.name() << std::endl; // Output mangled name: |
| 452 | |
| 453 | // N5boost14multiprecision6numberINS0_8backends16float128_backendELNS0_26expression_template_optionE0EEE |
| 454 | |
| 455 | `` |
| 456 | ] [/note] |
| 457 | |
| 458 | [section:overloading Overloading template functions with float128_t] |
| 459 | |
| 460 | An artifact of providing C++ standard library support for |
| 461 | quadmath may mandate the inclusion of `<boost/cstdfloat.hpp>` |
| 462 | [*before] the inclusion of other headers. |
| 463 | |
| 464 | Consider a function that calls `fabs(x)` and has previously injected `std::fabs()` |
| 465 | into local scope via a `using` directive: |
| 466 | |
| 467 | template <class T> |
| 468 | bool unsigned_compare(T a, T b) |
| 469 | { |
| 470 | using std::fabs; |
| 471 | return fabs(a) == fabs(b); |
| 472 | } |
| 473 | |
| 474 | In this function, the correct overload of `fabs` may be found via |
| 475 | [@http://en.wikipedia.org/wiki/Argument-dependent_name_lookup argument-dependent-lookup (ADL)] |
| 476 | or by calling one of the `std::fabs` overloads. There is a key difference between them |
| 477 | however: an overload in the same namespace as T and found via ADL need ['[*not be defined at the |
| 478 | time the function is declared]]. However, all the types declared in `<boost/cstdfloat.hpp>` are |
| 479 | fundamental types, so for these types we are relying on finding an overload declared in namespace `std`. |
| 480 | In that case however, ['[*all such overloads must be declared prior to the definition of function |
| 481 | `unsigned_compare` otherwise they are not considered]]. |
| 482 | |
| 483 | In the event that `<boost/cstdfloat.hpp>` has been included [*after] the |
| 484 | definition of the above function, the correct overload of `fabs`, while present, is simply |
| 485 | not considered as part of the overload set. |
| 486 | So the compiler tries to downcast the `float128_t` argument first to |
| 487 | `long double`, then to `double`, then to `float`; |
| 488 | the compilation fails because the result is ambiguous. |
| 489 | However the compiler error message will appear cruelly inscrutable, |
| 490 | at an apparently irelevant line number and making no mention of `float128`: |
| 491 | the word ['ambiguous] is the clue to what is wrong. |
| 492 | |
| 493 | Provided you `#include <boost/cstdfloat.hpp>` [*before] the inclusion |
| 494 | of the any header containing generic floating point code (such as other |
| 495 | Boost.Math headers, then the compiler |
| 496 | will know about and use the `std::fabs(std::float128_t)` |
| 497 | that we provide in `#include <boost/cstdfloat.hpp>`. |
| 498 | |
| 499 | [endsect] |
| 500 | |
| 501 | [section:exp_function Exponential function] |
| 502 | |
| 503 | There was a bug when using any quadmath `expq` function on GCC : |
| 504 | [@http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60349 GCC bug #60349] |
| 505 | caused by |
| 506 | [@http://sourceforge.net/p/mingw-w64/bugs/368/ mingw-64 bug #368]. |
| 507 | |
| 508 | To work round this defect, an alternative implementation of 128-bit exp |
| 509 | was temporarily provided by `boost/cstdfloat.hpp`. |
| 510 | |
| 511 | The mingw bug was fixed at 2014-03-12 and GCC 6.1.1 now works as expected. |
| 512 | |
| 513 | [tip It is essential to link to the quadmath library]. |
| 514 | |
| 515 | [endsect] [/section:exp_function exp function] |
| 516 | |
| 517 | [section:typeinfo `typeinfo`] |
| 518 | |
| 519 | For GCC 4.8.1 it was not yet possible to use `typeinfo` for `float_128` on GCC: |
| 520 | see [@http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43622 GCC 43622]. |
| 521 | |
| 522 | So this code (to display the mangled name) |
| 523 | failed to link `undefined reference to typeinfo for __float128` |
| 524 | |
| 525 | std::cout << typeid(boost::float128_t).name() << std::endl; |
| 526 | |
| 527 | This prevent using the existing tests for Boost.Math distributions, |
| 528 | (unless a few lines are commented out) |
| 529 | and if a MACRO BOOST_MATH_INSTRUMENT controlling them is defined |
| 530 | then some diagnostic displays in Boost.Math will not work. |
| 531 | |
| 532 | However this was only used for display purposes |
| 533 | and could be commented out until this was fixed in GCC 5. |
| 534 | |
| 535 | [tip Not all managed names can be [*displayed] using `std::cout`.] |
| 536 | |
| 537 | [endsect] [/section:typeinfo `typeinfo`] |
| 538 | |
| 539 | |
| 540 | [endsect] [/section:float128 Float128 type] |
| 541 | |
| 542 | [/ cstdfloat.qbk |
| 543 | Copyright 2014 Christopher Kormanyos, John Maddock and Paul A. Bristow. |
| 544 | Distributed under the Boost Software License, Version 1.0. |
| 545 | (See accompanying file LICENSE_1_0.txt or copy at |
| 546 | http://www.boost.org/LICENSE_1_0.txt). |
| 547 | ] |
| 548 | |
| 549 | |
| 550 | |
| 551 | |