refactor(MO): Separate value and tree in MOs

This commit is contained in:
Bertrand Benjamin 2018-11-13 09:14:50 +01:00
parent d89042391b
commit abf056ce33
7 changed files with 50 additions and 128 deletions

View File

@ -32,18 +32,20 @@ class MOFraction(MO):
>>> f >>> f
<MOFraction - 2 / 3> <MOFraction - 2 / 3>
""" """
base_value = Tree("/", _numerator = MO.factory(numerator)
MO.factory(numerator), _denominator = MO.factory(denominator)
MO.factory(denominator), base_tree = Tree("/",
_numerator,
_denominator,
) )
if negative: if negative:
value = Tree("-", None, base_value) tree = Tree("-", None, base_tree)
else: else:
value = base_value tree = base_tree
MO.__init__(self, value) MO.__init__(self, tree)
self._numerator = numerator self._numerator = _numerator
self._denominator = denominator self._denominator = _denominator
self.negative = negative self.negative = negative
@property @property

View File

@ -42,8 +42,10 @@ class MO(object):
"""MO for math object """MO for math object
This base class is representing int and Decimal. It stocks its value in This base class is representing int and Decimal.
self.value and it
:attr value: sympy compatible version of the MO
:attr _tree: tree version of the MO
""" """
@ -60,9 +62,9 @@ class MO(object):
<MO 3> <MO 3>
""" """
try: try:
self.value = value.value self._tree = value._tree
except AttributeError: except AttributeError:
self.value = value self._tree = value
self.is_scalar = True self.is_scalar = True
@ -100,31 +102,31 @@ class MO(object):
return f"<{self.__class__.__name__} {self.__txt__}>" return f"<{self.__class__.__name__} {self.__txt__}>"
def __str__(self): def __str__(self):
return str(self.value) return str(self._tree)
@property @property
def __txt__(self): def __txt__(self):
try: try:
return tree2txt(self.value) return tree2txt(self._tree)
except AttributeError: except AttributeError:
return str(self.value) return str(self._tree)
@property @property
def __tex__(self): def __tex__(self):
try: try:
return tree2tex(self.value) return tree2tex(self._tree)
except AttributeError: except AttributeError:
return str(self.value) return str(self._tree)
def __hash__(self): def __hash__(self):
return self.value.__hash__() return self._tree.__hash__()
def __eq__(self, other): def __eq__(self, other):
""" == a MOnumber """ """ == a MOnumber """
try: try:
return self.value == other.value return self._tree == other._tree
except AttributeError: except AttributeError:
return self.value == other return self._tree == other
@total_ordering @total_ordering
class MOnumber(MO): class MOnumber(MO):
@ -154,17 +156,19 @@ class MOnumber(MO):
""" """
try: try:
val = value.value val = value._tree
except AttributeError: except AttributeError:
val = value val = value
if isinstance(val, (int, Decimal)): if isinstance(val, (int, Decimal)):
MO.__init__(self, value) MO.__init__(self, val)
elif isinstance(val, float): elif isinstance(val, float):
MO.__init__(self, Decimal(val)) MO.__init__(self, Decimal(val))
else: else:
raise MOError("The value of an MOnumber need to be a int, a float or a Decimal") raise MOError("The value of an MOnumber need to be a int, a float or a Decimal")
self.value = self._tree
@property @property
def __txt__(self): def __txt__(self):
if self.value >= 0: if self.value >= 0:
@ -179,90 +183,6 @@ class MOnumber(MO):
return f"- {abs(self.value)}" return f"- {abs(self.value)}"
def __add__(self, other):
""" Adding a MOnumber """
try:
return self.value + other.value
except AttributeError:
return self.value + other
def __radd__(self, other):
""" rAdding a MOnumber """
try:
return self.value + other.value
except AttributeError:
return self.value + other
def __sub__(self, other):
""" Subing a MOnumber """
try:
return self.value - other.value
except AttributeError:
return self.value - other
def __rsub__(self, other):
""" rSubing a MOnumber """
try:
return self.value - other.value
except AttributeError:
return self.value - other
def __mul__(self, other):
""" Multiply a MOnumber """
try:
return self.value * other.value
except AttributeError:
return self.value * other
def __rmul__(self, other):
""" rMultiply a MOnumber """
try:
return self.value * other.value
except AttributeError:
return self.value * other
def __truediv__(self, other):
""" Divide a MOnumber """
try:
return self.value / other.value
except AttributeError:
return self.value / other
def __rtruediv__(self, other):
""" rDivide a MOnumber """
try:
return self.value / other.value
except AttributeError:
return self.value / other
def __floordiv__(self, other):
""" Integer Division a MOnumber """
try:
return self.value // other.value
except AttributeError:
return self.value // other
def __rfloordiv__(self, other):
""" rInteger Division a MOnumber """
try:
return other.value // self.value
except AttributeError:
return other // self.value
def __mod__(self, other):
""" Moduling a MOnumber """
try:
return self.value % other.value
except AttributeError:
return self.value % other
def __rmod__(self, other):
""" rModuling a MOnumber """
try:
return other.value % self.value
except AttributeError:
return other % self.value
def __lt__(self, other): def __lt__(self, other):
""" < a MOnumber """ """ < a MOnumber """
try: try:
@ -300,7 +220,7 @@ class MOstr(MO):
""" """
try: try:
val = value.value val = value._tree
except AttributeError: except AttributeError:
val = value val = value

