Example #1
0
def ibincoeff(n, k, integer=True):
    """
    Computation of a single binomial coefficient n over k, returning an 
    integer (possibly long). For integer=True integer arithmetics is used 
    throughout and there is no risk of overflow. For integer=False a floating- 
    point gamma function approximation is used and the result converted to 
    integer at the end (if an overflow occurs ERRCODE is returned). 
    """

    assert is_posinteger(n), \
               "n in n_over_k in ibincoeff must be a positive integer!"
    assert is_nonneginteger(k), \
           "k in n_over_k in ibincoeff must be a non-negative integer!"
    assert n >= k, "n must be >= k in n_over_k in ibincoeff!"

    if integer:
        ibico = _bicolongint(n, k)

    else:
        try:
            lnbico = lngamma(n + 1) - lngamma(k + 1) - lngamma(n - k + 1)
            ibico = safeint(round(exp(lnbico)), 'ibincoeff')
        except OverflowError:
            ibico = ERRCODE

    return ibico
Example #2
0
def fbincoeff(n, k, integer=True):
    """
    Computation of a single binomial coefficient n over k, returning a float 
    (an OverflowError returns float('inf'), which would occur for n > 1029 
    for IEEE754 floating-point standard). 
    """

    assert is_posinteger(n), \
               "n in n_over_k in fbincoeff must be a positive integer!"
    assert is_nonneginteger(k), \
           "k in n_over_k in fbincoeff must be a non-negative integer!"
    assert n >= k, "n must be >= k in n_over_k in fbincoeff!"

    if integer:
        bico = _bicolongint(n, k)
        try:
            fbico = round(float(bico))
        except OverflowError:
            fbico = float('inf')

    else:
        try:
            lnbico = lngamma(n + 1) - lngamma(k + 1) - lngamma(n - k + 1)
            fbico = round(exp(lnbico))
        except OverflowError:
            fbico = float('inf')

    return fbico
Example #3
0
def ibincoeff(n, k, integer=True):
    """
    Computation of a single binomial coefficient n over k, returning an 
    integer (possibly long). For integer=True integer arithmetics is used 
    throughout and there is no risk of overflow. For integer=False a floating- 
    point gamma function approximation is used and the result converted to 
    integer at the end (if an overflow occurs ERRCODE is returned). 
    """

    assert is_posinteger(n), \
               "n in n_over_k in ibincoeff must be a positive integer!"
    assert is_nonneginteger(k), \
           "k in n_over_k in ibincoeff must be a non-negative integer!"
    assert n >= k, "n must be >= k in n_over_k in ibincoeff!"

    if integer:
        ibico = _bicolongint(n, k)

    else:
        try:
            lnbico  =  lngamma(n+1) - lngamma(k+1) - lngamma(n-k+1)
            ibico   =  safeint(round(exp(lnbico)), 'ibincoeff')
        except OverflowError:
            ibico   =  ERRCODE

    return ibico
Example #4
0
def fbincoeff(n, k, integer=True):
    """
    Computation of a single binomial coefficient n over k, returning a float 
    (an OverflowError returns float('inf'), which would occur for n > 1029 
    for IEEE754 floating-point standard). 
    """

    assert is_posinteger(n), \
               "n in n_over_k in fbincoeff must be a positive integer!"
    assert is_nonneginteger(k), \
           "k in n_over_k in fbincoeff must be a non-negative integer!"
    assert n >= k, "n must be >= k in n_over_k in fbincoeff!"

    if integer:
        bico = _bicolongint(n, k)
        try:
            fbico = round(float(bico))
        except OverflowError:
            fbico = float('inf')

    else:
        try:
            lnbico  =  lngamma(n+1) - lngamma(k+1) - lngamma(n-k+1)
            fbico   =  round(exp(lnbico))
        except OverflowError:
            fbico   =  float('inf')

    return fbico
