expressiondomain.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. """Implementation of :class:`ExpressionDomain` class. """
  2. from sympy.core import sympify, SympifyError
  3. from sympy.polys.domains.characteristiczero import CharacteristicZero
  4. from sympy.polys.domains.field import Field
  5. from sympy.polys.domains.simpledomain import SimpleDomain
  6. from sympy.polys.polyutils import PicklableWithSlots
  7. from sympy.utilities import public
  8. eflags = dict(deep=False, mul=True, power_exp=False, power_base=False,
  9. basic=False, multinomial=False, log=False)
  10. @public
  11. class ExpressionDomain(Field, CharacteristicZero, SimpleDomain):
  12. """A class for arbitrary expressions. """
  13. is_SymbolicDomain = is_EX = True
  14. class Expression(PicklableWithSlots):
  15. """An arbitrary expression. """
  16. __slots__ = ('ex',)
  17. def __init__(self, ex):
  18. if not isinstance(ex, self.__class__):
  19. self.ex = sympify(ex)
  20. else:
  21. self.ex = ex.ex
  22. def __repr__(f):
  23. return 'EX(%s)' % repr(f.ex)
  24. def __str__(f):
  25. return 'EX(%s)' % str(f.ex)
  26. def __hash__(self):
  27. return hash((self.__class__.__name__, self.ex))
  28. def as_expr(f):
  29. return f.ex
  30. def numer(f):
  31. return f.__class__(f.ex.as_numer_denom()[0])
  32. def denom(f):
  33. return f.__class__(f.ex.as_numer_denom()[1])
  34. def simplify(f, ex):
  35. return f.__class__(ex.cancel().expand(**eflags))
  36. def __abs__(f):
  37. return f.__class__(abs(f.ex))
  38. def __neg__(f):
  39. return f.__class__(-f.ex)
  40. def _to_ex(f, g):
  41. try:
  42. return f.__class__(g)
  43. except SympifyError:
  44. return None
  45. def __add__(f, g):
  46. g = f._to_ex(g)
  47. if g is None:
  48. return NotImplemented
  49. elif g == EX.zero:
  50. return f
  51. elif f == EX.zero:
  52. return g
  53. else:
  54. return f.simplify(f.ex + g.ex)
  55. def __radd__(f, g):
  56. return f.simplify(f.__class__(g).ex + f.ex)
  57. def __sub__(f, g):
  58. g = f._to_ex(g)
  59. if g is None:
  60. return NotImplemented
  61. elif g == EX.zero:
  62. return f
  63. elif f == EX.zero:
  64. return -g
  65. else:
  66. return f.simplify(f.ex - g.ex)
  67. def __rsub__(f, g):
  68. return f.simplify(f.__class__(g).ex - f.ex)
  69. def __mul__(f, g):
  70. g = f._to_ex(g)
  71. if g is None:
  72. return NotImplemented
  73. if EX.zero in (f, g):
  74. return EX.zero
  75. elif f.ex.is_Number and g.ex.is_Number:
  76. return f.__class__(f.ex*g.ex)
  77. return f.simplify(f.ex*g.ex)
  78. def __rmul__(f, g):
  79. return f.simplify(f.__class__(g).ex*f.ex)
  80. def __pow__(f, n):
  81. n = f._to_ex(n)
  82. if n is not None:
  83. return f.simplify(f.ex**n.ex)
  84. else:
  85. return NotImplemented
  86. def __truediv__(f, g):
  87. g = f._to_ex(g)
  88. if g is not None:
  89. return f.simplify(f.ex/g.ex)
  90. else:
  91. return NotImplemented
  92. def __rtruediv__(f, g):
  93. return f.simplify(f.__class__(g).ex/f.ex)
  94. def __eq__(f, g):
  95. return f.ex == f.__class__(g).ex
  96. def __ne__(f, g):
  97. return not f == g
  98. def __bool__(f):
  99. return not f.ex.is_zero
  100. def gcd(f, g):
  101. from sympy.polys import gcd
  102. return f.__class__(gcd(f.ex, f.__class__(g).ex))
  103. def lcm(f, g):
  104. from sympy.polys import lcm
  105. return f.__class__(lcm(f.ex, f.__class__(g).ex))
  106. dtype = Expression
  107. zero = Expression(0)
  108. one = Expression(1)
  109. rep = 'EX'
  110. has_assoc_Ring = False
  111. has_assoc_Field = True
  112. def __init__(self):
  113. pass
  114. def to_sympy(self, a):
  115. """Convert ``a`` to a SymPy object. """
  116. return a.as_expr()
  117. def from_sympy(self, a):
  118. """Convert SymPy's expression to ``dtype``. """
  119. return self.dtype(a)
  120. def from_ZZ(K1, a, K0):
  121. """Convert a Python ``int`` object to ``dtype``. """
  122. return K1(K0.to_sympy(a))
  123. def from_ZZ_python(K1, a, K0):
  124. """Convert a Python ``int`` object to ``dtype``. """
  125. return K1(K0.to_sympy(a))
  126. def from_QQ(K1, a, K0):
  127. """Convert a Python ``Fraction`` object to ``dtype``. """
  128. return K1(K0.to_sympy(a))
  129. def from_QQ_python(K1, a, K0):
  130. """Convert a Python ``Fraction`` object to ``dtype``. """
  131. return K1(K0.to_sympy(a))
  132. def from_ZZ_gmpy(K1, a, K0):
  133. """Convert a GMPY ``mpz`` object to ``dtype``. """
  134. return K1(K0.to_sympy(a))
  135. def from_QQ_gmpy(K1, a, K0):
  136. """Convert a GMPY ``mpq`` object to ``dtype``. """
  137. return K1(K0.to_sympy(a))
  138. def from_GaussianIntegerRing(K1, a, K0):
  139. """Convert a ``GaussianRational`` object to ``dtype``. """
  140. return K1(K0.to_sympy(a))
  141. def from_GaussianRationalField(K1, a, K0):
  142. """Convert a ``GaussianRational`` object to ``dtype``. """
  143. return K1(K0.to_sympy(a))
  144. def from_RealField(K1, a, K0):
  145. """Convert a mpmath ``mpf`` object to ``dtype``. """
  146. return K1(K0.to_sympy(a))
  147. def from_PolynomialRing(K1, a, K0):
  148. """Convert a ``DMP`` object to ``dtype``. """
  149. return K1(K0.to_sympy(a))
  150. def from_FractionField(K1, a, K0):
  151. """Convert a ``DMF`` object to ``dtype``. """
  152. return K1(K0.to_sympy(a))
  153. def from_ExpressionDomain(K1, a, K0):
  154. """Convert a ``EX`` object to ``dtype``. """
  155. return a
  156. def get_ring(self):
  157. """Returns a ring associated with ``self``. """
  158. return self # XXX: EX is not a ring but we don't have much choice here.
  159. def get_field(self):
  160. """Returns a field associated with ``self``. """
  161. return self
  162. def is_positive(self, a):
  163. """Returns True if ``a`` is positive. """
  164. return a.ex.as_coeff_mul()[0].is_positive
  165. def is_negative(self, a):
  166. """Returns True if ``a`` is negative. """
  167. return a.ex.could_extract_minus_sign()
  168. def is_nonpositive(self, a):
  169. """Returns True if ``a`` is non-positive. """
  170. return a.ex.as_coeff_mul()[0].is_nonpositive
  171. def is_nonnegative(self, a):
  172. """Returns True if ``a`` is non-negative. """
  173. return a.ex.as_coeff_mul()[0].is_nonnegative
  174. def numer(self, a):
  175. """Returns numerator of ``a``. """
  176. return a.numer()
  177. def denom(self, a):
  178. """Returns denominator of ``a``. """
  179. return a.denom()
  180. def gcd(self, a, b):
  181. return self(1)
  182. def lcm(self, a, b):
  183. return a.lcm(b)
  184. EX = ExpressionDomain()