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.
This commit is contained in:
@@ -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[] = {
|
||||
|
||||
Reference in New Issue
Block a user