diff --git a/src/Lua/Standard/MathematicsLibrary.cs b/src/Lua/Standard/MathematicsLibrary.cs index d72e453a..7eb16567 100644 --- a/src/Lua/Standard/MathematicsLibrary.cs +++ b/src/Lua/Standard/MathematicsLibrary.cs @@ -224,23 +224,34 @@ public ValueTask Rad(LuaFunctionExecutionContext context, Memory public ValueTask Random(LuaFunctionExecutionContext context, Memory buffer, CancellationToken cancellationToken) { var rand = context.State.Environment[RandomInstanceKey].Read().Random; - + // When we call it without arguments, it returns a pseudo-random real number with uniform distribution in the interval [0,1 if (context.ArgumentCount == 0) { buffer.Span[0] = rand.NextDouble(); } + // When we call it with only one argument, an integer n, it returns an integer pseudo-random number such that 1 <= x <= n. + // This is different from the C# random functions. + // See: https://www.lua.org/pil/18.html else if (context.ArgumentCount == 1) { - var arg0 = context.GetArgument(0); - buffer.Span[0] = rand.NextDouble() * (arg0 - 1) + 1; + var arg0 = context.GetArgument(0); + if (arg0 < 0) + { + LuaRuntimeException.BadArgument(context.State.GetTraceback(), 0, "random"); + } + buffer.Span[0] = rand.Next(1, arg0 + 1); } + // Finally, we can call random with two integer arguments, l and u, to get a pseudo-random integer x such that l <= x <= u. else { - var arg0 = context.GetArgument(0); - var arg1 = context.GetArgument(1); - buffer.Span[0] = rand.NextDouble() * (arg1 - arg0) + arg0; + var arg0 = context.GetArgument(0); + var arg1 = context.GetArgument(1); + if (arg0 < 1 || arg1 <= arg0) + { + LuaRuntimeException.BadArgument(context.State.GetTraceback(), 1, "random"); + } + buffer.Span[0] = rand.Next(arg0, arg1 + 1); } - return new(1); }