function gammaln( x ) {
	var isNegative;
	var nadj;
	var flg;
	var p3;
	var p2;
	var p1;
	var p;
	var q;
	var t;
	var w;
	var y;
	var z;
	var r;

	// Special cases: NaN, +-infinity
	if ( isnan( x ) || isInfinite( x ) ) {
		return x;
	}
	// Special case: 0
	if ( x === 0.0 ) {
		return PINF;
	}
	if ( x < 0.0 ) {
		isNegative = true;
		x = -x;
	} else {
		isNegative = false;
	}
	// If |x| < 2**-56, return -ln(|x|)
	if ( x < TINY ) {
		return -ln( x );
	}
	if ( isNegative ) {
		// If |x| >= 2**52, must be -integer
		if ( x >= TWO52 ) {
			return PINF;
		}
		t = sinpi( x );
		if ( t === 0.0 ) {
			return PINF;
		}
		nadj = ln( PI / abs( t*x ) );
	}
	// If x equals 1 or 2, return 0
	if ( x === 1.0 || x === 2.0 ) {
		return 0.0;
	}
	// If x < 2, use lgamma(x) = lgamma(x+1) - log(x)
	if ( x < 2.0 ) {
		if ( x <= 0.9 ) {
			r = -ln( x );

			// 0.7316 <= x <=  0.9
			if ( x >= ( YMIN - 1.0 + 0.27 ) ) {
				y = 1.0 - x;
				flg = 0;
			}
			// 0.2316 <= x < 0.7316
			else if ( x >= (YMIN - 1.0 - 0.27) ) {
				y = x - (TC - 1.0);
				flg = 1;
			}
			// 0 < x < 0.2316
			else {
				y = x;
				flg = 2;
			}
		} else {
			r = 0.0;

			// 1.7316 <= x < 2
			if ( x >= (YMIN + 0.27) ) {
				y = 2.0 - x;
				flg = 0;
			}
			// 1.2316 <= x < 1.7316
			else if ( x >= (YMIN - 0.27) ) {
				y = x - TC;
				flg = 1;
			}
			// 0.9 < x < 1.2316
			else {
				y = x - 1.0;
				flg = 2;
			}
		}
		switch ( flg ) { // eslint-disable-line default-case
		case 0:
			z = y * y;
			p1 = A1C + (z*polyvalA1( z ));
			p2 = z * (A2C + (z*polyvalA2( z )));
			p = (y*p1) + p2;
			r += ( p - (0.5*y) );
			break;
		case 1:
			z = y * y;
			w = z * y;
			p1 = T1C + (w*polyvalT1( w ));
			p2 = T2C + (w*polyvalT2( w ));
			p3 = T3C + (w*polyvalT3( w ));
			p = (z*p1) - (TT - (w*(p2+(y*p3))));
			r += ( TF + p );
			break;
		case 2:
			p1 = y * (UC + (y*polyvalU( y )));
			p2 = VC + (y*polyvalV( y ));
			r += (-0.5*y) + (p1/p2);
			break;
		}
	}
	// 2 <= x < 8
	else if ( x < 8.0 ) {
		flg = trunc( x );
		y = x - flg;
		p = y * (SC + (y*polyvalS( y )));
		q = RC + (y*polyvalR( y ));
		r = (0.5*y) + (p/q);
		z = 1.0; // gammaln(1+s) = ln(s) + gammaln(s)
		switch ( flg ) { // eslint-disable-line default-case
		case 7:
			z *= y + 6.0;

			/* Falls through */
		case 6:
			z *= y + 5.0;

			/* Falls through */
		case 5:
			z *= y + 4.0;

			/* Falls through */
		case 4:
			z *= y + 3.0;

			/* Falls through */
		case 3:
			z *= y + 2.0;
			r += ln( z );
		}
	}
	// 8 <= x < 2**56
	else if ( x < TWO56 ) {
		t = ln( x );
		z = 1.0 / x;
		y = z * z;
		w = WC + (z*polyvalW( y ));
		r = ((x-0.5)*(t-1.0)) + w;
	}
	// 2**56 <= x <= Inf
	else {
		r = x * ( ln(x)-1.0 );
	}
	if ( isNegative ) {
		r = nadj - r;
	}
	return r;
}
Evaluates the natural logarithm of the gamma function.

## Method

1.  Argument reduction for \\(0 < x \leq 8\\). Since \\(\Gamma(1+s) = s \Gamma(s)\\), for \\(x \in \[0,8]\\), we may reduce \\(x\\) to a number in \\(\[1.5,2.5]\\) by

    ```tex
    \operatorname{lgamma}(1+s) = \ln(s) + \operatorname{lgamma}(s)
    ```

    For example,

    ```tex
    \begin{align*}
    \operatorname{lgamma}(7.3) &= \ln(6.3) + \operatorname{lgamma}(6.3) \\
    &= \ln(6.3 \cdot 5.3) + \operatorname{lgamma}(5.3) \\
    &= \ln(6.3 \cdot 5.3 \cdot 4.3 \cdot 3.3 \cdot2.3) + \operatorname{lgamma}(2.3)
    \end{align*}
    ```

