lmathlib.c revision 344220
1/* 2** $Id: lmathlib.c,v 1.119.1.1 2017/04/19 17:20:42 roberto Exp $ 3** Standard mathematical library 4** See Copyright Notice in lua.h 5*/ 6 7#define lmathlib_c 8#define LUA_LIB 9 10#include "lprefix.h" 11 12 13#include <stdlib.h> 14#include <math.h> 15 16#include "lua.h" 17 18#include "lauxlib.h" 19#include "lualib.h" 20 21 22#undef PI 23#define PI (l_mathop(3.141592653589793238462643383279502884)) 24 25 26#if !defined(l_rand) /* { */ 27#if defined(LUA_USE_POSIX) 28#define l_rand() random() 29#define l_srand(x) srandom(x) 30#define L_RANDMAX 2147483647 /* (2^31 - 1), following POSIX */ 31#else 32#define l_rand() rand() 33#define l_srand(x) srand(x) 34#define L_RANDMAX RAND_MAX 35#endif 36#endif /* } */ 37 38 39static int math_abs (lua_State *L) { 40 if (lua_isinteger(L, 1)) { 41 lua_Integer n = lua_tointeger(L, 1); 42 if (n < 0) n = (lua_Integer)(0u - (lua_Unsigned)n); 43 lua_pushinteger(L, n); 44 } 45 else 46 lua_pushnumber(L, l_mathop(fabs)(luaL_checknumber(L, 1))); 47 return 1; 48} 49 50static int math_sin (lua_State *L) { 51 lua_pushnumber(L, l_mathop(sin)(luaL_checknumber(L, 1))); 52 return 1; 53} 54 55static int math_cos (lua_State *L) { 56 lua_pushnumber(L, l_mathop(cos)(luaL_checknumber(L, 1))); 57 return 1; 58} 59 60static int math_tan (lua_State *L) { 61 lua_pushnumber(L, l_mathop(tan)(luaL_checknumber(L, 1))); 62 return 1; 63} 64 65static int math_asin (lua_State *L) { 66 lua_pushnumber(L, l_mathop(asin)(luaL_checknumber(L, 1))); 67 return 1; 68} 69 70static int math_acos (lua_State *L) { 71 lua_pushnumber(L, l_mathop(acos)(luaL_checknumber(L, 1))); 72 return 1; 73} 74 75static int math_atan (lua_State *L) { 76 lua_Number y = luaL_checknumber(L, 1); 77 lua_Number x = luaL_optnumber(L, 2, 1); 78 lua_pushnumber(L, l_mathop(atan2)(y, x)); 79 return 1; 80} 81 82 83static int math_toint (lua_State *L) { 84 int valid; 85 lua_Integer n = lua_tointegerx(L, 1, &valid); 86 if (valid) 87 lua_pushinteger(L, n); 88 else { 89 luaL_checkany(L, 1); 90 lua_pushnil(L); /* value is not convertible to integer */ 91 } 92 return 1; 93} 94 95 96static void pushnumint (lua_State *L, lua_Number d) { 97 lua_Integer n; 98 if (lua_numbertointeger(d, &n)) /* does 'd' fit in an integer? */ 99 lua_pushinteger(L, n); /* result is integer */ 100 else 101 lua_pushnumber(L, d); /* result is float */ 102} 103 104 105static int math_floor (lua_State *L) { 106 if (lua_isinteger(L, 1)) 107 lua_settop(L, 1); /* integer is its own floor */ 108 else { 109 lua_Number d = l_mathop(floor)(luaL_checknumber(L, 1)); 110 pushnumint(L, d); 111 } 112 return 1; 113} 114 115 116static int math_ceil (lua_State *L) { 117 if (lua_isinteger(L, 1)) 118 lua_settop(L, 1); /* integer is its own ceil */ 119 else { 120 lua_Number d = l_mathop(ceil)(luaL_checknumber(L, 1)); 121 pushnumint(L, d); 122 } 123 return 1; 124} 125 126 127static int math_fmod (lua_State *L) { 128 if (lua_isinteger(L, 1) && lua_isinteger(L, 2)) { 129 lua_Integer d = lua_tointeger(L, 2); 130 if ((lua_Unsigned)d + 1u <= 1u) { /* special cases: -1 or 0 */ 131 luaL_argcheck(L, d != 0, 2, "zero"); 132 lua_pushinteger(L, 0); /* avoid overflow with 0x80000... / -1 */ 133 } 134 else 135 lua_pushinteger(L, lua_tointeger(L, 1) % d); 136 } 137 else 138 lua_pushnumber(L, l_mathop(fmod)(luaL_checknumber(L, 1), 139 luaL_checknumber(L, 2))); 140 return 1; 141} 142 143 144/* 145** next function does not use 'modf', avoiding problems with 'double*' 146** (which is not compatible with 'float*') when lua_Number is not 147** 'double'. 148*/ 149static int math_modf (lua_State *L) { 150 if (lua_isinteger(L ,1)) { 151 lua_settop(L, 1); /* number is its own integer part */ 152 lua_pushnumber(L, 0); /* no fractional part */ 153 } 154 else { 155 lua_Number n = luaL_checknumber(L, 1); 156 /* integer part (rounds toward zero) */ 157 lua_Number ip = (n < 0) ? l_mathop(ceil)(n) : l_mathop(floor)(n); 158 pushnumint(L, ip); 159 /* fractional part (test needed for inf/-inf) */ 160 lua_pushnumber(L, (n == ip) ? l_mathop(0.0) : (n - ip)); 161 } 162 return 2; 163} 164 165 166static int math_sqrt (lua_State *L) { 167 lua_pushnumber(L, l_mathop(sqrt)(luaL_checknumber(L, 1))); 168 return 1; 169} 170 171 172static int math_ult (lua_State *L) { 173 lua_Integer a = luaL_checkinteger(L, 1); 174 lua_Integer b = luaL_checkinteger(L, 2); 175 lua_pushboolean(L, (lua_Unsigned)a < (lua_Unsigned)b); 176 return 1; 177} 178 179static int math_log (lua_State *L) { 180 lua_Number x = luaL_checknumber(L, 1); 181 lua_Number res; 182 if (lua_isnoneornil(L, 2)) 183 res = l_mathop(log)(x); 184 else { 185 lua_Number base = luaL_checknumber(L, 2); 186#if !defined(LUA_USE_C89) 187 if (base == l_mathop(2.0)) 188 res = l_mathop(log2)(x); else 189#endif 190 if (base == l_mathop(10.0)) 191 res = l_mathop(log10)(x); 192 else 193 res = l_mathop(log)(x)/l_mathop(log)(base); 194 } 195 lua_pushnumber(L, res); 196 return 1; 197} 198 199static int math_exp (lua_State *L) { 200 lua_pushnumber(L, l_mathop(exp)(luaL_checknumber(L, 1))); 201 return 1; 202} 203 204static int math_deg (lua_State *L) { 205 lua_pushnumber(L, luaL_checknumber(L, 1) * (l_mathop(180.0) / PI)); 206 return 1; 207} 208 209static int math_rad (lua_State *L) { 210 lua_pushnumber(L, luaL_checknumber(L, 1) * (PI / l_mathop(180.0))); 211 return 1; 212} 213 214 215static int math_min (lua_State *L) { 216 int n = lua_gettop(L); /* number of arguments */ 217 int imin = 1; /* index of current minimum value */ 218 int i; 219 luaL_argcheck(L, n >= 1, 1, "value expected"); 220 for (i = 2; i <= n; i++) { 221 if (lua_compare(L, i, imin, LUA_OPLT)) 222 imin = i; 223 } 224 lua_pushvalue(L, imin); 225 return 1; 226} 227 228 229static int math_max (lua_State *L) { 230 int n = lua_gettop(L); /* number of arguments */ 231 int imax = 1; /* index of current maximum value */ 232 int i; 233 luaL_argcheck(L, n >= 1, 1, "value expected"); 234 for (i = 2; i <= n; i++) { 235 if (lua_compare(L, imax, i, LUA_OPLT)) 236 imax = i; 237 } 238 lua_pushvalue(L, imax); 239 return 1; 240} 241 242/* 243** This function uses 'double' (instead of 'lua_Number') to ensure that 244** all bits from 'l_rand' can be represented, and that 'RANDMAX + 1.0' 245** will keep full precision (ensuring that 'r' is always less than 1.0.) 246*/ 247static int math_random (lua_State *L) { 248 lua_Integer low, up; 249 double r = (double)l_rand() * (1.0 / ((double)L_RANDMAX + 1.0)); 250 switch (lua_gettop(L)) { /* check number of arguments */ 251 case 0: { /* no arguments */ 252 lua_pushnumber(L, (lua_Number)r); /* Number between 0 and 1 */ 253 return 1; 254 } 255 case 1: { /* only upper limit */ 256 low = 1; 257 up = luaL_checkinteger(L, 1); 258 break; 259 } 260 case 2: { /* lower and upper limits */ 261 low = luaL_checkinteger(L, 1); 262 up = luaL_checkinteger(L, 2); 263 break; 264 } 265 default: return luaL_error(L, "wrong number of arguments"); 266 } 267 /* random integer in the interval [low, up] */ 268 luaL_argcheck(L, low <= up, 1, "interval is empty"); 269 luaL_argcheck(L, low >= 0 || up <= LUA_MAXINTEGER + low, 1, 270 "interval too large"); 271 r *= (double)(up - low) + 1.0; 272 lua_pushinteger(L, (lua_Integer)r + low); 273 return 1; 274} 275 276 277static int math_randomseed (lua_State *L) { 278 l_srand((unsigned int)(lua_Integer)luaL_checknumber(L, 1)); 279 (void)l_rand(); /* discard first value to avoid undesirable correlations */ 280 return 0; 281} 282 283 284static int math_type (lua_State *L) { 285 if (lua_type(L, 1) == LUA_TNUMBER) { 286 if (lua_isinteger(L, 1)) 287 lua_pushliteral(L, "integer"); 288 else 289 lua_pushliteral(L, "float"); 290 } 291 else { 292 luaL_checkany(L, 1); 293 lua_pushnil(L); 294 } 295 return 1; 296} 297 298 299/* 300** {================================================================== 301** Deprecated functions (for compatibility only) 302** =================================================================== 303*/ 304#if defined(LUA_COMPAT_MATHLIB) 305 306static int math_cosh (lua_State *L) { 307 lua_pushnumber(L, l_mathop(cosh)(luaL_checknumber(L, 1))); 308 return 1; 309} 310 311static int math_sinh (lua_State *L) { 312 lua_pushnumber(L, l_mathop(sinh)(luaL_checknumber(L, 1))); 313 return 1; 314} 315 316static int math_tanh (lua_State *L) { 317 lua_pushnumber(L, l_mathop(tanh)(luaL_checknumber(L, 1))); 318 return 1; 319} 320 321static int math_pow (lua_State *L) { 322 lua_Number x = luaL_checknumber(L, 1); 323 lua_Number y = luaL_checknumber(L, 2); 324 lua_pushnumber(L, l_mathop(pow)(x, y)); 325 return 1; 326} 327 328static int math_frexp (lua_State *L) { 329 int e; 330 lua_pushnumber(L, l_mathop(frexp)(luaL_checknumber(L, 1), &e)); 331 lua_pushinteger(L, e); 332 return 2; 333} 334 335static int math_ldexp (lua_State *L) { 336 lua_Number x = luaL_checknumber(L, 1); 337 int ep = (int)luaL_checkinteger(L, 2); 338 lua_pushnumber(L, l_mathop(ldexp)(x, ep)); 339 return 1; 340} 341 342static int math_log10 (lua_State *L) { 343 lua_pushnumber(L, l_mathop(log10)(luaL_checknumber(L, 1))); 344 return 1; 345} 346 347#endif 348/* }================================================================== */ 349 350 351 352static const luaL_Reg mathlib[] = { 353 {"abs", math_abs}, 354 {"acos", math_acos}, 355 {"asin", math_asin}, 356 {"atan", math_atan}, 357 {"ceil", math_ceil}, 358 {"cos", math_cos}, 359 {"deg", math_deg}, 360 {"exp", math_exp}, 361 {"tointeger", math_toint}, 362 {"floor", math_floor}, 363 {"fmod", math_fmod}, 364 {"ult", math_ult}, 365 {"log", math_log}, 366 {"max", math_max}, 367 {"min", math_min}, 368 {"modf", math_modf}, 369 {"rad", math_rad}, 370 {"random", math_random}, 371 {"randomseed", math_randomseed}, 372 {"sin", math_sin}, 373 {"sqrt", math_sqrt}, 374 {"tan", math_tan}, 375 {"type", math_type}, 376#if defined(LUA_COMPAT_MATHLIB) 377 {"atan2", math_atan}, 378 {"cosh", math_cosh}, 379 {"sinh", math_sinh}, 380 {"tanh", math_tanh}, 381 {"pow", math_pow}, 382 {"frexp", math_frexp}, 383 {"ldexp", math_ldexp}, 384 {"log10", math_log10}, 385#endif 386 /* placeholders */ 387 {"pi", NULL}, 388 {"huge", NULL}, 389 {"maxinteger", NULL}, 390 {"mininteger", NULL}, 391 {NULL, NULL} 392}; 393 394 395/* 396** Open math library 397*/ 398LUAMOD_API int luaopen_math (lua_State *L) { 399 luaL_newlib(L, mathlib); 400 lua_pushnumber(L, PI); 401 lua_setfield(L, -2, "pi"); 402 lua_pushnumber(L, (lua_Number)HUGE_VAL); 403 lua_setfield(L, -2, "huge"); 404 lua_pushinteger(L, LUA_MAXINTEGER); 405 lua_setfield(L, -2, "maxinteger"); 406 lua_pushinteger(L, LUA_MININTEGER); 407 lua_setfield(L, -2, "mininteger"); 408 return 1; 409} 410 411