Example #5
0
def dexppower(loc, scale, alpha, x, lngam1oalpha=False):
    """
    The exponential power distribution 
    f  =  (a/s) * exp(-abs([x-l]/s)**a) / [2*gamma(1/a)]
    F  =  1/2 * [1 + sgn(x-l) * Fgamma(1/a, abs([x-l]/s)**a)],   x in R
    s, a > 0
    where Fgamma is the gamma distribution cdf.

    NB It is possible to gain efficiency by providing the value of the 
    natural logarithm of the complete gamma function ln(gamma(1.0/alpha)) 
    as a pre-computed input (may be computed using numlib.specfunc.lngamma) 
    instead of the default 'False'.
    """

    assert scale > 0.0, \
               "scale parameter must be a positive float in dexppower!"
    assert alpha > 0.0, \
            "shape parameter alpha must be a positive float in dexppower!"

    if alpha == 1.0: return dlaplace(loc, scale, x)

    sinv = 1.0/float(scale)

    aux1 = - (sinv*abs(x-loc)) ** alpha
    if not lngam1oalpha: aux2 = lngamma(1.0/float(alpha))
    else:                aux2 = lngam1oalpha

    pdf  =  0.5*sinv*alpha * exp(aux1-aux2)   # Will always be >= 0

    return pdf
Example #6
0
def cexppower(loc, scale, alpha, x, lngam1oalpha=False, \
                                    tolf=FOURMACHEPS, itmax=128):
    """
    The exponential power distribution 
    f  =  (a/s) * exp(-abs([x-l]/s)**a) / [2*gamma(1/a)]
    F  =  1/2 * [1 + sgn(x-l) * Fgamma(1/a, abs([x-l]/s)**a)],   x in R
    s, a > 0
    where Fgamma is the gamma distribution cdf.

    NB It is possible to gain efficiency by providing the value of the 
    natural logarithm of the complete gamma function ln(gamma(1.0/alpha)) 
    as a pre-computed input (may be computed using numlib.specfunc.lngamma) 
    instead of the default 'False'.

    tolf and itmax are the numerical control parameters of cgamma.
    """

    assert scale > 0.0, \
               "scale parameter must be a positive float in cexppower!"
    assert alpha > 0.0, \
            "shape parameter alpha must be a positive float in cexppower!"

    if alpha == 1.0: return claplace(loc, scale, x)

    ainv = 1.0 / alpha
    xml = x - loc

    if not lngam1oalpha: lng1oa = lngamma(ainv)
    else: lng1oa = lngam1oalpha
    cg = cgamma(ainv, 1.0, abs(xml / scale)**alpha, lng1oa, tolf, itmax)
    cdf = 0.5 * (fsign(xml) * cg + 1.0)

    cdf = kept_within(0.0, cdf, 1.0)

    return cdf
Example #7
0
def cexppower(loc, scale, alpha, x, lngam1oalpha=False, tolf=FOURMACHEPS, itmax=128):
    """
    The exponential power distribution 
    f  =  (a/s) * exp(-abs([x-l]/s)**a) / [2*gamma(1/a)]
    F  =  1/2 * [1 + sgn(x-l) * Fgamma(1/a, abs([x-l]/s)**a)],   x in R
    s, a > 0
    where Fgamma is the gamma distribution cdf.

    NB It is possible to gain efficiency by providing the value of the 
    natural logarithm of the complete gamma function ln(gamma(1.0/alpha)) 
    as a pre-computed input (may be computed using numlib.specfunc.lngamma) 
    instead of the default 'False'.

    tolf and itmax are the numerical control parameters of cgamma.
    """

    assert scale > 0.0, "scale parameter must be a positive float in cexppower!"
    assert alpha > 0.0, "shape parameter alpha must be a positive float in cexppower!"

    if alpha == 1.0:
        return claplace(loc, scale, x)

    ainv = 1.0 / alpha
    xml = x - loc

    if not lngam1oalpha:
        lng1oa = lngamma(ainv)
    else:
        lng1oa = lngam1oalpha
    cg = cgamma(ainv, 1.0, abs(xml / scale) ** alpha, lng1oa, tolf, itmax)
    cdf = 0.5 * (fsign(xml) * cg + 1.0)

    cdf = kept_within(0.0, cdf, 1.0)

    return cdf
Example #8
0
def _stable_sym_tail(alpha, x):
    """
    An asymptotic expression for the tail.
    """

    # calpha = exp(lngamma(alpha)) * sin(PIHALF*alpha) / PI
    calpha = PIINV * exp(lngamma(alpha)) * sin(PIHALF * alpha)

    try:
        cdf = calpha / x ** alpha

    except ZeroDivisionError:
        cdf = log(calpha) - alpha * log(x)
        try:
            cdf = exp(cdf)
        except OverflowError:
            cdf = 0.0

    except OverflowError:
        cdf = log(calpha) - alpha * log(x)
        try:
            cdf = exp(cdf)
        except OverflowError:
            cdf = 0.0

    cdf = 1.0 - cdf

    cdf = kept_within(0.5, cdf, 1.0)
    return cdf
