Coverage for /usr/lib/python3/dist-packages/sympy/polys/domains/integerring.py: 60%
82 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:`IntegerRing` class. """
3from sympy.external.gmpy import MPZ, HAS_GMPY
5from sympy.polys.domains.groundtypes import (
6 SymPyInteger,
7 factorial,
8 gcdex, gcd, lcm, sqrt,
9)
11from sympy.polys.domains.characteristiczero import CharacteristicZero
12from sympy.polys.domains.ring import Ring
13from sympy.polys.domains.simpledomain import SimpleDomain
14from sympy.polys.polyerrors import CoercionFailed
15from sympy.utilities import public
17import math
19@public
20class IntegerRing(Ring, CharacteristicZero, SimpleDomain):
21 r"""The domain ``ZZ`` representing the integers `\mathbb{Z}`.
23 The :py:class:`IntegerRing` class represents the ring of integers as a
24 :py:class:`~.Domain` in the domain system. :py:class:`IntegerRing` is a
25 super class of :py:class:`PythonIntegerRing` and
26 :py:class:`GMPYIntegerRing` one of which will be the implementation for
27 :ref:`ZZ` depending on whether or not ``gmpy`` or ``gmpy2`` is installed.
29 See also
30 ========
32 Domain
33 """
35 rep = 'ZZ'
36 alias = 'ZZ'
37 dtype = MPZ
38 zero = dtype(0)
39 one = dtype(1)
40 tp = type(one)
43 is_IntegerRing = is_ZZ = True
44 is_Numerical = True
45 is_PID = True
47 has_assoc_Ring = True
48 has_assoc_Field = True
50 def __init__(self):
51 """Allow instantiation of this domain. """
53 def to_sympy(self, a):
54 """Convert ``a`` to a SymPy object. """
55 return SymPyInteger(int(a))
57 def from_sympy(self, a):
58 """Convert SymPy's Integer to ``dtype``. """
59 if a.is_Integer:
60 return MPZ(a.p)
61 elif a.is_Float and int(a) == a:
62 return MPZ(int(a))
63 else:
64 raise CoercionFailed("expected an integer, got %s" % a)
66 def get_field(self):
67 r"""Return the associated field of fractions :ref:`QQ`
69 Returns
70 =======
72 :ref:`QQ`:
73 The associated field of fractions :ref:`QQ`, a
74 :py:class:`~.Domain` representing the rational numbers
75 `\mathbb{Q}`.
77 Examples
78 ========
80 >>> from sympy import ZZ
81 >>> ZZ.get_field()
82 QQ
83 """
84 from sympy.polys.domains import QQ
85 return QQ
87 def algebraic_field(self, *extension, alias=None):
88 r"""Returns an algebraic field, i.e. `\mathbb{Q}(\alpha, \ldots)`.
90 Parameters
91 ==========
93 *extension : One or more :py:class:`~.Expr`.
94 Generators of the extension. These should be expressions that are
95 algebraic over `\mathbb{Q}`.
97 alias : str, :py:class:`~.Symbol`, None, optional (default=None)
98 If provided, this will be used as the alias symbol for the
99 primitive element of the returned :py:class:`~.AlgebraicField`.
101 Returns
102 =======
104 :py:class:`~.AlgebraicField`
105 A :py:class:`~.Domain` representing the algebraic field extension.
107 Examples
108 ========
110 >>> from sympy import ZZ, sqrt
111 >>> ZZ.algebraic_field(sqrt(2))
112 QQ<sqrt(2)>
113 """
114 return self.get_field().algebraic_field(*extension, alias=alias)
116 def from_AlgebraicField(K1, a, K0):
117 """Convert a :py:class:`~.ANP` object to :ref:`ZZ`.
119 See :py:meth:`~.Domain.convert`.
120 """
121 if a.is_ground:
122 return K1.convert(a.LC(), K0.dom)
124 def log(self, a, b):
125 r"""Logarithm of *a* to the base *b*.
127 Parameters
128 ==========
130 a: number
131 b: number
133 Returns
134 =======
136 $\\lfloor\log(a, b)\\rfloor$:
137 Floor of the logarithm of *a* to the base *b*
139 Examples
140 ========
142 >>> from sympy import ZZ
143 >>> ZZ.log(ZZ(8), ZZ(2))
144 3
145 >>> ZZ.log(ZZ(9), ZZ(2))
146 3
148 Notes
149 =====
151 This function uses ``math.log`` which is based on ``float`` so it will
152 fail for large integer arguments.
153 """
154 return self.dtype(math.log(int(a), b))
156 def from_FF(K1, a, K0):
157 """Convert ``ModularInteger(int)`` to GMPY's ``mpz``. """
158 return MPZ(a.to_int())
160 def from_FF_python(K1, a, K0):
161 """Convert ``ModularInteger(int)`` to GMPY's ``mpz``. """
162 return MPZ(a.to_int())
164 def from_ZZ(K1, a, K0):
165 """Convert Python's ``int`` to GMPY's ``mpz``. """
166 return MPZ(a)
168 def from_ZZ_python(K1, a, K0):
169 """Convert Python's ``int`` to GMPY's ``mpz``. """
170 return MPZ(a)
172 def from_QQ(K1, a, K0):
173 """Convert Python's ``Fraction`` to GMPY's ``mpz``. """
174 if a.denominator == 1:
175 return MPZ(a.numerator)
177 def from_QQ_python(K1, a, K0):
178 """Convert Python's ``Fraction`` to GMPY's ``mpz``. """
179 if a.denominator == 1:
180 return MPZ(a.numerator)
182 def from_FF_gmpy(K1, a, K0):
183 """Convert ``ModularInteger(mpz)`` to GMPY's ``mpz``. """
184 return a.to_int()
186 def from_ZZ_gmpy(K1, a, K0):
187 """Convert GMPY's ``mpz`` to GMPY's ``mpz``. """
188 return a
190 def from_QQ_gmpy(K1, a, K0):
191 """Convert GMPY ``mpq`` to GMPY's ``mpz``. """
192 if a.denominator == 1:
193 return a.numerator
195 def from_RealField(K1, a, K0):
196 """Convert mpmath's ``mpf`` to GMPY's ``mpz``. """
197 p, q = K0.to_rational(a)
199 if q == 1:
200 return MPZ(p)
202 def from_GaussianIntegerRing(K1, a, K0):
203 if a.y == 0:
204 return a.x
206 def gcdex(self, a, b):
207 """Compute extended GCD of ``a`` and ``b``. """
208 h, s, t = gcdex(a, b)
209 if HAS_GMPY:
210 return s, t, h
211 else:
212 return h, s, t
214 def gcd(self, a, b):
215 """Compute GCD of ``a`` and ``b``. """
216 return gcd(a, b)
218 def lcm(self, a, b):
219 """Compute LCM of ``a`` and ``b``. """
220 return lcm(a, b)
222 def sqrt(self, a):
223 """Compute square root of ``a``. """
224 return sqrt(a)
226 def factorial(self, a):
227 """Compute factorial of ``a``. """
228 return factorial(a)
231ZZ = IntegerRing()