Hi Clive,
many thanks for your information.
[Clive wrote:]
> Firstly, annex F does not apply to all implementations - it's an
> optional extra.
Oh... I didn't know that it was an optional feature :(
From a numerical analyst point of view, I guess this feature
makes definitively sense...
> Secondly, the requirements on conversion of constants are, um,
> complicated (they took an awful lot of discussion time in WG14
> meetings).
> Putting a constant like that is not sufficient. At the very
> least, if IEEE754 applies, you should be using a hex constant not
> a decimal one.
Now I understand why the internal functions of libm uses hex
constants to e.g. compare values...
> C99 6.4.4.2:
> [#3] [...]
> For decimal floating constants, and also for hexadecimal
> floating constants when FLT_RADIX is not a power of 2, the
> result is either the nearest representable value, or the
> larger or smaller representable value immediately adjacent
> to the nearest representable value, chosen in an
> implementation-defined manner. For hexadecimal floating
> constants when FLT_RADIX is a power of 2, the result is
> correctly rounded.
The formalism looks complicated, but it is quite simple in reality.
This § just says that if a number can't be exactly represented in
base 2 (the natural base of a computer), the rounding is up to the
implementation.
An illustration using the human base "10":
How is represented the constant 2.0/3, assuming that the
representation allows 5 places?
2.0/3 = 0.66666666...
This § says that the convertion will be either 0.66666 or 0.66667,
and that the outcome is implementation specific.
The only difference between this simple example and this §
is that computer uses base 2, not 10. But the principle is the same.
So you can easily deduce that the "last bit" might differ between
2 ISO C99 representation, even if IEEE754 is used.
That's at least my understanding...
An interesting point here: in <math.h> the constants M_E,
M_PI etc. are sometimes #define'd in decimal, even on a C99
implementation using IEEE754:
# define M_E 2.7182818284590452354 /* e */
# define M_LOG2E 1.4426950408889634074 /* log_2 e */
# define M_LOG10E 0.43429448190325182765 /* log_10 e */
[...]
This would means that such a <math.h> is deficient!!! Should we
submit an ardvaark on this issue???
> > I guess, you have understand the problem here. The fact is that
> > the coefficient is a constant (in the C99 sense). However, I can't
> > initialize it to 1.0 / sqrt (2 * M_PI), because the compiler will
> > issue something like:
> >
> > "error: initializer element is not constant"
>
> Of course. So my code initializes it on the first call and then uses
> that value on all subsequent calls.
That was perfectly clear ;-) That's why I said "you have understand
the problem".
> > If you don't want to have the value hard-coded, you could declare
> > the coefficient "c" as:
> >
> > const double c = (M_SQRT2 * M_2_SQRTPI) / 4;
> >
> > Ok, I agree that's hard to recognize the 1.0/sqrt(2*pi), so comments
> > are definitively needed.
>
> Those constants aren't in the C Standard so I can't check them.
I beg your pardon?? They are are defined in <math.h>, see
XBD / <math.h> of this SUS.
Regards,
Loic.
--
+++ GMX - Mail, Messaging & more http://www.gmx.net +++
Jetzt ein- oder umsteigen und USB-Speicheruhr als Prämie sichern!
|