Example #9
0
def dexppower(loc, scale, alpha, x, lngam1oalpha=False):
    """
    The exponential power distribution 
    f  =  (a/s) * exp(-abs([x-l]/s)**a) / [2*gamma(1/a)]
    F  =  1/2 * [1 + sgn(x-l) * Fgamma(1/a, abs([x-l]/s)**a)],   x in R
    s, a > 0
    where Fgamma is the gamma distribution cdf.

    NB It is possible to gain efficiency by providing the value of the 
    natural logarithm of the complete gamma function ln(gamma(1.0/alpha)) 
    as a pre-computed input (may be computed using numlib.specfunc.lngamma) 
    instead of the default 'False'.
    """

    assert scale > 0.0, \
               "scale parameter must be a positive float in dexppower!"
    assert alpha > 0.0, \
            "shape parameter alpha must be a positive float in dexppower!"

    if alpha == 1.0: return dlaplace(loc, scale, x)

    sinv = 1.0 / float(scale)

    aux1 = -(sinv * abs(x - loc))**alpha
    if not lngam1oalpha: aux2 = lngamma(1.0 / float(alpha))
    else: aux2 = lngam1oalpha

    pdf = 0.5 * sinv * alpha * exp(aux1 - aux2)  # Will always be >= 0

    return pdf
Example #10
0
def _stable_sym_tail(alpha, x):
    """
    An asymptotic expression for the tail.
    """

    #calpha = exp(lngamma(alpha)) * sin(PIHALF*alpha) / PI
    calpha = PIINV * exp(lngamma(alpha)) * sin(PIHALF * alpha)

    try:
        cdf = calpha / x**alpha

    except ZeroDivisionError:
        cdf = log(calpha) - alpha * log(x)
        try:
            cdf = exp(cdf)
        except OverflowError:
            cdf = 0.0

    except OverflowError:
        cdf = log(calpha) - alpha * log(x)
        try:
            cdf = exp(cdf)
        except OverflowError:
            cdf = 0.0

    cdf = 1.0 - cdf

    cdf = kept_within(0.5, cdf, 1.0)
    return cdf
Example #11
0
def lnbincoeff(n, k, integer=True):
    """
    Computation of the natural logarithm of a single binomial coefficient 
    n over k
    """

    assert is_posinteger(n), \
               "n in n_over_k in lnbincoeff must be a positive integer!"
    assert is_nonneginteger(k), \
           "k in n_over_k in lnbincoeff must be a non-negative integer!"
    assert n >= k, "n must be >= k in n_over_k in lnbincoeff!"

    if integer:
        bico    =  _bicolongint(n, k)
        lnbico  =  log(bico)

    else:
        lnbico  =  lngamma(n+1) - lngamma(k+1) - lngamma(n-k+1)

    return lnbico
Example #12
0
def lnbincoeff(n, k, integer=True):
    """
    Computation of the natural logarithm of a single binomial coefficient 
    n over k
    """

    assert is_posinteger(n), \
               "n in n_over_k in lnbincoeff must be a positive integer!"
    assert is_nonneginteger(k), \
           "k in n_over_k in lnbincoeff must be a non-negative integer!"
    assert n >= k, "n must be >= k in n_over_k in lnbincoeff!"

    if integer:
        bico = _bicolongint(n, k)
        lnbico = log(bico)

    else:
        lnbico = lngamma(n + 1) - lngamma(k + 1) - lngamma(n - k + 1)

    return lnbico
Example #13
0
def _dstable_sym_small(alpha, x, tolr):
    """
    A series expansion for small x due to Bergstrom. 
    Converges for x < 1.0 and in practice also for 
    somewhat larger x. 
    
    The function uses the Kahan summation procedure 
    (cf. Dahlquist, Bjorck & Anderson). 
    """

    summ   =  0.0
    c      =  0.0
    fact   = -1.0
    xx     =  x*x
    xpart  =  1.0
    k      =   0
    zero2  =  zero1  =  False
    while True:
        k       +=  1
        summo    =  summ
        twokm1   =  2*k - 1
        twokm1oa =  float(twokm1)/alpha
        r        =  lngamma(twokm1oa) - lnfactorial(twokm1)
        term     =  twokm1 * exp(r) * xpart
        fact     = - fact
        term    *=  fact
        y        =  term + c
        t        =  summ + y
        if fsign(y) == fsign(summ):
            f = (0.46*t-t) + t
            c = ((summ-f)-(t-f)) + y
        else:
            c = (summ-t) + y
        summ     =  t
        if abs(summ-summo) < tolr*abs(summ) and abs(term) < tolr and zero2:
            break
        xpart *=  xx
        if abs(term) < tolr:
            if zero1: zero2 = True
            else:     zero1 = True
    summ +=  c
    pdf   =  summ / (PI*alpha)

    pdf   =  kept_within(0.0, pdf)
    return pdf
