]> git.mxchange.org Git - simgear.git/blobdiff - simgear/nasal/mathlib.c
hla: Provide a directly property based api for property data element.
[simgear.git] / simgear / nasal / mathlib.c
index ea89e5fc4a5d00f9fc517320de03a501edf95273..639cce32cbc97a484248fe8f21fb60802489c787 100644 (file)
@@ -1,19 +1,32 @@
-#ifdef _MSC_VER
-#define _USE_MATH_DEFINES
-#endif
-
 #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, __FUNCTION__+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)
@@ -22,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)
@@ -31,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)
@@ -40,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)
@@ -49,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)
@@ -59,36 +72,23 @@ 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 struct func { char* name; naCFunction func; } funcs[] = {
+static naCFuncItem funcs[] = {
     { "sin", f_sin },
     { "cos", f_cos },
     { "exp", f_exp },
     { "ln", f_ln },
     { "sqrt", f_sqrt },
     { "atan2", f_atan2 },
+    { 0 }
 };
 
-naRef naMathLib(naContext c)
+naRef naInit_math(naContext c)
 {
-    naRef name, namespace = naNewHash(c);
-    int i, n = sizeof(funcs)/sizeof(struct func);
-    for(i=0; i<n; i++) {
-        naRef code = naNewCCode(c, funcs[i].func);
-        naRef name = naStr_fromdata(naNewString(c),
-                                    funcs[i].name, strlen(funcs[i].name));
-        naHash_set(namespace, name, naNewFunc(c, code));
-    }
-
-    // Set up constants for math.pi and math.e
-    name = naStr_fromdata(naNewString(c), "pi", 2);
-    naHash_set(namespace, name, naNum(M_PI));
-
-    name = naStr_fromdata(naNewString(c), "e", 1);
-    name = naInternSymbol(name);
-    naHash_set(namespace, name, naNum(M_E));
-
-    return namespace;
+    naRef ns = naGenLib(c, funcs);
+    naAddSym(c, ns, "pi", naNum(3.14159265358979323846));
+    naAddSym(c, ns, "e", naNum(2.7182818284590452354));
+    return ns;
 }