public override object ExecIdCall(IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, object[] args)
{
if (!f.HasTag(MATH_TAG))
{
return base.ExecIdCall(f, cx, scope, thisObj, args);
}
double x;
int methodId = f.MethodId();
switch (methodId)
{
case Id_toSource:
{
return "Math";
}
case Id_abs:
{
x = ScriptRuntime.ToNumber(args, 0);
// abs(-0.0) should be 0.0, but -0.0 < 0.0 == false
x = (x == 0.0) ? 0.0 : (x < 0.0) ? -x : x;
break;
}
case Id_acos:
case Id_asin:
{
x = ScriptRuntime.ToNumber(args, 0);
if (x == x && -1.0 <= x && x <= 1.0)
{
x = (methodId == Id_acos) ? Math.Acos(x) : Math.Asin(x);
}
else
{
x = double.NaN;
}
break;
}
case Id_atan:
{
x = ScriptRuntime.ToNumber(args, 0);
x = Math.Atan(x);
break;
}
case Id_atan2:
{
x = ScriptRuntime.ToNumber(args, 0);
x = Math.Atan2(x, ScriptRuntime.ToNumber(args, 1));
break;
}
case Id_ceil:
{
x = ScriptRuntime.ToNumber(args, 0);
x = System.Math.Ceiling(x);
break;
}
case Id_cos:
{
x = ScriptRuntime.ToNumber(args, 0);
x = (x == double.PositiveInfinity || x == double.NegativeInfinity) ? double.NaN : Math.Cos(x);
break;
}
case Id_exp:
{
x = ScriptRuntime.ToNumber(args, 0);
x = (x == double.PositiveInfinity) ? x : (x == double.NegativeInfinity) ? 0.0 : Math.Exp(x);
break;
}
case Id_floor:
{
x = ScriptRuntime.ToNumber(args, 0);
x = Math.Floor(x);
break;
}
case Id_log:
{
x = ScriptRuntime.ToNumber(args, 0);
// Java's log(<0) = -Infinity; we need NaN
x = (x < 0) ? double.NaN : Math.Log(x);
break;
}
case Id_max:
case Id_min:
{
x = (methodId == Id_max) ? double.NegativeInfinity : double.PositiveInfinity;
for (int i = 0; i != args.Length; ++i)
{
double d = ScriptRuntime.ToNumber(args[i]);
if (d != d)
{
x = d;
// NaN
break;
}
if (methodId == Id_max)
{
// if (x < d) x = d; does not work due to -0.0 >= +0.0
x = Math.Max(x, d);
}
else
{
x = Math.Min(x, d);
}
}
break;
}
case Id_pow:
{
x = ScriptRuntime.ToNumber(args, 0);
x = Js_pow(x, ScriptRuntime.ToNumber(args, 1));
break;
}
case Id_random:
{
x = Math.Random();
break;
}
case Id_round:
{
x = ScriptRuntime.ToNumber(args, 0);
if (x == x && x != double.PositiveInfinity && x != double.NegativeInfinity)
{
// Round only finite x
long l = Math.Round(x);
if (l != 0)
{
x = l;
}
else
{
// We must propagate the sign of d into the result
if (x < 0.0)
{
x = ScriptRuntime.negativeZero;
}
else
{
if (x != 0.0)
{
x = 0.0;
}
}
}
}
break;
}
case Id_sin:
{
x = ScriptRuntime.ToNumber(args, 0);
x = (x == double.PositiveInfinity || x == double.NegativeInfinity) ? double.NaN : Math.Sin(x);
break;
}
case Id_sqrt:
{
x = ScriptRuntime.ToNumber(args, 0);
x = Math.Sqrt(x);
break;
}
case Id_tan:
{
x = ScriptRuntime.ToNumber(args, 0);
x = Math.Tan(x);
break;
}
default:
{
throw new InvalidOperationException(methodId.ToString());
}
}
return ScriptRuntime.WrapNumber(x);
}