Example #14
0
def _dstable_sym_small(alpha, x, tolr):
    """
    A series expansion for small x due to Bergstrom. 
    Converges for x < 1.0 and in practice also for 
    somewhat larger x. 
    
    The function uses the Kahan summation procedure 
    (cf. Dahlquist, Bjorck & Anderson). 
    """

    summ = 0.0
    c = 0.0
    fact = -1.0
    xx = x * x
    xpart = 1.0
    k = 0
    zero2 = zero1 = False
    while True:
        k += 1
        summo = summ
        twokm1 = 2 * k - 1
        twokm1oa = float(twokm1) / alpha
        r = lngamma(twokm1oa) - lnfactorial(twokm1)
        term = twokm1 * exp(r) * xpart
        fact = -fact
        term *= fact
        y = term + c
        t = summ + y
        if fsign(y) == fsign(summ):
            f = (0.46 * t - t) + t
            c = ((summ - f) - (t - f)) + y
        else:
            c = (summ - t) + y
        summ = t
        if abs(summ - summo) < tolr * abs(summ) and abs(term) < tolr and zero2:
            break
        xpart *= xx
        if abs(term) < tolr:
            if zero1: zero2 = True
            else: zero1 = True
    summ += c
    pdf = summ / (PI * alpha)

    pdf = kept_within(0.0, pdf)
    return pdf
Example #15
0
def dpoisson(lam, tspan, n):
    """
    The Poisson distribution: p(N=n) = exp(-lam*tspan) * (lam*tspan)**n / n!
    n = 0, 1,...., inf
    """

    # Input check -----------
    assert  lam  >= 0.0, "Poisson rate must not be negative in dpoisson!"
    assert tspan >= 0.0, "time span must not be negative in dpoisson!"
    assert is_nonneginteger(n), \
                " must be a non-negative integer in dpoisson!"
    # -----------------------

    lamtau = lam*tspan
    ln  =  lamtau + lngamma(n+1) - n*log(lamtau)
    ln  =  kept_within(0.0, ln)
    pdf =  exp(-ln)    # Will always be >= 0.0

    return pdf
Example #16
0
def dpoisson(lam, tspan, n):
    """
    The Poisson distribution: p(N=n) = exp(-lam*tspan) * (lam*tspan)**n / n!
    n = 0, 1,...., inf
    """

    # Input check -----------
    assert lam >= 0.0, "Poisson rate must not be negative in dpoisson!"
    assert tspan >= 0.0, "time span must not be negative in dpoisson!"
    assert is_nonneginteger(n), \
                " must be a non-negative integer in dpoisson!"
    # -----------------------

    lamtau = lam * tspan
    ln = lamtau + lngamma(n + 1) - n * log(lamtau)
    ln = kept_within(0.0, ln)
    pdf = exp(-ln)  # Will always be >= 0.0

    return pdf
Example #17
0
def _dstable_sym_big(alpha, x, tolr):
    """
    A series expansion for large x due to Bergstrom. 
    Converges for x > 1.0
    
    The function uses the Kahan summation procedure 
    (cf. Dahlquist, Bjorck & Anderson). 
    """

    summ = 0.0
    c = 0.0
    fact = 1.0
    k = 0
    zero2 = zero1 = False
    while True:
        k += 1
        summo = summ
        ak = alpha * k
        akh = 0.5 * ak
        r = lngamma(ak) - lnfactorial(k)
        term = -ak * exp(r) * sin(PIHALF * ak) / pow(x, ak + 1)
        fact = -fact
        term *= fact
        y = term + c
        t = summ + y
        if fsign(y) == fsign(summ):
            f = (0.46 * t - t) + t
            c = ((summ - f) - (t - f)) + y
        else:
            c = (summ - t) + y
        summ = t
        if abs(summ - summo) < tolr * abs(summ) and abs(term) < tolr and zero2:
            break
        if abs(term) < tolr:
            if zero1: zero2 = True
            else: zero1 = True
    summ += c
    #pdf   =  summ / PI
    pdf = PIINV * summ

    pdf = kept_within(0.0, pdf)
    return pdf
