old_fractionfield.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. """Implementation of :class:`FractionField` class. """
  2. from sympy.polys.domains.field import Field
  3. from sympy.polys.domains.compositedomain import CompositeDomain
  4. from sympy.polys.polyclasses import DMF
  5. from sympy.polys.polyerrors import GeneratorsNeeded
  6. from sympy.polys.polyutils import dict_from_basic, basic_from_dict, _dict_reorder
  7. from sympy.utilities import public
  8. @public
  9. class FractionField(Field, CompositeDomain):
  10. """A class for representing rational function fields. """
  11. dtype = DMF
  12. is_FractionField = is_Frac = True
  13. has_assoc_Ring = True
  14. has_assoc_Field = True
  15. def __init__(self, dom, *gens):
  16. if not gens:
  17. raise GeneratorsNeeded("generators not specified")
  18. lev = len(gens) - 1
  19. self.ngens = len(gens)
  20. self.zero = self.dtype.zero(lev, dom)
  21. self.one = self.dtype.one(lev, dom)
  22. self.domain = self.dom = dom
  23. self.symbols = self.gens = gens
  24. def set_domain(self, dom):
  25. """Make a new fraction field with given domain. """
  26. return self.__class__(dom, *self.gens)
  27. def new(self, element):
  28. return self.dtype(element, self.dom, len(self.gens) - 1)
  29. def __str__(self):
  30. return str(self.dom) + '(' + ','.join(map(str, self.gens)) + ')'
  31. def __hash__(self):
  32. return hash((self.__class__.__name__, self.dtype, self.dom, self.gens))
  33. def __eq__(self, other):
  34. """Returns ``True`` if two domains are equivalent. """
  35. return isinstance(other, FractionField) and \
  36. self.dtype == other.dtype and self.dom == other.dom and self.gens == other.gens
  37. def to_sympy(self, a):
  38. """Convert ``a`` to a SymPy object. """
  39. return (basic_from_dict(a.numer().to_sympy_dict(), *self.gens) /
  40. basic_from_dict(a.denom().to_sympy_dict(), *self.gens))
  41. def from_sympy(self, a):
  42. """Convert SymPy's expression to ``dtype``. """
  43. p, q = a.as_numer_denom()
  44. num, _ = dict_from_basic(p, gens=self.gens)
  45. den, _ = dict_from_basic(q, gens=self.gens)
  46. for k, v in num.items():
  47. num[k] = self.dom.from_sympy(v)
  48. for k, v in den.items():
  49. den[k] = self.dom.from_sympy(v)
  50. return self((num, den)).cancel()
  51. def from_ZZ(K1, a, K0):
  52. """Convert a Python ``int`` object to ``dtype``. """
  53. return K1(K1.dom.convert(a, K0))
  54. def from_ZZ_python(K1, a, K0):
  55. """Convert a Python ``int`` object to ``dtype``. """
  56. return K1(K1.dom.convert(a, K0))
  57. def from_QQ_python(K1, a, K0):
  58. """Convert a Python ``Fraction`` object to ``dtype``. """
  59. return K1(K1.dom.convert(a, K0))
  60. def from_ZZ_gmpy(K1, a, K0):
  61. """Convert a GMPY ``mpz`` object to ``dtype``. """
  62. return K1(K1.dom.convert(a, K0))
  63. def from_QQ_gmpy(K1, a, K0):
  64. """Convert a GMPY ``mpq`` object to ``dtype``. """
  65. return K1(K1.dom.convert(a, K0))
  66. def from_RealField(K1, a, K0):
  67. """Convert a mpmath ``mpf`` object to ``dtype``. """
  68. return K1(K1.dom.convert(a, K0))
  69. def from_GlobalPolynomialRing(K1, a, K0):
  70. """Convert a ``DMF`` object to ``dtype``. """
  71. if K1.gens == K0.gens:
  72. if K1.dom == K0.dom:
  73. return K1(a.to_list())
  74. else:
  75. return K1(a.convert(K1.dom).to_list())
  76. else:
  77. monoms, coeffs = _dict_reorder(a.to_dict(), K0.gens, K1.gens)
  78. if K1.dom != K0.dom:
  79. coeffs = [ K1.dom.convert(c, K0.dom) for c in coeffs ]
  80. return K1(dict(zip(monoms, coeffs)))
  81. def from_FractionField(K1, a, K0):
  82. """
  83. Convert a fraction field element to another fraction field.
  84. Examples
  85. ========
  86. >>> from sympy.polys.polyclasses import DMF
  87. >>> from sympy.polys.domains import ZZ, QQ
  88. >>> from sympy.abc import x
  89. >>> f = DMF(([ZZ(1), ZZ(2)], [ZZ(1), ZZ(1)]), ZZ)
  90. >>> QQx = QQ.old_frac_field(x)
  91. >>> ZZx = ZZ.old_frac_field(x)
  92. >>> QQx.from_FractionField(f, ZZx)
  93. DMF([1, 2], [1, 1], QQ)
  94. """
  95. if K1.gens == K0.gens:
  96. if K1.dom == K0.dom:
  97. return a
  98. else:
  99. return K1((a.numer().convert(K1.dom).to_list(),
  100. a.denom().convert(K1.dom).to_list()))
  101. elif set(K0.gens).issubset(K1.gens):
  102. nmonoms, ncoeffs = _dict_reorder(
  103. a.numer().to_dict(), K0.gens, K1.gens)
  104. dmonoms, dcoeffs = _dict_reorder(
  105. a.denom().to_dict(), K0.gens, K1.gens)
  106. if K1.dom != K0.dom:
  107. ncoeffs = [ K1.dom.convert(c, K0.dom) for c in ncoeffs ]
  108. dcoeffs = [ K1.dom.convert(c, K0.dom) for c in dcoeffs ]
  109. return K1((dict(zip(nmonoms, ncoeffs)), dict(zip(dmonoms, dcoeffs))))
  110. def get_ring(self):
  111. """Returns a ring associated with ``self``. """
  112. from sympy.polys.domains import PolynomialRing
  113. return PolynomialRing(self.dom, *self.gens)
  114. def poly_ring(self, *gens):
  115. """Returns a polynomial ring, i.e. `K[X]`. """
  116. raise NotImplementedError('nested domains not allowed')
  117. def frac_field(self, *gens):
  118. """Returns a fraction field, i.e. `K(X)`. """
  119. raise NotImplementedError('nested domains not allowed')
  120. def is_positive(self, a):
  121. """Returns True if ``a`` is positive. """
  122. return self.dom.is_positive(a.numer().LC())
  123. def is_negative(self, a):
  124. """Returns True if ``a`` is negative. """
  125. return self.dom.is_negative(a.numer().LC())
  126. def is_nonpositive(self, a):
  127. """Returns True if ``a`` is non-positive. """
  128. return self.dom.is_nonpositive(a.numer().LC())
  129. def is_nonnegative(self, a):
  130. """Returns True if ``a`` is non-negative. """
  131. return self.dom.is_nonnegative(a.numer().LC())
  132. def numer(self, a):
  133. """Returns numerator of ``a``. """
  134. return a.numer()
  135. def denom(self, a):
  136. """Returns denominator of ``a``. """
  137. return a.denom()
  138. def factorial(self, a):
  139. """Returns factorial of ``a``. """
  140. return self.dtype(self.dom.factorial(a))