public static double Gamma(double x)
{
double p, z;
double q = Math.Abs(x);
if (q > 33.0)
{
if (x < 0.0)
{
p = Math.Floor(q);
if (p == q) throw new ArithmeticException("gamma: overflow");
//int i = (int)p;
z = q - p;
if (z > 0.5)
{
p += 1.0;
z = q - p;
}
z = q * Math.Sin(Math.PI * z);
if (z == 0.0) throw new ArithmeticException("gamma: overflow");
z = Math.Abs(z);
z = Math.PI / (z * Stirf(q));
return -z;
}
else
{
return Stirf(x);
}
}
z = 1.0;
while (x >= 3.0)
{
x -= 1.0;
z *= x;
}
while (x < 0.0)
{
if (x == 0.0)
{
throw new ArithmeticException("gamma: singular");
}
else if (x > -1.0E-9)
{
return (z / ((1.0 + GAMMA * x) * x));
}
z /= x;
x += 1.0;
}
while (x < 2.0)
{
if (x == 0.0)
{
throw new ArithmeticException("gamma: singular");
}
else if (x < 1.0E-9)
{
return (z / ((1.0 + GAMMA * x) * x));
}
z /= x;
x += 1.0;
}
if ((x == 2.0) || (x == 3.0)) return z;
x -= 2.0;
p = polevl(x, GAMMA_P, 6);
q = polevl(x, GAMMA_Q, 7);
return z*p/q;
}