Program: 57073
Project: 57073
Buggy source:
/** 
 * Returns the value of log B(p, q) for 0 ≤ x ≤ 1 and p, q > 0. Based on the <em>NSWC Library of Mathematics Subroutines</em> implementation,  {@code DBETLN}.
 * @param p First argument.
 * @param q Second argument.
 * @return the value of {@code log(Beta(p, q))},   {@code NaN} if{@code p <= 0} or {@code q <= 0}.
 */
public static double logBeta(final double p,final double q){
  if (Double.isNaN(p) || Double.isNaN(q) || (p <= 0.0)|| (q <= 0.0)) {
    return Double.NaN;
  }
  final double a=FastMath.min(p,q);
  final double b=FastMath.max(p,q);
  if (a >= 10.0) {
    final double w=sumDeltaMinusDeltaSum(a,b);
    final double h=a / b;
    final double c=h / (1.0 + h);
    final double u=-(a - 0.5) * FastMath.log(c);
    final double v=b * FastMath.log1p(h);
    if (u <= v) {
      return (((-0.5 * FastMath.log(b) + HALF_LOG_TWO_PI) + w) - u) - v;
    }
 else {
      return (((-0.5 * FastMath.log(b) + HALF_LOG_TWO_PI) + w) - v) - u;
    }
  }
 else   if (a > 2.0) {
    if (b > 1000.0) {
      final int n=(int)FastMath.floor(a - 1.0);
      double prod=1.0;
      double ared=a;
      for (int i=0; i < n; i++) {
        ared-=1.0;
        prod*=ared / (1.0 + ared / b);
      }
      return (FastMath.log(prod) - n * FastMath.log(b)) + (Gamma.logGamma(ared) + logGammaMinusLogGammaSum(ared,b));
    }
 else {
      double prod1=1.0;
      double ared=a;
      while (ared > 2.0) {
        ared-=1.0;
        final double h=ared / b;
        prod1*=h / (1.0 + h);
      }
      if (b < 10.0) {
        double prod2=1.0;
        double bred=b;
        while (bred > 2.0) {
          bred-=1.0;
          prod2*=bred / (ared + bred);
        }
        return FastMath.log(prod1) + FastMath.log(prod2) + (Gamma.logGamma(ared) + (Gamma.logGamma(bred) - logGammaSum(ared,bred)));
      }
 else {
        return FastMath.log(prod1) + Gamma.logGamma(ared) + logGammaMinusLogGammaSum(ared,b);
      }
    }
  }
 else   if (a >= 1.0) {
    if (b > 2.0) {
      if (b < 10.0) {
        double prod=1.0;
        double bred=b;
        while (bred > 2.0) {
          bred-=1.0;
          prod*=bred / (a + bred);
        }
        return FastMath.log(prod) + (Gamma.logGamma(a) + (Gamma.logGamma(bred) - logGammaSum(a,bred)));
      }
 else {
        return Gamma.logGamma(a) + logGammaMinusLogGammaSum(a,b);
      }
    }
 else {
      return Gamma.logGamma(a) + Gamma.logGamma(b) - logGammaSum(a,b);
    }
  }
 else {
    if (b >= 10.0) {
      return Gamma.logGamma(a) + logGammaMinusLogGammaSum(a,b);
    }
 else {
      return FastMath.log(Gamma.gamma(a) * Gamma.gamma(b) / Gamma.gamma(a + b));
    }
  }
}

Fixed version (ground truth):
/** 
 * Returns the value of   {@code log B(p, q)} for {@code 0 ≤ x ≤ 1} and {@code p, q > 0}. Based on the <em>NSWC Library of Mathematics Subroutines</em> implementation,  {@code DBETLN}.
 * @param p First argument.
 * @param q Second argument.
 * @return the value of {@code log(Beta(p, q))},   {@code NaN} if{@code p <= 0} or {@code q <= 0}.
 */
public static double logBeta(final double p,final double q){
  if (Double.isNaN(p) || Double.isNaN(q) || (p <= 0.0)|| (q <= 0.0)) {
    return Double.NaN;
  }
  final double a=FastMath.min(p,q);
  final double b=FastMath.max(p,q);
  if (a >= 10.0) {
    final double w=sumDeltaMinusDeltaSum(a,b);
    final double h=a / b;
    final double c=h / (1.0 + h);
    final double u=-(a - 0.5) * FastMath.log(c);
    final double v=b * FastMath.log1p(h);
    if (u <= v) {
      return (((-0.5 * FastMath.log(b) + HALF_LOG_TWO_PI) + w) - u) - v;
    }
 else {
      return (((-0.5 * FastMath.log(b) + HALF_LOG_TWO_PI) + w) - v) - u;
    }
  }
 else   if (a > 2.0) {
    if (b > 1000.0) {
      final int n=(int)FastMath.floor(a - 1.0);
      double prod=1.0;
      double ared=a;
      for (int i=0; i < n; i++) {
        ared-=1.0;
        prod*=ared / (1.0 + ared / b);
      }
      return (FastMath.log(prod) - n * FastMath.log(b)) + (Gamma.logGamma(ared) + logGammaMinusLogGammaSum(ared,b));
    }
 else {
      double prod1=1.0;
      double ared=a;
      while (ared > 2.0) {
        ared-=1.0;
        final double h=ared / b;
        prod1*=h / (1.0 + h);
      }
      if (b < 10.0) {
        double prod2=1.0;
        double bred=b;
        while (bred > 2.0) {
          bred-=1.0;
          prod2*=bred / (ared + bred);
        }
        return FastMath.log(prod1) + FastMath.log(prod2) + (Gamma.logGamma(ared) + (Gamma.logGamma(bred) - logGammaSum(ared,bred)));
      }
 else {
        return FastMath.log(prod1) + Gamma.logGamma(ared) + logGammaMinusLogGammaSum(ared,b);
      }
    }
  }
 else   if (a >= 1.0) {
    if (b > 2.0) {
      if (b < 10.0) {
        double prod=1.0;
        double bred=b;
        while (bred > 2.0) {
          bred-=1.0;
          prod*=bred / (a + bred);
        }
        return FastMath.log(prod) + (Gamma.logGamma(a) + (Gamma.logGamma(bred) - logGammaSum(a,bred)));
      }
 else {
        return Gamma.logGamma(a) + logGammaMinusLogGammaSum(a,b);
      }
    }
 else {
      return Gamma.logGamma(a) + Gamma.logGamma(b) - logGammaSum(a,b);
    }
  }
 else {
    if (b >= 10.0) {
      return Gamma.logGamma(a) + logGammaMinusLogGammaSum(a,b);
    }
 else {
      return FastMath.log(Gamma.gamma(a) * Gamma.gamma(b) / Gamma.gamma(a + b));
    }
  }
}