10000000000.0) { return 0.0; } elseif ($x < $a + 1.0) { return self::gammaSeriesExpansion($a, $x); } return 1.0 - self::gammaFraction($a, $x); } /** * Gamma series expansion * * @param float $a a * @param float $x Value * * @return float * * @see JSci * @author Jaco van Kooten * @license LGPL 2.1 * @since 1.0.0 */ private static function gammaSeriesExpansion(float $a, float $x) : float { $ap = $a; $del = 1.0 / $a; $sum = $del; for ($i = 1; $i < 150; ++$i) { ++$ap; $del *= $x / $ap; $sum += $del; if ($del < $sum * 2.22e-16) { return $sum * \exp(-$x + $a * \log($x) - self::logGamma($a)); } } return 0.0; } /** * Gamma fraction * * @param float $a a * @param float $x Value * * @return float * * @see JSci * @author Jaco van Kooten * @license LGPL 2.1 * @since 1.0.0 */ private static function gammaFraction(float $a, float $x) : float { $b = $x + 1.0 - $a; $c = 1.0 / 1.18e-37; $d = 1.0 / $b; $h = $d; $del = 0.0; for ($i = 1; $i < 150 && \abs($del - 1.0) > 2.22e-16; ++$i) { $an = - $i * ($i - $a); $b += 2.0; $d = $an * $d + $b; $c = $b + $an / $c; if (\abs($c) < 1.18e-37) { $c = 1.18e-37; } if (\abs($d) < 1.18e-37) { $d = 1.18e-37; } $d = 1.0 / $d; $del = $d * $c; $h *= $del; } return \exp(-$x + $a * \log($x) - self::logGamma($a)) * $h; } }