From a5f9262adbc87af945e4124c1ad291d0a14a061c Mon Sep 17 00:00:00 2001 From: andy Date: Fri, 30 Mar 2007 16:42:22 +0000 Subject: [PATCH] Melchior points out that NaN/Inf behavior is not platform-independent. So toss a runtime error ("floating point error") when any of the math library functions produce a non-finite value. Note that these are not the only locations that can do that (simply dividing by zero will produce an Inf), but it's still proper behavior. --- simgear/nasal/mathlib.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/simgear/nasal/mathlib.c b/simgear/nasal/mathlib.c index e20db595..367aa2d2 100644 --- a/simgear/nasal/mathlib.c +++ b/simgear/nasal/mathlib.c @@ -1,16 +1,32 @@ - #include #include #include "nasal.h" +// Toss a runtime error for any NaN or Inf values produced. Note that +// this assumes an IEEE 754 format. +#define VALIDATE(r) (valid(r.num) ? (r) : die(c, __func__+2)) + +static int valid(double d) +{ + union { double d; unsigned long long ull; } u; + u.d = d; + return ((u.ull >> 52) & 0x7ff) != 0x7ff; +} + +static naRef die(naContext c, const char* fn) +{ + naRuntimeError(c, "floating point error in math.%s()", fn); + return naNil(); +} + static naRef f_sin(naContext c, naRef me, int argc, naRef* args) { naRef a = naNumValue(argc > 0 ? args[0] : naNil()); if(naIsNil(a)) naRuntimeError(c, "non numeric argument to sin()"); a.num = sin(a.num); - return a; + return VALIDATE(a); } static naRef f_cos(naContext c, naRef me, int argc, naRef* args) @@ -19,7 +35,7 @@ static naRef f_cos(naContext c, naRef me, int argc, naRef* args) if(naIsNil(a)) naRuntimeError(c, "non numeric argument to cos()"); a.num = cos(a.num); - return a; + return VALIDATE(a); } static naRef f_exp(naContext c, naRef me, int argc, naRef* args) @@ -28,7 +44,7 @@ static naRef f_exp(naContext c, naRef me, int argc, naRef* args) if(naIsNil(a)) naRuntimeError(c, "non numeric argument to exp()"); a.num = exp(a.num); - return a; + return VALIDATE(a); } static naRef f_ln(naContext c, naRef me, int argc, naRef* args) @@ -37,7 +53,7 @@ static naRef f_ln(naContext c, naRef me, int argc, naRef* args) if(naIsNil(a)) naRuntimeError(c, "non numeric argument to ln()"); a.num = log(a.num); - return a; + return VALIDATE(a); } static naRef f_sqrt(naContext c, naRef me, int argc, naRef* args) @@ -46,7 +62,7 @@ static naRef f_sqrt(naContext c, naRef me, int argc, naRef* args) if(naIsNil(a)) naRuntimeError(c, "non numeric argument to sqrt()"); a.num = sqrt(a.num); - return a; + return VALIDATE(a); } static naRef f_atan2(naContext c, naRef me, int argc, naRef* args) @@ -56,7 +72,7 @@ static naRef f_atan2(naContext c, naRef me, int argc, naRef* args) if(naIsNil(a) || naIsNil(b)) naRuntimeError(c, "non numeric argument to atan2()"); a.num = atan2(a.num, b.num); - return a; + return VALIDATE(a); } static naCFuncItem funcs[] = { -- 2.39.5