integerring.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. """Implementation of :class:`IntegerRing` class. """
  2. from sympy.external.gmpy import MPZ, HAS_GMPY
  3. from sympy.polys.domains.groundtypes import (
  4. SymPyInteger,
  5. factorial,
  6. gcdex, gcd, lcm, sqrt,
  7. )
  8. from sympy.polys.domains.characteristiczero import CharacteristicZero
  9. from sympy.polys.domains.ring import Ring
  10. from sympy.polys.domains.simpledomain import SimpleDomain
  11. from sympy.polys.polyerrors import CoercionFailed
  12. from sympy.utilities import public
  13. import math
  14. @public
  15. class IntegerRing(Ring, CharacteristicZero, SimpleDomain):
  16. r"""The domain ``ZZ`` representing the integers `\mathbb{Z}`.
  17. The :py:class:`IntegerRing` class represents the ring of integers as a
  18. :py:class:`~.Domain` in the domain system. :py:class:`IntegerRing` is a
  19. super class of :py:class:`PythonIntegerRing` and
  20. :py:class:`GMPYIntegerRing` one of which will be the implementation for
  21. :ref:`ZZ` depending on whether or not ``gmpy`` or ``gmpy2`` is installed.
  22. See also
  23. ========
  24. Domain
  25. """
  26. rep = 'ZZ'
  27. alias = 'ZZ'
  28. dtype = MPZ
  29. zero = dtype(0)
  30. one = dtype(1)
  31. tp = type(one)
  32. is_IntegerRing = is_ZZ = True
  33. is_Numerical = True
  34. is_PID = True
  35. has_assoc_Ring = True
  36. has_assoc_Field = True
  37. def __init__(self):
  38. """Allow instantiation of this domain. """
  39. def to_sympy(self, a):
  40. """Convert ``a`` to a SymPy object. """
  41. return SymPyInteger(int(a))
  42. def from_sympy(self, a):
  43. """Convert SymPy's Integer to ``dtype``. """
  44. if a.is_Integer:
  45. return MPZ(a.p)
  46. elif a.is_Float and int(a) == a:
  47. return MPZ(int(a))
  48. else:
  49. raise CoercionFailed("expected an integer, got %s" % a)
  50. def get_field(self):
  51. r"""Return the associated field of fractions :ref:`QQ`
  52. Returns
  53. =======
  54. :ref:`QQ`:
  55. The associated field of fractions :ref:`QQ`, a
  56. :py:class:`~.Domain` representing the rational numbers
  57. `\mathbb{Q}`.
  58. Examples
  59. ========
  60. >>> from sympy import ZZ
  61. >>> ZZ.get_field()
  62. QQ
  63. """
  64. from sympy.polys.domains import QQ
  65. return QQ
  66. def algebraic_field(self, *extension, alias=None):
  67. r"""Returns an algebraic field, i.e. `\mathbb{Q}(\alpha, \ldots)`.
  68. Parameters
  69. ==========
  70. *extension : One or more :py:class:`~.Expr`.
  71. Generators of the extension. These should be expressions that are
  72. algebraic over `\mathbb{Q}`.
  73. alias : str, :py:class:`~.Symbol`, None, optional (default=None)
  74. If provided, this will be used as the alias symbol for the
  75. primitive element of the returned :py:class:`~.AlgebraicField`.
  76. Returns
  77. =======
  78. :py:class:`~.AlgebraicField`
  79. A :py:class:`~.Domain` representing the algebraic field extension.
  80. Examples
  81. ========
  82. >>> from sympy import ZZ, sqrt
  83. >>> ZZ.algebraic_field(sqrt(2))
  84. QQ<sqrt(2)>
  85. """
  86. return self.get_field().algebraic_field(*extension, alias=alias)
  87. def from_AlgebraicField(K1, a, K0):
  88. """Convert a :py:class:`~.ANP` object to :ref:`ZZ`.
  89. See :py:meth:`~.Domain.convert`.
  90. """
  91. if a.is_ground:
  92. return K1.convert(a.LC(), K0.dom)
  93. def log(self, a, b):
  94. r"""Logarithm of *a* to the base *b*.
  95. Parameters
  96. ==========
  97. a: number
  98. b: number
  99. Returns
  100. =======
  101. $\\lfloor\log(a, b)\\rfloor$:
  102. Floor of the logarithm of *a* to the base *b*
  103. Examples
  104. ========
  105. >>> from sympy import ZZ
  106. >>> ZZ.log(ZZ(8), ZZ(2))
  107. 3
  108. >>> ZZ.log(ZZ(9), ZZ(2))
  109. 3
  110. Notes
  111. =====
  112. This function uses ``math.log`` which is based on ``float`` so it will
  113. fail for large integer arguments.
  114. """
  115. return self.dtype(math.log(int(a), b))
  116. def from_FF(K1, a, K0):
  117. """Convert ``ModularInteger(int)`` to GMPY's ``mpz``. """
  118. return MPZ(a.to_int())
  119. def from_FF_python(K1, a, K0):
  120. """Convert ``ModularInteger(int)`` to GMPY's ``mpz``. """
  121. return MPZ(a.to_int())
  122. def from_ZZ(K1, a, K0):
  123. """Convert Python's ``int`` to GMPY's ``mpz``. """
  124. return MPZ(a)
  125. def from_ZZ_python(K1, a, K0):
  126. """Convert Python's ``int`` to GMPY's ``mpz``. """
  127. return MPZ(a)
  128. def from_QQ(K1, a, K0):
  129. """Convert Python's ``Fraction`` to GMPY's ``mpz``. """
  130. if a.denominator == 1:
  131. return MPZ(a.numerator)
  132. def from_QQ_python(K1, a, K0):
  133. """Convert Python's ``Fraction`` to GMPY's ``mpz``. """
  134. if a.denominator == 1:
  135. return MPZ(a.numerator)
  136. def from_FF_gmpy(K1, a, K0):
  137. """Convert ``ModularInteger(mpz)`` to GMPY's ``mpz``. """
  138. return a.to_int()
  139. def from_ZZ_gmpy(K1, a, K0):
  140. """Convert GMPY's ``mpz`` to GMPY's ``mpz``. """
  141. return a
  142. def from_QQ_gmpy(K1, a, K0):
  143. """Convert GMPY ``mpq`` to GMPY's ``mpz``. """
  144. if a.denominator == 1:
  145. return a.numerator
  146. def from_RealField(K1, a, K0):
  147. """Convert mpmath's ``mpf`` to GMPY's ``mpz``. """
  148. p, q = K0.to_rational(a)
  149. if q == 1:
  150. return MPZ(p)
  151. def from_GaussianIntegerRing(K1, a, K0):
  152. if a.y == 0:
  153. return a.x
  154. def gcdex(self, a, b):
  155. """Compute extended GCD of ``a`` and ``b``. """
  156. h, s, t = gcdex(a, b)
  157. if HAS_GMPY:
  158. return s, t, h
  159. else:
  160. return h, s, t
  161. def gcd(self, a, b):
  162. """Compute GCD of ``a`` and ``b``. """
  163. return gcd(a, b)
  164. def lcm(self, a, b):
  165. """Compute LCM of ``a`` and ``b``. """
  166. return lcm(a, b)
  167. def sqrt(self, a):
  168. """Compute square root of ``a``. """
  169. return sqrt(a)
  170. def factorial(self, a):
  171. """Compute factorial of ``a``. """
  172. return factorial(a)
  173. ZZ = IntegerRing()