Browse Source

Fix the result of math.random is inconsistent with Lua standard library.

wmltogether 11 months ago
parent
commit
0a05d766d4
1 changed files with 18 additions and 7 deletions
  1. 18 7
      src/Lua/Standard/MathematicsLibrary.cs

+ 18 - 7
src/Lua/Standard/MathematicsLibrary.cs

@@ -224,23 +224,34 @@ public sealed class MathematicsLibrary
     public ValueTask<int> Random(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var rand = context.State.Environment[RandomInstanceKey].Read<RandomUserData>().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.
+        // 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<double>(0);
-            buffer.Span[0] = rand.NextDouble() * (arg0 - 1) + 1;
+            var arg0 = context.GetArgument<int>(0);
+            if (arg0 < 0)
+            {
+                LuaRuntimeException.BadArgument(context.State.GetTraceback(), 0, "random");
+            }
+            buffer.Span[0] = rand.Next(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<double>(0);
-            var arg1 = context.GetArgument<double>(1);
-            buffer.Span[0] = rand.NextDouble() * (arg1 - arg0) + arg0;
+            var arg0 = context.GetArgument<int>(0);
+            var arg1 = context.GetArgument<int>(1);
+            if (arg1 <= arg0)
+            {
+                LuaRuntimeException.BadArgument(context.State.GetTraceback(), 1, "random");
+            }
+            buffer.Span[0] = rand.Next(arg0, arg1 + 1);
         }
-
         return new(1);
     }