Mail Archives: djgpp-workers/2000/05/12/07:12:59
I have a few comments and questions about the math functions in
DJGPP. The intention is, that I have contributed a math library to
the DJGPP project in 1994. It got lost somehow, but I may update it.
It has the long double versions of the most math functions. While
looking at the current math functions in libc, I see, that it tries
hard to find special arguments and domain errors, and sets errno. The
setting of errno seems not to be required by the latest C Standard.
Is the setting of errno really wanted for DJGPP?
To me, it seems redundant, because the error can already be detected
by the return value.
The checking code for the mathfunctions silently loads a NaN into the
top of the FPU-stack, when a domain error occures. This has IHMO a
significant disadvantage. When setting up the FPU control word, to
get exceptions for (say) overflow, div by zero and invalid (which I
find useful while debugging), the functions won't raise that
exception. So the error may be detected much later, than the point
were it occured, or even slip by undetected.
An example would be the following code:
#include <stdio.h>
#include <math.h>
double my_log(double x)
{
double y;
/* Is there a way, to tell gcc, that we need two registers in the
FPU? This question may be important when the function gets inlined.
Alternatively, in the input list one could set
: "t" (x), "u" (LN2)
but then, we "loose" one register with fyl2x. Is there a way to tell
this to gcc?
*/
__asm__ volatile(
"fldln2 \n"
"fldl %1 \n"
"fyl2x \n"
: "=t" (y)
: "m" (x));
return y;
}
int main(void)
{
double nan;
volatile short cw = 0x1372; /* exceptions for invalid, div by zero
and overflow unmasked */
__asm__ volatile("fldcw %0" : : "m" (cw)); /* Portable to x86 linux
*/
nan = log(x); /* No exception, using my_log yields an exception */
printf("%g\n", nan); /* Exception here, which probably should not
happen */
return 0;
}
So, I think, the easier implementation of my_log is preferrable. It
will always return the same values, but won't set errno.
(my_log should probably be coded as an .S, because of lack of
documentation for inline assembly with x87-FPU.)
Anyway, is there interest in long double versions of the math
functions?
Do you prefer, to not raise exceptions?
What I have right now, works with DJGPP 1.x. It is quite fast and
well tested. To update it for DJGPP 2.x, probably needs only some
header hacking, to appreciate the new C Standard.
Some functions are a compromise between correctness up to the last
bit and speed. I.e. the argument reduction code for the trig
functions is not as sophisticated as the argument reduction code in
libm, but uses additional precision for intermediate results (from
Stephen Moshiers cephes), and can be much faster than the
corresponding code in libm. Similar for powl. I also have functions,
that are missing right now, like expm1[l] or log1p[l], rint[l] ...
--
Regards, Dieter Buerssner
- Raw text -