Browse Source

Merge pull request #1 from AnnulusGames/math-lib

Add: mathematics library
Annulus Games 1 year ago
parent
commit
064a446e94
29 changed files with 566 additions and 0 deletions
  1. 38 0
      src/Lua/Internal/MathEx.cs
  2. 16 0
      src/Lua/Standard/Mathematics/AbsFunction.cs
  3. 16 0
      src/Lua/Standard/Mathematics/AcosFuncion.cs
  4. 16 0
      src/Lua/Standard/Mathematics/AsinFuncion.cs
  5. 18 0
      src/Lua/Standard/Mathematics/Atan2Function.cs
  6. 16 0
      src/Lua/Standard/Mathematics/AtanFuncion.cs
  7. 16 0
      src/Lua/Standard/Mathematics/CeilFuncion.cs
  8. 16 0
      src/Lua/Standard/Mathematics/CosFuncion.cs
  9. 16 0
      src/Lua/Standard/Mathematics/CoshFuncion.cs
  10. 16 0
      src/Lua/Standard/Mathematics/DegFunction.cs
  11. 16 0
      src/Lua/Standard/Mathematics/ExpFuncion.cs
  12. 16 0
      src/Lua/Standard/Mathematics/FloorFuncion.cs
  13. 17 0
      src/Lua/Standard/Mathematics/FmodFunction.cs
  14. 19 0
      src/Lua/Standard/Mathematics/FrexpFunction.cs
  15. 18 0
      src/Lua/Standard/Mathematics/LdexpFunction.cs
  16. 26 0
      src/Lua/Standard/Mathematics/LogFunction.cs
  17. 22 0
      src/Lua/Standard/Mathematics/MaxFunction.cs
  18. 22 0
      src/Lua/Standard/Mathematics/MinFunction.cs
  19. 18 0
      src/Lua/Standard/Mathematics/ModfFunction.cs
  20. 18 0
      src/Lua/Standard/Mathematics/PowFunction.cs
  21. 16 0
      src/Lua/Standard/Mathematics/RadFunction.cs
  22. 33 0
      src/Lua/Standard/Mathematics/RandomFunction.cs
  23. 16 0
      src/Lua/Standard/Mathematics/RandomSeedFunction.cs
  24. 16 0
      src/Lua/Standard/Mathematics/SinFuncion.cs
  25. 15 0
      src/Lua/Standard/Mathematics/SinhFuncion.cs
  26. 16 0
      src/Lua/Standard/Mathematics/SqrtFunction.cs
  27. 16 0
      src/Lua/Standard/Mathematics/TanFunction.cs
  28. 16 0
      src/Lua/Standard/Mathematics/TanhFunction.cs
  29. 46 0
      src/Lua/Standard/OpenLibExtensions.cs

+ 38 - 0
src/Lua/Internal/MathEx.cs

@@ -48,4 +48,42 @@ internal static class MathEx
 
         return newSize;
     }
+
+    const long DBL_EXP_MASK = 0x7ff0000000000000L;
+    const int DBL_MANT_BITS = 52;
+    const long DBL_SGN_MASK = -1 - 0x7fffffffffffffffL;
+    const long DBL_MANT_MASK = 0x000fffffffffffffL;
+    const long DBL_EXP_CLR_MASK = DBL_SGN_MASK | DBL_MANT_MASK;
+
+    public static (double m, int e) Frexp(double d)
+    {
+        var bits = BitConverter.DoubleToInt64Bits(d);
+        var exp = (int)((bits & DBL_EXP_MASK) >> DBL_MANT_BITS);
+        var e = 0;
+
+        if (exp == 0x7ff || d == 0D)
+            d += d;
+        else
+        {
+            // Not zero and finite.
+            e = exp - 1022;
+            if (exp == 0)
+            {
+                // Subnormal, scale d so that it is in [1, 2).
+                d *= BitConverter.Int64BitsToDouble(0x4350000000000000L); // 2^54
+                bits = BitConverter.DoubleToInt64Bits(d);
+                exp = (int)((bits & DBL_EXP_MASK) >> DBL_MANT_BITS);
+                e = exp - 1022 - 54;
+            }
+            // Set exponent to -1 so that d is in [0.5, 1).
+            d = BitConverter.Int64BitsToDouble((bits & DBL_EXP_CLR_MASK) | 0x3fe0000000000000L);
+        }
+
+        return (d, e);
+    }
+
+    public static (int i, double f) Modf(double d)
+    {
+        return ((int)Math.Truncate(d), d % 1.0);
+    }
 }

