def eval(cls, a, x): if a.is_Number: # TODO this should be non-recursive if a is S.One: return S.One - C.exp(-x) elif a is S.Half: return sqrt(pi) * erf(sqrt(x)) elif a.is_Integer or (2 * a).is_Integer: b = a - 1 if b.is_positive: return b * cls(b, x) - x**b * C.exp(-x) if not a.is_Integer: return (cls(a + 1, x) + x**a * C.exp(-x)) / a
def eval(cls, a, x): if a.is_Number: # TODO this should be non-recursive if a is S.One: return S.One - C.exp(-x) elif a is S.Half: return sqrt(pi) * erf(sqrt(x)) elif a.is_Integer or (2 * a).is_Integer: b = a - 1 if b.is_positive: return b * cls(b, x) - x ** b * C.exp(-x) if not a.is_Integer: return (cls(a + 1, x) + x ** a * C.exp(-x)) / a
def eval(cls, a, x): # For lack of a better place, we use this one to extract branching # information. The following can be # found in the literature (c/f references given above), albeit scattered: # 1) For fixed x != 0, lowergamma(s, x) is an entire function of s # 2) For fixed positive integers s, lowergamma(s, x) is an entire # function of x. # 3) For fixed non-positive integers s, # lowergamma(s, exp(I*2*pi*n)*x) = # 2*pi*I*n*(-1)**(-s)/factorial(-s) + lowergamma(s, x) # (this follows from lowergamma(s, x).diff(x) = x**(s-1)*exp(-x)). # 4) For fixed non-integral s, # lowergamma(s, x) = x**s*gamma(s)*lowergamma_unbranched(s, x), # where lowergamma_unbranched(s, x) is an entire function (in fact # of both s and x), i.e. # lowergamma(s, exp(2*I*pi*n)*x) = exp(2*pi*I*n*a)*lowergamma(a, x) from sympy import unpolarify, I, factorial, exp nx, n = x.extract_branch_factor() if a.is_integer and a > 0: nx = unpolarify(x) if nx != x: return lowergamma(a, nx) elif a.is_integer and a <= 0: if n != 0: return 2 * pi * I * n * (-1)**( -a) / factorial(-a) + lowergamma(a, nx) elif n != 0: return exp(2 * pi * I * n * a) * lowergamma(a, nx) # Special values. if a.is_Number: # TODO this should be non-recursive if a is S.One: return S.One - C.exp(-x) elif a is S.Half: return sqrt(pi) * erf(sqrt(x)) elif a.is_Integer or (2 * a).is_Integer: b = a - 1 if b.is_positive: return b * cls(b, x) - x**b * C.exp(-x) if not a.is_Integer: return (cls(a + 1, x) + x**a * C.exp(-x)) / a
def eval(cls, a, x): # For lack of a better place, we use this one to extract branching # information. The following can be # found in the literature (c/f references given above), albeit scattered: # 1) For fixed x != 0, lowergamma(s, x) is an entire function of s # 2) For fixed positive integers s, lowergamma(s, x) is an entire # function of x. # 3) For fixed non-positive integers s, # lowergamma(s, exp(I*2*pi*n)*x) = # 2*pi*I*n*(-1)**(-s)/factorial(-s) + lowergamma(s, x) # (this follows from lowergamma(s, x).diff(x) = x**(s-1)*exp(-x)). # 4) For fixed non-integral s, # lowergamma(s, x) = x**s*gamma(s)*lowergamma_unbranched(s, x), # where lowergamma_unbranched(s, x) is an entire function (in fact # of both s and x), i.e. # lowergamma(s, exp(2*I*pi*n)*x) = exp(2*pi*I*n*a)*lowergamma(a, x) from sympy import unpolarify, I, factorial, exp nx, n = x.extract_branch_factor() if a.is_integer and a > 0: nx = unpolarify(x) if nx != x: return lowergamma(a, nx) elif a.is_integer and a <= 0: if n != 0: return 2*pi*I*n*(-1)**(-a)/factorial(-a) + lowergamma(a, nx) elif n != 0: return exp(2*pi*I*n*a)*lowergamma(a, nx) # Special values. if a.is_Number: # TODO this should be non-recursive if a is S.One: return S.One - C.exp(-x) elif a is S.Half: return sqrt(pi)*erf(sqrt(x)) elif a.is_Integer or (2*a).is_Integer: b = a - 1 if b.is_positive: return b*cls(b, x) - x**b * C.exp(-x) if not a.is_Integer: return (cls(a + 1, x) + x**a * C.exp(-x))/a
def eval(cls, a, z): from sympy import unpolarify, I, factorial, exp, expint if z.is_Number: if z is S.NaN: return S.NaN elif z is S.Infinity: return S.Zero elif z is S.Zero: return gamma(a) # We extract branching information here. C/f lowergamma. nx, n = z.extract_branch_factor() if a.is_integer and a > 0: nx = unpolarify(z) if z != nx: return uppergamma(a, nx) elif a.is_integer and a <= 0: if n != 0: return -2 * pi * I * n * (-1)**( -a) / factorial(-a) + uppergamma(a, nx) elif n != 0: return gamma(a) * (1 - exp(2 * pi * I * n * a)) + exp( 2 * pi * I * n * a) * uppergamma(a, nx) # Special values. if a.is_Number: # TODO this should be non-recursive if a is S.One: return C.exp(-z) elif a is S.Half: return sqrt(pi) * (1 - erf(sqrt(z))) # TODO could use erfc... elif a.is_Integer or (2 * a).is_Integer: b = a - 1 if b.is_positive: return b * cls(b, z) + z**b * C.exp(-z) elif b.is_Integer: return expint(-b, z) * unpolarify(z)**(b + 1) if not a.is_Integer: return (cls(a + 1, z) - z**a * C.exp(-z)) / a
def eval(cls, a, z): if z.is_Number: if z is S.NaN: return S.NaN elif z is S.Infinity: return S.Zero elif z is S.Zero: return gamma(a) if a.is_Number: # TODO this should be non-recursive if a is S.One: return C.exp(-z) elif a is S.Half: return sqrt(pi) * (1 - erf(sqrt(z))) # TODO could use erfc... elif a.is_Integer or (2 * a).is_Integer: b = a - 1 if b.is_positive: return b * cls(b, z) + z ** b * C.exp(-z) if not a.is_Integer: return (cls(a + 1, z) - z ** a * C.exp(-z)) / a
def eval(cls, a, z): if z.is_Number: if z is S.NaN: return S.NaN elif z is S.Infinity: return S.Zero elif z is S.Zero: return gamma(a) if a.is_Number: # TODO this should be non-recursive if a is S.One: return C.exp(-z) elif a is S.Half: return sqrt(pi) * (1 - erf(sqrt(z))) # TODO could use erfc... elif a.is_Integer or (2 * a).is_Integer: b = a - 1 if b.is_positive: return b * cls(b, z) + z**b * C.exp(-z) if not a.is_Integer: return (cls(a + 1, z) - z**a * C.exp(-z)) / a
def eval(cls, a, z): from sympy import unpolarify, I, factorial, exp, expint if z.is_Number: if z is S.NaN: return S.NaN elif z is S.Infinity: return S.Zero elif z is S.Zero: return gamma(a) # We extract branching information here. C/f lowergamma. nx, n = z.extract_branch_factor() if a.is_integer and a > 0: nx = unpolarify(z) if z != nx: return uppergamma(a, nx) elif a.is_integer and a <= 0: if n != 0: return -2*pi*I*n*(-1)**(-a)/factorial(-a) + uppergamma(a, nx) elif n != 0: return gamma(a)*(1 - exp(2*pi*I*n*a)) + exp(2*pi*I*n*a)*uppergamma(a, nx) # Special values. if a.is_Number: # TODO this should be non-recursive if a is S.One: return C.exp(-z) elif a is S.Half: return sqrt(pi)*(1 - erf(sqrt(z))) # TODO could use erfc... elif a.is_Integer or (2*a).is_Integer: b = a - 1 if b.is_positive: return b*cls(b, z) + z**b * C.exp(-z) elif b.is_Integer: return expint(-b, z)*unpolarify(z)**(b + 1) if not a.is_Integer: return (cls(a + 1, z) - z**a * C.exp(-z))/a
from error_functions import erf, erfc import numpy for x in numpy.arange(-5., 5., 0.5): assert erf(x) + erfc(x) - 1. < 1.e-7