function gamma( x ) {
	var sign;
	var q;
	var p;
	var z;
	if (
		(isInteger( x ) && x < 0) ||
		x === NINF ||
		isnan( x )
	) {
		return NaN;
	}
	if ( x === 0.0 ) {
		if ( isNegativeZero( x ) ) {
			return NINF;
		}
		return PINF;
	}
	if ( x > 171.61447887182298 ) {
		return PINF;
	}
	if ( x < -170.5674972726612 ) {
		return 0.0;
	}
	q = abs( x );
	if ( q > 33.0 ) {
		if ( x >= 0.0 ) {
			return stirlingApprox( x );
		}
		p = floor( q );

		// Check whether `x` is even...
		if ( (p&1) === 0 ) {
			sign = -1.0;
		} else {
			sign = 1.0;
		}
		z = q - p;
		if ( z > 0.5 ) {
			p += 1.0;
			z = q - p;
		}
		z = q * sin( PI * z );
		return sign * PI / ( abs(z)*stirlingApprox(q) );
	}
	// Reduce `x`...
	z = 1.0;
	while ( x >= 3.0 ) {
		x -= 1.0;
		z *= x;
	}
	while ( x < 0.0 ) {
		if ( x > -1.0e-9 ) {
			return smallApprox( x, z );
		}
		z /= x;
		x += 1.0;
	}
	while ( x < 2.0 ) {
		if ( x < 1.0e-9 ) {
			return smallApprox( x, z );
		}
		z /= x;
		x += 1.0;
	}
	if ( x === 2.0 ) {
		return z;
	}
	x -= 2.0;
	return z * rateval( x );
}
Evaluates the gamma function.

## Method

1.  Arguments \\(|x| \leq 34\\) are reduced by recurrence and the function approximated by a rational function of degree \\(6/7\\) in the interval \\((2,3)\\).
2.  Large negative arguments are made positive using a reflection formula.
3.  Large arguments are handled by Stirling's formula.

## Notes

-   Relative error:

    | arithmetic | domain    | # trials | peak    | rms     |
    |:----------:|:---------:|:--------:|:-------:|:-------:|
    | DEC        | -34,34    | 10000    | 1.3e-16 | 2.5e-17 |
    | IEEE       | -170,-33  | 20000    | 2.3e-15 | 3.3e-16 |
    | IEEE       | -33, 33   | 20000    | 9.4e-16 | 2.2e-16 |
    | IEEE       | 33, 171.6 | 20000    | 2.3e-15 | 3.2e-16 |

-   Error for arguments outside the test range will be larger owing to error amplification by the exponential function.

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

@example
var v = gamma( 4.0 );
// returns 6.0

@example
var v = gamma( -1.5 );
// returns ~2.363

@example
var v = gamma( -0.5 );
// returns ~-3.545

@example
var v = gamma( 0.5 );
// returns ~1.772

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

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

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