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