117 lines
3.6 KiB
Python
117 lines
3.6 KiB
Python
|
"""
|
||
|
|
||
|
Module for the DomainScalar class.
|
||
|
|
||
|
A DomainScalar represents an element which is in a particular
|
||
|
Domain. The idea is that the DomainScalar class provides the
|
||
|
convenience routines for unifying elements with different domains.
|
||
|
|
||
|
It assists in Scalar Multiplication and getitem for DomainMatrix.
|
||
|
|
||
|
"""
|
||
|
from ..constructor import construct_domain
|
||
|
|
||
|
from sympy.polys.domains import Domain, ZZ
|
||
|
|
||
|
|
||
|
class DomainScalar:
|
||
|
r"""
|
||
|
docstring
|
||
|
"""
|
||
|
|
||
|
def __new__(cls, element, domain):
|
||
|
if not isinstance(domain, Domain):
|
||
|
raise TypeError("domain should be of type Domain")
|
||
|
if not domain.of_type(element):
|
||
|
raise TypeError("element %s should be in domain %s" % (element, domain))
|
||
|
return cls.new(element, domain)
|
||
|
|
||
|
@classmethod
|
||
|
def new(cls, element, domain):
|
||
|
obj = super().__new__(cls)
|
||
|
obj.element = element
|
||
|
obj.domain = domain
|
||
|
return obj
|
||
|
|
||
|
def __repr__(self):
|
||
|
return repr(self.element)
|
||
|
|
||
|
@classmethod
|
||
|
def from_sympy(cls, expr):
|
||
|
[domain, [element]] = construct_domain([expr])
|
||
|
return cls.new(element, domain)
|
||
|
|
||
|
def to_sympy(self):
|
||
|
return self.domain.to_sympy(self.element)
|
||
|
|
||
|
def to_domain(self, domain):
|
||
|
element = domain.convert_from(self.element, self.domain)
|
||
|
return self.new(element, domain)
|
||
|
|
||
|
def convert_to(self, domain):
|
||
|
return self.to_domain(domain)
|
||
|
|
||
|
def unify(self, other):
|
||
|
domain = self.domain.unify(other.domain)
|
||
|
return self.to_domain(domain), other.to_domain(domain)
|
||
|
|
||
|
def __add__(self, other):
|
||
|
if not isinstance(other, DomainScalar):
|
||
|
return NotImplemented
|
||
|
self, other = self.unify(other)
|
||
|
return self.new(self.element + other.element, self.domain)
|
||
|
|
||
|
def __sub__(self, other):
|
||
|
if not isinstance(other, DomainScalar):
|
||
|
return NotImplemented
|
||
|
self, other = self.unify(other)
|
||
|
return self.new(self.element - other.element, self.domain)
|
||
|
|
||
|
def __mul__(self, other):
|
||
|
if not isinstance(other, DomainScalar):
|
||
|
if isinstance(other, int):
|
||
|
other = DomainScalar(ZZ(other), ZZ)
|
||
|
else:
|
||
|
return NotImplemented
|
||
|
|
||
|
self, other = self.unify(other)
|
||
|
return self.new(self.element * other.element, self.domain)
|
||
|
|
||
|
def __floordiv__(self, other):
|
||
|
if not isinstance(other, DomainScalar):
|
||
|
return NotImplemented
|
||
|
self, other = self.unify(other)
|
||
|
return self.new(self.domain.quo(self.element, other.element), self.domain)
|
||
|
|
||
|
def __mod__(self, other):
|
||
|
if not isinstance(other, DomainScalar):
|
||
|
return NotImplemented
|
||
|
self, other = self.unify(other)
|
||
|
return self.new(self.domain.rem(self.element, other.element), self.domain)
|
||
|
|
||
|
def __divmod__(self, other):
|
||
|
if not isinstance(other, DomainScalar):
|
||
|
return NotImplemented
|
||
|
self, other = self.unify(other)
|
||
|
q, r = self.domain.div(self.element, other.element)
|
||
|
return (self.new(q, self.domain), self.new(r, self.domain))
|
||
|
|
||
|
def __pow__(self, n):
|
||
|
if not isinstance(n, int):
|
||
|
return NotImplemented
|
||
|
return self.new(self.element**n, self.domain)
|
||
|
|
||
|
def __pos__(self):
|
||
|
return self.new(+self.element, self.domain)
|
||
|
|
||
|
def __eq__(self, other):
|
||
|
if not isinstance(other, DomainScalar):
|
||
|
return NotImplemented
|
||
|
return self.element == other.element and self.domain == other.domain
|
||
|
|
||
|
def is_zero(self):
|
||
|
return self.element == self.domain.zero
|
||
|
|
||
|
def is_one(self):
|
||
|
return self.element == self.domain.one
|