MathematicsLibrary.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. namespace Lua.Standard;
  2. public static class MathematicsLibrary
  3. {
  4. public static void OpenMathLibrary(this LuaState state)
  5. {
  6. state.Environment[RandomInstanceKey] = new(new RandomUserData(new Random()));
  7. var math = new LuaTable(0, Functions.Length);
  8. foreach (var func in Functions)
  9. {
  10. math[func.Name] = func;
  11. }
  12. math["pi"] = Math.PI;
  13. math["huge"] = double.PositiveInfinity;
  14. state.Environment["math"] = math;
  15. state.LoadedModules["math"] = math;
  16. }
  17. public const string RandomInstanceKey = "__lua_mathematics_library_random_instance";
  18. static readonly LuaFunction[] Functions = [
  19. new("abs", Abs),
  20. new("acos", Acos),
  21. new("asin", Asin),
  22. new("atan2", Atan2),
  23. new("atan", Atan),
  24. new("ceil", Ceil),
  25. new("cos", Cos),
  26. new("cosh", Cosh),
  27. new("deg", Deg),
  28. new("exp", Exp),
  29. new("floor", Floor),
  30. new("fmod", Fmod),
  31. new("frexp", Frexp),
  32. new("ldexp", Ldexp),
  33. new("log", Log),
  34. new("max", Max),
  35. new("min", Min),
  36. new("modf", Modf),
  37. new("pow", Pow),
  38. new("rad", Rad),
  39. new("random", Random),
  40. new("randomseed", RandomSeed),
  41. new("sin", Sin),
  42. new("sinh", Sinh),
  43. new("sqrt", Sqrt),
  44. new("tan", Tan),
  45. new("tanh", Tanh),
  46. ];
  47. sealed class RandomUserData(Random random) : ILuaUserData
  48. {
  49. static LuaTable? SharedMetatable;
  50. public LuaTable? Metatable { get => SharedMetatable; set => SharedMetatable = value; }
  51. public Random Random { get; } = random;
  52. }
  53. public static ValueTask<int> Abs(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  54. {
  55. var arg0 = context.GetArgument<double>(0);
  56. buffer.Span[0] = Math.Abs(arg0);
  57. return new(1);
  58. }
  59. public static ValueTask<int> Acos(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  60. {
  61. var arg0 = context.GetArgument<double>(0);
  62. buffer.Span[0] = Math.Acos(arg0);
  63. return new(1);
  64. }
  65. public static ValueTask<int> Asin(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  66. {
  67. var arg0 = context.GetArgument<double>(0);
  68. buffer.Span[0] = Math.Asin(arg0);
  69. return new(1);
  70. }
  71. public static ValueTask<int> Atan2(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  72. {
  73. var arg0 = context.GetArgument<double>(0);
  74. var arg1 = context.GetArgument<double>(1);
  75. buffer.Span[0] = Math.Atan2(arg0, arg1);
  76. return new(1);
  77. }
  78. public static ValueTask<int> Atan(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  79. {
  80. var arg0 = context.GetArgument<double>(0);
  81. buffer.Span[0] = Math.Atan(arg0);
  82. return new(1);
  83. }
  84. public static ValueTask<int> Ceil(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  85. {
  86. var arg0 = context.GetArgument<double>(0);
  87. buffer.Span[0] = Math.Ceiling(arg0);
  88. return new(1);
  89. }
  90. public static ValueTask<int> Cos(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  91. {
  92. var arg0 = context.GetArgument<double>(0);
  93. buffer.Span[0] = Math.Cos(arg0);
  94. return new(1);
  95. }
  96. public static ValueTask<int> Cosh(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  97. {
  98. var arg0 = context.GetArgument<double>(0);
  99. buffer.Span[0] = Math.Cosh(arg0);
  100. return new(1);
  101. }
  102. public static ValueTask<int> Deg(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  103. {
  104. var arg0 = context.GetArgument<double>(0);
  105. buffer.Span[0] = arg0 * (180.0 / Math.PI);
  106. return new(1);
  107. }
  108. public static ValueTask<int> Exp(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  109. {
  110. var arg0 = context.GetArgument<double>(0);
  111. buffer.Span[0] = Math.Exp(arg0);
  112. return new(1);
  113. }
  114. public static ValueTask<int> Floor(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  115. {
  116. var arg0 = context.GetArgument<double>(0);
  117. buffer.Span[0] = Math.Floor(arg0);
  118. return new(1);
  119. }
  120. public static ValueTask<int> Fmod(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  121. {
  122. var arg0 = context.GetArgument<double>(0);
  123. var arg1 = context.GetArgument<double>(1);
  124. buffer.Span[0] = arg0 % arg1;
  125. return new(1);
  126. }
  127. public static ValueTask<int> Frexp(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  128. {
  129. var arg0 = context.GetArgument<double>(0);
  130. var (m, e) = MathEx.Frexp(arg0);
  131. buffer.Span[0] = m;
  132. buffer.Span[1] = e;
  133. return new(2);
  134. }
  135. public static ValueTask<int> Ldexp(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  136. {
  137. var arg0 = context.GetArgument<double>(0);
  138. var arg1 = context.GetArgument<double>(1);
  139. buffer.Span[0] = arg0 * Math.Pow(2, arg1);
  140. return new(1);
  141. }
  142. public static ValueTask<int> Log(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  143. {
  144. var arg0 = context.GetArgument<double>(0);
  145. if (context.ArgumentCount == 1)
  146. {
  147. buffer.Span[0] = Math.Log(arg0);
  148. }
  149. else
  150. {
  151. var arg1 = context.GetArgument<double>(1);
  152. buffer.Span[0] = Math.Log(arg0, arg1);
  153. }
  154. return new(1);
  155. }
  156. public static ValueTask<int> Max(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  157. {
  158. var x = context.GetArgument<double>(0);
  159. for (int i = 1; i < context.ArgumentCount; i++)
  160. {
  161. x = Math.Max(x, context.GetArgument<double>(i));
  162. }
  163. buffer.Span[0] = x;
  164. return new(1);
  165. }
  166. public static ValueTask<int> Min(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  167. {
  168. var x = context.GetArgument<double>(0);
  169. for (int i = 1; i < context.ArgumentCount; i++)
  170. {
  171. x = Math.Min(x, context.GetArgument<double>(i));
  172. }
  173. buffer.Span[0] = x;
  174. return new(1);
  175. }
  176. public static ValueTask<int> Modf(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  177. {
  178. var arg0 = context.GetArgument<double>(0);
  179. var (i, f) = MathEx.Modf(arg0);
  180. buffer.Span[0] = i;
  181. buffer.Span[1] = f;
  182. return new(2);
  183. }
  184. public static ValueTask<int> Pow(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  185. {
  186. var arg0 = context.GetArgument<double>(0);
  187. var arg1 = context.GetArgument<double>(1);
  188. buffer.Span[0] = Math.Pow(arg0, arg1);
  189. return new(1);
  190. }
  191. public static ValueTask<int> Rad(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  192. {
  193. var arg0 = context.GetArgument<double>(0);
  194. buffer.Span[0] = arg0 * (Math.PI / 180.0);
  195. return new(1);
  196. }
  197. public static ValueTask<int> Random(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  198. {
  199. var rand = context.State.Environment[RandomInstanceKey].Read<RandomUserData>().Random;
  200. if (context.ArgumentCount == 0)
  201. {
  202. buffer.Span[0] = rand.NextDouble();
  203. }
  204. else if (context.ArgumentCount == 1)
  205. {
  206. var arg0 = context.GetArgument<double>(0);
  207. buffer.Span[0] = rand.NextDouble() * (arg0 - 1) + 1;
  208. }
  209. else
  210. {
  211. var arg0 = context.GetArgument<double>(0);
  212. var arg1 = context.GetArgument<double>(1);
  213. buffer.Span[0] = rand.NextDouble() * (arg1 - arg0) + arg0;
  214. }
  215. return new(1);
  216. }
  217. public static ValueTask<int> RandomSeed(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  218. {
  219. var arg0 = context.GetArgument<double>(0);
  220. context.State.Environment[RandomInstanceKey] = new(new RandomUserData(new Random((int)BitConverter.DoubleToInt64Bits(arg0))));
  221. return new(0);
  222. }
  223. public static ValueTask<int> Sin(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  224. {
  225. var arg0 = context.GetArgument<double>(0);
  226. buffer.Span[0] = Math.Sin(arg0);
  227. return new(1);
  228. }
  229. public static ValueTask<int> Sinh(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  230. {
  231. var arg0 = context.GetArgument<double>(0);
  232. buffer.Span[0] = Math.Sinh(arg0);
  233. return new(1);
  234. }
  235. public static ValueTask<int> Sqrt(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  236. {
  237. var arg0 = context.GetArgument<double>(0);
  238. buffer.Span[0] = Math.Sqrt(arg0);
  239. return new(1);
  240. }
  241. public static ValueTask<int> Tan(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  242. {
  243. var arg0 = context.GetArgument<double>(0);
  244. buffer.Span[0] = Math.Tan(arg0);
  245. return new(1);
  246. }
  247. public static ValueTask<int> Tanh(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  248. {
  249. var arg0 = context.GetArgument<double>(0);
  250. buffer.Span[0] = Math.Tanh(arg0);
  251. return new(1);
  252. }
  253. }