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