+ 16 - 0
src/Lua/Standard/Mathematics/AbsFunction.cs

@@ -0,0 +1,16 @@
+
+namespace Lua.Standard.Mathematics;
+
+public sealed class AbsFunction : LuaFunction
+{
+    public static readonly AbsFunction Instance = new();
+
+    public override string Name => "abs";
+
+    protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    {
+        var arg0 = context.ReadArgument<double>(0);
+        buffer.Span[0] = Math.Abs(arg0);
+        return new(1);
+    }
+}

+ 16 - 0
src/Lua/Standard/Mathematics/AcosFuncion.cs

@@ -0,0 +1,16 @@
+
+namespace Lua.Standard.Mathematics;
+
+public sealed class AcosFunction : LuaFunction
+{
+    public static readonly AcosFunction Instance = new();
+
+    public override string Name => "acos";
+
+    protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    {
+        var arg0 = context.ReadArgument<double>(0);
+        buffer.Span[0] = Math.Acos(arg0);
+        return new(1);
+    }
+}

+ 16 - 0
src/Lua/Standard/Mathematics/AsinFuncion.cs

@@ -0,0 +1,16 @@
+
+namespace Lua.Standard.Mathematics;
+
+public sealed class AsinFunction : LuaFunction
+{
+    public static readonly AsinFunction Instance = new();
+
+    public override string Name => "asin";
+
+    protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    {
+        var arg0 = context.ReadArgument<double>(0);
+        buffer.Span[0] = Math.Asin(arg0);
+        return new(1);
+    }
+}

+ 18 - 0
src/Lua/Standard/Mathematics/Atan2Function.cs

@@ -0,0 +1,18 @@
+
+namespace Lua.Standard.Mathematics;
+
+public sealed class Atan2Function : LuaFunction
+{
+    public static readonly Atan2Function Instance = new();
+
+    public override string Name => "atan2";
+
+    protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    {
+        var arg0 = context.ReadArgument<double>(0);
+        var arg1 = context.ReadArgument<double>(1);
+
+        buffer.Span[0] = Math.Atan2(arg0, arg1);
+        return new(1);
+    }
+}

+ 16 - 0
src/Lua/Standard/Mathematics/AtanFuncion.cs

@@ -0,0 +1,16 @@
+
+namespace Lua.Standard.Mathematics;
+
+public sealed class AtanFunction : LuaFunction
+{
+    public static readonly AtanFunction Instance = new();
+
+    public override string Name => "atan";
+
+    protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    {
+        var arg0 = context.ReadArgument<double>(0);
+        buffer.Span[0] = Math.Atan(arg0);
+        return new(1);
+    }
+}

+ 16 - 0
src/Lua/Standard/Mathematics/CeilFuncion.cs

@@ -0,0 +1,16 @@
+
+namespace Lua.Standard.Mathematics;
+
+public sealed class CeilFunction : LuaFunction
+{
+    public static readonly CeilFunction Instance = new();
+
+    public override string Name => "ceil";
+
+    protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    {
+        var arg0 = context.ReadArgument<double>(0);
+        buffer.Span[0] = Math.Ceiling(arg0);
+        return new(1);
+    }
+}

+ 16 - 0
src/Lua/Standard/Mathematics/CosFuncion.cs

@@ -0,0 +1,16 @@
+
+namespace Lua.Standard.Mathematics;
+
+public sealed class CosFunction : LuaFunction
+{
+    public static readonly CosFunction Instance = new();
+
+    public override string Name => "cos";
+
+    protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    {
+        var arg0 = context.ReadArgument<double>(0);
+        buffer.Span[0] = Math.Cos(arg0);
+        return new(1);
+    }
+}

+ 16 - 0
src/Lua/Standard/Mathematics/CoshFuncion.cs

@@ -0,0 +1,16 @@
+
+namespace Lua.Standard.Mathematics;
+
+public sealed class CoshFunction : LuaFunction
+{
+    public static readonly CoshFunction Instance = new();
+
+    public override string Name => "cosh";
+
+    protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    {
+        var arg0 = context.ReadArgument<double>(0);
+        buffer.Span[0] = Math.Cosh(arg0);
+        return new(1);
+    }
+}

+ 16 - 0
src/Lua/Standard/Mathematics/DegFunction.cs

