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 14The header `<boost/cstdfloat.hpp>` provides [*optional] 15standardized floating-point `typedef`s having [*specified widths]. 16These are useful for writing portable code because they 17should behave identically on all platforms. 18These `typedef`s are the floating-point analog of specified-width integers in `<cstdint>` and `stdint.h`. 19 20The `typedef`s are based on __N3626 21proposed for a new C++14 standard header `<cstdfloat>` and 22__N1703 proposed for a new C language standard header `<stdfloat.h>`. 23 24All `typedef`s are in `namespace boost` (would be in namespace `std` if eventually standardized). 25 26The `typedef`s include `float16_t, float32_t, float64_t, float80_t, float128_t`, 27their corresponding least and fast types, 28and the corresponding maximum-width type. 29The `typedef`s are based on underlying built-in types 30such as `float`, `double`, or `long double`, or the proposed __short_float, 31or based on other compiler-specific non-standardized types such as `__float128`. 32The underlying types of these `typedef`s must conform with 33the corresponding specifications of binary16, binary32, binary64, 34and binary128 in __IEEE754 floating-point format, and 35`std::numeric_limits<>::is_iec559 == true`. 36 37The 128-bit floating-point type (of great interest in scientific and 38numeric programming) is not required in the Boost header, 39and may not be supplied for all platforms/compilers, because compiler 40support for a 128-bit floating-point type is not mandated by either 41the C standard or the C++ standard. 42 43If 128-bit floating-point is supported, then including `boost/cstdfloat.hpp` 44provides a [*native] 128-bit type, and 45includes other headers in folder `boost/math/cstdfloat` that provide C++ 46quad support for __C_math in `<cmath>`, `<limits>`, `<iostream>`, `<complex>`, 47and the available floating-point types. 48 49One can also, more robustly, include `boost/multiprecision/float128.hpp` 50and this provides a thin wrapper selecting the appropriate 128-bit native type 51from `cstdfloat` if available, or else a 128-bit multiprecision type. 52 53See [link math_toolkit.examples.je_lambda Jahnke-Emden-Lambda function example] 54for an example using both a `<cmath>` function and a Boost.Math function 55to evaluate a moderately interesting function, the 56[@http://mathworld.wolfram.com/LambdaFunction.html Jahnke-Emden-Lambda function] 57and [link math_toolkit.examples.normal_table normal distribution] 58as an example of a statistical distribution from Boost.Math. 59 60[endsect] [/section:specified_typedefs Overview] 61 62[section:rationale Rationale] 63 64The implementation of `<boost/cstdfloat.hpp>` is designed to utilize `<float.h>`, 65defined in the 1989 C standard. The preprocessor is used to query certain 66preprocessor definitions in `<float.h>` such as FLT_MAX, DBL_MAX, etc. 67Based on the results of these queries, an attempt is made to automatically 68detect the presence of built-in floating-point types having specified widths. 69An 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`] 71is performed with `BOOST_STATIC_ASSERT`. 72 73In addition, this Boost implementation `<boost/cstdfloat.hpp>` 74supports an 80-bit floating-point `typedef` if it can be detected, 75and a 128-bit floating-point `typedef` if it can be detected, 76provided 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 80The header `<boost/cstdfloat.hpp>` makes the standardized floating-point 81`typedef`s safely available in `namespace boost` without placing any names 82in `namespace std`. The intention is to complement rather than compete 83with a potential future C/C++ Standard Library that may contain these `typedef`s. 84Should some future C/C++ standard include `<stdfloat.h>` and `<cstdfloat>`, 85then `<boost/cstdfloat.hpp>` will continue to function, but will become redundant 86and may be safely deprecated. 87 88Because `<boost/cstdfloat.hpp>` is a Boost header, its name conforms to the 89boost header naming conventions, not the C++ Standard Library header 90naming conventions. 91 92[note 93`<boost/cstdfloat.hpp>` [*cannot synthesize or create 94a `typedef` if the underlying type is not provided by the compiler]. 95For example, if a compiler does not have an underlying floating-point 96type with 128 bits (highly sought-after in scientific and numeric programming), 97then `float128_t` and its corresponding least and fast types are [*not] 98provided 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 102of its floating-point `typedef`s, then there is no guarantee that 103specializations of `numeric_limits<>` will be available for these types. 104Typically, specializations of `numeric_limits<>` will only be available for these 105types if the compiler itself supports corresponding specializations 106for the underlying type(s), exceptions are GCC's `__float128` type and 107Intel's `_Quad` type which are explicitly supported via our own code.] 108 109[warning 110As an implementation artifact, certain C macro names from `<float.h>` 111may possibly be visible to users of `<boost/cstdfloat.hpp>`. 112Don't rely on using these macros; they are not part of any Boost-specified interface. 113Use `std::numeric_limits<>` for floating-point ranges, etc. instead.] 114 115[tip For best results, `<boost/cstdfloat.hpp>` should be `#include`d before 116other headers that define generic code making use of standard library functions 117defined in <cmath>. 118 119This is because `<boost/cstdfloat.hpp>` may define overloads of 120standard library functions where a non-standard type (i.e. other than 121`float`, `double`, or `long double`) is used for one of the specified 122width types. If generic code (for example in another Boost.Math header) 123calls a standard library function, then the correct overload will only be 124found if these overloads are defined prior to the point of use. 125See [link math_toolkit.float128.overloading overloading template functions with float128_t] 126and the implementation of `cstdfloat.hpp` for more details. 127 128For this reason, making `#include <boost/cstdfloat.hpp>` the [*first 129include] is usually best. 130] 131[endsect] [/section:rationale Rationale] 132 133[section:exact_typdefs Exact-Width Floating-Point `typedef`s] 134 135The `typedef float#_t`, with # replaced by the width, designates a 136floating-point type of exactly # bits. For example `float32_t` denotes 137a single-precision floating-point type with approximately 1387 decimal digits of precision (equivalent to binary32 in __IEEE754). 139 140Floating-point types in C and C++ are specified to be allowed to have 141(optionally) implementation-specific widths and formats. 142However, if a platform supports underlying 143floating-point types (conformant with __IEEE754) with widths of 14416, 32, 64, 80, 128 bits, or any combination thereof, 145then `<boost/cstdfloat.hpp>` does provide the corresponding `typedef`s 146`float16_t, float32_t, float64_t, float80_t, float128_t,` 147their corresponding least and fast types, 148and the corresponding maximum-width type. 149 150[h4 How to tell which widths are supported] 151 152The definition (or not) of a 153[link math_toolkit.macros floating-point constant macro] 154is 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 179This can be used to write code which will compile and run (albeit differently) on several platforms. 180Without 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 183The number of bits in just the significand can be determined using: 184 185 std::numeric_limits<boost::floatmax_t>::digits 186 187and 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`, 189so, for example, if `std::numeric_limits<boost::floatmax_t>::digits == 113`, 190then `floatmax_t` must be` float128_t`. 191 192The [*total] number of bits using `floatmax_t` can be found thus: 193 194[floatmax_1] 195 196and the number of 'guaranteed' decimal digits using 197 198 std::numeric_limits<boost::floatmax_t>::digits10 199 200and 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, 205but 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 214but this would fail to compile on a platform where `boost::float128_t` is not defined. 215So 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 221The `typedef float_least#_t`, with # replaced by the width, designates a 222floating-point type with a [*width of at least # bits], such that no 223floating-point type with lesser size has at least the specified width. 224Thus, `float_least32_t` denotes the smallest floating-point type with 225a width of at least 32 bits. 226 227Minimum-width floating-point types are provided for all existing 228exact-width floating-point types on a given platform. 229 230For example, if a platform supports `float32_t` and `float64_t`, 231then `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 237The `typedef float_fast#_t`, with # replaced by the width, designates 238the [*fastest] floating-point type with a [*width of at least # bits]. 239 240There is no absolute guarantee that these types are the fastest for all purposes. 241In any case, however, they satisfy the precision and width requirements. 242 243Fastest minimum-width floating-point types are provided for all existing 244exact-width floating-point types on a given platform. 245 246For example, if a platform supports `float32_t` and `float64_t`, 247then `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 253The `typedef floatmax_t` designates a floating-point type capable of representing 254any value of any floating-point type in a given platform most precisely. 255 256The greatest-width `typedef` is provided for all platforms, but, of course, the size may vary. 257 258To provide floating-point [*constants] most precisely representable for a `floatmax_t` type, 259use the macro `BOOST_FLOATMAX_C`. 260 261For example, replace a constant `123.4567890123456789012345678901234567890` with 262 263 BOOST_FLOATMAX_C(123.4567890123456789012345678901234567890) 264 265If, for example, `floatmax_t` is `float64_t` then the result will be equivalent to a `long double` suffixed with L, 266but 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 269If we display with `max_digits10`, the maximum possibly significant decimal digits: 270 271[floatmax_widths_1] 272 273then 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 281All macros of the type `BOOST_FLOAT16_C, BOOST_FLOAT32_C, BOOST_FLOAT64_C, 282BOOST_FLOAT80_C, BOOST_FLOAT128_C, ` and `BOOST_FLOATMAX_C` 283are 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 291from [@../../example/cstdfloat_example.cpp cstdfloat_example.cpp]. 292 293See 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 301The following code uses `<boost/cstdfloat.hpp>` in combination with 302`<boost/math/special_functions.hpp>` to compute a simplified 303version of the 304[@http://mathworld.wolfram.com/LambdaFunction.html Jahnke-Emden-Lambda function]. 305Here, we specify a floating-point type with [*exactly 64 bits] (i.e., `float64_t`). 306If we were to use, for instance, built-in `double`, 307then there would be no guarantee that the code would 308behave identically on all platforms. With `float64_t` from 309`<boost/cstdfloat.hpp>`, however, it is very likely to be identical. 310 311Using `float64_t`, we know that 312this code is as portable as possible and uses a floating-point type 313with approximately 15 decimal digits of precision, 314regardless of the compiler or version or operating system. 315 316[cstdfloat_example_1] 317[cstdfloat_example_2] 318[cstdfloat_example_3] 319 320For details, see [@../../example/cstdfloat_example.cpp cstdfloat_example.cpp] 321- a extensive example program. 322 323[h3:normal_table Normal distribution table] 324 325This example shows printing tables of a normal distribution's PDF and CDF, 326using `boost::math` implementation of normal distribution. 327 328A function templated on floating-point type prints a table for a range of standard variate z values. 329 330The example shows use of the specified-width typedefs to either use a specific width, 331or to use the maximum available on the platform, perhaps a high as 128-bit. 332 333The number of digits displayed is controlled by the precision of the type, 334so there are no spurious insignificant decimal digits: 335 336 float_32_t 0 0.39894228 337 float_128_t 0 0.398942280401432702863218082711682655 338 339Some 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, 350it's an C-ish extension to C++ and there is only 351minimal support for it in normal C++ 352(no IO streams or `numeric_limits` support, 353function names in libquadmath all have different names to the 354`std::` ones etc.) 355So 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, 358with all the usual standard `iostream`, `numeric_limits`, `complex` in namspace `std::` available, 359so 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 366they'll be treated as type `double` with catastrophic loss of precision. 367So 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 369functions from Boost.Math should then just work. 370* Make sure std lib functions are called [*unqualified] so that the correct 371overload is found via __ADL. So write 372 sqrt(variable) 373and not 374 std::sqrt(variable). 375* In general, try not to reinvent stuff - using constants from 376Boost.Math is probably less error prone than declaring your own, 377likewise the special functions etc. 378 379Some 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 386Since 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), 388and C++ Standard library functions are as-yet missing or incomplete in C++11, 389this Boost.Math implementation wraps `__float128` provided by the GCC compiler 390[@https://gcc.gnu.org/onlinedocs/gcc/Floating-Types.html GCC floating-point types] 391or the `_Quad` type provided by the Intel compiler. 392 393This is provided to in order to demonstrate, and users to evaluate, the feasibility and benefits of higher-precision floating-point, 394especially 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, 397allowing much higher precision or arbitrary precision, they are likely to be slower). 398 399We also provide (we believe full) support for `<limits>, <cmath>`, I/O stream operations in `<iostream>`, and `<complex>`. 400 401As a prototype for a future C++ standard, we place all these in `namespace std`. 402This 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 405these turn off full support for `__float128`. These requirements also apply to the Intel compiler on Linux, for 406Intel on Windows you need to compile with `-Qoption,cpp,--extended_float_type -DBOOST_MATH_USE_FLOAT128` in order to 407activate 128-bit floating point support.] 408 409The `__float128` type is provided by the [@http://gcc.gnu.org/onlinedocs/libquadmath/ libquadmath library] on GCC or 410by 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 416The source code is at [@https://gcc.gnu.org/onlinedocs/gcc-9.1.0/libquadmath/quadmath_005fsnprintf.html#quadmath_005fsnprintf quadmath_snprintf.c]. 417 418[h4 Using C++ `float128` quadmath type] 419 420For C++ programs, you will want to use the C++ type `float128` 421 422See example at [@../../example/cstdfloat_example.cpp cstdfloat_example.cpp]. 423 424A 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>`, 433for example for `std::cout << typeid<__float_128>.name();`. 434`` 435Link fails: undefined reference to typeinfo for __float128. 436`` 437See [@http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43622 GCC Bug 43622 - no C++ typeinfo for __float128]. 438But this is reported (Marc Glisse 2015-04-04 ) fixed in GCC 5 (and above). 439 440For example, with GCC6.1.1 this works as expected to a [*mangled] string name, and output (if possible - not always). 441`` 442const 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 446const std::type_info& tif128 = typeid(float128); // OK. 447std::cout << tif128.name() << std::endl; // OK. 448std::cout << typeid(float128).name() << std::endl; // OK. 449 450const 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) 451std::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 460An artifact of providing C++ standard library support for 461quadmath may mandate the inclusion of `<boost/cstdfloat.hpp>` 462[*before] the inclusion of other headers. 463 464Consider a function that calls `fabs(x)` and has previously injected `std::fabs()` 465into 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 474In 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)] 476or by calling one of the `std::fabs` overloads. There is a key difference between them 477however: an overload in the same namespace as T and found via ADL need ['[*not be defined at the 478time the function is declared]]. However, all the types declared in `<boost/cstdfloat.hpp>` are 479fundamental types, so for these types we are relying on finding an overload declared in namespace `std`. 480In that case however, ['[*all such overloads must be declared prior to the definition of function 481`unsigned_compare` otherwise they are not considered]]. 482 483In the event that `<boost/cstdfloat.hpp>` has been included [*after] the 484definition of the above function, the correct overload of `fabs`, while present, is simply 485not considered as part of the overload set. 486So the compiler tries to downcast the `float128_t` argument first to 487`long double`, then to `double`, then to `float`; 488the compilation fails because the result is ambiguous. 489However the compiler error message will appear cruelly inscrutable, 490at an apparently irrelevant line number and making no mention of `float128`: 491the word ['ambiguous] is the clue to what is wrong. 492 493Provided you `#include <boost/cstdfloat.hpp>` [*before] the inclusion 494of the any header containing generic floating point code (such as other 495Boost.Math headers, then the compiler 496will know about and use the `std::fabs(std::float128_t)` 497that we provide in `#include <boost/cstdfloat.hpp>`. 498 499[endsect] 500 501[section:exp_function Exponential function] 502 503There 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] 505caused by 506[@http://sourceforge.net/p/mingw-w64/bugs/368/ mingw-64 bug #368]. 507 508To work round this defect, an alternative implementation of 128-bit exp 509was temporarily provided by `boost/cstdfloat.hpp`. 510 511The 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, for example, in a b2/bjam file: `<linkflags>-lquadmath`]. 514 515[endsect] [/section:exp_function exp function] 516 517[section:typeinfo `typeinfo`] 518 519For GCC 4.8.1 it was not yet possible to use `typeinfo` for `float_128` on GCC: 520see [@http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43622 GCC 43622]. 521 522So this code (to display the mangled name) 523failed to link `undefined reference to typeinfo for __float128` 524 525 std::cout << typeid(boost::float128_t).name() << std::endl; 526 527This prevent using the existing tests for Boost.Math distributions, 528(unless a few lines are commented out) 529and if a MACRO BOOST_MATH_INSTRUMENT controlling them is defined 530then some diagnostic displays in Boost.Math will not work. 531 532However this was only used for display purposes 533and 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 552