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