@@ -0,0 +1,16 @@
+
+namespace Lua.Standard.Mathematics;
+
+public sealed class DegFunction : LuaFunction
+{
+    public static readonly DegFunction Instance = new();
+
+    public override string Name => "deg";
+
+    protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    {
+        var arg0 = context.ReadArgument<double>(0);
+        buffer.Span[0] = arg0 * (180.0 / Math.PI);
+        return new(1);
+    }
+}

+ 16 - 0
src/Lua/Standard/Mathematics/ExpFuncion.cs

@@ -0,0 +1,16 @@
+
+namespace Lua.Standard.Mathematics;
+
+public sealed class ExpFunction : LuaFunction
+{
+    public static readonly ExpFunction Instance = new();
+
+    public override string Name => "exp";
+
+    protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    {
+        var arg0 = context.ReadArgument<double>(0);
+        buffer.Span[0] = Math.Exp(arg0);
+        return new(1);
+    }
+}

+ 16 - 0
src/Lua/Standard/Mathematics/FloorFuncion.cs

@@ -0,0 +1,16 @@
+
+namespace Lua.Standard.Mathematics;
+
+public sealed class FloorFunction : LuaFunction
+{
+    public static readonly FloorFunction Instance = new();
+
+    public override string Name => "floor";
+
+    protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    {
+        var arg0 = context.ReadArgument<double>(0);
+        buffer.Span[0] = Math.Floor(arg0);
+        return new(1);
+    }
+}

+ 17 - 0
src/Lua/Standard/Mathematics/FmodFunction.cs

@@ -0,0 +1,17 @@
+
+namespace Lua.Standard.Mathematics;
+
+public sealed class FmodFunction : LuaFunction
+{
+    public static readonly FmodFunction Instance = new();
+
+    public override string Name => "fmod";
+
+    protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    {
+        var arg0 = context.ReadArgument<double>(0);
+        var arg1 = context.ReadArgument<double>(1);
+        buffer.Span[0] = arg0 % arg1;
+        return new(1);
+    }
+}

+ 19 - 0
src/Lua/Standard/Mathematics/FrexpFunction.cs

@@ -0,0 +1,19 @@
+
+namespace Lua.Standard.Mathematics;
+
+public sealed class FrexpFunction : LuaFunction
+{
+    public static readonly FrexpFunction Instance = new();
+
+    public override string Name => "frexp";
+
+    protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    {
+        var arg0 = context.ReadArgument<double>(0);
+
+        var (m, e) = MathEx.Frexp(arg0);
+        buffer.Span[0] = m;
+        buffer.Span[1] = e;
+        return new(2);
+    }
+}

+ 18 - 0
src/Lua/Standard/Mathematics/LdexpFunction.cs

@@ -0,0 +1,18 @@
+
+namespace Lua.Standard.Mathematics;
+
+public sealed class LdexpFunction : LuaFunction
+{
+    public static readonly LdexpFunction Instance = new();
+
+    public override string Name => "ldexp";
+
+    protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    {
+        var arg0 = context.ReadArgument<double>(0);
+        var arg1 = context.ReadArgument<double>(1);
+
+        buffer.Span[0] = arg0 * Math.Pow(2, arg1);
+        return new(1);
+    }
+}

+ 26 - 0
src/Lua/Standard/Mathematics/LogFunction.cs

@@ -0,0 +1,26 @@
+
+namespace Lua.Standard.Mathematics;
+
+public sealed class LogFunction : LuaFunction
+{
+    public static readonly LogFunction Instance = new();
+
+    public override string Name => "log";
+
+    protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    {
+        var arg0 = context.ReadArgument<double>(0);
+
+        if (context.ArgumentCount == 1)
+        {
+            buffer.Span[0] = Math.Log(arg0);
+        }
+        else
+        {
+            var arg1 = context.ReadArgument<double>(1);
+            buffer.Span[0] = Math.Log(arg0, arg1);
+        }
+        
+        return new(1);
+    }
+}

+ 22 - 0
src/Lua/Standard/Mathematics/MaxFunction.cs

@@ -0,0 +1,22 @@
+
+namespace Lua.Standard.Mathematics;
+
+public sealed class MaxFunction : LuaFunction
+{
+    public static readonly MaxFunction Instance = new();
+
+    public override string Name => "max";
+
+    protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    {
+        var x = context.ReadArgument<double>(0);
+        for (int i = 1; i < context.ArgumentCount; i++)
+        {
+            x = Math.Max(x, context.ReadArgument<double>(i));
+        }
+
+        buffer.Span[0] = x;
+
+        return new(1);
+    }
+}

