diff --git a/src/sage/calculus/calculus.py b/src/sage/calculus/calculus.py index 34abf305f70..37807450ac0 100644 --- a/src/sage/calculus/calculus.py +++ b/src/sage/calculus/calculus.py @@ -429,7 +429,7 @@ from sage.misc.parser import Parser, LookupNameMaker from sage.structure.element import Expression from sage.symbolic.ring import var, SR -from sage.symbolic.expression import symbol_table +from sage.symbolic.symbols import symbol_table from sage.symbolic.function import Function from sage.symbolic.function_factory import function_factory from sage.symbolic.integration.integral import (indefinite_integral, diff --git a/src/sage/functions/airy.py b/src/sage/functions/airy.py index eceb9e6eafc..11f4c56be8c 100644 --- a/src/sage/functions/airy.py +++ b/src/sage/functions/airy.py @@ -30,9 +30,9 @@ Verify that the Airy functions are solutions to the differential equation:: - sage: diff(airy_ai(x), x, 2) - x * airy_ai(x) + sage: diff(airy_ai(x), x, 2) - x * airy_ai(x) # needs sage.symbolic 0 - sage: diff(airy_bi(x), x, 2) - x * airy_bi(x) + sage: diff(airy_bi(x), x, 2) - x * airy_bi(x) # needs sage.symbolic 0 """ @@ -46,11 +46,17 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.symbolic.function import BuiltinFunction -from sage.symbolic.expression import Expression -from sage.symbolic.ring import SR -from sage.rings.integer_ring import ZZ from sage.calculus.functional import derivative +from sage.misc.lazy_import import lazy_import +from sage.rings.integer_ring import ZZ +from sage.structure.element import Expression +from sage.symbolic.function import BuiltinFunction + +lazy_import('sage.symbolic.ring', 'SR') + +lazy_import('sage.libs.mpmath.utils', 'call', as_='_mpmath_utils_call') +lazy_import('mpmath', ['airyai', 'airybi'], + as_=['_mpmath_airyai', '_mpmath_airybi']) class FunctionAiryAiGeneral(BuiltinFunction): @@ -76,6 +82,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.functions.airy import airy_ai_general sage: x, n = var('x n') sage: airy_ai_general(-2, x) @@ -95,10 +102,10 @@ def _derivative_(self, alpha, x, diff_param=None): EXAMPLES:: sage: from sage.functions.airy import airy_ai_general - sage: x, n = var('x n') - sage: derivative(airy_ai_general(n, x), x) + sage: x, n = var('x n') # needs sage.symbolic + sage: derivative(airy_ai_general(n, x), x) # needs sage.symbolic airy_ai(n + 1, x) - sage: derivative(airy_ai_general(n, x), n) + sage: derivative(airy_ai_general(n, x), n) # needs sage.symbolic Traceback (most recent call last): ... NotImplementedError: cannot differentiate airy_ai @@ -114,10 +121,10 @@ def _eval_(self, alpha, x): EXAMPLES:: sage: from sage.functions.airy import airy_ai_general - sage: x, n = var('x n') - sage: airy_ai_general(-2, 1.0) + sage: x, n = var('x n') # needs sage.symbolic + sage: airy_ai_general(-2, 1.0) # needs mpmath 0.136645379421096 - sage: airy_ai_general(n, 1.0) + sage: airy_ai_general(n, 1.0) # needs sage.symbolic airy_ai(n, 1.00000000000000) """ if not isinstance(x, Expression) and \ @@ -138,13 +145,11 @@ def _evalf_(self, alpha, x, parent=None, algorithm=None): EXAMPLES:: sage: from sage.functions.airy import airy_ai_general - sage: airy_ai_general(-2, 1.0) + sage: airy_ai_general(-2, 1.0) # needs mpmath 0.136645379421096 """ - import mpmath - from sage.libs.mpmath import utils as mpmath_utils - return mpmath_utils.call(mpmath.airyai, x, derivative=alpha, - parent=parent) + return _mpmath_utils_call(_mpmath_airyai, x, derivative=alpha, + parent=parent) class FunctionAiryAiSimple(BuiltinFunction): @@ -155,9 +160,9 @@ def __init__(self): EXAMPLES:: sage: from sage.functions.airy import airy_ai_simple - sage: f = airy_ai_simple(x); f + sage: f = airy_ai_simple(x); f # needs sage.symbolic airy_ai(x) - sage: airy_ai_simple(x)._sympy_() + sage: airy_ai_simple(x)._sympy_() # needs sage.symbolic airyai(x) """ BuiltinFunction.__init__(self, 'airy_ai', @@ -173,7 +178,7 @@ def _derivative_(self, x, diff_param=None): EXAMPLES:: sage: from sage.functions.airy import airy_ai_simple - sage: derivative(airy_ai_simple(x), x) + sage: derivative(airy_ai_simple(x), x) # needs sage.symbolic airy_ai_prime(x) """ return airy_ai_prime(x) @@ -183,13 +188,13 @@ def _eval_(self, x): EXAMPLES:: sage: from sage.functions.airy import airy_ai_simple - sage: airy_ai_simple(0) + sage: airy_ai_simple(0) # needs sage.symbolic 1/3*3^(1/3)/gamma(2/3) - sage: airy_ai_simple(0.0) + sage: airy_ai_simple(0.0) # needs mpmath 0.355028053887817 - sage: airy_ai_simple(I) + sage: airy_ai_simple(I) # needs sage.symbolic airy_ai(I) - sage: airy_ai_simple(1.0 * I) + sage: airy_ai_simple(1.0 * I) # needs sage.symbolic 0.331493305432141 - 0.317449858968444*I """ from .gamma import gamma @@ -202,27 +207,28 @@ def _evalf_(self, x, **kwargs): EXAMPLES:: sage: from sage.functions.airy import airy_ai_simple - sage: airy_ai_simple(0.0) + sage: airy_ai_simple(0.0) # needs mpmath 0.355028053887817 - sage: airy_ai_simple(1.0 * I) + sage: airy_ai_simple(1.0 * I) # needs sage.symbolic 0.331493305432141 - 0.317449858968444*I We can use several methods for numerical evaluation:: + sage: # needs sage.symbolic sage: airy_ai_simple(3).n(algorithm='mpmath') 0.00659113935746072 sage: airy_ai_simple(3).n(algorithm='mpmath', prec=100) 0.0065911393574607191442574484080 - sage: airy_ai_simple(3).n(algorithm='scipy') # rel tol 1e-10 + sage: airy_ai_simple(3).n(algorithm='scipy') # rel tol 1e-10 # needs scipy 0.006591139357460719 sage: airy_ai_simple(I).n(algorithm='scipy') # rel tol 1e-10 0.33149330543214117 - 0.3174498589684438*I TESTS:: - sage: parent(airy_ai_simple(3).n(algorithm='scipy')) + sage: parent(airy_ai_simple(3).n(algorithm='scipy')) # needs scipy sage.rings.real_mpfr sage.symbolic Real Field with 53 bits of precision - sage: airy_ai_simple(3).n(algorithm='scipy', prec=200) + sage: airy_ai_simple(3).n(algorithm='scipy', prec=200) # needs scipy sage.symbolic Traceback (most recent call last): ... NotImplementedError: airy_ai not implemented for precision > 53 @@ -246,9 +252,7 @@ def _evalf_(self, x, **kwargs): return CC(y) return parent(y) elif algorithm == 'mpmath': - import mpmath - from sage.libs.mpmath import utils as mpmath_utils - return mpmath_utils.call(mpmath.airyai, x, parent=parent) + return _mpmath_utils_call(_mpmath_airyai, x, parent=parent) else: raise ValueError("unknown algorithm '%s'" % algorithm) @@ -261,12 +265,13 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: x, n = var('x n') sage: airy_ai_prime(x) airy_ai_prime(x) sage: airy_ai_prime(0) -1/3*3^(2/3)/gamma(1/3) - sage: airy_ai_prime(x)._sympy_() + sage: airy_ai_prime(x)._sympy_() # needs sympy airyaiprime(x) """ BuiltinFunction.__init__(self, 'airy_ai_prime', @@ -280,7 +285,7 @@ def _derivative_(self, x, diff_param=None): """ EXAMPLES:: - sage: derivative(airy_ai_prime(x), x) + sage: derivative(airy_ai_prime(x), x) # needs sage.symbolic x*airy_ai(x) """ return x * airy_ai_simple(x) @@ -289,9 +294,9 @@ def _eval_(self, x): """ EXAMPLES:: - sage: airy_ai_prime(0) + sage: airy_ai_prime(0) # needs sage.symbolic -1/3*3^(2/3)/gamma(1/3) - sage: airy_ai_prime(0.0) + sage: airy_ai_prime(0.0) # needs mpmath -0.258819403792807 """ from .gamma import gamma @@ -303,25 +308,26 @@ def _evalf_(self, x, **kwargs): """ EXAMPLES:: - sage: airy_ai_prime(0.0) + sage: airy_ai_prime(0.0) # needs mpmath -0.258819403792807 We can use several methods for numerical evaluation:: + sage: # needs sage.symbolic sage: airy_ai_prime(4).n(algorithm='mpmath') -0.00195864095020418 sage: airy_ai_prime(4).n(algorithm='mpmath', prec=100) -0.0019586409502041789001381409184 - sage: airy_ai_prime(4).n(algorithm='scipy') # rel tol 1e-10 + sage: airy_ai_prime(4).n(algorithm='scipy') # rel tol 1e-10 # needs scipy -0.00195864095020418 - sage: airy_ai_prime(I).n(algorithm='scipy') # rel tol 1e-10 + sage: airy_ai_prime(I).n(algorithm='scipy') # rel tol 1e-10 # needs scipy -0.43249265984180707 + 0.09804785622924324*I TESTS:: - sage: parent(airy_ai_prime(3).n(algorithm='scipy')) + sage: parent(airy_ai_prime(3).n(algorithm='scipy')) # needs scipy sage.rings.real_mpfr sage.symbolic Real Field with 53 bits of precision - sage: airy_ai_prime(3).n(algorithm='scipy', prec=200) + sage: airy_ai_prime(3).n(algorithm='scipy', prec=200) # needs scipy sage.symbolic Traceback (most recent call last): ... NotImplementedError: airy_ai_prime not implemented @@ -346,9 +352,7 @@ def _evalf_(self, x, **kwargs): return CC(y) return parent(y) elif algorithm == 'mpmath': - import mpmath - from sage.libs.mpmath import utils as mpmath_utils - return mpmath_utils.call(mpmath.airyai, x, derivative=1, + return _mpmath_utils_call(_mpmath_airyai, x, derivative=1, parent=parent) else: raise ValueError("unknown algorithm '%s'" % algorithm) @@ -405,12 +409,13 @@ def airy_ai(alpha, x=None, hold_derivative=True, **kwds): EXAMPLES:: - sage: n, x = var('n x') - sage: airy_ai(x) + sage: n, x = var('n x') # needs sage.symbolic + sage: airy_ai(x) # needs sage.symbolic airy_ai(x) It can return derivatives or integrals:: + sage: # needs sage.symbolic sage: airy_ai(2, x) airy_ai(2, x) sage: airy_ai(1, x, hold_derivative=False) @@ -425,35 +430,35 @@ def airy_ai(alpha, x=None, hold_derivative=True, **kwds): It can be evaluated symbolically or numerically for real or complex values:: - sage: airy_ai(0) + sage: airy_ai(0) # needs sage.symbolic 1/3*3^(1/3)/gamma(2/3) - sage: airy_ai(0.0) + sage: airy_ai(0.0) # needs mpmath 0.355028053887817 - sage: airy_ai(I) + sage: airy_ai(I) # needs sage.symbolic airy_ai(I) - sage: airy_ai(1.0*I) + sage: airy_ai(1.0*I) # needs sage.symbolic 0.331493305432141 - 0.317449858968444*I The functions can be evaluated numerically either using mpmath. which can compute the values to arbitrary precision, and scipy:: - sage: airy_ai(2).n(prec=100) + sage: airy_ai(2).n(prec=100) # needs sage.symbolic 0.034924130423274379135322080792 - sage: airy_ai(2).n(algorithm='mpmath', prec=100) + sage: airy_ai(2).n(algorithm='mpmath', prec=100) # needs sage.symbolic 0.034924130423274379135322080792 - sage: airy_ai(2).n(algorithm='scipy') # rel tol 1e-10 + sage: airy_ai(2).n(algorithm='scipy') # rel tol 1e-10 # needs scipy sage.symbolic 0.03492413042327323 And the derivatives can be evaluated:: - sage: airy_ai(1, 0) + sage: airy_ai(1, 0) # needs sage.symbolic -1/3*3^(2/3)/gamma(1/3) - sage: airy_ai(1, 0.0) + sage: airy_ai(1, 0.0) # needs mpmath -0.258819403792807 Plots:: - sage: plot(airy_ai(x), (x, -10, 5)) + plot(airy_ai_prime(x), + sage: plot(airy_ai(x), (x, -10, 5)) + plot(airy_ai_prime(x), # needs sage.plot sage.symbolic ....: (x, -10, 5), color='red') Graphics object consisting of 2 graphics primitives @@ -515,6 +520,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.functions.airy import airy_bi_general sage: x, n = var('x n') sage: airy_bi_general(-2, x) @@ -534,10 +540,10 @@ def _derivative_(self, alpha, x, diff_param=None): EXAMPLES:: sage: from sage.functions.airy import airy_bi_general - sage: x, n = var('x n') - sage: derivative(airy_bi_general(n, x), x) + sage: x, n = var('x n') # needs sage.symbolic + sage: derivative(airy_bi_general(n, x), x) # needs sage.symbolic airy_bi(n + 1, x) - sage: derivative(airy_bi_general(n, x), n) + sage: derivative(airy_bi_general(n, x), n) # needs sage.symbolic Traceback (most recent call last): ... NotImplementedError: cannot differentiate airy_bi @@ -553,10 +559,10 @@ def _eval_(self, alpha, x): EXAMPLES:: sage: from sage.functions.airy import airy_bi_general - sage: x, n = var('x n') - sage: airy_bi_general(-2, 1.0) + sage: x, n = var('x n') # needs sage.symbolic + sage: airy_bi_general(-2, 1.0) # needs mpmath 0.388621540699059 - sage: airy_bi_general(n, 1.0) + sage: airy_bi_general(n, 1.0) # needs sage.symbolic airy_bi(n, 1.00000000000000) """ if not isinstance(x, Expression) and \ @@ -573,14 +579,14 @@ def _evalf_(self, alpha, x, **kwargs): EXAMPLES:: sage: from sage.functions.airy import airy_bi_general - sage: airy_bi_general(-2, 1.0) + sage: airy_bi_general(-2, 1.0) # needs mpmath 0.388621540699059 """ parent = kwargs.get('parent') import mpmath from sage.libs.mpmath import utils as mpmath_utils - return mpmath_utils.call(mpmath.airybi, x, derivative=alpha, + return _mpmath_utils_call(_mpmath_airybi, x, derivative=alpha, parent=parent) @@ -592,9 +598,9 @@ def __init__(self): EXAMPLES:: sage: from sage.functions.airy import airy_bi_simple - sage: f = airy_bi_simple(x); f + sage: f = airy_bi_simple(x); f # needs sage.symbolic airy_bi(x) - sage: f._sympy_() + sage: f._sympy_() # needs sympy sage.symbolic airybi(x) """ BuiltinFunction.__init__(self, 'airy_bi', @@ -610,7 +616,7 @@ def _derivative_(self, x, diff_param=None): EXAMPLES:: sage: from sage.functions.airy import airy_bi_simple - sage: derivative(airy_bi_simple(x), x) + sage: derivative(airy_bi_simple(x), x) # needs sage.symbolic airy_bi_prime(x) """ return airy_bi_prime(x) @@ -620,15 +626,15 @@ def _eval_(self, x): EXAMPLES:: sage: from sage.functions.airy import airy_bi_simple - sage: airy_bi_simple(0) + sage: airy_bi_simple(0) # needs sage.symbolic 1/3*3^(5/6)/gamma(2/3) - sage: airy_bi_simple(0.0) + sage: airy_bi_simple(0.0) # needs mpmath 0.614926627446001 - sage: airy_bi_simple(0).n() == airy_bi(0.0) + sage: airy_bi_simple(0).n() == airy_bi(0.0) # needs mpmath sage.symbolic True - sage: airy_bi_simple(I) + sage: airy_bi_simple(I) # needs sage.symbolic airy_bi(I) - sage: airy_bi_simple(1.0 * I) + sage: airy_bi_simple(1.0 * I) # needs sage.symbolic 0.648858208330395 + 0.344958634768048*I """ from .gamma import gamma @@ -641,27 +647,28 @@ def _evalf_(self, x, **kwargs): EXAMPLES:: sage: from sage.functions.airy import airy_bi_simple - sage: airy_bi_simple(0.0) + sage: airy_bi_simple(0.0) # needs mpmath 0.614926627446001 - sage: airy_bi_simple(1.0 * I) + sage: airy_bi_simple(1.0 * I) # needs sage.symbolic 0.648858208330395 + 0.344958634768048*I We can use several methods for numerical evaluation:: - sage: airy_bi_simple(3).n(algorithm='mpmath') + sage: # needs sage.symbolic + sage: airy_bi_simple(3).n(algorithm='mpmath') # needs mpmath 14.0373289637302 - sage: airy_bi_simple(3).n(algorithm='mpmath', prec=100) + sage: airy_bi_simple(3).n(algorithm='mpmath', prec=100) # needs mpmath 14.037328963730232031740267314 - sage: airy_bi_simple(3).n(algorithm='scipy') # rel tol 1e-10 + sage: airy_bi_simple(3).n(algorithm='scipy') # rel tol 1e-10 # needs scipy 14.037328963730136 - sage: airy_bi_simple(I).n(algorithm='scipy') # rel tol 1e-10 + sage: airy_bi_simple(I).n(algorithm='scipy') # rel tol 1e-10 # needs scipy 0.648858208330395 + 0.34495863476804844*I TESTS:: - sage: parent(airy_bi_simple(3).n(algorithm='scipy')) + sage: parent(airy_bi_simple(3).n(algorithm='scipy')) # needs scipy sage.rings.real_mpfr sage.symbolic Real Field with 53 bits of precision - sage: airy_bi_simple(3).n(algorithm='scipy', prec=200) + sage: airy_bi_simple(3).n(algorithm='scipy', prec=200) # needs scipy sage.symbolic Traceback (most recent call last): ... NotImplementedError: airy_bi not implemented for precision > 53 @@ -687,7 +694,7 @@ def _evalf_(self, x, **kwargs): elif algorithm == 'mpmath': import mpmath from sage.libs.mpmath import utils as mpmath_utils - return mpmath_utils.call(mpmath.airybi, x, parent=parent) + return _mpmath_utils_call(_mpmath_airybi, x, parent=parent) else: raise ValueError("unknown algorithm '%s'" % algorithm) @@ -700,12 +707,13 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: x, n = var('x n') sage: airy_bi_prime(x) airy_bi_prime(x) sage: airy_bi_prime(0) 3^(1/6)/gamma(1/3) - sage: airy_bi_prime(x)._sympy_() + sage: airy_bi_prime(x)._sympy_() # needs sympy airybiprime(x) """ BuiltinFunction.__init__(self, 'airy_bi_prime', @@ -719,7 +727,7 @@ def _derivative_(self, x, diff_param=None): """ EXAMPLES:: - sage: derivative(airy_bi_prime(x), x) + sage: derivative(airy_bi_prime(x), x) # needs sage.symbolic x*airy_bi(x) """ return x * airy_bi_simple(x) @@ -728,9 +736,9 @@ def _eval_(self, x): """ EXAMPLES:: - sage: airy_bi_prime(0) + sage: airy_bi_prime(0) # needs sage.symbolic 3^(1/6)/gamma(1/3) - sage: airy_bi_prime(0.0) + sage: airy_bi_prime(0.0) # needs mpmath 0.448288357353826 """ from .gamma import gamma @@ -742,25 +750,26 @@ def _evalf_(self, x, **kwargs): """ EXAMPLES:: - sage: airy_bi_prime(0.0) + sage: airy_bi_prime(0.0) # needs mpmath 0.448288357353826 We can use several methods for numerical evaluation:: + sage: # needs sage.symbolic sage: airy_bi_prime(4).n(algorithm='mpmath') 161.926683504613 sage: airy_bi_prime(4).n(algorithm='mpmath', prec=100) 161.92668350461340184309492429 - sage: airy_bi_prime(4).n(algorithm='scipy') # rel tol 1e-10 + sage: airy_bi_prime(4).n(algorithm='scipy') # rel tol 1e-10 # needs scipy 161.92668350461398 sage: airy_bi_prime(I).n(algorithm='scipy') # rel tol 1e-10 0.135026646710819 - 0.1288373867812549*I TESTS:: - sage: parent(airy_bi_prime(3).n(algorithm='scipy')) + sage: parent(airy_bi_prime(3).n(algorithm='scipy')) # needs scipy sage.rings.real_mpfr sage.symbolic Real Field with 53 bits of precision - sage: airy_bi_prime(3).n(algorithm='scipy', prec=200) + sage: airy_bi_prime(3).n(algorithm='scipy', prec=200) # needs scipy sage.symbolic Traceback (most recent call last): ... NotImplementedError: airy_bi_prime not implemented @@ -785,9 +794,7 @@ def _evalf_(self, x, **kwargs): return CC(y) return parent(y) elif algorithm == 'mpmath': - import mpmath - from sage.libs.mpmath import utils as mpmath_utils - return mpmath_utils.call(mpmath.airybi, x, derivative=1, + return _mpmath_utils_call(_mpmath_airybi, x, derivative=1, parent=parent) else: raise ValueError("unknown algorithm '%s'" % algorithm) @@ -845,12 +852,13 @@ def airy_bi(alpha, x=None, hold_derivative=True, **kwds): EXAMPLES:: - sage: n, x = var('n x') - sage: airy_bi(x) + sage: n, x = var('n x') # needs sage.symbolic + sage: airy_bi(x) # needs sage.symbolic airy_bi(x) It can return derivatives or integrals:: + sage: # needs sage.symbolic sage: airy_bi(2, x) airy_bi(2, x) sage: airy_bi(1, x, hold_derivative=False) @@ -865,35 +873,35 @@ def airy_bi(alpha, x=None, hold_derivative=True, **kwds): It can be evaluated symbolically or numerically for real or complex values:: - sage: airy_bi(0) + sage: airy_bi(0) # needs sage.symbolic 1/3*3^(5/6)/gamma(2/3) - sage: airy_bi(0.0) + sage: airy_bi(0.0) # needs mpmath 0.614926627446001 - sage: airy_bi(I) + sage: airy_bi(I) # needs sage.symbolic airy_bi(I) - sage: airy_bi(1.0*I) + sage: airy_bi(1.0*I) # needs sage.symbolic 0.648858208330395 + 0.344958634768048*I The functions can be evaluated numerically using mpmath, which can compute the values to arbitrary precision, and scipy:: - sage: airy_bi(2).n(prec=100) + sage: airy_bi(2).n(prec=100) # needs sage.symbolic 3.2980949999782147102806044252 - sage: airy_bi(2).n(algorithm='mpmath', prec=100) + sage: airy_bi(2).n(algorithm='mpmath', prec=100) # needs sage.symbolic 3.2980949999782147102806044252 - sage: airy_bi(2).n(algorithm='scipy') # rel tol 1e-10 + sage: airy_bi(2).n(algorithm='scipy') # rel tol 1e-10 # needs scipy sage.symbolic 3.2980949999782134 And the derivatives can be evaluated:: - sage: airy_bi(1, 0) + sage: airy_bi(1, 0) # needs sage.symbolic 3^(1/6)/gamma(1/3) - sage: airy_bi(1, 0.0) + sage: airy_bi(1, 0.0) # needs mpmath 0.448288357353826 Plots:: - sage: plot(airy_bi(x), (x, -10, 5)) + plot(airy_bi_prime(x), + sage: plot(airy_bi(x), (x, -10, 5)) + plot(airy_bi_prime(x), # needs sage.plot sage.symbolic ....: (x, -10, 5), color='red') Graphics object consisting of 2 graphics primitives diff --git a/src/sage/functions/bessel.py b/src/sage/functions/bessel.py index 48607c49f56..24ee74b561c 100644 --- a/src/sage/functions/bessel.py +++ b/src/sage/functions/bessel.py @@ -122,33 +122,34 @@ Evaluate the Bessel J function symbolically and numerically:: + sage: # needs sage.symbolic sage: bessel_J(0, x) bessel_J(0, x) sage: bessel_J(0, 0) 1 sage: bessel_J(0, x).diff(x) -1/2*bessel_J(1, x) + 1/2*bessel_J(-1, x) - - sage: N(bessel_J(0, 0), digits = 20) + sage: N(bessel_J(0, 0), digits=20) 1.0000000000000000000 - sage: find_root(bessel_J(0,x), 0, 5) + sage: find_root(bessel_J(0,x), 0, 5) # needs scipy 2.404825557695773 Plot the Bessel J function:: - sage: f(x) = Bessel(0)(x); f + sage: f(x) = Bessel(0)(x); f # needs sage.symbolic x |--> bessel_J(0, x) - sage: plot(f, (x, 1, 10)) + sage: plot(f, (x, 1, 10)) # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive Visualize the Bessel Y function on the complex plane (set plot_points to a higher value to get more detail):: - sage: complex_plot(bessel_Y(0, x), (-5, 5), (-5, 5), plot_points=20) + sage: complex_plot(bessel_Y(0, x), (-5, 5), (-5, 5), plot_points=20) # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive Evaluate a combination of Bessel functions:: + sage: # needs sage.symbolic sage: f(x) = bessel_J(1, x) - bessel_Y(0, x) sage: f(pi) bessel_J(1, pi) - bessel_Y(0, pi) @@ -160,6 +161,7 @@ Symbolically solve a second order differential equation with initial conditions `y(1) = a` and `y'(1) = b` in terms of Bessel functions:: + sage: # needs sage.symbolic sage: y = function('y')(x) sage: a, b = var('a, b') sage: diffeq = x^2*diff(y,x,x) + x*diff(y,x) + x^2*y == 0 @@ -212,18 +214,30 @@ from sage.misc.functional import sqrt from sage.functions.log import exp +from sage.functions.gamma import gamma from sage.functions.hyperbolic import sinh, cosh from sage.functions.trig import sin, cos -from sage.libs.mpmath import utils as mpmath_utils -from sage.misc.latex import latex +from sage.misc.lazy_import import lazy_import +from sage.rings.infinity import infinity, unsigned_infinity from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ -from sage.structure.element import get_coercion_model -from sage.symbolic.constants import pi -from sage.symbolic.ring import SR +from sage.structure.element import Expression, get_coercion_model from sage.symbolic.function import BuiltinFunction -from sage.symbolic.expression import Expression + +lazy_import('sage.misc.latex', 'latex') + +lazy_import('sage.symbolic.constants', 'pi') +lazy_import('sage.symbolic.ring', 'SR') + +lazy_import('sage.libs.mpmath.utils', 'call', as_='_mpmath_utils_call') +lazy_import('mpmath', + ['besseli', 'besselj', 'besselk', + 'bessely', 'hankel1', 'hankel2', + 'struveh', 'struvel'], + as_=['_mpmath_besseli', '_mpmath_besselj', '_mpmath_besselk', + '_mpmath_bessely', '_mpmath_hankel1', '_mpmath_hankel2', + '_mpmath_struveh', '_mpmath_struvel']) class Function_Bessel_J(BuiltinFunction): @@ -258,11 +272,12 @@ class Function_Bessel_J(BuiltinFunction): EXAMPLES:: - sage: bessel_J(1.0, 1.0) + sage: bessel_J(1.0, 1.0) # needs mpmath 0.440050585744933 + + sage: # needs sage.symbolic sage: bessel_J(2, I).n(digits=30) -0.135747669767038281182852569995 - sage: bessel_J(1, x) bessel_J(1, x) sage: n = var('n') @@ -271,34 +286,34 @@ class Function_Bessel_J(BuiltinFunction): Examples of symbolic manipulation:: + sage: # needs sage.symbolic sage: a = bessel_J(pi, bessel_J(1, I)); a bessel_J(pi, bessel_J(1, I)) sage: N(a, digits=20) 0.00059023706363796717363 - 0.0026098820470081958110*I - sage: f = bessel_J(2, x) sage: f.diff(x) -1/2*bessel_J(3, x) + 1/2*bessel_J(1, x) Comparison to a well-known integral representation of `J_1(1)`:: - sage: A = numerical_integral(1/pi*cos(x - sin(x)), 0, pi) - sage: A[0] # abs tol 1e-14 + sage: A = numerical_integral(1/pi*cos(x - sin(x)), 0, pi) # needs sage.symbolic + sage: A[0] # abs tol 1e-14 # needs sage.symbolic 0.44005058574493355 - sage: bessel_J(1.0, 1.0) - A[0] < 1e-15 + sage: bessel_J(1.0, 1.0) - A[0] < 1e-15 # needs sage.symbolic True Integration is supported directly and through Maxima:: - sage: f = bessel_J(2, x) - sage: f.integrate(x) + sage: f = bessel_J(2, x) # needs sage.symbolic + sage: f.integrate(x) # needs sage.symbolic 1/24*x^3*hypergeometric((3/2,), (5/2, 3), -1/4*x^2) Visualization (set plot_points to a higher value to get more detail):: - sage: plot(bessel_J(1,x), (x,0,5), color='blue') + sage: plot(bessel_J(1,x), (x,0,5), color='blue') # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive - sage: complex_plot(bessel_J(1, x), (-5, 5), (-5, 5), plot_points=20) + sage: complex_plot(bessel_J(1, x), (-5, 5), (-5, 5), plot_points=20) # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive ALGORITHM: @@ -308,7 +323,7 @@ class Function_Bessel_J(BuiltinFunction): Check whether the return value is real whenever the argument is real (:trac:`10251`):: - sage: bessel_J(5, 1.5) in RR + sage: bessel_J(5, 1.5) in RR # needs mpmath True REFERENCES: @@ -327,7 +342,7 @@ def __init__(self): sage: sage.functions.bessel.Function_Bessel_J() bessel_J - sage: bessel_J(x, x)._sympy_() + sage: bessel_J(x, x)._sympy_() # needs sympy sage.symbolic besselj(x, x) """ BuiltinFunction.__init__(self, 'bessel_J', nargs=2, @@ -342,6 +357,7 @@ def _eval_(self, n, x): """ EXAMPLES:: + sage: # needs sage.symbolic sage: n = var('n') sage: bessel_J(0, 0) 1 @@ -358,7 +374,6 @@ def _eval_(self, n, x): sage: bessel_J(n, 0) bessel_J(n, 0) """ - from sage.rings.infinity import unsigned_infinity if not isinstance(x, Expression) and x == 0: if n == 0: return ZZ.one() @@ -375,15 +390,16 @@ def _evalf_(self, n, x, parent=None, algorithm=None): """ EXAMPLES:: - sage: bessel_J(0.0, 1.0) + sage: bessel_J(0.0, 1.0) # needs mpmath 0.765197686557967 - sage: bessel_J(0, 1).n(digits=20) + sage: bessel_J(0, 1).n(digits=20) # needs sage.symbolic 0.76519768655796655145 - sage: bessel_J(0.5, 1.5) + sage: bessel_J(0.5, 1.5) # needs mpmath 0.649838074753747 Check for correct rounding (:trac:`17122`):: + sage: # needs sage.rings.real_mpfr sage: R = RealField(113) sage: a = R("8.935761195587725798762818805462843676e-01") sage: aa = RealField(200)(a) @@ -402,8 +418,7 @@ def _evalf_(self, n, x, parent=None, algorithm=None): pass n, x = get_coercion_model().canonical_coercion(n, x) - import mpmath - return mpmath_utils.call(mpmath.besselj, n, x, parent=parent) + return _mpmath_utils_call(_mpmath_besselj, n, x, parent=parent) def _derivative_(self, n, x, diff_param): """ @@ -411,6 +426,7 @@ def _derivative_(self, n, x, diff_param): EXAMPLES:: + sage: # needs sage.symbolic sage: f(z) = bessel_J(10, z) sage: derivative(f, z) z |--> -1/2*bessel_J(11, z) + 1/2*bessel_J(9, z) @@ -432,7 +448,7 @@ def _print_latex_(self, n, z): EXAMPLES:: - sage: latex(bessel_J(1, x)) + sage: latex(bessel_J(1, x)) # needs sage.symbolic J_{1}(x) """ return r"J_{%s}(%s)" % (latex(n), latex(z)) @@ -466,10 +482,12 @@ class Function_Bessel_Y(BuiltinFunction): EXAMPLES:: - sage: bessel_Y(1, x) + sage: bessel_Y(1, x) # needs sage.symbolic bessel_Y(1, x) - sage: bessel_Y(1.0, 1.0) + sage: bessel_Y(1.0, 1.0) # needs mpmath -0.781212821300289 + + sage: # needs sage.symbolic sage: n = var('n') sage: bessel_Y(n, x) bessel_Y(n, x) @@ -482,29 +500,30 @@ class Function_Bessel_Y(BuiltinFunction): Examples of symbolic manipulation:: + sage: # needs sage.symbolic sage: a = bessel_Y(pi, bessel_Y(1, I)); a bessel_Y(pi, bessel_Y(1, I)) sage: N(a, digits=20) 4.2059146571791095708 + 21.307914215321993526*I - sage: f = bessel_Y(2, x) sage: f.diff(x) -1/2*bessel_Y(3, x) + 1/2*bessel_Y(1, x) High precision and complex valued inputs (see :trac:`4230`):: - sage: bessel_Y(0, 1).n(128) + sage: bessel_Y(0, 1).n(128) # needs sage.symbolic 0.088256964215676957982926766023515162828 - sage: bessel_Y(0, RealField(200)(1)) + sage: bessel_Y(0, RealField(200)(1)) # needs sage.rings.real_mpfr 0.088256964215676957982926766023515162827817523090675546711044 - sage: bessel_Y(0, ComplexField(200)(0.5+I)) - 0.077763160184438051408593468823822434235010300228009867784073 + 1.0142336049916069152644677682828326441579314239591288411739*I + sage: bessel_Y(0, ComplexField(200)(0.5+I)) # needs sage.symbolic + 0.077763160184438051408593468823822434235010300228009867784073 + + 1.0142336049916069152644677682828326441579314239591288411739*I Visualization (set plot_points to a higher value to get more detail):: - sage: plot(bessel_Y(1,x), (x,0,5), color='blue') + sage: plot(bessel_Y(1, x), (x, 0, 5), color='blue') # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive - sage: complex_plot(bessel_Y(1, x), (-5, 5), (-5, 5), plot_points=20) + sage: complex_plot(bessel_Y(1, x), (-5, 5), (-5, 5), plot_points=20) # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive ALGORITHM: @@ -516,11 +535,12 @@ class Function_Bessel_Y(BuiltinFunction): Check whether the return value is real whenever the argument is real (:trac:`10251`):: - sage: bessel_Y(5, 1.5) in RR + sage: bessel_Y(5, 1.5) in RR # needs mpmath True Coercion works correctly (see :trac:`17130`):: + sage: # needs sage.rings.real_mpfr sage: r = bessel_Y(RealField(200)(1), 1.0); r -0.781212821300289 sage: parent(r) @@ -544,9 +564,9 @@ def __init__(self): EXAMPLES:: - sage: sage.functions.bessel.Function_Bessel_Y()(0, x) + sage: sage.functions.bessel.Function_Bessel_Y()(0, x) # needs sage.symbolic bessel_Y(0, x) - sage: bessel_Y(x, x)._sympy_() + sage: bessel_Y(x, x)._sympy_() # needs sympy sage.symbolic bessely(x, x) """ BuiltinFunction.__init__(self, 'bessel_Y', nargs=2, @@ -561,6 +581,7 @@ def _eval_(self, n, x): """ EXAMPLES:: + sage: # needs sage.symbolic sage: bessel_Y(1, 0) Infinity sage: bessel_Y(I,0) @@ -572,10 +593,9 @@ def _eval_(self, n, x): TESTS:: - sage: bessel_Y(0, 0) + sage: bessel_Y(0, 0) # needs sage.symbolic -Infinity """ - from sage.rings.infinity import infinity, unsigned_infinity if not isinstance(x, Expression) and x == 0: if n == 0: return -infinity @@ -590,15 +610,16 @@ def _evalf_(self, n, x, parent=None, algorithm=None): """ EXAMPLES:: - sage: bessel_Y(0.5, 1.5) + sage: bessel_Y(0.5, 1.5) # needs mpmath -0.0460831658930974 - sage: bessel_Y(1.0+2*I, 3.0+4*I) + sage: bessel_Y(1.0+2*I, 3.0+4*I) # needs mpmath sage.symbolic 0.699410324467538 + 0.228917940896421*I - sage: bessel_Y(0, 1).n(256) + sage: bessel_Y(0, 1).n(256) # needs mpmath sage.symbolic 0.08825696421567695798292676602351516282781752309067554671104384761199978932351 Check for correct rounding (:trac:`17122`):: + sage: # needs mpmath sage.rings.real_mpfr sage: R = RealField(113) sage: a = R("8.935761195587725798762818805462843676e-01") sage: aa = RealField(200)(a) @@ -617,8 +638,7 @@ def _evalf_(self, n, x, parent=None, algorithm=None): pass n, x = get_coercion_model().canonical_coercion(n, x) - import mpmath - return mpmath_utils.call(mpmath.bessely, n, x, parent=parent) + return _mpmath_utils_call(_mpmath_bessely, n, x, parent=parent) def _derivative_(self, n, x, diff_param): """ @@ -626,6 +646,7 @@ def _derivative_(self, n, x, diff_param): EXAMPLES:: + sage: # needs sage.symbolic sage: f(x) = bessel_Y(10, x) sage: derivative(f, x) x |--> -1/2*bessel_Y(11, x) + 1/2*bessel_Y(9, x) @@ -646,7 +667,7 @@ def _print_latex_(self, n, z): EXAMPLES:: - sage: latex(bessel_Y(1, x)) + sage: latex(bessel_Y(1, x)) # needs sage.symbolic Y_{1}(x) """ return r"Y_{%s}(%s)" % (latex(n), latex(z)) @@ -667,10 +688,12 @@ class Function_Bessel_I(BuiltinFunction): EXAMPLES:: + sage: bessel_I(1.0, 1.0) # needs mpmath + 0.565159103992485 + + sage: # needs sage.symbolic sage: bessel_I(1, x) bessel_I(1, x) - sage: bessel_I(1.0, 1.0) - 0.565159103992485 sage: n = var('n') sage: bessel_I(n, x) bessel_I(n, x) @@ -679,16 +702,17 @@ class Function_Bessel_I(BuiltinFunction): Examples of symbolic manipulation:: + sage: # needs sage.symbolic sage: a = bessel_I(pi, bessel_I(1, I)) sage: N(a, digits=20) 0.00026073272117205890524 - 0.0011528954889080572268*I - sage: f = bessel_I(2, x) sage: f.diff(x) 1/2*bessel_I(3, x) + 1/2*bessel_I(1, x) Special identities that bessel_I satisfies:: + sage: # needs sage.symbolic sage: bessel_I(1/2, x) sqrt(2)*sqrt(1/(pi*x))*sinh(x) sage: eq = bessel_I(1/2, x) == bessel_I(0.5, x) @@ -702,25 +726,26 @@ class Function_Bessel_I(BuiltinFunction): Examples of asymptotic behavior:: - sage: limit(bessel_I(0, x), x=oo) + sage: limit(bessel_I(0, x), x=oo) # needs sage.symbolic +Infinity - sage: limit(bessel_I(0, x), x=0) + sage: limit(bessel_I(0, x), x=0) # needs sage.symbolic 1 High precision and complex valued inputs:: - sage: bessel_I(0, 1).n(128) + sage: bessel_I(0, 1).n(128) # needs sage.symbolic 1.2660658777520083355982446252147175376 - sage: bessel_I(0, RealField(200)(1)) + sage: bessel_I(0, RealField(200)(1)) # needs sage.rings.real_mpfr 1.2660658777520083355982446252147175376076703113549622068081 - sage: bessel_I(0, ComplexField(200)(0.5+I)) - 0.80644357583493619472428518415019222845373366024179916785502 + 0.22686958987911161141397453401487525043310874687430711021434*I + sage: bessel_I(0, ComplexField(200)(0.5+I)) # needs sage.symbolic + 0.80644357583493619472428518415019222845373366024179916785502 + + 0.22686958987911161141397453401487525043310874687430711021434*I Visualization (set plot_points to a higher value to get more detail):: - sage: plot(bessel_I(1,x), (x,0,5), color='blue') + sage: plot(bessel_I(1, x), (x, 0, 5), color='blue') # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive - sage: complex_plot(bessel_I(1, x), (-5, 5), (-5, 5), plot_points=20) + sage: complex_plot(bessel_I(1, x), (-5, 5), (-5, 5), plot_points=20) # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive ALGORITHM: @@ -730,12 +755,12 @@ class Function_Bessel_I(BuiltinFunction): TESTS:: - sage: N(bessel_I(1,1),500) + sage: N(bessel_I(1,1),500) # needs sage.symbolic 0.565159103992485027207696027609863307328899621621092009480294489479255640964371134092664997766814410064677886055526302676857637684917179812041131208121 Check whether the return value is real whenever the argument is real (:trac:`10251`):: - sage: bessel_I(5, 1.5) in RR + sage: bessel_I(5, 1.5) in RR # needs mpmath True REFERENCES: @@ -752,9 +777,9 @@ def __init__(self): EXAMPLES:: - sage: bessel_I(1,x) + sage: bessel_I(1, x) # needs sage.symbolic bessel_I(1, x) - sage: bessel_I(x, x)._sympy_() + sage: bessel_I(x, x)._sympy_() # needs sympy sage.symbolic besseli(x, x) """ BuiltinFunction.__init__(self, 'bessel_I', nargs=2, @@ -768,6 +793,7 @@ def _eval_(self, n, x): """ EXAMPLES:: + sage: # needs sage.symbolic sage: n,y = var('n,y') sage: bessel_I(y, x) bessel_I(y, x) @@ -784,7 +810,6 @@ def _eval_(self, n, x): sage: bessel_I(n, 0) bessel_I(n, 0) """ - from sage.rings.infinity import unsigned_infinity if not isinstance(x, Expression) and x == 0: if n == 0: return ZZ.one() @@ -801,13 +826,12 @@ def _evalf_(self, n, x, parent=None, algorithm=None): """ EXAMPLES:: - sage: bessel_I(0.0, 1.0) + sage: bessel_I(0.0, 1.0) # needs mpmath 1.26606587775201 - sage: bessel_I(1,3).n(digits=20) + sage: bessel_I(1,3).n(digits=20) # needs sage.symbolic 3.9533702174026093965 """ - import mpmath - return mpmath_utils.call(mpmath.besseli, n, x, parent=parent) + return _mpmath_utils_call(_mpmath_besseli, n, x, parent=parent) def _derivative_(self, n, x, diff_param): """ @@ -816,6 +840,7 @@ def _derivative_(self, n, x, diff_param): EXAMPLES:: + sage: # needs sage.symbolic sage: f(z) = bessel_I(10, x) sage: derivative(f, x) z |--> 1/2*bessel_I(11, x) + 1/2*bessel_I(9, x) @@ -836,7 +861,7 @@ def _print_latex_(self, n, z): EXAMPLES:: - sage: latex(bessel_I(1, x)) + sage: latex(bessel_I(1, x)) # needs sage.symbolic I_{1}(x) """ return r"I_{%s}(%s)" % (latex(n), latex(z)) @@ -857,10 +882,12 @@ class Function_Bessel_K(BuiltinFunction): EXAMPLES:: + sage: bessel_K(1.0, 1.0) # needs mpmath + 0.601907230197235 + + sage: # needs sage.symbolic sage: bessel_K(1, x) bessel_K(1, x) - sage: bessel_K(1.0, 1.0) - 0.601907230197235 sage: n = var('n') sage: bessel_K(n, x) bessel_K(n, x) @@ -869,15 +896,14 @@ class Function_Bessel_K(BuiltinFunction): Examples of symbolic manipulation:: + sage: # needs sage.symbolic sage: a = bessel_K(pi, bessel_K(1, I)); a bessel_K(pi, bessel_K(1, I)) sage: N(a, digits=20) 3.8507583115005220156 + 0.068528298579883425456*I - sage: f = bessel_K(2, x) sage: f.diff(x) -1/2*bessel_K(3, x) - 1/2*bessel_K(1, x) - sage: bessel_K(1/2, x) sqrt(1/2)*sqrt(pi)*e^(-x)/sqrt(x) sage: bessel_K(1/2, -1) @@ -887,27 +913,28 @@ class Function_Bessel_K(BuiltinFunction): Examples of asymptotic behavior:: - sage: bessel_K(0, 0.0) + sage: bessel_K(0, 0.0) # needs mpmath +infinity - sage: limit(bessel_K(0, x), x=0) + sage: limit(bessel_K(0, x), x=0) # needs sage.symbolic +Infinity - sage: limit(bessel_K(0, x), x=oo) + sage: limit(bessel_K(0, x), x=oo) # needs sage.symbolic 0 High precision and complex valued inputs:: - sage: bessel_K(0, 1).n(128) + sage: bessel_K(0, 1).n(128) # needs sage.symbolic 0.42102443824070833333562737921260903614 - sage: bessel_K(0, RealField(200)(1)) + sage: bessel_K(0, RealField(200)(1)) # needs sage.rings.real_mpfr 0.42102443824070833333562737921260903613621974822666047229897 - sage: bessel_K(0, ComplexField(200)(0.5+I)) - 0.058365979093103864080375311643360048144715516692187818271179 - 0.67645499731334483535184142196073004335768129348518210260256*I + sage: bessel_K(0, ComplexField(200)(0.5+I)) # needs sage.rings.real_mpfr sage.symbolic + 0.058365979093103864080375311643360048144715516692187818271179 + - 0.67645499731334483535184142196073004335768129348518210260256*I Visualization (set plot_points to a higher value to get more detail):: - sage: plot(bessel_K(1,x), (x,0,5), color='blue') + sage: plot(bessel_K(1,x), (x,0,5), color='blue') # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive - sage: complex_plot(bessel_K(1, x), (-5, 5), (-5, 5), plot_points=20) + sage: complex_plot(bessel_K(1, x), (-5, 5), (-5, 5), plot_points=20) # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive ALGORITHM: @@ -921,13 +948,13 @@ class Function_Bessel_K(BuiltinFunction): The Bessel K function can be evaluated numerically at complex orders:: - sage: bessel_K(10 * I, 10).n() + sage: bessel_K(10 * I, 10).n() # needs sage.symbolic 9.82415743819925e-8 For a fixed imaginary order and increasing, real, second component the value of Bessel K is exponentially decaying:: - sage: for x in [10, 20, 50, 100, 200]: print(bessel_K(5*I, x).n()) + sage: for x in [10, 20, 50, 100, 200]: print(bessel_K(5*I, x).n()) # needs sage.symbolic 5.27812176514912e-6 3.11005908421801e-10 2.66182488515423e-23 - 8.59622057747552e-58*I @@ -936,7 +963,7 @@ class Function_Bessel_K(BuiltinFunction): Check whether the return value is real whenever the argument is real (:trac:`10251`):: - sage: bessel_K(5, 1.5) in RR + sage: bessel_K(5, 1.5) in RR # needs mpmath True REFERENCES: @@ -955,7 +982,7 @@ def __init__(self): sage: sage.functions.bessel.Function_Bessel_K() bessel_K - sage: bessel_K(x, x)._sympy_() + sage: bessel_K(x, x)._sympy_() # needs sympy sage.symbolic besselk(x, x) """ BuiltinFunction.__init__(self, 'bessel_K', nargs=2, @@ -969,6 +996,7 @@ def _eval_(self, n, x): """ EXAMPLES:: + sage: # needs sage.symbolic sage: n = var('n') sage: bessel_K(1, 0) Infinity @@ -979,10 +1007,9 @@ def _eval_(self, n, x): TESTS:: - sage: bessel_K(0, 0) + sage: bessel_K(0, 0) # needs sage.symbolic +Infinity """ - from sage.rings.infinity import infinity, unsigned_infinity if not isinstance(x, Expression) and x == 0: if n == 0: return infinity @@ -995,15 +1022,14 @@ def _evalf_(self, n, x, parent=None, algorithm=None): """ EXAMPLES:: - sage: bessel_K(0.0, 1.0) + sage: bessel_K(0.0, 1.0) # needs mpmath 0.421024438240708 - sage: bessel_K(-1, 1).n(128) + sage: bessel_K(-1, 1).n(128) # needs sage.symbolic 0.60190723019723457473754000153561733926 - sage: bessel_K(0, RealField(128)(1)) + sage: bessel_K(0, RealField(128)(1)) # needs sage.rings.real_mpfr 0.42102443824070833333562737921260903614 """ - import mpmath - return mpmath_utils.call(mpmath.besselk, n, x, parent=parent) + return _mpmath_utils_call(_mpmath_besselk, n, x, parent=parent) def _derivative_(self, n, x, diff_param): """ @@ -1011,6 +1037,7 @@ def _derivative_(self, n, x, diff_param): EXAMPLES:: + sage: # needs sage.symbolic sage: f(x) = bessel_K(10, x) sage: derivative(f, x) x |--> -1/2*bessel_K(11, x) - 1/2*bessel_K(9, x) @@ -1031,7 +1058,7 @@ def _print_latex_(self, n, z): EXAMPLES:: - sage: latex(bessel_K(1, x)) + sage: latex(bessel_K(1, x)) # needs sage.symbolic K_{1}(x) """ return r"K_{%s}(%s)" % (latex(n), latex(z)) @@ -1049,15 +1076,15 @@ def Bessel(*args, **kwds): A function factory that produces symbolic I, J, K, and Y Bessel functions. There are several ways to call this function: - - ``Bessel(order, type)`` - - ``Bessel(order)`` -- type defaults to 'J' - - ``Bessel(order, typ=T)`` - - ``Bessel(typ=T)`` -- order is unspecified, this is a 2-parameter - function - - ``Bessel()`` -- order is unspecified, type is 'J' + - ``Bessel(order, type)`` + - ``Bessel(order)`` -- type defaults to ``'J'`` + - ``Bessel(order, typ=T)`` + - ``Bessel(typ=T)`` -- order is unspecified, this is a 2-parameter + function + - ``Bessel()`` -- order is unspecified, type is ``'J'`` - where ``order`` can be any integer and T must be one of the strings 'I', - 'J', 'K', or 'Y'. + where ``order`` can be any integer and ``T`` must be one of the strings ``'I'``, + ``'J'``, ``'K'``, or ``'Y'``. See the EXAMPLES below. @@ -1067,53 +1094,58 @@ def Bessel(*args, **kwds): sage: Bessel() bessel_J + sage: Bessel(typ='K') + bessel_K + + sage: # needs sage.symbolic sage: Bessel(1)(x) bessel_J(1, x) sage: Bessel(1, 'Y')(x) bessel_Y(1, x) sage: Bessel(-2, 'Y')(x) bessel_Y(-2, x) - sage: Bessel(typ='K') - bessel_K sage: Bessel(0, typ='I')(x) bessel_I(0, x) Evaluation:: sage: f = Bessel(1) - sage: f(3.0) + sage: f(3.0) # needs mpmath 0.339058958525936 + + sage: # needs sage.symbolic sage: f(3) bessel_J(1, 3) sage: f(3).n(digits=50) 0.33905895852593645892551459720647889697308041819801 - sage: g = Bessel(typ='J') sage: g(1,3) bessel_J(1, 3) sage: g(2, 3+I).n() 0.634160370148554 + 0.0253384000032695*I - sage: abs(numerical_integral(1/pi*cos(3*sin(x)), 0.0, pi)[0] - Bessel(0, 'J')(3.0)) < 1e-15 + sage: abs(numerical_integral(1/pi*cos(3*sin(x)), 0.0, pi)[0] + ....: - Bessel(0, 'J')(3.0)) < 1e-15 True Symbolic calculus:: - sage: f(x) = Bessel(0, 'J')(x) - sage: derivative(f, x) + sage: f(x) = Bessel(0, 'J')(x) # needs sage.symbolic + sage: derivative(f, x) # needs sage.symbolic x |--> -1/2*bessel_J(1, x) + 1/2*bessel_J(-1, x) - sage: derivative(f, x, x) + sage: derivative(f, x, x) # needs sage.symbolic x |--> 1/4*bessel_J(2, x) - 1/2*bessel_J(0, x) + 1/4*bessel_J(-2, x) Verify that `J_0` satisfies Bessel's differential equation numerically using the ``test_relation()`` method:: - sage: y = bessel_J(0, x) - sage: diffeq = x^2*derivative(y,x,x) + x*derivative(y,x) + x^2*y == 0 - sage: diffeq.test_relation(proof=False) + sage: y = bessel_J(0, x) # needs sage.symbolic + sage: diffeq = x^2*derivative(y,x,x) + x*derivative(y,x) + x^2*y == 0 # needs sage.symbolic + sage: diffeq.test_relation(proof=False) # needs sage.symbolic True Conversion to other systems:: + sage: # needs sage.symbolic sage: x,y = var('x,y') sage: f = Bessel(typ='K')(x,y) sage: expected = f.derivative(y) @@ -1125,6 +1157,7 @@ def Bessel(*args, **kwds): satisfies `y(1) = 1` and `y'(1) = 1`, then verify the initial conditions and plot it:: + sage: # needs sage.symbolic sage: y = function('y')(x) sage: diffeq = x^2*diff(y,x,x) + x*diff(y,x) + x^2*y == 0 sage: f = desolve(diffeq, y, [1, 1, 1]); f @@ -1132,37 +1165,39 @@ def Bessel(*args, **kwds): 1)*bessel_Y(1, 1) - bessel_J(1, 1)*bessel_Y(0, 1)) - (bessel_J(1, 1) + bessel_J(0, 1))*bessel_Y(0, x)/(bessel_J(0, 1)*bessel_Y(1, 1) - bessel_J(1, 1)*bessel_Y(0, 1)) - sage: f.subs(x=1).n() # numerical verification + sage: f.subs(x=1).n() # numerical verification 1.00000000000000 sage: fp = f.diff(x) sage: fp.subs(x=1).n() 1.00000000000000 - sage: f.subs(x=1).simplify_full() # symbolic verification + sage: f.subs(x=1).simplify_full() # symbolic verification # needs sage.symbolic 1 - sage: fp = f.diff(x) - sage: fp.subs(x=1).simplify_full() + sage: fp = f.diff(x) # needs sage.symbolic + sage: fp.subs(x=1).simplify_full() # needs sage.symbolic 1 - sage: plot(f, (x,0,5)) + sage: plot(f, (x,0,5)) # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive Plotting:: - sage: f(x) = Bessel(0)(x); f + sage: f(x) = Bessel(0)(x); f # needs sage.symbolic x |--> bessel_J(0, x) - sage: plot(f, (x, 1, 10)) + sage: plot(f, (x, 1, 10)) # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive - sage: plot([ Bessel(i, 'J') for i in range(5) ], 2, 10) + sage: plot([Bessel(i, 'J') for i in range(5)], 2, 10) # needs sage.plot Graphics object consisting of 5 graphics primitives - sage: G = Graphics() - sage: G += sum([ plot(Bessel(i), 0, 4*pi, rgbcolor=hue(sin(pi*i/10))) for i in range(5) ]) - sage: show(G) + sage: G = Graphics() # needs sage.plot + sage: G += sum(plot(Bessel(i), 0, 4*pi, rgbcolor=hue(sin(pi*i/10))) # needs sage.plot sage.symbolic + ....: for i in range(5)) + sage: show(G) # needs sage.plot A recreation of Abramowitz and Stegun Figure 9.1:: + sage: # needs sage.plot sage.symbolic sage: G = plot(Bessel(0, 'J'), 0, 15, color='black') sage: G += plot(Bessel(0, 'Y'), 0, 15, color='black') sage: G += plot(Bessel(1, 'J'), 0, 15, color='black', linestyle='dotted') @@ -1220,11 +1255,11 @@ class Function_Struve_H(BuiltinFunction): EXAMPLES:: - sage: struve_H(-1/2,x) + sage: struve_H(-1/2, x) # needs sage.symbolic sqrt(2)*sqrt(1/(pi*x))*sin(x) - sage: struve_H(2,x) + sage: struve_H(2, x) # needs sage.symbolic struve_H(2, x) - sage: struve_H(1/2,pi).n() + sage: struve_H(1/2, pi).n() # needs sage.symbolic 0.900316316157106 REFERENCES: @@ -1239,10 +1274,11 @@ def __init__(self): r""" EXAMPLES:: + sage: # needs sage.symbolic sage: n = var('n') sage: maxima("struve_h(n,x);").sage() struve_H(n, x) - sage: struve_H(7/5,1)._maxima_() + sage: struve_H(7/5, 1)._maxima_() struve_h(7/5,1) sage: loads(dumps(struve_H(n,x))) struve_H(n, x) @@ -1258,19 +1294,20 @@ def _eval_(self, a, z): """ EXAMPLES:: - sage: struve_H(0,0) + sage: # needs sage.symbolic + sage: struve_H(0, 0) 0 - sage: struve_H(pi,0) + sage: struve_H(pi, 0) 0 - sage: struve_H(-1/2,x) + sage: struve_H(-1/2, x) sqrt(2)*sqrt(1/(pi*x))*sin(x) - sage: struve_H(1/2,-1) + sage: struve_H(1/2, -1) -sqrt(2)*sqrt(-1/pi)*(cos(1) - 1) - sage: struve_H(1/2,pi) + sage: struve_H(1/2, pi) 2*sqrt(2)/pi - sage: struve_H(2,x) + sage: struve_H(2, x) struve_H(2, x) - sage: struve_H(-3/2,x) + sage: struve_H(-3/2, x) -bessel_J(3/2, x) """ if z.is_zero() \ @@ -1278,10 +1315,8 @@ def _eval_(self, a, z): and a.real() >= -1: return ZZ.zero() if a == QQ((-1, 2)): - from sage.functions.trig import sin return sqrt(2 / (pi * z)) * sin(z) if a == QQ((1, 2)): - from sage.functions.trig import cos return sqrt(2 / (pi * z)) * (1 - cos(z)) if a < 0 and not SR(a).is_integer() and SR(2 * a).is_integer(): n = (a * (-2) - 1) / 2 @@ -1291,25 +1326,24 @@ def _evalf_(self, a, z, parent=None, algorithm=None): """ EXAMPLES:: - sage: struve_H(1/2,pi).n() + sage: struve_H(1/2, pi).n() # needs sage.symbolic 0.900316316157106 - sage: struve_H(1/2,pi).n(200) + sage: struve_H(1/2, pi).n(200) # needs sage.symbolic 0.9003163161571060695551991910... """ - import mpmath - return mpmath_utils.call(mpmath.struveh, a, z, parent=parent) + return _mpmath_utils_call(_mpmath_struveh, a, z, parent=parent) def _derivative_(self, a, z, diff_param=None): """ EXAMPLES:: - sage: diff(struve_H(3/2,x),x) - -1/2*sqrt(2)*sqrt(1/(pi*x))*(cos(x) - 1) + 1/16*sqrt(2)*x^(3/2)/sqrt(pi) - 1/2*struve_H(5/2, x) + sage: diff(struve_H(3/2,x), x) # needs sage.symbolic + -1/2*sqrt(2)*sqrt(1/(pi*x))*(cos(x) - 1) + 1/16*sqrt(2)*x^(3/2)/sqrt(pi) + - 1/2*struve_H(5/2, x) """ if diff_param == 0: raise ValueError("cannot differentiate struve_H in the first parameter") - from .gamma import gamma from .other import sqrt return (z**a / (sqrt(pi) * 2**a * gamma(a + Integer(3) / Integer(2))) - struve_H(a + 1, z) + struve_H(a - 1, z)) / 2 @@ -1317,7 +1351,7 @@ def _print_latex_(self, a, z): """ EXAMPLES:: - sage: latex(struve_H(2,x)) + sage: latex(struve_H(2,x)) # needs sage.symbolic H_{{2}}({x}) """ return r"H_{{%s}}({%s})" % (a, z) @@ -1336,11 +1370,11 @@ class Function_Struve_L(BuiltinFunction): EXAMPLES:: - sage: struve_L(2,x) + sage: struve_L(2, x) # needs sage.symbolic struve_L(2, x) - sage: struve_L(1/2,pi).n() + sage: struve_L(1/2, pi).n() # needs sage.symbolic 4.76805417696286 - sage: diff(struve_L(1,x),x) + sage: diff(struve_L(1,x), x) # needs sage.symbolic 1/3*x/pi - 1/2*struve_L(2, x) + 1/2*struve_L(0, x) REFERENCES: @@ -1355,12 +1389,13 @@ def __init__(self): r""" EXAMPLES:: + sage: # needs sage.symbolic sage: n = var('n') sage: maxima("struve_l(n,x);").sage() struve_L(n, x) - sage: struve_L(7/5,1)._maxima_() + sage: struve_L(7/5, 1)._maxima_() struve_l(7/5,1) - sage: loads(dumps(struve_L(n,x))) + sage: loads(dumps(struve_L(n, x))) struve_L(n, x) """ BuiltinFunction.__init__(self, 'struve_L', nargs=2, @@ -1374,19 +1409,20 @@ def _eval_(self, a, z): """ EXAMPLES:: - sage: struve_L(-2,0) + sage: # needs sage.symbolic + sage: struve_L(-2, 0) struve_L(-2, 0) - sage: struve_L(-1,0) + sage: struve_L(-1, 0) 0 - sage: struve_L(pi,0) + sage: struve_L(pi, 0) 0 - sage: struve_L(-1/2,x) + sage: struve_L(-1/2, x) sqrt(2)*sqrt(1/(pi*x))*sinh(x) - sage: struve_L(1/2,1) + sage: struve_L(1/2, 1) sqrt(2)*(cosh(1) - 1)/sqrt(pi) - sage: struve_L(2,x) + sage: struve_L(2, x) struve_L(2, x) - sage: struve_L(-3/2,x) + sage: struve_L(-3/2, x) -bessel_I(3/2, x) """ if z.is_zero() \ @@ -1394,10 +1430,8 @@ def _eval_(self, a, z): and a.real() >= -1: return ZZ.zero() if a == -Integer(1) / 2: - from sage.functions.hyperbolic import sinh return sqrt(2 / (pi * z)) * sinh(z) if a == Integer(1) / 2: - from sage.functions.hyperbolic import cosh return sqrt(2 / (pi * z)) * (cosh(z) - 1) if a < 0 and not SR(a).is_integer() and SR(2 * a).is_integer(): n = (a * (-2) - 1) / 2 @@ -1407,25 +1441,23 @@ def _evalf_(self, a, z, parent=None, algorithm=None): """ EXAMPLES:: - sage: struve_L(1/2,pi).n() + sage: struve_L(1/2, pi).n() # needs sage.symbolic 4.76805417696286 - sage: struve_L(1/2,pi).n(200) + sage: struve_L(1/2, pi).n(200) # needs sage.symbolic 4.768054176962864289162484345... """ - import mpmath - return mpmath_utils.call(mpmath.struvel, a, z, parent=parent) + return _mpmath_utils_call(_mpmath_struvel, a, z, parent=parent) def _derivative_(self, a, z, diff_param=None): """ EXAMPLES:: - sage: diff(struve_L(1,x),x) + sage: diff(struve_L(1,x), x) # needs sage.symbolic 1/3*x/pi - 1/2*struve_L(2, x) + 1/2*struve_L(0, x) """ if diff_param == 0: raise ValueError("cannot differentiate struve_L in the first parameter") - from .gamma import gamma from .other import sqrt return (z**a / (sqrt(pi) * 2**a * gamma(a + Integer(3) / Integer(2))) - struve_L(a + 1, z) + struve_L(a - 1, z)) / 2 @@ -1433,7 +1465,7 @@ def _print_latex_(self, a, z): """ EXAMPLES:: - sage: latex(struve_L(2,x)) + sage: latex(struve_L(2,x)) # needs sage.symbolic L_{{2}}({x}) """ return r"L_{{%s}}({%s})" % (a, z) @@ -1454,15 +1486,15 @@ class Function_Hankel1(BuiltinFunction): EXAMPLES:: - sage: hankel1(3, x) + sage: hankel1(3, x) # needs sage.symbolic hankel1(3, x) - sage: hankel1(3, 4.) + sage: hankel1(3, 4.) # needs mpmath 0.430171473875622 - 0.182022115953485*I - sage: latex(hankel1(3, x)) + sage: latex(hankel1(3, x)) # needs sage.symbolic H_{3}^{(1)}\left(x\right) - sage: hankel1(3., x).series(x == 2, 10).subs(x=3).n() # abs tol 1e-12 + sage: hankel1(3., x).series(x == 2, 10).subs(x=3).n() # abs tol 1e-12 # needs sage.symbolic 0.309062682819597 - 0.512591541605233*I - sage: hankel1(3, 3.) + sage: hankel1(3, 3.) # needs mpmath 0.309062722255252 - 0.538541616105032*I REFERENCES: @@ -1473,7 +1505,7 @@ def __init__(self): r""" TESTS:: - sage: hankel1(3, x)._sympy_() + sage: hankel1(3, x)._sympy_() # needs sympy sage.symbolic hankel1(3, x) """ BuiltinFunction.__init__(self, 'hankel1', nargs=2, @@ -1487,13 +1519,12 @@ def _evalf_(self, nu, z, parent, algorithm=None): r""" TESTS:: - sage: hankel1(3, 3).n(100) + sage: hankel1(3, 3).n(100) # needs sage.symbolic 0.30906272225525164361826019495 - 0.53854161610503161800470390534*I - sage: hankel1(I, I).n() + sage: hankel1(I, I).n() # needs sage.symbolic -0.886357449263715*I """ - from mpmath import hankel1 - return mpmath_utils.call(hankel1, nu, z, parent=parent) + return _mpmath_utils_call(_mpmath_hankel1, nu, z, parent=parent) def _latex_(self): r""" @@ -1508,7 +1539,7 @@ def _print_latex_(self, nu, z): r""" TESTS:: - sage: latex(hankel1(3, x)) + sage: latex(hankel1(3, x)) # needs sage.symbolic H_{3}^{(1)}\left(x\right) """ return r"H_{{{}}}^{{(1)}}\left({}\right)".format(latex(nu), latex(z)) @@ -1517,8 +1548,8 @@ def _derivative_(self, nu, z, diff_param): r""" TESTS:: - sage: y = var('y') - sage: hankel1(x, y).diff(y) + sage: y = var('y') # needs sage.symbolic + sage: hankel1(x, y).diff(y) # needs sage.symbolic x*hankel1(x, y)/y - hankel1(x + 1, y) """ if diff_param == 1: @@ -1542,15 +1573,15 @@ class Function_Hankel2(BuiltinFunction): EXAMPLES:: - sage: hankel2(3, x) + sage: hankel2(3, x) # needs sage.symbolic hankel2(3, x) - sage: hankel2(3, 4.) + sage: hankel2(3, 4.) # needs mpmath 0.430171473875622 + 0.182022115953485*I - sage: latex(hankel2(3, x)) + sage: latex(hankel2(3, x)) # needs sage.symbolic H_{3}^{(2)}\left(x\right) - sage: hankel2(3., x).series(x == 2, 10).subs(x=3).n() # abs tol 1e-12 + sage: hankel2(3., x).series(x == 2, 10).subs(x=3).n() # abs tol 1e-12 # needs sage.symbolic 0.309062682819597 + 0.512591541605234*I - sage: hankel2(3, 3.) + sage: hankel2(3, 3.) # needs mpmath 0.309062722255252 + 0.538541616105032*I REFERENCES: @@ -1561,7 +1592,7 @@ def __init__(self): r""" TESTS:: - sage: hankel2(3, x)._sympy_() + sage: hankel2(3, x)._sympy_() # needs sympy sage.symbolic hankel2(3, x) """ BuiltinFunction.__init__(self, 'hankel2', nargs=2, @@ -1575,13 +1606,12 @@ def _evalf_(self, nu, z, parent, algorithm=None): r""" TESTS:: - sage: hankel2(3, 3).n(100) + sage: hankel2(3, 3).n(100) # needs sage.symbolic 0.30906272225525164361826019495 + 0.53854161610503161800470390534*I - sage: hankel2(I, I).n() + sage: hankel2(I, I).n() # needs sage.symbolic 0.790274862674015 + 0.444006335520019*I """ - from mpmath import hankel2 - return mpmath_utils.call(hankel2, nu, z, parent=parent) + return _mpmath_utils_call(_mpmath_hankel2, nu, z, parent=parent) def _latex_(self): r""" @@ -1596,7 +1626,7 @@ def _print_latex_(self, nu, z): r""" TESTS:: - sage: latex(hankel2(3, x)) + sage: latex(hankel2(3, x)) # needs sage.symbolic H_{3}^{(2)}\left(x\right) """ return r"H_{{{}}}^{{(2)}}\left({}\right)".format(latex(nu), latex(z)) @@ -1605,8 +1635,8 @@ def _derivative_(self, nu, z, diff_param): r""" TESTS:: - sage: y = var('y') - sage: hankel2(x, y).diff(y) + sage: y = var('y') # needs sage.symbolic + sage: hankel2(x, y).diff(y) # needs sage.symbolic -1/2*hankel2(x + 1, y) + 1/2*hankel2(x - 1, y) """ if diff_param == 1: @@ -1630,16 +1660,18 @@ class SphericalBesselJ(BuiltinFunction): EXAMPLES:: + sage: spherical_bessel_J(3, 3.) # needs mpmath + 0.152051662030533 + sage: spherical_bessel_J(2.,3.) # rel tol 1e-10 # needs mpmath + 0.2986374970757335 + + sage: # needs sage.symbolic sage: spherical_bessel_J(3, x) spherical_bessel_J(3, x) sage: spherical_bessel_J(3 + 0.2 * I, 3) 0.150770999183897 - 0.0260662466510632*I sage: spherical_bessel_J(3, x).series(x == 2, 10).subs(x=3).n() 0.152051648665037 - sage: spherical_bessel_J(3, 3.) - 0.152051662030533 - sage: spherical_bessel_J(2.,3.) # rel tol 1e-10 - 0.2986374970757335 sage: spherical_bessel_J(4, x).simplify() -((45/x^2 - 105/x^4 - 1)*sin(x) + 5*(21/x^2 - 2)*cos(x)/x)/x sage: integrate(spherical_bessel_J(1,x)^2,(x,0,oo)) @@ -1659,7 +1691,7 @@ def __init__(self): r""" TESTS:: - sage: spherical_bessel_J(3, x)._sympy_() + sage: spherical_bessel_J(3, x)._sympy_() # needs sympy sage.symbolic jn(3, x) """ conversions = dict(mathematica='SphericalBesselJ', @@ -1672,12 +1704,12 @@ def _evalf_(self, n, z, parent, algorithm=None): r""" TESTS:: - sage: spherical_bessel_J(3, 3).n(100) + sage: spherical_bessel_J(3, 3).n(100) # needs sage.symbolic 0.15205166203053329097480571600 - sage: spherical_bessel_J(I, I).n() + sage: spherical_bessel_J(I, I).n() # needs sage.symbolic 0.215520585196889 - 0.282308805801851*I """ - return mpmath_utils.call(spherical_bessel_f, 'besselj', n, z, + return _mpmath_utils_call(spherical_bessel_f, 'besselj', n, z, parent=parent) def _latex_(self): @@ -1693,7 +1725,7 @@ def _print_latex_(self, n, z): r""" TESTS:: - sage: latex(spherical_bessel_J(4, x)) + sage: latex(spherical_bessel_J(4, x)) # needs sage.symbolic j_{4}\left(x\right) """ return r"j_{{{}}}\left({}\right)".format(latex(n), latex(z)) @@ -1702,8 +1734,8 @@ def _derivative_(self, n, z, diff_param): r""" TESTS:: - sage: y = var('y') - sage: spherical_bessel_J(x, y).diff(y) + sage: y = var('y') # needs sage.symbolic + sage: spherical_bessel_J(x, y).diff(y) # needs sage.symbolic -(x + 1)*spherical_bessel_J(x, y)/y + spherical_bessel_J(x - 1, y) """ if SR(n).is_numeric() and not SR(n).is_integer(): @@ -1730,6 +1762,7 @@ class SphericalBesselY(BuiltinFunction): EXAMPLES:: + sage: # needs sage.symbolic sage: spherical_bessel_Y(3, x) spherical_bessel_Y(3, x) sage: spherical_bessel_Y(3 + 0.2 * I, 3) @@ -1757,7 +1790,7 @@ def __init__(self): r""" TESTS:: - sage: spherical_bessel_Y(3, x)._sympy_() + sage: spherical_bessel_Y(3, x)._sympy_() # needs sympy sage.symbolic yn(3, x) """ conversions = dict(mathematica='SphericalBesselY', @@ -1770,12 +1803,12 @@ def _evalf_(self, n, z, parent, algorithm=None): r""" TESTS:: - sage: spherical_bessel_Y(3, 3).n(100) + sage: spherical_bessel_Y(3, 3).n(100) # needs sage.symbolic -0.50802305570981460285684870920 - sage: spherical_bessel_Y(I, I).n() + sage: spherical_bessel_Y(I, I).n() # needs sage.symbolic -0.174225389805399 + 1.36247234140312*I """ - return mpmath_utils.call(spherical_bessel_f, 'bessely', n, z, + return _mpmath_utils_call(spherical_bessel_f, 'bessely', n, z, parent=parent) def _latex_(self): @@ -1791,7 +1824,7 @@ def _print_latex_(self, n, z): r""" TESTS:: - sage: latex(spherical_bessel_Y(4, x)) + sage: latex(spherical_bessel_Y(4, x)) # needs sage.symbolic y_{4}\left(x\right) """ return r"y_{{{}}}\left({}\right)".format(latex(n), latex(z)) @@ -1800,8 +1833,8 @@ def _derivative_(self, n, z, diff_param): r""" TESTS:: - sage: y = var('y') - sage: spherical_bessel_Y(x, y).diff(y) + sage: y = var('y') # needs sage.symbolic + sage: spherical_bessel_Y(x, y).diff(y) # needs sage.symbolic -1/2*spherical_bessel_Y(x, y)/y -... 1/2*spherical_bessel_Y(x + 1, y) + 1/2*spherical_bessel_Y(x - 1, y) """ @@ -1830,6 +1863,7 @@ class SphericalHankel1(BuiltinFunction): EXAMPLES:: + sage: # needs sage.symbolic sage: spherical_hankel1(3, x) spherical_hankel1(3, x) sage: spherical_hankel1(3 + 0.2 * I, 3) @@ -1867,12 +1901,12 @@ def _evalf_(self, n, z, parent, algorithm=None): r""" TESTS:: - sage: spherical_hankel1(3, 3).n(100) + sage: spherical_hankel1(3, 3).n(100) # needs sage.symbolic 0.15205166203053329097480571600 - 0.50802305570981460285684870920*I - sage: spherical_hankel1(I, I).n() + sage: spherical_hankel1(I, I).n() # needs sage.symbolic -1.14695175620623 - 0.456534195607250*I """ - return mpmath_utils.call(spherical_bessel_f, 'hankel1', n, z, + return _mpmath_utils_call(spherical_bessel_f, 'hankel1', n, z, parent=parent) def _latex_(self): @@ -1888,7 +1922,7 @@ def _print_latex_(self, n, z): r""" TESTS:: - sage: latex(spherical_hankel1(4, x)) + sage: latex(spherical_hankel1(4, x)) # needs sage.symbolic h_{4}^{(1)}\left(x\right) """ return r"h_{{{}}}^{{(1)}}\left({}\right)".format(latex(n), latex(z)) @@ -1897,8 +1931,8 @@ def _derivative_(self, n, z, diff_param): r""" TESTS:: - sage: y = var('y') - sage: spherical_hankel1(x, y).diff(y) + sage: y = var('y') # needs sage.symbolic + sage: spherical_hankel1(x, y).diff(y) # needs sage.symbolic -1/2*spherical_hankel1(x, y)/y -... 1/2*spherical_hankel1(x + 1, y) + 1/2*spherical_hankel1(x - 1, y) """ @@ -1927,6 +1961,7 @@ class SphericalHankel2(BuiltinFunction): EXAMPLES:: + sage: # needs sage.symbolic sage: spherical_hankel2(3, x) spherical_hankel2(3, x) sage: spherical_hankel2(3 + 0.2 * I, 3) @@ -1967,13 +2002,13 @@ def _evalf_(self, n, z, parent, algorithm=None): r""" TESTS:: - sage: spherical_hankel2(3, 3).n(100) + sage: spherical_hankel2(3, 3).n(100) # needs sage.symbolic 0.15205166203053329097480571600 + 0.50802305570981460285684870920*I - sage: spherical_hankel2(I, I).n() + sage: spherical_hankel2(I, I).n() # needs sage.symbolic 1.57799292660001 - 0.108083415996452*I """ - return mpmath_utils.call(spherical_bessel_f, 'hankel2', n, z, - parent=parent) + return _mpmath_utils_call(spherical_bessel_f, 'hankel2', n, z, + parent=parent) def _latex_(self): r""" @@ -1988,7 +2023,7 @@ def _print_latex_(self, n, z): r""" TESTS:: - sage: latex(spherical_hankel2(4, x)) + sage: latex(spherical_hankel2(4, x)) # needs sage.symbolic h_{4}^{(2)}\left(x\right) """ return r"h_{{{}}}^{{(2)}}\left({}\right)".format(latex(n), latex(z)) @@ -1997,6 +2032,7 @@ def _derivative_(self, n, z, diff_param): r""" TESTS:: + sage: # needs sage.symbolic sage: y = var('y') sage: spherical_hankel2(x, y).diff(y) -1/2*spherical_hankel2(x, y)/y -... @@ -2033,9 +2069,9 @@ def spherical_bessel_f(F, n, z): EXAMPLES:: sage: from sage.functions.bessel import spherical_bessel_f - sage: spherical_bessel_f('besselj', 3, 4) + sage: spherical_bessel_f('besselj', 3, 4) # needs mpmath mpf('0.22924385795503024') - sage: spherical_bessel_f('hankel1', 3, 4) + sage: spherical_bessel_f('hankel1', 3, 4) # needs mpmath mpc(real='0.22924385795503024', imag='-0.21864196590306359') TESTS: @@ -2043,13 +2079,12 @@ def spherical_bessel_f(F, n, z): Check that :trac:`28474` is fixed:: sage: from sage.functions.bessel import spherical_bessel_f - sage: spherical_bessel_f('besselj', 3, -4) + sage: spherical_bessel_f('besselj', 3, -4) # needs mpmath mpc(real='-0.22924385795503024', imag='0.0') - sage: spherical_bessel_f('bessely', 3, -4) + sage: spherical_bessel_f('bessely', 3, -4) # needs mpmath mpc(real='-0.21864196590306359', imag='0.0') """ - from mpmath import mp - ctx = mp + from mpmath import mp as ctx prec = ctx.prec try: n = ctx.convert(n) diff --git a/src/sage/functions/error.py b/src/sage/functions/error.py index c5221683442..1e4b74d5afe 100644 --- a/src/sage/functions/error.py +++ b/src/sage/functions/error.py @@ -40,15 +40,26 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.structure.all import parent as s_parent -from sage.symbolic.function import BuiltinFunction -from sage.libs.mpmath import utils as mpmath_utils -from sage.symbolic.expression import Expression -from sage.functions.all import exp from sage.misc.functional import sqrt -from sage.symbolic.constants import I, pi -from sage.rings.rational import Rational +from sage.misc.lazy_import import lazy_import +from sage.misc.persist import register_unpickle_override from sage.rings.infinity import unsigned_infinity +from sage.rings.rational import Rational +from sage.structure.element import Expression, parent as s_parent +from sage.symbolic.function import BuiltinFunction + +lazy_import('sage.functions.log', ['exp']) +lazy_import('sage.functions.trig', ['sin', 'cos']) + +lazy_import('sage.symbolic.constants', ['I', 'pi']) + +lazy_import('sage.libs.mpmath.utils', 'call', as_='_mpmath_utils_call') +lazy_import('sage.libs.mpmath.all', 'erf', as_='_mpmath_erf') +lazy_import('sage.libs.mpmath.all', 'erfc', as_='_mpmath_erfc') +lazy_import('sage.libs.mpmath.all', 'erfi', as_='_mpmath_erfi') +lazy_import('sage.libs.mpmath.all', 'erfinv', as_='_mpmath_erfinv') +lazy_import('sage.libs.mpmath.all', 'fresnelc', as_='_mpmath_fresnelc') +lazy_import('sage.libs.mpmath.all', 'fresnels', as_='_mpmath_fresnels') class Function_erf(BuiltinFunction): @@ -68,21 +79,21 @@ class Function_erf(BuiltinFunction): We can evaluate numerically:: - sage: erf(2) + sage: erf(2) # needs sage.symbolic erf(2) - sage: erf(2).n() + sage: erf(2).n() # needs sage.symbolic 0.995322265018953 - sage: erf(2).n(100) + sage: erf(2).n(100) # needs sage.symbolic 0.99532226501895273416206925637 - sage: erf(ComplexField(100)(2+3j)) + sage: erf(ComplexField(100)(2+3j)) # needs sage.rings.real_mpfr -20.829461427614568389103088452 + 8.6873182714701631444280787545*I Basic symbolic properties are handled by Sage and Maxima:: - sage: x = var("x") - sage: diff(erf(x),x) + sage: x = var("x") # needs sage.symbolic + sage: diff(erf(x),x) # needs sage.symbolic 2*e^(-x^2)/sqrt(pi) - sage: integrate(erf(x),x) + sage: integrate(erf(x),x) # needs sage.symbolic x*erf(x) + e^(-x^2)/sqrt(pi) ALGORITHM: @@ -99,78 +110,78 @@ class Function_erf(BuiltinFunction): Check limits:: - sage: limit(erf(x),x=0) + sage: limit(erf(x), x=0) # needs sage.symbolic 0 - sage: limit(erf(x),x=infinity) + sage: limit(erf(x), x=infinity) # needs sage.symbolic 1 Check that it's odd:: - sage: erf(1.0) + sage: erf(1.0) # needs mpmath 0.842700792949715 - sage: erf(-1.0) + sage: erf(-1.0) # needs mpmath -0.842700792949715 Check against other implementations and against the definition:: - sage: erf(3).n() + sage: erf(3).n() # needs sage.symbolic 0.999977909503001 - sage: maxima.erf(3).n() + sage: maxima.erf(3).n() # needs sage.symbolic 0.999977909503001 - sage: (1-pari(3).erfc()) + sage: 1 - pari(3).erfc() # needs sage.libs.pari 0.999977909503001 - sage: RR(3).erf() + sage: RR(3).erf() # needs sage.rings.real_mpfr 0.999977909503001 - sage: (integrate(exp(-x**2),(x,0,3))*2/sqrt(pi)).n() + sage: (integrate(exp(-x**2), (x,0,3))*2/sqrt(pi)).n() # needs sage.symbolic 0.999977909503001 :trac:`9044`:: - sage: N(erf(sqrt(2)),200) + sage: N(erf(sqrt(2)),200) # needs sage.symbolic 0.95449973610364158559943472566693312505644755259664313203267 :trac:`11626`:: - sage: n(erf(2),100) + sage: n(erf(2),100) # needs sage.symbolic 0.99532226501895273416206925637 - sage: erf(2).n(100) + sage: erf(2).n(100) # needs sage.symbolic 0.99532226501895273416206925637 Test (indirectly) :trac:`11885`:: sage: erf(float(0.5)) 0.5204998778130465 - sage: erf(complex(0.5)) + sage: erf(complex(0.5)) # needs sage.rings.complex_double (0.5204998778130465+0j) Ensure conversion from maxima elements works:: - sage: merf = maxima(erf(x)).sage().operator() - sage: merf.parent() == erf.parent() + sage: merf = maxima(erf(x)).sage().operator() # needs sage.symbolic + sage: merf.parent() == erf.parent() # needs sage.symbolic True Make sure we can dump and load it:: - sage: loads(dumps(erf(2))) + sage: loads(dumps(erf(2))) # needs sage.symbolic erf(2) Special-case 0 for immediate evaluation:: - sage: erf(0) + sage: erf(0) # needs mpmath 0 - sage: solve(erf(x)==0,x) + sage: solve(erf(x)==0, x) # needs sage.symbolic [x == 0] Make sure that we can hold:: - sage: erf(0,hold=True) + sage: erf(0, hold=True) # needs sage.symbolic erf(0) - sage: simplify(erf(0,hold=True)) + sage: simplify(erf(0, hold=True)) # needs sage.symbolic 0 Check that high-precision ComplexField inputs work:: - sage: CC(erf(ComplexField(1000)(2+3j))) + sage: CC(erf(ComplexField(1000)(2+3j))) # needs sage.rings.real_mpfr -20.8294614276146 + 8.68731827147016*I """ @@ -180,9 +191,9 @@ def __init__(self): EXAMPLES:: - sage: maxima(erf(2)) + sage: maxima(erf(2)) # needs sage.symbolic erf(2) - sage: erf(2)._sympy_() + sage: erf(2)._sympy_() # needs sympy sage.symbolic erf(2) """ BuiltinFunction.__init__(self, "erf", latex_name=r"\operatorname{erf}", @@ -197,6 +208,7 @@ def _eval_(self, x): Input is not an expression but is exact:: + sage: # needs sage.symbolic sage: erf(0) 0 sage: erf(1) @@ -210,17 +222,17 @@ def _eval_(self, x): Input is not an expression and is not exact:: - sage: erf(0.0) + sage: erf(0.0) # needs mpmath 0.000000000000000 Input is an expression but not a trivial zero:: - sage: erf(x) + sage: erf(x) # needs sage.symbolic erf(x) Input is an expression which is trivially zero:: - sage: erf(SR(0)) + sage: erf(SR(0)) # needs sage.symbolic 0 """ if isinstance(x, Expression): @@ -240,39 +252,38 @@ def _evalf_(self, x, parent=None, algorithm=None): """ EXAMPLES:: - sage: erf(2).n() + sage: erf(2).n() # needs sage.symbolic 0.995322265018953 - sage: erf(2).n(200) + sage: erf(2).n(200) # needs sage.symbolic 0.99532226501895273416206925636725292861089179704006007673835 - sage: erf(pi - 1/2*I).n(100) + sage: erf(pi - 1/2*I).n(100) # needs sage.symbolic 1.0000111669099367825726058952 + 1.6332655417638522934072124547e-6*I TESTS: Check that PARI/GP through the GP interface gives the same answer:: - sage: gp.set_real_precision(59) # random + sage: gp.set_real_precision(59) # random # needs sage.libs.pari 38 - sage: print(gp.eval("1 - erfc(1)")); print(erf(1).n(200)) + sage: print(gp.eval("1 - erfc(1)")); print(erf(1).n(200)) # needs sage.libs.pari 0.84270079294971486934122063508260925929606699796630290845994 0.84270079294971486934122063508260925929606699796630290845994 Check that for an imaginary input, the output is also imaginary, see :trac:`13193`:: - sage: erf(3.0*I) + sage: erf(3.0*I) # needs sage.symbolic 1629.99462260157*I - sage: erf(33.0*I) + sage: erf(33.0*I) # needs sage.symbolic 1.51286977510409e471*I Check that real ball evaluation is fixed :trac:`28061`:: - sage: RealBallField(128)(erf(5)) # abs tol 1e-38 + sage: RealBallField(128)(erf(5)) # abs tol 1e-38 # needs sage.symbolic [0.99999999999846254020557196514981165651 +/- 7.33e-39] """ R = parent or s_parent(x) - import mpmath - y = mpmath_utils.call(mpmath.erf, x, parent=R) + y = _mpmath_utils_call(_mpmath_erf, x, parent=R) return y def _derivative_(self, x, diff_param=None): @@ -281,18 +292,18 @@ def _derivative_(self, x, diff_param=None): EXAMPLES:: - sage: erf(x).diff(x) + sage: erf(x).diff(x) # needs sage.symbolic 2*e^(-x^2)/sqrt(pi) TESTS: Check if :trac:`8568` is fixed:: - sage: var('c,x') + sage: var('c,x') # needs sage.symbolic (c, x) - sage: derivative(erf(c*x),x) + sage: derivative(erf(c*x),x) # needs sage.symbolic 2*c*e^(-c^2*x^2)/sqrt(pi) - sage: erf(c*x).diff(x)._maxima_init_() + sage: erf(c*x).diff(x)._maxima_init_() # needs sage.symbolic '((%pi)^(-1/2))*(_SAGE_VAR_c)*(exp(((_SAGE_VAR_c)^(2))*((_SAGE_VAR_x)^(2))*(-1)))*(2)' """ return 2*exp(-x**2)/sqrt(pi) @@ -317,9 +328,9 @@ def __init__(self): EXAMPLES:: - sage: maxima(erfi(2)) + sage: maxima(erfi(2)) # needs sage.symbolic erfi(2) - sage: erfi(2)._sympy_() + sage: erfi(2)._sympy_() # needs sympy sage.symbolic erfi(2) """ BuiltinFunction.__init__(self, "erfi", @@ -332,6 +343,7 @@ def _eval_(self, x): """ EXAMPLES:: + sage: # needs sage.symbolic sage: erfi(0) 0 sage: erfi(SR(0)) @@ -353,16 +365,15 @@ def _evalf_(self, x, parent=None, algorithm=None): """ EXAMPLES:: - sage: erfi(2.) + sage: erfi(2.) # needs mpmath 18.5648024145756 - sage: erfi(2).n(100) + sage: erfi(2).n(100) # needs sage.symbolic 18.564802414575552598704291913 - sage: erfi(-2*I).n(100) + sage: erfi(-2*I).n(100) # needs sage.symbolic -0.99532226501895273416206925637*I """ R = parent or s_parent(x) - import mpmath - return mpmath_utils.call(mpmath.erfi, x, parent=R) + return _mpmath_utils_call(_mpmath_erfi, x, parent=R) def _derivative_(self, x, diff_param=None): """ @@ -370,7 +381,7 @@ def _derivative_(self, x, diff_param=None): EXAMPLES:: - sage: erfi(x).diff(x) + sage: erfi(x).diff(x) # needs sage.symbolic 2*e^(x^2)/sqrt(pi) """ @@ -392,23 +403,23 @@ class Function_erfc(BuiltinFunction): EXAMPLES:: - sage: erfc(6) + sage: erfc(6) # needs sage.symbolic erfc(6) - sage: erfc(6).n() + sage: erfc(6).n() # needs sage.symbolic 2.15197367124989e-17 - sage: erfc(RealField(100)(1/2)) + sage: erfc(RealField(100)(1/2)) # needs sage.rings.real_mpfr 0.47950012218695346231725334611 - sage: 1 - erfc(0.5) + sage: 1 - erfc(0.5) # needs mpmath 0.520499877813047 - sage: erf(0.5) + sage: erf(0.5) # needs mpmath 0.520499877813047 TESTS: Check that :trac:`25991` is fixed:: - sage: erfc(x)._fricas_() # optional - fricas + sage: erfc(x)._fricas_() # optional - fricas, needs sage.symbolic - erf(x) + 1 """ @@ -416,9 +427,9 @@ def __init__(self): r""" EXAMPLES:: - sage: maxima(erfc(2)) + sage: maxima(erfc(2)) # needs sage.symbolic erfc(2) - sage: erfc(2)._sympy_() + sage: erfc(2)._sympy_() # needs sympy sage.symbolic erfc(2) """ BuiltinFunction.__init__(self, "erfc", @@ -432,6 +443,7 @@ def _eval_(self, x): """ EXAMPLES:: + sage: # needs sage.symbolic sage: erfc(0) 1 sage: erfc(SR(0)) @@ -458,16 +470,15 @@ def _evalf_(self, x, parent=None, algorithm=None): """ EXAMPLES:: - sage: erfc(4).n() + sage: erfc(4).n() # needs sage.symbolic 1.54172579002800e-8 - sage: erfc(4).n(100) + sage: erfc(4).n(100) # needs sage.symbolic 1.5417257900280018852159673487e-8 - sage: erfc(4*I).n(100) + sage: erfc(4*I).n(100) # needs sage.symbolic 1.0000000000000000000000000000 - 1.2969597307176392315279409506e6*I """ R = parent or s_parent(x) - import mpmath - return mpmath_utils.call(mpmath.erfc, x, parent=R) + return _mpmath_utils_call(_mpmath_erfc, x, parent=R) def _derivative_(self, x, diff_param=None): """ @@ -475,7 +486,7 @@ def _derivative_(self, x, diff_param=None): EXAMPLES:: - sage: erfc(x).diff(x) + sage: erfc(x).diff(x) # needs sage.symbolic -2*e^(-x^2)/sqrt(pi) """ return -2*exp(-x**2)/sqrt(pi) @@ -500,15 +511,16 @@ def __init__(self): EXAMPLES:: - sage: erfinv(2)._sympy_() + sage: erfinv(2)._sympy_() # needs sympy sage.symbolic erfinv(2) - sage: maxima(erfinv(2)) + sage: maxima(erfinv(2)) # needs sage.symbolic inverse_erf(2) TESTS: Check that :trac:`11349` is fixed:: + sage: # needs sage.symbolic sage: _ = var('z,t') sage: PDF = exp(-x^2 /2)/sqrt(2*pi) sage: integralExpr = integrate(PDF,x,z,oo).subs(z==log(t)) @@ -527,11 +539,11 @@ def _eval_(self, x): """ EXAMPLES:: - sage: erfinv(0) + sage: erfinv(0) # needs mpmath 0 - sage: erfinv(SR(0)) + sage: erfinv(SR(0)) # needs sage.symbolic 0 - sage: erfinv(1) + sage: erfinv(1) # needs sage.symbolic Infinity """ if isinstance(x, Expression): @@ -548,14 +560,13 @@ def _evalf_(self, x, parent=None, algorithm=None): """ EXAMPLES:: - sage: erfinv(0.2) + sage: erfinv(0.2) # needs mpmath 0.179143454621292 - sage: erfinv(1/5).n(100) + sage: erfinv(1/5).n(100) # needs sage.symbolic 0.17914345462129167649274901663 """ R = parent or s_parent(x) - import mpmath - return mpmath_utils.call(mpmath.erfinv, x, parent=R) + return _mpmath_utils_call(_mpmath_erfinv, x, parent=R) def _derivative_(self, x, diff_param=None): """ @@ -563,7 +574,7 @@ def _derivative_(self, x, diff_param=None): EXAMPLES:: - sage: erfinv(x).diff(x) + sage: erfinv(x).diff(x) # needs sage.symbolic 1/2*sqrt(pi)*e^(erfinv(x)^2) """ return sqrt(pi)*exp(erfinv(x)**2)/2 @@ -572,7 +583,6 @@ def _derivative_(self, x, diff_param=None): erfinv = Function_erfinv() -from sage.misc.persist import register_unpickle_override register_unpickle_override('sage.functions.other', 'Function_erf', Function_erf) @@ -599,6 +609,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: fresnel_sin(0) 0 sage: fresnel_sin(x).subs(x==0) @@ -606,7 +617,7 @@ def __init__(self): sage: x = var('x') sage: fresnel_sin(1).n(100) 0.43825914739035476607675669662 - sage: fresnel_sin(x)._sympy_() + sage: fresnel_sin(x)._sympy_() # needs sympy fresnels(x) """ BuiltinFunction.__init__(self, "fresnel_sin", nargs=1, @@ -621,15 +632,15 @@ def _eval_(self, x): r""" EXAMPLES:: - sage: fresnel_sin(pi) + sage: fresnel_sin(pi) # needs sage.symbolic fresnel_sin(pi) - sage: fresnel_sin(oo) + sage: fresnel_sin(oo) # needs mpmath 1/2 - sage: fresnel_sin(-oo) + sage: fresnel_sin(-oo) # needs mpmath -1/2 - sage: fresnel_sin(I*oo) + sage: fresnel_sin(I*oo) # needs sage.symbolic -1/2*I - sage: fresnel_sin(-I*oo) + sage: fresnel_sin(-I*oo) # needs sage.symbolic 1/2*I """ if isinstance(x, Expression): @@ -653,26 +664,23 @@ def _evalf_(self, x, parent=None, algorithm=None): r""" EXAMPLES:: - sage: fresnel_sin(pi) + sage: fresnel_sin(pi) # needs sage.symbolic fresnel_sin(pi) - sage: fresnel_sin(pi).n(100) + sage: fresnel_sin(pi).n(100) # needs sage.symbolic 0.59824907809026766482843860921 - sage: fresnel_sin(1.0+2*I) + sage: fresnel_sin(1.0+2*I) # needs sage.symbolic 36.7254648839914 + 15.5877511044046*I """ - import mpmath - from sage.libs.mpmath import utils as mpmath_utils - return mpmath_utils.call(mpmath.fresnels, x, parent=parent) + return _mpmath_utils_call(_mpmath_fresnels, x, parent=parent) def _derivative_(self, x, diff_param=None): """ EXAMPLES:: - sage: x = var('x') - sage: fresnel_sin(x).diff(x) + sage: x = var('x') # needs sage.symbolic + sage: fresnel_sin(x).diff(x) # needs sage.symbolic sin(1/2*pi*x^2) """ - from sage.functions.trig import sin return sin(pi*x**2/2) @@ -699,6 +707,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: fresnel_cos(0) 0 sage: fresnel_cos(x).subs(x==0) @@ -706,7 +715,7 @@ def __init__(self): sage: x = var('x') sage: fresnel_cos(1).n(100) 0.77989340037682282947420641365 - sage: fresnel_cos(x)._sympy_() + sage: fresnel_cos(x)._sympy_() # needs sympy fresnelc(x) """ BuiltinFunction.__init__(self, "fresnel_cos", nargs=1, @@ -721,15 +730,15 @@ def _eval_(self, x): r""" EXAMPLES:: - sage: fresnel_cos(pi) + sage: fresnel_cos(pi) # needs sage.symbolic fresnel_cos(pi) - sage: fresnel_cos(oo) + sage: fresnel_cos(oo) # needs mpmath 1/2 - sage: fresnel_cos(-oo) + sage: fresnel_cos(-oo) # needs mpmath -1/2 - sage: fresnel_cos(I*oo) + sage: fresnel_cos(I*oo) # needs sage.symbolic 1/2*I - sage: fresnel_cos(-I*oo) + sage: fresnel_cos(-I*oo) # needs sage.symbolic -1/2*I """ if isinstance(x, Expression): @@ -753,26 +762,23 @@ def _evalf_(self, x, parent=None, algorithm=None): r""" EXAMPLES:: - sage: fresnel_cos(pi) + sage: fresnel_cos(pi) # needs sage.symbolic fresnel_cos(pi) - sage: fresnel_cos(pi).n(100) + sage: fresnel_cos(pi).n(100) # needs sage.symbolic 0.52369854372622864215767570284 - sage: fresnel_cos(1.0+2*I) + sage: fresnel_cos(1.0+2*I) # needs sage.symbolic 16.0878713741255 - 36.2256879928817*I """ - import mpmath - from sage.libs.mpmath import utils as mpmath_utils - return mpmath_utils.call(mpmath.fresnelc, x, parent=parent) + return _mpmath_utils_call(_mpmath_fresnelc, x, parent=parent) def _derivative_(self, x, diff_param=None): """ EXAMPLES:: - sage: x = var('x') - sage: fresnel_cos(x).diff(x) + sage: x = var('x') # needs sage.symbolic + sage: fresnel_cos(x).diff(x) # needs sage.symbolic cos(1/2*pi*x^2) """ - from sage.functions.trig import cos return cos(pi*x**2/2) diff --git a/src/sage/functions/exp_integral.py b/src/sage/functions/exp_integral.py index a2099dbb4ab..5fb024c877c 100644 --- a/src/sage/functions/exp_integral.py +++ b/src/sage/functions/exp_integral.py @@ -46,20 +46,28 @@ # https://www.gnu.org/licenses/ # **************************************************************************** +import math +from sage.misc.lazy_import import lazy_import +from sage.rings.infinity import Infinity +from sage.rings.integer_ring import ZZ +from sage.structure.element import Expression, parent from sage.symbolic.function import BuiltinFunction -from sage.symbolic.expression import Expression -from sage.structure.all import parent -from sage.misc.latex import latex -from sage.libs.mpmath import utils as mpmath_utils -mpmath_utils_call = mpmath_utils.call # eliminate some overhead in _evalf_ -from sage.rings.real_mpfr import RealField -from sage.rings.integer_ring import ZZ -from sage.functions.log import exp, log -from sage.functions.trig import sin, cos -from sage.functions.hyperbolic import sinh, cosh -import math +lazy_import('sage.functions.log', ['exp', 'log']) +lazy_import('sage.functions.trig', ['sin', 'cos']) +lazy_import('sage.functions.hyperbolic', ['sinh', 'cosh']) + +lazy_import('sage.misc.latex', 'latex') +lazy_import('sage.rings.real_mpfr', 'RealField') + +lazy_import('sage.symbolic.ring', 'SR') + +lazy_import('sage.libs.mpmath.utils', 'call', as_='_mpmath_utils_call') +lazy_import('mpmath', + ['chi', 'ci', 'e1', 'ei', 'expint', 'ei', 'li', 'shi', 'si'], + as_=['_mpmath_chi', '_mpmath_ci', '_mpmath_e1', '_mpmath_ei', '_mpmath_expint', + '_mpmath_ei', '_mpmath_li', '_mpmath_shi', '_mpmath_si']) class Function_exp_integral_e(BuiltinFunction): @@ -79,61 +87,60 @@ class Function_exp_integral_e(BuiltinFunction): Numerical evaluation is handled using mpmath:: - sage: N(exp_integral_e(1,1)) + sage: N(exp_integral_e(1, 1)) # needs sage.symbolic 0.219383934395520 - sage: exp_integral_e(1, RealField(100)(1)) + sage: exp_integral_e(1, RealField(100)(1)) # needs sage.symbolic 0.21938393439552027367716377546 We can compare this to PARI's evaluation of :meth:`exponential_integral_1`:: - sage: N(exponential_integral_1(1)) + sage: N(exponential_integral_1(1)) # needs sage.symbolic 0.219383934395520 We can verify one case of [AS1964]_ 5.1.45, i.e. `E_n(z) = z^{n-1}\Gamma(1-n,z)`:: - sage: N(exp_integral_e(2, 3+I)) + sage: N(exp_integral_e(2, 3+I)) # needs sage.symbolic 0.00354575823814662 - 0.00973200528288687*I - sage: N((3+I)*gamma(-1, 3+I)) + sage: N((3+I)*gamma(-1, 3+I)) # needs sage.symbolic 0.00354575823814662 - 0.00973200528288687*I Maxima returns the following improper integral as a multiple of ``exp_integral_e(1,1)``:: - sage: uu = integral(e^(-x)*log(x+1),x,0,oo) - sage: uu + sage: uu = integral(e^(-x)*log(x+1), x, 0, oo); uu # needs sage.symbolic e*exp_integral_e(1, 1) - sage: uu.n(digits=30) + sage: uu.n(digits=30) # needs sage.symbolic 0.596347362323194074341078499369 Symbolic derivatives and integrals are handled by Sage and Maxima:: + sage: # needs sage.symbolic sage: x = var('x') sage: f = exp_integral_e(2,x) sage: f.diff(x) -exp_integral_e(1, x) - sage: f.integrate(x) -exp_integral_e(3, x) - - sage: f = exp_integral_e(-1,x) + sage: f = exp_integral_e(-1, x) sage: f.integrate(x) Ei(-x) - gamma(-1, x) Some special values of ``exp_integral_e`` can be simplified. [AS1964]_ 5.1.23:: - sage: exp_integral_e(0,x) + sage: exp_integral_e(0, x) # needs sage.symbolic e^(-x)/x [AS1964]_ 5.1.24:: - sage: exp_integral_e(6,0) + sage: # needs sage.symbolic + sage: exp_integral_e(6, 0) 1/5 sage: nn = var('nn') sage: assume(nn > 1) - sage: f = exp_integral_e(nn,0) + sage: f = exp_integral_e(nn, 0) sage: f.simplify() 1/(nn - 1) @@ -150,9 +157,9 @@ def __init__(self): EXAMPLES:: - sage: exp_integral_e(1, 0) + sage: exp_integral_e(1, 0) # needs sage.symbolic exp_integral_e(1, 0) - sage: exp_integral_e(1, x)._sympy_() + sage: exp_integral_e(1, x)._sympy_() # needs sage.symbolic expint(1, x) """ @@ -164,18 +171,18 @@ def _eval_(self, n, z): """ EXAMPLES:: - sage: exp_integral_e(1.0, x) + sage: exp_integral_e(1.0, x) # needs sage.symbolic exp_integral_e(1.00000000000000, x) - sage: exp_integral_e(x, 1.0) + sage: exp_integral_e(x, 1.0) # needs sage.symbolic exp_integral_e(x, 1.00000000000000) - sage: exp_integral_e(3, 0) + sage: exp_integral_e(3, 0) # needs mpmath 1/2 TESTS: Check that Python ints work (:trac:`14766`):: - sage: exp_integral_e(int(3), 0) + sage: exp_integral_e(int(3), 0) # needs mpmath 1/2 """ z_zero = False @@ -211,15 +218,14 @@ def _evalf_(self, n, z, parent=None, algorithm=None): """ EXAMPLES:: - sage: exp_integral_e(1.0, 1.0) + sage: exp_integral_e(1.0, 1.0) # needs mpmath 0.219383934395520 - sage: N(exp_integral_e(1, 1+I)) + sage: N(exp_integral_e(1, 1+I)) # needs sage.symbolic 0.000281624451981418 - 0.179324535039359*I - sage: exp_integral_e(1, RealField(100)(1)) + sage: exp_integral_e(1, RealField(100)(1)) # needs sage.rings.real_mpfr 0.21938393439552027367716377546 """ - import mpmath - return mpmath_utils.call(mpmath.expint, n, z, parent=parent) + return _mpmath_utils_call(_mpmath_expint, n, z, parent=parent) def _print_latex_(self, n, z): r""" @@ -227,7 +233,7 @@ def _print_latex_(self, n, z): EXAMPLES:: - sage: latex(exp_integral_e(1, -x - 1)) + sage: latex(exp_integral_e(1, -x - 1)) # needs sage.symbolic E_{1}\left(-x - 1\right) """ return r"E_{{{}}}\left({}\right)".format(latex(n), latex(z)) @@ -240,12 +246,12 @@ def _derivative_(self, n, z, diff_param=None): EXAMPLES:: + sage: # needs sage.symbolic sage: x = var('x') - sage: f = exp_integral_e(2,x) + sage: f = exp_integral_e(2, x) sage: f.diff(x) -exp_integral_e(1, x) - - sage: f = exp_integral_e(2,sqrt(x)) + sage: f = exp_integral_e(2, sqrt(x)) sage: f.diff(x) -1/2*exp_integral_e(1, sqrt(x))/sqrt(x) """ @@ -269,33 +275,33 @@ class Function_exp_integral_e1(BuiltinFunction): EXAMPLES:: - sage: exp_integral_e1(x) + sage: exp_integral_e1(x) # needs sage.symbolic exp_integral_e1(x) - sage: exp_integral_e1(1.0) + sage: exp_integral_e1(1.0) # needs mpmath 0.219383934395520 Numerical evaluation is handled using mpmath:: - sage: N(exp_integral_e1(1)) + sage: N(exp_integral_e1(1)) # needs sage.symbolic 0.219383934395520 - sage: exp_integral_e1(RealField(100)(1)) + sage: exp_integral_e1(RealField(100)(1)) # needs sage.rings.real_mpfr 0.21938393439552027367716377546 We can compare this to PARI's evaluation of :meth:`exponential_integral_1`:: - sage: N(exp_integral_e1(2.0)) + sage: N(exp_integral_e1(2.0)) # needs mpmath 0.0489005107080611 - sage: N(exponential_integral_1(2.0)) + sage: N(exponential_integral_1(2.0)) # needs sage.rings.real_mpfr 0.0489005107080611 Symbolic derivatives and integrals are handled by Sage and Maxima:: + sage: # needs sage.symbolic sage: x = var('x') sage: f = exp_integral_e1(x) sage: f.diff(x) -e^(-x)/x - sage: f.integrate(x) -exp_integral_e(2, x) @@ -311,9 +317,9 @@ def __init__(self): EXAMPLES:: - sage: exp_integral_e1(1) + sage: exp_integral_e1(1) # needs sage.symbolic exp_integral_e1(1) - sage: exp_integral_e1(x)._sympy_() + sage: exp_integral_e1(x)._sympy_() # needs sympy sage.symbolic expint(1, x) """ @@ -325,14 +331,13 @@ def _evalf_(self, z, parent=None, algorithm=None): """ EXAMPLES:: - sage: N(exp_integral_e1(1+I)) + sage: N(exp_integral_e1(1+I)) # needs sage.symbolic 0.000281624451981418 - 0.179324535039359*I - sage: exp_integral_e1(RealField(200)(0.5)) + sage: exp_integral_e1(RealField(200)(0.5)) # needs sage.rings.real_mpfr 0.55977359477616081174679593931508523522684689031635351524829 """ - import mpmath - return mpmath_utils_call(mpmath.e1, z, parent=parent) + return _mpmath_utils_call(_mpmath_e1, z, parent=parent) def _print_latex_(self, z): r""" @@ -340,7 +345,7 @@ def _print_latex_(self, z): EXAMPLES:: - sage: latex(exp_integral_e1(2)) + sage: latex(exp_integral_e1(2)) # needs sage.symbolic E_{1}\left(2\right) """ return r"E_{{1}}\left({}\right)".format(latex(z)) @@ -353,11 +358,11 @@ def _derivative_(self, z, diff_param=None): EXAMPLES:: + sage: # needs sage.symbolic sage: x = var('x') sage: f = exp_integral_e1(x) sage: f.diff(x) -e^(-x)/x - sage: f = exp_integral_e1(x^2) sage: f.diff(x) -2*e^(-x^2)/x @@ -383,22 +388,22 @@ class Function_log_integral(BuiltinFunction): Numerical evaluation for real and complex arguments is handled using mpmath:: - sage: N(log_integral(3)) + sage: N(log_integral(3)) # needs sage.symbolic 2.16358859466719 - sage: N(log_integral(3), digits=30) + sage: N(log_integral(3), digits=30) # needs sage.symbolic 2.16358859466719197287692236735 - sage: log_integral(ComplexField(100)(3+I)) + sage: log_integral(ComplexField(100)(3+I)) # needs sage.symbolic 2.2879892769816826157078450911 + 0.87232935488528370139883806779*I - sage: log_integral(0) + sage: log_integral(0) # needs mpmath 0 Symbolic derivatives and integrals are handled by Sage and Maxima:: + sage: # needs sage.symbolic sage: x = var('x') sage: f = log_integral(x) sage: f.diff(x) 1/log(x) - sage: f.integrate(x) x*log_integral(x) - Ei(2*log(x)) @@ -406,7 +411,7 @@ class Function_log_integral(BuiltinFunction): 1,925,320,391,606,803,968,923 many prime numbers less than 1e23. The value of ``log_integral(1e23)`` is very close to this:: - sage: log_integral(1e23) + sage: log_integral(1e23) # needs mpmath 1.92532039161405e21 ALGORITHM: @@ -429,18 +434,18 @@ def __init__(self): EXAMPLES:: - sage: log_integral(3) + sage: log_integral(3) # needs sage.symbolic log_integral(3) - sage: log_integral(x)._sympy_() + sage: log_integral(x)._sympy_() # needs sympy sage.symbolic li(x) - sage: log_integral(x)._fricas_init_() + sage: log_integral(x)._fricas_init_() # needs sage.symbolic 'li(x)' TESTS: Verify that :trac:`28917` is fixed:: - sage: latex(log_integral(x)) + sage: latex(log_integral(x)) # needs sage.symbolic \operatorname{log\_integral}\left(x\right) """ BuiltinFunction.__init__(self, "log_integral", nargs=1, @@ -453,12 +458,12 @@ def _eval_(self, z): """ EXAMPLES:: - sage: z = var('z') - sage: log_integral(z) + sage: z = var('z') # needs sage.symbolic + sage: log_integral(z) # needs sage.symbolic log_integral(z) - sage: log_integral(3.0) + sage: log_integral(3.0) # needs mpmath 2.16358859466719 - sage: log_integral(0) + sage: log_integral(0) # needs mpmath 0 """ @@ -473,14 +478,13 @@ def _evalf_(self, z, parent=None, algorithm=None): """ EXAMPLES:: - sage: N(log_integral(1e6)) + sage: N(log_integral(1e6)) # needs mpmath 78627.5491594622 - sage: log_integral(RealField(200)(1e6)) + sage: log_integral(RealField(200)(1e6)) # needs sage.rings.real_mpfr 78627.549159462181919862910747947261161321874382421767074759 """ - import mpmath - return mpmath_utils_call(mpmath.li, z, parent=parent) + return _mpmath_utils_call(_mpmath_li, z, parent=parent) def _derivative_(self, z, diff_param=None): r""" @@ -488,11 +492,11 @@ def _derivative_(self, z, diff_param=None): EXAMPLES:: + sage: # needs sage.symbolic sage: x = var('x') sage: f = log_integral(x) sage: f.diff(x) 1/log(x) - sage: f = log_integral(x^2) sage: f.diff(x) 2*x/log(x^2) @@ -537,13 +541,13 @@ class Function_log_integral_offset(BuiltinFunction): So we have:: - sage: li(4.5)-li(2.0)-Li(4.5) + sage: li(4.5) - li(2.0) - Li(4.5) # needs mpmath 0.000000000000000 `\operatorname{Li}(x)` is extended to complex arguments `z` by analytic continuation (see [AS1964]_ 5.1.3):: - sage: Li(6.6+5.4*I) + sage: Li(6.6 + 5.4*I) # needs sage.symbolic 3.97032201503632 + 2.62311237593572*I The function `\operatorname{Li}` is an approximation for the number of @@ -570,6 +574,7 @@ class Function_log_integral_offset(BuiltinFunction): Numerical evaluation for real and complex arguments is handled using mpmath:: + sage: # needs sage.symbolic sage: N(log_integral_offset(3)) 1.11842481454970 sage: N(log_integral_offset(3), digits=30) @@ -578,7 +583,7 @@ class Function_log_integral_offset(BuiltinFunction): 1.2428254968641898308632562019 + 0.87232935488528370139883806779*I sage: log_integral_offset(2) 0 - sage: for n in range(1,7): + sage: for n in range(1,7): # needs primecountpy ....: print('%-10s%-10s%-20s'%(10^n, prime_pi(10^n), N(Li(10^n)))) 10 4 5.12043572466980 100 25 29.0809778039621 @@ -591,20 +596,21 @@ class Function_log_integral_offset(BuiltinFunction): There are 1,925,320,391,606,803,968,923 prime numbers less than 1e23. The value of ``log_integral_offset(1e23)`` is very close to this:: - sage: log_integral_offset(1e23) + sage: log_integral_offset(1e23) # needs mpmath 1.92532039161405e21 Symbolic derivatives are handled by Sage and integration by Maxima:: + sage: # needs sage.symbolic sage: x = var('x') sage: f = log_integral_offset(x) sage: f.diff(x) 1/log(x) sage: f.integrate(x) -x*log_integral(2) + x*log_integral(x) - Ei(2*log(x)) - sage: Li(x).integrate(x,2.0,4.5).n(digits=10) + sage: Li(x).integrate(x, 2.0, 4.5).n(digits=10) 3.186411697 - sage: N(f.integrate(x,2.0,3.0)) # abs tol 1e-15 + sage: N(f.integrate(x, 2.0, 3.0)) # abs tol 1e-15 0.601621785860587 ALGORITHM: @@ -626,9 +632,9 @@ def __init__(self): EXAMPLES:: - sage: log_integral_offset(3) + sage: log_integral_offset(3) # needs sage.symbolic log_integral(3) - log_integral(2) - sage: log_integral_offset(x, hold=True)._sympy_() + sage: log_integral_offset(x, hold=True)._sympy_() # needs sympy sage.symbolic Li(x) TESTS: @@ -647,18 +653,17 @@ def _eval_(self, z): """ EXAMPLES:: - sage: z = var('z') - sage: log_integral_offset(z) + sage: z = var('z') # needs sage.symbolic + sage: log_integral_offset(z) # needs sage.symbolic -log_integral(2) + log_integral(z) - sage: log_integral_offset(3.0) + sage: log_integral_offset(3.0) # needs mpmath 1.11842481454970 - sage: log_integral_offset(2) + sage: log_integral_offset(2) # needs mpmath 0 """ if z == 2: - import sage.symbolic.ring - return sage.symbolic.ring.SR(0) + return SR(0) return li(z)-li(2) # If we return:(li(z)-li(2)) we get correct symbolic integration. # But on definite integration it returns x.xxxx-li(2). @@ -667,16 +672,15 @@ def _evalf_(self, z, parent=None, algorithm=None): """ EXAMPLES:: - sage: N(log_integral_offset(1e6)) + sage: N(log_integral_offset(1e6)) # needs mpmath 78626.5039956821 - sage: log_integral_offset(RealField(200)(1e6)) + sage: log_integral_offset(RealField(200)(1e6)) # needs sage.rings.real_mpfr 78626.503995682064427078066159058066548185351766843615873183 - sage: li(4.5)-li(2.0)-Li(4.5) + sage: li(4.5) - li(2.0) - Li(4.5) # needs mpmath 0.000000000000000 """ - import mpmath - return mpmath_utils_call(mpmath.li, z, offset=True, parent=parent) + return _mpmath_utils_call(_mpmath_li, z, offset=True, parent=parent) def _derivative_(self, z, diff_param=None): r""" @@ -684,11 +688,11 @@ def _derivative_(self, z, diff_param=None): EXAMPLES:: + sage: # needs sage.symbolic sage: x = var('x') sage: f = log_integral_offset(x) sage: f.diff(x) 1/log(x) - sage: f = log_integral_offset(x^2) sage: f.diff(x) 2*x/log(x^2) @@ -713,56 +717,55 @@ class Function_sin_integral(BuiltinFunction): Numerical evaluation for real and complex arguments is handled using mpmath:: - sage: sin_integral(0) + sage: sin_integral(0) # needs mpmath 0 - sage: sin_integral(0.0) + sage: sin_integral(0.0) # needs mpmath 0.000000000000000 - sage: sin_integral(3.0) + sage: sin_integral(3.0) # needs mpmath 1.84865252799947 - sage: N(sin_integral(3), digits=30) + sage: N(sin_integral(3), digits=30) # needs sage.symbolic 1.84865252799946825639773025111 - sage: sin_integral(ComplexField(100)(3+I)) + sage: sin_integral(ComplexField(100)(3+I)) # needs sage.symbolic 2.0277151656451253616038525998 + 0.015210926166954211913653130271*I The alias ``Si`` can be used instead of ``sin_integral``:: - sage: Si(3.0) + sage: Si(3.0) # needs mpmath 1.84865252799947 The limit of `\operatorname{Si}(z)` as `z \to \infty` is `\pi/2`:: - sage: N(sin_integral(1e23)) + sage: N(sin_integral(1e23)) # needs mpmath 1.57079632679490 - sage: N(pi/2) + sage: N(pi/2) # needs sage.symbolic 1.57079632679490 At 200 bits of precision `\operatorname{Si}(10^{23})` agrees with `\pi/2` up to `10^{-24}`:: - sage: sin_integral(RealField(200)(1e23)) + sage: sin_integral(RealField(200)(1e23)) # needs sage.rings.real_mpfr 1.5707963267948966192313288218697837425815368604836679189519 - sage: N(pi/2, prec=200) + sage: N(pi/2, prec=200) # needs sage.symbolic 1.5707963267948966192313216916397514420985846996875529104875 The exponential sine integral is analytic everywhere:: - sage: sin_integral(-1.0) + sage: sin_integral(-1.0) # needs mpmath -0.946083070367183 - sage: sin_integral(-2.0) + sage: sin_integral(-2.0) # needs mpmath -1.60541297680269 - sage: sin_integral(-1e23) + sage: sin_integral(-1e23) # needs mpmath -1.57079632679490 Symbolic derivatives and integrals are handled by Sage and Maxima:: + sage: # needs sage.symbolic sage: x = var('x') sage: f = sin_integral(x) sage: f.diff(x) sin(x)/x - sage: f.integrate(x) x*sin_integral(x) + cos(x) - sage: integrate(sin(x)/x, x) -1/2*I*Ei(I*x) + 1/2*I*Ei(-I*x) @@ -772,19 +775,20 @@ class Function_sin_integral(BuiltinFunction): \operatorname{Ei}(ix) - \pi/2`, which are both anti-derivatives of `\sin(x)/x`, at some random positive real numbers:: - sage: f(x) = 1/2*I*Ei(-I*x) - 1/2*I*Ei(I*x) - pi/2 - sage: g(x) = sin_integral(x) - sage: R = [ abs(RDF.random_element()) for i in range(100) ] - sage: all(abs(f(x) - g(x)) < 1e-10 for x in R) + sage: f(x) = 1/2*I*Ei(-I*x) - 1/2*I*Ei(I*x) - pi/2 # needs sage.symbolic + sage: g(x) = sin_integral(x) # needs sage.symbolic + sage: R = [abs(RDF.random_element()) for i in range(100)] + sage: all(abs(f(x) - g(x)) < 1e-10 for x in R) # needs sage.symbolic True The Nielsen spiral is the parametric plot of (Si(t), Ci(t)):: - sage: x=var('x') + sage: # needs sage.symbolic + sage: x = var('x') sage: f(x) = sin_integral(x) sage: g(x) = cos_integral(x) - sage: P = parametric_plot([f, g], (x, 0.5 ,20)) - sage: show(P, frame=True, axes=False) + sage: P = parametric_plot([f, g], (x, 0.5 ,20)) # needs sage.plot + sage: show(P, frame=True, axes=False) # needs sage.plot ALGORITHM: @@ -805,13 +809,14 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: sin_integral(1) sin_integral(1) - sage: sin_integral(x)._sympy_() + sage: sin_integral(x)._sympy_() # needs sympy Si(x) sage: sin_integral(x)._fricas_init_() 'Si(x)' - sage: sin_integral(x)._giac_() + sage: sin_integral(x)._giac_() # needs sage.libs.giac Si(sageVARx) """ BuiltinFunction.__init__(self, "sin_integral", nargs=1, @@ -824,12 +829,12 @@ def _eval_(self, z): """ EXAMPLES:: - sage: z = var('z') - sage: sin_integral(z) + sage: z = var('z') # needs sage.symbolic + sage: sin_integral(z) # needs sage.symbolic sin_integral(z) - sage: sin_integral(3.0) + sage: sin_integral(3.0) # needs mpmath 1.84865252799947 - sage: sin_integral(0) + sage: sin_integral(0) # needs mpmath 0 """ @@ -845,29 +850,28 @@ def _evalf_(self, z, parent=None, algorithm=None): The limit `\operatorname{Si}(z)` as `z \to \infty` is `\pi/2`:: - sage: N(sin_integral(1e23) - pi/2) + sage: N(sin_integral(1e23) - pi/2) # needs sage.symbolic 0.000000000000000 At 200 bits of precision `\operatorname{Si}(10^{23})` agrees with `\pi/2` up to `10^{-24}`:: - sage: sin_integral(RealField(200)(1e23)) + sage: sin_integral(RealField(200)(1e23)) # needs sage.rings.real_mpfr 1.5707963267948966192313288218697837425815368604836679189519 - sage: N(pi/2, prec=200) + sage: N(pi/2, prec=200) # needs sage.symbolic 1.5707963267948966192313216916397514420985846996875529104875 The exponential sine integral is analytic everywhere, even on the negative real axis:: - sage: sin_integral(-1.0) + sage: sin_integral(-1.0) # needs mpmath -0.946083070367183 - sage: sin_integral(-2.0) + sage: sin_integral(-2.0) # needs mpmath -1.60541297680269 - sage: sin_integral(-1e23) + sage: sin_integral(-1e23) # needs mpmath -1.57079632679490 """ - import mpmath - return mpmath_utils_call(mpmath.si, z, parent=parent) + return _mpmath_utils_call(_mpmath_si, z, parent=parent) def _derivative_(self, z, diff_param=None): r""" @@ -877,11 +881,11 @@ def _derivative_(self, z, diff_param=None): EXAMPLES:: + sage: # needs sage.symbolic sage: x = var('x') sage: f = sin_integral(x) sage: f.diff(x) sin(x)/x - sage: f = sin_integral(x^2) sage: f.diff(x) 2*sin(x^2)/x @@ -906,62 +910,63 @@ class Function_cos_integral(BuiltinFunction): EXAMPLES:: - sage: z = var('z') - sage: cos_integral(z) + sage: z = var('z') # needs sage.symbolic + sage: cos_integral(z) # needs sage.symbolic cos_integral(z) - sage: cos_integral(3.0) + sage: cos_integral(3.0) # needs mpmath 0.119629786008000 - sage: cos_integral(0) + sage: cos_integral(0) # needs sage.symbolic cos_integral(0) - sage: N(cos_integral(0)) + sage: N(cos_integral(0)) # needs mpmath -infinity Numerical evaluation for real and complex arguments is handled using mpmath:: - sage: cos_integral(3.0) + sage: cos_integral(3.0) # needs mpmath 0.119629786008000 The alias ``Ci`` can be used instead of ``cos_integral``:: - sage: Ci(3.0) + sage: Ci(3.0) # needs mpmath 0.119629786008000 Compare ``cos_integral(3.0)`` to the definition of the value using numerical integration:: - sage: a = numerical_integral((cos(x)-1)/x, 0, 3)[0] - sage: abs(N(euler_gamma + log(3)) + a - N(cos_integral(3.0))) < 1e-14 + sage: a = numerical_integral((cos(x)-1)/x, 0, 3)[0] # needs sage.symbolic + sage: abs(N(euler_gamma + log(3)) + a - N(cos_integral(3.0))) < 1e-14 # needs sage.symbolic True Arbitrary precision and complex arguments are handled:: - sage: N(cos_integral(3), digits=30) + sage: N(cos_integral(3), digits=30) # needs sage.symbolic 0.119629786008000327626472281177 - sage: cos_integral(ComplexField(100)(3+I)) + sage: cos_integral(ComplexField(100)(3+I)) # needs sage.symbolic 0.078134230477495714401983633057 - 0.37814733904787920181190368789*I The limit `\operatorname{Ci}(z)` as `z \to \infty` is zero:: - sage: N(cos_integral(1e23)) + sage: N(cos_integral(1e23)) # needs mpmath -3.24053937643003e-24 Symbolic derivatives and integrals are handled by Sage and Maxima:: + sage: # needs sage.symbolic sage: x = var('x') sage: f = cos_integral(x) sage: f.diff(x) cos(x)/x - sage: f.integrate(x) x*cos_integral(x) - sin(x) The Nielsen spiral is the parametric plot of (Si(t), Ci(t)):: - sage: t=var('t') + sage: # needs sage.symbolic + sage: t = var('t') sage: f(t) = sin_integral(t) sage: g(t) = cos_integral(t) - sage: P = parametric_plot([f, g], (t, 0.5 ,20)) - sage: show(P, frame=True, axes=False) + sage: P = parametric_plot([f, g], (t, 0.5 ,20)) # needs sage.plot + sage: show(P, frame=True, axes=False) # needs sage.plot ALGORITHM: @@ -982,13 +987,14 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: cos_integral(1) cos_integral(1) - sage: cos_integral(x)._sympy_() + sage: cos_integral(x)._sympy_() # needs sympy Ci(x) sage: cos_integral(x)._fricas_init_() 'Ci(x)' - sage: cos_integral(x)._giac_() + sage: cos_integral(x)._giac_() # needs sage.libs.giac Ci(sageVARx) """ BuiltinFunction.__init__(self, "cos_integral", nargs=1, @@ -1001,16 +1007,15 @@ def _evalf_(self, z, parent=None, algorithm=None): """ EXAMPLES:: - sage: N(cos_integral(1e23)) < 1e-20 + sage: N(cos_integral(1e23)) < 1e-20 # needs mpmath True - sage: N(cos_integral(10^-10), digits=30) + sage: N(cos_integral(10^-10), digits=30) # needs sage.symbolic -22.4486352650389239795759024568 - sage: cos_integral(ComplexField(100)(I)) + sage: cos_integral(ComplexField(100)(I)) # needs sage.symbolic 0.83786694098020824089467857943 + 1.5707963267948966192313216916*I """ - import mpmath - return mpmath_utils_call(mpmath.ci, z, parent=parent) + return _mpmath_utils_call(_mpmath_ci, z, parent=parent) def _derivative_(self, z, diff_param=None): r""" @@ -1018,11 +1023,11 @@ def _derivative_(self, z, diff_param=None): EXAMPLES:: + sage: # needs sage.symbolic sage: x = var('x') sage: f = cos_integral(x) sage: f.diff(x) cos(x)/x - sage: f = cos_integral(x^2) sage: f.diff(x) 2*cos(x^2)/x @@ -1048,45 +1053,45 @@ class Function_sinh_integral(BuiltinFunction): Numerical evaluation for real and complex arguments is handled using mpmath:: - sage: sinh_integral(3.0) + sage: sinh_integral(3.0) # needs mpmath 4.97344047585981 - sage: sinh_integral(1.0) + sage: sinh_integral(1.0) # needs mpmath 1.05725087537573 - sage: sinh_integral(-1.0) + sage: sinh_integral(-1.0) # needs mpmath -1.05725087537573 The alias ``Shi`` can be used instead of ``sinh_integral``:: - sage: Shi(3.0) + sage: Shi(3.0) # needs mpmath 4.97344047585981 Compare ``sinh_integral(3.0)`` to the definition of the value using numerical integration:: - sage: a = numerical_integral(sinh(x)/x, 0, 3)[0] - sage: abs(a - N(sinh_integral(3))) < 1e-14 + sage: a = numerical_integral(sinh(x)/x, 0, 3)[0] # needs sage.symbolic + sage: abs(a - N(sinh_integral(3))) < 1e-14 # needs sage.symbolic True Arbitrary precision and complex arguments are handled:: - sage: N(sinh_integral(3), digits=30) + sage: N(sinh_integral(3), digits=30) # needs sage.symbolic 4.97344047585980679771041838252 - sage: sinh_integral(ComplexField(100)(3+I)) + sage: sinh_integral(ComplexField(100)(3+I)) # needs sage.symbolic 3.9134623660329374406788354078 + 3.0427678212908839256360163759*I The limit `\operatorname{Shi}(z)` as `z \to \infty` is `\infty`:: - sage: N(sinh_integral(Infinity)) + sage: N(sinh_integral(Infinity)) # needs mpmath +infinity Symbolic derivatives and integrals are handled by Sage and Maxima:: - sage: x = var('x') - sage: f = sinh_integral(x) - sage: f.diff(x) + sage: x = var('x') # needs sage.symbolic + sage: f = sinh_integral(x) # needs sage.symbolic + sage: f.diff(x) # needs sage.symbolic sinh(x)/x - sage: f.integrate(x) + sage: f.integrate(x) # needs sage.symbolic x*sinh_integral(x) - cosh(x) Note that due to some problems with the way Maxima handles these @@ -1094,11 +1099,11 @@ class Function_sinh_integral(BuiltinFunction): results (typically when using inexact endpoints) due to inconsistent branching:: - sage: integrate(sinh_integral(x), x, 0, 1/2) + sage: integrate(sinh_integral(x), x, 0, 1/2) # needs sage.symbolic -cosh(1/2) + 1/2*sinh_integral(1/2) + 1 - sage: integrate(sinh_integral(x), x, 0, 1/2).n() # correct + sage: integrate(sinh_integral(x), x, 0, 1/2).n() # correct # needs sage.symbolic 0.125872409703453 - sage: integrate(sinh_integral(x), x, 0, 0.5).n() # fixed in maxima 5.29.1 + sage: integrate(sinh_integral(x), x, 0, 0.5).n() # fixed in maxima 5.29.1 # needs sage.symbolic 0.125872409703453 ALGORITHM: @@ -1120,9 +1125,9 @@ def __init__(self): EXAMPLES:: - sage: sinh_integral(1) + sage: sinh_integral(1) # needs sage.symbolic sinh_integral(1) - sage: sinh_integral(x)._sympy_() + sage: sinh_integral(x)._sympy_() # needs sympy sage.symbolic Shi(x) """ @@ -1136,12 +1141,12 @@ def _eval_(self, z): """ EXAMPLES:: - sage: z = var('z') - sage: sinh_integral(z) + sage: z = var('z') # needs sage.symbolic + sage: sinh_integral(z) # needs sage.symbolic sinh_integral(z) - sage: sinh_integral(3.0) + sage: sinh_integral(3.0) # needs mpmath 4.97344047585981 - sage: sinh_integral(0) + sage: sinh_integral(0) # needs mpmath 0 """ @@ -1156,14 +1161,13 @@ def _evalf_(self, z, parent=None, algorithm=None): """ EXAMPLES:: - sage: N(sinh_integral(10^-10), digits=30) + sage: N(sinh_integral(10^-10), digits=30) # needs sage.symbolic 1.00000000000000000000055555556e-10 - sage: sinh_integral(ComplexField(100)(I)) + sage: sinh_integral(ComplexField(100)(I)) # needs sage.symbolic 0.94608307036718301494135331382*I """ - import mpmath - return mpmath_utils_call(mpmath.shi, z, parent=parent) + return _mpmath_utils_call(_mpmath_shi, z, parent=parent) def _derivative_(self, z, diff_param=None): r""" @@ -1171,11 +1175,11 @@ def _derivative_(self, z, diff_param=None): EXAMPLES:: + sage: # needs sage.symbolic sage: x = var('x') sage: f = sinh_integral(x) sage: f.diff(x) sinh(x)/x - sage: f = sinh_integral(ln(x)) sage: f.diff(x) 1/2*(x^2 - 1)/(x^2*log(x)) @@ -1199,54 +1203,54 @@ class Function_cosh_integral(BuiltinFunction): EXAMPLES:: - sage: z = var('z') - sage: cosh_integral(z) + sage: z = var('z') # needs sage.symbolic + sage: cosh_integral(z) # needs sage.symbolic cosh_integral(z) - sage: cosh_integral(3.0) + sage: cosh_integral(3.0) # needs mpmath 4.96039209476561 Numerical evaluation for real and complex arguments is handled using mpmath:: - sage: cosh_integral(1.0) + sage: cosh_integral(1.0) # needs mpmath 0.837866940980208 The alias ``Chi`` can be used instead of ``cosh_integral``:: - sage: Chi(1.0) + sage: Chi(1.0) # needs mpmath 0.837866940980208 Here is an example from the mpmath documentation:: - sage: f(x) = cosh_integral(x) - sage: find_root(f, 0.1, 1.0) + sage: f(x) = cosh_integral(x) # needs sage.symbolic + sage: find_root(f, 0.1, 1.0) # needs scipy sage.symbolic 0.523822571389... Compare ``cosh_integral(3.0)`` to the definition of the value using numerical integration:: - sage: a = numerical_integral((cosh(x)-1)/x, 0, 3)[0] - sage: abs(N(euler_gamma + log(3)) + a - N(cosh_integral(3.0))) < 1e-14 + sage: a = numerical_integral((cosh(x)-1)/x, 0, 3)[0] # needs sage.symbolic + sage: abs(N(euler_gamma + log(3)) + a - N(cosh_integral(3.0))) < 1e-14 # needs sage.symbolic True Arbitrary precision and complex arguments are handled:: - sage: N(cosh_integral(3), digits=30) + sage: N(cosh_integral(3), digits=30) # needs sage.symbolic 4.96039209476560976029791763669 - sage: cosh_integral(ComplexField(100)(3+I)) + sage: cosh_integral(ComplexField(100)(3+I)) # needs sage.symbolic 3.9096723099686417127843516794 + 3.0547519627014217273323873274*I The limit of `\operatorname{Chi}(z)` as `z \to \infty` is `\infty`:: - sage: N(cosh_integral(Infinity)) + sage: N(cosh_integral(Infinity)) # needs mpmath +infinity Symbolic derivatives and integrals are handled by Sage and Maxima:: + sage: # needs sage.symbolic sage: x = var('x') sage: f = cosh_integral(x) sage: f.diff(x) cosh(x)/x - sage: f.integrate(x) x*cosh_integral(x) - sinh(x) @@ -1269,9 +1273,9 @@ def __init__(self): EXAMPLES:: - sage: cosh_integral(1) + sage: cosh_integral(1) # needs sage.symbolic cosh_integral(1) - sage: cosh_integral(x)._sympy_() + sage: cosh_integral(x)._sympy_() # needs sage.symbolic Chi(x) """ @@ -1285,14 +1289,13 @@ def _evalf_(self, z, parent=None, algorithm=None): """ EXAMPLES:: - sage: N(cosh_integral(10^-10), digits=30) + sage: N(cosh_integral(10^-10), digits=30) # needs sage.symbolic -22.4486352650389239795709024568 - sage: cosh_integral(ComplexField(100)(I)) + sage: cosh_integral(ComplexField(100)(I)) # needs sage.symbolic 0.33740392290096813466264620389 + 1.5707963267948966192313216916*I """ - import mpmath - return mpmath_utils_call(mpmath.chi, z, parent=parent) + return _mpmath_utils_call(_mpmath_chi, z, parent=parent) def _derivative_(self, z, diff_param=None): r""" @@ -1300,11 +1303,11 @@ def _derivative_(self, z, diff_param=None): EXAMPLES:: + sage: # needs sage.symbolic sage: x = var('x') sage: f = cosh_integral(x) sage: f.diff(x) cosh(x)/x - sage: f = cosh_integral(ln(x)) sage: f.diff(x) 1/2*(x^2 + 1)/(x^2*log(x)) @@ -1339,31 +1342,33 @@ class Function_exp_integral(BuiltinFunction): EXAMPLES:: + sage: # needs sage.symbolic sage: Ei(10) Ei(10) sage: Ei(I) Ei(I) sage: Ei(3+I) Ei(I + 3) - sage: Ei(1.3) - 2.72139888023202 sage: Ei(10r) Ei(10) - sage: Ei(1.3r) + + sage: Ei(1.3) # needs mpmath + 2.72139888023202 + sage: Ei(1.3r) # needs mpmath 2.7213988802320235 The branch cut for this function is along the negative real axis:: - sage: Ei(-3 + 0.1*I) + sage: Ei(-3 + 0.1*I) # needs sage.symbolic -0.0129379427181693 + 3.13993830250942*I - sage: Ei(-3 - 0.1*I) + sage: Ei(-3 - 0.1*I) # needs sage.symbolic -0.0129379427181693 - 3.13993830250942*I The precision for the result is deduced from the precision of the input. Convert the input to a higher precision explicitly if a result with higher precision is desired:: - sage: Ei(RealField(300)(1.1)) + sage: Ei(RealField(300)(1.1)) # needs sage.rings.real_mpfr 2.16737827956340282358378734233807621497112737591639704719499002090327541763352339357795426 ALGORITHM: Uses mpmath. @@ -1372,6 +1377,7 @@ class Function_exp_integral(BuiltinFunction): Show that the evaluation and limit issue in :trac:`13271` is fixed:: + sage: # needs sage.symbolic sage: var('Z') Z sage: (Ei(-Z)).limit(Z=oo) @@ -1385,9 +1391,9 @@ def __init__(self): """ TESTS:: - sage: Ei(10) + sage: Ei(10) # needs sage.symbolic Ei(10) - sage: Ei(x)._sympy_() + sage: Ei(x)._sympy_() # needs sympy sage.symbolic Ei(x) """ BuiltinFunction.__init__(self, "Ei", @@ -1399,6 +1405,7 @@ def _evalf_(self, x, parent=None, algorithm=None): """ EXAMPLES:: + sage: # needs sage.symbolic sage: Ei(10).n() 2492.22897624188 sage: Ei(20).n() @@ -1408,13 +1415,13 @@ def _evalf_(self, x, parent=None, algorithm=None): sage: Ei(3+I).n() 7.82313467600158 + 6.09751978399231*I """ - import mpmath - return mpmath_utils_call(mpmath.ei, x, parent=parent) + return _mpmath_utils_call(_mpmath_ei, x, parent=parent) def _derivative_(self, x, diff_param=None): """ EXAMPLES:: + sage: # needs sage.symbolic sage: Ei(x).diff(x) e^x/x sage: Ei(x).diff(x).subs(x=1) @@ -1463,27 +1470,29 @@ def exponential_integral_1(x, n=0): EXAMPLES:: + sage: # needs sage.libs.pari 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) - [0.000000000000000, 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.000000000000000, 2.22854325868847e-37, 6.33732515501151e-55, + 2.02336191509997e-72, 6.88522610630764e-90] + sage: r = exponential_integral_1(RealField(150)(1)); r 0.21938393439552027367716377546012164903104729 sage: parent(r) Real Field with 150 bits of precision sage: exponential_integral_1(RealField(150)(100)) 3.6835977616820321802351926205081189876552201e-46 + sage: exponential_integral_1(0) + +Infinity + 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) + sage: for prec in [20..1000]: # long time (22s on sage.math, 2013), needs sage.libs.pari ....: R = RealField(prec) ....: S = RealField(prec+64) ....: for t in range(8): # Try 8 values for each precision @@ -1497,7 +1506,7 @@ def exponential_integral_1(x, n=0): The absolute error for a vector should be less than `2^{-p} c`, 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) + sage: for prec in [20..128]: # long time (15s on sage.math, 2013), needs sage.libs.pari ....: R = RealField(prec) ....: S = RealField(prec+64) ....: a = R.random_element(-15,10).exp() @@ -1519,7 +1528,6 @@ def exponential_integral_1(x, n=0): """ 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 " + @@ -1527,7 +1535,6 @@ def exponential_integral_1(x, n=0): # x == 0 => return Infinity if not x: - from sage.rings.infinity import Infinity return Infinity # Figure out output precision diff --git a/src/sage/functions/gamma.py b/src/sage/functions/gamma.py index e93e518b0b9..54a3a5aa3ba 100644 --- a/src/sage/functions/gamma.py +++ b/src/sage/functions/gamma.py @@ -1,16 +1,24 @@ """ Gamma and related functions """ -from sage.symbolic.function import GinacFunction, BuiltinFunction -from sage.symbolic.expression import register_symbol, symbol_table -from sage.structure.all import parent as s_parent -from sage.rings.complex_mpfr import ComplexField +from sage.misc.lazy_import import lazy_import +from sage.rings.infinity import Infinity from sage.rings.rational import Rational -from sage.functions.exp_integral import Ei -from sage.libs.mpmath import utils as mpmath_utils -from .log import exp -from .other import sqrt -from sage.symbolic.constants import pi +from sage.structure.element import parent as s_parent +from sage.symbolic.function import GinacFunction, BuiltinFunction +from sage.symbolic.symbols import register_symbol, symbol_table + +lazy_import('sage.rings.complex_mpfr', 'ComplexField') + +lazy_import('sage.functions.error', 'erf') +lazy_import('sage.functions.exp_integral', 'Ei') +lazy_import('sage.functions.log', 'exp') +lazy_import('sage.functions.other', 'sqrt') + +lazy_import('sage.symbolic.constants', 'pi') + +lazy_import('sage.libs.mpmath.utils', 'call', as_='_mpmath_utils_call') +lazy_import('mpmath', 'gammainc', as_='_mpmath_gammainc') class Function_gamma(GinacFunction): @@ -32,9 +40,9 @@ def __init__(self): EXAMPLES:: sage: from sage.functions.gamma import gamma1 - sage: gamma1(CDF(0.5,14)) + sage: gamma1(CDF(0.5, 14)) # needs sage.libs.pari -4.0537030780372815e-10 - 5.773299834553605e-10*I - sage: gamma1(CDF(I)) + sage: gamma1(CDF(I)) # needs sage.libs.pari sage.symbolic -0.15494982830181067 - 0.49801566811835607*I Recall that `\Gamma(n)` is `n-1` factorial:: @@ -43,124 +51,124 @@ def __init__(self): True sage: gamma1(6) 120 - sage: gamma1(1/2) + sage: gamma1(1/2) # needs sage.symbolic sqrt(pi) sage: gamma1(-1) Infinity - sage: gamma1(I) + sage: gamma1(I) # needs sage.symbolic gamma(I) - sage: gamma1(x/2)(x=5) + sage: gamma1(x/2)(x=5) # needs sage.symbolic 3/4*sqrt(pi) sage: gamma1(float(6)) # For ARM: rel tol 3e-16 120.0 - sage: gamma(6.) + sage: gamma(6.) # needs sage.symbolic 120.000000000000 - sage: gamma1(x) + sage: gamma1(x) # needs sage.symbolic gamma(x) :: - sage: gamma1(pi) + sage: gamma1(pi) # needs sage.symbolic gamma(pi) - sage: gamma1(i) + sage: gamma1(i) # needs sage.symbolic gamma(I) - sage: gamma1(i).n() + sage: gamma1(i).n() # needs sage.symbolic -0.154949828301811 - 0.498015668118356*I sage: gamma1(int(5)) 24 :: - sage: conjugate(gamma(x)) + sage: conjugate(gamma(x)) # needs sage.symbolic gamma(conjugate(x)) :: - sage: plot(gamma1(x),(x,1,5)) + sage: plot(gamma1(x), (x,1,5)) # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive We are also able to compute the Laurent expansion of the Gamma function (as well as of functions containing the Gamma function):: - sage: gamma(x).series(x==0, 2) + sage: gamma(x).series(x==0, 2) # needs sage.symbolic 1*x^(-1) + (-euler_gamma) + (1/2*euler_gamma^2 + 1/12*pi^2)*x + Order(x^2) - sage: (gamma(x)^2).series(x==0, 1) + sage: (gamma(x)^2).series(x==0, 1) # needs sage.symbolic 1*x^(-2) + (-2*euler_gamma)*x^(-1) + (2*euler_gamma^2 + 1/6*pi^2) + Order(x) To prevent automatic evaluation use the ``hold`` argument:: - sage: gamma1(1/2,hold=True) + sage: gamma1(1/2, hold=True) # needs sage.symbolic gamma(1/2) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: gamma1(1/2,hold=True).simplify() + sage: gamma1(1/2, hold=True).simplify() # needs sage.symbolic sqrt(pi) TESTS: - sage: gamma(x)._sympy_() + sage: gamma(x)._sympy_() # needs sympy sage.symbolic gamma(x) We verify that we can convert this function to Maxima and convert back to Sage:: - sage: z = var('z') - sage: maxima(gamma1(z)).sage() + sage: z = var('z') # needs sage.symbolic + sage: maxima(gamma1(z)).sage() # needs sage.symbolic gamma(z) - sage: latex(gamma1(z)) + sage: latex(gamma1(z)) # needs sage.symbolic \Gamma\left(z\right) Test that :trac:`5556` is fixed:: - sage: gamma1(3/4) + sage: gamma1(3/4) # needs sage.symbolic gamma(3/4) - sage: gamma1(3/4).n(100) + sage: gamma1(3/4).n(100) # needs sage.symbolic 1.2254167024651776451290983034 Check that negative integer input works:: sage: (-1).gamma() Infinity - sage: (-1.).gamma() + sage: (-1.).gamma() # needs sage.rings.real_mpfr NaN - sage: CC(-1).gamma() + sage: CC(-1).gamma() # needs sage.libs.pari Infinity sage: RDF(-1).gamma() NaN - sage: CDF(-1).gamma() + sage: CDF(-1).gamma() # needs sage.libs.pari sage.rings.complex_double Infinity Check if :trac:`8297` is fixed:: - sage: latex(gamma(1/4)) + sage: latex(gamma(1/4)) # needs sage.symbolic \Gamma\left(\frac{1}{4}\right) Test pickling:: - sage: loads(dumps(gamma(x))) + sage: loads(dumps(gamma(x))) # needs sage.symbolic gamma(x) Check that the implementations roughly agrees (note there might be difference of several ulp on more complicated entries):: - sage: import mpmath - sage: float(gamma(10.)) == gamma(10.r) == float(gamma(mpmath.mpf(10))) + sage: import mpmath # needs mpmath + sage: float(gamma(10.)) == gamma(10.r) == float(gamma(mpmath.mpf(10))) # needs mpmath True - sage: float(gamma(8.5)) == gamma(8.5r) == float(gamma(mpmath.mpf(8.5))) + sage: float(gamma(8.5)) == gamma(8.5r) == float(gamma(mpmath.mpf(8.5))) # needs mpmath True Check that ``QQbar`` half integers work with the ``pi`` formula:: - sage: gamma(QQbar(1/2)) + sage: gamma(QQbar(1/2)) # needs sage.rings.number_field sage.symbolic sqrt(pi) - sage: gamma(QQbar(-9/2)) + sage: gamma(QQbar(-9/2)) # needs sage.rings.number_field sage.symbolic -32/945*sqrt(pi) .. SEEALSO:: @@ -197,14 +205,13 @@ def __init__(self): Numerical evaluation happens when appropriate, to the appropriate accuracy (see :trac:`10072`):: + sage: # needs sage.symbolic sage: log_gamma(6) log(120) sage: log_gamma(6.) 4.78749174278205 sage: log_gamma(6).n() 4.78749174278205 - sage: log_gamma(RealField(100)(6)) - 4.7874917427820459942477009345 sage: log_gamma(2.4 + I) -0.0308566579348816 + 0.693427705955790*I sage: log_gamma(-3.1) @@ -212,17 +219,21 @@ def __init__(self): sage: log_gamma(-1.1) == log(gamma(-1.1)) False + sage: log_gamma(RealField(100)(6)) # needs sage.rings.real_mpfr + 4.7874917427820459942477009345 + Symbolic input works (see :trac:`10075`):: - sage: log_gamma(3*x) + sage: log_gamma(3*x) # needs sage.symbolic log_gamma(3*x) - sage: log_gamma(3 + I) + sage: log_gamma(3 + I) # needs sage.symbolic log_gamma(I + 3) - sage: log_gamma(3 + I + x) + sage: log_gamma(3 + I + x) # needs sage.symbolic log_gamma(x + I + 3) Check that :trac:`12521` is fixed:: + sage: # needs sage.symbolic sage: log_gamma(-2.1) 1.53171380819509 - 9.42477796076938*I sage: log_gamma(CC(-2.1)) @@ -237,35 +248,38 @@ def __init__(self): to evaluate a held expression, use the ``n()`` numerical evaluation method:: - sage: log_gamma(SR(5), hold=True) + sage: log_gamma(SR(5), hold=True) # needs sage.symbolic log_gamma(5) - sage: log_gamma(SR(5), hold=True).n() + sage: log_gamma(SR(5), hold=True).n() # needs sage.symbolic 3.17805383034795 TESTS:: + sage: log_gamma(pari(6)) # needs sage.libs.pari + 4.78749174278205 + + sage: # needs sage.symbolic sage: log_gamma(-2.1 + I) -1.90373724496982 - 7.18482377077183*I - sage: log_gamma(pari(6)) - 4.78749174278205 - sage: log_gamma(x)._sympy_() + sage: log_gamma(x)._sympy_() # needs sympy loggamma(x) - sage: log_gamma(CC(6)) + sage: log_gamma(CC(6)) # needs sage.rings.real_mpfr 4.78749174278205 - sage: log_gamma(CC(-2.5)) + sage: log_gamma(CC(-2.5)) # needs sage.rings.real_mpfr -0.0562437164976741 - 9.42477796076938*I sage: log_gamma(RDF(-2.5)) -0.056243716497674054 - 9.42477796076938*I - sage: log_gamma(CDF(-2.5)) + sage: log_gamma(CDF(-2.5)) # needs sage.rings.complex_double -0.056243716497674054 - 9.42477796076938*I sage: log_gamma(float(-2.5)) (-0.056243716497674054-9.42477796076938j) - sage: log_gamma(complex(-2.5)) + sage: log_gamma(complex(-2.5)) # needs sage.rings.complex_double (-0.056243716497674054-9.42477796076938j) ``conjugate(log_gamma(x)) == log_gamma(conjugate(x))`` unless on the branch cut, which runs along the negative real axis.:: + sage: # needs sage.symbolic sage: conjugate(log_gamma(x)) conjugate(log_gamma(x)) sage: var('y', domain='positive') @@ -302,45 +316,49 @@ def __init__(self): EXAMPLES:: - sage: gamma_inc(CDF(0,1), 3) + sage: gamma_inc(CDF(0,1), 3) # needs sage.libs.pari sage.rings.complex_double 0.0032085749933691158 + 0.012406185811871568*I - sage: gamma_inc(RDF(1), 3) + sage: gamma_inc(RDF(1), 3) # needs sage.rings.complex_double 0.049787068367863944 - sage: gamma_inc(3,2) + + sage: # needs sage.symbolic + sage: gamma_inc(3, 2) gamma(3, 2) - sage: gamma_inc(x,0) + sage: gamma_inc(x, 0) gamma(x) - sage: latex(gamma_inc(3,2)) + sage: latex(gamma_inc(3, 2)) \Gamma\left(3, 2\right) - sage: loads(dumps((gamma_inc(3,2)))) + sage: loads(dumps((gamma_inc(3, 2)))) gamma(3, 2) - sage: i = ComplexField(30).0; gamma_inc(2, 1 + i) + + sage: i = ComplexField(30).0; gamma_inc(2, 1 + i) # needs sage.rings.real_mpfr 0.70709210 - 0.42035364*I - sage: gamma_inc(2., 5) + sage: gamma_inc(2., 5) # needs sage.rings.complex_double 0.0404276819945128 - sage: x,y=var('x,y') - sage: gamma_inc(x,y).diff(x) + + sage: x, y = var('x,y') # needs sage.symbolic + sage: gamma_inc(x,y).diff(x) # needs sage.symbolic diff(gamma(x, y), x) - sage: (gamma_inc(x,x+1).diff(x)).simplify() + sage: (gamma_inc(x, x + 1).diff(x)).simplify() # needs sage.symbolic -(x + 1)^(x - 1)*e^(-x - 1) + D[0](gamma)(x, x + 1) TESTS: Check that :trac:`21407` is fixed:: - sage: gamma(-1,5)._sympy_() + sage: gamma(-1, 5)._sympy_() # needs sympy sage.symbolic expint(2, 5)/5 - sage: gamma(-3/2,5)._sympy_() + sage: gamma(-3/2, 5)._sympy_() # needs sympy sage.symbolic -6*sqrt(5)*exp(-5)/25 + 4*sqrt(pi)*erfc(sqrt(5))/3 Check that :trac:`25597` is fixed:: - sage: gamma(-1,5)._fricas_() # optional - fricas + sage: gamma(-1, 5)._fricas_() # optional - fricas, needs sage.symbolic Gamma(- 1,5) - sage: var('t') # optional - fricas + sage: var('t') # needs sage.symbolic t - sage: integrate(-exp(-x)*x^(t-1), x, algorithm="fricas") # optional - fricas + sage: integrate(-exp(-x)*x^(t-1), x, algorithm="fricas") # optional - fricas, needs sage.symbolic gamma(t, x) .. SEEALSO:: @@ -356,6 +374,7 @@ def _method_arguments(self, x, y): r""" TESTS:: + sage: # needs sage.libs.flint sage: b = RBF(1, 1e-10) sage: gamma(b) # abs tol 1e-9 [1.0000000000 +/- 5.78e-11] @@ -372,21 +391,23 @@ def _eval_(self, x, y): """ EXAMPLES:: - sage: gamma_inc(2.,0) + sage: gamma_inc(2., 0) # needs sage.rings.complex_double 1.00000000000000 - sage: gamma_inc(2,0) + sage: gamma_inc(2, 0) # needs sage.rings.real_mpfr 1 - sage: gamma_inc(1/2,2) + + sage: # needs sage.symbolic + sage: gamma_inc(1/2, 2) -sqrt(pi)*(erf(sqrt(2)) - 1) - sage: gamma_inc(1/2,1) + sage: gamma_inc(1/2, 1) -sqrt(pi)*(erf(1) - 1) - sage: gamma_inc(1/2,0) + sage: gamma_inc(1/2, 0) sqrt(pi) - sage: gamma_inc(x,0) + sage: gamma_inc(x, 0) gamma(x) - sage: gamma_inc(1,2) + sage: gamma_inc(1, 2) e^(-2) - sage: gamma_inc(0,2) + sage: gamma_inc(0, 2) -Ei(-2) """ if y == 0: @@ -396,7 +417,6 @@ def _eval_(self, x, 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 @@ -404,41 +424,41 @@ def _evalf_(self, x, y, parent=None, algorithm='pari'): """ EXAMPLES:: - sage: gamma_inc(0,2) + sage: gamma_inc(0, 2) # needs sage.symbolic -Ei(-2) - sage: gamma_inc(0,2.) + sage: gamma_inc(0, 2.) # needs sage.rings.real_mpfr 0.0489005107080611 - sage: gamma_inc(0,2).n(algorithm='pari') + sage: gamma_inc(0, 2).n(algorithm='pari') # needs sage.libs.pari sage.symbolic 0.0489005107080611 - sage: gamma_inc(0,2).n(200) + sage: gamma_inc(0, 2).n(200) # needs sage.symbolic 0.048900510708061119567239835228... - sage: gamma_inc(3,2).n() + sage: gamma_inc(3, 2).n() # needs sage.symbolic 1.35335283236613 TESTS: Check that :trac:`7099` is fixed:: - sage: R = RealField(1024) - sage: gamma(R(9), R(10^-3)) # rel tol 1e-308 + sage: R = RealField(1024) # needs sage.rings.real_mpfr + sage: gamma(R(9), R(10^-3)) # rel tol 1e-308 # needs sage.rings.real_mpfr 40319.99999999999999999999999999988898884344822911869926361916294165058203634104838326009191542490601781777105678829520585311300510347676330951251563007679436243294653538925717144381702105700908686088851362675381239820118402497959018315224423868693918493033078310647199219674433536605771315869983788442389633 - sage: numerical_approx(gamma(9, 10^(-3)) - gamma(9), digits=40) # abs tol 1e-36 + sage: numerical_approx(gamma(9, 10^(-3)) - gamma(9), digits=40) # abs tol 1e-36 # needs sage.symbolic -1.110111598370794007949063502542063148294e-28 Check that :trac:`17328` is fixed:: - sage: gamma_inc(float(-1), float(-1)) + sage: gamma_inc(float(-1), float(-1)) # needs sage.rings.real_mpfr (-0.8231640121031085+3.141592653589793j) - sage: gamma_inc(RR(-1), RR(-1)) + sage: gamma_inc(RR(-1), RR(-1)) # needs sage.rings.complex_double -0.823164012103109 + 3.14159265358979*I - sage: gamma_inc(-1, float(-log(3))) - gamma_inc(-1, float(-log(2))) # abs tol 1e-15 + sage: gamma_inc(-1, float(-log(3))) - gamma_inc(-1, float(-log(2))) # abs tol 1e-15 # needs sage.symbolic (1.2730972164471142+0j) Check that :trac:`17130` is fixed:: - sage: r = gamma_inc(float(0), float(1)); r + sage: r = gamma_inc(float(0), float(1)); r # needs sage.rings.real_mpfr 0.21938393439552029 - sage: type(r) + sage: type(r) # needs sage.rings.real_mpfr <... 'float'> """ R = parent or s_parent(x) @@ -460,8 +480,7 @@ def _evalf_(self, x, y, parent=None, algorithm='pari'): if algorithm == 'pari': v = ComplexField(prec)(x).gamma_inc(y) else: - import mpmath - v = ComplexField(prec)(mpmath_utils.call(mpmath.gammainc, x, y, parent=R)) + v = ComplexField(prec)(_mpmath_utils_call(_mpmath_gammainc, x, y, parent=R)) if v.is_real(): return R(v) else: @@ -484,10 +503,12 @@ def __init__(self): EXAMPLES:: - sage: gamma_inc_lower(CDF(0,1), 3) + sage: gamma_inc_lower(CDF(0,1), 3) # needs sage.rings.complex_double -0.1581584032951798 - 0.5104218539302277*I - sage: gamma_inc_lower(RDF(1), 3) + sage: gamma_inc_lower(RDF(1), 3) # needs sage.rings.complex_double 0.950212931632136 + + sage: # needs sage.symbolic sage: gamma_inc_lower(3, 2, hold=True) gamma_inc_lower(3, 2) sage: gamma_inc_lower(3, 2) @@ -498,16 +519,17 @@ def __init__(self): \gamma\left(x, x\right) sage: loads(dumps((gamma_inc_lower(x, x)))) gamma_inc_lower(x, x) - sage: i = ComplexField(30).0; gamma_inc_lower(2, 1 + i) + + sage: i = ComplexField(30).0; gamma_inc_lower(2, 1 + i) # needs sage.rings.real_mpfr 0.29290790 + 0.42035364*I - sage: gamma_inc_lower(2., 5) + sage: gamma_inc_lower(2., 5) # needs sage.rings.complex_double 0.959572318005487 Interfaces to other software:: - sage: gamma_inc_lower(x,x)._sympy_() + sage: gamma_inc_lower(x, x)._sympy_() # needs sympy sage.symbolic lowergamma(x, x) - sage: maxima(gamma_inc_lower(x,x)) + sage: maxima(gamma_inc_lower(x, x)) # needs sage.symbolic gamma_incomplete_lower(_SAGE_VAR_x,_SAGE_VAR_x) .. SEEALSO:: @@ -522,33 +544,34 @@ def _eval_(self, x, y): """ EXAMPLES:: - sage: gamma_inc_lower(2.,0) + sage: gamma_inc_lower(2., 0) # needs sage.rings.complex_double 0.000000000000000 - sage: gamma_inc_lower(2,0) + + sage: # needs sage.symbolic + sage: gamma_inc_lower(2, 0) 0 - sage: gamma_inc_lower(1/2,2) + sage: gamma_inc_lower(1/2, 2) sqrt(pi)*erf(sqrt(2)) - sage: gamma_inc_lower(1/2,1) + sage: gamma_inc_lower(1/2, 1) sqrt(pi)*erf(1) - sage: gamma_inc_lower(1/2,0) + sage: gamma_inc_lower(1/2, 0) 0 - sage: gamma_inc_lower(x,0) + sage: gamma_inc_lower(x, 0) 0 - sage: gamma_inc_lower(1,2) + sage: gamma_inc_lower(1, 2) -e^(-2) + 1 - sage: gamma_inc_lower(0,2) + sage: gamma_inc_lower(0, 2) +Infinity - sage: gamma_inc_lower(2,377/79) + sage: gamma_inc_lower(2, 377/79) -456/79*e^(-377/79) + 1 - sage: gamma_inc_lower(3,x) + sage: gamma_inc_lower(3, x) -(x^2 + 2*x + 2)*e^(-x) + 2 - sage: gamma_inc_lower(9/2,37/7) + sage: gamma_inc_lower(9/2, 37/7) -1/38416*sqrt(pi)*(1672946*sqrt(259)*e^(-37/7)/sqrt(pi) - 252105*erf(1/7*sqrt(259))) """ if y == 0: return 0 if x == 0: - from sage.rings.infinity import Infinity return Infinity elif x == 1: return 1 - exp(-y) @@ -561,11 +584,11 @@ def _evalf_(self, x, y, parent=None, algorithm='mpmath'): """ EXAMPLES:: - sage: gamma_inc_lower(3,2.) + sage: gamma_inc_lower(3, 2.) # needs sage.rings.real_mpfr 0.646647167633873 - sage: gamma_inc_lower(3,2).n(200) + sage: gamma_inc_lower(3, 2).n(200) # needs sage.symbolic 0.646647167633873081060005050275155... - sage: gamma_inc_lower(0,2.) + sage: gamma_inc_lower(0, 2.) # needs sage.rings.real_mpfr +infinity """ R = parent or s_parent(x) @@ -587,18 +610,17 @@ def _evalf_(self, x, y, parent=None, algorithm='mpmath'): Cx = ComplexField(prec)(x) v = Cx.gamma() - Cx.gamma_inc(y) else: - import mpmath - v = ComplexField(prec)(mpmath_utils.call(mpmath.gammainc, x, 0, y, parent=R)) + v = ComplexField(prec)(_mpmath_utils_call(_mpmath_gammainc, x, 0, y, parent=R)) return R(v) if v.is_real() else C(v) def _derivative_(self, x, y, diff_param=None): """ EXAMPLES:: - sage: x,y = var('x,y') - sage: gamma_inc_lower(x,y).diff(y) + sage: x, y = var('x,y') # needs sage.symbolic + sage: gamma_inc_lower(x, y).diff(y) # needs sage.symbolic y^(x - 1)*e^(-y) - sage: gamma_inc_lower(x,y).diff(x) + sage: gamma_inc_lower(x, y).diff(x) # needs sage.symbolic Traceback (most recent call last): ... NotImplementedError: cannot differentiate gamma_inc_lower in the first parameter @@ -613,7 +635,7 @@ def _mathematica_init_evaled_(self, *args): r""" EXAMPLES:: - sage: gamma_inc_lower(4/3, 1)._mathematica_() # indirect doctest, optional - mathematica + sage: gamma_inc_lower(4/3, 1)._mathematica_() # indirect doctest # optional - mathematica, needs sage.symbolic Gamma[4/3, 0, 1] """ args_mathematica = [] @@ -641,9 +663,9 @@ def gamma(a, *args, **kwds): True sage: gamma(6) 120 - sage: gamma(1/2) + sage: gamma(1/2) # needs sage.symbolic sqrt(pi) - sage: gamma(-4/3) + sage: gamma(-4/3) # needs sage.symbolic gamma(-4/3) sage: gamma(-1) Infinity @@ -652,47 +674,48 @@ def gamma(a, *args, **kwds): :: - sage: gamma_inc(3,2) + sage: gamma_inc(3, 2) # needs sage.symbolic gamma(3, 2) - sage: gamma_inc(x,0) + sage: gamma_inc(x,0) # needs sage.symbolic gamma(x) :: - sage: gamma(5, hold=True) + sage: gamma(5, hold=True) # needs sage.symbolic gamma(5) - sage: gamma(x, 0, hold=True) + sage: gamma(x, 0, hold=True) # needs sage.symbolic gamma(x, 0) :: - sage: gamma(CDF(I)) + sage: gamma(CDF(I)) # needs sage.libs.pari sage.symbolic -0.15494982830181067 - 0.49801566811835607*I - sage: gamma(CDF(0.5,14)) + sage: gamma(CDF(0.5, 14)) # needs sage.libs.pari -4.0537030780372815e-10 - 5.773299834553605e-10*I Use ``numerical_approx`` to get higher precision from symbolic expressions:: - sage: gamma(pi).n(100) + sage: gamma(pi).n(100) # needs sage.symbolic 2.2880377953400324179595889091 - sage: gamma(3/4).n(100) + sage: gamma(3/4).n(100) # needs sage.symbolic 1.2254167024651776451290983034 The precision for the result is also deduced from the precision of the input. Convert the input to a higher precision explicitly if a result with higher precision is desired.:: - sage: t = gamma(RealField(100)(2.5)); t + sage: t = gamma(RealField(100)(2.5)); t # needs sage.rings.real_mpfr 1.3293403881791370204736256125 - sage: t.prec() + sage: t.prec() # needs sage.rings.real_mpfr 100 The gamma function only works with input that can be coerced to the Symbolic Ring:: - sage: Q. = NumberField(x^2+1) - sage: gamma(i) + sage: x = polygen(ZZ, 'x') + sage: Q. = NumberField(x^2 + 1) # needs sage.rings.number_field + sage: gamma(i) # needs sage.rings.number_field sage.symbolic Traceback (most recent call last): ... TypeError: cannot coerce arguments: no canonical coercion from Number Field in i with defining polynomial x^2 + 1 to Symbolic Ring @@ -743,37 +766,38 @@ def __init__(self): EXAMPLES:: sage: from sage.functions.gamma import psi1 - sage: psi1(x) + sage: psi1(x) # needs sage.symbolic psi(x) - sage: psi1(x).derivative(x) + sage: psi1(x).derivative(x) # needs sage.symbolic psi(1, x) :: - sage: psi1(3) + sage: psi1(3) # needs sage.symbolic -euler_gamma + 3/2 :: - sage: psi(.5) + sage: psi(.5) # needs sage.symbolic -1.96351002602142 - sage: psi(RealField(100)(.5)) + sage: psi(RealField(100)(.5)) # needs sage.rings.real_mpfr sage.symbolic -1.9635100260214234794409763330 TESTS:: - sage: latex(psi1(x)) + sage: latex(psi1(x)) # needs sage.symbolic \psi\left(x\right) - sage: loads(dumps(psi1(x)+1)) + sage: loads(dumps(psi1(x) + 1)) # needs sage.symbolic psi(x) + 1 + sage: # needs sage.symbolic sage: t = psi1(x); t psi(x) sage: t.subs(x=.2) -5.28903989659219 - sage: psi(x)._sympy_() + sage: psi(x)._sympy_() # needs sympy polygamma(0, x) - sage: psi(x)._fricas_() # optional - fricas + sage: psi(x)._fricas_() # optional - fricas digamma(x) """ GinacFunction.__init__(self, "psi", nargs=1, latex_name=r'\psi', @@ -791,6 +815,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.functions.gamma import psi2 sage: psi2(2, x) psi(2, x) @@ -802,39 +827,40 @@ def __init__(self): :: - sage: psi2(0, x) + sage: psi2(0, x) # needs sage.symbolic psi(x) - sage: psi2(-1, x) + sage: psi2(-1, x) # needs sage.symbolic log(gamma(x)) - sage: psi2(3, 1) + sage: psi2(3, 1) # needs sage.symbolic 1/15*pi^4 :: - sage: psi2(2, .5).n() + sage: psi2(2, .5).n() # needs sage.symbolic -16.8287966442343 - sage: psi2(2, .5).n(100) + sage: psi2(2, .5).n(100) # needs sage.symbolic -16.828796644234319995596334261 TESTS:: - sage: psi2(n, x).derivative(n) + sage: psi2(n, x).derivative(n) # needs sage.symbolic Traceback (most recent call last): ... RuntimeError: cannot diff psi(n,x) with respect to n + sage: # needs sage.symbolic sage: latex(psi2(2,x)) \psi\left(2, x\right) - sage: loads(dumps(psi2(2,x)+1)) + sage: loads(dumps(psi2(2,x) + 1)) psi(2, x) + 1 - sage: psi(2, x)._sympy_() + sage: psi(2, x)._sympy_() # needs sympy polygamma(2, x) - sage: psi(2, x)._fricas_() # optional - fricas + sage: psi(2, x)._fricas_() # optional - fricas polygamma(2,x) Fixed conversion:: - sage: psi(2,x)._maple_init_() + sage: psi(2, x)._maple_init_() # needs sage.symbolic 'Psi(2,x)' """ GinacFunction.__init__(self, "psi", nargs=2, latex_name=r'\psi', @@ -851,9 +877,9 @@ def _maxima_init_evaled_(self, *args): These are indirect doctests for this function.:: sage: from sage.functions.gamma import psi2 - sage: psi2(2, x)._maxima_() + sage: psi2(2, x)._maxima_() # needs sage.symbolic psi[2](_SAGE_VAR_x) - sage: psi2(4, x)._maxima_() + sage: psi2(4, x)._maxima_() # needs sage.symbolic psi[4](_SAGE_VAR_x) """ args_maxima = [] @@ -885,6 +911,7 @@ def psi(x, *args, **kwds): EXAMPLES:: + sage: # needs sage.symbolic sage: psi(x) psi(x) sage: psi(.5) @@ -900,14 +927,14 @@ def psi(x, *args, **kwds): :: - sage: psi(3, hold=True) + sage: psi(3, hold=True) # needs sage.symbolic psi(3) - sage: psi(1, 5, hold=True) + sage: psi(1, 5, hold=True) # needs sage.symbolic psi(1, 5) TESTS:: - sage: psi(2, x, 3) + sage: psi(2, x, 3) # needs sage.symbolic Traceback (most recent call last): ... TypeError: Symbolic function psi takes at most 2 arguments (3 given) @@ -979,30 +1006,32 @@ def __init__(self): EXAMPLES:: - sage: beta(3,2) + sage: # needs sage.symbolic + sage: beta(3, 2) 1/12 sage: beta(3,1) 1/3 - sage: beta(1/2,1/2) + sage: beta(1/2, 1/2) beta(1/2, 1/2) sage: beta(-1,1) -1 sage: beta(-1/2,-1/2) 0 - sage: ex = beta(x/2,3) + sage: ex = beta(x/2, 3) sage: set(ex.operands()) == set([1/2*x, 3]) True sage: beta(.5,.5) 3.14159265358979 - sage: beta(1,2.0+I) + sage: beta(1, 2.0+I) 0.400000000000000 - 0.200000000000000*I - sage: ex = beta(3,x+I) + sage: ex = beta(3, x+I) sage: set(ex.operands()) == set([x+I, 3]) True The result is symbolic if exact input is given:: - sage: ex = beta(2,1+5*I); ex + sage: # needs sage.symbolic + sage: ex = beta(2, 1+5*I); ex beta(... sage: set(ex.operands()) == set([1+5*I, 2]) True @@ -1015,7 +1044,7 @@ def __init__(self): sage: beta(2., I) -0.500000000000000 - 0.500000000000000*I - sage: beta(x, x)._sympy_() + sage: beta(x, x)._sympy_() # needs sympy sage.symbolic beta(x, x) Test pickling:: @@ -1025,7 +1054,7 @@ def __init__(self): Check that :trac:`15196` is fixed:: - sage: beta(-1.3,-0.4) + sage: beta(-1.3, -0.4) # needs sage.symbolic -4.92909641669610 """ GinacFunction.__init__(self, 'beta', nargs=2, @@ -1041,7 +1070,7 @@ def _method_arguments(self, x, y): r""" TESTS:: - sage: RBF(beta(sin(3),sqrt(RBF(2).add_error(1e-8)/3))) # abs tol 6e-7 + sage: RBF(beta(sin(3), sqrt(RBF(2).add_error(1e-8)/3))) # abs tol 6e-7 # needs sage.libs.flint sage.symbolic [7.407662 +/- 6.17e-7] """ return [x, y] diff --git a/src/sage/functions/generalized.py b/src/sage/functions/generalized.py index d912ea23719..3d58d4d9d0a 100644 --- a/src/sage/functions/generalized.py +++ b/src/sage/functions/generalized.py @@ -16,28 +16,28 @@ Dirac delta function:: - sage: dirac_delta(x) + sage: dirac_delta(x) # needs sage.symbolic dirac_delta(x) Heaviside step function:: - sage: heaviside(x) + sage: heaviside(x) # needs sage.symbolic heaviside(x) Unit step function:: - sage: unit_step(x) + sage: unit_step(x) # needs sage.symbolic unit_step(x) Signum (sgn) function:: - sage: sgn(x) + sage: sgn(x) # needs sage.symbolic sgn(x) Kronecker delta function:: - sage: m,n=var('m,n') - sage: kronecker_delta(m,n) + sage: m, n = var('m,n') # needs sage.symbolic + sage: kronecker_delta(m, n) # needs sage.symbolic kronecker_delta(m, n) """ @@ -51,9 +51,12 @@ # ############################################################################## -from sage.symbolic.function import (BuiltinFunction, GinacFunction) -from sage.rings.complex_interval_field import ComplexIntervalField +from sage.misc.lazy_import import lazy_import from sage.rings.integer_ring import ZZ +from sage.symbolic.function import BuiltinFunction, GinacFunction + +lazy_import('sage.misc.latex', 'latex') +lazy_import('sage.rings.complex_interval_field', 'ComplexIntervalField') class FunctionDiracDelta(BuiltinFunction): @@ -78,13 +81,14 @@ class FunctionDiracDelta(BuiltinFunction): EXAMPLES:: + sage: # needs sage.symbolic sage: dirac_delta(1) 0 sage: dirac_delta(0) dirac_delta(0) sage: dirac_delta(x) dirac_delta(x) - sage: integrate(dirac_delta(x), x, -1, 1, algorithm='sympy') + sage: integrate(dirac_delta(x), x, -1, 1, algorithm='sympy') # needs sympy 1 REFERENCES: @@ -102,6 +106,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: dirac_delta(1) 0 sage: dirac_delta(0) @@ -111,9 +116,9 @@ def __init__(self): sage: latex(dirac_delta(x)) \delta\left(x\right) - sage: loads(dumps(dirac_delta(x))) + sage: loads(dumps(dirac_delta(x))) # needs sage.symbolic dirac_delta(x) - sage: dirac_delta(x)._sympy_() + sage: dirac_delta(x)._sympy_() # needs sympy sage.symbolic DiracDelta(x) """ BuiltinFunction.__init__(self, "dirac_delta", latex_name=r"\delta", @@ -130,6 +135,7 @@ def _eval_(self, x): EXAMPLES:: + sage: # needs sage.symbolic sage: dirac_delta(1) 0 sage: dirac_delta(0) @@ -141,7 +147,7 @@ def _eval_(self, x): Evaluation test:: - sage: dirac_delta(x).subs(x=1) + sage: dirac_delta(x).subs(x=1) # needs sage.symbolic 0 """ try: @@ -154,8 +160,8 @@ def _evalf_(self, x, **kwds): """ TESTS:: - sage: h(x) = dirac_delta(x) - sage: h(pi).numerical_approx() + sage: h(x) = dirac_delta(x) # needs sage.symbolic + sage: h(pi).numerical_approx() # needs sage.symbolic 0.000000000000000 """ approx_x = ComplexIntervalField()(x) @@ -188,6 +194,7 @@ class FunctionHeaviside(GinacFunction): EXAMPLES:: + sage: # needs sage.symbolic sage: heaviside(-1) 0 sage: heaviside(1) @@ -197,23 +204,24 @@ class FunctionHeaviside(GinacFunction): sage: heaviside(x) heaviside(x) - sage: heaviside(-1/2) + sage: heaviside(-1/2) # needs sage.symbolic 0 - sage: heaviside(exp(-1000000000000000000000)) + sage: heaviside(exp(-1000000000000000000000)) # needs sage.symbolic 1 TESTS:: - sage: heaviside(x)._sympy_() + sage: heaviside(x)._sympy_() # needs sympy sage.symbolic Heaviside(x) - sage: heaviside(x).subs(x=1) + sage: heaviside(x).subs(x=1) # needs sage.symbolic 1 - sage: heaviside(x).subs(x=-1) + sage: heaviside(x).subs(x=-1) # needs sage.symbolic 0 :: - sage: ex = heaviside(x)+1 + sage: # needs sage.symbolic + sage: ex = heaviside(x) + 1 sage: t = loads(dumps(ex)); t heaviside(x) + 1 sage: bool(t == ex) @@ -236,6 +244,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: heaviside(-1) 0 sage: heaviside(1) @@ -246,9 +255,9 @@ def __init__(self): heaviside(x) sage: latex(heaviside(x)) H\left(x\right) - sage: heaviside(x)._sympy_() + sage: heaviside(x)._sympy_() # needs sympy Heaviside(x) - sage: heaviside(x)._giac_() + sage: heaviside(x)._giac_() # needs sage.libs.giac Heaviside(sageVARx) sage: h(x) = heaviside(x) sage: h(pi).numerical_approx() @@ -266,7 +275,7 @@ def _derivative_(self, x, diff_param=None): EXAMPLES:: - sage: heaviside(x).diff(x) + sage: heaviside(x).diff(x) # needs sage.symbolic dirac_delta(x) """ return dirac_delta(x) @@ -293,6 +302,7 @@ class FunctionUnitStep(GinacFunction): EXAMPLES:: + sage: # needs sage.symbolic sage: unit_step(-1) 0 sage: unit_step(1) @@ -306,6 +316,7 @@ class FunctionUnitStep(GinacFunction): TESTS:: + sage: # needs sage.symbolic sage: unit_step(x).subs(x=1) 1 sage: unit_step(x).subs(x=0) @@ -324,6 +335,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: unit_step(-1) 0 sage: unit_step(1) @@ -337,9 +349,9 @@ def __init__(self): TESTS:: - sage: t = loads(dumps(unit_step(x)+1)); t + sage: t = loads(dumps(unit_step(x) + 1)); t # needs sage.symbolic unit_step(x) + 1 - sage: t.subs(x=0) + sage: t.subs(x=0) # needs sage.symbolic 2 """ GinacFunction.__init__(self, "unit_step", latex_name=r"\mathrm{u}", @@ -351,7 +363,7 @@ def _derivative_(self, x, diff_param=None): EXAMPLES:: - sage: unit_step(x).diff(x) + sage: unit_step(x).diff(x) # needs sage.symbolic dirac_delta(x) """ return dirac_delta(x) @@ -384,7 +396,7 @@ class FunctionSignum(BuiltinFunction): 1 sage: sgn(0) 0 - sage: sgn(x) + sage: sgn(x) # needs sage.symbolic sgn(x) We can also use ``sign``:: @@ -393,24 +405,24 @@ class FunctionSignum(BuiltinFunction): 1 sage: sign(0) 0 - sage: a = AA(-5).nth_root(7) - sage: sign(a) + sage: a = AA(-5).nth_root(7) # needs sage.rings.number_field + sage: sign(a) # needs sage.rings.number_field -1 TESTS: Check if conversions to sympy and others work (:trac:`11921`):: - sage: sgn(x)._sympy_() + sage: sgn(x)._sympy_() # needs sympy sage.symbolic sign(x) - sage: sgn(x)._fricas_init_() + sage: sgn(x)._fricas_init_() # needs sage.symbolic '(x+->abs(x)/x)(x)' - sage: sgn(x)._giac_() + sage: sgn(x)._giac_() # needs sage.libs.giac sage.symbolic sign(sageVARx) Test for :trac:`31085`:: - sage: fricas(sign(x)).eval(x=-3) # optional - fricas + sage: fricas(sign(x)).eval(x=-3) # optional - fricas # needs sage.symbolic - 1 REFERENCES: @@ -430,9 +442,9 @@ def __init__(self): 1 sage: sgn(0) 0 - sage: sgn(x) + sage: sgn(x) # needs sage.symbolic sgn(x) - sage: sgn(x)._sympy_() + sage: sgn(x)._sympy_() # needs sympy sage.symbolic sign(x) """ BuiltinFunction.__init__(self, "sgn", latex_name=r"\mathrm{sgn}", @@ -452,18 +464,18 @@ def _eval_(self, x): 1 sage: sgn(0) 0 - sage: sgn(x) + sage: sgn(x) # needs sage.symbolic sgn(x) - sage: sgn(-exp(-10000000000000000000)) + sage: sgn(-exp(-10000000000000000000)) # needs sage.symbolic -1 Evaluation test:: - sage: sgn(x).subs(x=1) + sage: sgn(x).subs(x=1) # needs sage.symbolic 1 - sage: sgn(x).subs(x=0) + sage: sgn(x).subs(x=0) # needs sage.symbolic 0 - sage: sgn(x).subs(x=-1) + sage: sgn(x).subs(x=-1) # needs sage.symbolic -1 More tests:: @@ -472,9 +484,9 @@ def _eval_(self, x): 1 sage: sign(RDF(2)) 1 - sage: sign(AA(-2)) + sage: sign(AA(-2)) # needs sage.rings.number_field -1 - sage: sign(AA(0)) + sage: sign(AA(0)) # needs sage.rings.number_field 0 """ try: @@ -489,6 +501,7 @@ def _evalf_(self, x, **kwds): Check that :trac:`16587` is fixed:: + sage: # needs sage.symbolic sage: M = sgn(3/2, hold=True); M sgn(3/2) sage: M.n() @@ -518,7 +531,7 @@ def _derivative_(self, x, diff_param=None): EXAMPLES:: - sage: sgn(x).diff(x) + sage: sgn(x).diff(x) # needs sage.symbolic 2*dirac_delta(x) """ assert diff_param == 0 @@ -547,12 +560,12 @@ class FunctionKroneckerDelta(BuiltinFunction): EXAMPLES:: - sage: kronecker_delta(1,2) + sage: kronecker_delta(1,2) # needs sage.rings.complex_interval_field 0 - sage: kronecker_delta(1,1) + sage: kronecker_delta(1,1) # needs sage.rings.complex_interval_field 1 - sage: m,n=var('m,n') - sage: kronecker_delta(m,n) + sage: m, n = var('m,n') # needs sage.symbolic + sage: kronecker_delta(m, n) # needs sage.symbolic kronecker_delta(m, n) REFERENCES: @@ -566,12 +579,12 @@ def __init__(self): EXAMPLES:: - sage: kronecker_delta(1,2) + sage: kronecker_delta(1,2) # needs sage.rings.complex_interval_field 0 - sage: kronecker_delta(1,1) + sage: kronecker_delta(1,1) # needs sage.rings.complex_interval_field 1 - sage: y = var('y') - sage: kronecker_delta(x, y)._sympy_() + sage: y = var('y') # needs sage.symbolic + sage: kronecker_delta(x, y)._sympy_() # needs sympy sage.symbolic KroneckerDelta(x, y) """ BuiltinFunction.__init__(self, "kronecker_delta", nargs=2, @@ -585,25 +598,26 @@ def _eval_(self, m, n): EXAMPLES:: - sage: kronecker_delta(1,2) + sage: kronecker_delta(1,2) # needs sage.rings.complex_interval_field 0 - sage: kronecker_delta(1,1) + sage: kronecker_delta(1,1) # needs sage.rings.complex_interval_field 1 Kronecker delta is a symmetric function. We keep arguments sorted to ensure that k_d(m, n) - k_d(n, m) cancels automatically:: - sage: x,y = var('x,y') + sage: # needs sage.symbolic + sage: x, y = var('x,y') sage: kronecker_delta(x, y) kronecker_delta(x, y) sage: kronecker_delta(y, x) kronecker_delta(x, y) - sage: kronecker_delta(x,2*x) + sage: kronecker_delta(x, 2*x) kronecker_delta(2*x, x) Evaluation test:: - sage: kronecker_delta(1,x).subs(x=1) + sage: kronecker_delta(1, x).subs(x=1) # needs sage.symbolic 1 """ try: @@ -616,8 +630,8 @@ def _evalf_(self, m, n, **kwds): """ TESTS:: - sage: h(x) = kronecker_delta(3,x) - sage: h(pi).numerical_approx() + sage: h(x) = kronecker_delta(3, x) # needs sage.symbolic + sage: h(pi).numerical_approx() # needs sage.symbolic 0.000000000000000 """ if bool(repr(m) > repr(n)): @@ -637,7 +651,7 @@ def _derivative_(self, *args, **kwds): EXAMPLES:: - sage: kronecker_delta(x,1).diff(x) + sage: kronecker_delta(x, 1).diff(x) # needs sage.symbolic 0 """ # Kronecker delta is non-zero (but finite) only in the set of @@ -653,11 +667,10 @@ def _print_latex_(self, m, n, **kwds): EXAMPLES:: sage: from sage.misc.latex import latex - sage: m,n=var('m,n') - sage: latex(kronecker_delta(m,n)) + sage: m, n = var('m,n') # needs sage.symbolic + sage: latex(kronecker_delta(m, n)) # needs sage.symbolic \delta_{m,n} """ - from sage.misc.latex import latex return r"\delta_{%s,%s}" % (latex(m), latex(n)) diff --git a/src/sage/functions/hyperbolic.py b/src/sage/functions/hyperbolic.py index 9a362b8882f..6c70caef310 100644 --- a/src/sage/functions/hyperbolic.py +++ b/src/sage/functions/hyperbolic.py @@ -28,16 +28,15 @@ Inverse hyperbolic functions have logarithmic expressions, so expressions of the form ``exp(c*f(x))`` simplify:: + sage: # needs sage.symbolic sage: exp(2*atanh(x)) -(x + 1)/(x - 1) sage: exp(2*acoth(x)) (x + 1)/(x - 1) - sage: exp(2*asinh(x)) (x + sqrt(x^2 + 1))^2 sage: exp(2*acosh(x)) (x + sqrt(x^2 - 1))^2 - sage: exp(2*asech(x)) (sqrt(-x^2 + 1)/x + 1/x)^2 sage: exp(2*acsch(x)) @@ -54,28 +53,29 @@ def __init__(self): EXAMPLES:: - sage: sinh(pi) - sinh(pi) sage: sinh(3.1415) 11.5476653707437 + + sage: # needs sage.symbolic + sage: sinh(pi) + sinh(pi) sage: float(sinh(pi)) 11.54873935725774... sage: RR(sinh(pi)) 11.5487393572577 - sage: latex(sinh(x)) \sinh\left(x\right) - sage: sinh(x)._sympy_() + sage: sinh(x)._sympy_() # needs sympy sinh(x) To prevent automatic evaluation, use the ``hold`` parameter:: - sage: sinh(arccosh(x),hold=True) + sage: sinh(arccosh(x), hold=True) # needs sage.symbolic sinh(arccosh(x)) To then evaluate again, use the ``unhold`` method:: - sage: sinh(arccosh(x),hold=True).unhold() + sage: sinh(arccosh(x), hold=True).unhold() # needs sage.symbolic sqrt(x + 1)*sqrt(x - 1) """ GinacFunction.__init__(self, "sinh", latex_name=r"\sinh") @@ -91,28 +91,29 @@ def __init__(self): EXAMPLES:: - sage: cosh(pi) - cosh(pi) sage: cosh(3.1415) 11.5908832931176 + + sage: # needs sage.symbolic + sage: cosh(pi) + cosh(pi) sage: float(cosh(pi)) 11.591953275521519 sage: RR(cosh(1/2)) 1.12762596520638 - sage: latex(cosh(x)) \cosh\left(x\right) - sage: cosh(x)._sympy_() + sage: cosh(x)._sympy_() # needs sympy cosh(x) To prevent automatic evaluation, use the ``hold`` parameter:: - sage: cosh(arcsinh(x),hold=True) + sage: cosh(arcsinh(x), hold=True) # needs sage.symbolic cosh(arcsinh(x)) To then evaluate again, use the ``unhold`` method:: - sage: cosh(arcsinh(x),hold=True).unhold() + sage: cosh(arcsinh(x), hold=True).unhold() # needs sage.symbolic sqrt(x^2 + 1) """ GinacFunction.__init__(self, "cosh", latex_name=r"\cosh") @@ -128,14 +129,16 @@ def __init__(self): EXAMPLES:: - sage: tanh(pi) - tanh(pi) sage: tanh(3.1415) 0.996271386633702 - sage: float(tanh(pi)) - 0.99627207622075 sage: tan(3.1415/4) 0.999953674278156 + + sage: # needs sage.symbolic + sage: tanh(pi) + tanh(pi) + sage: float(tanh(pi)) + 0.99627207622075 sage: tanh(pi/4) tanh(1/4*pi) sage: RR(tanh(1/2)) @@ -143,32 +146,33 @@ def __init__(self): :: - sage: CC(tanh(pi + I*e)) + sage: CC(tanh(pi + I*e)) # needs sage.rings.real_mpfr sage.symbolic 0.997524731976164 - 0.00279068768100315*I - sage: ComplexField(100)(tanh(pi + I*e)) + sage: ComplexField(100)(tanh(pi + I*e)) # needs sage.rings.real_mpfr sage.symbolic 0.99752473197616361034204366446 - 0.0027906876810031453884245163923*I - sage: CDF(tanh(pi + I*e)) # rel tol 2e-15 + sage: CDF(tanh(pi + I*e)) # rel tol 2e-15 # needs sage.rings.complex_double sage.symbolic 0.9975247319761636 - 0.002790687681003147*I To prevent automatic evaluation, use the ``hold`` parameter:: - sage: tanh(arcsinh(x),hold=True) + sage: tanh(arcsinh(x), hold=True) # needs sage.symbolic tanh(arcsinh(x)) To then evaluate again, use the ``unhold`` method:: - sage: tanh(arcsinh(x),hold=True).unhold() + sage: tanh(arcsinh(x), hold=True).unhold() # needs sage.symbolic x/sqrt(x^2 + 1) TESTS:: - sage: latex(tanh(x)) + sage: latex(tanh(x)) # needs sage.symbolic \tanh\left(x\right) - sage: tanh(x)._sympy_() + sage: tanh(x)._sympy_() # needs sympy sage.symbolic tanh(x) Check that real/imaginary parts are correct (:trac:`20098`):: + sage: # needs sage.symbolic sage: tanh(1+2*I).n() 1.16673625724092 - 0.243458201185725*I sage: tanh(1+2*I).real().n() @@ -193,6 +197,12 @@ def __init__(self): EXAMPLES:: + sage: coth(3.1415) + 1.00374256795520 + sage: coth(complex(1, 2)) # abs tol 1e-15 # needs sage.rings.complex_double + (0.8213297974938518+0.17138361290918508j) + + sage: # needs sage.symbolic sage: coth(pi) coth(pi) sage: coth(0) @@ -207,22 +217,19 @@ def __init__(self): Infinity sage: coth(7.*pi*I/2) -I*cot(3.50000000000000*pi) - sage: coth(3.1415) - 1.00374256795520 sage: float(coth(pi)) 1.0037418731973213 sage: RR(coth(pi)) 1.00374187319732 - sage: coth(complex(1, 2)) # abs tol 1e-15 - (0.8213297974938518+0.17138361290918508j) + sage: # needs sage.symbolic sage: bool(diff(coth(x), x) == diff(1/tanh(x), x)) True sage: diff(coth(x), x) -1/sinh(x)^2 sage: latex(coth(x)) \coth\left(x\right) - sage: coth(x)._sympy_() + sage: coth(x)._sympy_() # needs sympy coth(x) """ GinacFunction.__init__(self, "coth", latex_name=r"\coth") @@ -231,9 +238,9 @@ def _eval_numpy_(self, x): """ EXAMPLES:: - sage: import numpy - sage: a = numpy.arange(2, 5) - sage: coth(a) + sage: import numpy # needs numpy + sage: a = numpy.arange(2, 5) # needs numpy + sage: coth(a) # needs numpy array([1.03731472, 1.00496982, 1.00067115]) """ return 1.0 / tanh(x) @@ -249,10 +256,12 @@ def __init__(self): EXAMPLES:: - sage: sech(pi) - sech(pi) sage: sech(3.1415) 0.0862747018248192 + + sage: # needs sage.symbolic + sage: sech(pi) + sech(pi) sage: float(sech(pi)) 0.0862667383340544... sage: RR(sech(pi)) @@ -270,13 +279,14 @@ def __init__(self): sage: sech(8.*pi*I/2) sec(4.00000000000000*pi) + sage: # needs sage.symbolic sage: bool(diff(sech(x), x) == diff(1/cosh(x), x)) True sage: diff(sech(x), x) -sech(x)*tanh(x) sage: latex(sech(x)) \operatorname{sech}\left(x\right) - sage: sech(x)._sympy_() + sage: sech(x)._sympy_() # needs sympy sech(x) """ GinacFunction.__init__(self, "sech", latex_name=r"\operatorname{sech}",) @@ -285,9 +295,9 @@ def _eval_numpy_(self, x): """ EXAMPLES:: - sage: import numpy - sage: a = numpy.arange(2, 5) - sage: sech(a) + sage: import numpy # needs numpy + sage: a = numpy.arange(2, 5) # needs numpy + sage: sech(a) # needs numpy array([0.26580223, 0.09932793, 0.03661899]) """ return 1.0 / cosh(x) @@ -303,10 +313,12 @@ def __init__(self): EXAMPLES:: - sage: csch(pi) - csch(pi) sage: csch(3.1415) 0.0865975907592133 + + sage: # needs sage.symbolic + sage: csch(pi) + csch(pi) sage: float(csch(pi)) 0.0865895375300469... sage: RR(csch(pi)) @@ -322,13 +334,14 @@ def __init__(self): sage: csch(7.*pi*I/2) -I*csc(3.50000000000000*pi) + sage: # needs sage.symbolic sage: bool(diff(csch(x), x) == diff(1/sinh(x), x)) True sage: diff(csch(x), x) -coth(x)*csch(x) sage: latex(csch(x)) \operatorname{csch}\left(x\right) - sage: csch(x)._sympy_() + sage: csch(x)._sympy_() # needs sympy csch(x) """ GinacFunction.__init__(self, "csch", latex_name=r"\operatorname{csch}") @@ -337,9 +350,9 @@ def _eval_numpy_(self, x): """ EXAMPLES:: - sage: import numpy - sage: a = numpy.arange(2, 5) - sage: csch(a) + sage: import numpy # needs numpy + sage: a = numpy.arange(2, 5) # needs numpy + sage: csch(a) # needs numpy array([0.27572056, 0.09982157, 0.03664357]) """ return 1.0 / sinh(x) @@ -364,24 +377,25 @@ def __init__(self): arcsinh sage: asinh(0.5) 0.481211825059603 - sage: asinh(1/2) + sage: asinh(1/2) # needs sage.symbolic arcsinh(1/2) - sage: asinh(1 + I*1.0) + sage: asinh(1 + I*1.0) # needs sage.symbolic 1.06127506190504 + 0.666239432492515*I To prevent automatic evaluation use the ``hold`` argument:: - sage: asinh(-2,hold=True) + sage: asinh(-2, hold=True) # needs sage.symbolic arcsinh(-2) To then evaluate again, use the ``unhold`` method:: - sage: asinh(-2,hold=True).unhold() + sage: asinh(-2, hold=True).unhold() # needs sage.symbolic -arcsinh(2) ``conjugate(asinh(x))==asinh(conjugate(x))`` unless on the branch cuts which run along the imaginary axis outside the interval [-I, +I].:: + sage: # needs sage.symbolic sage: conjugate(asinh(x)) conjugate(arcsinh(x)) sage: var('y', domain='positive') @@ -399,11 +413,11 @@ def __init__(self): TESTS:: - sage: asinh(x).operator() + sage: asinh(x).operator() # needs sage.symbolic arcsinh - sage: latex(asinh(x)) + sage: latex(asinh(x)) # needs sage.symbolic \operatorname{arsinh}\left(x\right) - sage: asinh(x)._sympy_() + sage: asinh(x)._sympy_() # needs sympy sage.symbolic asinh(x) """ GinacFunction.__init__(self, "arcsinh", @@ -422,6 +436,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: acosh(1/2) arccosh(1/2) sage: acosh(1 + I*1.0) @@ -430,7 +445,8 @@ def __init__(self): 1.3169578969248168 sage: cosh(float(acosh(2))) 2.0 - sage: acosh(complex(1, 2)) # abs tol 1e-15 + + sage: acosh(complex(1, 2)) # abs tol 1e-15 # needs sage.rings.complex_double (1.5285709194809982+1.1437177404024204j) .. warning:: @@ -442,14 +458,16 @@ def __init__(self): :: + sage: acosh(CC(0.5)) # needs sage.rings.real_mpfr + 1.04719755119660*I + + sage: # needs sage.symbolic sage: acosh(0.5) NaN sage: acosh(1/2) arccosh(1/2) sage: acosh(1/2).n() NaN - sage: acosh(CC(0.5)) - 1.04719755119660*I sage: acosh(0) 1/2*I*pi sage: acosh(-1) @@ -457,17 +475,18 @@ def __init__(self): To prevent automatic evaluation use the ``hold`` argument:: - sage: acosh(-1,hold=True) + sage: acosh(-1, hold=True) # needs sage.symbolic arccosh(-1) To then evaluate again, use the ``unhold`` method:: - sage: acosh(-1,hold=True).unhold() + sage: acosh(-1, hold=True).unhold() # needs sage.symbolic I*pi ``conjugate(arccosh(x))==arccosh(conjugate(x))`` unless on the branch cut which runs along the real axis from +1 to -inf.:: + sage: # needs sage.symbolic sage: conjugate(acosh(x)) conjugate(arccosh(x)) sage: var('y', domain='positive') @@ -485,11 +504,11 @@ def __init__(self): TESTS:: - sage: acosh(x).operator() + sage: acosh(x).operator() # needs sage.symbolic arccosh - sage: latex(acosh(x)) + sage: latex(acosh(x)) # needs sage.symbolic \operatorname{arcosh}\left(x\right) - sage: acosh(x)._sympy_() + sage: acosh(x)._sympy_() # needs sympy sage.symbolic acosh(x) """ GinacFunction.__init__(self, "arccosh", @@ -510,31 +529,32 @@ def __init__(self): sage: atanh(0.5) 0.549306144334055 - sage: atanh(1/2) + sage: atanh(1/2) # needs sage.symbolic 1/2*log(3) - sage: atanh(1 + I*1.0) + sage: atanh(1 + I*1.0) # needs sage.symbolic 0.402359478108525 + 1.01722196789785*I To prevent automatic evaluation use the ``hold`` argument:: - sage: atanh(-1/2,hold=True) + sage: atanh(-1/2, hold=True) # needs sage.symbolic arctanh(-1/2) To then evaluate again, use the ``unhold`` method:: - sage: atanh(-1/2,hold=True).unhold() + sage: atanh(-1/2, hold=True).unhold() # needs sage.symbolic -1/2*log(3) ``conjugate(arctanh(x)) == arctanh(conjugate(x))`` unless on the branch cuts which run along the real axis outside the interval [-1, +1]. :: + sage: # needs sage.symbolic sage: conjugate(atanh(x)) conjugate(arctanh(x)) sage: var('y', domain='positive') y sage: conjugate(atanh(y)) conjugate(arctanh(y)) - sage: conjugate(atanh(y+I)) + sage: conjugate(atanh(y + I)) conjugate(arctanh(y + I)) sage: conjugate(atanh(1/16)) 1/2*log(17/15) @@ -545,11 +565,11 @@ def __init__(self): TESTS:: - sage: atanh(x).operator() + sage: atanh(x).operator() # needs sage.symbolic arctanh - sage: latex(atanh(x)) + sage: latex(atanh(x)) # needs sage.symbolic \operatorname{artanh}\left(x\right) - sage: atanh(x)._sympy_() + sage: atanh(x)._sympy_() # needs sympy sage.symbolic atanh(x) """ GinacFunction.__init__(self, "arctanh", @@ -568,6 +588,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: acoth(2.0) 0.549306144334055 sage: acoth(2) @@ -577,28 +598,28 @@ def __init__(self): sage: acoth(2).n(200) 0.54930614433405484569762261846126285232374527891137472586735 - sage: bool(diff(acoth(x), x) == diff(atanh(x), x)) + sage: bool(diff(acoth(x), x) == diff(atanh(x), x)) # needs sage.symbolic True - sage: diff(acoth(x), x) + sage: diff(acoth(x), x) # needs sage.symbolic -1/(x^2 - 1) - sage: float(acoth(2)) + sage: float(acoth(2)) # needs sage.symbolic 0.5493061443340549 - sage: float(acoth(2).n(53)) # Correct result to 53 bits + sage: float(acoth(2).n(53)) # Correct result to 53 bits # needs sage.rings.real_mpfr sage.symbolic 0.5493061443340549 - sage: float(acoth(2).n(100)) # Compute 100 bits and then round to 53 + sage: float(acoth(2).n(100)) # Compute 100 bits and then round to 53 # needs sage.rings.real_mpfr sage.symbolic 0.5493061443340549 TESTS:: - sage: latex(acoth(x)) + sage: latex(acoth(x)) # needs sage.symbolic \operatorname{arcoth}\left(x\right) - sage: acoth(x)._sympy_() + sage: acoth(x)._sympy_() # needs sympy sage.symbolic acoth(x) Check that :trac:`23636` is fixed:: - sage: acoth(float(1.1)) + sage: acoth(float(1.1)) # needs sage.symbolic 1.5222612188617113 """ GinacFunction.__init__(self, "arccoth", @@ -611,9 +632,9 @@ def _eval_numpy_(self, x): """ EXAMPLES:: - sage: import numpy - sage: a = numpy.arange(2,5) - sage: acoth(a) + sage: import numpy # needs numpy + sage: a = numpy.arange(2,5) # needs numpy + sage: acoth(a) # needs numpy array([0.54930614, 0.34657359, 0.25541281]) """ return arctanh(1.0 / x) @@ -629,6 +650,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: asech(0.5) 1.31695789692482 sage: asech(1/2) @@ -640,11 +662,11 @@ def __init__(self): sage: float(asech(1/2)) 1.3169578969248168 - sage: diff(asech(x), x) + sage: diff(asech(x), x) # needs sage.symbolic -1/(sqrt(-x^2 + 1)*x) - sage: latex(asech(x)) + sage: latex(asech(x)) # needs sage.symbolic \operatorname{arsech}\left(x\right) - sage: asech(x)._sympy_() + sage: asech(x)._sympy_() # needs sympy sage.symbolic asech(x) """ GinacFunction.__init__(self, "arcsech", @@ -657,9 +679,9 @@ def _eval_numpy_(self, x): """ EXAMPLES:: - sage: import numpy - sage: a = numpy.linspace(0,1,3) - sage: asech(a) + sage: import numpy # needs numpy + sage: a = numpy.linspace(0,1,3) # needs numpy + sage: asech(a) # needs numpy doctest:...: RuntimeWarning: divide by zero encountered in ...divide array([ inf, 1.3169579, 0. ]) """ @@ -676,6 +698,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: acsch(2.0) 0.481211825059603 sage: acsch(2) @@ -687,18 +710,18 @@ def __init__(self): sage: float(acsch(1)) 0.881373587019543 - sage: diff(acsch(x), x) + sage: diff(acsch(x), x) # needs sage.symbolic -1/(sqrt(x^2 + 1)*x) - sage: latex(acsch(x)) + sage: latex(acsch(x)) # needs sage.symbolic \operatorname{arcsch}\left(x\right) TESTS: Check that :trac:`20818` is fixed:: - sage: acsch(float(0.1)) + sage: acsch(float(0.1)) # needs sage.symbolic 2.99822295029797 - sage: acsch(x)._sympy_() + sage: acsch(x)._sympy_() # needs sympy sage.symbolic acsch(x) """ GinacFunction.__init__(self, "arccsch", @@ -711,9 +734,9 @@ def _eval_numpy_(self, x): """ EXAMPLES:: - sage: import numpy - sage: a = numpy.linspace(0,1,3) - sage: acsch(a) + sage: import numpy # needs numpy + sage: a = numpy.linspace(0,1,3) # needs numpy + sage: acsch(a) # needs numpy doctest:...: RuntimeWarning: divide by zero encountered in ...divide array([ inf, 1.44363548, 0.88137359]) """ diff --git a/src/sage/functions/hypergeometric.py b/src/sage/functions/hypergeometric.py index fc2fb5875ce..1c2712382f3 100644 --- a/src/sage/functions/hypergeometric.py +++ b/src/sage/functions/hypergeometric.py @@ -49,6 +49,7 @@ Computing terms and series:: + sage: # needs sage.symbolic sage: var('z') z sage: hypergeometric([], [], z).series(z, 0) @@ -60,6 +61,7 @@ sage: hypergeometric([], [], z).series(z, 3) 1 + 1*z + 1/2*z^2 + Order(z^3) + sage: # needs sage.symbolic sage: hypergeometric([-2], [], z).series(z, 3) 1 + (-2)*z + 1*z^2 sage: hypergeometric([-2], [], z).series(z, 6) @@ -71,26 +73,27 @@ sage: hypergeometric([-2], [], z).series(z, 2).is_terminating_series() False - sage: hypergeometric([1], [], z).series(z, 6) + sage: hypergeometric([1], [], z).series(z, 6) # needs sage.symbolic 1 + 1*z + 1*z^2 + 1*z^3 + 1*z^4 + 1*z^5 + Order(z^6) - sage: hypergeometric([], [1/2], -z^2/4).series(z, 11) + sage: hypergeometric([], [1/2], -z^2/4).series(z, 11) # needs sage.symbolic 1 + (-1/2)*z^2 + 1/24*z^4 + (-1/720)*z^6 + 1/40320*z^8 +... (-1/3628800)*z^10 + Order(z^11) sage: hypergeometric([1], [5], x).series(x, 5) 1 + 1/5*x + 1/30*x^2 + 1/210*x^3 + 1/1680*x^4 + Order(x^5) - sage: sum(hypergeometric([1, 2], [3], 1/3).terms(6)).n() + sage: sum(hypergeometric([1, 2], [3], 1/3).terms(6)).n() # needs sage.symbolic 1.29788359788360 - sage: hypergeometric([1, 2], [3], 1/3).n() + sage: hypergeometric([1, 2], [3], 1/3).n() # needs sage.symbolic 1.29837194594696 sage: hypergeometric([], [], x).series(x, 20)(x=1).n() == e.n() True Plotting:: + sage: # needs sage.symbolic sage: f(x) = hypergeometric([1, 1], [3, 3, 3], x) - sage: plot(f, x, -30, 30) + sage: plot(f, x, -30, 30) # needs sage.plot Graphics object consisting of 1 graphics primitive sage: g(x) = hypergeometric([x], [], 2) sage: complex_plot(g, (-1, 1), (-1, 1)) @@ -98,6 +101,7 @@ Numeric evaluation:: + sage: # needs sage.symbolic sage: hypergeometric([1], [], 1/10).n() # geometric series 1.11111111111111 sage: hypergeometric([], [], 1).n() # e @@ -115,42 +119,42 @@ Conversions:: - sage: maxima(hypergeometric([1, 1, 1], [3, 3, 3], x)) + sage: maxima(hypergeometric([1, 1, 1], [3, 3, 3], x)) # needs sage.symbolic hypergeometric([1,1,1],[3,3,3],_SAGE_VAR_x) - sage: hypergeometric((5, 4), (4, 4), 3)._sympy_() + sage: hypergeometric((5, 4), (4, 4), 3)._sympy_() # needs sage.symbolic hyper((5, 4), (4, 4), 3) - sage: hypergeometric((5, 4), (4, 4), 3)._mathematica_init_() + sage: hypergeometric((5, 4), (4, 4), 3)._mathematica_init_() # needs sage.symbolic 'HypergeometricPFQ[{5,4},{4,4},3]' Arbitrary level of nesting for conversions:: - sage: maxima(nest(lambda y: hypergeometric([y], [], x), 3, 1)) + sage: maxima(nest(lambda y: hypergeometric([y], [], x), 3, 1)) # needs sage.symbolic 1/(1-_SAGE_VAR_x)^(1/(1-_SAGE_VAR_x)^(1/(1-_SAGE_VAR_x))) - sage: maxima(nest(lambda y: hypergeometric([y], [3], x), 3, 1))._sage_() + sage: maxima(nest(lambda y: hypergeometric([y], [3], x), 3, 1))._sage_() # needs sage.symbolic hypergeometric((hypergeometric((hypergeometric((1,), (3,), x),), (3,),... x),), (3,), x) - sage: nest(lambda y: hypergeometric([y], [], x), 3, 1)._mathematica_init_() + sage: nest(lambda y: hypergeometric([y], [], x), 3, 1)._mathematica_init_() # needs sage.symbolic 'HypergeometricPFQ[{HypergeometricPFQ[{HypergeometricPFQ[{1},{},x]},... The confluent hypergeometric functions can arise as solutions to second-order differential equations (example from `here `_):: - sage: var('m') + sage: var('m') # needs sage.symbolic m - sage: y = function('y')(x) - sage: desolve(diff(y, x, 2) + 2*x*diff(y, x) - 4*m*y, y, + sage: y = function('y')(x) # needs sage.symbolic + sage: desolve(diff(y, x, 2) + 2*x*diff(y, x) - 4*m*y, y, # needs sage.symbolic ....: contrib_ode=true, ivar=x) [y(x) == _K1*hypergeometric_M(-m, 1/2, -x^2) +... _K2*hypergeometric_U(-m, 1/2, -x^2)] Series expansions of confluent hypergeometric functions:: - sage: hypergeometric_M(2, 2, x).series(x, 3) + sage: hypergeometric_M(2, 2, x).series(x, 3) # needs sage.symbolic 1 + 1*x + 1/2*x^2 + Order(x^3) - sage: hypergeometric_U(2, 2, x).series(x == 3, 100).subs(x=1).n() + sage: hypergeometric_U(2, 2, x).series(x == 3, 100).subs(x=1).n() # needs sage.symbolic 0.403652637676806 - sage: hypergeometric_U(2, 2, 1).n() + sage: hypergeometric_U(2, 2, 1).n() # needs mpmath 0.403652637676806 """ @@ -174,18 +178,24 @@ from sage.functions.hyperbolic import cosh, sinh from sage.functions.log import exp, log from sage.functions.other import sqrt, real_part -from sage.libs.mpmath import utils as mpmath_utils -from sage.misc.latex import latex +from sage.misc.lazy_import import lazy_import from sage.misc.misc_c import prod from sage.rings.infinity import Infinity from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ -from sage.structure.element import get_coercion_model -from sage.symbolic.constants import pi -from sage.symbolic.expression import Expression +from sage.structure.element import Expression, get_coercion_model from sage.symbolic.function import BuiltinFunction -from sage.symbolic.ring import SR + +lazy_import('sage.misc.latex', 'latex') + +lazy_import('sage.symbolic.constants', 'pi') +lazy_import('sage.symbolic.ring', 'SR') + +lazy_import('sage.libs.mpmath.utils', 'call', as_='_mpmath_utils_call') +lazy_import('mpmath', 'hyp1f1', as_='_mpmath_hyp1f1') +lazy_import('mpmath', 'hyper', as_='_mpmath_hyper') +lazy_import('mpmath', 'hyperu', as_='_mpmath_hyperu') def rational_param_as_tuple(x): @@ -200,7 +210,7 @@ def rational_param_as_tuple(x): (1, 2) sage: rational_param_as_tuple(3) 3 - sage: rational_param_as_tuple(pi) + sage: rational_param_as_tuple(pi) # needs sage.symbolic pi """ try: @@ -237,7 +247,7 @@ def __init__(self): EXAMPLES:: - sage: maxima(hypergeometric) + sage: maxima(hypergeometric) # needs sage.symbolic hypergeometric TESTS:: @@ -268,6 +278,7 @@ def __call__(self, a, b, z, **kwargs): EXAMPLES:: + sage: # needs sage.symbolic sage: hypergeometric([], [], 1) hypergeometric((), (), 1) sage: hypergeometric([], [1], 1) @@ -292,7 +303,7 @@ def _print_latex_(self, a, b, z): r""" TESTS:: - sage: latex(hypergeometric([1, 1], [2], -1)) + sage: latex(hypergeometric([1, 1], [2], -1)) # needs sage.symbolic \,_2F_1\left(\begin{matrix} 1,1 \\ 2 \end{matrix} ; -1 \right) """ @@ -306,7 +317,7 @@ def _eval_(self, a, b, z, **kwargs): """ EXAMPLES:: - sage: hypergeometric([], [], 0) + sage: hypergeometric([], [], 0) # needs sage.symbolic 1 """ if not isinstance(a, tuple) or not isinstance(b, tuple): @@ -329,12 +340,12 @@ def _evalf_try_(self, a, b, z): EXAMPLES:: - sage: hypergeometric._evalf_try_((1.0,), (2.0,), 3.0) + sage: hypergeometric._evalf_try_((1.0,), (2.0,), 3.0) # needs mpmath 6.36184564106256 - sage: hypergeometric._evalf_try_((1.0, 1), (), 3.0) + sage: hypergeometric._evalf_try_((1.0, 1), (), 3.0) # needs mpmath -0.0377593153441588 + 0.750349833788561*I sage: hypergeometric._evalf_try_((1, 1), (), 3) # exact input - sage: hypergeometric._evalf_try_((x,), (), 1.0) # symbolic + sage: hypergeometric._evalf_try_((x,), (), 1.0) # symbolic # needs sage.symbolic sage: hypergeometric._evalf_try_(1.0, 2.0, 3.0) # not tuples """ # We need to override this for hypergeometric functions since @@ -353,32 +364,31 @@ def _evalf_(self, a, b, z, parent, algorithm=None): """ TESTS:: - sage: hypergeometric([1, 1], [2], -1).n() + sage: hypergeometric([1, 1], [2], -1).n() # needs sage.symbolic 0.693147180559945 - sage: hypergeometric([], [], RealField(100)(1)) + sage: hypergeometric([], [], RealField(100)(1)) # needs sage.rings.real_mpfr sage.symbolic 2.7182818284590452353602874714 """ if not isinstance(a, tuple) or not isinstance(b, tuple): raise TypeError("The first two parameters must be of type list") - from mpmath import hyper aa = [rational_param_as_tuple(c) for c in a] bb = [rational_param_as_tuple(c) for c in b] - return mpmath_utils.call(hyper, aa, bb, z, parent=parent) + return _mpmath_utils_call(_mpmath_hyper, aa, bb, z, parent=parent) def _tderivative_(self, a, b, z, *args, **kwargs): """ EXAMPLES:: - sage: hypergeometric([1/3, 2/3], [5], x^2).diff(x) + sage: hypergeometric([1/3, 2/3], [5], x^2).diff(x) # needs sage.symbolic 4/45*x*hypergeometric((4/3, 5/3), (6,), x^2) - sage: hypergeometric([1, 2], [x], 2).diff(x) + sage: hypergeometric([1, 2], [x], 2).diff(x) # needs sage.symbolic Traceback (most recent call last): ... NotImplementedError: derivative of hypergeometric function with... respect to parameters. Try calling .simplify_hypergeometric()... first. - sage: hypergeometric([1/3, 2/3], [5], 2).diff(x) + sage: hypergeometric([1/3, 2/3], [5], 2).diff(x) # needs sage.symbolic 0 """ diff_param = kwargs['diff_param'] @@ -404,16 +414,17 @@ def _fast_callable_(self, a, b, z, etb): EXAMPLES:: + sage: # needs sage.symbolic sage: h = hypergeometric([], [], x) sage: from sage.ext.fast_callable import ExpressionTreeBuilder sage: etb = ExpressionTreeBuilder(vars=['x']) sage: h._fast_callable_(etb) {hypergeometric((), (), x)}(v_0) - sage: var('x, y') + sage: var('x, y') # needs sage.symbolic (x, y) - sage: f = fast_callable(hypergeometric([y], [], x), vars=[x, y]) - sage: f(3, 4) + sage: f = fast_callable(hypergeometric([y], [], x), vars=[x, y]) # needs sage.symbolic + sage: f(3, 4) # needs sage.symbolic hypergeometric((4,), (), 3) """ return etb.call(self, *map(etb.var, etb._vars)) @@ -424,7 +435,7 @@ def sorted_parameters(self, a, b, z): EXAMPLES:: - sage: hypergeometric([2, 1, 3], [5, 4], + sage: hypergeometric([2, 1, 3], [5, 4], # needs sage.symbolic ....: 1/2).sorted_parameters() hypergeometric((1, 2, 3), (4, 5), 1/2) """ @@ -437,12 +448,12 @@ def eliminate_parameters(self, a, b, z): EXAMPLES:: - sage: hypergeometric([1, 1, 2, 5], [5, 1, 4], + sage: hypergeometric([1, 1, 2, 5], [5, 1, 4], # needs sage.symbolic ....: 1/2).eliminate_parameters() hypergeometric((1, 2), (4,), 1/2) sage: hypergeometric([x], [x], x).eliminate_parameters() hypergeometric((), (), x) - sage: hypergeometric((5, 4), (4, 4), 3).eliminate_parameters() + sage: hypergeometric((5, 4), (4, 4), 3).eliminate_parameters() # needs sage.symbolic hypergeometric((5,), (4,), 3) """ aa = list(a) # tuples are immutable @@ -475,6 +486,7 @@ def is_termwise_finite(self, a, b, z): EXAMPLES:: + sage: # needs sage.symbolic sage: hypergeometric([2], [3, 4], 5).is_termwise_finite() True sage: hypergeometric([2], [-3, 4], 5).is_termwise_finite() @@ -485,6 +497,7 @@ def is_termwise_finite(self, a, b, z): ....: 5).is_termwise_finite() # ambiguous False + sage: # needs sage.symbolic sage: hypergeometric([0], [-1], 5).is_termwise_finite() True sage: hypergeometric([0], [0], @@ -548,18 +561,19 @@ def is_absolutely_convergent(self, a, b, z): Degree giving infinite radius of convergence:: - sage: hypergeometric([2, 3], [4, 5], + sage: hypergeometric([2, 3], [4, 5], # needs sage.symbolic ....: 6).is_absolutely_convergent() True - sage: hypergeometric([2, 3], [-4, 5], + sage: hypergeometric([2, 3], [-4, 5], # needs sage.symbolic ....: 6).is_absolutely_convergent() # undefined False - sage: (hypergeometric([2, 3], [-4, 5], Infinity) + sage: (hypergeometric([2, 3], [-4, 5], Infinity) # needs sage.symbolic ....: .is_absolutely_convergent()) # undefined False Ordinary geometric series (unit radius of convergence):: + sage: # needs sage.symbolic sage: hypergeometric([1], [], 1/2).is_absolutely_convergent() True sage: hypergeometric([1], [], 2).is_absolutely_convergent() @@ -573,6 +587,7 @@ def is_absolutely_convergent(self, a, b, z): Degree `p = q+1` (unit radius of convergence):: + sage: # needs sage.symbolic sage: hypergeometric([2, 3], [4], 6).is_absolutely_convergent() False sage: hypergeometric([2, 3], [4], 1).is_absolutely_convergent() @@ -596,13 +611,13 @@ def is_absolutely_convergent(self, a, b, z): Degree giving zero radius of convergence:: - sage: hypergeometric([1, 2, 3], [4], + sage: hypergeometric([1, 2, 3], [4], # needs sage.symbolic ....: 2).is_absolutely_convergent() False - sage: hypergeometric([1, 2, 3], [4], + sage: hypergeometric([1, 2, 3], [4], # needs sage.symbolic ....: 1/2).is_absolutely_convergent() False - sage: (hypergeometric([1, 2, -3], [4], 1/2) + sage: (hypergeometric([1, 2, -3], [4], 1/2) # needs sage.symbolic ....: .is_absolutely_convergent()) # polynomial True """ @@ -658,6 +673,7 @@ def deflated(self, a, b, z): EXAMPLES:: + sage: # needs sage.symbolic sage: x = hypergeometric([6, 1], [3, 4, 5], 10) sage: y = x.deflated() sage: y @@ -669,6 +685,7 @@ def deflated(self, a, b, z): 2.87893612686782 2.87893612686782 + sage: # needs sage.symbolic sage: x = hypergeometric([6, 7], [3, 4, 5], 10) sage: y = x.deflated() sage: y @@ -691,6 +708,7 @@ def _deflated(self, a, b, z): EXAMPLES:: + sage: # needs sage.symbolic sage: x = hypergeometric([5], [4], 3) sage: y = x.deflated() sage: y @@ -748,6 +766,7 @@ def closed_form(hyp): EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.functions.hypergeometric import closed_form sage: var('a b c z') (a, b, c, z) @@ -939,6 +958,7 @@ class Hypergeometric_M(BuiltinFunction): EXAMPLES:: + sage: # needs mpmath sage: hypergeometric_M(1, 1, 1) hypergeometric_M(1, 1, 1) sage: hypergeometric_M(1, 1, 1.) @@ -947,16 +967,18 @@ class Hypergeometric_M(BuiltinFunction): 2.7182818284590452354 sage: hypergeometric_M(1, 1, 1).simplify_hypergeometric() e - sage: hypergeometric_M(1, 1/2, x).simplify_hypergeometric() - (-I*sqrt(pi)*x*erf(I*sqrt(-x))*e^x + sqrt(-x))/sqrt(-x) sage: hypergeometric_M(1, 3/2, 1).simplify_hypergeometric() 1/2*sqrt(pi)*erf(1)*e + + sage: hypergeometric_M(1, 1/2, x).simplify_hypergeometric() # needs sage.symbolic + (-I*sqrt(pi)*x*erf(I*sqrt(-x))*e^x + sqrt(-x))/sqrt(-x) + """ def __init__(self): r""" TESTS:: - sage: maxima(hypergeometric_M(1,1,x)) + sage: maxima(hypergeometric_M(1,1,x)) # needs sage.symbolic kummer_m(1,1,_SAGE_VAR_x) sage: latex(hypergeometric_M(1,1,x)) M\left(1, 1, x\right) @@ -973,8 +995,8 @@ def _eval_(self, a, b, z, **kwargs): """ TESTS:: - sage: (a,b)=var('a,b') - sage: hypergeometric_M(a,b,0) + sage: (a,b)=var('a,b') # needs sage.symbolic + sage: hypergeometric_M(a,b,0) # needs sage.symbolic 1 """ if not isinstance(z, Expression) and z == 0: @@ -985,11 +1007,10 @@ def _evalf_(self, a, b, z, parent, algorithm=None): """ TESTS:: - sage: hypergeometric_M(1,1,1).n() + sage: hypergeometric_M(1,1,1).n() # needs mpmath 2.71828182845905 """ - from mpmath import hyp1f1 - return mpmath_utils.call(hyp1f1, a, b, z, parent=parent) + return _mpmath_utils_call(_mpmath_hyp1f1, a, b, z, parent=parent) def _derivative_(self, a, b, z, diff_param): """ @@ -1014,9 +1035,9 @@ def generalized(self, a, b, z): EXAMPLES:: - sage: var('a b z') + sage: var('a b z') # needs sage.symbolic (a, b, z) - sage: hypergeometric_M(a, b, z).generalized() + sage: hypergeometric_M(a, b, z).generalized() # needs sage.symbolic hypergeometric((a,), (b,), z) """ @@ -1050,27 +1071,28 @@ class Hypergeometric_U(BuiltinFunction): EXAMPLES:: + sage: # needs mpmath sage: hypergeometric_U(1, 1, 1) hypergeometric_U(1, 1, 1) sage: hypergeometric_U(1, 1, 1.) 0.596347362323194 sage: hypergeometric_U(1, 1, 1).n(70) 0.59634736232319407434 - sage: hypergeometric_U(10^4, 1/3, 1).n() + sage: hypergeometric_U(10^4, 1/3, 1).n() # needs sage.libs.pari 6.60377008885811e-35745 - sage: hypergeometric_U(2 + I, 2, 1).n() - 0.183481989942099 - 0.458685959185190*I - sage: hypergeometric_U(1, 3, x).simplify_hypergeometric() - (x + 1)/x^2 sage: hypergeometric_U(1, 2, 2).simplify_hypergeometric() 1/2 + sage: hypergeometric_U(2 + I, 2, 1).n() # needs sage.symbolic + 0.183481989942099 - 0.458685959185190*I + sage: hypergeometric_U(1, 3, x).simplify_hypergeometric() # needs sage.symbolic + (x + 1)/x^2 """ def __init__(self): r""" TESTS:: - sage: maxima(hypergeometric_U(1,1,x)) + sage: maxima(hypergeometric_U(1,1,x)) # needs sage.symbolic kummer_u(1,1,_SAGE_VAR_x) sage: latex(hypergeometric_U(1,1,x)) U\left(1, 1, x\right) @@ -1090,11 +1112,10 @@ def _evalf_(self, a, b, z, parent, algorithm=None): """ TESTS:: - sage: hypergeometric_U(1,1,1).n() + sage: hypergeometric_U(1,1,1).n() # needs mpmath 0.596347362323194 """ - from mpmath import hyperu - return mpmath_utils.call(hyperu, a, b, z, parent=parent) + return _mpmath_utils_call(_mpmath_hyperu, a, b, z, parent=parent) def _derivative_(self, a, b, z, diff_param): """ @@ -1119,13 +1140,13 @@ def generalized(self, a, b, z): EXAMPLES:: - sage: var('a b z') + sage: var('a b z') # needs sage.symbolic (a, b, z) - sage: hypergeometric_U(a, b, z).generalized() + sage: hypergeometric_U(a, b, z).generalized() # needs sage.symbolic hypergeometric((a, a - b + 1), (), -1/z)/z^a - sage: hypergeometric_U(1, 3, 1/2).generalized() + sage: hypergeometric_U(1, 3, 1/2).generalized() # needs mpmath 2*hypergeometric((1, -1), (), -2) - sage: hypergeometric_U(3, I, 2).generalized() + sage: hypergeometric_U(3, I, 2).generalized() # needs sage.symbolic 1/8*hypergeometric((3, -I + 4), (), -1/2) """ diff --git a/src/sage/functions/jacobi.py b/src/sage/functions/jacobi.py index 8bb6b911add..629b24ce930 100644 --- a/src/sage/functions/jacobi.py +++ b/src/sage/functions/jacobi.py @@ -145,17 +145,21 @@ # the License, or (at your option) any later version. # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.symbolic.function import BuiltinFunction -from sage.functions.trig import (arctan, arcsin, arccos, arccot, arcsec, - arccsc, csc, sec, sin, cos, tan, cot) from sage.functions.hyperbolic import (arctanh, arccosh, arcsinh, arcsech, arccsch, arccoth, cosh, coth, sech, csch, tanh, sinh) -from sage.rings.rational_field import QQ -from sage.rings.integer import Integer from sage.functions.special import elliptic_e, elliptic_kc -from sage.libs.mpmath import utils -from sage.misc.latex import latex +from sage.functions.trig import (arctan, arcsin, arccos, arccot, arcsec, + arccsc, csc, sec, sin, cos, tan, cot) +from sage.misc.lazy_import import lazy_import +from sage.rings.integer import Integer +from sage.rings.rational_field import QQ +from sage.symbolic.function import BuiltinFunction + +lazy_import('sage.misc.latex', 'latex') + +lazy_import('sage.libs.mpmath.utils', 'call', as_='_mpmath_utils_call') +lazy_import('mpmath', 'ellipfun', as_='_mpmath_ellipfun') HALF = QQ((1, 2)) @@ -176,18 +180,19 @@ def __init__(self, kind): TESTS:: - sage: N(jacobi("sn", I, 1/2)) # abs tol 1e-12 + sage: N(jacobi("sn", I, 1/2)) # abs tol 1e-12 # needs sage.symbolic -8.59454886300046e-73 + 1.34737147138542*I - sage: CN = fricas(jacobi('cn',x, 2)); CN # optional - fricas + sage: # optional - fricas, needs sage.symbolic + sage: CN = fricas(jacobi('cn',x, 2)); CN jacobiCn(x,2) - sage: fricas.series(CN, x=0) # optional - fricas + sage: fricas.series(CN, x=0) 1 2 3 4 17 6 79 8 1381 10 11 1 - - x + - x - -- x + --- x - ----- x + O(x ) 2 8 80 640 19200 - sage: fricas(jacobi('sn',x, 2)) # optional - fricas + sage: fricas(jacobi('sn',x, 2)) jacobiSn(x,2) - sage: fricas(jacobi('dn',x, 2)) # optional - fricas + sage: fricas(jacobi('dn',x, 2)) jacobiDn(x,2) """ if kind not in ['nd', 'ns', 'nc', 'dn', 'ds', 'dc', 'sn', 'sd', @@ -208,7 +213,8 @@ def _eval_(self, x, m): Check that the simplifications are correct:: - sage: from mpmath import almosteq + sage: # needs mpmath sage.symbolic + sage: from sage.libs.mpmath.all import almosteq sage: almosteq(n(jacobi_nd(8, 0, hold=True)), n(jacobi_nd(8, 0))) True sage: almosteq(n(jacobi_nd(1, 1, hold=True)), n(jacobi_nd(1, 1))) @@ -356,13 +362,12 @@ def _evalf_(self, x, m, parent, algorithm=None): r""" TESTS:: - sage: jacobi_sn(3, 4).n(100) + sage: jacobi_sn(3, 4).n(100) # needs mpmath sage.symbolic -0.33260000892770027112809652714 + 1.7077912301715219199143891076e-33*I - sage: jacobi_dn(I, I).n() + sage: jacobi_dn(I, I).n() # needs mpmath sage.symbolic 0.874189950651018 + 0.667346865048825*I """ - from mpmath import ellipfun - return utils.call(ellipfun, self.kind, x, m, parent=parent) + return _mpmath_utils_call(_mpmath_ellipfun, self.kind, x, m, parent=parent) def _derivative_(self, x, m, diff_param): r""" @@ -371,6 +376,7 @@ def _derivative_(self, x, m, diff_param): sn, cn, and dn are analytic for all real ``x``, so we can check that the derivatives are correct by computing the series:: + sage: # needs mpmath sage.symbolic sage: from mpmath import almosteq sage: a = 0.9327542442482303 sage: b = 0.7402326293643771 @@ -508,7 +514,7 @@ def _print_latex_(self, x, m): r""" TESTS:: - sage: latex(jacobi_sn(x, 3)) + sage: latex(jacobi_sn(x, 3)) # needs sage.symbolic \operatorname{sn}\left(x\middle|3\right) """ return r"\operatorname{{{}}}\left({}\middle|{}\right)".format(self.kind, @@ -561,6 +567,7 @@ def _eval_(self, x, m): Check that the simplifications are correct:: + sage: # needs mpmath sage.symbolic sage: from mpmath import almosteq sage: almosteq(n(inverse_jacobi_cd(1, -8, hold=True)), ....: n(inverse_jacobi_cd(1, -8))) @@ -713,12 +720,12 @@ def _evalf_(self, x, m, parent, algorithm=None): r""" TESTS:: - sage: inverse_jacobi_cn(2, 3).n() + sage: inverse_jacobi_cn(2, 3).n() # needs mpmath 0.859663746362987*I - sage: inverse_jacobi_cd(3, 4).n(100) + sage: inverse_jacobi_cd(3, 4).n(100) # needs mpmath -0.67214752201235862490069823239 + 2.1565156474996432354386749988*I """ - return utils.call(inverse_jacobi_f, self.kind, x, m, parent=parent) + return _mpmath_utils_call(inverse_jacobi_f, self.kind, x, m, parent=parent) def _derivative_(self, x, m, diff_param): r""" @@ -727,6 +734,7 @@ def _derivative_(self, x, m, diff_param): Check that ``dy/dx * dx/dy == 1``, where ``y = jacobi_pq(x, m)`` and ``x = inverse_jacobi_pq(y, m)``:: + sage: # needs mpmath sage.symbolic sage: from mpmath import almosteq sage: a = 0.130103220857094 sage: b = 0.437176765041986 @@ -899,7 +907,7 @@ def _print_latex_(self, x, m): r""" TESTS:: - sage: latex(inverse_jacobi_dn(x, 3)) + sage: latex(inverse_jacobi_dn(x, 3)) # needs sage.symbolic \operatorname{arcdn}\left(x\middle|3\right) """ return r"\operatorname{{arc{}}}\left({}\middle|{}\right)".format(self.kind, @@ -935,6 +943,7 @@ def jacobi(kind, z, m, **kwargs): EXAMPLES:: + sage: # needs mpmath sage: jacobi('sn', 1, 1) tanh(1) sage: jacobi('cd', 1, 1/2) @@ -944,8 +953,9 @@ def jacobi(kind, z, m, **kwargs): sage: (RDF(jacobi('cn', 1, 1/2)), RDF(jacobi('dn', 1, 1/2)), ....: RDF(jacobi('cn', 1, 1/2) / jacobi('dn', 1, 1/2))) (0.5959765676721407, 0.8231610016315962, 0.7240097216593705) - sage: jsn = jacobi('sn', x, 1) - sage: P = plot(jsn, 0, 1) + + sage: jsn = jacobi('sn', x, 1) # needs sage.symbolic + sage: P = plot(jsn, 0, 1) # needs sage.plot sage.symbolic """ if kind == 'nd': return jacobi_nd(z, m, **kwargs) @@ -996,20 +1006,24 @@ def inverse_jacobi(kind, x, m, **kwargs): EXAMPLES:: - sage: jacobi('dn', inverse_jacobi('dn', 3, 0.4), 0.4) + sage: jacobi('dn', inverse_jacobi('dn', 3, 0.4), 0.4) # needs mpmath 3.00000000000000 - sage: inverse_jacobi('dn', 10, 1/10).n(digits=50) + sage: inverse_jacobi('dn', 10, 1/10).n(digits=50) # needs mpmath 2.4777736267904273296523691232988240759001423661683*I - sage: inverse_jacobi_dn(x, 1) + sage: inverse_jacobi_dn(x, 1) # needs sage.symbolic arcsech(x) - sage: inverse_jacobi_dn(1, 3) + sage: inverse_jacobi_dn(1, 3) # needs mpmath 0 + + sage: # needs sage.symbolic sage: m = var('m') sage: z = inverse_jacobi_dn(x, m).series(x, 4).subs(x=0.1, m=0.7) sage: jacobi_dn(z, 0.7) 0.0999892750039819... sage: inverse_jacobi_nd(x, 1) arccosh(x) + + sage: # needs mpmath sage: inverse_jacobi_nd(1, 2) 0 sage: inverse_jacobi_ns(10^-5, 3).n() @@ -1022,7 +1036,7 @@ def inverse_jacobi(kind, x, m, **kwargs): 0.499098231322220 sage: inverse_jacobi('sn', 0.4707504, 0.5) 0.499999911466555 - sage: P = plot(inverse_jacobi('sn', x, 0.5), 0, 1) + sage: P = plot(inverse_jacobi('sn', x, 0.5), 0, 1) # needs sage.plot """ if kind == 'nd': return inverse_jacobi_nd(x, m, **kwargs) @@ -1076,11 +1090,11 @@ def _eval_(self, x, m): r""" TESTS:: - sage: jacobi_am(x, 0) + sage: jacobi_am(x, 0) # needs sage.symbolic x - sage: jacobi_am(0, x) + sage: jacobi_am(0, x) # needs sage.symbolic 0 - sage: jacobi_am(3, 4.) + sage: jacobi_am(3, 4.) # needs mpmath -0.339059208303591 """ if m == 0: @@ -1093,18 +1107,18 @@ def _evalf_(self, x, m, parent, algorithm=None): r""" TESTS:: - sage: jacobi_am(1, 2).n(100) + sage: jacobi_am(1, 2).n(100) # needs mpmath 0.73704379494724574105101929735 """ - return utils.call(jacobi_am_f, x, m, parent=parent) + return _mpmath_utils_call(jacobi_am_f, x, m, parent=parent) def _derivative_(self, x, m, diff_param): r""" TESTS:: - sage: diff(jacobi_am(x, 3), x) + sage: diff(jacobi_am(x, 3), x) # needs sage.symbolic jacobi_dn(x, 3) - sage: diff(jacobi_am(3, x), x) + sage: diff(jacobi_am(3, x), x) # needs sage.symbolic -1/2*(x*jacobi_cn(3, x)*jacobi_sn(3, x) -... (3*x + elliptic_e(jacobi_am(3, x), x) - 3)*jacobi_dn(3, x))/((x - 1)*x) """ @@ -1128,7 +1142,7 @@ def _print_latex_(self, x, m): r""" TESTS:: - sage: latex(jacobi_am(3,x)) + sage: latex(jacobi_am(3,x)) # needs sage.symbolic \operatorname{am}\left(3\middle|x\right) """ return r"\operatorname{{am}}\left({}\middle|{}\right)".format(latex(x), @@ -1146,9 +1160,10 @@ def inverse_jacobi_f(kind, x, m): TESTS:: - sage: from mpmath import ellipfun, chop + sage: from mpmath import ellipfun, chop # needs mpmath sage: from sage.functions.jacobi import inverse_jacobi_f + sage: # needs mpmath sage: chop(ellipfun('sn', inverse_jacobi_f('sn', 0.6, 0), 0)) mpf('0.59999999999999998') sage: chop(ellipfun('sn', inverse_jacobi_f('sn', 0.6, 1), 1)) @@ -1162,6 +1177,7 @@ def inverse_jacobi_f(kind, x, m): sage: chop(ellipfun('sn', inverse_jacobi_f('sn', 0.8, 4), 4)) mpf('0.80000000000000004') + sage: # needs mpmath sage: chop(ellipfun('ns', inverse_jacobi_f('ns', 0.8, 0), 0)) mpf('0.80000000000000004') sage: chop(ellipfun('ns', inverse_jacobi_f('ns', -0.7, 1), 1)) @@ -1173,6 +1189,7 @@ def inverse_jacobi_f(kind, x, m): sage: chop(ellipfun('ns', inverse_jacobi_f('ns', -10, 6), 6)) mpf('-10.0') + sage: # needs mpmath sage: chop(ellipfun('cn', inverse_jacobi_f('cn', -10, 0), 0)) mpf('-9.9999999999999982') sage: chop(ellipfun('cn', inverse_jacobi_f('cn', 50, 1), 1)) @@ -1188,6 +1205,7 @@ def inverse_jacobi_f(kind, x, m): sage: chop(ellipfun('cn', inverse_jacobi_f('cn', -2, 0.9), 0.9)) mpf('-2.0') + sage: # needs mpmath sage: chop(ellipfun('nc', inverse_jacobi_f('nc', -4, 0), 0)) mpf('-3.9999999999999987') sage: chop(ellipfun('nc', inverse_jacobi_f('nc', 7, 1), 1)) @@ -1199,6 +1217,7 @@ def inverse_jacobi_f(kind, x, m): sage: chop(ellipfun('nc', inverse_jacobi_f('nc', -18, -4), -4)) mpf('-17.999999999999925') + sage: # needs mpmath sage: chop(ellipfun('dn', inverse_jacobi_f('dn', -0.3, 1), 1)) mpf('-0.29999999999999999') sage: chop(ellipfun('dn', inverse_jacobi_f('dn', 1, -1), -1)) @@ -1216,6 +1235,7 @@ def inverse_jacobi_f(kind, x, m): sage: chop(ellipfun('dn', inverse_jacobi_f('dn', -1.9, 0.2), 0.2)) mpf('-1.8999999999999999') + sage: # needs mpmath sage: chop(ellipfun('nd', inverse_jacobi_f('nd', -1.9, 1), 1)) mpf('-1.8999999999999999') sage: chop(ellipfun('nd', inverse_jacobi_f('nd', 1, -1), -1)) @@ -1227,6 +1247,7 @@ def inverse_jacobi_f(kind, x, m): sage: chop(ellipfun('nd', inverse_jacobi_f('nd', -3, 0.8), 0.8)) mpf('-2.9999999999999996') + sage: # needs mpmath sage: chop(ellipfun('sc', inverse_jacobi_f('sc', -3, 0), 0)) mpf('-3.0') sage: chop(ellipfun('sc', inverse_jacobi_f('sc', 2, 1), 1)) @@ -1236,6 +1257,7 @@ def inverse_jacobi_f(kind, x, m): sage: chop(ellipfun('sc', inverse_jacobi_f('sc', -7, 3), 3)) mpf('-7.0') + sage: # needs mpmath sage: chop(ellipfun('cs', inverse_jacobi_f('cs', -7, 0), 0)) mpf('-6.9999999999999991') sage: chop(ellipfun('cs', inverse_jacobi_f('cs', 8, 1), 1)) @@ -1247,18 +1269,19 @@ def inverse_jacobi_f(kind, x, m): sage: chop(ellipfun('cs', inverse_jacobi_f('cs', -6, 8), 8)) mpf('-6.0000000000000018') - sage: chop(ellipfun('cd', inverse_jacobi_f('cd', -6, 0), 0)) + sage: chop(ellipfun('cd', inverse_jacobi_f('cd', -6, 0), 0)) # needs mpmath mpf('-6.0000000000000009') - sage: chop(ellipfun('cd', inverse_jacobi_f('cd', 1, 3), 3)) + sage: chop(ellipfun('cd', inverse_jacobi_f('cd', 1, 3), 3)) # needs mpmath mpf('1.0') - sage: chop(ellipfun('cd', inverse_jacobi_f('cd', 6, 8), 8)) + sage: chop(ellipfun('cd', inverse_jacobi_f('cd', 6, 8), 8)) # needs mpmath mpf('6.0000000000000027') - sage: chop(ellipfun('dc', inverse_jacobi_f('dc', 5, 0), 0)) + sage: chop(ellipfun('dc', inverse_jacobi_f('dc', 5, 0), 0)) # needs mpmath mpf('5.0000000000000018') - sage: chop(ellipfun('dc', inverse_jacobi_f('dc', -4, 2), 2)) + sage: chop(ellipfun('dc', inverse_jacobi_f('dc', -4, 2), 2)) # needs mpmath mpf('-4.0000000000000018') + sage: # needs mpmath sage: chop(ellipfun('sd', inverse_jacobi_f('sd', -4, 0), 0)) mpf('-3.9999999999999991') sage: chop(ellipfun('sd', inverse_jacobi_f('sd', 7, 1), 1)) @@ -1268,12 +1291,10 @@ def inverse_jacobi_f(kind, x, m): sage: chop(ellipfun('sd', inverse_jacobi_f('sd', 8, 0.8), 0.8)) mpf('7.9999999999999991') - sage: chop(ellipfun('ds', inverse_jacobi_f('ds', 4, 0.25), 0.25)) + sage: chop(ellipfun('ds', inverse_jacobi_f('ds', 4, 0.25), 0.25)) # needs mpmath mpf('4.0') """ - from mpmath import mp - - ctx = mp + from mpmath import mp as ctx prec = ctx.prec try: x = ctx.convert(x) @@ -1614,6 +1635,7 @@ def jacobi_am_f(x, m): TESTS:: + sage: # needs mpmath sage: from mpmath import ellipf sage: from sage.functions.jacobi import jacobi_am_f sage: ellipf(jacobi_am_f(0.5, 1), 1) @@ -1629,9 +1651,7 @@ def jacobi_am_f(x, m): sage: jacobi_am_f(-3, 2) mpf('0.36067407399586108') """ - from mpmath import mp - - ctx = mp + from mpmath import mp as ctx prec = ctx.prec try: x = ctx.convert(x) diff --git a/src/sage/functions/log.py b/src/sage/functions/log.py index 6f9133841a3..38c6ca08bbe 100644 --- a/src/sage/functions/log.py +++ b/src/sage/functions/log.py @@ -8,20 +8,35 @@ - Tomas Kalvoda (2015-04-01): Add :meth:`exp_polar()` (:trac:`18085`) """ -from sage.symbolic.function import GinacFunction, BuiltinFunction -from sage.symbolic.constants import e as const_e -from sage.symbolic.constants import pi as const_pi -from sage.libs.mpmath import utils as mpmath_utils -from sage.structure.all import parent as s_parent -from sage.symbolic.expression import Expression, register_symbol -from sage.rings.real_double import RDF -from sage.rings.complex_double import CDF +from sage.misc.functional import log as log +from sage.misc.lazy_import import lazy_import from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ +from sage.rings.real_double import RDF +from sage.structure.element import Expression, parent as s_parent +from sage.symbolic.function import GinacFunction, BuiltinFunction +from sage.symbolic.symbols import register_symbol -from sage.misc.functional import log as log +lazy_import('sage.functions.gamma', 'psi1') +lazy_import('sage.functions.other', 'imag') +lazy_import('sage.functions.transcendental', ['hurwitz_zeta', 'zeta']) + +lazy_import('sage.symbolic.constants', 'e', as_='const_e') +lazy_import('sage.symbolic.constants', 'pi', as_='const_pi') +lazy_import('sage.rings.complex_double', 'CDF') + +lazy_import('sage.libs.flint.arith', 'harmonic_number', as_='_flint_harmonic_number') + +lazy_import('sage.libs.mpmath.utils', 'call', as_='_mpmath_utils_call') +lazy_import('mpmath', 'harmonic', as_='_mpmath_harmonic') +lazy_import('mpmath', 'lambertw', as_='_mpmath_lambertw') + +lazy_import('sympy', 'polylog', as_='_sympy_polylog') +lazy_import('sympy', 'sympify', as_='_sympify') + +lazy_import('scipy.special', 'lambertw', as_='_scipy_lambertw') class Function_exp(GinacFunction): @@ -30,6 +45,7 @@ class Function_exp(GinacFunction): EXAMPLES:: + sage: # needs sage.symbolic sage: exp(-1) e^(-1) sage: exp(2) @@ -42,28 +58,30 @@ class Function_exp(GinacFunction): x*e^(x^2) sage: exp(2.5) 12.1824939607035 + sage: exp(I*pi/12) + (1/4*I + 1/4)*sqrt(6) - (1/4*I - 1/4)*sqrt(2) + sage: exp(float(2.5)) 12.182493960703473 sage: exp(RDF('2.5')) 12.182493960703473 - sage: exp(I*pi/12) - (1/4*I + 1/4)*sqrt(6) - (1/4*I - 1/4)*sqrt(2) To prevent automatic evaluation, use the ``hold`` parameter:: - sage: exp(I*pi,hold=True) + sage: exp(I*pi, hold=True) # needs sage.symbolic e^(I*pi) - sage: exp(0,hold=True) + sage: exp(0, hold=True) # needs sage.symbolic e^0 To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: exp(0,hold=True).simplify() + sage: exp(0, hold=True).simplify() # needs sage.symbolic 1 :: + sage: # needs sage.symbolic sage: exp(pi*I/2) I sage: exp(pi*I) @@ -76,25 +94,26 @@ class Function_exp(GinacFunction): For the sake of simplification, the argument is reduced modulo the period of the complex exponential function, `2\pi i`:: - sage: k = var('k', domain='integer') - sage: exp(2*k*pi*I) + sage: k = var('k', domain='integer') # needs sage.symbolic + sage: exp(2*k*pi*I) # needs sage.symbolic 1 - sage: exp(log(2) + 2*k*pi*I) + sage: exp(log(2) + 2*k*pi*I) # needs sage.symbolic 2 The precision for the result is deduced from the precision of the input. Convert the input to a higher precision explicitly if a result with higher precision is desired:: - sage: t = exp(RealField(100)(2)); t + sage: t = exp(RealField(100)(2)); t # needs sage.rings.real_mpfr 7.3890560989306502272304274606 - sage: t.prec() + sage: t.prec() # needs sage.rings.real_mpfr 100 - sage: exp(2).n(100) + sage: exp(2).n(100) # needs sage.symbolic 7.3890560989306502272304274606 TESTS:: + sage: # needs sage.symbolic sage: latex(exp(x)) e^{x} sage: latex(exp(sqrt(x))) @@ -105,25 +124,27 @@ class Function_exp(GinacFunction): \left(e^{\sqrt{x}}\right)^{x} sage: latex(exp(sqrt(x)^x)) e^{\left(\sqrt{x}^{x}\right)} - sage: exp(x)._sympy_() + sage: exp(x)._sympy_() # needs sympy exp(x) Test conjugates:: - sage: conjugate(exp(x)) + sage: conjugate(exp(x)) # needs sage.symbolic e^conjugate(x) Test simplifications when taking powers of exp (:trac:`7264`):: + sage: # needs sage.symbolic sage: var('a,b,c,II') (a, b, c, II) sage: model_exp = exp(II)**a*(b) - sage: sol1_l={b: 5.0, a: 1.1} + sage: sol1_l = {b: 5.0, a: 1.1} sage: model_exp.subs(sol1_l) 5.00000000000000*e^(1.10000000000000*II) :: + sage: # needs sage.symbolic sage: exp(3)^II*exp(x) e^(3*II + x) sage: exp(x)*exp(x) @@ -135,14 +156,14 @@ class Function_exp(GinacFunction): Another instance of the same problem (:trac:`7394`):: - sage: 2*sqrt(e) + sage: 2*sqrt(e) # needs sage.symbolic 2*e^(1/2) Check that :trac:`19918` is fixed:: - sage: exp(-x^2).subs(x=oo) + sage: exp(-x^2).subs(x=oo) # needs sage.symbolic 0 - sage: exp(-x).subs(x=-oo) + sage: exp(-x).subs(x=-oo) # needs sage.symbolic +Infinity """ def __init__(self): @@ -151,7 +172,7 @@ def __init__(self): sage: loads(dumps(exp)) exp - sage: maxima(exp(x))._sage_() + sage: maxima(exp(x))._sage_() # needs sage.symbolic e^x """ GinacFunction.__init__(self, "exp", latex_name=r"\exp", @@ -169,20 +190,21 @@ class Function_log1(GinacFunction): EXAMPLES:: - sage: ln(e^2) + sage: ln(e^2) # needs sage.symbolic 2 - sage: ln(2) + sage: ln(2) # needs sage.symbolic log(2) - sage: ln(10) + sage: ln(10) # needs sage.symbolic log(10) TESTS:: + sage: # needs sage.symbolic sage: latex(x.log()) \log\left(x\right) sage: latex(log(1/4)) \log\left(\frac{1}{4}\right) - sage: log(x)._sympy_() + sage: log(x)._sympy_() # needs sympy log(x) sage: loads(dumps(ln(x)+1)) log(x) + 1 @@ -190,13 +212,14 @@ class Function_log1(GinacFunction): ``conjugate(log(x))==log(conjugate(x))`` unless on the branch cut which runs along the negative real axis.:: + sage: # needs sage.symbolic sage: conjugate(log(x)) conjugate(log(x)) sage: var('y', domain='positive') y sage: conjugate(log(y)) log(y) - sage: conjugate(log(y+I)) + sage: conjugate(log(y + I)) conjugate(log(y + I)) sage: conjugate(log(-1)) -I*pi @@ -208,20 +231,20 @@ class Function_log1(GinacFunction): sage: from sage.functions.log import function_log as log sage: log(float(5)) 1.6094379124341003 - sage: log(float(0)) + sage: log(float(0)) # needs sage.symbolic -inf - sage: log(float(-1)) + sage: log(float(-1)) # needs sage.symbolic 3.141592653589793j - sage: log(x).subs(x=float(-1)) + sage: log(x).subs(x=float(-1)) # needs sage.symbolic 3.141592653589793j :trac:`22142`:: - sage: log(QQbar(sqrt(2))) + sage: log(QQbar(sqrt(2))) # needs sage.rings.number_field sage.symbolic log(1.414213562373095?) - sage: log(QQbar(sqrt(2))*1.) + sage: log(QQbar(sqrt(2))*1.) # needs sage.rings.number_field sage.symbolic 0.346573590279973 - sage: polylog(QQbar(sqrt(2)),3) + sage: polylog(QQbar(sqrt(2)),3) # needs sage.rings.number_field sage.symbolic polylog(1.414213562373095?, 3) """ def __init__(self): @@ -230,7 +253,7 @@ def __init__(self): sage: loads(dumps(ln)) log - sage: maxima(ln(x))._sage_() + sage: maxima(ln(x))._sage_() # needs sage.symbolic log(x) """ GinacFunction.__init__(self, 'log', latex_name=r'\log', @@ -250,14 +273,14 @@ class Function_log2(GinacFunction): EXAMPLES:: sage: from sage.functions.log import logb - sage: logb(1000,10) + sage: logb(1000, 10) # needs sage.symbolic 3 TESTS:: - sage: logb(7, 2) + sage: logb(7, 2) # needs sage.symbolic log(7)/log(2) - sage: logb(int(7), 2) + sage: logb(int(7), 2) # needs sage.symbolic log(7)/log(2) """ def __init__(self): @@ -283,16 +306,17 @@ def __init__(self): `\text{Li}_s(z) = \sum_{k=1}^{\infty} z^k / k^s`. The first argument is `s` (usually an integer called the weight) - and the second argument is `z` : ``polylog(s, z)``. + and the second argument is `z`: ``polylog(s, z)``. This definition is valid for arbitrary complex numbers `s` and `z` with `|z| < 1`. It can be extended to `|z| \ge 1` by the process of analytic continuation, with a branch cut along the positive real axis - from `1` to `+\infty`. A `NaN` value may be returned for floating + from `1` to `+\infty`. A ``NaN`` value may be returned for floating point arguments that are on the branch cut. EXAMPLES:: + sage: # needs sage.symbolic sage: polylog(2.7, 0) 0.000000000000000 sage: polylog(2, 1) @@ -308,55 +332,54 @@ def __init__(self): sage: polylog(4, 0.5) 0.517479061673899 + sage: # needs sage.symbolic sage: polylog(1, x) -log(-x + 1) - sage: polylog(2,x^2+1) + sage: polylog(2, x^2 + 1) dilog(x^2 + 1) - sage: f = polylog(4, 1); f 1/90*pi^4 sage: f.n() 1.08232323371114 - sage: polylog(4, 2).n() 2.42786280675470 - 0.174371300025453*I - sage: complex(polylog(4,2)) + sage: complex(polylog(4, 2)) (2.4278628067547032-0.17437130002545306j) - sage: float(polylog(4,0.5)) + sage: float(polylog(4, 0.5)) 0.5174790616738993 - sage: z = var('z') - sage: polylog(2,z).series(z==0, 5) + sage: polylog(2, z).series(z==0, 5) 1*z + 1/4*z^2 + 1/9*z^3 + 1/16*z^4 + Order(z^5) sage: loads(dumps(polylog)) polylog - sage: latex(polylog(5, x)) + sage: latex(polylog(5, x)) # needs sage.symbolic {\rm Li}_{5}(x) - sage: polylog(x, x)._sympy_() + sage: polylog(x, x)._sympy_() # needs sympy sage.symbolic polylog(x, x) TESTS: Check if :trac:`8459` is fixed:: - sage: t = maxima(polylog(5,x)).sage(); t + sage: t = maxima(polylog(5,x)).sage(); t # needs sage.symbolic polylog(5, x) - sage: t.operator() == polylog + sage: t.operator() == polylog # needs sage.symbolic True - sage: t.subs(x=.5).n() + sage: t.subs(x=.5).n() # needs sage.symbolic 0.50840057924226... Check if :trac:`18386` is fixed:: - sage: polylog(2.0, 1) + sage: polylog(2.0, 1) # needs sage.symbolic 1.64493406684823 - sage: polylog(2, 1.0) + sage: polylog(2, 1.0) # needs sage.symbolic 1.64493406684823 - sage: polylog(2.0, 1.0) + sage: polylog(2.0, 1.0) # needs sage.symbolic 1.64493406684823 + sage: # needs sage.libs.flint sage: polylog(2, RealBallField(100)(1/3)) [0.36621322997706348761674629766... +/- ...] sage: polylog(2, ComplexBallField(100)(4/3)) @@ -370,12 +393,12 @@ def __init__(self): sage: parent(_) Complex ball field with 53 bits of precision - sage: polylog(1,-1) # known bug + sage: polylog(1, -1) # known bug # needs sage.symbolic -log(2) Check for :trac:`21907`:: - sage: bool(x*polylog(x,x)==0) + sage: bool(x*polylog(x,x)==0) # needs sage.symbolic False """ GinacFunction.__init__(self, "polylog", nargs=2, @@ -390,9 +413,9 @@ def _maxima_init_evaled_(self, *args): These are indirect doctests for this function:: - sage: polylog(2, x)._maxima_() + sage: polylog(2, x)._maxima_() # needs sage.symbolic li[2](_SAGE_VAR_x) - sage: polylog(4, x)._maxima_() + sage: polylog(4, x)._maxima_() # needs sage.symbolic polylog(4,_SAGE_VAR_x) """ args_maxima = [] @@ -414,8 +437,8 @@ def _method_arguments(self, k, z): r""" TESTS:: - sage: b = RBF(1/2, .0001) - sage: polylog(2, b) + sage: b = RBF(1/2, .0001) # needs sage.libs.flint + sage: polylog(2, b) # needs sage.libs.flint [0.582 +/- ...] """ return [z, k] @@ -430,10 +453,11 @@ def __init__(self): The dilogarithm function `\text{Li}_2(z) = \sum_{k=1}^{\infty} z^k / k^2`. - This is simply an alias for polylog(2, z). + This is simply an alias for ``polylog(2, z)``. EXAMPLES:: + sage: # needs sage.symbolic sage: dilog(1) 1/6*pi^2 sage: dilog(1/2) @@ -457,14 +481,16 @@ def __init__(self): sage: dilog(z).diff(z, 2) log(-z + 1)/z^2 - 1/((z - 1)*z) sage: dilog(z).series(z==1/2, 3) - (1/12*pi^2 - 1/2*log(2)^2) + (-2*log(1/2))*(z - 1/2) + (2*log(1/2) + 2)*(z - 1/2)^2 + Order(1/8*(2*z - 1)^3) + (1/12*pi^2 - 1/2*log(2)^2) + (-2*log(1/2))*(z - 1/2) + + (2*log(1/2) + 2)*(z - 1/2)^2 + Order(1/8*(2*z - 1)^3) - sage: latex(dilog(z)) + sage: latex(dilog(z)) # needs sage.symbolic {\rm Li}_2\left(z\right) Dilog has a branch point at `1`. Sage's floating point libraries may handle this differently from the symbolic package:: + sage: # needs sage.symbolic sage: dilog(1) 1/6*pi^2 sage: dilog(1.) @@ -479,9 +505,10 @@ def __init__(self): ``conjugate(dilog(x))==dilog(conjugate(x))`` unless on the branch cuts which run along the positive real axis beginning at 1.:: + sage: # needs sage.symbolic sage: conjugate(dilog(x)) conjugate(dilog(x)) - sage: var('y',domain='positive') + sage: var('y', domain='positive') y sage: conjugate(dilog(y)) conjugate(dilog(y)) @@ -497,10 +524,12 @@ def __init__(self): Check that return type matches argument type where possible (:trac:`18386`):: - sage: dilog(0.5) + sage: dilog(0.5) # needs sage.symbolic 0.582240526465012 - sage: dilog(-1.0) + sage: dilog(-1.0) # needs sage.symbolic -0.822467033424113 + + sage: # needs sage.rings.real_mpfr sage.symbolic sage: y = dilog(RealField(13)(0.5)) sage: parent(y) Real Field with 13 bits of precision @@ -520,16 +549,14 @@ def _sympy_(self, z): EXAMPLES:: - sage: w = dilog(x)._sympy_(); w + sage: w = dilog(x)._sympy_(); w # needs sympy sage.symbolic polylog(2, x) - sage: w.diff() + sage: w.diff() # needs sympy sage.symbolic polylog(1, x)/x - sage: w._sage_() + sage: w._sage_() # needs sympy sage.symbolic dilog(x) """ - import sympy - from sympy import polylog as sympy_polylog - return sympy_polylog(2, sympy.sympify(z, evaluate=False)) + return _sympy_polylog(2, _sympify(z, evaluate=False)) dilog = Function_dilog() @@ -566,55 +593,55 @@ class Function_lambert_w(BuiltinFunction): Evaluation of the principal branch:: - sage: lambert_w(1.0) + sage: lambert_w(1.0) # needs scipy 0.567143290409784 - sage: lambert_w(-1).n() + sage: lambert_w(-1).n() # needs mpmath -0.318131505204764 + 1.33723570143069*I - sage: lambert_w(-1.5 + 5*I) + sage: lambert_w(-1.5 + 5*I) # needs mpmath sage.symbolic 1.17418016254171 + 1.10651494102011*I Evaluation of other branches:: - sage: lambert_w(2, 1.0) + sage: lambert_w(2, 1.0) # needs scipy -2.40158510486800 + 10.7762995161151*I Solutions to certain exponential equations are returned in terms of lambert_w:: - sage: S = solve(e^(5*x)+x==0, x, to_poly_solve=True) - sage: z = S[0].rhs(); z + sage: S = solve(e^(5*x)+x==0, x, to_poly_solve=True) # needs sage.symbolic + sage: z = S[0].rhs(); z # needs sage.symbolic -1/5*lambert_w(5) - sage: N(z) + sage: N(z) # needs sage.symbolic -0.265344933048440 Check the defining equation numerically at `z=5`:: - sage: N(lambert_w(5)*exp(lambert_w(5)) - 5) + sage: N(lambert_w(5)*exp(lambert_w(5)) - 5) # needs mpmath 0.000000000000000 There are several special values of the principal branch which are automatically simplified:: - sage: lambert_w(0) + sage: lambert_w(0) # needs mpmath 0 - sage: lambert_w(e) + sage: lambert_w(e) # needs sage.symbolic 1 - sage: lambert_w(-1/e) + sage: lambert_w(-1/e) # needs sage.symbolic -1 Integration (of the principal branch) is evaluated using Maxima:: - sage: integrate(lambert_w(x), x) + sage: integrate(lambert_w(x), x) # needs sage.symbolic (lambert_w(x)^2 - lambert_w(x) + 1)*x/lambert_w(x) - sage: integrate(lambert_w(x), x, 0, 1) + sage: integrate(lambert_w(x), x, 0, 1) # needs sage.symbolic (lambert_w(1)^2 - lambert_w(1) + 1)/lambert_w(1) - 1 - sage: integrate(lambert_w(x), x, 0, 1.0) + sage: integrate(lambert_w(x), x, 0, 1.0) # needs sage.symbolic 0.3303661247616807 Warning: The integral of a non-principal branch is not implemented, neither is numerical integration using GSL. The :meth:`numerical_integral` function does work if you pass a lambda function:: - sage: numerical_integral(lambda x: lambert_w(x), 0, 1) + sage: numerical_integral(lambda x: lambert_w(x), 0, 1) # needs sage.modules (0.33036612476168054, 3.667800782666048e-15) """ @@ -624,27 +651,27 @@ def __init__(self): EXAMPLES:: - sage: lambert_w(0, 1.0) + sage: lambert_w(0, 1.0) # needs scipy 0.567143290409784 - sage: lambert_w(x, x)._sympy_() + sage: lambert_w(x, x)._sympy_() # needs sympy sage.symbolic LambertW(x, x) TESTS: Check that :trac:`25987` is fixed:: - sage: lambert_w(x)._fricas_() # optional - fricas + sage: lambert_w(x)._fricas_() # optional - fricas, needs sage.symbolic lambertW(x) - sage: fricas(lambert_w(x)).eval(x = -1/e) # optional - fricas + sage: fricas(lambert_w(x)).eval(x=-1/e) # optional - fricas, needs sage.symbolic - 1 The two-argument form of Lambert's function is not supported by FriCAS, so we return a generic operator:: - sage: var("n") + sage: var("n") # needs sage.symbolic n - sage: lambert_w(n, x)._fricas_() # optional - fricas + sage: lambert_w(n, x)._fricas_() # optional - fricas, needs sage.symbolic generalizedLambertW(n,x) """ BuiltinFunction.__init__(self, "lambert_w", nargs=2, @@ -662,9 +689,9 @@ def __call__(self, *args, **kwds): EXAMPLES:: - sage: lambert_w(1) + sage: lambert_w(1) # needs sage.symbolic lambert_w(1) - sage: lambert_w(1, 2) + sage: lambert_w(1, 2) # needs sage.symbolic lambert_w(1, 2) """ if len(args) == 2: @@ -678,6 +705,7 @@ def _method_arguments(self, n, z): r""" TESTS:: + sage: # needs sage.libs.flint sage: b = RBF(1, 0.001) sage: lambert_w(b) [0.567 +/- 6.44e-4] @@ -697,29 +725,29 @@ def _eval_(self, n, z): """ EXAMPLES:: - sage: lambert_w(6.0) + sage: lambert_w(6.0) # needs scipy 1.43240477589830 - sage: lambert_w(1) + sage: lambert_w(1) # needs sage.symbolic lambert_w(1) - sage: lambert_w(x+1) + sage: lambert_w(x + 1) # needs sage.symbolic lambert_w(x + 1) There are three special values which are automatically simplified:: - sage: lambert_w(0) + sage: lambert_w(0) # needs mpmath 0 - sage: lambert_w(e) + sage: lambert_w(e) # needs sage.symbolic 1 - sage: lambert_w(-1/e) + sage: lambert_w(-1/e) # needs sage.symbolic -1 - sage: lambert_w(SR(0)) + sage: lambert_w(SR(0)) # needs sage.symbolic 0 The special values only hold on the principal branch:: - sage: lambert_w(1,e) + sage: lambert_w(1, e) # needs sage.symbolic lambert_w(1, e) - sage: lambert_w(1, e.n()) + sage: lambert_w(1, e.n()) # needs sage.symbolic -0.532092121986380 + 4.59715801330257*I TESTS: @@ -728,11 +756,11 @@ def _eval_(self, n, z): value should be either the same as the parent of the input, or a Sage type:: - sage: parent(lambert_w(int(0))) + sage: parent(lambert_w(int(0))) # needs mpmath <... 'int'> - sage: parent(lambert_w(Integer(0))) + sage: parent(lambert_w(Integer(0))) # needs mpmath Integer Ring - sage: parent(lambert_w(e)) + sage: parent(lambert_w(e)) # needs sage.symbolic Symbolic Ring """ if not isinstance(z, Expression): @@ -750,13 +778,14 @@ def _evalf_(self, n, z, parent=None, algorithm=None): """ EXAMPLES:: - sage: N(lambert_w(1)) + sage: N(lambert_w(1)) # needs sage.symbolic 0.567143290409784 - sage: lambert_w(RealField(100)(1)) + sage: lambert_w(RealField(100)(1)) # needs sage.rings.real_mpfr 0.56714329040978387299996866221 SciPy is used to evaluate for float, RDF, and CDF inputs:: + sage: # needs scipy sage: lambert_w(RDF(1)) 0.5671432904097838 sage: lambert_w(float(1)) @@ -772,8 +801,7 @@ def _evalf_(self, n, z, parent=None, algorithm=None): """ R = parent or s_parent(z) if R is float or R is RDF: - from scipy.special import lambertw - res = lambertw(z, n) + res = _scipy_lambertw(z, n) # SciPy always returns a complex value, make it real if possible if not res.imag: return R(res.real) @@ -782,11 +810,9 @@ def _evalf_(self, n, z, parent=None, algorithm=None): else: return CDF(res) elif R is complex or R is CDF: - from scipy.special import lambertw - return R(lambertw(z, n)) + return R(_scipy_lambertw(z, n)) else: - import mpmath - return mpmath_utils.call(mpmath.lambertw, z, n, parent=R) + return _mpmath_utils_call(_mpmath_lambertw, z, n, parent=R) def _derivative_(self, n, z, diff_param=None): r""" @@ -794,19 +820,19 @@ def _derivative_(self, n, z, diff_param=None): EXAMPLES:: - sage: x = var('x') - sage: derivative(lambert_w(x), x) + sage: x = var('x') # needs sage.symbolic + sage: derivative(lambert_w(x), x) # needs sage.symbolic lambert_w(x)/(x*lambert_w(x) + x) - sage: derivative(lambert_w(2, exp(x)), x) + sage: derivative(lambert_w(2, exp(x)), x) # needs sage.symbolic e^x*lambert_w(2, e^x)/(e^x*lambert_w(2, e^x) + e^x) TESTS: Differentiation in the first parameter raises an error :trac:`14788`:: - sage: n = var('n') - sage: lambert_w(n, x).diff(n) + sage: n = var('n') # needs sage.symbolic + sage: lambert_w(n, x).diff(n) # needs sage.symbolic Traceback (most recent call last): ... ValueError: cannot differentiate lambert_w in the first parameter @@ -822,16 +848,16 @@ def _maxima_init_evaled_(self, n, z): These are indirect doctests for this function.:: - sage: lambert_w(0, x)._maxima_() + sage: lambert_w(0, x)._maxima_() # needs sage.symbolic lambert_w(_SAGE_VAR_x) - sage: lambert_w(1, x)._maxima_() + sage: lambert_w(1, x)._maxima_() # needs sage.symbolic generalized_lambert_w(1,_SAGE_VAR_x) TESTS:: - sage: lambert_w(x)._maxima_()._sage_() + sage: lambert_w(x)._maxima_()._sage_() # needs sage.symbolic lambert_w(x) - sage: lambert_w(2, x)._maxima_()._sage_() + sage: lambert_w(2, x)._maxima_()._sage_() # needs sage.symbolic lambert_w(2, x) """ if isinstance(z, str): @@ -852,9 +878,9 @@ def _print_(self, n, z): EXAMPLES:: - sage: lambert_w(1) + sage: lambert_w(1) # needs sage.symbolic lambert_w(1) - sage: lambert_w(0,x) + sage: lambert_w(0, x) # needs sage.symbolic lambert_w(x) """ if n == 0: @@ -869,13 +895,14 @@ def _print_latex_(self, n, z): EXAMPLES:: + sage: # needs sage.symbolic sage: latex(lambert_w(1)) \operatorname{W}({1}) - sage: latex(lambert_w(0,x)) + sage: latex(lambert_w(0, x)) \operatorname{W}({x}) - sage: latex(lambert_w(1,x)) + sage: latex(lambert_w(1, x)) \operatorname{W_{1}}({x}) - sage: latex(lambert_w(1,x+exp(x))) + sage: latex(lambert_w(1, x + exp(x))) \operatorname{W_{1}}({x + e^{x}}) """ if n == 0: @@ -908,23 +935,23 @@ def __init__(self): The following expressions are evaluated using the exponential function:: - sage: exp_polar(pi*I/2) + sage: exp_polar(pi*I/2) # needs sage.symbolic I - sage: x = var('x', domain='real') - sage: exp_polar(-1/2*I*pi + x) + sage: x = var('x', domain='real') # needs sage.symbolic + sage: exp_polar(-1/2*I*pi + x) # needs sage.symbolic e^(-1/2*I*pi + x) The function is left unevaluated when the imaginary part of the input `z` does not satisfy `-\pi < \Im(z) \leq \pi`:: - sage: exp_polar(2*pi*I) + sage: exp_polar(2*pi*I) # needs sage.symbolic exp_polar(2*I*pi) - sage: exp_polar(-4*pi*I) + sage: exp_polar(-4*pi*I) # needs sage.symbolic exp_polar(-4*I*pi) This fixes :trac:`18085`:: - sage: integrate(1/sqrt(1+x^3),x,algorithm='sympy') + sage: integrate(1/sqrt(1+x^3), x, algorithm='sympy') # needs sage.symbolic 1/3*x*gamma(1/3)*hypergeometric((1/3, 1/2), (4/3,), -x^3)/gamma(4/3) @@ -948,25 +975,23 @@ def _evalf_(self, z, parent=None, algorithm=None): If the imaginary part of `z` obeys `-\pi < z \leq \pi`, then `\operatorname{exp\_polar}(z)` is evaluated as `\exp(z)`:: - sage: exp_polar(1.0 + 2.0*I) + sage: exp_polar(1.0 + 2.0*I) # needs sage.symbolic -1.13120438375681 + 2.47172667200482*I If the imaginary part of `z` is outside of that interval the expression is left unevaluated:: - sage: exp_polar(-5.0 + 8.0*I) + sage: exp_polar(-5.0 + 8.0*I) # needs sage.symbolic exp_polar(-5.00000000000000 + 8.00000000000000*I) An attempt to numerically evaluate such an expression raises an error:: - sage: exp_polar(-5.0 + 8.0*I).n() + sage: exp_polar(-5.0 + 8.0*I).n() # needs sage.symbolic Traceback (most recent call last): ... ValueError: invalid attempt to numerically evaluate exp_polar() """ - from sage.functions.other import imag - if (not isinstance(z, Expression) and bool(-const_pi < imag(z) <= const_pi)): return exp(z) @@ -977,17 +1002,17 @@ def _eval_(self, z): """ EXAMPLES:: - sage: exp_polar(3*I*pi) + sage: exp_polar(3*I*pi) # needs sage.symbolic exp_polar(3*I*pi) - sage: x = var('x', domain='real') - sage: exp_polar(4*I*pi + x) + sage: x = var('x', domain='real') # needs sage.symbolic + sage: exp_polar(4*I*pi + x) # needs sage.symbolic exp_polar(4*I*pi + x) TESTS: Check that :trac:`24441` is fixed:: - sage: exp_polar(arcsec(jacobi_sn(1.1*I*x, x))) # should be fast + sage: exp_polar(arcsec(jacobi_sn(1.1*I*x, x))) # should be fast # needs sage.symbolic exp_polar(arcsec(jacobi_sn(1.10000000000000*I*x, x))) """ try: @@ -1021,7 +1046,7 @@ class Function_harmonic_number_generalized(BuiltinFunction): H_{s,m}=\zeta(m)-\zeta(m,s-1) If called with a single argument, that argument is ``s`` and ``m`` is - assumed to be 1 (the normal harmonic numbers ``H_s``). + assumed to be 1 (the normal harmonic numbers `H_s`). ALGORITHM: @@ -1035,42 +1060,44 @@ class Function_harmonic_number_generalized(BuiltinFunction): Evaluation of integer, rational, or complex argument:: - sage: harmonic_number(5) + sage: harmonic_number(5) # needs mpmath 137/60 - sage: harmonic_number(3,3) + + sage: # needs sage.symbolic + sage: harmonic_number(3, 3) 251/216 sage: harmonic_number(5/2) -2*log(2) + 46/15 - sage: harmonic_number(3.,3) + sage: harmonic_number(3., 3) zeta(3) - 0.0400198661225573 - sage: harmonic_number(3.,3.) + sage: harmonic_number(3., 3.) 1.16203703703704 - sage: harmonic_number(3,3).n(200) + sage: harmonic_number(3, 3).n(200) 1.16203703703703703703703... - sage: harmonic_number(1+I,5) + sage: harmonic_number(1 + I, 5) harmonic_number(I + 1, 5) - sage: harmonic_number(5,1.+I) + sage: harmonic_number(5, 1. + I) 1.57436810798989 - 1.06194728851357*I Solutions to certain sums are returned in terms of harmonic numbers:: - sage: k=var('k') - sage: sum(1/k^7,k,1,x) + sage: k = var('k') # needs sage.symbolic + sage: sum(1/k^7,k,1,x) # needs sage.symbolic harmonic_number(x, 7) Check the defining integral at a random integer:: - sage: n=randint(10,100) - sage: bool(SR(integrate((1-x^n)/(1-x),x,0,1)) == harmonic_number(n)) + sage: n = randint(10,100) + sage: bool(SR(integrate((1-x^n)/(1-x),x,0,1)) == harmonic_number(n)) # needs sage.symbolic True There are several special values which are automatically simplified:: - sage: harmonic_number(0) + sage: harmonic_number(0) # needs mpmath 0 - sage: harmonic_number(1) + sage: harmonic_number(1) # needs mpmath 1 - sage: harmonic_number(x,1) + sage: harmonic_number(x, 1) # needs sage.symbolic harmonic_number(x) """ @@ -1078,9 +1105,9 @@ def __init__(self): r""" EXAMPLES:: - sage: loads(dumps(harmonic_number(x,5))) + sage: loads(dumps(harmonic_number(x, 5))) # needs sage.symbolic harmonic_number(x, 5) - sage: harmonic_number(x, x)._sympy_() + sage: harmonic_number(x, x)._sympy_() # needs sympy sage.symbolic harmonic(x, x) """ BuiltinFunction.__init__(self, "harmonic_number", nargs=2, @@ -1089,15 +1116,15 @@ def __init__(self): def __call__(self, z, m=1, **kwds): r""" Custom call method allows the user to pass one argument or two. If - one argument is passed, we assume it is ``z`` and that ``m=1``. + one argument is passed, we assume it is ``z`` and that `m=1`. EXAMPLES:: - sage: harmonic_number(x) + sage: harmonic_number(x) # needs sage.symbolic harmonic_number(x) - sage: harmonic_number(x,1) + sage: harmonic_number(x, 1) # needs sage.symbolic harmonic_number(x) - sage: harmonic_number(x,2) + sage: harmonic_number(x, 2) # needs sage.symbolic harmonic_number(x, 2) """ return BuiltinFunction.__call__(self, z, m, **kwds) @@ -1106,30 +1133,32 @@ def _eval_(self, z, m): """ EXAMPLES:: - sage: harmonic_number(x,0) + sage: harmonic_number(5) # needs mpmath + 137/60 + + sage: # needs sage.symbolic + sage: harmonic_number(x, 0) x - sage: harmonic_number(x,1) + sage: harmonic_number(x, 1) harmonic_number(x) - sage: harmonic_number(5) - 137/60 - sage: harmonic_number(3,3) + sage: harmonic_number(3, 3) 251/216 - sage: harmonic_number(3,3).n() # this goes from rational to float + sage: harmonic_number(3, 3).n() # this goes from rational to float 1.16203703703704 - sage: harmonic_number(3,3.) # the following uses zeta functions + sage: harmonic_number(3, 3.) # the following uses zeta functions 1.16203703703704 - sage: harmonic_number(3.,3) + sage: harmonic_number(3., 3) zeta(3) - 0.0400198661225573 - sage: harmonic_number(0.1,5) + sage: harmonic_number(0.1, 5) zeta(5) - 0.650300133161038 - sage: harmonic_number(0.1,5).n() + sage: harmonic_number(0.1, 5).n() 0.386627621982332 - sage: harmonic_number(3,5/2) + sage: harmonic_number(3, 5/2) 1/27*sqrt(3) + 1/8*sqrt(2) + 1 TESTS:: - sage: harmonic_number(int(3), int(3)) + sage: harmonic_number(int(3), int(3)) # needs sage.symbolic 1.162037037037037 """ if m == 0: @@ -1144,13 +1173,14 @@ def _evalf_(self, z, m, parent=None, algorithm=None): """ EXAMPLES:: - sage: harmonic_number(3.,3) + sage: # needs sage.symbolic + sage: harmonic_number(3., 3) zeta(3) - 0.0400198661225573 - sage: harmonic_number(3.,3.) + sage: harmonic_number(3., 3.) 1.16203703703704 - sage: harmonic_number(3,3).n(200) + sage: harmonic_number(3, 3).n(200) 1.16203703703703703703703... - sage: harmonic_number(5,I).n() + sage: harmonic_number(5, I).n() 2.36889632899995 - 3.51181956521611*I """ if m == 0: @@ -1160,16 +1190,15 @@ def _evalf_(self, z, m, parent=None, algorithm=None): elif m == 1: return harmonic_m1._evalf_(z, parent, algorithm) - from sage.functions.transcendental import zeta, hurwitz_zeta return zeta(m) - hurwitz_zeta(m, z + 1) def _maxima_init_evaled_(self, n, z): """ EXAMPLES:: - sage: maxima_calculus(harmonic_number(x,2)) + sage: maxima_calculus(harmonic_number(x, 2)) # needs sage.symbolic gen_harmonic_number(2,_SAGE_VAR_x) - sage: maxima_calculus(harmonic_number(3,harmonic_number(x,3),hold=True)) + sage: maxima_calculus(harmonic_number(3, harmonic_number(x,3), hold=True)) # needs sage.symbolic 1/3^gen_harmonic_number(3,_SAGE_VAR_x)+1/2^gen_harmonic_number(3,_SAGE_VAR_x)+1 """ if isinstance(n, str): @@ -1192,6 +1221,7 @@ def _derivative_(self, n, m, diff_param=None): EXAMPLES:: + sage: # needs sage.symbolic sage: k,m,n = var('k,m,n') sage: sum(1/k, k, 1, x).diff(x) 1/6*pi^2 - harmonic_number(x, 2) @@ -1204,7 +1234,6 @@ def _derivative_(self, n, m, diff_param=None): ... ValueError: cannot differentiate harmonic_number in the second parameter """ - from sage.functions.transcendental import zeta if diff_param == 1: raise ValueError("cannot differentiate harmonic_number in the second parameter") if m == 1: @@ -1216,9 +1245,9 @@ def _print_(self, z, m): """ EXAMPLES:: - sage: harmonic_number(x) + sage: harmonic_number(x) # needs sage.symbolic harmonic_number(x) - sage: harmonic_number(x,2) + sage: harmonic_number(x, 2) # needs sage.symbolic harmonic_number(x, 2) """ if m == 1: @@ -1230,9 +1259,9 @@ def _print_latex_(self, z, m): """ EXAMPLES:: - sage: latex(harmonic_number(x)) + sage: latex(harmonic_number(x)) # needs sage.symbolic H_{x} - sage: latex(harmonic_number(x,2)) + sage: latex(harmonic_number(x, 2)) # needs sage.symbolic H_{{x},{2}} """ if m == 1: @@ -1250,13 +1279,14 @@ class _Function_swap_harmonic(BuiltinFunction): EXAMPLES:: - sage: maxima(harmonic_number(x,2)) # maxima expect interface + sage: # needs sage.symbolic + sage: maxima(harmonic_number(x, 2)) # maxima expect interface gen_harmonic_number(2,_SAGE_VAR_x) sage: from sage.calculus.calculus import symbolic_expression_from_maxima_string as sefms sage: sefms('gen_harmonic_number(3,x)') harmonic_number(x, 3) sage: from sage.interfaces.maxima_lib import maxima_lib, max_to_sr - sage: c=maxima_lib(harmonic_number(x,2)); c + sage: c = maxima_lib(harmonic_number(x,2)); c gen_harmonic_number(2,_SAGE_VAR_x) sage: max_to_sr(c.ecl()) harmonic_number(x, 2) @@ -1294,10 +1324,10 @@ def __init__(self): r""" EXAMPLES:: - sage: k=var('k') - sage: loads(dumps(sum(1/k,k,1,x))) + sage: k = var('k') # needs sage.symbolic + sage: loads(dumps(sum(1/k, k, 1, x))) # needs sage.symbolic harmonic_number(x) - sage: harmonic_number(x)._sympy_() + sage: harmonic_number(x)._sympy_() # needs sympy sage.symbolic harmonic(x) """ BuiltinFunction.__init__(self, "harmonic_number", nargs=1, @@ -1310,15 +1340,15 @@ def _eval_(self, z, **kwds): """ EXAMPLES:: - sage: harmonic_number(0) + sage: harmonic_number(0) # needs mpmath 0 - sage: harmonic_number(1) + sage: harmonic_number(1) # needs mpmath 1 - sage: harmonic_number(20) + sage: harmonic_number(20) # needs mpmath 55835135/15519504 - sage: harmonic_number(5/2) + sage: harmonic_number(5/2) # needs sage.symbolic -2*log(2) + 46/15 - sage: harmonic_number(2*x) + sage: harmonic_number(2*x) # needs sage.symbolic harmonic_number(2*x) """ if z in ZZ: @@ -1327,28 +1357,25 @@ def _eval_(self, z, **kwds): elif z == 1: return Integer(1) elif z > 1: - import sage.libs.flint.arith as flint_arith - return flint_arith.harmonic_number(z) + return _flint_harmonic_number(z) elif z in QQ: - from .gamma import psi1 return psi1(z + 1) - psi1(1) def _evalf_(self, z, parent=None, algorithm='mpmath'): """ EXAMPLES:: - sage: harmonic_number(20).n() # this goes from rational to float + sage: # needs mpmath + sage: harmonic_number(20).n() # this goes from rational to float 3.59773965714368 sage: harmonic_number(20).n(200) 3.59773965714368191148376906... - sage: harmonic_number(20.) # this computes the integral with mpmath + sage: harmonic_number(20.) # this computes the integral with mpmath 3.59773965714368 - sage: harmonic_number(1.0*I) + sage: harmonic_number(1.0*I) # needs sage.symbolic 0.671865985524010 + 1.07667404746858*I """ - from sage.libs.mpmath import utils as mpmath_utils - import mpmath - return mpmath_utils.call(mpmath.harmonic, z, parent=parent) + return _mpmath_utils_call(_mpmath_harmonic, z, parent=parent) def _derivative_(self, z, diff_param=None): """ @@ -1356,19 +1383,18 @@ def _derivative_(self, z, diff_param=None): EXAMPLES:: - sage: k=var('k') - sage: sum(1/k,k,1,x).diff(x) + sage: k = var('k') # needs sage.symbolic + sage: sum(1/k, k, 1, x).diff(x) # needs sage.symbolic 1/6*pi^2 - harmonic_number(x, 2) """ - from sage.functions.transcendental import zeta return zeta(2) - harmonic_number(z, 2) def _print_latex_(self, z): """ EXAMPLES:: - sage: k=var('k') - sage: latex(sum(1/k,k,1,x)) + sage: k = var('k') # needs sage.symbolic + sage: latex(sum(1/k, k, 1, x)) # needs sage.symbolic H_{x} """ return r"H_{%s}" % z diff --git a/src/sage/functions/min_max.py b/src/sage/functions/min_max.py index 28419136e52..caaed6f1193 100644 --- a/src/sage/functions/min_max.py +++ b/src/sage/functions/min_max.py @@ -7,15 +7,16 @@ Here you can see some differences:: - sage: max(x, x^2) + sage: max(x, x^2) # needs sage.symbolic x - sage: max_symbolic(x, x^2) + sage: max_symbolic(x, x^2) # needs sage.symbolic max(x, x^2) - sage: f(x) = max_symbolic(x, x^2); f(1/2) + sage: f(x) = max_symbolic(x, x^2); f(1/2) # needs sage.symbolic 1/2 This works as expected for more than two entries:: + sage: # needs sage.symbolic sage: max(3, 5, x) 5 sage: min(3, 5, x) @@ -33,11 +34,13 @@ # https://www.gnu.org/licenses/ ############################################################################### +from builtins import max as builtin_max, min as builtin_min + +from sage.misc.lazy_import import lazy_import +from sage.structure.element import Expression from sage.symbolic.function import BuiltinFunction -from sage.symbolic.expression import Expression -from sage.symbolic.ring import SR -from builtins import max as builtin_max, min as builtin_min +lazy_import('sage.symbolic.ring', 'SR') class MinMax_base(BuiltinFunction): @@ -45,6 +48,7 @@ def eval_helper(self, this_f, builtin_f, initial_val, args): """ EXAMPLES:: + sage: # needs sage.symbolic sage: max_symbolic(3, 5, x) # indirect doctest max(x, 5) sage: max_symbolic([5.0r]) # indirect doctest @@ -89,20 +93,20 @@ def __call__(self, *args, **kwds): """ EXAMPLES:: - sage: max_symbolic(3, 5, x) + sage: max_symbolic(3, 5, x) # needs sage.symbolic max(x, 5) - sage: max_symbolic(3, 5, x, hold=True) + sage: max_symbolic(3, 5, x, hold=True) # needs sage.symbolic max(3, 5, x) - sage: max_symbolic([3, 5, x]) + sage: max_symbolic([3, 5, x]) # needs sage.symbolic max(x, 5) :: - sage: min_symbolic(3, 5, x) + sage: min_symbolic(3, 5, x) # needs sage.symbolic min(x, 3) - sage: min_symbolic(3, 5, x, hold=True) + sage: min_symbolic(3, 5, x, hold=True) # needs sage.symbolic min(3, 5, x) - sage: min_symbolic([3, 5, x]) + sage: min_symbolic([3, 5, x]) # needs sage.symbolic min(x, 3) TESTS: @@ -116,6 +120,7 @@ def __call__(self, *args, **kwds): Check if a single argument which is not iterable works:: + sage: # needs sage.symbolic sage: max_symbolic(None) Traceback (most recent call last): ... @@ -162,6 +167,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: max_symbolic(3, x) max(3, x) sage: max_symbolic(3, x).subs(x=5) @@ -173,11 +179,11 @@ def __init__(self): TESTS:: - sage: loads(dumps(max_symbolic(x, 5))) + sage: loads(dumps(max_symbolic(x, 5))) # needs sage.symbolic max(x, 5) - sage: latex(max_symbolic(x, 5)) + sage: latex(max_symbolic(x, 5)) # needs sage.symbolic \max\left(x, 5\right) - sage: max_symbolic(x, 5)._sympy_() + sage: max_symbolic(x, 5)._sympy_() # needs sympy sage.symbolic Max(5, x) """ BuiltinFunction.__init__(self, 'max', nargs=0, latex_name=r"\max", @@ -187,6 +193,7 @@ def _eval_(self, *args): """ EXAMPLES:: + sage: # needs sage.symbolic sage: t = max_symbolic(x, 5); t max(x, 5) sage: t.subs(x=3) # indirect doctest @@ -215,6 +222,7 @@ def _evalf_(self, *args, **kwds): """ EXAMPLES:: + sage: # needs sage.symbolic sage: t = max_symbolic(sin(x), cos(x)) sage: t.subs(x=1).n(200) 0.84147098480789650665250232163029899962256306079837106567275 @@ -231,10 +239,10 @@ def _evalf_(self, *args, **kwds): We can usually integrate these expressions, but can't guarantee a symbolic answer in closed form:: - sage: f = max_symbolic(sin(x), cos(x)) - sage: r = integral(f, x, 0, 1) + sage: f = max_symbolic(sin(x), cos(x)) # needs sage.symbolic + sage: r = integral(f, x, 0, 1) # needs sage.symbolic ... - sage: r.n() # abs tol 1e-8 + sage: r.n() # abs tol 1e-8 # needs sage.symbolic 0.873911256504955 """ return max_symbolic(args) @@ -254,6 +262,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: min_symbolic(3, x) min(3, x) sage: min_symbolic(3, x).subs(x=5) @@ -265,11 +274,11 @@ def __init__(self): TESTS:: - sage: loads(dumps(min_symbolic(x, 5))) + sage: loads(dumps(min_symbolic(x, 5))) # needs sage.symbolic min(x, 5) - sage: latex(min_symbolic(x, 5)) + sage: latex(min_symbolic(x, 5)) # needs sage.symbolic \min\left(x, 5\right) - sage: min_symbolic(x, 5)._sympy_() + sage: min_symbolic(x, 5)._sympy_() # needs sympy sage.symbolic Min(5, x) """ BuiltinFunction.__init__(self, 'min', nargs=0, latex_name=r"\min", @@ -279,6 +288,7 @@ def _eval_(self, *args): """ EXAMPLES:: + sage: # needs sage.symbolic sage: t = min_symbolic(x, 5); t min(x, 5) sage: t.subs(x=3) # indirect doctest @@ -307,6 +317,7 @@ def _evalf_(self, *args, **kwds): """ EXAMPLES:: + sage: # needs sage.symbolic sage: t = min_symbolic(sin(x), cos(x)) sage: t.subs(x=1).n(200) 0.54030230586813971740093660744297660373231042061792222767010 diff --git a/src/sage/functions/orthogonal_polys.py b/src/sage/functions/orthogonal_polys.py index 60c785c74d4..7a9322973ad 100644 --- a/src/sage/functions/orthogonal_polys.py +++ b/src/sage/functions/orthogonal_polys.py @@ -395,20 +395,33 @@ import warnings -from sage.misc.latex import latex -from sage.rings.integer_ring import ZZ -from sage.rings.rational_field import QQ -from sage.rings.real_mpfr import RR -from sage.rings.cc import CC -from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing import sage.rings.abc -from sage.symbolic.function import BuiltinFunction, GinacFunction -from sage.symbolic.expression import Expression -from sage.symbolic.ring import SR -from sage.functions.other import factorial, binomial -from sage.structure.element import parent from sage.arith.misc import rising_factorial +from sage.misc.lazy_import import lazy_import +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ +from sage.symbolic.function import BuiltinFunction, GinacFunction +from sage.structure.element import Expression, parent + +lazy_import('sage.functions.other', ['factorial', 'binomial']) + +lazy_import('sage.misc.latex', 'latex') +lazy_import('sage.rings.cc', 'CC') +lazy_import('sage.rings.polynomial.polynomial_ring_constructor', 'PolynomialRing') +lazy_import('sage.rings.real_mpfr', 'RR') + +lazy_import('sage.symbolic.ring', 'SR') +lazy_import('sage.calculus.calculus', 'maxima', as_='_maxima') + +lazy_import('sage.libs.mpmath.utils', 'call', as_='_mpmath_utils_call') +lazy_import('sage.libs.mpmath.all', 'chebyt', as_='_mpmath_chebyt') +lazy_import('sage.libs.mpmath.all', 'chebyu', as_='_mpmath_chebyu') +lazy_import('sage.libs.mpmath.all', 'laguerre', as_='_mpmath_laguerre') +lazy_import('sage.libs.mpmath.all', 'legenp', as_='_mpmath_legenp') +lazy_import('sage.libs.mpmath.all', 'legenq', as_='_mpmath_legenq') + +lazy_import('scipy.special', 'eval_chebyu', as_='_scipy_chebyu') class OrthogonalFunction(BuiltinFunction): @@ -466,9 +479,9 @@ def _eval_special_values_(self, *args): EXAMPLES:: - sage: var('n') + sage: var('n') # needs sage.symbolic n - sage: chebyshev_T(n,-1) + sage: chebyshev_T(n, -1) # needs sage.symbolic (-1)^n """ raise ValueError("no special values known") @@ -480,9 +493,9 @@ def _eval_(self, n, *args): EXAMPLES:: - sage: var('n,x') + sage: var('n,x') # needs sage.symbolic (n, x) - sage: chebyshev_T(5,x) + sage: chebyshev_T(5, x) # needs sage.symbolic 16*x^5 - 20*x^3 + 5*x """ return None @@ -497,9 +510,10 @@ def __call__(self, *args, **kwds): EXAMPLES:: + sage: # needs sage.symbolic sage: chebyshev_T(5, x) 16*x^5 - 20*x^3 + 5*x - sage: chebyshev_T(5, x, algorithm='pari') + sage: chebyshev_T(5, x, algorithm='pari') # needs sage.libs.pari 16*x^5 - 20*x^3 + 5*x sage: chebyshev_T(5, x, algorithm='maxima') 16*x^5 - 20*x^3 + 5*x @@ -512,9 +526,8 @@ def __call__(self, *args, **kwds): elif algorithm == 'recursive': return self.eval_recursive(*args, **kwds) elif algorithm == 'maxima': - from sage.calculus.calculus import maxima kwds['hold'] = True - return maxima(self._eval_(*args, **kwds))._sage_() + return _maxima(self._eval_(*args, **kwds))._sage_() return super(OrthogonalFunction, self).__call__(*args, **kwds) @@ -525,7 +538,7 @@ class ChebyshevFunction(OrthogonalFunction): EXAMPLES:: - sage: chebyshev_T(3,x) + sage: chebyshev_T(3, x) # needs sage.symbolic 4*x^3 - 3*x """ def __call__(self, n, *args, **kwds): @@ -538,16 +551,17 @@ def __call__(self, n, *args, **kwds): EXAMPLES:: - sage: K. = NumberField(x^3-x-1) - sage: chebyshev_T(5, a) + sage: x = polygen(QQ, 'x') + sage: K. = NumberField(x^3 - x - 1) # needs sage.rings.number_field + sage: chebyshev_T(5, a) # needs sage.rings.number_field 16*a^2 + a - 4 - sage: chebyshev_T(5,MatrixSpace(ZZ, 2)([1, 2, -4, 7])) + sage: chebyshev_T(5, MatrixSpace(ZZ, 2)([1, 2, -4, 7])) # needs sage.modules [-40799 44162] [-88324 91687] sage: R. = QQ[] sage: parent(chebyshev_T(5, x)) Univariate Polynomial Ring in x over Rational Field - sage: chebyshev_T(5, 2, hold=True) + sage: chebyshev_T(5, 2, hold=True) # needs sage.symbolic chebyshev_T(5, 2) sage: chebyshev_T(1,2,3) Traceback (most recent call last): @@ -570,18 +584,20 @@ def _eval_(self, n, x): EXAMPLES:: + sage: # needs sage.symbolic sage: var('n,x') (n, x) - sage: chebyshev_T(5,x) + sage: chebyshev_T(5, x) 16*x^5 - 20*x^3 + 5*x sage: chebyshev_T(64, x) 2*(2*(2*(2*(2*(2*x^2 - 1)^2 - 1)^2 - 1)^2 - 1)^2 - 1)^2 - 1 - sage: chebyshev_T(n,-1) + sage: chebyshev_T(n, -1) (-1)^n - sage: chebyshev_T(-7,x) + sage: chebyshev_T(-7, x) 64*x^7 - 112*x^5 + 56*x^3 - 7*x - sage: chebyshev_T(3/2,x) + sage: chebyshev_T(3/2, x) chebyshev_T(3/2, x) + sage: R. = QQ[] sage: chebyshev_T(2,t) 2*t^2 - 1 @@ -589,14 +605,14 @@ def _eval_(self, n, x): 4*t^2 - 1 sage: parent(chebyshev_T(4, RIF(5))) Real Interval Field with 53 bits of precision - sage: RR2 = RealField(5) - sage: chebyshev_T(100000,RR2(2)) + sage: RR2 = RealField(5) # needs sage.rings.real_mpfr + sage: chebyshev_T(100000, RR2(2)) # needs sage.rings.real_mpfr 8.9e57180 - sage: chebyshev_T(5,Qp(3)(2)) + sage: chebyshev_T(5, Qp(3)(2)) # needs sage.rings.padics 2 + 3^2 + 3^3 + 3^4 + 3^5 + O(3^20) - sage: chebyshev_T(100001/2, 2) + sage: chebyshev_T(100001/2, 2) # needs sage.symbolic ...chebyshev_T(100001/2, 2) - sage: chebyshev_U._eval_(1.5, Mod(8,9)) is None + sage: chebyshev_U._eval_(1.5, Mod(8,9)) is None # needs mpmath True """ # n is an integer => evaluate algebraically (as polynomial) @@ -639,12 +655,11 @@ class Func_chebyshev_T(ChebyshevFunction): EXAMPLES:: - sage: chebyshev_T(5,x) + sage: chebyshev_T(5, x) # needs sage.symbolic 16*x^5 - 20*x^3 + 5*x - sage: var('k') + sage: var('k') # needs sage.symbolic k - sage: test = chebyshev_T(k,x) - sage: test + sage: test = chebyshev_T(k, x); test # needs sage.symbolic chebyshev_T(k, x) """ def __init__(self): @@ -653,15 +668,16 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: var('n, x') (n, x) sage: from sage.functions.orthogonal_polys import Func_chebyshev_T sage: chebyshev_T2 = Func_chebyshev_T() - sage: chebyshev_T2(1,x) + sage: chebyshev_T2(1, x) x - sage: chebyshev_T(x, x)._sympy_() + sage: chebyshev_T(x, x)._sympy_() # needs sympy chebyshevt(x, x) - sage: maxima(chebyshev_T(1,x, hold=True)) + sage: maxima(chebyshev_T(1, x, hold=True)) _SAGE_VAR_x sage: maxima(chebyshev_T(n, chebyshev_T(n, x))) chebyshev_t(_SAGE_VAR_n,chebyshev_t(_SAGE_VAR_n,_SAGE_VAR_x)) @@ -685,7 +701,7 @@ def _print_latex_(self, n, z): r""" TESTS:: - sage: latex(chebyshev_T(3, x, hold=True)) + sage: latex(chebyshev_T(3, x, hold=True)) # needs sage.symbolic T_{3}\left(x\right) """ return r"T_{{{}}}\left({}\right)".format(latex(n), latex(z)) @@ -697,15 +713,16 @@ def _eval_special_values_(self, n, x): EXAMPLES:: + sage: # needs sage.symbolic sage: var('n') n - sage: chebyshev_T(n,1) + sage: chebyshev_T(n, 1) 1 - sage: chebyshev_T(n,0) + sage: chebyshev_T(n, 0) 1/2*(-1)^(1/2*n)*((-1)^n + 1) - sage: chebyshev_T(n,-1) + sage: chebyshev_T(n, -1) (-1)^n - sage: chebyshev_T._eval_special_values_(3/2,x) + sage: chebyshev_T._eval_special_values_(3/2, x) Traceback (most recent call last): ... ValueError: no special value found @@ -731,13 +748,14 @@ def _evalf_(self, n, x, **kwds): EXAMPLES:: - sage: chebyshev_T._evalf_(10,3) + sage: # needs sage.rings.real_mpfr + sage: chebyshev_T._evalf_(10, 3) 2.26195370000000e7 - sage: chebyshev_T._evalf_(10,3,parent=RealField(75)) + sage: chebyshev_T._evalf_(10, 3, parent=RealField(75)) 2.261953700000000000000e7 - sage: chebyshev_T._evalf_(10,I) + sage: chebyshev_T._evalf_(10, I) # needs sage.symbolic -3363.00000000000 - sage: chebyshev_T._evalf_(5,0.3) + sage: chebyshev_T._evalf_(5, 0.3) 0.998880000000000 sage: chebyshev_T(1/2, 0) 0.707106781186548 @@ -750,15 +768,15 @@ def _evalf_(self, n, x, **kwds): This simply evaluates using :class:`RealField` or :class:`ComplexField`:: - sage: chebyshev_T(1234.5, RDF(2.1)) + sage: chebyshev_T(1234.5, RDF(2.1)) # needs sage.rings.real_mpfr 5.48174256255782e735 - sage: chebyshev_T(1234.5, I) + sage: chebyshev_T(1234.5, I) # needs sage.rings.real_mpfr sage.symbolic -1.21629397684152e472 - 1.21629397684152e472*I For large values of ``n``, mpmath fails (but the algebraic formula still works):: - sage: chebyshev_T._evalf_(10^6, 0.1) + sage: chebyshev_T._evalf_(10^6, 0.1) # needs sage.rings.real_mpfr Traceback (most recent call last): ... NoConvergence: Hypergeometric series converges too slowly. Try increasing maxterms. @@ -782,10 +800,7 @@ def _evalf_(self, n, x, **kwds): if not isinstance(real_parent, (sage.rings.abc.RealField, sage.rings.abc.ComplexField)): raise TypeError("cannot evaluate chebyshev_T with parent {}".format(real_parent)) - from sage.libs.mpmath.all import call as mpcall - from sage.libs.mpmath.all import chebyt as mpchebyt - - return mpcall(mpchebyt, n, x, parent=real_parent) + return _mpmath_utils_call(_mpmath_chebyt, n, x, parent=real_parent) def eval_formula(self, n, x): """ @@ -802,18 +817,20 @@ def eval_formula(self, n, x): EXAMPLES:: - sage: chebyshev_T.eval_formula(-1,x) + sage: # needs sage.symbolic + sage: chebyshev_T.eval_formula(-1, x) x - sage: chebyshev_T.eval_formula(0,x) + sage: chebyshev_T.eval_formula(0, x) 1 - sage: chebyshev_T.eval_formula(1,x) + sage: chebyshev_T.eval_formula(1, x) x - sage: chebyshev_T.eval_formula(2,0.1) == chebyshev_T._evalf_(2,0.1) - True - sage: chebyshev_T.eval_formula(10,x) + sage: chebyshev_T.eval_formula(10, x) 512*x^10 - 1280*x^8 + 1120*x^6 - 400*x^4 + 50*x^2 - 1 - sage: chebyshev_T.eval_algebraic(10,x).expand() + sage: chebyshev_T.eval_algebraic(10, x).expand() 512*x^10 - 1280*x^8 + 1120*x^6 - 400*x^4 + 50*x^2 - 1 + + sage: chebyshev_T.eval_formula(2, 0.1) == chebyshev_T._evalf_(2, 0.1) # needs sage.rings.complex_double + True """ if n < 0: return self.eval_formula(-n, x) @@ -841,9 +858,9 @@ def eval_algebraic(self, n, x): EXAMPLES:: - sage: chebyshev_T.eval_algebraic(5, x) + sage: chebyshev_T.eval_algebraic(5, x) # needs sage.symbolic 2*(2*(2*x^2 - 1)*x - x)*(2*x^2 - 1) - x - sage: chebyshev_T(-7, x) - chebyshev_T(7,x) + sage: chebyshev_T(-7, x) - chebyshev_T(7, x) # needs sage.symbolic 0 sage: R. = ZZ[] sage: chebyshev_T.eval_algebraic(-1, t) @@ -856,12 +873,15 @@ def eval_algebraic(self, n, x): 1/2 sage: chebyshev_T(7^100, Mod(2,3)) 2 - sage: n = 97; x = RIF(pi/2/n) - sage: chebyshev_T(n, cos(x)).contains_zero() + sage: n = 97; x = RIF(pi/2/n) # needs sage.symbolic + sage: chebyshev_T(n, cos(x)).contains_zero() # needs sage.symbolic True + + sage: # needs sage.rings.padics sage: R. = Zp(2, 8, 'capped-abs')[] - sage: chebyshev_T(10^6+1, t) - (2^7 + O(2^8))*t^5 + O(2^8)*t^4 + (2^6 + O(2^8))*t^3 + O(2^8)*t^2 + (1 + 2^6 + O(2^8))*t + O(2^8) + sage: chebyshev_T(10^6 + 1, t) + (2^7 + O(2^8))*t^5 + O(2^8)*t^4 + (2^6 + O(2^8))*t^3 + O(2^8)*t^2 + + (1 + 2^6 + O(2^8))*t + O(2^8) """ if n == 0: return parent(x).one() @@ -877,9 +897,9 @@ def _eval_recursive_(self, n, x, both=False): EXAMPLES:: - sage: chebyshev_T._eval_recursive_(5, x) + sage: chebyshev_T._eval_recursive_(5, x) # needs sage.symbolic (2*(2*(2*x^2 - 1)*x - x)*(2*x^2 - 1) - x, False) - sage: chebyshev_T._eval_recursive_(5, x, True) + sage: chebyshev_T._eval_recursive_(5, x, True) # needs sage.symbolic (2*(2*(2*x^2 - 1)*x - x)*(2*x^2 - 1) - x, 2*(2*x^2 - 1)^2 - 1) """ if n == 1: @@ -898,6 +918,7 @@ def _eval_numpy_(self, n, x): EXAMPLES:: + sage: # needs numpy scipy sage: import numpy sage: z = numpy.array([1,2]) sage: z2 = numpy.array([[1,2],[1,2]]) @@ -922,13 +943,14 @@ def _derivative_(self, n, x, diff_param): EXAMPLES:: + sage: # needs sage.symbolic sage: var('k') k - sage: derivative(chebyshev_T(k,x),x) + sage: derivative(chebyshev_T(k, x), x) k*chebyshev_U(k - 1, x) - sage: derivative(chebyshev_T(3,x),x) + sage: derivative(chebyshev_T(3, x), x) 12*x^2 - 3 - sage: derivative(chebyshev_T(k,x),k) + sage: derivative(chebyshev_T(k, x), k) Traceback (most recent call last): ... NotImplementedError: derivative w.r.t. to the index is not supported yet @@ -965,13 +987,14 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: var('n, x') (n, x) sage: from sage.functions.orthogonal_polys import Func_chebyshev_U sage: chebyshev_U2 = Func_chebyshev_U() - sage: chebyshev_U2(1,x) + sage: chebyshev_U2(1, x) 2*x - sage: chebyshev_U(x, x)._sympy_() + sage: chebyshev_U(x, x)._sympy_() # needs sympy chebyshevu(x, x) sage: maxima(chebyshev_U(2,x, hold=True)) 3*(...-...(8*(1-_SAGE_VAR_x))/3)+(4*(1-_SAGE_VAR_x)^2)/3+1) @@ -997,7 +1020,7 @@ def _print_latex_(self, n, z): r""" TESTS:: - sage: latex(chebyshev_U(3, x, hold=True)) + sage: latex(chebyshev_U(3, x, hold=True)) # needs sage.symbolic U_{3}\left(x\right) """ return r"U_{{{}}}\left({}\right)".format(latex(n), latex(z)) @@ -1018,6 +1041,7 @@ def eval_formula(self, n, x): EXAMPLES:: + sage: # needs sage.symbolic sage: chebyshev_U.eval_formula(10, x) 1024*x^10 - 2304*x^8 + 1792*x^6 - 560*x^4 + 60*x^2 - 1 sage: chebyshev_U.eval_formula(-2, x) @@ -1054,13 +1078,13 @@ def eval_algebraic(self, n, x): EXAMPLES:: - sage: chebyshev_U.eval_algebraic(5,x) + sage: chebyshev_U.eval_algebraic(5, x) # needs sage.symbolic -2*((2*x + 1)*(2*x - 1)*x - 4*(2*x^2 - 1)*x)*(2*x + 1)*(2*x - 1) sage: parent(chebyshev_U(3, Mod(8,9))) Ring of integers modulo 9 sage: parent(chebyshev_U(3, Mod(1,9))) Ring of integers modulo 9 - sage: chebyshev_U(-3,x) + chebyshev_U(1,x) + sage: chebyshev_U(-3, x) + chebyshev_U(1, x) # needs sage.symbolic 0 sage: chebyshev_U(-1,Mod(5,8)) 0 @@ -1075,11 +1099,11 @@ def eval_algebraic(self, n, x): 1 sage: chebyshev_U.eval_algebraic(1, t) 2*t - sage: n = 97; x = RIF(pi/n) - sage: chebyshev_U(n-1, cos(x)).contains_zero() + sage: n = 97; x = RIF(pi/n) # needs sage.symbolic + sage: chebyshev_U(n - 1, cos(x)).contains_zero() # needs sage.symbolic True - sage: R. = Zp(2, 6, 'capped-abs')[] - sage: chebyshev_U(10^6+1, t) + sage: R. = Zp(2, 6, 'capped-abs')[] # needs sage.rings.padics + sage: chebyshev_U(10^6 + 1, t) # needs sage.rings.padics (2 + O(2^6))*t + O(2^6) """ if n == -1: @@ -1096,10 +1120,11 @@ def _eval_recursive_(self, n, x, both=False): EXAMPLES:: - sage: chebyshev_U._eval_recursive_(3, x) + sage: chebyshev_U._eval_recursive_(3, x) # needs sage.symbolic (4*((2*x + 1)*(2*x - 1) - 2*x^2)*x, False) - sage: chebyshev_U._eval_recursive_(3, x, True) - (4*((2*x + 1)*(2*x - 1) - 2*x^2)*x, ((2*x + 1)*(2*x - 1) + 2*x)*((2*x + 1)*(2*x - 1) - 2*x)) + sage: chebyshev_U._eval_recursive_(3, x, True) # needs sage.symbolic + (4*((2*x + 1)*(2*x - 1) - 2*x^2)*x, + ((2*x + 1)*(2*x - 1) + 2*x)*((2*x + 1)*(2*x - 1) - 2*x)) """ if n == 0: return parent(x).one(), 2*x @@ -1117,11 +1142,11 @@ def _evalf_(self, n, x, **kwds): EXAMPLES:: - sage: chebyshev_U(5,-4+3.*I) + sage: chebyshev_U(5,-4+3.*I) # needs sage.symbolic 98280.0000000000 - 11310.0000000000*I - sage: chebyshev_U(10,3).n(75) + sage: chebyshev_U(10, 3).n(75) # needs sage.symbolic 4.661117900000000000000e7 - sage: chebyshev_U._evalf_(1.5, Mod(8,9)) + sage: chebyshev_U._evalf_(1.5, Mod(8,9)) # needs sage.rings.real_mpfr Traceback (most recent call last): ... TypeError: cannot evaluate chebyshev_U with parent Ring of integers modulo 9 @@ -1143,10 +1168,7 @@ def _evalf_(self, n, x, **kwds): if not isinstance(real_parent, (sage.rings.abc.RealField, sage.rings.abc.ComplexField)): raise TypeError("cannot evaluate chebyshev_U with parent {}".format(real_parent)) - from sage.libs.mpmath.all import call as mpcall - from sage.libs.mpmath.all import chebyu as mpchebyu - - return mpcall(mpchebyu, n, x, parent=real_parent) + return _mpmath_utils_call(_mpmath_chebyu, n, x, parent=real_parent) def _eval_special_values_(self, n, x): """ @@ -1155,13 +1177,14 @@ def _eval_special_values_(self, n, x): EXAMPLES:: + sage: # needs sage.symbolic sage: var('n') n - sage: chebyshev_U(n,1) + sage: chebyshev_U(n, 1) n + 1 - sage: chebyshev_U(n,0) + sage: chebyshev_U(n, 0) 1/2*(-1)^(1/2*n)*((-1)^n + 1) - sage: chebyshev_U(n,-1) + sage: chebyshev_U(n, -1) (-1)^n*(n + 1) sage: chebyshev_U._eval_special_values_(n, 2) Traceback (most recent call last): @@ -1185,6 +1208,7 @@ def _eval_numpy_(self, n, x): EXAMPLES:: + sage: # needs numpy scipy sage: import numpy sage: z = numpy.array([1,2]) sage: z2 = numpy.array([[1,2],[1,2]]) @@ -1199,8 +1223,7 @@ def _eval_numpy_(self, n, x): sage: chebyshev_U(z,0.1) array([ 0.2 , -0.96]) """ - from scipy.special import eval_chebyu - return eval_chebyu(n, x) + return _scipy_chebyu(n, x) def _derivative_(self, n, x, diff_param): """ @@ -1209,13 +1232,14 @@ def _derivative_(self, n, x, diff_param): EXAMPLES:: + sage: # needs sage.symbolic sage: var('k') k - sage: derivative(chebyshev_U(k,x),x) + sage: derivative(chebyshev_U(k,x), x) ((k + 1)*chebyshev_T(k + 1, x) - x*chebyshev_U(k, x))/(x^2 - 1) - sage: derivative(chebyshev_U(3,x),x) + sage: derivative(chebyshev_U(3,x), x) 24*x^2 - 4 - sage: derivative(chebyshev_U(k,x),k) + sage: derivative(chebyshev_U(k,x), k) Traceback (most recent call last): ... NotImplementedError: derivative w.r.t. to the index is not supported yet @@ -1234,29 +1258,31 @@ class Func_legendre_P(GinacFunction): r""" EXAMPLES:: + sage: # needs sage.symbolic sage: legendre_P(4, 2.0) 55.3750000000000 sage: legendre_P(1, x) x - sage: legendre_P(4, x+1) + sage: legendre_P(4, x + 1) 35/8*(x + 1)^4 - 15/4*(x + 1)^2 + 3/8 sage: legendre_P(1/2, I+1.) 1.05338240025858 + 0.359890322109665*I sage: legendre_P(0, SR(1)).parent() Symbolic Ring - sage: legendre_P(0, 0) + sage: legendre_P(0, 0) # needs sage.symbolic 1 - sage: legendre_P(1, x) + sage: legendre_P(1, x) # needs sage.symbolic x + sage: # needs sage.symbolic sage: legendre_P(4, 2.) 55.3750000000000 - sage: legendre_P(5.5,1.00001) + sage: legendre_P(5.5, 1.00001) 1.00017875754114 - sage: legendre_P(1/2, I+1).n() + sage: legendre_P(1/2, I + 1).n() 1.05338240025858 + 0.359890322109665*I - sage: legendre_P(1/2, I+1).n(59) + sage: legendre_P(1/2, I + 1).n(59) 1.0533824002585801 + 0.35989032210966539*I sage: legendre_P(42, RR(12345678)) 2.66314881466753e309 @@ -1267,22 +1293,24 @@ class Func_legendre_P(GinacFunction): sage: legendre_P(201/2, 0).n(100) 0.056138617863017877699963095883 + sage: # needs sage.symbolic sage: R. = QQ[] - sage: legendre_P(4,x) + sage: legendre_P(4, x) 35/8*x^4 - 15/4*x^2 + 3/8 - sage: legendre_P(10000,x).coefficient(x,1) + sage: legendre_P(10000, x).coefficient(x, 1) 0 sage: var('t,x') (t, x) - sage: legendre_P(-5,t) + sage: legendre_P(-5, t) 35/8*t^4 - 15/4*t^2 + 3/8 - sage: legendre_P(4, x+1) + sage: legendre_P(4, x + 1) 35/8*(x + 1)^4 - 15/4*(x + 1)^2 + 3/8 sage: legendre_P(4, sqrt(2)) 83/8 sage: legendre_P(4, I*e) 35/8*e^4 + 15/4*e^2 + 3/8 + sage: # needs sage.symbolic sage: n = var('n') sage: derivative(legendre_P(n,x), x) (n*x*legendre_P(n, x) - n*legendre_P(n - 1, x))/(x^2 - 1) @@ -1297,12 +1325,13 @@ class Func_legendre_P(GinacFunction): Verify that :trac:`33962` is fixed:: - sage: [legendre_P(n, 0) for n in range(-10, 10)] + sage: [legendre_P(n, 0) for n in range(-10, 10)] # needs sage.symbolic [0, 35/128, 0, -5/16, 0, 3/8, 0, -1/2, 0, 1, 1, 0, -1/2, 0, 3/8, 0, -5/16, 0, 35/128, 0] Verify that :trac:`33963` is fixed:: + sage: # needs sage.symbolic sage: n = var("n") sage: assume(n, "integer") sage: assume(n, "even") @@ -1336,7 +1365,7 @@ def __init__(self): sage: loads(dumps(legendre_Q)) legendre_Q - sage: maxima(legendre_Q(20,x, hold=True))._sage_().coefficient(x,10) + sage: maxima(legendre_Q(20, x, hold=True))._sage_().coefficient(x, 10) # needs sage.symbolic -29113619535/131072*log(-(x + 1)/(x - 1)) """ BuiltinFunction.__init__(self, "legendre_Q", nargs=2, latex_name=r"Q", @@ -1350,15 +1379,16 @@ def _eval_(self, n, x, *args, **kwds): EXAMPLES:: + sage: # needs sage.symbolic sage: legendre_Q(2,x) 1/4*(3*x^2 - 1)*(log(x + 1) - log(-x + 1)) - 3/2*x - sage: legendre_Q(5,0) + sage: legendre_Q(5, 0) -8/15 - sage: legendre_Q(2,2*x) + sage: legendre_Q(2, 2*x) 1/4*(12*x^2 - 1)*(log(2*x + 1) - log(-2*x + 1)) - 3*x sage: legendre_Q(1/2, I+1.) -0.511424110789061 + 1.34356195297194*I - sage: legendre_Q(-1,x) + sage: legendre_Q(-1, x) Infinity """ ret = self._eval_special_values_(n, x) @@ -1376,6 +1406,7 @@ def _eval_special_values_(self, n, x): EXAMPLES:: + sage: # needs sage.symbolic sage: var('n') n sage: legendre_Q(n, 0) @@ -1415,20 +1446,18 @@ def _evalf_(self, n, x, parent=None, **kwds): EXAMPLES:: - sage: legendre_Q(4, 2.) + sage: legendre_Q(4, 2.) # needs mpmath 0.00116107583162041 - 86.9828465962674*I - sage: legendre_Q(1/2, I+1.) + sage: legendre_Q(1/2, I+1.) # needs sage.symbolic -0.511424110789061 + 1.34356195297194*I - sage: legendre_Q(1/2, I+1).n(59) + sage: legendre_Q(1/2, I+1).n(59) # needs sage.symbolic -0.51142411078906080 + 1.3435619529719394*I """ ret = self._eval_special_values_(n, x) if ret is not None: return ret - import mpmath - from sage.libs.mpmath.all import call as mpcall - return mpcall(mpmath.legenq, n, 0, x, parent=parent) + return _mpmath_utils_call(_mpmath_legenq, n, 0, x, parent=parent) def eval_recursive(self, n, arg, **kwds): """ @@ -1436,9 +1465,9 @@ def eval_recursive(self, n, arg, **kwds): EXAMPLES:: - sage: legendre_Q.eval_recursive(2,x) + sage: legendre_Q.eval_recursive(2, x) # needs sage.symbolic 3/4*x^2*(log(x + 1) - log(-x + 1)) - 3/2*x - 1/4*log(x + 1) + 1/4*log(-x + 1) - sage: legendre_Q.eval_recursive(20,x).expand().coefficient(x,10) + sage: legendre_Q.eval_recursive(20, x).expand().coefficient(x, 10) # needs sage.symbolic -29113619535/131072*log(x + 1) + 29113619535/131072*log(-x + 1) """ from sage.functions.log import ln @@ -1472,15 +1501,17 @@ def eval_formula(self, n, arg, **kwds): EXAMPLES:: + sage: # needs sage.symbolic sage: legendre_Q.eval_formula(1, x) 1/2*x*(log(x + 1) - log(-x + 1)) - 1 - sage: legendre_Q.eval_formula(2,x).expand().collect(log(1+x)).collect(log(1-x)) + sage: legendre_Q.eval_formula(2, x).expand().collect(log(1+x)).collect(log(1-x)) 1/4*(3*x^2 - 1)*log(x + 1) - 1/4*(3*x^2 - 1)*log(-x + 1) - 3/2*x - sage: legendre_Q.eval_formula(20,x).coefficient(x,10) + sage: legendre_Q.eval_formula(20, x).coefficient(x, 10) -29113619535/131072*log(x + 1) + 29113619535/131072*log(-x + 1) sage: legendre_Q(0, 2) -1/2*I*pi + 1/2*log(3) - sage: legendre_Q(0, 2.) + + sage: legendre_Q(0, 2.) # needs mpmath 0.549306144334055 - 1.57079632679490*I """ from sage.functions.log import ln @@ -1498,9 +1529,9 @@ def _Wfunc(self, n, arg): EXAMPLES:: - sage: legendre_Q._Wfunc(2, x) + sage: legendre_Q._Wfunc(2, x) # needs sage.symbolic 3/2*x - sage: legendre_Q._Wfunc(7, x) + sage: legendre_Q._Wfunc(7, x) # needs sage.symbolic 429/16*x^6 - 275/8*x^4 + 849/80*x^2 - 16/35 """ if n == 0: @@ -1524,14 +1555,15 @@ def _derivative_(self, n, x, *args, **kwds): EXAMPLES:: + sage: # needs sage.symbolic sage: n = var('n') sage: derivative(legendre_Q(n,x), x) (n*x*legendre_Q(n, x) - n*legendre_Q(n - 1, x))/(x^2 - 1) - sage: ex1 = legendre_Q(5,x,hold=True).diff(x).expand().simplify_full() - sage: ex2 = legendre_Q(5,x).diff(x).expand().simplify_full() + sage: ex1 = legendre_Q(5, x, hold=True).diff(x).expand().simplify_full() + sage: ex2 = legendre_Q(5, x).diff(x).expand().simplify_full() sage: ex1.subs(x=7).n() == ex2.subs(x=7).n() True - sage: derivative(legendre_Q(n,x), n) + sage: derivative(legendre_Q(n, x), n) Traceback (most recent call last): ... NotImplementedError: Derivative w.r.t. to the index is not supported. @@ -1580,7 +1612,7 @@ class Func_assoc_legendre_P(BuiltinFunction): We give the first Ferrers functions for non-negative integers `n` and `m` in the interval `-1 |n|` for integers:: - sage: gen_legendre_P(2,3,4) + sage: gen_legendre_P(2, 3, 4) # needs mpmath 0 Case `x = 0`:: - sage: gen_legendre_P(13/2,2,0) + sage: # needs sage.symbolic + sage: gen_legendre_P(13/2, 2, 0) 4*sqrt(pi)/(gamma(13/4)*gamma(-15/4)) - sage: (m,n) = var('m,n') - sage: gen_legendre_P(n,m,0) + sage: m, n = var('m,n') + sage: gen_legendre_P(n, m, 0) sqrt(pi)*2^m/(gamma(-1/2*m + 1/2*n + 1)*gamma(-1/2*m - 1/2*n + 1/2)) - sage: gen_legendre_P(n,3,0) + sage: gen_legendre_P(n, 3, 0) 8*sqrt(pi)/(gamma(1/2*n - 1/2)*gamma(-1/2*n - 1)) - sage: gen_legendre_P(3,m,0) + sage: gen_legendre_P(3, m, 0) sqrt(pi)*2^m/(gamma(-1/2*m + 5/2)*gamma(-1/2*m - 1)) Case `m = n` for integers:: + sage: # needs sage.symbolic sage: m = var('m') sage: assume(m, 'integer') sage: gen_legendre_P(m, m, x) @@ -1739,9 +1775,9 @@ def _eval_special_values_(self, n, m, x): Case `n = 0`:: - sage: gen_legendre_P(m, 0, x) + sage: gen_legendre_P(m, 0, x) # needs sage.symbolic legendre_P(m, x) - sage: gen_legendre_P(2,0,4) == legendre_P(2,4) + sage: gen_legendre_P(2, 0, 4) == legendre_P(2, 4) # needs sage.symbolic True """ @@ -1769,11 +1805,11 @@ def _eval_int_ord_deg_(self, n, m, x): TESTS:: - sage: gen_legendre_P._eval_int_ord_deg_(-2, 1, x) + sage: gen_legendre_P._eval_int_ord_deg_(-2, 1, x) # needs sage.symbolic -sqrt(-x^2 + 1) - sage: gen_legendre_P._eval_int_ord_deg_(2, -1, x) + sage: gen_legendre_P._eval_int_ord_deg_(2, -1, x) # needs sage.symbolic 1/2*sqrt(-x^2 + 1)*x - sage: gen_legendre_P._eval_int_ord_deg_(-2, -1, x) + sage: gen_legendre_P._eval_int_ord_deg_(-2, -1, x) # needs sage.symbolic 1/2*sqrt(-x^2 + 1) """ @@ -1793,19 +1829,17 @@ def _evalf_(self, n, m, x, parent=None, **kwds): EXAMPLES:: - sage: gen_legendre_P(10,2,3).n() # abs tol 1e-14 + sage: gen_legendre_P(10, 2, 3).n() # abs tol 1e-14 # needs sage.symbolic -7.19496360000000e8 - sage: gen_legendre_P(5/2,2,1.+I) + sage: gen_legendre_P(5/2,2,1.+I) # needs sage.symbolic 14.3165258449040 - 12.7850496155152*I - sage: gen_legendre_P(5/2,2,ComplexField(70)(1+I)) + sage: gen_legendre_P(5/2, 2, ComplexField(70)(1+I)) # needs sage.rings.real_mpfr sage.symbolic 14.316525844904028532 - 12.785049615515157033*I - sage: gen_legendre_P(2/3,1,0.) + sage: gen_legendre_P(2/3, 1, 0.) # needs mpmath -0.773063511309286 """ - import mpmath - from sage.libs.mpmath.all import call as mpcall - return mpcall(mpmath.legenp, n, m, x, parent=parent) + return _mpmath_utils_call(_mpmath_legenp, n, m, x, parent=parent) def eval_gen_poly(self, n, m, arg, **kwds): r""" @@ -1826,9 +1860,9 @@ def eval_gen_poly(self, n, m, arg, **kwds): EXAMPLES:: - sage: gen_legendre_P(7,4,x) + sage: gen_legendre_P(7, 4, x) # needs sage.symbolic 3465/2*(13*x^3 - 3*x)*(x^2 - 1)^2 - sage: gen_legendre_P(3,1,sqrt(x)) + sage: gen_legendre_P(3, 1, sqrt(x)) # needs sage.symbolic -3/2*(5*x - 1)*sqrt(-x + 1) REFERENCE: @@ -1855,10 +1889,12 @@ def _derivative_(self, n, m, x, *args, **kwds): EXAMPLES:: - sage: (m,n) = var('m,n') + sage: # needs sage.symbolic + sage: m, n = var('m,n') sage: derivative(gen_legendre_P(n,m,x), x) - -((n + 1)*x*gen_legendre_P(n, m, x) + (m - n - 1)*gen_legendre_P(n + 1, m, x))/(x^2 - 1) - sage: gen_legendre_P(3,2,x,hold=True).diff(x).expand().simplify_full() + -((n + 1)*x*gen_legendre_P(n, m, x) + + (m - n - 1)*gen_legendre_P(n + 1, m, x))/(x^2 - 1) + sage: gen_legendre_P(3, 2, x, hold=True).diff(x).expand().simplify_full() -45*x^2 + 15 sage: derivative(gen_legendre_P(n,m,x), n) Traceback (most recent call last): @@ -1884,7 +1920,7 @@ def __init__(self): sage: loads(dumps(gen_legendre_Q)) gen_legendre_Q - sage: maxima(gen_legendre_Q(2,1,3, hold=True))._sage_().simplify_full() + sage: maxima(gen_legendre_Q(2, 1, 3, hold=True))._sage_().simplify_full() # needs sage.symbolic 1/4*sqrt(2)*(36*pi - 36*I*log(2) + 25*I) """ BuiltinFunction.__init__(self, "gen_legendre_Q", nargs=3, latex_name=r"Q", @@ -1898,7 +1934,7 @@ def _eval_(self, n, m, x, *args, **kwds): EXAMPLES:: - sage: gen_legendre_Q(2,1,3) + sage: gen_legendre_Q(2, 1, 3) # needs sage.symbolic -1/4*sqrt(-2)*(-36*I*pi + 36*log(2) - 25) """ ret = self._eval_special_values_(n, m, x) @@ -1915,8 +1951,8 @@ def _eval_special_values_(self, n, m, x): EXAMPLES:: - sage: n, m = var('n m') - sage: gen_legendre_Q(n,m,0) + sage: n, m = var('n m') # needs sage.symbolic + sage: gen_legendre_Q(n, m, 0) # needs sage.symbolic -sqrt(pi)*2^(m - 1)*gamma(1/2*m + 1/2*n + 1/2)*sin(1/2*pi*m + 1/2*pi*n)/gamma(-1/2*m + 1/2*n + 1) """ if m == 0: @@ -1936,18 +1972,16 @@ def _evalf_(self, n, m, x, parent=None, **kwds): EXAMPLES:: - sage: gen_legendre_Q(2,1,3.) + sage: gen_legendre_Q(2, 1, 3.) # needs mpmath -39.9859464434253 + 0.0165114736149193*I - sage: gen_legendre_Q(2,1,ComplexField(70)(3)) + sage: gen_legendre_Q(2, 1, ComplexField(70)(3)) # needs sage.rings.real_mpfr -39.985946443425296223 + 0.016511473614919329585*I """ ret = self._eval_special_values_(n, m, x) if ret is not None: return ret - import mpmath - from sage.libs.mpmath.all import call as mpcall - return mpcall(mpmath.legenq, n, m, x, parent=parent) + return _mpmath_utils_call(_mpmath_legenq, n, m, x, parent=parent) def eval_recursive(self, n, m, x, **kwds): """ @@ -1955,15 +1989,16 @@ def eval_recursive(self, n, m, x, **kwds): EXAMPLES:: - sage: gen_legendre_Q(3,4,x) + sage: # needs sage.symbolic + sage: gen_legendre_Q(3, 4, x) 48/(x^2 - 1)^2 - sage: gen_legendre_Q(4,5,x) + sage: gen_legendre_Q(4, 5, x) -384/((x^2 - 1)^2*sqrt(-x^2 + 1)) - sage: gen_legendre_Q(0,1,x) + sage: gen_legendre_Q(0, 1, x) -1/sqrt(-x^2 + 1) - sage: gen_legendre_Q(0,2,x) + sage: gen_legendre_Q(0, 2, x) -1/2*((x + 1)^2 - (x - 1)^2)/(x^2 - 1) - sage: gen_legendre_Q(2,2,x).subs(x=2).expand() + sage: gen_legendre_Q(2, 2, x).subs(x=2).expand() 9/2*I*pi - 9/2*log(3) + 14/3 """ from sage.misc.functional import sqrt @@ -1985,11 +2020,13 @@ def _derivative_(self, n, m, x, *args, **kwds): EXAMPLES:: - sage: (m,n) = var('m,n') + sage: # needs sage.symbolic + sage: m, n = var('m,n') sage: derivative(gen_legendre_Q(n,m,x), x) - -((n + 1)*x*gen_legendre_Q(n, m, x) + (m - n - 1)*gen_legendre_Q(n + 1, m, x))/(x^2 - 1) - sage: ex1=gen_legendre_Q(3,2,x,hold=True).diff(x).expand().simplify_full() - sage: ex2=gen_legendre_Q(3,2,x).diff(x).expand().simplify_full() + -((n + 1)*x*gen_legendre_Q(n, m, x) + + (m - n - 1)*gen_legendre_Q(n + 1, m, x))/(x^2 - 1) + sage: ex1 = gen_legendre_Q(3, 2, x, hold=True).diff(x).expand().simplify_full() + sage: ex2 = gen_legendre_Q(3, 2, x).diff(x).expand().simplify_full() sage: ex1.subs(x=5).n() == ex2.subs(x=5).n() True sage: derivative(gen_legendre_Q(n,m,x), n) @@ -2017,44 +2054,43 @@ class Func_hermite(GinacFunction): EXAMPLES:: + sage: # needs sage.symbolic sage: x = PolynomialRing(QQ, 'x').gen() - sage: hermite(2,x) + sage: hermite(2, x) 4*x^2 - 2 - sage: hermite(3,x) + sage: hermite(3, x) 8*x^3 - 12*x - sage: hermite(3,2) + sage: hermite(3, 2) 40 sage: S. = PolynomialRing(RR) - sage: hermite(3,y) + sage: hermite(3, y) 8.00000000000000*y^3 - 12.0000000000000*y sage: R. = QQ[] - sage: hermite(3,y^2) + sage: hermite(3, y^2) 8*y^6 - 12*y^2 sage: w = var('w') - sage: hermite(3,2*w) + sage: hermite(3, 2*w) 64*w^3 - 24*w - sage: hermite(5,3.1416) + sage: hermite(5, 3.1416) 5208.69733891963 - sage: hermite(5,RealField(100)(pi)) + sage: hermite(5, RealField(100)(pi)) 5208.6167627118104649470287166 Check that :trac:`17192` is fixed:: + sage: # needs sage.symbolic sage: x = PolynomialRing(QQ, 'x').gen() - sage: hermite(0,x) + sage: hermite(0, x) 1 - - sage: hermite(-1,x) + sage: hermite(-1, x) Traceback (most recent call last): ... RuntimeError: hermite_eval: The index n must be a nonnegative integer - - sage: hermite(-7,x) + sage: hermite(-7, x) Traceback (most recent call last): ... RuntimeError: hermite_eval: The index n must be a nonnegative integer - - sage: m,x = SR.var('m,x') + sage: m, x = SR.var('m,x') sage: hermite(m, x).diff(m) Traceback (most recent call last): ... @@ -2068,17 +2104,17 @@ def __init__(self): sage: loads(dumps(hermite)) hermite - sage: hermite(x, x)._sympy_() + sage: hermite(x, x)._sympy_() # needs sympy sage.symbolic hermite(x, x) TESTS:: - sage: fricas(hermite(x, 5)) # optional - fricas + sage: fricas(hermite(x, 5)) # optional - fricas # needs sage.symbolic hermiteH(x,5) - sage: hermite(5,x) + sage: hermite(5, x) # needs sage.symbolic 32*x^5 - 160*x^3 + 120*x - sage: fricas.hermiteH(5,x) # optional - fricas + sage: fricas.hermiteH(5, x) # optional - fricas # needs sage.symbolic 5 3 32 x - 160 x + 120 x """ @@ -2111,7 +2147,7 @@ class Func_jacobi_P(OrthogonalFunction): sage: x = PolynomialRing(QQ, 'x').gen() sage: jacobi_P(2,0,0,x) 3/2*x^2 - 1/2 - sage: jacobi_P(2,1,2,1.2) + sage: jacobi_P(2,1,2,1.2) # needs sage.symbolic 5.01000000000000 """ def __init__(self): @@ -2120,22 +2156,22 @@ def __init__(self): EXAMPLES:: - sage: n,a,b,x = SR.var('n,a,b,x') + sage: n, a, b, x = SR.var('n,a,b,x') # needs sage.symbolic sage: loads(dumps(jacobi_P)) jacobi_P - sage: jacobi_P(n, a, b, x, hold=True)._sympy_() + sage: jacobi_P(n, a, b, x, hold=True)._sympy_() # needs sympy sage.symbolic jacobi(n, a, b, x) TESTS:: - sage: fricas(jacobi_P(1/2,4,1/3,x)) # optional - fricas + sage: fricas(jacobi_P(1/2, 4, 1/3, x)) # optional - fricas, needs sage.symbolic 1 1 jacobiP(-,4,-,x) 2 3 - sage: jacobi_P(1,2,3,x) + sage: jacobi_P(1, 2, 3, x) # needs sage.symbolic 7/2*x - 1/2 - sage: fricas.jacobiP(1,2,3,x) # optional - fricas + sage: fricas.jacobiP(1, 2, 3, x) # optional - fricas, needs sage.symbolic 7 x - 1 ------- 2 @@ -2151,16 +2187,17 @@ def _eval_(self, n, a, b, x): """ EXAMPLES:: - sage: n,a,b,x = SR.var('n,a,b,x') - sage: jacobi_P(1,n,n,n) + sage: # needs sage.symbolic + sage: n, a, b, x = SR.var('n,a,b,x') + sage: jacobi_P(1, n, n, n) (n + 1)*n - sage: jacobi_P(2,n,n,n) + sage: jacobi_P(2, n, n, n) 1/4*(2*n - 1)*(n + 2)*(n + 1)^2 - sage: jacobi_P(1,n,n,x) + sage: jacobi_P(1, n, n, x) (n + 1)*x - sage: jacobi_P(3,2,1,x) + sage: jacobi_P(3, 2, 1, x) 21/2*x^3 + 7/2*x^2 - 7/2*x - 1/2 - sage: jacobi_P(1,a,b,x) + sage: jacobi_P(1, a, b, x) 1/2*a*x + 1/2*b*x + 1/2*a - 1/2*b + x TESTS: @@ -2199,11 +2236,11 @@ def _evalf_(self, n, a, b, x, **kwds): """ EXAMPLES:: - sage: jacobi_P(2, 1, 2, 1.2) + sage: jacobi_P(2, 1, 2, 1.2) # needs sage.symbolic 5.01000000000000 - sage: jacobi_P(2, 1, 2, 1.2, hold=True).n(20) + sage: jacobi_P(2, 1, 2, 1.2, hold=True).n(20) # needs sage.symbolic 5.0100 - sage: jacobi_P(2, 1, 2, pi+I, hold=True).n(100) + sage: jacobi_P(2, 1, 2, pi + I, hold=True).n(100) # needs sage.symbolic 41.103034125334442891187112674 + 31.486722862692829003857755524*I """ from sage.rings.complex_arb import ComplexBallField as CBF @@ -2246,62 +2283,66 @@ class Func_ultraspherical(GinacFunction): EXAMPLES:: + sage: # needs sage.symbolic sage: ultraspherical(8, 101/11, x) 795972057547264/214358881*x^8 - 62604543852032/19487171*x^6... sage: x = PolynomialRing(QQ, 'x').gen() - sage: ultraspherical(2,3/2,x) + sage: ultraspherical(2, 3/2, x) 15/2*x^2 - 3/2 - sage: ultraspherical(1,1,x) + sage: ultraspherical(1, 1, x) 2*x - sage: t = PolynomialRing(RationalField(),"t").gen() - sage: gegenbauer(3,2,t) + sage: t = PolynomialRing(RationalField(), "t").gen() + sage: gegenbauer(3, 2, t) 32*t^3 - 12*t sage: x = SR.var('x') sage: n = ZZ.random_element(5, 5001) sage: a = QQ.random_element().abs() + 5 - sage: s = ( (n+1)*ultraspherical(n+1,a,x) - ....: - 2*x*(n+a)*ultraspherical(n,a,x) - ....: + (n+2*a-1)*ultraspherical(n-1,a,x) ) + sage: s = ( (n + 1)*ultraspherical(n + 1, a, x) + ....: - 2*x*(n + a)*ultraspherical(n, a, x) + ....: + (n + 2*a - 1)*ultraspherical(n - 1, a, x) ) sage: s.expand().is_zero() True - sage: ultraspherical(5,9/10,3.1416) + sage: ultraspherical(5, 9/10, 3.1416) 6949.55439044240 - sage: ultraspherical(5,9/10,RealField(100)(pi)) + sage: ultraspherical(5, 9/10, RealField(100)(pi)) # needs sage.rings.real_mpfr 6949.4695419382702451843080687 - sage: a,n = SR.var('a,n') - sage: gegenbauer(2,a,x) + sage: # needs sage.symbolic + sage: a, n = SR.var('a,n') + sage: gegenbauer(2, a, x) 2*(a + 1)*a*x^2 - a - sage: gegenbauer(3,a,x) + sage: gegenbauer(3, a, x) 4/3*(a + 2)*(a + 1)*a*x^3 - 2*(a + 1)*a*x - sage: gegenbauer(3,a,x).expand() + sage: gegenbauer(3, a, x).expand() 4/3*a^3*x^3 + 4*a^2*x^3 + 8/3*a*x^3 - 2*a^2*x - 2*a*x - sage: gegenbauer(10,a,x).expand().coefficient(x,2) + sage: gegenbauer(10, a, x).expand().coefficient(x, 2) 1/12*a^6 + 5/4*a^5 + 85/12*a^4 + 75/4*a^3 + 137/6*a^2 + 10*a - sage: ex = gegenbauer(100,a,x) - sage: (ex.subs(a==55/98) - gegenbauer(100,55/98,x)).is_trivial_zero() + sage: ex = gegenbauer(100, a, x) + sage: (ex.subs(a==55/98) - gegenbauer(100, 55/98, x)).is_trivial_zero() True - sage: gegenbauer(2,-3,x) + sage: # needs sage.symbolic + sage: gegenbauer(2, -3, x) 12*x^2 + 3 sage: gegenbauer(120,-99/2,3) 1654502372608570682112687530178328494861923493372493824 - sage: gegenbauer(5,9/2,x) + sage: gegenbauer(5, 9/2, x) 21879/8*x^5 - 6435/4*x^3 + 1287/8*x sage: gegenbauer(15,3/2,5) 3903412392243800 - sage: derivative(gegenbauer(n,a,x),x) + sage: derivative(gegenbauer(n, a, x), x) # needs sage.symbolic 2*a*gegenbauer(n - 1, a + 1, x) - sage: derivative(gegenbauer(3,a,x),x) + sage: derivative(gegenbauer(3, a, x), x) # needs sage.symbolic 4*(a + 2)*(a + 1)*a*x^2 - 2*(a + 1)*a - sage: derivative(gegenbauer(n,a,x),a) + sage: derivative(gegenbauer(n, a, x), a) # needs sage.symbolic Traceback (most recent call last): ... RuntimeError: derivative w.r.t. to the second index is not supported yet Numerical evaluation with the mpmath library:: + sage: # needs mpmath sage: from mpmath import gegenbauer as gegenbauer_mp sage: from mpmath import mp sage: mp.pretty = True; mp.dps=25 @@ -2315,15 +2356,15 @@ class Func_ultraspherical(GinacFunction): Check that :trac:`17192` is fixed:: sage: x = PolynomialRing(QQ, 'x').gen() - sage: ultraspherical(0,1,x) + sage: ultraspherical(0, 1, x) # needs sage.symbolic 1 - sage: ultraspherical(-1,1,x) + sage: ultraspherical(-1, 1, x) # needs sage.symbolic Traceback (most recent call last): ... RuntimeError: gegenb_eval: The index n must be a nonnegative integer - sage: ultraspherical(-7,1,x) + sage: ultraspherical(-7, 1, x) # needs sage.symbolic Traceback (most recent call last): ... RuntimeError: gegenb_eval: The index n must be a nonnegative integer @@ -2336,7 +2377,7 @@ def __init__(self): sage: loads(dumps(ultraspherical)) gegenbauer - sage: ultraspherical(x, x, x)._sympy_() + sage: ultraspherical(x, x, x)._sympy_() # needs sympy sage.symbolic gegenbauer(x, x, x) """ GinacFunction.__init__(self, "gegenbauer", nargs=3, latex_name=r"C", @@ -2362,15 +2403,19 @@ def __init__(self): EXAMPLES:: - sage: n,x = var('n,x') - sage: loads(dumps(laguerre)) - laguerre - sage: laguerre(x, x)._sympy_() + sage: # needs sage.symbolic + sage: n, x = var('n,x') + sage: laguerre(x, x)._sympy_() # needs sympy laguerre(x, x) sage: maxima(laguerre(1, x, hold=True)) 1-_SAGE_VAR_x sage: maxima(laguerre(n, laguerre(n, x))) laguerre(_SAGE_VAR_n,laguerre(_SAGE_VAR_n,_SAGE_VAR_x)) + + TESTS:: + + sage: loads(dumps(laguerre)) + laguerre """ OrthogonalFunction.__init__(self, "laguerre", nargs=2, latex_name=r"L", conversions={'maxima': 'laguerre', @@ -2386,17 +2431,17 @@ def _eval_(self, n, x, *args, **kwds): EXAMPLES:: sage: x = PolynomialRing(QQ, 'x').gen() - sage: laguerre(2,x) + sage: laguerre(2, x) # needs mpmath 1/2*x^2 - 2*x + 1 - sage: laguerre(3,x) + sage: laguerre(3, x) # needs mpmath -1/6*x^3 + 3/2*x^2 - 3*x + 1 - sage: laguerre(2,2) + sage: laguerre(2, 2) # needs mpmath -1 - sage: laguerre(-1, x) + sage: laguerre(-1, x) # needs sage.symbolic e^x - sage: laguerre(-6, x) + sage: laguerre(-6, x) # needs sage.symbolic 1/120*(x^5 + 25*x^4 + 200*x^3 + 600*x^2 + 600*x + 120)*e^x - sage: laguerre(-9,2) + sage: laguerre(-9,2) # needs sage.symbolic 66769/315*e^2 """ from sage.rings.integer import Integer @@ -2416,9 +2461,9 @@ def _eval_special_values_(self, n, x): EXAMPLES:: - sage: laguerre(0, 0) + sage: laguerre(0, 0) # needs mpmath 1 - sage: laguerre(1, x) + sage: laguerre(1, x) # needs sage.symbolic -x + 1 """ if n == 0 or x == 0: @@ -2432,14 +2477,14 @@ def _pol_laguerre(self, n, x): EXAMPLES:: - sage: laguerre(3,sin(x)) + sage: laguerre(3, sin(x)) # needs sage.symbolic -1/6*sin(x)^3 + 3/2*sin(x)^2 - 3*sin(x) + 1 sage: R. = PolynomialRing(QQ, 'x') - sage: laguerre(4,x) + sage: laguerre(4, x) # needs mpmath 1/24*x^4 - 2/3*x^3 + 3*x^2 - 4*x + 1 - sage: laguerre(4,x+1) + sage: laguerre(4, x + 1) # needs mpmath 1/24*(x + 1)^4 - 2/3*(x + 1)^3 + 3*(x + 1)^2 - 4*x - 3 - sage: laguerre(10,1+I) + sage: laguerre(10,1+I) # needs sage.symbolic 142511/113400*I + 95867/22680 """ if hasattr(x, 'pyobject'): @@ -2456,24 +2501,22 @@ def _evalf_(self, n, x, **kwds): EXAMPLES:: - sage: laguerre(100,RealField(300)(pi)) + sage: laguerre(100, RealField(300)(pi)) # needs sage.symbolic -0.638322077840648311606324... - sage: laguerre(10,1.+I) + sage: laguerre(10,1.+I) # needs sage.symbolic 4.22694003527337 + 1.25671075837743*I - sage: laguerre(-9, 2.) + sage: laguerre(-9, 2.) # needs sage.symbolic 1566.22186244286 """ the_parent = kwds.get('parent', None) if the_parent is None: the_parent = parent(x) - import mpmath - from sage.libs.mpmath.all import call as mpcall if n < 0: # work around mpmath issue 307 from sage.functions.log import exp - return exp(x) * mpcall(mpmath.laguerre, -n-1, 0, -x, parent=the_parent) + return exp(x) * _mpmath_utils_call(_mpmath_laguerre, -n-1, 0, -x, parent=the_parent) else: - return mpcall(mpmath.laguerre, n, 0, x, parent=the_parent) + return _mpmath_utils_call(_mpmath_laguerre, n, 0, x, parent=the_parent) def _derivative_(self, n, x, *args, **kwds): """ @@ -2481,13 +2524,13 @@ def _derivative_(self, n, x, *args, **kwds): EXAMPLES:: - sage: n=var('n') - sage: diff(laguerre(n,x), x) + sage: n = var('n') # needs sage.symbolic + sage: diff(laguerre(n, x), x) # needs sage.symbolic -gen_laguerre(n - 1, 1, x) TESTS:: - sage: diff(laguerre(x,x)) + sage: diff(laguerre(x, x)) # needs sage.symbolic Traceback (most recent call last): ... NotImplementedError: Derivative w.r.t. to the index is not supported. @@ -2515,15 +2558,19 @@ def __init__(self): EXAMPLES:: - sage: a,n,x = var('a, n, x') - sage: loads(dumps(gen_laguerre)) - gen_laguerre - sage: gen_laguerre(x, x, x)._sympy_() + sage: # needs sage.symbolic + sage: a, n, x = var('a, n, x') + sage: gen_laguerre(x, x, x)._sympy_() # needs sympy assoc_laguerre(x, x, x) - sage: maxima(gen_laguerre(1,2,x, hold=True)) + sage: maxima(gen_laguerre(1, 2, x, hold=True)) 3*(1-_SAGE_VAR_x/3) sage: maxima(gen_laguerre(n, a, gen_laguerre(n, a, x))) gen_laguerre(_SAGE_VAR_n,_SAGE_VAR_a, gen_laguerre(_SAGE_VAR_n,_SAGE_VAR_a,_SAGE_VAR_x)) + + TESTS:: + + sage: loads(dumps(gen_laguerre)) + gen_laguerre """ OrthogonalFunction.__init__(self, "gen_laguerre", nargs=3, latex_name=r"L", conversions={'maxima': 'gen_laguerre', @@ -2537,6 +2584,7 @@ def _eval_(self, n, a, x, *args, **kwds): EXAMPLES:: + sage: # needs sage.symbolic sage: gen_laguerre(2, 1, x) 1/2*x^2 - 3*x + 3 sage: gen_laguerre(2, 1/2, x) @@ -2562,11 +2610,11 @@ def _eval_special_values_(self, n, a, x): EXAMPLES:: - sage: gen_laguerre(0, 1, pi) + sage: gen_laguerre(0, 1, pi) # needs sage.symbolic 1 - sage: gen_laguerre(1, 2, x) + sage: gen_laguerre(1, 2, x) # needs sage.symbolic -x + 3 - sage: gen_laguerre(3, 4, 0) + sage: gen_laguerre(3, 4, 0) # needs mpmath 35 """ if n == 0: @@ -2583,14 +2631,14 @@ def _pol_gen_laguerre(self, n, a, x): """ EXAMPLES:: - sage: gen_laguerre(3, 1/2, sin(x)) + sage: gen_laguerre(3, 1/2, sin(x)) # needs sage.symbolic -1/6*sin(x)^3 + 7/4*sin(x)^2 - 35/8*sin(x) + 35/16 sage: R. = PolynomialRing(QQ, 'x') - sage: gen_laguerre(4, -1/2, x) + sage: gen_laguerre(4, -1/2, x) # needs mpmath 1/24*x^4 - 7/12*x^3 + 35/16*x^2 - 35/16*x + 35/128 - sage: gen_laguerre(4, -1/2, x+1) + sage: gen_laguerre(4, -1/2, x + 1) # needs mpmath 1/24*(x + 1)^4 - 7/12*(x + 1)^3 + 35/16*(x + 1)^2 - 35/16*x - 245/128 - sage: gen_laguerre(10, 1, 1+I) + sage: gen_laguerre(10, 1, 1+I) # needs sage.symbolic 25189/2100*I + 11792/2835 """ return sum(binomial(n + a, n - k) * (-1)**k / factorial(k) * x**k @@ -2600,17 +2648,15 @@ def _evalf_(self, n, a, x, **kwds): """ EXAMPLES:: - sage: gen_laguerre(100,1,RealField(300)(pi)) + sage: gen_laguerre(100, 1, RealField(300)(pi)) # needs sage.symbolic -0.89430788373354541911... - sage: gen_laguerre(10,1/2,1.+I) + sage: gen_laguerre(10,1/2,1.+I) # needs sage.symbolic 5.34469635574906 + 5.23754057922902*I """ the_parent = kwds.get('parent', None) if the_parent is None: the_parent = parent(x) - import mpmath - from sage.libs.mpmath.all import call as mpcall - return mpcall(mpmath.laguerre, n, a, x, parent=the_parent) + return _mpmath_utils_call(_mpmath_laguerre, n, a, x, parent=the_parent) def _derivative_(self, n, a, x, diff_param): """ @@ -2618,17 +2664,17 @@ def _derivative_(self, n, a, x, diff_param): EXAMPLES:: - sage: (a,n)=var('a,n') - sage: diff(gen_laguerre(n,a,x), x) + sage: a, n = var('a,n') # needs sage.symbolic + sage: diff(gen_laguerre(n,a,x), x) # needs sage.symbolic -gen_laguerre(n - 1, a + 1, x) - sage: gen_laguerre(n,a,x).diff(a) + sage: gen_laguerre(n,a,x).diff(a) # needs sage.symbolic Traceback (most recent call last): ... NotImplementedError: Derivative w.r.t. to the second index is not supported. TESTS:: - sage: diff(gen_laguerre(n,a,x), n) + sage: diff(gen_laguerre(n,a,x), n) # needs sage.symbolic Traceback (most recent call last): ... NotImplementedError: Derivative w.r.t. to the index is not supported. @@ -2671,8 +2717,8 @@ class Func_krawtchouk(OrthogonalFunction): We verify the orthogonality for `n = 4`:: sage: n = 4 - sage: p = SR.var('p') - sage: matrix([[sum(binomial(n,m) * p**m * (1-p)**(n-m) + sage: p = SR.var('p') # needs sage.symbolic + sage: matrix([[sum(binomial(n,m) * p**m * (1-p)**(n-m) # needs sage.symbolic ....: * krawtchouk(i,m,n,p) * krawtchouk(j,m,n,p) ....: for m in range(n+1)).expand().factor() ....: for i in range(n+1)] for j in range(n+1)]) @@ -2684,8 +2730,8 @@ class Func_krawtchouk(OrthogonalFunction): We verify the relationship between the Krawtchouk implementations:: - sage: q = SR.var('q') - sage: all(codes.bounds.krawtchouk(n, 1/q, j, x)*(-q)^j + sage: q = SR.var('q') # needs sage.symbolic + sage: all(codes.bounds.krawtchouk(n, 1/q, j, x)*(-q)^j # needs sage.symbolic ....: == krawtchouk(j, x, n, 1-q) for j in range(n+1)) True """ @@ -2695,10 +2741,10 @@ def __init__(self): EXAMPLES:: - sage: k,x,n,p = var('k,x,n,p') + sage: k, x, n, p = var('k,x,n,p') # needs sage.symbolic sage: TestSuite(krawtchouk).run() - sage: TestSuite(krawtchouk(k, x, n, p)).run() - sage: TestSuite(krawtchouk(3, x, n, p)).run() + sage: TestSuite(krawtchouk(k, x, n, p)).run() # needs sage.symbolic + sage: TestSuite(krawtchouk(3, x, n, p)).run() # needs sage.symbolic """ super().__init__(name="krawtchouk", nargs=4, latex_name="K") @@ -2708,8 +2754,8 @@ def eval_formula(self, k, x, n, p): EXAMPLES:: - sage: x,n,p = var('x,n,p') - sage: krawtchouk.eval_formula(3, x, n, p).expand().collect(x) + sage: x, n, p = var('x,n,p') # needs sage.symbolic + sage: krawtchouk.eval_formula(3, x, n, p).expand().collect(x) # needs sage.symbolic -1/6*n^3*p^3 + 1/2*n^2*p^3 - 1/3*n*p^3 - 1/2*(n*p - 2*p + 1)*x^2 + 1/6*x^3 + 1/6*(3*n^2*p^2 - 9*n*p^2 + 3*n*p + 6*p^2 - 6*p + 2)*x """ @@ -2723,7 +2769,8 @@ def _eval_(self, j, x, n, p, *args, **kwds): EXAMPLES:: - sage: k,x,n,p = var('k,x,n,p') + sage: # needs sage.symbolic + sage: k, x, n, p = var('k,x,n,p') sage: krawtchouk(3, x, 5, p).expand() -10*p^3 + 6*p^2*x - 3/2*p*x^2 + 1/6*x^3 + 3/2*p*x - 1/2*x^2 + 1/3*x sage: krawtchouk(k, x, 5, p) @@ -2733,11 +2780,11 @@ def _eval_(self, j, x, n, p, *args, **kwds): sage: krawtchouk(k, x, n, p) (-1)^k*p^k*binomial(n, k)*hypergeometric((-k, -x), (-n,), 1/p) - sage: k3_hypergeo = krawtchouk(k,x,n,p)(k=3).simplify_hypergeometric() - sage: bool(k3_hypergeo == krawtchouk(3,x,n,p)) + sage: k3_hypergeo = krawtchouk(k,x,n,p)(k=3).simplify_hypergeometric() # needs sage.symbolic + sage: bool(k3_hypergeo == krawtchouk(3,x,n,p)) # needs sage.symbolic True - sage: krawtchouk(2,x,n,p,hold=True) + sage: krawtchouk(2, x, n, p, hold=True) # needs sage.symbolic krawtchouk(2, x, n, p) """ if kwds.get('hold', False): @@ -2757,21 +2804,24 @@ def eval_recursive(self, j, x, n, p, *args, **kwds): EXAMPLES:: - sage: x,n,p = var('x,n,p') - sage: krawtchouk.eval_recursive(0,x,n,p) + sage: # needs sage.symbolic + sage: x, n, p = var('x,n,p') + sage: krawtchouk.eval_recursive(0, x, n, p) 1 - sage: krawtchouk.eval_recursive(1,x,n,p) + sage: krawtchouk.eval_recursive(1, x, n, p) -n*p + x - sage: krawtchouk.eval_recursive(2,x,n,p).collect(x) - 1/2*n^2*p^2 + 1/2*n*(p - 1)*p - n*p^2 + 1/2*n*p - 1/2*(2*n*p - 2*p + 1)*x + 1/2*x^2 - sage: bool(krawtchouk.eval_recursive(2,x,n,p) == krawtchouk(2,x,n,p)) + sage: krawtchouk.eval_recursive(2, x, n, p).collect(x) + 1/2*n^2*p^2 + 1/2*n*(p - 1)*p - n*p^2 + 1/2*n*p + - 1/2*(2*n*p - 2*p + 1)*x + 1/2*x^2 + sage: bool(krawtchouk.eval_recursive(2, x, n, p) == krawtchouk(2, x, n, p)) True - sage: bool(krawtchouk.eval_recursive(3,x,n,p) == krawtchouk(3,x,n,p)) + sage: bool(krawtchouk.eval_recursive(3, x, n, p) == krawtchouk(3, x, n, p)) True - sage: bool(krawtchouk.eval_recursive(4,x,n,p) == krawtchouk(4,x,n,p)) + sage: bool(krawtchouk.eval_recursive(4, x, n, p) == krawtchouk(4, x, n, p)) True - sage: M = matrix([[-1/2,-1],[1,0]]) - sage: krawtchouk.eval_recursive(2, M, 3, 1/2) + + sage: M = matrix([[-1/2, -1], [1, 0]]) # needs sage.modules + sage: krawtchouk.eval_recursive(2, M, 3, 1/2) # needs sage.modules [ 9/8 7/4] [-7/4 1/4] """ @@ -2804,10 +2854,10 @@ def __init__(self): EXAMPLES:: - sage: n,x,b,c = var('n,x,b,c') + sage: n, x, b, c = var('n,x,b,c') # needs sage.symbolic sage: TestSuite(meixner).run() - sage: TestSuite(meixner(3, x, b, c)).run() - sage: TestSuite(meixner(n, x, b, c)).run() + sage: TestSuite(meixner(3, x, b, c)).run() # needs sage.symbolic + sage: TestSuite(meixner(n, x, b, c)).run() # needs sage.symbolic """ super().__init__(name="meixner", nargs=4, latex_name="M") @@ -2817,8 +2867,8 @@ def eval_formula(self, n, x, b, c): EXAMPLES:: - sage: x,b,c = var('x,b,c') - sage: meixner.eval_formula(3, x, b, c).expand().collect(x) + sage: x, b, c = var('x,b,c') # needs sage.symbolic + sage: meixner.eval_formula(3, x, b, c).expand().collect(x) # needs sage.symbolic -x^3*(3/c - 3/c^2 + 1/c^3 - 1) + b^3 + 3*(b - 2*b/c + b/c^2 - 1/c - 1/c^2 + 1/c^3 + 1)*x^2 + 3*b^2 + (3*b^2 + 6*b - 3*b^2/c - 3*b/c - 3*b/c^2 - 2/c^3 + 2)*x + 2*b @@ -2837,7 +2887,8 @@ def _eval_(self, n, x, b, c, *args, **kwds): EXAMPLES:: - sage: n,x,b,c = var('n,x,b,c') + sage: # needs sage.symbolic + sage: n, x, b, c = var('n,x,b,c') sage: meixner(2, x, b, c).collect(x) -x^2*(2/c - 1/c^2 - 1) + b^2 + (2*b - 2*b/c - 1/c^2 + 1)*x + b sage: meixner(3, x, b, c).factor().collect(x) @@ -2847,16 +2898,17 @@ def _eval_(self, n, x, b, c, *args, **kwds): sage: meixner(n, x, b, c) gamma(b + n)*hypergeometric((-n, -x), (b,), -1/c + 1)/gamma(b) - sage: n3_hypergeo = meixner(n,x,b,c)(n=3).simplify_hypergeometric() + sage: # needs sage.symbolic + sage: n3_hypergeo = meixner(n, x, b, c)(n=3).simplify_hypergeometric() sage: n3_hypergeo = n3_hypergeo.simplify_full() - sage: bool(n3_hypergeo == meixner(3,x,b,c)) + sage: bool(n3_hypergeo == meixner(3, x, b, c)) True - sage: n4_hypergeo = meixner(n,x,b,c)(n=4).simplify_hypergeometric() + sage: n4_hypergeo = meixner(n, x, b, c)(n=4).simplify_hypergeometric() sage: n4_hypergeo = n4_hypergeo.simplify_full() - sage: bool(n4_hypergeo == meixner(4,x,b,c)) + sage: bool(n4_hypergeo == meixner(4, x, b, c)) True - sage: meixner(2,x,b,c,hold=True) + sage: meixner(2, x, b, c, hold=True) # needs sage.symbolic meixner(2, x, b, c) """ if kwds.get('hold', False): @@ -2877,24 +2929,25 @@ def eval_recursive(self, n, x, b, c, *args, **kwds): EXAMPLES:: - sage: x,b,c = var('x,b,c') - sage: meixner.eval_recursive(0,x,b,c) + sage: # needs sage.symbolic + sage: x, b, c = var('x,b,c') + sage: meixner.eval_recursive(0, x, b, c) 1 - sage: meixner.eval_recursive(1,x,b,c) + sage: meixner.eval_recursive(1, x, b, c) -x*(1/c - 1) + b - sage: meixner.eval_recursive(2,x,b,c).simplify_full().collect(x) + sage: meixner.eval_recursive(2, x, b, c).simplify_full().collect(x) -x^2*(2/c - 1/c^2 - 1) + b^2 + (2*b - 2*b/c - 1/c^2 + 1)*x + b - sage: bool(meixner(2,x,b,c) == meixner.eval_recursive(2,x,b,c)) + sage: bool(meixner(2, x, b, c) == meixner.eval_recursive(2, x, b, c)) True - sage: bool(meixner(3,x,b,c) == meixner.eval_recursive(3,x,b,c)) + sage: bool(meixner(3, x, b, c) == meixner.eval_recursive(3, x, b, c)) True - sage: bool(meixner(4,x,b,c) == meixner.eval_recursive(4,x,b,c)) + sage: bool(meixner(4, x, b, c) == meixner.eval_recursive(4, x, b, c)) True - sage: M = matrix([[-1/2,-1],[1,0]]) + sage: M = matrix([[-1/2, -1], [1, 0]]) sage: ret = meixner.eval_recursive(2, M, b, c).simplify_full().factor() sage: for i in range(2): # make the output polynomials in 1/c ....: for j in range(2): - ....: ret[i,j] = ret[i,j].collect(c) + ....: ret[i, j] = ret[i, j].collect(c) sage: ret [b^2 + 1/2*(2*b + 3)/c - 1/4/c^2 - 5/4 -2*b + (2*b - 1)/c + 3/2/c^2 - 1/2] [ 2*b - (2*b - 1)/c - 3/2/c^2 + 1/2 b^2 + b + 2/c - 1/c^2 - 1] @@ -2926,20 +2979,21 @@ class Func_hahn(OrthogonalFunction): We verify the orthogonality for `n = 3`:: + sage: # needs sage.symbolic sage: n = 2 - sage: a,b = SR.var('a,b') - sage: def rho(k,a,b,n): - ....: return binomial(a+k,k) * binomial(b+n-k,n-k) - sage: M = matrix([[sum(rho(k,a,b,n) - ....: * hahn(i,k,a,b,n) * hahn(j,k,a,b,n) - ....: for k in range(n+1)).expand().factor() + sage: a, b = SR.var('a,b') + sage: def rho(k, a, b, n): + ....: return binomial(a + k, k) * binomial(b + n - k, n - k) + sage: M = matrix([[sum(rho(k, a, b, n) + ....: * hahn(i, k, a, b, n) * hahn(j, k, a, b, n) + ....: for k in range(n + 1)).expand().factor() ....: for i in range(n+1)] for j in range(n+1)]) sage: M = M.factor() sage: P = rising_factorial - sage: def diag(i,a,b,n): - ....: return ((-1)^i * factorial(i) * P(b+1,i) * P(i+a+b+1,n+1) - ....: / (factorial(n) * (2*i+a+b+1) * P(-n,i) * P(a+1,i))) - sage: all(M[i,i] == diag(i,a,b,n) for i in range(3)) + sage: def diag(i, a, b, n): + ....: return ((-1)^i * factorial(i) * P(b + 1, i) * P(i + a + b + 1, n + 1) + ....: / (factorial(n) * (2*i + a + b + 1) * P(-n, i) * P(a + 1, i))) + sage: all(M[i,i] == diag(i, a, b, n) for i in range(3)) True sage: all(M[i,j] == 0 for i in range(3) for j in range(3) if i != j) True @@ -2950,10 +3004,10 @@ def __init__(self): EXAMPLES:: - sage: k,x,a,b,n = var('k,x,a,b,n') + sage: k, x, a, b, n = var('k,x,a,b,n') # needs sage.symbolic sage: TestSuite(hahn).run() - sage: TestSuite(hahn(3, x, a, b, n)).run() - sage: TestSuite(hahn(k, x, a, b, n)).run(skip="_test_category") + sage: TestSuite(hahn(3, x, a, b, n)).run() # needs sage.symbolic + sage: TestSuite(hahn(k, x, a, b, n)).run(skip="_test_category") # needs sage.symbolic """ super().__init__(name="hahn", nargs=5, latex_name="Q") @@ -2963,7 +3017,8 @@ def eval_formula(self, k, x, a, b, n): EXAMPLES:: - sage: k,x,a,b,n = var('k,x,a,b,n') + sage: # needs sage.symbolic + sage: k, x, a, b, n = var('k,x,a,b,n') sage: Q2 = hahn.eval_formula(2, x, a, b, n).simplify_full() sage: Q2.coefficient(x^2).factor() (a + b + 4)*(a + b + 3)/((a + 2)*(a + 1)*(n - 1)*n) @@ -2982,20 +3037,21 @@ def _eval_(self, k, x, a, b, n, *args, **kwds): EXAMPLES:: - sage: k,x,a,b,n = var('k,x,a,b,n') - sage: hahn(1, x, a, b, n).collect(x) + sage: k, x, a, b, n = var('k,x,a,b,n') # needs sage.symbolic + sage: hahn(1, x, a, b, n).collect(x) # needs sage.symbolic -(a + b + 2)*x/((a + 1)*n) + 1 - sage: hahn(k, x, a, b, n) + sage: hahn(k, x, a, b, n) # needs sage.symbolic hypergeometric((-k, a + b + k + 1, -x), (a + 1, -n), 1) - sage: k2_hypergeo = hahn(k,x,a,b,n)(k=2).simplify_hypergeometric() - sage: bool(k2_hypergeo == hahn(2,x,a,b,n)) + sage: # needs sage.symbolic + sage: k2_hypergeo = hahn(k, x, a, b, n)(k=2).simplify_hypergeometric() + sage: bool(k2_hypergeo == hahn(2, x, a, b, n)) True - sage: k3_hypergeo = hahn(k,x,a,b,n)(k=3).simplify_hypergeometric() - sage: bool(k3_hypergeo == hahn(3,x,a,b,n)) + sage: k3_hypergeo = hahn(k, x, a, b, n)(k=3).simplify_hypergeometric() + sage: bool(k3_hypergeo == hahn(3, x, a, b, n)) True - sage: hahn(2,x,a,b,n,hold=True) + sage: hahn(2, x, a, b, n, hold=True) # needs sage.symbolic hahn(2, x, a, b, n) """ if kwds.get('hold', False): @@ -3015,20 +3071,21 @@ def eval_recursive(self, k, x, a, b, n, *args, **kwds): EXAMPLES:: - sage: x,a,b,n = var('x,a,b,n') - sage: hahn.eval_recursive(0,x,a,b,n) + sage: # needs sage.symbolic + sage: x, a, b, n = var('x,a,b,n') + sage: hahn.eval_recursive(0, x, a, b, n) 1 - sage: hahn.eval_recursive(1,x,a,b,n) + sage: hahn.eval_recursive(1, x, a, b, n) -(a + b + 2)*x/((a + 1)*n) + 1 - sage: bool(hahn(2,x,a,b,n) == hahn.eval_recursive(2,x,a,b,n)) + sage: bool(hahn(2, x, a, b, n) == hahn.eval_recursive(2, x, a, b, n)) True - sage: bool(hahn(3,x,a,b,n) == hahn.eval_recursive(3,x,a,b,n)) + sage: bool(hahn(3, x, a, b, n) == hahn.eval_recursive(3, x, a, b, n)) True - sage: bool(hahn(4,x,a,b,n) == hahn.eval_recursive(4,x,a,b,n)) + sage: bool(hahn(4, x, a, b, n) == hahn.eval_recursive(4, x, a, b, n)) True - sage: M = matrix([[-1/2,-1],[1,0]]) - sage: ret = hahn.eval_recursive(2, M, 1, 2, n).simplify_full().factor() - sage: ret + sage: M = matrix([[-1/2, -1], [1, 0]]) # needs sage.modules + sage: ret = hahn.eval_recursive(2, M, 1, 2, n).simplify_full().factor() # needs sage.modules + sage: ret # needs sage.modules [1/4*(4*n^2 + 8*n - 19)/((n - 1)*n) 3/2*(4*n + 3)/((n - 1)*n)] [ -3/2*(4*n + 3)/((n - 1)*n) (n^2 - n - 7)/((n - 1)*n)] """ diff --git a/src/sage/functions/other.py b/src/sage/functions/other.py index 5a0f06a27f8..38276c57fbe 100644 --- a/src/sage/functions/other.py +++ b/src/sage/functions/other.py @@ -6,39 +6,37 @@ Check that gamma function imports are deprecated (:trac:`24411`):: sage: from sage.functions.other import beta - sage: beta(x, x) + sage: beta(x, x) # needs sage.symbolic doctest:warning...: DeprecationWarning: Importing beta from here is deprecated; please use "from sage.functions.gamma import beta" instead. See https://github.com/sagemath/sage/issues/24411 for details. beta(x, x) """ -from sage.misc.lazy_import import lazy_import -lazy_import('sage.functions.gamma', - ('gamma', 'log_gamma', 'gamma_inc', - 'gamma_inc_lower', 'psi', 'beta'), deprecation=24411) +import math -from sage.symbolic.function import GinacFunction, BuiltinFunction -from sage.symbolic.expression import Expression, register_symbol, symbol_table -from sage.symbolic.ring import SR, SymbolicRing +from sage.arith.misc import binomial as arith_binomial +from sage.functions.trig import arctan2 +from sage.misc.functional import sqrt +from sage.misc.lazy_import import lazy_import from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ from sage.rings.rational import Rational -from sage.rings.complex_mpfr import ComplexField -from sage.misc.latex import latex -from sage.structure.element import Element -import math - -from sage.structure.element import coercion_model - +from sage.structure.element import coercion_model, Element, Expression # avoid name conflicts with `parent` as a function parameter -from sage.structure.all import parent as s_parent +from sage.structure.element import parent as s_parent +from sage.symbolic.function import GinacFunction, BuiltinFunction +from sage.symbolic.symbols import register_symbol, symbol_table -from sage.functions.trig import arctan2 +lazy_import('sage.misc.latex', 'latex') +lazy_import('sage.rings.complex_mpfr', 'ComplexField') -from sage.arith.misc import binomial as arith_binomial +lazy_import('sage.symbolic.ring', 'SR') -from sage.misc.functional import sqrt + +lazy_import('sage.functions.gamma', + ('gamma', 'log_gamma', 'gamma_inc', + 'gamma_inc_lower', 'psi', 'beta'), deprecation=24411) class Function_abs(GinacFunction): @@ -48,14 +46,16 @@ def __init__(self): EXAMPLES:: + sage: abs(-2) + 2 + + sage: # needs sage.symbolic sage: var('x y') (x, y) sage: abs(x) abs(x) sage: abs(x^2 + y^2) abs(x^2 + y^2) - sage: abs(-2) - 2 sage: sqrt(x^2) sqrt(x^2) sage: abs(sqrt(x)) @@ -66,20 +66,21 @@ def __init__(self): sage: f = sage.functions.other.Function_abs() sage: latex(f) \mathrm{abs} - sage: latex(abs(x)) + sage: latex(abs(x)) # needs sage.symbolic {\left| x \right|} - sage: abs(x)._sympy_() + sage: abs(x)._sympy_() # needs sympy sage.symbolic Abs(x) Test pickling:: - sage: loads(dumps(abs(x))) + sage: loads(dumps(abs(x))) # needs sage.symbolic abs(x) TESTS: Check that :trac:`12588` is fixed:: + sage: # needs sage.symbolic sage: abs(pi*I) pi sage: abs(pi*I*catalan) @@ -117,7 +118,7 @@ def __init__(self): sage: abs((pi+e)*x) (pi + e)*abs(x) - sage: fricas(abs(x)).sage().derivative() # optional - fricas + sage: fricas(abs(x)).sage().derivative() # optional - fricas # needs sage.symbolic 1/2*(x + conjugate(x))/abs(x) """ GinacFunction.__init__(self, "abs", latex_name=r"\mathrm{abs}", @@ -146,9 +147,9 @@ def _eval_floor_ceil(self, x, method, bits=0, **kwds): TESTS:: - sage: numbers = [SR(10^100 + exp(-100)), SR(10^100 - exp(-100)), SR(10^100)] - sage: numbers += [-n for n in numbers] - sage: for n in numbers: + sage: numbers = [SR(10^100 + exp(-100)), SR(10^100 - exp(-100)), SR(10^100)] # needs sage.symbolic + sage: numbers += [-n for n in numbers] # needs sage.symbolic + sage: for n in numbers: # needs sage.symbolic ....: f = floor(n) ....: c = ceil(n) ....: if f == c: @@ -158,6 +159,7 @@ def _eval_floor_ceil(self, x, method, bits=0, **kwds): A test from :trac:`12121`:: + sage: # needs sage.symbolic sage: e1 = pi - continued_fraction(pi).convergent(2785) sage: e2 = e - continued_fraction(e).convergent(1500) sage: f = e1/e2 @@ -174,7 +176,7 @@ def _eval_floor_ceil(self, x, method, bits=0, **kwds): Traceback (most recent call last): ... ValueError: Calling ceil() on infinity or NaN - sage: ceil(NaN) + sage: ceil(NaN) # needs sage.symbolic Traceback (most recent call last): ... ValueError: Calling ceil() on infinity or NaN @@ -182,10 +184,10 @@ def _eval_floor_ceil(self, x, method, bits=0, **kwds): Test that elements of symbolic subrings work in the same way as elements of ``SR``, :trac:`32724`:: - sage: SCR = SR.subring(no_variables=True) - sage: floor(log(2^(3/2)) / log(2) + 1/2) + sage: SCR = SR.subring(no_variables=True) # needs sage.symbolic + sage: floor(log(2^(3/2)) / log(2) + 1/2) # needs sage.symbolic 2 - sage: floor(SCR(log(2^(-3/2)) / log(2) + 1/2)) + sage: floor(SCR(log(2^(-3/2)) / log(2) + 1/2)) # needs sage.symbolic -1 """ # First, some obvious things... @@ -224,7 +226,7 @@ def _eval_floor_ceil(self, x, method, bits=0, **kwds): # Might it be needed to simplify x? This only applies for # elements of SR (or its subrings) - need_to_simplify = isinstance(s_parent(x), SymbolicRing) + need_to_simplify = isinstance(x, Expression) # An integer which is close to x. We use this to increase precision # by subtracting this guess before converting to an interval field. @@ -320,8 +322,8 @@ def __init__(self): EXAMPLES:: - sage: a = ceil(2/5 + x) - sage: a + sage: # needs sage.symbolic + sage: a = ceil(2/5 + x); a ceil(x + 2/5) sage: a(x=4) 5 @@ -338,7 +340,7 @@ def __init__(self): :: - sage: ceil(sin(8)/sin(2)) + sage: ceil(sin(8)/sin(2)) # needs sage.symbolic 2 :: @@ -350,45 +352,45 @@ def __init__(self): :: - sage: ceil(factorial(50)/exp(1)) + sage: ceil(factorial(50)/exp(1)) # needs sage.symbolic 11188719610782480504630258070757734324011354208865721592720336801 - sage: ceil(SR(10^50 + 10^(-50))) + sage: ceil(SR(10^50 + 10^(-50))) # needs sage.symbolic 100000000000000000000000000000000000000000000000001 - sage: ceil(SR(10^50 - 10^(-50))) + sage: ceil(SR(10^50 - 10^(-50))) # needs sage.symbolic 100000000000000000000000000000000000000000000000000 Small numbers which are extremely close to an integer are hard to deal with:: - sage: ceil((33^100 + 1)^(1/100)) + sage: ceil((33^100 + 1)^(1/100)) # needs sage.symbolic Traceback (most recent call last): ... ValueError: cannot compute ceil(...) using 256 bits of precision This can be fixed by giving a sufficiently large ``bits`` argument:: - sage: ceil((33^100 + 1)^(1/100), bits=500) + sage: ceil((33^100 + 1)^(1/100), bits=500) # needs sage.symbolic Traceback (most recent call last): ... ValueError: cannot compute ceil(...) using 512 bits of precision - sage: ceil((33^100 + 1)^(1/100), bits=1000) + sage: ceil((33^100 + 1)^(1/100), bits=1000) # needs sage.symbolic 34 :: - sage: ceil(sec(e)) + sage: ceil(sec(e)) # needs sage.symbolic -1 - sage: latex(ceil(x)) + sage: latex(ceil(x)) # needs sage.symbolic \left \lceil x \right \rceil - sage: ceil(x)._sympy_() + sage: ceil(x)._sympy_() # needs sympy sage.symbolic ceiling(x) :: - sage: import numpy - sage: a = numpy.linspace(0,2,6) - sage: ceil(a) + sage: import numpy # needs numpy + sage: a = numpy.linspace(0,2,6) # needs numpy + sage: ceil(a) # needs numpy array([0., 1., 1., 2., 2., 2.]) Test pickling:: @@ -405,7 +407,7 @@ def _print_latex_(self, x): r""" EXAMPLES:: - sage: latex(ceil(x)) # indirect doctest + sage: latex(ceil(x)) # indirect doctest # needs sage.symbolic \left \lceil x \right \rceil """ return r"\left \lceil %s \right \rceil"%latex(x) @@ -419,13 +421,13 @@ def __call__(self, x, **kwds): TESTS:: - sage: ceil(SR(10^50 + 10^(-50))) + sage: ceil(SR(10^50 + 10^(-50))) # needs sage.symbolic 100000000000000000000000000000000000000000000000001 - sage: ceil(SR(10^50 - 10^(-50))) + sage: ceil(SR(10^50 - 10^(-50))) # needs sage.symbolic 100000000000000000000000000000000000000000000000000 sage: ceil(int(10^50)) 100000000000000000000000000000000000000000000000000 - sage: ceil((1725033*pi - 5419351)/(25510582*pi - 80143857)) + sage: ceil((1725033*pi - 5419351)/(25510582*pi - 80143857)) # needs sage.symbolic -2 """ return _eval_floor_ceil(self, x, "ceil", **kwds) @@ -434,12 +436,13 @@ def _eval_(self, x): """ EXAMPLES:: - sage: ceil(x).subs(x==7.5) + sage: ceil(x).subs(x==7.5) # needs sage.symbolic 8 - sage: ceil(x) + sage: ceil(x) # needs sage.symbolic ceil(x) - sage: var('x',domain='integer') + sage: # needs sage.symbolic + sage: var('x', domain='integer') x sage: ceil(x) x @@ -496,6 +499,8 @@ def __init__(self): 5 sage: type(floor(5.4)) + + sage: # needs sage.symbolic sage: var('x') x sage: a = floor(5.25 + x); a @@ -507,6 +512,7 @@ def __init__(self): :: + sage: # needs sage.symbolic sage: floor(cos(8) / cos(2)) 0 sage: floor(log(4) / log(2)) @@ -522,11 +528,11 @@ def __init__(self): :: - sage: floor(factorial(50)/exp(1)) + sage: floor(factorial(50)/exp(1)) # needs sage.symbolic 11188719610782480504630258070757734324011354208865721592720336800 - sage: floor(SR(10^50 + 10^(-50))) + sage: floor(SR(10^50 + 10^(-50))) # needs sage.symbolic 100000000000000000000000000000000000000000000000000 - sage: floor(SR(10^50 - 10^(-50))) + sage: floor(SR(10^50 - 10^(-50))) # needs sage.symbolic 99999999999999999999999999999999999999999999999999 sage: floor(int(10^50)) 100000000000000000000000000000000000000000000000000 @@ -534,27 +540,27 @@ def __init__(self): Small numbers which are extremely close to an integer are hard to deal with:: - sage: floor((33^100 + 1)^(1/100)) + sage: floor((33^100 + 1)^(1/100)) # needs sage.symbolic Traceback (most recent call last): ... ValueError: cannot compute floor(...) using 256 bits of precision This can be fixed by giving a sufficiently large ``bits`` argument:: - sage: floor((33^100 + 1)^(1/100), bits=500) + sage: floor((33^100 + 1)^(1/100), bits=500) # needs sage.symbolic Traceback (most recent call last): ... ValueError: cannot compute floor(...) using 512 bits of precision - sage: floor((33^100 + 1)^(1/100), bits=1000) + sage: floor((33^100 + 1)^(1/100), bits=1000) # needs sage.symbolic 33 :: - sage: import numpy - sage: a = numpy.linspace(0,2,6) - sage: floor(a) + sage: import numpy # needs numpy + sage: a = numpy.linspace(0,2,6) # needs numpy + sage: floor(a) # needs numpy array([0., 0., 0., 1., 1., 2.]) - sage: floor(x)._sympy_() + sage: floor(x)._sympy_() # needs sympy sage.symbolic floor(x) Test pickling:: @@ -569,7 +575,7 @@ def _print_latex_(self, x): r""" EXAMPLES:: - sage: latex(floor(x)) + sage: latex(floor(x)) # needs sage.symbolic \left \lfloor x \right \rfloor """ return r"\left \lfloor %s \right \rfloor"%latex(x) @@ -583,13 +589,13 @@ def __call__(self, x, **kwds): TESTS:: - sage: floor(SR(10^50 + 10^(-50))) + sage: floor(SR(10^50 + 10^(-50))) # needs sage.symbolic 100000000000000000000000000000000000000000000000000 - sage: floor(SR(10^50 - 10^(-50))) + sage: floor(SR(10^50 - 10^(-50))) # needs sage.symbolic 99999999999999999999999999999999999999999999999999 sage: floor(int(10^50)) 100000000000000000000000000000000000000000000000000 - sage: floor((1725033*pi - 5419351)/(25510582*pi - 80143857)) + sage: floor((1725033*pi - 5419351)/(25510582*pi - 80143857)) # needs sage.symbolic -3 """ return _eval_floor_ceil(self, x, "floor", **kwds) @@ -598,12 +604,13 @@ def _eval_(self, x): """ EXAMPLES:: - sage: floor(x).subs(x==7.5) + sage: floor(x).subs(x==7.5) # needs sage.symbolic 7 - sage: floor(x) + sage: floor(x) # needs sage.symbolic floor(x) - sage: var('x',domain='integer') + sage: # needs sage.symbolic + sage: var('x', domain='integer') x sage: floor(x) x @@ -645,17 +652,17 @@ def __init__(self): EXAMPLES:: - sage: x = SR('x') - sage: x.Order() + sage: x = SR('x') # needs sage.symbolic + sage: x.Order() # needs sage.symbolic Order(x) - sage: (x^2 + x).Order() + sage: (x^2 + x).Order() # needs sage.symbolic Order(x^2 + x) TESTS: Check that :trac:`19425` is resolved:: - sage: x.Order().operator() + sage: x.Order().operator() # needs sage.symbolic Order """ GinacFunction.__init__(self, "Order", @@ -666,6 +673,7 @@ def _sympy_(self, arg): """ EXAMPLES:: + sage: # needs sympy sage.symbolic sage: x.Order()._sympy_() O(x) sage: SR(1).Order()._sympy_() @@ -675,9 +683,9 @@ def _sympy_(self, arg): sage: exp(x).series(x==1, 3)._sympy_() E + E*(x - 1) + E*(x - 1)**2/2 + O((x - 1)**3, (x, 1)) - sage: (-(pi-x)^3).Order()._sympy_() + sage: (-(pi-x)^3).Order()._sympy_() # needs sympy sage.symbolic O((x - pi)**3, (x, pi)) - sage: cos(x).series(x==pi, 3)._sympy_() + sage: cos(x).series(x==pi, 3)._sympy_() # needs sympy sage.symbolic -1 + (pi - x)**2/2 + O((x - pi)**3, (x, pi)) """ roots = arg.solve(arg.default_variable(), algorithm='sympy', @@ -708,6 +716,8 @@ def __init__(self): sage: frac(456/123) 29/41 + + sage: # needs sage.symbolic sage: var('x') x sage: a = frac(5.4 + x); a @@ -716,7 +726,7 @@ def __init__(self): cos(8)/cos(2) sage: latex(frac(x)) \operatorname{frac}\left(x\right) - sage: frac(x)._sympy_() + sage: frac(x)._sympy_() # needs sympy frac(x) Test pickling:: @@ -732,9 +742,9 @@ def _evalf_(self, x, **kwds): """ EXAMPLES:: - sage: frac(pi).n() + sage: frac(pi).n() # needs sage.symbolic 0.141592653589793 - sage: frac(pi).n(200) + sage: frac(pi).n(200) # needs sage.symbolic 0.14159265358979323846264338327950288419716939937510582097494 """ return x - floor(x) @@ -743,9 +753,9 @@ def _eval_(self, x): """ EXAMPLES:: - sage: frac(x).subs(x==7.5) + sage: frac(x).subs(x==7.5) # needs sage.symbolic 0.500000000000000 - sage: frac(x) + sage: frac(x) # needs sage.symbolic frac(x) """ try: @@ -781,9 +791,9 @@ class Function_real_nth_root(BuiltinFunction): EXAMPLES:: - sage: real_nth_root(2, 3) + sage: real_nth_root(2, 3) # needs sage.symbolic 2^(1/3) - sage: real_nth_root(-2, 3) + sage: real_nth_root(-2, 3) # needs sage.symbolic -2^(1/3) sage: real_nth_root(8, 3) 2 @@ -804,8 +814,8 @@ class Function_real_nth_root(BuiltinFunction): Some symbolic calculus:: - sage: f = real_nth_root(x, 5)^3 - sage: f + sage: # needs sage.symbolic + sage: f = real_nth_root(x, 5)^3; f real_nth_root(x^3, 5) sage: f.diff() 3/5*x^2*real_nth_root(x^(-12), 5) @@ -822,14 +832,14 @@ def __init__(self): TESTS:: - sage: cube_root = real_nth_root(x, 3) - sage: loads(dumps(cube_root)) + sage: cube_root = real_nth_root(x, 3) # needs sage.symbolic + sage: loads(dumps(cube_root)) # needs sage.symbolic real_nth_root(x, 3) :: - sage: f = real_nth_root(x, 3) - sage: f._sympy_() + sage: f = real_nth_root(x, 3) # needs sage.symbolic + sage: f._sympy_() # needs sympy sage.symbolic Piecewise((Abs(x)**(1/3)*sign(x), Eq(im(x), 0)), (x**(1/3), True)) """ @@ -842,9 +852,9 @@ def _print_latex_(self, base, exp): r""" TESTS:: - sage: latex(real_nth_root(x, 3)) + sage: latex(real_nth_root(x, 3)) # needs sage.symbolic x^{\frac{1}{3}} - sage: latex(real_nth_root(x^2 + x, 3)) + sage: latex(real_nth_root(x^2 + x, 3)) # needs sage.symbolic {\left(x^{2} + x\right)}^{\frac{1}{3}} """ return latex(base**(1/exp)) @@ -855,7 +865,7 @@ def _evalf_(self, base, exp, parent=None): sage: real_nth_root(RDF(-2), 3) -1.25992104989487... - sage: real_nth_root(Reals(100)(2), 2) + sage: real_nth_root(Reals(100)(2), 2) # needs sage.rings.real_mpfr 1.4142135623730950488016887242 """ if hasattr(exp, 'real_part'): @@ -894,9 +904,9 @@ def _eval_(self, base, exp): """ TESTS:: - sage: real_nth_root(x, 1) + sage: real_nth_root(x, 1) # needs sage.symbolic x - sage: real_nth_root(x, 3) + sage: real_nth_root(x, 3) # needs sage.symbolic real_nth_root(x, 3) sage: real_nth_root(RIF(2), 3) @@ -919,8 +929,8 @@ def _power_(self, base, exp, power_param=None): """ TESTS:: - sage: f = real_nth_root(x, 3) - sage: f^5 + sage: f = real_nth_root(x, 3) # needs sage.symbolic + sage: f^5 # needs sage.symbolic real_nth_root(x^5, 3) """ return self(base**power_param, exp) @@ -929,6 +939,7 @@ def _derivative_(self, base, exp, diff_param=None): """ TESTS:: + sage: # needs sage.symbolic sage: f = real_nth_root(x, 3) sage: f.diff() 1/3*real_nth_root(x^(-2), 3) @@ -954,6 +965,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: arg(3+i) arctan(1/3) sage: arg(-1+i) @@ -971,6 +983,7 @@ def __init__(self): sage: arg(0) 0 + sage: # needs sage.symbolic sage: latex(arg(x)) {\rm arg}\left(x\right) sage: maxima(arg(x)) @@ -979,25 +992,25 @@ def __init__(self): atan(1/2) sage: maxima(arg(sqrt(2)+i)) atan(1/sqrt(2)) - sage: arg(x)._sympy_() + sage: arg(x)._sympy_() # needs sympy arg(x) - sage: arg(2+i) + sage: arg(2+i) # needs sage.symbolic arctan(1/2) - sage: arg(sqrt(2)+i) + sage: arg(sqrt(2)+i) # needs sage.symbolic arg(sqrt(2) + I) - sage: arg(sqrt(2)+i).simplify() + sage: arg(sqrt(2)+i).simplify() # needs sage.symbolic arctan(1/2*sqrt(2)) TESTS:: - sage: arg(0.0) + sage: arg(0.0) # needs sage.rings.complex_double 0.000000000000000 - sage: arg(3.0) + sage: arg(3.0) # needs sage.rings.complex_double 0.000000000000000 - sage: arg(-2.5) + sage: arg(-2.5) # needs sage.rings.complex_double 3.14159265358979 - sage: arg(2.0+3*i) + sage: arg(2.0+3*i) # needs sage.symbolic 0.982793723247329 """ BuiltinFunction.__init__(self, "arg", @@ -1010,6 +1023,7 @@ def _eval_(self, x): """ EXAMPLES:: + sage: # needs sage.symbolic sage: arg(3+i) arctan(1/3) sage: arg(-1+i) @@ -1043,6 +1057,7 @@ def _evalf_(self, x, parent=None, algorithm=None): """ EXAMPLES:: + sage: # needs sage.rings.complex_double sage: arg(0.0) 0.000000000000000 sage: arg(3.0) @@ -1051,19 +1066,20 @@ def _evalf_(self, x, parent=None, algorithm=None): 0.00000000000000000000000000 sage: arg(3.00000000000000000000000000).prec() 90 - sage: arg(ComplexIntervalField(90)(3)).prec() - 90 - sage: arg(ComplexIntervalField(90)(3)).parent() - Real Interval Field with 90 bits of precision - sage: arg(3.0r) - 0.0 sage: arg(RDF(3)) 0.0 sage: arg(RDF(3)).parent() Real Double Field sage: arg(-2.5) 3.14159265358979 - sage: arg(2.0+3*i) + + sage: arg(ComplexIntervalField(90)(3)).prec() # needs sage.rings.complex_interval_field + 90 + sage: arg(ComplexIntervalField(90)(3)).parent() # needs sage.rings.complex_interval_field + Real Interval Field with 90 bits of precision + sage: arg(3.0r) # needs sage.rings.real_mpfr + 0.0 + sage: arg(2.0+3*i) # needs sage.symbolic 0.982793723247329 TESTS: @@ -1071,7 +1087,7 @@ def _evalf_(self, x, parent=None, algorithm=None): Make sure that the ``_evalf_`` method works when it receives a keyword argument ``parent`` :trac:`12289`:: - sage: arg(5+I, hold=True).n() + sage: arg(5+I, hold=True).n() # needs sage.symbolic 0.197395559849881 """ try: @@ -1105,19 +1121,19 @@ def __init__(self): It is possible to prevent automatic evaluation using the ``hold`` parameter:: - sage: real_part(I,hold=True) + sage: real_part(I, hold=True) # needs sage.symbolic real_part(I) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: real_part(I,hold=True).simplify() + sage: real_part(I, hold=True).simplify() # needs sage.symbolic 0 EXAMPLES:: - sage: z = 1+2*I - sage: real(z) + sage: z = 1+2*I # needs sage.symbolic + sage: real(z) # needs sage.symbolic 1 sage: real(5/3) 5/3 @@ -1134,6 +1150,7 @@ def __init__(self): Sage can recognize some expressions as real and accordingly return the identical argument:: + sage: # needs sage.symbolic sage: SR.var('x', domain='integer').real_part() x sage: SR.var('x', domain='integer').imag_part() @@ -1152,22 +1169,22 @@ def __init__(self): sage: loads(dumps(real_part)) real_part - sage: real_part(x)._sympy_() + sage: real_part(x)._sympy_() # needs sympy sage.symbolic re(x) Check if :trac:`6401` is fixed:: - sage: latex(x.real()) + sage: latex(x.real()) # needs sage.symbolic \Re \left( x \right) - sage: f(x) = function('f')(x) - sage: latex( f(x).real()) + sage: f(x) = function('f')(x) # needs sage.symbolic + sage: latex( f(x).real()) # needs sage.symbolic \Re \left( f\left(x\right) \right) Check that some real part expansions evaluate correctly (:trac:`21614`):: - sage: real(sqrt(sin(x))).subs(x==0) + sage: real(sqrt(sin(x))).subs(x==0) # needs sage.symbolic 0 """ GinacFunction.__init__(self, "real_part", @@ -1200,36 +1217,36 @@ def __init__(self): It is possible to prevent automatic evaluation using the ``hold`` parameter:: - sage: imag_part(I,hold=True) + sage: imag_part(I, hold=True) # needs sage.symbolic imag_part(I) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: imag_part(I,hold=True).simplify() + sage: imag_part(I, hold=True).simplify() # needs sage.symbolic 1 TESTS:: - sage: z = 1+2*I - sage: imaginary(z) + sage: z = 1+2*I # needs sage.symbolic + sage: imaginary(z) # needs sage.symbolic 2 - sage: imag(z) + sage: imag(z) # needs sage.symbolic 2 sage: imag(complex(3, 4)) 4.0 sage: loads(dumps(imag_part)) imag_part - sage: imag_part(x)._sympy_() + sage: imag_part(x)._sympy_() # needs sympy sage.symbolic im(x) Check if :trac:`6401` is fixed:: - sage: latex(x.imag()) + sage: latex(x.imag()) # needs sage.symbolic \Im \left( x \right) - sage: f(x) = function('f')(x) - sage: latex( f(x).imag()) + sage: f(x) = function('f')(x) # needs sage.symbolic + sage: latex(f(x).imag()) # needs sage.symbolic \Im \left( f\left(x\right) \right) """ GinacFunction.__init__(self, "imag_part", @@ -1267,21 +1284,22 @@ def __init__(self): It is possible to prevent automatic evaluation using the ``hold`` parameter:: - sage: conjugate(I,hold=True) + sage: conjugate(I, hold=True) # needs sage.symbolic conjugate(I) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: conjugate(I,hold=True).simplify() + sage: conjugate(I, hold=True).simplify() # needs sage.symbolic -I TESTS:: + sage: # needs sage.symbolic sage: x,y = var('x,y') sage: x.conjugate() conjugate(x) - sage: _._sympy_() + sage: _._sympy_() # needs sympy conjugate(x) sage: latex(conjugate(x)) \overline{x} @@ -1300,6 +1318,7 @@ def __init__(self): Check if :trac:`8755` is fixed:: + sage: # needs sage.symbolic sage: conjugate(sqrt(-3)) conjugate(sqrt(-3)) sage: conjugate(sqrt(3)) @@ -1308,14 +1327,15 @@ def __init__(self): conjugate(sqrt(x)) sage: conjugate(x^2) conjugate(x)^2 - sage: var('y',domain='positive') + sage: var('y', domain='positive') y sage: conjugate(sqrt(y)) sqrt(y) Check if :trac:`10964` is fixed:: - sage: z= I*sqrt(-3); z + sage: # needs sage.symbolic + sage: z = I*sqrt(-3); z I*sqrt(-3) sage: conjugate(z) -I*conjugate(sqrt(-3)) @@ -1326,8 +1346,8 @@ def __init__(self): Check that sums are handled correctly:: - sage: y = var('y', domain='real') - sage: conjugate(y + I) + sage: y = var('y', domain='real') # needs sage.symbolic + sage: conjugate(y + I) # needs sage.symbolic y - I Test pickling:: @@ -1352,7 +1372,7 @@ def __init__(self): INPUT: - - ``n`` - a non-negative integer, a complex number (except negative + - ``n`` -- a non-negative integer, a complex number (except negative integers) or any symbolic expression @@ -1369,6 +1389,7 @@ def __init__(self): sage: factorial(6) == 6*5*4*3*2 True + sage: # needs sage.symbolic sage: x = SR.var('x') sage: f = factorial(x + factorial(x)); f factorial(x + factorial(x)) @@ -1379,24 +1400,24 @@ def __init__(self): To prevent automatic evaluation use the ``hold`` argument:: - sage: factorial(5, hold=True) + sage: factorial(5, hold=True) # needs sage.symbolic factorial(5) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: factorial(5, hold=True).simplify() + sage: factorial(5, hold=True).simplify() # needs sage.symbolic 120 We can also give input other than nonnegative integers. For other nonnegative numbers, the :func:`sage.functions.gamma.gamma` function is used:: - sage: factorial(1/2) + sage: factorial(1/2) # needs sage.symbolic 1/2*sqrt(pi) - sage: factorial(3/4) + sage: factorial(3/4) # needs sage.symbolic gamma(7/4) - sage: factorial(2.3) + sage: factorial(2.3) # needs sage.symbolic 2.68343738195577 But negative input always fails:: @@ -1408,9 +1429,9 @@ def __init__(self): And very large integers remain unevaluated:: - sage: factorial(2**64) + sage: factorial(2**64) # needs sage.symbolic factorial(18446744073709551616) - sage: SR(2**64).factorial() + sage: SR(2**64).factorial() # needs sage.symbolic factorial(18446744073709551616) TESTS: @@ -1418,6 +1439,7 @@ def __init__(self): We verify that we can convert this function to Maxima and bring it back into Sage.:: + sage: # needs sage.symbolic sage: z = var('z') sage: factorial._maxima_init_() 'factorial' @@ -1425,17 +1447,18 @@ def __init__(self): factorial(_SAGE_VAR_z) sage: _.sage() factorial(z) - sage: _._sympy_() + sage: _._sympy_() # needs sympy factorial(z) sage: k = var('k') sage: factorial(k) factorial(k) - sage: factorial(3.14) + sage: factorial(3.14) # needs sage.symbolic 7.173269190187... Test latex typesetting:: + sage: # needs sage.symbolic sage: latex(factorial(x)) x! sage: latex(factorial(2*x)) @@ -1454,6 +1477,7 @@ def __init__(self): Check that :trac:`11539` is fixed:: + sage: # needs sage.symbolic sage: (factorial(x) == 0).simplify() factorial(x) == 0 sage: maxima(factorial(x) == 0).sage() @@ -1464,8 +1488,8 @@ def __init__(self): Check that :trac:`16166` is fixed:: - sage: RBF = RealBallField(53) - sage: factorial(RBF(4.2)) # abs tol 1e-13 + sage: RBF = RealBallField(53) # needs sage.libs.flint + sage: factorial(RBF(4.2)) # abs tol 1e-13 # needs sage.libs.flint [32.5780960503314 +/- 6.06e-14] Test pickling:: @@ -1490,6 +1514,7 @@ def _eval_(self, x): EXAMPLES:: + sage: # needs sage.symbolic sage: k = var('k') sage: k.factorial() factorial(k) @@ -1508,14 +1533,14 @@ def _eval_(self, x): Check that :trac:`25421` is fixed:: - sage: factorial(RBF(2)**64) + sage: factorial(RBF(2)**64) # needs sage.libs.flint [+/- 2.30e+347382171326740403407] Check that :trac:`26749` is fixed:: - sage: factorial(float(3.2)) # abs tol 1e-14 + sage: factorial(float(3.2)) # abs tol 1e-14 # needs sage.symbolic 7.7566895357931776 - sage: type(factorial(float(3.2))) + sage: type(factorial(float(3.2))) # needs sage.symbolic """ if isinstance(x, (int, Integer)): @@ -1532,6 +1557,7 @@ def _eval_(self, x): from sage.functions.gamma import gamma return gamma(x + 1) + factorial = Function_factorial() @@ -1564,40 +1590,42 @@ def __init__(self): EXAMPLES:: - sage: binomial(5,2) + sage: # needs sage.symbolic + sage: binomial(5, 2) 10 - sage: binomial(2,0) + sage: binomial(2, 0) 1 - sage: binomial(1/2, 0) + sage: binomial(1/2, 0) # needs sage.libs.pari 1 - sage: binomial(3,-1) + sage: binomial(3, -1) 0 - sage: binomial(20,10) + sage: binomial(20, 10) 184756 sage: binomial(-2, 5) -6 - sage: binomial(RealField()('2.5'), 2) - 1.87500000000000 - sage: n=var('n'); binomial(n,2) + sage: n = var('n'); binomial(n, 2) 1/2*(n - 1)*n - sage: n=var('n'); binomial(n,n) + sage: n = var('n'); binomial(n, n) 1 - sage: n=var('n'); binomial(n,n-1) + sage: n = var('n'); binomial(n, n - 1) n sage: binomial(2^100, 2^100) 1 + sage: binomial(RealField()('2.5'), 2) # needs sage.rings.real_mpfr + 1.87500000000000 + :: - sage: k, i = var('k,i') - sage: binomial(k,i) + sage: k, i = var('k,i') # needs sage.symbolic + sage: binomial(k,i) # needs sage.symbolic binomial(k, i) We can use a ``hold`` parameter to prevent automatic evaluation:: - sage: SR(5).binomial(3, hold=True) + sage: SR(5).binomial(3, hold=True) # needs sage.symbolic binomial(5, 3) - sage: SR(5).binomial(3, hold=True).simplify() + sage: SR(5).binomial(3, hold=True).simplify() # needs sage.symbolic 10 TESTS: @@ -1607,12 +1635,13 @@ def __init__(self): :: - sage: n,k = var('n,k') + sage: # needs sage.symbolic + sage: n, k = var('n,k') sage: maxima(binomial(n,k)) binomial(_SAGE_VAR_n,_SAGE_VAR_k) sage: _.sage() binomial(n, k) - sage: _._sympy_() + sage: _._sympy_() # needs sympy binomial(n, k) sage: binomial._maxima_init_() 'binomial' @@ -1620,19 +1649,19 @@ def __init__(self): For polynomials:: sage: y = polygen(QQ, 'y') - sage: binomial(y, 2).parent() + sage: binomial(y, 2).parent() # needs sage.symbolic Univariate Polynomial Ring in y over Rational Field :trac:`16726`:: - sage: binomial(CIF(1), 2) + sage: binomial(CIF(1), 2) # needs sage.symbolic 0 - sage: binomial(CIF(3), 2) + sage: binomial(CIF(3), 2) # needs sage.symbolic 3 Test pickling:: - sage: loads(dumps(binomial(n,k))) + sage: loads(dumps(binomial(n, k))) # needs sage.symbolic binomial(n, k) """ GinacFunction.__init__(self, "binomial", nargs=2, preserved_arg=1, @@ -1649,6 +1678,7 @@ def _binomial_sym(self, n, k): EXAMPLES:: + sage: # needs sage.symbolic sage: binomial._binomial_sym(x, 3) 1/6*(x - 1)*(x - 2)*x sage: binomial._binomial_sym(x, x) @@ -1657,7 +1687,6 @@ def _binomial_sym(self, n, k): ValueError: second argument must be an integer sage: binomial._binomial_sym(x, SR(3)) 1/6*(x - 1)*(x - 2)*x - sage: binomial._binomial_sym(x, 0r) 1 sage: binomial._binomial_sym(x, -1) @@ -1691,8 +1720,10 @@ def _eval_(self, n, k): 10 sage: type(binomial._eval_(5, 3)) - sage: type(binomial._eval_(5., 3)) + sage: type(binomial._eval_(5., 3)) # needs sage.rings.real_mpfr + + sage: # needs sage.symbolic sage: binomial._eval_(x, 3) 1/6*(x - 1)*(x - 2)*x sage: binomial._eval_(x, x-2) @@ -1726,17 +1757,18 @@ def _evalf_(self, n, k, parent=None, algorithm=None): 10.0 sage: type(binomial._evalf_(5.r, 3)) <... 'float'> - sage: binomial._evalf_(1/2,1/1) + sage: binomial._evalf_(1/2, 1/1) # needs sage.libs.pari 1/2 - sage: binomial._evalf_(10^20+1/1,10^20) + sage: binomial._evalf_(10^20 + 1/1, 10^20) 100000000000000000001 - sage: binomial._evalf_(SR(10**7),10**7) + sage: binomial._evalf_(SR(10**7), 10**7) # needs sage.symbolic 1 - sage: binomial._evalf_(3/2,SR(1/1)) + sage: binomial._evalf_(3/2, SR(1/1)) # needs sage.symbolic 3/2 """ return arith_binomial(n, k) + binomial = Function_binomial() @@ -1747,9 +1779,9 @@ class Function_sum(BuiltinFunction): EXAMPLES:: sage: from sage.functions.other import symbolic_sum as ssum - sage: r = ssum(x, x, 1, 10); r + sage: r = ssum(x, x, 1, 10); r # needs sage.symbolic sum(x, x, 1, 10) - sage: r.unhold() + sage: r.unhold() # needs sage.symbolic 55 """ def __init__(self): @@ -1757,7 +1789,7 @@ def __init__(self): EXAMPLES:: sage: from sage.functions.other import symbolic_sum as ssum - sage: maxima(ssum(x, x, 1, 10)) + sage: maxima(ssum(x, x, 1, 10)) # needs sage.symbolic 55 """ BuiltinFunction.__init__(self, "sum", nargs=4, @@ -1768,7 +1800,7 @@ def _print_latex_(self, x, var, a, b): EXAMPLES:: sage: from sage.functions.other import symbolic_sum as ssum - sage: latex(ssum(x^2, x, 1, 10)) + sage: latex(ssum(x^2, x, 1, 10)) # needs sage.symbolic {\sum_{x=1}^{10} x^{2}} """ return r"{{\sum_{{{}={}}}^{{{}}} {}}}".format(latex(var), latex(a), @@ -1780,20 +1812,21 @@ def _sympy_(self, term, k, a, n): EXAMPLES:: + sage: # needs sage.symbolic sage: var('k, n') (k, n) - sage: s = sum(k, k, 1, n, hold=True) - sage: s + sage: s = sum(k, k, 1, n, hold=True); s sum(k, k, 1, n) - sage: s._sympy_() # indirect test + sage: s._sympy_() # indirect test # needs sympy Sum(k, (k, 1, n)) - sage: s._sympy_().doit() + sage: s._sympy_().doit() # needs sympy n**2/2 + n/2 """ import sympy return sympy.Sum(term, (k, a, n)) + symbolic_sum = Function_sum() @@ -1804,24 +1837,25 @@ class Function_prod(BuiltinFunction): EXAMPLES:: sage: from sage.functions.other import symbolic_product as sprod - sage: r = sprod(x, x, 1, 10); r + sage: r = sprod(x, x, 1, 10); r # needs sage.symbolic product(x, x, 1, 10) - sage: r.unhold() + sage: r.unhold() # needs sage.symbolic 3628800 """ def __init__(self): """ EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.functions.other import symbolic_product as sprod sage: _ = var('m n', domain='integer') sage: r = maxima(sprod(sin(m), m, 1, n)).sage(); r product(sin(m), m, 1, n) sage: isinstance(r.operator(), sage.functions.other.Function_prod) True - sage: r = sympy(sprod(sin(m), m, 1, n)).sage(); r # known bug + sage: r = sympy(sprod(sin(m), m, 1, n)).sage(); r # known bug # needs sympy product(sin(m), m, 1, n) - sage: isinstance(r.operator(), # known bug + sage: isinstance(r.operator(), # known bug # needs sympy ....: sage.functions.other.Function_prod) True sage: giac(sprod(m, m, 1, n)).sage() @@ -1836,7 +1870,7 @@ def _print_latex_(self, x, var, a, b): EXAMPLES:: sage: from sage.functions.other import symbolic_product as sprod - sage: latex(sprod(x^2, x, 1, 10)) + sage: latex(sprod(x^2, x, 1, 10)) # needs sage.symbolic {\prod_{x=1}^{10} x^{2}} """ return r"{{\prod_{{{}={}}}^{{{}}} {}}}".format(latex(var), latex(a), @@ -1848,10 +1882,10 @@ def _sympy_(self, term, k, a, n): EXAMPLES:: - sage: var('k, n') + sage: var('k, n') # needs sage.symbolic (k, n) - sage: p = product(k^2+k+1,k,1,n, hold=True) - sage: p._sympy_() # indirect test + sage: p = product(k^2 + k + 1, k, 1, n, hold=True) # needs sympy sage.symbolic + sage: p._sympy_() # indirect test # needs sympy sage.symbolic Product(k**2 + k + 1, (k, 1, n)) """ import sympy @@ -1867,11 +1901,12 @@ class Function_limit(BuiltinFunction): This function is called to create formal wrappers of limits that Maxima can't compute:: - sage: a = lim(exp(x^2)*(1-erf(x)), x=infinity); a + sage: a = lim(exp(x^2)*(1-erf(x)), x=infinity); a # needs sage.symbolic -limit((erf(x) - 1)*e^(x^2), x, +Infinity) EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.functions.other import symbolic_limit as slimit sage: slimit(1/x, x, +oo) limit(1/x, x, +Infinity) @@ -1889,7 +1924,7 @@ def __init__(self): EXAMPLES:: sage: from sage.functions.other import symbolic_limit as slimit - sage: maxima(slimit(1/x, x, +oo)) + sage: maxima(slimit(1/x, x, +oo)) # needs sage.symbolic 0 """ BuiltinFunction.__init__(self, "limit", nargs=0, @@ -1909,6 +1944,7 @@ def _print_latex_(self, ex, var, to, direction=''): r""" EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.functions.other import symbolic_limit as slimit sage: var('x,a') (x, a) @@ -1923,6 +1959,7 @@ def _print_latex_(self, ex, var, to, direction=''): When one-sided limits are converted back from maxima, the direction argument becomes a symbolic variable. We check if typesetting these works:: + sage: # needs sage.symbolic sage: from sage.functions.other import symbolic_limit as slimit sage: var('minus,plus') (minus, plus) @@ -1941,12 +1978,13 @@ def _print_latex_(self, ex, var, to, direction=''): Check if :trac:`13181` is fixed:: + sage: # needs sage.symbolic sage: t = var('t') - sage: latex(limit(exp_integral_e(1/2, I*t - I*x)*sqrt(-t + x),t=x,dir='-')) + sage: latex(limit(exp_integral_e(1/2, I*t - I*x)*sqrt(-t + x), t=x, dir='-')) \lim_{t \to x^-}\, \sqrt{-t + x} E_{\frac{1}{2}}\left(i \, t - i \, x\right) - sage: latex(limit(exp_integral_e(1/2, I*t - I*x)*sqrt(-t + x),t=x,dir='+')) + sage: latex(limit(exp_integral_e(1/2, I*t - I*x)*sqrt(-t + x), t=x, dir='+')) \lim_{t \to x^+}\, \sqrt{-t + x} E_{\frac{1}{2}}\left(i \, t - i \, x\right) - sage: latex(limit(exp_integral_e(1/2, I*t - I*x)*sqrt(-t + x),t=x)) + sage: latex(limit(exp_integral_e(1/2, I*t - I*x)*sqrt(-t + x), t=x)) \lim_{t \to x}\, \sqrt{-t + x} E_{\frac{1}{2}}\left(i \, t - i \, x\right) """ if repr(direction) == 'minus': @@ -1972,6 +2010,7 @@ class Function_cases(GinacFunction): EXAMPLES:: + sage: # needs sage.symbolic sage: ex = cases([(x==0, pi), (True, 0)]); ex cases(((x == 0, pi), (1, 0))) sage: ex.subs(x==0) @@ -1986,9 +2025,10 @@ class Function_cases(GinacFunction): The first encountered default is used, as well as the first relation that can be trivially decided:: - sage: cases(((True, pi), (True, 0))) + sage: cases(((True, pi), (True, 0))) # needs sage.symbolic pi + sage: # needs sage.symbolic sage: _ = var('y') sage: ex = cases(((x==0, pi), (y==1, 0))); ex cases(((x == 0, pi), (y == 1, 0))) @@ -2010,7 +2050,7 @@ def __call__(self, l, **kwargs): """ EXAMPLES:: - sage: ex = cases([(x==0, pi), (True, 0)]); ex + sage: ex = cases([(x==0, pi), (True, 0)]); ex # needs sage.symbolic cases(((x == 0, pi), (1, 0))) TESTS:: @@ -2020,7 +2060,7 @@ def __call__(self, l, **kwargs): ... TypeError: ...__call__() missing 1 required positional argument: 'l' - sage: cases(x) + sage: cases(x) # needs sage.symbolic Traceback (most recent call last): ... RuntimeError: cases argument not a sequence @@ -2032,17 +2072,16 @@ def _print_latex_(self, l, **kwargs): r""" EXAMPLES:: - sage: ex = cases([(x==0, pi), (True, 0)]); ex + sage: ex = cases([(x==0, pi), (True, 0)]); ex # needs sage.symbolic cases(((x == 0, pi), (1, 0))) - sage: latex(ex) + sage: latex(ex) # needs sage.symbolic \begin{cases}{\pi} & {x = 0}\\{0} & {1}\end{cases} TESTS: Verify that :trac:`25624` is fixed:: - sage: L = latex(cases([(x == 0, 0), (1, 1)])) - sage: L + sage: L = latex(cases([(x == 0, 0), (1, 1)])); L # needs sage.symbolic \begin{cases}{0} & {x = 0}\\{1} & {1}\end{cases} """ if not isinstance(l, (list, tuple)): @@ -2063,10 +2102,9 @@ def _sympy_(self, l): EXAMPLES:: - sage: ex = cases(((x<0, pi), (x==1, 1), (True, 0))) - sage: assert ex == ex._sympy_()._sage_() + sage: ex = cases(((x<0, pi), (x==1, 1), (True, 0))) # needs sage.symbolic + sage: assert ex == ex._sympy_()._sage_() # needs sympy sage.symbolic """ - from sage.symbolic.ring import SR from sympy import Piecewise as pw args = [] for tup in l.operands(): @@ -2094,6 +2132,7 @@ class Function_crootof(BuiltinFunction): EXAMPLES:: + sage: # needs sage.symbolic sage: c = complex_root_of(x^6 + x + 1, 1); c complex_root_of(x^6 + x + 1, 1) sage: c.n() @@ -2118,6 +2157,7 @@ def _eval_(self, poly, index): """ TESTS:: + sage: # needs sage.symbolic sage: _ = var('y') sage: complex_root_of(1, 1) Traceback (most recent call last): @@ -2143,9 +2183,9 @@ def _evalf_(self, poly, index, parent=None, algorithm=None): """ EXAMPLES:: - sage: complex_root_of(x^2-2, 1).n() + sage: complex_root_of(x^2 - 2, 1).n() # needs sage.symbolic 1.41421356237309 - sage: complex_root_of(x^2-2, 3).n() + sage: complex_root_of(x^2 - 2, 3).n() # needs sage.symbolic Traceback (most recent call last): ... IndexError: root index out of [-2, 1] range, got 3 @@ -2154,9 +2194,9 @@ def _evalf_(self, poly, index, parent=None, algorithm=None): Check that low precision is handled (:trac:`24378`):: - sage: complex_root_of(x^8-1, 7).n(2) + sage: complex_root_of(x^8 - 1, 7).n(2) # needs sage.symbolic 0.75 + 0.75*I - sage: complex_root_of(x^8-1, 7).n(20) + sage: complex_root_of(x^8 - 1, 7).n(20) # needs sage.symbolic 0.70711 + 0.70711*I """ from sympy.core.evalf import prec_to_dps @@ -2176,12 +2216,13 @@ class Function_elementof(BuiltinFunction): Formal set membership function that is only accessible internally. This function is called to express a set membership statement, - usually as part of a solution set returned by ``solve()``. + usually as part of a solution set returned by :func:`solve`. See :class:`sage.sets.set.Set` and :class:`sage.sets.real_set.RealSet` for possible set arguments. EXAMPLES:: + sage: # needs sage.symbolic sage: from sage.functions.other import element_of sage: element_of(x, SR(ZZ)) element_of(x, Integer Ring) @@ -2208,9 +2249,9 @@ def _eval_(self, x, s): EXAMPLES:: sage: from sage.functions.other import element_of - sage: element_of(x, SR(RealSet(-oo, oo))) + sage: element_of(x, SR(RealSet(-oo, oo))) # needs sage.symbolic element_of(x, (-oo, +oo)) - sage: element_of(x, 0) + sage: element_of(x, 0) # needs sage.symbolic Traceback (most recent call last): ... ValueError: not a set: 0 @@ -2234,9 +2275,9 @@ def _print_latex_(self, ex, s): EXAMPLES:: sage: from sage.functions.other import element_of - sage: latex(element_of(x, SR(ZZ))) + sage: latex(element_of(x, SR(ZZ))) # needs sage.symbolic x \in \Bold{Z} - sage: latex(element_of(x, SR(Set([4,6,8])))) + sage: latex(element_of(x, SR(Set([4,6,8])))) # needs sage.symbolic x \in \left\{8, 4, 6\right\} """ return r"{} \in {}".format(latex(ex), latex(s)) diff --git a/src/sage/functions/piecewise.py b/src/sage/functions/piecewise.py index 6955f6209eb..ff3851a1776 100644 --- a/src/sage/functions/piecewise.py +++ b/src/sage/functions/piecewise.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.symbolic r""" Piecewise functions @@ -71,11 +71,12 @@ # https://www.gnu.org/licenses/ # **************************************************************************** - -from sage.symbolic.function import BuiltinFunction -from sage.sets.real_set import RealSet -from sage.symbolic.ring import SR +from sage.misc.lazy_import import lazy_import from sage.rings.infinity import minus_infinity, infinity +from sage.sets.real_set import RealSet +from sage.symbolic.function import BuiltinFunction + +lazy_import('sage.symbolic.ring', 'SR') class PiecewiseFunction(BuiltinFunction): @@ -756,17 +757,22 @@ def integral(self, parameters, variable, x=None, a=None, b=None, definite=False, sage: f2(x) = 3 - x sage: f = piecewise([[(-2, 0), f1], [(0, 3), f2]]) sage: f.integral() - piecewise(x|-->2*x + 4 on (-2, 0), x|-->-1/2*x^2 + 3*x + 4 on (0, 3); x) + piecewise(x|-->2*x + 4 on (-2, 0), + x|-->-1/2*x^2 + 3*x + 4 on (0, 3); x) sage: f1(y) = -1 sage: f2(y) = y + 3 sage: f3(y) = -y - 1 sage: f4(y) = y^2 - 1 sage: f5(y) = 3 - sage: f = piecewise([[[-4,-3],f1],[(-3,-2),f2],[[-2,0],f3],[(0,2),f4],[[2,3],f5]]) - sage: F = f.integral(y) - sage: F - piecewise(y|-->-y - 4 on [-4, -3], y|-->1/2*y^2 + 3*y + 7/2 on (-3, -2), y|-->-1/2*y^2 - y - 1/2 on [-2, 0], y|-->1/3*y^3 - y - 1/2 on (0, 2), y|-->3*y - 35/6 on [2, 3]; y) + sage: f = piecewise([[[-4,-3],f1], [(-3,-2),f2], [[-2,0],f3], + ....: [(0,2),f4], [[2,3],f5]]) + sage: F = f.integral(y); F + piecewise(y|-->-y - 4 on [-4, -3], + y|-->1/2*y^2 + 3*y + 7/2 on (-3, -2), + y|-->-1/2*y^2 - y - 1/2 on [-2, 0], + y|-->1/3*y^3 - y - 1/2 on (0, 2), + y|-->3*y - 35/6 on [2, 3]; y) Ensure results are consistent with FTC:: @@ -792,7 +798,9 @@ def integral(self, parameters, variable, x=None, a=None, b=None, definite=False, sage: f3(y) = 3 sage: f = piecewise([[(-infinity, -3), f1], [(-3, 0), f2], [(0, infinity), f3]]) sage: f.integral() - piecewise(y|-->1/3*y^3 + 3*y^2 + 9*y + 9 on (-oo, -3), y|-->1/2*y^2 + 3*y + 9/2 on (-3, 0), y|-->3*y + 9/2 on (0, +oo); y) + piecewise(y|-->1/3*y^3 + 3*y^2 + 9*y + 9 on (-oo, -3), + y|-->1/2*y^2 + 3*y + 9/2 on (-3, 0), + y|-->3*y + 9/2 on (0, +oo); y) :: @@ -934,33 +942,51 @@ def convolution(self, parameters, variable, other): EXAMPLES:: sage: x = PolynomialRing(QQ,'x').gen() - sage: f = piecewise([[[0,1],1]]) ## example 0 + sage: f = piecewise([[[0,1],1]]) ## example 0 sage: g = f.convolution(f); g piecewise(x|-->x on (0, 1], x|-->-x + 2 on (1, 2]; x) sage: h = f.convolution(g); h - piecewise(x|-->1/2*x^2 on (0, 1], x|-->-x^2 + 3*x - 3/2 on (1, 2], x|-->1/2*x^2 - 3*x + 9/2 on (2, 3]; x) - sage: f = piecewise([[(0,1),1],[(1,2),2],[(2,3),1]]) ## example 1 + piecewise(x|-->1/2*x^2 on (0, 1], + x|-->-x^2 + 3*x - 3/2 on (1, 2], + x|-->1/2*x^2 - 3*x + 9/2 on (2, 3]; x) + sage: f = piecewise([[(0,1),1], [(1,2),2], [(2,3),1]]) ## example 1 sage: g = f.convolution(f) sage: h = f.convolution(g); h - piecewise(x|-->1/2*x^2 on (0, 1], x|-->2*x^2 - 3*x + 3/2 on (1, 3], x|-->-2*x^2 + 21*x - 69/2 on (3, 4], x|-->-5*x^2 + 45*x - 165/2 on (4, 5], x|-->-2*x^2 + 15*x - 15/2 on (5, 6], x|-->2*x^2 - 33*x + 273/2 on (6, 8], x|-->1/2*x^2 - 9*x + 81/2 on (8, 9]; x) - sage: f = piecewise([[(-1,1),1]]) ## example 2 + piecewise(x|-->1/2*x^2 on (0, 1], + x|-->2*x^2 - 3*x + 3/2 on (1, 3], + x|-->-2*x^2 + 21*x - 69/2 on (3, 4], + x|-->-5*x^2 + 45*x - 165/2 on (4, 5], + x|-->-2*x^2 + 15*x - 15/2 on (5, 6], + x|-->2*x^2 - 33*x + 273/2 on (6, 8], + x|-->1/2*x^2 - 9*x + 81/2 on (8, 9]; x) + sage: f = piecewise([[(-1,1),1]]) ## example 2 sage: g = piecewise([[(0,3),x]]) sage: f.convolution(g) - piecewise(x|-->1/2*x^2 + x + 1/2 on (-1, 1], x|-->2*x on (1, 2], x|-->-1/2*x^2 + x + 4 on (2, 4]; x) - sage: g = piecewise([[(0,3),1],[(3,4),2]]) + piecewise(x|-->1/2*x^2 + x + 1/2 on (-1, 1], + x|-->2*x on (1, 2], + x|-->-1/2*x^2 + x + 4 on (2, 4]; x) + sage: g = piecewise([[(0,3),1], [(3,4),2]]) sage: f.convolution(g) - piecewise(x|-->x + 1 on (-1, 1], x|-->2 on (1, 2], x|-->x on (2, 3], x|-->-x + 6 on (3, 4], x|-->-2*x + 10 on (4, 5]; x) + piecewise(x|-->x + 1 on (-1, 1], + x|-->2 on (1, 2], + x|-->x on (2, 3], + x|-->-x + 6 on (3, 4], + x|-->-2*x + 10 on (4, 5]; x) Check that the bugs raised in :trac:`12123` are fixed:: sage: f = piecewise([[(-2, 2), 2]]) sage: g = piecewise([[(0, 2), 3/4]]) sage: f.convolution(g) - piecewise(x|-->3/2*x + 3 on (-2, 0], x|-->3 on (0, 2], x|-->-3/2*x + 6 on (2, 4]; x) + piecewise(x|-->3/2*x + 3 on (-2, 0], + x|-->3 on (0, 2], + x|-->-3/2*x + 6 on (2, 4]; x) sage: f = piecewise([[(-1, 1), 1]]) sage: g = piecewise([[(0, 1), x], [(1, 2), -x + 2]]) sage: f.convolution(g) - piecewise(x|-->1/2*x^2 + x + 1/2 on (-1, 0], x|-->-1/2*x^2 + x + 1/2 on (0, 2], x|-->1/2*x^2 - 3*x + 9/2 on (2, 3]; x) + piecewise(x|-->1/2*x^2 + x + 1/2 on (-1, 0], + x|-->-1/2*x^2 + x + 1/2 on (0, 2], + x|-->1/2*x^2 - 3*x + 9/2 on (2, 3]; x) """ from sage.symbolic.integration.integral import definite_integral f = self @@ -1014,11 +1040,14 @@ def trapezoid(self, parameters, variable, N): sage: f = piecewise([[[0,1], x^2], [RealSet.open_closed(1,2), 5-x^2]]) sage: f.trapezoid(2) - piecewise(x|-->1/2*x on (0, 1/2), x|-->3/2*x - 1/2 on (1/2, 1), x|-->7/2*x - 5/2 on (1, 3/2), x|-->-7/2*x + 8 on (3/2, 2); x) - sage: f = piecewise([[[-1,1], 1-x^2]]) + piecewise(x|-->1/2*x on (0, 1/2), + x|-->3/2*x - 1/2 on (1/2, 1), + x|-->7/2*x - 5/2 on (1, 3/2), + x|-->-7/2*x + 8 on (3/2, 2); x) + sage: f = piecewise([[[-1,1], 1 - x^2]]) sage: f.trapezoid(4).integral(definite=True) 5/4 - sage: f = piecewise([[[-1,1], 1/2+x-x^3]]) ## example 3 + sage: f = piecewise([[[-1,1], 1/2 + x - x^3]]) ## example 3 sage: f.trapezoid(6).integral(definite=True) 1 @@ -1031,7 +1060,10 @@ def trapezoid(self, parameters, variable, N): sage: f2 = 5-y^2 sage: f = piecewise([[[0,1],f1], [RealSet.open_closed(1,2),f2]]) sage: f.trapezoid(2) - piecewise(y|-->1/2*y on (0, 1/2), y|-->3/2*y - 1/2 on (1/2, 1), y|-->7/2*y - 5/2 on (1, 3/2), y|-->-7/2*y + 8 on (3/2, 2); y) + piecewise(y|-->1/2*y on (0, 1/2), + y|-->3/2*y - 1/2 on (1/2, 1), + y|-->7/2*y - 5/2 on (1, 3/2), + y|-->-7/2*y + 8 on (3/2, 2); y) """ def func(x0, x1): f0, f1 = self(x0), self(x1) @@ -1066,7 +1098,7 @@ def laplace(self, parameters, variable, x='x', s='t'): EXAMPLES:: sage: x, s, w = var('x, s, w') - sage: f = piecewise([[(0,1),1],[[1,2], 1-x]]) + sage: f = piecewise([[(0,1),1], [[1,2], 1 - x]]) sage: f.laplace(x, s) -e^(-s)/s + (s + 1)*e^(-2*s)/s^2 + 1/s - e^(-s)/s^2 sage: f.laplace(x, w) @@ -1075,7 +1107,7 @@ def laplace(self, parameters, variable, x='x', s='t'): :: sage: y, t = var('y, t') - sage: f = piecewise([[[1,2], 1-y]]) + sage: f = piecewise([[[1,2], 1 - y]]) sage: f.laplace(y, t) (t + 1)*e^(-2*t)/t^2 - e^(-t)/t^2 @@ -1085,7 +1117,7 @@ def laplace(self, parameters, variable, x='x', s='t'): sage: t = var('t') sage: f1(t) = -t sage: f2(t) = 2 - sage: f = piecewise([[[0,1],f1],[(1,infinity),f2]]) + sage: f = piecewise([[[0,1],f1], [(1,infinity),f2]]) sage: f.laplace(t,s) (s + 1)*e^(-s)/s^2 + 2*e^(-s)/s - 1/s^2 """ @@ -1151,8 +1183,8 @@ def fourier_series_cosine_coefficient(self, parameters, more than one period, the half-period must be passed as the second argument; for instance:: - sage: f2 = piecewise([((0,1), x), ((1,2), 2-x), - ....: ((2,3), x-2), ((3,4), 2-(x-2))]) + sage: f2 = piecewise([((0,1), x), ((1,2), 2 - x), + ....: ((2,3), x - 2), ((3,4), 2 - (x-2))]) sage: bool(f2.restriction((0,2)) == f) # f2 extends f on (0,4) True sage: f2.fourier_series_cosine_coefficient(3, 1) # half-period = 1 @@ -1160,7 +1192,7 @@ def fourier_series_cosine_coefficient(self, parameters, The default half-period is 2 and one has:: - sage: f2.fourier_series_cosine_coefficient(3) # half-period = 2 + sage: f2.fourier_series_cosine_coefficient(3) # half-period = 2 0 The Fourier coefficient `-4/(9\pi^2)` obtained above is actually @@ -1382,15 +1414,15 @@ def _sympy_(self, parameters, variable): EXAMPLES:: sage: ex = piecewise([((0, 1), pi), ([1, 2], x)]) - sage: f = ex._sympy_(); f + sage: f = ex._sympy_(); f # needs sympy Piecewise((pi, (x > 0) & (x < 1)), (x, (x >= 1) & (x <= 2))) - sage: f.diff() + sage: f.diff() # needs sympy Piecewise((0, (x > 0) & (x < 1)), (1, (x >= 1) & (x <= 2))) sage: ex = piecewise([((-100, -2), 1/x), ((1, +oo), cos(x))]) - sage: g = ex._sympy_(); g + sage: g = ex._sympy_(); g # needs sympy Piecewise((1/x, (x > -100) & (x < -2)), (cos(x), x > 1)) - sage: g.diff() + sage: g.diff() # needs sympy Piecewise((-1/x**2, (x > -100) & (x < -2)), (-sin(x), x > 1)) """ from sympy import Piecewise as pw @@ -1408,22 +1440,22 @@ def _giac_init_(self, parameters, variable): EXAMPLES:: sage: ex = piecewise([((0, 1), pi), ([1, 2], x)]) - sage: f = ex._giac_(); f + sage: f = ex._giac_(); f # needs sage.libs.giac piecewise(((sageVARx>0) and (1>sageVARx)),pi,((sageVARx>=1) and (2>=sageVARx)),sageVARx) - sage: f.diff(x) + sage: f.diff(x) # needs sage.libs.giac piecewise(((sageVARx>0) and (1>sageVARx)),0,((sageVARx>=1) and (2>=sageVARx)),1) - sage: ex = piecewise([((-100, -2), 1/x), ((1, +oo), cos(x))]) - sage: g = ex._giac_(); g + sage: ex = piecewise([((-100, -2), 1/x), ((1, +oo), cos(x))]) # needs sage.libs.giac + sage: g = ex._giac_(); g # needs sage.libs.giac piecewise(((sageVARx>-100) and ((-2)>sageVARx)),1/sageVARx,sageVARx>1,cos(sageVARx)) - sage: g.diff(x) + sage: g.diff(x) # needs sage.libs.giac piecewise(((sageVARx>-100) and ((-2)>sageVARx)),-1/sageVARx^2,sageVARx>1,-sin(sageVARx)) TESTS:: - sage: f = piecewise([([0,1],x),((1,2),3*x)]) - sage: a = libgiac(f) # random because verbose - sage: a + sage: f = piecewise([([0,1], x), ((1,2), 3*x)]) + sage: a = libgiac(f) # random because verbose # needs sage.libs.giac + sage: a # needs sage.libs.giac piecewise(((sageVARx>=0) and (1>=sageVARx)),sageVARx,((sageVARx>1) and (2>sageVARx)),sageVARx*3) """ from sage.misc.flatten import flatten diff --git a/src/sage/functions/prime_pi.pyx b/src/sage/functions/prime_pi.pyx index fd2956be193..141e538cf74 100644 --- a/src/sage/functions/prime_pi.pyx +++ b/src/sage/functions/prime_pi.pyx @@ -1,3 +1,4 @@ +# sage.doctest: needs primecountpy r""" Counting primes @@ -32,10 +33,13 @@ AUTHORS: # https://www.gnu.org/licenses/ # **************************************************************************** +from sage.misc.lazy_import import LazyImport from sage.rings.integer cimport Integer from sage.symbolic.function cimport BuiltinFunction -from primecountpy.primecount import prime_pi as _prime_pi -from primecountpy.primecount import phi as _phi + +_prime_pi = LazyImport('primecountpy.primecount', 'prime_pi', as_name='prime_pi') +_phi = LazyImport('primecountpy.primecount', 'phi', as_name='_phi') + cdef class PrimePi(BuiltinFunction): def __init__(self): @@ -45,8 +49,8 @@ cdef class PrimePi(BuiltinFunction): INPUT: - - ``x`` - a real number - - ``prime_bound`` - (default 0) a real number < 2^32, ``prime_pi`` will + - ``x`` -- a real number + - ``prime_bound`` -- (default 0) a real number < 2^32; :func:`prime_pi` will make sure to use all the primes up to ``prime_bound`` (although, possibly more) in computing ``prime_pi``, this can potentially speedup the time of computation, at a cost to memory usage. @@ -59,6 +63,7 @@ cdef class PrimePi(BuiltinFunction): These examples test common inputs:: + sage: # needs sage.symbolic sage: prime_pi(7) 4 sage: prime_pi(100) @@ -73,13 +78,13 @@ cdef class PrimePi(BuiltinFunction): The following test is to verify that :trac:`4670` has been essentially resolved:: - sage: prime_pi(10^10) + sage: prime_pi(10^10) # needs sage.symbolic 455052511 - The ``prime_pi`` function also has a special plotting method, so it + The :func:`prime_pi` function also has a special plotting method, so it plots quickly and perfectly as a step function:: - sage: P = plot(prime_pi, 50, 100) + sage: P = plot(prime_pi, 50, 100) # needs sage.plot sage.symbolic """ super(PrimePi, self).__init__('prime_pi', latex_name=r"\pi", @@ -91,6 +96,7 @@ cdef class PrimePi(BuiltinFunction): r""" EXAMPLES:: + sage: # needs sage.symbolic sage: prime_pi.__call__(756) 133 sage: prime_pi.__call__(6574, 577) @@ -128,7 +134,7 @@ cdef class PrimePi(BuiltinFunction): Make sure we actually compute correct results for 64-bit entries:: - sage: for i in (32..42): prime_pi(2^i) # long time (13s on sage.math, 2011) + sage: for i in (32..42): prime_pi(2^i) # long time (13s on sage.math, 2011) 203280221 393615806 762939111 @@ -181,9 +187,9 @@ cdef class PrimePi(BuiltinFunction): EXAMPLES:: - sage: plot(prime_pi, 1, 100) + sage: plot(prime_pi, 1, 100) # needs sage.plot sage.symbolic Graphics object consisting of 1 graphics primitive - sage: prime_pi.plot(1, 51, thickness=2, vertical_lines=False) + sage: prime_pi.plot(1, 51, thickness=2, vertical_lines=False) # needs sage.plot sage.symbolic Graphics object consisting of 16 graphics primitives """ from sage.plot.step import plot_step_function @@ -200,9 +206,10 @@ cdef class PrimePi(BuiltinFunction): v.append((xmax, y)) return plot_step_function(v, vertical_lines=vertical_lines, **kwds) -######## + prime_pi = PrimePi() + cpdef Integer legendre_phi(x, a): r""" Legendre's formula, also known as the partial sieve function, is a useful @@ -257,4 +264,5 @@ cpdef Integer legendre_phi(x, a): # Deal with the general case return Integer(_phi(y, a)) + partial_sieve_function = legendre_phi diff --git a/src/sage/functions/special.py b/src/sage/functions/special.py index bf352a8bbc6..93e032d0677 100644 --- a/src/sage/functions/special.py +++ b/src/sage/functions/special.py @@ -141,15 +141,27 @@ # **************************************************************************** import sage.rings.abc + +from sage.misc.functional import sqrt +from sage.misc.lazy_import import lazy_import from sage.rings.integer import Integer -from sage.misc.latex import latex from sage.rings.integer_ring import ZZ -from sage.symbolic.constants import pi +from sage.structure.element import parent as s_parent from sage.symbolic.function import BuiltinFunction -from sage.libs.mpmath import utils as mpmath_utils -from sage.functions.all import sin, cot, exp -from sage.misc.functional import sqrt -from sage.symbolic.constants import I + +lazy_import('sage.functions.jacobi', 'jacobi_am_f') +lazy_import('sage.functions.log', ['exp']) +lazy_import('sage.functions.trig', ['sin', 'cot']) + +lazy_import('sage.misc.latex', 'latex') + +lazy_import('sage.symbolic.constants', ['I', 'pi']) + +lazy_import('sage.libs.mpmath.utils', 'call', as_='_mpmath_utils_call') +lazy_import('mpmath', + ['spherharm', 'ellipe', 'ellipf', 'ellipk', 'ellippi'], + as_=['_mpmath_spherharm', '_mpmath_ellipe', '_mpmath_ellipf', + '_mpmath_ellipk', '_mpmath_ellippi']) class SphericalHarmonic(BuiltinFunction): @@ -161,6 +173,7 @@ class SphericalHarmonic(BuiltinFunction): EXAMPLES:: + sage: # needs sage.symbolic sage: x, y = var('x, y') sage: spherical_harmonic(3, 2, x, y) 1/8*sqrt(30)*sqrt(7)*cos(x)*e^(2*I*y)*sin(x)^2/sqrt(pi) @@ -175,6 +188,7 @@ class SphericalHarmonic(BuiltinFunction): The degree `n` and the order `m` can be symbolic:: + sage: # needs sage.symbolic sage: n, m = var('n m') sage: spherical_harmonic(n, m, x, y) spherical_harmonic(n, m, x, y) @@ -189,26 +203,27 @@ class SphericalHarmonic(BuiltinFunction): The convention regarding the Condon-Shortley phase `(-1)^m` is the same as for SymPy's spherical harmonics and :wikipedia:`Spherical_harmonics`:: + sage: # needs sage.symbolic sage: spherical_harmonic(1, 1, x, y) -1/4*sqrt(3)*sqrt(2)*e^(I*y)*sin(x)/sqrt(pi) - sage: from sympy import Ynm - sage: Ynm(1, 1, x, y).expand(func=True) + sage: from sympy import Ynm # needs sympy + sage: Ynm(1, 1, x, y).expand(func=True) # needs sympy -sqrt(6)*exp(I*y)*sin(x)/(4*sqrt(pi)) - sage: spherical_harmonic(1, 1, x, y) - Ynm(1, 1, x, y) + sage: spherical_harmonic(1, 1, x, y) - Ynm(1, 1, x, y) # needs sympy 0 It also agrees with SciPy's spherical harmonics:: - sage: spherical_harmonic(1, 1, pi/2, pi).n() # abs tol 1e-14 + sage: spherical_harmonic(1, 1, pi/2, pi).n() # abs tol 1e-14 # needs sage.symbolic 0.345494149471335 - sage: from scipy.special import sph_harm # NB: arguments x and y are swapped - sage: sph_harm(1, 1, pi.n(), (pi/2).n()) # abs tol 1e-14 + sage: from scipy.special import sph_harm # NB: arguments x and y are swapped # needs scipy + sage: sph_harm(1, 1, pi.n(), (pi/2).n()) # abs tol 1e-14 # needs scipy sage.symbolic (0.3454941494713355-4.231083042742082e-17j) Note that this convention differs from the one in Maxima, as revealed by the sign difference for odd values of `m`:: - sage: maxima.spherical_harmonic(1, 1, x, y).sage() + sage: maxima.spherical_harmonic(1, 1, x, y).sage() # needs sage.symbolic 1/2*sqrt(3/2)*e^(I*y)*sin(x)/sqrt(pi) It follows that, contrary to Maxima, SageMath uses the same sign convention @@ -224,8 +239,8 @@ def __init__(self): r""" TESTS:: - sage: n, m, theta, phi = var('n m theta phi') - sage: spherical_harmonic(n, m, theta, phi)._sympy_() + sage: n, m, theta, phi = var('n m theta phi') # needs sage.symbolic + sage: spherical_harmonic(n, m, theta, phi)._sympy_() # needs sympy sage.symbolic Ynm(n, m, theta, phi) """ BuiltinFunction.__init__(self, 'spherical_harmonic', nargs=4, @@ -239,6 +254,7 @@ def _eval_(self, n, m, theta, phi, **kwargs): r""" TESTS:: + sage: # needs sage.symbolic sage: x, y = var('x y') sage: spherical_harmonic(1, 2, x, y) 0 @@ -255,28 +271,29 @@ def _eval_(self, n, m, theta, phi, **kwargs): Check that :trac:`20939` is fixed:: - sage: ex = spherical_harmonic(3, 2, 1, 2*pi/3) - sage: QQbar(ex * sqrt(pi)/cos(1)/sin(1)^2).minpoly() + sage: ex = spherical_harmonic(3, 2, 1, 2*pi/3) # needs sage.symbolic + sage: QQbar(ex * sqrt(pi)/cos(1)/sin(1)^2).minpoly() # needs sage.rings.number_field sage.symbolic x^4 + 105/32*x^2 + 11025/1024 Check whether Sage yields correct results compared to Maxima, up to the Condon-Shortley phase factor `(-1)^m` (see :trac:`25034` and :trac:`33117`):: - sage: spherical_harmonic(1, 1, pi/3, pi/6).n() # abs tol 1e-14 + sage: # needs sage.symbolic + sage: spherical_harmonic(1, 1, pi/3, pi/6).n() # abs tol 1e-14 -0.259120612103502 - 0.149603355150537*I - sage: maxima.spherical_harmonic(1, 1, pi/3, pi/6).n() # abs tol 1e-14 + sage: maxima.spherical_harmonic(1, 1, pi/3, pi/6).n() # abs tol 1e-14 0.259120612103502 + 0.149603355150537*I - sage: spherical_harmonic(1, -1, pi/3, pi/6).n() # abs tol 1e-14 + sage: spherical_harmonic(1, -1, pi/3, pi/6).n() # abs tol 1e-14 0.259120612103502 - 0.149603355150537*I - sage: maxima.spherical_harmonic(1, -1, pi/3, pi/6).n() # abs tol 1e-14 + sage: maxima.spherical_harmonic(1, -1, pi/3, pi/6).n() # abs tol 1e-14 -0.259120612103502 + 0.149603355150537*I Check that :trac:`33501` is fixed:: - sage: spherical_harmonic(2, 1, x, y) + sage: spherical_harmonic(2, 1, x, y) # needs sage.symbolic -1/4*sqrt(6)*sqrt(5)*cos(x)*e^(I*y)*sin(x)/sqrt(pi) - sage: spherical_harmonic(5, -3, x, y) + sage: spherical_harmonic(5, -3, x, y) # needs sage.symbolic -1/32*(9*sqrt(385)*sin(x)^4 - 8*sqrt(385)*sin(x)^2)*e^(-3*I*y)*sin(x)/sqrt(pi) """ @@ -298,9 +315,9 @@ def _evalf_(self, n, m, theta, phi, parent, **kwds): r""" TESTS:: - sage: spherical_harmonic(3 + I, 2, 1, 2).n(100) + sage: spherical_harmonic(3 + I, 2, 1, 2).n(100) # needs sage.symbolic -0.35115433730748836508201061672 - 0.41556223397536866209990358597*I - sage: spherical_harmonic(I, I, I, I).n() + sage: spherical_harmonic(I, I, I, I).n() # needs sage.symbolic 7.66678546069894 - 0.265754432549751*I Consistency with ``_eval_``:: @@ -308,21 +325,20 @@ def _evalf_(self, n, m, theta, phi, parent, **kwds): sage: d = lambda a, b: abs(spherical_harmonic(a, b, 1., 2.) ....: - spherical_harmonic(a, b, 1, 2).n()) sage: ab = [(0, 0), (1, -1), (1, 0), (1, 1), (3, 2), (3, 3)] - sage: all(d(a, b) < 1e-14 for a, b in ab) + sage: all(d(a, b) < 1e-14 for a, b in ab) # needs sage.symbolic True """ - from mpmath import spherharm - return mpmath_utils.call(spherharm, n, m, theta, phi, parent=parent) + return _mpmath_utils_call(_mpmath_spherharm, n, m, theta, phi, parent=parent) def _derivative_(self, n, m, theta, phi, diff_param): r""" TESTS:: + sage: # needs sage.symbolic sage: n, m, theta, phi = var('n m theta phi') sage: Ynm = spherical_harmonic(n, m, theta, phi) - sage: DY_theta = Ynm.diff(theta) - sage: DY_theta + sage: DY_theta = Ynm.diff(theta); DY_theta m*cot(theta)*spherical_harmonic(n, m, theta, phi) + sqrt(-(m + n + 1)*(m - n))*e^(-I*phi)*spherical_harmonic(n, m + 1, theta, phi) sage: Ynm.diff(phi) @@ -330,6 +346,7 @@ def _derivative_(self, n, m, theta, phi, diff_param): Check that :trac:`33117` is fixed:: + sage: # needs sage.symbolic sage: DY_theta.subs({n: 1, m: 0}) -1/2*sqrt(3)*sin(theta)/sqrt(pi) sage: Ynm.subs({n: 1, m: 0}).diff(theta) @@ -365,8 +382,8 @@ def _print_latex_(self, n, m, theta, phi): r""" TESTS:: - sage: y = var('y') - sage: latex(spherical_harmonic(3, 2, x, y, hold=True)) + sage: y = var('y') # needs sage.symbolic + sage: latex(spherical_harmonic(3, 2, x, y, hold=True)) # needs sage.symbolic Y_{3}^{2}\left(x, y\right) """ return r"Y_{{{}}}^{{{}}}\left({}, {}\right)".format( @@ -402,30 +419,31 @@ def elliptic_j(z, prec=53): EXAMPLES:: - sage: elliptic_j(CC(i)) + sage: elliptic_j(CC(i)) # needs sage.rings.real_mpfr 1728.00000000000 - sage: elliptic_j(sqrt(-2.0)) + sage: elliptic_j(sqrt(-2.0)) # needs sage.rings.complex_double 8000.00000000000 - sage: z = ComplexField(100)(1,sqrt(11))/2 - sage: elliptic_j(z) + sage: z = ComplexField(100)(1, sqrt(11))/2 # needs sage.rings.real_mpfr sage.symbolic + sage: elliptic_j(z) # needs sage.rings.real_mpfr sage.symbolic -32768.000... - sage: elliptic_j(z).real().round() + sage: elliptic_j(z).real().round() # needs sage.rings.real_mpfr sage.symbolic -32768 :: - sage: tau = (1 + sqrt(-163))/2 - sage: (-elliptic_j(tau.n(100)).real().round())^(1/3) + sage: tau = (1 + sqrt(-163))/2 # needs sage.symbolic + sage: (-elliptic_j(tau.n(100)).real().round())^(1/3) # needs sage.symbolic 640320 This example shows the need for higher precision than the default one of the `ComplexField`, see :trac:`28355`:: - sage: -elliptic_j(tau) # rel tol 1e-2 + sage: # needs sage.symbolic + sage: -elliptic_j(tau) # rel tol 1e-2 2.62537412640767e17 - 732.558854258998*I - sage: -elliptic_j(tau,75) # rel tol 1e-2 + sage: -elliptic_j(tau, 75) # rel tol 1e-2 2.625374126407680000000e17 - 0.0001309913593909879441262*I - sage: -elliptic_j(tau,100) # rel tol 1e-2 + sage: -elliptic_j(tau, 100) # rel tol 1e-2 2.6253741264076799999999999999e17 - 1.3012822400356887122945119790e-12*I sage: (-elliptic_j(tau, 100).real().round())^(1/3) 640320 @@ -455,16 +473,16 @@ class EllipticE(BuiltinFunction): EXAMPLES:: - sage: z = var("z") - sage: elliptic_e(z, 1) + sage: z = var("z") # needs sage.symbolic + sage: elliptic_e(z, 1) # needs sage.symbolic elliptic_e(z, 1) - sage: elliptic_e(z, 1).simplify() # not tested - gives wrong answer with maxima < 5.47 + sage: elliptic_e(z, 1).simplify() # not tested # needs sage.symbolic 2*round(z/pi) - sin(pi*round(z/pi) - z) - sage: elliptic_e(z, 0) + sage: elliptic_e(z, 0) # needs sage.symbolic z - sage: elliptic_e(0.5, 0.1) # abs tol 2e-15 + sage: elliptic_e(0.5, 0.1) # abs tol 2e-15 # needs mpmath 0.498011394498832 - sage: elliptic_e(1/2, 1/10).n(200) + sage: elliptic_e(1/2, 1/10).n(200) # needs sage.symbolic 0.4980113944988315331154610406... .. SEEALSO:: @@ -487,27 +505,28 @@ def __init__(self): sage: loads(dumps(elliptic_e)) elliptic_e - sage: elliptic_e(x, x)._sympy_() + sage: elliptic_e(x, x)._sympy_() # needs sympy sage.symbolic elliptic_e(x, x) Check that :trac:`34085` is fixed:: - sage: _ = var("x y") - sage: fricas(elliptic_e(x, y)) # optional - fricas + sage: _ = var("x y") # needs sage.symbolic + sage: fricas(elliptic_e(x, y)) # optional - fricas, needs sage.symbolic ellipticE(sin(x),y) However, the conversion is only correct in the interval `[-\pi/2, \pi/2]`:: - sage: fricas(elliptic_e(x, y)).D(x).sage()/elliptic_e(x, y).diff(x) # optional - fricas + sage: fricas(elliptic_e(x, y)).D(x).sage()/elliptic_e(x, y).diff(x) # optional - fricas, needs sage.symbolic cos(x)/sqrt(-sin(x)^2 + 1) Numerically:: - sage: f = lambda x, y: elliptic_e(arcsin(x), y).subs(x=x, y=y) # optional - fricas - sage: g = lambda x, y: fricas.ellipticE(x, y).sage() # optional - fricas - sage: d = lambda x, y: f(x, y) - g(x, y) # optional - fricas - sage: [d(N(-pi/2+x), y) for x in range(1, 3) for y in range(-2,2)] # optional - fricas tol 1e-8 + sage: f = lambda x, y: elliptic_e(arcsin(x), y).subs(x=x, y=y) + sage: g = lambda x, y: fricas.ellipticE(x, y).sage() + sage: d = lambda x, y: f(x, y) - g(x, y) + sage: [d(N(-pi/2 + x), y) # tol 1e-8 # optional - fricas, needs sage.symbolic + ....: for x in range(1, 3) for y in range(-2, 2)] [0.000000000000000, 0.000000000000000, 0.000000000000000, @@ -530,6 +549,7 @@ def _eval_(self, z, m): """ EXAMPLES:: + sage: # needs sage.symbolic sage: z = var("z") sage: elliptic_e(0, x) 0 @@ -542,7 +562,7 @@ def _eval_(self, z, m): Here arccoth doesn't have 1 in its domain, so we just hold the expression:: - sage: elliptic_e(arccoth(1), x^2*e) + sage: elliptic_e(arccoth(1), x^2*e) # needs sage.symbolic elliptic_e(+Infinity, x^2*e) """ if z == 0: @@ -556,32 +576,31 @@ def _evalf_(self, z, m, parent=None, algorithm=None): """ EXAMPLES:: - sage: elliptic_e(0.5, 0.1) + sage: elliptic_e(0.5, 0.1) # needs mpmath 0.498011394498832 - sage: elliptic_e(1/2, 1/10).n(200) + sage: elliptic_e(1/2, 1/10).n(200) # needs sage.symbolic 0.4980113944988315331154610406... - sage: elliptic_e(I, I).n() + sage: elliptic_e(I, I).n() # needs sage.symbolic -0.189847437084712 + 1.03209769372160*I TESTS: This gave an error in Maxima (:trac:`15046`):: - sage: elliptic_e(2.5, 2.5) + sage: elliptic_e(2.5, 2.5) # needs mpmath 0.535647771608740 + 1.63996015168665*I """ - R = parent or parent(z) - from mpmath import ellipe - return mpmath_utils.call(ellipe, z, m, parent=R) + R = parent or s_parent(z) + return _mpmath_utils_call(_mpmath_ellipe, z, m, parent=R) def _derivative_(self, z, m, diff_param): """ EXAMPLES:: - sage: x,z = var('x,z') - sage: elliptic_e(z, x).diff(z, 1) + sage: x, z = var('x,z') # needs sage.symbolic + sage: elliptic_e(z, x).diff(z, 1) # needs sage.symbolic sqrt(-x*sin(z)^2 + 1) - sage: elliptic_e(z, x).diff(x, 1) + sage: elliptic_e(z, x).diff(x, 1) # needs sage.symbolic 1/2*(elliptic_e(z, x) - elliptic_f(z, x))/x """ if diff_param == 0: @@ -593,7 +612,7 @@ def _print_latex_(self, z, m): r""" EXAMPLES:: - sage: latex(elliptic_e(pi, x)) + sage: latex(elliptic_e(pi, x)) # needs sage.symbolic E(\pi\,|\,x) """ return r"E(%s\,|\,%s)" % (latex(z), latex(m)) @@ -612,9 +631,9 @@ class EllipticEC(BuiltinFunction): EXAMPLES:: - sage: elliptic_ec(0.1) + sage: elliptic_ec(0.1) # needs mpmath 1.53075763689776 - sage: elliptic_ec(x).diff() + sage: elliptic_ec(x).diff() # needs sage.symbolic 1/2*(elliptic_ec(x) - elliptic_kc(x))/x .. SEEALSO:: @@ -631,17 +650,17 @@ def __init__(self): sage: loads(dumps(elliptic_ec)) elliptic_ec - sage: elliptic_ec(x)._sympy_() + sage: elliptic_ec(x)._sympy_() # needs sage.symbolic elliptic_e(x) TESTS:: - sage: fricas(elliptic_ec(x)) # optional - fricas + sage: fricas(elliptic_ec(x)) # optional - fricas, needs sage.symbolic ellipticE(x) - sage: elliptic_ec(0.5) # abs tol 1e-8 + sage: elliptic_ec(0.5) # abs tol 1e-8 # needs sage.symbolic 1.35064388104768 - sage: fricas.ellipticE(0.5).sage() # abs tol 1e-8 # optional - fricas + sage: fricas.ellipticE(0.5).sage() # abs tol 1e-8 # optional - fricas, needs sage.symbolic 1.3506438810476755025201749 """ BuiltinFunction.__init__(self, 'elliptic_ec', nargs=1, latex_name='E', @@ -654,11 +673,11 @@ def _eval_(self, x): """ EXAMPLES:: - sage: elliptic_ec(0) + sage: elliptic_ec(0) # needs sage.symbolic 1/2*pi - sage: elliptic_ec(1) + sage: elliptic_ec(1) # needs sage.symbolic 1 - sage: elliptic_ec(x) + sage: elliptic_ec(x) # needs sage.symbolic elliptic_ec(x) """ if x == 0: @@ -670,22 +689,21 @@ def _evalf_(self, x, parent=None, algorithm=None): """ EXAMPLES:: - sage: elliptic_ec(sqrt(2)/2).n() + sage: elliptic_ec(sqrt(2)/2).n() # needs sage.symbolic 1.23742252487318 - sage: elliptic_ec(sqrt(2)/2).n(200) + sage: elliptic_ec(sqrt(2)/2).n(200) # needs sage.symbolic 1.237422524873181672854746084083... - sage: elliptic_ec(I).n() + sage: elliptic_ec(I).n() # needs sage.symbolic 1.63241178144043 - 0.369219492375499*I """ - R = parent or parent(x) - from mpmath import ellipe - return mpmath_utils.call(ellipe, x, parent=R) + R = parent or s_parent(x) + return _mpmath_utils_call(_mpmath_ellipe, x, parent=R) def _derivative_(self, x, diff_param): """ EXAMPLES:: - sage: elliptic_ec(x).diff() + sage: elliptic_ec(x).diff() # needs sage.symbolic 1/2*(elliptic_ec(x) - elliptic_kc(x))/x """ return (elliptic_ec(x) - elliptic_kc(x)) / (Integer(2) * x) @@ -710,7 +728,7 @@ class EllipticEU(BuiltinFunction): EXAMPLES:: - sage: elliptic_eu (0.5, 0.1) + sage: elliptic_eu(0.5, 0.1) # needs mpmath 0.496054551286597 .. SEEALSO:: @@ -737,7 +755,7 @@ def _eval_(self, u, m): """ EXAMPLES:: - sage: elliptic_eu(1,1) + sage: elliptic_eu(1, 1) # needs sage.symbolic elliptic_eu(1, 1) """ pass @@ -746,22 +764,22 @@ def _evalf_(self, u, m, parent=None, algorithm=None): """ EXAMPLES:: - sage: elliptic_eu(1,1).n() + sage: elliptic_eu(1, 1).n() # needs sage.symbolic 0.761594155955765 - sage: elliptic_eu(1,1).n(200) + sage: elliptic_eu(1, 1).n(200) # needs sage.symbolic 0.7615941559557648881194582... """ - R = parent or parent(u) - return mpmath_utils.call(elliptic_eu_f, u, m, parent=R) + R = parent or s_parent(u) + return _mpmath_utils_call(elliptic_eu_f, u, m, parent=R) def _derivative_(self, u, m, diff_param): """ EXAMPLES:: - sage: x,m = var('x,m') - sage: elliptic_eu(x,m).diff(x) + sage: x, m = var('x,m') # needs sage.symbolic + sage: elliptic_eu(x, m).diff(x) # needs sage.symbolic sqrt(-m*jacobi_sn(x, m)^2 + 1)*jacobi_dn(x, m) - sage: elliptic_eu(x,m).diff(m) + sage: elliptic_eu(x, m).diff(m) # needs sage.symbolic 1/2*(elliptic_eu(x, m) - elliptic_f(jacobi_am(x, m), m))/m - 1/2*(m*jacobi_cn(x, m)*jacobi_sn(x, m) @@ -785,7 +803,7 @@ def _print_latex_(self, u, m): """ EXAMPLES:: - sage: latex(elliptic_eu(1,x)) + sage: latex(elliptic_eu(1, x)) # needs sage.symbolic E(1;x) """ return r"E(%s;%s)" % (latex(u), latex(m)) @@ -801,13 +819,10 @@ def elliptic_eu_f(u, m): EXAMPLES:: sage: from sage.functions.special import elliptic_eu_f - sage: elliptic_eu_f(0.5, 0.1) + sage: elliptic_eu_f(0.5, 0.1) # needs mpmath mpf('0.49605455128659691') """ - from mpmath import mp - from sage.functions.jacobi import jacobi_am_f - - ctx = mp + from mpmath import mp as ctx prec = ctx.prec try: u = ctx.convert(u) @@ -834,12 +849,12 @@ class EllipticF(BuiltinFunction): EXAMPLES:: - sage: z = var("z") - sage: elliptic_f (z, 0) + sage: z = var("z") # needs sage.symbolic + sage: elliptic_f(z, 0) # needs sage.symbolic z - sage: elliptic_f (z, 1).simplify() + sage: elliptic_f(z, 1).simplify() # needs sage.symbolic log(tan(1/4*pi + 1/2*z)) - sage: elliptic_f (0.2, 0.1) + sage: elliptic_f(0.2, 0.1) # needs mpmath 0.200132506747543 .. SEEALSO:: @@ -856,27 +871,28 @@ def __init__(self): sage: loads(dumps(elliptic_f)) elliptic_f - sage: elliptic_f(x, 2)._sympy_() + sage: elliptic_f(x, 2)._sympy_() # needs sympy sage.symbolic elliptic_f(x, 2) Check that :trac:`34186` is fixed:: - sage: _ = var("x y") - sage: fricas(elliptic_f(x, y)) # optional - fricas + sage: _ = var("x y") # needs sage.symbolic + sage: fricas(elliptic_f(x, y)) # optional - fricas, needs sage.symbolic ellipticF(sin(x),y) However, the conversion is only correct in the interval `[-\pi/2, \pi/2]`:: - sage: fricas(elliptic_f(x, y)).D(x).sage()/elliptic_f(x, y).diff(x) # optional - fricas + sage: fricas(elliptic_f(x, y)).D(x).sage()/elliptic_f(x, y).diff(x) # optional - fricas, needs sage.symbolic cos(x)/sqrt(-sin(x)^2 + 1) Numerically:: - sage: f = lambda x, y: elliptic_f(arcsin(x), y).subs(x=x, y=y) # optional - fricas - sage: g = lambda x, y: fricas.ellipticF(x, y).sage() # optional - fricas - sage: d = lambda x, y: f(x, y) - g(x, y) # optional - fricas - sage: [d(N(-pi/2+x), y) for x in range(1, 3) for y in range(-2,2)] # optional - fricas tol 1e-8 + sage: f = lambda x, y: elliptic_f(arcsin(x), y).subs(x=x, y=y) + sage: g = lambda x, y: fricas.ellipticF(x, y).sage() + sage: d = lambda x, y: f(x, y) - g(x, y) + sage: [d(N(-pi/2 + x), y) # tol 1e-8 # optional - fricas, needs sage.symbolic + ....: for x in range(1, 3) for y in range(-2,2)] [0.000000000000000, 0.000000000000000, 0.000000000000000, @@ -897,13 +913,14 @@ def _eval_(self, z, m): """ EXAMPLES:: - sage: elliptic_f(x,1) + sage: # needs sage.symbolic + sage: elliptic_f(x, 1) elliptic_f(x, 1) - sage: elliptic_f(x,0) + sage: elliptic_f(x, 0) x - sage: elliptic_f(0,1) + sage: elliptic_f(0, 1) 0 - sage: elliptic_f(pi/2,x) + sage: elliptic_f(pi/2, x) elliptic_kc(x) """ if m == 0: @@ -917,25 +934,24 @@ def _evalf_(self, z, m, parent=None, algorithm=None): """ EXAMPLES:: - sage: elliptic_f(1,1).n() + sage: elliptic_f(1, 1).n() # needs sage.symbolic 1.22619117088352 - sage: elliptic_f(1,1).n(200) + sage: elliptic_f(1, 1).n(200) # needs sage.symbolic 1.22619117088351707081306096... - sage: elliptic_f(I,I).n() + sage: elliptic_f(I, I).n() # needs sage.symbolic 0.149965060031782 + 0.925097284105771*I """ - R = parent or parent(z) - from mpmath import ellipf - return mpmath_utils.call(ellipf, z, m, parent=R) + R = parent or s_parent(z) + return _mpmath_utils_call(_mpmath_ellipf, z, m, parent=R) def _derivative_(self, z, m, diff_param): """ EXAMPLES:: - sage: x,m = var('x,m') - sage: elliptic_f(x,m).diff(x) + sage: x, m = var('x,m') # needs sage.symbolic + sage: elliptic_f(x, m).diff(x) # needs sage.symbolic 1/sqrt(-m*sin(x)^2 + 1) - sage: elliptic_f(x,m).diff(m) + sage: elliptic_f(x, m).diff(m) # needs sage.symbolic -1/2*elliptic_f(x, m)/m + 1/4*sin(2*x)/(sqrt(-m*sin(x)^2 + 1)*(m - 1)) - 1/2*elliptic_e(x, m)/((m - 1)*m) @@ -953,7 +969,7 @@ def _print_latex_(self, z, m): r""" EXAMPLES:: - sage: latex(elliptic_f(x,pi)) + sage: latex(elliptic_f(x, pi)) # needs sage.symbolic F(x\,|\,\pi) """ return r"F(%s\,|\,%s)" % (latex(z), latex(m)) @@ -972,7 +988,7 @@ class EllipticKC(BuiltinFunction): EXAMPLES:: - sage: elliptic_kc(0.5) + sage: elliptic_kc(0.5) # needs mpmath 1.85407467730137 .. SEEALSO:: @@ -993,17 +1009,17 @@ def __init__(self): sage: loads(dumps(elliptic_kc)) elliptic_kc - sage: elliptic_kc(x)._sympy_() + sage: elliptic_kc(x)._sympy_() # needs sage.symbolic elliptic_k(x) TESTS:: - sage: fricas(elliptic_kc(x)) # optional - fricas + sage: fricas(elliptic_kc(x)) # optional - fricas, needs sage.symbolic ellipticK(x) - sage: elliptic_kc(0.3) # abs tol 1e-8 + sage: elliptic_kc(0.3) # abs tol 1e-8 # needs mpmath 1.71388944817879 - sage: fricas.ellipticK(0.3).sage() # abs tol 1e-3 # optional - fricas + sage: fricas.ellipticK(0.3).sage() # abs tol 1e-3 # optional - fricas, needs sage.symbolic 1.7138894481787910555457043 """ BuiltinFunction.__init__(self, 'elliptic_kc', nargs=1, latex_name='K', @@ -1016,9 +1032,9 @@ def _eval_(self, z): """ EXAMPLES:: - sage: elliptic_kc(0) + sage: elliptic_kc(0) # needs sage.symbolic 1/2*pi - sage: elliptic_kc(1/2) + sage: elliptic_kc(1/2) # needs sage.symbolic elliptic_kc(1/2) TESTS: @@ -1026,10 +1042,10 @@ def _eval_(self, z): Check if complex numbers in the arguments are converted to maxima correctly (see :trac:`7557`):: - sage: t = jacobi_sn(1.2+2*I*elliptic_kc(1-.5),.5) - sage: maxima(t) # abs tol 1e-13 + sage: t = jacobi_sn(1.2 + 2*I*elliptic_kc(1 - .5), .5) # needs sage.symbolic + sage: maxima(t) # abs tol 1e-13 # needs sage.symbolic 0.88771548861928029 - 1.7301614091485560e-15*%i - sage: t.n() # abs tol 1e-13 + sage: t.n() # abs tol 1e-13 # needs sage.symbolic 0.887715488619280 - 1.73016140914856e-15*I """ if z == 0: @@ -1041,22 +1057,21 @@ def _evalf_(self, z, parent=None, algorithm=None): """ EXAMPLES:: - sage: elliptic_kc(1/2).n() + sage: elliptic_kc(1/2).n() # needs sage.symbolic 1.85407467730137 - sage: elliptic_kc(1/2).n(200) + sage: elliptic_kc(1/2).n(200) # needs sage.symbolic 1.85407467730137191843385034... - sage: elliptic_kc(I).n() + sage: elliptic_kc(I).n() # needs sage.symbolic 1.42127228104504 + 0.295380284214777*I """ - R = parent or parent(z) - from mpmath import ellipk - return mpmath_utils.call(ellipk, z, parent=R) + R = parent or s_parent(z) + return _mpmath_utils_call(_mpmath_ellipk, z, parent=R) def _derivative_(self, z, diff_param): """ EXAMPLES:: - sage: elliptic_kc(x).diff(x) + sage: elliptic_kc(x).diff(x) # needs sage.symbolic -1/2*((x - 1)*elliptic_kc(x) + elliptic_ec(x))/((x - 1)*x) """ @@ -1085,15 +1100,15 @@ class EllipticPi(BuiltinFunction): EXAMPLES:: - sage: N(elliptic_pi(1, pi/4, 1)) + sage: N(elliptic_pi(1, pi/4, 1)) # needs sage.symbolic 1.14779357469632 Compare the value computed by Maxima to the definition as a definite integral (using GSL):: - sage: elliptic_pi(0.1, 0.2, 0.3) + sage: elliptic_pi(0.1, 0.2, 0.3) # needs mpmath 0.200665068220979 - sage: numerical_integral(1/(1-0.1*sin(x)^2)/sqrt(1-0.3*sin(x)^2), 0.0, 0.2) + sage: numerical_integral(1/(1-0.1*sin(x)^2)/sqrt(1-0.3*sin(x)^2), 0.0, 0.2) # needs sage.symbolic (0.2006650682209791, 2.227829789769088e-15) REFERENCES: @@ -1106,7 +1121,7 @@ def __init__(self): sage: loads(dumps(elliptic_pi)) elliptic_pi - sage: elliptic_pi(x, pi/4, 1)._sympy_() + sage: elliptic_pi(x, pi/4, 1)._sympy_() # needs sympy sage.symbolic elliptic_pi(x, pi/4, 1) """ BuiltinFunction.__init__(self, 'elliptic_pi', nargs=3, @@ -1119,9 +1134,9 @@ def _eval_(self, n, z, m): """ EXAMPLES:: - sage: elliptic_pi(x,x,pi) + sage: elliptic_pi(x, x, pi) # needs sympy sage.symbolic elliptic_pi(x, x, pi) - sage: elliptic_pi(0,x,pi) + sage: elliptic_pi(0, x, pi) # needs sympy sage.symbolic elliptic_f(x, pi) """ if n == 0: @@ -1131,32 +1146,33 @@ def _evalf_(self, n, z, m, parent=None, algorithm=None): """ EXAMPLES:: - sage: elliptic_pi(pi,1/2,1).n() + sage: # needs sage.symbolic + sage: elliptic_pi(pi, 1/2, 1).n() 0.795062820631931 - sage: elliptic_pi(pi,1/2,1).n(200) + sage: elliptic_pi(pi, 1/2, 1).n(200) 0.79506282063193125292514098445... - sage: elliptic_pi(pi,1,1).n() + sage: elliptic_pi(pi, 1, 1).n() 0.0991592574231369 - 1.30004368185937*I - sage: elliptic_pi(pi,I,I).n() + sage: elliptic_pi(pi, I, I).n() 0.0542471560940594 + 0.552096453413081*I """ - R = parent or parent(z) - from mpmath import ellippi - return mpmath_utils.call(ellippi, n, z, m, parent=R) + R = parent or s_parent(z) + return _mpmath_utils_call(_mpmath_ellippi, n, z, m, parent=R) def _derivative_(self, n, z, m, diff_param): """ EXAMPLES:: - sage: n,z,m = var('n,z,m') - sage: elliptic_pi(n,z,m).diff(n) + sage: # needs sage.symbolic + sage: n, z, m = var('n,z,m') + sage: elliptic_pi(n, z, m).diff(n) 1/4*(sqrt(-m*sin(z)^2 + 1)*n*sin(2*z)/(n*sin(z)^2 - 1) + 2*(m - n)*elliptic_f(z, m)/n + 2*(n^2 - m)*elliptic_pi(n, z, m)/n + 2*elliptic_e(z, m))/((m - n)*(n - 1)) - sage: elliptic_pi(n,z,m).diff(z) + sage: elliptic_pi(n, z, m).diff(z) -1/(sqrt(-m*sin(z)^2 + 1)*(n*sin(z)^2 - 1)) - sage: elliptic_pi(n,z,m).diff(m) + sage: elliptic_pi(n, z, m).diff(m) 1/4*(m*sin(2*z)/(sqrt(-m*sin(z)^2 + 1)*(m - 1)) - 2*elliptic_e(z, m)/(m - 1) - 2*elliptic_pi(n, z, m))/(m - n) @@ -1183,7 +1199,7 @@ def _print_latex_(self, n, z, m): r""" EXAMPLES:: - sage: latex(elliptic_pi(x,pi,0)) + sage: latex(elliptic_pi(x, pi, 0)) # needs sage.symbolic \Pi(x,\pi,0) """ return r"\Pi(%s,%s,%s)" % (latex(n), latex(z), latex(m)) diff --git a/src/sage/functions/spike_function.py b/src/sage/functions/spike_function.py index 83fde81b0ca..4739ca7ffb4 100644 --- a/src/sage/functions/spike_function.py +++ b/src/sage/functions/spike_function.py @@ -20,10 +20,11 @@ import math from sage.misc.lazy_import import lazy_import -lazy_import("sage.plot.all", "line") -from sage.modules.free_module_element import vector from sage.rings.real_double import RDF +lazy_import('sage.modules.free_module_element', 'vector') +lazy_import('sage.plot.all', 'line') + class SpikeFunction: """ @@ -31,9 +32,9 @@ class SpikeFunction: INPUT: - - ``v`` - list of pairs (x, height) + - ``v`` -- list of pairs (x, height) - - ``eps`` - parameter that determines approximation to a true spike + - ``eps`` -- parameter that determines approximation to a true spike OUTPUT: @@ -41,12 +42,12 @@ class SpikeFunction: EXAMPLES:: - sage: spike_function([(-3,4),(-1,1),(2,3)],0.001) + sage: spike_function([(-3,4), (-1,1), (2,3)], 0.001) A spike function with spikes at [-3.0, -1.0, 2.0] Putting the spikes too close together may delete some:: - sage: spike_function([(1,1),(1.01,4)],0.1) + sage: spike_function([(1,1), (1.01,4)], 0.1) Some overlapping spikes have been deleted. You might want to use a smaller value for eps. A spike function with spikes at [1.0] @@ -55,10 +56,9 @@ class SpikeFunction: ``spike_function``, but one can use it directly:: sage: from sage.functions.spike_function import SpikeFunction - sage: S = SpikeFunction([(0,1),(1,2),(pi,-5)]) - sage: S + sage: S = SpikeFunction([(0,1), (1,2), (pi,-5)]); S # needs sage.symbolic A spike function with spikes at [0.0, 1.0, 3.141592653589793] - sage: S.support + sage: S.support # needs sage.symbolic [0.0, 1.0, 3.141592653589793] """ def __init__(self, v, eps=0.0000001): @@ -67,7 +67,7 @@ def __init__(self, v, eps=0.0000001): EXAMPLES:: - sage: S = spike_function([(-3,4),(-1,1),(2,3)],0.001); S + sage: S = spike_function([(-3,4), (-1,1), (2,3)], 0.001); S A spike function with spikes at [-3.0, -1.0, 2.0] sage: S.height [4.0, 1.0, 3.0] @@ -99,7 +99,7 @@ def __repr__(self): EXAMPLES:: - sage: spike_function([(-3,4),(-1,1),(2,3)],0.001) + sage: spike_function([(-3,4), (-1,1), (2,3)], 0.001) A spike function with spikes at [-3.0, -1.0, 2.0] """ return "A spike function with spikes at %s" % self.support @@ -113,7 +113,7 @@ def _eval(self, x): EXAMPLES:: - sage: S = spike_function([(0,5)],eps=.001) + sage: S = spike_function([(0,5)], eps=.001) sage: S(0) 5.0 sage: S(.1) @@ -156,10 +156,10 @@ def plot_fft_abs(self, samples=2**12, xmin=None, xmax=None, **kwds): EXAMPLES:: - sage: S = spike_function([(-3,4),(-1,1),(2,3)]); S + sage: S = spike_function([(-3,4), (-1,1), (2,3)]); S A spike function with spikes at [-3.0, -1.0, 2.0] - sage: P = S.plot_fft_abs(8) - sage: p = P[0]; p.ydata # abs tol 1e-8 + sage: P = S.plot_fft_abs(8) # needs sage.plot + sage: p = P[0]; p.ydata # abs tol 1e-8 # needs sage.plot [5.0, 5.0, 3.367958691924177, 3.367958691924177, 4.123105625617661, 4.123105625617661, 4.759921664218055, 4.759921664218055] """ @@ -175,10 +175,10 @@ def plot_fft_arg(self, samples=2**12, xmin=None, xmax=None, **kwds): EXAMPLES:: - sage: S = spike_function([(-3,4),(-1,1),(2,3)]); S + sage: S = spike_function([(-3,4), (-1,1), (2,3)]); S A spike function with spikes at [-3.0, -1.0, 2.0] - sage: P = S.plot_fft_arg(8) - sage: p = P[0]; p.ydata # abs tol 1e-8 + sage: P = S.plot_fft_arg(8) # needs sage.plot + sage: p = P[0]; p.ydata # abs tol 1e-8 # needs sage.plot [0.0, 0.0, -0.211524990023434, -0.211524990023434, 0.244978663126864, 0.244978663126864, -0.149106180027477, -0.149106180027477] @@ -194,9 +194,9 @@ def vector(self, samples=2**16, xmin=None, xmax=None): EXAMPLES:: - sage: S = spike_function([(-3,4),(-1,1),(2,3)],0.001); S + sage: S = spike_function([(-3,4), (-1,1), (2,3)],0.001); S A spike function with spikes at [-3.0, -1.0, 2.0] - sage: S.vector(16) + sage: S.vector(16) # needs sage.modules (4.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) """ @@ -220,8 +220,8 @@ def _ranges(self, xmin, xmax): EXAMPLES:: - sage: S = spike_function([(-1,1),(1,40)]) - sage: S._ranges(None,None) + sage: S = spike_function([(-1,1), (1,40)]) + sage: S._ranges(None, None) (-1.0, 1.0) """ width = (self.support[-1] + self.support[0])/float(2) @@ -239,9 +239,9 @@ def plot(self, xmin=None, xmax=None, **kwds): EXAMPLES:: - sage: S = spike_function([(-1,1),(1,40)]) - sage: P = plot(S) - sage: P[0] + sage: S = spike_function([(-1,1), (1,40)]) + sage: P = plot(S) # needs sage.plot + sage: P[0] # needs sage.plot Line defined by 8 points """ v = [] diff --git a/src/sage/functions/transcendental.py b/src/sage/functions/transcendental.py index bafa3283990..d0a30362fdf 100644 --- a/src/sage/functions/transcendental.py +++ b/src/sage/functions/transcendental.py @@ -15,25 +15,26 @@ # # https://www.gnu.org/licenses/ # **************************************************************************** +import math import sys +from sage.misc.lazy_import import lazy_import from sage.misc.misc import increase_recursion_limit from sage.rings.integer_ring import ZZ -from sage.rings.real_mpfr import RR -from sage.rings.real_double import RDF -from sage.rings.complex_mpfr import ComplexField, is_ComplexNumber -from sage.rings.cc import CC -from sage.rings.real_mpfr import (RealField, is_RealNumber) - from sage.symbolic.function import GinacFunction, BuiltinFunction -import sage.libs.mpmath.utils as mpmath_utils -from sage.combinat.combinat import bernoulli_polynomial +lazy_import('sage.functions.gamma', 'psi') +lazy_import('sage.functions.other', 'factorial') -from .gamma import psi -from .other import factorial +lazy_import('sage.combinat.combinat', 'bernoulli_polynomial') +lazy_import('sage.rings.cc', 'CC') +lazy_import('sage.rings.complex_mpfr', ['ComplexField', 'is_ComplexNumber']) +lazy_import('sage.rings.polynomial.polynomial_real_mpfr_dense', 'PolynomialRealDense') +lazy_import('sage.rings.real_double', 'RDF') +lazy_import('sage.rings.real_mpfr', ['RR', 'RealField', 'is_RealNumber']) -I = CC.gen(0) +lazy_import('sage.libs.mpmath.utils', 'call', as_='_mpmath_utils_call') +lazy_import('mpmath', 'zeta', as_='_mpmath_zeta') class Function_zeta(GinacFunction): @@ -45,21 +46,23 @@ def __init__(self): - ``s`` - real or complex number - If s is a real number the computation is done using the MPFR + If s is a real number, the computation is done using the MPFR library. When the input is not real, the computation is done using the PARI C library. EXAMPLES:: + sage: RR = RealField(200) # needs sage.rings.real_mpfr + sage: zeta(RR(2)) # needs sage.rings.real_mpfr + 1.6449340668482264364724151666460251892189499012067984377356 + + sage: # needs sage.symbolic sage: zeta(x) zeta(x) sage: zeta(2) 1/6*pi^2 sage: zeta(2.) 1.64493406684823 - sage: RR = RealField(200) - sage: zeta(RR(2)) - 1.6449340668482264364724151666460251892189499012067984377356 sage: zeta(I) zeta(I) sage: zeta(I).n() @@ -72,80 +75,81 @@ def __init__(self): It is possible to use the ``hold`` argument to prevent automatic evaluation:: - sage: zeta(2,hold=True) + sage: zeta(2, hold=True) # needs sage.symbolic zeta(2) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: a = zeta(2,hold=True); a.simplify() + sage: a = zeta(2, hold=True); a.simplify() # needs sage.symbolic 1/6*pi^2 The Laurent expansion of `\zeta(s)` at `s=1` is implemented by means of the :wikipedia:`Stieltjes constants `:: - sage: s = SR('s') - sage: zeta(s).series(s==1, 2) + sage: s = SR('s') # needs sage.symbolic + sage: zeta(s).series(s==1, 2) # needs sage.symbolic 1*(s - 1)^(-1) + euler_gamma + (-stieltjes(1))*(s - 1) + Order((s - 1)^2) Generally, the Stieltjes constants occur in the Laurent expansion of `\zeta`-type singularities:: - sage: zeta(2*s/(s+1)).series(s==1, 2) + sage: zeta(2*s/(s+1)).series(s==1, 2) # needs sage.symbolic 2*(s - 1)^(-1) + (euler_gamma + 1) + (-1/2*stieltjes(1))*(s - 1) + Order((s - 1)^2) TESTS:: + sage: # needs sage.symbolic sage: latex(zeta(x)) \zeta(x) sage: a = loads(dumps(zeta(x))) sage: a.operator() == zeta True - sage: zeta(x)._sympy_() + sage: zeta(x)._sympy_() # needs sympy zeta(x) - sage: zeta(1) + sage: zeta(1) # needs sage.symbolic Infinity - sage: zeta(x).subs(x=1) + sage: zeta(x).subs(x=1) # needs sage.symbolic Infinity Check that :trac:`19799` is resolved:: - sage: zeta(pi) + sage: zeta(pi) # needs sage.symbolic zeta(pi) - sage: zeta(pi).n() # rel tol 1e-10 + sage: zeta(pi).n() # rel tol 1e-10 # needs sage.symbolic 1.17624173838258 Check that :trac:`20082` is fixed:: - sage: zeta(x).series(x==pi, 2) + sage: zeta(x).series(x==pi, 2) # needs sage.symbolic (zeta(pi)) + (zetaderiv(1, pi))*(-pi + x) + Order((pi - x)^2) - sage: (zeta(x) * 1/(1 - exp(-x))).residue(x==2*pi*I) + sage: (zeta(x) * 1/(1 - exp(-x))).residue(x==2*pi*I) # needs sage.symbolic zeta(2*I*pi) Check that :trac:`20102` is fixed:: - sage: (zeta(x)^2).series(x==1, 1) + sage: (zeta(x)^2).series(x==1, 1) # needs sage.symbolic 1*(x - 1)^(-2) + (2*euler_gamma)*(x - 1)^(-1) + (euler_gamma^2 - 2*stieltjes(1)) + Order(x - 1) - sage: (zeta(x)^4).residue(x==1) + sage: (zeta(x)^4).residue(x==1) # needs sage.symbolic 4/3*euler_gamma*(3*euler_gamma^2 - 2*stieltjes(1)) - 28/3*euler_gamma*stieltjes(1) + 2*stieltjes(2) Check that the right infinities are returned (:trac:`19439`):: - sage: zeta(1.0) + sage: zeta(1.0) # needs sage.symbolic +infinity - sage: zeta(SR(1.0)) + sage: zeta(SR(1.0)) # needs sage.symbolic Infinity Fixed conversion:: - sage: zeta(3)._maple_init_() + sage: zeta(3)._maple_init_() # needs sage.symbolic 'Zeta(3)' - sage: zeta(3)._maple_().sage() # optional - maple + sage: zeta(3)._maple_().sage() # optional - maple # needs sage.symbolic zeta(3) """ GinacFunction.__init__(self, 'zeta', @@ -173,6 +177,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: _ = var('n') sage: stieltjes(n) stieltjes(n) @@ -184,25 +189,26 @@ def __init__(self): stieltjes(2) sage: stieltjes(2).n(100) -0.0096903631928723184845303860352 - sage: RR = RealField(200) - sage: stieltjes(RR(2)) + sage: RR = RealField(200) # needs sage.rings.real_mpfr + sage: stieltjes(RR(2)) # needs sage.rings.real_mpfr -0.0096903631928723184845303860352125293590658061013407498807014 It is possible to use the ``hold`` argument to prevent automatic evaluation:: - sage: stieltjes(0,hold=True) + sage: stieltjes(0, hold=True) # needs sage.symbolic stieltjes(0) + sage: # needs sage.symbolic sage: latex(stieltjes(n)) \gamma_{n} sage: a = loads(dumps(stieltjes(n))) sage: a.operator() == stieltjes True - sage: stieltjes(x)._sympy_() + sage: stieltjes(x)._sympy_() # needs sympy stieltjes(x) - sage: stieltjes(x).subs(x==0) + sage: stieltjes(x).subs(x==0) # needs sage.symbolic euler_gamma """ GinacFunction.__init__(self, "stieltjes", nargs=1, @@ -219,9 +225,9 @@ def __init__(self): r""" TESTS:: - sage: latex(hurwitz_zeta(x, 2)) + sage: latex(hurwitz_zeta(x, 2)) # needs sage.symbolic \zeta\left(x, 2\right) - sage: hurwitz_zeta(x, 2)._sympy_() + sage: hurwitz_zeta(x, 2)._sympy_() # needs sympy sage.symbolic zeta(x, 2) """ BuiltinFunction.__init__(self, 'hurwitz_zeta', nargs=2, @@ -233,16 +239,18 @@ def _eval_(self, s, x): r""" TESTS:: + sage: # needs sage.symbolic 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 sage: hurwitz_zeta(0, x) -x + 1/2 + + sage: hurwitz_zeta(3, 0.5) # needs mpmath + 8.41439832211716 """ if x == 1: return zeta(s) @@ -257,22 +265,21 @@ def _evalf_(self, s, x, parent=None, algorithm=None): r""" TESTS:: - sage: hurwitz_zeta(11/10, 1/2).n() + sage: hurwitz_zeta(11/10, 1/2).n() # needs sage.symbolic 12.1038134956837 - sage: hurwitz_zeta(11/10, 1/2).n(100) + sage: hurwitz_zeta(11/10, 1/2).n(100) # needs sage.symbolic 12.103813495683755105709077413 sage: hurwitz_zeta(11/10, 1 + 1j).n() 9.85014164287853 - 1.06139499403981*I """ - from mpmath import zeta - return mpmath_utils.call(zeta, s, x, parent=parent) + return _mpmath_utils_call(_mpmath_zeta, s, x, parent=parent) def _derivative_(self, s, x, diff_param): r""" TESTS:: - sage: y = var('y') - sage: diff(hurwitz_zeta(x, y), y) + sage: y = var('y') # needs sage.symbolic + sage: diff(hurwitz_zeta(x, y), y) # needs sage.symbolic -x*hurwitz_zeta(x + 1, y) """ if diff_param == 1: @@ -305,6 +312,7 @@ def hurwitz_zeta(s, x, **kwargs): Symbolic evaluations:: + sage: # needs sage.symbolic sage: hurwitz_zeta(x, 1) zeta(x) sage: hurwitz_zeta(4, 3) @@ -318,13 +326,13 @@ def hurwitz_zeta(s, x, **kwargs): Numerical evaluations:: - sage: hurwitz_zeta(3, 1/2).n() + sage: hurwitz_zeta(3, 1/2).n() # needs mpmath 8.41439832211716 - sage: hurwitz_zeta(11/10, 1/2).n() + sage: hurwitz_zeta(11/10, 1/2).n() # needs sage.symbolic 12.1038134956837 - sage: hurwitz_zeta(3, x).series(x, 60).subs(x=0.5).n() + sage: hurwitz_zeta(3, x).series(x, 60).subs(x=0.5).n() # needs sage.symbolic 8.41439832211716 - sage: hurwitz_zeta(3, 0.5) + sage: hurwitz_zeta(3, 0.5) # needs mpmath 8.41439832211716 REFERENCES: @@ -341,31 +349,32 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: zetaderiv(1, x) zetaderiv(1, x) sage: zetaderiv(1, x).diff(x) zetaderiv(2, x) sage: var('n') n - sage: zetaderiv(n,x) + sage: zetaderiv(n, x) zetaderiv(n, x) sage: zetaderiv(1, 4).n() -0.0689112658961254 - sage: import mpmath; mpmath.diff(lambda x: mpmath.zeta(x), 4) + sage: import mpmath; mpmath.diff(lambda x: mpmath.zeta(x), 4) # needs mpmath mpf('-0.068911265896125382') TESTS:: - sage: latex(zetaderiv(2,x)) + sage: latex(zetaderiv(2, x)) # needs sage.symbolic \zeta^\prime\left(2, x\right) - sage: a = loads(dumps(zetaderiv(2,x))) - sage: a.operator() == zetaderiv + sage: a = loads(dumps(zetaderiv(2, x))) # needs sage.symbolic + sage: a.operator() == zetaderiv # needs sage.symbolic True - sage: b = RBF(3/2, 1e-10) - sage: zetaderiv(1, b, hold=True) + sage: b = RBF(3/2, 1e-10) # needs sage.libs.flint + sage: zetaderiv(1, b, hold=True) # needs sage.libs.flint sage.symbolic zetaderiv(1, [1.500000000 +/- 1.01e-10]) - sage: zetaderiv(b, 1) + sage: zetaderiv(b, 1) # needs sage.libs.flint sage.symbolic zetaderiv([1.500000000 +/- 1.01e-10], 1) """ GinacFunction.__init__(self, "zetaderiv", nargs=2, @@ -375,19 +384,18 @@ def _evalf_(self, n, x, parent=None, algorithm=None): r""" TESTS:: - sage: zetaderiv(0, 3, hold=True).n() == zeta(3).n() + sage: zetaderiv(0, 3, hold=True).n() == zeta(3).n() # needs sage.symbolic True - sage: zetaderiv(2, 3 + I).n() + sage: zetaderiv(2, 3 + I).n() # needs sage.symbolic 0.0213814086193841 - 0.174938812330834*I """ - from mpmath import zeta - return mpmath_utils.call(zeta, x, 1, n, parent=parent) + return _mpmath_utils_call(_mpmath_zeta, x, 1, n, parent=parent) def _method_arguments(self, k, x, **args): r""" TESTS:: - sage: zetaderiv(1, RBF(3/2, 0.0001)) + sage: zetaderiv(1, RBF(3/2, 0.0001)) # needs sage.libs.flint [-3.93 +/- ...e-3] """ return [x, k] @@ -422,13 +430,16 @@ def zeta_symmetric(s): EXAMPLES:: - sage: zeta_symmetric(0.7) - 0.497580414651127 - sage: zeta_symmetric(1-0.7) - 0.497580414651127 + sage: # needs sage.rings.real_mpfr sage: RR = RealField(200) sage: zeta_symmetric(RR(0.7)) 0.49758041465112690357779107525638385212657443284080589766062 + + sage: # needs sage.libs.pari sage.rings.real_mpfr + sage: zeta_symmetric(0.7) + 0.497580414651127 + sage: zeta_symmetric(1 - 0.7) + 0.497580414651127 sage: C. = ComplexField() sage: zeta_symmetric(0.5 + i*14.0) 0.000201294444235258 + 1.49077798716757e-19*I @@ -452,10 +463,6 @@ def zeta_symmetric(s): return (s/2 + 1).gamma() * (s-1) * (R.pi()**(-s/2)) * s.zeta() -import math -from sage.rings.polynomial.polynomial_real_mpfr_dense import PolynomialRealDense - - class DickmanRho(BuiltinFunction): r""" Dickman's function is the continuous function satisfying the @@ -490,13 +497,14 @@ class DickmanRho(BuiltinFunction): EXAMPLES:: + sage: # needs sage.symbolic sage: dickman_rho(2) 0.306852819440055 sage: dickman_rho(10) 2.77017183772596e-11 sage: dickman_rho(10.00000000000000000000000000000000000000) 2.77017183772595898875812120063434232634e-11 - sage: plot(log(dickman_rho(x)), (x, 0, 15)) + sage: plot(log(dickman_rho(x)), (x, 0, 15)) # needs sage.plot Graphics object consisting of 1 graphics primitive AUTHORS: @@ -515,11 +523,11 @@ def __init__(self): TESTS:: - sage: dickman_rho(x) + sage: dickman_rho(x) # needs sage.symbolic dickman_rho(x) - sage: dickman_rho(3) + sage: dickman_rho(3) # needs sage.symbolic 0.0486083882911316 - sage: dickman_rho(pi) + sage: dickman_rho(pi) # needs sage.symbolic 0.0359690758968463 """ self._cur_prec = 0 @@ -529,9 +537,12 @@ def _eval_(self, x): """ EXAMPLES:: - sage: [dickman_rho(n) for n in [1..10]] - [1.00000000000000, 0.306852819440055, 0.0486083882911316, 0.00491092564776083, 0.000354724700456040, 0.0000196496963539553, 8.74566995329392e-7, 3.23206930422610e-8, 1.01624828273784e-9, 2.77017183772596e-11] - sage: dickman_rho(0) + sage: [dickman_rho(n) for n in [1..10]] # needs sage.symbolic + [1.00000000000000, 0.306852819440055, 0.0486083882911316, + 0.00491092564776083, 0.000354724700456040, 0.0000196496963539553, + 8.74566995329392e-7, 3.23206930422610e-8, 1.01624828273784e-9, + 2.77017183772596e-11] + sage: dickman_rho(0) # needs sage.symbolic 1.00000000000000 """ if not is_RealNumber(x): @@ -576,7 +587,7 @@ def power_series(self, n, abs_prec): -9.9376e-8*x^11 + 3.7722e-7*x^10 - 1.4684e-6*x^9 + 5.8783e-6*x^8 - 0.000024259*x^7 + 0.00010341*x^6 - 0.00045583*x^5 + 0.0020773*x^4 - 0.0097336*x^3 + 0.045224*x^2 - 0.11891*x + 0.13032 sage: f(-1), f(0), f(1) (0.30685, 0.13032, 0.048608) - sage: dickman_rho(2), dickman_rho(2.5), dickman_rho(3) + sage: dickman_rho(2), dickman_rho(2.5), dickman_rho(3) # needs sage.symbolic (0.306852819440055, 0.130319561832251, 0.0486083882911316) """ return self._compute_power_series(n, abs_prec, cache_ring=None) @@ -654,11 +665,11 @@ def approximate(self, x, parent=None): EXAMPLES:: - sage: dickman_rho.approximate(10) + sage: dickman_rho.approximate(10) # needs sage.rings.real_mpfr 2.41739196365564e-11 - sage: dickman_rho(10) + sage: dickman_rho(10) # needs sage.symbolic 2.77017183772596e-11 - sage: dickman_rho.approximate(1000) + sage: dickman_rho.approximate(1000) # needs sage.rings.real_mpfr 4.32938809066403e-3464 """ log, exp, sqrt, pi = math.log, math.exp, math.sqrt, math.pi diff --git a/src/sage/functions/trig.py b/src/sage/functions/trig.py index 16aeeae43ab..62e5bd35b2e 100644 --- a/src/sage/functions/trig.py +++ b/src/sage/functions/trig.py @@ -1,9 +1,10 @@ r""" Trigonometric functions """ -from sage.symbolic.function import GinacFunction import math +from sage.symbolic.function import GinacFunction + class Function_sin(GinacFunction): def __init__(self): @@ -12,45 +13,48 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: sin(0) 0 sage: sin(x).subs(x==0) 0 sage: sin(2).n(100) 0.90929742682568169539601986591 - sage: loads(dumps(sin)) - sin - sage: sin(x)._sympy_() + sage: sin(x)._sympy_() # needs sympy sin(x) We can prevent evaluation using the ``hold`` parameter:: - sage: sin(0,hold=True) + sage: sin(0, hold=True) # needs sage.symbolic sin(0) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: a = sin(0,hold=True); a.simplify() + sage: a = sin(0, hold=True); a.simplify() # needs sage.symbolic 0 If possible, the argument is also reduced modulo the period length `2\pi`, and well-known identities are directly evaluated:: - sage: k = var('k', domain='integer') - sage: sin(1 + 2*k*pi) + sage: k = var('k', domain='integer') # needs sage.symbolic + sage: sin(1 + 2*k*pi) # needs sage.symbolic sin(1) - sage: sin(k*pi) + sage: sin(k*pi) # needs sage.symbolic 0 TESTS:: - sage: conjugate(sin(x)) + sage: loads(dumps(sin)) + sin + + sage: conjugate(sin(x)) # needs sage.symbolic sin(conjugate(x)) sage: sin(complex(1,1)) # rel tol 1e-15 (1.2984575814159773+0.6349639147847361j) + sage: # needs sage.symbolic sage: sin(pi/5) 1/4*sqrt(-2*sqrt(5) + 10) sage: sin(pi/8) @@ -94,27 +98,33 @@ def __init__(self): sage: csc(104*pi/105) csc(1/105*pi) - sage: all(sin(rat*pi).n(200)-sin(rat*pi,hold=True).n(200) < 1e-30 for rat in [1/5,2/5,1/30,7/30,11/30,13/30,1/8,3/8,1/24,5/24,7/24,11/24]) + sage: all(sin(rat*pi).n(200) - sin(rat*pi, hold=True).n(200) < 1e-30 # needs sage.symbolic + ....: for rat in [1/5, 2/5, 1/30, 7/30, 11/30, 13/30, + ....: 1/8, 3/8, 1/24, 5/24, 7/24, 11/24]) True - sage: all(cos(rat*pi).n(200)-cos(rat*pi,hold=True).n(200) < 1e-30 for rat in [1/10,3/10,1/12,5/12,1/15,2/15,4/15,7/15,1/8,3/8,1/24,5/24,11/24]) + sage: all(cos(rat*pi).n(200)-cos(rat*pi, hold=True).n(200) < 1e-30 # needs sage.symbolic + ....: for rat in [1/10, 3/10, 1/12, 5/12, 1/15, 2/15, 4/15, 7/15, + ....: 1/8, 3/8, 1/24, 5/24, 11/24]) True - sage: all(tan(rat*pi).n(200)-tan(rat*pi,hold=True).n(200) < 1e-30 for rat in [1/5,2/5,1/10,3/10,1/20,3/20,7/20,9/20,1/8,3/8,1/16,3/16,5/16,7/16,1/24,5/24,7/24,11/24]) + sage: all(tan(rat*pi).n(200)-tan(rat*pi, hold=True).n(200) < 1e-30 # needs sage.symbolic + ....: for rat in [1/5, 2/5, 1/10, 3/10, 1/20, 3/20, 7/20, 9/20, + ....: 1/8, 3/8, 1/16, 3/16, 5/16, 7/16, 1/24, 5/24, 7/24, 11/24]) True Check that :trac:`20456` is fixed:: - sage: assume(x>0) - sage: sin(pi*x) + sage: assume(x > 0) # needs sage.symbolic + sage: sin(pi*x) # needs sage.symbolic sin(pi*x) - sage: forget() + sage: forget() # needs sage.symbolic Check that :trac:`20752` is fixed:: - sage: sin(3*pi+41/42*pi) + sage: sin(3*pi + 41/42*pi) # needs sage.symbolic -sin(1/42*pi) - sage: sin(-5*pi+1/42*pi) + sage: sin(-5*pi + 1/42*pi) # needs sage.symbolic -sin(1/42*pi) - sage: sin(pi-1/42*pi) + sage: sin(pi - 1/42*pi) # needs sage.symbolic sin(1/42*pi) """ GinacFunction.__init__(self, 'sin', latex_name=r"\sin", @@ -132,32 +142,32 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: cos(pi) -1 sage: cos(x).subs(x==pi) -1 sage: cos(2).n(100) -0.41614683654714238699756822950 - sage: loads(dumps(cos)) - cos - sage: cos(x)._sympy_() + sage: cos(x)._sympy_() # needs sympy cos(x) We can prevent evaluation using the ``hold`` parameter:: - sage: cos(0,hold=True) + sage: cos(0, hold=True) # needs sage.symbolic cos(0) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: a = cos(0,hold=True); a.simplify() + sage: a = cos(0, hold=True); a.simplify() # needs sage.symbolic 1 If possible, the argument is also reduced modulo the period length `2\pi`, and well-known identities are directly evaluated:: + sage: # needs sage.symbolic sage: k = var('k', domain='integer') sage: cos(1 + 2*k*pi) cos(1) @@ -168,18 +178,21 @@ def __init__(self): TESTS:: - sage: conjugate(cos(x)) + sage: loads(dumps(cos)) + cos + + sage: conjugate(cos(x)) # needs sage.symbolic cos(conjugate(x)) sage: cos(complex(1,1)) # rel tol 1e-15 (0.8337300251311491-0.9888977057628651j) Check that :trac:`20752` is fixed:: - sage: cos(3*pi+41/42*pi) + sage: cos(3*pi + 41/42*pi) # needs sage.symbolic cos(1/42*pi) - sage: cos(-5*pi+1/42*pi) + sage: cos(-5*pi + 1/42*pi) # needs sage.symbolic -cos(1/42*pi) - sage: cos(pi-1/42*pi) + sage: cos(pi - 1/42*pi) # needs sage.symbolic -cos(1/42*pi) """ GinacFunction.__init__(self, 'cos', latex_name=r"\cos", @@ -197,12 +210,14 @@ def __init__(self): EXAMPLES:: - sage: tan(pi) - 0 sage: tan(3.1415) -0.0000926535900581913 sage: tan(3.1415/4) 0.999953674278156 + + sage: # needs sage.symbolic + sage: tan(pi) + 0 sage: tan(pi/4) 1 sage: tan(1/2) @@ -212,37 +227,37 @@ def __init__(self): We can prevent evaluation using the ``hold`` parameter:: - sage: tan(pi/4,hold=True) + sage: tan(pi/4, hold=True) # needs sage.symbolic tan(1/4*pi) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: a = tan(pi/4,hold=True); a.simplify() + sage: a = tan(pi/4, hold=True); a.simplify() # needs sage.symbolic 1 If possible, the argument is also reduced modulo the period length `\pi`, and well-known identities are directly evaluated:: - sage: k = var('k', domain='integer') - sage: tan(1 + 2*k*pi) + sage: k = var('k', domain='integer') # needs sage.symbolic + sage: tan(1 + 2*k*pi) # needs sage.symbolic tan(1) - sage: tan(k*pi) + sage: tan(k*pi) # needs sage.symbolic 0 TESTS:: - sage: tan(x)._sympy_() + sage: tan(x)._sympy_() # needs sympy sage.symbolic tan(x) - sage: conjugate(tan(x)) + sage: conjugate(tan(x)) # needs sage.symbolic tan(conjugate(x)) sage: tan(complex(1,1)) # rel tol 1e-15 (0.2717525853195118+1.0839233273386946j) Check that :trac:`19791` is fixed:: - sage: tan(2+I).imag().n() + sage: tan(2+I).imag().n() # needs sage.symbolic 1.16673625724092 """ GinacFunction.__init__(self, 'tan', latex_name=r"\tan") @@ -258,6 +273,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: cot(pi/4) 1 sage: RR(cot(pi/4)) @@ -267,24 +283,25 @@ def __init__(self): sage: cot(0.5) 1.83048772171245 - sage: latex(cot(x)) + sage: latex(cot(x)) # needs sage.symbolic \cot\left(x\right) - sage: cot(x)._sympy_() + sage: cot(x)._sympy_() # needs sympy sage.symbolic cot(x) We can prevent evaluation using the ``hold`` parameter:: - sage: cot(pi/4,hold=True) + sage: cot(pi/4, hold=True) # needs sage.symbolic cot(1/4*pi) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: a = cot(pi/4,hold=True); a.simplify() + sage: a = cot(pi/4, hold=True); a.simplify() # needs sage.symbolic 1 EXAMPLES:: + sage: # needs sage.symbolic sage: cot(pi/4) 1 sage: cot(x).subs(x==pi/4) @@ -294,7 +311,8 @@ def __init__(self): sage: cot(x) cot(x) - sage: n(cot(pi/4),100) + sage: # needs sage.symbolic + sage: n(cot(pi/4), 100) 1.0000000000000000000000000000 sage: float(cot(1)) 0.64209261593433... @@ -305,29 +323,29 @@ def __init__(self): TESTS:: - sage: cot(float(0)) + sage: cot(float(0)) # needs sage.symbolic Infinity - sage: cot(SR(0)) + sage: cot(SR(0)) # needs sage.symbolic Infinity - sage: cot(float(0.1)) + sage: cot(float(0.1)) # needs sage.symbolic 9.966644423259238 sage: type(_) <... 'float'> - sage: cot(float(0)) + sage: cot(float(0)) # needs sage.symbolic Infinity - sage: cot(SR(0)) + sage: cot(SR(0)) # needs sage.symbolic Infinity - sage: cot(float(0.1)) + sage: cot(float(0.1)) # needs sage.symbolic 9.966644423259238 sage: type(_) <... 'float'> Test complex input:: - sage: cot(complex(1,1)) # rel tol 1e-15 + sage: cot(complex(1,1)) # rel tol 1e-15 # needs sage.rings.complex_double (0.21762156185440273-0.8680141428959249j) - sage: cot(1.+I) + sage: cot(1.+I) # needs sage.symbolic 0.217621561854403 - 0.868014142895925*I """ GinacFunction.__init__(self, 'cot', latex_name=r"\cot") @@ -336,9 +354,9 @@ def _eval_numpy_(self, x): """ EXAMPLES:: - sage: import numpy - sage: a = numpy.arange(2, 5) - sage: cot(a) + sage: import numpy # needs numpy + sage: a = numpy.arange(2, 5) # needs numpy + sage: cot(a) # needs numpy array([-0.45765755, -7.01525255, 0.86369115]) """ return 1.0 / tan(x) @@ -354,6 +372,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: sec(pi/4) sqrt(2) sage: sec(x).subs(x==pi/4) @@ -373,31 +392,32 @@ def __init__(self): sage: sec(0.5) 1.13949392732455 + sage: # needs sage.symbolic sage: bool(diff(sec(x), x) == diff(1/cos(x), x)) True sage: diff(sec(x), x) sec(x)*tan(x) sage: latex(sec(x)) \sec\left(x\right) - sage: sec(x)._sympy_() + sage: sec(x)._sympy_() # needs sympy sec(x) We can prevent evaluation using the ``hold`` parameter:: - sage: sec(pi/4,hold=True) + sage: sec(pi/4, hold=True) # needs sage.symbolic sec(1/4*pi) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: a = sec(pi/4,hold=True); a.simplify() + sage: a = sec(pi/4, hold=True); a.simplify() # needs sage.symbolic sqrt(2) TESTS: Test complex input:: - sage: sec(complex(1,1)) # rel tol 1e-15 + sage: sec(complex(1,1)) # rel tol 1e-15 # needs sage.rings.complex_double (0.49833703055518686+0.5910838417210451j) """ GinacFunction.__init__(self, 'sec', latex_name=r"\sec") @@ -406,9 +426,9 @@ def _eval_numpy_(self, x): """ EXAMPLES:: - sage: import numpy - sage: a = numpy.arange(2, 5) - sage: sec(a) + sage: import numpy # needs numpy + sage: a = numpy.arange(2, 5) # needs numpy + sage: sec(a) # needs numpy array([-2.40299796, -1.01010867, -1.52988566]) """ return 1 / cos(x) @@ -424,6 +444,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: csc(pi/4) sqrt(2) sage: csc(x).subs(x==pi/4) @@ -434,7 +455,7 @@ def __init__(self): csc(x) sage: RR(csc(pi/4)) 1.41421356237310 - sage: n(csc(pi/4),100) + sage: n(csc(pi/4), 100) 1.4142135623730950488016887242 sage: float(csc(pi/4)) 1.4142135623730951 @@ -443,31 +464,32 @@ def __init__(self): sage: csc(0.5) 2.08582964293349 + sage: # needs sage.symbolic sage: bool(diff(csc(x), x) == diff(1/sin(x), x)) True sage: diff(csc(x), x) -cot(x)*csc(x) sage: latex(csc(x)) \csc\left(x\right) - sage: csc(x)._sympy_() + sage: csc(x)._sympy_() # needs sympy csc(x) We can prevent evaluation using the ``hold`` parameter:: - sage: csc(pi/4,hold=True) + sage: csc(pi/4, hold=True) # needs sage.symbolic csc(1/4*pi) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: a = csc(pi/4,hold=True); a.simplify() + sage: a = csc(pi/4,hold=True); a.simplify() # needs sage.symbolic sqrt(2) TESTS: Test complex input:: - sage: csc(complex(1,1)) # rel tol 1e-15 + sage: csc(complex(1,1)) # rel tol 1e-15 # needs sage.rings.complex_double (0.6215180171704284-0.30393100162842646j) """ GinacFunction.__init__(self, 'csc', latex_name=r"\csc") @@ -476,9 +498,9 @@ def _eval_numpy_(self, x): """ EXAMPLES:: - sage: import numpy - sage: a = numpy.arange(2, 5) - sage: csc(a) + sage: import numpy # needs numpy + sage: a = numpy.arange(2, 5) # needs numpy + sage: csc(a) # needs numpy array([ 1.09975017, 7.0861674 , -1.32134871]) """ return 1 / sin(x) @@ -500,25 +522,26 @@ def __init__(self): sage: arcsin(0.5) 0.523598775598299 - sage: arcsin(1/2) + sage: arcsin(1/2) # needs sage.symbolic 1/6*pi - sage: arcsin(1 + 1.0*I) + sage: arcsin(1 + 1.0*I) # needs sage.symbolic 0.666239432492515 + 1.06127506190504*I We can delay evaluation using the ``hold`` parameter:: - sage: arcsin(0,hold=True) + sage: arcsin(0, hold=True) # needs sage.symbolic arcsin(0) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: a = arcsin(0,hold=True); a.simplify() + sage: a = arcsin(0, hold=True); a.simplify() # needs sage.symbolic 0 ``conjugate(arcsin(x))==arcsin(conjugate(x))``, unless on the branch cuts which run along the real axis outside the interval [-1, +1].:: + sage: # needs sage.symbolic sage: conjugate(arcsin(x)) conjugate(arcsin(x)) sage: var('y', domain='positive') @@ -536,13 +559,13 @@ def __init__(self): TESTS:: - sage: arcsin(x)._sympy_() + sage: arcsin(x)._sympy_() # needs sympy sage.symbolic asin(x) - sage: arcsin(x).operator() + sage: arcsin(x).operator() # needs sage.symbolic arcsin - sage: asin(complex(1,1)) + sage: asin(complex(1,1)) # needs sage.rings.complex_double (0.6662394324925152+1.0612750619050357j) - sage: asin(SR(2.1)) + sage: asin(SR(2.1)) # needs sage.symbolic 1.57079632679490 - 1.37285914424258*I """ GinacFunction.__init__(self, 'arcsin', latex_name=r"\arcsin", @@ -563,27 +586,28 @@ def __init__(self): sage: arccos(0.5) 1.04719755119660 - sage: arccos(1/2) + sage: arccos(1/2) # needs sage.symbolic 1/3*pi - sage: arccos(1 + 1.0*I) + sage: arccos(1 + 1.0*I) # needs sage.symbolic 0.904556894302381 - 1.06127506190504*I - sage: arccos(3/4).n(100) + sage: arccos(3/4).n(100) # needs sage.symbolic 0.72273424781341561117837735264 We can delay evaluation using the ``hold`` parameter:: - sage: arccos(0,hold=True) + sage: arccos(0, hold=True) # needs sage.symbolic arccos(0) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: a = arccos(0,hold=True); a.simplify() + sage: a = arccos(0, hold=True); a.simplify() # needs sage.symbolic 1/2*pi ``conjugate(arccos(x))==arccos(conjugate(x))``, unless on the branch cuts, which run along the real axis outside the interval [-1, +1].:: + sage: # needs sage.symbolic sage: conjugate(arccos(x)) conjugate(arccos(x)) sage: var('y', domain='positive') @@ -601,13 +625,13 @@ def __init__(self): TESTS:: - sage: arccos(x)._sympy_() + sage: arccos(x)._sympy_() # needs sympy sage.symbolic acos(x) - sage: arccos(x).operator() + sage: arccos(x).operator() # needs sage.symbolic arccos - sage: acos(complex(1,1)) + sage: acos(complex(1,1)) # needs sage.rings.complex_double (0.9045568943023814-1.0612750619050357j) - sage: acos(SR(2.1)) + sage: acos(SR(2.1)) # needs sage.symbolic 1.37285914424258*I """ GinacFunction.__init__(self, 'arccos', latex_name=r"\arccos", @@ -626,6 +650,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: arctan(1/2) arctan(1/2) sage: RDF(arctan(1/2)) # rel tol 1e-15 @@ -637,18 +662,19 @@ def __init__(self): We can delay evaluation using the ``hold`` parameter:: - sage: arctan(0,hold=True) + sage: arctan(0, hold=True) # needs sage.symbolic arctan(0) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: a = arctan(0,hold=True); a.simplify() + sage: a = arctan(0, hold=True); a.simplify() # needs sage.symbolic 0 ``conjugate(arctan(x))==arctan(conjugate(x))``, unless on the branch cuts which run along the imaginary axis outside the interval [-I, +I].:: + sage: # needs sage.symbolic sage: conjugate(arctan(x)) conjugate(arctan(x)) sage: var('y', domain='positive') @@ -668,18 +694,18 @@ def __init__(self): TESTS:: - sage: arctan(x)._sympy_() + sage: arctan(x)._sympy_() # needs sympy sage.symbolic atan(x) - sage: arctan(x).operator() + sage: arctan(x).operator() # needs sage.symbolic arctan - sage: atan(complex(1,1)) + sage: atan(complex(1,1)) # needs sage.rings.complex_double (1.0172219678978514+0.4023594781085251j) Check that :trac:`19918` is fixed:: - sage: arctan(-x).subs(x=oo) + sage: arctan(-x).subs(x=oo) # needs sage.symbolic -1/2*pi - sage: arctan(-x).subs(x=-oo) + sage: arctan(-x).subs(x=-oo) # needs sage.symbolic 1/2*pi """ GinacFunction.__init__(self, 'arctan', latex_name=r"\arctan", @@ -698,6 +724,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: arccot(1/2) arccot(1/2) sage: RDF(arccot(1/2)) # abs tol 2e-16 @@ -715,24 +742,24 @@ def __init__(self): We can delay evaluation using the ``hold`` parameter:: - sage: arccot(1,hold=True) + sage: arccot(1, hold=True) # needs sage.symbolic arccot(1) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: a = arccot(1,hold=True); a.simplify() + sage: a = arccot(1, hold=True); a.simplify() # needs sage.symbolic 1/4*pi TESTS: Test complex input:: - sage: arccot(x)._sympy_() + sage: arccot(x)._sympy_() # needs sympy sage.symbolic acot(x) - sage: arccot(complex(1,1)) # rel tol 1e-15 + sage: arccot(complex(1,1)) # rel tol 1e-15 # needs sage.rings.complex_double (0.5535743588970452-0.4023594781085251j) - sage: arccot(1.+I) + sage: arccot(1.+I) # needs sage.symbolic 0.553574358897045 - 0.402359478108525*I """ @@ -745,9 +772,9 @@ def _eval_numpy_(self, x): """ EXAMPLES:: - sage: import numpy - sage: a = numpy.arange(2, 5) - sage: arccot(a) + sage: import numpy # needs numpy + sage: a = numpy.arange(2, 5) # needs numpy + sage: arccot(a) # needs numpy array([0.46364761, 0.32175055, 0.24497866]) """ return math.pi / 2 - arctan(x) @@ -763,6 +790,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: arccsc(2) arccsc(2) sage: RDF(arccsc(2)) # rel tol 1e-15 @@ -775,25 +803,25 @@ def __init__(self): arccsc(I + 1) sage: diff(acsc(x), x) -1/(sqrt(x^2 - 1)*x) - sage: arccsc(x)._sympy_() + sage: arccsc(x)._sympy_() # needs sympy acsc(x) We can delay evaluation using the ``hold`` parameter:: - sage: arccsc(1,hold=True) + sage: arccsc(1, hold=True) # needs sage.symbolic arccsc(1) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: a = arccsc(1,hold=True); a.simplify() + sage: a = arccsc(1, hold=True); a.simplify() # needs sage.symbolic 1/2*pi TESTS: Test complex input:: - sage: arccsc(complex(1,1)) # rel tol 1e-15 + sage: arccsc(complex(1,1)) # rel tol 1e-15 # needs sage.rings.complex_double (0.45227844715119064-0.5306375309525178j) """ GinacFunction.__init__(self, 'arccsc', latex_name=r"\operatorname{arccsc}", @@ -805,9 +833,9 @@ def _eval_numpy_(self, x): """ EXAMPLES:: - sage: import numpy - sage: a = numpy.arange(2, 5) - sage: arccsc(a) + sage: import numpy # needs numpy + sage: a = numpy.arange(2, 5) # needs numpy + sage: arccsc(a) # needs numpy array([0.52359878, 0.33983691, 0.25268026]) """ return arcsin(1.0 / x) @@ -823,6 +851,7 @@ def __init__(self): EXAMPLES:: + sage: # needs sage.symbolic sage: arcsec(2) arcsec(2) sage: arcsec(2.0) @@ -837,25 +866,25 @@ def __init__(self): arcsec(I + 1) sage: diff(asec(x), x) 1/(sqrt(x^2 - 1)*x) - sage: arcsec(x)._sympy_() + sage: arcsec(x)._sympy_() # needs sympy asec(x) We can delay evaluation using the ``hold`` parameter:: - sage: arcsec(1,hold=True) + sage: arcsec(1, hold=True) # needs sage.symbolic arcsec(1) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: a = arcsec(1,hold=True); a.simplify() + sage: a = arcsec(1, hold=True); a.simplify() # needs sage.symbolic 0 TESTS: Test complex input:: - sage: arcsec(complex(1,1)) # rel tol 1e-15 + sage: arcsec(complex(1,1)) # rel tol 1e-15 # needs sage.rings.complex_double (1.118517879643706+0.5306375309525178j) """ GinacFunction.__init__(self, 'arcsec', latex_name=r"\operatorname{arcsec}", @@ -867,9 +896,9 @@ def _eval_numpy_(self, x): """ EXAMPLES:: - sage: import numpy - sage: a = numpy.arange(2, 5) - sage: arcsec(a) + sage: import numpy # needs numpy + sage: a = numpy.arange(2, 5) # needs numpy + sage: arcsec(a) # needs numpy array([1.04719755, 1.23095942, 1.31811607]) """ return arccos(1.0 / x) @@ -902,89 +931,91 @@ def __init__(self): Note the difference between the two functions:: - sage: arctan2(1,-1) + sage: arctan2(1, -1) # needs sage.symbolic 3/4*pi - sage: arctan(1/-1) + sage: arctan(1/-1) # needs sage.symbolic -1/4*pi This is consistent with Python and Maxima:: - sage: maxima.atan2(1,-1) + sage: maxima.atan2(1, -1) # needs sage.symbolic (3*%pi)/4 sage: math.atan2(1,-1) 2.356194490192345 More examples:: - sage: arctan2(1,0) + sage: arctan2(1, 0) # needs sage.symbolic 1/2*pi - sage: arctan2(2,3) + sage: arctan2(2, 3) # needs sage.symbolic arctan(2/3) - sage: arctan2(-1,-1) + sage: arctan2(-1, -1) # needs sage.symbolic -3/4*pi Of course we can approximate as well:: - sage: arctan2(-1/2,1).n(100) + sage: arctan2(-1/2, 1).n(100) # needs sage.symbolic -0.46364760900080611621425623146 - sage: arctan2(2,3).n(100) + sage: arctan2(2, 3).n(100) # needs sage.symbolic 0.58800260354756755124561108063 We can delay evaluation using the ``hold`` parameter:: - sage: arctan2(-1/2,1,hold=True) + sage: arctan2(-1/2, 1, hold=True) # needs sage.symbolic arctan2(-1/2, 1) To then evaluate again, we currently must use Maxima via :meth:`sage.symbolic.expression.Expression.simplify`:: - sage: arctan2(-1/2,1,hold=True).simplify() + sage: arctan2(-1/2, 1, hold=True).simplify() # needs sage.symbolic -arctan(1/2) The function also works with numpy arrays as input:: + sage: # needs numpy sage: import numpy sage: a = numpy.linspace(1, 3, 3) sage: b = numpy.linspace(3, 6, 3) sage: atan2(a, b) array([0.32175055, 0.41822433, 0.46364761]) - sage: atan2(1,a) + sage: atan2(1,a) # needs numpy array([0.78539816, 0.46364761, 0.32175055]) - sage: atan2(a, 1) + sage: atan2(a, 1) # needs numpy array([0.78539816, 1.10714872, 1.24904577]) TESTS:: - sage: x,y = var('x,y') - sage: arctan2(y,x).operator() + sage: x,y = var('x,y') # needs sage.symbolic + sage: arctan2(y, x).operator() # needs sage.symbolic arctan2 Check if :trac:`8565` is fixed:: - sage: atan2(-pi,0) + sage: atan2(-pi, 0) # needs sage.symbolic -1/2*pi Check if :trac:`8564` is fixed:: - sage: arctan2(x,x)._sympy_() + sage: arctan2(x,x)._sympy_() # needs sympy sage.symbolic atan2(x, x) Check if numerical evaluation works :trac:`9913`:: - sage: arctan2(0, -log(2)).n() + sage: arctan2(0, -log(2)).n() # needs sage.symbolic 3.14159265358979 Check that atan2(0,0) returns NaN :trac:`21614`:: - sage: atan2(0,0) + sage: # needs sage.symbolic + sage: atan2(0, 0) NaN - sage: atan2(0,0).n() + sage: atan2(0, 0).n() NaN - sage: atan2(0,0,hold=True) + sage: atan2(0, 0, hold=True) arctan2(0, 0) - sage: atan2(0,0,hold=True).n() + sage: atan2(0, 0, hold=True).n() Traceback (most recent call last): ... RuntimeError: atan2(): division by zero @@ -992,7 +1023,7 @@ def __init__(self): Check if :trac:`10062` is fixed, this was caused by ``(I*I).is_positive()`` returning ``True``:: - sage: arctan2(0, I*I) + sage: arctan2(0, I*I) # needs sage.symbolic pi """ GinacFunction.__init__(self, 'arctan2', nargs=2, latex_name=r"\arctan", diff --git a/src/sage/functions/wigner.py b/src/sage/functions/wigner.py index 53d0b744f6a..af987c20084 100644 --- a/src/sage/functions/wigner.py +++ b/src/sage/functions/wigner.py @@ -23,10 +23,14 @@ # https://www.gnu.org/licenses/ # ********************************************************************** -from sage.rings.complex_mpfr import ComplexNumber +from sage.misc.lazy_import import lazy_import from sage.rings.integer import Integer from sage.rings.finite_rings.integer_mod import Mod -from sage.symbolic.constants import pi + +lazy_import('sage.rings.complex_mpfr', 'ComplexNumber') + +lazy_import('sage.symbolic.constants', 'pi') + # This list of precomputed factorials is needed to massively # accelerate future calculations of the various coefficients @@ -78,15 +82,15 @@ def wigner_3j(j_1, j_2, j_3, m_1, m_2, m_3, prec=None): EXAMPLES:: - sage: wigner_3j(2, 6, 4, 0, 0, 0) + sage: wigner_3j(2, 6, 4, 0, 0, 0) # needs sage.symbolic sqrt(5/143) sage: wigner_3j(2, 6, 4, 0, 0, 1) 0 - sage: wigner_3j(0.5, 0.5, 1, 0.5, -0.5, 0) + sage: wigner_3j(0.5, 0.5, 1, 0.5, -0.5, 0) # needs sage.symbolic sqrt(1/6) - sage: wigner_3j(40, 100, 60, -10, 60, -50) + sage: wigner_3j(40, 100, 60, -10, 60, -50) # needs sage.symbolic 95608/18702538494885*sqrt(21082735836735314343364163310/220491455010479533763) - sage: wigner_3j(2500, 2500, 5000, 2488, 2400, -4888, prec=64) + sage: wigner_3j(2500, 2500, 5000, 2488, 2400, -4888, prec=64) # needs sage.rings.real_mpfr 7.60424456883448589e-12 It is an error to have arguments that are not integer or half @@ -223,11 +227,11 @@ def clebsch_gordan(j_1, j_2, j_3, m_1, m_2, m_3, prec=None): EXAMPLES:: - sage: simplify(clebsch_gordan(3/2,1/2,2, 3/2,1/2,2)) + sage: simplify(clebsch_gordan(3/2,1/2,2, 3/2,1/2,2)) # needs sage.symbolic 1 - sage: clebsch_gordan(1.5,0.5,1, 1.5,-0.5,1) + sage: clebsch_gordan(1.5,0.5,1, 1.5,-0.5,1) # needs sage.symbolic 1/2*sqrt(3) - sage: clebsch_gordan(3/2,1/2,1, -1/2,1/2,0) + sage: clebsch_gordan(3/2,1/2,1, -1/2,1/2,0) # needs sage.symbolic -sqrt(3)*sqrt(1/6) .. NOTE:: @@ -275,7 +279,7 @@ def _big_delta_coeff(aa, bb, cc, prec=None): EXAMPLES:: sage: from sage.functions.wigner import _big_delta_coeff - sage: _big_delta_coeff(1,1,1) + sage: _big_delta_coeff(1,1,1) # needs sage.symbolic 1/2*sqrt(1/6) """ if int(aa + bb - cc) != (aa + bb - cc): @@ -325,7 +329,7 @@ def racah(aa, bb, cc, dd, ee, ff, prec=None): EXAMPLES:: - sage: racah(3,3,3,3,3,3) + sage: racah(3,3,3,3,3,3) # needs sage.symbolic -1/14 .. NOTE:: @@ -398,6 +402,7 @@ def wigner_6j(j_1, j_2, j_3, j_4, j_5, j_6, prec=None): EXAMPLES:: + sage: # needs sage.symbolic sage: wigner_6j(3,3,3,3,3,3) -1/14 sage: wigner_6j(5,5,5,5,5,5) @@ -497,23 +502,24 @@ def wigner_9j(j_1, j_2, j_3, j_4, j_5, j_6, j_7, j_8, j_9, prec=None): A couple of examples and test cases, note that for speed reasons a precision is given:: - sage: wigner_9j(1,1,1, 1,1,1, 1,1,0 ,prec=64) # ==1/18 + sage: # needs sage.symbolic + sage: wigner_9j(1,1,1, 1,1,1, 1,1,0, prec=64) # ==1/18 0.0555555555555555555 sage: wigner_9j(1,1,1, 1,1,1, 1,1,1) 0 - sage: wigner_9j(1,1,1, 1,1,1, 1,1,2 ,prec=64) # ==1/18 + sage: wigner_9j(1,1,1, 1,1,1, 1,1,2, prec=64) # ==1/18 0.0555555555555555556 - sage: wigner_9j(1,2,1, 2,2,2, 1,2,1 ,prec=64) # ==-1/150 + sage: wigner_9j(1,2,1, 2,2,2, 1,2,1, prec=64) # ==-1/150 -0.00666666666666666667 - sage: wigner_9j(3,3,2, 2,2,2, 3,3,2 ,prec=64) # ==157/14700 + sage: wigner_9j(3,3,2, 2,2,2, 3,3,2, prec=64) # ==157/14700 0.0106802721088435374 - sage: wigner_9j(3,3,2, 3,3,2, 3,3,2 ,prec=64) # ==3221*sqrt(70)/(246960*sqrt(105)) - 365/(3528*sqrt(70)*sqrt(105)) + sage: wigner_9j(3,3,2, 3,3,2, 3,3,2, prec=64) # ==3221*sqrt(70)/(246960*sqrt(105)) - 365/(3528*sqrt(70)*sqrt(105)) 0.00944247746651111739 - sage: wigner_9j(3,3,1, 3.5,3.5,2, 3.5,3.5,1 ,prec=64) # ==3221*sqrt(70)/(246960*sqrt(105)) - 365/(3528*sqrt(70)*sqrt(105)) + sage: wigner_9j(3,3,1, 3.5,3.5,2, 3.5,3.5,1, prec=64) # ==3221*sqrt(70)/(246960*sqrt(105)) - 365/(3528*sqrt(70)*sqrt(105)) 0.0110216678544351364 - sage: wigner_9j(100,80,50, 50,100,70, 60,50,100 ,prec=1000)*1.0 + sage: wigner_9j(100,80,50, 50,100,70, 60,50,100, prec=1000)*1.0 1.05597798065761e-7 - sage: wigner_9j(30,30,10, 30.5,30.5,20, 30.5,30.5,10 ,prec=1000)*1.0 # ==(80944680186359968990/95103769817469)*sqrt(1/682288158959699477295) + sage: wigner_9j(30,30,10, 30.5,30.5,20, 30.5,30.5,10, prec=1000)*1.0 # ==(80944680186359968990/95103769817469)*sqrt(1/682288158959699477295) 0.0000325841699408828 sage: wigner_9j(64,62.5,114.5, 61.5,61,112.5, 113.5,110.5,60, prec=1000)*1.0 -3.41407910055520e-39 @@ -529,7 +535,7 @@ def wigner_9j(j_1, j_2, j_3, j_4, j_5, j_6, j_7, j_8, j_9, prec=None): Traceback (most recent call last): ... ValueError: j values must be integer or half integer and fulfill the triangle relation - sage: wigner_9j(1,1,1, 0.5,1,1.5, 0.5,1,2.5,prec=64) + sage: wigner_9j(1,1,1, 0.5,1,1.5, 0.5,1,2.5,prec=64) # needs sage.rings.real_mpfr Traceback (most recent call last): ... ValueError: j values must be integer or half integer and fulfill the triangle relation @@ -584,6 +590,7 @@ def gaunt(l_1, l_2, l_3, m_1, m_2, m_3, prec=None): EXAMPLES:: + sage: # needs sage.symbolic sage: gaunt(1,0,1,1,0,-1) -1/2/sqrt(pi) sage: gaunt(1,0,1,1,0,0) diff --git a/src/sage/misc/derivative.pyx b/src/sage/misc/derivative.pyx index 45ee7a918c5..52468d77c58 100644 --- a/src/sage/misc/derivative.pyx +++ b/src/sage/misc/derivative.pyx @@ -186,8 +186,8 @@ def multi_derivative(F, args): INPUT: - F -- any object with a _derivative(var) method. - args -- any tuple that can be processed by derivative_parse(). + - ``F`` -- any object with a ``_derivative(var)`` method. + - ``args`` -- any tuple that can be processed by :func:`derivative_parse`. EXAMPLES:: diff --git a/src/sage/misc/dev_tools.py b/src/sage/misc/dev_tools.py index bc127127208..23b357703d8 100644 --- a/src/sage/misc/dev_tools.py +++ b/src/sage/misc/dev_tools.py @@ -203,15 +203,25 @@ def load_submodules(module=None, exclude_pattern=None): sys.stdout.write("failed\n") -def find_objects_from_name(name, module_name=None): +def find_objects_from_name(name, module_name=None, include_lazy_imports=False): r""" Return the list of objects from ``module_name`` whose name is ``name``. - If ``module_name`` is ``None``, the function runs through all - loaded modules and returns the list of objects whose name matches ``name``. + INPUT: + + - ``name`` -- string + + - ``module_name`` -- string or ``None``: + + - If ``module_name`` is ``None``, the function runs through all + loaded modules and returns the list of objects whose name matches ``name``. - If ``module_name`` is not ``None``, then search only in submodules of - ``module_name``. + - If ``module_name`` is a string, then search only in submodules of + ``module_name``. + + - ``include_lazy_imports`` -- boolean (default: ``False``); whether to + include unresolved lazy imports (i.e., :class:`~sage.misc.lazy_import.LazyImport` + objects) in the output. In order to search through more modules you might use the function :func:`load_submodules`. @@ -240,11 +250,22 @@ def find_objects_from_name(name, module_name=None): sage: dt.find_objects_from_name is dt.find_objects_from_name True + When ``include_lazy_imports=True`` is used, several + :class:`~sage.misc.lazy_import.LazyImport` objects that are resolving to the + same object may be included in the output:: + + sage: dt.find_objects_from_name('RR', include_lazy_imports=True) + [Real Field with 53 bits of precision, + ... + Real Field with 53 bits of precision, + RR] + .. NOTE:: It might be a good idea to move this function into :mod:`sage.misc.sageinspect`. """ + from sage.misc.lazy_import import LazyImport obj = [] for smodule_name, smodule in sys.modules.items(): @@ -252,7 +273,7 @@ def find_objects_from_name(name, module_name=None): continue if hasattr(smodule, '__dict__') and name in smodule.__dict__: u = smodule.__dict__[name] - if all(v is not u for v in obj): + if (not isinstance(u, LazyImport) or include_lazy_imports) and all(v is not u for v in obj): obj.append(u) return obj @@ -547,10 +568,10 @@ def expand_comma_separated_names(obj): obj = [G[name]] else: # 1.b. object inside a submodule of sage - obj = find_objects_from_name(name, 'sage') + obj = find_objects_from_name(name, 'sage', include_lazy_imports=True) if not obj: # 1.c. object from something already imported - obj = find_objects_from_name(name) + obj = find_objects_from_name(name, include_lazy_imports=True) # remove lazy imported objects from list obj i = 0 diff --git a/src/sage/symbolic/constants.py b/src/sage/symbolic/constants.py index 77783b4a75c..07c3f34af39 100644 --- a/src/sage/symbolic/constants.py +++ b/src/sage/symbolic/constants.py @@ -603,8 +603,8 @@ def _sympy_(self): EXAMPLES:: - sage: import sympy - sage: sympy.pi == pi # indirect doctest + sage: import sympy # needs sympy + sage: sympy.pi == pi # indirect doctest # needs sympy True """ import sympy @@ -744,10 +744,10 @@ def _sympy_(self): EXAMPLES:: - sage: bool(NaN._sympy_()._sage_() == NaN) + sage: bool(NaN._sympy_()._sage_() == NaN) # needs sympy True - sage: import sympy - sage: sympy.nan == NaN # this should be fixed + sage: import sympy # needs sympy + sage: sympy.nan == NaN # this should be fixed # needs sympy False """ import sympy @@ -850,8 +850,8 @@ def _sympy_(self): EXAMPLES:: - sage: import sympy - sage: sympy.GoldenRatio == golden_ratio # indirect doctest + sage: import sympy # needs sympy + sage: sympy.GoldenRatio == golden_ratio # indirect doctest # needs sympy True """ import sympy @@ -1007,8 +1007,8 @@ def _sympy_(self): EXAMPLES:: - sage: import sympy - sage: sympy.EulerGamma == euler_gamma # indirect doctest + sage: import sympy # needs sympy + sage: sympy.EulerGamma == euler_gamma # indirect doctest # needs sympy True """ import sympy @@ -1077,8 +1077,8 @@ def _sympy_(self): EXAMPLES:: - sage: import sympy - sage: sympy.Catalan == catalan # indirect doctest + sage: import sympy # needs sympy + sage: sympy.Catalan == catalan # indirect doctest # needs sympy True """ import sympy diff --git a/src/sage/symbolic/constants_c_impl.pxi b/src/sage/symbolic/constants_c_impl.pxi index 093f9b79037..b92b14318aa 100644 --- a/src/sage/symbolic/constants_c_impl.pxi +++ b/src/sage/symbolic/constants_c_impl.pxi @@ -105,8 +105,8 @@ cdef class E(Expression): 2.7182818284590452353602874714 sage: e._real_double_(RDF) # abs tol 5e-16 2.718281828459045 - sage: import sympy - sage: sympy.E == e # indirect doctest + sage: import sympy # needs sympy + sage: sympy.E == e # indirect doctest # needs sympy True TESTS:: diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index ce8f8d3b850..2300c10d125 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -406,6 +406,8 @@ from sage.arith.numerical_approx cimport digits_to_bits include "pynac.pxi" include "pynac_impl.pxi" +from sage.symbolic.symbols import symbol_table, register_symbol # used to be defined in pynac_impl + cpdef bint is_Expression(x): """ @@ -1103,7 +1105,7 @@ cdef class Expression(Expression_abc): sage: i = var('i') sage: f = integral(exp(x + x^2)/(x+1), x) ... - sage: f._sympy_character_art(False) + sage: f._sympy_character_art(False) # needs sympy ' / \n | \n | 2 \n | x + x \n | e...' """ from sympy import pretty, sympify @@ -1125,13 +1127,13 @@ cdef class Expression(Expression_abc): EXAMPLES:: sage: i = var('i') - sage: ascii_art(sum(i^2/pi*x^i, i, 0, oo)) + sage: ascii_art(sum(i^2/pi*x^i, i, 0, oo)) # needs sympy 2 x + x ------------------------------- 3 2 - pi*x + 3*pi*x - 3*pi*x + pi - sage: ascii_art(integral(exp(x + x^2)/(x+1), x)) + sage: ascii_art(integral(exp(x + x^2)/(x+1), x)) # needs sympy / | | 2 @@ -1154,13 +1156,13 @@ cdef class Expression(Expression_abc): EXAMPLES:: sage: i = var('i') - sage: unicode_art(sum(i^2/pi*x^i, i, 0, oo)) + sage: unicode_art(sum(i^2/pi*x^i, i, 0, oo)) # needs sympy 2 x + x ─────────────────────────── 3 2 - π⋅x + 3⋅π⋅x - 3⋅π⋅x + π - sage: unicode_art(integral(exp(x + x^2)/(x+1), x)) + sage: unicode_art(integral(exp(x + x^2)/(x+1), x)) # needs sympy ⌠ ⎮ 2 ⎮ x + x @@ -1173,12 +1175,12 @@ cdef class Expression(Expression_abc): Check that :trac:`28891` is fixed:: - sage: unicode_art(exp(x).series(x, 4)) + sage: unicode_art(exp(x).series(x, 4)) # needs sympy 2 3 x x ⎛ 4⎞ 1 + x + ── + ── + O⎝x ⎠ 2 6 - sage: unicode_art(exp(x).series(x==1, 3)) + sage: unicode_art(exp(x).series(x==1, 3)) # needs sympy 2 ℯ⋅(x - 1) ⎛ 3 ⎞ ℯ + ℯ⋅(x - 1) + ────────── + O⎝(x - 1) ; x → 1⎠ @@ -1186,6 +1188,7 @@ cdef class Expression(Expression_abc): Check that complex numbers are handled correctly (:trac:`28903`):: + sage: # needs sympy sage: unicode_art(SR(I)) ⅈ sage: unicode_art(SR(13 - I)) @@ -1195,17 +1198,17 @@ cdef class Expression(Expression_abc): sage: unicode_art(cos(I)) cosh(1) - sage: unicode_art(SR(CC(1/3, 1))) + sage: unicode_art(SR(CC(1/3, 1))) # needs sympy 0.333333333333333 + 1.0⋅ⅈ - sage: unicode_art(SR(CDF(1/3, 1))) + sage: unicode_art(SR(CDF(1/3, 1))) # needs sympy 0.333333333333333 + 1.0⋅ⅈ - sage: unicode_art(SR(RealField(100)(1/7))) + sage: unicode_art(SR(RealField(100)(1/7))) # needs sympy 0.14285714285714285714285714286 - sage: K. = QuadraticField(-1) - sage: unicode_art(SR(2 + a)) + sage: K. = QuadraticField(-1) # needs sympy + sage: unicode_art(SR(2 + a)) # needs sympy 2 + ⅈ - sage: unicode_art(SR(1/3 + a/2)) + sage: unicode_art(SR(1/3 + a/2)) # needs sympy 1 ⅈ ─ + ─ 3 2 @@ -1293,7 +1296,7 @@ cdef class Expression(Expression_abc): EXAMPLES:: - sage: gap(e + pi^2 + x^3) + sage: gap(e + pi^2 + x^3) # needs sage.libs.gap x^3 + pi^2 + e """ return '"%s"' % repr(self) @@ -1304,7 +1307,7 @@ cdef class Expression(Expression_abc): EXAMPLES:: - sage: singular(e + pi^2 + x^3) + sage: singular(e + pi^2 + x^3) # needs sage.libs.singular x^3 + pi^2 + e """ return '"%s"' % repr(self) @@ -4375,7 +4378,7 @@ cdef class Expression(Expression_abc): :: sage: k = GF(7) - sage: f = expand((k(1)*x^5 + k(1)*x^2 + k(2))^7); f # known bug + sage: f = expand((k(1)*x^5 + k(1)*x^2 + k(2))^7); f # known bug x^35 + x^14 + 2 sage: x^oo @@ -4846,7 +4849,8 @@ cdef class Expression(Expression_abc): sage: g.truncate() x^3 - x^2*sin(y) - 5*x + 3 sage: g = f.series(x==1, 4); g - (-sin(y) - 1) + (-2*sin(y) - 2)*(x - 1) + (-sin(y) + 3)*(x - 1)^2 + 1*(x - 1)^3 + Order((x - 1)^4) + (-sin(y) - 1) + (-2*sin(y) - 2)*(x - 1) + (-sin(y) + 3)*(x - 1)^2 + + 1*(x - 1)^3 + Order((x - 1)^4) sage: h = g.truncate(); h (x - 1)^3 - (x - 1)^2*(sin(y) - 3) - 2*(x - 1)*(sin(y) + 1) - sin(y) - 1 sage: h.expand() @@ -4860,7 +4864,8 @@ cdef class Expression(Expression_abc): sage: f.series(x) 1*x^(-1) + (-1/6)*x + ... + Order(x^20) sage: f.series(x==1,3) - (sin(1)) + (cos(1) - 2*sin(1))*(x - 1) + (-2*cos(1) + 5/2*sin(1))*(x - 1)^2 + Order((x - 1)^3) + (sin(1)) + (cos(1) - 2*sin(1))*(x - 1) + (-2*cos(1) + 5/2*sin(1))*(x - 1)^2 + + Order((x - 1)^3) sage: f.series(x==1,3).truncate().expand() -2*x^2*cos(1) + 5/2*x^2*sin(1) + 5*x*cos(1) - 7*x*sin(1) - 3*cos(1) + 11/2*sin(1) @@ -5030,11 +5035,11 @@ cdef class Expression(Expression_abc): INPUT: - - ``*args`` - the following notation is supported + - ``*args`` -- the following notation is supported - - ``x, a, n`` - variable, point, degree + - ``x, a, n`` -- variable, point, degree - - ``(x, a), (y, b), n`` - variables with points, degree of polynomial + - ``(x, a), (y, b), n`` -- variables with points, degree of polynomial EXAMPLES:: @@ -5045,32 +5050,32 @@ cdef class Expression(Expression_abc): :: - sage: taylor(sqrt (sin(x) + a*x + 1), x, 0, 3) + sage: taylor(sqrt(sin(x) + a*x + 1), x, 0, 3) 1/48*(3*a^3 + 9*a^2 + 9*a - 1)*x^3 - 1/8*(a^2 + 2*a + 1)*x^2 + 1/2*(a + 1)*x + 1 :: - sage: taylor (sqrt (x + 1), x, 0, 5) + sage: taylor(sqrt(x + 1), x, 0, 5) 7/256*x^5 - 5/128*x^4 + 1/16*x^3 - 1/8*x^2 + 1/2*x + 1 :: - sage: taylor (1/log (x + 1), x, 0, 3) + sage: taylor(1/log(x + 1), x, 0, 3) -19/720*x^3 + 1/24*x^2 - 1/12*x + 1/x + 1/2 :: - sage: taylor (cos(x) - sec(x), x, 0, 5) + sage: taylor(cos(x) - sec(x), x, 0, 5) -1/6*x^4 - x^2 :: - sage: taylor ((cos(x) - sec(x))^3, x, 0, 9) + sage: taylor((cos(x) - sec(x))^3, x, 0, 9) -1/2*x^8 - x^6 :: - sage: taylor (1/(cos(x) - sec(x))^3, x, 0, 5) + sage: taylor(1/(cos(x) - sec(x))^3, x, 0, 5) -15377/7983360*x^4 - 6767/604800*x^2 + 11/120/x^2 + 1/2/x^4 - 1/x^6 - 347/15120 TESTS: @@ -5308,7 +5313,10 @@ cdef class Expression(Expression_abc): sage: f.expand_trig() sin((3*cos(cos(2*x))^2*sin(cos(2*x)) - sin(cos(2*x))^3)*x) sage: f.expand_trig(full=True) - sin((3*(cos(cos(x)^2)*cos(sin(x)^2) + sin(cos(x)^2)*sin(sin(x)^2))^2*(cos(sin(x)^2)*sin(cos(x)^2) - cos(cos(x)^2)*sin(sin(x)^2)) - (cos(sin(x)^2)*sin(cos(x)^2) - cos(cos(x)^2)*sin(sin(x)^2))^3)*x) + sin((3*(cos(cos(x)^2)*cos(sin(x)^2) + + sin(cos(x)^2)*sin(sin(x)^2))^2*(cos(sin(x)^2)*sin(cos(x)^2) + - cos(cos(x)^2)*sin(sin(x)^2)) + - (cos(sin(x)^2)*sin(cos(x)^2) - cos(cos(x)^2)*sin(sin(x)^2))^3)*x) sage: sin(2*x).expand_trig(times=False) sin(2*x) sage: sin(2*x).expand_trig(times=True) @@ -5352,9 +5360,9 @@ cdef class Expression(Expression_abc): INPUT: - - ``self`` - a symbolic expression + - ``self`` -- a symbolic expression - - ``var`` - (default: None) the variable which is used for + - ``var`` -- (default: ``None``) the variable which is used for these transformations. If not specified, all variables are used. @@ -6548,15 +6556,18 @@ cdef class Expression(Expression_abc): sage: x.iterator() Traceback (most recent call last): ... - ValueError: expressions containing only a numeric coefficient, constant or symbol have no operands + ValueError: expressions containing only a numeric coefficient, + constant or symbol have no operands sage: pi.iterator() Traceback (most recent call last): ... - ValueError: expressions containing only a numeric coefficient, constant or symbol have no operands + ValueError: expressions containing only a numeric coefficient, + constant or symbol have no operands sage: SR(5).iterator() Traceback (most recent call last): ... - ValueError: expressions containing only a numeric coefficient, constant or symbol have no operands + ValueError: expressions containing only a numeric coefficient, + constant or symbol have no operands """ if (is_a_symbol(self._gobj) or is_a_constant(self._gobj) or is_a_numeric(self._gobj)): @@ -6576,7 +6587,8 @@ cdef class Expression(Expression_abc): sage: x.op Traceback (most recent call last): ... - TypeError: expressions containing only a numeric coefficient, constant or symbol have no operands + TypeError: expressions containing only a numeric coefficient, + constant or symbol have no operands sage: t.op[0] x^2 @@ -7602,9 +7614,11 @@ cdef class Expression(Expression_abc): sage: f = sum((e*I)^n*x^n for n in range(5)); f x^4*e^4 - I*x^3*e^3 - x^2*e^2 + I*x*e + 1 sage: f.polynomial(CDF) # abs tol 5e-16 - 54.598150033144236*x^4 - 20.085536923187668*I*x^3 - 7.38905609893065*x^2 + 2.718281828459045*I*x + 1.0 + 54.598150033144236*x^4 - 20.085536923187668*I*x^3 - 7.38905609893065*x^2 + + 2.718281828459045*I*x + 1.0 sage: f.polynomial(CC) - 54.5981500331442*x^4 - 20.0855369231877*I*x^3 - 7.38905609893065*x^2 + 2.71828182845905*I*x + 1.00000000000000 + 54.5981500331442*x^4 - 20.0855369231877*I*x^3 - 7.38905609893065*x^2 + + 2.71828182845905*I*x + 1.00000000000000 A multivariate polynomial over a finite field:: @@ -7711,7 +7725,8 @@ cdef class Expression(Expression_abc): sage: R = ComplexField(100)['x,y'] sage: R(f) - 2.7182818284590452353602874714*x^3 + 3.1415926535897932384626433833*y^3 + 1.4142135623730950488016887242 + 1.0000000000000000000000000000*I + 2.7182818284590452353602874714*x^3 + 3.1415926535897932384626433833*y^3 + + 1.4142135623730950488016887242 + 1.0000000000000000000000000000*I TESTS: @@ -8673,7 +8688,7 @@ cdef class Expression(Expression_abc): Check that :trac:`29400` is fixed:: - sage: cot(1 + i).imag().n() - (1/tan(1 + i)).imag().n() # abs tol 10^-12 + sage: cot(1 + i).imag().n() - (1/tan(1 + i)).imag().n() # abs tol 10^-12 0.00000000000000 """ return new_Expression_from_GEx(self._parent, @@ -9049,7 +9064,7 @@ cdef class Expression(Expression_abc): 1/3*pi sage: SR(0.4).arccos() 1.15927948072741 - sage: plot(lambda x: SR(x).arccos(), -1,1) + sage: plot(lambda x: SR(x).arccos(), -1,1) # needs sage.plot Graphics object consisting of 1 graphics primitive To prevent automatic evaluation use the ``hold`` argument:: @@ -9100,7 +9115,7 @@ cdef class Expression(Expression_abc): arctan(1/2) sage: SR(0.5).arctan() 0.463647609000806 - sage: plot(lambda x: SR(x).arctan(), -20,20) + sage: plot(lambda x: SR(x).arctan(), -20,20) # needs sage.plot Graphics object consisting of 1 graphics primitive To prevent automatic evaluation use the ``hold`` argument:: @@ -9370,7 +9385,7 @@ cdef class Expression(Expression_abc): 0.761594155955765 sage: maxima('tanh(1.0)') 0.7615941559557649 - sage: plot(lambda x: SR(x).tanh(), -1, 1) + sage: plot(lambda x: SR(x).tanh(), -1, 1) # needs sage.plot Graphics object consisting of 1 graphics primitive To prevent automatic evaluation use the ``hold`` argument:: @@ -9646,7 +9661,7 @@ cdef class Expression(Expression_abc): 0.500000000000000 sage: math.log(0.5) -0.6931471805599453 - sage: plot(lambda x: SR(x).log(), 0.1,10) + sage: plot(lambda x: SR(x).log(), 0.1,10) # needs sage.plot Graphics object consisting of 1 graphics primitive To prevent automatic evaluation use the ``hold`` argument:: @@ -9695,11 +9710,11 @@ cdef class Expression(Expression_abc): 1/6*pi^2 sage: SR(3).zeta() zeta(3) - sage: SR(CDF(0,1)).zeta() # abs tol 1e-16 + sage: SR(CDF(0,1)).zeta() # abs tol 1e-16 # needs sage.libs.pari 0.003300223685324103 - 0.4181554491413217*I - sage: CDF(0,1).zeta() # abs tol 1e-16 + sage: CDF(0,1).zeta() # abs tol 1e-16 # needs sage.libs.pari 0.003300223685324103 - 0.4181554491413217*I - sage: plot(lambda x: SR(x).zeta(), -10,10).show(ymin=-3,ymax=3) + sage: plot(lambda x: SR(x).zeta(), -10,10).show(ymin=-3, ymax=3) # needs sage.plot To prevent automatic evaluation use the ``hold`` argument:: @@ -9874,7 +9889,7 @@ cdef class Expression(Expression_abc): We plot the familiar plot of this log-convex function:: - sage: plot(gamma(x), -6,4).show(ymin=-3,ymax=3) + sage: plot(gamma(x), -6, 4).show(ymin=-3, ymax=3) # needs sage.plot To prevent automatic evaluation use the ``hold`` argument:: @@ -9935,10 +9950,11 @@ cdef class Expression(Expression_abc): sage: SR(5-1).factorial().log() log(24) sage: from sage.misc.verbose import set_verbose - sage: set_verbose(-1); plot(lambda x: SR(x).log_gamma(), -7,8, plot_points=1000).show() + sage: set_verbose(-1) + sage: plot(lambda x: SR(x).log_gamma(), -7,8, plot_points=1000).show() # needs sage.plot sage: math.exp(0.5) 1.6487212707001282 - sage: plot(lambda x: (SR(x).exp() - SR(-x).exp())/2 - SR(x).sinh(), -1, 1) + sage: plot(lambda x: (SR(x).exp() - SR(-x).exp())/2 - SR(x).sinh(), -1, 1) # needs sage.plot Graphics object consisting of 1 graphics primitive To prevent automatic evaluation use the ``hold`` argument:: @@ -12189,14 +12205,14 @@ cdef class Expression(Expression_abc): - ``x`` - variable to view the function in terms of (use default variable if not given) - - ``explicit_solutions`` - bool (default True); require that + - ``explicit_solutions`` -- bool (default ``True``); require that roots be explicit rather than implicit - - ``multiplicities`` - bool (default True); when True, return + - ``multiplicities`` -- bool (default ``True``); when ``True``, return multiplicities - - ``ring`` - a ring (default None): if not None, convert - self to a polynomial over ring and find roots over ring + - ``ring`` -- a ring (default ``None``): if not ``None``, convert + ``self`` to a polynomial over ring and find roots over ring OUTPUT: @@ -12291,19 +12307,31 @@ cdef class Expression(Expression_abc): Now let us find some roots over different rings:: sage: f.roots(ring=CC) - [(-0.0588115223184..., 1), (-1.331099917875... - 1.52241655183732*I, 1), (-1.331099917875... + 1.52241655183732*I, 1), (1.36050567903502 - 1.51880872209965*I, 1), (1.36050567903502 + 1.51880872209965*I, 1)] + [(-0.0588115223184..., 1), + (-1.331099917875... - 1.52241655183732*I, 1), + (-1.331099917875... + 1.52241655183732*I, 1), + (1.36050567903502 - 1.51880872209965*I, 1), + (1.36050567903502 + 1.51880872209965*I, 1)] sage: (2.5*f).roots(ring=RR) [(-0.058811522318449..., 1)] sage: f.roots(ring=CC, multiplicities=False) - [-0.05881152231844..., -1.331099917875... - 1.52241655183732*I, -1.331099917875... + 1.52241655183732*I, 1.36050567903502 - 1.51880872209965*I, 1.36050567903502 + 1.51880872209965*I] + [-0.05881152231844..., + -1.331099917875... - 1.52241655183732*I, + -1.331099917875... + 1.52241655183732*I, + 1.36050567903502 - 1.51880872209965*I, + 1.36050567903502 + 1.51880872209965*I] sage: f.roots(ring=QQ) [] sage: f.roots(ring=QQbar, multiplicities=False) - [-0.05881152231844944?, -1.331099917875796? - 1.522416551837318?*I, -1.331099917875796? + 1.522416551837318?*I, 1.360505679035020? - 1.518808722099650?*I, 1.360505679035020? + 1.518808722099650?*I] + [-0.05881152231844944?, + -1.331099917875796? - 1.522416551837318?*I, + -1.331099917875796? + 1.522416551837318?*I, + 1.360505679035020? - 1.518808722099650?*I, + 1.360505679035020? + 1.518808722099650?*I] Root finding over finite fields:: - sage: f.roots(ring=GF(7^2, 'a')) + sage: f.roots(ring=GF(7^2, 'a')) # needs sage.rings.finite_rings [(3, 1), (4*a + 6, 2), (3*a + 3, 2)] TESTS:: @@ -12319,7 +12347,8 @@ cdef class Expression(Expression_abc): (f6, f5, f4, x) sage: e = 15*f6*x^2 + 5*f5*x + f4 sage: res = e.roots(x); res - [(-1/30*(5*f5 + sqrt(25*f5^2 - 60*f4*f6))/f6, 1), (-1/30*(5*f5 - sqrt(25*f5^2 - 60*f4*f6))/f6, 1)] + [(-1/30*(5*f5 + sqrt(25*f5^2 - 60*f4*f6))/f6, 1), + (-1/30*(5*f5 - sqrt(25*f5^2 - 60*f4*f6))/f6, 1)] sage: e.subs(x=res[0][0]).is_zero() True """ @@ -12346,27 +12375,27 @@ cdef class Expression(Expression_abc): .. warning:: - This is not a numerical solver - use ``find_root`` to solve - for self == 0 numerically on an interval. + This is not a numerical solver -- use :meth:`find_root` to solve + for ``self == 0`` numerically on an interval. INPUT: - - ``x`` - variable(s) to solve for + - ``x`` -- variable(s) to solve for - - ``multiplicities`` - bool (default: False); if True, + - ``multiplicities`` -- bool (default: ``False``); if ``True``, return corresponding multiplicities. This keyword is incompatible with ``to_poly_solve=True`` and does not make any sense when solving an inequality. - - ``solution_dict`` - bool (default: False); if True or non-zero, + - ``solution_dict`` -- bool (default: ``False``); if ``True`` or non-zero, return a list of dictionaries containing solutions. Not used when solving an inequality. - - ``explicit_solutions`` - bool (default: False); require that + - ``explicit_solutions`` -- bool (default: ``False``); require that all roots be explicit rather than implicit. Not used when solving an inequality. - - ``to_poly_solve`` - bool (default: False) or string; use + - ``to_poly_solve`` -- bool (default: ``False``) or string; use Maxima's ``to_poly_solver`` package to search for more possible solutions, but possibly encounter approximate solutions. This keyword is incompatible with ``multiplicities=True`` @@ -12378,7 +12407,11 @@ cdef class Expression(Expression_abc): sage: z = var('z') sage: (z^5 - 1).solve(z) - [z == 1/4*sqrt(5) + 1/4*I*sqrt(2*sqrt(5) + 10) - 1/4, z == -1/4*sqrt(5) + 1/4*I*sqrt(-2*sqrt(5) + 10) - 1/4, z == -1/4*sqrt(5) - 1/4*I*sqrt(-2*sqrt(5) + 10) - 1/4, z == 1/4*sqrt(5) - 1/4*I*sqrt(2*sqrt(5) + 10) - 1/4, z == 1] + [z == 1/4*sqrt(5) + 1/4*I*sqrt(2*sqrt(5) + 10) - 1/4, + z == -1/4*sqrt(5) + 1/4*I*sqrt(-2*sqrt(5) + 10) - 1/4, + z == -1/4*sqrt(5) - 1/4*I*sqrt(-2*sqrt(5) + 10) - 1/4, + z == 1/4*sqrt(5) - 1/4*I*sqrt(2*sqrt(5) + 10) - 1/4, + z == 1] sage: solve((z^3-1)^3, z, multiplicities=True) ([z == 1/2*I*sqrt(3) - 1/2, z == -1/2*I*sqrt(3) - 1/2, z == 1], [3, 3, 3]) @@ -12389,7 +12422,9 @@ cdef class Expression(Expression_abc): sage: w = x^4 - (1+3*i)*x^3 - (2-4*i)*x^2 + (6-2*i)*x - 4 - 4*i sage: w.solve(x,multiplicities=True) - ([x == -1/2*sqrt(2*I) + 3/2*I - 1/2, x == 1/2*sqrt(2*I) + 3/2*I - 1/2, x == (-I + 1), x == (I + 1)], + ([x == -1/2*sqrt(2*I) + 3/2*I - 1/2, + x == 1/2*sqrt(2*I) + 3/2*I - 1/2, + x == (-I + 1), x == (I + 1)], [1, 1, 1, 1]) See :func:`sage.symbolic.relation.solve` or the output of ``solve?`` @@ -12414,11 +12449,11 @@ cdef class Expression(Expression_abc): EXAMPLES:: sage: x,y = var('x,y') - sage: solve_diophantine(3*x == 4) + sage: solve_diophantine(3*x == 4) # needs sympy [] - sage: solve_diophantine(x^2 - 9) + sage: solve_diophantine(x^2 - 9) # needs sympy [-3, 3] - sage: sorted(solve_diophantine(x^2 + y^2 == 25)) + sage: sorted(solve_diophantine(x^2 + y^2 == 25)) # needs sympy [(-5, 0), (-4, -3), (-4, 3), (-3, -4), (-3, 4), (0, -5)... The function is used when ``solve()`` is called with all variables @@ -12426,45 +12461,52 @@ cdef class Expression(Expression_abc): sage: assume(x, 'integer') sage: assume(y, 'integer') - sage: sorted(solve(x*y == 1, (x,y))) + sage: sorted(solve(x*y == 1, (x,y))) # needs sympy [(-1, -1), (1, 1)] You can also pick specific variables, and get the solution as a dictionary:: + sage: # needs sympy sage: solve_diophantine(x*y == 10, x) [-10, -5, -2, -1, 1, 2, 5, 10] sage: sorted(solve_diophantine(x*y - y == 10, (x,y))) [(-9, -1), (-4, -2), (-1, -5), (0, -10), (2, 10), (3, 5), (6, 2), (11, 1)] sage: res = solve_diophantine(x*y - y == 10, solution_dict=True) - sage: sol = [{y: -5, x: -1}, {y: -10, x: 0}, {y: -1, x: -9}, {y: -2, x: -4}, {y: 10, x: 2}, {y: 1, x: 11}, {y: 2, x: 6}, {y: 5, x: 3}] - sage: all(solution in res for solution in sol) and bool(len(res) == len(sol)) + sage: sol = [{y: -5, x: -1}, {y: -10, x: 0}, {y: -1, x: -9}, {y: -2, x: -4}, + ....: {y: 10, x: 2}, {y: 1, x: 11}, {y: 2, x: 6}, {y: 5, x: 3}] + sage: all(solution in res + ....: for solution in sol) and bool(len(res) == len(sol)) True If the solution is parametrized the parameter(s) are not defined, but you can substitute them with specific integer values:: + sage: # needs sympy sage: x,y,z = var('x,y,z') - sage: sol = solve_diophantine(x^2-y==0); sol + sage: sol = solve_diophantine(x^2-y == 0); sol (t, t^2) sage: [(sol[0].subs(t=t),sol[1].subs(t=t)) for t in range(-3,4)] [(-3, 9), (-2, 4), (-1, 1), (0, 0), (1, 1), (2, 4), (3, 9)] sage: sol = solve_diophantine(x^2 + y^2 == z^2); sol (2*p*q, p^2 - q^2, p^2 + q^2) - sage: [(sol[0].subs(p=p,q=q),sol[1].subs(p=p,q=q),sol[2].subs(p=p,q=q)) for p in range(1,4) for q in range(1,4)] - [(2, 0, 2), (4, -3, 5), (6, -8, 10), (4, 3, 5), (8, 0, 8), (12, -5, 13), (6, 8, 10), (12, 5, 13), (18, 0, 18)] + sage: [(sol[0].subs(p=p,q=q), sol[1].subs(p=p,q=q), sol[2].subs(p=p,q=q)) + ....: for p in range(1,4) for q in range(1,4)] + [(2, 0, 2), (4, -3, 5), (6, -8, 10), (4, 3, 5), (8, 0, 8), + (12, -5, 13), (6, 8, 10), (12, 5, 13), (18, 0, 18)] Solve Brahmagupta-Pell equations:: - sage: sol = sorted(solve_diophantine(x^2 - 2*y^2 == 1), key=str) - sage: sol - [(-sqrt(2)*(2*sqrt(2) + 3)^t + sqrt(2)*(-2*sqrt(2) + 3)^t - 3/2*(2*sqrt(2) + 3)^t - 3/2*(-2*sqrt(2) + 3)^t,... - sage: [(sol[1][0].subs(t=t).simplify_full(),sol[1][1].subs(t=t).simplify_full()) for t in range(-1,5)] + sage: sol = sorted(solve_diophantine(x^2 - 2*y^2 == 1), key=str); sol # needs sympy + [(-sqrt(2)*(2*sqrt(2) + 3)^t + sqrt(2)*(-2*sqrt(2) + 3)^t + - 3/2*(2*sqrt(2) + 3)^t - 3/2*(-2*sqrt(2) + 3)^t,... + sage: [(sol[1][0].subs(t=t).simplify_full(), # needs sympy + ....: sol[1][1].subs(t=t).simplify_full()) for t in range(-1,5)] [(1, 0), (3, -2), (17, -12), (99, -70), (577, -408), (3363, -2378)] TESTS:: - sage: solve_diophantine(x^2 - y, x, y) + sage: solve_diophantine(x^2 - y, x, y) # needs sympy Traceback (most recent call last): ... AttributeError: please use a tuple or list for several variables. @@ -12551,6 +12593,7 @@ cdef class Expression(Expression_abc): Note that in this example both f(-2) and f(3) are positive, yet we still find a root in that interval:: + sage: # needs scipy sage: f = x^2 - 1 sage: f.find_root(-2, 3) 1.0 @@ -12570,9 +12613,9 @@ cdef class Expression(Expression_abc): More examples:: - sage: (sin(x) + exp(x)).find_root(-10, 10) + sage: (sin(x) + exp(x)).find_root(-10, 10) # needs scipy -0.588532743981862... - sage: sin(x).find_root(-1,1) + sage: sin(x).find_root(-1,1) # needs scipy 0.0 This example was fixed along with :trac:`4942` - @@ -12580,34 +12623,34 @@ cdef class Expression(Expression_abc): pi is a root for tan(x), but an asymptote to 1/tan(x) added an example to show handling of both cases:: - sage: (tan(x)).find_root(3,3.5) + sage: (tan(x)).find_root(3,3.5) # needs scipy 3.1415926535... - sage: (1/tan(x)).find_root(3, 3.5) + sage: (1/tan(x)).find_root(3, 3.5) # needs scipy Traceback (most recent call last): ... NotImplementedError: Brent's method failed to find a zero for f on the interval An example with a square root:: - sage: f = 1 + x + sqrt(x+2); f.find_root(-2,10) + sage: f = 1 + x + sqrt(x+2); f.find_root(-2,10) # needs scipy -1.618033988749895 Some examples that Ted Kosan came up with:: sage: t = var('t') sage: v = 0.004*(9600*e^(-(1200*t)) - 2400*e^(-(300*t))) - sage: v.find_root(0, 0.002) + sage: v.find_root(0, 0.002) # needs scipy 0.001540327067911417... With this expression, we can see there is a zero very close to the origin:: sage: a = .004*(8*e^(-(300*t)) - 8*e^(-(1200*t)))*(720000*e^(-(300*t)) - 11520000*e^(-(1200*t))) +.004*(9600*e^(-(1200*t)) - 2400*e^(-(300*t)))^2 - sage: show(plot(a, 0, .002), xmin=0, xmax=.002) + sage: show(plot(a, 0, .002), xmin=0, xmax=.002) # needs sage.plot It is easy to approximate with ``find_root``:: - sage: a.find_root(0,0.002) + sage: a.find_root(0,0.002) # needs scipy 0.0004110514049349... Using solve takes more effort, and even then gives @@ -12651,7 +12694,7 @@ cdef class Expression(Expression_abc): sage: x = SR.symbol('x', domain='real') sage: f = (sqrt(x) - I).abs() - sage: f.find_root(-2, 2, rtol=1e-6) # abs tol 1e-6 + sage: f.find_root(-2, 2, rtol=1e-6) # abs tol 1e-6 # needs scipy -1.0000000049668551 """ @@ -12691,9 +12734,9 @@ cdef class Expression(Expression_abc): EXAMPLES:: sage: f = x*cos(x) - sage: f.find_local_maximum(0,5) + sage: f.find_local_maximum(0,5) # needs scipy (0.5610963381910451, 0.8603335890...) - sage: f.find_local_maximum(0,5, tol=0.1, maxfun=10) + sage: f.find_local_maximum(0,5, tol=0.1, maxfun=10) # needs scipy (0.561090323458081..., 0.857926501456...) """ minval, x = (-self).find_local_minimum(a, b, var, tol, @@ -12743,6 +12786,7 @@ cdef class Expression(Expression_abc): EXAMPLES:: + sage: # needs scipy sage: f = x*cos(x) sage: f.find_local_minimum(1, 5) (-3.288371395590..., 3.4256184695...) @@ -12750,7 +12794,7 @@ cdef class Expression(Expression_abc): (-3.288371361890..., 3.4257507903...) sage: f.find_local_minimum(1, 5, tol=1e-2, maxfun=10) (-3.288370845983..., 3.4250840220...) - sage: show(f.plot(0, 20)) + sage: show(f.plot(0, 20)) # needs sage.plot sage: f.find_local_minimum(1, 15) (-9.477294259479..., 9.5293344109...) @@ -12761,7 +12805,7 @@ cdef class Expression(Expression_abc): sage: x = SR.symbol('x', domain='real') sage: f = (x + I).abs() - sage: f.find_local_minimum(-1,1) # abs tol 1e-7 + sage: f.find_local_minimum(-1,1) # abs tol 1e-7 # needs scipy (1.0, 1.6937685757340167e-08) ALGORITHM: @@ -12859,57 +12903,59 @@ cdef class Expression(Expression_abc): This displays a straight line:: - sage: sin(2).plot((x,0,3)) + sage: sin(2).plot((x,0,3)) # needs sage.plot Graphics object consisting of 1 graphics primitive This draws a red oscillatory curve:: - sage: sin(x^2).plot((x,0,2*pi), rgbcolor=(1,0,0)) + sage: sin(x^2).plot((x,0,2*pi), rgbcolor=(1,0,0)) # needs sage.plot Graphics object consisting of 1 graphics primitive Another plot using the variable theta:: sage: var('theta') theta - sage: (cos(theta) - erf(theta)).plot((theta,-2*pi,2*pi)) + sage: (cos(theta) - erf(theta)).plot((theta,-2*pi,2*pi)) # needs sage.plot Graphics object consisting of 1 graphics primitive A very thick green plot with a frame:: - sage: sin(x).plot((x,-4*pi, 4*pi), thickness=20, rgbcolor=(0,0.7,0)).show(frame=True) + sage: sin(x).plot((x, -4*pi, 4*pi), # needs sage.plot + ....: thickness=20, rgbcolor=(0,0.7,0)).show(frame=True) You can embed 2d plots in 3d space as follows:: - sage: plot(sin(x^2), (x,-pi, pi), thickness=2).plot3d(z = 1) # long time + sage: plot(sin(x^2), (x, -pi, pi), thickness=2).plot3d(z=1) # long time, needs sage.plot Graphics3d Object A more complicated family:: - sage: G = sum([plot(sin(n*x), (x,-2*pi, 2*pi)).plot3d(z=n) for n in [0,0.1,..1]]) - sage: G.show(frame_aspect_ratio=[1,1,1/2]) # long time (5s on sage.math, 2012) + sage: G = sum(plot(sin(n*x), (x, -2*pi, 2*pi)).plot3d(z=n) # needs sage.plot + ....: for n in [0,0.1,..1]) + sage: G.show(frame_aspect_ratio=[1,1,1/2]) # long time (5s on sage.math, 2012), needs sage.plot A plot involving the floor function:: - sage: plot(1.0 - x * floor(1/x), (x,0.00001,1.0)) + sage: plot(1.0 - x * floor(1/x), (x,0.00001,1.0)) # needs sage.plot Graphics object consisting of 1 graphics primitive Sage used to allow symbolic functions with "no arguments"; this no longer works:: - sage: plot(2*sin, -4, 4) + sage: plot(2*sin, -4, 4) # needs sage.plot Traceback (most recent call last): ... TypeError: unsupported operand parent(s) for *: 'Integer Ring' and '' You should evaluate the function first:: - sage: plot(2*sin(x), -4, 4) + sage: plot(2*sin(x), -4, 4) # needs sage.plot Graphics object consisting of 1 graphics primitive TESTS:: sage: f(x) = x*(1 - x) - sage: plot(f,0,1) + sage: plot(f, 0, 1) # needs sage.plot Graphics object consisting of 1 graphics primitive """ from sage.plot.plot import plot @@ -12966,7 +13012,7 @@ cdef class Expression(Expression_abc): sage: f = s._plot_fast_callable(x) sage: abs(f(10) - abs((I*10+1)^4)) < 1e-11 True - sage: plot(s) + sage: plot(s) # needs sage.plot Graphics object consisting of 1 graphics primitive Check that :trac:`15030` is fixed:: @@ -12974,7 +13020,7 @@ cdef class Expression(Expression_abc): sage: abs(log(x))._plot_fast_callable(x)(-0.2) # abs tol 1e-10 3.52985761682672 sage: f = function('f', evalf_func=lambda self,x,parent: I*x) - sage: plot(abs(f(x)), 0,5) + sage: plot(abs(f(x)), 0,5) # needs sage.plot Graphics object consisting of 1 graphics primitive """ from sage.ext.fast_callable import fast_callable @@ -12986,31 +13032,26 @@ cdef class Expression(Expression_abc): ############ def sum(self, *args, **kwds): r""" - Return the symbolic sum - `\sum_{v = a}^b self` + Return the symbolic sum `\sum_{v = a}^b` ``self`` with respect to the variable `v` with endpoints `a` and `b`. INPUT: - - ``v`` - a variable or variable name + - ``v`` -- a variable or variable name - - ``a`` - lower endpoint of the sum + - ``a`` -- lower endpoint of the sum - - ``b`` - upper endpoint of the sum + - ``b`` -- upper endpoint of the sum - ``algorithm`` - (default: ``'maxima'``) one of - - ``'maxima'`` - use Maxima (the default) - - - ``'maple'`` - (optional) use Maple - - - ``'mathematica'`` - (optional) use Mathematica - - - ``'giac'`` - (optional) use Giac - - - ``'sympy'`` - use SymPy + - ``'maxima'`` -- use Maxima (the default) + - ``'maple'`` -- (optional) use Maple + - ``'mathematica'`` -- (optional) use Mathematica + - ``'giac'`` -- (optional) use Giac + - ``'sympy'`` -- use SymPy EXAMPLES:: @@ -13171,29 +13212,27 @@ cdef class Expression(Expression_abc): def prod(self, *args, **kwds): r""" + Return the symbolic product `\prod_{v = a}^b` ``self``. - Return the symbolic product `\prod_{v = a}^b expression` with - respect to the variable `v` with endpoints `a` and `b`. + This is the product respect to the variable `v` with endpoints `a` and `b`. INPUT: - - ``expression`` - a symbolic expression - - - ``v`` - a variable or variable name + - ``expression`` -- a symbolic expression - - ``a`` - lower endpoint of the product + - ``v`` -- a variable or variable name - - ``b`` - upper endpoint of the product - - - ``algorithm`` - (default: ``'maxima'``) one of + - ``a`` -- lower endpoint of the product - - ``'maxima'`` - use Maxima (the default) + - ``b`` -- upper endpoint of the product - - ``'giac'`` - (optional) use Giac + - ``algorithm`` -- (default: ``'maxima'``) one of - - ``'sympy'`` - use SymPy + - ``'maxima'`` -- use Maxima (the default) + - ``'giac'`` -- (optional) use Giac + - ``'sympy'`` -- use SymPy - - ``hold`` - (default: ``False``) if ``True`` don't evaluate + - ``hold`` -- (default: ``False``) if ``True``, don't evaluate TESTS: @@ -13220,8 +13259,9 @@ cdef class Expression(Expression_abc): def integral(self, *args, **kwds): """ - Compute the integral of self. Please see - :func:`sage.symbolic.integration.integral.integrate` for more details. + Compute the integral of ``self``. + + Please see :func:`sage.symbolic.integration.integral.integrate` for more details. EXAMPLES:: @@ -13286,8 +13326,9 @@ cdef class Expression(Expression_abc): def nintegral(self, *args, **kwds): """ - Compute the numerical integral of self. Please see - :obj:`sage.calculus.calculus.nintegral` for more details. + Compute the numerical integral of ``self``. + + Please see :obj:`sage.calculus.calculus.nintegral` for more details. EXAMPLES:: @@ -13320,8 +13361,9 @@ cdef class Expression(Expression_abc): def limit(self, *args, **kwds): """ - Return a symbolic limit. See - :obj:`sage.calculus.calculus.limit` + Return a symbolic limit. + + See :obj:`sage.calculus.calculus.limit` EXAMPLES:: @@ -13333,8 +13375,9 @@ cdef class Expression(Expression_abc): def laplace(self, t, s): """ - Return Laplace transform of self. See - :obj:`sage.calculus.calculus.laplace` + Return Laplace transform of ``self``. + + See :obj:`sage.calculus.calculus.laplace` EXAMPLES:: @@ -13348,8 +13391,9 @@ cdef class Expression(Expression_abc): def inverse_laplace(self, t, s): """ - Return inverse Laplace transform of self. See - :obj:`sage.calculus.calculus.inverse_laplace` + Return inverse Laplace transform of ``self``. + + See :obj:`sage.calculus.calculus.inverse_laplace` EXAMPLES:: @@ -13363,7 +13407,7 @@ cdef class Expression(Expression_abc): def add_to_both_sides(self, x): """ - Return a relation obtained by adding *x* to both sides of + Return a relation obtained by adding ``x`` to both sides of this relation. EXAMPLES:: @@ -13382,7 +13426,7 @@ cdef class Expression(Expression_abc): def subtract_from_both_sides(self, x): """ - Return a relation obtained by subtracting *x* from both sides + Return a relation obtained by subtracting ``x`` from both sides of this relation. EXAMPLES:: @@ -13400,7 +13444,7 @@ cdef class Expression(Expression_abc): def multiply_both_sides(self, x, checksign=None): """ Return a relation obtained by multiplying both sides of this - relation by *x*. + relation by ``x``. .. NOTE:: @@ -13449,11 +13493,11 @@ cdef class Expression(Expression_abc): def divide_both_sides(self, x, checksign=None): """ Return a relation obtained by dividing both sides of this - relation by *x*. + relation by ``x``. .. NOTE:: - The *checksign* keyword argument is currently ignored and + The ``checksign`` keyword argument is currently ignored and is included for backward compatibility reasons only. EXAMPLES:: @@ -13473,16 +13517,15 @@ cdef class Expression(Expression_abc): def implicit_derivative(self, Y, X, n=1): """ - Return the n'th derivative of Y with respect to X given implicitly by this expression. + Return the `n`-th derivative of `Y` with respect to `X` given implicitly by this expression. INPUT: - - ``Y`` - The dependent variable of the implicit expression. - - - ``X`` - The independent variable with respect to which the derivative is taken. + - ``Y`` -- The dependent variable of the implicit expression. + - ``X`` -- The independent variable with respect to which the derivative is taken. - - ``n`` - (default : 1) the order of the derivative. + - ``n`` -- (default: 1) the order of the derivative. EXAMPLES:: @@ -13574,20 +13617,20 @@ def solve_diophantine(f, *args, **kwds): The argument, if not given as symbolic equation, is set equal to zero. It can be given in any form that can be converted to symbolic. Please - see :meth:`Expression.solve_diophantine()` for a detailed + see :meth:`Expression.solve_diophantine` for a detailed synopsis. EXAMPLES:: sage: R. = PolynomialRing(ZZ); R Multivariate Polynomial Ring in a, b over Integer Ring - sage: solve_diophantine(a^2-3*b^2+1) + sage: solve_diophantine(a^2 - 3*b^2 + 1) [] - sage: sorted(solve_diophantine(a^2-3*b^2+2), key=str) + sage: sorted(solve_diophantine(a^2 - 3*b^2 + 2), key=str) [(-1/2*sqrt(3)*(sqrt(3) + 2)^t + 1/2*sqrt(3)*(-sqrt(3) + 2)^t - 1/2*(sqrt(3) + 2)^t - 1/2*(-sqrt(3) + 2)^t, -1/6*sqrt(3)*(sqrt(3) + 2)^t + 1/6*sqrt(3)*(-sqrt(3) + 2)^t - 1/2*(sqrt(3) + 2)^t - 1/2*(-sqrt(3) + 2)^t), - (1/2*sqrt(3)*(sqrt(3) + 2)^t - 1/2*sqrt(3)*(-sqrt(3) + 2)^t + 1/2*(sqrt(3) + 2)^t + 1/2*(-sqrt(3) + 2)^t, - 1/6*sqrt(3)*(sqrt(3) + 2)^t - 1/6*sqrt(3)*(-sqrt(3) + 2)^t + 1/2*(sqrt(3) + 2)^t + 1/2*(-sqrt(3) + 2)^t)] + (1/2*sqrt(3)*(sqrt(3) + 2)^t - 1/2*sqrt(3)*(-sqrt(3) + 2)^t + 1/2*(sqrt(3) + 2)^t + 1/2*(-sqrt(3) + 2)^t, + 1/6*sqrt(3)*(sqrt(3) + 2)^t - 1/6*sqrt(3)*(-sqrt(3) + 2)^t + 1/2*(sqrt(3) + 2)^t + 1/2*(-sqrt(3) + 2)^t)] """ from sage.symbolic.ring import SR @@ -13755,8 +13798,8 @@ cpdef new_Expression(parent, x): sage: a.parent() Symbolic Ring - sage: K. = QuadraticField(-3) - sage: a + sin(x) + sage: K. = QuadraticField(-3) # needs sage.rings.number_field + sage: a + sin(x) # needs sage.rings.number_field I*sqrt(3) + sin(x) sage: x = var('x'); y0,y1 = PolynomialRing(ZZ,2,'y').gens() sage: x+y0/y1 diff --git a/src/sage/symbolic/expression_conversion_algebraic.py b/src/sage/symbolic/expression_conversion_algebraic.py new file mode 100644 index 00000000000..f1b30784598 --- /dev/null +++ b/src/sage/symbolic/expression_conversion_algebraic.py @@ -0,0 +1,306 @@ +r""" +Conversion of symbolic expressions to algebraic numbers +""" +# **************************************************************************** +# Copyright (C) 2009-2012 Mike Hansen +# 2015-2018 Ralf Stephan +# 2015 Nils Bruin +# 2017 Jeroen Demeyer +# 2019-2022 Frédéric Chapoton +# 2021 Dave Witte Morris +# 2023 Vincent Delecroix +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# https://www.gnu.org/licenses/ +# **************************************************************************** + +from operator import eq, ne, gt, lt, ge, le, mul, pow, neg, add, truediv +from functools import reduce + +import sage.rings.abc + +from sage.functions.all import exp +from sage.symbolic.expression_conversions import Converter +from sage.symbolic.operators import add_vararg, mul_vararg +from sage.symbolic.ring import SR + + +############# +# Algebraic # +############# +class AlgebraicConverter(Converter): + def __init__(self, field): + """ + EXAMPLES:: + + sage: from sage.symbolic.expression_conversions import AlgebraicConverter + sage: a = AlgebraicConverter(QQbar) + sage: a.field + Algebraic Field + sage: a.reciprocal_trig_functions['cot'] + tan + """ + self.field = field + + from sage.functions.all import reciprocal_trig_functions + self.reciprocal_trig_functions = reciprocal_trig_functions + + def pyobject(self, ex, obj): + """ + EXAMPLES:: + + sage: from sage.symbolic.expression_conversions import AlgebraicConverter + sage: a = AlgebraicConverter(QQbar) + sage: f = SR(2) + sage: a.pyobject(f, f.pyobject()) + 2 + sage: _.parent() + Algebraic Field + """ + return self.field(obj) + + def arithmetic(self, ex, operator): + """ + Convert a symbolic expression to an algebraic number. + + EXAMPLES:: + + sage: from sage.symbolic.expression_conversions import AlgebraicConverter + sage: f = 2^(1/2) + sage: a = AlgebraicConverter(QQbar) + sage: a.arithmetic(f, f.operator()) + 1.414213562373095? + + TESTS:: + + sage: f = pi^6 + sage: a = AlgebraicConverter(QQbar) + sage: a.arithmetic(f, f.operator()) + Traceback (most recent call last): + ... + TypeError: unable to convert pi^6 to Algebraic Field + + Test that :trac:`14602` is fixed:: + + sage: K = QuadraticField(3) + sage: K(sqrt(3)).parent() is K + True + sage: sqrt(K(3)).parent() is K + True + sage: (K(3)^(1/2)).parent() + Symbolic Ring + sage: bool(K.gen() == K(3)^(1/2) == sqrt(K(3)) == K(sqrt(3)) == sqrt(3)) + True + sage: L = QuadraticField(3, embedding=-AA(3).sqrt()) + sage: bool(L.gen() == -sqrt(3)) + True + """ + # We try to avoid simplifying, because maxima's simplify command + # can change the value of a radical expression (by changing which + # root is selected). + try: + if operator is pow: + from sage.rings.rational import Rational + base, expt = ex.operands() + base = self.field(base) + expt = Rational(expt) + return self.field(base**expt) + else: + if operator is add_vararg: + operator = add + elif operator is mul_vararg: + operator = mul + return reduce(operator, map(self, ex.operands())) + except TypeError: + pass + + if operator is pow: + from sage.symbolic.constants import e, pi, I + from sage.rings.rational_field import QQ + + base, expt = ex.operands() + if base == e and expt / (pi * I) in QQ: + return exp(expt)._algebraic_(self.field) + + raise TypeError("unable to convert %r to %s" % (ex, self.field)) + + def composition(self, ex, operator): + """ + Coerce to an algebraic number. + + EXAMPLES:: + + sage: from sage.symbolic.expression_conversions import AlgebraicConverter + sage: a = AlgebraicConverter(QQbar) + sage: a.composition(exp(I*pi/3, hold=True), exp) + 0.500000000000000? + 0.866025403784439?*I + sage: a.composition(sin(pi/7), sin) + 0.4338837391175581? + 0.?e-18*I + + sage: x = SR.var('x') + sage: a.composition(complex_root_of(x^3 - x^2 - x - 1, 0), complex_root_of) + 1.839286755214161? + sage: a.composition(complex_root_of(x^5 - 1, 3), complex_root_of) + 0.3090169943749474? - 0.9510565162951536?*I + sage: a.composition(complex_root_of(x^2 + 1, 0), complex_root_of) + 1.?e-684 - 0.9999999999999999?*I + sage: a.composition(complex_root_of(x^2 + 1, 1), complex_root_of) + 1.?e-684 + 0.9999999999999999?*I + + TESTS:: + + sage: QQbar(zeta(7)) + Traceback (most recent call last): + ... + TypeError: unable to convert zeta(7) to Algebraic Field + + Test :trac:`22571`:: + + sage: a.composition(exp(0, hold=True), exp) + 1 + sage: a.composition(exp(1, hold=True), exp) + Traceback (most recent call last): + ... + ValueError: unable to represent as an algebraic number + sage: a.composition(exp(pi*I*RR(1), hold=True), exp) + Traceback (most recent call last): + ... + TypeError: unable to convert e^(1.00000000000000*I*pi) to Algebraic Field + sage: a.composition(exp(pi*CC.gen(), hold=True), exp) + Traceback (most recent call last): + ... + TypeError: unable to convert e^(1.00000000000000*I*pi) to Algebraic Field + sage: bool(sin(pi*RR("0.7000000000000002")) > 0) + True + + Check that :trac:`24440` is fixed:: + + sage: QQbar(tanh(pi + 0.1)) + Traceback (most recent call last): + ... + ValueError: unable to represent as an algebraic number + sage: QQbar(sin(I*pi/7)) + Traceback (most recent call last): + ... + ValueError: unable to represent as an algebraic number + sage: QQbar(sin(I*pi/7, hold=True)) + Traceback (most recent call last): + ... + ValueError: unable to represent as an algebraic number + """ + func = operator + operands = ex.operands() + if len(operands) == 1: + operand = operands[0] + else: + operand = None + + if isinstance(self.field, sage.rings.abc.UniversalCyclotomicField): + QQbar = self.field + hold = True + else: + QQbar = self.field.algebraic_closure() + hold = False + + zeta = QQbar.zeta + # Note that comparing functions themselves goes via maxima, and is SLOW + func_name = repr(func) + if func_name == 'exp': + if operand.is_trivial_zero(): + return self.field.one() + if not (SR(-1).sqrt() * operand).is_real(): + raise ValueError("unable to represent as an algebraic number") + # Coerce (not convert, see #22571) arg to a rational + from sage.rings.rational_field import QQ + arg = operand.imag()/(2*ex.parent().pi()) + try: + rat_arg = QQ.coerce(arg.pyobject()) + except TypeError: + raise TypeError("unable to convert %r to %s" % (ex, self.field)) + res = zeta(rat_arg.denom())**rat_arg.numer() + return self.field(res) + elif func_name in ['sin', 'cos', 'tan']: + exp_ia = exp(SR(-1).sqrt() * operand, hold=hold)._algebraic_(QQbar) + if func_name == 'sin': + res = (exp_ia - ~exp_ia) / (2 * zeta(4)) + elif func_name == 'cos': + res = (exp_ia + ~exp_ia) / 2 + else: + res = -zeta(4) * (exp_ia - ~exp_ia) / (exp_ia + ~exp_ia) + return self.field(res) + elif func_name in ['sinh', 'cosh', 'tanh']: + if not (SR(-1).sqrt()*operand).is_real(): + raise ValueError("unable to represent as an algebraic number") + exp_a = exp(operand, hold=hold)._algebraic_(QQbar) + if func_name == 'sinh': + res = (exp_a - ~exp_a) / 2 + elif func_name == 'cosh': + res = (exp_a + ~exp_a) / 2 + else: + res = (exp_a - ~exp_a) / (exp_a + ~exp_a) + return self.field(res) + elif func_name in self.reciprocal_trig_functions: + res = ~self.reciprocal_trig_functions[func_name](operand)._algebraic_(QQbar) + return self.field(res) + elif func_name == 'complex_root_of': + cr = ex._sympy_() + poly = cr.poly._sage_() + interval = cr._get_interval()._sage_() + return self.field.polynomial_root(poly, interval) + elif operand is not None: + res = func(operand._algebraic_(self.field)) + # We have to handle the case where we get the same symbolic + # expression back. For example, QQbar(zeta(7)). See + # issue #12665. + if (res - ex).is_trivial_zero(): + raise TypeError("unable to convert %r to %s" % (ex, self.field)) + return self.field(res) + + raise ValueError("unable to represent as an algebraic number") + + +def algebraic(ex, field): + """ + Returns the symbolic expression *ex* as a element of the algebraic + field *field*. + + EXAMPLES:: + + sage: a = SR(5/6) + sage: AA(a) + 5/6 + sage: type(AA(a)) + + sage: QQbar(a) + 5/6 + sage: type(QQbar(a)) + + sage: QQbar(i) + I + sage: AA(golden_ratio) + 1.618033988749895? + sage: QQbar(golden_ratio) + 1.618033988749895? + sage: QQbar(sin(pi/3)) + 0.866025403784439? + + sage: QQbar(sqrt(2) + sqrt(8)) + 4.242640687119285? + sage: AA(sqrt(2) ^ 4) == 4 + True + sage: AA(-golden_ratio) + -1.618033988749895? + sage: QQbar((2*SR(I))^(1/2)) + 1 + 1*I + sage: QQbar(e^(pi*I/3)) + 0.50000000000000000? + 0.866025403784439?*I + + sage: AA(x*sin(0)) + 0 + sage: QQbar(x*sin(0)) + 0 + """ + return AlgebraicConverter(field)(ex) diff --git a/src/sage/symbolic/expression_conversion_sympy.py b/src/sage/symbolic/expression_conversion_sympy.py new file mode 100644 index 00000000000..4a3b1556ce1 --- /dev/null +++ b/src/sage/symbolic/expression_conversion_sympy.py @@ -0,0 +1,317 @@ +# sage.doctest: needs sympy +r""" +Conversion of symbolic expressions to SymPy +""" +# **************************************************************************** +# Copyright (C) 2009 Mike Hansen +# 2011 D. S. McNeil +# 2011 Francois Bissey +# 2017 Ralf Stephan +# 2017 Marco Mancini +# 2017 Travis Scrimshaw +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# https://www.gnu.org/licenses/ +# **************************************************************************** + +from operator import eq, ne, gt, lt, ge, le, mul, pow, neg, add, truediv + +from sage.structure.element import Expression +from sage.symbolic.expression_conversions import Converter +from sage.symbolic.operators import arithmetic_operators + +######### +# Sympy # +######### +class SympyConverter(Converter): + """ + Converts any expression to SymPy. + + EXAMPLES:: + + sage: import sympy + sage: var('x,y') + (x, y) + sage: f = exp(x^2) - arcsin(pi+x)/y + sage: f._sympy_() + exp(x**2) - asin(x + pi)/y + sage: _._sage_() + -arcsin(pi + x)/y + e^(x^2) + + sage: sympy.sympify(x) # indirect doctest + x + + TESTS: + + Make sure we can convert I (:trac:`6424`):: + + sage: bool(I._sympy_() == I) + True + sage: (x+I)._sympy_() + x + I + + """ + def __init__(self): + """ + TESTS:: + + sage: from sage.symbolic.expression_conversions import SympyConverter + sage: s = SympyConverter() # indirect doctest + sage: TestSuite(s).run(skip="_test_pickling") + """ + from sage.interfaces.sympy import sympy_init + sympy_init() + + def __call__(self, ex=None): + """ + EXAMPLES:: + + sage: from sage.symbolic.expression_conversions import SympyConverter + sage: s = SympyConverter() + sage: f(x, y) = x^2 + y^2; f + (x, y) |--> x^2 + y^2 + sage: s(f) + Lambda((x, y), x**2 + y**2) + """ + if isinstance(ex, Expression) and ex.is_callable(): + from sympy import Symbol, Lambda + return Lambda(tuple(Symbol(str(arg)) for arg in ex.arguments()), + super().__call__(ex)) + return super().__call__(ex) + + def pyobject(self, ex, obj): + """ + EXAMPLES:: + + sage: from sage.symbolic.expression_conversions import SympyConverter + sage: s = SympyConverter() + sage: f = SR(2) + sage: s.pyobject(f, f.pyobject()) + 2 + sage: type(_) + + """ + try: + return obj._sympy_() + except AttributeError: + return obj + + def arithmetic(self, ex, operator): + """ + EXAMPLES:: + + sage: from sage.symbolic.expression_conversions import SympyConverter + sage: s = SympyConverter() + sage: f = x + 2 + sage: s.arithmetic(f, f.operator()) + x + 2 + """ + import sympy + operator = arithmetic_operators[operator] + ops = [sympy.sympify(self(a), evaluate=False) for a in ex.operands()] + if operator == "+": + return sympy.Add(*ops) + elif operator == "*": + return sympy.Mul(*ops) + elif operator == "-": + return sympy.Sub(*ops) + elif operator == "/": + return sympy.Div(*ops) + elif operator == "^": + return sympy.Pow(*ops) + else: + raise NotImplementedError + + def symbol(self, ex): + """ + EXAMPLES:: + + sage: + sage: from sage.symbolic.expression_conversions import SympyConverter + sage: s = SympyConverter() + sage: s.symbol(x) + x + sage: type(_) + + """ + import sympy + return sympy.symbols(repr(ex)) + + def relation(self, ex, op): + """ + EXAMPLES:: + + sage: + sage: import operator + sage: from sage.symbolic.expression_conversions import SympyConverter + sage: s = SympyConverter() + sage: s.relation(x == 3, operator.eq) + Eq(x, 3) + sage: s.relation(pi < 3, operator.lt) + pi < 3 + sage: s.relation(x != pi, operator.ne) + Ne(x, pi) + sage: s.relation(x > 0, operator.gt) + x > 0 + """ + from sympy import Eq, Ne, Gt, Lt, Ge, Le + ops = {eq: Eq, ne: Ne, gt: Gt, lt: Lt, ge: Ge, le: Le} + return ops.get(op)(self(ex.lhs()), self(ex.rhs()), evaluate=False) + + def composition(self, ex, operator): + """ + EXAMPLES:: + + sage: from sage.symbolic.expression_conversions import SympyConverter + sage: s = SympyConverter() + sage: f = sin(2) + sage: s.composition(f, f.operator()) + sin(2) + sage: type(_) + sin + sage: f = arcsin(2) + sage: s.composition(f, f.operator()) + asin(2) + """ + g = ex.operands() + try: + return operator._sympy_(*g) + except (AttributeError, TypeError): + pass + f = operator._sympy_init_() + import sympy + + f_sympy = getattr(sympy, f, None) + if f_sympy: + return f_sympy(*sympy.sympify(g, evaluate=False)) + else: + return sympy.Function(str(f))(*g, evaluate=False) + + def tuple(self, ex): + """ + Conversion of tuples. + + EXAMPLES:: + + sage: t = SR._force_pyobject((3, 4, e^x)) + sage: t._sympy_() + (3, 4, e^x) + sage: t = SR._force_pyobject((cos(x),)) + sage: t._sympy_() + (cos(x),) + + TESTS:: + + sage: from sage.symbolic.expression_conversions import sympy_converter + sage: F = hypergeometric([1/3,2/3],[1,1],x) + sage: F._sympy_() + hyper((1/3, 2/3), (1, 1), x) + + sage: F = hypergeometric([1/3,2/3],[1],x) + sage: F._sympy_() + hyper((1/3, 2/3), (1,), x) + + sage: var('a,b,c,d') + (a, b, c, d) + sage: hypergeometric((a,b,),(c,),d)._sympy_() + hyper((a, b), (c,), d) + """ + return tuple(ex.operands()) + + def derivative(self, ex, operator): + """ + Convert the derivative of ``self`` in sympy. + + INPUT: + + - ``ex`` -- a symbolic expression + + - ``operator`` -- operator + + TESTS:: + + sage: var('x','y') + (x, y) + + sage: f_sage = function('f_sage')(x, y) + sage: f_sympy = f_sage._sympy_() + + sage: df_sage = f_sage.diff(x, 2, y, 1); df_sage + diff(f_sage(x, y), x, x, y) + sage: df_sympy = df_sage._sympy_(); df_sympy + Derivative(f_sage(x, y), (x, 2), y) + sage: df_sympy == f_sympy.diff(x, 2, y, 1) + True + + Check that :trac:`28964` is fixed:: + + sage: f = function('f') + sage: _ = var('x,t') + sage: diff(f(x, t), x)._sympy_(), diff(f(x, t), t)._sympy_() + (Derivative(f(x, t), x), Derivative(f(x, t), t)) + + Check differentiating by variables with multiple occurrences + (:trac:`28964`):: + + sage: f = function('f') + sage: _ = var('x1,x2,x3,x,t') + sage: f(x, x, t).diff(x)._sympy_()._sage_() + D[0](f)(x, x, t) + D[1](f)(x, x, t) + + sage: g = f(x1, x2, x3, t).diff(x1, 2, x2).subs(x1==x, x2==x, x3==x); g + D[0, 0, 1](f)(x, x, x, t) + sage: g._sympy_() + Subs(Derivative(f(_xi_1, _xi_2, x, t), (_xi_1, 2), _xi_2), + (_xi_1, _xi_2), (x, x)) + sage: assert g._sympy_()._sage_() == g + + Check that the use of dummy variables does not cause a collision:: + + sage: f = function('f') + sage: _ = var('x1,x2,x,xi_1') + sage: g = f(x1, x2, xi_1).diff(x1).subs(x1==x, x2==x); g + D[0](f)(x, x, xi_1) + sage: assert g._sympy_()._sage_() == g + """ + import sympy + + # retrieve derivated function + f = operator.function() + + # retrieve order + order = operator._parameter_set + # arguments + _args = [a._sympy_() for a in ex.operands()] + + # when differentiating by a variable that occurs multiple times, + # substitute it by a dummy variable + subs_new = [] + subs_old = [] + sympy_arg = [] + for idx in order: + a = _args[idx] + if _args.count(a) > 1: + D = sympy.Dummy('xi_%i' % (idx + 1)) + # to avoid collisions with ordinary symbols when converting + # back to Sage, we pick an unused variable name for the dummy + while D._sage_() in ex.variables(): + D = sympy.Dummy(D.name + '_0') + subs_old.append(a) + subs_new.append(D) + _args[idx] = D + sympy_arg.append(D) + else: + sympy_arg.append(a) + + f_sympy = f._sympy_()(*_args) + result = f_sympy.diff(*sympy_arg) + if subs_new: + return sympy.Subs(result, subs_new, subs_old) + else: + return result + + +sympy_converter = SympyConverter() diff --git a/src/sage/symbolic/expression_conversions.py b/src/sage/symbolic/expression_conversions.py index 3dd93e032f7..2f44dd34a3e 100644 --- a/src/sage/symbolic/expression_conversions.py +++ b/src/sage/symbolic/expression_conversions.py @@ -18,6 +18,9 @@ from operator import eq, ne, gt, lt, ge, le, mul, pow, neg, add, truediv from functools import reduce +import sage.rings.abc + +from sage.misc.lazy_import import lazy_import from sage.symbolic.ring import SR from sage.structure.element import Expression from sage.functions.all import exp @@ -25,6 +28,9 @@ from sage.rings.number_field.number_field_element_base import NumberFieldElement_base from sage.rings.universal_cyclotomic_field import UniversalCyclotomicField +lazy_import('sage.symbolic.expression_conversion_sympy', ['SympyConverter', 'sympy_converter']) +lazy_import('sage.symbolic.expression_conversion_algebraic', ['AlgebraicConverter', 'algebraic']) + class FakeExpression(): r""" @@ -651,298 +657,6 @@ def composition(self, ex, operator): return self.interface._function_call_string(op, ops, []) -######### -# Sympy # -######### -class SympyConverter(Converter): - """ - Converts any expression to SymPy. - - EXAMPLES:: - - sage: import sympy - sage: var('x,y') - (x, y) - sage: f = exp(x^2) - arcsin(pi+x)/y - sage: f._sympy_() - exp(x**2) - asin(x + pi)/y - sage: _._sage_() - -arcsin(pi + x)/y + e^(x^2) - - sage: sympy.sympify(x) # indirect doctest - x - - TESTS: - - Make sure we can convert I (:trac:`6424`):: - - sage: bool(I._sympy_() == I) - True - sage: (x+I)._sympy_() - x + I - - """ - def __init__(self): - """ - TESTS:: - - sage: from sage.symbolic.expression_conversions import SympyConverter - sage: s = SympyConverter() # indirect doctest - sage: TestSuite(s).run(skip="_test_pickling") - """ - from sage.interfaces.sympy import sympy_init - sympy_init() - - def __call__(self, ex=None): - """ - EXAMPLES:: - - sage: from sage.symbolic.expression_conversions import SympyConverter - sage: s = SympyConverter() - sage: f(x, y) = x^2 + y^2; f - (x, y) |--> x^2 + y^2 - sage: s(f) - Lambda((x, y), x**2 + y**2) - """ - if isinstance(ex, Expression) and ex.is_callable(): - from sympy import Symbol, Lambda - return Lambda(tuple(Symbol(str(arg)) for arg in ex.arguments()), - super().__call__(ex)) - return super().__call__(ex) - - def pyobject(self, ex, obj): - """ - EXAMPLES:: - - sage: from sage.symbolic.expression_conversions import SympyConverter - sage: s = SympyConverter() - sage: f = SR(2) - sage: s.pyobject(f, f.pyobject()) - 2 - sage: type(_) - - """ - try: - return obj._sympy_() - except AttributeError: - return obj - - def arithmetic(self, ex, operator): - """ - EXAMPLES:: - - sage: from sage.symbolic.expression_conversions import SympyConverter - sage: s = SympyConverter() - sage: f = x + 2 - sage: s.arithmetic(f, f.operator()) - x + 2 - """ - import sympy - operator = arithmetic_operators[operator] - ops = [sympy.sympify(self(a), evaluate=False) for a in ex.operands()] - if operator == "+": - return sympy.Add(*ops) - elif operator == "*": - return sympy.Mul(*ops) - elif operator == "-": - return sympy.Sub(*ops) - elif operator == "/": - return sympy.Div(*ops) - elif operator == "^": - return sympy.Pow(*ops) - else: - raise NotImplementedError - - def symbol(self, ex): - """ - EXAMPLES:: - - sage: from sage.symbolic.expression_conversions import SympyConverter - sage: s = SympyConverter() - sage: s.symbol(x) - x - sage: type(_) - - """ - import sympy - return sympy.symbols(repr(ex)) - - def relation(self, ex, op): - """ - EXAMPLES:: - - sage: import operator - sage: from sage.symbolic.expression_conversions import SympyConverter - sage: s = SympyConverter() - sage: s.relation(x == 3, operator.eq) - Eq(x, 3) - sage: s.relation(pi < 3, operator.lt) - pi < 3 - sage: s.relation(x != pi, operator.ne) - Ne(x, pi) - sage: s.relation(x > 0, operator.gt) - x > 0 - """ - from sympy import Eq, Ne, Gt, Lt, Ge, Le - ops = {eq: Eq, ne: Ne, gt: Gt, lt: Lt, ge: Ge, le: Le} - return ops.get(op)(self(ex.lhs()), self(ex.rhs()), evaluate=False) - - def composition(self, ex, operator): - """ - EXAMPLES:: - - sage: from sage.symbolic.expression_conversions import SympyConverter - sage: s = SympyConverter() - sage: f = sin(2) - sage: s.composition(f, f.operator()) - sin(2) - sage: type(_) - sin - sage: f = arcsin(2) - sage: s.composition(f, f.operator()) - asin(2) - """ - g = ex.operands() - try: - return operator._sympy_(*g) - except (AttributeError, TypeError): - pass - f = operator._sympy_init_() - import sympy - - f_sympy = getattr(sympy, f, None) - if f_sympy: - return f_sympy(*sympy.sympify(g, evaluate=False)) - else: - return sympy.Function(str(f))(*g, evaluate=False) - - def tuple(self, ex): - """ - Conversion of tuples. - - EXAMPLES:: - - sage: t = SR._force_pyobject((3, 4, e^x)) - sage: t._sympy_() - (3, 4, e^x) - sage: t = SR._force_pyobject((cos(x),)) - sage: t._sympy_() - (cos(x),) - - TESTS:: - - sage: from sage.symbolic.expression_conversions import sympy_converter - sage: F = hypergeometric([1/3,2/3],[1,1],x) - sage: F._sympy_() - hyper((1/3, 2/3), (1, 1), x) - - sage: F = hypergeometric([1/3,2/3],[1],x) - sage: F._sympy_() - hyper((1/3, 2/3), (1,), x) - - sage: var('a,b,c,d') - (a, b, c, d) - sage: hypergeometric((a,b,),(c,),d)._sympy_() - hyper((a, b), (c,), d) - """ - return tuple(ex.operands()) - - def derivative(self, ex, operator): - """ - Convert the derivative of ``self`` in sympy. - - INPUT: - - - ``ex`` -- a symbolic expression - - - ``operator`` -- operator - - TESTS:: - - sage: var('x','y') - (x, y) - - sage: f_sage = function('f_sage')(x, y) - sage: f_sympy = f_sage._sympy_() - - sage: df_sage = f_sage.diff(x, 2, y, 1); df_sage - diff(f_sage(x, y), x, x, y) - sage: df_sympy = df_sage._sympy_(); df_sympy - Derivative(f_sage(x, y), (x, 2), y) - sage: df_sympy == f_sympy.diff(x, 2, y, 1) - True - - Check that :trac:`28964` is fixed:: - - sage: f = function('f') - sage: _ = var('x,t') - sage: diff(f(x, t), x)._sympy_(), diff(f(x, t), t)._sympy_() - (Derivative(f(x, t), x), Derivative(f(x, t), t)) - - Check differentiating by variables with multiple occurrences - (:trac:`28964`):: - - sage: f = function('f') - sage: _ = var('x1,x2,x3,x,t') - sage: f(x, x, t).diff(x)._sympy_()._sage_() - D[0](f)(x, x, t) + D[1](f)(x, x, t) - - sage: g = f(x1, x2, x3, t).diff(x1, 2, x2).subs(x1==x, x2==x, x3==x); g - D[0, 0, 1](f)(x, x, x, t) - sage: g._sympy_() - Subs(Derivative(f(_xi_1, _xi_2, x, t), (_xi_1, 2), _xi_2), - (_xi_1, _xi_2), (x, x)) - sage: assert g._sympy_()._sage_() == g - - Check that the use of dummy variables does not cause a collision:: - - sage: f = function('f') - sage: _ = var('x1,x2,x,xi_1') - sage: g = f(x1, x2, xi_1).diff(x1).subs(x1==x, x2==x); g - D[0](f)(x, x, xi_1) - sage: assert g._sympy_()._sage_() == g - """ - import sympy - - # retrieve derivated function - f = operator.function() - - # retrieve order - order = operator._parameter_set - # arguments - _args = [a._sympy_() for a in ex.operands()] - - # when differentiating by a variable that occurs multiple times, - # substitute it by a dummy variable - subs_new = [] - subs_old = [] - sympy_arg = [] - for idx in order: - a = _args[idx] - if _args.count(a) > 1: - D = sympy.Dummy('xi_%i' % (idx + 1)) - # to avoid collisions with ordinary symbols when converting - # back to Sage, we pick an unused variable name for the dummy - while D._sage_() in ex.variables(): - D = sympy.Dummy(D.name + '_0') - subs_old.append(a) - subs_new.append(D) - _args[idx] = D - sympy_arg.append(D) - else: - sympy_arg.append(a) - - f_sympy = f._sympy_()(*_args) - result = f_sympy.diff(*sympy_arg) - if subs_new: - return sympy.Subs(result, subs_new, subs_old) - else: - return result - - -sympy_converter = SympyConverter() - - ########## # FriCAS # ########## @@ -1132,284 +846,6 @@ def derivative(self, ex, operator): fricas_converter = FriCASConverter() -############# -# Algebraic # -############# -class AlgebraicConverter(Converter): - def __init__(self, field): - """ - EXAMPLES:: - - sage: from sage.symbolic.expression_conversions import AlgebraicConverter - sage: a = AlgebraicConverter(QQbar) - sage: a.field - Algebraic Field - sage: a.reciprocal_trig_functions['cot'] - tan - """ - self.field = field - - from sage.functions.all import reciprocal_trig_functions - self.reciprocal_trig_functions = reciprocal_trig_functions - - def pyobject(self, ex, obj): - """ - EXAMPLES:: - - sage: from sage.symbolic.expression_conversions import AlgebraicConverter - sage: a = AlgebraicConverter(QQbar) - sage: f = SR(2) - sage: a.pyobject(f, f.pyobject()) - 2 - sage: _.parent() - Algebraic Field - """ - return self.field(obj) - - def arithmetic(self, ex, operator): - """ - Convert a symbolic expression to an algebraic number. - - EXAMPLES:: - - sage: from sage.symbolic.expression_conversions import AlgebraicConverter - sage: f = 2^(1/2) - sage: a = AlgebraicConverter(QQbar) - sage: a.arithmetic(f, f.operator()) - 1.414213562373095? - - TESTS:: - - sage: f = pi^6 - sage: a = AlgebraicConverter(QQbar) - sage: a.arithmetic(f, f.operator()) - Traceback (most recent call last): - ... - TypeError: unable to convert pi^6 to Algebraic Field - - Test that :trac:`14602` is fixed:: - - sage: K = QuadraticField(3) - sage: K(sqrt(3)).parent() is K - True - sage: sqrt(K(3)).parent() is K - True - sage: (K(3)^(1/2)).parent() - Symbolic Ring - sage: bool(K.gen() == K(3)^(1/2) == sqrt(K(3)) == K(sqrt(3)) == sqrt(3)) - True - sage: L = QuadraticField(3, embedding=-AA(3).sqrt()) - sage: bool(L.gen() == -sqrt(3)) - True - """ - # We try to avoid simplifying, because maxima's simplify command - # can change the value of a radical expression (by changing which - # root is selected). - try: - if operator is pow: - from sage.rings.rational import Rational - base, expt = ex.operands() - base = self.field(base) - expt = Rational(expt) - return self.field(base**expt) - else: - if operator is add_vararg: - operator = add - elif operator is mul_vararg: - operator = mul - return reduce(operator, map(self, ex.operands())) - except TypeError: - pass - - if operator is pow: - from sage.symbolic.constants import e, pi, I - from sage.rings.rational_field import QQ - - base, expt = ex.operands() - if base == e and expt / (pi * I) in QQ: - return exp(expt)._algebraic_(self.field) - - raise TypeError("unable to convert %r to %s" % (ex, self.field)) - - def composition(self, ex, operator): - """ - Coerce to an algebraic number. - - EXAMPLES:: - - sage: from sage.symbolic.expression_conversions import AlgebraicConverter - sage: a = AlgebraicConverter(QQbar) - sage: a.composition(exp(I*pi/3, hold=True), exp) - 0.500000000000000? + 0.866025403784439?*I - sage: a.composition(sin(pi/7), sin) - 0.4338837391175581? + 0.?e-18*I - - sage: x = SR.var('x') - sage: a.composition(complex_root_of(x^3 - x^2 - x - 1, 0), complex_root_of) - 1.839286755214161? - sage: a.composition(complex_root_of(x^5 - 1, 3), complex_root_of) - 0.3090169943749474? - 0.9510565162951536?*I - sage: a.composition(complex_root_of(x^2 + 1, 0), complex_root_of) - 1.?e-684 - 0.9999999999999999?*I - sage: a.composition(complex_root_of(x^2 + 1, 1), complex_root_of) - 1.?e-684 + 0.9999999999999999?*I - - TESTS:: - - sage: QQbar(zeta(7)) - Traceback (most recent call last): - ... - TypeError: unable to convert zeta(7) to Algebraic Field - - Test :trac:`22571`:: - - sage: a.composition(exp(0, hold=True), exp) - 1 - sage: a.composition(exp(1, hold=True), exp) - Traceback (most recent call last): - ... - ValueError: unable to represent as an algebraic number - sage: a.composition(exp(pi*I*RR(1), hold=True), exp) - Traceback (most recent call last): - ... - TypeError: unable to convert e^(1.00000000000000*I*pi) to Algebraic Field - sage: a.composition(exp(pi*CC.gen(), hold=True), exp) - Traceback (most recent call last): - ... - TypeError: unable to convert e^(1.00000000000000*I*pi) to Algebraic Field - sage: bool(sin(pi*RR("0.7000000000000002")) > 0) - True - - Check that :trac:`24440` is fixed:: - - sage: QQbar(tanh(pi + 0.1)) - Traceback (most recent call last): - ... - ValueError: unable to represent as an algebraic number - sage: QQbar(sin(I*pi/7)) - Traceback (most recent call last): - ... - ValueError: unable to represent as an algebraic number - sage: QQbar(sin(I*pi/7, hold=True)) - Traceback (most recent call last): - ... - ValueError: unable to represent as an algebraic number - """ - func = operator - operands = ex.operands() - if len(operands) == 1: - operand = operands[0] - else: - operand = None - - if isinstance(self.field, UniversalCyclotomicField): - QQbar = self.field - hold = True - else: - QQbar = self.field.algebraic_closure() - hold = False - - zeta = QQbar.zeta - # Note that comparing functions themselves goes via maxima, and is SLOW - func_name = repr(func) - if func_name == 'exp': - if operand.is_trivial_zero(): - return self.field.one() - if not (SR(-1).sqrt() * operand).is_real(): - raise ValueError("unable to represent as an algebraic number") - # Coerce (not convert, see #22571) arg to a rational - from sage.rings.rational_field import QQ - arg = operand.imag()/(2*ex.parent().pi()) - try: - rat_arg = QQ.coerce(arg.pyobject()) - except TypeError: - raise TypeError("unable to convert %r to %s" % (ex, self.field)) - res = zeta(rat_arg.denom())**rat_arg.numer() - return self.field(res) - elif func_name in ['sin', 'cos', 'tan']: - exp_ia = exp(SR(-1).sqrt() * operand, hold=hold)._algebraic_(QQbar) - if func_name == 'sin': - res = (exp_ia - ~exp_ia) / (2 * zeta(4)) - elif func_name == 'cos': - res = (exp_ia + ~exp_ia) / 2 - else: - res = -zeta(4) * (exp_ia - ~exp_ia) / (exp_ia + ~exp_ia) - return self.field(res) - elif func_name in ['sinh', 'cosh', 'tanh']: - if not (SR(-1).sqrt()*operand).is_real(): - raise ValueError("unable to represent as an algebraic number") - exp_a = exp(operand, hold=hold)._algebraic_(QQbar) - if func_name == 'sinh': - res = (exp_a - ~exp_a) / 2 - elif func_name == 'cosh': - res = (exp_a + ~exp_a) / 2 - else: - res = (exp_a - ~exp_a) / (exp_a + ~exp_a) - return self.field(res) - elif func_name in self.reciprocal_trig_functions: - res = ~self.reciprocal_trig_functions[func_name](operand)._algebraic_(QQbar) - return self.field(res) - elif func_name == 'complex_root_of': - cr = ex._sympy_() - poly = cr.poly._sage_() - interval = cr._get_interval()._sage_() - return self.field.polynomial_root(poly, interval) - elif operand is not None: - res = func(operand._algebraic_(self.field)) - # We have to handle the case where we get the same symbolic - # expression back. For example, QQbar(zeta(7)). See - # issue #12665. - if (res - ex).is_trivial_zero(): - raise TypeError("unable to convert %r to %s" % (ex, self.field)) - return self.field(res) - - raise ValueError("unable to represent as an algebraic number") - - -def algebraic(ex, field): - """ - Returns the symbolic expression *ex* as a element of the algebraic - field *field*. - - EXAMPLES:: - - sage: a = SR(5/6) - sage: AA(a) - 5/6 - sage: type(AA(a)) - - sage: QQbar(a) - 5/6 - sage: type(QQbar(a)) - - sage: QQbar(i) - I - sage: AA(golden_ratio) - 1.618033988749895? - sage: QQbar(golden_ratio) - 1.618033988749895? - sage: QQbar(sin(pi/3)) - 0.866025403784439? - - sage: QQbar(sqrt(2) + sqrt(8)) - 4.242640687119285? - sage: AA(sqrt(2) ^ 4) == 4 - True - sage: AA(-golden_ratio) - -1.618033988749895? - sage: QQbar((2*SR(I))^(1/2)) - 1 + 1*I - sage: QQbar(e^(pi*I/3)) - 0.50000000000000000? + 0.866025403784439?*I - - sage: AA(x*sin(0)) - 0 - sage: QQbar(x*sin(0)) - 0 - """ - return AlgebraicConverter(field)(ex) - - ############## # Polynomial # ############## diff --git a/src/sage/symbolic/function.pyx b/src/sage/symbolic/function.pyx index 0d347103756..f4bd22df0a6 100644 --- a/src/sage/symbolic/function.pyx +++ b/src/sage/symbolic/function.pyx @@ -77,9 +77,9 @@ like a symbol. Setting ``nargs=0`` allows any number of arguments:: ....: def _eval_(self, *args): ....: pass sage: f = Test1() - sage: f() + sage: f() # needs sage.symbolic test() - sage: f(1,2,3)*f(1,2,3) + sage: f(1,2,3)*f(1,2,3) # needs sage.symbolic test(1, 2, 3)^2 In the following the ``sin`` function of ``CBF(0)`` is called because with @@ -97,14 +97,14 @@ is attempted, and after that ``sin()`` which succeeds:: sage: f = Test2() sage: f(0) 5 - sage: f(0, hold=True) + sage: f(0, hold=True) # needs sage.symbolic my_sin(0) - sage: f(0, hold=True).n() + sage: f(0, hold=True).n() # needs sage.rings.real_mpfr 3.50000000000000 - sage: f(CBF(0)) + sage: f(CBF(0)) # needs sage.libs.flint 0 - sage: latex(f(0, hold=True)) + sage: latex(f(0, hold=True)) # needs sage.symbolic \SIN\left(0\right) sage: f(1,2) Traceback (most recent call last): @@ -141,11 +141,6 @@ is attempted, and after that ``sin()`` which succeeds:: from sage.structure.sage_object cimport SageObject from sage.structure.element cimport Element, parent, Expression from sage.misc.lazy_attribute import lazy_attribute -from .expression import ( - call_registered_function, find_registered_function, register_or_update_function, - get_sfunction_from_hash -) -from .expression import get_sfunction_from_serial as get_sfunction_from_serial from sage.structure.coerce cimport (coercion_model, py_scalar_to_element, is_numpy_type, is_mpmath_type) @@ -153,6 +148,17 @@ from sage.structure.richcmp cimport richcmp from sage.misc.fpickle import pickle_function, unpickle_function +from .symbols import symbol_table, register_symbol + +try: + from .expression import ( + call_registered_function, find_registered_function, register_or_update_function, + get_sfunction_from_hash, get_sfunction_from_serial as get_sfunction_from_serial + ) +except ImportError: + register_or_update_function = None + + # List of functions which ginac allows us to define custom behavior for. # Changing the order of this list could cause problems unpickling old pickles. sfunctions_funcs = ['eval', 'evalf', 'conjugate', 'real_part', 'imag_part', @@ -176,32 +182,34 @@ cdef class Function(SageObject): EXAMPLES:: - sage: f = function('f', nargs=1, conjugate_func=lambda self,x: 2r*x) # indirect doctest - sage: f(2) + sage: f = function('f', nargs=1, # indirect doctest # needs sage.symbolic + ....: conjugate_func=lambda self, x: 2r*x) + sage: f(2) # needs sage.symbolic f(2) - sage: f(2).conjugate() + sage: f(2).conjugate() # needs sage.symbolic 4 TESTS:: # eval_func raises exception sage: def ef(self, x): raise RuntimeError("foo") - sage: bar = function("bar", nargs=1, eval_func=ef) - sage: bar(x) + sage: bar = function("bar", nargs=1, eval_func=ef) # needs sage.symbolic + sage: bar(x) # needs sage.symbolic Traceback (most recent call last): ... RuntimeError: foo # eval_func returns non coercible sage: def ef(self, x): return ZZ - sage: bar = function("bar", nargs=1, eval_func=ef) - sage: bar(x) + sage: bar = function("bar", nargs=1, eval_func=ef) # needs sage.symbolic + sage: bar(x) # needs sage.symbolic Traceback (most recent call last): ... - TypeError: function did not return a symbolic expression or an element that can be coerced into a symbolic expression + TypeError: function did not return a symbolic expression + or an element that can be coerced into a symbolic expression # eval_func is not callable - sage: bar = function("bar", nargs=1, eval_func=5) + sage: bar = function("bar", nargs=1, eval_func=5) # needs sage.symbolic Traceback (most recent call last): ... ValueError: eval_func parameter must be callable @@ -230,13 +238,11 @@ cdef class Function(SageObject): callable(getattr(self, real_fname)): raise ValueError(real_fname + " parameter must be callable") - if not self._is_registered(): - self._register_function() - - from .expression import symbol_table, register_symbol - - symbol_table['functions'][self._name] = self + symbol_table['functions'][self._name] = self + if register_or_update_function: # Symbolic subsystem present + if not self._is_registered(): + self._register_function() register_symbol(self, self._conversions) cdef _is_registered(self): @@ -255,6 +261,7 @@ cdef class Function(SageObject): functions was broken. We check here that this is fixed (:trac:`11919`):: + sage: # needs sage.symbolic sage: f = function('f')(x) sage: s = dumps(f) sage: loads(s) @@ -281,7 +288,7 @@ cdef class Function(SageObject): TESTS:: - sage: coth(5) # indirect doctest + sage: coth(5) # indirect doctest # needs sage.symbolic coth(5) sage: coth(0.5) 2.16395341373865 @@ -302,13 +309,13 @@ cdef class Function(SageObject): sage: test = Test() sage: test(1.3, 4) 2.30000000000000 - sage: test(pi, 4) + sage: test(pi, 4) # needs sage.symbolic test(pi, 4) - sage: test(2, x) + sage: test(2, x) # needs sage.symbolic 3 sage: test(2., 4) 3.00000000000000 - sage: test(1 + 1.0*I, 2) + sage: test(1 + 1.0*I, 2) # needs sage.symbolic 2.00000000000000 + 1.00000000000000*I sage: class Test2(BuiltinFunction): ....: def __init__(self): @@ -324,7 +331,7 @@ cdef class Function(SageObject): sage: test2 = Test2() sage: test2(1.3) 0.500000000000000 - sage: test2(pi) + sage: test2(pi) # needs sage.symbolic 3 """ # If any of the inputs is numerical and none is symbolic, @@ -342,10 +349,10 @@ cdef class Function(SageObject): """ EXAMPLES:: - sage: f = function('f', nargs=1, conjugate_func=lambda self,x: 2r*x) - sage: f.__hash__() #random + sage: f = function('f', nargs=1, conjugate_func=lambda self, x: 2r*x) # needs sage.symbolic + sage: f.__hash__() # random # needs sage.symbolic -2224334885124003860 - sage: hash(f(2)) #random + sage: hash(f(2)) # random # needs sage.symbolic 4168614485 """ return hash(self._name)*(self._nargs+1)*self._serial @@ -354,7 +361,7 @@ cdef class Function(SageObject): """ EXAMPLES:: - sage: foo = function("foo", nargs=2); foo + sage: foo = function("foo", nargs=2); foo # needs sage.symbolic foo """ return self._name @@ -383,12 +390,13 @@ cdef class Function(SageObject): """ TESTS:: + sage: # needs sage.symbolic sage: foo = function("foo", nargs=2) sage: foo == foo True sage: foo == 2 False - sage: foo(1,2).operator() == foo + sage: foo(1, 2).operator() == foo True """ @@ -402,56 +410,55 @@ cdef class Function(SageObject): """ Evaluates this function at the given arguments. - We coerce the arguments into symbolic expressions if coerce=True, then + We coerce the arguments into symbolic expressions if ``coerce=True``, then call the Pynac evaluation method, which in turn passes the arguments to a custom automatic evaluation method if ``_eval_()`` is defined. EXAMPLES:: + sage: # needs sage.symbolic sage: foo = function("foo", nargs=2) sage: x,y,z = var("x y z") - sage: foo(x,y) + sage: foo(x, y) foo(x, y) - sage: foo(y) Traceback (most recent call last): ... TypeError: Symbolic function foo takes exactly 2 arguments (1 given) - sage: bar = function("bar") sage: bar(x) bar(x) - sage: bar(x,y) + sage: bar(x, y) bar(x, y) The `hold` argument prevents automatic evaluation of the function:: - sage: exp(log(x)) + sage: exp(log(x)) # needs sage.symbolic x - sage: exp(log(x), hold=True) + sage: exp(log(x), hold=True) # needs sage.symbolic e^log(x) We can also handle numpy types:: - sage: import numpy - sage: sin(numpy.arange(5)) + sage: import numpy # needs numpy + sage: sin(numpy.arange(5)) # needs numpy array([ 0. , 0.84147098, 0.90929743, 0.14112001, -0.7568025 ]) Symbolic functions evaluate non-exact input numerically, and return symbolic expressions on exact input, or if any input is symbolic:: - sage: arctan(1) + sage: arctan(1) # needs sage.symbolic 1/4*pi - sage: arctan(float(1)) + sage: arctan(float(1)) # needs sage.rings.complex_double 0.7853981633974483 - sage: type(lambert_w(SR(0))) + sage: type(lambert_w(SR(0))) # needs sage.symbolic Precision of the result depends on the precision of the input:: sage: arctan(RR(1)) 0.785398163397448 - sage: arctan(RealField(100)(1)) + sage: arctan(RealField(100)(1)) # needs sage.rings.real_mpfr 0.78539816339744830961566084582 Return types for non-exact input depends on the input type:: @@ -466,29 +473,31 @@ cdef class Function(SageObject): Test coercion:: - sage: bar(ZZ) + sage: bar(ZZ) # needs sage.symbolic Traceback (most recent call last): ... TypeError: cannot coerce arguments: ... - sage: exp(QQbar(I)) + sage: exp(QQbar(I)) # needs sage.rings.number_field sage.symbolic e^I For functions with single argument, if coercion fails we try to call a method with the name of the function on the object:: - sage: M = matrix(SR, 2, 2, [x, 0, 0, I*pi]) - sage: exp(M) + sage: M = matrix(SR, 2, 2, [x, 0, 0, I*pi]) # needs sage.modules sage.symbolic + sage: exp(M) # needs sage.modules sage.symbolic [e^x 0] [ 0 -1] Make sure we can pass mpmath arguments (:trac:`13608`):: - sage: import mpmath - sage: with mpmath.workprec(128): sin(mpmath.mpc('0.5', '1.2')) - mpc(real='0.86807452059118713192871150787046523179886', imag='1.3246769633571289324095313649562791720086') + sage: import mpmath # needs mpmath + sage: with mpmath.workprec(128): sin(mpmath.mpc('0.5', '1.2')) # needs mpmath + mpc(real='0.86807452059118713192871150787046523179886', + imag='1.3246769633571289324095313649562791720086') Check that :trac:`10133` is fixed:: + sage: # needs sage.symbolic sage: out = sin(0) sage: out, parent(out) (0, Integer Ring) @@ -504,6 +513,7 @@ cdef class Function(SageObject): Check that ``real_part`` and ``imag_part`` still works after :trac:`21216`:: + sage: # needs numpy sage.symbolic sage: import numpy sage: a = numpy.array([1+2*I, -2-3*I], dtype=complex) sage: real_part(a) @@ -516,11 +526,9 @@ cdef class Function(SageObject): # if the given input is a symbolic expression, we don't convert it back # to a numeric type at the end + symbolic_input = any(isinstance(arg, Expression) for arg in args) + from .ring import SR - if any(parent(arg) is SR for arg in args): - symbolic_input = True - else: - symbolic_input = False if coerce: try: @@ -545,7 +553,7 @@ cdef class Function(SageObject): raise TypeError("arguments must be symbolic expressions") return call_registered_function(self._serial, self._nargs, args, hold, - not symbolic_input, SR) + not symbolic_input, SR) def name(self): """ @@ -553,8 +561,8 @@ cdef class Function(SageObject): EXAMPLES:: - sage: foo = function("foo", nargs=2) - sage: foo.name() + sage: foo = function("foo", nargs=2) # needs sage.symbolic + sage: foo.name() # needs sage.symbolic 'foo' """ return self._name @@ -565,12 +573,12 @@ cdef class Function(SageObject): EXAMPLES:: + sage: # needs sage.symbolic sage: foo = function("foo", nargs=2) sage: foo.number_of_arguments() 2 - sage: foo(x,x) + sage: foo(x, x) foo(x, x) - sage: foo(x) Traceback (most recent call last): ... @@ -595,7 +603,7 @@ cdef class Function(SageObject): EXAMPLES:: - sage: sin.default_variable() + sage: sin.default_variable() # needs sage.symbolic x """ from .ring import SR @@ -615,14 +623,15 @@ cdef class Function(SageObject): sage: [sin._is_numerical(a) for a in [5., 5.4r]] [True, True] - sage: [sin._is_numerical(a) for a in [5, pi]] + sage: [sin._is_numerical(a) for a in [5, pi]] # needs sage.symbolic [False, False] - sage: [sin._is_numerical(R(1)) for R in [RIF, CIF, RBF, CBF]] + sage: [sin._is_numerical(R(1)) for R in [RIF, CIF, RBF, CBF]] # needs sage.libs.flint [False, False, False, False] The following calls used to yield incorrect results because intervals were considered numerical by this method:: + sage: # needs sage.libs.flint sage: b = RBF(3/2, 1e-10) sage: airy_ai(b) airy_ai([1.500000000 +/- 1.01e-10]) @@ -650,7 +659,7 @@ cdef class Function(SageObject): """ EXAMPLES:: - sage: sin._interface_init_(maxima) + sage: sin._interface_init_(maxima) # needs sage.symbolic 'sin' """ if I is None: @@ -665,7 +674,7 @@ cdef class Function(SageObject): 'Sin' sage: exp._mathematica_init_() 'Exp' - sage: (exp(x) + sin(x) + tan(x))._mathematica_init_() + sage: (exp(x) + sin(x) + tan(x))._mathematica_init_() # needs sage.symbolic '(Exp[x])+(Sin[x])+(Tan[x])' """ s = self._conversions.get('mathematica', None) @@ -681,7 +690,7 @@ cdef class Function(SageObject): sage: g = SymbolicFunction('g', conversions=dict(sympy='gg')) sage: g._sympy_init_() 'gg' - sage: g(x)._sympy_() + sage: g(x)._sympy_() # needs sage.symbolic gg(x) """ return self._conversions.get('sympy', self._name) @@ -691,9 +700,9 @@ cdef class Function(SageObject): """ EXAMPLES:: - sage: cos._sympy_() + sage: cos._sympy_() # needs sympy cos - sage: _(0) + sage: _(0) # needs sympy 1 """ f = self._sympy_init_() @@ -742,16 +751,17 @@ cdef class Function(SageObject): EXAMPLES:: + sage: # needs numpy sage: import numpy sage: a = numpy.arange(5) sage: csc(a) doctest:...: RuntimeWarning: divide by zero encountered in ...divide array([ inf, 1.18839511, 1.09975017, 7.0861674 , -1.32134871]) - sage: factorial(a) Traceback (most recent call last): ... - NotImplementedError: The Function factorial does not support numpy arrays as arguments + NotImplementedError: The Function factorial does + not support numpy arrays as arguments """ raise NotImplementedError("The Function %s does not support numpy arrays as arguments" % self.name()) @@ -769,8 +779,8 @@ cdef class Function(SageObject): implementation, using sage reals instead of mpmath ones. This might change when aliases for these functions are established:: - sage: import mpmath - sage: with mpmath.workprec(128): arcsin(mpmath.mpf('0.5')) + sage: import mpmath # needs mpmath + sage: with mpmath.workprec(128): arcsin(mpmath.mpf('0.5')) # needs mpmath mpf('0.52359877559829887307710723054658381403157') TESTS: @@ -779,6 +789,7 @@ cdef class Function(SageObject): not using mpmath, we have to create a custom function which will certainly never get created in mpmath. :: + sage: # needs mpmath sage: import mpmath sage: from sage.symbolic.function import BuiltinFunction sage: class NoMpmathFn(BuiltinFunction): @@ -806,6 +817,7 @@ cdef class Function(SageObject): res = sage_to_mpmath(res, prec) return res + cdef class GinacFunction(BuiltinFunction): """ This class provides a wrapper around symbolic functions already defined in @@ -824,12 +836,12 @@ cdef class GinacFunction(BuiltinFunction): TESTS:: sage: from sage.functions.trig import Function_sin - sage: s = Function_sin() # indirect doctest - sage: s(0) + sage: s = Function_sin() # indirect doctest + sage: s(0) # needs sage.symbolic 0 - sage: s(pi) + sage: s(pi) # needs sage.symbolic 0 - sage: s(pi/2) + sage: s(pi/2) # needs sage.symbolic 1 """ self._ginac_name = ginac_name @@ -873,8 +885,8 @@ cdef class BuiltinFunction(Function): TESTS:: sage: from sage.functions.trig import Function_cot - sage: c = Function_cot() # indirect doctest - sage: c(pi/2) + sage: c = Function_cot() # indirect doctest + sage: c(pi/2) # needs sage.symbolic 0 """ self._preserved_arg = preserved_arg @@ -924,7 +936,7 @@ cdef class BuiltinFunction(Function): EXAMPLES:: - sage: exp(5) + sage: exp(5) # needs sage.symbolic e^5 sage: gamma(15) 87178291200 @@ -944,16 +956,17 @@ cdef class BuiltinFunction(Function): (1.5430806348152437-0j) sage: assert type(_) is complex + sage: # needs mpmath sage: import mpmath sage: cos(mpmath.mpf('1.321412')) mpf('0.24680737898640387') sage: cos(mpmath.mpc(1,1)) mpc(real='0.83373002513114902', imag='-0.98889770576286506') - sage: import numpy - sage: sin(numpy.int32(0)) + sage: import numpy # needs numpy + sage: sin(numpy.int32(0)) # needs numpy 0.0 - sage: type(_) + sage: type(_) # needs numpy TESTS:: @@ -1081,15 +1094,15 @@ cdef class BuiltinFunction(Function): sage: from sage.symbolic.function import BuiltinFunction sage: class AFunction(BuiltinFunction): ....: def __init__(self, name, exp=1): - ....: self.exponent=exp + ....: self.exponent = exp ....: BuiltinFunction.__init__(self, name, nargs=1) ....: def _eval_(self, arg): ....: return arg**self.exponent sage: p2 = AFunction('p2', 2) - sage: p2(x) + sage: p2(x) # needs sage.symbolic x^2 sage: p3 = AFunction('p3', 3) - sage: p3(x) + sage: p3(x) # needs sage.symbolic x^3 sage: loads(dumps(cot)) == cot # trac #15138 True @@ -1132,7 +1145,7 @@ cdef class BuiltinFunction(Function): (, ()) sage: f = loads(dumps(cot)) #indirect doctest - sage: f(pi/2) + sage: f(pi/2) # needs sage.symbolic 0 """ return self.__class__, tuple() @@ -1179,11 +1192,11 @@ cdef class SymbolicFunction(Function): sage: foo = my_function() sage: foo foo - sage: foo(2,3) + sage: foo(2, 3) # needs sage.symbolic foo(2, 3) - sage: foo(2,3).n() + sage: foo(2, 3).n() # needs sage.rings.real_mpfr 12.0000000000000 - sage: foo(2,3).conjugate() + sage: foo(2, 3).conjugate() # needs sage.symbolic 2 """ self.__hinit = False @@ -1222,13 +1235,13 @@ cdef class SymbolicFunction(Function): """ TESTS:: - sage: foo = function("foo", nargs=2) - sage: hash(foo) # random output + sage: foo = function("foo", nargs=2) # needs sage.symbolic + sage: hash(foo) # random output # needs sage.symbolic -6859868030555295348 sage: def ev(self, x): return 2*x - sage: foo = function("foo", nargs=2, eval_func = ev) - sage: hash(foo) # random output + sage: foo = function("foo", nargs=2, eval_func=ev) # needs sage.symbolic + sage: hash(foo) # random output # needs sage.symbolic -6859868030555295348 """ return self._serial*self._hash_() @@ -1268,35 +1281,41 @@ cdef class SymbolicFunction(Function): EXAMPLES:: + sage: # needs sage.symbolic sage: foo = function("foo", nargs=2) sage: foo.__getstate__() - (2, 'foo', 2, None, {}, True, [None, None, None, None, None, None, None, None, None, None, None]) + (2, 'foo', 2, None, {}, True, + [None, None, None, None, None, None, None, None, None, None, None]) sage: t = loads(dumps(foo)) sage: t == foo True sage: var('x,y') (x, y) - sage: t(x,y) + sage: t(x, y) foo(x, y) sage: def ev(self, x,y): return 2*x - sage: foo = function("foo", nargs=2, eval_func = ev) - sage: foo.__getstate__() - (2, 'foo', 2, None, {}, True, [..., None, None, None, None, None, None, None, None, None, None]) + sage: foo = function("foo", nargs=2, eval_func=ev) # needs sage.symbolic + sage: foo.__getstate__() # needs sage.symbolic + (2, 'foo', 2, None, {}, True, + [..., None, None, None, None, None, None, None, None, None, None]) + sage: # needs sage.symbolic sage: u = loads(dumps(foo)) sage: u == foo True sage: t == u False - sage: u(y,x) + sage: u(y, x) 2*y sage: def evalf_f(self, x, **kwds): return int(6) - sage: foo = function("foo", nargs=1, evalf_func=evalf_f) - sage: foo.__getstate__() - (2, 'foo', 1, None, {}, True, [None, ..., None, None, None, None, None, None, None, None, None]) + sage: foo = function("foo", nargs=1, evalf_func=evalf_f) # needs sage.symbolic + sage: foo.__getstate__() # needs sage.symbolic + (2, 'foo', 1, None, {}, True, + [None, ..., None, None, None, None, None, None, None, None, None]) + sage: # needs sage.symbolic sage: v = loads(dumps(foo)) sage: v == foo True @@ -1309,11 +1328,11 @@ cdef class SymbolicFunction(Function): Test pickling expressions with symbolic functions:: - sage: u = loads(dumps(foo(x)^2 + foo(y) + x^y)); u + sage: u = loads(dumps(foo(x)^2 + foo(y) + x^y)); u # needs sage.symbolic foo(x)^2 + x^y + foo(y) - sage: u.subs(y=0) + sage: u.subs(y=0) # needs sage.symbolic foo(x)^2 + foo(0) + 1 - sage: u.subs(y=0).n() + sage: u.subs(y=0).n() # needs sage.symbolic 43.0000000000000 """ return (2, self._name, self._nargs, self._latex_name, self._conversions, @@ -1330,6 +1349,7 @@ cdef class SymbolicFunction(Function): TESTS:: + sage: # needs sage.symbolic sage: var('x,y') (x, y) sage: foo = function("foo", nargs=2) @@ -1338,23 +1358,24 @@ cdef class SymbolicFunction(Function): :: - sage: g = function('g', nargs=1, conjugate_func=lambda y,x: 2*x) + sage: # needs sage.symbolic + sage: g = function('g', nargs=1, conjugate_func=lambda y, x: 2*x) sage: st = g.__getstate__() sage: f = function('f') sage: f(x) f(x) - sage: f(x).conjugate() # no special conjugate method + sage: f(x).conjugate() # no special conjugate method conjugate(f(x)) sage: f.__setstate__(st) - sage: f(x+1).conjugate() # now there is a special method + sage: f(x + 1).conjugate() # now there is a special method 2*x + 2 Note that the other direction doesn't work here, since ``foo._hash_()`` hash already been initialized.:: - sage: bar + sage: bar # needs sage.symbolic foo - sage: bar(x,y) + sage: bar(x, y) # needs sage.symbolic foo(x, y) """ # check input diff --git a/src/sage/symbolic/ginac/numeric.cpp b/src/sage/symbolic/ginac/numeric.cpp index b40ed64edb5..3d3ba0b22ec 100644 --- a/src/sage/symbolic/ginac/numeric.cpp +++ b/src/sage/symbolic/ginac/numeric.cpp @@ -209,9 +209,9 @@ PyObject* RR_get() { static PyObject* ptr = nullptr; if (ptr == nullptr) { - PyObject* m = PyImport_ImportModule("sage.rings.all"); + PyObject* m = PyImport_ImportModule("sage.rings.real_mpfr"); if (m == nullptr) - py_error("Error importing sage.rings.all"); + py_error("Error importing sage.rings.real_mpfr"); ptr = PyObject_GetAttrString(m, "RR"); if (ptr == nullptr) py_error("Error getting RR attribute"); @@ -225,13 +225,10 @@ PyObject* CC_get() static PyObject* ptr = nullptr; if (ptr) return ptr; - PyObject* m = PyImport_ImportModule("sage.rings.all"); + PyObject* m = PyImport_ImportModule("sage.rings.cc"); if (m == nullptr) - py_error("Error importing sage.rings.all"); - ptr = PyObject_GetAttrString(m, "ComplexField"); - if (ptr == nullptr) - py_error("Error getting ComplexField attribute"); - ptr = PyObject_CallObject(ptr, NULL); + py_error("Error importing sage.rings.cc"); + ptr = PyObject_GetAttrString(m, "CC"); if (ptr == nullptr) py_error("Error getting CC attribute"); Py_INCREF(ptr); @@ -310,9 +307,9 @@ int precision(const GiNaC::numeric& num, PyObject*& a_parent) { } PyObject* CBF(int res) { - PyObject* m = PyImport_ImportModule("sage.rings.all"); + PyObject* m = PyImport_ImportModule("sage.rings.complex_arb"); if (m == nullptr) - py_error("Error importing arb"); + py_error("Error importing sage.rings.complex_arb"); PyObject* f = PyObject_GetAttrString(m, "ComplexBallField"); if (f == nullptr) py_error("Error getting ComplexBallField attribute"); @@ -392,9 +389,9 @@ PyObject* CallBallMethod1Arg(PyObject* field, const char* meth, const GiNaC::num } PyObject* CoerceBall(PyObject* ball, int prec) { - PyObject* m = PyImport_ImportModule("sage.rings.all"); + PyObject* m = PyImport_ImportModule("sage.rings.complex_mpfr"); if (m == nullptr) - py_error("Error importing sage.rings.all"); + py_error("Error importing sage.rings.complex_mpfr"); PyObject* f = PyObject_GetAttrString(m, "ComplexField"); if (f == nullptr) py_error("Error getting ComplexField attribute"); diff --git a/src/sage/symbolic/integration/external.py b/src/sage/symbolic/integration/external.py index 55e658513e5..1e242c3f442 100644 --- a/src/sage/symbolic/integration/external.py +++ b/src/sage/symbolic/integration/external.py @@ -3,7 +3,7 @@ TESTS:: sage: from sage.symbolic.integration.external import sympy_integrator - sage: sympy_integrator(sin(x), x) + sage: sympy_integrator(sin(x), x) # needs sympy -cos(x) """ from sage.symbolic.expression import Expression @@ -54,9 +54,9 @@ def sympy_integrator(expression, v, a=None, b=None): EXAMPLES:: sage: from sage.symbolic.integration.external import sympy_integrator - sage: sympy_integrator(sin(x), x) + sage: sympy_integrator(sin(x), x) # needs sympy -cos(x) - sage: sympy_integrator(cos(x), x) + sage: sympy_integrator(cos(x), x) # needs sympy sin(x) """ import sympy @@ -136,14 +136,15 @@ def fricas_integrator(expression, v, a=None, b=None, noPole=True): EXAMPLES:: - sage: from sage.symbolic.integration.external import fricas_integrator # optional - fricas - sage: fricas_integrator(sin(x), x) # optional - fricas + sage: # optional - fricas + sage: from sage.symbolic.integration.external import fricas_integrator + sage: fricas_integrator(sin(x), x) -cos(x) - sage: fricas_integrator(cos(x), x) # optional - fricas + sage: fricas_integrator(cos(x), x) sin(x) - sage: fricas_integrator(1/(x^2-2), x, 0, 1) # optional - fricas + sage: fricas_integrator(1/(x^2-2), x, 0, 1) -1/8*sqrt(2)*(log(2) - log(-24*sqrt(2) + 34)) - sage: fricas_integrator(1/(x^2+6), x, -oo, oo) # optional - fricas + sage: fricas_integrator(1/(x^2+6), x, -oo, oo) 1/6*sqrt(6)*pi TESTS: diff --git a/src/sage/symbolic/integration/integral.py b/src/sage/symbolic/integration/integral.py index e84ad357ee2..e431e76a767 100644 --- a/src/sage/symbolic/integration/integral.py +++ b/src/sage/symbolic/integration/integral.py @@ -362,9 +362,9 @@ def _sympy_(self, f, x, a, b): EXAMPLES:: - sage: integral(x, x, 0, 1, hold=True)._sympy_() + sage: integral(x, x, 0, 1, hold=True)._sympy_() # needs sympy Integral(x, (x, 0, 1)) - sage: _.doit() + sage: _.doit() # needs sympy 1/2 """ from sympy.integrals import Integral @@ -619,12 +619,12 @@ def integrate(expression, v=None, a=None, b=None, algorithm=None, hold=False): sage: integrate(x*sin(log(x)), x) -1/5*x^2*(cos(log(x)) - 2*sin(log(x))) - sage: integrate(x*sin(log(x)), x, algorithm='sympy') + sage: integrate(x*sin(log(x)), x, algorithm='sympy') # needs sympy -1/5*x^2*cos(log(x)) + 2/5*x^2*sin(log(x)) sage: _ = var('y, z') sage: (x^y - z).integrate(y) -y*z + x^y/log(x) - sage: (x^y - z).integrate(y, algorithm="sympy") + sage: (x^y - z).integrate(y, algorithm="sympy") # needs sympy -y*z + cases(((log(x) != 0, x^y/log(x)), (1, y))) We integrate the above function in Maple now:: @@ -681,7 +681,7 @@ def integrate(expression, v=None, a=None, b=None, algorithm=None, hold=False): sage: integrate(f(x), x, 1, 2, algorithm="fricas") # optional - fricas -1/2*pi + arctan(8) + arctan(5) + arctan(2) + arctan(1/2) - sage: integrate(f(x), x, 1, 2, algorithm="sympy") + sage: integrate(f(x), x, 1, 2, algorithm="sympy") # needs sympy -1/2*pi + arctan(8) + arctan(5) + arctan(2) + arctan(1/2) Using Giac to integrate the absolute value of a trigonometric expression:: @@ -856,7 +856,7 @@ def integrate(expression, v=None, a=None, b=None, algorithm=None, hold=False): Verify that MinusInfinity works with sympy (:trac:`12345`):: - sage: integral(1/x^2, x, -infinity, -1, algorithm='sympy') + sage: integral(1/x^2, x, -infinity, -1, algorithm='sympy') # needs sympy 1 Check that :trac:`11737` is fixed:: diff --git a/src/sage/symbolic/pynac.pxi b/src/sage/symbolic/pynac.pxi index 03da305ca97..09f0ad032d5 100644 --- a/src/sage/symbolic/pynac.pxi +++ b/src/sage/symbolic/pynac.pxi @@ -3,7 +3,7 @@ Declarations for pynac, a Python frontend for ginac Check that we can externally cimport this (:trac:`18825`):: - sage: cython( # optional - sage.misc.cython + sage: cython( # needs sage.misc.cython ....: ''' ....: cimport sage.symbolic.expression ....: ''') diff --git a/src/sage/symbolic/pynac_impl.pxi b/src/sage/symbolic/pynac_impl.pxi index 114257901a2..68c31dcfde7 100644 --- a/src/sage/symbolic/pynac_impl.pxi +++ b/src/sage/symbolic/pynac_impl.pxi @@ -57,7 +57,6 @@ from sage.structure.coerce cimport coercion_model from sage.structure.element cimport Element, parent from sage.symbolic.function cimport Function - ################################################################# # Symbolic function helpers ################################################################# @@ -2365,51 +2364,6 @@ cdef mpq_ptr py_mpq_from_rational(x): return ((x).value) -symbol_table = {'functions': {}} - - -def register_symbol(obj, conversions, nargs=None): - """ - Add an object to the symbol table, along with how to convert it to - other systems such as Maxima, Mathematica, etc. This table is used - to convert *from* other systems back to Sage. - - INPUT: - - - `obj` -- a symbolic object or function. - - - `conversions` -- a dictionary of conversions, where the keys - are the names of interfaces (e.g., - 'maxima'), and the values are the string - representation of obj in that system. - - - ``nargs`` -- optional number of arguments. For most functions, - this can be deduced automatically. - - EXAMPLES:: - - sage: from sage.symbolic.expression import register_symbol as rs - sage: rs(SR(5),{'maxima':'five'}) - sage: SR(maxima_calculus('five')) - 5 - """ - conversions = dict(conversions) - try: - conversions['sage'] = obj.name() - except AttributeError: - pass - if nargs is None: - try: - nargs = obj.number_of_arguments() - except AttributeError: - nargs = -1 # meaning unknown number of arguments - for system, name in conversions.iteritems(): - system_table = symbol_table.get(system, None) - if system_table is None: - symbol_table[system] = system_table = {} - system_table[(name, nargs)] = obj - - import sage.rings.integer ginac_pyinit_Integer(sage.rings.integer.Integer) diff --git a/src/sage/symbolic/ring.pyx b/src/sage/symbolic/ring.pyx index 6f2a2389cca..d45b88e24de 100644 --- a/src/sage/symbolic/ring.pyx +++ b/src/sage/symbolic/ring.pyx @@ -1159,24 +1159,24 @@ cdef class NumpyToSRMorphism(Morphism): We check that :trac:`8949` and :trac:`9769` are fixed (see also :trac:`18076`):: - sage: import numpy + sage: import numpy # needs numpy sage: f(x) = x^2 - sage: f(numpy.int8('2')) + sage: f(numpy.int8('2')) # needs numpy 4 - sage: f(numpy.int32('3')) + sage: f(numpy.int32('3')) # needs numpy 9 Note that the answer is a Sage integer and not a numpy type:: - sage: a = f(numpy.int8('2')).pyobject() - sage: type(a) + sage: a = f(numpy.int8('2')).pyobject() # needs numpy + sage: type(a) # needs numpy This behavior also applies to standard functions:: sage: cos(int('2')) cos(2) - sage: numpy.cos(int('2')) + sage: numpy.cos(int('2')) # needs numpy -0.4161468365471424 """ cdef _intermediate_ring @@ -1192,6 +1192,7 @@ cdef class NumpyToSRMorphism(Morphism): EXAMPLES:: + sage: # needs numpy sage: import numpy sage: from sage.symbolic.ring import NumpyToSRMorphism sage: f = NumpyToSRMorphism(numpy.float64) @@ -1200,7 +1201,7 @@ cdef class NumpyToSRMorphism(Morphism): sage: _.parent() Symbolic Ring - sage: NumpyToSRMorphism(str) + sage: NumpyToSRMorphism(str) # needs numpy Traceback (most recent call last): ... TypeError: <... 'str'> is not a numpy number type @@ -1227,17 +1228,16 @@ cdef class NumpyToSRMorphism(Morphism): This should be called when coercing or converting a NumPy float or complex to the Symbolic Ring:: + sage: # needs numpy sage: import numpy sage: SR(numpy.int32('1')).pyobject().parent() Integer Ring sage: SR(numpy.int64('-2')).pyobject().parent() Integer Ring - sage: SR(numpy.float16('1')).pyobject().parent() Real Double Field sage: SR(numpy.float64('2.0')).pyobject().parent() Real Double Field - sage: SR(numpy.complex64(1jr)).pyobject().parent() Complex Double Field """ @@ -1252,6 +1252,7 @@ cdef class UnderscoreSageMorphism(Morphism): EXAMPLES:: + sage: # needs sympy sage: import sympy sage: from sage.symbolic.ring import UnderscoreSageMorphism sage: b = sympy.var('b') @@ -1274,9 +1275,9 @@ cdef class UnderscoreSageMorphism(Morphism): This should be called when coercing or converting a SymPy object to the Symbolic Ring:: - sage: import sympy - sage: b = sympy.var('b') - sage: bool(SR(b) == SR(b._sage_())) + sage: import sympy # needs sympy + sage: b = sympy.var('b') # needs sympy + sage: bool(SR(b) == SR(b._sage_())) # needs sympy True """ return self.codomain()(a._sage_()) diff --git a/src/sage/symbolic/symbols.py b/src/sage/symbolic/symbols.py new file mode 100644 index 00000000000..7fe7cdb4472 --- /dev/null +++ b/src/sage/symbolic/symbols.py @@ -0,0 +1,55 @@ +r""" +Symbol table +""" +# **************************************************************************** +# Copyright (C) 2009 Mike Hansen +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# https://www.gnu.org/licenses/ +# **************************************************************************** + +symbol_table = {'functions': {}} + + +def register_symbol(obj, conversions, nargs=None): + """ + Add an object to the symbol table, along with how to convert it to + other systems such as Maxima, Mathematica, etc. This table is used + to convert *from* other systems back to Sage. + + INPUT: + + - ``obj`` -- a symbolic object or function. + + - ``conversions`` -- a dictionary of conversions, where the keys + are the names of interfaces (e.g., ``'maxima'``), and the values + are the string representation of ``obj`` in that system. + + - ``nargs`` -- optional number of arguments. For most functions, + this can be deduced automatically. + + EXAMPLES:: + + sage: from sage.symbolic.symbols import register_symbol as rs + sage: rs(SR(5), {'maxima': 'five'}) # needs sage.symbolic + sage: SR(maxima_calculus('five')) # needs sage.symbolic + 5 + """ + conversions = dict(conversions) + try: + conversions['sage'] = obj.name() + except AttributeError: + pass + if nargs is None: + try: + nargs = obj.number_of_arguments() + except AttributeError: + nargs = -1 # meaning unknown number of arguments + for system, name in conversions.items(): + system_table = symbol_table.get(system, None) + if system_table is None: + symbol_table[system] = system_table = {} + system_table[(name, nargs)] = obj diff --git a/src/sage/symbolic/symengine.py b/src/sage/symbolic/symengine.py index 123eb51b824..5c3a46eb8b0 100644 --- a/src/sage/symbolic/symengine.py +++ b/src/sage/symbolic/symengine.py @@ -1,16 +1,18 @@ r""" EXAMPLES:: - sage: import symengine # optional - symengine_py - sage: x, y = symengine.var("x y") # optional - symengine_py - sage: expr = (x + symengine.GoldenRatio * symengine.exp(y))**2 # optional - symengine_py - sage: SR(expr) # optional - symengine_py + sage: # optional - symengine_py + sage: import symengine + sage: x, y = symengine.var("x y") + sage: expr = (x + symengine.GoldenRatio * symengine.exp(y))**2 + sage: SR(expr) (golden_ratio*e^y + x)^2 - sage: f = symengine.Lambdify([x, y], expr) # optional - symengine_py - sage: f(3, 5) # optional - symengine_py + sage: # optional - symengine_py + sage: f = symengine.Lambdify([x, y], expr) + sage: f(3, 5) array(59115.86131768) - sage: g = fast_callable(SR(expr), vars=[SR(x),SR(y)], domain=RDF) # optional - symengine_py - sage: g(3, 5) # optional - symengine_py + sage: g = fast_callable(SR(expr), vars=[SR(x),SR(y)], domain=RDF) + sage: g(3, 5) 59115.86131767523 """