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