• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tarantool / luajit / 11139910794

02 Oct 2024 07:45AM UTC coverage: 92.891% (+0.006%) from 92.885%
11139910794

push

github

Buristan
Fix bit op coercion in DUALNUM builds.

Thanks to Sergey Kaplun.

(cherry picked from commit f5fd22203)

The `lj_carith_check64()` function coerces the given number value to the
32-bit wide value. In this case, the 64-bit-wide operands will lose
upper bits.

This patch removes the excess coercion for the DUALNUM mode and drops
the corresponding skipcond introduced for the test in the previous
commit.

Sergey Kaplun:
* added the description and the test for the problem

Part of tarantool/tarantool#10199

5684 of 6026 branches covered (94.32%)

Branch coverage included in aggregate %.

1 of 1 new or added line in 1 file covered. (100.0%)

2 existing lines in 1 file now uncovered.

21679 of 23431 relevant lines covered (92.52%)

2951479.61 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.75
/src/lib_math.c
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(.)
4✔
24
{
25
  lj_lib_checknumber(L, 1);
4✔
26
  return FFH_RETRY;
1✔
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)
5,001✔
32
{
33
  lj_lib_checknum(L, 1);
5,001✔
34
  return FFH_RETRY;
5,000✔
35
}
36
LJLIB_ASM_(math_log10)                LJLIB_REC(math_call IRCALL_log10)
37
LJLIB_ASM_(math_exp)                LJLIB_REC(math_call IRCALL_exp)
38
LJLIB_ASM_(math_sin)                LJLIB_REC(math_call IRCALL_sin)
39
LJLIB_ASM_(math_cos)                LJLIB_REC(math_call IRCALL_cos)
40
LJLIB_ASM_(math_tan)                LJLIB_REC(math_call IRCALL_tan)
41
LJLIB_ASM_(math_asin)                LJLIB_REC(math_call IRCALL_asin)
42
LJLIB_ASM_(math_acos)                LJLIB_REC(math_call IRCALL_acos)
43
LJLIB_ASM_(math_atan)                LJLIB_REC(math_call IRCALL_atan)
44
LJLIB_ASM_(math_sinh)                LJLIB_REC(math_call IRCALL_sinh)
45
LJLIB_ASM_(math_cosh)                LJLIB_REC(math_call IRCALL_cosh)
46
LJLIB_ASM_(math_tanh)                LJLIB_REC(math_call IRCALL_tanh)
47
LJLIB_ASM_(math_frexp)
48
LJLIB_ASM_(math_modf)
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)
4✔
90
{
91
  int i = 0;
4✔
92
  do { lj_lib_checknumber(L, ++i); } while (L->base+i < L->top);
4✔
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)
66,353✔
125
{
126
  uint64_t z, r = 0;
66,353✔
127
  TW223_GEN(0, 63, 31, 18)
66,353✔
128
  TW223_GEN(1, 58, 19, 28)
66,353✔
129
  TW223_GEN(2, 55, 24,  7)
66,353✔
130
  TW223_GEN(3, 47, 21,  8)
66,353✔
131
  return (r & U64x(000fffff,ffffffff)) | U64x(3ff00000,00000000);
66,353✔
132
}
133

134
/* PRNG initialization function. */
135
static void random_init(RandomState *rs, double d)
20✔
136
{
137
  uint32_t r = 0x11090601;  /* 64-k[i] as four 8 bit constants. */
20✔
138
  int i;
20✔
139
  for (i = 0; i < 4; i++) {
100✔
140
    U64double u;
80✔
141
    uint32_t m = 1u << (r&255);
80✔
142
    r >>= 8;
80✔
143
    u.d = d = d * 3.14159265358979323846 + 2.7182818284590452354;
80✔
144
    if (u.u64 < m) u.u64 += m;  /* Ensure k[i] MSB of gen[i] are non-zero. */
80✔
145
    rs->gen[i] = u.u64;
80✔
146
  }
147
  rs->valid = 1;
20✔
148
  for (i = 0; i < 10; i++)
220✔
149
    lj_math_random_step(rs);
200✔
150
}
20✔
151

152
/* PRNG extract function. */
153
LJLIB_PUSH(top-2)  /* Upvalue holds userdata with RandomState. */
154
LJLIB_CF(math_random)                LJLIB_REC(.)
61,863✔
155
{
156
  int n = (int)(L->top - L->base);
61,863✔
157
  RandomState *rs = (RandomState *)(uddata(udataV(lj_lib_upvalue(L, 1))));
61,863✔
158
  U64double u;
61,863✔
159
  double d;
61,863✔
160
  if (LJ_UNLIKELY(!rs->valid)) random_init(rs, 0.0);
61,863✔
161
  u.u64 = lj_math_random_step(rs);
61,863✔
162
  d = u.d - 1.0;
61,863✔
163
  if (n > 0) {
61,863✔
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);
507✔
176
#endif
177
    if (n == 1) {
507✔
178
      d = lj_vm_floor(d*r1) + 1.0;  /* d is an int in range [1, r1] */
251✔
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);
256✔
191
#endif
192
      d = lj_vm_floor(d*(r2-r1+1.0)) + r1;  /* d is an int in range [r1, r2] */
256✔
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);
61,863✔
202
  return 1;
61,863✔
203
}
204

205
/* PRNG seed function. */
206
LJLIB_PUSH(top-2)  /* Upvalue holds userdata with RandomState. */
207
LJLIB_CF(math_randomseed)
19✔
208
{
209
  RandomState *rs = (RandomState *)(uddata(udataV(lj_lib_upvalue(L, 1))));
19✔
210
  random_init(rs, lj_lib_checknum(L, 1));
19✔
211
  return 0;
19✔
212
}
213

214
/* ------------------------------------------------------------------------ */
215

216
#include "lj_libdef.h"
217

218
LUALIB_API int luaopen_math(lua_State *L)
335✔
219
{
220
  RandomState *rs;
335✔
221
  rs = (RandomState *)lua_newuserdata(L, sizeof(RandomState));
335✔
222
  rs->valid = 0;  /* Use lazy initialization to save some time on startup. */
335✔
223
  LJ_LIB_REG(L, LUA_MATHLIBNAME, math);
335✔
224
  return 1;
335✔
225
}
226

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc