private static function _logGamma($x) { // Log Gamma related constants static $lg_d1 = -0.5772156649015329; static $lg_d2 = 0.42278433509846713; static $lg_d4 = 1.791759469228055; static $lg_p1 = array(4.945235359296727, 201.8112620856775, 2290.8383738313464, 11319.672059033808, 28557.246356716354, 38484.962284437934, 26377.487876241954, 7225.813979700288); static $lg_p2 = array(4.974607845568932, 542.4138599891071, 15506.93864978365, 184793.29044456323, 1088204.7694688288, 3338152.96798703, 5106661.678927353, 3074109.0548505397); static $lg_p4 = array(14745.0216605994, 2426813.3694867045, 121475557.40450932, 2663432449.630977, 29403789566.34554, 170266573776.5399, 492612579337.7431, 560625185622.3951); static $lg_q1 = array(67.48212550303778, 1113.3323938571993, 7738.757056935398, 27639.870744033407, 54993.102062261576, 61611.22180066002, 36351.2759150194, 8785.536302431014); static $lg_q2 = array(183.03283993705926, 7765.049321445006, 133190.38279660742, 1136705.8213219696, 5267964.117437947, 13467014.543111017, 17827365.303532742, 9533095.591844354); static $lg_q4 = array(2690.5301758708993, 639388.5654300093, 41355999.30241388, 1120872109.616148, 14886137286.788137, 101680358627.24382, 341747634550.73773, 446315818741.9713); static $lg_c = array(-0.001910444077728, 0.0008417138778129501, -0.0005952379913043012, 0.0007936507935003503, -0.0027777777777776816, 0.08333333333333333, 0.0057083835261); // Rough estimate of the fourth root of logGamma_xBig static $lg_frtbig = 2.25E+76; static $pnt68 = 0.6796875; if ($x == self::$_logGammaCache_x) { return self::$_logGammaCache_result; } $y = $x; if ($y > 0.0 && $y <= LOG_GAMMA_X_MAX_VALUE) { if ($y <= EPS) { $res = -log(y); } elseif ($y <= 1.5) { // --------------------- // EPS .LT. X .LE. 1.5 // --------------------- if ($y < $pnt68) { $corr = -log($y); $xm1 = $y; } else { $corr = 0.0; $xm1 = $y - 1.0; } if ($y <= 0.5 || $y >= $pnt68) { $xden = 1.0; $xnum = 0.0; for ($i = 0; $i < 8; ++$i) { $xnum = $xnum * $xm1 + $lg_p1[$i]; $xden = $xden * $xm1 + $lg_q1[$i]; } $res = $corr + $xm1 * ($lg_d1 + $xm1 * ($xnum / $xden)); } else { $xm2 = $y - 1.0; $xden = 1.0; $xnum = 0.0; for ($i = 0; $i < 8; ++$i) { $xnum = $xnum * $xm2 + $lg_p2[$i]; $xden = $xden * $xm2 + $lg_q2[$i]; } $res = $corr + $xm2 * ($lg_d2 + $xm2 * ($xnum / $xden)); } } elseif ($y <= 4.0) { // --------------------- // 1.5 .LT. X .LE. 4.0 // --------------------- $xm2 = $y - 2.0; $xden = 1.0; $xnum = 0.0; for ($i = 0; $i < 8; ++$i) { $xnum = $xnum * $xm2 + $lg_p2[$i]; $xden = $xden * $xm2 + $lg_q2[$i]; } $res = $xm2 * ($lg_d2 + $xm2 * ($xnum / $xden)); } elseif ($y <= 12.0) { // ---------------------- // 4.0 .LT. X .LE. 12.0 // ---------------------- $xm4 = $y - 4.0; $xden = -1.0; $xnum = 0.0; for ($i = 0; $i < 8; ++$i) { $xnum = $xnum * $xm4 + $lg_p4[$i]; $xden = $xden * $xm4 + $lg_q4[$i]; } $res = $lg_d4 + $xm4 * ($xnum / $xden); } else { // --------------------------------- // Evaluate for argument .GE. 12.0 // --------------------------------- $res = 0.0; if ($y <= $lg_frtbig) { $res = $lg_c[6]; $ysq = $y * $y; for ($i = 0; $i < 6; ++$i) { $res = $res / $ysq + $lg_c[$i]; } } $res /= $y; $corr = log($y); $res = $res + log(SQRT2PI) - 0.5 * $corr; $res += $y * ($corr - 1.0); } } else { // -------------------------- // Return for bad arguments // -------------------------- $res = MAX_VALUE; } // ------------------------------ // Final adjustments and return // ------------------------------ self::$_logGammaCache_x = $x; self::$_logGammaCache_result = $res; return $res; }