Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Roblox
GitHub Repository: Roblox/luau
Path: blob/master/VM/src/lmathlib.cpp
2725 views
1
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
2
// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details
3
#include "lualib.h"
4
5
#include "lstate.h"
6
7
#include <limits>
8
#include <math.h>
9
#include <time.h>
10
11
#define LUAU_PI (3.14159265358979323846)
12
#define RADIANS_PER_DEGREE (LUAU_PI / 180.0)
13
14
#define LUAU_NAN (std::numeric_limits<double>::quiet_NaN())
15
#define LUAU_E (2.71828182845904523536)
16
#define LUAU_PHI (1.61803398874989484820)
17
#define LUAU_SQRT2 (1.41421356237309504880)
18
#define LUAU_TAU (6.28318530717958647692)
19
20
#define PCG32_INC 105
21
22
LUAU_FASTFLAGVARIABLE(LuauNewMathConstantsRuntime)
23
24
static uint32_t pcg32_random(uint64_t* state)
25
{
26
uint64_t oldstate = *state;
27
*state = oldstate * 6364136223846793005ULL + (PCG32_INC | 1);
28
uint32_t xorshifted = uint32_t(((oldstate >> 18u) ^ oldstate) >> 27u);
29
uint32_t rot = uint32_t(oldstate >> 59u);
30
return (xorshifted >> rot) | (xorshifted << ((-int32_t(rot)) & 31));
31
}
32
33
static void pcg32_seed(uint64_t* state, uint64_t seed)
34
{
35
*state = 0;
36
pcg32_random(state);
37
*state += seed;
38
pcg32_random(state);
39
}
40
41
static int math_abs(lua_State* L)
42
{
43
lua_pushnumber(L, fabs(luaL_checknumber(L, 1)));
44
return 1;
45
}
46
47
static int math_sin(lua_State* L)
48
{
49
lua_pushnumber(L, sin(luaL_checknumber(L, 1)));
50
return 1;
51
}
52
53
static int math_sinh(lua_State* L)
54
{
55
lua_pushnumber(L, sinh(luaL_checknumber(L, 1)));
56
return 1;
57
}
58
59
static int math_cos(lua_State* L)
60
{
61
lua_pushnumber(L, cos(luaL_checknumber(L, 1)));
62
return 1;
63
}
64
65
static int math_cosh(lua_State* L)
66
{
67
lua_pushnumber(L, cosh(luaL_checknumber(L, 1)));
68
return 1;
69
}
70
71
static int math_tan(lua_State* L)
72
{
73
lua_pushnumber(L, tan(luaL_checknumber(L, 1)));
74
return 1;
75
}
76
77
static int math_tanh(lua_State* L)
78
{
79
lua_pushnumber(L, tanh(luaL_checknumber(L, 1)));
80
return 1;
81
}
82
83
static int math_asin(lua_State* L)
84
{
85
lua_pushnumber(L, asin(luaL_checknumber(L, 1)));
86
return 1;
87
}
88
89
static int math_acos(lua_State* L)
90
{
91
lua_pushnumber(L, acos(luaL_checknumber(L, 1)));
92
return 1;
93
}
94
95
static int math_atan(lua_State* L)
96
{
97
lua_pushnumber(L, atan(luaL_checknumber(L, 1)));
98
return 1;
99
}
100
101
static int math_atan2(lua_State* L)
102
{
103
lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
104
return 1;
105
}
106
107
static int math_ceil(lua_State* L)
108
{
109
lua_pushnumber(L, ceil(luaL_checknumber(L, 1)));
110
return 1;
111
}
112
113
static int math_floor(lua_State* L)
114
{
115
lua_pushnumber(L, floor(luaL_checknumber(L, 1)));
116
return 1;
117
}
118
119
static int math_fmod(lua_State* L)
120
{
121
lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
122
return 1;
123
}
124
125
static int math_modf(lua_State* L)
126
{
127
double ip;
128
double fp = modf(luaL_checknumber(L, 1), &ip);
129
lua_pushnumber(L, ip);
130
lua_pushnumber(L, fp);
131
return 2;
132
}
133
134
static int math_sqrt(lua_State* L)
135
{
136
lua_pushnumber(L, sqrt(luaL_checknumber(L, 1)));
137
return 1;
138
}
139
140
static int math_pow(lua_State* L)
141
{
142
lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
143
return 1;
144
}
145
146
static int math_log(lua_State* L)
147
{
148
double x = luaL_checknumber(L, 1);
149
double res;
150
if (lua_isnoneornil(L, 2))
151
res = log(x);
152
else
153
{
154
double base = luaL_checknumber(L, 2);
155
if (base == 2.0)
156
res = log2(x);
157
else if (base == 10.0)
158
res = log10(x);
159
else
160
res = log(x) / log(base);
161
}
162
lua_pushnumber(L, res);
163
return 1;
164
}
165
166
static int math_log10(lua_State* L)
167
{
168
lua_pushnumber(L, log10(luaL_checknumber(L, 1)));
169
return 1;
170
}
171
172
static int math_exp(lua_State* L)
173
{
174
lua_pushnumber(L, exp(luaL_checknumber(L, 1)));
175
return 1;
176
}
177
178
static int math_deg(lua_State* L)
179
{
180
lua_pushnumber(L, luaL_checknumber(L, 1) / RADIANS_PER_DEGREE);
181
return 1;
182
}
183
184
static int math_rad(lua_State* L)
185
{
186
lua_pushnumber(L, luaL_checknumber(L, 1) * RADIANS_PER_DEGREE);
187
return 1;
188
}
189
190
static int math_frexp(lua_State* L)
191
{
192
int e;
193
lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e));
194
lua_pushinteger(L, e);
195
return 2;
196
}
197
198
static int math_ldexp(lua_State* L)
199
{
200
lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkinteger(L, 2)));
201
return 1;
202
}
203
204
static int math_min(lua_State* L)
205
{
206
int n = lua_gettop(L); // number of arguments
207
double dmin = luaL_checknumber(L, 1);
208
int i;
209
for (i = 2; i <= n; i++)
210
{
211
double d = luaL_checknumber(L, i);
212
if (d < dmin)
213
dmin = d;
214
}
215
lua_pushnumber(L, dmin);
216
return 1;
217
}
218
219
static int math_max(lua_State* L)
220
{
221
int n = lua_gettop(L); // number of arguments
222
double dmax = luaL_checknumber(L, 1);
223
int i;
224
for (i = 2; i <= n; i++)
225
{
226
double d = luaL_checknumber(L, i);
227
if (d > dmax)
228
dmax = d;
229
}
230
lua_pushnumber(L, dmax);
231
return 1;
232
}
233
234
static int math_random(lua_State* L)
235
{
236
global_State* g = L->global;
237
switch (lua_gettop(L))
238
{ // check number of arguments
239
case 0:
240
{ // no arguments
241
// Using ldexp instead of division for speed & clarity.
242
// See http://mumble.net/~campbell/tmp/random_real.c for details on generating doubles from integer ranges.
243
uint32_t rl = pcg32_random(&g->rngstate);
244
uint32_t rh = pcg32_random(&g->rngstate);
245
double rd = ldexp(double(rl | (uint64_t(rh) << 32)), -64);
246
lua_pushnumber(L, rd); // number between 0 and 1
247
break;
248
}
249
case 1:
250
{ // only upper limit
251
int u = luaL_checkinteger(L, 1);
252
luaL_argcheck(L, 1 <= u, 1, "interval is empty");
253
254
uint64_t x = uint64_t(u) * pcg32_random(&g->rngstate);
255
int r = int(1 + (x >> 32));
256
lua_pushinteger(L, r); // int between 1 and `u'
257
break;
258
}
259
case 2:
260
{ // lower and upper limits
261
int l = luaL_checkinteger(L, 1);
262
int u = luaL_checkinteger(L, 2);
263
luaL_argcheck(L, l <= u, 2, "interval is empty");
264
265
uint32_t ul = uint32_t(u) - uint32_t(l);
266
luaL_argcheck(L, ul < UINT_MAX, 2, "interval is too large"); // -INT_MIN..INT_MAX interval can result in integer overflow
267
uint64_t x = uint64_t(ul + 1) * pcg32_random(&g->rngstate);
268
int r = int(l + (x >> 32));
269
lua_pushinteger(L, r); // int between `l' and `u'
270
break;
271
}
272
default:
273
luaL_error(L, "wrong number of arguments");
274
}
275
return 1;
276
}
277
278
static int math_randomseed(lua_State* L)
279
{
280
int seed = luaL_checkinteger(L, 1);
281
282
pcg32_seed(&L->global->rngstate, seed);
283
return 0;
284
}
285
286
static const unsigned char kPerlinHash[257] = {
287
151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23,
288
190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20,
289
125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92,
290
41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196, 135, 130,
291
116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207,
292
206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43,
293
172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144,
294
12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45,
295
127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180, 151
296
};
297
298
const float kPerlinGrad[16][3] = {
299
{1, 1, 0},
300
{-1, 1, 0},
301
{1, -1, 0},
302
{-1, -1, 0},
303
{1, 0, 1},
304
{-1, 0, 1},
305
{1, 0, -1},
306
{-1, 0, -1},
307
{0, 1, 1},
308
{0, -1, 1},
309
{0, 1, -1},
310
{0, -1, -1},
311
{1, 1, 0},
312
{0, -1, 1},
313
{-1, 1, 0},
314
{0, -1, -1}
315
};
316
317
inline float perlin_fade(float t)
318
{
319
return t * t * t * (t * (t * 6 - 15) + 10);
320
}
321
322
inline float perlin_lerp(float t, float a, float b)
323
{
324
return a + t * (b - a);
325
}
326
327
inline float perlin_grad(int hash, float x, float y, float z)
328
{
329
const float* g = kPerlinGrad[hash & 15];
330
return g[0] * x + g[1] * y + g[2] * z;
331
}
332
333
static float perlin(float x, float y, float z)
334
{
335
float xflr = floorf(x);
336
float yflr = floorf(y);
337
float zflr = floorf(z);
338
339
int xi = int(xflr) & 255;
340
int yi = int(yflr) & 255;
341
int zi = int(zflr) & 255;
342
343
float xf = x - xflr;
344
float yf = y - yflr;
345
float zf = z - zflr;
346
347
float u = perlin_fade(xf);
348
float v = perlin_fade(yf);
349
float w = perlin_fade(zf);
350
351
const unsigned char* p = kPerlinHash;
352
353
int a = (p[xi] + yi) & 255;
354
int aa = (p[a] + zi) & 255;
355
int ab = (p[a + 1] + zi) & 255;
356
357
int b = (p[xi + 1] + yi) & 255;
358
int ba = (p[b] + zi) & 255;
359
int bb = (p[b + 1] + zi) & 255;
360
361
float la = perlin_lerp(u, perlin_grad(p[aa], xf, yf, zf), perlin_grad(p[ba], xf - 1, yf, zf));
362
float lb = perlin_lerp(u, perlin_grad(p[ab], xf, yf - 1, zf), perlin_grad(p[bb], xf - 1, yf - 1, zf));
363
float la1 = perlin_lerp(u, perlin_grad(p[aa + 1], xf, yf, zf - 1), perlin_grad(p[ba + 1], xf - 1, yf, zf - 1));
364
float lb1 = perlin_lerp(u, perlin_grad(p[ab + 1], xf, yf - 1, zf - 1), perlin_grad(p[bb + 1], xf - 1, yf - 1, zf - 1));
365
366
return perlin_lerp(w, perlin_lerp(v, la, lb), perlin_lerp(v, la1, lb1));
367
}
368
369
static int math_noise(lua_State* L)
370
{
371
int nx, ny, nz;
372
double x = lua_tonumberx(L, 1, &nx);
373
double y = lua_tonumberx(L, 2, &ny);
374
double z = lua_tonumberx(L, 3, &nz);
375
376
luaL_argexpected(L, nx, 1, "number");
377
luaL_argexpected(L, ny || lua_isnoneornil(L, 2), 2, "number");
378
luaL_argexpected(L, nz || lua_isnoneornil(L, 3), 3, "number");
379
380
double r = perlin((float)x, (float)y, (float)z);
381
382
lua_pushnumber(L, r);
383
return 1;
384
}
385
386
static int math_clamp(lua_State* L)
387
{
388
double v = luaL_checknumber(L, 1);
389
double min = luaL_checknumber(L, 2);
390
double max = luaL_checknumber(L, 3);
391
392
luaL_argcheck(L, min <= max, 3, "max must be greater than or equal to min");
393
394
double r = v < min ? min : v;
395
r = r > max ? max : r;
396
397
lua_pushnumber(L, r);
398
return 1;
399
}
400
401
static int math_sign(lua_State* L)
402
{
403
double v = luaL_checknumber(L, 1);
404
lua_pushnumber(L, v > 0.0 ? 1.0 : v < 0.0 ? -1.0 : 0.0);
405
return 1;
406
}
407
408
static int math_round(lua_State* L)
409
{
410
lua_pushnumber(L, round(luaL_checknumber(L, 1)));
411
return 1;
412
}
413
414
static int math_map(lua_State* L)
415
{
416
double x = luaL_checknumber(L, 1);
417
double inmin = luaL_checknumber(L, 2);
418
double inmax = luaL_checknumber(L, 3);
419
double outmin = luaL_checknumber(L, 4);
420
double outmax = luaL_checknumber(L, 5);
421
422
double result = outmin + (x - inmin) * (outmax - outmin) / (inmax - inmin);
423
lua_pushnumber(L, result);
424
return 1;
425
}
426
427
static int math_lerp(lua_State* L)
428
{
429
double a = luaL_checknumber(L, 1);
430
double b = luaL_checknumber(L, 2);
431
double t = luaL_checknumber(L, 3);
432
433
double r = (t == 1.0) ? b : a + (b - a) * t;
434
lua_pushnumber(L, r);
435
return 1;
436
}
437
438
static int math_isnan(lua_State* L)
439
{
440
double x = luaL_checknumber(L, 1);
441
442
lua_pushboolean(L, isnan(x));
443
return 1;
444
}
445
446
static int math_isinf(lua_State* L)
447
{
448
double x = luaL_checknumber(L, 1);
449
450
lua_pushboolean(L, isinf(x));
451
return 1;
452
}
453
454
static int math_isfinite(lua_State* L)
455
{
456
double x = luaL_checknumber(L, 1);
457
458
lua_pushboolean(L, isfinite(x));
459
return 1;
460
}
461
462
static const luaL_Reg mathlib[] = {
463
{"abs", math_abs},
464
{"acos", math_acos},
465
{"asin", math_asin},
466
{"atan2", math_atan2},
467
{"atan", math_atan},
468
{"ceil", math_ceil},
469
{"cosh", math_cosh},
470
{"cos", math_cos},
471
{"deg", math_deg},
472
{"exp", math_exp},
473
{"floor", math_floor},
474
{"fmod", math_fmod},
475
{"frexp", math_frexp},
476
{"ldexp", math_ldexp},
477
{"log10", math_log10},
478
{"log", math_log},
479
{"max", math_max},
480
{"min", math_min},
481
{"modf", math_modf},
482
{"pow", math_pow},
483
{"rad", math_rad},
484
{"random", math_random},
485
{"randomseed", math_randomseed},
486
{"sinh", math_sinh},
487
{"sin", math_sin},
488
{"sqrt", math_sqrt},
489
{"tanh", math_tanh},
490
{"tan", math_tan},
491
{"noise", math_noise},
492
{"clamp", math_clamp},
493
{"sign", math_sign},
494
{"round", math_round},
495
{"map", math_map},
496
{"lerp", math_lerp},
497
{"isnan", math_isnan},
498
{"isinf", math_isinf},
499
{"isfinite", math_isfinite},
500
{NULL, NULL},
501
};
502
503
/*
504
** Open math library
505
*/
506
int luaopen_math(lua_State* L)
507
{
508
uint64_t seed = lua_encodepointer(L, uintptr_t(L));
509
seed ^= time(NULL);
510
seed ^= clock();
511
512
pcg32_seed(&L->global->rngstate, seed);
513
514
luaL_register(L, LUA_MATHLIBNAME, mathlib);
515
516
lua_pushnumber(L, LUAU_PI);
517
lua_setfield(L, -2, "pi");
518
lua_pushnumber(L, HUGE_VAL);
519
lua_setfield(L, -2, "huge");
520
521
if (FFlag::LuauNewMathConstantsRuntime)
522
{
523
lua_pushnumber(L, LUAU_NAN);
524
lua_setfield(L, -2, "nan");
525
lua_pushnumber(L, LUAU_E);
526
lua_setfield(L, -2, "e");
527
lua_pushnumber(L, LUAU_PHI);
528
lua_setfield(L, -2, "phi");
529
lua_pushnumber(L, LUAU_SQRT2);
530
lua_setfield(L, -2, "sqrt2");
531
lua_pushnumber(L, LUAU_TAU);
532
lua_setfield(L, -2, "tau");
533
}
534
535
return 1;
536
}
537
538