Source code for skypy.utils.special

"""Special functions.

This module computes useful special functions.

.. autosummary::
   :nosignatures:
   :toctree: ../api/

   gammaincc

"""

import numpy as np
import scipy.special as sc


def _gammaincc(a, x):
    '''gammaincc for positive or negative indices and scalar inputs'''
    if x < 0:
        raise ValueError('negative x in gammaincc')
    if x == 0:
        if a > 0:
            return 1
        s = sc.gammasgn(a)
        if s == 0:
            return 0
        return s*np.inf
    if np.isinf(x):
        return 0
    if a < 0:
        n = np.floor(a)
    else:
        n = 0
    g = sc.gammaincc(a-n, x) if a != n else 0
    if n < 0:
        f = np.exp(sc.xlogy(a-n, x)-x-sc.gammaln(a-n+1))
        while n < 0:
            f *= (a-n)/x
            g -= f
            n += 1
    return g


[docs]def gammaincc(a, x): r'''Regularized upper incomplete gamma function. This implementation of `gammaincc` allows :math:`a` real and :math:`x` nonnegative. Parameters ---------- a : array_like Real parameter. x : array_like Nonnegative argument. Returns ------- scalar or ndarray Values of the upper incomplete gamma function. Notes ----- The function value is computed via a recurrence from the value of `scipy.special.gammaincc` for arguments :math:`a-n, x` where :math:`n` is the smallest integer such that :math:`a-n \ge 0`. See also -------- scipy.special.gammaincc : Computes the start of the recurrence. ''' if np.broadcast(a, x).ndim == 0: return _gammaincc(a, x) a, x = np.broadcast_arrays(a, x) if np.any(x < 0): raise ValueError('negative x in gammaincc') # nonpositive a need special treatment i = a <= 0 # find integer n such that a + n >= 0 n = np.where(i, np.floor(a), 0) # compute gammaincc for a-n and x as usual g = np.where(a == n, 0, sc.gammaincc(a-n, x)) # deal with nonpositive a # the number n keeps track of iterations still to do if np.any(i): # all x = inf are done n[i & np.isinf(x)] = 0 # do x = 0 for nonpositive a; depends on Gamma(a) i = i & (x == 0) s = sc.gammasgn(a[i]) g[i] = np.where(s == 0, 0, np.copysign(np.inf, s)) n[i] = 0 # these are still to do i = n < 0 # recurrence f = np.empty_like(g) f[i] = np.exp(sc.xlogy(a[i]-n[i], x[i])-x[i]-sc.gammaln(a[i]-n[i]+1)) while np.any(i): f[i] *= (a[i]-n[i])/x[i] g[i] -= f[i] n[i] += 1 i[i] = n[i] < 0 return g