fractionfield.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. """Implementation of :class:`FractionField` class. """
  2. from sympy.polys.domains.compositedomain import CompositeDomain
  3. from sympy.polys.domains.field import Field
  4. from sympy.polys.polyerrors import CoercionFailed, GeneratorsError
  5. from sympy.utilities import public
  6. @public
  7. class FractionField(Field, CompositeDomain):
  8. """A class for representing multivariate rational function fields. """
  9. is_FractionField = is_Frac = True
  10. has_assoc_Ring = True
  11. has_assoc_Field = True
  12. def __init__(self, domain_or_field, symbols=None, order=None):
  13. from sympy.polys.fields import FracField
  14. if isinstance(domain_or_field, FracField) and symbols is None and order is None:
  15. field = domain_or_field
  16. else:
  17. field = FracField(symbols, domain_or_field, order)
  18. self.field = field
  19. self.dtype = field.dtype
  20. self.gens = field.gens
  21. self.ngens = field.ngens
  22. self.symbols = field.symbols
  23. self.domain = field.domain
  24. # TODO: remove this
  25. self.dom = self.domain
  26. def new(self, element):
  27. return self.field.field_new(element)
  28. @property
  29. def zero(self):
  30. return self.field.zero
  31. @property
  32. def one(self):
  33. return self.field.one
  34. @property
  35. def order(self):
  36. return self.field.order
  37. @property
  38. def is_Exact(self):
  39. return self.domain.is_Exact
  40. def get_exact(self):
  41. return FractionField(self.domain.get_exact(), self.symbols)
  42. def __str__(self):
  43. return str(self.domain) + '(' + ','.join(map(str, self.symbols)) + ')'
  44. def __hash__(self):
  45. return hash((self.__class__.__name__, self.dtype.field, self.domain, self.symbols))
  46. def __eq__(self, other):
  47. """Returns ``True`` if two domains are equivalent. """
  48. return isinstance(other, FractionField) and \
  49. (self.dtype.field, self.domain, self.symbols) ==\
  50. (other.dtype.field, other.domain, other.symbols)
  51. def to_sympy(self, a):
  52. """Convert ``a`` to a SymPy object. """
  53. return a.as_expr()
  54. def from_sympy(self, a):
  55. """Convert SymPy's expression to ``dtype``. """
  56. return self.field.from_expr(a)
  57. def from_ZZ(K1, a, K0):
  58. """Convert a Python ``int`` object to ``dtype``. """
  59. return K1(K1.domain.convert(a, K0))
  60. def from_ZZ_python(K1, a, K0):
  61. """Convert a Python ``int`` object to ``dtype``. """
  62. return K1(K1.domain.convert(a, K0))
  63. def from_QQ(K1, a, K0):
  64. """Convert a Python ``Fraction`` object to ``dtype``. """
  65. dom = K1.domain
  66. conv = dom.convert_from
  67. if dom.is_ZZ:
  68. return K1(conv(K0.numer(a), K0)) / K1(conv(K0.denom(a), K0))
  69. else:
  70. return K1(conv(a, K0))
  71. def from_QQ_python(K1, a, K0):
  72. """Convert a Python ``Fraction`` object to ``dtype``. """
  73. return K1(K1.domain.convert(a, K0))
  74. def from_ZZ_gmpy(K1, a, K0):
  75. """Convert a GMPY ``mpz`` object to ``dtype``. """
  76. return K1(K1.domain.convert(a, K0))
  77. def from_QQ_gmpy(K1, a, K0):
  78. """Convert a GMPY ``mpq`` object to ``dtype``. """
  79. return K1(K1.domain.convert(a, K0))
  80. def from_GaussianRationalField(K1, a, K0):
  81. """Convert a ``GaussianRational`` object to ``dtype``. """
  82. return K1(K1.domain.convert(a, K0))
  83. def from_GaussianIntegerRing(K1, a, K0):
  84. """Convert a ``GaussianInteger`` object to ``dtype``. """
  85. return K1(K1.domain.convert(a, K0))
  86. def from_RealField(K1, a, K0):
  87. """Convert a mpmath ``mpf`` object to ``dtype``. """
  88. return K1(K1.domain.convert(a, K0))
  89. def from_ComplexField(K1, a, K0):
  90. """Convert a mpmath ``mpf`` object to ``dtype``. """
  91. return K1(K1.domain.convert(a, K0))
  92. def from_AlgebraicField(K1, a, K0):
  93. """Convert an algebraic number to ``dtype``. """
  94. if K1.domain != K0:
  95. a = K1.domain.convert_from(a, K0)
  96. if a is not None:
  97. return K1.new(a)
  98. def from_PolynomialRing(K1, a, K0):
  99. """Convert a polynomial to ``dtype``. """
  100. if a.is_ground:
  101. return K1.convert_from(a.coeff(1), K0.domain)
  102. try:
  103. return K1.new(a.set_ring(K1.field.ring))
  104. except (CoercionFailed, GeneratorsError):
  105. # XXX: We get here if K1=ZZ(x,y) and K0=QQ[x,y]
  106. # and the poly a in K0 has non-integer coefficients.
  107. # It seems that K1.new can handle this but K1.new doesn't work
  108. # when K0.domain is an algebraic field...
  109. try:
  110. return K1.new(a)
  111. except (CoercionFailed, GeneratorsError):
  112. return None
  113. def from_FractionField(K1, a, K0):
  114. """Convert a rational function to ``dtype``. """
  115. try:
  116. return a.set_field(K1.field)
  117. except (CoercionFailed, GeneratorsError):
  118. return None
  119. def get_ring(self):
  120. """Returns a field associated with ``self``. """
  121. return self.field.to_ring().to_domain()
  122. def is_positive(self, a):
  123. """Returns True if ``LC(a)`` is positive. """
  124. return self.domain.is_positive(a.numer.LC)
  125. def is_negative(self, a):
  126. """Returns True if ``LC(a)`` is negative. """
  127. return self.domain.is_negative(a.numer.LC)
  128. def is_nonpositive(self, a):
  129. """Returns True if ``LC(a)`` is non-positive. """
  130. return self.domain.is_nonpositive(a.numer.LC)
  131. def is_nonnegative(self, a):
  132. """Returns True if ``LC(a)`` is non-negative. """
  133. return self.domain.is_nonnegative(a.numer.LC)
  134. def numer(self, a):
  135. """Returns numerator of ``a``. """
  136. return a.numer
  137. def denom(self, a):
  138. """Returns denominator of ``a``. """
  139. return a.denom
  140. def factorial(self, a):
  141. """Returns factorial of ``a``. """
  142. return self.dtype(self.domain.factorial(a))