Example #18
0
def _dstable_sym_big(alpha, x, tolr):
    """
    A series expansion for large x due to Bergstrom. 
    Converges for x > 1.0
    
    The function uses the Kahan summation procedure 
    (cf. Dahlquist, Bjorck & Anderson). 
    """

    summ  = 0.0
    c     = 0.0
    fact  = 1.0
    k     =  0
    zero2 = zero1 = False
    while True:
        k     +=  1
        summo  =  summ
        ak     =  alpha * k
        akh    =  0.5 * ak
        r      =  lngamma(ak) - lnfactorial(k)
        term   = - ak * exp(r) * sin(PIHALF*ak) / pow(x, ak+1)
        fact   = - fact
        term  *=  fact
        y      =  term + c
        t      =  summ + y
        if fsign(y) == fsign(summ):
            f = (0.46*t-t) + t
            c = ((summ-f)-(t-f)) + y
        else:
            c = (summ-t) + y
        summ   =  t
        if abs(summ-summo) < tolr*abs(summ) and abs(term) < tolr and zero2:
            break
        if abs(term) < tolr:
            if zero1: zero2 = True
            else:     zero1 = True
    summ +=  c
    #pdf   =  summ / PI
    pdf   =  PIINV * summ

    pdf   =  kept_within(0.0, pdf)
    return pdf
Example #19
0
def dgamma(alpha, lam, x, lngamalpha=False):
    """
    The gamma distrib. f = lam * exp(-lam*x) * (lam*x)**(alpha-1) / gamma(alpha)
    F is the integral = the incomplete gamma or the incomplete gamma / complete 
    gamma depending on how the incomplete gamma function is defined.
    x, lam, alpha >= 0
    
    NB It is possible to gain efficiency by providing the value of the 
    natural logarithm of the complete gamma function ln(gamma(alpha)) 
    as a pre-computed input (may be computed using numlib.specfunc.lngamma) 
    instead of the default 'False'.

    NB  dgamma may return float('inf') for alpha < 1.0!
    """

    assert alpha >= 0.0, "alpha must not be negative in dgamma!"
    assert lam >= 0.0, "lambda must not be negative i dgamma!"
    assert x >= 0.0, "variate must not be negative in dgamma!"

    lamx = lam * x
    if lngamalpha: lga = lngamalpha
    else: lga = lngamma(alpha)

    if alpha < 1.0:
        if lamx == 0.0:
            pdf = float('inf')
        else:
            alpham1 = alpha - 1.0
            try:
                pdf = lam * exp(-lamx - lga) / pow(lamx, -alpham1)
            except OverflowError:
                pdf = lam * exp(-lamx + alpham1 * log(lamx) - lga)

    else:
        alpham1 = alpha - 1.0
        try:
            pdf = lam * exp(-lamx - lga) * pow(lamx, alpham1)
        except OverflowError:
            pdf = lam * exp(-lamx + alpham1 * log(lamx) - lga)

    return pdf  # Will always be >= 0.0
Example #20
0
def dgamma(alpha, lam, x, lngamalpha=False):
    """
    The gamma distrib. f = lam * exp(-lam*x) * (lam*x)**(alpha-1) / gamma(alpha)
    F is the integral = the incomplete gamma or the incomplete gamma / complete 
    gamma depending on how the incomplete gamma function is defined.
    x, lam, alpha >= 0
    
    NB It is possible to gain efficiency by providing the value of the 
    natural logarithm of the complete gamma function ln(gamma(alpha)) 
    as a pre-computed input (may be computed using numlib.specfunc.lngamma) 
    instead of the default 'False'.

    NB  dgamma may return float('inf') for alpha < 1.0!
    """

    assert alpha >= 0.0, "alpha must not be negative in dgamma!"
    assert  lam  >= 0.0, "lambda must not be negative i dgamma!"
    assert   x   >= 0.0, "variate must not be negative in dgamma!"

    lamx  = lam * x
    if lngamalpha: lga = lngamalpha
    else:          lga = lngamma(alpha)

    if alpha < 1.0:
        if lamx == 0.0:
            pdf  = float('inf')
        else:
            alpham1 = alpha - 1.0
            try:
                pdf  = lam * exp(-lamx-lga) / pow(lamx, -alpham1)
            except OverflowError:
                pdf  = lam * exp(-lamx + alpham1*log(lamx) - lga)

    else:
        alpham1 = alpha - 1.0
        try:                  pdf  = lam * exp(-lamx-lga) * pow(lamx, alpham1)
        except OverflowError: pdf  = lam * exp(-lamx + alpham1*log(lamx) - lga)

    return pdf    # Will always be >= 0.0
