X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fnasal%2Fmathlib.c;h=639cce32cbc97a484248fe8f21fb60802489c787;hb=bcb320b537b6f7e5e3724e8a30d309322171eb43;hp=07f8ef81dba63f056899fea113cde5930dc114bf;hpb=1786692406214447db12b9d5af5364582af23d3b;p=simgear.git diff --git a/simgear/nasal/mathlib.c b/simgear/nasal/mathlib.c index 07f8ef81..639cce32 100644 --- a/simgear/nasal/mathlib.c +++ b/simgear/nasal/mathlib.c @@ -3,87 +3,92 @@ #include "nasal.h" -static naRef f_sin(naContext c, naRef args) +// 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(naVec_get(args, 0)); + 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 args) +static naRef f_cos(naContext c, naRef me, int argc, naRef* args) { - naRef a = naNumValue(naVec_get(args, 0)); + naRef a = naNumValue(argc > 0 ? args[0] : naNil()); 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 args) +static naRef f_exp(naContext c, naRef me, int argc, naRef* args) { - naRef a = naNumValue(naVec_get(args, 0)); + naRef a = naNumValue(argc > 0 ? args[0] : naNil()); 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 args) +static naRef f_ln(naContext c, naRef me, int argc, naRef* args) { - naRef a = naNumValue(naVec_get(args, 0)); + naRef a = naNumValue(argc > 0 ? args[0] : naNil()); 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 args) +static naRef f_sqrt(naContext c, naRef me, int argc, naRef* args) { - naRef a = naNumValue(naVec_get(args, 0)); + naRef a = naNumValue(argc > 0 ? args[0] : naNil()); 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 args) +static naRef f_atan2(naContext c, naRef me, int argc, naRef* args) { - naRef a = naNumValue(naVec_get(args, 0)); - naRef b = naNumValue(naVec_get(args, 1)); + naRef a = naNumValue(argc > 0 ? args[0] : naNil()); + naRef b = naNumValue(argc > 1 ? args[1] : naNil()); 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