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