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