]> git.mxchange.org Git - simgear.git/commitdiff
Melchior points out that NaN/Inf behavior is not platform-independent.
authorandy <andy>
Fri, 30 Mar 2007 16:42:22 +0000 (16:42 +0000)
committerandy <andy>
Fri, 30 Mar 2007 16:42:22 +0000 (16:42 +0000)
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

index e20db595bd9974026903887b5c2928d9e4ab553b..367aa2d2da846fb675b4aae4500da7a1f63edcae 100644 (file)
@@ -1,16 +1,32 @@
-
 #include <math.h>
 #include <string.h>
 
 #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[] = {