Example #21
0
def cgamma(alpha, lam, x, lngamalpha=False, tolf=FOURMACHEPS, itmax=128):
    """
    The gamma distrib. f = lam * exp(-lam*x) * (lam*x)**(alpha-1) / gamma(alpha)
    F is the integral = the incomplete gamma or the incomplete gamma / complete 
    gamma depending on how the incomplete gamma function is defined.
    x, lam, alpha >= 0
    tolf  =  allowed fractional error in computation of the incomplete function
    itmax =  maximum number of iterations to obtain accuracy 

    NB It is possible to gain efficiency by providing the value of the 
    natural logarithm of the complete gamma function ln(gamma(alpha)) 
    as a pre-computed input (may be computed using numlib.specfunc.lngamma) 
    instead of the default 'False'.
    """

    assert alpha >= 0.0, "alpha must not be negative in cgamma!"
    assert lam >= 0.0, "lambda must not be negative i cgamma!"
    assert x >= 0.0, "variate must not be negative in cgamma!"
    assert tolf >= 0.0, "tolerance must not be negative in cgamma!"
    assert is_posinteger(itmax), \
           "maximum number of iterations must be a positive integer in cgamma!"

    if alpha == 1.0: return cexpo(1.0 / lam, x)

    lamx = lam * x
    if lamx == 0.0: return 0.0
    if lngamalpha: lnga = lngamalpha
    else: lnga = lngamma(alpha)

    # -------------------------------------------------------------------------
    def _gamser():
        # A series expansion is used for lamx < alpha + 1.0
        # (cf. Abramowitz & Stegun)
        apn = alpha
        summ = 1.0 / apn
        dela = summ
        converged = False
        for k in range(0, itmax):
            apn += 1.0
            dela = dela * lamx / apn
            summ += dela
            if abs(dela) < abs(summ) * tolf:
                converged = True
                return summ * exp(-lamx + alpha * log(lamx) - lnga), converged
        return summ * exp(-lamx + alpha * log(lamx) - lnga), converged

    # -------------------------------------------------------------------------
    def _gamcf():
        # A continued fraction expansion is used for
        # lamx >= alpha + 1.0 (cf. Abramowitz & Stegun):
        gold = 0.0
        a0 = 1.0
        a1 = lamx
        b0 = 0.0
        b1 = 1.0
        fac = 1.0
        converged = False
        for k in range(0, itmax):
            ak = float(k + 1)
            aka = ak - alpha
            a0 = (a1 + a0 * aka) * fac
            b0 = (b1 + b0 * aka) * fac
            akf = ak * fac
            a1 = lamx * a0 + akf * a1
            b1 = lamx * b0 + akf * b1
            if a1 != 0.0:
                fac = 1.0 / a1
                g = b1 * fac
                if abs(g - gold) < abs(g) * tolf:
                    converged = True
                    return 1.0 - exp(-lamx + alpha * log(lamx) -
                                     lnga) * g, converged
                gold = g
        return 1.0 - exp(-lamx + alpha * log(lamx) - lnga) * g, converged

    # -------------------------------------------------------------------------

    if lamx < alpha + 1.0:
        cdf, converged = _gamser()
    else:
        cdf, converged = _gamcf()

    if not converged:
        warn("cgamma has not converged for itmax = " + \
                     str(itmax) + " and tolf = " + str(tolf))

    cdf = kept_within(0.0, cdf, 1.0)

    return cdf
