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