using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; namespace Language.Lua.Library { public static class MathLib { public static void RegisterModule(LuaTable enviroment) { LuaTable module = new LuaTable(); RegisterFunctions(module); enviroment.SetNameValue("math", module); } public static void RegisterFunctions(LuaTable module) { module.SetNameValue("huge", new LuaNumber(double.MaxValue)); module.SetNameValue("pi", new LuaNumber(Math.PI)); module.Register("abs", abs); module.Register("acos", acos); module.Register("asin", asin); module.Register("atan", atan); module.Register("atan2", atan2); module.Register("ceil", ceil); module.Register("cos", cos); module.Register("cosh", cosh); module.Register("deg", deg); module.Register("exp", exp); module.Register("floor", floor); module.Register("fmod", fmod); module.Register("log", log); module.Register("log10", log10); module.Register("max", max); module.Register("min", min); module.Register("modf", modf); module.Register("pow", pow); module.Register("rad", rad); module.Register("random", random); module.Register("randomseed", randomseed); module.Register("sin", sin); module.Register("sinh", sinh); module.Register("sqrt", sqrt); module.Register("tan", tan); module.Register("tanh", tanh); } public static LuaValue abs(LuaValue[] values) { LuaNumber number = CheckArgs(values); return new LuaNumber(Math.Abs(number.Number)); } public static LuaValue acos(LuaValue[] values) { LuaNumber number = CheckArgs(values); return new LuaNumber(Math.Acos(number.Number)); } public static LuaValue asin(LuaValue[] values) { LuaNumber number = CheckArgs(values); return new LuaNumber(Math.Asin(number.Number)); } public static LuaValue atan(LuaValue[] values) { LuaNumber number = CheckArgs(values); return new LuaNumber(Math.Atan(number.Number)); } public static LuaValue atan2(LuaValue[] values) { var numbers = CheckArgs2(values); return new LuaNumber(Math.Atan2(numbers.Item1, numbers.Item2)); } public static LuaValue ceil(LuaValue[] values) { LuaNumber number = CheckArgs(values); return new LuaNumber(Math.Ceiling(number.Number)); } public static LuaValue cos(LuaValue[] values) { LuaNumber number = CheckArgs(values); return new LuaNumber(Math.Cos(number.Number)); } public static LuaValue cosh(LuaValue[] values) { LuaNumber number = CheckArgs(values); return new LuaNumber(Math.Cosh(number.Number)); } public static LuaValue deg(LuaValue[] values) { LuaNumber number = CheckArgs(values); return new LuaNumber(number.Number * 180 / Math.PI); } public static LuaValue exp(LuaValue[] values) { LuaNumber number = CheckArgs(values); return new LuaNumber(Math.Exp(number.Number)); } public static LuaValue floor(LuaValue[] values) { LuaNumber number = CheckArgs(values); return new LuaNumber(Math.Floor(number.Number)); } public static LuaValue fmod(LuaValue[] values) { var numbers = CheckArgs2(values); return new LuaNumber(Math.IEEERemainder(numbers.Item1, numbers.Item2)); } public static LuaValue log(LuaValue[] values) { LuaNumber number = CheckArgs(values); return new LuaNumber(Math.Log(number.Number)); } public static LuaValue log10(LuaValue[] values) { LuaNumber number = CheckArgs(values); return new LuaNumber(Math.Log10(number.Number)); } public static LuaValue max(LuaValue[] values) { return new LuaNumber(values.Max(v => (v as LuaNumber).Number)); } public static LuaValue min(LuaValue[] values) { return new LuaNumber(values.Min(v => (v as LuaNumber).Number)); } public static LuaValue modf(LuaValue[] values) { LuaNumber number = CheckArgs(values); double integer = Math.Floor(number.Number); return new LuaMultiValue(new LuaNumber[] { new LuaNumber(integer), new LuaNumber(number.Number - integer) } ); } public static LuaValue pow(LuaValue[] values) { var numbers = CheckArgs2(values); return new LuaNumber(Math.Pow(numbers.Item1, numbers.Item2)); } public static LuaValue rad(LuaValue[] values) { LuaNumber number = CheckArgs(values); return new LuaNumber(number.Number * Math.PI / 180); } static Random randomGenerator = new Random(); public static LuaValue random(LuaValue[] values) { if (values.Length == 0) { return new LuaNumber(randomGenerator.NextDouble()); } else if (values.Length == 1) { LuaNumber number1 = values[0] as LuaNumber; return new LuaNumber(randomGenerator.Next((int)number1.Number) + 1); //[PixelCrushers] Lua random(x) is [1..x]. } else { var numbers = CheckArgs2(values); return new LuaNumber(randomGenerator.Next((int)numbers.Item1, (int)numbers.Item2 + 1)); //[PixelCrushers] Added "+1" (upper is inclusive) } } public static LuaValue randomseed(LuaValue[] values) { LuaNumber number = CheckArgs(values); randomGenerator = new Random((int)number.Number); return number; } public static LuaValue sin(LuaValue[] values) { LuaNumber number = CheckArgs(values); return new LuaNumber(Math.Sin(number.Number)); } public static LuaValue sinh(LuaValue[] values) { LuaNumber number = CheckArgs(values); return new LuaNumber(Math.Sinh(number.Number)); } public static LuaValue sqrt(LuaValue[] values) { LuaNumber number = CheckArgs(values); return new LuaNumber(Math.Sqrt(number.Number)); } public static LuaValue tan(LuaValue[] values) { LuaNumber number = CheckArgs(values); return new LuaNumber(Math.Tan(number.Number)); } public static LuaValue tanh(LuaValue[] values) { LuaNumber number = CheckArgs(values); return new LuaNumber(Math.Tanh(number.Number)); } private static LuaNumber CheckArgs(LuaValue[] values) { if (values.Length >= 1) { LuaNumber number = values[0] as LuaNumber; if (number != null) { return number; } else { throw new LuaError("bad argument #1 to 'abs' (number expected, got {0})", values[0].GetTypeCode()); } } else { throw new LuaError("bad argument #1 to 'abs' (number expected, got no value)"); } } private static Tuple CheckArgs2(LuaValue[] values) { if (values.Length >= 2) { LuaNumber number1 = values[0] as LuaNumber; if (number1 == null) { throw new LuaError("bad argument #1 to 'abs' (number expected, got {0})", values[0].GetTypeCode()); } LuaNumber number2 = values[1] as LuaNumber; if (number2 == null) { throw new LuaError("bad argument #2 to 'abs' (number expected, got {0})", values[1].GetTypeCode()); } return Tuple.Create(number1.Number, number2.Number); } else { throw new LuaError("bad argument #1 to 'abs' (number expected, got no value)"); } } } }