+ 22 - 0
src/Lua/Standard/Mathematics/MinFunction.cs

@@ -0,0 +1,22 @@
+
+namespace Lua.Standard.Mathematics;
+
+public sealed class MinFunction : LuaFunction
+{
+    public static readonly MinFunction Instance = new();
+
+    public override string Name => "min";
+
+    protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    {
+        var x = context.ReadArgument<double>(0);
+        for (int i = 1; i < context.ArgumentCount; i++)
+        {
+            x = Math.Min(x, context.ReadArgument<double>(i));
+        }
+
+        buffer.Span[0] = x;
+
+        return new(1);
+    }
+}

+ 18 - 0
src/Lua/Standard/Mathematics/ModfFunction.cs

@@ -0,0 +1,18 @@
+
+namespace Lua.Standard.Mathematics;
+
+public sealed class ModfFunction : LuaFunction
+{
+    public static readonly ModfFunction Instance = new();
+
+    public override string Name => "modf";
+
+    protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    {
+        var arg0 = context.ReadArgument<double>(0);
+        var (i, f) = MathEx.Modf(arg0);
+        buffer.Span[0] = i;
+        buffer.Span[1] = f;
+        return new(2);
+    }
+}

+ 18 - 0
src/Lua/Standard/Mathematics/PowFunction.cs

@@ -0,0 +1,18 @@
+
+namespace Lua.Standard.Mathematics;
+
+public sealed class PowFunction : LuaFunction
+{
+    public static readonly PowFunction Instance = new();
+
+    public override string Name => "pow";
+
+    protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    {
+        var arg0 = context.ReadArgument<double>(0);
+        var arg1 = context.ReadArgument<double>(1);
+
+        buffer.Span[0] = Math.Pow(arg0, arg1);
+        return new(1);
+    }
+}

+ 16 - 0
src/Lua/Standard/Mathematics/RadFunction.cs

@@ -0,0 +1,16 @@
+
+namespace Lua.Standard.Mathematics;
+
+public sealed class RadFunction : LuaFunction
+{
+    public static readonly RadFunction Instance = new();
+
+    public override string Name => "rad";
+
+    protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    {
+        var arg0 = context.ReadArgument<double>(0);
+        buffer.Span[0] = arg0 * (Math.PI / 180.0);
+        return new(1);
+    }
+}

+ 33 - 0
src/Lua/Standard/Mathematics/RandomFunction.cs

@@ -0,0 +1,33 @@
+
+namespace Lua.Standard.Mathematics;
+
+public sealed class RandomFunction : LuaFunction
+{
+    public const string RandomInstanceKey = "__lua_mathematics_library_random_instance";
+    public static readonly RandomFunction Instance = new();
+
+    public override string Name => "random";
+
+    protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    {
+        var rand = context.State.Environment[RandomInstanceKey].Read<Random>();
+
+        if (context.ArgumentCount == 0)
+        {
+            buffer.Span[0] = rand.NextDouble();
+        }
+        else if (context.ArgumentCount == 1)
+        {
+            var arg0 = context.ReadArgument<double>(0);
+            buffer.Span[0] = rand.NextDouble() * (arg0 - 1) + 1;
+        }
+        else
+        {
+            var arg0 = context.ReadArgument<double>(0);
+            var arg1 = context.ReadArgument<double>(1);
+            buffer.Span[0] = rand.NextDouble() * (arg1 - arg0) + arg0;
+        }
+
+        return new(1);
+    }
+}

+ 16 - 0
src/Lua/Standard/Mathematics/RandomSeedFunction.cs

@@ -0,0 +1,16 @@
+
+namespace Lua.Standard.Mathematics;
+
+public sealed class RandomSeedFunction : LuaFunction
+{
+    public static readonly RandomSeedFunction Instance = new();
+
+    public override string Name => "randomseed";
+
+    protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    {
+        var arg0 = context.ReadArgument<double>(0);
+        context.State.Environment[RandomFunction.RandomInstanceKey] = new(new Random((int)BitConverter.DoubleToInt64Bits(arg0)));
+        return new(0);
+    }
+}

+ 16 - 0
src/Lua/Standard/Mathematics/SinFuncion.cs

