def _eval_(self, n, x): """ EXAMPLES:: sage: y=var('y') sage: bessel_I(y,x) bessel_I(y, x) sage: bessel_I(0.0, 1.0) 1.26606587775201 sage: bessel_I(1/2, 1) sqrt(2)*sinh(1)/sqrt(pi) sage: bessel_I(-1/2, pi) sqrt(2)*cosh(pi)/pi """ if (not isinstance(n, Expression) and not isinstance(x, Expression) and (is_inexact(n) or is_inexact(x))): coercion_model = get_coercion_model() n, x = coercion_model.canonical_coercion(n, x) return self._evalf_(n, x, parent(n)) # special identities if n == Integer(1) / Integer(2): return sqrt(2 / (pi * x)) * sinh(x) elif n == -Integer(1) / Integer(2): return sqrt(2 / (pi * x)) * cosh(x) return None # leaves the expression unevaluated
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) -(erf(sqrt(2)) - 1)*sqrt(pi) sage: gamma_inc(1/2,1) -(erf(1) - 1)*sqrt(pi) 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 not isinstance(x, Expression) and not isinstance(y, Expression) and \ (is_inexact(x) or is_inexact(y)): x, y = coercion_model.canonical_coercion(x, y) return self._evalf_(x, y, parent(x)) 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 return sqrt(pi)*(1-erf(sqrt(y))) return None
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) -(erf(sqrt(2)) - 1)*sqrt(pi) sage: gamma_inc(1/2,1) -(erf(1) - 1)*sqrt(pi) 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 not isinstance(x, Expression) and not isinstance(y, Expression) and \ (is_inexact(x) or is_inexact(y)): x, y = coercion_model.canonical_coercion(x, y) return self._evalf_(x, y, parent(x)) 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 return sqrt(pi) * (1 - erf(sqrt(y))) return None
def _eval_(self, z): """ EXAMPLES:: sage: z = var('z') sage: sin_integral(z) sin_integral(z) sage: sin_integral(3.0) 1.84865252799947 sage: sin_integral(0) 0 """ if not isinstance(z, Expression) and is_inexact(z): return self._evalf_(z, parent(z)) # special case: z = 0 if isinstance(z, Expression): if z.is_trivial_zero(): return z else: if not z: return z return None # leaves the expression unevaluated
def _eval_(self, n, m, theta, phi, **kwargs): r""" TESTS:: sage: x, y = var('x y') sage: spherical_harmonic(1, 2, x, y) 0 sage: spherical_harmonic(1, -2, x, y) 0 sage: spherical_harmonic(1/2, 2, x, y) spherical_harmonic(1/2, 2, x, y) sage: spherical_harmonic(3, 2, x, y) 15/4*sqrt(7/30)*cos(x)*e^(2*I*y)*sin(x)^2/sqrt(pi) sage: spherical_harmonic(3, 2, 1, 2) 15/4*sqrt(7/30)*cos(1)*e^(4*I)*sin(1)^2/sqrt(pi) sage: spherical_harmonic(3 + I, 2., 1, 2) -0.351154337307488 - 0.415562233975369*I """ from sage.structure.coerce import parent cc = get_coercion_model().canonical_coercion coerced = cc(phi, cc(theta, cc(n, m)[0])[0])[0] if is_inexact(coerced) and not isinstance(coerced, Expression): return self._evalf_(n, m, theta, phi, parent=parent(coerced)) elif n in ZZ and m in ZZ and n > -1: if abs(m) > n: return ZZ(0) return meval("spherical_harmonic({},{},{},{})".format( ZZ(n), ZZ(m), maxima(theta), maxima(phi))) return
def _eval_(self, x): """ Evaluate the factorial function. Note that this method overrides the eval method defined in GiNaC which calls numeric evaluation on all numeric input. We preserve exact results if the input is a rational number. EXAMPLES:: sage: k = var('k') sage: k.factorial() factorial(k) sage: SR(1/2).factorial() 1/2*sqrt(pi) sage: SR(3/4).factorial() gamma(7/4) sage: SR(5).factorial() 120 sage: SR(3245908723049857203948572398475r).factorial() factorial(3245908723049857203948572398475L) sage: SR(3245908723049857203948572398475).factorial() factorial(3245908723049857203948572398475) """ if isinstance(x, Rational): return gamma(x+1) elif isinstance(x, (Integer, int)) or \ (not isinstance(x, Expression) and is_inexact(x)): return py_factorial_py(x) return None
def _eval_(self, x): """ Evaluate the factorial function. Note that this method overrides the eval method defined in GiNaC which calls numeric evaluation on all numeric input. We preserve exact results if the input is a rational number. EXAMPLES:: sage: k = var('k') sage: k.factorial() factorial(k) sage: SR(1/2).factorial() 1/2*sqrt(pi) sage: SR(3/4).factorial() gamma(7/4) sage: SR(5).factorial() 120 sage: SR(3245908723049857203948572398475r).factorial() factorial(3245908723049857203948572398475L) sage: SR(3245908723049857203948572398475).factorial() factorial(3245908723049857203948572398475) """ if isinstance(x, Rational): return gamma(x + 1) elif isinstance(x, (Integer, int)) or \ (not isinstance(x, Expression) and is_inexact(x)): return py_factorial_py(x) return None
def _eval_(self, n, m, theta, phi, **kwargs): r""" TESTS:: sage: x, y = var('x y') sage: spherical_harmonic(1, 2, x, y) 0 sage: spherical_harmonic(1, -2, x, y) 0 sage: spherical_harmonic(1/2, 2, x, y) spherical_harmonic(1/2, 2, x, y) sage: spherical_harmonic(3, 2, x, y) 15/4*sqrt(7/30)*cos(x)*e^(2*I*y)*sin(x)^2/sqrt(pi) sage: spherical_harmonic(3, 2, 1, 2) 15/4*sqrt(7/30)*cos(1)*e^(4*I)*sin(1)^2/sqrt(pi) sage: spherical_harmonic(3 + I, 2., 1, 2) -0.351154337307488 - 0.415562233975369*I """ from sage.structure.coerce import parent cc = get_coercion_model().canonical_coercion coerced = cc(phi, cc(theta, cc(n, m)[0])[0])[0] if is_inexact(coerced) and not isinstance(coerced, Expression): return self._evalf_(n, m, theta, phi, parent=parent(coerced)) elif n in ZZ and m in ZZ and n > -1: if abs(m) > n: return ZZ(0) return meval("spherical_harmonic({},{},{},{})".format(ZZ(n), ZZ(m), maxima(theta), maxima(phi))) return
def _eval_(self, n, z): """ EXAMPLES:: sage: exp_integral_e(1.0, x) exp_integral_e(1.00000000000000, x) sage: exp_integral_e(x, 1.0) exp_integral_e(x, 1.00000000000000) sage: exp_integral_e(1.0, 1.0) 0.219383934395520 """ if not isinstance(n, Expression) and not isinstance(z, Expression) and \ (is_inexact(n) or is_inexact(z)): coercion_model = sage.structure.element.get_coercion_model() n, z = coercion_model.canonical_coercion(n, z) return self._evalf_(n, z, parent(n)) z_zero = False # special case: z == 0 and n > 1 if isinstance(z, Expression): if z.is_trivial_zero(): z_zero = True # for later if n > 1: return 1/(n-1) else: if not z: z_zero = True if n > 1: return 1/(n-1) # special case: n == 0 if isinstance(n, Expression): if n.is_trivial_zero(): if z_zero: return None else: return exp(-z)/z else: if not n: if z_zero: return None else: return exp(-z)/z return None # leaves the expression unevaluated
def _eval_(self, n, x): """ EXAMPLES:: sage: a,b = var('a, b') sage: bessel_Y(a, b) bessel_Y(a, b) sage: bessel_Y(0, 1).n(128) 0.088256964215676957982926766023515162828 """ if (not isinstance(n, Expression) and not isinstance(x, Expression) and (is_inexact(n) or is_inexact(x))): coercion_model = get_coercion_model() n, x = coercion_model.canonical_coercion(n, x) return self._evalf_(n, x, parent(n)) return None # leaves the expression unevaluated
def _eval_(self, n, x): """ EXAMPLES:: sage: a, b = var('a, b') sage: bessel_J(a, b) bessel_J(a, b) sage: bessel_J(1.0, 1.0) 0.440050585744933 """ if (not isinstance(n, Expression) and not isinstance(x, Expression) and (is_inexact(n) or is_inexact(x))): coercion_model = get_coercion_model() n, x = coercion_model.canonical_coercion(n, x) return self._evalf_(n, x, parent(n)) return None
def _eval_(self, n, z): """ EXAMPLES:: sage: exp_integral_e(1.0, x) exp_integral_e(1.00000000000000, x) sage: exp_integral_e(x, 1.0) exp_integral_e(x, 1.00000000000000) sage: exp_integral_e(1.0, 1.0) 0.219383934395520 """ if not isinstance(n, Expression) and not isinstance(z, Expression) and \ (is_inexact(n) or is_inexact(z)): coercion_model = sage.structure.element.get_coercion_model() n, z = coercion_model.canonical_coercion(n, z) return self._evalf_(n, z, parent(n)) z_zero = False # special case: z == 0 and n > 1 if isinstance(z, Expression): if z.is_trivial_zero(): z_zero = True # for later if n > 1: return 1 / (n - 1) else: if not z: z_zero = True if n > 1: return 1 / (n - 1) # special case: n == 0 if isinstance(n, Expression): if n.is_trivial_zero(): if z_zero: return None else: return exp(-z) / z else: if not n: if z_zero: return None else: return exp(-z) / z return None # leaves the expression unevaluated
def _eval_(self, n, z ): """ EXAMPLES:: """ # howto find a common parent for n and z here? if not isinstance(z, Expression) and is_inexact(z): return self._evalf_(n, z, parent(z)) return None
def _eval_(self, n, z): """ EXAMPLES:: sage: lambert_w(6.0) 1.43240477589830 sage: lambert_w(1) lambert_w(1) sage: lambert_w(x+1) lambert_w(x + 1) There are three special values which are automatically simplified:: sage: lambert_w(0) 0 sage: lambert_w(e) 1 sage: lambert_w(-1/e) -1 sage: lambert_w(SR(0)) 0 The special values only hold on the principal branch:: sage: lambert_w(1,e) lambert_w(1, e) sage: lambert_w(1, e.n()) -0.532092121986380 + 4.59715801330257*I TESTS: When automatic simplication occurs, the parent of the output value should be either the same as the parent of the input, or a Sage type:: sage: parent(lambert_w(int(0))) <type 'int'> sage: parent(lambert_w(Integer(0))) Integer Ring sage: parent(lambert_w(e)) Integer Ring """ if not isinstance(z, Expression): if is_inexact(z): return self._evalf_(n, z, parent=sage_structure_coerce_parent(z)) elif n == 0 and z == 0: return sage_structure_coerce_parent(z)(Integer(0)) elif n == 0: if z.is_trivial_zero(): return sage_structure_coerce_parent(z)(Integer(0)) elif (z - const_e).is_trivial_zero(): return sage_structure_coerce_parent(z)(Integer(1)) elif (z + 1 / const_e).is_trivial_zero(): return sage_structure_coerce_parent(z)(Integer(-1)) return None
def _eval_(self, n, z): """ EXAMPLES:: sage: lambert_w(6.0) 1.43240477589830 sage: lambert_w(1) lambert_w(1) sage: lambert_w(x+1) lambert_w(x + 1) There are three special values which are automatically simplified:: sage: lambert_w(0) 0 sage: lambert_w(e) 1 sage: lambert_w(-1/e) -1 sage: lambert_w(SR(0)) 0 The special values only hold on the principal branch:: sage: lambert_w(1,e) lambert_w(1, e) sage: lambert_w(1, e.n()) -0.532092121986380 + 4.59715801330257*I TESTS: When automatic simplication occurs, the parent of the output value should be either the same as the parent of the input, or a Sage type:: sage: parent(lambert_w(int(0))) <type 'int'> sage: parent(lambert_w(Integer(0))) Integer Ring sage: parent(lambert_w(e)) Integer Ring """ if not isinstance(z, Expression): if is_inexact(z): return self._evalf_(n, z, parent=sage_structure_coerce_parent(z)) elif n == 0 and z == 0: return sage_structure_coerce_parent(z)(Integer(0)) elif n == 0: if z.is_trivial_zero(): return sage_structure_coerce_parent(z)(Integer(0)) elif (z-const_e).is_trivial_zero(): return sage_structure_coerce_parent(z)(Integer(1)) elif (z+1/const_e).is_trivial_zero(): return sage_structure_coerce_parent(z)(Integer(-1)) return None
def _eval_(self, n, x): """ EXAMPLES:: sage: bessel_K(1,0) bessel_K(1, 0) sage: bessel_K(1.0, 0.0) +infinity sage: bessel_K(-1, 1).n(128) 0.60190723019723457473754000153561733926 """ if (not isinstance(n, Expression) and not isinstance(x, Expression) and (is_inexact(n) or is_inexact(x))): coercion_model = get_coercion_model() n, x = coercion_model.canonical_coercion(n, x) return self._evalf_(n, x, parent(n)) # special identity if n == Integer(1) / Integer(2) and x > 0: return sqrt(pi / 2) * exp(-x) * x**(-Integer(1) / Integer(2)) return None # leaves the expression unevaluated
def _eval_(self, n, x): """ EXAMPLES:: sage: bessel_K(1,0) bessel_K(1, 0) sage: bessel_K(1.0, 0.0) +infinity sage: bessel_K(-1, 1).n(128) 0.60190723019723457473754000153561733926 """ if (not isinstance(n, Expression) and not isinstance(x, Expression) and (is_inexact(n) or is_inexact(x))): coercion_model = get_coercion_model() n, x = coercion_model.canonical_coercion(n, x) return self._evalf_(n, x, parent(n)) # special identity if n == Integer(1) / Integer(2) and x > 0: return sqrt(pi / 2) * exp(-x) * x ** (-Integer(1) / Integer(2)) return None # leaves the expression unevaluated
def _eval_(self, z): """ EXAMPLES:: sage: exp_integral_e1(x) exp_integral_e1(x) sage: exp_integral_e1(1.0) 0.219383934395520 """ if not isinstance(z, Expression) and is_inexact(z): return self._evalf_(z, parent(z)) return None # leaves the expression unevaluated
def _eval_(self, z): """ EXAMPLES:: sage: z = var('z') sage: cosh_integral(z) cosh_integral(z) sage: cosh_integral(3.0) 4.96039209476561 """ if not isinstance(z, Expression) and is_inexact(z): return self._evalf_(z, parent(z)) return None
def _eval_(self, x ): """ EXAMPLES:: sage: Ei(10) Ei(10) sage: Ei(I) Ei(I) sage: Ei(1.3) 2.72139888023202 sage: Ei(10r) Ei(10) sage: Ei(1.3r) 2.7213988802320235 """ if not isinstance(x, Expression) and is_inexact(x): return self._evalf_(x, parent(x)) return None
def _eval_(self, a, b, z, **kwargs): """ EXAMPLES:: sage: hypergeometric([], [], 0) 1 """ if not isinstance(a,tuple) or not isinstance(b,tuple): raise ValueError('First two parameters must be of type list.') coercion_model = get_coercion_model() co = reduce(lambda x, y: coercion_model.canonical_coercion(x, y)[0], a + b + (z,)) if is_inexact(co) and not isinstance(co, Expression): from sage.structure.coerce import parent return self._evalf_(a, b, z, parent=parent(co)) if not isinstance(z, Expression) and z == 0: # Expression is excluded return Integer(1) # to avoid call to Maxima return
def _eval_(self, x): """ EXAMPLES:: sage: Ei(10) Ei(10) sage: Ei(I) Ei(I) sage: Ei(1.3) 2.72139888023202 sage: Ei(10r) Ei(10) sage: Ei(1.3r) 2.72139888023202 """ if not isinstance(x, Expression) and is_inexact(x): return self._evalf_(x, parent(x)) return None
def _eval_(self, z): """ EXAMPLES:: sage: z = var('z') sage: cos_integral(z) cos_integral(z) sage: cos_integral(3.0) 0.119629786008000 sage: cos_integral(0) cos_integral(0) sage: N(cos_integral(0)) -infinity """ if not isinstance(z, Expression) and is_inexact(z): return self._evalf_(z, parent(z)) return None # leaves the expression unevaluated
def _eval_(self, z): """ EXAMPLES:: sage: z = var('z') sage: log_integral_offset(z) -log_integral(2) + log_integral(z) sage: log_integral_offset(3.0) 1.11842481454970 sage: log_integral_offset(2) 0 """ if not isinstance(z, Expression) and is_inexact(z): return self._evalf_(z, parent(z)) if z == 2: import sage.symbolic.ring return sage.symbolic.ring.SR(0) return li(z) - li(2)
def _eval_(self,z): """ EXAMPLES:: sage: z = var('z') sage: log_integral_offset(z) -log_integral(2) + log_integral(z) sage: log_integral_offset(3.0) 1.11842481454970 sage: log_integral_offset(2) 0 """ if not isinstance(z,Expression) and is_inexact(z): return self._evalf_(z,parent(z)) if z==2: import sage.symbolic.ring return sage.symbolic.ring.SR(0) return li(z)-li(2)
def _eval_(self, z): """ EXAMPLES:: sage: z = var('z') sage: log_integral(z) log_integral(z) sage: log_integral(3.0) 2.16358859466719 sage: log_integral(0) 0 """ if isinstance(z, Expression): if z.is_trivial_zero(): # special case: z = 0 return z else: if is_inexact(z): return self._evalf_(z, parent(z)) elif not z: return z return None # leaves the expression unevaluated
def _eval_(self, s, x): r""" TESTS:: sage: hurwitz_zeta(x, 1) zeta(x) sage: hurwitz_zeta(4, 3) 1/90*pi^4 - 17/16 sage: hurwitz_zeta(-4, x) -1/5*x^5 + 1/2*x^4 - 1/3*x^3 + 1/30*x sage: hurwitz_zeta(3, 0.5) 8.41439832211716 """ co = get_coercion_model().canonical_coercion(s, x)[0] if is_inexact(co) and not isinstance(co, Expression): return self._evalf_(s, x, parent=parent(co)) if x == 1: return zeta(s) if s in ZZ and s > 1: return ((-1)**s) * psi(s - 1, x) / factorial(s - 1) elif s in ZZ and s < 0: return -bernoulli_polynomial(x, -s + 1) / (-s + 1) else: return
def _eval_(self, x): """ EXAMPLES:: sage: arg(3+i) arctan(1/3) sage: arg(-1+i) 3/4*pi sage: arg(2+2*i) 1/4*pi sage: arg(2+x) arg(x + 2) sage: arg(2.0+i+x) arg(x + 2.00000000000000 + 1.00000000000000*I) sage: arg(-3) pi sage: arg(3) 0 sage: arg(0) 0 sage: arg(sqrt(2)+i) arg(sqrt(2) + I) """ if not isinstance(x, Expression): # x contains no variables if is_inexact(x): # inexact complex numbers, e.g. 2.0+i return self._evalf_(x, parent(x)) else: # exact complex numbers, e.g. 2+i return arctan2(imag_part(x), real_part(x)) else: # x contains variables, e.g. 2+i+y or 2.0+i+y # or x involves an expression such as sqrt(2) return None
def _eval_(self, x): """ EXAMPLES:: sage: arg(3+i) arctan(1/3) sage: arg(-1+i) 3/4*pi sage: arg(2+2*i) 1/4*pi sage: arg(2+x) arg(x + 2) sage: arg(2.0+i+x) arg(x + 2.00000000000000 + 1.00000000000000*I) sage: arg(-3) pi sage: arg(3) 0 sage: arg(0) 0 sage: arg(sqrt(2)+i) arg(sqrt(2) + I) """ if not isinstance(x,Expression): # x contains no variables if is_inexact(x): # inexact complex numbers, e.g. 2.0+i return self._evalf_(x, parent(x)) else: # exact complex numbers, e.g. 2+i return arctan2(imag_part(x),real_part(x)) else: # x contains variables, e.g. 2+i+y or 2.0+i+y # or x involves an expression such as sqrt(2) return None
def _eval_(self, s, x): r""" TESTS:: sage: hurwitz_zeta(x, 1) zeta(x) sage: hurwitz_zeta(4, 3) 1/90*pi^4 - 17/16 sage: hurwitz_zeta(-4, x) -1/5*x^5 + 1/2*x^4 - 1/3*x^3 + 1/30*x sage: hurwitz_zeta(3, 0.5) 8.41439832211716 """ co = get_coercion_model().canonical_coercion(s, x)[0] if is_inexact(co) and not isinstance(co, Expression): return self._evalf_(s, x, parent=parent(co)) if x == 1: return zeta(s) if s in ZZ and s > 1: return ((-1) ** s) * psi(s - 1, x) / factorial(s - 1) elif s in ZZ and s < 0: return -bernoulli_polynomial(x, -s + 1) / (-s + 1) else: return
def exponential_integral_1(x, n=0): r""" Returns the exponential integral `E_1(x)`. If the optional argument `n` is given, computes list of the first `n` values of the exponential integral `E_1(x m)`. The exponential integral `E_1(x)` is .. math:: E_1(x) = \int_{x}^{\infty} e^{-t}/t dt INPUT: - ``x`` -- a positive real number - ``n`` -- (default: 0) a nonnegative integer; if nonzero, then return a list of values ``E_1(x*m)`` for m = 1,2,3,...,n. This is useful, e.g., when computing derivatives of L-functions. OUTPUT: A real number if n is 0 (the default) or a list of reals if n > 0. The precision is the same as the input, with a default of 53 bits in case the input is exact. EXAMPLES:: sage: exponential_integral_1(2) 0.0489005107080611 sage: exponential_integral_1(2,4) # abs tol 1e-18 [0.0489005107080611, 0.00377935240984891, 0.000360082452162659, 0.0000376656228439245] sage: exponential_integral_1(40,5) [1.03677326145166e-19, 2.22854325868847e-37, 6.33732515501151e-55, 2.02336191509997e-72, 6.88522610630764e-90] sage: exponential_integral_1(0) +Infinity sage: r = exponential_integral_1(RealField(150)(1)) sage: r 0.21938393439552027367716377546012164903104729 sage: parent(r) Real Field with 150 bits of precision sage: exponential_integral_1(RealField(150)(100)) 3.6835977616820321802351926205081189876552201e-46 TESTS: The relative error for a single value should be less than 1 ulp:: sage: for prec in [20..1000]: # long time (22s on sage.math, 2013) ....: R = RealField(prec) ....: S = RealField(prec+64) ....: for t in range(8): # Try 8 values for each precision ....: a = R.random_element(-15,10).exp() ....: x = exponential_integral_1(a) ....: y = exponential_integral_1(S(a)) ....: e = float(abs(S(x) - y)/x.ulp()) ....: if e >= 1.0: ....: print "exponential_integral_1(%s) with precision %s has error of %s ulp"%(a, prec, e) The absolute error for a vector should be less than `c 2^{-p}`, where `p` is the precision in bits of `x` and `c = 2 max(1, exponential_integral_1(x))`:: sage: for prec in [20..128]: # long time (15s on sage.math, 2013) ....: R = RealField(prec) ....: S = RealField(prec+64) ....: a = R.random_element(-15,10).exp() ....: n = 2^ZZ.random_element(14) ....: x = exponential_integral_1(a, n) ....: y = exponential_integral_1(S(a), n) ....: c = RDF(2 * max(1.0, y[0])) ....: for i in range(n): ....: e = float(abs(S(x[i]) - y[i]) << prec) ....: if e >= c: ....: print "exponential_integral_1(%s, %s)[%s] with precision %s has error of %s >= %s"%(a, n, i, prec, e, c) ALGORITHM: use the PARI C-library function ``eint1``. REFERENCE: - See Proposition 5.6.12 of Cohen's book "A Course in Computational Algebraic Number Theory". """ if isinstance(x, Expression): if x.is_trivial_zero(): from sage.rings.infinity import Infinity return Infinity else: raise NotImplementedError("Use the symbolic exponential integral " + "function: exp_integral_e1.") elif not is_inexact(x): # x is exact and not an expression if not x: # test if exact x == 0 quickly from sage.rings.infinity import Infinity return Infinity # else x is not an exact 0 from sage.libs.pari.all import pari # Figure out output precision try: prec = parent(x).precision() except AttributeError: prec = 53 R = RealField(prec) if n <= 0: # Add extra bits to the input. # (experimentally verified -- Jeroen Demeyer) inprec = prec + math.ceil(math.log(2*prec)) x = RealField(inprec)(x)._pari_() return R(x.eint1()) else: # PARI's algorithm is less precise as n grows larger: # add extra bits. # (experimentally verified -- Jeroen Demeyer) inprec = prec + 1 + math.ceil(1.4427 * math.log(n)) x = RealField(inprec)(x)._pari_() return [R(z) for z in x.eint1(n)]
def exponential_integral_1(x, n=0): r""" Returns the exponential integral `E_1(x)`. If the optional argument `n` is given, computes list of the first `n` values of the exponential integral `E_1(x m)`. The exponential integral `E_1(x)` is .. math:: E_1(x) = \int_{x}^{\infty} e^{-t}/t dt INPUT: - ``x`` - a positive real number - ``n`` - (default: 0) a nonnegative integer; if nonzero, then return a list of values E_1(x\*m) for m = 1,2,3,...,n. This is useful, e.g., when computing derivatives of L-functions. OUTPUT: - ``float`` - if n is 0 (the default) or - ``list`` - list of floats if n 0 EXAMPLES:: sage: exponential_integral_1(2) 0.04890051070806112 sage: exponential_integral_1(2,4) # rel tol 1e-10 [0.04890051070806112, 0.0037793524098489067, 0.00036008245216265873, 3.7665622843924751e-05] sage: exponential_integral_1(0) +Infinity IMPLEMENTATION: We use the PARI C-library functions eint1 and veceint1. REFERENCE: - See page 262, Prop 5.6.12, of Cohen's book "A Course in Computational Algebraic Number Theory". REMARKS: When called with the optional argument n, the PARI C-library is fast for values of n up to some bound, then very very slow. For example, if x=5, then the computation takes less than a second for n=800000, and takes "forever" for n=900000. """ if isinstance(x, Expression): if x.is_trivial_zero(): from sage.rings.infinity import Infinity return Infinity else: raise NotImplementedError( "Use the symbolic exponential integral " + "function: exp_integral_e1.") elif not is_inexact(x): # x is exact and not an expression if not x: # test if exact x == 0 quickly from sage.rings.infinity import Infinity return Infinity # else x is in not an exact 0 from sage.libs.pari.all import pari if n <= 0: return float(pari(x).eint1()) else: return [float(z) for z in pari(x).eint1(n)]
def exponential_integral_1(x, n=0): r""" Returns the exponential integral `E_1(x)`. If the optional argument `n` is given, computes list of the first `n` values of the exponential integral `E_1(x m)`. The exponential integral `E_1(x)` is .. math:: E_1(x) = \int_{x}^{\infty} e^{-t}/t dt INPUT: - ``x`` -- a positive real number - ``n`` -- (default: 0) a nonnegative integer; if nonzero, then return a list of values ``E_1(x*m)`` for m = 1,2,3,...,n. This is useful, e.g., when computing derivatives of L-functions. OUTPUT: A real number if n is 0 (the default) or a list of reals if n > 0. The precision is the same as the input, with a default of 53 bits in case the input is exact. EXAMPLES:: sage: exponential_integral_1(2) 0.0489005107080611 sage: exponential_integral_1(2,4) # abs tol 1e-18 [0.0489005107080611, 0.00377935240984891, 0.000360082452162659, 0.0000376656228439245] sage: exponential_integral_1(40,5) [1.03677326145166e-19, 2.22854325868847e-37, 6.33732515501151e-55, 2.02336191509997e-72, 6.88522610630764e-90] sage: exponential_integral_1(0) +Infinity sage: r = exponential_integral_1(RealField(150)(1)) sage: r 0.21938393439552027367716377546012164903104729 sage: parent(r) Real Field with 150 bits of precision sage: exponential_integral_1(RealField(150)(100)) 3.6835977616820321802351926205081189876552201e-46 TESTS: The relative error for a single value should be less than 1 ulp:: sage: for prec in [20..1000]: # long time (22s on sage.math, 2013) ....: R = RealField(prec) ....: S = RealField(prec+64) ....: for t in range(8): # Try 8 values for each precision ....: a = R.random_element(-15,10).exp() ....: x = exponential_integral_1(a) ....: y = exponential_integral_1(S(a)) ....: e = float(abs(S(x) - y)/x.ulp()) ....: if e >= 1.0: ....: print "exponential_integral_1(%s) with precision %s has error of %s ulp"%(a, prec, e) The absolute error for a vector should be less than `c 2^{-p}`, where `p` is the precision in bits of `x` and `c = 2 max(1, exponential_integral_1(x))`:: sage: for prec in [20..128]: # long time (15s on sage.math, 2013) ....: R = RealField(prec) ....: S = RealField(prec+64) ....: a = R.random_element(-15,10).exp() ....: n = 2^ZZ.random_element(14) ....: x = exponential_integral_1(a, n) ....: y = exponential_integral_1(S(a), n) ....: c = RDF(2 * max(1.0, y[0])) ....: for i in range(n): ....: e = float(abs(S(x[i]) - y[i]) << prec) ....: if e >= c: ....: print "exponential_integral_1(%s, %s)[%s] with precision %s has error of %s >= %s"%(a, n, i, prec, e, c) ALGORITHM: use the PARI C-library function ``eint1``. REFERENCE: - See Proposition 5.6.12 of Cohen's book "A Course in Computational Algebraic Number Theory". """ if isinstance(x, Expression): if x.is_trivial_zero(): from sage.rings.infinity import Infinity return Infinity else: raise NotImplementedError( "Use the symbolic exponential integral " + "function: exp_integral_e1.") elif not is_inexact(x): # x is exact and not an expression if not x: # test if exact x == 0 quickly from sage.rings.infinity import Infinity return Infinity # else x is not an exact 0 from sage.libs.pari.all import pari # Figure out output precision try: prec = parent(x).precision() except AttributeError: prec = 53 R = RealField(prec) if n <= 0: # Add extra bits to the input. # (experimentally verified -- Jeroen Demeyer) inprec = prec + math.ceil(math.log(2 * prec)) x = RealField(inprec)(x)._pari_() return R(x.eint1()) else: # PARI's algorithm is less precise as n grows larger: # add extra bits. # (experimentally verified -- Jeroen Demeyer) inprec = prec + 1 + math.ceil(1.4427 * math.log(n)) x = RealField(inprec)(x)._pari_() return [R(z) for z in x.eint1(n)]
def exponential_integral_1(x, n=0): r""" Returns the exponential integral `E_1(x)`. If the optional argument `n` is given, computes list of the first `n` values of the exponential integral `E_1(x m)`. The exponential integral `E_1(x)` is .. math:: E_1(x) = \int_{x}^{\infty} e^{-t}/t dt INPUT: - ``x`` - a positive real number - ``n`` - (default: 0) a nonnegative integer; if nonzero, then return a list of values E_1(x\*m) for m = 1,2,3,...,n. This is useful, e.g., when computing derivatives of L-functions. OUTPUT: - ``float`` - if n is 0 (the default) or - ``list`` - list of floats if n 0 EXAMPLES:: sage: exponential_integral_1(2) 0.04890051070806112 sage: exponential_integral_1(2,4) # rel tol 1e-10 [0.04890051070806112, 0.0037793524098489067, 0.00036008245216265873, 3.7665622843924751e-05] sage: exponential_integral_1(0) +Infinity IMPLEMENTATION: We use the PARI C-library functions eint1 and veceint1. REFERENCE: - See page 262, Prop 5.6.12, of Cohen's book "A Course in Computational Algebraic Number Theory". REMARKS: When called with the optional argument n, the PARI C-library is fast for values of n up to some bound, then very very slow. For example, if x=5, then the computation takes less than a second for n=800000, and takes "forever" for n=900000. """ if isinstance(x, Expression): if x.is_trivial_zero(): from sage.rings.infinity import Infinity return Infinity else: raise NotImplementedError("Use the symbolic exponential integral " + "function: exp_integral_e1.") elif not is_inexact(x): # x is exact and not an expression if not x: # test if exact x == 0 quickly from sage.rings.infinity import Infinity return Infinity # else x is in not an exact 0 from sage.libs.pari.all import pari if n <= 0: return float(pari(x).eint1()) else: return [float(z) for z in pari(x).eint1(n)]