1 /* 2 ** $Id: lmathlib.c,v 1.3 2015/02/02 14:03:05 lneto 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 - 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 (base == 10.0) res = l_mathop(log10)(x); 187 else res = l_mathop(log)(x)/l_mathop(log)(base); 188 } 189 lua_pushnumber(L, res); 190 return 1; 191 } 192 193 static int math_exp (lua_State *L) { 194 lua_pushnumber(L, l_mathop(exp)(luaL_checknumber(L, 1))); 195 return 1; 196 } 197 198 static int math_deg (lua_State *L) { 199 lua_pushnumber(L, luaL_checknumber(L, 1) * (l_mathop(180.0) / PI)); 200 return 1; 201 } 202 203 static int math_rad (lua_State *L) { 204 lua_pushnumber(L, luaL_checknumber(L, 1) * (PI / l_mathop(180.0))); 205 return 1; 206 } 207 208 209 static int math_min (lua_State *L) { 210 int n = lua_gettop(L); /* number of arguments */ 211 int imin = 1; /* index of current minimum value */ 212 int i; 213 luaL_argcheck(L, n >= 1, 1, "value expected"); 214 for (i = 2; i <= n; i++) { 215 if (lua_compare(L, i, imin, LUA_OPLT)) 216 imin = i; 217 } 218 lua_pushvalue(L, imin); 219 return 1; 220 } 221 222 223 static int math_max (lua_State *L) { 224 int n = lua_gettop(L); /* number of arguments */ 225 int imax = 1; /* index of current maximum value */ 226 int i; 227 luaL_argcheck(L, n >= 1, 1, "value expected"); 228 for (i = 2; i <= n; i++) { 229 if (lua_compare(L, imax, i, LUA_OPLT)) 230 imax = i; 231 } 232 lua_pushvalue(L, imax); 233 return 1; 234 } 235 236 /* 237 ** This function uses 'double' (instead of 'lua_Number') to ensure that 238 ** all bits from 'l_rand' can be represented, and that 'RANDMAX + 1.0' 239 ** will keep full precision (ensuring that 'r' is always less than 1.0.) 240 */ 241 static int math_random (lua_State *L) { 242 lua_Integer low, up; 243 double r = (double)l_rand() * (1.0 / ((double)L_RANDMAX + 1.0)); 244 switch (lua_gettop(L)) { /* check number of arguments */ 245 case 0: { /* no arguments */ 246 lua_pushnumber(L, (lua_Number)r); /* Number between 0 and 1 */ 247 return 1; 248 } 249 case 1: { /* only upper limit */ 250 low = 1; 251 up = luaL_checkinteger(L, 1); 252 break; 253 } 254 case 2: { /* lower and upper limits */ 255 low = luaL_checkinteger(L, 1); 256 up = luaL_checkinteger(L, 2); 257 break; 258 } 259 default: return luaL_error(L, "wrong number of arguments"); 260 } 261 /* random integer in the interval [low, up] */ 262 luaL_argcheck(L, low <= up, 1, "interval is empty"); 263 luaL_argcheck(L, low >= 0 || up <= LUA_MAXINTEGER + low, 1, 264 "interval too large"); 265 r *= (double)(up - low) + 1.0; 266 lua_pushinteger(L, (lua_Integer)r + low); 267 return 1; 268 } 269 270 271 static int math_randomseed (lua_State *L) { 272 l_srand((unsigned int)(lua_Integer)luaL_checknumber(L, 1)); 273 (void)rand(); /* discard first value to avoid undesirable correlations */ 274 return 0; 275 } 276 277 278 static int math_type (lua_State *L) { 279 if (lua_type(L, 1) == LUA_TNUMBER) { 280 if (lua_isinteger(L, 1)) 281 lua_pushliteral(L, "integer"); 282 else 283 lua_pushliteral(L, "float"); 284 } 285 else { 286 luaL_checkany(L, 1); 287 lua_pushnil(L); 288 } 289 return 1; 290 } 291 292 293 /* 294 ** {================================================================== 295 ** Deprecated functions (for compatibility only) 296 ** =================================================================== 297 */ 298 #if defined(LUA_COMPAT_MATHLIB) 299 300 static int math_cosh (lua_State *L) { 301 lua_pushnumber(L, l_mathop(cosh)(luaL_checknumber(L, 1))); 302 return 1; 303 } 304 305 static int math_sinh (lua_State *L) { 306 lua_pushnumber(L, l_mathop(sinh)(luaL_checknumber(L, 1))); 307 return 1; 308 } 309 310 static int math_tanh (lua_State *L) { 311 lua_pushnumber(L, l_mathop(tanh)(luaL_checknumber(L, 1))); 312 return 1; 313 } 314 315 static int math_pow (lua_State *L) { 316 lua_Number x = luaL_checknumber(L, 1); 317 lua_Number y = luaL_checknumber(L, 2); 318 lua_pushnumber(L, l_mathop(pow)(x, y)); 319 return 1; 320 } 321 322 static int math_frexp (lua_State *L) { 323 int e; 324 lua_pushnumber(L, l_mathop(frexp)(luaL_checknumber(L, 1), &e)); 325 lua_pushinteger(L, e); 326 return 2; 327 } 328 329 static int math_ldexp (lua_State *L) { 330 lua_Number x = luaL_checknumber(L, 1); 331 int ep = (int)luaL_checkinteger(L, 2); 332 lua_pushnumber(L, l_mathop(ldexp)(x, ep)); 333 return 1; 334 } 335 336 static int math_log10 (lua_State *L) { 337 lua_pushnumber(L, l_mathop(log10)(luaL_checknumber(L, 1))); 338 return 1; 339 } 340 341 #endif 342 /* }================================================================== */ 343 344 345 346 static const luaL_Reg mathlib[] = { 347 {"abs", math_abs}, 348 {"acos", math_acos}, 349 {"asin", math_asin}, 350 {"atan", math_atan}, 351 {"ceil", math_ceil}, 352 {"cos", math_cos}, 353 {"deg", math_deg}, 354 {"exp", math_exp}, 355 {"tointeger", math_toint}, 356 {"floor", math_floor}, 357 {"fmod", math_fmod}, 358 {"ult", math_ult}, 359 {"log", math_log}, 360 {"max", math_max}, 361 {"min", math_min}, 362 {"modf", math_modf}, 363 {"rad", math_rad}, 364 {"random", math_random}, 365 {"randomseed", math_randomseed}, 366 {"sin", math_sin}, 367 {"sqrt", math_sqrt}, 368 {"tan", math_tan}, 369 {"type", math_type}, 370 #if defined(LUA_COMPAT_MATHLIB) 371 {"atan2", math_atan}, 372 {"cosh", math_cosh}, 373 {"sinh", math_sinh}, 374 {"tanh", math_tanh}, 375 {"pow", math_pow}, 376 {"frexp", math_frexp}, 377 {"ldexp", math_ldexp}, 378 {"log10", math_log10}, 379 #endif 380 /* placeholders */ 381 {"pi", NULL}, 382 {"huge", NULL}, 383 {"maxinteger", NULL}, 384 {"mininteger", NULL}, 385 {NULL, NULL} 386 }; 387 388 389 /* 390 ** Open math library 391 */ 392 LUAMOD_API int luaopen_math (lua_State *L) { 393 luaL_newlib(L, mathlib); 394 lua_pushnumber(L, PI); 395 lua_setfield(L, -2, "pi"); 396 lua_pushnumber(L, (lua_Number)HUGE_VAL); 397 lua_setfield(L, -2, "huge"); 398 lua_pushinteger(L, LUA_MAXINTEGER); 399 lua_setfield(L, -2, "maxinteger"); 400 lua_pushinteger(L, LUA_MININTEGER); 401 lua_setfield(L, -2, "mininteger"); 402 return 1; 403 } 404 405