00001 #include <math.h>
00002 #include <string.h>
00003
00004 #include "nasal.h"
00005
00006
00007
00008 #define VALIDATE(r) (valid(r.num) ? (r) : die(c, __FUNCTION__+2))
00009
00010 static int valid(double d)
00011 {
00012 union { double d; unsigned long long ull; } u;
00013 u.d = d;
00014 return ((u.ull >> 52) & 0x7ff) != 0x7ff;
00015 }
00016
00017 static naRef die(naContext c, const char* fn)
00018 {
00019 naRuntimeError(c, "floating point error in math.%s()", fn);
00020 return naNil();
00021 }
00022
00023 static naRef f_sin(naContext c, naRef me, int argc, naRef* args)
00024 {
00025 naRef a = naNumValue(argc > 0 ? args[0] : naNil());
00026 if(naIsNil(a))
00027 naRuntimeError(c, "non numeric argument to sin()");
00028 a.num = sin(a.num);
00029 return VALIDATE(a);
00030 }
00031
00032 static naRef f_cos(naContext c, naRef me, int argc, naRef* args)
00033 {
00034 naRef a = naNumValue(argc > 0 ? args[0] : naNil());
00035 if(naIsNil(a))
00036 naRuntimeError(c, "non numeric argument to cos()");
00037 a.num = cos(a.num);
00038 return VALIDATE(a);
00039 }
00040
00041 static naRef f_exp(naContext c, naRef me, int argc, naRef* args)
00042 {
00043 naRef a = naNumValue(argc > 0 ? args[0] : naNil());
00044 if(naIsNil(a))
00045 naRuntimeError(c, "non numeric argument to exp()");
00046 a.num = exp(a.num);
00047 return VALIDATE(a);
00048 }
00049
00050 static naRef f_ln(naContext c, naRef me, int argc, naRef* args)
00051 {
00052 naRef a = naNumValue(argc > 0 ? args[0] : naNil());
00053 if(naIsNil(a))
00054 naRuntimeError(c, "non numeric argument to ln()");
00055 a.num = log(a.num);
00056 return VALIDATE(a);
00057 }
00058
00059 static naRef f_sqrt(naContext c, naRef me, int argc, naRef* args)
00060 {
00061 naRef a = naNumValue(argc > 0 ? args[0] : naNil());
00062 if(naIsNil(a))
00063 naRuntimeError(c, "non numeric argument to sqrt()");
00064 a.num = sqrt(a.num);
00065 return VALIDATE(a);
00066 }
00067
00068 static naRef f_atan2(naContext c, naRef me, int argc, naRef* args)
00069 {
00070 naRef a = naNumValue(argc > 0 ? args[0] : naNil());
00071 naRef b = naNumValue(argc > 1 ? args[1] : naNil());
00072 if(naIsNil(a) || naIsNil(b))
00073 naRuntimeError(c, "non numeric argument to atan2()");
00074 a.num = atan2(a.num, b.num);
00075 return VALIDATE(a);
00076 }
00077
00078 static naCFuncItem funcs[] = {
00079 { "sin", f_sin },
00080 { "cos", f_cos },
00081 { "exp", f_exp },
00082 { "ln", f_ln },
00083 { "sqrt", f_sqrt },
00084 { "atan2", f_atan2 },
00085 { 0 }
00086 };
00087
00088 naRef naInit_math(naContext c)
00089 {
00090 naRef ns = naGenLib(c, funcs);
00091 naAddSym(c, ns, "pi", naNum(3.14159265358979323846));
00092 naAddSym(c, ns, "e", naNum(2.7182818284590452354));
00093 return ns;
00094 }