src/pgm_density.c
/*
 * Approximate the logarithm of the distribution function of PG(h, z).
 *
 * logsumexp is applied as an attempt to prevent underflow. The sum of
 * terms is truncated at `PGM_MAX_SERIES_TERMS` terms.
 *
 * Note: The first term of the sum is evaluated before the loop to avoid
 * redundancy.
 */
Approximate the logarithm of the distribution function of PG(h, z).
logsumexp is applied as an attempt to prevent underflow. The sum of
terms is truncated at `PGM_MAX_SERIES_TERMS` terms.

The first term of the sum is evaluated before the loop to avoid
redundancy.
Approximate the logarithm of the distribution function of PG ( h z ) . logsumexp is applied as an attempt to prevent underflow . The sum of terms is truncated at ` PGM_MAX_SERIES_TERMS ` terms . The first term of the sum is evaluated before the loop to avoid redundancy .
double
pgm_polyagamma_logcdf(double x, double h, double z)
{
    if (islessequal(x, 0.)) {
        return -INFINITY;
    }
    else if (isinf(x)) {
        return 0.;
    }
    z = fabs(z);
    double c, zn;
    logcdf_func_t logcdf;
    double lg = pgm_lgamma(h);
    struct cdf_args arg = {.a = h, .x = x, .z = z};
    if (z > 0.) {
        logcdf = invgauss_logcdf;
        c = h * log1p(exp(-z)) - lg;
        arg.s2x = sqrt(x);
        zn = z;
    }
    else {
        logcdf = invgamma_logcdf;
        c = h * PGM_LOG2 - lg;
        arg.s2x = sqrt(2. * x);
        zn = 0.;
    }
    double first = lg + logcdf(&arg);
    double sum = 1.;
    double sign = -1.;
    for (unsigned int n = 1; n < PGM_MAX_SERIES_TERMS; n++, sign = -sign, zn = z * n) {
        arg.a = 2 * n + h;
        double curr = pgm_lgamma(n + h) + logcdf(&arg) - pgm_lgamma(n + 1) - zn;
        sum += sign * exp(curr - first);
    }
    return c + (first + log(sum));
}
double pgm_polyagamma_logcdf ( double x , double h , double z ) { if ( islessequal ( x , 0. ) ) { return - INFINITY ; } else if ( isinf ( x ) ) { return 0. ; } z = fabs ( z ) ; double c , zn ; logcdf_func_t logcdf ; double lg = pgm_lgamma ( h ) ; struct cdf_args arg = { . a = h , . x = x , . z = z } ; if ( z > 0. ) { logcdf = invgauss_logcdf ; c = h * log1p ( exp ( - z ) ) - lg ; arg . s2x = sqrt ( x ) ; zn = z ; } else { logcdf = invgamma_logcdf ; c = h * PGM_LOG2 - lg ; arg . s2x = sqrt ( 2. * x ) ; zn = 0. ; } double first = lg + logcdf ( & arg ) ; double sum = 1. ; double sign = -1. ; for ( unsigned int n = 1 ; n < PGM_MAX_SERIES_TERMS ; n ++ , sign = - sign , zn = z * n ) { arg . a = 2 * n + h ; double curr = pgm_lgamma ( n + h ) + logcdf ( & arg ) - pgm_lgamma ( n + 1 ) - zn ; sum += sign * exp ( curr - first ) ; } return c + ( first + log ( sum ) ) ; }
Approximate the logarithm of the distribution function of PG(h, z).
Approximate the logarithm of the distribution function of PG ( h z ) .