LCOV - code coverage report
Current view: top level - src - lmathlib.c Coverage Total Hit
Test: Lua 5.3.6 Lines: 99.5 % 185 184
Test Date: 2024-04-28 10:23:15
Legend: Lines: hit not hit

            Line data    Source code
       1              : /*
       2              : ** $Id: lmathlib.c,v 1.119.1.1 2017/04/19 17:20:42 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            6 : static int math_abs (lua_State *L) {
      40            6 :   if (lua_isinteger(L, 1)) {
      41            3 :     lua_Integer n = lua_tointeger(L, 1);
      42            3 :     if (n < 0) n = (lua_Integer)(0u - (lua_Unsigned)n);
      43            3 :     lua_pushinteger(L, n);
      44              :   }
      45              :   else
      46            3 :     lua_pushnumber(L, l_mathop(fabs)(luaL_checknumber(L, 1)));
      47            6 :   return 1;
      48              : }
      49              : 
      50            1 : static int math_sin (lua_State *L) {
      51            1 :   lua_pushnumber(L, l_mathop(sin)(luaL_checknumber(L, 1)));
      52            1 :   return 1;
      53              : }
      54              : 
      55            1 : static int math_cos (lua_State *L) {
      56            1 :   lua_pushnumber(L, l_mathop(cos)(luaL_checknumber(L, 1)));
      57            1 :   return 1;
      58              : }
      59              : 
      60            1 : static int math_tan (lua_State *L) {
      61            1 :   lua_pushnumber(L, l_mathop(tan)(luaL_checknumber(L, 1)));
      62            1 :   return 1;
      63              : }
      64              : 
      65            1 : static int math_asin (lua_State *L) {
      66            1 :   lua_pushnumber(L, l_mathop(asin)(luaL_checknumber(L, 1)));
      67            1 :   return 1;
      68              : }
      69              : 
      70            1 : static int math_acos (lua_State *L) {
      71            1 :   lua_pushnumber(L, l_mathop(acos)(luaL_checknumber(L, 1)));
      72            1 :   return 1;
      73              : }
      74              : 
      75            2 : static int math_atan (lua_State *L) {
      76            2 :   lua_Number y = luaL_checknumber(L, 1);
      77            2 :   lua_Number x = luaL_optnumber(L, 2, 1);
      78            2 :   lua_pushnumber(L, l_mathop(atan2)(y, x));
      79            2 :   return 1;
      80              : }
      81              : 
      82              : 
      83           59 : static int math_toint (lua_State *L) {
      84              :   int valid;
      85           59 :   lua_Integer n = lua_tointegerx(L, 1, &valid);
      86           59 :   if (valid)
      87           54 :     lua_pushinteger(L, n);
      88              :   else {
      89            5 :     luaL_checkany(L, 1);
      90            5 :     lua_pushnil(L);  /* value is not convertible to integer */
      91              :   }
      92           59 :   return 1;
      93              : }
      94              : 
      95              : 
      96            7 : static void pushnumint (lua_State *L, lua_Number d) {
      97              :   lua_Integer n;
      98            7 :   if (lua_numbertointeger(d, &n))  /* does 'd' fit in an integer? */
      99            7 :     lua_pushinteger(L, n);  /* result is integer */
     100              :   else
     101            0 :     lua_pushnumber(L, d);  /* result is float */
     102            7 : }
     103              : 
     104              : 
     105            4 : static int math_floor (lua_State *L) {
     106            4 :   if (lua_isinteger(L, 1))
     107            1 :     lua_settop(L, 1);  /* integer is its own floor */
     108              :   else {
     109            3 :     lua_Number d = l_mathop(floor)(luaL_checknumber(L, 1));
     110            3 :     pushnumint(L, d);
     111              :   }
     112            4 :   return 1;
     113              : }
     114              : 
     115              : 
     116            4 : static int math_ceil (lua_State *L) {
     117            4 :   if (lua_isinteger(L, 1))
     118            1 :     lua_settop(L, 1);  /* integer is its own ceil */
     119              :   else {
     120            3 :     lua_Number d = l_mathop(ceil)(luaL_checknumber(L, 1));
     121            3 :     pushnumint(L, d);
     122              :   }
     123            4 :   return 1;
     124              : }
     125              : 
     126              : 
     127            9 : static int math_fmod (lua_State *L) {
     128           13 :   if (lua_isinteger(L, 1) && lua_isinteger(L, 2)) {
     129            5 :     lua_Integer d = lua_tointeger(L, 2);
     130            5 :     if ((lua_Unsigned)d + 1u <= 1u) {  /* special cases: -1 or 0 */
     131            2 :       luaL_argcheck(L, d != 0, 2, "zero");
     132            1 :       lua_pushinteger(L, 0);  /* avoid overflow with 0x80000... / -1 */
     133              :     }
     134              :     else
     135            3 :       lua_pushinteger(L, lua_tointeger(L, 1) % d);
     136              :   }
     137              :   else
     138            4 :     lua_pushnumber(L, l_mathop(fmod)(luaL_checknumber(L, 1),
     139              :                                      luaL_checknumber(L, 2)));
     140            8 :   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            2 : static int math_modf (lua_State *L) {
     150            2 :   if (lua_isinteger(L ,1)) {
     151            1 :     lua_settop(L, 1);  /* number is its own integer part */
     152            1 :     lua_pushnumber(L, 0);  /* no fractional part */
     153              :   }
     154              :   else {
     155            1 :     lua_Number n = luaL_checknumber(L, 1);
     156              :     /* integer part (rounds toward zero) */
     157            1 :     lua_Number ip = (n < 0) ? l_mathop(ceil)(n) : l_mathop(floor)(n);
     158            1 :     pushnumint(L, ip);
     159              :     /* fractional part (test needed for inf/-inf) */
     160            1 :     lua_pushnumber(L, (n == ip) ? l_mathop(0.0) : (n - ip));
     161              :   }
     162            2 :   return 2;
     163              : }
     164              : 
     165              : 
     166            2 : static int math_sqrt (lua_State *L) {
     167            2 :   lua_pushnumber(L, l_mathop(sqrt)(luaL_checknumber(L, 1)));
     168            2 :   return 1;
     169              : }
     170              : 
     171              : 
     172            7 : static int math_ult (lua_State *L) {
     173            7 :   lua_Integer a = luaL_checkinteger(L, 1);
     174            5 :   lua_Integer b = luaL_checkinteger(L, 2);
     175            3 :   lua_pushboolean(L, (lua_Unsigned)a < (lua_Unsigned)b);
     176            3 :   return 1;
     177              : }
     178              : 
     179            4 : static int math_log (lua_State *L) {
     180            4 :   lua_Number x = luaL_checknumber(L, 1);
     181              :   lua_Number res;
     182            4 :   if (lua_isnoneornil(L, 2))
     183            1 :     res = l_mathop(log)(x);
     184              :   else {
     185            3 :     lua_Number base = luaL_checknumber(L, 2);
     186              : #if !defined(LUA_USE_C89)
     187            3 :     if (base == l_mathop(2.0))
     188            1 :       res = l_mathop(log2)(x); else
     189              : #endif
     190            2 :     if (base == l_mathop(10.0))
     191            1 :       res = l_mathop(log10)(x);
     192              :     else
     193            1 :       res = l_mathop(log)(x)/l_mathop(log)(base);
     194              :   }
     195            4 :   lua_pushnumber(L, res);
     196            4 :   return 1;
     197              : }
     198              : 
     199            2 : static int math_exp (lua_State *L) {
     200            2 :   lua_pushnumber(L, l_mathop(exp)(luaL_checknumber(L, 1)));
     201            2 :   return 1;
     202              : }
     203              : 
     204            1 : static int math_deg (lua_State *L) {
     205            1 :   lua_pushnumber(L, luaL_checknumber(L, 1) * (l_mathop(180.0) / PI));
     206            1 :   return 1;
     207              : }
     208              : 
     209            1 : static int math_rad (lua_State *L) {
     210            1 :   lua_pushnumber(L, luaL_checknumber(L, 1) * (PI / l_mathop(180.0)));
     211            1 :   return 1;
     212              : }
     213              : 
     214              : 
     215            4 : static int math_min (lua_State *L) {
     216            4 :   int n = lua_gettop(L);  /* number of arguments */
     217            4 :   int imin = 1;  /* index of current minimum value */
     218              :   int i;
     219            4 :   luaL_argcheck(L, n >= 1, 1, "value expected");
     220            7 :   for (i = 2; i <= n; i++) {
     221            4 :     if (lua_compare(L, i, imin, LUA_OPLT))
     222            1 :       imin = i;
     223              :   }
     224            3 :   lua_pushvalue(L, imin);
     225            3 :   return 1;
     226              : }
     227              : 
     228              : 
     229            6 : static int math_max (lua_State *L) {
     230            6 :   int n = lua_gettop(L);  /* number of arguments */
     231            6 :   int imax = 1;  /* index of current maximum value */
     232              :   int i;
     233            6 :   luaL_argcheck(L, n >= 1, 1, "value expected");
     234           13 :   for (i = 2; i <= n; i++) {
     235            8 :     if (lua_compare(L, imax, i, LUA_OPLT))
     236            6 :       imax = i;
     237              :   }
     238            5 :   lua_pushvalue(L, imax);
     239            5 :   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           13 : static int math_random (lua_State *L) {
     248              :   lua_Integer low, up;
     249           13 :   double r = (double)l_rand() * (1.0 / ((double)L_RANDMAX + 1.0));
     250           13 :   switch (lua_gettop(L)) {  /* check number of arguments */
     251            4 :     case 0: {  /* no arguments */
     252            4 :       lua_pushnumber(L, (lua_Number)r);  /* Number between 0 and 1 */
     253            4 :       return 1;
     254              :     }
     255            4 :     case 1: {  /* only upper limit */
     256            4 :       low = 1;
     257            4 :       up = luaL_checkinteger(L, 1);
     258            4 :       break;
     259              :     }
     260            4 :     case 2: {  /* lower and upper limits */
     261            4 :       low = luaL_checkinteger(L, 1);
     262            4 :       up = luaL_checkinteger(L, 2);
     263            4 :       break;
     264              :     }
     265            1 :     default: return luaL_error(L, "wrong number of arguments");
     266              :   }
     267              :   /* random integer in the interval [low, up] */
     268            8 :   luaL_argcheck(L, low <= up, 1, "interval is empty");
     269            5 :   luaL_argcheck(L, low >= 0 || up <= LUA_MAXINTEGER + low, 1,
     270              :                    "interval too large");
     271            5 :   r *= (double)(up - low) + 1.0;
     272            5 :   lua_pushinteger(L, (lua_Integer)r + low);
     273            5 :   return 1;
     274              : }
     275              : 
     276              : 
     277            2 : static int math_randomseed (lua_State *L) {
     278            2 :   l_srand((unsigned int)(lua_Integer)luaL_checknumber(L, 1));
     279            2 :   (void)l_rand(); /* discard first value to avoid undesirable correlations */
     280            2 :   return 0;
     281              : }
     282              : 
     283              : 
     284           15 : static int math_type (lua_State *L) {
     285           15 :   if (lua_type(L, 1) == LUA_TNUMBER) {
     286           14 :       if (lua_isinteger(L, 1))
     287            9 :         lua_pushliteral(L, "integer");
     288              :       else
     289            5 :         lua_pushliteral(L, "float");
     290              :   }
     291              :   else {
     292            1 :     luaL_checkany(L, 1);
     293            1 :     lua_pushnil(L);
     294              :   }
     295           15 :   return 1;
     296              : }
     297              : 
     298              : 
     299              : /*
     300              : ** {==================================================================
     301              : ** Deprecated functions (for compatibility only)
     302              : ** ===================================================================
     303              : */
     304              : #if defined(LUA_COMPAT_MATHLIB)
     305              : 
     306            1 : static int math_cosh (lua_State *L) {
     307            1 :   lua_pushnumber(L, l_mathop(cosh)(luaL_checknumber(L, 1)));
     308            1 :   return 1;
     309              : }
     310              : 
     311            1 : static int math_sinh (lua_State *L) {
     312            1 :   lua_pushnumber(L, l_mathop(sinh)(luaL_checknumber(L, 1)));
     313            1 :   return 1;
     314              : }
     315              : 
     316            1 : static int math_tanh (lua_State *L) {
     317            1 :   lua_pushnumber(L, l_mathop(tanh)(luaL_checknumber(L, 1)));
     318            1 :   return 1;
     319              : }
     320              : 
     321            1 : static int math_pow (lua_State *L) {
     322            1 :   lua_Number x = luaL_checknumber(L, 1);
     323            1 :   lua_Number y = luaL_checknumber(L, 2);
     324            1 :   lua_pushnumber(L, l_mathop(pow)(x, y));
     325            1 :   return 1;
     326              : }
     327              : 
     328            1 : static int math_frexp (lua_State *L) {
     329              :   int e;
     330            1 :   lua_pushnumber(L, l_mathop(frexp)(luaL_checknumber(L, 1), &e));
     331            1 :   lua_pushinteger(L, e);
     332            1 :   return 2;
     333              : }
     334              : 
     335            1 : static int math_ldexp (lua_State *L) {
     336            1 :   lua_Number x = luaL_checknumber(L, 1);
     337            1 :   int ep = (int)luaL_checkinteger(L, 2);
     338            1 :   lua_pushnumber(L, l_mathop(ldexp)(x, ep));
     339            1 :   return 1;
     340              : }
     341              : 
     342            1 : static int math_log10 (lua_State *L) {
     343            1 :   lua_pushnumber(L, l_mathop(log10)(luaL_checknumber(L, 1)));
     344            1 :   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           86 : LUAMOD_API int luaopen_math (lua_State *L) {
     399           86 :   luaL_newlib(L, mathlib);
     400           86 :   lua_pushnumber(L, PI);
     401           86 :   lua_setfield(L, -2, "pi");
     402           86 :   lua_pushnumber(L, (lua_Number)HUGE_VAL);
     403           86 :   lua_setfield(L, -2, "huge");
     404           86 :   lua_pushinteger(L, LUA_MAXINTEGER);
     405           86 :   lua_setfield(L, -2, "maxinteger");
     406           86 :   lua_pushinteger(L, LUA_MININTEGER);
     407           86 :   lua_setfield(L, -2, "mininteger");
     408           86 :   return 1;
     409              : }
     410              : 
        

Generated by: LCOV version 2.0-1