From 94a301a27a8a75c4684790a99a898262b8354f68 Mon Sep 17 00:00:00 2001 From: Benoit Giannangeli Date: Sun, 26 Feb 2017 15:13:22 +0100 Subject: math.random/randomseed --- src/lapi.js | 2 +- src/lmathlib.js | 134 +++++++++++++++++++++++++++++++++++++++++++------------- src/luaconf.js | 5 ++- src/lvm.js | 2 +- 4 files changed, 108 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/lapi.js b/src/lapi.js index 4eb55cd..d0c099f 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -545,7 +545,7 @@ const lua_topointer = function(L, idx) { const lua_compare = function(L, index1, index2, op) { let o1 = index2addr(L, index1); - let o2 = index2addr(L, index1); + let o2 = index2addr(L, index2); return lua_compare_(L, o1, o2, op); }; diff --git a/src/lmathlib.js b/src/lmathlib.js index f4cc978..54bdc46 100644 --- a/src/lmathlib.js +++ b/src/lmathlib.js @@ -1,18 +1,55 @@ /* jshint esversion: 6 */ "use strict"; -const assert = require('assert'); +const assert = require('assert'); +const seedrandom = require('seedrandom'); -const lua = require('./lua.js'); -const lapi = require('./lapi.js'); -const lauxlib = require('./lauxlib.js'); -const lstate = require('./lstate.js'); -const ldo = require('./ldo.js'); -const ldebug = require('./ldebug.js'); -const llimit = require('./llimit.js'); -const CT = lua.constant_types; -const TS = lua.thread_status; +const lua = require('./lua.js'); +const lapi = require('./lapi.js'); +const lauxlib = require('./lauxlib.js'); +const lstate = require('./lstate.js'); +const ldo = require('./ldo.js'); +const ldebug = require('./ldebug.js'); +const llimit = require('./llimit.js'); +const luaconf = require('./luaconf.js'); +const CT = lua.constant_types; +const TS = lua.thread_status; +var RNG = seedrandom(); + +const math_randomseed = function(L) { + RNG = seedrandom(Math.abs(lauxlib.luaL_checknumber(L, 1))); +}; + +const math_random = function(L) { + let low, up; + let r = RNG(); + switch (lapi.lua_gettop(L)) { /* check number of arguments */ + case 0: + lapi.lua_pushnumber(L, r); /* Number between 0 and 1 */ + return 1; + case 1: { + low = 1; + up = lauxlib.luaL_checkinteger(L, 1); + break; + } + case 2: { + low = lauxlib.luaL_checkinteger(L, 1); + up = lauxlib.luaL_checkinteger(L, 2); + break; + } + default: return lauxlib.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 <= Number.MAX_SAFE_INTEGER + low, 1, + "interval too large"); + + r *= (up - low) + 1; + lapi.lua_pushinteger(L, r + low); + return 1; +}; const math_abs = function(L) { if (lapi.lua_isinteger(L, 1)) @@ -53,7 +90,7 @@ const math_atan = function(L) { }; const math_toint = function(L) { - let n = lapi.lua_tointegerx(L, 1) + let n = lapi.lua_tointegerx(L, 1); if (n !== false) lapi.lua_pushinteger(L, n); else { @@ -91,6 +128,7 @@ const math_ceil = function(L) { const math_sqrt = function(L) { lapi.lua_pushnumber(L, Math.sqrt(lauxlib.luaL_checknumber(L, 1))); + return 1; }; const math_ult = function(L) { @@ -102,6 +140,7 @@ const math_ult = function(L) { const math_log = function(L) { let x = lauxlib.luaL_checknumber(L, 1); + let res; if (lapi.lua_isnoneornil(L, 2)) res = Math.log(x); else { @@ -129,6 +168,7 @@ const math_deg = function(L) { const math_rad = function(L) { lapi.lua_pushnumber(L, lauxlib.luaL_checknumber(L, 1) * (Math.PI / 180)); + return 1; }; const math_min = function(L) { @@ -168,27 +208,59 @@ const math_type = function(L) { return 1; }; +const math_fmod = function(L) { + if (lapi.lua_isinteger(L, 1) && lapi.lua_isinteger(L, 2)) { + let d = lapi.lua_tointeger(L, 2); + if (Math.abs(d) + 1 <= 1) { + lauxlib.luaL_argcheck(L, d !== 0, 2, "zero"); + lapi.lua_pushinteger(L, 0); + } else + lapi.lua_pushinteger(L, lapi.lua_tointeger(L, 1) % d); + } else { + let a = lauxlib.luaL_checknumber(L, 1); + let b = lauxlib.luaL_checknumber(L, 2); + lapi.lua_pushnumber(L, Number((a - (Math.floor(a / b) * b)).toPrecision(8))); + } + return 1; +}; + +const math_modf = function(L) { + if (lapi.lua_isinteger(L, 1)) { + lapi.lua_settop(L, 1); /* number is its own integer part */ + lapi.lua_pushnumber(L, 0); /* no fractional part */ + } else { + let n = lauxlib.luaL_checknumber(L, 1); + let ip = n < 0 ? Math.ceil(n) : Math.floor(n); + pushnumint(L, ip); + lapi.lua_pushnumber(L, n === ip ? 0 : n - ip); + } + return 2; +}; + const mathlib = { - "abs": math_abs, - "acos": math_acos, - "asin": math_asin, - "atan": math_atan, - "ceil": math_ceil, - "cos": math_cos, - "deg": math_deg, - "exp": math_exp, - "floor": math_floor, - "log": math_log, - "max": math_max, - "min": math_min, - "rad": math_rad, - "sin": math_sin, - "sqrt": math_sqrt, - "sqrt": math_sqrt, - "tan": math_tan, - "tointeger": math_toint, - "type": math_type, - "ult": math_ult + "abs": math_abs, + "acos": math_acos, + "asin": math_asin, + "atan": math_atan, + "ceil": math_ceil, + "cos": math_cos, + "deg": math_deg, + "exp": math_exp, + "floor": math_floor, + "fmod": math_fmod, + "log": math_log, + "max": math_max, + "min": math_min, + "modf": math_modf, + "rad": math_rad, + "random": math_random, + "randomseed": math_randomseed, + "sin": math_sin, + "sqrt": math_sqrt, + "tan": math_tan, + "tointeger": math_toint, + "type": math_type, + "ult": math_ult }; const luaopen_math = function(L) { diff --git a/src/luaconf.js b/src/luaconf.js index 7297b28..f0066de 100644 --- a/src/luaconf.js +++ b/src/luaconf.js @@ -20,5 +20,6 @@ const lua_numbertointeger = function(n) { return n|0; }; -module.exports.LUAI_MAXSTACK = LUAI_MAXSTACK; -module.exports.LUA_IDSIZE = LUA_IDSIZE; \ No newline at end of file +module.exports.LUAI_MAXSTACK = LUAI_MAXSTACK; +module.exports.LUA_IDSIZE = LUA_IDSIZE; +module.exports.lua_numbertointeger = lua_numbertointeger; \ No newline at end of file diff --git a/src/lvm.js b/src/lvm.js index d623a72..d987cc1 100644 --- a/src/lvm.js +++ b/src/lvm.js @@ -838,7 +838,7 @@ const luaV_tointeger = function(obj, mode) { } else if (obj.ttisinteger()) { return obj.value|0; } else if (obj.ttisstring()) { - return luaV_tointeger(parseFloat(obj.value), mode); // TODO: luaO_str2num + return luaV_tointeger(new TValue(CT.LUA_TNUMFLT, parseFloat(obj.value)), mode); // TODO: luaO_str2num } return false; -- cgit v1.2.3-70-g09d2