root/lib_math.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. LJLIB_ASM
  2. LJLIB_ASM_
  3. LJLIB_ASM_
  4. LJLIB_LUA
  5. LJLIB_ASM_
  6. LJLIB_ASM
  7. LJLIB_ASM_
  8. lj_math_random_step
  9. random_init
  10. LJLIB_PUSH
  11. LJLIB_PUSH
  12. luaopen_math

   1 /*
   2 ** Math library.
   3 ** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
   4 */
   5 
   6 #include <math.h>
   7 
   8 #define lib_math_c
   9 #define LUA_LIB
  10 
  11 #include "lua.h"
  12 #include "lauxlib.h"
  13 #include "lualib.h"
  14 
  15 #include "lj_obj.h"
  16 #include "lj_lib.h"
  17 #include "lj_vm.h"
  18 
  19 /* ------------------------------------------------------------------------ */
  20 
  21 #define LJLIB_MODULE_math
  22 
  23 LJLIB_ASM(math_abs)             LJLIB_REC(.)
  24 {
  25   lj_lib_checknumber(L, 1);
  26   return FFH_RETRY;
  27 }
  28 LJLIB_ASM_(math_floor)          LJLIB_REC(math_round IRFPM_FLOOR)
  29 LJLIB_ASM_(math_ceil)           LJLIB_REC(math_round IRFPM_CEIL)
  30 
  31 LJLIB_ASM(math_sqrt)            LJLIB_REC(math_unary IRFPM_SQRT)
  32 {
  33   lj_lib_checknum(L, 1);
  34   return FFH_RETRY;
  35 }
  36 LJLIB_ASM_(math_log10)          LJLIB_REC(math_unary IRFPM_LOG10)
  37 LJLIB_ASM_(math_exp)            LJLIB_REC(math_unary IRFPM_EXP)
  38 LJLIB_ASM_(math_sin)            LJLIB_REC(math_unary IRFPM_SIN)
  39 LJLIB_ASM_(math_cos)            LJLIB_REC(math_unary IRFPM_COS)
  40 LJLIB_ASM_(math_tan)            LJLIB_REC(math_unary IRFPM_TAN)
  41 LJLIB_ASM_(math_asin)           LJLIB_REC(math_atrig FF_math_asin)
  42 LJLIB_ASM_(math_acos)           LJLIB_REC(math_atrig FF_math_acos)
  43 LJLIB_ASM_(math_atan)           LJLIB_REC(math_atrig FF_math_atan)
  44 LJLIB_ASM_(math_sinh)           LJLIB_REC(math_htrig IRCALL_sinh)
  45 LJLIB_ASM_(math_cosh)           LJLIB_REC(math_htrig IRCALL_cosh)
  46 LJLIB_ASM_(math_tanh)           LJLIB_REC(math_htrig IRCALL_tanh)
  47 LJLIB_ASM_(math_frexp)
  48 LJLIB_ASM_(math_modf)           LJLIB_REC(.)
  49 
  50 LJLIB_ASM(math_log)             LJLIB_REC(math_log)
  51 {
  52   double x = lj_lib_checknum(L, 1);
  53   if (L->base+1 < L->top) {
  54     double y = lj_lib_checknum(L, 2);
  55 #ifdef LUAJIT_NO_LOG2
  56     x = log(x); y = 1.0 / log(y);
  57 #else
  58     x = lj_vm_log2(x); y = 1.0 / lj_vm_log2(y);
  59 #endif
  60     setnumV(L->base-1-LJ_FR2, x*y);  /* Do NOT join the expression to x / y. */
  61     return FFH_RES(1);
  62   }
  63   return FFH_RETRY;
  64 }
  65 
  66 LJLIB_LUA(math_deg) /* function(x) return x * 57.29577951308232 end */
  67 LJLIB_LUA(math_rad) /* function(x) return x * 0.017453292519943295 end */
  68 
  69 LJLIB_ASM(math_atan2)           LJLIB_REC(.)
  70 {
  71   lj_lib_checknum(L, 1);
  72   lj_lib_checknum(L, 2);
  73   return FFH_RETRY;
  74 }
  75 LJLIB_ASM_(math_pow)            LJLIB_REC(.)
  76 LJLIB_ASM_(math_fmod)
  77 
  78 LJLIB_ASM(math_ldexp)           LJLIB_REC(.)
  79 {
  80   lj_lib_checknum(L, 1);
  81 #if LJ_DUALNUM && !LJ_TARGET_X86ORX64
  82   lj_lib_checkint(L, 2);
  83 #else
  84   lj_lib_checknum(L, 2);
  85 #endif
  86   return FFH_RETRY;
  87 }
  88 
  89 LJLIB_ASM(math_min)             LJLIB_REC(math_minmax IR_MIN)
  90 {
  91   int i = 0;
  92   do { lj_lib_checknumber(L, ++i); } while (L->base+i < L->top);
  93   return FFH_RETRY;
  94 }
  95 LJLIB_ASM_(math_max)            LJLIB_REC(math_minmax IR_MAX)
  96 
  97 LJLIB_PUSH(3.14159265358979323846) LJLIB_SET(pi)
  98 LJLIB_PUSH(1e310) LJLIB_SET(huge)
  99 
 100 /* ------------------------------------------------------------------------ */
 101 
 102 /* This implements a Tausworthe PRNG with period 2^223. Based on:
 103 **   Tables of maximally-equidistributed combined LFSR generators,
 104 **   Pierre L'Ecuyer, 1991, table 3, 1st entry.
 105 ** Full-period ME-CF generator with L=64, J=4, k=223, N1=49.
 106 */
 107 
 108 /* PRNG state. */
 109 struct RandomState {
 110   uint64_t gen[4];      /* State of the 4 LFSR generators. */
 111   int valid;            /* State is valid. */
 112 };
 113 
 114 /* Union needed for bit-pattern conversion between uint64_t and double. */
 115 typedef union { uint64_t u64; double d; } U64double;
 116 
 117 /* Update generator i and compute a running xor of all states. */
 118 #define TW223_GEN(i, k, q, s) \
 119   z = rs->gen[i]; \
 120   z = (((z<<q)^z) >> (k-s)) ^ ((z&((uint64_t)(int64_t)-1 << (64-k)))<<s); \
 121   r ^= z; rs->gen[i] = z;
 122 
 123 /* PRNG step function. Returns a double in the range 1.0 <= d < 2.0. */
 124 LJ_NOINLINE uint64_t LJ_FASTCALL lj_math_random_step(RandomState *rs)
 125 {
 126   uint64_t z, r = 0;
 127   TW223_GEN(0, 63, 31, 18)
 128   TW223_GEN(1, 58, 19, 28)
 129   TW223_GEN(2, 55, 24,  7)
 130   TW223_GEN(3, 47, 21,  8)
 131   return (r & U64x(000fffff,ffffffff)) | U64x(3ff00000,00000000);
 132 }
 133 
 134 /* PRNG initialization function. */
 135 static void random_init(RandomState *rs, double d)
 136 {
 137   uint32_t r = 0x11090601;  /* 64-k[i] as four 8 bit constants. */
 138   int i;
 139   for (i = 0; i < 4; i++) {
 140     U64double u;
 141     uint32_t m = 1u << (r&255);
 142     r >>= 8;
 143     u.d = d = d * 3.14159265358979323846 + 2.7182818284590452354;
 144     if (u.u64 < m) u.u64 += m;  /* Ensure k[i] MSB of gen[i] are non-zero. */
 145     rs->gen[i] = u.u64;
 146   }
 147   rs->valid = 1;
 148   for (i = 0; i < 10; i++)
 149     lj_math_random_step(rs);
 150 }
 151 
 152 /* PRNG extract function. */
 153 LJLIB_PUSH(top-2)  /* Upvalue holds userdata with RandomState. */
 154 LJLIB_CF(math_random)           LJLIB_REC(.)
 155 {
 156   int n = (int)(L->top - L->base);
 157   RandomState *rs = (RandomState *)(uddata(udataV(lj_lib_upvalue(L, 1))));
 158   U64double u;
 159   double d;
 160   if (LJ_UNLIKELY(!rs->valid)) random_init(rs, 0.0);
 161   u.u64 = lj_math_random_step(rs);
 162   d = u.d - 1.0;
 163   if (n > 0) {
 164 #if LJ_DUALNUM
 165     int isint = 1;
 166     double r1;
 167     lj_lib_checknumber(L, 1);
 168     if (tvisint(L->base)) {
 169       r1 = (lua_Number)intV(L->base);
 170     } else {
 171       isint = 0;
 172       r1 = numV(L->base);
 173     }
 174 #else
 175     double r1 = lj_lib_checknum(L, 1);
 176 #endif
 177     if (n == 1) {
 178       d = lj_vm_floor(d*r1) + 1.0;  /* d is an int in range [1, r1] */
 179     } else {
 180 #if LJ_DUALNUM
 181       double r2;
 182       lj_lib_checknumber(L, 2);
 183       if (tvisint(L->base+1)) {
 184         r2 = (lua_Number)intV(L->base+1);
 185       } else {
 186         isint = 0;
 187         r2 = numV(L->base+1);
 188       }
 189 #else
 190       double r2 = lj_lib_checknum(L, 2);
 191 #endif
 192       d = lj_vm_floor(d*(r2-r1+1.0)) + r1;  /* d is an int in range [r1, r2] */
 193     }
 194 #if LJ_DUALNUM
 195     if (isint) {
 196       setintV(L->top-1, lj_num2int(d));
 197       return 1;
 198     }
 199 #endif
 200   }  /* else: d is a double in range [0, 1] */
 201   setnumV(L->top++, d);
 202   return 1;
 203 }
 204 
 205 /* PRNG seed function. */
 206 LJLIB_PUSH(top-2)  /* Upvalue holds userdata with RandomState. */
 207 LJLIB_CF(math_randomseed)
 208 {
 209   RandomState *rs = (RandomState *)(uddata(udataV(lj_lib_upvalue(L, 1))));
 210   random_init(rs, lj_lib_checknum(L, 1));
 211   return 0;
 212 }
 213 
 214 /* ------------------------------------------------------------------------ */
 215 
 216 #include "lj_libdef.h"
 217 
 218 LUALIB_API int luaopen_math(lua_State *L)
 219 {
 220   RandomState *rs;
 221   rs = (RandomState *)lua_newuserdata(L, sizeof(RandomState));
 222   rs->valid = 0;  /* Use lazy initialization to save some time on startup. */
 223   LJ_LIB_REG(L, LUA_MATHLIBNAME, math);
 224   return 1;
 225 }
 226 

/* [<][>][^][v][top][bottom][index][help] */