[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