123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739 |
- using System;
- using Jint.Native.Number;
- using Jint.Native.Object;
- using Jint.Runtime;
- using Jint.Runtime.Interop;
- namespace Jint.Native.Math
- {
- public sealed class MathInstance : ObjectInstance
- {
- private static readonly Random _random = new Random();
- private MathInstance(Engine engine) : base(engine, "Math")
- {
- }
- public static MathInstance CreateMathObject(Engine engine)
- {
- var math = new MathInstance(engine);
- math.Extensible = true;
- math.Prototype = engine.Object.PrototypeObject;
- return math;
- }
- public void Configure()
- {
- FastAddProperty("abs", new ClrFunctionInstance(Engine, Abs), true, false, true);
- FastAddProperty("acos", new ClrFunctionInstance(Engine, Acos), true, false, true);
- FastAddProperty("asin", new ClrFunctionInstance(Engine, Asin), true, false, true);
- FastAddProperty("atan", new ClrFunctionInstance(Engine, Atan), true, false, true);
- FastAddProperty("atan2", new ClrFunctionInstance(Engine, Atan2), true, false, true);
- FastAddProperty("ceil", new ClrFunctionInstance(Engine, Ceil), true, false, true);
- FastAddProperty("cos", new ClrFunctionInstance(Engine, Cos), true, false, true);
- FastAddProperty("exp", new ClrFunctionInstance(Engine, Exp), true, false, true);
- FastAddProperty("floor", new ClrFunctionInstance(Engine, Floor), true, false, true);
- FastAddProperty("log", new ClrFunctionInstance(Engine, Log), true, false, true);
- FastAddProperty("max", new ClrFunctionInstance(Engine, Max, 2), true, false, true);
- FastAddProperty("min", new ClrFunctionInstance(Engine, Min, 2), true, false, true);
- FastAddProperty("pow", new ClrFunctionInstance(Engine, Pow, 2), true, false, true);
- FastAddProperty("random", new ClrFunctionInstance(Engine, Random), true, false, true);
- FastAddProperty("round", new ClrFunctionInstance(Engine, Round), true, false, true);
- FastAddProperty("sin", new ClrFunctionInstance(Engine, Sin), true, false, true);
- FastAddProperty("sqrt", new ClrFunctionInstance(Engine, Sqrt), true, false, true);
- FastAddProperty("tan", new ClrFunctionInstance(Engine, Tan), true, false, true);
- FastAddProperty("trunc", new ClrFunctionInstance(Engine, Truncate), true, false, true);
- FastAddProperty("sign", new ClrFunctionInstance(Engine, Sign), true, false, true);
- FastAddProperty("cbrt", new ClrFunctionInstance(Engine, Cbrt), true, false, true);
- FastAddProperty("E", System.Math.E, false, false, false);
- FastAddProperty("LN10", System.Math.Log(10), false, false, false);
- FastAddProperty("LN2", System.Math.Log(2), false, false, false);
- FastAddProperty("LOG2E", System.Math.Log(System.Math.E, 2), false, false, false);
- FastAddProperty("LOG10E", System.Math.Log(System.Math.E, 10), false, false, false);
- FastAddProperty("PI", System.Math.PI, false, false, false);
- FastAddProperty("SQRT1_2", System.Math.Sqrt(0.5), false, false, false);
- FastAddProperty("SQRT2", System.Math.Sqrt(2), false, false, false);
- }
- private static JsValue Abs(JsValue thisObject, JsValue[] arguments)
- {
- var x = TypeConverter.ToNumber(arguments.At(0));
- if (double.IsNaN(x))
- {
- return double.NaN;
- }
- else if (NumberInstance.IsNegativeZero(x))
- {
- return +0;
- }
- else if (double.IsInfinity(x))
- {
- return double.PositiveInfinity;
- }
- return System.Math.Abs(x);
- }
- private static JsValue Acos(JsValue thisObject, JsValue[] arguments)
- {
- var x = TypeConverter.ToNumber(arguments.At(0));
- if (double.IsNaN(x) || (x > 1) || (x < -1))
- {
- return double.NaN;
- }
- else if (x == 1)
- {
- return 0;
- }
- return System.Math.Acos(x);
- }
- private static JsValue Asin(JsValue thisObject, JsValue[] arguments)
- {
- var x = TypeConverter.ToNumber(arguments.At(0));
- if (double.IsNaN(x) || (x > 1) || (x < -1))
- {
- return double.NaN;
- }
- else if (NumberInstance.IsPositiveZero(x) || NumberInstance.IsNegativeZero(x))
- {
- return x;
- }
- return System.Math.Asin(x);
- }
- private static JsValue Atan(JsValue thisObject, JsValue[] arguments)
- {
- var x = TypeConverter.ToNumber(arguments.At(0));
- if (double.IsNaN(x))
- {
- return double.NaN;
- }
- else if (NumberInstance.IsPositiveZero(x) || NumberInstance.IsNegativeZero(x))
- {
- return x;
- }
- else if (double.IsPositiveInfinity(x))
- {
- return System.Math.PI / 2;
- }
- else if (double.IsNegativeInfinity(x))
- {
- return -System.Math.PI / 2;
- }
- return System.Math.Atan(x);
- }
- private static JsValue Atan2(JsValue thisObject, JsValue[] arguments)
- {
- var y = TypeConverter.ToNumber(arguments.At(0));
- var x = TypeConverter.ToNumber(arguments.At(1));
- // If either x or y is NaN, the result is NaN.
- if (double.IsNaN(x) || double.IsNaN(y))
- {
- return double.NaN;
- }
- if (y > 0 && x.Equals(0))
- {
- return System.Math.PI/2;
- }
-
- if (NumberInstance.IsPositiveZero(y))
- {
- // If y is +0 and x>0, the result is +0.
- if (x > 0)
- {
- return +0;
- }
- // If y is +0 and x is +0, the result is +0.
- if (NumberInstance.IsPositiveZero(x))
- {
- return +0;
- }
- // If y is +0 and x is −0, the result is an implementation-dependent approximation to +π.
- if (NumberInstance.IsNegativeZero(x))
- {
- return System.Math.PI;
- }
-
- // If y is +0 and x<0, the result is an implementation-dependent approximation to +π.
- if (x < 0)
- {
- return System.Math.PI;
- }
- }
- if (NumberInstance.IsNegativeZero(y))
- {
- // If y is −0 and x>0, the result is −0.
- if (x > 0)
- {
- return -0;
- }
- // If y is −0 and x is +0, the result is −0.
- if (NumberInstance.IsPositiveZero(x))
- {
- return -0;
- }
- // If y is −0 and x is −0, the result is an implementation-dependent approximation to −π.
- if (NumberInstance.IsNegativeZero(x))
- {
- return -System.Math.PI;
- }
- // If y is −0 and x<0, the result is an implementation-dependent approximation to −π.
- if (x < 0)
- {
- return -System.Math.PI;
- }
- }
- // If y<0 and x is +0, the result is an implementation-dependent approximation to −π/2.
- // If y<0 and x is −0, the result is an implementation-dependent approximation to −π/2.
- if (y < 0 && x.Equals(0))
- {
- return -System.Math.PI/2;
- }
- // If y>0 and y is finite and x is +∞, the result is +0.
- if (y > 0 && !double.IsInfinity(y))
- {
- if (double.IsPositiveInfinity(x))
- {
- return +0;
- }
- // If y>0 and y is finite and x is −∞, the result if an implementation-dependent approximation to +π.
- if (double.IsNegativeInfinity(x))
- {
- return System.Math.PI;
- }
- }
- // If y<0 and y is finite and x is +∞, the result is −0.
- // If y<0 and y is finite and x is −∞, the result is an implementation-dependent approximation to −π.
- if (y < 0 && !double.IsInfinity(y))
- {
- if (double.IsPositiveInfinity(x))
- {
- return -0;
- }
- // If y>0 and y is finite and x is −∞, the result if an implementation-dependent approximation to +π.
- if (double.IsNegativeInfinity(x))
- {
- return -System.Math.PI;
- }
- }
-
- // If y is +∞ and x is finite, the result is an implementation-dependent approximation to +π/2.
- if (double.IsPositiveInfinity(y) && !double.IsInfinity(x))
- {
- return System.Math.PI/2;
- }
- // If y is −∞ and x is finite, the result is an implementation-dependent approximation to −π/2.
- if (double.IsNegativeInfinity(y) && !double.IsInfinity(x))
- {
- return -System.Math.PI / 2;
- }
- // If y is +∞ and x is +∞, the result is an implementation-dependent approximation to +π/4.
- if (double.IsPositiveInfinity(y) && double.IsPositiveInfinity(x))
- {
- return System.Math.PI/4;
- }
-
- // If y is +∞ and x is −∞, the result is an implementation-dependent approximation to +3π/4.
- if (double.IsPositiveInfinity(y) && double.IsNegativeInfinity(x))
- {
- return 3 * System.Math.PI / 4;
- }
-
- // If y is −∞ and x is +∞, the result is an implementation-dependent approximation to −π/4.
- if (double.IsNegativeInfinity(y) && double.IsPositiveInfinity(x))
- {
- return -System.Math.PI / 4;
- }
-
- // If y is −∞ and x is −∞, the result is an implementation-dependent approximation to −3π/4.
- if (double.IsNegativeInfinity(y) && double.IsNegativeInfinity(x))
- {
- return - 3 * System.Math.PI / 4;
- }
-
- return System.Math.Atan2(y, x);
- }
- private static JsValue Ceil(JsValue thisObject, JsValue[] arguments)
- {
- var x = TypeConverter.ToNumber(arguments.At(0));
- if (double.IsNaN(x))
- {
- return double.NaN;
- }
- else if (NumberInstance.IsPositiveZero(x))
- {
- return +0;
- }
- else if (NumberInstance.IsNegativeZero(x))
- {
- return -0;
- }
- else if (double.IsPositiveInfinity(x))
- {
- return double.PositiveInfinity;
- }
- else if (double.IsNegativeInfinity(x))
- {
- return double.NegativeInfinity;
- }
- return System.Math.Ceiling(x);
- }
- private static JsValue Cos(JsValue thisObject, JsValue[] arguments)
- {
- var x = TypeConverter.ToNumber(arguments.At(0));
- if (double.IsNaN(x))
- {
- return double.NaN;
- }
- else if (NumberInstance.IsPositiveZero(x))
- {
- return 1;
- }
- else if (NumberInstance.IsNegativeZero(x))
- {
- return 1;
- }
- else if (double.IsInfinity(x))
- {
- return double.NaN;
- }
- return System.Math.Cos(x);
- }
- private static JsValue Exp(JsValue thisObject, JsValue[] arguments)
- {
- var x = TypeConverter.ToNumber(arguments.At(0));
- if (double.IsNaN(x))
- {
- return double.NaN;
- }
- else if (NumberInstance.IsPositiveZero(x) || NumberInstance.IsNegativeZero(x))
- {
- return 1;
- }
- else if (double.IsPositiveInfinity(x))
- {
- return double.PositiveInfinity;
- }
- else if (double.IsNegativeInfinity(x))
- {
- return +0;
- }
- return System.Math.Exp(x);
- }
- private static JsValue Floor(JsValue thisObject, JsValue[] arguments)
- {
- var x = TypeConverter.ToNumber(arguments.At(0));
- if (double.IsNaN(x))
- {
- return double.NaN;
- }
- else if (NumberInstance.IsPositiveZero(x))
- {
- return +0;
- }
- else if (NumberInstance.IsNegativeZero(x))
- {
- return -0;
- }
- else if (double.IsPositiveInfinity(x))
- {
- return double.PositiveInfinity;
- }
- else if (double.IsNegativeInfinity(x))
- {
- return double.NegativeInfinity;
- }
- return System.Math.Floor(x);
- }
- private static JsValue Log(JsValue thisObject, JsValue[] arguments)
- {
- var x = TypeConverter.ToNumber(arguments.At(0));
- if (double.IsNaN(x))
- {
- return double.NaN;
- }
- if (x < 0)
- {
- return double.NaN;
- }
- else if (x == 0)
- {
- return double.NegativeInfinity;
- }
- else if (double.IsPositiveInfinity(x))
- {
- return double.PositiveInfinity;
- }
- else if (x == 1)
- {
- return +0;
- }
- return System.Math.Log(x);
- }
- private static JsValue Max(JsValue thisObject, JsValue[] arguments)
- {
- if (arguments.Length == 0)
- {
- return Double.NegativeInfinity;
- }
- double max = TypeConverter.ToNumber(arguments.At(0));
- if (double.IsNaN(max))
- {
- return double.NaN;
- }
- for (int i = 0; i < arguments.Length; i++)
- {
- var value = TypeConverter.ToNumber(arguments[i]);
- if (double.IsNaN(value))
- {
- return double.NaN;
- }
- max = System.Math.Max(max, value);
- }
- return max;
- }
- private static JsValue Min(JsValue thisObject, JsValue[] arguments)
- {
- if (arguments.Length == 0)
- {
- return Double.PositiveInfinity;
- }
- double min = TypeConverter.ToNumber(arguments.At(0));
- for (int i = 0; i < arguments.Length; i++)
- {
- min = System.Math.Min(min, TypeConverter.ToNumber(arguments[i]));
- }
- return min;
- }
- private static JsValue Pow(JsValue thisObject, JsValue[] arguments)
- {
- var x = TypeConverter.ToNumber(arguments.At(0));
- var y = TypeConverter.ToNumber(arguments.At(1));
- if (double.IsNaN(y))
- {
- return double.NaN;
- }
- if (y.Equals(0))
- {
- return 1;
- }
- if (double.IsNaN(x) && !y.Equals(0))
- {
- return double.NaN;
- }
- if (System.Math.Abs(x) > 1)
- {
- if (double.IsPositiveInfinity(y))
- {
- return double.PositiveInfinity;
- }
- if (double.IsNegativeInfinity(y))
- {
- return +0;
- }
- }
- if (System.Math.Abs(x).Equals(1))
- {
- if (double.IsInfinity(y))
- {
- return double.NaN;
- }
- }
- if (System.Math.Abs(x) < 1)
- {
- if (double.IsPositiveInfinity(y))
- {
- return 0;
- }
- if (double.IsNegativeInfinity(y))
- {
- return double.PositiveInfinity;
- }
- }
- if (double.IsPositiveInfinity(x))
- {
- if (y > 0)
- {
- return double.PositiveInfinity;
- }
- if (y < 0)
- {
- return +0;
- }
- }
- if (double.IsNegativeInfinity(x))
- {
- if (y > 0)
- {
- if (System.Math.Abs(y % 2).Equals(1))
- {
- return double.NegativeInfinity;
- }
- return double.PositiveInfinity;
- }
- if (y < 0)
- {
- if (System.Math.Abs(y % 2).Equals(1))
- {
- return -0;
- }
- return +0;
- }
- }
- if (NumberInstance.IsPositiveZero(x))
- {
- // If x is +0 and y>0, the result is +0.
- if (y > 0)
- {
- return 0;
- }
- // If x is +0 and y<0, the result is +∞.
- if (y < 0)
- {
- return double.PositiveInfinity;
- }
- }
- if (NumberInstance.IsNegativeZero(x))
- {
- if (y > 0)
- {
- // If x is −0 and y>0 and y is an odd integer, the result is −0.
- if (System.Math.Abs(y % 2).Equals(1))
- {
- return -0;
- }
- // If x is −0 and y>0 and y is not an odd integer, the result is +0.
- return +0;
- }
- if (y < 0)
- {
- // If x is −0 and y<0 and y is an odd integer, the result is −∞.
- if (System.Math.Abs(y % 2).Equals(1))
- {
- return double.NegativeInfinity;
- }
- // If x is −0 and y<0 and y is not an odd integer, the result is +∞.
- return double.PositiveInfinity;
- }
- }
- // If x<0 and x is finite and y is finite and y is not an integer, the result is NaN.
- if (x < 0 && !double.IsInfinity(x) && !double.IsInfinity(y) && !y.Equals((int)y))
- {
- return double.NaN;
- }
- return System.Math.Pow(x, y);
- }
- private static JsValue Random(JsValue thisObject, JsValue[] arguments)
- {
- return _random.NextDouble();
- }
- private static JsValue Round(JsValue thisObject, JsValue[] arguments)
- {
- var x = TypeConverter.ToNumber(arguments.At(0));
- var round = System.Math.Round(x);
- if (round.Equals(x - 0.5))
- {
- return round + 1;
- }
- return round;
- }
- private static JsValue Sin(JsValue thisObject, JsValue[] arguments)
- {
- var x = TypeConverter.ToNumber(arguments.At(0));
- if (double.IsNaN(x))
- {
- return double.NaN;
- }
- else if (NumberInstance.IsPositiveZero(x))
- {
- return +0;
- }
- else if (NumberInstance.IsNegativeZero(x))
- {
- return -0;
- }
- else if (double.IsInfinity(x))
- {
- return double.NaN;
- }
- return System.Math.Sin(x);
- }
- private static JsValue Sqrt(JsValue thisObject, JsValue[] arguments)
- {
- var x = TypeConverter.ToNumber(arguments.At(0));
- return System.Math.Sqrt(x);
- }
- private static JsValue Tan(JsValue thisObject, JsValue[] arguments)
- {
- var x = TypeConverter.ToNumber(arguments.At(0));
- return System.Math.Tan(x);
- }
- private static JsValue Truncate(JsValue thisObject, JsValue[] arguments)
- {
- var x = TypeConverter.ToNumber(arguments.At(0));
- if (double.IsNaN(x))
- {
- return double.NaN;
- }
- if (NumberInstance.IsPositiveZero(x) || NumberInstance.IsNegativeZero(x))
- {
- return x;
- }
- if (double.IsPositiveInfinity(x))
- {
- return double.PositiveInfinity;
- }
- if (double.IsNegativeInfinity(x))
- {
- return double.NegativeInfinity;
- }
- return System.Math.Truncate(x);
- }
- private static JsValue Sign(JsValue thisObject, JsValue[] arguments)
- {
- var x = TypeConverter.ToNumber(arguments.At(0));
- if (double.IsNaN(x))
- {
- return double.NaN;
- }
- if (NumberInstance.IsPositiveZero(x) || NumberInstance.IsNegativeZero(x))
- {
- return x;
- }
- if (double.IsPositiveInfinity(x))
- {
- return 1;
- }
- if (double.IsNegativeInfinity(x))
- {
- return -1;
- }
- return System.Math.Sign(x);
- }
- private static JsValue Cbrt(JsValue thisObject, JsValue[] arguments)
- {
- var x = TypeConverter.ToNumber(arguments.At(0));
- if (double.IsNaN(x))
- {
- return double.NaN;
- }
- else if (NumberInstance.IsPositiveZero(x) || NumberInstance.IsNegativeZero(x))
- {
- return x;
- }
- else if (double.IsPositiveInfinity(x))
- {
- return double.PositiveInfinity;
- }
- else if (double.IsNegativeInfinity(x))
- {
- return double.NegativeInfinity;
- }
- if (System.Math.Sign(x) >= 0)
- {
- return System.Math.Pow(x, 1.0/3.0);
- }
- return -1 * System.Math.Pow(System.Math.Abs(x), 1.0 / 3.0);
- }
- }
- }
|