mirror of
https://github.com/luau-lang/luau.git
synced 2024-12-14 06:00:39 +00:00
76f67e0733
Type checker/autocomplete: * `Luau::autocomplete` no longer performs typechecking internally, make sure to run `Frontend::check` before performing autocomplete requests * Autocomplete string suggestions without "" are now only suggested inside the "" * Autocomplete suggestions now include `function (anonymous autofilled)` key with a full suggestion for the function expression (with arguments included) stored in `AutocompleteEntry::insertText` * `AutocompleteEntry::indexedWithSelf` is provided for function call suggestions made with `:` * Cyclic modules now see each other type exports as `any` to prevent memory use-after-free (similar to module return type) Runtime: * Updated inline/loop unroll cost model to better handle assignments (Fixes https://github.com/Roblox/luau/issues/978) * `math.noise` speed was improved by ~30% * `table.concat` speed was improved by ~5-7% * `tonumber` and `tostring` now have fastcall paths that execute ~1.5x and ~2.5x faster respectively (fixes #777) * Fixed crash in `luaL_typename` when index refers to a non-existing value * Fixed potential out of memory scenario when using `string.sub` or `string.char` in a loop * Fixed behavior of some fastcall builtins when called without arguments under -O2 to match original functions * Support for native code execution in VM is now enabled by default (note: native code still has to be generated explicitly) * `Codegen::compile` now accepts `CodeGen_OnlyNativeModules` flag. When set, only modules that have a `--!native` hot-comment at the top will be compiled to native code In our new typechecker: * Generic type packs are no longer considered to be variadic during unification * Timeout and cancellation now works in new solver * Fixed false positive errors around 'table' and 'function' type refinements * Table literals now use covariant unification rules. This is sound since literal has no type specified and has no aliases * Fixed issues with blocked types escaping the constraint solver * Fixed more places where error messages that should've been suppressed were still reported * Fixed errors when iterating over a top table type In our native code generation (jit): * 'DebugLuauAbortingChecks' flag is now supported on A64 * LOP_NEWCLOSURE has been translated to IR
525 lines
16 KiB
C++
525 lines
16 KiB
C++
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
|
|
// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details
|
|
#include "lualib.h"
|
|
|
|
#include "lstate.h"
|
|
|
|
#include <math.h>
|
|
#include <time.h>
|
|
|
|
LUAU_FASTFLAGVARIABLE(LuauFasterNoise, false)
|
|
|
|
#undef PI
|
|
#define PI (3.14159265358979323846)
|
|
#define RADIANS_PER_DEGREE (PI / 180.0)
|
|
|
|
#define PCG32_INC 105
|
|
|
|
static uint32_t pcg32_random(uint64_t* state)
|
|
{
|
|
uint64_t oldstate = *state;
|
|
*state = oldstate * 6364136223846793005ULL + (PCG32_INC | 1);
|
|
uint32_t xorshifted = uint32_t(((oldstate >> 18u) ^ oldstate) >> 27u);
|
|
uint32_t rot = uint32_t(oldstate >> 59u);
|
|
return (xorshifted >> rot) | (xorshifted << ((-int32_t(rot)) & 31));
|
|
}
|
|
|
|
static void pcg32_seed(uint64_t* state, uint64_t seed)
|
|
{
|
|
*state = 0;
|
|
pcg32_random(state);
|
|
*state += seed;
|
|
pcg32_random(state);
|
|
}
|
|
|
|
static int math_abs(lua_State* L)
|
|
{
|
|
lua_pushnumber(L, fabs(luaL_checknumber(L, 1)));
|
|
return 1;
|
|
}
|
|
|
|
static int math_sin(lua_State* L)
|
|
{
|
|
lua_pushnumber(L, sin(luaL_checknumber(L, 1)));
|
|
return 1;
|
|
}
|
|
|
|
static int math_sinh(lua_State* L)
|
|
{
|
|
lua_pushnumber(L, sinh(luaL_checknumber(L, 1)));
|
|
return 1;
|
|
}
|
|
|
|
static int math_cos(lua_State* L)
|
|
{
|
|
lua_pushnumber(L, cos(luaL_checknumber(L, 1)));
|
|
return 1;
|
|
}
|
|
|
|
static int math_cosh(lua_State* L)
|
|
{
|
|
lua_pushnumber(L, cosh(luaL_checknumber(L, 1)));
|
|
return 1;
|
|
}
|
|
|
|
static int math_tan(lua_State* L)
|
|
{
|
|
lua_pushnumber(L, tan(luaL_checknumber(L, 1)));
|
|
return 1;
|
|
}
|
|
|
|
static int math_tanh(lua_State* L)
|
|
{
|
|
lua_pushnumber(L, tanh(luaL_checknumber(L, 1)));
|
|
return 1;
|
|
}
|
|
|
|
static int math_asin(lua_State* L)
|
|
{
|
|
lua_pushnumber(L, asin(luaL_checknumber(L, 1)));
|
|
return 1;
|
|
}
|
|
|
|
static int math_acos(lua_State* L)
|
|
{
|
|
lua_pushnumber(L, acos(luaL_checknumber(L, 1)));
|
|
return 1;
|
|
}
|
|
|
|
static int math_atan(lua_State* L)
|
|
{
|
|
lua_pushnumber(L, atan(luaL_checknumber(L, 1)));
|
|
return 1;
|
|
}
|
|
|
|
static int math_atan2(lua_State* L)
|
|
{
|
|
lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
|
|
return 1;
|
|
}
|
|
|
|
static int math_ceil(lua_State* L)
|
|
{
|
|
lua_pushnumber(L, ceil(luaL_checknumber(L, 1)));
|
|
return 1;
|
|
}
|
|
|
|
static int math_floor(lua_State* L)
|
|
{
|
|
lua_pushnumber(L, floor(luaL_checknumber(L, 1)));
|
|
return 1;
|
|
}
|
|
|
|
static int math_fmod(lua_State* L)
|
|
{
|
|
lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
|
|
return 1;
|
|
}
|
|
|
|
static int math_modf(lua_State* L)
|
|
{
|
|
double ip;
|
|
double fp = modf(luaL_checknumber(L, 1), &ip);
|
|
lua_pushnumber(L, ip);
|
|
lua_pushnumber(L, fp);
|
|
return 2;
|
|
}
|
|
|
|
static int math_sqrt(lua_State* L)
|
|
{
|
|
lua_pushnumber(L, sqrt(luaL_checknumber(L, 1)));
|
|
return 1;
|
|
}
|
|
|
|
static int math_pow(lua_State* L)
|
|
{
|
|
lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
|
|
return 1;
|
|
}
|
|
|
|
static int math_log(lua_State* L)
|
|
{
|
|
double x = luaL_checknumber(L, 1);
|
|
double res;
|
|
if (lua_isnoneornil(L, 2))
|
|
res = log(x);
|
|
else
|
|
{
|
|
double base = luaL_checknumber(L, 2);
|
|
if (base == 2.0)
|
|
res = log2(x);
|
|
else if (base == 10.0)
|
|
res = log10(x);
|
|
else
|
|
res = log(x) / log(base);
|
|
}
|
|
lua_pushnumber(L, res);
|
|
return 1;
|
|
}
|
|
|
|
static int math_log10(lua_State* L)
|
|
{
|
|
lua_pushnumber(L, log10(luaL_checknumber(L, 1)));
|
|
return 1;
|
|
}
|
|
|
|
static int math_exp(lua_State* L)
|
|
{
|
|
lua_pushnumber(L, exp(luaL_checknumber(L, 1)));
|
|
return 1;
|
|
}
|
|
|
|
static int math_deg(lua_State* L)
|
|
{
|
|
lua_pushnumber(L, luaL_checknumber(L, 1) / RADIANS_PER_DEGREE);
|
|
return 1;
|
|
}
|
|
|
|
static int math_rad(lua_State* L)
|
|
{
|
|
lua_pushnumber(L, luaL_checknumber(L, 1) * RADIANS_PER_DEGREE);
|
|
return 1;
|
|
}
|
|
|
|
static int math_frexp(lua_State* L)
|
|
{
|
|
int e;
|
|
lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e));
|
|
lua_pushinteger(L, e);
|
|
return 2;
|
|
}
|
|
|
|
static int math_ldexp(lua_State* L)
|
|
{
|
|
lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkinteger(L, 2)));
|
|
return 1;
|
|
}
|
|
|
|
static int math_min(lua_State* L)
|
|
{
|
|
int n = lua_gettop(L); // number of arguments
|
|
double dmin = luaL_checknumber(L, 1);
|
|
int i;
|
|
for (i = 2; i <= n; i++)
|
|
{
|
|
double d = luaL_checknumber(L, i);
|
|
if (d < dmin)
|
|
dmin = d;
|
|
}
|
|
lua_pushnumber(L, dmin);
|
|
return 1;
|
|
}
|
|
|
|
static int math_max(lua_State* L)
|
|
{
|
|
int n = lua_gettop(L); // number of arguments
|
|
double dmax = luaL_checknumber(L, 1);
|
|
int i;
|
|
for (i = 2; i <= n; i++)
|
|
{
|
|
double d = luaL_checknumber(L, i);
|
|
if (d > dmax)
|
|
dmax = d;
|
|
}
|
|
lua_pushnumber(L, dmax);
|
|
return 1;
|
|
}
|
|
|
|
static int math_random(lua_State* L)
|
|
{
|
|
global_State* g = L->global;
|
|
switch (lua_gettop(L))
|
|
{ // check number of arguments
|
|
case 0:
|
|
{ // no arguments
|
|
// Using ldexp instead of division for speed & clarity.
|
|
// See http://mumble.net/~campbell/tmp/random_real.c for details on generating doubles from integer ranges.
|
|
uint32_t rl = pcg32_random(&g->rngstate);
|
|
uint32_t rh = pcg32_random(&g->rngstate);
|
|
double rd = ldexp(double(rl | (uint64_t(rh) << 32)), -64);
|
|
lua_pushnumber(L, rd); // number between 0 and 1
|
|
break;
|
|
}
|
|
case 1:
|
|
{ // only upper limit
|
|
int u = luaL_checkinteger(L, 1);
|
|
luaL_argcheck(L, 1 <= u, 1, "interval is empty");
|
|
|
|
uint64_t x = uint64_t(u) * pcg32_random(&g->rngstate);
|
|
int r = int(1 + (x >> 32));
|
|
lua_pushinteger(L, r); // int between 1 and `u'
|
|
break;
|
|
}
|
|
case 2:
|
|
{ // lower and upper limits
|
|
int l = luaL_checkinteger(L, 1);
|
|
int u = luaL_checkinteger(L, 2);
|
|
luaL_argcheck(L, l <= u, 2, "interval is empty");
|
|
|
|
uint32_t ul = uint32_t(u) - uint32_t(l);
|
|
luaL_argcheck(L, ul < UINT_MAX, 2, "interval is too large"); // -INT_MIN..INT_MAX interval can result in integer overflow
|
|
uint64_t x = uint64_t(ul + 1) * pcg32_random(&g->rngstate);
|
|
int r = int(l + (x >> 32));
|
|
lua_pushinteger(L, r); // int between `l' and `u'
|
|
break;
|
|
}
|
|
default:
|
|
luaL_error(L, "wrong number of arguments");
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static int math_randomseed(lua_State* L)
|
|
{
|
|
int seed = luaL_checkinteger(L, 1);
|
|
|
|
pcg32_seed(&L->global->rngstate, seed);
|
|
return 0;
|
|
}
|
|
|
|
// TODO: Delete with LuauFasterNoise
|
|
static const unsigned char kPerlin[512] = {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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61,
|
|
156, 180};
|
|
|
|
static const unsigned char kPerlinHash[257] = {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, 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, 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, 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, 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, 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, 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, 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, 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};
|
|
|
|
const float kPerlinGrad[16][3] = {{1, 1, 0}, {-1, 1, 0}, {1, -1, 0}, {-1, -1, 0}, {1, 0, 1}, {-1, 0, 1}, {1, 0, -1}, {-1, 0, -1}, {0, 1, 1},
|
|
{0, -1, 1}, {0, 1, -1}, {0, -1, -1}, {1, 1, 0}, {0, -1, 1}, {-1, 1, 0}, {0, -1, -1}};
|
|
|
|
static float perlin_fade(float t)
|
|
{
|
|
return t * t * t * (t * (t * 6 - 15) + 10);
|
|
}
|
|
|
|
static float perlin_lerp(float t, float a, float b)
|
|
{
|
|
return a + t * (b - a);
|
|
}
|
|
|
|
static float grad(unsigned char hash, float x, float y, float z)
|
|
{
|
|
LUAU_ASSERT(!FFlag::LuauFasterNoise);
|
|
unsigned char h = hash & 15;
|
|
float u = (h < 8) ? x : y;
|
|
float v = (h < 4) ? y : (h == 12 || h == 14) ? x : z;
|
|
|
|
return (h & 1 ? -u : u) + (h & 2 ? -v : v);
|
|
}
|
|
|
|
static float perlin_grad(int hash, float x, float y, float z)
|
|
{
|
|
const float* g = kPerlinGrad[hash & 15];
|
|
return g[0] * x + g[1] * y + g[2] * z;
|
|
}
|
|
|
|
static float perlin_dep(float x, float y, float z)
|
|
{
|
|
LUAU_ASSERT(!FFlag::LuauFasterNoise);
|
|
float xflr = floorf(x);
|
|
float yflr = floorf(y);
|
|
float zflr = floorf(z);
|
|
|
|
int xi = int(xflr) & 255;
|
|
int yi = int(yflr) & 255;
|
|
int zi = int(zflr) & 255;
|
|
|
|
float xf = x - xflr;
|
|
float yf = y - yflr;
|
|
float zf = z - zflr;
|
|
|
|
float u = perlin_fade(xf);
|
|
float v = perlin_fade(yf);
|
|
float w = perlin_fade(zf);
|
|
|
|
const unsigned char* p = kPerlin;
|
|
|
|
int a = p[xi] + yi;
|
|
int aa = p[a] + zi;
|
|
int ab = p[a + 1] + zi;
|
|
|
|
int b = p[xi + 1] + yi;
|
|
int ba = p[b] + zi;
|
|
int bb = p[b + 1] + zi;
|
|
|
|
return perlin_lerp(w,
|
|
perlin_lerp(v, perlin_lerp(u, grad(p[aa], xf, yf, zf), grad(p[ba], xf - 1, yf, zf)),
|
|
perlin_lerp(u, grad(p[ab], xf, yf - 1, zf), grad(p[bb], xf - 1, yf - 1, zf))),
|
|
perlin_lerp(v, perlin_lerp(u, grad(p[aa + 1], xf, yf, zf - 1), grad(p[ba + 1], xf - 1, yf, zf - 1)),
|
|
perlin_lerp(u, grad(p[ab + 1], xf, yf - 1, zf - 1), grad(p[bb + 1], xf - 1, yf - 1, zf - 1))));
|
|
}
|
|
|
|
static float perlin(float x, float y, float z)
|
|
{
|
|
LUAU_ASSERT(FFlag::LuauFasterNoise);
|
|
float xflr = floorf(x);
|
|
float yflr = floorf(y);
|
|
float zflr = floorf(z);
|
|
|
|
int xi = int(xflr) & 255;
|
|
int yi = int(yflr) & 255;
|
|
int zi = int(zflr) & 255;
|
|
|
|
float xf = x - xflr;
|
|
float yf = y - yflr;
|
|
float zf = z - zflr;
|
|
|
|
float u = perlin_fade(xf);
|
|
float v = perlin_fade(yf);
|
|
float w = perlin_fade(zf);
|
|
|
|
const unsigned char* p = kPerlinHash;
|
|
|
|
int a = (p[xi] + yi) & 255;
|
|
int aa = (p[a] + zi) & 255;
|
|
int ab = (p[a + 1] + zi) & 255;
|
|
|
|
int b = (p[xi + 1] + yi) & 255;
|
|
int ba = (p[b] + zi) & 255;
|
|
int bb = (p[b + 1] + zi) & 255;
|
|
|
|
float la = perlin_lerp(u, perlin_grad(p[aa], xf, yf, zf), perlin_grad(p[ba], xf - 1, yf, zf));
|
|
float lb = perlin_lerp(u, perlin_grad(p[ab], xf, yf - 1, zf), perlin_grad(p[bb], xf - 1, yf - 1, zf));
|
|
float la1 = perlin_lerp(u, perlin_grad(p[aa + 1], xf, yf, zf - 1), perlin_grad(p[ba + 1], xf - 1, yf, zf - 1));
|
|
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));
|
|
|
|
return perlin_lerp(w, perlin_lerp(v, la, lb), perlin_lerp(v, la1, lb1));
|
|
}
|
|
|
|
static int math_noise(lua_State* L)
|
|
{
|
|
if (FFlag::LuauFasterNoise)
|
|
{
|
|
int nx, ny, nz;
|
|
double x = lua_tonumberx(L, 1, &nx);
|
|
double y = lua_tonumberx(L, 2, &ny);
|
|
double z = lua_tonumberx(L, 3, &nz);
|
|
|
|
luaL_argexpected(L, nx, 1, "number");
|
|
luaL_argexpected(L, ny || lua_isnoneornil(L, 2), 2, "number");
|
|
luaL_argexpected(L, nz || lua_isnoneornil(L, 3), 3, "number");
|
|
|
|
double r = perlin((float)x, (float)y, (float)z);
|
|
|
|
lua_pushnumber(L, r);
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
double x = luaL_checknumber(L, 1);
|
|
double y = luaL_optnumber(L, 2, 0.0);
|
|
double z = luaL_optnumber(L, 3, 0.0);
|
|
|
|
double r = perlin_dep((float)x, (float)y, (float)z);
|
|
|
|
lua_pushnumber(L, r);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
static int math_clamp(lua_State* L)
|
|
{
|
|
double v = luaL_checknumber(L, 1);
|
|
double min = luaL_checknumber(L, 2);
|
|
double max = luaL_checknumber(L, 3);
|
|
|
|
luaL_argcheck(L, min <= max, 3, "max must be greater than or equal to min");
|
|
|
|
double r = v < min ? min : v;
|
|
r = r > max ? max : r;
|
|
|
|
lua_pushnumber(L, r);
|
|
return 1;
|
|
}
|
|
|
|
static int math_sign(lua_State* L)
|
|
{
|
|
double v = luaL_checknumber(L, 1);
|
|
lua_pushnumber(L, v > 0.0 ? 1.0 : v < 0.0 ? -1.0 : 0.0);
|
|
return 1;
|
|
}
|
|
|
|
static int math_round(lua_State* L)
|
|
{
|
|
lua_pushnumber(L, round(luaL_checknumber(L, 1)));
|
|
return 1;
|
|
}
|
|
|
|
static const luaL_Reg mathlib[] = {
|
|
{"abs", math_abs},
|
|
{"acos", math_acos},
|
|
{"asin", math_asin},
|
|
{"atan2", math_atan2},
|
|
{"atan", math_atan},
|
|
{"ceil", math_ceil},
|
|
{"cosh", math_cosh},
|
|
{"cos", math_cos},
|
|
{"deg", math_deg},
|
|
{"exp", math_exp},
|
|
{"floor", math_floor},
|
|
{"fmod", math_fmod},
|
|
{"frexp", math_frexp},
|
|
{"ldexp", math_ldexp},
|
|
{"log10", math_log10},
|
|
{"log", math_log},
|
|
{"max", math_max},
|
|
{"min", math_min},
|
|
{"modf", math_modf},
|
|
{"pow", math_pow},
|
|
{"rad", math_rad},
|
|
{"random", math_random},
|
|
{"randomseed", math_randomseed},
|
|
{"sinh", math_sinh},
|
|
{"sin", math_sin},
|
|
{"sqrt", math_sqrt},
|
|
{"tanh", math_tanh},
|
|
{"tan", math_tan},
|
|
{"noise", math_noise},
|
|
{"clamp", math_clamp},
|
|
{"sign", math_sign},
|
|
{"round", math_round},
|
|
{NULL, NULL},
|
|
};
|
|
|
|
/*
|
|
** Open math library
|
|
*/
|
|
int luaopen_math(lua_State* L)
|
|
{
|
|
uint64_t seed = uintptr_t(L);
|
|
seed ^= time(NULL);
|
|
seed ^= clock();
|
|
|
|
pcg32_seed(&L->global->rngstate, seed);
|
|
|
|
luaL_register(L, LUA_MATHLIBNAME, mathlib);
|
|
lua_pushnumber(L, PI);
|
|
lua_setfield(L, -2, "pi");
|
|
lua_pushnumber(L, HUGE_VAL);
|
|
lua_setfield(L, -2, "huge");
|
|
return 1;
|
|
}
|