Bug #1877 https://sourceforge.net/p/gnuplot/bugs/1877/
Requests that gnuplot's exponentiation operation A**B
return zero rather than "undefined" in the case of underflow.
I.e. for 0 < A < 1 and very large B.
The gnuplot code base currently has two vestigial mechanisms
for trapping and dealing with floating point exceptions.
eval.c (evaluate_at):
(void) signal(SIGFPE, (sigfunc) fpe);
internal.c (GP_MATHERR):
callback routine for use by SVID math library exception handling
Both of these mechanisms have been deprecated in current standards.
Testing current linux builds of gnuplot shows that neither of these
mechanisms is activated by underflow in practice.
Instead we do a simple-minded test before returning from
evaluate_at():
if (errno == EDOM || errno == ERANGE)
undefined = TRUE;
This works (at least on linux) but does not distinguish between
overflow and underflow.
Question 1: What is the current recommended test for underflow?
------------
As I understand the linux man pages, the recommended replacement
for the deprecated SVID matherr callback mechanism is use of a
C99 macro fpclassify(val). In our case this would look something
like:
val = proposed_return_from_evaluate;
int fperror = fpclassify(val);
if (fperror == FP_ZERO || fperror == FP_SUBNORMAL) {
errno = 0;
val = 0.0;
}
This works in my testing, but it depends on availability of
the fpclassify() macro. Is there a way to test for this in
./configure? How? The macro is in C99 but not in earlier C standards.
Apparently it does exist in some non-C99 compilers like Solaris/SunOS.
Question 2: Where would we use it?
------------
We already have an explicit simple-minded test, maybe outdated,
for underflow in
eval.c (gp_exp) used internally and in expression evaluation
and in
standard.c (f_tanh) used in expression evaluation.
The request in Bug #1877 is to test also in
internal.c (f_power) used in expression evaluation.
Or it might be possible to replace the test in evaluate_at().
That way it would apply to all evaluated expressions, not just
exp() pow() and tanh(). I am not certain whether the relevant
error status is guaranteed to have been propagated to that point,
but the first question is would we even want to do this?
Ethan
|