Coverage for /usr/lib/python3/dist-packages/sympy/polys/domains/domain.py: 39%
396 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:`Domain` class. """
3from __future__ import annotations
4from typing import Any
6from sympy.core.numbers import AlgebraicNumber
7from sympy.core import Basic, sympify
8from sympy.core.sorting import default_sort_key, ordered
9from sympy.external.gmpy import HAS_GMPY
10from sympy.polys.domains.domainelement import DomainElement
11from sympy.polys.orderings import lex
12from sympy.polys.polyerrors import UnificationFailed, CoercionFailed, DomainError
13from sympy.polys.polyutils import _unify_gens, _not_a_coeff
14from sympy.utilities import public
15from sympy.utilities.iterables import is_sequence
18@public
19class Domain:
20 """Superclass for all domains in the polys domains system.
22 See :ref:`polys-domainsintro` for an introductory explanation of the
23 domains system.
25 The :py:class:`~.Domain` class is an abstract base class for all of the
26 concrete domain types. There are many different :py:class:`~.Domain`
27 subclasses each of which has an associated ``dtype`` which is a class
28 representing the elements of the domain. The coefficients of a
29 :py:class:`~.Poly` are elements of a domain which must be a subclass of
30 :py:class:`~.Domain`.
32 Examples
33 ========
35 The most common example domains are the integers :ref:`ZZ` and the
36 rationals :ref:`QQ`.
38 >>> from sympy import Poly, symbols, Domain
39 >>> x, y = symbols('x, y')
40 >>> p = Poly(x**2 + y)
41 >>> p
42 Poly(x**2 + y, x, y, domain='ZZ')
43 >>> p.domain
44 ZZ
45 >>> isinstance(p.domain, Domain)
46 True
47 >>> Poly(x**2 + y/2)
48 Poly(x**2 + 1/2*y, x, y, domain='QQ')
50 The domains can be used directly in which case the domain object e.g.
51 (:ref:`ZZ` or :ref:`QQ`) can be used as a constructor for elements of
52 ``dtype``.
54 >>> from sympy import ZZ, QQ
55 >>> ZZ(2)
56 2
57 >>> ZZ.dtype # doctest: +SKIP
58 <class 'int'>
59 >>> type(ZZ(2)) # doctest: +SKIP
60 <class 'int'>
61 >>> QQ(1, 2)
62 1/2
63 >>> type(QQ(1, 2)) # doctest: +SKIP
64 <class 'sympy.polys.domains.pythonrational.PythonRational'>
66 The corresponding domain elements can be used with the arithmetic
67 operations ``+,-,*,**`` and depending on the domain some combination of
68 ``/,//,%`` might be usable. For example in :ref:`ZZ` both ``//`` (floor
69 division) and ``%`` (modulo division) can be used but ``/`` (true
70 division) cannot. Since :ref:`QQ` is a :py:class:`~.Field` its elements
71 can be used with ``/`` but ``//`` and ``%`` should not be used. Some
72 domains have a :py:meth:`~.Domain.gcd` method.
74 >>> ZZ(2) + ZZ(3)
75 5
76 >>> ZZ(5) // ZZ(2)
77 2
78 >>> ZZ(5) % ZZ(2)
79 1
80 >>> QQ(1, 2) / QQ(2, 3)
81 3/4
82 >>> ZZ.gcd(ZZ(4), ZZ(2))
83 2
84 >>> QQ.gcd(QQ(2,7), QQ(5,3))
85 1/21
86 >>> ZZ.is_Field
87 False
88 >>> QQ.is_Field
89 True
91 There are also many other domains including:
93 1. :ref:`GF(p)` for finite fields of prime order.
94 2. :ref:`RR` for real (floating point) numbers.
95 3. :ref:`CC` for complex (floating point) numbers.
96 4. :ref:`QQ(a)` for algebraic number fields.
97 5. :ref:`K[x]` for polynomial rings.
98 6. :ref:`K(x)` for rational function fields.
99 7. :ref:`EX` for arbitrary expressions.
101 Each domain is represented by a domain object and also an implementation
102 class (``dtype``) for the elements of the domain. For example the
103 :ref:`K[x]` domains are represented by a domain object which is an
104 instance of :py:class:`~.PolynomialRing` and the elements are always
105 instances of :py:class:`~.PolyElement`. The implementation class
106 represents particular types of mathematical expressions in a way that is
107 more efficient than a normal SymPy expression which is of type
108 :py:class:`~.Expr`. The domain methods :py:meth:`~.Domain.from_sympy` and
109 :py:meth:`~.Domain.to_sympy` are used to convert from :py:class:`~.Expr`
110 to a domain element and vice versa.
112 >>> from sympy import Symbol, ZZ, Expr
113 >>> x = Symbol('x')
114 >>> K = ZZ[x] # polynomial ring domain
115 >>> K
116 ZZ[x]
117 >>> type(K) # class of the domain
118 <class 'sympy.polys.domains.polynomialring.PolynomialRing'>
119 >>> K.dtype # class of the elements
120 <class 'sympy.polys.rings.PolyElement'>
121 >>> p_expr = x**2 + 1 # Expr
122 >>> p_expr
123 x**2 + 1
124 >>> type(p_expr)
125 <class 'sympy.core.add.Add'>
126 >>> isinstance(p_expr, Expr)
127 True
128 >>> p_domain = K.from_sympy(p_expr)
129 >>> p_domain # domain element
130 x**2 + 1
131 >>> type(p_domain)
132 <class 'sympy.polys.rings.PolyElement'>
133 >>> K.to_sympy(p_domain) == p_expr
134 True
136 The :py:meth:`~.Domain.convert_from` method is used to convert domain
137 elements from one domain to another.
139 >>> from sympy import ZZ, QQ
140 >>> ez = ZZ(2)
141 >>> eq = QQ.convert_from(ez, ZZ)
142 >>> type(ez) # doctest: +SKIP
143 <class 'int'>
144 >>> type(eq) # doctest: +SKIP
145 <class 'sympy.polys.domains.pythonrational.PythonRational'>
147 Elements from different domains should not be mixed in arithmetic or other
148 operations: they should be converted to a common domain first. The domain
149 method :py:meth:`~.Domain.unify` is used to find a domain that can
150 represent all the elements of two given domains.
152 >>> from sympy import ZZ, QQ, symbols
153 >>> x, y = symbols('x, y')
154 >>> ZZ.unify(QQ)
155 QQ
156 >>> ZZ[x].unify(QQ)
157 QQ[x]
158 >>> ZZ[x].unify(QQ[y])
159 QQ[x,y]
161 If a domain is a :py:class:`~.Ring` then is might have an associated
162 :py:class:`~.Field` and vice versa. The :py:meth:`~.Domain.get_field` and
163 :py:meth:`~.Domain.get_ring` methods will find or create the associated
164 domain.
166 >>> from sympy import ZZ, QQ, Symbol
167 >>> x = Symbol('x')
168 >>> ZZ.has_assoc_Field
169 True
170 >>> ZZ.get_field()
171 QQ
172 >>> QQ.has_assoc_Ring
173 True
174 >>> QQ.get_ring()
175 ZZ
176 >>> K = QQ[x]
177 >>> K
178 QQ[x]
179 >>> K.get_field()
180 QQ(x)
182 See also
183 ========
185 DomainElement: abstract base class for domain elements
186 construct_domain: construct a minimal domain for some expressions
188 """
190 dtype: type | None = None
191 """The type (class) of the elements of this :py:class:`~.Domain`:
193 >>> from sympy import ZZ, QQ, Symbol
194 >>> ZZ.dtype
195 <class 'int'>
196 >>> z = ZZ(2)
197 >>> z
198 2
199 >>> type(z)
200 <class 'int'>
201 >>> type(z) == ZZ.dtype
202 True
204 Every domain has an associated **dtype** ("datatype") which is the
205 class of the associated domain elements.
207 See also
208 ========
210 of_type
211 """
213 zero: Any = None
214 """The zero element of the :py:class:`~.Domain`:
216 >>> from sympy import QQ
217 >>> QQ.zero
218 0
219 >>> QQ.of_type(QQ.zero)
220 True
222 See also
223 ========
225 of_type
226 one
227 """
229 one: Any = None
230 """The one element of the :py:class:`~.Domain`:
232 >>> from sympy import QQ
233 >>> QQ.one
234 1
235 >>> QQ.of_type(QQ.one)
236 True
238 See also
239 ========
241 of_type
242 zero
243 """
245 is_Ring = False
246 """Boolean flag indicating if the domain is a :py:class:`~.Ring`.
248 >>> from sympy import ZZ
249 >>> ZZ.is_Ring
250 True
252 Basically every :py:class:`~.Domain` represents a ring so this flag is
253 not that useful.
255 See also
256 ========
258 is_PID
259 is_Field
260 get_ring
261 has_assoc_Ring
262 """
264 is_Field = False
265 """Boolean flag indicating if the domain is a :py:class:`~.Field`.
267 >>> from sympy import ZZ, QQ
268 >>> ZZ.is_Field
269 False
270 >>> QQ.is_Field
271 True
273 See also
274 ========
276 is_PID
277 is_Ring
278 get_field
279 has_assoc_Field
280 """
282 has_assoc_Ring = False
283 """Boolean flag indicating if the domain has an associated
284 :py:class:`~.Ring`.
286 >>> from sympy import QQ
287 >>> QQ.has_assoc_Ring
288 True
289 >>> QQ.get_ring()
290 ZZ
292 See also
293 ========
295 is_Field
296 get_ring
297 """
299 has_assoc_Field = False
300 """Boolean flag indicating if the domain has an associated
301 :py:class:`~.Field`.
303 >>> from sympy import ZZ
304 >>> ZZ.has_assoc_Field
305 True
306 >>> ZZ.get_field()
307 QQ
309 See also
310 ========
312 is_Field
313 get_field
314 """
316 is_FiniteField = is_FF = False
317 is_IntegerRing = is_ZZ = False
318 is_RationalField = is_QQ = False
319 is_GaussianRing = is_ZZ_I = False
320 is_GaussianField = is_QQ_I = False
321 is_RealField = is_RR = False
322 is_ComplexField = is_CC = False
323 is_AlgebraicField = is_Algebraic = False
324 is_PolynomialRing = is_Poly = False
325 is_FractionField = is_Frac = False
326 is_SymbolicDomain = is_EX = False
327 is_SymbolicRawDomain = is_EXRAW = False
328 is_FiniteExtension = False
330 is_Exact = True
331 is_Numerical = False
333 is_Simple = False
334 is_Composite = False
336 is_PID = False
337 """Boolean flag indicating if the domain is a `principal ideal domain`_.
339 >>> from sympy import ZZ
340 >>> ZZ.has_assoc_Field
341 True
342 >>> ZZ.get_field()
343 QQ
345 .. _principal ideal domain: https://en.wikipedia.org/wiki/Principal_ideal_domain
347 See also
348 ========
350 is_Field
351 get_field
352 """
354 has_CharacteristicZero = False
356 rep: str | None = None
357 alias: str | None = None
359 def __init__(self):
360 raise NotImplementedError
362 def __str__(self):
363 return self.rep
365 def __repr__(self):
366 return str(self)
368 def __hash__(self):
369 return hash((self.__class__.__name__, self.dtype))
371 def new(self, *args):
372 return self.dtype(*args)
374 @property
375 def tp(self):
376 """Alias for :py:attr:`~.Domain.dtype`"""
377 return self.dtype
379 def __call__(self, *args):
380 """Construct an element of ``self`` domain from ``args``. """
381 return self.new(*args)
383 def normal(self, *args):
384 return self.dtype(*args)
386 def convert_from(self, element, base):
387 """Convert ``element`` to ``self.dtype`` given the base domain. """
388 if base.alias is not None:
389 method = "from_" + base.alias
390 else:
391 method = "from_" + base.__class__.__name__
393 _convert = getattr(self, method)
395 if _convert is not None:
396 result = _convert(element, base)
398 if result is not None:
399 return result
401 raise CoercionFailed("Cannot convert %s of type %s from %s to %s" % (element, type(element), base, self))
403 def convert(self, element, base=None):
404 """Convert ``element`` to ``self.dtype``. """
406 if base is not None:
407 if _not_a_coeff(element):
408 raise CoercionFailed('%s is not in any domain' % element)
409 return self.convert_from(element, base)
411 if self.of_type(element):
412 return element
414 if _not_a_coeff(element):
415 raise CoercionFailed('%s is not in any domain' % element)
417 from sympy.polys.domains import ZZ, QQ, RealField, ComplexField
419 if ZZ.of_type(element):
420 return self.convert_from(element, ZZ)
422 if isinstance(element, int):
423 return self.convert_from(ZZ(element), ZZ)
425 if HAS_GMPY:
426 integers = ZZ
427 if isinstance(element, integers.tp):
428 return self.convert_from(element, integers)
430 rationals = QQ
431 if isinstance(element, rationals.tp):
432 return self.convert_from(element, rationals)
434 if isinstance(element, float):
435 parent = RealField(tol=False)
436 return self.convert_from(parent(element), parent)
438 if isinstance(element, complex):
439 parent = ComplexField(tol=False)
440 return self.convert_from(parent(element), parent)
442 if isinstance(element, DomainElement):
443 return self.convert_from(element, element.parent())
445 # TODO: implement this in from_ methods
446 if self.is_Numerical and getattr(element, 'is_ground', False):
447 return self.convert(element.LC())
449 if isinstance(element, Basic):
450 try:
451 return self.from_sympy(element)
452 except (TypeError, ValueError):
453 pass
454 else: # TODO: remove this branch
455 if not is_sequence(element):
456 try:
457 element = sympify(element, strict=True)
458 if isinstance(element, Basic):
459 return self.from_sympy(element)
460 except (TypeError, ValueError):
461 pass
463 raise CoercionFailed("Cannot convert %s of type %s to %s" % (element, type(element), self))
465 def of_type(self, element):
466 """Check if ``a`` is of type ``dtype``. """
467 return isinstance(element, self.tp) # XXX: this isn't correct, e.g. PolyElement
469 def __contains__(self, a):
470 """Check if ``a`` belongs to this domain. """
471 try:
472 if _not_a_coeff(a):
473 raise CoercionFailed
474 self.convert(a) # this might raise, too
475 except CoercionFailed:
476 return False
478 return True
480 def to_sympy(self, a):
481 """Convert domain element *a* to a SymPy expression (Expr).
483 Explanation
484 ===========
486 Convert a :py:class:`~.Domain` element *a* to :py:class:`~.Expr`. Most
487 public SymPy functions work with objects of type :py:class:`~.Expr`.
488 The elements of a :py:class:`~.Domain` have a different internal
489 representation. It is not possible to mix domain elements with
490 :py:class:`~.Expr` so each domain has :py:meth:`~.Domain.to_sympy` and
491 :py:meth:`~.Domain.from_sympy` methods to convert its domain elements
492 to and from :py:class:`~.Expr`.
494 Parameters
495 ==========
497 a: domain element
498 An element of this :py:class:`~.Domain`.
500 Returns
501 =======
503 expr: Expr
504 A normal SymPy expression of type :py:class:`~.Expr`.
506 Examples
507 ========
509 Construct an element of the :ref:`QQ` domain and then convert it to
510 :py:class:`~.Expr`.
512 >>> from sympy import QQ, Expr
513 >>> q_domain = QQ(2)
514 >>> q_domain
515 2
516 >>> q_expr = QQ.to_sympy(q_domain)
517 >>> q_expr
518 2
520 Although the printed forms look similar these objects are not of the
521 same type.
523 >>> isinstance(q_domain, Expr)
524 False
525 >>> isinstance(q_expr, Expr)
526 True
528 Construct an element of :ref:`K[x]` and convert to
529 :py:class:`~.Expr`.
531 >>> from sympy import Symbol
532 >>> x = Symbol('x')
533 >>> K = QQ[x]
534 >>> x_domain = K.gens[0] # generator x as a domain element
535 >>> p_domain = x_domain**2/3 + 1
536 >>> p_domain
537 1/3*x**2 + 1
538 >>> p_expr = K.to_sympy(p_domain)
539 >>> p_expr
540 x**2/3 + 1
542 The :py:meth:`~.Domain.from_sympy` method is used for the opposite
543 conversion from a normal SymPy expression to a domain element.
545 >>> p_domain == p_expr
546 False
547 >>> K.from_sympy(p_expr) == p_domain
548 True
549 >>> K.to_sympy(p_domain) == p_expr
550 True
551 >>> K.from_sympy(K.to_sympy(p_domain)) == p_domain
552 True
553 >>> K.to_sympy(K.from_sympy(p_expr)) == p_expr
554 True
556 The :py:meth:`~.Domain.from_sympy` method makes it easier to construct
557 domain elements interactively.
559 >>> from sympy import Symbol
560 >>> x = Symbol('x')
561 >>> K = QQ[x]
562 >>> K.from_sympy(x**2/3 + 1)
563 1/3*x**2 + 1
565 See also
566 ========
568 from_sympy
569 convert_from
570 """
571 raise NotImplementedError
573 def from_sympy(self, a):
574 """Convert a SymPy expression to an element of this domain.
576 Explanation
577 ===========
579 See :py:meth:`~.Domain.to_sympy` for explanation and examples.
581 Parameters
582 ==========
584 expr: Expr
585 A normal SymPy expression of type :py:class:`~.Expr`.
587 Returns
588 =======
590 a: domain element
591 An element of this :py:class:`~.Domain`.
593 See also
594 ========
596 to_sympy
597 convert_from
598 """
599 raise NotImplementedError
601 def sum(self, args):
602 return sum(args)
604 def from_FF(K1, a, K0):
605 """Convert ``ModularInteger(int)`` to ``dtype``. """
606 return None
608 def from_FF_python(K1, a, K0):
609 """Convert ``ModularInteger(int)`` to ``dtype``. """
610 return None
612 def from_ZZ_python(K1, a, K0):
613 """Convert a Python ``int`` object to ``dtype``. """
614 return None
616 def from_QQ_python(K1, a, K0):
617 """Convert a Python ``Fraction`` object to ``dtype``. """
618 return None
620 def from_FF_gmpy(K1, a, K0):
621 """Convert ``ModularInteger(mpz)`` to ``dtype``. """
622 return None
624 def from_ZZ_gmpy(K1, a, K0):
625 """Convert a GMPY ``mpz`` object to ``dtype``. """
626 return None
628 def from_QQ_gmpy(K1, a, K0):
629 """Convert a GMPY ``mpq`` object to ``dtype``. """
630 return None
632 def from_RealField(K1, a, K0):
633 """Convert a real element object to ``dtype``. """
634 return None
636 def from_ComplexField(K1, a, K0):
637 """Convert a complex element to ``dtype``. """
638 return None
640 def from_AlgebraicField(K1, a, K0):
641 """Convert an algebraic number to ``dtype``. """
642 return None
644 def from_PolynomialRing(K1, a, K0):
645 """Convert a polynomial to ``dtype``. """
646 if a.is_ground:
647 return K1.convert(a.LC, K0.dom)
649 def from_FractionField(K1, a, K0):
650 """Convert a rational function to ``dtype``. """
651 return None
653 def from_MonogenicFiniteExtension(K1, a, K0):
654 """Convert an ``ExtensionElement`` to ``dtype``. """
655 return K1.convert_from(a.rep, K0.ring)
657 def from_ExpressionDomain(K1, a, K0):
658 """Convert a ``EX`` object to ``dtype``. """
659 return K1.from_sympy(a.ex)
661 def from_ExpressionRawDomain(K1, a, K0):
662 """Convert a ``EX`` object to ``dtype``. """
663 return K1.from_sympy(a)
665 def from_GlobalPolynomialRing(K1, a, K0):
666 """Convert a polynomial to ``dtype``. """
667 if a.degree() <= 0:
668 return K1.convert(a.LC(), K0.dom)
670 def from_GeneralizedPolynomialRing(K1, a, K0):
671 return K1.from_FractionField(a, K0)
673 def unify_with_symbols(K0, K1, symbols):
674 if (K0.is_Composite and (set(K0.symbols) & set(symbols))) or (K1.is_Composite and (set(K1.symbols) & set(symbols))):
675 raise UnificationFailed("Cannot unify %s with %s, given %s generators" % (K0, K1, tuple(symbols)))
677 return K0.unify(K1)
679 def unify(K0, K1, symbols=None):
680 """
681 Construct a minimal domain that contains elements of ``K0`` and ``K1``.
683 Known domains (from smallest to largest):
685 - ``GF(p)``
686 - ``ZZ``
687 - ``QQ``
688 - ``RR(prec, tol)``
689 - ``CC(prec, tol)``
690 - ``ALG(a, b, c)``
691 - ``K[x, y, z]``
692 - ``K(x, y, z)``
693 - ``EX``
695 """
696 if symbols is not None:
697 return K0.unify_with_symbols(K1, symbols)
699 if K0 == K1:
700 return K0
702 if K0.is_EXRAW:
703 return K0
704 if K1.is_EXRAW:
705 return K1
707 if K0.is_EX:
708 return K0
709 if K1.is_EX:
710 return K1
712 if K0.is_FiniteExtension or K1.is_FiniteExtension:
713 if K1.is_FiniteExtension:
714 K0, K1 = K1, K0
715 if K1.is_FiniteExtension:
716 # Unifying two extensions.
717 # Try to ensure that K0.unify(K1) == K1.unify(K0)
718 if list(ordered([K0.modulus, K1.modulus]))[1] == K0.modulus:
719 K0, K1 = K1, K0
720 return K1.set_domain(K0)
721 else:
722 # Drop the generator from other and unify with the base domain
723 K1 = K1.drop(K0.symbol)
724 K1 = K0.domain.unify(K1)
725 return K0.set_domain(K1)
727 if K0.is_Composite or K1.is_Composite:
728 K0_ground = K0.dom if K0.is_Composite else K0
729 K1_ground = K1.dom if K1.is_Composite else K1
731 K0_symbols = K0.symbols if K0.is_Composite else ()
732 K1_symbols = K1.symbols if K1.is_Composite else ()
734 domain = K0_ground.unify(K1_ground)
735 symbols = _unify_gens(K0_symbols, K1_symbols)
736 order = K0.order if K0.is_Composite else K1.order
738 if ((K0.is_FractionField and K1.is_PolynomialRing or
739 K1.is_FractionField and K0.is_PolynomialRing) and
740 (not K0_ground.is_Field or not K1_ground.is_Field) and domain.is_Field
741 and domain.has_assoc_Ring):
742 domain = domain.get_ring()
744 if K0.is_Composite and (not K1.is_Composite or K0.is_FractionField or K1.is_PolynomialRing):
745 cls = K0.__class__
746 else:
747 cls = K1.__class__
749 from sympy.polys.domains.old_polynomialring import GlobalPolynomialRing
750 if cls == GlobalPolynomialRing:
751 return cls(domain, symbols)
753 return cls(domain, symbols, order)
755 def mkinexact(cls, K0, K1):
756 prec = max(K0.precision, K1.precision)
757 tol = max(K0.tolerance, K1.tolerance)
758 return cls(prec=prec, tol=tol)
760 if K1.is_ComplexField:
761 K0, K1 = K1, K0
762 if K0.is_ComplexField:
763 if K1.is_ComplexField or K1.is_RealField:
764 return mkinexact(K0.__class__, K0, K1)
765 else:
766 return K0
768 if K1.is_RealField:
769 K0, K1 = K1, K0
770 if K0.is_RealField:
771 if K1.is_RealField:
772 return mkinexact(K0.__class__, K0, K1)
773 elif K1.is_GaussianRing or K1.is_GaussianField:
774 from sympy.polys.domains.complexfield import ComplexField
775 return ComplexField(prec=K0.precision, tol=K0.tolerance)
776 else:
777 return K0
779 if K1.is_AlgebraicField:
780 K0, K1 = K1, K0
781 if K0.is_AlgebraicField:
782 if K1.is_GaussianRing:
783 K1 = K1.get_field()
784 if K1.is_GaussianField:
785 K1 = K1.as_AlgebraicField()
786 if K1.is_AlgebraicField:
787 return K0.__class__(K0.dom.unify(K1.dom), *_unify_gens(K0.orig_ext, K1.orig_ext))
788 else:
789 return K0
791 if K0.is_GaussianField:
792 return K0
793 if K1.is_GaussianField:
794 return K1
796 if K0.is_GaussianRing:
797 if K1.is_RationalField:
798 K0 = K0.get_field()
799 return K0
800 if K1.is_GaussianRing:
801 if K0.is_RationalField:
802 K1 = K1.get_field()
803 return K1
805 if K0.is_RationalField:
806 return K0
807 if K1.is_RationalField:
808 return K1
810 if K0.is_IntegerRing:
811 return K0
812 if K1.is_IntegerRing:
813 return K1
815 if K0.is_FiniteField and K1.is_FiniteField:
816 return K0.__class__(max(K0.mod, K1.mod, key=default_sort_key))
818 from sympy.polys.domains import EX
819 return EX
821 def __eq__(self, other):
822 """Returns ``True`` if two domains are equivalent. """
823 return isinstance(other, Domain) and self.dtype == other.dtype
825 def __ne__(self, other):
826 """Returns ``False`` if two domains are equivalent. """
827 return not self == other
829 def map(self, seq):
830 """Rersively apply ``self`` to all elements of ``seq``. """
831 result = []
833 for elt in seq:
834 if isinstance(elt, list):
835 result.append(self.map(elt))
836 else:
837 result.append(self(elt))
839 return result
841 def get_ring(self):
842 """Returns a ring associated with ``self``. """
843 raise DomainError('there is no ring associated with %s' % self)
845 def get_field(self):
846 """Returns a field associated with ``self``. """
847 raise DomainError('there is no field associated with %s' % self)
849 def get_exact(self):
850 """Returns an exact domain associated with ``self``. """
851 return self
853 def __getitem__(self, symbols):
854 """The mathematical way to make a polynomial ring. """
855 if hasattr(symbols, '__iter__'):
856 return self.poly_ring(*symbols)
857 else:
858 return self.poly_ring(symbols)
860 def poly_ring(self, *symbols, order=lex):
861 """Returns a polynomial ring, i.e. `K[X]`. """
862 from sympy.polys.domains.polynomialring import PolynomialRing
863 return PolynomialRing(self, symbols, order)
865 def frac_field(self, *symbols, order=lex):
866 """Returns a fraction field, i.e. `K(X)`. """
867 from sympy.polys.domains.fractionfield import FractionField
868 return FractionField(self, symbols, order)
870 def old_poly_ring(self, *symbols, **kwargs):
871 """Returns a polynomial ring, i.e. `K[X]`. """
872 from sympy.polys.domains.old_polynomialring import PolynomialRing
873 return PolynomialRing(self, *symbols, **kwargs)
875 def old_frac_field(self, *symbols, **kwargs):
876 """Returns a fraction field, i.e. `K(X)`. """
877 from sympy.polys.domains.old_fractionfield import FractionField
878 return FractionField(self, *symbols, **kwargs)
880 def algebraic_field(self, *extension, alias=None):
881 r"""Returns an algebraic field, i.e. `K(\alpha, \ldots)`. """
882 raise DomainError("Cannot create algebraic field over %s" % self)
884 def alg_field_from_poly(self, poly, alias=None, root_index=-1):
885 r"""
886 Convenience method to construct an algebraic extension on a root of a
887 polynomial, chosen by root index.
889 Parameters
890 ==========
892 poly : :py:class:`~.Poly`
893 The polynomial whose root generates the extension.
894 alias : str, optional (default=None)
895 Symbol name for the generator of the extension.
896 E.g. "alpha" or "theta".
897 root_index : int, optional (default=-1)
898 Specifies which root of the polynomial is desired. The ordering is
899 as defined by the :py:class:`~.ComplexRootOf` class. The default of
900 ``-1`` selects the most natural choice in the common cases of
901 quadratic and cyclotomic fields (the square root on the positive
902 real or imaginary axis, resp. $\mathrm{e}^{2\pi i/n}$).
904 Examples
905 ========
907 >>> from sympy import QQ, Poly
908 >>> from sympy.abc import x
909 >>> f = Poly(x**2 - 2)
910 >>> K = QQ.alg_field_from_poly(f)
911 >>> K.ext.minpoly == f
912 True
913 >>> g = Poly(8*x**3 - 6*x - 1)
914 >>> L = QQ.alg_field_from_poly(g, "alpha")
915 >>> L.ext.minpoly == g
916 True
917 >>> L.to_sympy(L([1, 1, 1]))
918 alpha**2 + alpha + 1
920 """
921 from sympy.polys.rootoftools import CRootOf
922 root = CRootOf(poly, root_index)
923 alpha = AlgebraicNumber(root, alias=alias)
924 return self.algebraic_field(alpha, alias=alias)
926 def cyclotomic_field(self, n, ss=False, alias="zeta", gen=None, root_index=-1):
927 r"""
928 Convenience method to construct a cyclotomic field.
930 Parameters
931 ==========
933 n : int
934 Construct the nth cyclotomic field.
935 ss : boolean, optional (default=False)
936 If True, append *n* as a subscript on the alias string.
937 alias : str, optional (default="zeta")
938 Symbol name for the generator.
939 gen : :py:class:`~.Symbol`, optional (default=None)
940 Desired variable for the cyclotomic polynomial that defines the
941 field. If ``None``, a dummy variable will be used.
942 root_index : int, optional (default=-1)
943 Specifies which root of the polynomial is desired. The ordering is
944 as defined by the :py:class:`~.ComplexRootOf` class. The default of
945 ``-1`` selects the root $\mathrm{e}^{2\pi i/n}$.
947 Examples
948 ========
950 >>> from sympy import QQ, latex
951 >>> K = QQ.cyclotomic_field(5)
952 >>> K.to_sympy(K([-1, 1]))
953 1 - zeta
954 >>> L = QQ.cyclotomic_field(7, True)
955 >>> a = L.to_sympy(L([-1, 1]))
956 >>> print(a)
957 1 - zeta7
958 >>> print(latex(a))
959 1 - \zeta_{7}
961 """
962 from sympy.polys.specialpolys import cyclotomic_poly
963 if ss:
964 alias += str(n)
965 return self.alg_field_from_poly(cyclotomic_poly(n, gen), alias=alias,
966 root_index=root_index)
968 def inject(self, *symbols):
969 """Inject generators into this domain. """
970 raise NotImplementedError
972 def drop(self, *symbols):
973 """Drop generators from this domain. """
974 if self.is_Simple:
975 return self
976 raise NotImplementedError # pragma: no cover
978 def is_zero(self, a):
979 """Returns True if ``a`` is zero. """
980 return not a
982 def is_one(self, a):
983 """Returns True if ``a`` is one. """
984 return a == self.one
986 def is_positive(self, a):
987 """Returns True if ``a`` is positive. """
988 return a > 0
990 def is_negative(self, a):
991 """Returns True if ``a`` is negative. """
992 return a < 0
994 def is_nonpositive(self, a):
995 """Returns True if ``a`` is non-positive. """
996 return a <= 0
998 def is_nonnegative(self, a):
999 """Returns True if ``a`` is non-negative. """
1000 return a >= 0
1002 def canonical_unit(self, a):
1003 if self.is_negative(a):
1004 return -self.one
1005 else:
1006 return self.one
1008 def abs(self, a):
1009 """Absolute value of ``a``, implies ``__abs__``. """
1010 return abs(a)
1012 def neg(self, a):
1013 """Returns ``a`` negated, implies ``__neg__``. """
1014 return -a
1016 def pos(self, a):
1017 """Returns ``a`` positive, implies ``__pos__``. """
1018 return +a
1020 def add(self, a, b):
1021 """Sum of ``a`` and ``b``, implies ``__add__``. """
1022 return a + b
1024 def sub(self, a, b):
1025 """Difference of ``a`` and ``b``, implies ``__sub__``. """
1026 return a - b
1028 def mul(self, a, b):
1029 """Product of ``a`` and ``b``, implies ``__mul__``. """
1030 return a * b
1032 def pow(self, a, b):
1033 """Raise ``a`` to power ``b``, implies ``__pow__``. """
1034 return a ** b
1036 def exquo(self, a, b):
1037 """Exact quotient of *a* and *b*. Analogue of ``a / b``.
1039 Explanation
1040 ===========
1042 This is essentially the same as ``a / b`` except that an error will be
1043 raised if the division is inexact (if there is any remainder) and the
1044 result will always be a domain element. When working in a
1045 :py:class:`~.Domain` that is not a :py:class:`~.Field` (e.g. :ref:`ZZ`
1046 or :ref:`K[x]`) ``exquo`` should be used instead of ``/``.
1048 The key invariant is that if ``q = K.exquo(a, b)`` (and ``exquo`` does
1049 not raise an exception) then ``a == b*q``.
1051 Examples
1052 ========
1054 We can use ``K.exquo`` instead of ``/`` for exact division.
1056 >>> from sympy import ZZ
1057 >>> ZZ.exquo(ZZ(4), ZZ(2))
1058 2
1059 >>> ZZ.exquo(ZZ(5), ZZ(2))
1060 Traceback (most recent call last):
1061 ...
1062 ExactQuotientFailed: 2 does not divide 5 in ZZ
1064 Over a :py:class:`~.Field` such as :ref:`QQ`, division (with nonzero
1065 divisor) is always exact so in that case ``/`` can be used instead of
1066 :py:meth:`~.Domain.exquo`.
1068 >>> from sympy import QQ
1069 >>> QQ.exquo(QQ(5), QQ(2))
1070 5/2
1071 >>> QQ(5) / QQ(2)
1072 5/2
1074 Parameters
1075 ==========
1077 a: domain element
1078 The dividend
1079 b: domain element
1080 The divisor
1082 Returns
1083 =======
1085 q: domain element
1086 The exact quotient
1088 Raises
1089 ======
1091 ExactQuotientFailed: if exact division is not possible.
1092 ZeroDivisionError: when the divisor is zero.
1094 See also
1095 ========
1097 quo: Analogue of ``a // b``
1098 rem: Analogue of ``a % b``
1099 div: Analogue of ``divmod(a, b)``
1101 Notes
1102 =====
1104 Since the default :py:attr:`~.Domain.dtype` for :ref:`ZZ` is ``int``
1105 (or ``mpz``) division as ``a / b`` should not be used as it would give
1106 a ``float``.
1108 >>> ZZ(4) / ZZ(2)
1109 2.0
1110 >>> ZZ(5) / ZZ(2)
1111 2.5
1113 Using ``/`` with :ref:`ZZ` will lead to incorrect results so
1114 :py:meth:`~.Domain.exquo` should be used instead.
1116 """
1117 raise NotImplementedError
1119 def quo(self, a, b):
1120 """Quotient of *a* and *b*. Analogue of ``a // b``.
1122 ``K.quo(a, b)`` is equivalent to ``K.div(a, b)[0]``. See
1123 :py:meth:`~.Domain.div` for more explanation.
1125 See also
1126 ========
1128 rem: Analogue of ``a % b``
1129 div: Analogue of ``divmod(a, b)``
1130 exquo: Analogue of ``a / b``
1131 """
1132 raise NotImplementedError
1134 def rem(self, a, b):
1135 """Modulo division of *a* and *b*. Analogue of ``a % b``.
1137 ``K.rem(a, b)`` is equivalent to ``K.div(a, b)[1]``. See
1138 :py:meth:`~.Domain.div` for more explanation.
1140 See also
1141 ========
1143 quo: Analogue of ``a // b``
1144 div: Analogue of ``divmod(a, b)``
1145 exquo: Analogue of ``a / b``
1146 """
1147 raise NotImplementedError
1149 def div(self, a, b):
1150 """Quotient and remainder for *a* and *b*. Analogue of ``divmod(a, b)``
1152 Explanation
1153 ===========
1155 This is essentially the same as ``divmod(a, b)`` except that is more
1156 consistent when working over some :py:class:`~.Field` domains such as
1157 :ref:`QQ`. When working over an arbitrary :py:class:`~.Domain` the
1158 :py:meth:`~.Domain.div` method should be used instead of ``divmod``.
1160 The key invariant is that if ``q, r = K.div(a, b)`` then
1161 ``a == b*q + r``.
1163 The result of ``K.div(a, b)`` is the same as the tuple
1164 ``(K.quo(a, b), K.rem(a, b))`` except that if both quotient and
1165 remainder are needed then it is more efficient to use
1166 :py:meth:`~.Domain.div`.
1168 Examples
1169 ========
1171 We can use ``K.div`` instead of ``divmod`` for floor division and
1172 remainder.
1174 >>> from sympy import ZZ, QQ
1175 >>> ZZ.div(ZZ(5), ZZ(2))
1176 (2, 1)
1178 If ``K`` is a :py:class:`~.Field` then the division is always exact
1179 with a remainder of :py:attr:`~.Domain.zero`.
1181 >>> QQ.div(QQ(5), QQ(2))
1182 (5/2, 0)
1184 Parameters
1185 ==========
1187 a: domain element
1188 The dividend
1189 b: domain element
1190 The divisor
1192 Returns
1193 =======
1195 (q, r): tuple of domain elements
1196 The quotient and remainder
1198 Raises
1199 ======
1201 ZeroDivisionError: when the divisor is zero.
1203 See also
1204 ========
1206 quo: Analogue of ``a // b``
1207 rem: Analogue of ``a % b``
1208 exquo: Analogue of ``a / b``
1210 Notes
1211 =====
1213 If ``gmpy`` is installed then the ``gmpy.mpq`` type will be used as
1214 the :py:attr:`~.Domain.dtype` for :ref:`QQ`. The ``gmpy.mpq`` type
1215 defines ``divmod`` in a way that is undesirable so
1216 :py:meth:`~.Domain.div` should be used instead of ``divmod``.
1218 >>> a = QQ(1)
1219 >>> b = QQ(3, 2)
1220 >>> a # doctest: +SKIP
1221 mpq(1,1)
1222 >>> b # doctest: +SKIP
1223 mpq(3,2)
1224 >>> divmod(a, b) # doctest: +SKIP
1225 (mpz(0), mpq(1,1))
1226 >>> QQ.div(a, b) # doctest: +SKIP
1227 (mpq(2,3), mpq(0,1))
1229 Using ``//`` or ``%`` with :ref:`QQ` will lead to incorrect results so
1230 :py:meth:`~.Domain.div` should be used instead.
1232 """
1233 raise NotImplementedError
1235 def invert(self, a, b):
1236 """Returns inversion of ``a mod b``, implies something. """
1237 raise NotImplementedError
1239 def revert(self, a):
1240 """Returns ``a**(-1)`` if possible. """
1241 raise NotImplementedError
1243 def numer(self, a):
1244 """Returns numerator of ``a``. """
1245 raise NotImplementedError
1247 def denom(self, a):
1248 """Returns denominator of ``a``. """
1249 raise NotImplementedError
1251 def half_gcdex(self, a, b):
1252 """Half extended GCD of ``a`` and ``b``. """
1253 s, t, h = self.gcdex(a, b)
1254 return s, h
1256 def gcdex(self, a, b):
1257 """Extended GCD of ``a`` and ``b``. """
1258 raise NotImplementedError
1260 def cofactors(self, a, b):
1261 """Returns GCD and cofactors of ``a`` and ``b``. """
1262 gcd = self.gcd(a, b)
1263 cfa = self.quo(a, gcd)
1264 cfb = self.quo(b, gcd)
1265 return gcd, cfa, cfb
1267 def gcd(self, a, b):
1268 """Returns GCD of ``a`` and ``b``. """
1269 raise NotImplementedError
1271 def lcm(self, a, b):
1272 """Returns LCM of ``a`` and ``b``. """
1273 raise NotImplementedError
1275 def log(self, a, b):
1276 """Returns b-base logarithm of ``a``. """
1277 raise NotImplementedError
1279 def sqrt(self, a):
1280 """Returns square root of ``a``. """
1281 raise NotImplementedError
1283 def evalf(self, a, prec=None, **options):
1284 """Returns numerical approximation of ``a``. """
1285 return self.to_sympy(a).evalf(prec, **options)
1287 n = evalf
1289 def real(self, a):
1290 return a
1292 def imag(self, a):
1293 return self.zero
1295 def almosteq(self, a, b, tolerance=None):
1296 """Check if ``a`` and ``b`` are almost equal. """
1297 return a == b
1299 def characteristic(self):
1300 """Return the characteristic of this domain. """
1301 raise NotImplementedError('characteristic()')
1304__all__ = ['Domain']