Coverage for /usr/lib/python3/dist-packages/sympy/polys/domains/expressiondomain.py: 47%
153 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
1"""Implementation of :class:`ExpressionDomain` class. """
4from sympy.core import sympify, SympifyError
5from sympy.polys.domains.characteristiczero import CharacteristicZero
6from sympy.polys.domains.field import Field
7from sympy.polys.domains.simpledomain import SimpleDomain
8from sympy.polys.polyutils import PicklableWithSlots
9from sympy.utilities import public
11eflags = {"deep": False, "mul": True, "power_exp": False, "power_base": False,
12 "basic": False, "multinomial": False, "log": False}
14@public
15class ExpressionDomain(Field, CharacteristicZero, SimpleDomain):
16 """A class for arbitrary expressions. """
18 is_SymbolicDomain = is_EX = True
20 class Expression(PicklableWithSlots):
21 """An arbitrary expression. """
23 __slots__ = ('ex',)
25 def __init__(self, ex):
26 if not isinstance(ex, self.__class__):
27 self.ex = sympify(ex)
28 else:
29 self.ex = ex.ex
31 def __repr__(f):
32 return 'EX(%s)' % repr(f.ex)
34 def __str__(f):
35 return 'EX(%s)' % str(f.ex)
37 def __hash__(self):
38 return hash((self.__class__.__name__, self.ex))
40 def as_expr(f):
41 return f.ex
43 def numer(f):
44 return f.__class__(f.ex.as_numer_denom()[0])
46 def denom(f):
47 return f.__class__(f.ex.as_numer_denom()[1])
49 def simplify(f, ex):
50 return f.__class__(ex.cancel().expand(**eflags))
52 def __abs__(f):
53 return f.__class__(abs(f.ex))
55 def __neg__(f):
56 return f.__class__(-f.ex)
58 def _to_ex(f, g):
59 try:
60 return f.__class__(g)
61 except SympifyError:
62 return None
64 def __add__(f, g):
65 g = f._to_ex(g)
67 if g is None:
68 return NotImplemented
69 elif g == EX.zero:
70 return f
71 elif f == EX.zero:
72 return g
73 else:
74 return f.simplify(f.ex + g.ex)
76 def __radd__(f, g):
77 return f.simplify(f.__class__(g).ex + f.ex)
79 def __sub__(f, g):
80 g = f._to_ex(g)
82 if g is None:
83 return NotImplemented
84 elif g == EX.zero:
85 return f
86 elif f == EX.zero:
87 return -g
88 else:
89 return f.simplify(f.ex - g.ex)
91 def __rsub__(f, g):
92 return f.simplify(f.__class__(g).ex - f.ex)
94 def __mul__(f, g):
95 g = f._to_ex(g)
97 if g is None:
98 return NotImplemented
100 if EX.zero in (f, g):
101 return EX.zero
102 elif f.ex.is_Number and g.ex.is_Number:
103 return f.__class__(f.ex*g.ex)
105 return f.simplify(f.ex*g.ex)
107 def __rmul__(f, g):
108 return f.simplify(f.__class__(g).ex*f.ex)
110 def __pow__(f, n):
111 n = f._to_ex(n)
113 if n is not None:
114 return f.simplify(f.ex**n.ex)
115 else:
116 return NotImplemented
118 def __truediv__(f, g):
119 g = f._to_ex(g)
121 if g is not None:
122 return f.simplify(f.ex/g.ex)
123 else:
124 return NotImplemented
126 def __rtruediv__(f, g):
127 return f.simplify(f.__class__(g).ex/f.ex)
129 def __eq__(f, g):
130 return f.ex == f.__class__(g).ex
132 def __ne__(f, g):
133 return not f == g
135 def __bool__(f):
136 return not f.ex.is_zero
138 def gcd(f, g):
139 from sympy.polys import gcd
140 return f.__class__(gcd(f.ex, f.__class__(g).ex))
142 def lcm(f, g):
143 from sympy.polys import lcm
144 return f.__class__(lcm(f.ex, f.__class__(g).ex))
146 dtype = Expression
148 zero = Expression(0)
149 one = Expression(1)
151 rep = 'EX'
153 has_assoc_Ring = False
154 has_assoc_Field = True
156 def __init__(self):
157 pass
159 def to_sympy(self, a):
160 """Convert ``a`` to a SymPy object. """
161 return a.as_expr()
163 def from_sympy(self, a):
164 """Convert SymPy's expression to ``dtype``. """
165 return self.dtype(a)
167 def from_ZZ(K1, a, K0):
168 """Convert a Python ``int`` object to ``dtype``. """
169 return K1(K0.to_sympy(a))
171 def from_ZZ_python(K1, a, K0):
172 """Convert a Python ``int`` object to ``dtype``. """
173 return K1(K0.to_sympy(a))
175 def from_QQ(K1, a, K0):
176 """Convert a Python ``Fraction`` object to ``dtype``. """
177 return K1(K0.to_sympy(a))
179 def from_QQ_python(K1, a, K0):
180 """Convert a Python ``Fraction`` object to ``dtype``. """
181 return K1(K0.to_sympy(a))
183 def from_ZZ_gmpy(K1, a, K0):
184 """Convert a GMPY ``mpz`` object to ``dtype``. """
185 return K1(K0.to_sympy(a))
187 def from_QQ_gmpy(K1, a, K0):
188 """Convert a GMPY ``mpq`` object to ``dtype``. """
189 return K1(K0.to_sympy(a))
191 def from_GaussianIntegerRing(K1, a, K0):
192 """Convert a ``GaussianRational`` object to ``dtype``. """
193 return K1(K0.to_sympy(a))
195 def from_GaussianRationalField(K1, a, K0):
196 """Convert a ``GaussianRational`` object to ``dtype``. """
197 return K1(K0.to_sympy(a))
199 def from_RealField(K1, a, K0):
200 """Convert a mpmath ``mpf`` object to ``dtype``. """
201 return K1(K0.to_sympy(a))
203 def from_PolynomialRing(K1, a, K0):
204 """Convert a ``DMP`` object to ``dtype``. """
205 return K1(K0.to_sympy(a))
207 def from_FractionField(K1, a, K0):
208 """Convert a ``DMF`` object to ``dtype``. """
209 return K1(K0.to_sympy(a))
211 def from_ExpressionDomain(K1, a, K0):
212 """Convert a ``EX`` object to ``dtype``. """
213 return a
215 def get_ring(self):
216 """Returns a ring associated with ``self``. """
217 return self # XXX: EX is not a ring but we don't have much choice here.
219 def get_field(self):
220 """Returns a field associated with ``self``. """
221 return self
223 def is_positive(self, a):
224 """Returns True if ``a`` is positive. """
225 return a.ex.as_coeff_mul()[0].is_positive
227 def is_negative(self, a):
228 """Returns True if ``a`` is negative. """
229 return a.ex.could_extract_minus_sign()
231 def is_nonpositive(self, a):
232 """Returns True if ``a`` is non-positive. """
233 return a.ex.as_coeff_mul()[0].is_nonpositive
235 def is_nonnegative(self, a):
236 """Returns True if ``a`` is non-negative. """
237 return a.ex.as_coeff_mul()[0].is_nonnegative
239 def numer(self, a):
240 """Returns numerator of ``a``. """
241 return a.numer()
243 def denom(self, a):
244 """Returns denominator of ``a``. """
245 return a.denom()
247 def gcd(self, a, b):
248 return self(1)
250 def lcm(self, a, b):
251 return a.lcm(b)
254EX = ExpressionDomain()