View File

@ -55,15 +55,15 @@ class MOstrPower(MO):
_power = MO.factory(power) _power = MO.factory(power)
if power <= 1: if power <= 1:
raise MOError("The power of a MOstrPower should be greater than 1") raise MOError("The power of a MOstrPower should be greater than 1")
elif not isinstance(_power.value, int): elif not isinstance(_power._tree, int):
raise MOError("The power of a monomial should be a integer") raise MOError("The power of a monomial should be a integer")
self._power = _power self._power = _power
value = Tree("^", _tree = Tree("^",
self._variable, self._variable,
self._power self._power
) )
MO.__init__(self, value) MO.__init__(self, _tree)
@property @property
def variable(self): def variable(self):
@ -103,13 +103,13 @@ class MOMonomial(MO):
raise raise
self._variable = variable self._variable = variable
value = Tree("*", _tree = Tree("*",
self._coefficient, self._coefficient,
self._variable self._variable
) )
MO.__init__(self, value) MO.__init__(self, _tree)
@property @property
def coefficient(self): def coefficient(self):

View File

@ -183,22 +183,22 @@ def mofraction_mofraction(left, right):
num = Tree("+", left.numerator, right.numerator) num = Tree("+", left.numerator, right.numerator)
return Tree("/", num, left.denominator) return Tree("/", num, left.denominator)
denom_lcm = lcm(left.denominator, right.denominator) denom_lcm = lcm(left.denominator.value, right.denominator.value)
if left.denominator == denom_lcm: if left.denominator.value == denom_lcm:
left_frac = left left_frac = left
else: else:
multiply_by = denom_lcm // left.denominator multiply_by = MO.factory(denom_lcm // left.denominator.value)
left_num = Tree("*", left.numerator, MO.factory(multiply_by)) left_num = Tree("*", left.numerator, multiply_by)
left_denom = Tree("*", left.denominator, MO.factory(multiply_by)) left_denom = Tree("*", left.denominator, multiply_by)
left_frac = Tree("/", left_num, left_denom) left_frac = Tree("/", left_num, left_denom)
if right.denominator == denom_lcm: if right.denominator.value == denom_lcm:
right_frac = right right_frac = right
else: else:
multiply_by = denom_lcm // right.denominator multiply_by = MO.factory(denom_lcm // right.denominator.value)
right_num = Tree("*", right.numerator, MO.factory(multiply_by)) right_num = Tree("*", right.numerator, multiply_by)
right_denom = Tree("*", right.denominator, MO.factory(multiply_by)) right_denom = Tree("*", right.denominator, multiply_by)
right_frac = Tree("/", right_num, right_denom) right_frac = Tree("/", right_num, right_denom)
return Tree("+", left_frac, right_frac) return Tree("+", left_frac, right_frac)

View File

@ -80,7 +80,7 @@ def monumber_monumber(left, right):
""" """
if type(left.value) in [float, Decimal] or \ if type(left.value) in [float, Decimal] or \
type(right.value) in [float, Decimal]: type(right.value) in [float, Decimal]:
return MO.factory(left / right) return MO.factory(left.value / right.value)
else: else:
raise NotImplementedError("Can't divide 2 int. Need to create a Fraction instead") raise NotImplementedError("Can't divide 2 int. Need to create a Fraction instead")

View File

@ -78,14 +78,14 @@ def mofraction(left, right):
return MOFraction(right._numerator, right._denominator) return MOFraction(right._numerator, right._denominator)
try: try:
if right._numerator < 0: if right._numerator.value < 0:
return MOFraction(-right._numerator, right._denominator) return MOFraction(-right._numerator.value, right._denominator)
except TypeError: except TypeError:
pass pass
try: try:
if right._denominator < 0: if right._denominator.value < 0:
return MOFraction(right._numerator, -right._denominator) return MOFraction(right._numerator, -right._denominator.value)
except TypeError: except TypeError:
pass pass

View File

@ -206,7 +206,7 @@ def mostr_mostrpower(left, right):
if left.variable != right.variable: if left.variable != right.variable:
raise MultiplyError("Can't multiply MOstr and MOstrPower if they don't" raise MultiplyError("Can't multiply MOstr and MOstrPower if they don't"
f"have same variable (got {left.variable} and {right.variable})") f"have same variable (got {left.variable} and {right.variable})")
return MOstrPower(left.variable, right.power+1) return MOstrPower(left.variable, right.power.value+1)
@multiply.register(MOstrPower, MOstr) @multiply.register(MOstrPower, MOstr)
@special_case(multiply_filter) @special_case(multiply_filter)
@ -227,7 +227,7 @@ def mostr_mostrpower(left, right):
if left.variable != right.variable: if left.variable != right.variable:
raise MultiplyError("Can't multiply MOstr and MOstrPower if they don't" raise MultiplyError("Can't multiply MOstr and MOstrPower if they don't"
f"have same variable (got {left.variable} and {right.variable})") f"have same variable (got {left.variable} and {right.variable})")
return MOstrPower(left.variable, left.power+1) return MOstrPower(left.variable, left.power.value+1)
@multiply.register(MOstrPower, MOstrPower) @multiply.register(MOstrPower, MOstrPower)
@special_case(multiply_filter) @special_case(multiply_filter)