Example #22
0
def cgamma(alpha, lam, x, lngamalpha=False, tolf=FOURMACHEPS, itmax=128):
    """
    The gamma distrib. f = lam * exp(-lam*x) * (lam*x)**(alpha-1) / gamma(alpha)
    F is the integral = the incomplete gamma or the incomplete gamma / complete 
    gamma depending on how the incomplete gamma function is defined.
    x, lam, alpha >= 0
    tolf  =  allowed fractional error in computation of the incomplete function
    itmax =  maximum number of iterations to obtain accuracy 

    NB It is possible to gain efficiency by providing the value of the 
    natural logarithm of the complete gamma function ln(gamma(alpha)) 
    as a pre-computed input (may be computed using numlib.specfunc.lngamma) 
    instead of the default 'False'.
    """

    assert alpha >= 0.0, "alpha must not be negative in cgamma!"
    assert lam >= 0.0, "lambda must not be negative i cgamma!"
    assert x >= 0.0, "variate must not be negative in cgamma!"
    assert tolf >= 0.0, "tolerance must not be negative in cgamma!"
    assert is_posinteger(itmax), "maximum number of iterations must be a positive integer in cgamma!"

    if alpha == 1.0:
        return cexpo(1.0 / lam, x)

    lamx = lam * x
    if lamx == 0.0:
        return 0.0
    if lngamalpha:
        lnga = lngamalpha
    else:
        lnga = lngamma(alpha)

    # -------------------------------------------------------------------------
    def _gamser():
        # A series expansion is used for lamx < alpha + 1.0
        # (cf. Abramowitz & Stegun)
        apn = alpha
        summ = 1.0 / apn
        dela = summ
        converged = False
        for k in range(0, itmax):
            apn += 1.0
            dela = dela * lamx / apn
            summ += dela
            if abs(dela) < abs(summ) * tolf:
                converged = True
                return summ * exp(-lamx + alpha * log(lamx) - lnga), converged
        return summ * exp(-lamx + alpha * log(lamx) - lnga), converged

    # -------------------------------------------------------------------------
    def _gamcf():
        # A continued fraction expansion is used for
        # lamx >= alpha + 1.0 (cf. Abramowitz & Stegun):
        gold = 0.0
        a0 = 1.0
        a1 = lamx
        b0 = 0.0
        b1 = 1.0
        fac = 1.0
        converged = False
        for k in range(0, itmax):
            ak = float(k + 1)
            aka = ak - alpha
            a0 = (a1 + a0 * aka) * fac
            b0 = (b1 + b0 * aka) * fac
            akf = ak * fac
            a1 = lamx * a0 + akf * a1
            b1 = lamx * b0 + akf * b1
            if a1 != 0.0:
                fac = 1.0 / a1
                g = b1 * fac
                if abs(g - gold) < abs(g) * tolf:
                    converged = True
                    return 1.0 - exp(-lamx + alpha * log(lamx) - lnga) * g, converged
                gold = g
        return 1.0 - exp(-lamx + alpha * log(lamx) - lnga) * g, converged

    # -------------------------------------------------------------------------

    if lamx < alpha + 1.0:
        cdf, converged = _gamser()
    else:
        cdf, converged = _gamcf()

    if not converged:
        warn("cgamma has not converged for itmax = " + str(itmax) + " and tolf = " + str(tolf))

    cdf = kept_within(0.0, cdf, 1.0)

    return cdf
Example #23
0
def dstable_sym(alpha, location, scale, x):
    """
    The pdf of a SYMMETRICAL stable distribution where alpha is the tail 
    exponent. For numerical reasons alpha is restricted to [0.1, 0.9] and 
    [1.125, 1.9] - but alpha = 1.0 (the Cauchy) and alpha = 2.0 (scaled 
    normal) are also allowed!

    Numerics are somewhat crude but the fractional error is mostly < 0.001 - 
    sometimes much less - and the absolute error is almost always < 0.001 - 
    sometimes much less... 

    NB This function is somewhat slow, particularly for small alpha !!!!!
    """

    # NB Do not change the numerical parameters - they are matched! The
    # corresponding cdf function cstable_sym is partly based on this
    # function so changes in one of them are likely to require changes
    # in the others!

    assert 0.1 <= alpha and alpha <= 2.0,  \
                           "alpha must be in [0.1, 2.0] in dstable_sym!"
    if alpha < 1.0:        assert alpha <= 0.9,   \
               "alpha <= 1.0 must be <= 0.9 in dstable_sym!"
    if alpha > 1.0:        assert alpha >= 1.125, \
              "alpha > 1.0 must be >= 1.125 in dstable_sym!"
    if alpha > 1.9:        assert alpha == 2.0,   \
                 "alpha > 1.9 must be = 2.0 in dstable_sym!"
    assert scale > 0.0, "scale must be a positive float in dstable_sym!"

    if alpha == 1.0: return dcauchy(location, scale, x)
    if alpha == 2.0: return dnormal(location, SQRT2 * scale, x)

    x = (x - location) / float(scale)
    x = abs(x)

    # Compute the value at the peak/mode (for x = 0) for later use:
    #peak = exp(lngamma(1.0+1.0/alpha)) / PI
    peak = PIINV * exp(lngamma(1.0 + 1.0 / alpha))

    if alpha < 1.0:
        # For sufficiently small abs(x) the value at the peak is used
        # (heuristically; based on experimentation). For x >= 1.0 the
        # series expansion for large x due to Bergstrom is used. For x
        # "in between" the integral formulation is used:
        if alpha <= 0.25:
            point = 0.5**37
        else:
            point = 1.25 * pow(10.0, -4.449612602 + 3.078368893 * alpha)
        if x <= point:
            pdf = peak
        elif x >= 1.0:
            pdf = _dstable_sym_big(alpha, x, MACHEPS)
        else:
            pdf = _dstable_sym_int(alpha, x, 0.5**17, 17)

    elif alpha > 1.0:
        # For sufficiently small abs(x) the series expansion for small x due
        # to Bergstrom is used. For x sufficiently large x an asymptotic
        # expression is used. For x "in between" the integral formulation
        # is used (all limits heuristically based):
        y1 = -2.212502985 + alpha * (3.03077875081 - alpha * 0.742811132)
        if x <= pow(10.0, y1):
            pdf = _dstable_sym_small(alpha, x, MACHEPS)
        else:
            pdf = _dstable_sym_int(alpha, x, 0.5**19, 21)

    pdf = kept_within(0.0, pdf, peak)
    return pdf
