summaryrefslogtreecommitdiff
path: root/src/lmathlib.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/lmathlib.js')
-rw-r--r--src/lmathlib.js220
1 files changed, 136 insertions, 84 deletions
diff --git a/src/lmathlib.js b/src/lmathlib.js
index ac41d8a..8313e93 100644
--- a/src/lmathlib.js
+++ b/src/lmathlib.js
@@ -1,138 +1,189 @@
"use strict";
-const lua = require('./lua.js');
-const lauxlib = require('./lauxlib.js');
-const luaconf = require('./luaconf.js');
+const {
+ LUA_OPLT,
+ LUA_TNUMBER,
+ lua_compare,
+ lua_gettop,
+ lua_isinteger,
+ lua_isnoneornil,
+ lua_pushboolean,
+ lua_pushinteger,
+ lua_pushliteral,
+ lua_pushnil,
+ lua_pushnumber,
+ lua_pushvalue,
+ lua_setfield,
+ lua_settop,
+ lua_tointeger,
+ lua_tointegerx,
+ lua_type
+} = require('./lua.js');
+const {
+ luaL_argcheck,
+ luaL_argerror,
+ luaL_checkany,
+ luaL_checkinteger,
+ luaL_checknumber,
+ luaL_error,
+ luaL_newlib,
+ luaL_optnumber
+} = require('./lauxlib.js');
+const {
+ LUA_MAXINTEGER,
+ LUA_MININTEGER,
+ lua_numbertointeger
+} = require('./luaconf.js');
+const { to_luastring } = require("./fengaricore.js");
+
+let rand_state;
+/* use same parameters as glibc LCG */
+const l_rand = function() {
+ rand_state = (1103515245 * rand_state + 12345) & 0x7fffffff;
+ return rand_state;
+};
+const l_srand = function(x) {
+ rand_state = x|0;
+ if (rand_state === 0)
+ rand_state = 1;
+};
const math_random = function(L) {
let low, up;
- let r = Math.random();
- switch (lua.lua_gettop(L)) { /* check number of arguments */
+ /* use Math.random until randomseed is called */
+ let r = (rand_state === void 0)?Math.random():(l_rand() / 0x80000000);
+ switch (lua_gettop(L)) { /* check number of arguments */
case 0:
- lua.lua_pushnumber(L, r); /* Number between 0 and 1 */
+ lua_pushnumber(L, r); /* Number between 0 and 1 */
return 1;
case 1: {
low = 1;
- up = lauxlib.luaL_checkinteger(L, 1);
+ up = luaL_checkinteger(L, 1);
break;
}
case 2: {
- low = lauxlib.luaL_checkinteger(L, 1);
- up = lauxlib.luaL_checkinteger(L, 2);
+ low = luaL_checkinteger(L, 1);
+ up = luaL_checkinteger(L, 2);
break;
}
- default: return lauxlib.luaL_error(L, "wrong number of arguments");
+ default: return luaL_error(L, "wrong number of arguments");
}
/* random integer in the interval [low, up] */
- lauxlib.luaL_argcheck(L, low <= up, 1, "interval is empty");
- lauxlib.luaL_argcheck(L, low >= 0 || up <= luaconf.LUA_MAXINTEGER + low, 1,
+ luaL_argcheck(L, low <= up, 1, "interval is empty");
+ luaL_argcheck(L, low >= 0 || up <= LUA_MAXINTEGER + low, 1,
"interval too large");
r *= (up - low) + 1;
- lua.lua_pushinteger(L, Math.floor(r) + low);
+ lua_pushinteger(L, Math.floor(r) + low);
return 1;
};
+const math_randomseed = function(L) {
+ l_srand(luaL_checknumber(L, 1));
+ l_rand(); /* discard first value to avoid undesirable correlations */
+ return 0;
+};
+
const math_abs = function(L) {
- if (lua.lua_isinteger(L, 1)) {
- let n = lua.lua_tointeger(L, 1);
+ if (lua_isinteger(L, 1)) {
+ let n = lua_tointeger(L, 1);
if (n < 0) n = (-n)|0;
- lua.lua_pushinteger(L, n);
+ lua_pushinteger(L, n);
}
else
- lua.lua_pushnumber(L, Math.abs(lauxlib.luaL_checknumber(L, 1)));
+ lua_pushnumber(L, Math.abs(luaL_checknumber(L, 1)));
return 1;
};
const math_sin = function(L) {
- lua.lua_pushnumber(L, Math.sin(lauxlib.luaL_checknumber(L, 1)));
+ lua_pushnumber(L, Math.sin(luaL_checknumber(L, 1)));
return 1;
};
const math_cos = function(L) {
- lua.lua_pushnumber(L, Math.cos(lauxlib.luaL_checknumber(L, 1)));
+ lua_pushnumber(L, Math.cos(luaL_checknumber(L, 1)));
return 1;
};
const math_tan = function(L) {
- lua.lua_pushnumber(L, Math.tan(lauxlib.luaL_checknumber(L, 1)));
+ lua_pushnumber(L, Math.tan(luaL_checknumber(L, 1)));
return 1;
};
const math_asin = function(L) {
- lua.lua_pushnumber(L, Math.asin(lauxlib.luaL_checknumber(L, 1)));
+ lua_pushnumber(L, Math.asin(luaL_checknumber(L, 1)));
return 1;
};
const math_acos = function(L) {
- lua.lua_pushnumber(L, Math.acos(lauxlib.luaL_checknumber(L, 1)));
+ lua_pushnumber(L, Math.acos(luaL_checknumber(L, 1)));
return 1;
};
const math_atan = function(L) {
- let y = lauxlib.luaL_checknumber(L, 1);
- let x = lauxlib.luaL_optnumber(L, 2, 1);
- lua.lua_pushnumber(L, Math.atan2(y, x));
+ let y = luaL_checknumber(L, 1);
+ let x = luaL_optnumber(L, 2, 1);
+ lua_pushnumber(L, Math.atan2(y, x));
return 1;
};
const math_toint = function(L) {
- let n = lua.lua_tointegerx(L, 1);
+ let n = lua_tointegerx(L, 1);
if (n !== false)
- lua.lua_pushinteger(L, n);
+ lua_pushinteger(L, n);
else {
- lauxlib.luaL_checkany(L, 1);
- lua.lua_pushnil(L); /* value is not convertible to integer */
+ luaL_checkany(L, 1);
+ lua_pushnil(L); /* value is not convertible to integer */
}
return 1;
};
const pushnumint = function(L, d) {
- let n = luaconf.lua_numbertointeger(d);
+ let n = lua_numbertointeger(d);
if (n !== false) /* does 'd' fit in an integer? */
- lua.lua_pushinteger(L, n); /* result is integer */
+ lua_pushinteger(L, n); /* result is integer */
else
- lua.lua_pushnumber(L, d); /* result is float */
+ lua_pushnumber(L, d); /* result is float */
};
const math_floor = function(L) {
- if (lua.lua_isinteger(L, 1))
- lua.lua_settop(L, 1);
+ if (lua_isinteger(L, 1))
+ lua_settop(L, 1);
else
- pushnumint(L, Math.floor(lauxlib.luaL_checknumber(L, 1)));
+ pushnumint(L, Math.floor(luaL_checknumber(L, 1)));
return 1;
};
const math_ceil = function(L) {
- if (lua.lua_isinteger(L, 1))
- lua.lua_settop(L, 1);
+ if (lua_isinteger(L, 1))
+ lua_settop(L, 1);
else
- pushnumint(L, Math.ceil(lauxlib.luaL_checknumber(L, 1)));
+ pushnumint(L, Math.ceil(luaL_checknumber(L, 1)));
return 1;
};
const math_sqrt = function(L) {
- lua.lua_pushnumber(L, Math.sqrt(lauxlib.luaL_checknumber(L, 1)));
+ lua_pushnumber(L, Math.sqrt(luaL_checknumber(L, 1)));
return 1;
};
const math_ult = function(L) {
- let a = lauxlib.luaL_checkinteger(L, 1);
- let b = lauxlib.luaL_checkinteger(L, 2);
- lua.lua_pushboolean(L, (a >= 0)?(b<0 || a<b):(b<0 && a<b));
+ let a = luaL_checkinteger(L, 1);
+ let b = luaL_checkinteger(L, 2);
+ lua_pushboolean(L, (a >= 0)?(b<0 || a<b):(b<0 && a<b));
return 1;
};
const math_log = function(L) {
- let x = lauxlib.luaL_checknumber(L, 1);
+ let x = luaL_checknumber(L, 1);
let res;
- if (lua.lua_isnoneornil(L, 2))
+ if (lua_isnoneornil(L, 2))
res = Math.log(x);
else {
- let base = lauxlib.luaL_checknumber(L, 2);
+ let base = luaL_checknumber(L, 2);
if (base === 2)
res = Math.log2(x);
else if (base === 10)
@@ -140,87 +191,87 @@ const math_log = function(L) {
else
res = Math.log(x)/Math.log(base);
}
- lua.lua_pushnumber(L, res);
+ lua_pushnumber(L, res);
return 1;
};
const math_exp = function(L) {
- lua.lua_pushnumber(L, Math.exp(lauxlib.luaL_checknumber(L, 1)));
+ lua_pushnumber(L, Math.exp(luaL_checknumber(L, 1)));
return 1;
};
const math_deg = function(L) {
- lua.lua_pushnumber(L, lauxlib.luaL_checknumber(L, 1) * (180 / Math.PI));
+ lua_pushnumber(L, luaL_checknumber(L, 1) * (180 / Math.PI));
return 1;
};
const math_rad = function(L) {
- lua.lua_pushnumber(L, lauxlib.luaL_checknumber(L, 1) * (Math.PI / 180));
+ lua_pushnumber(L, luaL_checknumber(L, 1) * (Math.PI / 180));
return 1;
};
const math_min = function(L) {
- let n = lua.lua_gettop(L); /* number of arguments */
+ let n = lua_gettop(L); /* number of arguments */
let imin = 1; /* index of current minimum value */
- lauxlib.luaL_argcheck(L, n >= 1, 1, "value expected");
+ luaL_argcheck(L, n >= 1, 1, "value expected");
for (let i = 2; i <= n; i++){
- if (lua.lua_compare(L, i, imin, lua.LUA_OPLT))
+ if (lua_compare(L, i, imin, LUA_OPLT))
imin = i;
}
- lua.lua_pushvalue(L, imin);
+ lua_pushvalue(L, imin);
return 1;
};
const math_max = function(L) {
- let n = lua.lua_gettop(L); /* number of arguments */
+ let n = lua_gettop(L); /* number of arguments */
let imax = 1; /* index of current minimum value */
- lauxlib.luaL_argcheck(L, n >= 1, 1, "value expected");
+ luaL_argcheck(L, n >= 1, 1, "value expected");
for (let i = 2; i <= n; i++){
- if (lua.lua_compare(L, imax, i, lua.LUA_OPLT))
+ if (lua_compare(L, imax, i, LUA_OPLT))
imax = i;
}
- lua.lua_pushvalue(L, imax);
+ lua_pushvalue(L, imax);
return 1;
};
const math_type = function(L) {
- if (lua.lua_type(L, 1) === lua.LUA_TNUMBER) {
- if (lua.lua_isinteger(L, 1))
- lua.lua_pushliteral(L, "integer");
+ if (lua_type(L, 1) === LUA_TNUMBER) {
+ if (lua_isinteger(L, 1))
+ lua_pushliteral(L, "integer");
else
- lua.lua_pushliteral(L, "float");
+ lua_pushliteral(L, "float");
} else {
- lauxlib.luaL_checkany(L, 1);
- lua.lua_pushnil(L);
+ luaL_checkany(L, 1);
+ lua_pushnil(L);
}
return 1;
};
const math_fmod = function(L) {
- if (lua.lua_isinteger(L, 1) && lua.lua_isinteger(L, 2)) {
- let d = lua.lua_tointeger(L, 2);
+ if (lua_isinteger(L, 1) && lua_isinteger(L, 2)) {
+ let d = lua_tointeger(L, 2);
/* no special case needed for -1 in javascript */
if (d === 0) {
- lauxlib.luaL_argerror(L, 2, "zero");
+ luaL_argerror(L, 2, "zero");
} else
- lua.lua_pushinteger(L, (lua.lua_tointeger(L, 1) % d)|0);
+ lua_pushinteger(L, (lua_tointeger(L, 1) % d)|0);
} else {
- let a = lauxlib.luaL_checknumber(L, 1);
- let b = lauxlib.luaL_checknumber(L, 2);
- lua.lua_pushnumber(L, a%b);
+ let a = luaL_checknumber(L, 1);
+ let b = luaL_checknumber(L, 2);
+ lua_pushnumber(L, a%b);
}
return 1;
};
const math_modf = function(L) {
- if (lua.lua_isinteger(L, 1)) {
- lua.lua_settop(L, 1); /* number is its own integer part */
- lua.lua_pushnumber(L, 0); /* no fractional part */
+ if (lua_isinteger(L, 1)) {
+ lua_settop(L, 1); /* number is its own integer part */
+ lua_pushnumber(L, 0); /* no fractional part */
} else {
- let n = lauxlib.luaL_checknumber(L, 1);
+ let n = luaL_checknumber(L, 1);
let ip = n < 0 ? Math.ceil(n) : Math.floor(n);
pushnumint(L, ip);
- lua.lua_pushnumber(L, n === ip ? 0 : n - ip);
+ lua_pushnumber(L, n === ip ? 0 : n - ip);
}
return 2;
};
@@ -242,6 +293,7 @@ const mathlib = {
"modf": math_modf,
"rad": math_rad,
"random": math_random,
+ "randomseed": math_randomseed,
"sin": math_sin,
"sqrt": math_sqrt,
"tan": math_tan,
@@ -251,15 +303,15 @@ const mathlib = {
};
const luaopen_math = function(L) {
- lauxlib.luaL_newlib(L, mathlib);
- lua.lua_pushnumber(L, Math.PI);
- lua.lua_setfield(L, -2, lua.to_luastring("pi", true));
- lua.lua_pushnumber(L, Infinity);
- lua.lua_setfield(L, -2, lua.to_luastring("huge", true));
- lua.lua_pushinteger(L, luaconf.LUA_MAXINTEGER);
- lua.lua_setfield(L, -2, lua.to_luastring("maxinteger", true));
- lua.lua_pushinteger(L, luaconf.LUA_MININTEGER);
- lua.lua_setfield(L, -2, lua.to_luastring("mininteger", true));
+ luaL_newlib(L, mathlib);
+ lua_pushnumber(L, Math.PI);
+ lua_setfield(L, -2, to_luastring("pi", true));
+ lua_pushnumber(L, Infinity);
+ lua_setfield(L, -2, to_luastring("huge", true));
+ lua_pushinteger(L, LUA_MAXINTEGER);
+ lua_setfield(L, -2, to_luastring("maxinteger", true));
+ lua_pushinteger(L, LUA_MININTEGER);
+ lua_setfield(L, -2, to_luastring("mininteger", true));
return 1;
};