domainscalar.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. """
  2. Module for the DomainScalar class.
  3. A DomainScalar represents an element which is in a particular
  4. Domain. The idea is that the DomainScalar class provides the
  5. convenience routines for unifying elements with different domains.
  6. It assists in Scalar Multiplication and getitem for DomainMatrix.
  7. """
  8. from ..constructor import construct_domain
  9. from sympy.polys.domains import Domain, ZZ
  10. class DomainScalar:
  11. r"""
  12. docstring
  13. """
  14. def __new__(cls, element, domain):
  15. if not isinstance(domain, Domain):
  16. raise TypeError("domain should be of type Domain")
  17. if not domain.of_type(element):
  18. raise TypeError("element %s should be in domain %s" % (element, domain))
  19. return cls.new(element, domain)
  20. @classmethod
  21. def new(cls, element, domain):
  22. obj = super().__new__(cls)
  23. obj.element = element
  24. obj.domain = domain
  25. return obj
  26. def __repr__(self):
  27. return repr(self.element)
  28. @classmethod
  29. def from_sympy(cls, expr):
  30. [domain, [element]] = construct_domain([expr])
  31. return cls.new(element, domain)
  32. def to_sympy(self):
  33. return self.domain.to_sympy(self.element)
  34. def to_domain(self, domain):
  35. element = domain.convert_from(self.element, self.domain)
  36. return self.new(element, domain)
  37. def convert_to(self, domain):
  38. return self.to_domain(domain)
  39. def unify(self, other):
  40. domain = self.domain.unify(other.domain)
  41. return self.to_domain(domain), other.to_domain(domain)
  42. def __bool__(self):
  43. return bool(self.element)
  44. def __add__(self, other):
  45. if not isinstance(other, DomainScalar):
  46. return NotImplemented
  47. self, other = self.unify(other)
  48. return self.new(self.element + other.element, self.domain)
  49. def __sub__(self, other):
  50. if not isinstance(other, DomainScalar):
  51. return NotImplemented
  52. self, other = self.unify(other)
  53. return self.new(self.element - other.element, self.domain)
  54. def __mul__(self, other):
  55. if not isinstance(other, DomainScalar):
  56. if isinstance(other, int):
  57. other = DomainScalar(ZZ(other), ZZ)
  58. else:
  59. return NotImplemented
  60. self, other = self.unify(other)
  61. return self.new(self.element * other.element, self.domain)
  62. def __floordiv__(self, other):
  63. if not isinstance(other, DomainScalar):
  64. return NotImplemented
  65. self, other = self.unify(other)
  66. return self.new(self.domain.quo(self.element, other.element), self.domain)
  67. def __mod__(self, other):
  68. if not isinstance(other, DomainScalar):
  69. return NotImplemented
  70. self, other = self.unify(other)
  71. return self.new(self.domain.rem(self.element, other.element), self.domain)
  72. def __divmod__(self, other):
  73. if not isinstance(other, DomainScalar):
  74. return NotImplemented
  75. self, other = self.unify(other)
  76. q, r = self.domain.div(self.element, other.element)
  77. return (self.new(q, self.domain), self.new(r, self.domain))
  78. def __pow__(self, n):
  79. if not isinstance(n, int):
  80. return NotImplemented
  81. return self.new(self.element**n, self.domain)
  82. def __pos__(self):
  83. return self.new(+self.element, self.domain)
  84. def __neg__(self):
  85. return self.new(-self.element, self.domain)
  86. def __eq__(self, other):
  87. if not isinstance(other, DomainScalar):
  88. return NotImplemented
  89. return self.element == other.element and self.domain == other.domain
  90. def is_zero(self):
  91. return self.element == self.domain.zero
  92. def is_one(self):
  93. return self.element == self.domain.one