123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- """Implementation of :class:`IntegerRing` class. """
- from sympy.external.gmpy import MPZ, HAS_GMPY
- from sympy.polys.domains.groundtypes import (
- SymPyInteger,
- factorial,
- gcdex, gcd, lcm, sqrt,
- )
- from sympy.polys.domains.characteristiczero import CharacteristicZero
- from sympy.polys.domains.ring import Ring
- from sympy.polys.domains.simpledomain import SimpleDomain
- from sympy.polys.polyerrors import CoercionFailed
- from sympy.utilities import public
- import math
- @public
- class IntegerRing(Ring, CharacteristicZero, SimpleDomain):
- r"""The domain ``ZZ`` representing the integers `\mathbb{Z}`.
- The :py:class:`IntegerRing` class represents the ring of integers as a
- :py:class:`~.Domain` in the domain system. :py:class:`IntegerRing` is a
- super class of :py:class:`PythonIntegerRing` and
- :py:class:`GMPYIntegerRing` one of which will be the implementation for
- :ref:`ZZ` depending on whether or not ``gmpy`` or ``gmpy2`` is installed.
- See also
- ========
- Domain
- """
- rep = 'ZZ'
- alias = 'ZZ'
- dtype = MPZ
- zero = dtype(0)
- one = dtype(1)
- tp = type(one)
- is_IntegerRing = is_ZZ = True
- is_Numerical = True
- is_PID = True
- has_assoc_Ring = True
- has_assoc_Field = True
- def __init__(self):
- """Allow instantiation of this domain. """
- def to_sympy(self, a):
- """Convert ``a`` to a SymPy object. """
- return SymPyInteger(int(a))
- def from_sympy(self, a):
- """Convert SymPy's Integer to ``dtype``. """
- if a.is_Integer:
- return MPZ(a.p)
- elif a.is_Float and int(a) == a:
- return MPZ(int(a))
- else:
- raise CoercionFailed("expected an integer, got %s" % a)
- def get_field(self):
- r"""Return the associated field of fractions :ref:`QQ`
- Returns
- =======
- :ref:`QQ`:
- The associated field of fractions :ref:`QQ`, a
- :py:class:`~.Domain` representing the rational numbers
- `\mathbb{Q}`.
- Examples
- ========
- >>> from sympy import ZZ
- >>> ZZ.get_field()
- QQ
- """
- from sympy.polys.domains import QQ
- return QQ
- def algebraic_field(self, *extension):
- r"""Returns an algebraic field, i.e. `\mathbb{Q}(\alpha, \ldots)`.
- Parameters
- ==========
- *extension: One or more Expr.
- Generators of the extension. These should be expressions that are
- algebraic over `\mathbb{Q}`.
- Returns
- =======
- :py:class:`~.AlgebraicField`
- A :py:class:`~.Domain` representing the algebraic field extension.
- Examples
- ========
- >>> from sympy import ZZ, sqrt
- >>> ZZ.algebraic_field(sqrt(2))
- QQ<sqrt(2)>
- """
- return self.get_field().algebraic_field(*extension)
- def from_AlgebraicField(K1, a, K0):
- """Convert a :py:class:`~.ANP` object to :ref:`ZZ`.
- See :py:meth:`~.Domain.convert`.
- """
- if a.is_ground:
- return K1.convert(a.LC(), K0.dom)
- def log(self, a, b):
- r"""logarithm of *a* to the base *b*
- Parameters
- ==========
- a: number
- b: number
- Returns
- =======
- $\\lfloor\log(a, b)\\rfloor$:
- Floor of the logarithm of *a* to the base *b*
- Examples
- ========
- >>> from sympy import ZZ
- >>> ZZ.log(ZZ(8), ZZ(2))
- 3
- >>> ZZ.log(ZZ(9), ZZ(2))
- 3
- Notes
- =====
- This function uses ``math.log`` which is based on ``float`` so it will
- fail for large integer arguments.
- """
- return self.dtype(math.log(int(a), b))
- def from_FF(K1, a, K0):
- """Convert ``ModularInteger(int)`` to GMPY's ``mpz``. """
- return MPZ(a.to_int())
- def from_FF_python(K1, a, K0):
- """Convert ``ModularInteger(int)`` to GMPY's ``mpz``. """
- return MPZ(a.to_int())
- def from_ZZ(K1, a, K0):
- """Convert Python's ``int`` to GMPY's ``mpz``. """
- return MPZ(a)
- def from_ZZ_python(K1, a, K0):
- """Convert Python's ``int`` to GMPY's ``mpz``. """
- return MPZ(a)
- def from_QQ(K1, a, K0):
- """Convert Python's ``Fraction`` to GMPY's ``mpz``. """
- if a.denominator == 1:
- return MPZ(a.numerator)
- def from_QQ_python(K1, a, K0):
- """Convert Python's ``Fraction`` to GMPY's ``mpz``. """
- if a.denominator == 1:
- return MPZ(a.numerator)
- def from_FF_gmpy(K1, a, K0):
- """Convert ``ModularInteger(mpz)`` to GMPY's ``mpz``. """
- return a.to_int()
- def from_ZZ_gmpy(K1, a, K0):
- """Convert GMPY's ``mpz`` to GMPY's ``mpz``. """
- return a
- def from_QQ_gmpy(K1, a, K0):
- """Convert GMPY ``mpq`` to GMPY's ``mpz``. """
- if a.denominator == 1:
- return a.numerator
- def from_RealField(K1, a, K0):
- """Convert mpmath's ``mpf`` to GMPY's ``mpz``. """
- p, q = K0.to_rational(a)
- if q == 1:
- return MPZ(p)
- def from_GaussianIntegerRing(K1, a, K0):
- if a.y == 0:
- return a.x
- def gcdex(self, a, b):
- """Compute extended GCD of ``a`` and ``b``. """
- h, s, t = gcdex(a, b)
- if HAS_GMPY:
- return s, t, h
- else:
- return h, s, t
- def gcd(self, a, b):
- """Compute GCD of ``a`` and ``b``. """
- return gcd(a, b)
- def lcm(self, a, b):
- """Compute LCM of ``a`` and ``b``. """
- return lcm(a, b)
- def sqrt(self, a):
- """Compute square root of ``a``. """
- return sqrt(a)
- def factorial(self, a):
- """Compute factorial of ``a``. """
- return factorial(a)
- ZZ = IntegerRing()
|