2.  Compute a polynomial approximation of \\(\mathrm{lgamma}\\) around its minimum (\\(\mathrm{ymin} = 1.461632144968362245\\)) to maintain monotonicity. On the interval \\(\[\mathrm{ymin} - 0.23, \mathrm{ymin} + 0.27]\\) (i.e., \\(\[1.23164,1.73163]\\)), we let \\(z = x - \mathrm{ymin}\\) and use

    ```tex
    \operatorname{lgamma}(x) = -1.214862905358496078218 + z^2 \cdot \operatorname{poly}(z)
    ```

    where \\(\operatorname{poly}(z)\\) is a \\(14\\) degree polynomial.

3.  Compute a rational approximation in the primary interval \\(\[2,3]\\). Let \\( s = x - 2.0 \\). We can thus use the approximation

    ```tex
    \operatorname{lgamma}(x) = \frac{s}{2} + s\frac{\operatorname{P}(s)}{\operatorname{Q}(s)}
    ```

    with accuracy

    ```tex
    \biggl|\frac{\mathrm{P}}{\mathrm{Q}} - \biggr(\operatorname{lgamma}(x)-\frac{s}{2}\biggl)\biggl| < 2^{-61.71}
    ```

    The algorithms are based on the observation

    ```tex
    \operatorname{lgamma}(2+s) = s(1 - \gamma) + \frac{\zeta(2) - 1}{2} s^2 - \frac{\zeta(3) - 1}{3} s^3 + \ldots
    ```

    where \\(\zeta\\) is the zeta function and \\(\gamma = 0.5772156649...\\) is the Euler-Mascheroni constant, which is very close to \\(0.5\\).

4.  For \\(x \geq 8\\),

    ```tex
    \operatorname{lgamma}(x) \approx \biggl(x-\frac{1}{2}\biggr) \ln(x) - x + \frac{\ln(2\pi)}{2} + \frac{1}{12x} - \frac{1}{360x^3} + \ldots
    ```

    which can be expressed

    ```tex
    \operatorname{lgamma}(x) \approx \biggl(x-\frac{1}{2}\biggr)(\ln(x)-1)-\frac{\ln(2\pi)-1}{2} + \ldots
    ```

    Let \\(z = \frac{1}{x}\\). We can then use the approximation

    ```tex
    f(z) = \operatorname{lgamma}(x) - \biggl(x-\frac{1}{2}\biggr)(\ln(x)-1)
    ```

    by

    ```tex
    w = w_0 + w_1 z + w_2 z^3 + w_3 z^5 + \ldots + w_6 z^{11}
    ```

    where

    ```tex
    |w - f(z)| < 2^{-58.74}
    ```

5.  For negative \\(x\\), since

    ```tex
    -x \Gamma(-x) \Gamma(x) = \frac{\pi}{\sin(\pi x)}
    ```

    where \\(\Gamma\\) is the gamma function, we have

    ```tex
    \Gamma(x) = \frac{\pi}{\sin(\pi x)(-x)\Gamma(-x)}
    ```

    Since \\(\Gamma(-x)\\) is positive,

    ```tex
    \operatorname{sign}(\Gamma(x)) = \operatorname{sign}(\sin(\pi x))
    ```

    for \\(x < 0\\). Hence, for \\(x < 0\\),

    ```tex
    \mathrm{signgam} = \operatorname{sign}(\sin(\pi x))
    ```

    and

    ```tex
    \begin{align*}
    \operatorname{lgamma}(x) &= \ln(|\Gamma(x)|) \\
    &= \ln\biggl(\frac{\pi}{|x \sin(\pi x)|}\biggr) - \operatorname{lgamma}(-x)
    \end{align*}
    ```

    <!-- <note> -->

    Note that one should avoid computing \\(\pi (-x)\\) directly in the computation of \\(\sin(\pi (-x))\\).

    <!-- </note> -->

## Special Cases

```tex
\begin{align*}
\operatorname{lgamma}(2+s) &\approx s (1-\gamma) & \mathrm{for\ tiny\ s} \\
\operatorname{lgamma}(x) &\approx -\ln(x) & \mathrm{for\ tiny\ x} \\
\operatorname{lgamma}(1) &= 0 & \\
\operatorname{lgamma}(2) &= 0 & \\
\operatorname{lgamma}(0) &= \infty & \\
\operatorname{lgamma}(\infty) &= \infty & \\
\operatorname{lgamma}(-\mathrm{integer}) &= \pm \infty
\end{align*}
```

@param {number} x - input value
@returns {number} function value

@example
var v = gammaln( 1.0 );
// returns 0.0

@example
var v = gammaln( 2.0 );
// returns 0.0

@example
var v = gammaln( 4.0 );
// returns ~1.792

@example
var v = gammaln( -0.5 );
// returns ~1.266

@example
var v = gammaln( 0.5 );
// returns ~0.572

@example
var v = gammaln( 0.0 );
// returns Infinity

@example
var v = gammaln( NaN );
// returns NaN