diff --git a/doc/cstdfloat/cstdfloat.qbk b/doc/cstdfloat/cstdfloat.qbk index d828ac67b..f3894d885 100644 --- a/doc/cstdfloat/cstdfloat.qbk +++ b/doc/cstdfloat/cstdfloat.qbk @@ -1,18 +1,25 @@ - [/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] + [section:overview Overview] The header `` 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 ``. -All `typedef`s are in `namespace boost`. +These `typedef`s are the floating-point analog of specified-width integers in `` and `stdint.h`. + +The `typedef`s are based on __N3626 +proposed for a new C++14 standard header `` and +__N1703 proposed for a new C language standard header ``. + +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, @@ -24,44 +31,20 @@ The underlying types of these `typedef`s must conform with the corresponding specifications of binary16, binary32, binary64, and binary128 in __IEEE754 floating-point format. -The `typedef`s are based on __N3626 -proposed for a new C++14 standard header `` and -__N1703 proposed for a new C language standard header ``. - -The 128-bit floating-point type, of great interest in scientific and -numeric programming, is not required in the Boost header, +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. -The following code uses `` in combination with -`` to compute a simplified -version of the 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 -``, however, it is very likely to be identical. +See [link float_t.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 float_t.examples.normal_table normal distribution] +an example of a statistical distribution from Boost.Math -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. - - #include - #include - #include - - boost::float64_t jahnke_emden_lambda(boost::float64_t v, boost::float64_t x) - { - const boost::float64_t gamma_v_plus_one = boost::math::tgamma(v + 1); - const boost::float64_t x_half_pow_v = std::pow(x /2, v); - - return gamma_v_plus_one * boost::math::cyl_bessel_j(x, v) / x_half_pow_v; - } - -See `cstdfloat_test.cpp` for a more detailed test program. - -[endsect] [/section:overview Overview] +[endsect] [/section:overview Overview] [section:rationale Rationale] @@ -74,26 +57,27 @@ An unequivocal test regarding 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 implementation `` -supports an 80-bit floating-point `typedef` if this can be detected -and if the underlying type conforms with +In addition, this Boost implementation `` +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] (if`std::numeric_limits<>::is_iec559` is true for this type). The header `` 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++ Standard Library that may contain these `typedef`s. -Should some future C++ standard include `` and ``, +with a potential future C/C++ Standard Library that may contain these `typedef`s. +Should some future C/C++ standard include `` and ``, then `` will continue to function, but will become redundant and may be safely deprecated. -Because `` is a boost header, its name conforms to the +Because `` is a Boost header, its name conforms to the boost header naming conventions, not the C++ Standard Library header naming conventions. [note - [*cannot synthesize or create +`` [*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), @@ -101,7 +85,7 @@ then `float128_t` and its corresponding least and fast types are not provided by `.] [warning If `` uses a compiler-specific non-standardized type -[*not] derived from `float, double,` or `long double`) for one or more +([*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. Specializations of `numeric_limits<>` will only be available for these @@ -114,6 +98,22 @@ may possibly be visible to users of ``. 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, `` should be `#include`d before +other headers like ``. + +In addition to detecting and type defining built-in types +such as `float`, `double`, and `long double`, `` +may also detect compiler-specific floating-point type(s) +and subsequently type define these to floating-point types +having specified widths in `namespace boost`. When this occurs, +and `` type defines such a non-built-in type to +one of` boost::float16_t, boost::float32_t, boost::float80_t, or +boost::float128_t`, it might lead to ambiguous symbols for certain +`` functions in `namespace std`. See implementation for more details. + +For this reason, making `#include ` the [*first +include] is usually best. +] [endsect] [/section:rationale Rationale] [section:exact_typdefs Exact-Width Floating-Point `typedef`s] @@ -127,13 +127,71 @@ 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, 128 bits, or any combination thereof, +16, 32, 64, 80, 128 bits, or any combination thereof, then `` 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. -The absence of `float128_t` is indicated by the macro `BOOST_NO_FLOAT128_T`. +[h4 How to tell which widths are supported] + +The definition (or not) of a +[link float_t.macros floating-point constant macro] +is the way to test if a specific width is available on a platform. + + #if defined(BOOST_FLOAT16_C) + // Can use boost::float16_t. + #endif + + #if defined(BOOST_FLOAT32_C) + // Can use boost::float32_t. + #endif + + #if defined(BOOST_FLOAT64_C) + // Can use boost::float64_t. + #endif + + #if defined(BOOST_FLOAT80_C) + // Can use boost::float80_t. + #endif + + #if defined(BOOST_FLOAT128_C) + // Can use boost::float128_t. + #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::digits + +and from this one can safely infer the total number of bits because the type must be IEEE754 format, +so, for example, if `std::numeric_limits::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::digits10 + +and the maximum number of possibly significant decimal digits using + + std::numeric_limits::max_digits10 + +[tip `max_digits10` is not always supported, but can be calculated at compile-time using the Kahan formula. +A function `boost::math::max_digits10` is provided that works correctly on all compilers.] + +[note One could test + + std::is_same::value == true + +but this would fail to compile on a platform where `boost::float128_t` is not defined. +So use the MACROs BOOST_FLOATnnn_C. ] [endsect] [/section:exact_typdefs Exact-Width Floating-Point `typedef`s] @@ -172,33 +230,199 @@ then `float_fast32_t` and `float_fast64_t` will also be supported, etc. [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. +any value of any floating-point type in a given platform most precisely. -The greatest-width typedef is provided for all platforms. +The greatest-width `typedef` is provided for all platforms, but, of course, the size may vary. + +To provide floating-point [*constants] most precisely possible 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` is supported). + +If we display with `maxdigits10`, the maximum possibly significant decimal digits: + +[floatmax_widths_1] + +then on a 128-bit platform (GCC 4.8.1. 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, BOOST_FLOATMAX_C` -are always defined after inclusion of -``. +BOOST_FLOAT80_C, BOOST_FLOAT128_C, ` and `BOOST_FLOATMAX_C` +are always defined after inclusion of ``. -These allow floating-point [*constants of at least the specified width] to be declared. +[cstdfloat_constant_2] -For example: +[tip Boost.Math provides many constants 'built-in', so always use Boost.Math constants if available, for example:] - #include +[cstdfloat_constant_1] - // Declare Pythagoras' constant with approximately 7 decimal digits of precision. - static const boost::float32_t pi = BOOST_FLOAT32_C(3.1415926536); - - // Declare the Euler-gamma constant with approximately 34 decimal digits of precision. - static const boost::float128_t euler = BOOST_FLOAT128_C(0.57721566490153286060651209008240243104216); +from [@../../../example/cstdfloat_example.cpp cstdfloat_example.cpp]. [endsect] [/section:macros Floating-Point Constant Macros] +[section:examples Examples] + +[h3:je_lambda Jahnke-Emden-Lambda function] + +This is example has already be used as an example of using `float_t typedefs` +and CMath and Boost.Math functions. + +The following code uses `` in combination with +`` 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 +``, 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` implmentation of normal. + +A function templated on floating-point type prints a table for a range of 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 Implementation of Float128 type] + +Since few compilers implement 128-bit floating-point, and the language features like suffix Q, +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. + +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 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 `, `, I/O stream operations in ``, and ``. + +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, use `-std=gnu++11` explicitly, and do not use `-std=stdc++11`, and do not use any 'strict' options.] + +The `__float128` type is provided by the [@http://gcc.gnu.org/onlinedocs/libquadmath/ libquadmath library]. + +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 have noted is in trying to use ``, 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].] + +[section Overloading template functions with float128_t] + +An artifact of providing C++ standard library support for +quadmath may mandate the inclusion of `` +[*above] the inclusion of other headers. + +Function-providing header-files like `` make heavy use of template programming +and the `using` directive to inject numerous `` functions into the +local scope of a function. + +Consider a function that calls `fabs(x)` and has previously injected `std::fabs()` +into function scope via a `using` directive. + +For example, a floating-point comparison code generates heavy +template instantiations using `std::fabs()` from `` +(and perhaps other similar headers files providing functions). +But at the time of instantiation, the [*compiler does not yet know] +that there is an overload of, say, `std::fabs(std::float128_t)`. + +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 ` [*above] the inclusion +of the floating-point comparison header, then the compiler +will know about `std::fabs(std::float128_t)`. This is because +we inject these overloads into the `namespace std` in the +`/detail` headers of ``. +[endsect] + +[section:exp_function Exponential function] + +There is a bug whe using any quadmath `expq` function on GCC: + +[@http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60349 GCC bug #60349] + +[@http://sourceforge.net/p/mingw-w64/bugs/368/ mingw-64 bug #368] + +To work round this defect, an alternative implementation of 128-bit exp +is temporarily provided by `boost/cstdfloat.hpp`. + +[endsect] [/section:exp_function exp function] + +[section:typeinfo `typeinfo`] + +It is 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 fails 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 is only used for display purposes and can be commented out until this is fixed. + +[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. diff --git a/doc/cstdfloat/cstdfloat_header.qbk b/doc/cstdfloat/cstdfloat_header.qbk index aeb44f017..2a4d7e9f4 100644 --- a/doc/cstdfloat/cstdfloat_header.qbk +++ b/doc/cstdfloat/cstdfloat_header.qbk @@ -1,4 +1,5 @@ [article Standardized Floating-Point typedefs for C and C++ + [id float_t] [quickbook 1.6] [copyright 2014 Christopher Kormanyos, John Maddock, Paul A. Bristow] [license diff --git a/doc/cstdfloat/jamfile.v2 b/doc/cstdfloat/jamfile.v2 index f0be5d808..0e0c24227 100644 --- a/doc/cstdfloat/jamfile.v2 +++ b/doc/cstdfloat/jamfile.v2 @@ -1,7 +1,7 @@ # Boost.cstdfloat documentation Jamfile.v2 # # Copyright Paul A. Bristow 2014. -# Use, modification and distribution is subject to +# Use, modification and distribution is subject to # 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) @@ -27,83 +27,82 @@ boostbook standalone : cstdfloat : - + # General settings # ================= - # Path for links to Boost folder, for example: boost_1_55_0 or boost-trunk, relative to folder /doc/html. + # Path for links to Boost folder, for example: boost_1_55_0 or boost-trunk, relative to folder /doc/html. boost.root=../../../../.. # Path for libraries index: - boost.libraries=../../../../../../libs/libraries.htm + boost.libraries=../../../../../../libs/libraries.htm - # Or a local custom stylesheet: - #html.stylesheet=boostbook.css - html.stylesheet=boostbook.css + # Or a local custom stylesheet: + #html.stylesheet=boostbook.css + html.stylesheet=math.css - #nav.layout=none # No navigation bar (home, prev, next). - # Defining creates a runtime error: Global parameter nav.layout already defined. - nav.layout=horizontal # to get a horizontal navigation bar (you probably DO want this). + #nav.layout=none # No navigation bar (home, prev, next). + # Defining creates a runtime error: Global parameter nav.layout already defined. + nav.layout=horizontal # to get a horizontal navigation bar (you probably DO want this). - # Path for links to Boost logo. - #boost.image=Boost # options are: none (no logo), Boost (for boost.png), or your own logo, for example, inspired_by_boost.png - #boost.image.src=boost.png # - #boost.image.w=180 # Width of logo in pixels. (JM has W = 162, h = 46) + # Path for links to Boost logo. + #boost.image=Boost # options are: none (no logo), Boost (for boost.png), or your own logo, for example, inspired_by_boost.png + #boost.image.src=boost.png # + #boost.image.w=180 # Width of logo in pixels. (JM has W = 162, h = 46) #boost.image.h=90 # Height of logo in pixels. - + # Some general style settings: - table.footnote.number.format=1 - footnote.number.format=1 + table.footnote.number.format=1 + footnote.number.format=1 - # HTML options first: - # Use graphics not text for navigation: - navig.graphics=1 - # How far down we chunk nested sections, basically all of them: - chunk.section.depth=10 - # Don't put the first section on the same page as the TOC: - chunk.first.sections=1 - # How far down sections get TOC's - toc.section.depth=10 - # Max depth in each TOC: - toc.max.depth=4 - # How far down we go with TOC's - generate.section.toc.level=10 - # Index on type: - index.on.type=1 - boost.noexpand.chapter.toc=1 + # HTML options first: + # Use graphics not text for navigation: + navig.graphics=1 + # How far down we chunk nested sections, basically all of them: + chunk.section.depth=10 + # Don't put the first section on the same page as the TOC: + chunk.first.sections=1 + # How far down sections get TOC's + toc.section.depth=10 + # Max depth in each TOC: + toc.max.depth=4 + # How far down we go with TOC's + generate.section.toc.level=10 + # Index on type: + index.on.type=1 + boost.noexpand.chapter.toc=1 - #root.filename="sf_dist_and_tools" - #graphicsize.extension=1 - #use.extensions=1 + #root.filename="sf_dist_and_tools" + #graphicsize.extension=1 + #use.extensions=1 - # PDF Options: - # TOC Generation: this is needed for FOP-0.9 and later: - fop1.extensions=0 - pdf:xep.extensions=1 - # TOC generation: this is needed for FOP 0.2, but must not be set to zero for FOP-0.9! - pdf:fop.extensions=0 - pdf:fop1.extensions=0 - # No indent on body text: - pdf:body.start.indent=0pt - # Margin size: - pdf:page.margin.inner=0.5in - # Margin size: - pdf:page.margin.outer=0.5in - # Paper type = A4 - pdf:paper.type=A4 - # Yes, we want graphics for admonishments: - admon.graphics=1 - # Set this one for PDF generation *only*: - # default pnd graphics are awful in PDF form, - # better use SVG's instead: - pdf:admon.graphics.extension=".svg" - pdf:use.role.for.mediaobject=1 - pdf:preferred.mediaobject.role=print - pdf:img.src.path=$(images_location)/ - pdf:draft.mode="no" - pdf:boost.url.prefix=http://www.boost.org/doc/libs/release/libs/math/doc/html - pdf:index.on.type=1 + # PDF Options: + # TOC Generation: this is needed for FOP-0.9 and later: + fop1.extensions=0 + pdf:xep.extensions=1 + # TOC generation: this is needed for FOP 0.2, but must not be set to zero for FOP-0.9! + pdf:fop.extensions=0 + pdf:fop1.extensions=0 + # No indent on body text: + pdf:body.start.indent=0pt + # Margin size: + pdf:page.margin.inner=0.5in + # Margin size: + pdf:page.margin.outer=0.5in + # Paper type = A4 + pdf:paper.type=A4 + # Yes, we want graphics for admonishments: + admon.graphics=1 + # Set this one for PDF generation *only*: + # default pnd graphics are awful in PDF form, + # better use SVG's instead: + pdf:admon.graphics.extension=".svg" + pdf:use.role.for.mediaobject=1 + pdf:preferred.mediaobject.role=print + pdf:img.src.path=$(images_location)/ + pdf:draft.mode="no" + pdf:boost.url.prefix=http://www.boost.org/doc/libs/release/libs/math/doc/html + pdf:index.on.type=1 ; - - + install pdf-install : standalone : PDF . cstdfloat.pdf ;