Task

Implement one algorithm (or more) to compute the Gamma (



Γ


{\displaystyle \Gamma }

) function (in the real field only).

If your language has the function as built-in or you know a library which has it, compare your implementation's results with the results of the built-in/library function.

The Gamma function can be defined as:

  



Γ
(
x
)
=


∫

0


∞



t

x
−
1



e

−
t


d
t



{\displaystyle \Gamma (x)=\displaystyle \int _{0}^{\infty }t^{x-1}e^{-t}dt}


This suggests a straightforward (but inefficient) way of computing the 



Γ


{\displaystyle \Gamma }

 through numerical integration.



Better suggested methods:

 Lanczos approximation
 Stirling's approximation


import std.stdio, std.math, std.mathspecial;
 
real taylorGamma(in real x) pure nothrow @safe @nogc {
    static immutable real[30] table = [
     0x1p+0,                    0x1.2788cfc6fb618f4cp-1,
    -0x1.4fcf4026afa2dcecp-1,  -0x1.5815e8fa27047c8cp-5,
     0x1.5512320b43fbe5dep-3,  -0x1.59af103c340927bep-5,
    -0x1.3b4af28483e214e4p-7,   0x1.d919c527f60b195ap-8,
    -0x1.317112ce3a2a7bd2p-10, -0x1.c364fe6f1563ce9cp-13,
     0x1.0c8a78cd9f9d1a78p-13, -0x1.51ce8af47eabdfdcp-16,
    -0x1.4fad41fc34fbb2p-20,    0x1.302509dbc0de2c82p-20,
    -0x1.b9986666c225d1d4p-23,  0x1.a44b7ba22d628acap-28,
     0x1.57bc3fc384333fb2p-28, -0x1.44b4cedca388f7c6p-30,
     0x1.cae7675c18606c6p-34,   0x1.11d065bfaf06745ap-37,
    -0x1.0423bac8ca3faaa4p-38,  0x1.1f20151323cd0392p-41,
    -0x1.72cb88ea5ae6e778p-46, -0x1.815f72a05f16f348p-48,
     0x1.6198491a83bccbep-50,  -0x1.10613dde57a88bd6p-53,
     0x1.5e3fee81de0e9c84p-60,  0x1.a0dc770fb8a499b6p-60,
    -0x1.0f635344a29e9f8ep-62,  0x1.43d79a4b90ce8044p-66];
 
    immutable real y = x - 1.0L;
    real sm = table[$ - 1];
    foreach_reverse (immutable an; table[0 .. $ - 1])
        sm = sm * y + an;
    return 1.0L / sm;
}
 
real lanczosGamma(real z) pure nothrow @safe @nogc {
    // Coefficients used by the GNU Scientific Library.
    // http://en.wikipedia.org/wiki/Lanczos_approximation
    enum g = 7;
    static immutable real[9] table =
        [    0.99999_99999_99809_93,
           676.52036_81218_851,
         -1259.13921_67224_028,
           771.32342_87776_5313,
          -176.61502_91621_4059,
            12.50734_32786_86905,
            -0.13857_10952_65720_12,
             9.98436_95780_19571_6e-6,
             1.50563_27351_49311_6e-7];
 
    // Reflection formula.
    if (z < 0.5L) {
        return PI / (sin(PI * z) * lanczosGamma(1 - z));
    } else {
        z -= 1;
        real x = table[0];
        foreach (immutable i; 1 .. g + 2)
            x += table[i] / (z + i);
        immutable real t = z + g + 0.5L;
        return sqrt(2 * PI) * t ^^ (z + 0.5L) * exp(-t) * x;
    }
}
 
void main() {
    foreach (immutable i; 1 .. 11) {
        immutable real x = i / 3.0L;
        writefln("%f: %20.19e %20.19e %20.19e", x,
                 x.taylorGamma, x.lanczosGamma, x.gamma);
    }
}