1 /* 2 ** $Id: lmathlib.c,v 1.119 2016/12/22 13:08:50 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 39 static 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 50 static int math_sin (lua_State *L) { 51 lua_pushnumber(L, l_mathop(sin)(luaL_checknumber(L, 1))); 52 return 1; 53 } 54 55 static int math_cos (lua_State *L) { 56 lua_pushnumber(L, l_mathop(cos)(luaL_checknumber(L, 1))); 57 return 1; 58 } 59 60 static int math_tan (lua_State *L) { 61 lua_pushnumber(L, l_mathop(tan)(luaL_checknumber(L, 1))); 62 return 1; 63 } 64 65 static int math_asin (lua_State *L) { 66 lua_pushnumber(L, l_mathop(asin)(luaL_checknumber(L, 1))); 67 return 1; 68 } 69 70 static int math_acos (lua_State *L) { 71 lua_pushnumber(L, l_mathop(acos)(luaL_checknumber(L, 1))); 72 return 1; 73 } 74 75 static 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 83 static 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 96 static 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 105 static 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 116 static 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 127 static 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 */ 149 static 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 166 static int math_sqrt (lua_State *L) { 167 lua_pushnumber(L, l_mathop(sqrt)(luaL_checknumber(L, 1))); 168 return 1; 169 } 170 171 172 static 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 179 static 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 199 static int math_exp (lua_State *L) { 200 lua_pushnumber(L, l_mathop(exp)(luaL_checknumber(L, 1))); 201 return 1; 202 } 203 204 static int math_deg (lua_State *L) { 205 lua_pushnumber(L, luaL_checknumber(L, 1) * (l_mathop(180.0) / PI)); 206 return 1; 207 } 208 209 static 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 215 static 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 229 static 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 */ 247 static 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 277 static 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 284 static 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 306 static int math_cosh (lua_State *L) { 307 lua_pushnumber(L, l_mathop(cosh)(luaL_checknumber(L, 1))); 308 return 1; 309 } 310 311 static int math_sinh (lua_State *L) { 312 lua_pushnumber(L, l_mathop(sinh)(luaL_checknumber(L, 1))); 313 return 1; 314 } 315 316 static int math_tanh (lua_State *L) { 317 lua_pushnumber(L, l_mathop(tanh)(luaL_checknumber(L, 1))); 318 return 1; 319 } 320 321 static 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 328 static 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 335 static 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 342 static 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 352 static 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 */ 398 LUAMOD_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