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