Use multipledispatch for multiply

This commit is contained in:
Bertrand Benjamin 2018-03-17 10:28:43 +03:00
parent f2fb80c55b
commit c08ea7b86a

View File

@ -10,6 +10,7 @@
Multiply MO Multiply MO
""" """
from multipledispatch import Dispatcher
from ..tree import Tree from ..tree import Tree
from ..MO.mo import MO, MOnumber, MOstr from ..MO.mo import MO, MOnumber, MOstr
from ..MO.fraction import MOFraction from ..MO.fraction import MOFraction
@ -17,66 +18,42 @@ from ..MO.monomial import MOMonomial
from .exceptions import MultiplyError from .exceptions import MultiplyError
from .type_filter import args_are from .type_filter import args_are
multiply_doc = """ Multiply MOs
def multiply(left, right): :param left: left MO
""" Perform the addition of left and right :param right: right MO
:returns: Tree or MO
:param left: left MO """
:param right: right MO
:returns: Tree or MO
>>> a = MOnumber(4) multiply = Dispatcher("multiply", doc=multiply_doc)
>>> b = MOnumber(6)
>>> multiply(a, b)
<MOnumber 24>
>>> b = MOnumber(0)
>>> multiply(a, b)
<MOnumber 0>
""" @multiply.register(MOnumber, MOnumber)
if left.value == 0 or right.value == 0:
return MOnumber(0)
elif left.value == 1:
return right
elif right.value == 1:
return left
return MULFUNCTIONS[(type(left), type(right))](left, right)
@args_are(MOnumber, MOnumber)
def monumber_monumber(left, right): def monumber_monumber(left, right):
""" Multiply 2 monumbers """ Simply multiply values
:param left: left MOnumber
:param right: right MOnumber
:returns: MONumber
>>> a = MOnumber(4) >>> a = MOnumber(4)
>>> b = MOnumber(6) >>> b = MOnumber(6)
>>> monumber_monumber(a, b) >>> multiply(a, b)
<MOnumber 24> <MOnumber 24>
""" """
return MO.factory(left.value * right.value) return MO.factory(left.value * right.value)
@args_are(MOnumber, MOFraction) @multiply.register(MOnumber, MOFraction)
def monumber_mofraction(left, right): def monumber_mofraction(left, right):
""" Multiply a monumber and a mofraction """ Return division Tree with on the numertor MOnumber times numerator of MOFraction
:param left: a monumber
:param right: a mofraction
:returns: Tree with the multiplication on the numerator
>>> a = MOnumber(4) >>> a = MOnumber(4)
>>> b = MOFraction(6, 5) >>> b = MOFraction(6, 5)
>>> print(monumber_mofraction(a, b)) >>> print(multiply(a, b))
/ /
> * > *
| > 4 | > 4
| > 6 | > 6
> 5 > 5
>>> b = MOFraction(6, 5, True) >>> b = MOFraction(6, 5, True)
>>> print(monumber_mofraction(a, b)) >>> print(multiply(a, b))
/ /
> * > *
| > 4 | > 4
@ -86,49 +63,32 @@ def monumber_mofraction(left, right):
> 5 > 5
""" """
if not isinstance(left, MOnumber) or not isinstance(right, MOFraction):
raise MultiplyError(f"Wrong type for left (got {left.__class__.__name__}) \
or right (got {right.__class__.__name__})")
num = Tree("*", left, right.numerator) num = Tree("*", left, right.numerator)
return Tree("/", num, right._denominator) return Tree("/", num, right._denominator)
@args_are(MOFraction, MOnumber) @multiply.register(MOFraction, MOnumber)
def mofraction_monumber(left, right): def mofraction_monumber(left, right):
""" Multiply a monumber and a mofraction """ Return division Tree with on the numertor MOnumber times numerator of MOFraction
:param left: a mofraction
:param right: a monumber
:returns: Tree with the number converted into a mofraction
>>> a = MOFraction(6, 5) >>> a = MOFraction(6, 5)
>>> b = MOnumber(4) >>> b = MOnumber(4)
>>> print(mofraction_monumber(a, b)) >>> print(multiply(a, b))
/ /
> * > *
| > 6 | > 6
| > 4 | > 4
> 5 > 5
""" """
if not isinstance(left, MOFraction) or not isinstance(right, MOnumber):
raise MultiplyError(f"Wrong type for left (got {left.__class__.__name__})"
f"or right (got {right.__class__.__name__})")
num = Tree("*", left.numerator, right) num = Tree("*", left.numerator, right)
return Tree("/", num, left._denominator) return Tree("/", num, left._denominator)
@args_are(MOFraction, MOFraction) @multiply.register(MOFraction, MOFraction)
def mofraction_mofraction(left, right): def mofraction_mofraction(left, right):
""" Multiply two mofractions """ Multiply two mofractions (numertors together and denominators together)
:param left: a mofraction
:param right: a mofraction
:returns: Tree with a new calculus
>>> a = MOFraction(1, 5) >>> a = MOFraction(1, 5)
>>> b = MOFraction(4, 5) >>> b = MOFraction(4, 5)
>>> print(mofraction_mofraction(a, b)) >>> print(multiply(a, b))
/ /
> * > *
| > 1 | > 1
@ -137,63 +97,50 @@ def mofraction_mofraction(left, right):
| > 5 | > 5
| > 5 | > 5
""" """
if not isinstance(left, MOFraction) or not isinstance(right, MOFraction):
raise AddError(f"Wrong type for left (got {left.__class__.__name__})"
f"or right (got {right.__class__.__name__})")
num = Tree("*", left.numerator, right.numerator) num = Tree("*", left.numerator, right.numerator)
denom = Tree("*", left.denominator, right.denominator) denom = Tree("*", left.denominator, right.denominator)
return Tree("/", num, denom) return Tree("/", num, denom)
@args_are((MOnumber, MOFraction), MOstr) @multiply.register((MOnumber, MOFraction), MOstr)
def moscalar_mostr(left, right): def moscalar_mostr(left, right):
""" Multiply a scalar with a letter """ Multiply a scalar with a letter to create a MOMonomial
>>> a = MOnumber(2) >>> a = MOnumber(2)
>>> b = MOstr('x') >>> b = MOstr('x')
>>> moscalar_mostr(a, b) >>> multiply(a, b)
<MOMonomial 2x> <MOMonomial 2x>
>>> a = MOFraction(1, 5) >>> a = MOFraction(1, 5)
>>> moscalar_mostr(a, b) >>> multiply(a, b)
<MOMonomial 1 / 5x> <MOMonomial 1 / 5x>
""" """
return MOMonomial(left, right) return MOMonomial(left, right)
@args_are(MOstr, (MOnumber, MOFraction)) @multiply.register(MOstr, (MOnumber, MOFraction))
def mostr_moscalar(left, right): def mostr_moscalar(left, right):
""" Multiply a scalar with a letter """ Multiply a scalar with a letter to create a MOMonomial
>>> a = MOstr('x') >>> a = MOstr('x')
>>> b = MOnumber(2) >>> b = MOnumber(2)
>>> mostr_moscalar(a, b) >>> multiply(a, b)
<MOMonomial 2x> <MOMonomial 2x>
>>> b = MOFraction(1, 5) >>> b = MOFraction(1, 5)
>>> mostr_moscalar(a, b) >>> multiply(a, b)
<MOMonomial 1 / 5x> <MOMonomial 1 / 5x>
""" """
return MOMonomial(right, left) return MOMonomial(right, left)
@args_are((MOnumber, MOFraction), MOMonomial) @multiply.register((MOnumber, MOFraction), MOMonomial)
def moscalar_monomonial(left, right): def moscalar_monomonial(left, right):
""" Multiply a scalar with a monomial """ Multiply a scalar with a monomial
>>> a = MOnumber(4) >>> a = MOnumber(4)
>>> b = MOMonomial(5, 'x', 3) >>> b = MOMonomial(5, 'x', 3)
# >>> print(moscalar_monomonial(a, b)) # >>> print(multiply(a, b))
""" """
coefficient = Tree('*', left, right._coefficient) coefficient = Tree('*', left, right._coefficient)
return Tree('*', coefficient, MOMonomial(1, right._variable, right._power)) return Tree('*', coefficient, MOMonomial(1, right._variable, right._power))
# TODO: Faire un décorateur pour un enregistrement automatique |dim. mars 11 18:24:32 EAT 2018
MULFUNCTIONS = {
(MOnumber, MOnumber): monumber_monumber,
(MOnumber, MOFraction): monumber_mofraction,
(MOFraction, MOnumber): mofraction_monumber,
(MOFraction, MOFraction): mofraction_mofraction,
}
# ----------------------------- # -----------------------------
# Reglages pour 'vim' # Reglages pour 'vim'
# vim:set autoindent expandtab tabstop=4 shiftwidth=4: # vim:set autoindent expandtab tabstop=4 shiftwidth=4: