1 /*
2 ** $Id: lmathlib.c,v 1.67.1.1 2007/12/27 13:02:25 roberto Exp $
3 ** Standard mathematical library
4 ** See Copyright Notice in lua.h
5 */
6
7
8 #include <stdlib.h>
9 //SPRING#include <math.h>
10 #include "streflop_cond.h"
11 #include "System/FastMath.h"
12
13 #define lmathlib_c
14 #define LUA_LIB
15
16 #include "lua.h"
17 #include "lauxlib.h"
18 #include "lualib.h"
19
20
21 #undef PI
22 #define PI (3.14159265358979323846)
23 #define RADIANS_PER_DEGREE (PI/180.0)
24
25
math_abs(lua_State * L)26 static int math_abs (lua_State *L) {
27 lua_pushnumber(L, math::fabs(luaL_checknumber_noassert(L, 1)));
28 return 1;
29 }
30
math_sin(lua_State * L)31 static int math_sin (lua_State *L) {
32 lua_pushnumber(L, math::sin(luaL_checknumber_noassert(L, 1)));
33 return 1;
34 }
35
math_sinh(lua_State * L)36 static int math_sinh (lua_State *L) {
37 lua_pushnumber(L, math::sinh(luaL_checknumber_noassert(L, 1)));
38 return 1;
39 }
40
math_cos(lua_State * L)41 static int math_cos (lua_State *L) {
42 lua_pushnumber(L, math::cos(luaL_checknumber_noassert(L, 1)));
43 return 1;
44 }
45
math_cosh(lua_State * L)46 static int math_cosh (lua_State *L) {
47 lua_pushnumber(L, math::cosh(luaL_checknumber_noassert(L, 1)));
48 return 1;
49 }
50
math_tan(lua_State * L)51 static int math_tan (lua_State *L) {
52 lua_pushnumber(L, math::tan(luaL_checknumber_noassert(L, 1)));
53 return 1;
54 }
55
math_tanh(lua_State * L)56 static int math_tanh (lua_State *L) {
57 lua_pushnumber(L, math::tanh(luaL_checknumber_noassert(L, 1)));
58 return 1;
59 }
60
math_asin(lua_State * L)61 static int math_asin (lua_State *L) {
62 lua_pushnumber(L, math::asin(luaL_checknumber_noassert(L, 1)));
63 return 1;
64 }
65
math_acos(lua_State * L)66 static int math_acos (lua_State *L) {
67 lua_pushnumber(L, math::acos(luaL_checknumber_noassert(L, 1)));
68 return 1;
69 }
70
math_atan(lua_State * L)71 static int math_atan (lua_State *L) {
72 lua_pushnumber(L, math::atan(luaL_checknumber_noassert(L, 1)));
73 return 1;
74 }
75
math_atan2(lua_State * L)76 static int math_atan2 (lua_State *L) {
77 lua_pushnumber(L, math::atan2(luaL_checknumber_noassert(L, 1), luaL_checknumber_noassert(L, 2)));
78 return 1;
79 }
80
math_ceil(lua_State * L)81 static int math_ceil (lua_State *L) {
82 lua_pushnumber(L, math::ceil(luaL_checknumber_noassert(L, 1)));
83 return 1;
84 }
85
math_floor(lua_State * L)86 static int math_floor (lua_State *L) {
87 lua_pushnumber(L, math::floor(luaL_checknumber_noassert(L, 1)));
88 return 1;
89 }
90
math_fmod(lua_State * L)91 static int math_fmod (lua_State *L) {
92 lua_pushnumber(L, math::fmod(luaL_checknumber_noassert(L, 1), luaL_checknumber_noassert(L, 2)));
93 return 1;
94 }
95
math_modf(lua_State * L)96 static int math_modf (lua_State *L) {
97 // FIXME -- streflop does not have modf()
98 // double fp = math::modf(luaL_checknumber_noassert(L, 1), &ip);
99 const float in = (float)luaL_checknumber_noassert(L, 1);
100
101 if (math::isnan(in)) {
102 lua_pushnumber(L, in);
103 lua_pushnumber(L, in);
104 }
105 else if (math::isinf(in)) {
106 lua_pushnumber(L, in);
107 lua_pushnumber(L, 0.0f);
108 }
109 else {
110 const float fp = math::fmod(in, 1.0f);
111 const float ip = (in - fp);
112 lua_pushnumber(L, ip);
113 lua_pushnumber(L, fp);
114 }
115 return 2;
116 }
117
math_sqrt(lua_State * L)118 static int math_sqrt (lua_State *L) {
119 lua_pushnumber(L, math::sqrt(luaL_checknumber_noassert(L, 1)));
120 return 1;
121 }
122
math_pow(lua_State * L)123 static int math_pow (lua_State *L) {
124 lua_pushnumber(L, math::pow(luaL_checknumber_noassert(L, 1), luaL_checknumber_noassert(L, 2)));
125 return 1;
126 }
127
math_log(lua_State * L)128 static int math_log (lua_State *L) {
129 lua_pushnumber(L, math::log(luaL_checknumber_noassert(L, 1)));
130 return 1;
131 }
132
math_log10(lua_State * L)133 static int math_log10 (lua_State *L) {
134 lua_pushnumber(L, math::log10(luaL_checknumber_noassert(L, 1)));
135 return 1;
136 }
137
math_exp(lua_State * L)138 static int math_exp (lua_State *L) {
139 lua_pushnumber(L, math::exp(luaL_checknumber_noassert(L, 1)));
140 return 1;
141 }
142
math_deg(lua_State * L)143 static int math_deg (lua_State *L) {
144 lua_pushnumber(L, luaL_checknumber_noassert(L, 1)/RADIANS_PER_DEGREE);
145 return 1;
146 }
147
math_rad(lua_State * L)148 static int math_rad (lua_State *L) {
149 lua_pushnumber(L, luaL_checknumber_noassert(L, 1)*RADIANS_PER_DEGREE);
150 return 1;
151 }
152
math_frexp(lua_State * L)153 static int math_frexp (lua_State *L) {
154 int e;
155 lua_pushnumber(L, math::frexp(luaL_checknumber_noassert(L, 1), &e));
156 lua_pushinteger(L, e);
157 return 2;
158 }
159
math_ldexp(lua_State * L)160 static int math_ldexp (lua_State *L) {
161 lua_pushnumber(L, math::ldexp(luaL_checknumber_noassert(L, 1), luaL_checkint(L, 2)));
162 return 1;
163 }
164
165
166
math_min(lua_State * L)167 static int math_min (lua_State *L) {
168 int n = lua_gettop(L); /* number of arguments */
169 lua_Number dmin = luaL_checknumber_noassert(L, 1);
170 int i;
171 for (i=2; i<=n; i++) {
172 lua_Number d = luaL_checknumber_noassert(L, i);
173 if (d < dmin)
174 dmin = d;
175 }
176 lua_pushnumber(L, dmin);
177 return 1;
178 }
179
180
math_max(lua_State * L)181 static int math_max (lua_State *L) {
182 int n = lua_gettop(L); /* number of arguments */
183 lua_Number dmax = luaL_checknumber_noassert(L, 1);
184 int i;
185 for (i=2; i<=n; i++) {
186 lua_Number d = luaL_checknumber_noassert(L, i);
187 if (d > dmax)
188 dmax = d;
189 }
190 lua_pushnumber(L, dmax);
191 return 1;
192 }
193
194
195
math_random(lua_State * L)196 static int math_random (lua_State *L) {
197 /* the `%' avoids the (rare) case of r==1, and is needed also because on
198 some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */
199 lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX;
200 switch (lua_gettop(L)) { /* check number of arguments */
201 case 0: { /* no arguments */
202 lua_pushnumber(L, r); /* Number between 0 and 1 */
203 break;
204 }
205 case 1: { /* only upper limit */
206 int u = luaL_checkint(L, 1);
207 luaL_argcheck(L, 1<=u, 1, "interval is empty");
208 lua_pushnumber(L, math::floor(r*u)+1); /* int between 1 and `u' */
209 break;
210 }
211 case 2: { /* lower and upper limits */
212 int l = luaL_checkint(L, 1);
213 int u = luaL_checkint(L, 2);
214 luaL_argcheck(L, l<=u, 2, "interval is empty");
215 lua_pushnumber(L, math::floor(r*(u-l+1))+l); /* int between `l' and `u' */
216 break;
217 }
218 default: return luaL_error(L, "wrong number of arguments");
219 }
220 return 1;
221 }
222
math_randomseed(lua_State * L)223 static int math_randomseed (lua_State *L) {
224 srand(luaL_checkint(L, 1));
225 return 0;
226 }
227
228
229 static const luaL_Reg mathlib[] = {
230 {"abs", math_abs},
231 {"acos", math_acos},
232 {"asin", math_asin},
233 {"atan2", math_atan2},
234 {"atan", math_atan},
235 {"ceil", math_ceil},
236 {"cosh", math_cosh},
237 {"cos", math_cos},
238 {"deg", math_deg},
239 {"exp", math_exp},
240 {"floor", math_floor},
241 {"fmod", math_fmod},
242 {"frexp", math_frexp},
243 {"ldexp", math_ldexp},
244 {"log10", math_log10},
245 {"log", math_log},
246 {"max", math_max},
247 {"min", math_min},
248 {"modf", math_modf},
249 {"pow", math_pow},
250 {"rad", math_rad},
251 {"random", math_random},
252 {"randomseed", math_randomseed},
253 {"sinh", math_sinh},
254 {"sin", math_sin},
255 {"sqrt", math_sqrt},
256 {"tanh", math_tanh},
257 {"tan", math_tan},
258 {NULL, NULL}
259 };
260
261
262 /*
263 ** Open math library
264 */
luaopen_math(lua_State * L)265 LUALIB_API int luaopen_math (lua_State *L) {
266 luaL_register(L, LUA_MATHLIBNAME, mathlib);
267 lua_pushnumber(L, PI);
268 lua_setfield(L, -2, "pi");
269 #ifdef STREFLOP_H
270 lua_pushnumber(L, math::SimplePositiveInfinity); // streflop
271 #else
272 lua_pushnumber(L, HUGE_VAL);
273 #endif
274 lua_setfield(L, -2, "huge");
275 #if defined(LUA_COMPAT_MOD)
276 lua_getfield(L, -1, "fmod");
277 lua_setfield(L, -2, "mod");
278 #endif
279 return 1;
280 }
281
282