[Space Lua]: Implement math.random and math.randomseed (#1845)

This commit is contained in:
Matouš Jan Fialka
2026-02-21 17:56:49 +01:00
committed by GitHub
parent 472ff93416
commit 3bb80ece3f
3 changed files with 278 additions and 44 deletions
+18 -44
View File
@@ -5,6 +5,10 @@ import {
LuaTable,
} from "../runtime.ts";
import { isNegativeZero, isTaggedFloat } from "../numeric.ts";
import { LuaPRNG } from "./prng.ts";
// One PRNG per module load, auto-seeded at startup
const prng = new LuaPRNG();
// Fast unwrap: avoids function call overhead for the common plain-number case
function untagNumber(x: any): number {
@@ -52,51 +56,21 @@ export const mathApi = new LuaTable({
random: new LuaBuiltinFunction((_sf, m?: number, n?: number) => {
if (m !== undefined) m = untagNumber(m);
if (n !== undefined) n = untagNumber(n);
if (m === undefined && n === undefined) {
return Math.random();
try {
return prng.random(m, n);
} catch (e: any) {
throw new LuaRuntimeError(e.message, _sf);
}
if (!Number.isInteger(m)) {
throw new LuaRuntimeError(
"bad argument #1 to 'math.random' (integer expected)",
_sf,
);
}
if (n === undefined) {
if (m! == 0) {
const high = Math.floor(Math.random() * 0x100000000);
const low = Math.floor(Math.random() * 0x100000000);
let result = (BigInt(high) << 32n) | BigInt(low);
if (result & (1n << 63n)) {
result -= 1n << 64n;
}
return result;
}
if (m! < 1) {
throw new LuaRuntimeError(
"bad argument #1 to 'math.random' (interval is empty)",
_sf,
);
}
return Math.floor(Math.random() * m!) + 1;
}
if (!Number.isInteger(n!)) {
throw new LuaRuntimeError(
"bad argument #2 to 'math.random' (integer expected)",
_sf,
);
}
if (n! < m!) {
throw new LuaRuntimeError(
"bad argument #1 to 'math.random' (interval is empty)",
_sf,
);
}
return Math.floor(Math.random() * (n! - m! + 1)) + m!;
}),
/**
* Seeds the pseudo-random generator. With no arguments, uses a
* time-based seed. Returns the two seed integers used (Lua 5.4 contract).
*/
randomseed: new LuaBuiltinFunction((_sf, x?: number, y?: number) => {
if (x !== undefined) x = untagNumber(x);
if (y !== undefined) y = untagNumber(y);
const [s1, s2] = prng.randomseed(x, y);
return new LuaMultiRes([s1, s2]);
}),
// Basic functions