[Ecls-list] [PATCH] Improve floating-point exception handling.
Alexander Gavrilov
angavrilov at gmail.com
Mon Jun 1 10:30:41 UTC 2009
Some not-so-rare errors like 0/0 or sqrt(-1) produce
the Invalid Operation exception. Since ECL cannot
handle it, such failures in compiled code sometimes
go undetected until much later.
This adds support for this exception, also enabling
it by default. I also add support for the Inexact
Result exception where possible, and improve the
priority order of signalled exceptions when checked
via fetestexcept.
Signed-off-by: Alexander Gavrilov <angavrilov at gmail.com>
---
It is really annoying to spend an hour thinking why
there might be a division by zero in a part of code,
only to find that it was actually a NaN written
directly to a float array by a completely different
function.
Alexander
src/c/unixint.d | 23 +++++++++++++++++------
src/h/internal.h | 2 ++
2 files changed, 19 insertions(+), 6 deletions(-)
diff --git a/src/c/unixint.d b/src/c/unixint.d
index c1f0c16..724d7a2 100644
--- a/src/c/unixint.d
+++ b/src/c/unixint.d
@@ -233,14 +233,14 @@ handler_fn_protype(lisp_signal_handler, int sig, siginfo_t *info, void *aux)
int bits = fetestexcept(FE_ALL_EXCEPT);
if (bits & FE_DIVBYZERO)
condition = @'division-by-zero';
- if (bits & FE_OVERFLOW)
+ else if (bits & FE_INVALID)
+ condition = @'floating-point-invalid-operation';
+ else if (bits & FE_OVERFLOW)
condition = @'floating-point-overflow';
- if (bits & FE_UNDERFLOW)
+ else if (bits & FE_UNDERFLOW)
condition = @'floating-point-underflow';
- if (bits & FE_INEXACT)
+ else if (bits & FE_INEXACT)
condition = @'floating-point-inexact';
- if (bits & FE_INVALID)
- condition = @'floating-point-invalid-operation';
#endif
#ifdef SA_SIGINFO
if (info) {
@@ -250,6 +250,10 @@ handler_fn_protype(lisp_signal_handler, int sig, siginfo_t *info, void *aux)
condition = @'floating-point-overflow';
if (info->si_code == FPE_FLTUND)
condition = @'floating-point-underflow';
+ if (info->si_code == FPE_FLTRES)
+ condition = @'floating-point-inexact';
+ if (info->si_code == FPE_FLTINV)
+ condition = @'floating-point-invalid-operation';
}
#endif
si_trap_fpe(@'last', Ct);
@@ -532,6 +536,9 @@ void handle_fpe_signal(int sig, int num)
cl_object condition = @'arithmetic-error';
switch (num) {
+ case _FPE_INVALID:
+ condition = @'floating-point-invalid-operation';
+ break;
case _FPE_OVERFLOW:
condition = @'floating-point-overflow';
break;
@@ -571,8 +578,12 @@ si_trap_fpe(cl_object condition, cl_object flag)
bits = FE_OVERFLOW;
else if (condition == @'floating-point-underflow')
bits = FE_UNDERFLOW;
+ else if (condition == @'floating-point-invalid-operation')
+ bits = FE_INVALID;
+ else if (condition == @'floating-point-inexact')
+ bits = FE_INEXACT;
else if (condition == Ct)
- bits = FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW;
+ bits = FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW | FE_INVALID;
else if (condition == @'last')
bits = last_bits;
#if defined(_MSC_VER) || defined(mingw32)
diff --git a/src/h/internal.h b/src/h/internal.h
index 1f244f5..1f9fda8 100644
--- a/src/h/internal.h
+++ b/src/h/internal.h
@@ -316,6 +316,8 @@ extern cl_fixnum ecl_runtime(void);
# define FE_DIVBYZERO EM_ZERODIVIDE
# define FE_OVERFLOW EM_OVERFLOW
# define FE_UNDERFLOW EM_UNDERFLOW
+# define FE_INVALID EM_INVALID
+# define FE_INEXACT EM_INEXACT
typedef int fenv_t;
# else
# ifdef _MCW_EM
--
1.6.3.rc3.12.gb7937
More information about the ecl-devel
mailing list