diGamma function

double diGamma(
  1. double x
)

Computes the Digamma function which is mathematically defined as the derivative of the logarithm of the gamma function.

This implementation is based on Jose Bernardo Algorithm AS 103: Psi ( Digamma ) Function, Applied Statistics, Volume 25, Number 3, 1976, pages 315-317. Using the modifications as in Tom Minka's lightspeed toolbox.

Implementation

double diGamma(double x) {
  const double c = 12.0;
  const double d1 = -0.57721566490153286;
  const double d2 = 1.6449340668482264365;
  const double s = 1e-6;
  const double s3 = 1.0 / 12.0;
  const double s4 = 1.0 / 120.0;
  const double s5 = 1.0 / 252.0;
  const double s6 = 1.0 / 240.0;
  const double s7 = 1.0 / 132.0;

  if ((x.isInfinite && x.isNegative) || x.isNaN) {
    return double.nan;
  }

  // Handle special cases.
  if (x <= 0 && x.floor() == x) {
    return double.negativeInfinity;
  }

  // Use inversion formula for negative numbers.
  if (x < 0) {
    return diGamma(1.0 - x) + (constants.pi / trig.tan(-constants.pi * x));
  }

  if (x <= s) {
    return d1 - (1 / x) + (d2 * x);
  }

  double result = 0.0;
  while (x < c) {
    result -= 1 / x;
    x++;
  }

  if (x >= c) {
    var r = 1 / x;
    result += stdmath.log(x) - (0.5 * r);
    r *= r;

    result -= r * (s3 - (r * (s4 - (r * (s5 - (r * (s6 - (r * s7))))))));
  }

  return result;
}