@@ -0,0 +1,16 @@
+
+namespace Lua.Standard.Mathematics;
+
+public sealed class SinFunction : LuaFunction
+{
+    public static readonly SinFunction Instance = new();
+
+    public override string Name => "sin";
+
+    protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    {
+        var arg0 = context.ReadArgument<double>(0);
+        buffer.Span[0] = Math.Sin(arg0);
+        return new(1);
+    }
+}

+ 15 - 0
src/Lua/Standard/Mathematics/SinhFuncion.cs

@@ -0,0 +1,15 @@
+
+namespace Lua.Standard.Mathematics;
+public sealed class SinhFunction : LuaFunction
+{
+    public static readonly SinhFunction Instance = new();
+
+    public override string Name => "sinh";
+
+    protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    {
+        var arg0 = context.ReadArgument<double>(0);
+        buffer.Span[0] = Math.Sinh(arg0);
+        return new(1);
+    }
+}

+ 16 - 0
src/Lua/Standard/Mathematics/SqrtFunction.cs

@@ -0,0 +1,16 @@
+
+namespace Lua.Standard.Mathematics;
+
+public sealed class SqrtFunction : LuaFunction
+{
+    public static readonly SqrtFunction Instance = new();
+
+    public override string Name => "sqrt";
+
+    protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    {
+        var arg0 = context.ReadArgument<double>(0);
+        buffer.Span[0] = Math.Sqrt(arg0);
+        return new(1);
+    }
+}

+ 16 - 0
src/Lua/Standard/Mathematics/TanFunction.cs

@@ -0,0 +1,16 @@
+
+namespace Lua.Standard.Mathematics;
+
+public sealed class TanFunction : LuaFunction
+{
+    public static readonly TanFunction Instance = new();
+
+    public override string Name => "tan";
+
+    protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    {
+        var arg0 = context.ReadArgument<double>(0);
+        buffer.Span[0] = Math.Tan(arg0);
+        return new(1);
+    }
+}

+ 16 - 0
src/Lua/Standard/Mathematics/TanhFunction.cs

@@ -0,0 +1,16 @@
+
+namespace Lua.Standard.Mathematics;
+
+public sealed class TanhFunction : LuaFunction
+{
+    public static readonly TanhFunction Instance = new();
+
+    public override string Name => "tanh";
+
+    protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    {
+        var arg0 = context.ReadArgument<double>(0);
+        buffer.Span[0] = Math.Tanh(arg0);
+        return new(1);
+    }
+}

+ 46 - 0
src/Lua/Standard/OpenLibExtensions.cs

@@ -1,4 +1,5 @@
 using Lua.Standard.Base;
+using Lua.Standard.Mathematics;
 
 namespace Lua.Standard;
 
@@ -15,6 +16,36 @@ public static class OpenLibExtensions
         ToStringFunction.Instance
     ];
 
+    static readonly LuaFunction[] mathFunctions = [
+        AbsFunction.Instance,
+        AcosFunction.Instance,
+        AsinFunction.Instance,
+        Atan2Function.Instance,
+        AtanFunction.Instance,
+        CeilFunction.Instance,
+        CosFunction.Instance,
+        CoshFunction.Instance,
+        DegFunction.Instance,
+        ExpFunction.Instance,
+        FloorFunction.Instance,
+        FmodFunction.Instance,
+        FrexpFunction.Instance,
+        LdexpFunction.Instance,
+        LogFunction.Instance,
+        MaxFunction.Instance,
+        MinFunction.Instance,
+        ModfFunction.Instance,
+        PowFunction.Instance,
+        RadFunction.Instance,
+        RandomFunction.Instance,
+        RandomSeedFunction.Instance,
+        SinFunction.Instance,
+        SinhFunction.Instance,
+        SqrtFunction.Instance,
+        TanFunction.Instance,
+        TanhFunction.Instance,
+    ];
+
     public static void OpenBaseLibrary(this LuaState state)
     {
         state.Environment["_G"] = state.Environment;
@@ -24,4 +55,19 @@ public static class OpenLibExtensions
             state.Environment[func.Name] = func;
         }
     }
+
+    public static void OpenMathLibrary(this LuaState state)
+    {
+        state.Environment[RandomFunction.RandomInstanceKey] = new(new Random());
+        state.Environment["pi"] = Math.PI;
+        state.Environment["huge"] = double.PositiveInfinity;
+
+        var table = new LuaTable(0, mathFunctions.Length);
+        foreach (var func in mathFunctions)
+        {
+            table[func.Name] = func;
+        }
+
+        state.Environment["math"] = table;
+    }
 }