integerring.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  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):
  67. r"""Returns an algebraic field, i.e. `\mathbb{Q}(\alpha, \ldots)`.
  68. Parameters
  69. ==========
  70. *extension: One or more Expr.
  71. Generators of the extension. These should be expressions that are
  72. algebraic over `\mathbb{Q}`.
  73. Returns
  74. =======
  75. :py:class:`~.AlgebraicField`
  76. A :py:class:`~.Domain` representing the algebraic field extension.
  77. Examples
  78. ========
  79. >>> from sympy import ZZ, sqrt
  80. >>> ZZ.algebraic_field(sqrt(2))
  81. QQ<sqrt(2)>
  82. """
  83. return self.get_field().algebraic_field(*extension)
  84. def from_AlgebraicField(K1, a, K0):
  85. """Convert a :py:class:`~.ANP` object to :ref:`ZZ`.
  86. See :py:meth:`~.Domain.convert`.
  87. """
  88. if a.is_ground:
  89. return K1.convert(a.LC(), K0.dom)
  90. def log(self, a, b):
  91. r"""logarithm of *a* to the base *b*
  92. Parameters
  93. ==========
  94. a: number
  95. b: number
  96. Returns
  97. =======
  98. $\\lfloor\log(a, b)\\rfloor$:
  99. Floor of the logarithm of *a* to the base *b*
  100. Examples
  101. ========
  102. >>> from sympy import ZZ
  103. >>> ZZ.log(ZZ(8), ZZ(2))
  104. 3
  105. >>> ZZ.log(ZZ(9), ZZ(2))
  106. 3
  107. Notes
  108. =====
  109. This function uses ``math.log`` which is based on ``float`` so it will
  110. fail for large integer arguments.
  111. """
  112. return self.dtype(math.log(int(a), b))
  113. def from_FF(K1, a, K0):
  114. """Convert ``ModularInteger(int)`` to GMPY's ``mpz``. """
  115. return MPZ(a.to_int())
  116. def from_FF_python(K1, a, K0):
  117. """Convert ``ModularInteger(int)`` to GMPY's ``mpz``. """
  118. return MPZ(a.to_int())
  119. def from_ZZ(K1, a, K0):
  120. """Convert Python's ``int`` to GMPY's ``mpz``. """
  121. return MPZ(a)
  122. def from_ZZ_python(K1, a, K0):
  123. """Convert Python's ``int`` to GMPY's ``mpz``. """
  124. return MPZ(a)
  125. def from_QQ(K1, a, K0):
  126. """Convert Python's ``Fraction`` to GMPY's ``mpz``. """
  127. if a.denominator == 1:
  128. return MPZ(a.numerator)
  129. def from_QQ_python(K1, a, K0):
  130. """Convert Python's ``Fraction`` to GMPY's ``mpz``. """
  131. if a.denominator == 1:
  132. return MPZ(a.numerator)
  133. def from_FF_gmpy(K1, a, K0):
  134. """Convert ``ModularInteger(mpz)`` to GMPY's ``mpz``. """
  135. return a.to_int()
  136. def from_ZZ_gmpy(K1, a, K0):
  137. """Convert GMPY's ``mpz`` to GMPY's ``mpz``. """
  138. return a
  139. def from_QQ_gmpy(K1, a, K0):
  140. """Convert GMPY ``mpq`` to GMPY's ``mpz``. """
  141. if a.denominator == 1:
  142. return a.numerator
  143. def from_RealField(K1, a, K0):
  144. """Convert mpmath's ``mpf`` to GMPY's ``mpz``. """
  145. p, q = K0.to_rational(a)
  146. if q == 1:
  147. return MPZ(p)
  148. def from_GaussianIntegerRing(K1, a, K0):
  149. if a.y == 0:
  150. return a.x
  151. def gcdex(self, a, b):
  152. """Compute extended GCD of ``a`` and ``b``. """
  153. h, s, t = gcdex(a, b)
  154. if HAS_GMPY:
  155. return s, t, h
  156. else:
  157. return h, s, t
  158. def gcd(self, a, b):
  159. """Compute GCD of ``a`` and ``b``. """
  160. return gcd(a, b)
  161. def lcm(self, a, b):
  162. """Compute LCM of ``a`` and ``b``. """
  163. return lcm(a, b)
  164. def sqrt(self, a):
  165. """Compute square root of ``a``. """
  166. return sqrt(a)
  167. def factorial(self, a):
  168. """Compute factorial of ``a``. """
  169. return factorial(a)
  170. ZZ = IntegerRing()