
Boost : 
From: Paul A. Bristow (boost_at_[hidden])
Date: 20020906 18:48:12
Thanks to Gaby for these useful references to Floating point formats.
> http://nssdc.gsfc.nasa.gov/nssdc/formats/
>
http://www.tru64unix.compaq.com/docs/base_doc/DOCUMENTATION/V51_HTML/ARH9LBT
E/FLTNGCHP.HTM#fpfmtfig
Under the expert guidance of Sylvain Pion [Sylvain.Pion_at_[hidden]]
I have used NTL, an arbitrary precision to calculate the EXACT
representations
of the intervals of pi for float, double and long double.
As he has eventually persuaded me, it seems necessary to meet the
requirements
of the C++ Standard [2.13.3.1] which says :
" [...] If the scaled value is in the range of representable values for its
type, the result is the scaled value if representable else the larger or
smaller representable value nearest the scaled value, chosen in an
implementationdefined manner. [...] "
to provide sufficient decimal digits = number of significand bits.
These have effectively infinite trailing zeros.
(In practice these don't seem to matter beyond the significant_digits10,
a few more than digits10, give by the formula given by Kahan.
But it might... so for full portability ...)
for 24 bit significand formats:
static const float pi_f_l = 13176794.0f/(1 << 22)
static const float pi_f_u = 13176795.0f/(1 << 22);
or more simply
static const float pi_f_l = 3.141592502593994140625;
static const float pi_f_u = 3.1415927410125732421875;
for double 53 bit significand formats:
static const double pi_d_l =
3.141592653589793115997963468544185161590576171875;
static const double pi_d_u =
3.141592653589793560087173318606801331043243408203125;
pi_d_l = 0x400921fb54442d18
pi_d_u = 0x400921fb54442d19
pi_d = 0x400921fb54442d18  same as lower interval.
and long double 64 bit significand formats:
static const long double pi_l_l = 14488038916154245684.0l/(1 << 62);
static const long double pi_l_u = 14488038916154245685.0l/(1 << 62);
or to avoid your complex format and choking the compiler
static const long double pi_l_l2 =
3.141592653589793238295968524909085317631252110004425048828125;
static const long double pi_l_u2 =
3.14159265358979323851280895940618620443274267017841339111328125;
(These actual values are unchecked as yet!)
Values can be calculated for all useful significands 
mainly IEEE and VAX formats  and selected somehow,
switch or macro as discussed by several people,
using numeric_limits<>::digits, and also radix if desired.
(Are there really any machines using radix other than 2 that we need to
cater for?)
I am warming to the idea of adding intervals
for ALL the math constants discussed previously.
Both the math constants and the interval library
will be VERY MUCH more useful if these are available.
Does this seem a reasonable scheme?
Paul
Dr Paul A Bristow, hetp Chromatography
Prizet Farmhouse, Kendal, Cumbria, LA8 8AB UK
+44 1539 561830 Mobile +44 7714 33 02 04
mailto:pbristow_at_[hidden]
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk