public static double Log(double x)
{
if (x == 0)
return Double.PositiveInfinity;
double p, q, w, z;
if (x < -34.0)
{
q = -x;
w = Log(q);
p = Math.Floor(q);
if (p == q)
throw new OverflowException();
z = q - p;
if (z > 0.5)
{
p += 1.0;
z = p - q;
}
z = q * Math.Sin(System.Math.PI * z);
if (z == 0.0)
throw new OverflowException();
z = Constants.LogPI - Math.Log(z) - w;
return z;
}
if (x < 13.0)
{
z = 1.0;
while (x >= 3.0)
{
x -= 1.0;
z *= x;
}
while (x < 2.0)
{
if (x == 0.0)
throw new OverflowException();
z /= x;
x += 1.0;
}
if (z < 0.0)
z = -z;
if (x == 2.0)
return System.Math.Log(z);
x -= 2.0;
p = x * Special.Polevl(x, log_B, 5) / Special.P1evl(x, log_C, 6);
return (Math.Log(z) + p);
}
if (x > 2.556348e305)
throw new OverflowException();
q = (x - 0.5) * Math.Log(x) - x + 0.91893853320467274178;
if (x > 1.0e8)
return (q);
p = 1.0 / (x * x);
if (x >= 1000.0)
{
q += ((7.9365079365079365079365e-4 * p
- 2.7777777777777777777778e-3) * p
+ 0.0833333333333333333333) / x;
}
else
{
q += Special.Polevl(p, log_A, 4) / x;
}
return q;
}