def _eval_(self, x, y): """ EXAMPLES:: sage: gamma_inc(2.,0) 1.00000000000000 sage: gamma_inc(2,0) 1 sage: gamma_inc(1/2,2) -sqrt(pi)*(erf(sqrt(2)) - 1) sage: gamma_inc(1/2,1) -sqrt(pi)*(erf(1) - 1) sage: gamma_inc(1/2,0) sqrt(pi) sage: gamma_inc(x,0) gamma(x) sage: gamma_inc(1,2) e^(-2) sage: gamma_inc(0,2) -Ei(-2) """ if y == 0: return gamma(x) if x == 1: return exp(-y) if x == 0: return -Ei(-y) if x == Rational((1, 2)): # only for x>0 from sage.functions.error import erf return sqrt(pi) * (1 - erf(sqrt(y))) return None
def _closed_form(hyp): a, b, z = hyp.operands() a, b = a.operands(), b.operands() p, q = len(a), len(b) if z == 0: return Integer(1) if p == q == 0: return exp(z) if p == 1 and q == 0: return (1 - z)**(-a[0]) if p == 0 and q == 1: # TODO: make this require only linear time def _0f1(b, z): F12 = cosh(2 * sqrt(z)) F32 = sinh(2 * sqrt(z)) / (2 * sqrt(z)) if 2 * b == 1: return F12 if 2 * b == 3: return F32 if 2 * b > 3: return ((b - 2) * (b - 1) / z * (_0f1(b - 2, z) - _0f1(b - 1, z))) if 2 * b < 1: return (_0f1(b + 1, z) + z / (b * (b + 1)) * _0f1(b + 2, z)) raise ValueError # Can evaluate 0F1 in terms of elementary functions when # the parameter is a half-integer if 2 * b[0] in ZZ and b[0] not in ZZ: return _0f1(b[0], z) # Confluent hypergeometric function if p == 1 and q == 1: aa, bb = a[0], b[0] if aa * 2 == 1 and bb * 2 == 3: t = sqrt(-z) return sqrt(pi) / 2 * erf(t) / t if a == 1 and b == 2: return (exp(z) - 1) / z n, m = aa, bb if n in ZZ and m in ZZ and m > 0 and n > 0: rf = rising_factorial if m <= n: return (exp(z) * sum( rf(m - n, k) * (-z)**k / factorial(k) / rf(m, k) for k in range(n - m + 1))) else: T = sum( rf(n - m + 1, k) * z**k / (factorial(k) * rf(2 - m, k)) for k in range(m - n)) U = sum( rf(1 - n, k) * (-z)**k / (factorial(k) * rf(2 - m, k)) for k in range(n)) return (factorial(m - 2) * rf(1 - m, n) * z**(1 - m) / factorial(n - 1) * (T - exp(z) * U)) if p == 2 and q == 1: R12 = QQ((1, 2)) R32 = QQ((3, 2)) def _2f1(a, b, c, z): """ Evaluation of 2F1(a, b; c; z), assuming a, b, c positive integers or half-integers """ if b == c: return (1 - z)**(-a) if a == c: return (1 - z)**(-b) if a == 0 or b == 0: return Integer(1) if a > b: a, b = b, a if b >= 2: F1 = _2f1(a, b - 1, c, z) F2 = _2f1(a, b - 2, c, z) q = (b - 1) * (z - 1) return (((c - 2 * b + 2 + (b - a - 1) * z) * F1 + (b - c - 1) * F2) / q) if c > 2: # how to handle this case? if a - c + 1 == 0 or b - c + 1 == 0: raise NotImplementedError F1 = _2f1(a, b, c - 1, z) F2 = _2f1(a, b, c - 2, z) r1 = (c - 1) * (2 - c - (a + b - 2 * c + 3) * z) r2 = (c - 1) * (c - 2) * (1 - z) q = (a - c + 1) * (b - c + 1) * z return (r1 * F1 + r2 * F2) / q if (a, b, c) == (R12, 1, 2): return (2 - 2 * sqrt(1 - z)) / z if (a, b, c) == (1, 1, 2): return -log(1 - z) / z if (a, b, c) == (1, R32, R12): return (1 + z) / (1 - z)**2 if (a, b, c) == (1, R32, 2): return 2 * (1 / sqrt(1 - z) - 1) / z if (a, b, c) == (R32, 2, R12): return (1 + 3 * z) / (1 - z)**3 if (a, b, c) == (R32, 2, 1): return (2 + z) / (2 * (sqrt(1 - z) * (1 - z)**2)) if (a, b, c) == (2, 2, 1): return (1 + z) / (1 - z)**3 raise NotImplementedError aa, bb = a cc, = b if z == 1: return (gamma(cc) * gamma(cc - aa - bb) / gamma(cc - aa) / gamma(cc - bb)) if ((aa * 2) in ZZ and (bb * 2) in ZZ and (cc * 2) in ZZ and aa > 0 and bb > 0 and cc > 0): try: return _2f1(aa, bb, cc, z) except NotImplementedError: pass return hyp
def _closed_form(hyp): a, b, z = hyp.operands() a, b = a.operands(), b.operands() p, q = len(a), len(b) if z == 0: return Integer(1) if p == q == 0: return exp(z) if p == 1 and q == 0: return (1 - z) ** (-a[0]) if p == 0 and q == 1: # TODO: make this require only linear time def _0f1(b, z): F12 = cosh(2 * sqrt(z)) F32 = sinh(2 * sqrt(z)) / (2 * sqrt(z)) if 2 * b == 1: return F12 if 2 * b == 3: return F32 if 2 * b > 3: return ((b - 2) * (b - 1) / z * (_0f1(b - 2, z) - _0f1(b - 1, z))) if 2 * b < 1: return (_0f1(b + 1, z) + z / (b * (b + 1)) * _0f1(b + 2, z)) raise ValueError # Can evaluate 0F1 in terms of elementary functions when # the parameter is a half-integer if 2 * b[0] in ZZ and b[0] not in ZZ: return _0f1(b[0], z) # Confluent hypergeometric function if p == 1 and q == 1: aa, bb = a[0], b[0] if aa * 2 == 1 and bb * 2 == 3: t = sqrt(-z) return sqrt(pi) / 2 * erf(t) / t if a == 1 and b == 2: return (exp(z) - 1) / z n, m = aa, bb if n in ZZ and m in ZZ and m > 0 and n > 0: rf = rising_factorial if m <= n: return (exp(z) * sum(rf(m - n, k) * (-z) ** k / factorial(k) / rf(m, k) for k in range(n - m + 1))) else: T = sum(rf(n - m + 1, k) * z ** k / (factorial(k) * rf(2 - m, k)) for k in range(m - n)) U = sum(rf(1 - n, k) * (-z) ** k / (factorial(k) * rf(2 - m, k)) for k in range(n)) return (factorial(m - 2) * rf(1 - m, n) * z ** (1 - m) / factorial(n - 1) * (T - exp(z) * U)) if p == 2 and q == 1: R12 = QQ('1/2') R32 = QQ('3/2') def _2f1(a, b, c, z): """ Evaluation of 2F1(a, b; c; z), assuming a, b, c positive integers or half-integers """ if b == c: return (1 - z) ** (-a) if a == c: return (1 - z) ** (-b) if a == 0 or b == 0: return Integer(1) if a > b: a, b = b, a if b >= 2: F1 = _2f1(a, b - 1, c, z) F2 = _2f1(a, b - 2, c, z) q = (b - 1) * (z - 1) return (((c - 2 * b + 2 + (b - a - 1) * z) * F1 + (b - c - 1) * F2) / q) if c > 2: # how to handle this case? if a - c + 1 == 0 or b - c + 1 == 0: raise NotImplementedError F1 = _2f1(a, b, c - 1, z) F2 = _2f1(a, b, c - 2, z) r1 = (c - 1) * (2 - c - (a + b - 2 * c + 3) * z) r2 = (c - 1) * (c - 2) * (1 - z) q = (a - c + 1) * (b - c + 1) * z return (r1 * F1 + r2 * F2) / q if (a, b, c) == (R12, 1, 2): return (2 - 2 * sqrt(1 - z)) / z if (a, b, c) == (1, 1, 2): return -log(1 - z) / z if (a, b, c) == (1, R32, R12): return (1 + z) / (1 - z) ** 2 if (a, b, c) == (1, R32, 2): return 2 * (1 / sqrt(1 - z) - 1) / z if (a, b, c) == (R32, 2, R12): return (1 + 3 * z) / (1 - z) ** 3 if (a, b, c) == (R32, 2, 1): return (2 + z) / (2 * (sqrt(1 - z) * (1 - z) ** 2)) if (a, b, c) == (2, 2, 1): return (1 + z) / (1 - z) ** 3 raise NotImplementedError aa, bb = a cc, = b if z == 1: return (gamma(cc) * gamma(cc - aa - bb) / gamma(cc - aa) / gamma(cc - bb)) if ((aa * 2) in ZZ and (bb * 2) in ZZ and (cc * 2) in ZZ and aa > 0 and bb > 0 and cc > 0): try: return _2f1(aa, bb, cc, z) except NotImplementedError: pass return hyp