Example #24
0
def dstable_sym(alpha, location, scale, x):
    """
    The pdf of a SYMMETRICAL stable distribution where alpha is the tail 
    exponent. For numerical reasons alpha is restricted to [0.1, 0.9] and 
    [1.125, 1.9] - but alpha = 1.0 (the Cauchy) and alpha = 2.0 (scaled 
    normal) are also allowed!

    Numerics are somewhat crude but the fractional error is mostly < 0.001 - 
    sometimes much less - and the absolute error is almost always < 0.001 - 
    sometimes much less... 

    NB This function is somewhat slow, particularly for small alpha !!!!!
    """

    # NB Do not change the numerical parameters - they are matched! The 
    # corresponding cdf function cstable_sym is partly based on this 
    # function so changes in one of them are likely to require changes 
    # in the others!

    assert 0.1 <= alpha and alpha <= 2.0,  \
                           "alpha must be in [0.1, 2.0] in dstable_sym!"
    if alpha < 1.0: assert alpha <= 0.9,   \
                           "alpha <= 1.0 must be <= 0.9 in dstable_sym!"
    if alpha > 1.0: assert alpha >= 1.125, \
                          "alpha > 1.0 must be >= 1.125 in dstable_sym!"
    if alpha > 1.9: assert alpha == 2.0,   \
                             "alpha > 1.9 must be = 2.0 in dstable_sym!"
    assert scale > 0.0, "scale must be a positive float in dstable_sym!"

    if alpha == 1.0: return dcauchy(location, scale, x)
    if alpha == 2.0: return dnormal(location, SQRT2*scale, x)

    x  =  (x-location) / float(scale)
    x  =  abs(x)

    # Compute the value at the peak/mode (for x = 0) for later use:
    #peak = exp(lngamma(1.0+1.0/alpha)) / PI
    peak = PIINV * exp(lngamma(1.0+1.0/alpha))

    if alpha < 1.0:
        # For sufficiently small abs(x) the value at the peak is used 
        # (heuristically; based on experimentation). For x >= 1.0 the 
        # series expansion for large x due to Bergstrom is used. For x 
        # "in between" the integral formulation is used:
        if alpha <= 0.25:
            point = 0.5**37
        else:
            point = 1.25 * pow(10.0, -4.449612602 + 3.078368893*alpha)
        if x <= point:
            pdf = peak
        elif x >= 1.0:
            pdf = _dstable_sym_big(alpha, x, MACHEPS)
        else:
            pdf = _dstable_sym_int(alpha, x, 0.5**17, 17)

    elif alpha > 1.0:
        # For sufficiently small abs(x) the series expansion for small x due 
        # to Bergstrom is used. For x sufficiently large x an asymptotic 
        # expression is used. For x "in between" the integral formulation 
        # is used (all limits heuristically based):
        y1 = -2.212502985 + alpha*(3.03077875081 - alpha*0.742811132)
        if x <= pow(10.0, y1):
            pdf = _dstable_sym_small(alpha, x, MACHEPS)
        else:
            pdf = _dstable_sym_int(alpha, x, 0.5**19, 21)

    pdf = kept_within(0.0, pdf, peak)
    return pdf