diff --git a/sympy/core/assumptions.py b/sympy/core/assumptions.py index 59aa52ea9f..1f5868e5ca 100644 --- a/sympy/core/assumptions.py +++ b/sympy/core/assumptions.py @@ -163,9 +163,10 @@ 'real == extended_real & finite', 'rational -> algebraic', 'algebraic -> complex', - 'extended_real -> complex & hermitian', + 'real -> complex & hermitian', 'imaginary -> complex & antihermitian', - 'complex -> commutative', + 'complex -> finite & commutative', + 'extended_real -> commutative', 'odd == integer & ~even', 'even == integer & ~odd', diff --git a/sympy/core/basic.py b/sympy/core/basic.py index f51119e34f..a70a576dab 100644 --- a/sympy/core/basic.py +++ b/sympy/core/basic.py @@ -137,10 +137,9 @@ def assumptions0(self): {'commutative': True} >>> x = Symbol("x", positive=True) >>> x.assumptions0 == \ - ... {'commutative': True, 'complex': True, 'extended_real': True, - ... 'hermitian': True, 'imaginary': False, 'negative': False, - ... 'nonnegative': True, 'nonpositive': False, 'nonzero': True, - ... 'positive': True, 'zero': False} + ... {'commutative': True, 'extended_real': True, 'imaginary': False, + ... 'negative': False, 'nonnegative': True, 'nonpositive': False, + ... 'nonzero': True, 'positive': True, 'zero': False} True """ return {} diff --git a/sympy/core/expr.py b/sympy/core/expr.py index d55cca0047..c4348c1ea3 100644 --- a/sympy/core/expr.py +++ b/sympy/core/expr.py @@ -236,7 +236,7 @@ def __ge__(self, other): except SympifyError: raise TypeError("Invalid comparison %s >= %s" % (self, other)) for me in (self, other): - if me.is_complex and me.is_extended_real is False: + if me.is_commutative and me.is_extended_real is False: raise TypeError("Invalid comparison of complex %s" % me) if me is S.NaN: raise TypeError("Invalid NaN comparison") @@ -254,7 +254,7 @@ def __le__(self, other): except SympifyError: raise TypeError("Invalid comparison %s <= %s" % (self, other)) for me in (self, other): - if me.is_complex and me.is_extended_real is False: + if me.is_commutative and me.is_extended_real is False: raise TypeError("Invalid comparison of complex %s" % me) if me is S.NaN: raise TypeError("Invalid NaN comparison") @@ -272,7 +272,7 @@ def __gt__(self, other): except SympifyError: raise TypeError("Invalid comparison %s > %s" % (self, other)) for me in (self, other): - if me.is_complex and me.is_extended_real is False: + if me.is_commutative and me.is_extended_real is False: raise TypeError("Invalid comparison of complex %s" % me) if me is S.NaN: raise TypeError("Invalid NaN comparison") @@ -290,7 +290,7 @@ def __lt__(self, other): except SympifyError: raise TypeError("Invalid comparison %s < %s" % (self, other)) for me in (self, other): - if me.is_complex and me.is_extended_real is False: + if me.is_commutative and me.is_extended_real is False: raise TypeError("Invalid comparison of complex %s" % me) if me is S.NaN: raise TypeError("Invalid NaN comparison") @@ -812,7 +812,7 @@ def conjugate(self): def _eval_transpose(self): from sympy.functions.elementary.complexes import conjugate - if self.is_complex: + if self.is_complex or self.is_extended_real: return self elif self.is_hermitian: return conjugate(self) diff --git a/sympy/core/function.py b/sympy/core/function.py index f021056265..ae3cdcfca7 100644 --- a/sympy/core/function.py +++ b/sympy/core/function.py @@ -495,9 +495,6 @@ def _eval_derivative(self, s): def _eval_is_commutative(self): return fuzzy_and(a.is_commutative for a in self.args) - def _eval_is_complex(self): - return fuzzy_and(a.is_complex for a in self.args) - def as_base_exp(self): """ Returns the method as the 2-tuple (base, exponent). diff --git a/sympy/core/mul.py b/sympy/core/mul.py index ba46dd234b..93676938c4 100644 --- a/sympy/core/mul.py +++ b/sympy/core/mul.py @@ -1028,7 +1028,7 @@ def _eval_is_extended_real(self): zero = one_neither = False for t in self.args: - if not t.is_complex: + if t.is_finite and not t.is_complex: return t.is_complex elif t.is_imaginary: real = not real diff --git a/sympy/core/numbers.py b/sympy/core/numbers.py index 80dfdd0c56..d44a4d0580 100644 --- a/sympy/core/numbers.py +++ b/sympy/core/numbers.py @@ -2804,7 +2804,6 @@ class ComplexInfinity(AtomicExpr, metaclass=Singleton): is_infinite = True is_number = True is_prime = False - is_complex = True is_extended_real = False __slots__ = [] diff --git a/sympy/core/power.py b/sympy/core/power.py index 471b68ea76..24282afac0 100644 --- a/sympy/core/power.py +++ b/sympy/core/power.py @@ -433,10 +433,9 @@ def _eval_is_extended_real(self): return i.is_integer def _eval_is_complex(self): - if all(a.is_complex for a in self.args): - return True - elif self.base is S.Exp1: - return self.exp.is_complex + from sympy import log + if self.base.is_complex: + return (log(self.base)*self.exp).is_complex def _eval_is_imaginary(self): from sympy import arg, log diff --git a/sympy/core/relational.py b/sympy/core/relational.py index b24a126025..cccb001aa2 100644 --- a/sympy/core/relational.py +++ b/sympy/core/relational.py @@ -320,7 +320,8 @@ def __new__(cls, lhs, rhs=0, **options): # If appropriate, check if the difference evaluates. Detect # incompatibility such as lhs real and rhs not real. - if lhs.is_complex and rhs.is_complex: + if ((lhs.is_complex and rhs.is_complex) or + (lhs.is_extended_real and rhs.is_extended_real)): r = (lhs - rhs).is_zero if r is not None: return _sympify(r) diff --git a/sympy/core/tests/test_arit.py b/sympy/core/tests/test_arit.py index fab1b489b0..be20f5d9d7 100644 --- a/sympy/core/tests/test_arit.py +++ b/sympy/core/tests/test_arit.py @@ -33,7 +33,7 @@ def test_Symbol(): assert x.is_imaginary is None # could be I or 1 + I x = Symbol('x', complex=True, imaginary=False) assert x.is_extended_real is None # could be 1 or 1 + I - x = Symbol('x', extended_real=True) + x = Symbol('x', real=True) assert x.is_complex x = Symbol('x', imaginary=True) assert x.is_complex @@ -368,16 +368,18 @@ def test_Add_Mul_is_integer(): def test_Add_Mul_is_finite(): x = Symbol('x', extended_real=True, finite=False) - - assert sin(x).is_finite is True - assert (x*sin(x)).is_finite is False - assert (1024*sin(x)).is_finite is True - assert (sin(x)*exp(x)).is_finite is not True - assert (sin(x)*cos(x)).is_finite is True - assert (x*sin(x)*exp(x)).is_finite is not True - - assert (sin(x) - 67).is_finite is True - assert (sin(x) + exp(x)).is_finite is not True + y = Symbol('y', real=True) + z = Symbol('z', real=True) + + assert y.is_finite is True + assert (x*y).is_finite is False + assert (1024*y).is_finite is True + assert (y*exp(x)).is_finite is not True + assert (y*z).is_finite is True + assert (x*y*exp(x)).is_finite is not True + + assert (y - 67).is_finite is True + assert (y + exp(x)).is_finite is not True assert (1 + x).is_finite is False assert (1 + x**2 + (1 + x)*(1 - x)).is_finite is None assert (sqrt(2)*(1 + x)).is_finite is False @@ -490,12 +492,9 @@ def test_Mul_is_rational(): r = Symbol('r', rational=True) assert (pi*r).is_rational is None - # issue 8008 z = Symbol('z', zero=True) i = Symbol('i', imaginary=True) - assert (z*i).is_rational is None - bi = Symbol('i', imaginary=True, finite=True) - assert (z*bi).is_zero is True + assert (z*i).is_rational def test_Add_is_rational(): @@ -1032,16 +1031,17 @@ def test_Pow_is_finite(): x = Symbol('x', extended_real=True) p = Symbol('p', positive=True) n = Symbol('n', negative=True) + y = Symbol('y', real=True) assert (x**2).is_finite is None # x could be oo assert (x**x).is_finite is None # ditto assert (p**x).is_finite is None # ditto assert (n**x).is_finite is None # ditto assert (1/S.Pi).is_finite - assert (sin(x)**2).is_finite is True - assert (sin(x)**x).is_finite is None - assert (sin(x)**exp(x)).is_finite is None - assert (1/sin(x)).is_finite is None # if zero, no, otherwise yes + assert (y**2).is_finite is True + assert (y**x).is_finite is None + assert (y**exp(x)).is_finite is None + assert (1/y).is_finite is None # if zero, no, otherwise yes assert (1/exp(x)).is_finite is None # x could be -oo @@ -1208,7 +1208,7 @@ def test_Pow_is_nonpositive_nonnegative(): def test_Mul_is_imaginary_real(): r = Symbol('r', extended_real=True) - p = Symbol('p', positive=True) + p = Symbol('p', positive=True, real=True) i = Symbol('i', imaginary=True) ii = Symbol('ii', imaginary=True) x = Symbol('x') diff --git a/sympy/core/tests/test_assumptions.py b/sympy/core/tests/test_assumptions.py index 6c80563969..377c66af0a 100644 --- a/sympy/core/tests/test_assumptions.py +++ b/sympy/core/tests/test_assumptions.py @@ -99,10 +99,10 @@ def test_infinity(): assert oo.is_commutative is True assert oo.is_integer is False assert oo.is_rational is False - assert oo.is_algebraic is None - assert oo.is_transcendental is None + assert oo.is_algebraic is False + assert oo.is_transcendental is False assert oo.is_extended_real is True - assert oo.is_complex is True + assert oo.is_complex is False assert oo.is_noninteger is False assert oo.is_irrational is False assert oo.is_imaginary is False @@ -126,10 +126,10 @@ def test_neg_infinity(): assert mm.is_commutative is True assert mm.is_integer is False assert mm.is_rational is False - assert mm.is_algebraic is None - assert mm.is_transcendental is None + assert mm.is_algebraic is False + assert mm.is_transcendental is False assert mm.is_extended_real is True - assert mm.is_complex is True + assert mm.is_complex is False assert mm.is_noninteger is False assert mm.is_irrational is False assert mm.is_imaginary is False @@ -149,9 +149,10 @@ def test_neg_infinity(): def test_zoo(): zoo = S.ComplexInfinity - assert zoo.is_complex + assert zoo.is_complex is False assert zoo.is_real is False assert zoo.is_prime is False + assert zoo.is_infinite def test_nan(): diff --git a/sympy/core/tests/test_function.py b/sympy/core/tests/test_function.py index af70396857..b8bdef78d8 100644 --- a/sympy/core/tests/test_function.py +++ b/sympy/core/tests/test_function.py @@ -361,10 +361,13 @@ def test_function_complex(): assert sin(x).is_commutative is True assert exp(x).is_commutative is True assert log(x).is_commutative is True - assert f(x).is_complex is True assert sin(x).is_complex is True assert exp(x).is_complex is True - assert log(x).is_complex is True + assert log(x).is_complex is None # could be zero + n = Symbol('n', complex=True, nonzero=True) + z = Symbol('z', zero=True) + assert log(n).is_complex is True + assert log(z).is_complex is False def test_function__eval_nseries(): diff --git a/sympy/functions/elementary/complexes.py b/sympy/functions/elementary/complexes.py index 2da2894b54..1fbb422b3b 100644 --- a/sympy/functions/elementary/complexes.py +++ b/sympy/functions/elementary/complexes.py @@ -881,6 +881,10 @@ def _eval_evalf(self, prec): ub = periodic_argument(z, oo)._eval_evalf(prec) return (ub - ceiling(ub/period - S(1)/2)*period)._eval_evalf(prec) + def _eval_is_real(self): + if self.args[1].is_positive: + return True + def unbranched_argument(arg): from sympy import oo diff --git a/sympy/functions/elementary/exponential.py b/sympy/functions/elementary/exponential.py index dad42a0db5..92681b1011 100644 --- a/sympy/functions/elementary/exponential.py +++ b/sympy/functions/elementary/exponential.py @@ -422,6 +422,13 @@ def _eval_is_finite(self): return False return arg.is_finite + def _eval_is_complex(self): + arg = self.args[0] + if arg.is_zero: + return False + elif arg.is_nonzero: + return arg.is_complex + def _eval_is_positive(self): return (self.args[0] - 1).is_positive diff --git a/sympy/functions/elementary/tests/test_complexes.py b/sympy/functions/elementary/tests/test_complexes.py index 7973943c36..01f4386cce 100644 --- a/sympy/functions/elementary/tests/test_complexes.py +++ b/sympy/functions/elementary/tests/test_complexes.py @@ -751,6 +751,8 @@ def test_periodic_argument(): assert Abs(polar_lift(1 + I)) == Abs(1 + I) + assert periodic_argument(x, pi).is_real is True + @pytest.mark.xfail def test_principal_branch_fail(): diff --git a/sympy/functions/elementary/tests/test_piecewise.py b/sympy/functions/elementary/tests/test_piecewise.py index d00964c37c..c3f06f8312 100644 --- a/sympy/functions/elementary/tests/test_piecewise.py +++ b/sympy/functions/elementary/tests/test_piecewise.py @@ -208,7 +208,7 @@ def test_piecewise_integrate(): def test_piecewise_integrate_inequality_conditions(): x, y = symbols("x y", real=True) - c1, c2 = symbols("c1 c2", positive=True) + c1, c2 = symbols("c1 c2", positive=True, real=True) g = Piecewise((0, c1*x > 1), (1, c1*x > 0), (0, True)) assert integrate(g, (x, -oo, 0)) == 0 assert integrate(g, (x, -5, 0)) == 0 diff --git a/sympy/functions/elementary/tests/test_trigonometric.py b/sympy/functions/elementary/tests/test_trigonometric.py index a4aab9b105..8de333e84f 100644 --- a/sympy/functions/elementary/tests/test_trigonometric.py +++ b/sympy/functions/elementary/tests/test_trigonometric.py @@ -8,7 +8,8 @@ FiniteSet, asec, acsc, sech, csch) x, y, z = symbols('x y z') -r = Symbol('r', extended_real=True) +r = Symbol('r', real=True) +c = Symbol('c', complex=True) k = Symbol('k', integer=True) p = Symbol('p', positive=True) n = Symbol('n', negative=True) @@ -102,7 +103,8 @@ def test_sin(): assert sin(k*pi*I) == sinh(k*pi)*I - assert sin(r).is_extended_real is True + assert sin(r).is_real + assert sin(c).is_complex assert sin(0, evaluate=False).is_algebraic assert sin(a).is_algebraic is None @@ -289,7 +291,8 @@ def test_cos(): assert cos(x*I) == cosh(x) assert cos(k*pi*I) == cosh(k*pi) - assert cos(r).is_extended_real is True + assert cos(r).is_real + assert cos(c).is_complex assert cos(0, evaluate=False).is_algebraic assert cos(a).is_algebraic is None @@ -1184,7 +1187,7 @@ def test_sec(): assert sec(x).expand(trig=True) == 1/cos(x) assert sec(2*x).expand(trig=True) == 1/(2*cos(x)**2 - 1) - assert sec(x).is_extended_real + assert sec(r).is_extended_real assert sec(z).is_extended_real is None assert sec(a).is_algebraic is None @@ -1259,7 +1262,7 @@ def test_csc(): assert csc(x).expand(trig=True) == 1/sin(x) assert csc(2*x).expand(trig=True) == 1/(2*sin(x)*cos(x)) - assert csc(x).is_extended_real + assert csc(r).is_extended_real assert csc(z).is_extended_real is None assert csc(a).is_algebraic is None diff --git a/sympy/functions/elementary/trigonometric.py b/sympy/functions/elementary/trigonometric.py index 8866db97f1..2bff7ad5e2 100644 --- a/sympy/functions/elementary/trigonometric.py +++ b/sympy/functions/elementary/trigonometric.py @@ -393,13 +393,11 @@ def _eval_as_leading_term(self, x): else: return self.func(arg) - def _eval_is_extended_real(self): - return self.args[0].is_extended_real + def _eval_is_complex(self): + return self.args[0].is_complex - def _eval_is_finite(self): - arg = self.args[0] - if arg.is_extended_real: - return True + def _eval_is_real(self): + return self.args[0].is_real class cos(TrigonometricFunction): @@ -770,14 +768,11 @@ def _eval_as_leading_term(self, x): else: return self.func(arg) - def _eval_is_extended_real(self): - return self.args[0].is_extended_real - - def _eval_is_finite(self): - arg = self.args[0] + def _eval_is_real(self): + return self.args[0].is_real - if arg.is_extended_real: - return True + def _eval_is_complex(self): + return self.args[0].is_complex class tan(TrigonometricFunction): @@ -1151,7 +1146,7 @@ def _eval_expand_trig(self, **hints): return self._calculate_reciprocal("_eval_expand_trig", **hints) def _eval_is_extended_real(self): - return self._reciprocal_of(self.args[0])._eval_is_extended_real() + return (1/self._reciprocal_of(self.args[0])).is_extended_real def _eval_as_leading_term(self, x): return (1/self._reciprocal_of(self.args[0]))._eval_as_leading_term(x) @@ -2478,8 +2473,9 @@ def _eval_rewrite_as_arg(self, y, x): d = x**2 + y**2 return arg(n/sqrt(d)) - I*log(abs(n)/sqrt(abs(d))) - def _eval_is_extended_real(self): - return self.args[0].is_extended_real and self.args[1].is_extended_real + def _eval_is_real(self): + # XXX this seems to be wrong for (0, 0) + return self.args[0].is_real and self.args[1].is_real def _eval_conjugate(self): return self.func(self.args[0].conjugate(), self.args[1].conjugate()) diff --git a/sympy/integrals/tests/test_transforms.py b/sympy/integrals/tests/test_transforms.py index 600d08863d..4aa6e38423 100644 --- a/sympy/integrals/tests/test_transforms.py +++ b/sympy/integrals/tests/test_transforms.py @@ -773,7 +773,7 @@ def test_issue_7173(): def test_issue_8514(): - a, b, c, = symbols('a b c', positive=True) + a, b, c, = symbols('a b c', positive=True, finite=True) t = symbols('t', positive=True) ft = simplify(inverse_laplace_transform(1/(a*s**2 + b*s + c), s, t)) assert ft == ((exp(t*(exp(I*atan2(0, -4*a*c + b**2)/2) - diff --git a/sympy/matrices/matrices.py b/sympy/matrices/matrices.py index 5a9a2cf1af..9d5af940c7 100644 --- a/sympy/matrices/matrices.py +++ b/sympy/matrices/matrices.py @@ -1777,9 +1777,9 @@ def norm(self, ord=None): ======== >>> from sympy import Matrix, Symbol, trigsimp, cos, sin, oo - >>> x = Symbol('x', extended_real=True) + >>> x = Symbol('x', real=True) >>> v = Matrix([cos(x), sin(x)]) - >>> trigsimp( v.norm() ) + >>> trigsimp(v.norm()) 1 >>> v.norm(10) (sin(x)**10 + cos(x)**10)**(1/10) diff --git a/sympy/matrices/tests/test_matrices.py b/sympy/matrices/tests/test_matrices.py index 5071e0c738..3baba57d3c 100644 --- a/sympy/matrices/tests/test_matrices.py +++ b/sympy/matrices/tests/test_matrices.py @@ -1816,7 +1816,7 @@ def test_diagonal_solve(): def test_matrix_norm(): # Vector Tests # Test columns and symbols - x = Symbol('x', extended_real=True) + x = Symbol('x', real=True) v = Matrix([cos(x), sin(x)]) assert trigsimp(v.norm(2)) == 1 assert v.norm(10) == Pow(cos(x)**10 + sin(x)**10, S(1)/10) diff --git a/sympy/polys/polyutils.py b/sympy/polys/polyutils.py index 46a01437a4..46472d047e 100644 --- a/sympy/polys/polyutils.py +++ b/sympy/polys/polyutils.py @@ -35,8 +35,11 @@ def _nsort(roots, separated=False): if not separated: return list(roots) r = list(roots)[0] - if r.is_complex and r.is_extended_real is not None: - return [[r], []] if r.is_extended_real else [[], [r]] + if r.is_extended_real: + return [[r], []] + elif r.is_extended_real is False: + if r.is_complex is not None: + return [[], [r]] if not all(r.is_number for r in roots): raise NotImplementedError # see issue 6137: diff --git a/sympy/series/limits.py b/sympy/series/limits.py index 46cb05f229..d112adfea4 100644 --- a/sympy/series/limits.py +++ b/sympy/series/limits.py @@ -1,6 +1,7 @@ from sympy.core import S, Symbol, Add, sympify, Expr, PoleError, Mul from sympy.core.symbol import Dummy from sympy.functions.combinatorial.factorials import factorial +from sympy.functions.elementary.trigonometric import sin, cos from sympy.functions.special.gamma_functions import gamma from sympy.series.order import Order from .gruntz import limitinf @@ -44,7 +45,8 @@ def heuristics(e, z, z0, dir): r = [] for a in e.args: l = limit(a, z, z0, dir) - if l.has(S.Infinity) and l.is_finite is None: + if l.has(S.Infinity) and (l.func not in (sin, cos) and + l.is_finite is None): return elif isinstance(l, Limit): return diff --git a/sympy/series/tests/test_limits.py b/sympy/series/tests/test_limits.py index dcb0c05a83..4ed81ae3f9 100644 --- a/sympy/series/tests/test_limits.py +++ b/sympy/series/tests/test_limits.py @@ -8,6 +8,7 @@ Function, subfactorial, PoleError) from sympy.series.limits import heuristics from sympy.series.order import Order + from sympy.abc import x, y, z, a @@ -164,7 +165,6 @@ def test_ceiling_requires_robust_assumptions(): def test_atan(): - x = Symbol("x", extended_real=True) assert limit(atan(x)*sin(1/x), x, 0) == 0 assert limit(atan(x) + sqrt(x + 1) - sqrt(x), x, oo) == pi/2 @@ -179,7 +179,7 @@ def test_abs(): def test_heuristic(): x = Symbol("x", extended_real=True) assert heuristics(sin(1/x) + atan(x), x, 0, '+') == sin(oo) - assert limit(log(2 + sqrt(atan(x))*sqrt(sin(1/x))), x, 0) == log(2) + assert heuristics(log(2 + sqrt(atan(x))*sin(1/x)), x, 0, '+') == log(2) def test_issue_3871(): diff --git a/sympy/solvers/tests/test_ode.py b/sympy/solvers/tests/test_ode.py index d30f9b1914..1443aeb8be 100644 --- a/sympy/solvers/tests/test_ode.py +++ b/sympy/solvers/tests/test_ode.py @@ -13,7 +13,7 @@ from sympy.solvers.deutils import ode_order C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10 = symbols('C0:11') -x, y, z = symbols('x:z', extended_real=True) +x, y, z = symbols('x:z', real=True) f = Function('f') g = Function('g') h = Function('h')