1 /* 2 ** $Id: lmathlib.c,v 1.83.1.1 2013/04/12 18:48:47 roberto Exp $ 3 ** Standard mathematical library 4 ** See Copyright Notice in lua.h 5 */ 6 7 8 #include <stdlib.h> 9 #include <math.h> 10 11 #define lmathlib_c 12 #define LUA_LIB 13 14 #include "lua.h" 15 16 #include "lauxlib.h" 17 #include "lualib.h" 18 19 20 #undef PI 21 #define PI ((lua_Number)(3.1415926535897932384626433832795)) 22 #define RADIANS_PER_DEGREE ((lua_Number)(PI/180.0)) 23 24 25 26 static int math_abs (lua_State *L) { 27 lua_pushnumber(L, l_mathop(fabs)(luaL_checknumber(L, 1))); 28 return 1; 29 } 30 31 static int math_sin (lua_State *L) { 32 lua_pushnumber(L, l_mathop(sin)(luaL_checknumber(L, 1))); 33 return 1; 34 } 35 36 static int math_sinh (lua_State *L) { 37 lua_pushnumber(L, l_mathop(sinh)(luaL_checknumber(L, 1))); 38 return 1; 39 } 40 41 static int math_cos (lua_State *L) { 42 lua_pushnumber(L, l_mathop(cos)(luaL_checknumber(L, 1))); 43 return 1; 44 } 45 46 static int math_cosh (lua_State *L) { 47 lua_pushnumber(L, l_mathop(cosh)(luaL_checknumber(L, 1))); 48 return 1; 49 } 50 51 static int math_tan (lua_State *L) { 52 lua_pushnumber(L, l_mathop(tan)(luaL_checknumber(L, 1))); 53 return 1; 54 } 55 56 static int math_tanh (lua_State *L) { 57 lua_pushnumber(L, l_mathop(tanh)(luaL_checknumber(L, 1))); 58 return 1; 59 } 60 61 static int math_asin (lua_State *L) { 62 lua_pushnumber(L, l_mathop(asin)(luaL_checknumber(L, 1))); 63 return 1; 64 } 65 66 static int math_acos (lua_State *L) { 67 lua_pushnumber(L, l_mathop(acos)(luaL_checknumber(L, 1))); 68 return 1; 69 } 70 71 static int math_atan (lua_State *L) { 72 lua_pushnumber(L, l_mathop(atan)(luaL_checknumber(L, 1))); 73 return 1; 74 } 75 76 static int math_atan2 (lua_State *L) { 77 lua_pushnumber(L, l_mathop(atan2)(luaL_checknumber(L, 1), 78 luaL_checknumber(L, 2))); 79 return 1; 80 } 81 82 static int math_ceil (lua_State *L) { 83 lua_pushnumber(L, l_mathop(ceil)(luaL_checknumber(L, 1))); 84 return 1; 85 } 86 87 static int math_floor (lua_State *L) { 88 lua_pushnumber(L, l_mathop(floor)(luaL_checknumber(L, 1))); 89 return 1; 90 } 91 92 static int math_fmod (lua_State *L) { 93 lua_pushnumber(L, l_mathop(fmod)(luaL_checknumber(L, 1), 94 luaL_checknumber(L, 2))); 95 return 1; 96 } 97 98 static int math_modf (lua_State *L) { 99 lua_Number ip; 100 lua_Number fp = l_mathop(modf)(luaL_checknumber(L, 1), &ip); 101 lua_pushnumber(L, ip); 102 lua_pushnumber(L, fp); 103 return 2; 104 } 105 106 static int math_sqrt (lua_State *L) { 107 lua_pushnumber(L, l_mathop(sqrt)(luaL_checknumber(L, 1))); 108 return 1; 109 } 110 111 static int math_pow (lua_State *L) { 112 lua_Number x = luaL_checknumber(L, 1); 113 lua_Number y = luaL_checknumber(L, 2); 114 lua_pushnumber(L, l_mathop(pow)(x, y)); 115 return 1; 116 } 117 118 static int math_log (lua_State *L) { 119 lua_Number x = luaL_checknumber(L, 1); 120 lua_Number res; 121 if (lua_isnoneornil(L, 2)) 122 res = l_mathop(log)(x); 123 else { 124 lua_Number base = luaL_checknumber(L, 2); 125 if (base == (lua_Number)10.0) res = l_mathop(log10)(x); 126 else res = l_mathop(log)(x)/l_mathop(log)(base); 127 } 128 lua_pushnumber(L, res); 129 return 1; 130 } 131 132 #if defined(LUA_COMPAT_LOG10) 133 static int math_log10 (lua_State *L) { 134 lua_pushnumber(L, l_mathop(log10)(luaL_checknumber(L, 1))); 135 return 1; 136 } 137 #endif 138 139 static int math_exp (lua_State *L) { 140 lua_pushnumber(L, l_mathop(exp)(luaL_checknumber(L, 1))); 141 return 1; 142 } 143 144 static int math_deg (lua_State *L) { 145 lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE); 146 return 1; 147 } 148 149 static int math_rad (lua_State *L) { 150 lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE); 151 return 1; 152 } 153 154 static int math_frexp (lua_State *L) { 155 int e; 156 lua_pushnumber(L, l_mathop(frexp)(luaL_checknumber(L, 1), &e)); 157 lua_pushinteger(L, e); 158 return 2; 159 } 160 161 static int math_ldexp (lua_State *L) { 162 lua_Number x = luaL_checknumber(L, 1); 163 int ep = luaL_checkint(L, 2); 164 lua_pushnumber(L, l_mathop(ldexp)(x, ep)); 165 return 1; 166 } 167 168 169 170 static int math_min (lua_State *L) { 171 int n = lua_gettop(L); /* number of arguments */ 172 lua_Number dmin = luaL_checknumber(L, 1); 173 int i; 174 for (i=2; i<=n; i++) { 175 lua_Number d = luaL_checknumber(L, i); 176 if (d < dmin) 177 dmin = d; 178 } 179 lua_pushnumber(L, dmin); 180 return 1; 181 } 182 183 184 static int math_max (lua_State *L) { 185 int n = lua_gettop(L); /* number of arguments */ 186 lua_Number dmax = luaL_checknumber(L, 1); 187 int i; 188 for (i=2; i<=n; i++) { 189 lua_Number d = luaL_checknumber(L, i); 190 if (d > dmax) 191 dmax = d; 192 } 193 lua_pushnumber(L, dmax); 194 return 1; 195 } 196 197 198 static int math_random (lua_State *L) { 199 /* the `%' avoids the (rare) case of r==1, and is needed also because on 200 some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */ 201 lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX; 202 switch (lua_gettop(L)) { /* check number of arguments */ 203 case 0: { /* no arguments */ 204 lua_pushnumber(L, r); /* Number between 0 and 1 */ 205 break; 206 } 207 case 1: { /* only upper limit */ 208 lua_Number u = luaL_checknumber(L, 1); 209 luaL_argcheck(L, (lua_Number)1.0 <= u, 1, "interval is empty"); 210 lua_pushnumber(L, l_mathop(floor)(r*u) + (lua_Number)(1.0)); /* [1, u] */ 211 break; 212 } 213 case 2: { /* lower and upper limits */ 214 lua_Number l = luaL_checknumber(L, 1); 215 lua_Number u = luaL_checknumber(L, 2); 216 luaL_argcheck(L, l <= u, 2, "interval is empty"); 217 lua_pushnumber(L, l_mathop(floor)(r*(u-l+1)) + l); /* [l, u] */ 218 break; 219 } 220 default: return luaL_error(L, "wrong number of arguments"); 221 } 222 return 1; 223 } 224 225 226 static int math_randomseed (lua_State *L) { 227 srand(luaL_checkunsigned(L, 1)); 228 (void)rand(); /* discard first value to avoid undesirable correlations */ 229 return 0; 230 } 231 232 233 static const luaL_Reg mathlib[] = { 234 {"abs", math_abs}, 235 {"acos", math_acos}, 236 {"asin", math_asin}, 237 {"atan2", math_atan2}, 238 {"atan", math_atan}, 239 {"ceil", math_ceil}, 240 {"cosh", math_cosh}, 241 {"cos", math_cos}, 242 {"deg", math_deg}, 243 {"exp", math_exp}, 244 {"floor", math_floor}, 245 {"fmod", math_fmod}, 246 {"frexp", math_frexp}, 247 {"ldexp", math_ldexp}, 248 #if defined(LUA_COMPAT_LOG10) 249 {"log10", math_log10}, 250 #endif 251 {"log", math_log}, 252 {"max", math_max}, 253 {"min", math_min}, 254 {"modf", math_modf}, 255 {"pow", math_pow}, 256 {"rad", math_rad}, 257 {"random", math_random}, 258 {"randomseed", math_randomseed}, 259 {"sinh", math_sinh}, 260 {"sin", math_sin}, 261 {"sqrt", math_sqrt}, 262 {"tanh", math_tanh}, 263 {"tan", math_tan}, 264 {NULL, NULL} 265 }; 266 267 268 /* 269 ** Open math library 270 */ 271 LUAMOD_API int luaopen_math (lua_State *L) { 272 luaL_newlib(L, mathlib); 273 lua_pushnumber(L, PI); 274 lua_setfield(L, -2, "pi"); 275 lua_pushnumber(L, HUGE_VAL); 276 lua_setfield(L, -2, "huge"); 277 return 1; 278 } 279 280