public static double LogGamma(double x)
{
double p, q, w, z;
if (x < -34.0)
{
q = -x;
w = LogGamma(q);
p = Math.Floor(q);
if (p == q) throw new ArithmeticException("lgam: Overflow");
z = q - p;
if (z > 0.5)
{
p += 1.0;
z = p - q;
}
z = q * Math.Sin(Math.PI * z);
if (z == 0.0) throw new
ArithmeticException("lgamma: Overflow");
z = 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
ArithmeticException("lgamma: Overflow");
z /= x;
x += 1.0;
}
if (z < 0.0) z = -z;
if (x == 2.0) return Math.Log(z);
x -= 2.0;
p = x*polevl(x, LGAMMA_B, 5)/p1evl(x, LGAMMA_C, 6);
return (Math.Log(z) + p);
}
if (x > 2.556348e305) throw new
ArithmeticException("lgamma: Overflow");
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 += polevl(p, LGAMMA_A, 4)/x;
return q;
}