Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5205 | clevermous | 1 | /* |
2 | ** $Id: lmathlib.c,v 1.80 2011/07/05 12:49:35 roberto Exp $ |
||
3 | ** Standard mathematical library |
||
4 | ** See Copyright Notice in lua.h |
||
5 | */ |
||
6 | |||
7 | |||
8 | #include |
||
9 | #include |
||
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 | /* macro 'l_tg' allows the addition of an 'l' or 'f' to all math operations */ |
||
26 | #if !defined(l_tg) |
||
27 | #define l_tg(x) (x) |
||
28 | #endif |
||
29 | |||
30 | |||
31 | |||
32 | static int math_abs (lua_State *L) { |
||
33 | lua_pushnumber(L, l_tg(fabs)(luaL_checknumber(L, 1))); |
||
34 | return 1; |
||
35 | } |
||
36 | |||
37 | static int math_sin (lua_State *L) { |
||
38 | lua_pushnumber(L, l_tg(sin)(luaL_checknumber(L, 1))); |
||
39 | return 1; |
||
40 | } |
||
41 | |||
42 | static int math_sinh (lua_State *L) { |
||
43 | lua_pushnumber(L, l_tg(sinh)(luaL_checknumber(L, 1))); |
||
44 | return 1; |
||
45 | } |
||
46 | |||
47 | static int math_cos (lua_State *L) { |
||
48 | lua_pushnumber(L, l_tg(cos)(luaL_checknumber(L, 1))); |
||
49 | return 1; |
||
50 | } |
||
51 | |||
52 | static int math_cosh (lua_State *L) { |
||
53 | lua_pushnumber(L, l_tg(cosh)(luaL_checknumber(L, 1))); |
||
54 | return 1; |
||
55 | } |
||
56 | |||
57 | static int math_tan (lua_State *L) { |
||
58 | lua_pushnumber(L, l_tg(tan)(luaL_checknumber(L, 1))); |
||
59 | return 1; |
||
60 | } |
||
61 | |||
62 | static int math_tanh (lua_State *L) { |
||
63 | lua_pushnumber(L, l_tg(tanh)(luaL_checknumber(L, 1))); |
||
64 | return 1; |
||
65 | } |
||
66 | |||
67 | static int math_asin (lua_State *L) { |
||
68 | lua_pushnumber(L, l_tg(asin)(luaL_checknumber(L, 1))); |
||
69 | return 1; |
||
70 | } |
||
71 | |||
72 | static int math_acos (lua_State *L) { |
||
73 | lua_pushnumber(L, l_tg(acos)(luaL_checknumber(L, 1))); |
||
74 | return 1; |
||
75 | } |
||
76 | |||
77 | static int math_atan (lua_State *L) { |
||
78 | lua_pushnumber(L, l_tg(atan)(luaL_checknumber(L, 1))); |
||
79 | return 1; |
||
80 | } |
||
81 | |||
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 | |||
88 | static int math_ceil (lua_State *L) { |
||
89 | lua_pushnumber(L, l_tg(ceil)(luaL_checknumber(L, 1))); |
||
90 | return 1; |
||
91 | } |
||
92 | |||
93 | static int math_floor (lua_State *L) { |
||
94 | lua_pushnumber(L, l_tg(floor)(luaL_checknumber(L, 1))); |
||
95 | return 1; |
||
96 | } |
||
97 | |||
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 | |||
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 | |||
112 | static int math_sqrt (lua_State *L) { |
||
113 | lua_pushnumber(L, l_tg(sqrt)(luaL_checknumber(L, 1))); |
||
114 | return 1; |
||
115 | } |
||
116 | |||
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 | |||
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) |
||
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 | |||
144 | static int math_exp (lua_State *L) { |
||
145 | lua_pushnumber(L, l_tg(exp)(luaL_checknumber(L, 1))); |
||
146 | return 1; |
||
147 | } |
||
148 | |||
149 | static int math_deg (lua_State *L) { |
||
150 | lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE); |
||
151 | return 1; |
||
152 | } |
||
153 | |||
154 | static int math_rad (lua_State *L) { |
||
155 | lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE); |
||
156 | return 1; |
||
157 | } |
||
158 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | */ |
||
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 | }=>=>=n;>>=n;> |
||
283 |