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