1 /*
2 ** $Id: lmathlib.c,v 1.1 2002/02/14 10:46:59 jcatki 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 #include "lua.h"
12 
13 #include "lauxlib.h"
14 #include "lualib.h"
15 
16 
17 #undef PI
18 #define PI (3.14159265358979323846)
19 #define RADIANS_PER_DEGREE (PI/180.0)
20 
21 
22 
23 /*
24 ** If you want Lua to operate in radians (instead of degrees),
25 ** define RADIANS
26 */
27 #ifdef RADIANS
28 #define FROMRAD(a)	(a)
29 #define TORAD(a)	(a)
30 #else
31 #define FROMRAD(a)	((a)/RADIANS_PER_DEGREE)
32 #define TORAD(a)	((a)*RADIANS_PER_DEGREE)
33 #endif
34 
35 
math_abs(lua_State * L)36 static int math_abs (lua_State *L) {
37   lua_pushnumber(L, fabs(luaL_check_number(L, 1)));
38   return 1;
39 }
40 
math_sin(lua_State * L)41 static int math_sin (lua_State *L) {
42   lua_pushnumber(L, sin(TORAD(luaL_check_number(L, 1))));
43   return 1;
44 }
45 
math_cos(lua_State * L)46 static int math_cos (lua_State *L) {
47   lua_pushnumber(L, cos(TORAD(luaL_check_number(L, 1))));
48   return 1;
49 }
50 
math_tan(lua_State * L)51 static int math_tan (lua_State *L) {
52   lua_pushnumber(L, tan(TORAD(luaL_check_number(L, 1))));
53   return 1;
54 }
55 
math_asin(lua_State * L)56 static int math_asin (lua_State *L) {
57   lua_pushnumber(L, FROMRAD(asin(luaL_check_number(L, 1))));
58   return 1;
59 }
60 
math_acos(lua_State * L)61 static int math_acos (lua_State *L) {
62   lua_pushnumber(L, FROMRAD(acos(luaL_check_number(L, 1))));
63   return 1;
64 }
65 
math_atan(lua_State * L)66 static int math_atan (lua_State *L) {
67   lua_pushnumber(L, FROMRAD(atan(luaL_check_number(L, 1))));
68   return 1;
69 }
70 
math_atan2(lua_State * L)71 static int math_atan2 (lua_State *L) {
72   lua_pushnumber(L, FROMRAD(atan2(luaL_check_number(L, 1), luaL_check_number(L, 2))));
73   return 1;
74 }
75 
math_ceil(lua_State * L)76 static int math_ceil (lua_State *L) {
77   lua_pushnumber(L, ceil(luaL_check_number(L, 1)));
78   return 1;
79 }
80 
math_floor(lua_State * L)81 static int math_floor (lua_State *L) {
82   lua_pushnumber(L, floor(luaL_check_number(L, 1)));
83   return 1;
84 }
85 
math_mod(lua_State * L)86 static int math_mod (lua_State *L) {
87   lua_pushnumber(L, fmod(luaL_check_number(L, 1), luaL_check_number(L, 2)));
88   return 1;
89 }
90 
math_sqrt(lua_State * L)91 static int math_sqrt (lua_State *L) {
92   lua_pushnumber(L, sqrt(luaL_check_number(L, 1)));
93   return 1;
94 }
95 
math_pow(lua_State * L)96 static int math_pow (lua_State *L) {
97   lua_pushnumber(L, pow(luaL_check_number(L, 1), luaL_check_number(L, 2)));
98   return 1;
99 }
100 
math_log(lua_State * L)101 static int math_log (lua_State *L) {
102   lua_pushnumber(L, log(luaL_check_number(L, 1)));
103   return 1;
104 }
105 
math_log10(lua_State * L)106 static int math_log10 (lua_State *L) {
107   lua_pushnumber(L, log10(luaL_check_number(L, 1)));
108   return 1;
109 }
110 
math_exp(lua_State * L)111 static int math_exp (lua_State *L) {
112   lua_pushnumber(L, exp(luaL_check_number(L, 1)));
113   return 1;
114 }
115 
math_deg(lua_State * L)116 static int math_deg (lua_State *L) {
117   lua_pushnumber(L, luaL_check_number(L, 1)/RADIANS_PER_DEGREE);
118   return 1;
119 }
120 
math_rad(lua_State * L)121 static int math_rad (lua_State *L) {
122   lua_pushnumber(L, luaL_check_number(L, 1)*RADIANS_PER_DEGREE);
123   return 1;
124 }
125 
math_frexp(lua_State * L)126 static int math_frexp (lua_State *L) {
127   int e;
128   lua_pushnumber(L, frexp(luaL_check_number(L, 1), &e));
129   lua_pushnumber(L, e);
130   return 2;
131 }
132 
math_ldexp(lua_State * L)133 static int math_ldexp (lua_State *L) {
134   lua_pushnumber(L, ldexp(luaL_check_number(L, 1), luaL_check_int(L, 2)));
135   return 1;
136 }
137 
138 
139 
math_min(lua_State * L)140 static int math_min (lua_State *L) {
141   int n = lua_gettop(L);  /* number of arguments */
142   double dmin = luaL_check_number(L, 1);
143   int i;
144   for (i=2; i<=n; i++) {
145     double d = luaL_check_number(L, i);
146     if (d < dmin)
147       dmin = d;
148   }
149   lua_pushnumber(L, dmin);
150   return 1;
151 }
152 
153 
math_max(lua_State * L)154 static int math_max (lua_State *L) {
155   int n = lua_gettop(L);  /* number of arguments */
156   double dmax = luaL_check_number(L, 1);
157   int i;
158   for (i=2; i<=n; i++) {
159     double d = luaL_check_number(L, i);
160     if (d > dmax)
161       dmax = d;
162   }
163   lua_pushnumber(L, dmax);
164   return 1;
165 }
166 
167 
math_random(lua_State * L)168 static int math_random (lua_State *L) {
169   /* the '%' avoids the (rare) case of r==1, and is needed also because on
170      some systems (SunOS!) "rand()" may return a value larger than RAND_MAX */
171   double r = (double)(rand()%RAND_MAX) / (double)RAND_MAX;
172   switch (lua_gettop(L)) {  /* check number of arguments */
173     case 0: {  /* no arguments */
174       lua_pushnumber(L, r);  /* Number between 0 and 1 */
175       break;
176     }
177     case 1: {  /* only upper limit */
178       int u = luaL_check_int(L, 1);
179       luaL_arg_check(L, 1<=u, 1, "interval is empty");
180       lua_pushnumber(L, (int)(r*u)+1);  /* integer between 1 and `u' */
181       break;
182     }
183     case 2: {  /* lower and upper limits */
184       int l = luaL_check_int(L, 1);
185       int u = luaL_check_int(L, 2);
186       luaL_arg_check(L, l<=u, 2, "interval is empty");
187       lua_pushnumber(L, (int)(r*(u-l+1))+l);  /* integer between `l' and `u' */
188       break;
189     }
190     default: lua_error(L, "wrong number of arguments");
191   }
192   return 1;
193 }
194 
195 
math_randomseed(lua_State * L)196 static int math_randomseed (lua_State *L) {
197   srand(luaL_check_int(L, 1));
198   return 0;
199 }
200 
201 
202 static const struct luaL_reg mathlib[] = {
203 {"abs",   math_abs},
204 {"sin",   math_sin},
205 {"cos",   math_cos},
206 {"tan",   math_tan},
207 {"asin",  math_asin},
208 {"acos",  math_acos},
209 {"atan",  math_atan},
210 {"atan2", math_atan2},
211 {"ceil",  math_ceil},
212 {"floor", math_floor},
213 {"mod",   math_mod},
214 {"frexp", math_frexp},
215 {"ldexp", math_ldexp},
216 {"sqrt",  math_sqrt},
217 {"min",   math_min},
218 {"max",   math_max},
219 {"log",   math_log},
220 {"log10", math_log10},
221 {"exp",   math_exp},
222 {"deg",   math_deg},
223 {"rad",   math_rad},
224 {"random",     math_random},
225 {"randomseed", math_randomseed}
226 };
227 
228 /*
229 ** Open math library
230 */
lua_mathlibopen(lua_State * L)231 LUALIB_API void lua_mathlibopen (lua_State *L) {
232   luaL_openl(L, mathlib);
233   lua_pushcfunction(L, math_pow);
234   lua_settagmethod(L, LUA_TNUMBER, "pow");
235   lua_pushnumber(L, PI);
236   lua_setglobal(L, "PI");
237 }
238 
239