From 7758900b5e12172d7b0306e67a9dc045e7c33643 Mon Sep 17 00:00:00 2001 From: Raymond Toy <toy.raymond@gmail.com> Date: Thu, 21 Aug 2014 20:32:32 -0700 Subject: [PATCH] Handle invalid correctly. If the argument is a quiet NaN, then we don't want to signal an invalid operation. For all other floats, we do want to signal that. Add function isQNaN to detect quiet NaN. --- src/lisp/setexception.c | 43 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/src/lisp/setexception.c b/src/lisp/setexception.c index a0f568c05..a77a9d8fa 100644 --- a/src/lisp/setexception.c +++ b/src/lisp/setexception.c @@ -4,6 +4,37 @@ #include "fdlibm.h" +/* + * Test if the given number is a quiet NaN + */ + +int +isQNaN(double x) +{ + int hx; + union { int i[2]; double d; } ux; + + ux.d = x; + hx = ux.i[HIWORD] & 0x7fffffff; + + if (hx >= 0x7ff00000) { + /* + * We have some kind of infinity or NaN. Get the (top) + * mantissa bits. We have a quiet NaN if the most significant + * bit is 1. The other bits of the mantissa don't matter. We + * also don't distinguish this from the quiet NaN + * floating-point indefinite which only has the most + * significant bit set. These are all considered NaNs for our + * purposes. + */ + hx &= 0xfffff; + + return hx & 0x80000; + } + + return 0; +} + /* * Signal the floating-point exception of the given |type|, based on * the value of |x|. @@ -36,13 +67,21 @@ fdlibm_setexception(double x, enum FDLIBM_EXCEPTION type) case 3: { /* invalid */ - feraiseexcept(FE_INVALID); + + if (!isQNaN(x)) { + /* + * If it's not a quiet NaN, we want to signal an invalid + * operation. Otherwise, we silently return a NaN. + */ + feraiseexcept(FE_INVALID); + } + /* * FIXME: Of the many NaN values that we have, what NaN * should we return? */ union { int i[2]; double d; } ux; - ux.i[HIWORD] = 0x7ff00000; + ux.i[HIWORD] = 0x7ff80000; ux.i[LOWORD] = 0xdeadbeef; ret = ux.d; -- GitLab